From 647f1a9aaccf70d09c0ad2eb6a2403206358ec28 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sat, 12 Apr 2025 13:13:04 -0600 Subject: [PATCH] Initialize the geist actor type & refactor the HeroData data model --- module/data/Actor/Entity.mjs | 196 ++++++++++++++++++++++++++++++++++ module/data/Actor/Geist.mjs | 3 + module/data/Actor/Hero.mjs | 197 +---------------------------------- system.json | 3 +- 4 files changed, 203 insertions(+), 196 deletions(-) create mode 100644 module/data/Actor/Entity.mjs create mode 100644 module/data/Actor/Geist.mjs diff --git a/module/data/Actor/Entity.mjs b/module/data/Actor/Entity.mjs new file mode 100644 index 0000000..7a424d9 --- /dev/null +++ b/module/data/Actor/Entity.mjs @@ -0,0 +1,196 @@ +import { derivedMaximumBar } from "../helpers.mjs"; +import { gameTerms } from "../../gameTerms.mjs"; +import { rankToInteger } from "../../utils/rank.mjs"; +import { sumReduce } from "../../utils/sumReduce.mjs"; + +const { fields } = foundry.data; + +export class EntityData extends foundry.abstract.TypeDataModel { + + // MARK: Token Attrs + static get trackableAttributes() { + return { + bar: [ + `guts`, + ], + value: [ + `ability.grit`, + `ability.gait`, + `ability.grip`, + `ability.glim`, + `level.glory`, + `level.step`, + `level.rank`, + `coin.gold`, + `coin.silver`, + `coin.copper`, + ], + }; + }; + + // MARK: Schema + static defineSchema() { + return { + ability: new fields.SchemaField({ + grit: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + gait: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + grip: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + glim: new fields.NumberField({ + min: 0, + initial: 1, + integer: true, + required: true, + nullable: false, + }), + }), + guts: derivedMaximumBar(0, 5), + coin: new fields.SchemaField({ + gold: new fields.NumberField({ + initial: 5, + integer: true, + required: true, + nullable: false, + }), + silver: new fields.NumberField({ + initial: 0, + integer: true, + required: true, + nullable: false, + }), + copper: new fields.NumberField({ + initial: 0, + integer: true, + required: true, + nullable: false, + }), + }), + fate: new fields.StringField({ + initial: ``, + blank: true, + trim: true, + nullable: false, + choices: () => { + return Object.values(gameTerms.FatePath).concat(``); + }, + }), + level: new fields.SchemaField({ + glory: new fields.NumberField({ + min: 0, + initial: 0, + integer: true, + required: true, + nullable: false, + }), + step: new fields.NumberField({ + min: 1, + initial: 1, + max: 3, + integer: true, + required: true, + nullable: false, + }), + rank: new fields.StringField({ + initial: gameTerms.Rank.NOVICE, + required: true, + nullable: false, + blank: false, + trim: true, + choices: Object.values(gameTerms.Rank), + }), + }), + }; + }; + + // MARK: Base Data + prepareBaseData() { + super.prepareBaseData(); + + // Calculate the person's base Crafting aura + const rank = rankToInteger(this.level.rank); + this.aura = { + normal: ( rank + 1 ) * 2, + heavy: ( rank + 2 ) * 2, + }; + + this.guts.max = 0; + + // The limitations imposed on things like inventory spaces and equipped + // weapon count + this.limit = { + weapons: 4, + equipment: 12, + skills: 4, + }; + }; + + // MARK: Derived Data + prepareDerivedData() { + super.prepareDerivedData(); + + this.guts.max += Object.values(this.ability).reduce(sumReduce); + + // Movement speeds + this.speed = { + move: this.ability.gait + 3, + run: (this.ability.gait + 3) * 2, + }; + }; + + // #region Getters + get equippedArmour() { + const armours = this.parent.itemTypes.armour; + const slots = Object.fromEntries( + Object.values(gameTerms.Anatomy).map(v => [v, null]), + ); + for (const armour of armours) { + if (!armour.system.equipped) { continue }; + for (const locationTag of [...armour.system.location.values()]) { + const location = locationTag.toLowerCase(); + slots[location] = armour; + }; + }; + return slots; + }; + + get equippedShield() { + const shields = this.parent.itemTypes.shield; + return shields.find(item => item.system.equipped); + }; + + get defense() { + const defenses = {}; + const armour = this.equippedArmour; + for (const slot in armour) { + defenses[slot] = armour[slot]?.system.protection ?? 0; + }; + + const shield = this.equippedShield; + if (shield) { + for (const location of [...shield.system.location.values()]) { + const slot = location.toLowerCase(); + defenses[slot] += shield.system.protection; + }; + }; + + return defenses; + }; + // #endregion +}; diff --git a/module/data/Actor/Geist.mjs b/module/data/Actor/Geist.mjs new file mode 100644 index 0000000..440392a --- /dev/null +++ b/module/data/Actor/Geist.mjs @@ -0,0 +1,3 @@ +import { EntityData } from "./Entity.mjs"; + +export class GeistData extends EntityData {}; diff --git a/module/data/Actor/Hero.mjs b/module/data/Actor/Hero.mjs index 6f589d6..6e6c364 100644 --- a/module/data/Actor/Hero.mjs +++ b/module/data/Actor/Hero.mjs @@ -1,196 +1,3 @@ -import { derivedMaximumBar } from "../helpers.mjs"; -import { gameTerms } from "../../gameTerms.mjs"; -import { rankToInteger } from "../../utils/rank.mjs"; -import { sumReduce } from "../../utils/sumReduce.mjs"; +import { EntityData } from "./Entity.mjs"; -const { fields } = foundry.data; - -export class HeroData extends foundry.abstract.TypeDataModel { - - // MARK: Token Attrs - static get trackableAttributes() { - return { - bar: [ - `guts`, - ], - value: [ - `ability.grit`, - `ability.gait`, - `ability.grip`, - `ability.glim`, - `level.glory`, - `level.step`, - `level.rank`, - `coin.gold`, - `coin.silver`, - `coin.copper`, - ], - }; - }; - - // MARK: Schema - static defineSchema() { - return { - ability: new fields.SchemaField({ - grit: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - gait: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - grip: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - glim: new fields.NumberField({ - min: 0, - initial: 1, - integer: true, - required: true, - nullable: false, - }), - }), - guts: derivedMaximumBar(0, 5), - coin: new fields.SchemaField({ - gold: new fields.NumberField({ - initial: 5, - integer: true, - required: true, - nullable: false, - }), - silver: new fields.NumberField({ - initial: 0, - integer: true, - required: true, - nullable: false, - }), - copper: new fields.NumberField({ - initial: 0, - integer: true, - required: true, - nullable: false, - }), - }), - fate: new fields.StringField({ - initial: ``, - blank: true, - trim: true, - nullable: false, - choices: () => { - return Object.values(gameTerms.FatePath).concat(``); - }, - }), - level: new fields.SchemaField({ - glory: new fields.NumberField({ - min: 0, - initial: 0, - integer: true, - required: true, - nullable: false, - }), - step: new fields.NumberField({ - min: 1, - initial: 1, - max: 3, - integer: true, - required: true, - nullable: false, - }), - rank: new fields.StringField({ - initial: gameTerms.Rank.NOVICE, - required: true, - nullable: false, - blank: false, - trim: true, - choices: Object.values(gameTerms.Rank), - }), - }), - }; - }; - - // MARK: Base Data - prepareBaseData() { - super.prepareBaseData(); - - // Calculate the person's base Crafting aura - const rank = rankToInteger(this.level.rank); - this.aura = { - normal: ( rank + 1 ) * 2, - heavy: ( rank + 2 ) * 2, - }; - - this.guts.max = 0; - - // The limitations imposed on things like inventory spaces and equipped - // weapon count - this.limit = { - weapons: 4, - equipment: 12, - skills: 4, - }; - }; - - // MARK: Derived Data - prepareDerivedData() { - super.prepareDerivedData(); - - this.guts.max += Object.values(this.ability).reduce(sumReduce); - - // Movement speeds - this.speed = { - move: this.ability.gait + 3, - run: (this.ability.gait + 3) * 2, - }; - }; - - // #region Getters - get equippedArmour() { - const armours = this.parent.itemTypes.armour; - const slots = Object.fromEntries( - Object.values(gameTerms.Anatomy).map(v => [v, null]), - ); - for (const armour of armours) { - if (!armour.system.equipped) { continue }; - for (const locationTag of [...armour.system.location.values()]) { - const location = locationTag.toLowerCase(); - slots[location] = armour; - }; - }; - return slots; - }; - - get equippedShield() { - const shields = this.parent.itemTypes.shield; - return shields.find(item => item.system.equipped); - }; - - get defense() { - const defenses = {}; - const armour = this.equippedArmour; - for (const slot in armour) { - defenses[slot] = armour[slot]?.system.protection ?? 0; - }; - - const shield = this.equippedShield; - if (shield) { - for (const location of [...shield.system.location.values()]) { - const slot = location.toLowerCase(); - defenses[slot] += shield.system.protection; - }; - }; - - return defenses; - }; - // #endregion -}; +export class HeroData extends EntityData {}; diff --git a/system.json b/system.json index 1fe6d62..b0750c5 100644 --- a/system.json +++ b/system.json @@ -43,7 +43,8 @@ }, "documentTypes": { "Actor": { - "hero": {} + "hero": {}, + "geist": {} }, "Item": { "ammo": {},