D&D: class-balance Phase 3 — off-tier caster lift (druid + sorcerer)

Design steer from user — "relatively easy but not too easy" — narrowed the
target: lift the embarrassing caster trailers on off-tier cells (a casual
player walking into a slightly too-hard dungeon underleveled) without
pushing the already-saturated in-tier ceiling.

Levers:
- Druid passive: was the only chassis with a purely defensive passive
  (5% DR, no offense), and it read it — L1/T1 mean 0.77 (lowest at the
  entry tier), L1/T2 0.04. Added a level + WIS-scaled FlatDmgStart burst,
  same shape as the Phase-2 Bard/Mage/Warlock pass. Kept the DR; no
  DamageBonus rider so high-tier ceilings stay flat.
- Sorcerer passive: burst base 3→5. Sorcerer was second-worst caster
  off-tier (L1/T2 0.10 vs Mage 0.27 pre-tune) despite a comparable stat
  line; the bump pulls it toward arcane-chassis parity.

Observed lifts:
- Druid L1/T1: 0.77 → 0.86 (+9pp) — chassis now functional at its
  intended tier
- L2/T2 cross-class spread: 77pp → 63pp; druid trailer 0.23 → 0.35
- L1/T1 spread: 23pp → 14pp

Off-tier diagnostic: added a focused log to TestClassBalance_Phase1_FullMatrix
that names the trailing class at each off-tier (lvl, tier) cell. Not
asserted — L1 in T2 is *supposed* to be hard, so the diagnostic is for
watching the gap, not the absolute number.

In-tier parity assertion (35pp band on the diagonal) still passes;
TestApplyClassPassives updated for the new druid/sorcerer FlatDmgStart
values; full plugin -short suite clean.
This commit is contained in:
prosolis
2026-05-14 20:32:41 -07:00
parent 76f814c0c9
commit d7fe32d893
4 changed files with 114 additions and 9 deletions

View File

@@ -43,7 +43,7 @@ var dndClassAbilities = map[DnDClass]DnDClassAbility{
// CombatModifiers channels the same way the original five do.
ClassDruid: {
Name: "Wild Resilience",
Description: "The wild lends you its toughness: incoming damage is reduced 5%.",
Description: "The wild lends you its toughness incoming damage is reduced 5% — and a thorn surge on engage scaled by your Wisdom.",
},
ClassBard: {
Name: "Bardic Inspiration",
@@ -137,6 +137,14 @@ func applyClassPassives(stats *CombatStats, mods *CombatModifiers, c *DnDCharact
// subclass DamageReduct riders. DamageReduct is initialized to 1.0
// by DerivePlayerStats before passives run.
mods.DamageReduct *= 0.95
// Phase 3 class-balance: druid was the only caster chassis with a
// purely defensive passive, and the off-tier numbers showed it —
// L1/T2 mean 0.04 vs Mage 0.27. Mirror the other caster bursts so
// the L1-4 druid can chip a T2 monster: WIS-scaled FlatDmgStart on
// engage. No DamageBonus rider; the chassis keeps its defensive
// identity, and the burst alone (plus the existing DR) lifts the
// off-tier cells without pushing in-tier wins past 1.0.
mods.FlatDmgStart += c.Level + clampNonNeg(abilityModifier(c.WIS))
case ClassBard:
// Phase 2 class-balance: bare +1 initiative left Bard the weakest
// class chassis (T5 mean 0.48 pre-tune). Add a Ranger-tier rider
@@ -149,11 +157,15 @@ func applyClassPassives(stats *CombatStats, mods *CombatModifiers, c *DnDCharact
mods.FlatDmgStart += c.Level + clampNonNeg(abilityModifier(c.CHA))
case ClassSorcerer:
// Innate Sorcery — pre-combat burst, CHA-scaled like the Sorcerer's
// spellcasting stat. Floors at the flat 3 for low-CHA builds.
// spellcasting stat. Floors at the flat base for low-CHA builds.
// Phase 2 class-balance: pure FlatDmgStart faded at higher tiers as
// monster HP grew. Adding a 5% damage rider plus level scaling on the
// burst keeps the chassis relevant past L1.
mods.FlatDmgStart += 3 + c.Level + clampNonNeg(abilityModifier(c.CHA))
// Phase 3 class-balance: sorcerer was the second-worst off-tier caster
// (L1/T2 0.10 pre-tune), trailing mage by ~17pp despite a comparable
// stat line. Bump the burst base 3→5 to lift the L1-4 chassis without
// touching the +0.05 rider that already saturates at high tier.
mods.FlatDmgStart += 5 + c.Level + clampNonNeg(abilityModifier(c.CHA))
mods.DamageBonus += 0.05
case ClassWarlock:
// Phase 2 class-balance: bumped from 10% to 12% damage + 1 attack —