From b05915bd804c31a83c1f10b81fd646da6962f892 Mon Sep 17 00:00:00 2001 From: George Brocklehurst Date: Sun, 20 Jul 2025 10:08:39 +0100 Subject: [PATCH] Downtime: allow moves to be taken individually. Fixes https://github.com/Foundryborne/daggerheart/issues/374 Some downtime moves require a roll to see how successful they are. In these cases, the player might want to see how their first move works out before they select their next one. This commit updates the downtime dialog to allow for this behaviour: - The "Take Downtime" button is enabled whenever any moves are selected. - Clicking the button only closes the dialog when all moves have been made. To keep track of this, the `nrChoices` object has been expanded to include a `taken` counter, which is increased whenever a move is taken. After making one move the selection is reset, but the number of moves displayed in the dialog header and the number of permitted selections both take the number of taken moves into account. --- module/applications/dialogs/downtime.mjs | 51 ++++++++++++++++++------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 4922b4ed..15f84c6f 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -12,11 +12,13 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV ); this.nrChoices = { shortRest: { + taken: 0, max: (shortrest ? this.moveData.shortRest.nrChoices : 0) + actor.system.bonuses.rest[`${shortrest ? 'short' : 'long'}Rest`].shortMoves }, longRest: { + taken: 0, max: (!shortrest ? this.moveData.longRest.nrChoices : 0) + actor.system.bonuses.rest[`${shortrest ? 'short' : 'long'}Rest`].longMoves @@ -67,15 +69,23 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV return acc; }, 0); + const shortRestMovesSelected = Object.values(this.moveData.shortRest.moves).reduce( + (acc, x) => acc + (x.selected ?? 0), + 0 + ); + const longRestMovesSelected = Object.values(this.moveData.longRest.moves).reduce( + (acc, x) => acc + (x.selected ?? 0), + 0 + ); context.nrChoices = { ...this.nrChoices, shortRest: { ...this.nrChoices.shortRest, - current: Object.values(this.moveData.shortRest.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0) + current: this.nrChoices.shortRest.taken + shortRestMovesSelected }, longRest: { ...this.nrChoices.longRest, - current: Object.values(this.moveData.longRest.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0) + current: this.nrChoices.longRest.taken + longRestMovesSelected } }; context.nrChoices.total = { @@ -86,26 +96,23 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV context.shortRestMoves = this.nrChoices.shortRest.max > 0 ? this.moveData.shortRest : null; context.longRestMoves = this.nrChoices.longRest.max > 0 ? this.moveData.longRest : null; - context.disabledDowntime = context.nrChoices.total.current < context.nrChoices.total.max; + context.disabledDowntime = shortRestMovesSelected === 0 && longRestMovesSelected === 0; return context; } static selectMove(_, target) { - const nrSelected = Object.values(this.moveData[target.dataset.category].moves).reduce( - (acc, x) => acc + (x.selected ?? 0), - 0 - ); + const { category, move } = target.dataset; - if (nrSelected === this.nrChoices[target.dataset.category].max) { + const nrSelected = Object.values(this.moveData[category].moves).reduce((acc, x) => acc + (x.selected ?? 0), 0); + + if (nrSelected + this.nrChoices[category].taken >= this.nrChoices[category].max) { ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noMoreMoves')); return; } - const move = target.dataset.move; - this.moveData[target.dataset.category].moves[move].selected = this.moveData[target.dataset.category].moves[move] - .selected - ? this.moveData[target.dataset.category].moves[move].selected + 1 + this.moveData[category].moves[move].selected = this.moveData[category].moves[move].selected + ? this.moveData[category].moves[move].selected + 1 : 1; this.render(); @@ -158,7 +165,25 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV cls.create(msg.toObject()); - this.close(); + // Reset selection and update number of taken moves + for (const [catName, category] of Object.entries(this.moveData)) { + for (const move of Object.values(category.moves)) { + if (move.selected > 0) { + this.nrChoices[catName].taken += move.selected; + move.selected = 0; + } + } + } + + // We can close the window when all moves are taken + if ( + this.nrChoices.shortRest.taken >= this.nrChoices.shortRest.max && + this.nrChoices.longRest.taken >= this.nrChoices.longRest.max + ) { + this.close(); + } else { + this.render(); + } } static async updateData(event, element, formData) {