A client-side BepInEx mod for Valheim: choose which spirit the Spirit Caller summons next. Players without the mod only ever see vanilla things.
What it does for players is in package/README.md, which is also the mod's Thunderstore and Hexium page. Changes: CHANGELOG.md.
Made with AI assistance.
The staff's attack fires staff_SpiritCaller_spawn, an object with only a SpawnAbility and no ZNetView: it exists
only in the caster's game, and only the caster's game runs the attack (Humanoid.OnAttackTrigger checks ownership).
SpawnAbility.Spawn rolls m_spawnPrefab[Random.Range(...)] over the four spirits and creates the winner, a vanilla
creature everyone receives as usual. So choosing the spirit is a change in the caster's game alone.
Three Harmony patches:
SpawnAbility.Setupprefix: for the local player's Spirit Caller cast with a pick, the cast's ownm_spawnPrefabbecomes a one-entry array with the picked spirit before the roll. The staff's list is never written to.Player.SetControlspostfix: reads the secondary-attack press after vanilla's own rules (inventory, chat, radial menu, sitting, emoting, steering). With the Spirit Caller in hand it moves to the next pick (Random → the staff's spirits in its own order → Random) and shows a centre message. The staff has no secondary attack, so vanilla does nothing with the press. The game's own spirit names ($spiritcaller_*) are empty in every language, so the message names the animal each spirit is made from (Wolf_spiritcaller→Wolf→$enemy_wolf).KeyHints.UpdateHintspostfix: shows the secondary-attack hint while the staff is out and labels it "Next spirit", the same way the game relabels its hints; puts the game's label back afterwards.
The pick lives in memory only and goes back to Random on every scene load. The game's cap per kind (staff level, oldest unsummoned) and the casting cost are untouched.
Needs the .NET SDK (8+) and the game's DLLs (a local Valheim install, or the dedicated server's).
make build # bin/Release/PickYourSpirit.dll
make test # builds the plugin, then unit tests: the pick rules, the game members the patches use, and the hook check
make package # Algo7-PickYourSpirit-<version>.zip for r2modman's "Import local mod"The version comes from the git tag (MinVer).
CI builds and tests against the free dedicated server's DLLs (.github/scripts/valheim-managed.sh) on every push and
pull request, and every day at 06:00 UTC (.github/workflows/daily.yml, or "Run workflow" in Actions), so a game update
that breaks a hook turns it red within a day; GitHub switches the daily run off after 60 days without repository
activity (turn it back on under Actions → Daily check). The hook check (tests/HookCheck.cs, in make test) reads the
built DLL and the game DLLs with Mono.Cecil and fails when a Harmony hook's target or parameters, or a member the code
looks up by name, no longer match the game. A vX.Y.Z tag with a matching ## X.Y.Z section in CHANGELOG.md
releases to GitHub, Thunderstore and Hexium after manual approval.
| Path | What |
|---|---|
src/Plugin.cs |
Entry point, patching, scene-load reset |
src/SpiritRules.cs |
The pick rules (Unity-free, unit tested) |
src/SpiritCaller.cs |
The staff, its spirit list, the pick, the message |
src/CastPatches.cs, src/ButtonPatches.cs, src/HintPatches.cs |
The three patches |
tests/ |
Unit tests and the hook check (make test) |
package/ |
Mod page (Thunderstore and Hexium) and icon |