From 259b66236c0483e905dc4cbd532886e4836465b2 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Tue, 31 Mar 2026 11:26:45 -0400 Subject: [PATCH] [V14] Update duality and fate chat commands (#1759) * Update duality and fate chat commands for v14 * FateRoll withfear/withHope wasn't working after merging with v14-Dev. Fixed --------- Co-authored-by: WBHarry --- daggerheart.mjs | 75 --------------------------- module/applications/ui/chatLog.mjs | 83 +++++++++++++++++++++++++++++- module/dice/fateRoll.mjs | 6 +-- 3 files changed, 84 insertions(+), 80 deletions(-) diff --git a/daggerheart.mjs b/daggerheart.mjs index 82fae3c9..240d8704 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -9,10 +9,7 @@ import * as dice from './module/dice/_module.mjs'; import * as fields from './module/data/fields/_module.mjs'; import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs'; import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs'; -import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs'; import { BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll } from './module/dice/_module.mjs'; -import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs'; -import { enrichedFateRoll, getFateTypeData } from './module/enrichers/FateRollEnricher.mjs'; import { handlebarsRegistration, runMigrations, @@ -335,78 +332,6 @@ Hooks.on('renderHandlebarsApplication', (_, element) => { enricherRenderSetup(element); }); -Hooks.on('chatMessage', (_, message) => { - if (message.startsWith('/dr')) { - const result = - message.trim().toLowerCase() === '/dr' ? { result: {} } : rollCommandToJSON(message.replace(/\/dr\s?/, '')); - if (!result) { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.dualityParsing')); - return false; - } - - const { result: rollCommand, flavor } = result; - - const reaction = rollCommand.reaction; - const traitValue = rollCommand.trait?.toLowerCase(); - const advantage = rollCommand.advantage - ? CONFIG.DH.ACTIONS.advantageState.advantage.value - : rollCommand.disadvantage - ? CONFIG.DH.ACTIONS.advantageState.disadvantage.value - : undefined; - const difficulty = rollCommand.difficulty; - const grantResources = rollCommand.grantResources; - - const target = getCommandTarget({ allowNull: true }); - const title = - (flavor ?? traitValue) - ? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { - ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label) - }) - : game.i18n.localize('DAGGERHEART.GENERAL.duality'); - - enrichedDualityRoll({ - reaction, - traitValue, - target, - difficulty, - title, - label: game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll'), - actionType: null, - advantage, - grantResources - }); - return false; - } - - if (message.startsWith('/fr')) { - const result = - message.trim().toLowerCase() === '/fr' ? { result: {} } : rollCommandToJSON(message.replace(/\/fr\s?/, '')); - - if (!result) { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateParsing')); - return false; - } - - const { result: rollCommand, flavor } = result; - const fateTypeData = getFateTypeData(rollCommand?.type); - - if (!fateTypeData) - return ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing')); - - const { value: fateType, label: fateTypeLabel } = fateTypeData; - const target = getCommandTarget({ allowNull: true }); - const title = flavor ?? game.i18n.localize('DAGGERHEART.GENERAL.fateRoll'); - - enrichedFateRoll({ - target, - title, - label: fateTypeLabel, - fateType - }); - return false; - } -}); - Hooks.on(CONFIG.DH.HOOKS.hooksConfig.tagTeamStart, async data => { if (data.openForAllPlayers && data.partyId) { const party = game.actors.get(data.partyId); diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index fc826425..8cbacb09 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -1,5 +1,8 @@ import { abilities } from '../../config/actorConfig.mjs'; -import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; +import { enrichedDualityRoll } from '../../enrichers/DualityRollEnricher.mjs'; +import { enrichedFateRoll, getFateTypeData } from '../../enrichers/FateRollEnricher.mjs'; +import { getCommandTarget, rollCommandToJSON } from '../../helpers/utils.mjs'; +import { emitAsGM, GMUpdateEvent } from '../../systemRegistration/socket.mjs'; export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog { constructor(options) { @@ -21,6 +24,84 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo classes: ['daggerheart'] }; + static CHAT_COMMANDS = { + ...super.CHAT_COMMANDS, + dr: { + rgx: /^(?:\/dr)((?:\s)[^]*)?/, + fn: (_, match) => { + const argString = match[1]?.trim(); + const result = argString ? rollCommandToJSON(argString) : { result: {} }; + if (!result) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.dualityParsing')); + return false; + } + + const { result: rollCommand, flavor } = result; + + const reaction = rollCommand.reaction; + const traitValue = rollCommand.trait?.toLowerCase(); + const advantage = rollCommand.advantage + ? CONFIG.DH.ACTIONS.advantageState.advantage.value + : rollCommand.disadvantage + ? CONFIG.DH.ACTIONS.advantageState.disadvantage.value + : undefined; + const difficulty = rollCommand.difficulty; + const grantResources = rollCommand.grantResources; + + const target = getCommandTarget({ allowNull: true }); + const title = + (flavor ?? traitValue) + ? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { + ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label) + }) + : game.i18n.localize('DAGGERHEART.GENERAL.duality'); + + enrichedDualityRoll({ + reaction, + traitValue, + target, + difficulty, + title, + label: game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll'), + actionType: null, + advantage, + grantResources + }); + return false; + } + }, + fr: { + rgx: /^(?:\/fr)((?:\s)[^]*)?/, + fn: (_, match) => { + const argString = match[1]?.trim(); + const result = argString ? rollCommandToJSON(argString) : { result: {} }; + + if (!result) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateParsing')); + return false; + } + + const { result: rollCommand, flavor } = result; + const fateTypeData = getFateTypeData(rollCommand?.type); + + if (!fateTypeData) + return ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing')); + + const { value: fateType, label: fateTypeLabel } = fateTypeData; + const target = getCommandTarget({ allowNull: true }); + const title = flavor ?? game.i18n.localize('DAGGERHEART.GENERAL.fateRoll'); + + enrichedFateRoll({ + target, + title, + label: fateTypeLabel, + fateType + }); + return false; + } + } + }; + _getEntryContextOptions() { return [ ...super._getEntryContextOptions(), diff --git a/module/dice/fateRoll.mjs b/module/dice/fateRoll.mjs index ec03715a..114fad59 100644 --- a/module/dice/fateRoll.mjs +++ b/module/dice/fateRoll.mjs @@ -44,13 +44,11 @@ export default class FateRoll extends D20Roll { } get withHope() { - if (!this._evaluatedl) return; - return this.dHope.total >= this.dFear.total; + return this.data.fateType === 'Hope'; } get withFear() { - if (!this._evaluated) return; - return this.dHope.total < this.dFear.total; + return this.data.fateType === 'Fear'; } get totalLabel() {