diff --git a/lang/en.json b/lang/en.json index 75f2b886..dd63d219 100755 --- a/lang/en.json +++ b/lang/en.json @@ -251,6 +251,8 @@ "Downtime": { "downtimeHeader": "Downtime Moves ({current}/{max})", "longRest": { + "title": "Long Rest", + "moves": "Long Rest Moves ({current}/{max})", "clearStress": { "description": "Describe how you blow off steam or pull yourself together, and clear all marked Stress.", "name": "Clear Stress" @@ -267,7 +269,6 @@ "description": "Describe how you patch yourself up and remove all marked Hit Points. You may also do this on an ally instead.", "name": "Tend to Wounds" }, - "title": "Long Rest", "workOnAProject": { "description": "Establish or continue work on a project.", "name": "Work on a Project" @@ -275,6 +276,7 @@ }, "shortRest": { "title": "Short Rest", + "moves": "Short Rest Moves ({current}/{max})", "tendToWounds": { "name": "Tend to Wounds", "description": "Describe how you hastily patch yourself up, then clear a number of Hit Points equal to 1d4 + your tier. You can do this to an ally instead." @@ -291,7 +293,8 @@ "name": "Prepare", "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." } - } + }, + "takeDowntime": "Take Downtime" }, "HUD": { "tokenHUD": { @@ -1161,6 +1164,28 @@ "hint": "The cost in stress you can pay to reduce minor damage to none." } } + }, + "rest": { + "shortRest": { + "shortRestMoves": { + "label": "Short Rest: Short Rest Moves", + "hint": "The number of Short Rest Moves the character can take during a Short Rest." + }, + "longRestMoves": { + "label": "Short Rest: Long Rest Moves", + "hint": "The number of Long Rest Moves the character can take during a Short Rest." + } + }, + "longRest": { + "shortRestMoves": { + "label": "Long Rest: Short Rest Moves", + "hint": "The number of Short Rest Moves the character can take during a Long Rest." + }, + "longRestMoves": { + "label": "Long Rest: Long Rest Moves", + "hint": "The number of Long Rest Moves the character can take during a Long Rest." + } + } } }, "Tabs": { diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 3966f7e4..6fe5b0a2 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -7,8 +7,16 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV this.actor = actor; this.shortrest = shortrest; - const options = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves; - this.moveData = shortrest ? options.shortRest : options.longRest; + this.moveData = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves; + this.nrChoices = { + shortRest: { + max: actor.system.rules.rest[`${shortrest ? 'short' : 'long'}Rest`].shortMoves + }, + longRest: { + max: actor.system.rules.rest[`${shortrest ? 'short' : 'long'}Rest`].longMoves + } + }; + this.nrChoices.total = { max: this.nrChoices.shortRest.max + this.nrChoices.longRest.max }; } get title() { @@ -17,7 +25,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV static DEFAULT_OPTIONS = { tag: 'form', - classes: ['daggerheart', 'views', 'downtime'], + classes: ['daggerheart', 'views', 'dh-style', 'downtime'], position: { width: 680, height: 'auto' }, actions: { selectMove: this.selectMove, @@ -29,7 +37,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV static PARTS = { application: { id: 'downtime', - template: 'systems/daggerheart/templates/dialogs/downtime.hbs' + template: 'systems/daggerheart/templates/dialogs/downtime/downtime.hbs' } }; @@ -45,38 +53,70 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV const context = await super._prepareContext(_options); context.selectedActivity = this.selectedActivity; context.moveData = this.moveData; - context.nrCurrentChoices = Object.values(this.moveData.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0); - context.disabledDowntime = context.nrCurrentChoices < context.moveData.nrChoices; + context.nrCurrentChoices = Object.values(this.moveData).reduce((acc, category) => { + acc += Object.values(category.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0); + return acc; + }, 0); + + context.nrChoices = { + ...this.nrChoices, + shortRest: { + ...this.nrChoices.shortRest, + current: Object.values(this.moveData.shortRest.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0) + }, + longRest: { + ...this.nrChoices.longRest, + current: Object.values(this.moveData.longRest.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0) + } + }; + context.nrChoices.total = { + ...this.nrChoices.total, + current: context.nrChoices.shortRest.current + context.nrChoices.longRest.current + }; + + 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; return context; } - static selectMove(_, button) { - const nrSelected = Object.values(this.moveData.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0); - if (nrSelected === this.moveData.nrChoices) { + static selectMove(_, target) { + const nrSelected = Object.values(this.moveData[target.dataset.category].moves).reduce( + (acc, x) => acc + (x.selected ?? 0), + 0 + ); + + if (nrSelected === this.nrChoices[target.dataset.category].max) { ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noMoreMoves')); return; } - const move = button.dataset.move; - this.moveData.moves[move].selected = this.moveData.moves[move].selected - ? this.moveData.moves[move].selected + 1 + 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 : 1; this.render(); } deselectMove(event) { - const move = event.currentTarget.dataset.move; - this.moveData.moves[move].selected = this.moveData.moves[move].selected - ? this.moveData.moves[move].selected - 1 + const button = event.target.closest('.activity-image'); + const move = button.dataset.move; + this.moveData[button.dataset.category].moves[move].selected = this.moveData[button.dataset.category].moves[move] + .selected + ? this.moveData[button.dataset.category].moves[move].selected - 1 : 0; this.render(); } static async takeDowntime() { - const moves = Object.values(this.moveData.moves).filter(x => x.selected); + const moves = Object.values(this.moveData).flatMap(category => { + return Object.values(category.moves).filter(x => x.selected); + }); const cls = getDocumentClass('ChatMessage'); const msg = new cls({ diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 20bada01..9d494b69 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -122,12 +122,9 @@ export default class DhCharacter extends BaseDataActor { label: 'DAGGERHEART.GENERAL.Range.other' }) }), - rally: new fields.ArrayField( - new fields.StringField(), - { - label: 'DAGGERHEART.CLASS.Feature.rallyDice' - } - ) + rally: new fields.ArrayField(new fields.StringField(), { + label: 'DAGGERHEART.CLASS.Feature.rallyDice' + }) }), companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }), rules: new fields.SchemaField({ @@ -174,6 +171,44 @@ export default class DhCharacter extends BaseDataActor { */ flipMinDiceValue: new fields.BooleanField({ intial: false }) }), + rest: new fields.SchemaField({ + shortRest: new fields.SchemaField({ + shortMoves: new fields.NumberField({ + required: true, + integer: true, + min: 1, + initial: 2, + label: 'DAGGERHEART.GENERAL.Rules.rest.shortRest.shortRestMoves.label', + hint: 'DAGGERHEART.GENERAL.Rules.rest.shortRest.shortRestMoves.hint' + }), + longMoves: new fields.NumberField({ + required: true, + integer: true, + min: 0, + initial: 0, + label: 'DAGGERHEART.GENERAL.Rules.rest.shortRest.longRestMoves.label', + hint: 'DAGGERHEART.GENERAL.Rules.rest.shortRest.longRestMoves.hint' + }) + }), + longRest: new fields.SchemaField({ + shortMoves: new fields.NumberField({ + required: true, + integer: true, + min: 0, + initial: 0, + label: 'DAGGERHEART.GENERAL.Rules.rest.longRest.shortRestMoves.label', + hint: 'DAGGERHEART.GENERAL.Rules.rest.longRest.shortRestMoves.hint' + }), + longMoves: new fields.NumberField({ + required: true, + integer: true, + min: 1, + initial: 2, + label: 'DAGGERHEART.GENERAL.Rules.rest.longRest.longRestMoves.label', + hint: 'DAGGERHEART.GENERAL.Rules.rest.longRest.longRestMoves.hint' + }) + }) + }), runeWard: new fields.BooleanField({ initial: false }) }) }; diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index 8456094c..0c455750 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -25,6 +25,7 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/settings/components/settings-item-line.hbs', 'systems/daggerheart/templates/ui/chat/parts/damage-chat.hbs', 'systems/daggerheart/templates/ui/chat/parts/target-chat.hbs', - 'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs' + 'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs', + 'systems/daggerheart/templates/dialogs/downtime/activities.hbs' ]); }; diff --git a/styles/less/dialog/downtime/downtime-container.less b/styles/less/dialog/downtime/downtime-container.less index 4e785e7b..856b6eaa 100644 --- a/styles/less/dialog/downtime/downtime-container.less +++ b/styles/less/dialog/downtime/downtime-container.less @@ -3,12 +3,6 @@ .daggerheart.views { .downtime-container { - .downtime-header { - margin: 0; - color: light-dark(@dark-blue, @golden); - text-align: center; - } - .activity-container { display: flex; align-items: center; @@ -73,6 +67,12 @@ } } + footer { + margin-top: 8px; + display: flex; + gap: 8px; + } + &.downtime { .activity-text-area { resize: none; diff --git a/templates/dialogs/downtime.hbs b/templates/dialogs/downtime.hbs deleted file mode 100644 index fd5fa405..00000000 --- a/templates/dialogs/downtime.hbs +++ /dev/null @@ -1,24 +0,0 @@ -