import { ModifiableData } from "../common/common-data"; import { DS4Item } from "../item/item"; import { DS4Armor, DS4ItemDataType, DS4Shield, ItemType } from "../item/item-data"; import { DS4ActorDataType } from "./actor-data"; export class DS4Actor extends Actor { /** @override */ prepareDerivedData(): void { const data = this.data; const attributes = data.data.attributes; Object.values(attributes).forEach( (attribute: ModifiableData) => (attribute.total = attribute.base + attribute.mod), ); const traits = data.data.traits; Object.values(traits).forEach((trait: ModifiableData) => (trait.total = trait.base + trait.mod)); this._prepareCombatValues(); } /** * The list of item types that can be owned by this actor. */ get ownableItemTypes(): Array { switch (this.data.type) { case "character": return [ "weapon", "armor", "shield", "trinket", "equipment", "spell", "talent", "racialAbility", "language", "alphabet", ]; case "creature": return ["weapon", "armor", "shield", "trinket", "equipment", "spell", "specialCreatureAbility"]; default: return []; } } /** * Checks whether or not the given item type can be owned by the actor. * @param itemType the item type to check */ canOwnItemType(itemType: ItemType): boolean { return this.ownableItemTypes.includes(itemType); } /** * Prepares the combat values of the actor. */ private _prepareCombatValues(): void { const data = this.data.data; const armorValueOfEquippedItems = this._calculateArmorValueOfEquippedItems(); data.combatValues.hitPoints.base = (data.attributes.body.total ?? 0) + (data.traits.constitution.total ?? 0) + 10; data.combatValues.defense.base = (data.attributes.body.total ?? 0) + (data.traits.constitution.total ?? 0) + armorValueOfEquippedItems; data.combatValues.initiative.base = (data.attributes.mobility.total ?? 0) + (data.traits.agility.total ?? 0); data.combatValues.movement.base = (data.attributes.mobility.total ?? 0) / 2 + 1; data.combatValues.meleeAttack.base = (data.attributes.body.total ?? 0) + (data.traits.strength.total ?? 0); data.combatValues.rangedAttack.base = (data.attributes.mobility.total ?? 0) + (data.traits.dexterity.total ?? 0); data.combatValues.spellcasting.base = (data.attributes.mind.total ?? 0) + (data.traits.aura.total ?? 0) - armorValueOfEquippedItems; data.combatValues.targetedSpellcasting.base = (data.attributes.mind.total ?? 0) + (data.traits.dexterity.total ?? 0) - armorValueOfEquippedItems; Object.values(data.combatValues).forEach( (combatValue: ModifiableData) => (combatValue.total = combatValue.base + combatValue.mod), ); data.combatValues.hitPoints.max = data.combatValues.hitPoints.total; } /** * Calculates the total armor value of all equipped items. */ private _calculateArmorValueOfEquippedItems(): number { return this.items .filter((item) => ["armor", "shield"].includes(item.type)) .map((item) => item.data.data as DS4Armor | DS4Shield) .filter((itemData) => itemData.equipped) .map((itemData) => itemData.armorValue) .reduce((a, b) => a + b, 0); } }