From 920ab3fd7655525ff34f8811c3fc4cc57e735d3b Mon Sep 17 00:00:00 2001 From: WBHarry Date: Wed, 23 Jul 2025 00:37:25 +0200 Subject: [PATCH] Fixed Weapon/Armor features. Fixed Feature actions --- .../sheets/api/application-mixin.mjs | 20 ++++----- module/applications/ui/chatLog.mjs | 2 +- module/data/fields/_module.mjs | 1 + module/data/item/armor.mjs | 45 ++++++++++++++----- module/data/item/feature.mjs | 4 +- module/data/item/weapon.mjs | 38 ++++++++-------- module/documents/item.mjs | 14 +++--- module/documents/tooltipManager.mjs | 19 ++++---- module/helpers/utils.mjs | 2 +- .../global/partials/inventory-item-V2.hbs | 2 +- 10 files changed, 84 insertions(+), 63 deletions(-) diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 67dddc50..b5853694 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -82,7 +82,6 @@ export default function DHApplicationMixin(Base) { deleteDoc: DHSheetV2.#deleteDoc, toChat: DHSheetV2.#toChat, useItem: DHSheetV2.#useItem, - useAction: DHSheetV2.#useAction, toggleEffect: DHSheetV2.#toggleEffect, toggleExtended: DHSheetV2.#toggleExtended }, @@ -378,9 +377,15 @@ export default function DHApplicationMixin(Base) { static async #createDoc(event, target) { const { documentClass, type, inVault, disabled } = target.dataset; const parentIsItem = this.document.documentName === 'Item'; - const parent = parentIsItem && documentClass === 'Item' ? (type === 'action' ? this.document.system : null) : this.document; + const parent = + parentIsItem && documentClass === 'Item' + ? type === 'action' + ? this.document.system + : null + : this.document; - const cls = type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass); + const cls = + type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass); const data = { name: cls.defaultName({ type, parent }), type @@ -436,15 +441,6 @@ export default function DHApplicationMixin(Base) { await doc.use(event); } - /** - * Use a item - * @type {ApplicationClickAction} - */ - static async #useAction(event, target) { - const doc = getDocFromElement(target); - await action.use(event); - } - /** * Toggle a ActiveEffect * @type {ApplicationClickAction} diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 50fe8904..16c7a1a3 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -294,7 +294,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)]; const actor = game.actors.get(message.system.source.actor); - await actor.useAction(action); + await actor.use(action); }; actionUseButton = async (event, message) => { diff --git a/module/data/fields/_module.mjs b/module/data/fields/_module.mjs index 682ff1c4..9ad789eb 100644 --- a/module/data/fields/_module.mjs +++ b/module/data/fields/_module.mjs @@ -1,3 +1,4 @@ +export { ActionCollection } from './actionField.mjs'; export { default as FormulaField } from './formulaField.mjs'; export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs'; export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs'; diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index 85026121..625e3e1b 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -1,7 +1,6 @@ import AttachableItem from './attachableItem.mjs'; -import { ActionField } from '../fields/actionField.mjs'; +import { ActionsField } from '../fields/actionField.mjs'; import { armorFeatures } from '../../config/itemConfig.mjs'; -import { actionsTypes } from '../action/_module.mjs'; export default class DHArmor extends AttachableItem { /** @inheritDoc */ @@ -40,7 +39,7 @@ export default class DHArmor extends AttachableItem { major: new fields.NumberField({ integer: true, initial: 0 }), severe: new fields.NumberField({ integer: true, initial: 0 }) }), - actions: new fields.ArrayField(new ActionField()) + actions: new ActionsField() }; } @@ -65,7 +64,10 @@ export default class DHArmor extends AttachableItem { actionIds.push(...feature.actionIds); } await this.parent.deleteEmbeddedDocuments('ActiveEffect', effectIds); - changes.system.actions = this.actions.filter(x => !actionIds.includes(x._id)); + changes.system.actions = actionIds.reduce((acc, id) => { + acc[`-=${id}`] = null; + return acc; + }, {}); for (var feature of added) { const featureData = armorFeatures[feature.value]; @@ -79,17 +81,38 @@ export default class DHArmor extends AttachableItem { ]); feature.effectIds = embeddedItems.map(x => x.id); } + + const newActions = {}; if (featureData.actions?.length > 0) { - const newActions = featureData.actions.map(action => { - const cls = actionsTypes[action.type]; - return new cls( - { ...action, _id: foundry.utils.randomID(), name: game.i18n.localize(action.name) }, + for (let action of featureData.actions) { + const embeddedEffects = await this.parent.createEmbeddedDocuments( + 'ActiveEffect', + (action.effects ?? []).map(effect => ({ + ...effect, + transfer: false, + name: game.i18n.localize(effect.name), + description: game.i18n.localize(effect.description) + })) + ); + + const cls = game.system.api.models.actions.actionsTypes[action.type]; + const actionId = foundry.utils.randomID(); + newActions[actionId] = new cls( + { + ...cls.getSourceConfig(this), + ...action, + _id: actionId, + name: game.i18n.localize(action.name), + description: game.i18n.localize(action.description), + effects: embeddedEffects.map(x => ({ _id: x.id })) + }, { parent: this } ); - }); - changes.system.actions = [...this.actions, ...newActions]; - feature.actionIds = newActions.map(x => x._id); + } } + + changes.system.actions = newActions; + feature.actionIds = Object.keys(newActions); } } } diff --git a/module/data/item/feature.mjs b/module/data/item/feature.mjs index 3f7fdad8..9507282a 100644 --- a/module/data/item/feature.mjs +++ b/module/data/item/feature.mjs @@ -1,5 +1,5 @@ import BaseDataItem from './base.mjs'; -import { ActionField } from '../fields/actionField.mjs'; +import { ActionField, ActionsField } from '../fields/actionField.mjs'; export default class DHFeature extends BaseDataItem { /** @inheritDoc */ @@ -25,7 +25,7 @@ export default class DHFeature extends BaseDataItem { subType: new fields.StringField({ choices: CONFIG.DH.ITEM.featureSubTypes, nullable: true, initial: null }), originId: new fields.StringField({ nullable: true, initial: null }), identifier: new fields.StringField(), - actions: new fields.ArrayField(new ActionField()) + actions: new ActionsField() }; } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index fd26975b..234b4303 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -1,5 +1,4 @@ import AttachableItem from './attachableItem.mjs'; -import { actionsTypes } from '../action/_module.mjs'; import { ActionsField, ActionField } from '../fields/actionField.mjs'; export default class DHWeapon extends AttachableItem { @@ -66,7 +65,6 @@ export default class DHWeapon extends AttachableItem { } }), actions: new ActionsField() - // actions: new fields.ArrayField(new ActionField()) }; } @@ -96,7 +94,10 @@ export default class DHWeapon extends AttachableItem { } await this.parent.deleteEmbeddedDocuments('ActiveEffect', removedEffectsUpdate); - changes.system.actions = this.actions.filter(x => !removedActionsUpdate.includes(x._id)); + changes.system.actions = removedActionsUpdate.reduce((acc, id) => { + acc[`-=${id}`] = null; + return acc; + }, {}); for (let weaponFeature of added) { const featureData = CONFIG.DH.ITEM.weaponFeatures[weaponFeature.value]; @@ -111,7 +112,7 @@ export default class DHWeapon extends AttachableItem { weaponFeature.effectIds = embeddedItems.map(x => x.id); } - const newActions = []; + const newActions = {}; if (featureData.actions?.length > 0) { for (let action of featureData.actions) { const embeddedEffects = await this.parent.createEmbeddedDocuments( @@ -123,24 +124,25 @@ export default class DHWeapon extends AttachableItem { description: game.i18n.localize(effect.description) })) ); - const cls = actionsTypes[action.type]; - newActions.push( - new cls( - { - ...action, - _id: foundry.utils.randomID(), - name: game.i18n.localize(action.name), - description: game.i18n.localize(action.description), - effects: embeddedEffects.map(x => ({ _id: x.id })) - }, - { parent: this } - ) + + const cls = game.system.api.models.actions.actionsTypes[action.type]; + const actionId = foundry.utils.randomID(); + newActions[actionId] = new cls( + { + ...cls.getSourceConfig(this), + ...action, + _id: actionId, + name: game.i18n.localize(action.name), + description: game.i18n.localize(action.description), + effects: embeddedEffects.map(x => ({ _id: x.id })) + }, + { parent: this } ); } } - changes.system.actions = [...this.actions, ...newActions]; - weaponFeature.actionIds = newActions.map(x => x._id); + changes.system.actions = newActions; + weaponFeature.actionIds = Object.keys(newActions); } } } diff --git a/module/documents/item.mjs b/module/documents/item.mjs index ba1c73ae..fe72b5ab 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -12,15 +12,15 @@ export default class DHItem extends foundry.documents.Item { /** @inheritDoc */ getEmbeddedDocument(embeddedName, id, options) { let doc; - switch ( embeddedName ) { - case "Action": + switch (embeddedName) { + case 'Action': doc = this.system.actions?.get(id); - if(!doc && this.system.attack?.id === id) doc = this.system.attack; + if (!doc && this.system.attack?.id === id) doc = this.system.attack; break; default: return super.getEmbeddedDocument(embeddedName, id, options); } - if ( options?.strict && !doc ) { + if (options?.strict && !doc) { throw new Error(`The key ${id} does not exist in the ${embeddedName} Collection`); } return doc; @@ -124,9 +124,9 @@ export default class DHItem extends foundry.documents.Item { async use(event) { const actions = this.system.actionsList; - if (actions?.length) { - let action = actions[0]; - if (actions.length > 1 && !event?.shiftKey) { + if (actions?.size) { + let action = actions.contents[0]; + if (actions.size > 1 && !event?.shiftKey) { // Actions Choice Dialog action = await this.selectActionDialog(event); } diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index bf6083ab..71dd71d2 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -4,19 +4,18 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti let html = options.html; if (element.dataset.tooltip?.startsWith('#item#')) { - const splitValues = element.dataset.tooltip.slice(6).split('#action#'); - const itemUuid = splitValues[0]; - const actionId = splitValues.length > 1 ? splitValues[1] : null; - - const baseItem = await foundry.utils.fromUuid(itemUuid); - const item = actionId ? baseItem.system.actions.get(actionId) : baseItem; + const itemUuid = element.dataset.tooltip.slice(6); + const item = await foundry.utils.fromUuid(itemUuid); if (item) { - const type = actionId ? 'action' : item.type; - const description = await TextEditor.enrichHTML(item.system.description); - for (let feature of item.system.features) { - feature.system.enrichedDescription = await TextEditor.enrichHTML(feature.system.description); + const isAction = item instanceof game.system.api.models.actions.actionsTypes.base; + const description = await TextEditor.enrichHTML(isAction ? item.description : item.system.description); + if (item.system?.features) { + for (let feature of item.system.features) { + feature.system.enrichedDescription = await TextEditor.enrichHTML(feature.system.description); + } } + const type = isAction ? 'action' : item.type; html = await foundry.applications.handlebars.renderTemplate( `systems/daggerheart/templates/ui/tooltip/${type}.hbs`, { diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 7e73695e..5ee52018 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -96,7 +96,7 @@ export const tagifyElement = (element, options, onChange, tagifyOptions = {}) => mapValueTo: 'name', searchKeys: ['name'], enabled: 0, - maxItems: 20, + maxItems: 100, closeOnSelect: true, highlightFirst: false }, diff --git a/templates/sheets/global/partials/inventory-item-V2.hbs b/templates/sheets/global/partials/inventory-item-V2.hbs index 8d7fb1a8..88b571cb 100644 --- a/templates/sheets/global/partials/inventory-item-V2.hbs +++ b/templates/sheets/global/partials/inventory-item-V2.hbs @@ -249,7 +249,7 @@ Parameters: {{#if (and showActions (eq item.type 'feature'))}}
{{#each item.system.actions as | action |}} - {{/each}}