#For AI assistants
The same text as plain Markdown is at valheiman.com/api.txt. Give it to your assistant as the reference. Short version: the namespace is Valheiman.Api in PathOfValheiman.dll (BepInEx GUID treextr.pathofvalheiman). Use a soft dependency, call from the main thread, check Pov.Has(feature), and never reflect into PassiveTree.*.
The supported way for other Valheim mods to work with Path of Valheiman (PoV): read the character's progression and stats, show PoV's equipment and items in your own interface, keep PoV's cells in your own inventory, give tree or profession XP for your own activities, keep your skills out of PoV's skill freeze, and leave your creatures alone.
Everything is in the namespace Valheiman.Api inside PathOfValheiman.dll. Web version: https://valheiman.com/api
Availability: API 1.0.0 since Path of Valheiman 5.0.8, 1.1.0 since 5.0.9. Check Pov.Has(...) at runtime and your mod keeps working with older PoV versions.
#Rules in one screen
- Versioning. Semantic versioning. Within major version 1 nothing is removed and nothing changes meaning; minor versions only add. Check
Pov.AtLeast(1, minor)andPov.Has("feature"). - Only
Valheiman.Apiis a promise. Everything else in the DLL (thePassiveTree.*namespaces) is PoV's inside and changes without notice. Do not reflect into it; ask for what you need instead. - Soft dependency. Your mod must load without PoV. Keep PoV calls in a class of their own, touched only when PoV is installed (see Quick start).
- Main thread. Call everything from Unity's main thread.
- Never throws for missing state. Without a local player or world, calls return empty values: 0, null, false, empty lists.
- Local vs world. Character data (progression, equipment, XP) is the local player's, kept on their client. Creature data lives in the creature's ZDO: readable on every peer; PoV writes it only on the ZDO owner. World settings belong to the host. Calls that must run on every machine say so.
- Hosting. Several parts of PoV's interface can be handed to your mod (
...Host(yourGuid)): PoV keeps the logic and data and stops drawing that part.nullgives it back. The last host wins.
#Quick start
- Reference the API: download
PathOfValheiman.ref.dll(a small reference assembly with the public types only) from https://valheiman.com/api-assets/PathOfValheiman.ref.dll, or reference the realPathOfValheiman.dll. SetPrivate=falseso it is not copied into your package.
<Reference Include="PathOfValheiman">
<HintPath>libs\PathOfValheiman.ref.dll</HintPath>
<Private>false</Private>
</Reference>- Declare a soft dependency and keep the calls behind a check:
[BepInPlugin("my.mod", "My Mod", "1.0.0")]
[BepInDependency("treextr.pathofvalheiman", BepInDependency.DependencyFlags.SoftDependency)]
public class MyMod : BaseUnityPlugin
{
public static bool Pov => Chainloader.PluginInfos.ContainsKey("treextr.pathofvalheiman");
void Update() { if (Pov) PovBridge.Tick(); }
}
// Only this class mentions PoV types: it is never loaded when PoV is absent.
static class PovBridge
{
public static void Tick()
{
if (!Valheiman.Api.Pov.Has("progress")) return;
int points = Valheiman.Api.Progression.FreePoints;
}
}- Listen instead of polling where you can:
Pov.Changedand theEventsclass.
#Features
Pov.Has(name) is true for each feature this PoV provides.
| Feature | What it gives |
|---|---|
progress, stats | level, XP, points, tree nodes; stat values by name |
events | character loaded, level up, node taken/removed, stats changed, loot rolled |
grant | give tree XP or profession XP from your mod |
crafting | the craft tree (professions) |
build | the character's path, ascendancy class and masteries |
skills.exempt | keep your mod's skills out of PoV's skill freeze |
equipment, equipment.cells, equipment.keys | equipment cells, their items, hotkeys |
equipment.host | your mod draws the equipment |
equipment.off | your mod turns PoV's equipment system off |
storage | your inventory mod keeps PoV's storage cells |
purse | coins kept in their own cells |
looks, looks.portrait | transmog; a turning character portrait for your window |
trinkets | extra trinket seats |
rows, rows.host | extra backpack rows from the tree; your mod sizes the inventory |
rarity, rarity.host, tooltip | item rarity and colours, tooltip affix rows; your mod draws rarity frames |
items.details | affixes with ids, tiers and roll ranges; implicits; corrupted, identified, item level; sockets and sigils; influences |
chests | crafting from nearby chests |
quickstack, quickstack.host | bag tidying; your mod provides the buttons |
shield | the energy shield |
hud, hud.claim | PoV's HUD pieces; your mod places them |
creatures, creatures.leave-alone | creature rarity, stars, modifiers, levels; opt your creatures out |
difficulty | the world's PoV preset and Valheim combat modifier |
text | PoV's texts in the player's language |
#Pov
Pov.Guid // "treextr.pathofvalheiman"
Pov.Version // "1.1.0" - the API's version, not the mod's
Pov.AtLeast(1, 0) // this API is 1.0 or newer within major 1
Pov.Has("storage")
Pov.Changed += areas => { /* "equipment", "keys", "purse", "looks", "progress", "host" */ };Pov.Changed fires on the main thread at most once per frame with the areas that changed.
#Progression and stats
Progression.Level; Progression.Xp; Progression.XpToNextLevel;
Progression.FreePoints; Progression.SpentPoints;
Progression.HasNode("node-id"); Progression.Nodes; // taken node ids
Progression.TreeOpen; // the tree window is open
Stats.Get("XpGainPct"); Stats.Has("TidyPack"); Stats.Names; // unknown names read 0
Shield.Enabled; Shield.Current; Shield.Max; Shield.Regenerating;
Build.Path; // dreng, skitalets, koldun, ratnik, trickster, warden - or null
Build.PathTitle; // in the player's language
Build.AscendancyClass; // or null
Build.Masteries; // category -> chosen options#Events
Events.CharacterLoaded += player => { };
Events.LevelUp += level => { };
Events.NodeTaken += nodeId => { };
Events.NodeRemoved += nodeId => { };
Events.StatsChanged += () => { }; // read Stats again
Events.LootRolled += items => { }; // PoV rolled kill loot for the local player (rarity and affixes set)A listener that throws is logged and does not stop the others.
#Grant XP from your mod
Grant.TreeXp(120f, XpKind.Kills, "my.mod"); // counted like PoV's own XP of that kind
Grant.ProfessionXp("smith", 40); // one craft-tree profession
Crafting.Professions; // miner, smith, armorer, woodcutter, builder, shipwright, sailor, hunter, herder, cook,
// brewer, beekeeper, farmer, forager, fisher, pathfinder, delver
Crafting.TotalXp; Crafting.HasNode("craft-node-id");XpKind:Combat,Kills,Crafting,Gathering,Mining,Building,Travel,Map. Each kind has its own world multiplier. Peaceful kinds (Crafting,Gathering,Mining,Building) go to the craft tree, as PoV's own do.- At most
Grant.MaxPerCall(5000) per call. Local player only: call it on the client whose player did the thing. - Typical use: an enchanting table, a new gathering activity, a quest reward.
#Skills: keep yours out of the freeze
PoV replaces skill levels with its tree: with the world setting on, every skill is frozen. A skill mod can keep its own skills working as without PoV:
// In Awake, on every machine:
SkillFreeze.Exempt(mySkillType); // true; false for a Valheim skill (those stay PoV's)
SkillFreeze.Frozen; // the freeze is on in this world
SkillFreeze.IsExempt(type);An exempt skill gains experience and reports its real level. It also keeps its level on death (PoV skips the vanilla death loss while the freeze is on).
#Equipment
PoV keeps equipment in cells. By default they are hidden rows of the player's own inventory, under the backpack. Never compute where they are: the first row is remembered per character, other mods change the inventory height, and an inventory mod may keep the cells itself (see Storage). Use the API.
Cell ids (stable): helmet, chest, legs, cape, belt, quiver, trinket, utility, utility.wisp, utility.wishbone, trinket.1, trinket.2, trinket.hand (the extra trinket seats talents open; worn seats like trinket, not storage), food.0..2, potion.0..2, arrow.0..2, tool.0..7, purse.0..7, key.0..7. Later minor versions may add cells; treat unknown ids gracefully.
Equipment.On; // the system is on
Equipment.TurnedOffFor; // the other equipment mod that keeps the slots instead, or null
foreach (CellInfo c in Equipment.Cells) { c.Id; c.Kind; c.Index; c.Title; c.Worn; }
Equipment.ItemIn(player, "food.0");
Equipment.IsOpen(player, "potion.2"); // food/potion/arrow cells depend on the belt and quiver worn
Equipment.Accepts("tool.3", item);
Equipment.Put(player, "food.1", item); // worn cells: wears the item; false if refused
Equipment.TakeOut(player, "helmet");
Equipment.GridPosition(player, "key.0"); // where the cell's item lies; (-1,-1) if none
Equipment.IsCellPosition(player, pos); // sorters and stackers: leave these positions alone
Equipment.BackpackRows(player);
Equipment.FoodCells(player); Equipment.PotionCells(player); Equipment.ArrowCells(player);
Equipment.KeyLabel("tool.0"); // "Alt+1"
Purse.Open(player); Purse.Coins(player); Purse.Empty(player);
Trinkets.Seats; Trinkets.OrdinarySeats; Trinkets.Worn(player);Turn it off. Equipment.TurnOff("my.guid") in Awake: PoV's equipment system is off as if the player switched it off (rows, window, tool bar and purse stay away; cells a save still holds go back to the backpack). TurnOff(null) gives it back from the next character load. If you only want to keep the items yourself, Storage.Register is better: PoV's rules and effects then keep working.
Draw it yourself. Equipment.Host("my.guid"): PoV keeps the cells and rules, removes its window and HUD bars and stops hiding its rows in the backpack grid. Equipment.Host(null) gives it back.
#Storage: keep PoV's cells in your inventory mod
For inventory mods that manage slots themselves. Your mod keeps where the items lie and draws them; PoV keeps every rule and effect: what a cell accepts, how many food/potion/arrow cells are open, the hotkeys, the utility items' effects, the purse's death and weight rules, transmog, the tree's extra rows.
class MyStorage : IStorageProvider
{
public string Id => "my.guid";
public int Contract => Storage.Contract; // 1
public ItemDrop.ItemData ItemIn(Player p, string cell) { ... } // never moves anything
public bool Put(Player p, string cell, ItemDrop.ItemData item) { ... } // move it, or change nothing
public bool TakeOut(Player p, string cell) { ... } // into the backpack; false if no room
}
string refused = Storage.Register(new MyStorage()); // in Awake, before a character loads; null = accepted
Storage.Changed("food.0"); // once after every committed changeStorage.Cellslists the cells you keep:food.*,potion.*,arrow.*,tool.*,purse.*,key.*,utility,utility.wisp,utility.wishbone. Armour, belt, quiver and trinket stay the game's own equipment.- Items stay real items of the player's own inventory. Return those very items, not copies.
- Check
Equipment.Accepts(cell, item)andEquipment.IsOpen(player, cell)before placing. Your own slot counts and filters do not override PoV's rules: an item a cell does not accept is ignored there (PoV reads the cell as empty). - The choice is made when the character loads and holds for the session. With a provider active, PoV never attaches its rows, never reads item positions as cells, and hands you
Rows.HostandEquipment.Host. Size the backpack withStorage.ExtraRows. - Death and weight: PoV keeps purse items out of the grave and removes their weight itself, through
ItemIn. ReadStorage.KeptOnDeathandStorage.Weightlessto show it, but do not apply it again. - Coins and keys picked up are not sorted into their cells by PoV; place them yourself if you like.
- If your provider throws, PoV logs it and pauses the cells for the session (
Storage.Suspended). It never falls back to its own rows mid-session. Unregistertakes effect from the next character load. Nothing is converted: PoV rows in an old save are not moved into your slots.- Local player only, never on a dedicated server.
#Looks (transmog)
Looks.CanChange(item); Looks.Choices(item); Looks.IsOpen(look); Looks.Current(player, item);
Looks.SameLook(a, b); Looks.HiddenLook;
Looks.WhyNot(player, item, look, canHide); // null when allowed, else a translated reason
string refused = Looks.Apply(player, list); // (item, look, canHide) tuples; one Rune of Guise each
Looks.Reset(player, item); Looks.Runes(player); Looks.RuneIcon;
using var portrait = Looks.CreatePortrait(rawImage); // Tick(player) each frame, Turn(deg), ShowBackground, TryOn#Items and tooltips
Rarity r = Items.RarityOf(item); // Common, Magic, Rare, Unique, Legendary
Items.RarityTitle(r); Items.RarityNameColor(r); Items.RarityFrameColor(r);
Items.Signature(item); // changes when anything PoV keeps on the item changes: redraw then
string type = Tooltip.Describe(item, out var rows); // AffixRow: Name, Effect, Tint, Socket, EmptySocket, Warning
Items.HostRarityFrames("my.guid"); // you draw rarity frames on inventory cells; PoV stopsEverything PoV keeps on an item, as data (feature items.details):
Items.IsCorrupted(item); Items.IsIdentified(item); Items.ItemLevel(item); Items.IsJewel(item);
foreach (AffixInfo a in Items.Affixes(item)) // empty while the item is unidentified
{
a.Id; // stable affix id from the loot catalogue, or the unique line's mechanic id
a.Place; // Prefix, Suffix or Unique (unique items and jewels)
a.Tier; // "T1", "T2" ... or ""
a.Value; // the rolled number, as the tooltip shows it
a.Min; a.Max; // the tier's roll range, already scaled for the item's slot
a.Text; // the tooltip line in the player's language
a.Local; // works on the item itself (weapon damage, armour) instead of the character
foreach (AffixStat st in a.Stats) { st.Stat; st.Form; st.Value; st.Subjects; } // PoV stat names, see Stats.Names
}
foreach (ImplicitInfo i in Items.Implicits(item)) { i.Id; i.Value; i.Min; i.Max; i.Text; } // e.g. belt food/potion slots
foreach (SocketInfo s in Items.Sockets(item)) { s.Kind; s.Sigil; } // "runic" / "corrupted" / "divine", sigil prefab or null
Items.Influences(item); // influence ids#Inventory and conveniences
Rows.Extra; // extra backpack rows the tree gives
Rows.Host("my.guid"); // you size the inventory; PoV stops changing its height
Conveniences.CraftFromChests; Conveniences.ChestReach(station); Conveniences.ChestCircleShown = true;
QuickStack.Available; QuickStack.StackKey; QuickStack.SortKey;
QuickStack.HostButtons("my.guid"); // you show the buttons; PoV's hotkeys keep working#HUD
foreach (HudPiece p in HudPieces.Pieces()) { p.Id; p.Title; p.Rect; p.ClaimedBy; }
HudPieces.Claim("level", "my.guid"); // PoV stops moving and fading it; null gives it backPiece ids: level, buffs, monolith, shield, gauges, craft-queue, tasks (more may come).
#Creatures
Creatures.RarityOf(c); // Magic, Rare, Unique from stars; Common when PoV's creature rarity is off
Creatures.Stars(c);
Creatures.ModifiersOf(c); // ids: swift, furious, armored, warded, burning, ...
Creatures.Modifiers; // every modifier: Id, Title, About
Creatures.Level(c); Creatures.BiomeLevel(Heightmap.Biome.Swamp);
Creatures.IsPovBoss(c); // PoV's own monolith bosses
Creatures.DamageFactor(c); // how much PoV multiplies its damageLeave your creatures alone. A boss overhaul or elite-creature mod that designs its creatures itself:
// In Awake, on every machine (server and clients):
Creatures.LeaveAlone("Bonemass", "my.guid");PoV then gives that prefab no rarity, stars or modifiers and does not scale its health or damage. Creatures.LeftAloneBy(prefab) tells who asked.
#Difficulty
Difficulty.Preset; // 0 vanilla creatures, 1 easy, 2 normal, 3 hard, 4 merciless
Difficulty.PresetTitle;
Difficulty.VanillaCombat; // Valheim's Combat modifier: 0 very easy ... 4 very hard, 5 none of these
Difficulty.MonsterPower(c); // altar monster power for this creature (1 = none)#Texts
Texts.Get(key, englishFallback): a PoV text in the player's language.
#Recipes
- A skill mod (new skills):
SkillFreeze.Exempt(yourSkill)in Awake. Optionally alsoGrant.TreeXpfor the activity, so it feeds the tree too. - A boss or elite-creature overhaul:
Creatures.LeaveAlone(prefab, guid)for each creature you design. - An inventory/equipment UI mod: either draw PoV's cells (
Equipment.Host+Equipment.*) or keep them yourself (Storage.Register). UseEquipment.IsCellPositionin sorting and stacking. - A HUD mod:
HudPieces.Pieces()andHudPieces.Claim, then place the rects as you like. - A loot mod: read
Items.RarityOf,Tooltip.Describe,Creatures.RarityOf/ModifiersOffor drop chances;Events.LootRolledto react to PoV's drops. - A crafting station or profession mod:
Grant.ProfessionXp(profession, xp).
#Missing something?
Ask on the PoV Discord (https://discord.gg/XZsYRF2YtQ) with what you need. New members come in minor versions.
#Changelog
- 1.1.0: trinket seat cells
trinket.1,trinket.2,trinket.hand. Known issue in PoV 5.0.9:Pov.AtLeast(1, 1)returns false there (Pov.Versionsays "1.1.0"); to detect the trinket cells, checkEquipment.Cell("trinket.1") != null. Fixed in the next update. - 1.0.0: first release.
