feat(spells): allow spells to ignore spell resistance
SpellSpec gains spell_resistance: bool = True (JSON 'spell_resistance'). When false, _spell_delivery_blocked skips the targeted SR check and _apply_area_effect skips the per-creature SR check (threaded through the effect chain). Verified each imported spell against the local KB and set false on the 28 whose SRD block says 'Spell Resistance: no' (Acid Arrow, Flurry of Snowballs, Web, Darkness, Sanctuary, the Protection from X spells, etc.). Added no-SR targeted/area tests and a high-SR control in test_spell_resistance.py, and the README. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -238,6 +238,11 @@ class SpellSpec:
|
||||
# area/save-only spells keep this False.
|
||||
requires_ranged_touch: bool = False
|
||||
cast_time: CastTime = "standard"
|
||||
# PF1e (CRB, Magic — Spell Resistance): most spells are subject to a
|
||||
# target's SR, but the SRD stat block marks a handful "Spell Resistance:
|
||||
# no" (Acid Arrow, Flurry of Snowballs, ...). False = skip the SR check
|
||||
# entirely (targeted and per-creature in areas). Default True.
|
||||
spell_resistance: bool = True
|
||||
effects: tuple[SpellEffect, ...] = ()
|
||||
description: str = ""
|
||||
|
||||
@@ -573,6 +578,7 @@ def load_spell(path: str | Path) -> SpellSpec:
|
||||
base_dc=_as_int(data.get("base_dc", 10)),
|
||||
requires_ranged_touch=bool(data.get("requires_ranged_touch", False)),
|
||||
cast_time=cast_time,
|
||||
spell_resistance=bool(data.get("spell_resistance", True)),
|
||||
effects=effects,
|
||||
description=_as_str(data.get("description", "")),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user