Dafini-NorntasticSkillGrowth icon

NorntasticSkillGrowth

Skyrim-style perk trees for every Valheim skill, plus weapon forms, craft disciplines, dual wield, ally auras, prestige and respec. Optional Jewelcrafting support.

Last updated 2 weeks ago
Total downloads 433
Total rating 1 
Categories Mods AI Generated
Dependency string Dafini-NorntasticSkillGrowth-0.14.2
Dependants 0 other packages depend on this package

This mod requires the following mods to function

denikson-BepInExPack_Valheim-5.4.2350 icon
denikson-BepInExPack_Valheim

BepInEx pack for Valheim. Preconfigured with the correct entry point for mods and preferred defaults for the community.

Preferred version: 5.4.2350
ValheimModding-Jotunn-2.30.0 icon
ValheimModding-Jotunn

Jötunn (/ˈjɔːtʊn/, 'giant'), the Valheim Library was created with the goal of making the lives of mod developers easier. It enables you to create mods for Valheim using an abstracted API so you can focus on the actual content creation.

Preferred version: 2.30.0

README

Norntastic Skill Growth

Skyrim-style perk trees for every Valheim skill, four overlapping sector trees, and three experimental skills. Built against Valheim 1.0.12, BepInEx 5.4.2350, Jötunn 2.30.0.

This drop is Stages 0 through 7 — everything but the balance pass.


What works right now

  • Loads against 1.0.12 and logs every registered skill, including ones other mods added
  • High-water point tracking with a retroactive grant on first load — an existing character walks in with every point their levels have already earned
  • Perk purchase with level gates, prerequisites and a point budget
  • Refunds with downstream cascade, priced in respec points (or free, per config)
  • Prestige at level 100
  • Auto-generated stub trees for foreign skills
  • Persistence in the character's own save, travelling with the .fch across worlds
  • All 31 trees, 360 nodes and 715 ranks loaded from an editable perks.json
  • Perk effects via one aggregate status effect, with live conditions
  • A full-screen perk panel — press P — with the node graph, the skill rail, per-rank detail, buy/refund and prestige
  • Armor, Unarmored and Tavern Brawler registered as real skills, so their trees earn points like any other
  • Armor and Unarmored level from taking hits — Armor off what your gear absorbed, Unarmored only when every armour slot is empty, on a deliberately front-loaded curve
  • An on-hit dispatcher and the first handler family: bleed across Axes and Swords
  • Tavern Brawler: swing or throw any inventory item as an improvised weapon, with damage derived from what the item actually is

Effect coverage — read this before judging the mod

69 of 384 nodes currently do something. 315 are authored but not implemented.

That is not a shortfall against a plan, it is what the trees turned out to be. When every node was mapped against the status-effect API, only the unconditional numeric perks fit — damage percentages, stamina costs, regeneration, armour, carry weight. Everything else is a mechanic: a bleed, a stack counter, an active ability, a yield change, a co-op aura. Each of those needs its own code.

The breakdown of what the 313 are waiting on:

Needs Share
Bespoke combat code (bleeds, counters, on-hit, AoE) ~45%
Yield / gathering patches (ore, wood, crops, fish) ~11%
Active abilities and event triggers ~11%
Crafting, building and durability patches ~5%
Chance-based procs ~5%
Mount patches ~3%
Conditions not yet modelled ~7%
Co-op auras ~2%

So the honest roadmap is not "one more stage". It is a long tail, and the mod is built for that: PerkHandler is a one-perk-at-a-time extension point, registered by node id, and Effects/Handlers/ is where they land. Nothing in Core or Effects changes as perks go live. A perk that is not implemented says so — in the panel, in nsg.tree, and in the message when you buy it. It never silently does nothing.

The Character.Damage dispatcher is the cheapest hook in the whole plan: HitData carries m_skill, so one patch makes every "when you land a hit, do X" perk implementable without another. Eighteen authored perks are that shape. Twelve are done, and Character.IsStaggering() being public means the "against staggered targets" family rides the same hook.

Tavern Brawler

Ready an inventory item with J, swing it with G, throw it with H. Damage comes from the item — weight is the base, anything with its own edge keeps half of it, tool tier stands in for an edge on things that have no damage profile at all. Skill is worth up to +60% by level 100, roughly a weapon skill's worth.

Only items with no durability can break. A tool, a weapon, a piece of armour — anything whose SharedData sets m_useDurability — wears down instead and is never destroyed. The one edge case handled explicitly: Valheim destroys a broken item when m_destroyBroken is set, so those are floored at 1 durability and can reach broken-but-present, never gone.

Materials, food and trophies have no durability to wear, so those are what shatter, one out of the stack at a time. Heavier things survive better and skill reduces the chance further, before Careful Grip touches it. A thrown breakable always leaves your hand; the roll decides whether it is lying where it landed or gone.

Six of its twelve perks are live: Anything Goes, Careful Grip, Bottle Service, Bar Fight, Ore Toss and Closing Time.

What still doesn't work

  • No Unwoven Thread item. nsg.rp stands in for it.
  • The brawler's readied item is cycled with a key rather than picked in the inventory screen. Patching InventoryGui for a right-click-to-ready gesture is nicer and a much bigger surface to get wrong.
  • Throws are hitscan, not arcing projectiles.
  • The panel has no pan or zoom; trees are laid out to fit.
  • No custom icons for the three new skills; Jötunn's default is used.

Building

Full walkthrough, written for r2modman: BUILDING.md.

The short version:

$env:VALHEIM_INSTALL = "C:\Program Files (x86)\Steam\steamapps\common\Valheim"
$env:BEPINEX_ROOT    = "$env:APPDATA\r2modmanPlus-local\Valheim\profiles\<YourProfile>"
.\pack.ps1

Then r2modman → Settings → Import local mod and pick the zip in dist\.

The two paths are different on purpose: under r2modman, BepInEx and Jötunn live inside the profile, not the game folder, and each mod gets its own Author-ModName directory — Jötunn ends up at plugins\ValheimModding-Jotunn\Jotunn.dll. The build probes that layout and the flat one, and tells you where it looked if both miss.

ServerSync is optional. Without lib/ServerSync.dll the mod builds and runs, it just doesn't push config from the server — fine for a first build and for single player. See BUILDING.md section 6 for adding it.

Tests

./tests/run.sh

Runs the point engine and the effect layer against the real perks.json with no game, no BepInEx and no Jötunn — tests/Stubs.cs stands in for every external type. 58 assertions covering retroactivity, the high-water ratchet, sector normalisation, purchase gating, the cascade refund, prestige arithmetic, the save round-trip, effect aggregation and conditional effects. Needs mono-devel, or swap mcs for csc.

The UI, the Harmony patches and the console are excluded — they need a live game. Everything that can be tested without one, is.

Linting against the real assembly

pip install dnfile
python3 tests/lint_api.py "<Valheim>/valheim_Data/Managed/assembly_valheim.dll"

The stub compile proves the code is internally consistent, but the stubs are hand-written, so a Valheim member that does not actually exist compiles happily and throws at runtime. This checks every Valheim member the mod names against the shipped assembly. It found four invented equipment accessors on its first run — GetChestItem() and friends do not exist; Humanoid exposes m_chestItem as a public field. Run it after every Valheim update.


Installing

Drop Norntastic.dll in BepInEx/plugins/. Everyone on the server needs it — the mod declares EveryoneMustHaveMod.

On first launch it writes BepInEx/config/Norntastic/perks.json. The file on disk wins from then on, so edit trees freely and nsg.reload to pick them up without restarting.


Console

nsg.status first. Cheat commands need devcommands.

Command What
nsg.status Points earned, spent and open across every tree
nsg.trees Every tree key, kind and size
nsg.tree <key> Every node in a tree with its state, including anything held
nsg.buy <perkId> Spend a point
nsg.refund <perkId> Refund one rank, cascading downstream
nsg.clear <treeKey> Refund a whole tree, free (cheat)
nsg.prestige <treeKey> Prestige at level 100
nsg.rp [n] Grant respec points (cheat)
nsg.sethw <skillKey> <level> Set a high-water mark (cheat) — the fast way to test
nsg.reload Re-read perks.json (cheat)
nsg.panel Open the perk panel

Tavern Brawler binds G / H / J by default — swing, throw, cycle.

The quickest way to see the whole thing work:

nsg.sethw axes 100
nsg.tree axes
nsg.buy ax1
nsg.buy ax1
nsg.prestige axes
nsg.status

How the economy works

Three things are stored per character, and points are not one of them:

highWater : skillKey -> highest level ever reached   (monotonic)
allocated : perkId   -> ranks bought
prestige  : skillKey -> times prestiged

Everything else derives:

earned(skill)  = floor(highWater / interval) + prestige
earned(sector) = floor(sum(member highWater) / (5 x memberCount)) + sum(member prestige)

Why it has to work this way. Valheim 1.0 added a total skill cap: Skills.RaiseSkill calls RebalanceSkills, which — when the total is over the cap — walks the whole skill dictionary and proportionally scales every other skill down. Levelling Axes actively drains Swords. Add the DeathSkillsReset world modifier and death zeroes everything.

If points tracked the live level, players on a capped world would watch perks wink out while doing nothing wrong. They don't, because the high-water mark never moves down, and because a perk's level requirement is checked when you buy it and never again. A perk below its requirement shows as held and keeps applying.

That also makes retroactivity free: seeding highWater from current levels on first load is the retroactive grant. No migration step, no already-granted flag to get wrong.

Prestige resets the live skill but not the high-water mark, so it costs you the vanilla skill's own effectiveness and nothing else.


Known unknowns

  • Skills.m_useSkillCap and m_totalSkillCap are Unity inspector values on the Player prefab, not global keys, so the cap's default state can't be read from the assembly. Open the skills panel in game: SkillsDialog has an m_totalSkillText, so a running total means the cap is live.
  • ValheimPlus patches Skills.RaiseSkill for its own gain multipliers and separately touches stamina, carry weight, build cost and durability. Harmony composes the patches; the numbers multiply. Turn its skill/stamina/building modules off for the balance pass.

Built with AI assistance.