fix(rules): bear's endurance +2 hp per Hit Die via split flat scaling, aid morale scoped to fear-descriptor saves (SRD spells/aid.md), charm person range close per SRD spells/charm-person.md, README synced (29 conditions, acid arrow total cap, mirror image instance-level miss chance)

This commit is contained in:
2026-09-19 13:34:30 +02:00
parent 35ce41e5f9
commit b95533d49f
5 changed files with 29 additions and 16 deletions
+12 -8
View File
@@ -1133,11 +1133,11 @@ Règles modélisées :
tire désormais ses cinq missiles. tire désormais ses cinq missiles.
- Dégâts récurrents de sort (S2c) : un `DamageEffect` peut déclarer - Dégâts récurrents de sort (S2c) : un `DamageEffect` peut déclarer
`"recurring": {"formula": "2d4", "types": ["acid"], "base_rounds": 1, `"recurring": {"formula": "2d4", "types": ["acid"], "base_rounds": 1,
"per_levels": 3, "max": 6}` — le nombre de rounds de récurrence vaut "per_levels": 3, "max": 7}` — le nombre de rounds de récurrence vaut
`base_rounds + niveau // per_levels`, plafonné à `max` (SRD Acid Arrow : `base_rounds + niveau // per_levels`, plafonné à `max` **en total** (SRD Acid Arrow :
« For every three caster levels you possess, the acid [...] lasts for another « For every three caster levels you possess, the acid [...] lasts for another
round [...] dealing another 2d4 points of damage in each round » → 1 round au round [...] dealing another 2d4 points of damage in each round » → 1 round au
niveau 1, 2 au niveau 3, 6 au niveau 18+). À l'attaque initiale réussie, une niveau 1, 2 au niveau 3, 7 au niveau 18+ : 1 + 6 rounds additionnels). À l'attaque initiale réussie, une
source de dégâts récurrents (`RecurringDamage` sur le `CombatantState`, liste source de dégâts récurrents (`RecurringDamage` sur le `CombatantState`, liste
`recurring_damage`) est posée sur la cible vivante ; au **début du tour** de `recurring_damage`) est posée sur la cible vivante ; au **début du tour** de
la cible (dans `_turn_gate`, après le tick de saignement), chaque source la cible (dans `_turn_gate`, après le tick de saignement), chaque source
@@ -1184,7 +1184,11 @@ Règles modélisées :
portent un champ `miss_chance` ; quand la portent un champ `miss_chance` ; quand la
cible en porte une, après la touche et la confirmation de critique, le moteur cible en porte une, après la touche et la confirmation de critique, le moteur
tire un d100 : si `d100 ≤ miss_chance`, l'attaque rate complètement (aucun tire un d100 : si `d100 ≤ miss_chance`, l'attaque rate complètement (aucun
dégât, pas de critique, deed non consommé — journalisé « concealment »). Une dégât, pas de critique, deed non consommé — journalisé « concealment »). Le
champ est porté par l'**instance** de condition, pas seulement par la
définition : Mirror Image (SRD spells/mirror-image.md) jette ses images à
l'incantation (1d4 + 1 par 3 niveaux, max 8) et impose une instance `blurred`
dont le `miss_chance` vaut `images/(images+1)` en pourcentage. Une
cible avec **n'importe quelle dissimulation** (`miss_chance > 0` — flou 20 % cible avec **n'importe quelle dissimulation** (`miss_chance > 0` — flou 20 %
comme dissimulation totale 50 %) ne peut pas être la victime d'une attaque comme dissimulation totale 50 %) ne peut pas être la victime d'une attaque
sournoise (conformance A7 — SRD rogue « Sneak Attack » : sournoise (conformance A7 — SRD rogue « Sneak Attack » :
@@ -1259,7 +1263,7 @@ Règles modélisées :
convention de scalage par niveau que `ConditionEffect` (voir « Formes de zone et convention de scalage par niveau que `ConditionEffect` (voir « Formes de zone et
scalage »). Les deux sorts importés (`summon_monster_i/ii.json`) portent scalage »). Les deux sorts importés (`summon_monster_i/ii.json`) portent
`duration_rounds_per_level: 1`. `duration_rounds_per_level: 1`.
- Conditions effectives : 28 conditions prédéfinies (`conditions.py`). Leurs drapeaux - Conditions effectives : 29 conditions prédéfinies (`conditions.py`). Leurs drapeaux
comportementaux sont appliqués par le moteur : `cant_act` (étourdi, paralysé, dazed, comportementaux sont appliqués par le moteur : `cant_act` (étourdi, paralysé, dazed,
endormi, inerme, fasciné) annule le tour ; `cant_attack` (nauséeux, épinglé) 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 de mouvement — conformance L9 (SRD « Conditions — Nauseated ») : « The only
@@ -1617,7 +1621,7 @@ Règles modélisées :
case de leur conjurateur), case de leur conjurateur),
terrain_semantics (un dict par type de terrain : type, move_cost, terrain_semantics (un dict par type de terrain : type, move_cost,
blocks_los, cover, cover_bonus), condition_definitions (C2 : tuple trié de (nom, blocks_los, cover, cover_bonus), condition_definitions (C2 : tuple trié de (nom,
{mods, flags, speed_mult, miss_chance}) — définitions complètes des 28 {mods, flags, speed_mult, miss_chance}) — définitions complètes des 29
conditions de CONDITIONS_BY_NAME pour que la LLM interprète les drapeaux, conditions de CONDITIONS_BY_NAME pour que la LLM interprète les drapeaux,
les modificateurs et les chances de rater (concealment)). les modificateurs et les chances de rater (concealment)).
Les helpers publics du moteur (L5) sont désormais embarqués EN DONNÉES dans Les helpers publics du moteur (L5) sont désormais embarqués EN DONNÉES dans
@@ -1770,11 +1774,11 @@ Limites de sorts (conformance D6-D9, documentées plutôt que bricolées) :
enhancement…) gardent la valeur la plus élevée. Les pénalités suivent les enhancement…) gardent la valeur la plus élevée. Les pénalités suivent les
mêmes règles. Fondation pour sorts, conditions, dons et capacités de classe. mêmes règles. Fondation pour sorts, conditions, dons et capacités de classe.
- `conditions.py` — conditions PF1e : `Condition` (dataclass avec - `conditions.py` — conditions PF1e : `Condition` (dataclass avec
modificateurs + flags comportementaux + `miss_chance`) et 28 conditions prédéfinies modificateurs + flags comportementaux + `miss_chance`) et 29 conditions prédéfinies
(shaken, sickened, fatigued, exhausted, entangled, dazzled, blinded, (shaken, sickened, fatigued, exhausted, entangled, dazzled, blinded,
deafened, flat-footed, prone, stunned, paralyzed, nauseated, dazed, deafened, flat-footed, prone, stunned, paralyzed, nauseated, dazed,
staggered, frightened, panicked, cowering, helpless, fascinated, invisible, staggered, frightened, panicked, cowering, helpless, fascinated, invisible,
bleeding, confused). bleeding, confused, bane).
Les modificateurs sont intégrés Les modificateurs sont intégrés
à `resolve_attack` (attaque, dégâts, CA) et `resolve_save` (jets de à `resolve_attack` (attaque, dégâts, CA) et `resolve_save` (jets de
sauvegarde) via `_stat_modifiers` qui collecte effets + conditions ; les sauvegarde) via `_stat_modifiers` qui collecte effets + conditions ; les
+4 -2
View File
@@ -11,10 +11,12 @@
"type": "buff", "type": "buff",
"modifiers": [ "modifiers": [
{ "target": "attack", "value": 1, "bonus_type": "morale" }, { "target": "attack", "value": 1, "bonus_type": "morale" },
{ "target": "will", "value": 1, "bonus_type": "morale" } { "target": "fort", "value": 1, "bonus_type": "morale", "condition": "fear" },
{ "target": "ref", "value": 1, "bonus_type": "morale", "condition": "fear" },
{ "target": "will", "value": 1, "bonus_type": "morale", "condition": "fear" }
], ],
"duration_rounds": 10 "duration_rounds": 10
} }
], ],
"description": "The subject gains a +1 morale bonus on attack rolls and on saving throws against fear effects (modeled as Will). Duration 10 min/level approximated as 10 rounds." "description": "SRD spells/aid.md: the subject gains a +1 morale bonus on attack rolls and on saves against fear effects, plus temporary hit points equal to 1d8 + caster level (maximum 1d8+10). The save bonus is scoped to fear effects via the descriptor-conditioned modifiers (all three saves, replacing the previous unconditional Will-only approximation). The temporary hit points are deferred: CombatantState has no temp-HP track (same gap as the virtue cantrip). Duration 1 min/level approximated as 10 rounds."
} }
+10 -3
View File
@@ -10,11 +10,18 @@
{ {
"type": "buff", "type": "buff",
"modifiers": [ "modifiers": [
{ "target": "fort", "value": 2, "bonus_type": "enhancement" }, { "target": "fort", "value": 2, "bonus_type": "enhancement" }
{ "target": "hp", "value": 2, "bonus_type": "enhancement" }
], ],
"duration_rounds": 60 "duration_rounds": 60
},
{
"type": "buff",
"modifiers": [
{ "target": "hp", "value": 0, "bonus_type": "enhancement" }
],
"duration_rounds": 60,
"scaling_flat": { "amount": 2, "per_levels": 1, "max": 40 }
} }
], ],
"description": "The subject gains a +4 enhancement bonus to Constitution, granting +2 to Fortitude saves and +2 hit points per Hit Die (SRD bear's endurance; the hp modifier is informational — the engine has no per-HD hp pool). Will negates (harmless). Duration 10 min/level approximated as 60 rounds." "description": "SRD spells/bear-s-endurance.md: the subject gains a +4 enhancement bonus to Constitution - +2 to Fortitude saves and +2 hit points per Hit Die - for 10 min./level. The engine has no ability-score track, so the +4 Con is encoded as its combat consequences: an unscaled +2 Fortitude enhancement, and a separate hp modifier carrying the per-HD bonus via flat scaling (+2 per level, capped at +40 for level 20; caster level stands in for the target's Hit Dice, and the hp target is informational - the engine has no per-HD hp pool). Will negates (harmless). Duration 10 min/level approximated as 60 rounds."
} }
+2 -2
View File
@@ -2,7 +2,7 @@
"name": "Charm Person", "name": "Charm Person",
"level": 1, "level": 1,
"school": "enchantment", "school": "enchantment",
"range": "medium", "range": "close",
"save": "will", "save": "will",
"base_dc": 10, "base_dc": 10,
"cast_time": "standard", "cast_time": "standard",
@@ -14,5 +14,5 @@
"save_negates": true "save_negates": true
} }
], ],
"description": "The charmed person regards the caster as a trusted friend (modeled as the fascinated condition; the charmed condition is not in the engine). Duration 1 hour/level approximated as 100 rounds. Will negates." "description": "SRD spells/charm-person.md: range close (25 ft. + 5 ft./2 levels) - corrected from the previous medium approximation. The charmed person regards the caster as a trusted friend; the engine has no charmed condition, so it is modeled as fascinated (the subject takes no actions). Duration 1 hour/level approximated as 100 rounds. Will negates."
} }
+1 -1
View File
@@ -45,7 +45,7 @@ _BATCH1: dict[str, tuple[str, int, str, str, str]] = {
"Bleed": ("bleed", 0, "necromancy", "close", "will"), "Bleed": ("bleed", 0, "necromancy", "close", "will"),
"Bless": ("bless", 1, "enchantment", "medium", "none"), "Bless": ("bless", 1, "enchantment", "medium", "none"),
"Blindness/Deafness": ("blindness_deafness", 2, "necromancy", "medium", "fort"), "Blindness/Deafness": ("blindness_deafness", 2, "necromancy", "medium", "fort"),
"Charm Person": ("charm_person", 1, "enchantment", "medium", "will"), "Charm Person": ("charm_person", 1, "enchantment", "close", "will"),
"Color Spray": ("color_spray", 1, "illusion", "close", "will"), "Color Spray": ("color_spray", 1, "illusion", "close", "will"),
"Comprehend Languages": ("comprehend_languages", 1, "divination", "personal", "none"), "Comprehend Languages": ("comprehend_languages", 1, "divination", "personal", "none"),
"Create Alcool": ("create_alcool", 0, "conjuration", "close", "none"), "Create Alcool": ("create_alcool", 0, "conjuration", "close", "none"),