fix(rules): README/abilities wording - grapple applies only grappled (pin out of scope), pinned/nauseated cant_attack, confused no-AoO, Weapon Focus group matching

This commit is contained in:
2026-09-16 20:31:49 +02:00
parent 3a5948c35c
commit e89ea42168
3 changed files with 21 additions and 7 deletions
+13 -4
View File
@@ -1218,7 +1218,7 @@ Règles modélisées :
(`_expire_summons` décrémente puis retire).
- 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
endormi, inerme, fasciné) annule le tour ; `cant_attack` (nauséeux, épinglé) n'autorise qu'une unique action
de mouvement — conformance L9 (SRD « Conditions — Nauseated ») : « The only
action such a character can take is a single move actions per turn » — seuls
les vraies actions de mouvement (`move`, `stand_up`, `retrieve_weapon`,
@@ -1242,7 +1242,11 @@ Règles modélisées :
désormais réellement aux compétences de Dexterity (Acrobaties, Escalade,
Équilibre, Évasion, Vol, Équitation, Manipulation de corde, Discrétion,
Natation, Désamorçage — conformance P2) —, −2 attaque/CA/Réflexes, sans
déplacement ni AoO. Épinglé : même −4 `dex_skills`.
déplacement ni AoO. Épinglé : même −4 `dex_skills`, et `cant_attack` — un
épinglé ne peut pas attaquer (SRD « Conditions — Pinned » : il « peut
seulement tenter de se libérer ») ; lacune documentée : le moteur ne pose
**jamais** `pinned` (pas de boucle de maintien du grapple), la condition
n'est atteignable que par injection directe.
Aveuglé (conformance P2) : −2 CA, perte du bonus de Dextérité à la CA, −4
aux compétences de Dexterity (`dex_skills`) et **aucun malus plat
d'attaque** — la pénalité RAW est la dissimulation totale (50 % d'échec,
@@ -1271,7 +1275,9 @@ Règles modélisées :
ennemi, une seule si en allonge ; sinon le tour est perdu, journalisé).
Simplification documentée : la clause « si elle est blessée, riposte
l'agresseur » est réduite à « attaque la créature la plus proche » ; le coup
de grâce n'est pas modélisé.
de grâce n'est pas modélisé. Une créature confuse ne fait **aucune**
attaque d'opportunité (`cant_aoo`) — simplification de la clause SRD « not
already devoted to attacking », le moteur n'ayant pas ce concept.
- Manœuvres de combat : trip, disarm, bull_rush, sunder, grapple, escape,
overrun, dirty trick, steal, reposition et drag sont modélisées, chacune
comme une tentative unique (1d20 + CMB contre CMD) : le jet de manœuvre est
@@ -1326,7 +1332,10 @@ Règles modélisées :
your attack exceeds your opponent's CMD you can push the target back an
additional 5 feet » — `1 + marge//5` cases, stoppées au premier obstacle
(un 20 naturel sous le CMD ne donne que la poussée de base) ;
grapple → `grappled`/`pinned` ; conformance L8 (SRD « Grapple ») : « If
grapple → `grappled` uniquement (la boucle de maintien du grapple et
l'application de `pinned` sont hors périmètre du moteur — la définition
de la condition `pinned` est conforme au SRD, mais elle n'est jamais
posée par le moteur lui-même) ; conformance L8 (SRD « Grapple ») : « If
you successfully grapple a creature that is not adjacent to you, move
that creature to an adjacent open space (if no space is available, your
grapple fails) » — une réussite à distance **tire la cible** sur la case
+4 -1
View File
@@ -37,7 +37,10 @@ class AbilitySpec:
# ── Passive combat feats ─────────────────────────────────────────────────────
# Weapon Focus: +1 attack with a specific weapon (untyped, CRB)
# Weapon Focus: +1 attack with the named weapon GROUP (untyped, CRB) — the
# filter matches a weapon name case-insensitively as a substring (the engine
# resolves it in CombatEngine._weapon_filter_matches), so "Pistol" covers
# sheets that name individual pistols (e.g. "... (pistolet, masterwork)").
def weapon_focus(weapon_name: str) -> AbilitySpec:
return AbilitySpec(
name=f"Weapon Focus ({weapon_name})",
+4 -2
View File
@@ -2571,8 +2571,10 @@ class CombatEngine:
"""Collect all StatModifiers for ``target`` from all sources.
``weapon_name`` filters out modifiers with a ``weapon_filter`` that
doesn't match (e.g. Weapon Focus (Pistol) only applies to "Pistol").
Modifiers without a ``weapon_filter`` are always included.
doesn't match (e.g. Weapon Focus (Pistol) only applies to weapons
whose name contains "Pistol", case-insensitively — see
``_weapon_filter_matches``). Modifiers without a ``weapon_filter``
are always included.
Modifiers whose ``condition`` is set are only included when the named
runtime condition holds for ``state`` (evaluated via