From 7c7d30854c98247b30a4cbd0ef9d2e0c16b89a9f Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Mon, 22 Mar 2021 09:04:45 +0100 Subject: [PATCH 1/3] Separate data and _data for DS4Item --- package.json | 2 +- src/module/actor/actor-data.ts | 34 +++++------ src/module/actor/actor.ts | 8 +-- src/module/actor/sheets/actor-sheet.ts | 2 +- src/module/common/common-data.ts | 9 +++ src/module/global.d.ts | 6 ++ src/module/item/item-data.ts | 40 ++++++------- src/module/item/item-prepared-data.ts | 80 ++++++++++++++++++++++++++ src/module/item/item.ts | 9 ++- src/module/migrations.ts | 2 +- src/module/rolls/check-factory.ts | 2 +- yarn.lock | 10 ++-- 12 files changed, 150 insertions(+), 54 deletions(-) create mode 100644 src/module/global.d.ts create mode 100644 src/module/item/item-prepared-data.ts diff --git a/package.json b/package.json index 5ac79213..771fe7f0 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "postinstall": "husky install" }, "devDependencies": { - "@league-of-foundry-developers/foundry-vtt-types": "^0.7.9-3", + "@league-of-foundry-developers/foundry-vtt-types": "^0.7.9-4", "@rollup/plugin-node-resolve": "^11.2.0", "@types/fs-extra": "^9.0.8", "@types/jest": "^26.0.20", diff --git a/src/module/actor/actor-data.ts b/src/module/actor/actor-data.ts index 7fcb8398..10ebedcf 100644 --- a/src/module/actor/actor-data.ts +++ b/src/module/actor/actor-data.ts @@ -1,4 +1,4 @@ -import { ModifiableData, ResourceData, UsableResource } from "../common/common-data"; +import { ModifiableDataTotal, ResourceData, UsableResource } from "../common/common-data"; import { DS4 } from "../config"; import { DS4ItemData } from "../item/item-data"; @@ -21,29 +21,29 @@ interface DS4ActorDataDataBase { } interface DS4ActorDataDataAttributes { - body: ModifiableData; - mobility: ModifiableData; - mind: ModifiableData; + body: ModifiableDataTotal; + mobility: ModifiableDataTotal; + mind: ModifiableDataTotal; } interface DS4ActorDataDataTraits { - strength: ModifiableData; - constitution: ModifiableData; - agility: ModifiableData; - dexterity: ModifiableData; - intellect: ModifiableData; - aura: ModifiableData; + strength: ModifiableDataTotal; + constitution: ModifiableDataTotal; + agility: ModifiableDataTotal; + dexterity: ModifiableDataTotal; + intellect: ModifiableDataTotal; + aura: ModifiableDataTotal; } interface DS4ActorDataDataCombatValues { hitPoints: ResourceData; - defense: ModifiableData; - initiative: ModifiableData; - movement: ModifiableData; - meleeAttack: ModifiableData; - rangedAttack: ModifiableData; - spellcasting: ModifiableData; - targetedSpellcasting: ModifiableData; + defense: ModifiableDataTotal; + initiative: ModifiableDataTotal; + movement: ModifiableDataTotal; + meleeAttack: ModifiableDataTotal; + rangedAttack: ModifiableDataTotal; + spellcasting: ModifiableDataTotal; + targetedSpellcasting: ModifiableDataTotal; } interface DS4ActorDataDataRolling { diff --git a/src/module/actor/actor.ts b/src/module/actor/actor.ts index 0e4cbb0d..b89f03e6 100644 --- a/src/module/actor/actor.ts +++ b/src/module/actor/actor.ts @@ -1,4 +1,4 @@ -import { ModifiableData } from "../common/common-data"; +import { ModifiableDataTotal } from "../common/common-data"; import { DS4 } from "../config"; import { DS4Item } from "../item/item"; import { ItemType } from "../item/item-data"; @@ -32,11 +32,11 @@ export class DS4Actor extends Actor { const attributes = data.data.attributes; Object.values(attributes).forEach( - (attribute: ModifiableData) => (attribute.total = attribute.base + attribute.mod), + (attribute: ModifiableDataTotal) => (attribute.total = attribute.base + attribute.mod), ); const traits = data.data.traits; - Object.values(traits).forEach((trait: ModifiableData) => (trait.total = trait.base + trait.mod)); + Object.values(traits).forEach((trait: ModifiableDataTotal) => (trait.total = trait.base + trait.mod)); } applyActiveEffectsToBaseData(): void { @@ -184,7 +184,7 @@ export class DS4Actor extends Actor { (data.attributes.mind.total ?? 0) + (data.traits.dexterity.total ?? 0) - armorValueOfEquippedItems; Object.values(data.combatValues).forEach( - (combatValue: ModifiableData) => (combatValue.total = combatValue.base + combatValue.mod), + (combatValue: ModifiableDataTotal) => (combatValue.total = combatValue.base + combatValue.mod), ); } diff --git a/src/module/actor/sheets/actor-sheet.ts b/src/module/actor/sheets/actor-sheet.ts index 470f33ea..069fce43 100644 --- a/src/module/actor/sheets/actor-sheet.ts +++ b/src/module/actor/sheets/actor-sheet.ts @@ -160,7 +160,7 @@ export class DS4ActorSheet extends ActorSheet> { ev.preventDefault(); const el: HTMLFormElement = $(ev.currentTarget).get(0); const id = $(ev.currentTarget).parents(".item").data("itemId"); - const item = duplicate(this.actor.getOwnedItem(id)); + const item = duplicate(this.actor.getOwnedItem(id)); const property: string | undefined = $(ev.currentTarget).data("property"); // Early return: diff --git a/src/module/common/common-data.ts b/src/module/common/common-data.ts index d23b61d0..5956d6f1 100644 --- a/src/module/common/common-data.ts +++ b/src/module/common/common-data.ts @@ -1,6 +1,15 @@ export interface ModifiableData { base: T; mod: T; +} + +export interface HasTotal { + total: T; +} + +export interface ModifiableDataTotal { + base: T; + mod: T; total?: T; } diff --git a/src/module/global.d.ts b/src/module/global.d.ts new file mode 100644 index 00000000..c560d623 --- /dev/null +++ b/src/module/global.d.ts @@ -0,0 +1,6 @@ +declare namespace ClientSettings { + interface Values { + "ds4.systemMigrationVersion": number; + "ds4.useSlayingDiceForAutomatedChecks": boolean; + } +} diff --git a/src/module/item/item-data.ts b/src/module/item/item-data.ts index c28fbe86..fbae27e3 100644 --- a/src/module/item/item-data.ts +++ b/src/module/item/item-data.ts @@ -16,7 +16,7 @@ export type DS4ItemData = | DS4AlphabetData | DS4SpecialCreatureAbilityData; -interface DS4ItemDataHelper extends Item.Data { +export interface DS4ItemDataHelper extends Item.Data { type: U; } @@ -34,17 +34,13 @@ type DS4SpecialCreatureAbilityData = DS4ItemDataHelper { +export interface DS4TalentRank extends ModifiableData { max: number; } -interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable, DS4ItemDataDataRollable { +export interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable { spellType: "spellcasting" | "targetedSpellcasting"; bonus: string; spellCategory: @@ -81,17 +77,23 @@ interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable scrollPrice: number; } -interface DS4ShieldDataData +export interface DS4ShieldDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable, DS4ItemDataDataProtective {} -interface DS4EquipmentDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {} -interface DS4LootDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical {} -type DS4RacialAbilityDataData = DS4ItemDataDataBase; -type DS4LanguageDataData = DS4ItemDataDataBase; -type DS4AlphabetDataData = DS4ItemDataDataBase; -interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase { + +export interface DS4EquipmentDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {} + +export interface DS4LootDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical {} + +export type DS4RacialAbilityDataData = DS4ItemDataDataBase; + +export type DS4LanguageDataData = DS4ItemDataDataBase; + +export type DS4AlphabetDataData = DS4ItemDataDataBase; + +export interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase { experiencePoints: number; } @@ -115,10 +117,6 @@ interface DS4ItemDataDataEquipable { equipped: boolean; } -interface DS4ItemDataDataRollable { - rollable?: boolean; -} - interface DS4ItemDataDataProtective { armorValue: number; } diff --git a/src/module/item/item-prepared-data.ts b/src/module/item/item-prepared-data.ts new file mode 100644 index 00000000..981383f4 --- /dev/null +++ b/src/module/item/item-prepared-data.ts @@ -0,0 +1,80 @@ +import { HasTotal } from "../common/common-data"; +import { + DS4AlphabetDataData, + DS4ArmorDataData, + DS4EquipmentDataData, + DS4ItemDataHelper, + DS4LanguageDataData, + DS4LootDataData, + DS4RacialAbilityDataData, + DS4ShieldDataData, + DS4SpecialCreatureAbilityDataData, + DS4SpellDataData, + DS4TalentDataData, + DS4TalentRank, + DS4WeaponDataData, +} from "./item-data"; + +export type DS4ItemPreparedData = + | DS4WeaponPreparedData + | DS4ArmorPreparedData + | DS4ShieldPreparedData + | DS4SpellPreparedData + | DS4EquipmentPreparedData + | DS4LootPreparedData + | DS4TalentPreparedData + | DS4RacialAbilityPreparedData + | DS4LanguagePreparedData + | DS4AlphabetPreparedData + | DS4SpecialCreatureAbilityPreparedData; + +type DS4WeaponPreparedData = DS4ItemDataHelper; +type DS4ArmorPreparedData = DS4ItemDataHelper; +type DS4ShieldPreparedData = DS4ItemDataHelper; +type DS4SpellPreparedData = DS4ItemDataHelper; +type DS4EquipmentPreparedData = DS4ItemDataHelper; +type DS4LootPreparedData = DS4ItemDataHelper; +type DS4TalentPreparedData = DS4ItemDataHelper; +type DS4RacialAbilityPreparedData = DS4ItemDataHelper; +type DS4LanguagePreparedData = DS4ItemDataHelper; +type DS4AlphabetPreparedData = DS4ItemDataHelper; +type DS4SpecialCreatureAbilityPreparedData = DS4ItemDataHelper< + DS4SpecialCreatureAbilityPreparedDataData, + "specialCreatureAbility" +>; + +interface DS4WeaponPreparedDataData extends DS4WeaponDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4ArmorPreparedDataData extends DS4ArmorDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4ShieldPreparedDataData extends DS4ShieldDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4SpellPreparedDataData extends DS4SpellDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4EquipmentPreparedDataData extends DS4EquipmentDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4LootPreparedDataData extends DS4LootDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4TalentPreparedDataData extends DS4TalentDataData, DS4ItemPreparedDataDataRollable { + rank: DS4TalentPreparedRank; +} + +interface DS4TalentPreparedRank extends DS4TalentRank, HasTotal { + max: number; +} + +interface DS4RacialAbilityPreparedDataData extends DS4RacialAbilityDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4LanguagePreparedDataData extends DS4LanguageDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4AlphabetPreparedDataData extends DS4AlphabetDataData, DS4ItemPreparedDataDataRollable {} + +interface DS4SpecialCreatureAbilityPreparedDataData + extends DS4SpecialCreatureAbilityDataData, + DS4ItemPreparedDataDataRollable {} + +// templates + +interface DS4ItemPreparedDataDataRollable { + rollable: boolean; +} diff --git a/src/module/item/item.ts b/src/module/item/item.ts index 07b5dc47..1c93e68a 100644 --- a/src/module/item/item.ts +++ b/src/module/item/item.ts @@ -3,11 +3,12 @@ import { DS4 } from "../config"; import { createCheckRoll } from "../rolls/check-factory"; import notifications from "../ui/notifications"; import { AttackType, DS4ItemData, ItemType } from "./item-data"; +import { DS4ItemPreparedData } from "./item-prepared-data"; /** * The Item class for DS4 */ -export class DS4Item extends Item { +export class DS4Item extends Item { /** * @override */ @@ -23,6 +24,8 @@ export class DS4Item extends Item { } if (this.data.type === "weapon" || this.data.type === "spell") { this.data.data.rollable = this.data.data.equipped; + } else { + this.data.data.rollable = false; } } @@ -94,7 +97,7 @@ export class DS4Item extends Item { const checkTargetNumber = (ownerDataData.combatValues[combatValue].total as number) + weaponBonus; await createCheckRoll(checkTargetNumber, { - rollMode: game.settings.get("core", "rollMode"), + rollMode: game.settings.get("core", "rollMode") as Const.DiceRollMode, // TODO(types): Type this setting in upstream maximumCoupResult: ownerDataData.rolling.maximumCoupResult, minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult, flavor: game.i18n.format("DS4.ItemWeaponCheckFlavor", { actor: actor.name, weapon: this.name }), @@ -138,7 +141,7 @@ export class DS4Item extends Item { const checkTargetNumber = (ownerDataData.combatValues[spellType].total as number) + (spellBonus ?? 0); await createCheckRoll(checkTargetNumber, { - rollMode: game.settings.get("core", "rollMode"), + rollMode: game.settings.get("core", "rollMode") as Const.DiceRollMode, // TODO(types): Type this setting in upstream maximumCoupResult: ownerDataData.rolling.maximumCoupResult, minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult, flavor: game.i18n.format("DS4.ItemSpellCheckFlavor", { actor: actor.name, spell: this.name }), diff --git a/src/module/migrations.ts b/src/module/migrations.ts index e9a157c7..525400c5 100644 --- a/src/module/migrations.ts +++ b/src/module/migrations.ts @@ -9,7 +9,7 @@ async function migrate(): Promise { return; } - const oldMigrationVersion: number = game.settings.get("ds4", "systemMigrationVersion"); + const oldMigrationVersion = game.settings.get("ds4", "systemMigrationVersion"); const targetMigrationVersion = migrations.length; diff --git a/src/module/rolls/check-factory.ts b/src/module/rolls/check-factory.ts index 5498acab..475c50fc 100644 --- a/src/module/rolls/check-factory.ts +++ b/src/module/rolls/check-factory.ts @@ -79,7 +79,7 @@ export async function createCheckRoll( const newOptions: Partial = { maximumCoupResult: gmModifierData.maximumCoupResult ?? options.maximumCoupResult, minimumFumbleResult: gmModifierData.minimumFumbleResult ?? options.minimumFumbleResult, - useSlayingDice: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks") ?? false, + useSlayingDice: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks"), rollMode: gmModifierData.rollMode ?? options.rollMode, flavor: options.flavor, }; diff --git a/yarn.lock b/yarn.lock index 21e5aac0..e2748004 100644 --- a/yarn.lock +++ b/yarn.lock @@ -647,9 +647,9 @@ __metadata: languageName: node linkType: hard -"@league-of-foundry-developers/foundry-vtt-types@npm:^0.7.9-3": - version: 0.7.9-3 - resolution: "@league-of-foundry-developers/foundry-vtt-types@npm:0.7.9-3" +"@league-of-foundry-developers/foundry-vtt-types@npm:^0.7.9-4": + version: 0.7.9-4 + resolution: "@league-of-foundry-developers/foundry-vtt-types@npm:0.7.9-4" dependencies: "@types/howler": 2.2.1 "@types/jquery": 3.5.1 @@ -659,7 +659,7 @@ __metadata: pixi.js: 5.3.4 tinymce: 5.6.2 typescript: ^4.1.4 - checksum: 75524c7aa78ddb77cad1a9d041af30ae5bbd708f5b26568dabbb3d913a4643aefcc6f2ed80e1e76b3c17050579665eab155f035f840db6397691cf68eeee9b3f + checksum: 9aeee3d49c20dd69e736abd50347e43f5cfdcfdca7fba5af9fb321250cc3ca78758daed14fe6328005f3b606ed0ace49bf2562d7262912c1461132718ab793b8 languageName: node linkType: hard @@ -2891,7 +2891,7 @@ __metadata: version: 0.0.0-use.local resolution: "dungeonslayers4@workspace:." dependencies: - "@league-of-foundry-developers/foundry-vtt-types": ^0.7.9-3 + "@league-of-foundry-developers/foundry-vtt-types": ^0.7.9-4 "@rollup/plugin-node-resolve": ^11.2.0 "@types/fs-extra": ^9.0.8 "@types/jest": ^26.0.20 From 17633ced68f1753f7d2d428249a0ffb6060e88f7 Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Mon, 22 Mar 2021 10:18:43 +0100 Subject: [PATCH 2/3] Separate types for data and _data for DS4Actor --- src/module/actor/actor-data.ts | 64 +++++++++++----------- src/module/actor/actor-prepared-data.ts | 69 ++++++++++++++++++++++++ src/module/actor/actor.ts | 15 +++--- src/module/actor/sheets/actor-sheet.ts | 13 +++-- src/module/common/common-data.ts | 27 +++++----- src/module/item/item-data.ts | 70 +++++++++++++------------ src/module/item/item-prepared-data.ts | 18 +++---- 7 files changed, 174 insertions(+), 102 deletions(-) create mode 100644 src/module/actor/actor-prepared-data.ts diff --git a/src/module/actor/actor-data.ts b/src/module/actor/actor-data.ts index 10ebedcf..dffd84d9 100644 --- a/src/module/actor/actor-data.ts +++ b/src/module/actor/actor-data.ts @@ -1,4 +1,4 @@ -import { ModifiableDataTotal, ResourceData, UsableResource } from "../common/common-data"; +import { ModifiableData, ModifiableDataBase, ResourceData, UsableResource } from "../common/common-data"; import { DS4 } from "../config"; import { DS4ItemData } from "../item/item-data"; @@ -6,50 +6,48 @@ export type DS4ActorData = DS4CharacterData | DS4CreatureData; type ActorType = keyof typeof DS4.i18n.actorTypes; -interface DS4ActorDataHelper extends Actor.Data { +export interface DS4ActorDataHelper extends Actor.Data { type: U; } type DS4CharacterData = DS4ActorDataHelper; type DS4CreatureData = DS4ActorDataHelper; +// templates + interface DS4ActorDataDataBase { attributes: DS4ActorDataDataAttributes; traits: DS4ActorDataDataTraits; combatValues: DS4ActorDataDataCombatValues; - rolling: DS4ActorDataDataRolling; } interface DS4ActorDataDataAttributes { - body: ModifiableDataTotal; - mobility: ModifiableDataTotal; - mind: ModifiableDataTotal; + body: ModifiableDataBase; + mobility: ModifiableDataBase; + mind: ModifiableDataBase; } interface DS4ActorDataDataTraits { - strength: ModifiableDataTotal; - constitution: ModifiableDataTotal; - agility: ModifiableDataTotal; - dexterity: ModifiableDataTotal; - intellect: ModifiableDataTotal; - aura: ModifiableDataTotal; + strength: ModifiableDataBase; + constitution: ModifiableDataBase; + agility: ModifiableDataBase; + dexterity: ModifiableDataBase; + intellect: ModifiableDataBase; + aura: ModifiableDataBase; } interface DS4ActorDataDataCombatValues { hitPoints: ResourceData; - defense: ModifiableDataTotal; - initiative: ModifiableDataTotal; - movement: ModifiableDataTotal; - meleeAttack: ModifiableDataTotal; - rangedAttack: ModifiableDataTotal; - spellcasting: ModifiableDataTotal; - targetedSpellcasting: ModifiableDataTotal; + defense: ModifiableData; + initiative: ModifiableData; + movement: ModifiableData; + meleeAttack: ModifiableData; + rangedAttack: ModifiableData; + spellcasting: ModifiableData; + targetedSpellcasting: ModifiableData; } -interface DS4ActorDataDataRolling { - maximumCoupResult?: number; - minimumFumbleResult?: number; -} +// types interface DS4CharacterDataData extends DS4ActorDataDataBase { baseInfo: DS4CharacterDataDataBaseInfo; @@ -58,25 +56,25 @@ interface DS4CharacterDataData extends DS4ActorDataDataBase { profile: DS4CharacterDataDataProfile; currency: DS4CharacterDataDataCurrency; } -interface DS4CharacterDataDataBaseInfo { +export interface DS4CharacterDataDataBaseInfo { race: string; class: string; heroClass: string; culture: string; } -interface DS4CharacterDataDataProgression { +export interface DS4CharacterDataDataProgression { level: number; experiencePoints: number; talentPoints: UsableResource; progressPoints: UsableResource; } -interface DS4CharacterDataDataLanguage { +export interface DS4CharacterDataDataLanguage { languages: string; alphabets: string; } -interface DS4CharacterDataDataProfile { +export interface DS4CharacterDataDataProfile { biography: string; gender: string; birthday: string; @@ -89,7 +87,7 @@ interface DS4CharacterDataDataProfile { specialCharacteristics: string; } -interface DS4CharacterDataDataCurrency { +export interface DS4CharacterDataDataCurrency { gold: number; silver: number; copper: number; @@ -99,11 +97,7 @@ interface DS4CreatureDataData extends DS4ActorDataDataBase { baseInfo: DS4CreatureDataDataBaseInfo; } -type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead"; - -type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal"; - -interface DS4CreatureDataDataBaseInfo { +export interface DS4CreatureDataDataBaseInfo { loot: string; foeFactor: number; creatureType: CreatureType; @@ -111,3 +105,7 @@ interface DS4CreatureDataDataBaseInfo { experiencePoints: number; description: string; } + +type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead"; + +type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal"; diff --git a/src/module/actor/actor-prepared-data.ts b/src/module/actor/actor-prepared-data.ts new file mode 100644 index 00000000..fcbe0139 --- /dev/null +++ b/src/module/actor/actor-prepared-data.ts @@ -0,0 +1,69 @@ +import { ModifiableDataBaseTotal, ResourceDataBaseTotalMax } from "../common/common-data"; +import { + DS4ActorDataHelper, + DS4CharacterDataDataBaseInfo, + DS4CharacterDataDataCurrency, + DS4CharacterDataDataLanguage, + DS4CharacterDataDataProfile, + DS4CharacterDataDataProgression, + DS4CreatureDataDataBaseInfo, +} from "./actor-data"; + +export type DS4ActorPreparedData = DS4CharacterPreparedData | DS4CreaturePreparedData; + +type DS4CharacterPreparedData = DS4ActorDataHelper; +type DS4CreaturePreparedData = DS4ActorDataHelper; + +// templates + +interface DS4ActorPreparedDataDataBase { + attributes: DS4ActorPreparedDataDataAttributes; + traits: DS4ActorPreparedDataDataTraits; + combatValues: DS4ActorPreparedDataDataCombatValues; + rolling: DS4ActorPreparedDataDataRolling; +} + +interface DS4ActorPreparedDataDataAttributes { + body: ModifiableDataBaseTotal; + mobility: ModifiableDataBaseTotal; + mind: ModifiableDataBaseTotal; +} + +interface DS4ActorPreparedDataDataTraits { + strength: ModifiableDataBaseTotal; + constitution: ModifiableDataBaseTotal; + agility: ModifiableDataBaseTotal; + dexterity: ModifiableDataBaseTotal; + intellect: ModifiableDataBaseTotal; + aura: ModifiableDataBaseTotal; +} + +interface DS4ActorPreparedDataDataCombatValues { + hitPoints: ResourceDataBaseTotalMax; + defense: ModifiableDataBaseTotal; + initiative: ModifiableDataBaseTotal; + movement: ModifiableDataBaseTotal; + meleeAttack: ModifiableDataBaseTotal; + rangedAttack: ModifiableDataBaseTotal; + spellcasting: ModifiableDataBaseTotal; + targetedSpellcasting: ModifiableDataBaseTotal; +} + +interface DS4ActorPreparedDataDataRolling { + maximumCoupResult: number; + minimumFumbleResult: number; +} + +// types + +interface DS4CharacterPreparedDataData extends DS4ActorPreparedDataDataBase { + baseInfo: DS4CharacterDataDataBaseInfo; + progression: DS4CharacterDataDataProgression; + language: DS4CharacterDataDataLanguage; + profile: DS4CharacterDataDataProfile; + currency: DS4CharacterDataDataCurrency; +} + +interface DS4CreaturePreparedDataData extends DS4ActorPreparedDataDataBase { + baseInfo: DS4CreatureDataDataBaseInfo; +} diff --git a/src/module/actor/actor.ts b/src/module/actor/actor.ts index b89f03e6..bccfe3c3 100644 --- a/src/module/actor/actor.ts +++ b/src/module/actor/actor.ts @@ -1,16 +1,17 @@ -import { ModifiableDataTotal } from "../common/common-data"; +import { ModifiableDataBaseTotal } from "../common/common-data"; import { DS4 } from "../config"; import { DS4Item } from "../item/item"; import { ItemType } from "../item/item-data"; import { DS4ActorData } from "./actor-data"; +import { DS4ActorPreparedData } from "./actor-prepared-data"; /** * The Actor class for DS4 */ -export class DS4Actor extends Actor { +export class DS4Actor extends Actor { /** @override */ prepareData(): void { - this.data = duplicate(this._data) as DS4ActorData; + this.data = duplicate(this._data) as DS4ActorPreparedData; if (!this.data.img) this.data.img = CONST.DEFAULT_TOKEN; if (!this.data.name) this.data.name = "New " + this.entity; this.prepareBaseData(); @@ -32,11 +33,13 @@ export class DS4Actor extends Actor { const attributes = data.data.attributes; Object.values(attributes).forEach( - (attribute: ModifiableDataTotal) => (attribute.total = attribute.base + attribute.mod), + (attribute: ModifiableDataBaseTotal) => (attribute.total = attribute.base + attribute.mod), ); const traits = data.data.traits; - Object.values(traits).forEach((trait: ModifiableDataTotal) => (trait.total = trait.base + trait.mod)); + Object.values(traits).forEach( + (trait: ModifiableDataBaseTotal) => (trait.total = trait.base + trait.mod), + ); } applyActiveEffectsToBaseData(): void { @@ -184,7 +187,7 @@ export class DS4Actor extends Actor { (data.attributes.mind.total ?? 0) + (data.traits.dexterity.total ?? 0) - armorValueOfEquippedItems; Object.values(data.combatValues).forEach( - (combatValue: ModifiableDataTotal) => (combatValue.total = combatValue.base + combatValue.mod), + (combatValue: ModifiableDataBaseTotal) => (combatValue.total = combatValue.base + combatValue.mod), ); } diff --git a/src/module/actor/sheets/actor-sheet.ts b/src/module/actor/sheets/actor-sheet.ts index 069fce43..dd8dfd47 100644 --- a/src/module/actor/sheets/actor-sheet.ts +++ b/src/module/actor/sheets/actor-sheet.ts @@ -1,4 +1,4 @@ -import { ModifiableMaybeData } from "../../common/common-data"; +import { ModifiableDataBaseTotal } from "../../common/common-data"; import { DS4 } from "../../config"; import { DS4Item } from "../../item/item"; import { DS4ItemData } from "../../item/item-data"; @@ -75,17 +75,16 @@ export class DS4ActorSheet extends ActorSheet> { protected _addTooltipsToData(data: ActorSheet.Data): ActorSheet.Data { const valueGroups = [data.data.attributes, data.data.traits, data.data.combatValues]; + valueGroups.forEach((valueGroup) => { - Object.values(valueGroup).forEach( - (attribute: ModifiableMaybeData & { tooltip?: string }) => { - attribute.tooltip = this._getTooltipForValue(attribute); - }, - ); + Object.values(valueGroup).forEach((attribute: ModifiableDataBaseTotal & { tooltip?: string }) => { + attribute.tooltip = this._getTooltipForValue(attribute); + }); }); return data; } - protected _getTooltipForValue(value: ModifiableMaybeData): string { + protected _getTooltipForValue(value: ModifiableDataBaseTotal): string { return `${value.base} (${game.i18n.localize("DS4.TooltipBaseValue")}) + ${value.mod} (${game.i18n.localize( "DS4.TooltipModifier", )}) ➞ ${game.i18n.localize("DS4.TooltipEffects")} ➞ ${value.total}`; diff --git a/src/module/common/common-data.ts b/src/module/common/common-data.ts index 5956d6f1..8850062f 100644 --- a/src/module/common/common-data.ts +++ b/src/module/common/common-data.ts @@ -1,29 +1,30 @@ export interface ModifiableData { - base: T; mod: T; } +export interface HasBase { + base: T; +} +export interface ModifiableDataBase extends ModifiableData, HasBase {} + export interface HasTotal { total: T; } -export interface ModifiableDataTotal { - base: T; - mod: T; - total?: T; -} +export interface ModifiableDataTotal extends ModifiableData, HasTotal {} -export interface ModifiableMaybeData { - base?: T; - mod: T; - total?: T; -} +export interface ModifiableDataBaseTotal extends ModifiableDataBase, HasTotal {} -export interface ResourceData extends ModifiableMaybeData { +export interface ResourceData extends ModifiableData { value: T; - max?: T; } +export interface HasMax { + max: T; +} + +export interface ResourceDataBaseTotalMax extends ResourceData, HasBase, HasTotal, HasMax {} + export interface UsableResource { total: T; used: T; diff --git a/src/module/item/item-data.ts b/src/module/item/item-data.ts index fbae27e3..7fa85fab 100644 --- a/src/module/item/item-data.ts +++ b/src/module/item/item-data.ts @@ -1,4 +1,4 @@ -import { ModifiableData } from "../common/common-data"; +import { ModifiableDataBase } from "../common/common-data"; import { DS4 } from "../config"; export type ItemType = keyof typeof DS4.i18n.itemTypes; @@ -32,7 +32,38 @@ type DS4LanguageData = DS4ItemDataHelper; type DS4AlphabetData = DS4ItemDataHelper; type DS4SpecialCreatureAbilityData = DS4ItemDataHelper; -export type AttackType = keyof typeof DS4["i18n"]["attackTypes"]; +// templates + +interface DS4ItemDataDataBase { + description: string; +} +interface DS4ItemDataDataPhysical { + quantity: number; + price: number; + availability: "hamlet" | "village" | "city" | "elves" | "dwarves" | "nowhere" | "unset"; + storageLocation: string; +} + +export function isDS4ItemDataTypePhysical(input: DS4ItemData["data"]): boolean { + return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input; +} + +interface DS4ItemDataDataEquipable { + equipped: boolean; +} + +interface DS4ItemDataDataProtective { + armorValue: number; +} + +interface UnitData { + value: string; + unit: UnitType; +} +type TemporalUnit = "rounds" | "minutes" | "hours" | "days" | "custom"; +type DistanceUnit = "meter" | "kilometer" | "custom"; + +// types export interface DS4WeaponDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable { attackType: AttackType; @@ -40,6 +71,8 @@ export interface DS4WeaponDataData extends DS4ItemDataDataBase, DS4ItemDataDataP opponentDefense: number; } +export type AttackType = keyof typeof DS4["i18n"]["attackTypes"]; + export interface DS4ArmorDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, @@ -53,7 +86,7 @@ export interface DS4TalentDataData extends DS4ItemDataDataBase { rank: DS4TalentRank; } -export interface DS4TalentRank extends ModifiableData { +export interface DS4TalentRank extends ModifiableDataBase { max: number; } @@ -96,34 +129,3 @@ export type DS4AlphabetDataData = DS4ItemDataDataBase; export interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase { experiencePoints: number; } - -// templates - -interface DS4ItemDataDataBase { - description: string; -} -interface DS4ItemDataDataPhysical { - quantity: number; - price: number; - availability: "hamlet" | "village" | "city" | "elves" | "dwarves" | "nowhere" | "unset"; - storageLocation: string; -} - -export function isDS4ItemDataTypePhysical(input: DS4ItemData["data"]): boolean { - return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input; -} - -interface DS4ItemDataDataEquipable { - equipped: boolean; -} - -interface DS4ItemDataDataProtective { - armorValue: number; -} - -interface UnitData { - value: string; - unit: UnitType; -} -type TemporalUnit = "rounds" | "minutes" | "hours" | "days" | "custom"; -type DistanceUnit = "meter" | "kilometer" | "custom"; diff --git a/src/module/item/item-prepared-data.ts b/src/module/item/item-prepared-data.ts index 981383f4..4dede57f 100644 --- a/src/module/item/item-prepared-data.ts +++ b/src/module/item/item-prepared-data.ts @@ -43,6 +43,14 @@ type DS4SpecialCreatureAbilityPreparedData = DS4ItemDataHelper< "specialCreatureAbility" >; +// templates + +interface DS4ItemPreparedDataDataRollable { + rollable: boolean; +} + +//types + interface DS4WeaponPreparedDataData extends DS4WeaponDataData, DS4ItemPreparedDataDataRollable {} interface DS4ArmorPreparedDataData extends DS4ArmorDataData, DS4ItemPreparedDataDataRollable {} @@ -59,9 +67,7 @@ interface DS4TalentPreparedDataData extends DS4TalentDataData, DS4ItemPreparedDa rank: DS4TalentPreparedRank; } -interface DS4TalentPreparedRank extends DS4TalentRank, HasTotal { - max: number; -} +interface DS4TalentPreparedRank extends DS4TalentRank, HasTotal {} interface DS4RacialAbilityPreparedDataData extends DS4RacialAbilityDataData, DS4ItemPreparedDataDataRollable {} @@ -72,9 +78,3 @@ interface DS4AlphabetPreparedDataData extends DS4AlphabetDataData, DS4ItemPrepar interface DS4SpecialCreatureAbilityPreparedDataData extends DS4SpecialCreatureAbilityDataData, DS4ItemPreparedDataDataRollable {} - -// templates - -interface DS4ItemPreparedDataDataRollable { - rollable: boolean; -} From cb5ad74a71f2b1dc7b5dad16f0d74da32cb93105 Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Mon, 22 Mar 2021 10:28:37 +0100 Subject: [PATCH 3/3] Remove some unnecessary casts and fallbacks --- src/module/actor/actor.ts | 20 +++++++++----------- src/module/item/item.ts | 4 ++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/module/actor/actor.ts b/src/module/actor/actor.ts index bccfe3c3..a8515444 100644 --- a/src/module/actor/actor.ts +++ b/src/module/actor/actor.ts @@ -75,7 +75,7 @@ export class DS4Actor extends Actor return changes.concat( e.data.changes.filter(predicate).flatMap((c) => { - const duplicatedChange = duplicate(c) as ActiveEffect.Change; + const duplicatedChange = duplicate(c); duplicatedChange.priority = duplicatedChange.priority ?? duplicatedChange.mode * 10; return Array(factor).fill({ ...duplicatedChange, @@ -172,19 +172,17 @@ export class DS4Actor extends Actor 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.hitPoints.base = data.attributes.body.total + data.traits.constitution.total + 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.attributes.body.total + data.traits.constitution.total + armorValueOfEquippedItems; + data.combatValues.initiative.base = data.attributes.mobility.total + data.traits.agility.total; + data.combatValues.movement.base = data.attributes.mobility.total / 2 + 1; + data.combatValues.meleeAttack.base = data.attributes.body.total + data.traits.strength.total; + data.combatValues.rangedAttack.base = data.attributes.mobility.total + data.traits.dexterity.total; data.combatValues.spellcasting.base = - (data.attributes.mind.total ?? 0) + (data.traits.aura.total ?? 0) - armorValueOfEquippedItems; + data.attributes.mind.total + data.traits.aura.total - armorValueOfEquippedItems; data.combatValues.targetedSpellcasting.base = - (data.attributes.mind.total ?? 0) + (data.traits.dexterity.total ?? 0) - armorValueOfEquippedItems; + data.attributes.mind.total + data.traits.dexterity.total - armorValueOfEquippedItems; Object.values(data.combatValues).forEach( (combatValue: ModifiableDataBaseTotal) => (combatValue.total = combatValue.base + combatValue.mod), diff --git a/src/module/item/item.ts b/src/module/item/item.ts index 1c93e68a..68a1ffb5 100644 --- a/src/module/item/item.ts +++ b/src/module/item/item.ts @@ -94,7 +94,7 @@ export class DS4Item extends Item { const ownerDataData = actor.data.data; const weaponBonus = this.data.data.weaponBonus; const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType); - const checkTargetNumber = (ownerDataData.combatValues[combatValue].total as number) + weaponBonus; + const checkTargetNumber = ownerDataData.combatValues[combatValue].total + weaponBonus; await createCheckRoll(checkTargetNumber, { rollMode: game.settings.get("core", "rollMode") as Const.DiceRollMode, // TODO(types): Type this setting in upstream @@ -138,7 +138,7 @@ export class DS4Item extends Item { ); } const spellType = this.data.data.spellType; - const checkTargetNumber = (ownerDataData.combatValues[spellType].total as number) + (spellBonus ?? 0); + const checkTargetNumber = ownerDataData.combatValues[spellType].total + (spellBonus ?? 0); await createCheckRoll(checkTargetNumber, { rollMode: game.settings.get("core", "rollMode") as Const.DiceRollMode, // TODO(types): Type this setting in upstream