feat(rules): add ongoing spell damage
Acid Arrow (SRD spells/acid-arrow.md) deals 2d4 acid, then 2d4 again at the start of each of the target's turns for 1 round + 1 per three caster levels (max 6). DamageEffect gains a RecurringDamageSpec (JSON 'recurring'); a landed hit attaches a RecurringDamage source to CombatantState.recurring_damage, ticked in _turn_gate (after bleed), reduced by energy resistance/immunity but never DR (spell damage), cleared at expiry, and exposed in the observation snapshot. Extracted _resolve_one_projectile to keep _apply_damage_effect under the complexity ceiling. Updated acid_arrow.json, added tests/test_recurring_damage.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:
@@ -961,6 +961,22 @@ Règles modélisées :
|
||||
Missile (auto-touché, pas d'attaque) et Scorching Ray sont ainsi SRD-conformes
|
||||
sur le nombre de projectiles ; la fiche dorée du liche (niveau d'incanteur 11)
|
||||
tire désormais ses cinq missiles.
|
||||
- Dégâts récurrents de sort (S2c) : un `DamageEffect` peut déclarer
|
||||
`"recurring": {"formula": "2d4", "types": ["acid"], "base_rounds": 1,
|
||||
"per_levels": 3, "max": 6}` — le nombre de rounds de récurrence vaut
|
||||
`base_rounds + niveau // per_levels`, plafonné à `max` (SRD Acid Arrow :
|
||||
« 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
|
||||
niveau 1, 2 au niveau 3, 6 au niveau 18+). À l'attaque initiale réussie, une
|
||||
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
|
||||
la cible (dans `_turn_gate`, après le tick de saignement), chaque source
|
||||
jetle ses dés, est **réduite par la résistance/immunité énergétique** (acide)
|
||||
mais **jamais par la RD** (c'est un dégât de sort), inflige ce dégât, puis
|
||||
perd un round ; arrivée à 0 round elle est retirée. L'observation expose
|
||||
chaque source sous `recurring_damage` (`{formula, types, rounds_left}`).
|
||||
Simplification documentée : la neutralisation d'acide (immersion/eau) n'est
|
||||
pas modélisée — le dégât court jusqu'à l'expiration de sa durée.
|
||||
- Résistance aux sorts (SR) et résistances/immunités énergétiques : un combattant
|
||||
avec `spell_resistance > 0` oppose sa SR à chaque sort qui le cible — jet
|
||||
`d20 + niveau du jeteur` contre la SR ; si le total est inférieur, le sort est
|
||||
@@ -1340,7 +1356,10 @@ Règles modélisées :
|
||||
son tour), running (bool — course en cours jusqu'au prochain tour du
|
||||
combattant : il perd son bonus de Dextérité à la CA), bleed_damage (int —
|
||||
dégâts de saignement subis au début du tour du combattant, 0 = ne saigne
|
||||
pas ; V5b ; `bleeding`/`confused` sont visibles via `conditions`).
|
||||
pas ; V5b ; `bleeding`/`confused` sont visibles via `conditions`),
|
||||
recurring_damage (S2c — liste des sources de dégâts récurrents de sort
|
||||
actives, chacune `{formula, types, rounds_left}` ; tick au début du tour,
|
||||
réduit par résistance énergétique, jamais par la RD).
|
||||
- Par paire combattant actif × cible : target_index, distance_ft, weapon_for,
|
||||
range_penalty, can_charge, can_step5_to_attack, has_line_of_effect,
|
||||
flanking, movement_cost_ft, target_threatens_me, enemies_threatening_me,
|
||||
@@ -1415,13 +1434,6 @@ plutôt que bricolées) :
|
||||
Limites de sorts (conformance D6-D9, documentées plutôt que bricolées — le
|
||||
moteur n'a pas encore de sauvegarde partielle) :
|
||||
|
||||
- **Acid Arrow — sans dégâts continus** (SRD spells/acid-arrow.md : portée
|
||||
**longue** — corrigée, conformance D7 — et « For every three caster levels
|
||||
you possess, the acid, unless neutralized, lasts for another round [...],
|
||||
dealing another 2d4 points of damage in each round ») : le moteur n'a pas de
|
||||
subsystem de dégâts continus par sort (ni neutralisation d'acide) ; seuls les
|
||||
2d4 de dégâts initiaux sont modélisés, les rounds de dégâts persistants sont
|
||||
hors périmètre.
|
||||
- **Fear — sauvegarde totale** (SRD spells/fear.md : « each
|
||||
living creature in the area [...] becomes panicked unless it succeeds on a
|
||||
Will save [...]. If the Will save succeeds, the creature is shaken for 1
|
||||
|
||||
Reference in New Issue
Block a user