fix(rules): harmless spells on willing targets forgo the save roll - SpellSpec gains a data-driven 'harmless' flag set on the 29 SRD '(harmless)' spells (verified one by one against the KB); a same-side/self target consumes NO save die (SRD saving-throw.md: '(harmless) ... can attempt a saving throw if it desires' + 'Voluntarily Giving up a Saving Throw'), while hostile targets and undead receiving a cure (harmful to them, Will half for undead damage) keep the roll; snapshot spell summaries expose 'harmless'; golden transcript unchanged (no harmless-save cast in it); +8 tests, 3 fixtures re-pinned for the removed die
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
|
||||
SRD "Cure Light Wounds" (spells/cure-light-wounds.md): "Since undead are
|
||||
powered by negative energy, this spell deals damage to them instead of curing
|
||||
their wounds. An undead creature can apply spell resistance, and can attempt
|
||||
a Will save to take half damage." The engine resolves SR upstream and the
|
||||
their wounds. An undead creature can apply spell resistance, and can attempt a
|
||||
Will save to take half damage." The engine resolves SR upstream and the
|
||||
rolled Will save halves the damage here; living targets keep healing exactly
|
||||
as before.
|
||||
as before — and as a willing same-side target of a (harmless) spell a living
|
||||
target forgoes the Will roll entirely (no die consumed).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -70,9 +71,12 @@ class TestCureDamagesUndead:
|
||||
def test_living_target_still_heals(self) -> None:
|
||||
"""Given: a living ally at 5/20 hp
|
||||
When: cured with a die roll of 8
|
||||
Then: it heals 13 hp (behavior unchanged for the living)."""
|
||||
Then: it heals 13 hp (behavior unchanged for the living). The ally is
|
||||
a willing target of a (harmless) spell, so NO Will die is consumed
|
||||
(SRD saving-throw.md: "(harmless)" + "Voluntarily Giving up a Saving
|
||||
Throw") — the queue holds only the heal die."""
|
||||
engine, c, t = _make_engine(
|
||||
_caster(), _make_target(), [1, 8], target_pos=(1, 0), target_side="players"
|
||||
_caster(), _make_target(), [8], target_pos=(1, 0), target_side="players"
|
||||
)
|
||||
t.hp = 5
|
||||
engine._cast_spell(c, t, "Cure Light Wounds")
|
||||
@@ -96,7 +100,7 @@ class TestCureUndeadAttrition:
|
||||
|
||||
def test_living_heal_records_no_damage(self) -> None:
|
||||
engine, c, t = _make_engine(
|
||||
_caster(), _make_target(), [1, 8], target_pos=(1, 0), target_side="players"
|
||||
_caster(), _make_target(), [8], target_pos=(1, 0), target_side="players"
|
||||
)
|
||||
t.hp = 5
|
||||
engine._cast_spell(c, t, "Cure Light Wounds")
|
||||
|
||||
Reference in New Issue
Block a user