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:
2026-09-13 12:44:35 +02:00
parent c96b36d3f9
commit 9768f5ae1d
32 changed files with 142 additions and 9 deletions
+8 -7
View File
@@ -982,7 +982,14 @@ Règles modélisées :
`d20 + niveau du jeteur` contre la SR ; si le total est inférieur, le sort est
résisté (journalisé, tous les effets annulés pour cette cible). Pour les sorts à
zone, la SR est résolue par créature touchée (pas seulement sur la cible
primaire). Les dégâts énergétiques (feu, froid, électricité, acide, son…) sont
primaire). **Drapeau `spell_resistance` par sort (S2e)** : `SpellSpec` porte un
booléen `spell_resistance` (JSON `"spell_resistance"`, défaut `true`). Quand un
sort le déclare `false` (les sorts dont la fiche SRD indique « Spell Resistance:
no » — Acid Arrow, Flurry of Snowballs, Web, Darkness, Sanctuary, les
`Protection from …`, etc. ; 28 sorts importés vérifiés contre le KB), la
vérification de SR est **totalement sautée**, tanto sur la cible directe que par
créature dans une zone. Les 28 sorts SRD « RM : non » portent désormais
`"spell_resistance": false` ; les 79 autres gardent le défaut `true`. Les dégâts énergétiques (feu, froid, électricité, acide, son…) sont
annulés par l'immunité (`immunities`) ou réduits par la résistance du type
correspondant, **composante par composante** (conformance B21, CRB « Energy
Resistance ») : chaque composante de dégâts (`DamageComponent`) est réduite
@@ -1446,12 +1453,6 @@ Limites de sorts (conformance D6-D9, documentées plutôt que bricolées) :
modélisé, S1a/S1c) : la sauvegarde partielle est désormais modélisée (panic
à l'échec, `shaken` 1 round au succès — voir « Sauvegardes partielles » plus
bas) ; seule la durée « 1 round/niveau » du `panicked` reste fixée à 4 rounds.
- **Résistance aux sorts appliquée à tout sort ciblé** : le moteur oppose la
SR du combattant à chaque sort qui le cible, sans drapeau par sort ; les
rares sorts dont la fiche SRD déclare « Spell Resistance: no » (ex. Acid
Arrow) ne sont donc pas distingués et se heurtent quand même à la SR
(conformance D9 — documenté plutôt qu'un drapeau `spell_resistance` par
sort).
## Architecture