diff --git a/lang/en.json b/lang/en.json index b9e0fefa..0295b691 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1518,7 +1518,9 @@ "noAvailableArmorMarks": "You have no more available armor marks", "notEnoughStress": "You don't have enough stress", "damageIgnore": "{character} did not take damage", - "featureIsMissing": "Feature is missing" + "featureIsMissing": "Feature is missing", + "actionIsMissing": "Action is missing", + "unownedActionMacro": "Cannot make a Use macro for an Action not on your character" }, "Tooltip": { "openItemWorld": "Open Item World", diff --git a/module/applications/sheets/api/base-item.mjs b/module/applications/sheets/api/base-item.mjs index 0c25a44d..723b4802 100644 --- a/module/applications/sheets/api/base-item.mjs +++ b/module/applications/sheets/api/base-item.mjs @@ -30,7 +30,8 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { }, dragDrop: [ { dragSelector: null, dropSelector: '.tab.features .drop-section' }, - { dragSelector: '.feature-item', dropSelector: null } + { dragSelector: '.feature-item', dropSelector: null }, + { dragSelector: '.action-item', dropSelector: null } ] }; @@ -258,6 +259,23 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { const featureData = { type: 'Item', data: { ...feature.toObject(), _id: null }, fromInternal: true }; event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); + } else { + const actionItem = event.currentTarget.closest('.action-item'); + if (actionItem) { + const action = this.document.system.actions[actionItem.dataset.index]; + if (!action) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.actionIsMissing')); + return; + } + + const actionData = { + type: 'Action', + data: { ...action.toObject(), id: action.id, itemUuid: this.document.uuid }, + fromInternal: true + }; + event.dataTransfer.setData('text/plain', JSON.stringify(actionData)); + event.dataTransfer.setDragImage(actionItem.querySelector('img'), 60, 0); + } } } diff --git a/module/applications/ui/hotbar.mjs b/module/applications/ui/hotbar.mjs index 9ac87f75..4fffb4af 100644 --- a/module/applications/ui/hotbar.mjs +++ b/module/applications/ui/hotbar.mjs @@ -1,4 +1,4 @@ -export default class DhHotbar extends Hotbar { +export default class DhHotbar extends foundry.applications.ui.Hotbar { constructor(options) { super(options); @@ -19,6 +19,25 @@ export default class DhHotbar extends Hotbar { await item.use({}); } + static async useAction(itemUuid, actionId) { + const item = await foundry.utils.fromUuid(itemUuid); + if (!item) { + return ui.notifications.warn('WARNING.ObjectDoesNotExist', { + format: { + name: game.i18n.localize('Document'), + identifier: itemUuid + } + }); + } + + const action = item.system.actions.find(x => x.id === actionId); + if (!action) { + return ui.notifications.warn('DAGGERHEART.UI.Notifications.actionIsMissing'); + } + + await action.use({}); + } + setupHooks() { Hooks.on('hotbarDrop', (bar, data, slot) => { if (data.type === 'Item') { @@ -35,6 +54,16 @@ export default class DhHotbar extends Hotbar { this.createItemMacro(data, slot); return false; } + } else if (data.type === 'Action') { + const item = foundry.utils.fromUuidSync(data.data.itemUuid); + if (item.uuid.startsWith('Compendium')) return true; + if (!item.isOwned || !item.isOwner) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.unownedActionMacro')); + return false; + } + + this.createActionMacro(data, slot); + return false; } }); } @@ -49,4 +78,15 @@ export default class DhHotbar extends Hotbar { await game.user.assignHotbarMacro(macro, slot); return false; } + + async createActionMacro(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.useAction("${data.data.itemUuid}", "${data.data.id}");` + }); + await game.user.assignHotbarMacro(macro, slot); + return false; + } } diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs index 881ecf20..34e8b790 100644 --- a/module/data/countdowns.mjs +++ b/module/data/countdowns.mjs @@ -135,8 +135,8 @@ export const registerCountdownHooks = () => { if (application) { foundry.applications.instances.get(application)?.render(); } else { - foundry.applications.instances.get('narrative-countdowns').render(); - foundry.applications.instances.get('encounter-countdowns').render(); + foundry.applications.instances.get('narrative-countdowns')?.render(); + foundry.applications.instances.get('encounter-countdowns')?.render(); } return false;