feat(combat): use fly speed for movement

Movement budget is now max(land, fly) speed. Updates the harvie golden: Harvie (land 10 / fly 80) is a flyer and now flies at 80 ft, so he wins vs the goblin instead of being pinned crawling at 10 ft.
This commit is contained in:
2026-09-10 17:46:57 +02:00
parent ec0397351a
commit 79ac190728
4 changed files with 272 additions and 19 deletions
+19 -8
View File
@@ -412,11 +412,20 @@ Règles modélisées :
de l'arme). Une arme à allonge (`reach_ft` > 5) menace l'anneau de cases à
distance égale à son allonge — les cases à 5 ft sont une « dead zone » où
elle ne frappe pas ; une arme sans allonge menace les cases adjacentes.
Mouvement : un déplacement parcourt jusqu'à la
vitesse du combattant en cases le long du plus court chemin réel (champ de
coût Dijkstra depuis la cible, diagonales 5-10-5), en s'arrêtant adjacent à
l'ennemi le plus proche — les combattants contournent les murs au lieu
d'osciller contre eux.
Mouvement : un déplacement parcourt jusqu'à la
vitesse du combattant en cases le long du plus court chemin réel (champ de
coût Dijkstra depuis la cible, diagonales 5-10-5), en s'arrêtant adjacent à
l'ennemi le plus proche — les combattants contournent les murs au lieu
d'osciller contre eux.
Vitesse de déplacement (V4) : le budget de tout mouvement (déplacement,
charge 2×, retraite 2×, course 4×) est le **meilleur entre la vitesse au
sol (`speed_land_ft`) et la vitesse de vol (`speed_fly_ft`)** — une créature
dotée d'une vitesse de vol (harvie : vol 80 vs sol 30, ierlieth : vol 40)
se déplace donc à sa vitesse de vol. Simplification documentée : voler
PAR-DESSUS les obstacles ou le terrain difficile n'est PAS modélisé — la
praticabilité et les coûts de terrain de la grille s'appliquent à tout le
budget (pas de vol 3D ni de maniabilité) ; le snapshot expose ce budget
sous la clé additive `speed_effective_ft`.
Destination explicite : `Action(kind="move", destination=(r, c))` et
`Action(kind="5foot_step", destination=(r, c))` déplacent le combattant vers
la case `(r, c)` désignée (monter au couvert, quitter un défilé, se
@@ -686,7 +695,9 @@ Règles modélisées :
metamagic_feats (tuple trié), weapon_damage {weapon_id: dégâts courants},
summon_duration (int ou None), immediate_used, deed_up_close_and_deadly
(flags actuels), active_buffs {source, rounds_left, mods: tuple de
{target, value, bonus_type}} (E5), speed_land_ft, speed_fly_ft, ac {total,
{target, value, bonus_type}} (E5), speed_land_ft, speed_fly_ft,
speed_effective_ft (V4 : budget de déplacement effectif = max(land, fly),
en pieds), ac {total,
touch, flat_footed}, saves {fort, ref, will}, cmb, cmd, attacks
(référentiel complet : id, name, kind, attack_bonus, damage, damage_bonus,
crit_range, crit_mult, reach_ft, range_increment_ft, count, firearm —
@@ -759,8 +770,8 @@ Règles modélisées :
`channel_energy`, `hexes`, `grit`, `arcane_pool`, `bardic_rounds`, plus
`spell_slot_{level}` ajouté par le snapshot). Limites documentées : pas de
grille `reachable_ft` budget=speed (délibérément rejetée —
`movement_cost_ft` par paire + `terrain_semantics` + `speed_land_ft`
suffisent). Le couvert par paire est exposé via la clé `cover_bonus`
`movement_cost_ft` par paire + `terrain_semantics` + `speed_effective_ft`
suffisent). Le couvert par paire est exposé via la clé `cover_bonus`
(calcul identique à `resolve_attack`, couvert mou des créatures inclus).
Les API de décision exposées (items L1-L8)
s'y retrouvent : `direction`/`trick_condition`/`weapon_id` sur `Action`,