From bfcbb9f290d8c62b7a829b64be3ac8a8e9d45c8c Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 19 Mar 2026 16:02:23 +0100 Subject: [PATCH] Removed last traces of ArmorEffect --- lang/en.json | 25 +- module/applications/sheets/items/armor.mjs | 2 +- module/data/activeEffect/armorEffect.mjs | 244 ------------------ .../data/activeEffect/changeTypes/armor.mjs | 21 +- module/data/item/armor.mjs | 6 +- module/systemRegistration/migrations.mjs | 11 +- system.json | 3 +- templates/sheets/activeEffect/changes.hbs | 2 +- 8 files changed, 41 insertions(+), 273 deletions(-) delete mode 100644 module/data/activeEffect/armorEffect.mjs diff --git a/lang/en.json b/lang/en.json index dcfba5ce..ea89ca2d 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1864,6 +1864,17 @@ "name": "Healing Roll" } }, + "ChangeTypes": { + "armor": { + "newArmorEffect": "Armor Effect", + "FIELDS": { + "armorInteraction": { + "label": "Armor Interaction", + "hint": "Does the character wearing armor suppress this effect?" + } + } + } + }, "Duration": { "passive": "Passive", "temporary": "Temporary" @@ -1885,15 +1896,6 @@ "Attachments": { "attachHint": "Drop items here to attach them", "transferHint": "If checked, this effect will be applied to any actor that owns this Effect's parent Item. The effect is always applied if this Item is attached to another one." - }, - "Armor": { - "newArmorEffect": "Armor Effect", - "FIELDS": { - "armorInteraction": { - "label": "Armor Interaction", - "hint": "Does the character wearing armor suppress this effect?" - } - } } }, "GENERAL": { @@ -3079,10 +3081,7 @@ "tokenActorsMissing": "[{names}] missing Actors", "domainTouchRequirement": "This domain card requires {nr} {domain} cards in the loadout to be used", "knowTheTide": "Know The Tide gained a token", - "lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}", - "cannotAlterArmorEffectChanges": "You cannot alter the changes length of an armor effect", - "cannotAlterArmorEffectType": "You cannot alter the type of armor effect changes", - "cannotAlterArmorEffectKey": "You cannot alter they key of armor effect changes" + "lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}" }, "Progress": { "migrationLabel": "Performing system migration. Please wait and do not close Foundry." diff --git a/module/applications/sheets/items/armor.mjs b/module/applications/sheets/items/armor.mjs index 4c69c822..93325405 100644 --- a/module/applications/sheets/items/armor.mjs +++ b/module/applications/sheets/items/armor.mjs @@ -64,7 +64,7 @@ export default class ArmorSheet extends ItemAttachmentSheet(DHBaseItemSheet) { const armorEffect = this.document.system.armorEffect; if (Number.isNaN(value) || !armorEffect) return; - await armorEffect.system.updateArmorMax(value); + await armorEffect.system.armorChange.typeData.updateArmorMax(value); this.render(); } diff --git a/module/data/activeEffect/armorEffect.mjs b/module/data/activeEffect/armorEffect.mjs deleted file mode 100644 index 6bf0ecec..00000000 --- a/module/data/activeEffect/armorEffect.mjs +++ /dev/null @@ -1,244 +0,0 @@ -import { getScrollTextData, itemAbleRollParse } from '../../helpers/utils.mjs'; - -/** - * ArmorEffects are ActiveEffects that have a static changes field of length 1. It includes current and maximum armor. - * When applied to a character, it adds to their currently marked and maximum armor. - */ -export default class ArmorEffect extends foundry.data.ActiveEffectTypeDataModel { - static defineSchema() { - const fields = foundry.data.fields; - - return { - ...super.defineSchema(), - changes: new fields.ArrayField( - new fields.SchemaField({ - key: new fields.StringField({ - required: true, - nullable: false, - initial: 'system.armorScore' - }), - type: new fields.StringField({ - required: true, - blank: false, - initial: CONFIG.DH.GENERAL.activeEffectModes.armor.id, - validate: ArmorEffect.#validateType - }), - phase: new fields.StringField({ required: true, blank: false, initial: 'initial' }), - priority: new fields.NumberField({ integer: true, initial: 20 }), - value: new fields.NumberField({ - required: true, - integer: true, - initial: 0, - min: 0, - label: 'DAGGERHEART.GENERAL.value' - }), - max: new fields.StringField({ - required: true, - nullable: false, - initial: '1', - label: 'DAGGERHEART.GENERAL.max' - }) - }), - { - initial: [ - { - key: 'system.armorScore', - type: CONFIG.DH.GENERAL.activeEffectModes.armor.id, - phase: 'initial', - priority: 20, - value: 0, - max: '1' - } - ] - } - ), - armorInteraction: new fields.StringField({ - required: true, - choices: CONFIG.DH.GENERAL.activeEffectArmorInteraction, - initial: CONFIG.DH.GENERAL.activeEffectArmorInteraction.none.id, - label: 'DAGGERHEART.EFFECTS.Armor.FIELDS.armorInteraction.label', - hint: 'DAGGERHEART.EFFECTS.Armor.FIELDS.armorInteraction.hint' - }) - }; - } - - get isSuppressed() { - if (this.parent.actor?.type !== 'character') return false; - - switch (this.armorInteraction) { - case CONFIG.DH.GENERAL.activeEffectArmorInteraction.active.id: - return !this.parent.actor.system.armor; - case CONFIG.DH.GENERAL.activeEffectArmorInteraction.inactive.id: - return Boolean(this.parent.actor.system.armor); - default: - return false; - } - } - - /* Type Functions */ - - /** - * Validate that an {@link EffectChangeData#type} string is well-formed. - * @param {string} type The string to be validated - * @returns {true} - * @throws {Error} An error if the type string is malformed - */ - static #validateType(type) { - if (type !== CONFIG.DH.GENERAL.activeEffectModes.armor.id) - throw new Error('An armor effect must have change.type "armor"'); - - return true; - } - - static armorChangeEffect = { - label: 'Armor', - defaultPriortiy: 20, - handler: (actor, change, _options, _field, replacementData) => { - game.system.api.documents.DhActiveEffect.applyChange( - actor, - { - ...change, - key: 'system.armorScore.value', - type: CONFIG.DH.GENERAL.activeEffectModes.add.id, - value: change.value - }, - replacementData - ); - game.system.api.documents.DhActiveEffect.applyChange( - actor, - { - ...change, - key: 'system.armorScore.max', - type: CONFIG.DH.GENERAL.activeEffectModes.add.id, - value: change.max - }, - replacementData - ); - return {}; - }, - render: null - }; - - /* Helpers */ - - get armorChange() { - if (this.changes.length !== 1) - throw new Error('Unexpected error. An armor effect should have a changes field of length 1.'); - - const actor = this.parent.actor?.type === 'character' ? this.parent.actor : null; - const changeData = this.changes[0]; - const maxParse = actor ? itemAbleRollParse(changeData.max, actor, this.parent.parent) : null; - const maxRoll = maxParse ? new Roll(maxParse).evaluateSync() : null; - const maxEvaluated = maxRoll ? (maxRoll.isDeterministic ? maxRoll.total : null) : null; - - return { - ...changeData, - max: maxEvaluated ?? changeData.max - }; - } - - get armorData() { - return { value: this.armorChange.value, max: this.armorChange.max }; - } - - async updateArmorMax(newMax) { - const { effect, ...baseChange } = this.armorChange; - const newChanges = [ - { - ...baseChange, - max: newMax, - value: Math.min(this.armorChange.value, newMax) - } - ]; - await this.parent.update({ 'system.changes': newChanges }); - } - - static orderEffectsForAutoChange(armorEffects, increasing) { - const getEffectWeight = effect => { - switch (effect.parent.type) { - case 'class': - case 'subclass': - case 'ancestry': - case 'community': - case 'feature': - case 'domainCard': - return 2; - case 'armor': - return 3; - case 'loot': - case 'consumable': - return 4; - case 'weapon': - return 5; - case 'character': - return 6; - default: - return 1; - } - }; - - return armorEffects - .filter(x => !x.disabled && !x.isSuppressed) - .sort((a, b) => - increasing ? getEffectWeight(b) - getEffectWeight(a) : getEffectWeight(a) - getEffectWeight(b) - ); - } - - /* Overrides */ - - static getDefaultObject() { - return { - key: 'system.armorScore', - type: 'armor', - name: game.i18n.localize('DAGGERHEART.EFFECTS.Armor.newArmorEffect'), - img: 'icons/equipment/chest/breastplate-helmet-metal.webp' - }; - } - - async _preUpdate(changes, options, user) { - const allowed = await super._preUpdate(changes, options, user); - if (allowed === false) return false; - - if (changes.system?.changes) { - const changesChanged = changes.system.changes.length !== this.changes.length; - if (changesChanged) { - ui.notifications.error( - game.i18n.localize('DAGGERHEART.UI.Notifications.cannotAlterArmorEffectChanges') - ); - return false; - } - - if (changes.system.changes.length === 1) { - if (changes.system.changes[0].type !== CONFIG.DH.GENERAL.activeEffectModes.armor.id) { - ui.notifications.error( - game.i18n.localize('DAGGERHEART.UI.Notifications.cannotAlterArmorEffectType') - ); - return false; - } - - if (changes.system.changes[0].key !== 'system.armorScore') { - ui.notifications.error( - game.i18n.localize('DAGGERHEART.UI.Notifications.cannotAlterArmorEffectKey') - ); - return false; - } - - if ( - changes.system.changes[0].value !== this.armorChange.value && - this.parent.actor?.type === 'character' - ) { - options.scrollingTextData = [ - getScrollTextData(this.parent.actor, changes.system.changes[0], 'armor') - ]; - } - } - } - } - - _onUpdate(changes, options, userId) { - super._onUpdate(changes, options, userId); - - if (options.scrollingTextData && this.parent.actor?.type === 'character') - this.parent.actor.queueScrollText(options.scrollingTextData); - } -} diff --git a/module/data/activeEffect/changeTypes/armor.mjs b/module/data/activeEffect/changeTypes/armor.mjs index 5ef38989..f368fa78 100644 --- a/module/data/activeEffect/changeTypes/armor.mjs +++ b/module/data/activeEffect/changeTypes/armor.mjs @@ -16,8 +16,8 @@ export default class Armor extends foundry.abstract.DataModel { required: true, choices: CONFIG.DH.GENERAL.activeEffectArmorInteraction, initial: CONFIG.DH.GENERAL.activeEffectArmorInteraction.none.id, - label: 'DAGGERHEART.EFFECTS.Armor.FIELDS.armorInteraction.label', - hint: 'DAGGERHEART.EFFECTS.Armor.FIELDS.armorInteraction.hint' + label: 'DAGGERHEART.EFFECTS.ChangeTypes.armor.FIELDS.armorInteraction.label', + hint: 'DAGGERHEART.EFFECTS.ChangeTypes.armor.FIELDS.armorInteraction.hint' }) }; } @@ -62,20 +62,31 @@ export default class Armor extends foundry.abstract.DataModel { } } - static getInitialValue() { + static getInitialValue(locked) { return { key: 'Armor', type: CONFIG.DH.GENERAL.activeEffectModes.armor.id, value: 0, typeData: { type: 'armor', - max: 0 + max: 0, + locked }, phase: 'initial', priority: 20 }; } + static getDefaultArmorEffect() { + return { + name: game.i18n.localize('DAGGERHEART.EFFECTS.ChangeTypes.armor.newArmorEffect'), + img: 'icons/equipment/chest/breastplate-helmet-metal.webp', + system: { + changes: [Armor.getInitialValue(true)] + } + }; + } + /* Helpers */ getArmorData(parentChange) { @@ -94,7 +105,7 @@ export default class Armor extends foundry.abstract.DataModel { const newChanges = [ ...this.parent.changes.map(change => ({ ...change, - value: change.type === 'armor' ? Math.min(this.parent.value, newMax) : change.value, + value: change.type === 'armor' ? Math.min(change.value, newMax) : change.value, typeData: change.type === 'armor' ? { ...change.typeData, max: newMax } : change.typeData })) ]; diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index 76f05859..ba70e4b9 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -52,7 +52,7 @@ export default class DHArmor extends AttachableItem { } get armorEffect() { - return this.parent.effects.find(x => x.type === 'armor'); + return this.parent.effects.find(x => x.system.armorData); } get armorData() { @@ -80,9 +80,9 @@ export default class DHArmor extends AttachableItem { async _onCreate(_data, _options, userId) { if (userId !== game.user.id) return; - if (!this.parent.effects.some(x => x.type === 'armor')) { + if (!this.parent.effects.some(x => x.system.armorData)) { this.parent.createEmbeddedDocuments('ActiveEffect', [ - game.system.api.data.activeEffects.ArmorEffect.getDefaultObject() + game.system.api.data.activeEffects.changeTypes.armor.getDefaultArmorEffect() ]); } } diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index dff85fef..7426cff4 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -374,15 +374,18 @@ export async function runMigrations() { if (migrationArmorScore !== undefined && !hasArmorEffect) { await item.createEmbeddedDocuments('ActiveEffect', [ { - ...game.system.api.data.activeEffects.ArmorEffect.getDefaultObject(), + ...game.system.api.data.activeEffects.changeTypes.armor.getDefaultArmorEffect(), changes: [ { - key: 'system.armorScore', - type: CONFIG.DH.GENERAL.activeEffectModes.armor.id, + key: 'Armor', + type: CONFIG.DH.GENERAL.activeEffectModes.armor, phase: 'initial', priority: 20, value: 0, - max: migrationArmorScore.toString() + typeData: { + type: 'armor', + max: migrationArmorScore.toString() + } } ] } diff --git a/system.json b/system.json index dfbb473e..41e46edb 100644 --- a/system.json +++ b/system.json @@ -278,8 +278,7 @@ }, "ActiveEffect": { "beastform": {}, - "horde": {}, - "armor": {} + "horde": {} }, "Combat": { "combat": {} diff --git a/templates/sheets/activeEffect/changes.hbs b/templates/sheets/activeEffect/changes.hbs index fe9ed238..e687c2e9 100644 --- a/templates/sheets/activeEffect/changes.hbs +++ b/templates/sheets/activeEffect/changes.hbs @@ -14,7 +14,7 @@ {{/each}} -
+
{{localize "DAGGERHEART.GENERAL.armor"}} {{#if typedChanges.armor}}