export default class OathHammerCharacter extends foundry.abstract.TypeDataModel { static defineSchema() { const fields = foundry.data.fields const requiredInteger = { required: true, nullable: false, integer: true } const schema = {} schema.background = new fields.HTMLField({ required: true, textSearch: true }) schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.notes = new fields.HTMLField({ required: true, textSearch: true }) // Lineage (simple fields on the actor — not an Item) schema.lineage = new fields.SchemaField({ name: new fields.StringField({ required: true, nullable: false, initial: "" }), traits: new fields.HTMLField({ required: true, textSearch: true }), }) const attributeField = () => new fields.SchemaField({ rank: new fields.NumberField({ ...requiredInteger, initial: 1, min: 1, max: 4 }) }) schema.attributes = new fields.SchemaField({ might: attributeField(), toughness: attributeField(), agility: attributeField(), willpower: attributeField(), intelligence: attributeField(), fate: attributeField() }) // Skills: 26 skills each with a rank (0–4), a bonus/penalty modifier, and color dice. // Total dice = attr rank + skill rank. Modifier = bonus (+) or penalty (-) dice. // Color dice: type (white 4+, red 3+, black 2+) + count of colored dice in the pool. const skillField = () => new fields.SchemaField({ rank: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0, max: 4 }), modifier: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }), colorDiceType: new fields.StringField({ required: true, nullable: false, initial: "white", choices: { white: "OATHHAMMER.ColorDice.White", red: "OATHHAMMER.ColorDice.Red", black: "OATHHAMMER.ColorDice.Black" } }), colorDice: new fields.NumberField({ ...requiredInteger, initial: 4, min: 0 }), }) schema.skills = new fields.SchemaField({ academics: skillField(), acrobatics: skillField(), animalHandling:skillField(), athletics: skillField(), brewing: skillField(), carpentry: skillField(), defense: skillField(), dexterity: skillField(), diplomacy: skillField(), discipline: skillField(), fighting: skillField(), folklore: skillField(), fortune: skillField(), heal: skillField(), leadership: skillField(), magic: skillField(), masonry: skillField(), orientation: skillField(), perception: skillField(), resilience: skillField(), ride: skillField(), shooting: skillField(), smithing: skillField(), stealth: skillField(), survival: skillField(), tracking: skillField(), }) schema.grit = new fields.SchemaField({ value: new fields.NumberField({ ...requiredInteger, initial: 2, min: 0 }), max: new fields.NumberField({ ...requiredInteger, initial: 2, min: 0 }) }) // Luck.max is derived from fate.rank; resets at session start. schema.luck = new fields.SchemaField({ value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }) }) schema.arcaneStress = new fields.SchemaField({ value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), threshold: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }) }) schema.miracleBlocked = new fields.BooleanField({ required: true, initial: false }) schema.movement = new fields.SchemaField({ base: new fields.NumberField({ ...requiredInteger, initial: 30, min: 0 }), adjusted: new fields.NumberField({ ...requiredInteger, initial: 30, min: 0 }) }) schema.defense = new fields.SchemaField({ value: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }), armorRating: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), bonus: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) }) schema.experience = new fields.SchemaField({ current: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), total: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), level: new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) }) schema.biodata = new fields.SchemaField({ age: new fields.StringField({ required: true, nullable: false, initial: "" }), gender: new fields.StringField({ required: true, nullable: false, initial: "" }), height: new fields.StringField({ required: true, nullable: false, initial: "" }), weight: new fields.StringField({ required: true, nullable: false, initial: "" }), eyes: new fields.StringField({ required: true, nullable: false, initial: "" }), hair: new fields.StringField({ required: true, nullable: false, initial: "" }), alignment: new fields.StringField({ required: true, nullable: false, initial: "" }) }) schema.currency = new fields.SchemaField({ gold: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), silver: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), copper: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) }) return schema } static LOCALIZATION_PREFIXES = ["OATHHAMMER.Character"] prepareDerivedData() { super.prepareDerivedData() // Grit max = Resilience skill rank + Toughness attribute rank (rulebook p.5) this.grit.max = this.skills.resilience.rank + this.attributes.toughness.rank // Luck max = Fate rank; restores at session start this.luck.max = this.attributes.fate.rank // Defense score = 10 + Agility + Armor Rating + bonus this.defense.value = 10 + this.attributes.agility.rank + this.defense.armorRating + this.defense.bonus } }