docs(rules): document 3D flight over ground terrain (airborne view: difficult terrain cost 1, cross non-LoS impassable cells, blocks_los still stops flight; elevation climb still applies; LoE/cover/high-ground unchanged) and the deferred 3D line-of-effect/maneuverability with SRD citations (Movement, Position and Distance; Aiming a Spell); map legend + grid.py notes, test count 1981
This commit is contained in:
@@ -235,6 +235,10 @@ ligne d'effet ⇒ l'attaque est impossible ; couvert ⇒ bonus de CA. Le champ
|
||||
optionnel `cover_bonus` (`2`, `4` ou `8`) encode le niveau de couvert PF1e
|
||||
(partiel +2, standard +4, amélioré +8) ; `cover: true` sans `cover_bonus`
|
||||
vaut couvert standard (+4), idem pour un terrain `blocks_los`.
|
||||
Une créature **aérienne** (vol ≥ sol, voir « Vitesse de déplacement ») ignore
|
||||
les coûts de `move_cost` > 1 et **enjambe** les cases `move_cost: null` qui ne
|
||||
portent **pas** `blocks_los` (fosses, gravats, piliers non bloquants) ; une
|
||||
case `blocks_los` (barrière solide, hauteur supposée pleine) l'arrête aussi.
|
||||
|
||||
Sémantique de `blocks_los` — **ligne d'effet, non ligne de vision** (SRD
|
||||
« Aiming a Spell — Line of Effect ») : « A line of effect is a straight,
|
||||
@@ -839,11 +843,43 @@ Règles modélisées :
|
||||
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`.
|
||||
se déplace donc à sa vitesse de vol. **Vol au-dessus du terrain (3D)** :
|
||||
une créature dont le budget vient de sa vitesse de vol (`speed_fly_ft >=
|
||||
`speed_land_ft`, `_is_airborne`) est **aérienne** et se déplace sur une
|
||||
« vue aérienne » de la grille (`Grid.airborne_view`) : le terrain difficile
|
||||
au sol (coût > 1) ne la ralentit pas (coût 1) et elle **enjambe** les cases
|
||||
infranchissables au sol (fosses, eau, gravats, piliers — `move_cost: null`
|
||||
sans `blocks_los`), conformément au SRD « Movement, Position, and Distance »
|
||||
(Terrain and Obstacles) : « Flying and incorporeal creatures are not
|
||||
hampered by difficult terrain » et « Flying and incorporeal creatures are
|
||||
able to avoid most obstacles ». **Exception** : une case qui **bloque la
|
||||
ligne d'effet** (`blocks_los` — mur/pilier, barrière solide supposée de
|
||||
hauteur pleine) **arrête aussi le vol** (elle reste infranchissable dans la
|
||||
vue aérienne). La règle des coins (diagonale) suit la même vue : un
|
||||
aérien peut passer en diagonale au ras d'une fosse (SRD « Measuring
|
||||
Distance » : « You can also move diagonally past other impassable
|
||||
obstacles, such as pits ») mais pas au ras d'un coin de mur. Les portiers
|
||||
de course/charge/pas de placement (« You can't run or charge across
|
||||
difficult terrain », « movement isn't hampered by difficult terrain ») ne
|
||||
bloquent pas un aérien, puisque son déplacement n'est pas gêné par le
|
||||
terrain. Le coût de **montée** (élévation) s'applique aussi au vol : la
|
||||
couche `elevation` encode des **marches** (hauteurs de sol), non des
|
||||
hauteurs de mur ou de falaise, et n'est donc pas survolable (simplification
|
||||
documentée). La **ligne d'effet**, le **couvert** et l'**avantage de
|
||||
hauteur** restent calculés sur la grille réelle (inchangée par le vol) :
|
||||
la géométrie de combat n'est pas affectée par le statut aérien. Les
|
||||
créatures non aériennes (`speed_fly_ft` absent, ou vol < sol) sont bit-par
|
||||
identiques (elles paient le terrain et ne traversent pas les obstacles) ;
|
||||
les transcripts dorés (arène ouverte, sol uniforme) sont inchangés. Le
|
||||
snapshot expose le budget sous la clé additive `speed_effective_ft`.
|
||||
**Hors périmètre (vol 3D incomplet)** : la **ligne d'effet 3D** (un vol à
|
||||
l'altitude X passe au-dessus d'un mur de hauteur Y, franchit le rebord
|
||||
d'une falaise) n'est **pas** modélisable — la carte ne porte aucune hauteur
|
||||
de mur ni de falaise (seule la hauteur de sol `elevation` existe, et
|
||||
`blocks_los` est un booléen « barrière solide », pas une hauteur) ; la
|
||||
**maniabilité de vol** (turn/pitch, chute en fin de tour, `hover`) et les
|
||||
autres vitesses de déplacement (natation, escalade, creusement) ne sont pas
|
||||
modélisées.
|
||||
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
|
||||
@@ -894,7 +930,11 @@ Règles modélisées :
|
||||
critique (règle du high ground). Conformance vérifiée (SRD Table 8-5
|
||||
« Attack Roll Modifiers ») : « On higher ground — Melee +1, Ranged +0 » —
|
||||
le bonus est à juste titre réservé aux attaques de mêlée, les attaques à
|
||||
distance ne le reçoivent pas. La ligne d'effet reste 2D (pas de LoS 3D).
|
||||
distance ne le reçoivent pas. La ligne d'effet reste 2D (pas de LoS 3D) :
|
||||
la couche `elevation` encode des hauteurs de **sol** (marches), non de murs
|
||||
ou falaises — survol aérien du terrain au sol modélisé (voir « Vitesse de
|
||||
déplacement »), mais la ligne d'effet 3D selon l'altitude reste hors
|
||||
périmètre faute de données de hauteur de mur.
|
||||
- Actions immédiates hors-tour : politique de réaction optionnelle
|
||||
`reaction_policy(engine, state, event)` (défaut : aucune) ; sur événement
|
||||
(`attack_resolved`, `movement_step`, `spell_cast`, `damage_taken`) une
|
||||
@@ -2078,6 +2118,20 @@ plutôt que bricolées) :
|
||||
taille — une créature Huge (3×3) est simplement bloquée par tout endroit où
|
||||
son footprint ne rentre pas ; ni le squeeze payant, ni la réduction de
|
||||
footprint dans les couloirs ne sont modélisés.
|
||||
- **Vol 3D — ligne d'effet par l'altitude hors périmètre** : le survol du
|
||||
terrain au sol est modélisé (voir « Vitesse de déplacement » : terrain
|
||||
difficile à coût 1, enjambement des obstacles non bloquants, barrières
|
||||
`blocks_los` infranchissables, SRD « Movement, Position, and Distance ») ;
|
||||
restent hors périmètre la **ligne d'effet 3D** (un vol à une altitude
|
||||
donnée passe AU-DESSUS d'un mur de hauteur finie ou franchit le rebord
|
||||
d'une falaise) et la **maniabilité de vol** (tourner/monter/plonger, chute
|
||||
en fin de mouvement, don Hover) : la carte ne porte **aucune hauteur de
|
||||
mur ni de falaise** — seule la hauteur de **sol** (`elevation`, marches)
|
||||
existe, et `blocks_los` est un booléen « barrière solide » (SRD « Aiming a
|
||||
Spell — Line of Effect »), pas une hauteur — donc « altitude du vol contre
|
||||
hauteur de l'obstacle » n'est pas exprimable dans les données ; la ligne
|
||||
d'effet reste strictement 2D et une barrière `blocks_los` est supposée de
|
||||
hauteur pleine (elle arrête aussi le vol).
|
||||
- **Passage à travers une créature (3 catégories d'écart) — approximations** :
|
||||
la règle est modélisée (traversée + AoO d'entrée, voir « Mouvement ») et le
|
||||
test d'Acrobatics « Tumbling » est désormais modélisé (voir « Acrobatics —
|
||||
@@ -2167,7 +2221,9 @@ Limites de sorts (conformance D6-D9, documentées plutôt que bricolées) :
|
||||
(dimensions, caractères connus, zones, déploiement, markers).
|
||||
- `grid.py` — grille 5-10-5 : `distance`, `step_cost` (terrain + élévation),
|
||||
règle des coins (`diagonal_allowed`), Dijkstra `reachable` avec ou sans
|
||||
budget.
|
||||
budget ; `airborne_view` = vue de la grille pour les créatures aériennes
|
||||
(terrain difficile/coûteux → coût 1, cases infranchissables non bloquantes
|
||||
→ traversables, `blocks_los` reste bloquant).
|
||||
- `los.py` — ligne d'effet et couvert par la règle des coins : gate de ligne
|
||||
d'effet dans `weapon_for`, bonus de couvert par niveau (+2/+4/+8 terrain via
|
||||
`cover_bonus`, +4 couvert mou des créatures) dans `resolve_attack`.
|
||||
@@ -2273,7 +2329,7 @@ Limites de sorts (conformance D6-D9, documentées plutôt que bricolées) :
|
||||
La gate de validation complète (tests + lint + types) :
|
||||
|
||||
```bash
|
||||
uv run pytest -q # 1970 tests
|
||||
uv run pytest -q # 1981 tests
|
||||
uv run ruff check src tests
|
||||
uv run basedpyright src # mode strict
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user