fix(rules): distinguish natural reach from reach weapons
PF1e CRB 'Big and Little Creatures in Combat': a creature's natural reach is a disk (a Large creature still threatens and strikes adjacent squares), while a reach weapon doubles the wielder's natural reach but 'can't strike at their natural reach or less' (a ring whose dead zone is the natural reach). The engine keyed the ring off reach_ft > 5, so reach-10 natural attacks (giant belostomatid bite/claw, mounted hooves) wrongly got a 5-ft dead zone. AttackSpec gains reach_weapon (parsed from the combatant JSON); the disk-vs-ring rule is centralized in _melee_reach_zone_cells and applied consistently to weapon selection, melee usability, threatened squares and charge end placement. Esha's Lance is the only reach weapon in the shipped data; Large natural attackers keep the default (disk). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -269,7 +269,13 @@ jusqu'à 10 incréments, une arme `touch` jusqu'à 5 (jet/firearm), au-delà ell
|
||||
n'est pas sélectionnable. `damage_bonus` et `dr` sont optionnels.
|
||||
Le booléen `two_handed` (optionnel, défaut `false`) marque une arme tenue à
|
||||
deux mains : Power Attack donne alors +3X (et non +2X) aux dégâts (conformance
|
||||
B16). `spell_resistance` (entier), `resistances` (dict type → montant) et
|
||||
B16). Le booléen `reach_weapon` (optionnel, défaut `false`) marque une arme
|
||||
dotée de la qualité « reach » du CRB (lance, glaive, longspear, etc.) : elle
|
||||
double l'allonge naturelle du porteur mais ne frappe pas à cette allonge
|
||||
naturelle ou moins — anneau avec dead zone (conformance R1, voir « Mêlée »).
|
||||
Le `reach_ft` d'une attaque naturelle (morsure, sabots) n'est **pas** une arme
|
||||
à allonge : il encode l'allonge naturelle de la créature, qui reste un disque.
|
||||
`spell_resistance` (entier), `resistances` (dict type → montant) et
|
||||
`immunities` (liste de types) sont optionnels.
|
||||
Deux monstres d'exemple sont fournis : gobelin et orc.
|
||||
|
||||
@@ -565,11 +571,19 @@ Règles modélisées :
|
||||
aucun jet n'est effectué. Sans `weapon_id`, la sélection automatique est
|
||||
inchangée. `default_policy` ne choisit pas d'arme (disponible via une
|
||||
politique personnalisée).
|
||||
- Mêlée : allonge effective = max(allonge naturelle du gabarit (Small/Medium
|
||||
5 ft, Large 10 ft, Huge 15 ft, Gargantuan 20 ft, Colossal 30 ft), `reach_ft`
|
||||
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.
|
||||
- Mêlée (conformance R1, CRB « Big and Little Creatures in Combat ») :
|
||||
l'**allonge naturelle** du gabarit (Small/Medium 5 ft, Large 10 ft, Huge
|
||||
15 ft, Gargantuan 20 ft, Colossal 30 ft) est un **disque** : la créature
|
||||
frappe et menace toutes les cases jusqu'à son allonge, l'adjacence
|
||||
comprise — une créature Large dont l'attaque naturelle a `reach_ft` 10
|
||||
menace donc aussi les cases adjacentes (le `reach_ft` d'une attaque
|
||||
naturelle EST son allonge naturelle). Une **arme à allonge**
|
||||
(`reach_weapon: true` dans le JSON) est un **anneau** : elle double
|
||||
l'allonge naturelle du porteur mais ne frappe pas à l'allonge naturelle ou
|
||||
moins — la zone utilisable est `allonge naturelle < distance ≤ 2 ×
|
||||
allonge naturelle`, la dead zone vaut donc 5 ft pour un porteur
|
||||
Small/Medium et 10 ft pour un porteur Large. Une arme ordinaire sans
|
||||
allonge menace les cases adjacentes (disque de 5 ft).
|
||||
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 à
|
||||
@@ -647,9 +661,9 @@ Règles modélisées :
|
||||
(étourdi/paralysé ne flanque pas). Les attaques à distance ignorent le
|
||||
flanquement ; un allié désarmé ou à distance ne compte pas.
|
||||
- Attaques d'opportunité : un combattant actif doté d'une arme de mêlée menace
|
||||
les cases à distance de son allonge effective (les 8 cases adjacentes pour
|
||||
une arme sans allonge ; l'anneau à son allonge pour une arme reach — la
|
||||
dead zone de 5 ft n'est pas menacée). Deux déclencheurs sont modélisés : (1) quitter une
|
||||
les cases de sa zone d'allonge (voir « Mêlée » : le disque de l'allonge
|
||||
naturelle — les 8 cases adjacentes pour un Small/Medium sans allonge — ou
|
||||
l'anneau d'une arme à allonge, dont la dead zone n'est pas menacée). Deux déclencheurs sont modélisés : (1) quitter une
|
||||
case menacée — le mouvement est résolu pas à pas, et chaque ennemi qui menace
|
||||
la case actuelle porte une AoO avant que le mouvant ne la quitte ; (2) tirer
|
||||
avec une arme à distance depuis une case menacée — chaque ennemi menaçant
|
||||
|
||||
Reference in New Issue
Block a user