From a198f6be489e01fe7add15e131cda2f7df22f1ce Mon Sep 17 00:00:00 2001 From: WBHarry Date: Tue, 15 Jul 2025 23:15:47 +0200 Subject: [PATCH] Added MacroDrag for Attacks --- lang/en.json | 4 +- module/applications/sheets/api/base-actor.mjs | 24 ++++++++++- module/applications/ui/hotbar.mjs | 41 ++++++++++++++++++- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/lang/en.json b/lang/en.json index 0295b691..20e2d066 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1520,7 +1520,9 @@ "damageIgnore": "{character} did not take damage", "featureIsMissing": "Feature is missing", "actionIsMissing": "Action is missing", - "unownedActionMacro": "Cannot make a Use macro for an Action not on your character" + "attackIsMissing": "Attack is missing", + "unownedActionMacro": "Cannot make a Use macro for an Action not on your character", + "unownedAttackMacro": "Cannot make a Use macro for an Attack that doesn't belong to one of your characters" }, "Tooltip": { "openItemWorld": "Open Item World", diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 7102fa1c..da1467a1 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -23,7 +23,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { actions: { openSettings: DHBaseActorSheet.#openSettings }, - dragDrop: [] + dragDrop: [{ dragSelector: '.inventory-item[data-type="attack"]', dropSelector: null }] }; /**@type {typeof DHBaseActorSettings}*/ @@ -49,4 +49,26 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { static async #openSettings() { await this.settingSheet.render({ force: true }); } + + /* -------------------------------------------- */ + /* Application Drag/Drop */ + /* -------------------------------------------- */ + + /** + * On dragStart on the item. + * @param {DragEvent} event - The drag event + */ + async _onDragStart(event) { + const attackItem = event.currentTarget.closest('.inventory-item[data-type="attack"]'); + + if (attackItem) { + const attackData = { + type: 'Attack', + actorUuid: this.document.uuid, + fromInternal: true + }; + event.dataTransfer.setData('text/plain', JSON.stringify(attackData)); + event.dataTransfer.setDragImage(attackItem.querySelector('img'), 60, 0); + } + } } diff --git a/module/applications/ui/hotbar.mjs b/module/applications/ui/hotbar.mjs index 4fffb4af..636465c4 100644 --- a/module/applications/ui/hotbar.mjs +++ b/module/applications/ui/hotbar.mjs @@ -38,6 +38,25 @@ export default class DhHotbar extends foundry.applications.ui.Hotbar { await action.use({}); } + static async useAttack(actorUuid) { + const actor = await foundry.utils.fromUuid(actorUuid); + if (!actor) { + return ui.notifications.warn('WARNING.ObjectDoesNotExist', { + format: { + name: game.i18n.localize('Document'), + identifier: actorUuid + } + }); + } + + const attack = actor.system.attack; + if (!attack) { + return ui.notifications.warn('DAGGERHEART.UI.Notifications.attackIsMissing'); + } + + await attack.use({}); + } + setupHooks() { Hooks.on('hotbarDrop', (bar, data, slot) => { if (data.type === 'Item') { @@ -64,6 +83,16 @@ export default class DhHotbar extends foundry.applications.ui.Hotbar { this.createActionMacro(data, slot); return false; + } else if (data.type === 'Attack') { + const actor = foundry.utils.fromUuidSync(data.actorUuid); + if (actor.uuid.startsWith('Compendium')) return true; + if (!actor.isOwner) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.unownedAttackMacro')); + return false; + } + + this.createAttackMacro(data, slot); + return false; } }); } @@ -76,7 +105,6 @@ export default class DhHotbar extends foundry.applications.ui.Hotbar { command: `await game.system.api.applications.ui.DhHotbar.useItem("${data.uuid}");` }); await game.user.assignHotbarMacro(macro, slot); - return false; } async createActionMacro(data, slot) { @@ -87,6 +115,15 @@ export default class DhHotbar extends foundry.applications.ui.Hotbar { command: `await game.system.api.applications.ui.DhHotbar.useAction("${data.data.itemUuid}", "${data.data.id}");` }); await game.user.assignHotbarMacro(macro, slot); - return false; + } + + async createAttackMacro(data, slot) { + const macro = await Macro.implementation.create({ + name: `${game.i18n.localize('Display')} ${name}`, + type: CONST.MACRO_TYPES.SCRIPT, + img: 'icons/svg/book.svg', + command: `await game.system.api.applications.ui.DhHotbar.useAttack("${data.actorUuid}");` + }); + await game.user.assignHotbarMacro(macro, slot); } }