feat(data): transpose Foundry PC sheets into data/pcs
All 8 sheets from fiches_personnages/ converted to the strict Combatant
JSON schema (data/monsters convention) so the CLI can run PCs directly:
--side players data/pcs/esha.json
- id derived from the file stem; source field points at the original sheet
- oni: placeholder attacks without encoded damage ('une Pioche', 'Weapon')
left out, documented in notes (pick stats ambiguous light/heavy in the
rules KB; no identification possible for 'Weapon')
- README: PC section now documents data/pcs usage
- tests: parametrized load check + golden spots for the 8 PC files
This commit is contained in:
@@ -232,12 +232,24 @@ Champ `range_increment_ft` (optionnel, uniquement pour `kind: ranged`) : portée
|
|||||||
maximale de tir — au-delà, l'arme n'est pas utilisable. `damage_bonus` et `dr`
|
maximale de tir — au-delà, l'arme n'est pas utilisable. `damage_bonus` et `dr`
|
||||||
sont optionnels. Deux monstres d'exemple sont fournis : gobelin et orc.
|
sont optionnels. Deux monstres d'exemple sont fournis : gobelin et orc.
|
||||||
|
|
||||||
### Fiches de personnages
|
### Fiches de personnages (PJ)
|
||||||
|
|
||||||
`fiches_personnages/` contient 8 fiches de PJ au format Foundry VTT
|
`fiches_personnages/` contient les 8 fiches de PJ au format Foundry VTT
|
||||||
(`pf1-sheet/v1`) ; le chargeur `loaders/foundry.py` sait les lire. Les
|
(`pf1-sheet/v1`) ; le chargeur `loaders/foundry.py` sait les lire. Elles sont
|
||||||
rencontres CLI se construisent pour l'instant avec des monstres JSON — les
|
transposées en JSON au schéma `Combatant` dans `data/pcs/` (`esha.json`,
|
||||||
fiches Foundry alimenteront la couche PJ dans une phase ultérieure.
|
`harvie.json`, `ierlieth.json`, `jeanne.json`, `misty.json`, `nairda.json`,
|
||||||
|
`oni.json`, `tammara.json`) et se passent directement à la CLI comme les
|
||||||
|
monstres :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run pf1e-sim --map data/maps/sample_arena.yaml \
|
||||||
|
--side players data/pcs/oni.json \
|
||||||
|
--side monsters data/pcs/tammara.json --runs 200
|
||||||
|
```
|
||||||
|
|
||||||
|
Les armes placeholder des fiches sans dégâts encodés sont omises (notées
|
||||||
|
dans `notes` le cas échéant) ; le champ `source` de chaque fichier pointe
|
||||||
|
vers la fiche Foundry d'origine.
|
||||||
|
|
||||||
## Règles implémentées et limites de la Phase 0
|
## Règles implémentées et limites de la Phase 0
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"name": "Esha Randu",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Medium",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 14,
|
||||||
|
"dex_score": 18,
|
||||||
|
"con_score": 14,
|
||||||
|
"int_score": 16,
|
||||||
|
"wis_score": 12,
|
||||||
|
"cha_score": 9
|
||||||
|
},
|
||||||
|
"hp_max": 32,
|
||||||
|
"ac": {
|
||||||
|
"total": 19,
|
||||||
|
"touch": 15,
|
||||||
|
"flat_footed": 14
|
||||||
|
},
|
||||||
|
"bab": 4,
|
||||||
|
"initiative_mod": 5,
|
||||||
|
"speed_land_ft": 25,
|
||||||
|
"saves": {
|
||||||
|
"fort": 6,
|
||||||
|
"ref": 10,
|
||||||
|
"will": 5
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Lance",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 7,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d8",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 4,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 3,
|
||||||
|
"reach_ft": 10,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Composite Shortbow +3",
|
||||||
|
"kind": "ranged",
|
||||||
|
"attack_bonus": 9,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d6",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 3,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 3,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Earth Breaker",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 8,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "2d6",
|
||||||
|
"types": [
|
||||||
|
"bludgeoning"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 4,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 3,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/esha_sheet.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"name": "Harvie",
|
||||||
|
"level": 2,
|
||||||
|
"size": "Small",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 10,
|
||||||
|
"dex_score": 15,
|
||||||
|
"con_score": 12,
|
||||||
|
"int_score": 2,
|
||||||
|
"wis_score": 14,
|
||||||
|
"cha_score": 6
|
||||||
|
},
|
||||||
|
"hp_max": 15,
|
||||||
|
"ac": {
|
||||||
|
"total": 14,
|
||||||
|
"touch": 13,
|
||||||
|
"flat_footed": 12
|
||||||
|
},
|
||||||
|
"bab": 1,
|
||||||
|
"initiative_mod": 2,
|
||||||
|
"speed_land_ft": 10,
|
||||||
|
"saves": {
|
||||||
|
"fort": 4,
|
||||||
|
"ref": 5,
|
||||||
|
"will": 2
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Talons (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 2,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"slashing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bite (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": -3,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/harvie_sheet.json",
|
||||||
|
"speed_fly_ft": 80
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"name": "Ierlieth",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Tiny",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 8,
|
||||||
|
"dex_score": 17,
|
||||||
|
"con_score": 11,
|
||||||
|
"int_score": 10,
|
||||||
|
"wis_score": 10,
|
||||||
|
"cha_score": 9
|
||||||
|
},
|
||||||
|
"hp_max": 29,
|
||||||
|
"ac": {
|
||||||
|
"total": 17,
|
||||||
|
"touch": 15,
|
||||||
|
"flat_footed": 14
|
||||||
|
},
|
||||||
|
"bab": 3,
|
||||||
|
"initiative_mod": 3,
|
||||||
|
"speed_land_ft": 15,
|
||||||
|
"saves": {
|
||||||
|
"fort": 3,
|
||||||
|
"ref": 6,
|
||||||
|
"will": 3
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Bite (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 4,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": -1,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tail (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": -1,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"bludgeoning"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/ierlieth_sheet.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"name": "Jeanne",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Large",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 18,
|
||||||
|
"dex_score": 14,
|
||||||
|
"con_score": 15,
|
||||||
|
"int_score": 2,
|
||||||
|
"wis_score": 12,
|
||||||
|
"cha_score": 6
|
||||||
|
},
|
||||||
|
"hp_max": 31,
|
||||||
|
"ac": {
|
||||||
|
"total": 23,
|
||||||
|
"touch": 11,
|
||||||
|
"flat_footed": 21
|
||||||
|
},
|
||||||
|
"bab": 3,
|
||||||
|
"initiative_mod": 2,
|
||||||
|
"speed_land_ft": 40,
|
||||||
|
"saves": {
|
||||||
|
"fort": 6,
|
||||||
|
"ref": 6,
|
||||||
|
"will": 2
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Hooves (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 8,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"bludgeoning"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 4,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bite (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 3,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d3",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 2,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/jeanne_sheet.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
{
|
||||||
|
"name": "Misty",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Medium",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 12,
|
||||||
|
"dex_score": 19,
|
||||||
|
"con_score": 14,
|
||||||
|
"int_score": 16,
|
||||||
|
"wis_score": 7,
|
||||||
|
"cha_score": 18
|
||||||
|
},
|
||||||
|
"hp_max": 31,
|
||||||
|
"ac": {
|
||||||
|
"total": 20,
|
||||||
|
"touch": 14,
|
||||||
|
"flat_footed": 16
|
||||||
|
},
|
||||||
|
"bab": 3,
|
||||||
|
"initiative_mod": 4,
|
||||||
|
"speed_land_ft": 30,
|
||||||
|
"saves": {
|
||||||
|
"fort": 7,
|
||||||
|
"ref": 9,
|
||||||
|
"will": 3
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "MWK Rapier",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 8,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d6",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 1,
|
||||||
|
"crit_range": 18,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dagger",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 7,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 1,
|
||||||
|
"crit_range": 19,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Talons (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 4,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"slashing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 1,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bite (attaque naturelle)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 4,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 1,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Unarmed Strike",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 4,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d3",
|
||||||
|
"types": [
|
||||||
|
"bludgeoning"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 1,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/misty_sheet.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"name": "Nairda Guisenda",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Medium",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 9,
|
||||||
|
"dex_score": 16,
|
||||||
|
"con_score": 14,
|
||||||
|
"int_score": 21,
|
||||||
|
"wis_score": 14,
|
||||||
|
"cha_score": 12
|
||||||
|
},
|
||||||
|
"hp_max": 31,
|
||||||
|
"ac": {
|
||||||
|
"total": 13,
|
||||||
|
"touch": 13,
|
||||||
|
"flat_footed": 10
|
||||||
|
},
|
||||||
|
"bab": 3,
|
||||||
|
"initiative_mod": 3,
|
||||||
|
"speed_land_ft": 30,
|
||||||
|
"saves": {
|
||||||
|
"fort": 4,
|
||||||
|
"ref": 5,
|
||||||
|
"will": 7
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Coup à mains nues (aucune arme encodée)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 2,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d3",
|
||||||
|
"types": [
|
||||||
|
"bludgeoning"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": -1,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attaque à distance (aucune arme encodée)",
|
||||||
|
"kind": "ranged",
|
||||||
|
"attack_bonus": 6,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d4",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/nairda_sheet.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"name": "Oni Triumvir",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Medium",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 12,
|
||||||
|
"dex_score": 14,
|
||||||
|
"con_score": 14,
|
||||||
|
"int_score": 12,
|
||||||
|
"wis_score": 18,
|
||||||
|
"cha_score": 16
|
||||||
|
},
|
||||||
|
"hp_max": 36,
|
||||||
|
"ac": {
|
||||||
|
"total": 19,
|
||||||
|
"touch": 18,
|
||||||
|
"flat_footed": 17
|
||||||
|
},
|
||||||
|
"bab": 4,
|
||||||
|
"initiative_mod": 2,
|
||||||
|
"speed_land_ft": 30,
|
||||||
|
"saves": {
|
||||||
|
"fort": 7,
|
||||||
|
"ref": 7,
|
||||||
|
"will": 9
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Longbow",
|
||||||
|
"kind": "ranged",
|
||||||
|
"attack_bonus": 6,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d8",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 3,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alchemist's Fire",
|
||||||
|
"kind": "touch",
|
||||||
|
"attack_bonus": 6,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d6",
|
||||||
|
"types": [
|
||||||
|
"fire"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attaques naturelles (Shifter Claws / formes fées)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 5,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d6",
|
||||||
|
"types": [
|
||||||
|
"slashing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 1,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/oni_sheet.json",
|
||||||
|
"notes": "Armes placeholder Foundry sans dégâts encodés omises : 'une Pioche' (non maîtrisée) et 'Weapon' (à remplacer par la vraie arme)."
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
{
|
||||||
|
"name": "Tammara Cailean",
|
||||||
|
"level": 4,
|
||||||
|
"size": "Medium",
|
||||||
|
"abilities": {
|
||||||
|
"str_score": 14,
|
||||||
|
"dex_score": 20,
|
||||||
|
"con_score": 14,
|
||||||
|
"int_score": 9,
|
||||||
|
"wis_score": 17,
|
||||||
|
"cha_score": 12
|
||||||
|
},
|
||||||
|
"hp_max": 36,
|
||||||
|
"ac": {
|
||||||
|
"total": 20,
|
||||||
|
"touch": 16,
|
||||||
|
"flat_footed": 14
|
||||||
|
},
|
||||||
|
"bab": 4,
|
||||||
|
"initiative_mod": 7,
|
||||||
|
"speed_land_ft": 30,
|
||||||
|
"saves": {
|
||||||
|
"fort": 7,
|
||||||
|
"ref": 10,
|
||||||
|
"will": 8
|
||||||
|
},
|
||||||
|
"attacks": [
|
||||||
|
{
|
||||||
|
"name": "Rapier (masterwork)",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 7,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d6",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 2,
|
||||||
|
"crit_range": 18,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Braises d'Automne (pistolet ?)",
|
||||||
|
"kind": "ranged",
|
||||||
|
"attack_bonus": 9,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d8",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 4,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Adieux du Printemps (pistolet, masterwork)",
|
||||||
|
"kind": "ranged",
|
||||||
|
"attack_bonus": 10,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d8",
|
||||||
|
"types": [
|
||||||
|
"piercing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 4,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alchemist's Fire",
|
||||||
|
"kind": "touch",
|
||||||
|
"attack_bonus": 9,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d6",
|
||||||
|
"types": [
|
||||||
|
"fire"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 0,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1,
|
||||||
|
"range_increment_ft": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Unarmed Strike",
|
||||||
|
"kind": "melee",
|
||||||
|
"attack_bonus": 6,
|
||||||
|
"damage": [
|
||||||
|
{
|
||||||
|
"formula": "1d3",
|
||||||
|
"types": [
|
||||||
|
"bludgeoning"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"damage_bonus": 2,
|
||||||
|
"crit_range": 20,
|
||||||
|
"crit_mult": 2,
|
||||||
|
"reach_ft": 5,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "fiches_personnages/tammara_sheet.json"
|
||||||
|
}
|
||||||
@@ -11,6 +11,43 @@ from pf1e_simulator.dice import DiceExpr
|
|||||||
from pf1e_simulator.loaders.monster import MonsterLoadError, load_monster
|
from pf1e_simulator.loaders.monster import MonsterLoadError, load_monster
|
||||||
|
|
||||||
MONSTERS_DIR = Path(__file__).resolve().parents[1] / "data" / "monsters"
|
MONSTERS_DIR = Path(__file__).resolve().parents[1] / "data" / "monsters"
|
||||||
|
PCS_DIR = Path(__file__).resolve().parents[1] / "data" / "pcs"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"stem",
|
||||||
|
["esha", "harvie", "ierlieth", "jeanne", "misty", "nairda", "oni", "tammara"],
|
||||||
|
)
|
||||||
|
def test_pc_sheet_loads(stem: str) -> None:
|
||||||
|
"""Every transposed PC sheet loads through the strict monster JSON path."""
|
||||||
|
combatant = load_monster(PCS_DIR / f"{stem}.json")
|
||||||
|
assert combatant.attacks
|
||||||
|
assert combatant.hp_max >= 1
|
||||||
|
assert combatant.ac.total >= 10
|
||||||
|
assert combatant.speed_land_ft >= 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_pc_sheets_golden_spots() -> None:
|
||||||
|
esha = load_monster(PCS_DIR / "esha.json")
|
||||||
|
assert esha.name == "Esha Randu"
|
||||||
|
assert [a.name for a in esha.attacks] == [
|
||||||
|
"Lance",
|
||||||
|
"Composite Shortbow +3",
|
||||||
|
"Earth Breaker",
|
||||||
|
]
|
||||||
|
assert esha.attacks[0].reach_ft == 10
|
||||||
|
assert esha.attacks[1].range_increment_ft == 70
|
||||||
|
|
||||||
|
harvie = load_monster(PCS_DIR / "harvie.json")
|
||||||
|
assert harvie.size == "Small"
|
||||||
|
assert harvie.speed_fly_ft == 80
|
||||||
|
|
||||||
|
oni = load_monster(PCS_DIR / "oni.json")
|
||||||
|
assert "Pioche" in oni.notes
|
||||||
|
assert "Weapon" in oni.notes
|
||||||
|
|
||||||
|
tammara = load_monster(PCS_DIR / "tammara.json")
|
||||||
|
assert tammara.initiative_mod == 7
|
||||||
|
|
||||||
|
|
||||||
def _write(tmp_path: Path, payload: dict[str, object]) -> Path:
|
def _write(tmp_path: Path, payload: dict[str, object]) -> Path:
|
||||||
|
|||||||
Reference in New Issue
Block a user