Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#4819, #4993] Add activity macros, pass event to item macros #4994

Open
wants to merge 1 commit into
base: 4.2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dnd5e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ Hooks.once("i18nInit", () => {
Hooks.once("ready", function() {
// Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
Hooks.on("hotbarDrop", (bar, data, slot) => {
if ( ["Item", "ActiveEffect"].includes(data.type) ) {
if ( ["ActiveEffect", "Activity", "Item"].includes(data.type) ) {
documents.macro.create5eMacro(data, slot);
return false;
}
Expand Down
45 changes: 6 additions & 39 deletions module/applications/actor/character-sheet-2.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -394,55 +394,22 @@ export default class ActorSheet5eCharacter2 extends ActorSheetV2Mixin(ActorSheet

/* -------------------------------------------- */

/**
* Handling beginning a drag-drop operation on an Activity.
* @param {DragEvent} event The originating drag event.
* @protected
*/
_onDragActivity(event) {
const { itemId } = event.target.closest("[data-item-id]").dataset;
const { activityId } = event.target.closest("[data-activity-id]").dataset;
const activity = this.actor.items.get(itemId)?.system.activities?.get(activityId);
if ( activity ) event.dataTransfer.setData("text/plain", JSON.stringify(activity.toDragData()));
}

/* -------------------------------------------- */

/**
* Handle beginning a drag-drop operation on an Item.
* @param {DragEvent} event The originating drag event.
* @protected
*/
_onDragItem(event) {
const { itemId } = event.target.closest("[data-item-id]").dataset;
const item = this.actor.items.get(itemId);
if ( item ) event.dataTransfer.setData("text/plain", JSON.stringify(item.toDragData()));
}

/* -------------------------------------------- */

/** @inheritDoc */
_onDragStart(event) {
// Add another deferred deactivation to catch the second pointerenter event that seems to be fired on Firefox.
requestAnimationFrame(() => game.tooltip.deactivate());
game.tooltip.deactivate();

const modes = CONFIG.DND5E.spellPreparationModes;

const { key } = event.target.closest("[data-key]")?.dataset ?? {};
const { level, preparationMode } = event.target.closest("[data-level]")?.dataset ?? {};
const isSlots = event.target.closest("[data-favorite-id]") || event.target.classList.contains("spell-header");
let type;
if ( key in CONFIG.DND5E.skills ) type = "skill";
else if ( key in CONFIG.DND5E.tools ) type = "tool";
else if ( modes[preparationMode]?.upcast && (level !== "0") && isSlots ) type = "slots";
if ( !type ) {
if ( event.target.matches("[data-item-id] > .item-row") ) return this._onDragItem(event);
else if ( event.target.matches("[data-item-id] [data-activity-id], [data-item-id][data-activity-id]") ) {
return this._onDragActivity(event);
}
return super._onDragStart(event);
}
if ( !type ) return super._onDragStart(event);

// Add another deferred deactivation to catch the second pointerenter event that seems to be fired on Firefox.
requestAnimationFrame(() => game.tooltip.deactivate());
game.tooltip.deactivate();

const dragData = { dnd5e: { action: "favorite", type } };
if ( type === "slots" ) dragData.dnd5e.id = (preparationMode === "prepared") ? `spell${level}` : preparationMode;
else dragData.dnd5e.id = key;
Expand Down
6 changes: 5 additions & 1 deletion module/applications/actor/npc-sheet-2.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ export default class ActorSheet5eNPC2 extends ActorSheetV2Mixin(ActorSheet5eNPC)
height: 700,
resizable: true,
scrollY: [".sheet-body"],
tabs: [{ navSelector: ".tabs", contentSelector: ".tab-body", initial: "features" }]
tabs: [{ navSelector: ".tabs", contentSelector: ".tab-body", initial: "features" }],
dragDrop: [
{ dragSelector: ".item-list .item > .item-row", dropSelector: null },
{ dragSelector: ".item-list .item .activity-row", dropSelector: null }
]
});
}

Expand Down
42 changes: 42 additions & 0 deletions module/applications/actor/sheet-v2-mixin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,48 @@ export default function ActorSheetV2Mixin(Base) {

/* -------------------------------------------- */

/**
* Handling beginning a drag-drop operation on an Activity.
* @param {DragEvent} event The originating drag event.
* @protected
*/
_onDragActivity(event) {
const { itemId } = event.target.closest("[data-item-id]").dataset;
const { activityId } = event.target.closest("[data-activity-id]").dataset;
const activity = this.actor.items.get(itemId)?.system.activities?.get(activityId);
if ( activity ) event.dataTransfer.setData("text/plain", JSON.stringify(activity.toDragData()));
}

/* -------------------------------------------- */

/**
* Handle beginning a drag-drop operation on an Item.
* @param {DragEvent} event The originating drag event.
* @protected
*/
_onDragItem(event) {
const { itemId } = event.target.closest("[data-item-id]").dataset;
const item = this.actor.items.get(itemId);
if ( item ) event.dataTransfer.setData("text/plain", JSON.stringify(item.toDragData()));
}

/* -------------------------------------------- */

/** @inheritDoc */
_onDragStart(event) {
// Add another deferred deactivation to catch the second pointerenter event that seems to be fired on Firefox.
requestAnimationFrame(() => game.tooltip.deactivate());
game.tooltip.deactivate();

if ( event.target.matches("[data-item-id] > .item-row") ) return this._onDragItem(event);
else if ( event.target.matches("[data-item-id] [data-activity-id], [data-item-id][data-activity-id]") ) {
return this._onDragActivity(event);
}
return super._onDragStart(event);
}

/* -------------------------------------------- */

/**
* Handle performing some action on an owned Item.
* @param {PointerEvent} event The triggering event.
Expand Down
31 changes: 23 additions & 8 deletions module/documents/macro.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,44 @@
export async function create5eMacro(dropData, slot) {
const macroData = { type: "script", scope: "actor" };
switch ( dropData.type ) {
case "Activity":
const activity = await fromUuid(dropData.uuid);
if ( !activity ) {
ui.notifications.warn("MACRO.5eUnownedWarn", { localize: true });
return null;
}
foundry.utils.mergeObject(macroData, {
name: `${activity.item.name}: ${activity.name}`,
img: activity.img,
command: `dnd5e.documents.macro.rollItem("${activity.item._source.name}", { activityName: "${
activity._source.name}", event });`,
flags: { "dnd5e.itemMacro": true }
});
break;
case "Item":
const itemData = await Item.implementation.fromDropData(dropData);
if ( !itemData ) {
ui.notifications.warn("MACRO.5eUnownedWarn", {localize: true});
ui.notifications.warn("MACRO.5eUnownedWarn", { localize: true });
return null;
}
foundry.utils.mergeObject(macroData, {
name: itemData.name,
img: itemData.img,
command: `dnd5e.documents.macro.rollItem("${itemData._source.name}")`,
flags: {"dnd5e.itemMacro": true}
command: `dnd5e.documents.macro.rollItem("${itemData._source.name}", { event })`,
flags: { "dnd5e.itemMacro": true }
});
break;
case "ActiveEffect":
const effectData = await ActiveEffect.implementation.fromDropData(dropData);
if ( !effectData ) {
ui.notifications.warn("MACRO.5eUnownedWarn", {localize: true});
ui.notifications.warn("MACRO.5eUnownedWarn", { localize: true });
return null;
}
foundry.utils.mergeObject(macroData, {
name: effectData.name,
img: effectData.img,
command: `dnd5e.documents.macro.toggleEffect("${effectData.name}")`,
flags: {"dnd5e.effectMacro": true}
flags: { "dnd5e.effectMacro": true }
});
break;
default:
Expand Down Expand Up @@ -84,12 +98,13 @@ function getMacroTarget(name, documentType) {
* @param {string} itemName Name of the item on the selected actor to trigger.
* @param {object} [options={}]
* @param {string} [options.activityName] Name of a specific activity on the item to trigger.
* @param {Event} [options.event] The triggering event.
* @returns {Promise<ChatMessage|object>} Usage result.
*/
export function rollItem(itemName, { activityName }={}) {
export function rollItem(itemName, { activityName, event }={}) {
let target = getMacroTarget(itemName, "Item");
if ( activityName ) target = target?.system.activities?.getName(activityName);
return target?.use({ legacy: false });
return target?.use({ event, legacy: false });
}

/* -------------------------------------------- */
Expand All @@ -101,5 +116,5 @@ export function rollItem(itemName, { activityName }={}) {
*/
export function toggleEffect(effectName) {
const effect = getMacroTarget(effectName, "ActiveEffect");
return effect?.update({disabled: !effect.disabled});
return effect?.update({ disabled: !effect.disabled });
}