fix(rules): correct P1 PF1e conformance bugs (area saves, concentration, prone, slots, helpless, nauseated)

This commit is contained in:
2026-09-10 20:52:28 +02:00
parent 1ca5aed758
commit 5afe495c4a
15 changed files with 790 additions and 86 deletions
+40 -15
View File
@@ -350,8 +350,12 @@ Règles modélisées :
- Se jeter à terre (`Action(kind="drop_prone")`, action libre) : le combattant
ajoute `prone` à la liste `conditions` **sans durée**, donc la condition
persiste jusqu'à `stand_up` (contrairement à trip/overrun qui posent
`active_conditions` avec 1 round). Les modificateurs de `prone` (−4 CA, −4 aux
attaques à distance) s'appliquent immédiatement. Si la condition est déjà
`active_conditions` avec 1 round). Les modificateurs de `prone` s'appliquent
immédiatement : l'attaquant à plat ventre subit −4 à ses attaques (de mêlée
selon le CRB ; les armes à distance sont traitées comme des arbalètes —
utilisables à −4, simplification documentée), la cible à plat ventre subit
−4 CA contre les attaques de mêlée et gagne +4 CA contre les attaques à
distance. Si la condition est déjà
présente, l'action est rejetée (`already_prone`). Le kind ne requiert pas de
cible. `default_policy` ne la choisit pas (disponible via une politique
personnalisée).
@@ -555,15 +559,19 @@ Règles modélisées :
condition inconnue ou non supportée reste exclue (False).
- Incantation : chaque `CombatantState` porte `spell_slots_left` (initialisé depuis
le champ `spell_slots` du JSON, ex. `{"1": 4, ...}`) ; `_cast_spell` dépense
l'emplacement du niveau concerné (`spend_spell_slot`). Le DD vaut `10 + niveau du
l'emplacement du niveau concerné (`spend_spell_slot`) — **sans emplacement
disponible, l'incantation est refusée** (journalisée `NO SPELL SLOT`, aucun
jet consommé) ; les cantrips (niveau 0) s'incantent librement. Le DD vaut `10 + niveau du
sort + mod de la caractéristique d'incantation` (`casting_ability`), la sauvegarde
est résolue par `resolve_save`, et la RD ne réduit pas les dégâts des sorts
(`test_dr_does_not_reduce_spell_damage`). Incanter dans une
case menacée provoque des AoO ; tout dégât subi pendant l'incantation impose un
jet de concentration dont le DD dépend de la situation (`_concentration_dc`) :
`10 + dégâts + niveau` si blessé, `10 + CMB de l'adversaire + niveau` si agrippé,
sinon `15 + 2×niveau` (incantation défensive), jet = d20 + niveau + mod de CON
(+4 avec le don Combat Casting). Un sort ciblé avec sauvegarde fait pleins dégâts
sinon `15 + 2×niveau` (incantation défensive), jet = d20 + niveau + mod de
la caractéristique d'incantation (Int/Wis/Cha — jamais Constitution, CRB) ;
le don Combat Casting n'accorde son +4 qu'en incantation défensive ou quand
on est agrippé, jamais pour les dégâts subis pendant l'incantation. Un sort ciblé avec sauvegarde fait pleins dégâts
sur un échec et **aucun dégât sur un succès** (la sauvegarde annule) ; le
demi-dégât sur sauvegarde réussie ne s'applique que là où l'effet le déclare
(`half_on_save: true` pour les rayons/lignes/cônes, `AreaEffect.save_for_half`
@@ -609,9 +617,15 @@ Règles modélisées :
de Dextérité à la CA** (même chemin `denies_dex_to_ac` que flat-footed/course).
L'invisibilité est symétrique : subi comme cible, la condition accorde le
concealment total de 50 % ci-dessus.
- Cible inerme (helpless, V5a) : les attaques de **mêlée** contre une cible
`helpless` gagnent **+4 au jet d'attaque et à la confirmation** (aucun bonus à
distance) ; `helpless` porte `denies_dex_to_ac` (CA flat-footed) + `cant_act`.
- Cible inerme (helpless, V5a + conformance P1) : sont traitées comme
**inertes** les conditions `helpless`, `paralyzed`, `asleep` et
`unconscious` (CRB : inerme = paralysé, immobilisé, ligoté, endormi,
inconscient — `stunned` **ne** rend **pas** inerme). Les attaques de
**mêlée** contre une cible inerme gagnent **+4 au jet d'attaque et à la
confirmation** (aucun bonus à distance) ; la cible a une **Dextérité
effective de 0** : son modificateur de Dextérité est entièrement remplacé
par la pénalité Dex 0 (−5), en plus de la perte du bonus de Dextérité
(CA flat-footed via `denies_dex_to_ac`).
Simplification documentée : l'attaque sournoise automatique du roublard sur
cible inerme n'est pas modélisée (la cible, privée de Dextérité, la déclenche
déjà via le chemin `denies_dex_to_ac`).
@@ -639,15 +653,22 @@ Règles modélisées :
- Conditions effectives : 28 conditions prédéfinies (`conditions.py`). Leurs drapeaux
comportementaux sont appliqués par le moteur : `cant_act` (étourdi, paralysé, dazed,
endormi, inerme, fasciné) annule le tour ; `cant_attack` (nauséeux) n'autorise qu'une unique action
simple et bloque toute attaque / manœuvre ; `staggered` restreint à une action
de mouvement (`move`, `5foot_step`, `stand_up`, `drop_prone`) et bloque toute
attaque, manœuvre **et incantation** (CRB : un nauséeux ne peut ni attaquer,
ni incanter, ni se concentrer) ; `staggered` restreint à une action
simple (pas d'attaque à outrance) ; `cant_move` bloque le déplacement ;
`denies_dex_to_ac` (à plat ventre, paralysé…) fait perdre le bonus de Dextérité à
`denies_dex_to_ac` (flat-footed, paralysé, aveuglé…) fait perdre le bonus de Dextérité à
la CA (CA flat-footed) ; `miss_chance` (flou 20 %, déplacement 50 %, invisible
50 %) impose la
chance de rater du concealment. À plat ventre : −4 CA et −4 aux attaques à distance.
chance de rater du concealment. À plat ventre : l'attaquant à plat ventre
subit −4 à ses attaques (mêlée selon le CRB ; distance traitée arbalète à
−4, simplification documentée) ; la cible à plat ventre subit −4 CA contre
la mêlée et gagne +4 CA contre la distance (le CRB inverse du « −4 CA
contre tout » précédemment modélisé).
Agrippé : −4 Dextérité, −2 attaque/CA/Réflexes, sans déplacement ni AoO.
Inerme (`helpless`) : ne peut pas agir, perd sa Dextérité à la CA, +4 en mêlée
contre lui (voir « Cible inerme »). Fasciné (`fascinated`) : ne peut pas agir.
Inerme (`helpless`, `paralyzed`, `asleep`, `unconscious`) : ne peut pas agir,
Dextérité effective 0 (−5 CA en plus de la perte du bonus), +4 en mêlée
contre lui (voir « Cible inerme ») ; `stunned` ne rend pas inerte. Fasciné (`fascinated`) : ne peut pas agir.
Invisible (`invisible`) : concealment total subi +2 attaquant / perte de Dex
de la cible (voir « Attaquant invisible »).
Saignement (`bleeding`, V5b) : une créature qui saigne subit `bleed_damage`
@@ -690,8 +711,12 @@ Règles modélisées :
- Sortilèges du sorcier (witch hex) : le DD vaut `10 + niveau//2 + mod d'Intelligence`
(evil_eye, slumber, cackle) ; `cackle` prolonge d'un round les sortilèges déjà
actifs, sur une liste instantanée pour ne pas s'étendre à l'infini. Les sorts à
zone (AoE) utilisent le DD d'incantation du jeteur et, sur une sauvegarde réussie,
ne font que la moitié des dégâts.
zone (AoE) utilisent le DD d'incantation du jeteur et chaque créature de la
zone effectue la sauvegarde listée par le sort (Volonté / Réflexes /
Constitution — le sort primaire réutilise son jet déjà effectué) ; un succès
annule ou divise par deux selon ce que l'effet déclare (`save_negates` /
`half_on_save` / `AreaEffect.save_for_half`) — les zones « sauvegarde
annule » (Sleep, Color Spray, Web) sauvent donc aussi.
- Dons : les 8 PJ portent 55 noms de dons uniques ; le chargeur résout chacun d'eux
soit vers un effet réel (Power Attack actif, Weapon Focus ciblé par arme, Toughness
lié au niveau, dons passifs via `_stat_modifiers`), soit vers un « no-op » tracé en