Fix apv2, WIP
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* DataModel pour les acteurs de type "character" (personnage).
|
||||
* Étend foundry.abstract.TypeDataModel.
|
||||
*/
|
||||
import {
|
||||
woundSchema,
|
||||
combatStatusSchema,
|
||||
equipmentSchema,
|
||||
attributeSchema,
|
||||
abilitiesSchema,
|
||||
skillCategoriesSchema,
|
||||
skillsSchema
|
||||
} from "./_shared.mjs"
|
||||
|
||||
export default class VermineCharacterData extends foundry.abstract.TypeDataModel {
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["VERMINE.character"]
|
||||
|
||||
/** @override */
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
|
||||
return {
|
||||
// Blessures (base)
|
||||
minorWound: new fields.SchemaField(woundSchema(1, 5)),
|
||||
majorWound: new fields.SchemaField(woundSchema(4, 4)),
|
||||
deadlyWound: new fields.SchemaField(woundSchema(8, 2)),
|
||||
|
||||
// Statut de combat (base)
|
||||
combatStatus: combatStatusSchema("7"),
|
||||
|
||||
// Adaptation (totems humain/adapté)
|
||||
adaptation: new fields.SchemaField({
|
||||
value: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1, min: 0, max: 5 }),
|
||||
min: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
|
||||
max: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 5, min: 0 }),
|
||||
totems: new fields.SchemaField({
|
||||
human: new fields.SchemaField({
|
||||
value: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1, min: 0, max: 3 }),
|
||||
min: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
|
||||
max: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3, min: 0 })
|
||||
}),
|
||||
adapted: new fields.SchemaField({
|
||||
value: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1, min: 0, max: 3 }),
|
||||
min: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
|
||||
max: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3, min: 0 })
|
||||
})
|
||||
})
|
||||
}),
|
||||
|
||||
// Identité
|
||||
identity: new fields.SchemaField({
|
||||
height: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
weight: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
age: new fields.StringField({ required: true, nullable: false, initial: "15" }),
|
||||
ageType: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 2 }),
|
||||
profile: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
instincts: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
prohibits: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
objectives: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
relations: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
biography: new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
}),
|
||||
|
||||
// Équipement
|
||||
equipment: equipmentSchema(),
|
||||
|
||||
// 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)
|
||||
}),
|
||||
|
||||
// Rencontres
|
||||
encounters: new fields.ArrayField(new fields.StringField({ required: true, nullable: false, initial: "" })),
|
||||
|
||||
// Caractéristiques (8)
|
||||
abilities: abilitiesSchema(),
|
||||
|
||||
// Catégories de compétences
|
||||
skill_categories: skillCategoriesSchema(),
|
||||
|
||||
// Compétences (30)
|
||||
skills: skillsSchema()
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData()
|
||||
|
||||
// 1. Déterminer la tranche d'âge
|
||||
this._setAgeType()
|
||||
|
||||
// 2. Calculer les modificateurs de caractéristiques
|
||||
this._setAbilityModifiers()
|
||||
|
||||
// 3. Calculer les réserves (sang-froid et effort)
|
||||
this._setSelfControlMax()
|
||||
this._setEffortMax()
|
||||
|
||||
// 4. Calculer les seuils de blessures
|
||||
this._setWoundThresholds()
|
||||
|
||||
// 5. Mettre à jour le statut de combat
|
||||
this._updateCombatStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
* Détermine la tranche d'âge (1=jeune, 2=adulte, 3=vieux)
|
||||
* à partir de l'âge et de la config VERMINE.AgeTypes.
|
||||
*/
|
||||
_setAgeType() {
|
||||
const age = this.identity.age
|
||||
const ageTypes = CONFIG.VERMINE.AgeTypes
|
||||
for (const [type, cfg] of Object.entries(ageTypes)) {
|
||||
if (age >= parseInt(cfg.beginning, 10)) {
|
||||
this.identity.ageType = parseInt(type, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule les modificateurs de caractéristiques (règle d20).
|
||||
*/
|
||||
_setAbilityModifiers() {
|
||||
for (const ability of Object.values(this.abilities)) {
|
||||
ability.mod = Math.floor((ability.value - 10) / 2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le max de sang-froid :
|
||||
* somme des caractéristiques mentales + sociales + modificateur d'âge.
|
||||
*/
|
||||
_setSelfControlMax() {
|
||||
const abilities = Object.values(this.abilities)
|
||||
const modFromAge = this._getModFromAgeSelfControl()
|
||||
const sum = abilities
|
||||
.filter(a => a.category === "mental" || a.category === "social")
|
||||
.reduce((acc, a) => acc + a.value, 0)
|
||||
this.attributes.self_control.max = sum + modFromAge
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le max d'effort :
|
||||
* somme des caractéristiques physiques + manuelles + modificateur d'âge.
|
||||
*/
|
||||
_setEffortMax() {
|
||||
const abilities = Object.values(this.abilities)
|
||||
const modFromAge = this._getModFromAgeEffort()
|
||||
const sum = abilities
|
||||
.filter(a => a.category === "physical" || a.category === "manual")
|
||||
.reduce((acc, a) => acc + a.value, 0)
|
||||
this.attributes.effort.max = sum + modFromAge
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule les seuils de blessures à partir de la Santé.
|
||||
*/
|
||||
_setWoundThresholds() {
|
||||
const health = this.abilities.health.value
|
||||
const ageMods = this._getModFromAgeWounds()
|
||||
|
||||
this.minorWound.threshold = health
|
||||
this.majorWound.threshold = health + 3
|
||||
this.deadlyWound.threshold = (health + 7 < 11) ? health + 7 : 10
|
||||
|
||||
this.minorWound.max = 4 + ageMods.l
|
||||
this.majorWound.max = 3 + ageMods.h
|
||||
this.deadlyWound.max = 2 + ageMods.d
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour le label du statut de combat en fonction de la difficulté.
|
||||
*/
|
||||
_updateCombatStatus() {
|
||||
const difficulty = parseInt(this.combatStatus.difficulty) || 9
|
||||
let newLabel = "Passif"
|
||||
switch (difficulty) {
|
||||
case 5: newLabel = "Offensif"; break
|
||||
case 7: newLabel = "Actif"; break
|
||||
case 9: newLabel = "Passif"; break
|
||||
}
|
||||
if (this.combatStatus.label !== newLabel) {
|
||||
this.combatStatus.label = newLabel
|
||||
}
|
||||
}
|
||||
|
||||
// ── Modificateurs liés à l'âge ──────────────────────────────────────
|
||||
|
||||
/** @returns {number} Modificateur de sang-froid selon l'âge. */
|
||||
_getModFromAgeSelfControl() {
|
||||
return this.identity.ageType === 1 ? -1 : 0
|
||||
}
|
||||
|
||||
/** @returns {number} Modificateur d'effort selon l'âge. */
|
||||
_getModFromAgeEffort() {
|
||||
if (this.identity.ageType === 1) return -1
|
||||
if (this.identity.ageType === 3) return -2
|
||||
return 0
|
||||
}
|
||||
|
||||
/** @returns {{l: number, h: number, d: number}} Modificateurs de blessures selon l'âge. */
|
||||
_getModFromAgeWounds() {
|
||||
if (this.identity.ageType === 1) return { l: 0, h: 0, d: -1 }
|
||||
if (this.identity.ageType === 3) return { l: -1, h: -1, d: -1 }
|
||||
return { l: 0, h: 0, d: 0 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user