fix(rules): document the spell_slots data convention - JSON slots are final per-encounter budgets, engine computes no bonus spells (evidence: PC sheets carry the base class table without bonus, lich slots match no RAW daily table)

This commit is contained in:
2026-09-19 12:04:30 +02:00
parent b2739c5747
commit 1902877cfe
+17 -1
View File
@@ -962,7 +962,23 @@ Règles modélisées :
conditions de peur, écoles enchantement/divination) et les effets de zone. Toute conditions de peur, écoles enchantement/divination) et les effets de zone. Toute
condition inconnue ou non supportée reste exclue (False). condition inconnue ou non supportée reste exclue (False).
- Incantation : chaque `CombatantState` porte `spell_slots_left` (initialisé depuis - Incantation : chaque `CombatantState` porte `spell_slots_left` (initialisé depuis
le champ `spell_slots` du JSON, ex. `{"1": 4, ...}`) ; `_cast_spell` dépense le champ `spell_slots` du JSON, ex. `{"1": 4, ...}`) — convention de données :
`spell_slots` est une valeur **finale** par rencontre et le moteur ne calcule
**jamais** les sorts bonus de la caractéristique d'incantation élevée (SRD
« Abilities and Spellcasters » + Table 1-3 « Ability Modifiers and Bonus
Spells » : sagesse 18 (+4) → +1 sort par niveau 1-4) — les éventuels sorts
bonus doivent être **encodés dans le JSON par l'auteur de la fiche**.
Preuve du choix (constat 2026-09) : les fiches PJ actuelles encodent la
table de classe de BASE sans bonus (oni, clerc 4, SAG 18 → `{1:4, 2:3}` =
table de base 4/3, alors que le RAW avec bonus serait 5/4 ; nairda, sorcière
4, INT 21 → `{1:4, 2:3}` au lieu de 6/4), tandis que le liche (INT 20,
niveau d'incanteur 11) porte `{1:4, 2:4, 3:4, 4:4, 5:4, 6:3}`, qui ne
correspond à AUCUNE table quotidienne RAW (sorcier 11 : 7/7/7/6/6/4 + bonus)
— les slots sont donc un budget abstrait d'encounter authored, pas une
progression RAW ; un calcul moteur de bonus s'appliquerait sur des données
non-RAW et gonflerait arbitrairement le budget. Conséquence assumée : les
PJ incanteurs tiennent moins de sorts par rencontre que le RAW ne le
permettrait. `_cast_spell` dépense
l'emplacement du niveau concerné (`spend_spell_slot`) — **sans emplacement l'emplacement du niveau concerné (`spend_spell_slot`) — **sans emplacement
disponible, l'incantation est refusée** (journalisée `NO SPELL SLOT`, feedback disponible, l'incantation est refusée** (journalisée `NO SPELL SLOT`, feedback
`ok=False, reason="no_slot"`, aucun jet consommé) ; les cantrips (niveau 0) s'incantent librement. Le DD vaut `10 + niveau du `ok=False, reason="no_slot"`, aucun jet consommé) ; les cantrips (niveau 0) s'incantent librement. Le DD vaut `10 + niveau du