feat: fiche PNJ (profil + niveaux) et passage du véhicule en acteur
Release Creation / build (release) Failing after 1m17s
Release Creation / build (release) Failing after 1m17s
This commit is contained in:
+75
-62
@@ -2,17 +2,22 @@
|
||||
* DataModel pour les acteurs de type "npc" (PNJ).
|
||||
* Étend foundry.abstract.TypeDataModel.
|
||||
*
|
||||
* Note : le champ libre de compétences (texte descriptif) est nommé "freeSkills"
|
||||
* pour éviter le conflit avec le SchemaField "skills" qui contient les 30 compétences.
|
||||
* Conforme aux règles des PNJ (regles/regles_pnj.txt) : un PNJ n'a ni
|
||||
* caractéristiques chiffrées, ni réserves détaillées, ni liste de compétences.
|
||||
* Il est défini uniquement par son Profil (identité) et trois critères :
|
||||
* Menace, Expérience et Rôle. Toutes les valeurs utiles en jeu sont dérivées
|
||||
* des tableaux de référence (CONFIG.VERMINE.npc*Levels) et exposées dans
|
||||
* "system.computed".
|
||||
*
|
||||
* Note : le champ libre de description des Spécialités est nommé "freeSkills"
|
||||
* pour éviter le conflit avec le champ "skills" que le template.json historique
|
||||
* définissait comme texte libre pour les PNJ.
|
||||
*/
|
||||
import {
|
||||
woundSchema,
|
||||
combatStatusSchema,
|
||||
equipmentSchema,
|
||||
attributeSchema,
|
||||
abilitiesSchema,
|
||||
skillCategoriesSchema,
|
||||
skillsSchema
|
||||
attributeSchema
|
||||
} from "./_shared.mjs"
|
||||
|
||||
export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
||||
@@ -23,8 +28,7 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
||||
/**
|
||||
* Migration des données avant traitement par le schéma.
|
||||
* Avant DataModel, template.json définissait "skills" comme un champ texte libre
|
||||
* pour les PNJ. Le DataModel réserve "skills" pour les 30 compétences individuelles
|
||||
* (SchemaField) et utilise "freeSkills" pour le texte libre.
|
||||
* pour les PNJ. Le DataModel utilise "freeSkills" pour cette description.
|
||||
* @param {Object} source Données brutes avant validation du schéma
|
||||
* @returns {Object} Données migrées
|
||||
*/
|
||||
@@ -48,9 +52,10 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
||||
// Statut de combat (base, difficulté par défaut 9 pour PNJ)
|
||||
combatStatus: combatStatusSchema("9"),
|
||||
|
||||
// Identité
|
||||
// Identité (Profil du PNJ)
|
||||
identity: new fields.SchemaField({
|
||||
name: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
age: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
profile: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
origin: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
@@ -58,30 +63,29 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
||||
notes: new fields.HTMLField({ required: true, initial: "" })
|
||||
}),
|
||||
|
||||
// Attributs (XP, réputation, sang-froid, effort)
|
||||
attributes: new fields.SchemaField({
|
||||
xp: attributeSchema(0, 0, 10),
|
||||
reputation: attributeSchema(0, 0, 10),
|
||||
self_control: attributeSchema(0, 0, 5),
|
||||
effort: attributeSchema(0, 0, 5)
|
||||
}),
|
||||
|
||||
// Niveaux PNJ (menace, expérience, rôle)
|
||||
// Critères de définition du PNJ (Menace, Expérience, Rôle)
|
||||
threat: attributeSchema(1, 1, 4),
|
||||
experience: attributeSchema(1, 1, 4),
|
||||
role: attributeSchema(1, 1, 4),
|
||||
|
||||
// Compétences (les 30 compétences individuelles)
|
||||
skills: skillsSchema(),
|
||||
|
||||
// Description libre des compétences (champ texte PNJ)
|
||||
// Description libre des Spécialités (champ texte PNJ)
|
||||
freeSkills: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
|
||||
// Catégories de compétences
|
||||
skill_categories: skillCategoriesSchema(),
|
||||
|
||||
// Caractéristiques (8)
|
||||
abilities: abilitiesSchema(),
|
||||
// Valeurs calculées (dérivées des niveaux de menace / expérience / rôle)
|
||||
computed: new fields.SchemaField({
|
||||
attack: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
vigor: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
action: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3 }),
|
||||
specialties: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 4 }),
|
||||
rerolls: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
contact: new fields.StringField({ required: true, nullable: false, initial: "7" }),
|
||||
reaction: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3 }),
|
||||
reactionBonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
pools: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
gear: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 9 }),
|
||||
gearHindrance: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
protection: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1 })
|
||||
}),
|
||||
|
||||
// Équipement
|
||||
equipment: equipmentSchema()
|
||||
@@ -92,58 +96,67 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData()
|
||||
|
||||
// 1. Calculer les seuils de blessures selon le niveau de menace
|
||||
// 1. Calculer les valeurs dérivées selon les niveaux de menace/expérience/rôle
|
||||
this._setNpcComputedValues()
|
||||
|
||||
// 2. Calculer les seuils de blessures selon le niveau de menace
|
||||
this._setNpcWoundThresholds()
|
||||
|
||||
// 2. Calculer les réserves selon le niveau de rôle
|
||||
this._setNpcAttributes()
|
||||
|
||||
// 3. Définir les libellés des caractéristiques
|
||||
this._setAbilityLabels()
|
||||
|
||||
// 4. Mettre à jour le statut de combat
|
||||
// 3. Mettre à jour le statut de combat
|
||||
this._updateCombatStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule les seuils de blessures à partir du niveau de menace.
|
||||
* Utilise CONFIG.VERMINE.npcThreatLevels.
|
||||
* Calcule les valeurs dérivées à partir des niveaux de Menace, Expérience
|
||||
* et Rôle. Utilise CONFIG.VERMINE.npcThreatLevels, .npcExperienceLevels
|
||||
* et .npcRoleLevels.
|
||||
*/
|
||||
_setNpcComputedValues() {
|
||||
const threatLevel = this.threat?.value || 1
|
||||
const expLevel = this.experience?.value || 1
|
||||
const roleLevel = this.role?.value || 1
|
||||
|
||||
const threatConfig = CONFIG.VERMINE.npcThreatLevels[threatLevel] || {}
|
||||
const expConfig = CONFIG.VERMINE.npcExperienceLevels[expLevel] || {}
|
||||
const roleConfig = CONFIG.VERMINE.npcRoleLevels[roleLevel] || {}
|
||||
|
||||
// Menace
|
||||
this.computed.attack = threatConfig.attack || 0
|
||||
this.computed.vigor = threatConfig.vigor || 0
|
||||
|
||||
// Expérience
|
||||
this.computed.action = expConfig.action || 3
|
||||
this.computed.specialties = expConfig.specialties || 4
|
||||
this.computed.rerolls = expConfig.rerolls || 0
|
||||
this.computed.contact = expConfig.contact || "7"
|
||||
|
||||
// Rôle
|
||||
this.computed.reaction = roleConfig.reaction || 0
|
||||
this.computed.reactionBonus = roleConfig.reaction_bonus || 0
|
||||
this.computed.pools = roleConfig.pools || 0
|
||||
this.computed.gear = roleConfig.gear || 9
|
||||
this.computed.gearHindrance = roleConfig.gear_hindrance || 0
|
||||
this.computed.protection = roleConfig.protection || 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule les seuils et le nombre de boîtes de blessures à partir du
|
||||
* niveau de menace (tableau "Niveau de Menace"). Utilise
|
||||
* CONFIG.VERMINE.npcThreatLevels.
|
||||
*/
|
||||
_setNpcWoundThresholds() {
|
||||
const health = this.abilities?.health?.value || 1
|
||||
const threatLevel = this.threat?.value || 1
|
||||
const threatConfig = CONFIG.VERMINE.npcThreatLevels[threatLevel] || {}
|
||||
|
||||
this.minorWound.threshold = health
|
||||
this.majorWound.threshold = health + 3
|
||||
this.deadlyWound.threshold = Math.min(health + 7, 10)
|
||||
this.minorWound.threshold = threatConfig.minorThreshold ?? 1
|
||||
this.majorWound.threshold = threatConfig.majorThreshold ?? 4
|
||||
this.deadlyWound.threshold = threatConfig.deadlyThreshold ?? 6
|
||||
|
||||
this.minorWound.max = threatConfig.minorWound || 1
|
||||
this.majorWound.max = threatConfig.majorWound || 1
|
||||
this.deadlyWound.max = threatConfig.deadlyWound || 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit les attributs dérivés (effort, sang-froid) selon le niveau de rôle.
|
||||
* Utilise CONFIG.VERMINE.npcRoleLevels.
|
||||
*/
|
||||
_setNpcAttributes() {
|
||||
const roleLevel = this.role?.value || 1
|
||||
const roleConfig = CONFIG.VERMINE.npcRoleLevels[roleLevel] || {}
|
||||
|
||||
this.attributes.effort.max = roleConfig.pools || 0
|
||||
this.attributes.self_control.max = roleConfig.reaction_bonus || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit les libellés localisés des caractéristiques.
|
||||
*/
|
||||
_setAbilityLabels() {
|
||||
for (const [k, v] of Object.entries(this.abilities)) {
|
||||
v.label = game.i18n.localize(CONFIG.VERMINE.abilities[k]) ?? k
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour le label du statut de combat en fonction de la difficulté.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user