feat(rules): support multi-projectile spells
SRD Magic Missile fires one missile +1 per two caster levels beyond 1st (max 5, 1d4+1 force, auto-hit); Scorching Ray fires one ray +1 per four levels beyond 3rd (max 3, 4d6 fire, ranged touch each). DamageEffect gains a ProjectileScaling spec (JSON 'projectiles'); _apply_damage_effect loops count_for(caster_level) projectiles, each rolling its own damage and (for a declared-projectile ray) its own ranged touch attack, with the target-drops-mid-sequence convention losing the rest. Updated magic_missile.json/scorching_ray.json, the golden lich transcript (CL 11 now fires 5 missiles, Tammara dies round 1: 43 damage), the scripted MM queues in test_spells/test_conformance_spellflow, added tests/test_multi_projectile.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:
@@ -940,7 +940,27 @@ Règles modélisées :
|
||||
inchangé. Simplification documentée : le scalage ne s'applique qu'aux
|
||||
dégâts (`DamageEffect`) — les soins par niveau (Cure Light Wounds
|
||||
« +1 per caster level (maximum +5) ») ne sont pas scalés (la fiche dorée
|
||||
épingle `1d8+1`).
|
||||
épingle `1d8+1`).
|
||||
- Sorts multi-projectiles (S2b) : un `DamageEffect` peut déclarer
|
||||
`"projectiles": {"base": 1, "per_levels": 2, "at_level": 1, "max": 5}` — le
|
||||
nombre de projectiles tirés vaut `base + (niveau - at_level) // per_levels`
|
||||
(delta de niveau planché à 0), plafonné à `max` (SRD Magic Missile : « one
|
||||
missile, plus one additional missile per two caster levels beyond 1st [...]
|
||||
maximum of five » → 1 au niveau 1, 2 au niveau 4, 5 au niveau 9 ; Scorching
|
||||
Ray : `per_levels` 4, `at_level` 3, `max` 3 → 1/2/3 rayons aux niveaux
|
||||
1/7/11). À l'incantation, chaque projectile **jetle ses propres dégâts** et,
|
||||
si le sort exige une attaque de contact à distance (`requires_ranged_touch`,
|
||||
Scorching Ray), **jetle sa propre attaque de contact à distance** (couvert,
|
||||
dissimulation et menace de critique incluss — un rayon qui rate ne inflige
|
||||
rien, les autres partent quand même) ; les dégâts de sort ne sont pas réduits
|
||||
par la RD, et la résistance énergétique s'applique à chaque projectile. La RS
|
||||
est opposée une fois par cible (le moteur ne répartit pas les projectiles sur
|
||||
plusieurs cibles — toutes touchent la cible résolue). Si la cible tombe en
|
||||
cours de séquence (pv < 0 ou morte), les projectiles restants sont **perdus**
|
||||
(même convention que les attaques multiples d'une arme `count` > 1). Magic
|
||||
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.
|
||||
- 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
|
||||
@@ -1393,7 +1413,7 @@ plutôt que bricolées) :
|
||||
Dextérité/Force du CMB (conformance L1) tient compte de leur taille.
|
||||
|
||||
Limites de sorts (conformance D6-D9, documentées plutôt que bricolées — le
|
||||
moteur n'a ni projectiles multiples, ni sauvegarde partielle) :
|
||||
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
|
||||
@@ -1409,13 +1429,6 @@ moteur n'a ni projectiles multiples, ni sauvegarde partielle) :
|
||||
bien `panicked` (conformance D8), mais le moteur n'a pas de sauvegarde
|
||||
partielle pour les conditions — un succès annule totalement l'effet au lieu
|
||||
de poser `shaken` 1 round ; la durée « 1 round/niveau » est fixée à 4 rounds.
|
||||
- **Magic Missile — un seul projectile** (SRD spells/magic-missile.md :
|
||||
« You strike [...] with one missile, plus one additional missile per two
|
||||
caster levels beyond 1st [...] maximum of five missiles ») : le moteur
|
||||
n'a pas de scalage multi-projectiles ni de répartition sur plusieurs
|
||||
cibles ; le sort tire une unique missile (1d4+1 force, touche
|
||||
automatiquement) sur la cible résolue (conformance D9 — documenté, la
|
||||
fiche dorée est inchangée).
|
||||
- **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
|
||||
|
||||
Reference in New Issue
Block a user