From b29dcf43609360cacf9f2204377036da33a1edd8 Mon Sep 17 00:00:00 2001 From: prosolis <5590409+prosolis@users.noreply.github.com> Date: Fri, 17 Jul 2026 17:22:06 -0700 Subject: [PATCH] combat: relabel DamageReduct comments to match calcDamage player-defender direction Review follow-up on the caster-floor rebaseline: the survival-half doc in casterBlasterFloor described an HP add the code never makes (Defense only), and the pre-existing Druid *0.95 rider still read as a damage cut when, for a player-defender through calcDamage, DamageReduct<1 raises damage taken. Comment -only; no runtime change, guardrail test unaffected. --- internal/plugin/dnd_passives.go | 17 +++++++++++------ internal/plugin/dnd_xp_test.go | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/internal/plugin/dnd_passives.go b/internal/plugin/dnd_passives.go index 780df00..131193e 100644 --- a/internal/plugin/dnd_passives.go +++ b/internal/plugin/dnd_passives.go @@ -139,9 +139,10 @@ func cantripDice(level int) int { // the primary lever is damage. Multiplicative form — the spell modifier // (INT for Mage, CHA for Sorcerer/Warlock) rides EVERY die, matching 5e // Agonizing Blast. cantripDice scales 1→4 across levels. -// - Survival: just enough HP/Def (scaled by level) that the caster lives long -// enough for the cantrip to connect the kill — NOT a tank rider. calcDamage -// defense has diminishing returns, so this leans on HP. +// - Survival: just enough Defense (scaled by level) that the caster lives long +// enough for the cantrip to connect the kill — NOT a tank rider. This adds +// Defense only (no HP add); calcDamage's diminishing returns keep the L20 +// +20 Def from becoming a wall. // // casterCantripBase / casterDefPerLevel are the caster tuning dials; see the // rebaseline plan for the sweep that set them. The cantrip floor only becomes a @@ -246,9 +247,13 @@ func applyClassPassives(stats *CombatStats, mods *CombatModifiers, c *DnDCharact mods.ExtraAttacks += 1 } case ClassDruid: - // Wild Resilience — multiplicative, so it stacks cleanly with the - // subclass DamageReduct riders. DamageReduct is initialized to 1.0 - // by DerivePlayerStats before passives run. + // Multiplicative, so it stacks cleanly with the subclass DamageReduct + // riders (DamageReduct is initialized to 1.0 by DerivePlayerStats before + // passives run). NOTE the player-defender direction: DamageReduct feeds + // calcDamage as a defense multiplier, so <1 = MORE damage taken. This + // line is therefore a mild survival trim in the same direction as the + // rebaseline *0.2 below — not the damage cut the "Wild Resilience" name + // suggests. Left as-is because the rebaseline sweep is tuned to it. mods.DamageReduct *= 0.95 // rebaseline: the Druid wins T5 rooms on the survival tiebreak, immune to // every damage lever. DamageReduct is a defense multiplier (calcDamage) — diff --git a/internal/plugin/dnd_xp_test.go b/internal/plugin/dnd_xp_test.go index 20b8bf1..17d7852 100644 --- a/internal/plugin/dnd_xp_test.go +++ b/internal/plugin/dnd_xp_test.go @@ -229,7 +229,7 @@ func TestApplyClassPassives(t *testing.T) { // -3 to-hit trim (both offset a new 2nd swing gated at L5, not seen here); // Druid took a survival trim (DR 0.95→0.19) + -0.20 damage; Bard a DR 0.4 // survival trim; Sorcerer a +1 to-hit to match the blasters; Paladin a - // 0.9 DR survival trim. Caster CantripPerRound / MaxHP / Defense adds are + // 0.9 DR survival trim. Caster CantripPerRound / Defense adds are // not asserted here. {ClassFighter, 0.05, -2, false, 0, 1.0, 0, 0}, // Phase 2 class-balance rebalance: rogue picked up +5% damage,