From aea2ef99c09883ce90e1cffe35b296d1d8db70c1 Mon Sep 17 00:00:00 2001 From: psitacus Date: Sun, 27 Jul 2025 14:32:41 -0600 Subject: [PATCH] allow /dr and [[/dr]] to be rolled without selection --- daggerheart.mjs | 2 +- module/applications/dialogs/d20RollDialog.mjs | 4 ++-- module/enrichers/DualityRollEnricher.mjs | 16 +++++++++++----- module/helpers/utils.mjs | 13 ++++++++----- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/daggerheart.mjs b/daggerheart.mjs index fb743553..9b30ef0e 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -202,7 +202,7 @@ Hooks.on('chatMessage', (_, message) => { : undefined; const difficulty = rollCommand.difficulty; - const target = getCommandTarget(); + const target = getCommandTarget({ allowNull: true }); const title = traitValue ? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label) diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 05ca1505..44635a67 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -91,10 +91,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio context.roll = this.roll; context.rollType = this.roll?.constructor.name; context.rallyDie = this.roll.rallyChoices; - context.experiences = Object.keys(this.config.data.experiences).map(id => ({ + context.experiences = this.config.data?.experiences ? Object.keys(this.config.data.experiences).map(id => ({ id, ...this.config.data.experiences[id] - })); + })) : []; context.selectedExperiences = this.config.experiences; context.advantage = this.config.roll?.advantage; context.disadvantage = this.config.roll?.disadvantage; diff --git a/module/enrichers/DualityRollEnricher.mjs b/module/enrichers/DualityRollEnricher.mjs index 70f376e7..2b968945 100644 --- a/module/enrichers/DualityRollEnricher.mjs +++ b/module/enrichers/DualityRollEnricher.mjs @@ -58,7 +58,7 @@ function getDualityMessage(roll) { export const renderDualityButton = async event => { const button = event.currentTarget, traitValue = button.dataset.trait?.toLowerCase(), - target = getCommandTarget(), + target = getCommandTarget({ allowNull: true }), difficulty = button.dataset.difficulty, advantage = button.dataset.advantage ? Number(button.dataset.advantage) : undefined; @@ -80,13 +80,11 @@ export const enrichedDualityRoll = async ( { traitValue, target, difficulty, title, label, actionType, advantage }, event ) => { - if (!target) return; - const config = { event: event ?? {}, title: title, roll: { - modifier: traitValue ? target.system.traits[traitValue].value : null, + modifier: traitValue && target ? target.system.traits[traitValue].value : null, label: label, difficulty: difficulty, advantage, @@ -96,5 +94,13 @@ export const enrichedDualityRoll = async ( template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs' } }; - await target.diceRoll(config); + + if (target) { + await target.diceRoll(config); + } else { + // For no target, call DualityRoll directly with basic data + config.data = { experiences: {}, traits: {} }; + config.source = { actor: null }; + await CONFIG.Dice.daggerheart.DualityRoll.build(config); + } }; diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index e2f30130..60c434c6 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -31,21 +31,24 @@ export function rollCommandToJSON(text) { return Object.keys(result).length > 0 ? result : null; } -export const getCommandTarget = () => { +export const getCommandTarget = (options = {}) => { + const { allowNull = false } = options; let target = game.canvas.tokens.controlled.length > 0 ? game.canvas.tokens.controlled[0].actor : null; if (!game.user.isGM) { target = game.user.character; - if (!target) { + if (!target && !allowNull) { ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noAssignedPlayerCharacter')); return null; } } - if (!target) { + if (!target && !allowNull) { ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noSelectedToken')); return null; } - if (target.type !== 'character') { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.onlyUseableByPC')); + if (target && target.type !== 'character') { + if (!allowNull) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.onlyUseableByPC')); + } return null; }