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:
@@ -6240,6 +6240,7 @@ class CombatEngine:
|
||||
"summary": "",
|
||||
"half_on_save": False,
|
||||
"save_negates": False,
|
||||
"harmless": False,
|
||||
"area": None,
|
||||
"cast_time": "standard",
|
||||
}
|
||||
@@ -6254,6 +6255,7 @@ class CombatEngine:
|
||||
"summary": _spell_summary(spell),
|
||||
"half_on_save": half_on_save,
|
||||
"save_negates": spell.save != "none" and not half_on_save,
|
||||
"harmless": spell.harmless,
|
||||
"area": _spell_area_dict(spell),
|
||||
"cast_time": spell.cast_time,
|
||||
}
|
||||
@@ -6710,6 +6712,35 @@ class CombatEngine:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _save_forgone(
|
||||
self, caster: CombatantState, target: CombatantState, spell: SpellSpec
|
||||
) -> bool:
|
||||
"""True when a willing target forgoes the save of a harmless spell.
|
||||
|
||||
PF1e (SRD "Spell Descriptions — Saving Throw",
|
||||
rules/prpg-core-rulebook/saving-throw.md): "(harmless): The spell is
|
||||
usually beneficial, not harmful, but a targeted creature can attempt
|
||||
a saving throw if it desires" and "Voluntarily Giving up a Saving
|
||||
Throw: A creature can voluntarily forego a saving throw and willingly
|
||||
accept a spell's result". The engine's willingness proxy is the side:
|
||||
self and same-side creatures are willing, so a spell flagged
|
||||
``harmless`` rolled on them consumes NO save die. Two faithful
|
||||
exceptions keep the roll: a hostile target is not willing (it may
|
||||
attempt the save), and a cure spell is HARMFUL to an undead target
|
||||
(SRD cure-light-wounds.md: it "deals damage to them instead of
|
||||
curing their wounds [...] can attempt a Will save to take half
|
||||
damage"), so an undead never forgoes that save.
|
||||
"""
|
||||
if not spell.harmless:
|
||||
return False
|
||||
if target is not caster and target.side != caster.side:
|
||||
return False
|
||||
return not any(
|
||||
isinstance(effect, HealEffect)
|
||||
and target.combatant.creature_type == "undead"
|
||||
for effect in spell.effects
|
||||
)
|
||||
|
||||
def _apply_and_log_cast(
|
||||
self,
|
||||
caster: CombatantState,
|
||||
@@ -6744,6 +6775,7 @@ class CombatEngine:
|
||||
target, spell.save, dc, save_descriptors=spell_save_descriptors(spell)
|
||||
)
|
||||
if spell.save != "none" and target is not None
|
||||
and not self._save_forgone(caster, target, spell)
|
||||
else None
|
||||
)
|
||||
caster_live = self._stats[caster.combatant.id]
|
||||
|
||||
Reference in New Issue
Block a user