From 599e9c7aa0a6ff4726230eae7a7c6a9e39a46ad4 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Tue, 5 Aug 2025 13:43:14 +0200 Subject: [PATCH] Downtime window now enumerates the actions/resources that will be refreshed upon completion. Resources can now specify their progression direction (#591) --- lang/en.json | 8 +++ module/applications/dialogs/downtime.mjs | 62 ++++++++++++++++++- module/config/itemConfig.mjs | 11 ++++ module/data/item/base.mjs | 5 ++ .../dialog/downtime/downtime-container.less | 30 +++++++++ templates/dialogs/downtime/downtime.hbs | 20 ++++++ .../global/partials/resource-section.hbs | 6 +- 7 files changed, 140 insertions(+), 2 deletions(-) diff --git a/lang/en.json b/lang/en.json index 423f8c06..890ef945 100755 --- a/lang/en.json +++ b/lang/en.json @@ -375,6 +375,9 @@ "description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope." } }, + "refreshable": { + "title": "Refreshing Resources" + }, "takeDowntime": "Take Downtime" }, "HUD": { @@ -903,6 +906,10 @@ "abbreviation": "FR" } }, + "ItemResourceProgression": { + "increasing": "Increasing", + "decreasing": "Decreasing" + }, "ItemResourceType": { "simple": "Simple", "diceValue": "Dice Value" @@ -1968,6 +1975,7 @@ "dieFaces": { "label": "Die Faces" }, "icon": { "label": "Icon" }, "max": { "label": "Max" }, + "progression": { "label": "Progression" }, "recovery": { "label": "Recovery" }, "type": { "label": "Type" }, "value": { "label": "Value" } diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index d6bfc7ac..8d6bbda1 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -24,6 +24,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV actor.system.bonuses.rest[`${shortrest ? 'short' : 'long'}Rest`].longMoves } }; + + this.refreshables = this.getRefreshables(); } get title() { @@ -81,11 +83,56 @@ 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.refreshables = this.refreshables; + context.disabledDowntime = shortRestMovesSelected === 0 && longRestMovesSelected === 0; return context; } + getRefreshables() { + const actionItems = this.actor.items.reduce((acc, x) => { + if (x.system.actions) { + const recoverable = x.system.actions.reduce((acc, action) => { + if (action.uses.recovery && (action.uses.recovery === 'shortRest') === this.shortrest) { + acc.push({ + title: x.name, + name: action.name, + uuid: action.uuid + }); + } + + return acc; + }, []); + + if (recoverable) { + acc.push(...recoverable); + } + } + + return acc; + }, []); + const resourceItems = this.actor.items.reduce((acc, x) => { + if ( + x.system.resource && + x.system.resource.type && + (x.system.resource.recovery === 'shortRest') === this.shortrest + ) { + acc.push({ + title: game.i18n.localize(`TYPES.Item.${x.type}`), + name: x.name, + uuid: x.uuid + }); + } + + return acc; + }, []); + return { + actionItems, + resourceItems + }; + } + static selectMove(_, target) { const { category, move } = target.dataset; @@ -172,11 +219,24 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV } } - // We can close the window when all moves are taken + // We can close the window and refresh resources when all moves are taken if ( this.nrChoices.shortRest.taken >= this.nrChoices.shortRest.max && this.nrChoices.longRest.taken >= this.nrChoices.longRest.max ) { + for (var data of this.refreshables.actionItems) { + const action = await foundry.utils.fromUuid(data.uuid); + await action.parent.parent.update({ [`system.actions.${action.id}.uses.value`]: action.uses.max ?? 1 }); + } + + for (var data of this.refreshables.resourceItems) { + const feature = await foundry.utils.fromUuid(data.uuid); + const increasing = + feature.system.resource.progression === CONFIG.DH.ITEM.itemResourceProgression.increasing.id; + const resetValue = increasing ? 0 : (feature.system.resource.max ?? 0); + await feature.update({ 'system.resource.value': resetValue }); + } + this.close(); } else { this.render(); diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index 8fe33818..b37da49e 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -1473,6 +1473,17 @@ export const itemResourceTypes = { } }; +export const itemResourceProgression = { + increasing: { + id: 'increasing', + label: 'DAGGERHEART.CONFIG.ItemResourceProgression.increasing' + }, + decreasing: { + id: 'decreasing', + label: 'DAGGERHEART.CONFIG.ItemResourceProgression.decreasing' + } +}; + export const beastformTypes = { normal: { id: 'normal', diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 61b2ce5f..9405be7b 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -56,6 +56,11 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { initial: null, nullable: true }), + progression: new fields.StringField({ + required: true, + choices: CONFIG.DH.ITEM.itemResourceProgression, + initial: CONFIG.DH.ITEM.itemResourceProgression.increasing.id + }), diceStates: new fields.TypedObjectField( new fields.SchemaField({ value: new fields.NumberField({ integer: true, initial: 1, min: 1 }), diff --git a/styles/less/dialog/downtime/downtime-container.less b/styles/less/dialog/downtime/downtime-container.less index 6a520d4b..55fb5b70 100644 --- a/styles/less/dialog/downtime/downtime-container.less +++ b/styles/less/dialog/downtime/downtime-container.less @@ -63,6 +63,36 @@ } } + .refreshables-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4px; + font-size: 12px; + + &.wide { + grid-template-columns: 1fr 1fr 1fr 1fr; + } + + .refreshable-container { + border: 1px solid light-dark(@dark-blue, @golden); + border-radius: 6px; + color: light-dark(@dark, @beige); + background-image: url('../assets/parchments/dh-parchment-dark.png'); + padding: 0 2px; + text-align: center; + display: flex; + flex-direction: column; + gap: 2px; + + .refreshable-title { + font-weight: bold; + } + + .refreshable-name { + } + } + } + footer { margin-top: 8px; display: flex; diff --git a/templates/dialogs/downtime/downtime.hbs b/templates/dialogs/downtime/downtime.hbs index c8e44e5d..13c1face 100644 --- a/templates/dialogs/downtime/downtime.hbs +++ b/templates/dialogs/downtime/downtime.hbs @@ -7,6 +7,26 @@ {{#if shortRestMoves.moves}}{{> "systems/daggerheart/templates/dialogs/downtime/activities.hbs" moves=shortRestMoves.moves category='shortRest' nrChoices=nrChoices.shortRest}}{{/if}} {{#if longRestMoves.moves}}{{> "systems/daggerheart/templates/dialogs/downtime/activities.hbs" moves=longRestMoves.moves category='longRest' nrChoices=nrChoices.longRest}}{{/if}} + +
+ {{localize "DAGGERHEART.APPLICATIONS.Downtime.refreshable.title"}} + +
+ {{#each this.refreshables.actionItems as | item |}} +
+
{{item.title}}
+
{{item.name}}
+
+ {{/each}} + {{#each this.refreshables.resourceItems as | item |}} +
+
{{item.title}}
+
{{item.name}}
+
+ {{/each}} +
+
+