From b9d67e44dad38487b7c9fbdd81d4e669e4fc7393 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:17:22 +0100 Subject: [PATCH] [Fix] Downtime Actions (#1295) * Fixed so downtime actiosn can be used again * Update module/data/fields/action/targetField.mjs Co-authored-by: Carlos Fernandez * . --------- Co-authored-by: Carlos Fernandez --- module/applications/dialogs/downtime.mjs | 15 ++++++++---- module/applications/ui/chatLog.mjs | 13 +++++++++-- module/config/itemConfig.mjs | 5 ++++ module/data/action/baseAction.mjs | 3 +++ module/data/chat-message/actorRoll.mjs | 28 +++++++++++++++++++---- module/data/fields/action/damageField.mjs | 4 +++- module/data/fields/action/targetField.mjs | 18 +++++++-------- module/documents/chatMessage.mjs | 8 ++++--- styles/less/ui/chat/damage-summary.less | 9 +++++--- styles/less/ui/chat/effect-summary.less | 9 +++++--- templates/ui/chat/damageSummary.hbs | 2 +- templates/ui/chat/downtime.hbs | 2 +- templates/ui/chat/effectSummary.hbs | 2 +- 13 files changed, 86 insertions(+), 32 deletions(-) diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index b0f51c4e..2ed2302c 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -178,10 +178,17 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV } static async takeDowntime() { - const moves = Object.values(this.moveData).flatMap(category => { - return Object.values(category.moves) - .filter(x => x.selected) - .flatMap(move => [...Array(move.selected).keys()].map(_ => move)); + const moves = Object.keys(this.moveData).flatMap(categoryKey => { + const category = this.moveData[categoryKey]; + return Object.keys(category.moves) + .filter(x => category.moves[x].selected) + .flatMap(key => { + const move = category.moves[key]; + return [...Array(move.selected).keys()].map(_ => ({ + ...move, + movePath: `${categoryKey}.moves.${key}` + })); + }); }); const cls = getDocumentClass('ChatMessage'); diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index c62affeb..e2e3b6d4 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -132,12 +132,21 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } async actionUseButton(event, message) { - const { moveIndex, actionIndex } = event.currentTarget.dataset; + const { moveIndex, actionIndex, movePath } = event.currentTarget.dataset; const parent = await foundry.utils.fromUuid(message.system.actor); const actionType = message.system.moves[moveIndex].actions[actionIndex]; const cls = game.system.api.models.actions.actionsTypes[actionType.type]; const action = new cls( - { ...actionType, _id: foundry.utils.randomID(), name: game.i18n.localize(actionType.name) }, + { + ...actionType, + _id: foundry.utils.randomID(), + name: game.i18n.localize(actionType.name), + originItem: { + type: CONFIG.DH.ITEM.originItemType.restMove, + itemPath: movePath, + actionIndex: actionIndex + } + }, { parent: parent.system } ); diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index d815181b..544d6b2d 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -1547,3 +1547,8 @@ export const beastformTypes = { label: 'DAGGERHEART.CONFIG.BeastformType.hybrid' } }; + +export const originItemType = { + itemCollection: 'itemCollection', + restMove: 'restMove' +}; diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index 8cadd4f8..ba401ae9 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -1,6 +1,7 @@ import DhpActor from '../../documents/actor.mjs'; import D20RollDialog from '../../applications/dialogs/d20RollDialog.mjs'; import { ActionMixin } from '../fields/actionField.mjs'; +import { originItemField } from '../chat-message/actorRoll.mjs'; const fields = foundry.data.fields; @@ -25,6 +26,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel description: new fields.HTMLField(), img: new fields.FilePathField({ initial: undefined, categories: ['IMAGE'], base64: false }), chatDisplay: new fields.BooleanField({ initial: true, label: 'DAGGERHEART.ACTIONS.Config.displayInChat' }), + originItem: originItemField(), actionType: new fields.StringField({ choices: CONFIG.DH.ITEM.actionTypes, initial: 'action', @@ -215,6 +217,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel title: `${this.item instanceof CONFIG.Actor.documentClass ? '' : `${this.item.name}: `}${game.i18n.localize(this.name)}`, source: { item: this.item._id, + originItem: this.originItem, action: this._id, actor: this.actor.uuid }, diff --git a/module/data/chat-message/actorRoll.mjs b/module/data/chat-message/actorRoll.mjs index a2cb03f9..61262529 100644 --- a/module/data/chat-message/actorRoll.mjs +++ b/module/data/chat-message/actorRoll.mjs @@ -17,6 +17,16 @@ const targetsField = () => }) ); +export const originItemField = () => + new fields.SchemaField({ + type: new fields.StringField({ + choices: CONFIG.DH.ITEM.originItemType, + initial: CONFIG.DH.ITEM.originItemType.itemCollection + }), + itemPath: new fields.StringField(), + actionIndex: new fields.StringField() + }); + export default class DHActorRoll extends foundry.abstract.TypeDataModel { static defineSchema() { return { @@ -35,6 +45,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { source: new fields.SchemaField({ actor: new fields.StringField(), item: new fields.StringField(), + originItem: originItemField(), action: new fields.StringField() }), damage: new fields.ObjectField(), @@ -51,14 +62,23 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { get actionItem() { const actionActor = this.actionActor; if (!actionActor || !this.source.item) return null; - return actionActor.items.get(this.source.item); + + switch (this.source.originItem.type) { + case CONFIG.DH.ITEM.originItemType.restMove: + const restMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves; + return Array.from(foundry.utils.getProperty(restMoves, `${this.source.originItem.itemPath}`).actions)[ + this.source.originItem.actionIndex + ]; + default: + const item = actionActor.items.get(this.source.item); + return item ? item.system.actionsList?.find(a => a.id === this.source.action) : null; + } } get action() { - const actionActor = this.actionActor, - actionItem = this.actionItem; + const { actionActor, actionItem: itemAction } = this; if (!this.source.action) return null; - if (actionItem) return actionItem.system.actionsList?.find(a => a.id === this.source.action); + if (itemAction) return itemAction; else if (actionActor?.system.attack?._id === this.source.action) return actionActor.system.attack; return null; } diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index c5fd19b9..bb81c702 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -98,7 +98,9 @@ export default class DamageField extends fields.SchemaField { }); } - const token = game.scenes.find(x => x.active).tokens.find(x => x.id === target.id); + const token = target.id + ? game.scenes.find(x => x.active).tokens.find(x => x.id === target.id) + : actor.prototypeToken; if (config.hasHealing) damagePromises.push( actor.takeHealing(config.damage).then(updates => targetDamage.push({ token, updates })) diff --git a/module/data/fields/action/targetField.mjs b/module/data/fields/action/targetField.mjs index 439f2be1..41383fea 100644 --- a/module/data/fields/action/targetField.mjs +++ b/module/data/fields/action/targetField.mjs @@ -24,7 +24,7 @@ export default class TargetField extends fields.SchemaField { if (!this.target?.type) return (config.targets = []); config.hasTarget = true; let targets; - // If the Action is configured as self-targeted, set targets as the owner. + // If the Action is configured as self-targeted, set targets as the owner. Probably better way than to fallback to getDependentTokens if (this.target?.type === CONFIG.DH.GENERAL.targetTypes.self.id) targets = [this.actor.token ?? this.actor.prototypeToken]; else { @@ -72,17 +72,17 @@ export default class TargetField extends fields.SchemaField { /** * Format actor to useful datas for Action roll workflow. - * @param {*} actor Actor object to format. + * @param {*} token Token object to format. * @returns {*} Formatted Actor. */ - static formatTarget(actor) { + static formatTarget(token) { return { - id: actor.id, - actorId: actor.actor.uuid, - name: actor.actor.name, - img: actor.actor.img, - difficulty: actor.actor.system.difficulty, - evasion: actor.actor.system.evasion, + id: token.id, + actorId: token.actor.uuid, + name: token.actor.name, + img: token.actor.img, + difficulty: token.actor.system.difficulty, + evasion: token.actor.system.evasion, saved: { value: null, success: null diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index ec4c5a49..7e313891 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -145,9 +145,11 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { }); html.querySelectorAll('.token-target-container').forEach(element => { - element.addEventListener('pointerover', this.hoverTarget); - element.addEventListener('pointerout', this.unhoverTarget); - element.addEventListener('click', this.clickTarget); + if (element.dataset.token) { + element.addEventListener('pointerover', this.hoverTarget); + element.addEventListener('pointerout', this.unhoverTarget); + element.addEventListener('click', this.clickTarget); + } }); } diff --git a/styles/less/ui/chat/damage-summary.less b/styles/less/ui/chat/damage-summary.less index 02fdbadf..3fea45e5 100644 --- a/styles/less/ui/chat/damage-summary.less +++ b/styles/less/ui/chat/damage-summary.less @@ -28,12 +28,15 @@ display: flex; flex-direction: column; gap: 2px; - cursor: pointer; transition: all 0.3s ease; border-radius: 6px; - &:hover { - background: @golden-10; + &.clickable { + cursor: pointer; + + &:hover { + background: @golden-10; + } } header { diff --git a/styles/less/ui/chat/effect-summary.less b/styles/less/ui/chat/effect-summary.less index 9bea1fd9..053c0be8 100644 --- a/styles/less/ui/chat/effect-summary.less +++ b/styles/less/ui/chat/effect-summary.less @@ -90,11 +90,14 @@ background: transparent; transition: all 0.3s ease; padding: 5px; - cursor: pointer; transition: all 0.3s ease; - &:hover { - background: @golden-10; + &.clickable { + cursor: pointer; + + &:hover { + background: @golden-10; + } } img { diff --git a/templates/ui/chat/damageSummary.hbs b/templates/ui/chat/damageSummary.hbs index aa8246e1..721f153f 100644 --- a/templates/ui/chat/damageSummary.hbs +++ b/templates/ui/chat/damageSummary.hbs @@ -1,6 +1,6 @@