mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
J3 D8-c: concentration ×3 multiplier in spellExpectedDamage
`spellExpectedDamage` (`dnd_class_balance.go`) now multiplies expected
damage by 3 when `sp.Concentration && sp.Effect ∈ {EffectDamageSave,
EffectDamageAuto}`. Attack-roll concentration excluded by design —
hex-style cases ride per-hit mods, not the score. Closes the picker
gap that walked past heat_metal / spike_growth / flaming_sphere /
cloud_of_daggers in favour of one-shot blasts of similar slot level.
Measured on n=5000 d8c corpus vs d8prereq baseline (sim_results,
gitignored): per-class means all within ±2.4pp (1σ ≈ 2.2pp); macro
leaderboard unchanged. Real picker swap lands at T3 manor_blackspire
— bard +11pp, mage +10pp, sorcerer +9pp, druid +5pp. T4/T5 caster
wall unchanged → confirms HP+AC is the binding constraint past T3
(D8-d-fix territory), not picker quality.
Side discovery: cleric flat / warlock −6pp manor — spirit_guardians-
style AOE-save concentration spells appear to resolve once in
SimulateCombat / turn-engine instead of re-ticking per round. The
multiplier is correct in expectation; the engine under-delivers.
Filed as separate follow-up; D8-c stays.
Plan §8 D8-c marked SHIPPED.
This commit is contained in:
@@ -272,9 +272,19 @@ func spellExpectedDamage(s SpellDefinition, slot, charLevel int) float64 {
|
||||
}
|
||||
avgFace := (float64(faces) + 1) / 2
|
||||
avg := float64(dice)*avgFace + float64(flat)
|
||||
// Auto-damage (Magic Missile) doesn't roll to hit — count its
|
||||
// expected-on-table value at face. Attack/save spells roll, and the
|
||||
// engine will resolve hit chance at cast time.
|
||||
// Concentration damage spells (heat_metal, spirit_guardians,
|
||||
// flaming_sphere, call_lightning, spike_growth, cloud_of_daggers, …)
|
||||
// re-tick each round while concentration holds. Without this factor
|
||||
// the picker scores them as one-shots and they lose to higher-tier
|
||||
// blasts on every comparison. Conservative ×3 = roughly the median
|
||||
// fight length the picker can hope to keep concentration up; tier-
|
||||
// scaled would be more correct but adds noise here.
|
||||
// EffectDamageAttack is excluded — single-target attack-roll spells
|
||||
// aren't generally concentration; the rare ones (hex-style) get
|
||||
// their lift from mods, not this score.
|
||||
if s.Concentration && (s.Effect == EffectDamageSave || s.Effect == EffectDamageAuto) {
|
||||
avg *= 3
|
||||
}
|
||||
return avg
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user