From cb2116ffefa84685677dd52798c55edf06671c06 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sat, 23 May 2026 23:55:46 +0200 Subject: [PATCH] Initial --- lang/en.json | 1 + module/applications/ui/chatLog.mjs | 20 +++++++++-- module/dice/die/dualityDie.mjs | 21 ++--------- module/dice/dualityRoll.mjs | 56 ++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 21 deletions(-) diff --git a/lang/en.json b/lang/en.json index a06c46c2..775dd6a3 100755 --- a/lang/en.json +++ b/lang/en.json @@ -3097,6 +3097,7 @@ } }, "ChatLog": { + "rerollActionRoll": "Reroll Action", "rerollDamage": "Reroll Damage", "assignTagRoll": "Assign as Tag Roll" }, diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 34b25591..985d8138 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -103,6 +103,20 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo _getEntryContextOptions() { return [ ...super._getEntryContextOptions(), + { + label: 'DAGGERHEART.UI.ChatLog.rerollActionRoll', + icon: '', + visible: li => { + const message = game.messages.get(li.dataset.messageId); + return game.user.isGM || message.isAuthor; + }, + callback: async li => { + const message = game.messages.get(li.dataset.messageId); + const reroll = await message.rolls[0].reroll({ liveRoll: true }); + + message.update({ rolls: [reroll] }); + } + }, { label: 'DAGGERHEART.UI.ChatLog.rerollDamage', icon: '', @@ -113,9 +127,11 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo : false; return (game.user.isGM || message.isAuthor) && hasRolledDamage; }, - callback: li => { + callback: async li => { const message = game.messages.get(li.dataset.messageId); - new game.system.api.applications.dialogs.RerollDamageDialog(message).render({ force: true }); + const reroll = await message.rolls[0].reroll(); + message.update({ rolls: [reroll] }); + // new game.system.api.applications.dialogs.RerollDamageDialog(message).render({ force: true }); } } ]; diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs index 83229425..2de4270e 100644 --- a/module/dice/die/dualityDie.mjs +++ b/module/dice/die/dualityDie.mjs @@ -1,4 +1,5 @@ import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; +import DualityRoll from '../dualityRoll.mjs'; export default class DualityDie extends foundry.dice.terms.Die { constructor(options) { @@ -12,24 +13,6 @@ export default class DualityDie extends foundry.dice.terms.Die { return roll.withHope ? 1 : roll.withFear ? -1 : 0; } - #updateResources(oldDuality, newDuality, actor) { - const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); - if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return; - - const updates = []; - const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0); - const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); - const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); - - if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); - - const resourceUpdates = new ResourceUpdateMap(actor); - resourceUpdates.addResources(updates); - resourceUpdates.updateResources(); - } - async reroll(modifier, options) { const oldDuality = this.#getDualityState(options.liveRoll.roll); await super.reroll(modifier, options); @@ -57,7 +40,7 @@ export default class DualityDie extends foundry.dice.terms.Die { if (options.liveRoll.isReaction) return; const newDuality = this.#getDualityState(options.liveRoll.roll); - this.#updateResources(oldDuality, newDuality, options.liveRoll.actor); + DualityRoll.updateResources(oldDuality, newDuality, options.liveRoll.actor); } } diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 5e03a680..e4efc4f3 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -1,6 +1,8 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import D20Roll from './d20Roll.mjs'; import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; +import { getDiceSoNicePresets } from '../config/generalConfig.mjs'; +import { ResourceUpdateMap } from '../data/action/baseAction.mjs'; export default class DualityRoll extends D20Roll { _advantageNumber = 1; @@ -380,4 +382,58 @@ export default class DualityRoll extends D20Roll { if (currentCombatant?.actorId == config.data.id) ui.combat.setCombatantSpotlight(currentCombatant.id); } } + + static updateResources(oldDuality, newDuality, actor) { + const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return; + + const updates = []; + const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0); + const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); + const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); + + if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); + + const resourceUpdates = new ResourceUpdateMap(actor); + resourceUpdates.addResources(updates); + resourceUpdates.updateResources(); + } + + async reroll(options) { + const oldDuality = this.withHope ? 1 : this.withFear ? -1 : 0; + const rerolled = DualityRoll.fromData((await super.reroll(options)).toJSON()); + + if (options?.liveRoll) { + if (game.modules.get('dice-so-nice')?.active) { + const diceAppearance = await getDiceSoNicePresets( + rerolled, + rerolled.dHope.denomination, + rerolled.dFear.denomination + ); + rerolled.dHope.options.appearance = diceAppearance.hope.appearance; + rerolled.dFear.options.appearance = diceAppearance.fear.appearance; + if (rerolled.dAdvantage) rerolled.dAdvantage.options.appearance = diceAppearance.advantage.appearance; + if (rerolled.dDisadvantage) + rerolled.dDisadvantage.options.appearance = diceAppearance.disadvantage.appearance; + + await game.dice3d.showForRoll(rerolled, game.user, true); + } else { + foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); + } + + if (this.options.actionType === 'reaction') return; + + const newDuality = rerolled.withHope ? 1 : rerolled.withFear ? -1 : 0; + const actor = await foundry.utils.fromUuid(this.options.source.actor); + DualityRoll.updateResources(oldDuality, newDuality, actor); + } + + return rerolled; + } + + fromJSON(json) { + return super.fromJSON(json); + } }