Files

75 lines
3.3 KiB
JavaScript

import { SYSTEM } from "../config/system.mjs"
export default class AwECharacter extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
const requiredInteger = { required: true, nullable: false, integer: true }
const schema = {}
schema.description = new fields.HTMLField({ required: true, textSearch: true })
schema.notes = new fields.HTMLField({ required: true, textSearch: true })
// Identity
schema.pronouns = new fields.StringField({ initial: "", required: false, nullable: true })
schema.specialization = new fields.StringField({ initial: "", required: false, nullable: true })
// Core stats
schema.level = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1, max: 10,
choices: Object.fromEntries([1,2,3,4,5,6,7,8,9,10].map(v => [v, String(v)])) })
schema.stride = new fields.NumberField({ ...requiredInteger, initial: 5, min: 0 })
// Hit Points
schema.hp = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }),
temp: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
})
// Flow Points
schema.flowPoints = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
temp: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
})
// Attributes: agility, fitness, awareness, influence
// boostLevel: how many boosts applied (0-4)
// mod = level + boostLevel (computed in prepareDerivedData)
// dc = 10 + mod (computed)
// bonus: manual +/- bonus
const attributeField = () => new fields.SchemaField({
// boosts: permanent +1 increments from background, field, step5, and level 3/6/9 progression
// max 7: 4 at creation + 3 from additional boosts at levels 3, 6, 9
boostLevel: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 7,
choices: Object.fromEntries(Array.from({length: 8}, (_, i) => [i, String(i)])) }),
bonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 })
})
schema.attributes = new fields.SchemaField(
Object.values(SYSTEM.ATTRIBUTES).reduce((obj, attr) => {
obj[attr.id] = attributeField()
return obj
}, {})
)
// Condition penalty magnitudes (used when the respective condition is active)
schema.inhibitedPenalty = new fields.NumberField({ required: true, nullable: false, integer: true, initial: 2, min: 0 })
schema.vulnerablePenalty = new fields.NumberField({ required: true, nullable: false, integer: true, initial: 2, min: 0 })
return schema
}
/** @override */
prepareDerivedData() {
super.prepareDerivedData()
const level = this.level
for (const attrId of Object.keys(SYSTEM.ATTRIBUTES)) {
const attr = this.attributes[attrId]
attr.mod = level + attr.boostLevel + attr.bonus
attr.dc = 10 + attr.mod
const bonusPart = attr.bonus !== 0 ? ` + Bonus ${attr.bonus >= 0 ? '+' : ''}${attr.bonus}` : ''
attr.modBreakdown = `Level ${level} + Boosts ${attr.boostLevel}${bonusPart} = ${attr.mod >= 0 ? '+' : ''}${attr.mod}`
}
}
}