diff --git a/module/deltagreen.js b/module/deltagreen.js index 6f91fa7..f9c3d6f 100644 --- a/module/deltagreen.js +++ b/module/deltagreen.js @@ -13,7 +13,7 @@ import { rollItemMacro, rollItemSkillCheckMacro, rollSkillMacro, - rollSkillTestForItemAndActor, + rollSkillTestAndDamageForOwnedItem, } from "./other/macro-functions.js"; Hooks.once("init", async () => { @@ -24,7 +24,7 @@ Hooks.once("init", async () => { rollItemSkillCheckMacro, rollSkillMacro, ParseDeltaGreenStatBlock, - rollSkillTestForItemAndActor, + rollSkillTestAndDamageForOwnedItem, }; /** @@ -63,9 +63,12 @@ Hooks.once("init", async () => { Hooks.once("ready", async () => { // Wait to register hotbar drop hook on ready so that modules could register earlier if they want to - Hooks.on("hotbarDrop", (bar, data, slot) => - createDeltaGreenMacro(data, slot), - ); + Hooks.on("hotbarDrop", (bar, data, slot) => { + if (data.type === "Item") { + createDeltaGreenMacro(data, slot); + return false; + } + }); }); Hooks.on("preCreateItem", (item) => { diff --git a/module/item/item.js b/module/item/item.js index e0479da..ef40f62 100644 --- a/module/item/item.js +++ b/module/item/item.js @@ -22,7 +22,7 @@ export default class DeltaGreenItem extends Item { * @param {Event} event The originating click event * @private */ - async roll() { + async roll(isCrit = false) { // Basic template rendering data const item = this; const { actor } = this; @@ -44,6 +44,10 @@ export default class DeltaGreenItem extends Item { diceFormula += actorSystemData.statistics.str.meleeDamageBonusFormula; } + if (isCrit) { + diceFormula = "2*(" + diceFormula + ")"; + } + roll = new DGDamageRoll( diceFormula, {}, diff --git a/module/other/macro-functions.js b/module/other/macro-functions.js index 0f0f8bd..d40d4e1 100644 --- a/module/other/macro-functions.js +++ b/module/other/macro-functions.js @@ -12,29 +12,38 @@ import * as DGRolls from "../roll/roll.js"; * @returns {Promise} */ export async function createDeltaGreenMacro(data, slot) { - // Definitely should not be doing assignments in conditionals but if we fix this, it breaks macro creation. - // eslint-disable-next-line no-cond-assign - if ((data.type = "Item" && data.itemData.type !== "weapon")) return; - // if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items"); - const item = data.itemData; + if (data.type !== "Item") { + return true; + } + + if (!data.uuid.includes("Actor.") && !data.uuid.includes("Token.")) { + ui.notifications.warn("You can only create macro buttons for owned Items"); + return true; + } + + const item = await fromUuid(data.uuid); + + if (item.type !== "weapon") { + return true; + } // Create the macro command - let command = "// Uncomment line below to also roll skill check if desired."; - command += `\n//game.deltagreen.rollItemSkillCheckMacro("${item._id}");`; - command += `\ngame.deltagreen.rollItemMacro("${item._id}");`; + let command = + "// If a damage roll on a successful attack should not be automatically rolled, change the last argument from 'true' to 'false':"; + command += `\ngame.deltagreen.rollSkillTestAndDamageForOwnedItem("${data.uuid}", true);`; - // let macro = game.macros.entities.find(m => (m.name === data.name) && (m.command === command)); - // if (!macro) { const macro = await Macro.create({ - name: data.itemData.name, + name: item.name, type: "script", - img: data.itemData.img, - command, + img: item.img, + thumbnail: item.img, + command: command, flags: { "deltagreen.itemMacro": true }, }); - // } - game.user.assignHotbarMacro(macro, slot); + await game.user.assignHotbarMacro(macro, slot); + + return false; } /** @@ -122,3 +131,52 @@ export function rollSkillMacro(skillName) { return actor.sheet.processRoll({}, roll); // sendPercentileTestToChat(actor, translatedSkillLabel, skill.proficiency); } + +/** + * Roll a skill check for an item that is owned by a specific actor. + * @param {*} itemId + * @param {*} actorId + * @returns {null|Boolean} + */ +export async function rollSkillTestAndDamageForOwnedItem( + itemUuId, + rollDamageOnSuccess, +) { + let item; + + try { + item = await fromUuid(itemUuId); + + if (item == null) { + return ui.notifications.warn("Invalid item targeted in macro."); + } + + if (item.type !== "weapon") { + return ui.notifications.warn( + "Can only roll weapons/attacks as item macros.", + ); + } + } catch { + return ui.notifications.warn("Invalid item targeted in macro."); + } + + const rollOptions = { + rollType: "weapon", + key: item.system.skill, + actor: item.parent, + specialTrainingName: null, // Only applies to Special Training Rolls + item, + }; + + const roll = new DGRolls.DGPercentileRoll("1D100", {}, rollOptions); + + await roll.evaluate(); + + roll.toChat(); + + if (roll.isSuccess && rollDamageOnSuccess) { + item.roll(roll.isCritical); + } + + return roll.isSuccess; +}