From d137e33c3dc95672c1e2c6e7a9966b22392c5d6d Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Tue, 25 Nov 2025 00:36:43 +0100 Subject: [PATCH] [Feature] Countdown Rols And Randomzie (#1329) * . * . * . * Raised system version --- lang/en.json | 14 ++-- module/applications/ui/countdownEdit.mjs | 39 +++++++++-- module/applications/ui/countdowns.mjs | 27 ++++++-- module/data/action/countdownAction.mjs | 23 ++++++- module/data/countdowns.mjs | 22 ++++++- module/data/fields/action/countdownField.mjs | 28 +++++++- module/helpers/utils.mjs | 6 ++ ...ary_Adult_Flickerfly_G7jiltRjgvVhZewm.json | 3 +- ...ary_Arch_Necromancer_WPEOIGfclNJxWb87.json | 3 +- ...rsary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json | 3 +- ...sary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json | 3 +- ...rlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json | 3 +- ..._Undefeated_Champion_RXkZTwBRi4dJ3JE5.json | 3 +- .../adversary_Gorgon_8mJYMpbLTb8qIOrr.json | 3 +- ...adversary_Head_Guard_mK3A5FTx6k8iPU3F.json | 3 +- ..._Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json | 3 +- .../adversary_Monarch_yx0vK2yfNVZKWUUi.json | 3 +- ...ersary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json | 3 +- ...ersary_Secret_Keeper_sLAccjvCWfeedbpI.json | 3 +- ...dversary_Stonewraith_3aAS2Qm3R6cgaYfE.json | 3 +- ...Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json | 3 +- ...inCard_Mass_Disguise_dT95m0Jam8sWbeuC.json | 3 +- ...g_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json | 3 +- ...Bustling_Marketplace_HZKA7hkej7JJY503.json | 6 +- ...ronment_Castle_Siege_1eZ32Esq7rfZOjlu.json | 3 +- ...ironment_Chaos_Realm_2Z1mKc65LxNk2PqR.json | 5 +- ...ent_Cliffside_Ascent_LPpfdlNKqiZIl04w.json | 3 +- ...ironment_Cult_Ritual_QAXXiOKBDmCTauHD.json | 3 +- ...nt_Divine_Usurpation_4DLYez7VbMCFDAuZ.json | 5 +- ...ronment_Haunted_City_OzYbizKraK92FDiI.json | 3 +- ...onment_Mountain_Pass_acMu9wJrMZZzLSTJ.json | 3 +- ...ronment_Raging_River_t4cdqTfzcqP3H1vJ.json | 3 +- styles/less/ui/countdown/countdown-edit.less | 57 ++++++++++++++++- system.json | 2 +- templates/actionTypes/countdown.hbs | 2 +- templates/ui/countdown-edit.hbs | 64 +++++++++++-------- templates/ui/countdowns.hbs | 2 +- 37 files changed, 281 insertions(+), 87 deletions(-) diff --git a/lang/en.json b/lang/en.json index c969ce15..c99cf652 100755 --- a/lang/en.json +++ b/lang/en.json @@ -344,7 +344,8 @@ "progress": { "current": { "label": "Current" }, "looping": { "label": "Looping" }, - "max": { "label": "Max" }, + "start": { "label": "Start" }, + "startFormula": { "label": "Start Formula" }, "type": { "label": { "label": "Label", "hint": "Used for custom" }, "value": { "label": "Value" } @@ -372,12 +373,13 @@ "newCountdown": "New Countdown", "removeCountdownTitle": "Remove Countdown", "removeCountdownText": "Are you sure you want to remove the countdown: {name}?", - "current": "Current", - "max": "Max", - "currentCountdownValue": "Current: {value}", - "currentCountdownMax": "Max: {value}", + "current": "Current Value", + "start": "Start Value", + "startFormula": "Randomized Start Value Formula", + "currentCountdownCurrent": "Current: {value}", + "currentCountdownStart": "Start: {value}", "category": "Category", - "progressionType": "Progression Type", + "progressionType": "Progression", "decreasing": "Decreasing", "looping": "Looping", "defaultOwnershipTooltip": "The default player ownership of countdowns", diff --git a/module/applications/ui/countdownEdit.mjs b/module/applications/ui/countdownEdit.mjs index 1844538c..7f1deea3 100644 --- a/module/applications/ui/countdownEdit.mjs +++ b/module/applications/ui/countdownEdit.mjs @@ -1,4 +1,5 @@ import { DhCountdown } from '../../data/countdowns.mjs'; +import { waitForDiceSoNice } from '../../helpers/utils.mjs'; import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -26,6 +27,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio toggleCountdownEdit: CountdownEdit.#toggleCountdownEdit, editCountdownImage: CountdownEdit.#editCountdownImage, editCountdownOwnership: CountdownEdit.#editCountdownOwnership, + randomiseCountdownStart: CountdownEdit.#randomiseCountdownStart, removeCountdown: CountdownEdit.#removeCountdown }, form: { handler: this.updateData, submitOnChange: true } @@ -57,6 +59,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio ? 'DAGGERHEART.UI.Countdowns.decreasingLoop' : 'DAGGERHEART.UI.Countdowns.loop' : null; + const randomizeValid = !new Roll(countdown.progress.startFormula ?? '').isDeterministic; acc[key] = { ...countdown, typeName: game.i18n.localize(CONFIG.DH.GENERAL.countdownBaseTypes[countdown.type].label), @@ -67,6 +70,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio ) }, editing: this.editingCountdowns.has(key), + randomizeValid, loopTooltip }; @@ -123,18 +127,26 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio // Sync current and max if max is changing and they were equal before for (const [id, countdown] of Object.entries(settingsData.countdowns ?? {})) { const existing = this.data.countdowns[id]; - const wasEqual = existing && existing.progress.current === existing.progress.max; - if (wasEqual && countdown.progress.max !== existing.progress.max) { - countdown.progress.current = countdown.progress.max; - } else { - countdown.progress.current = Math.min(countdown.progress.current, countdown.progress.max); - } + countdown.progress.current = this.getMatchingCurrentValue( + existing, + countdown.progress.start, + countdown.progress.current + ); } this.hideNewCountdowns = hideNewCountdowns; this.updateSetting(settingsData); } + getMatchingCurrentValue(oldCount, newStart, newCurrent) { + const wasEqual = oldCount && oldCount.progress.current === oldCount.progress.start; + if (wasEqual && newStart !== oldCount.progress.start) { + return newStart; + } else { + return Math.min(newCurrent, newStart); + } + } + async gmSetSetting(data) { await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data), game.socket.emit(`system.${CONFIG.DH.id}`, { @@ -190,6 +202,21 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio this.updateSetting({ [`countdowns.${button.dataset.countdownId}`]: data }); } + static async #randomiseCountdownStart(_, button) { + const countdown = this.data.countdowns[button.dataset.countdownId]; + const roll = await new Roll(countdown.progress.startFormula).roll(); + const message = await roll.toMessage({ title: 'Countdown' }); + + await waitForDiceSoNice(message); + await this.updateSetting({ + [`countdowns.${button.dataset.countdownId}.progress`]: { + start: roll.total, + current: this.getMatchingCurrentValue(countdown, roll.total, countdown.progress.current) + } + }); + this.render(); + } + static async #removeCountdown(event, button) { const { countdownId } = button.dataset; diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index f9f7036c..d35f2eb8 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -1,3 +1,4 @@ +import { waitForDiceSoNice } from '../../helpers/utils.mjs'; import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -123,13 +124,14 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application : 'DAGGERHEART.UI.Countdowns.loop' : null; const loopDisabled = - !countdownEditable || (isLooping && (countdown.progress.current > 0 || countdown.progress.max === '0')); + !countdownEditable || + (isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0')); acc[key] = { ...countdown, editable: countdownEditable, noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0, - shouldLoop: isLooping && countdown.progress.current === 0 && countdown.progress.max > 0, + shouldLoop: isLooping && countdown.progress.current === 0 && countdown.progress.start > 0, loopDisabled: isLooping ? loopDisabled : null, loopTooltip: isLooping && game.i18n.localize(loopTooltip) }; @@ -182,16 +184,27 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); const countdown = settings.countdowns[target.id]; + + let progressMax = countdown.progress.start; + let message = null; + if (countdown.progress.startFormula) { + const roll = await new Roll(countdown.progress.startFormula).evaluate(); + progressMax = roll.total; + message = await roll.toMessage(); + } + const newMax = countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id - ? Number(countdown.progress.max) + 1 + ? Number(progressMax) + 1 : countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id - ? Math.max(Number(countdown.progress.max) - 1, 0) - : countdown.progress.max; + ? Math.max(Number(progressMax) - 1, 0) + : progressMax; + + await waitForDiceSoNice(message); await settings.updateSource({ [`countdowns.${target.id}.progress`]: { current: newMax, - max: newMax + start: newMax } }); await emitAsGM(GMUpdateEvent.UpdateCountdowns, DhCountdowns.gmSetSetting.bind(settings), settings, null, { @@ -205,7 +218,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); const countdown = settings.countdowns[target.id]; const newCurrent = increase - ? Math.min(countdown.progress.current + 1, countdown.progress.max) + ? Math.min(countdown.progress.current + 1, countdown.progress.start) : Math.max(countdown.progress.current - 1, 0); await settings.updateSource({ [`countdowns.${target.id}.progress.current`]: newCurrent }); await emitAsGM(GMUpdateEvent.UpdateCountdowns, DhCountdowns.gmSetSetting.bind(settings), settings, null, { diff --git a/module/data/action/countdownAction.mjs b/module/data/action/countdownAction.mjs index a22285d9..abcc6b40 100644 --- a/module/data/action/countdownAction.mjs +++ b/module/data/action/countdownAction.mjs @@ -8,7 +8,10 @@ export default class DhCountdownAction extends DHBaseAction { ...super.defaultValues, countdown: { name: this.parent.parent.name, - img: this.img + img: this.img, + progress: { + startFormula: '1' + } } }; } @@ -21,10 +24,26 @@ export default class DhCountdownAction extends DHBaseAction { { ...game.system.api.data.countdowns.DhCountdown.defaultCountdown(), name: parent.parent.name, - img: parent.parent.img + img: parent.parent.img, + progress: { + startFormula: '1' + } } ]; return updateSource; } + + /** @inheritDoc */ + static migrateData(source) { + for (const countdown of source.countdown) { + if (countdown.progress.max) { + countdown.progress.startFormula = countdown.progress.max; + countdown.progress.start = 1; + countdown.progress.max = null; + } + } + + return super.migrateData(source); + } } diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs index b3ef9a54..b944bf73 100644 --- a/module/data/countdowns.mjs +++ b/module/data/countdowns.mjs @@ -167,10 +167,15 @@ export class DhCountdown extends foundry.abstract.DataModel { initial: 1, label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.current.label' }), - max: new FormulaField({ + start: new fields.NumberField({ required: true, + integer: true, initial: 1, - label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.max.label', + label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.start.label', + deterministic: false + }), + startFormula: new FormulaField({ + label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.startFormula.label', deterministic: false }), looping: new fields.StringField({ @@ -206,7 +211,7 @@ export class DhCountdown extends foundry.abstract.DataModel { ownership: ownership, progress: { current: 1, - max: 1 + start: 1 } }; } @@ -225,4 +230,15 @@ export class DhCountdown extends foundry.abstract.DataModel { return acc; }, {}); } + + /** @inheritDoc */ + static migrateData(source) { + if (source.progress.max) { + source.progress.start = Number(source.progress.max); + source.progress.max = null; + source.progress.startFormula = null; + } + + return super.migrateData(source); + } } diff --git a/module/data/fields/action/countdownField.mjs b/module/data/fields/action/countdownField.mjs index 2a3b3d69..f49e71ad 100644 --- a/module/data/fields/action/countdownField.mjs +++ b/module/data/fields/action/countdownField.mjs @@ -40,18 +40,40 @@ export default class CountdownField extends fields.ArrayField { } const data = { countdowns: {} }; + const countdownMessages = []; for (let countdown of config.countdowns) { - const { total: max } = await new Roll(countdown.progress.max).evaluate(); + let startFormula = countdown.progress.startFormula ? countdown.progress.startFormula : null; + let countdownStart = startFormula ?? '1'; + if (startFormula) { + const roll = await new Roll(startFormula).roll(); + if (roll.dice.length > 0) { + countdownStart = roll.total; + const message = await roll.toMessage(); + countdownMessages.push(message); + } else { + startFormula = null; + } + } + data.countdowns[foundry.utils.randomID()] = { ...countdown, progress: { ...countdown.progress, - current: max, - max: max + current: countdownStart, + start: countdownStart, + startFormula } }; } + if (game.modules.get('dice-so-nice')?.active) { + await Promise.all( + countdownMessages.map(message => { + return game.dice3d.waitFor3DAnimationByMessageID(message.id); + }) + ); + } + await emitAsGM( GMUpdateEvent.UpdateCountdowns, async () => { diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index c0ca20f9..e2ce9904 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -445,3 +445,9 @@ export function itemIsIdentical(a, b) { return compendiumSource && name & description; } + +export async function waitForDiceSoNice(message) { + if (message && game.modules.get('dice-so-nice')?.active) { + await game.dice3d.waitFor3DAnimationByMessageID(message.id); + } +} diff --git a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json index 8abd4129..12b806ea 100644 --- a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json +++ b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json @@ -738,7 +738,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "1d6", + "start": 1, + "startFormula": "1d6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json b/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json index 031786a9..8215fb0e 100644 --- a/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json +++ b/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json @@ -794,7 +794,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "2d6", + "start": 1, + "startFormula": "2d6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json index f442da25..1ba76388 100644 --- a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json +++ b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json @@ -476,7 +476,8 @@ "progress": { "looping": "looping", "type": "custom", - "max": "6", + "start": 1, + "startFormula": "6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json b/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json index ad396a8f..adc83527 100644 --- a/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json +++ b/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json @@ -579,7 +579,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "2d6", + "start": 1, + "startFormula": "2d6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json b/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json index 423c40d2..ca1428ad 100644 --- a/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json +++ b/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json @@ -623,7 +623,8 @@ "progress": { "looping": "decreasing", "type": "actionRoll", - "max": "8", + "start": 1, + "startFormula": "8", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json b/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json index 1666ee1c..4c8fdf98 100644 --- a/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json +++ b/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json @@ -634,7 +634,8 @@ "progress": { "looping": "noLooping", "type": "actionRoll", - "max": "1d8", + "start": 1, + "startFormula": "1d8", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json b/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json index 378fffd2..bceedcaa 100644 --- a/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json +++ b/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json @@ -630,7 +630,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "4", + "start": 1, + "startFormula": "4", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json b/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json index bbe7e153..ca2aa873 100644 --- a/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json +++ b/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json @@ -361,7 +361,8 @@ "progress": { "looping": "noLooping", "type": "characterAttack", - "max": "5", + "start": 1, + "startFormula": "5", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json b/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json index 3084864e..653cf234 100644 --- a/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json +++ b/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json @@ -640,7 +640,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "1d6", + "start": 1, + "startFormula": "1d6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json b/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json index 56d5fedb..f475be63 100644 --- a/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json +++ b/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json @@ -376,7 +376,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "8", + "start": 1, + "startFormula": "8", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json index 1bbe078b..75c58cd9 100644 --- a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json +++ b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json @@ -625,7 +625,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "1d6", + "start": 1, + "startFormula": "1d6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Secret_Keeper_sLAccjvCWfeedbpI.json b/src/packs/adversaries/adversary_Secret_Keeper_sLAccjvCWfeedbpI.json index 9e16426e..7d33814c 100644 --- a/src/packs/adversaries/adversary_Secret_Keeper_sLAccjvCWfeedbpI.json +++ b/src/packs/adversaries/adversary_Secret_Keeper_sLAccjvCWfeedbpI.json @@ -488,7 +488,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "6", + "start": 1, + "startFormula": "6", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json b/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json index 19865d9f..aac857eb 100644 --- a/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json +++ b/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json @@ -543,7 +543,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "8", + "start": 1, + "startFormula": "8", "current": 1 }, "ownership": {} diff --git a/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json b/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json index 64e6f4f9..f9f048ac 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json @@ -862,7 +862,8 @@ "progress": { "looping": "noLooping", "type": "fear", - "max": "1d12", + "start": 1, + "startFormula": "1d12", "current": 1 }, "ownership": {} diff --git a/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json b/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json index 704feaa5..964070e9 100644 --- a/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json +++ b/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json @@ -63,7 +63,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "8", + "start": 1, + "startFormula": "8", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json b/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json index a8ed164a..7e535796 100644 --- a/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json +++ b/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json @@ -545,7 +545,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "6", + "start": 1, + "startFormula": "6", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Bustling_Marketplace_HZKA7hkej7JJY503.json b/src/packs/environments/environment_Bustling_Marketplace_HZKA7hkej7JJY503.json index 93a2c22c..c6ac921f 100644 --- a/src/packs/environments/environment_Bustling_Marketplace_HZKA7hkej7JJY503.json +++ b/src/packs/environments/environment_Bustling_Marketplace_HZKA7hkej7JJY503.json @@ -291,7 +291,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "6", + "start": 1, + "startFormula": "6", "current": 1 }, "ownership": {} @@ -304,7 +305,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "4", + "start": 1, + "startFormula": "4", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json b/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json index cbeba54f..036d1470 100644 --- a/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json +++ b/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json @@ -283,7 +283,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "6", + "start": 1, + "startFormula": "6", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Chaos_Realm_2Z1mKc65LxNk2PqR.json b/src/packs/environments/environment_Chaos_Realm_2Z1mKc65LxNk2PqR.json index ff130b70..1055d2e5 100644 --- a/src/packs/environments/environment_Chaos_Realm_2Z1mKc65LxNk2PqR.json +++ b/src/packs/environments/environment_Chaos_Realm_2Z1mKc65LxNk2PqR.json @@ -225,7 +225,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "8", + "start": 1, + "startFormula": "8", "current": 1 }, "ownership": {} @@ -341,7 +342,7 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "4", + "startValue": "4", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json b/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json index d4807e68..28dfdfda 100644 --- a/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json +++ b/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json @@ -174,7 +174,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "12", + "start": 1, + "startFormula": "12", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json b/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json index ae7902e2..a0b10ed8 100644 --- a/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json +++ b/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json @@ -374,7 +374,8 @@ "progress": { "looping": "noLooping", "type": "fear", - "max": "6", + "start": 1, + "startFormula": "6", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json b/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json index d6540a11..b4cbc8d4 100644 --- a/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json +++ b/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json @@ -197,7 +197,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "8", + "start": 1, + "startFormula": "8", "current": 1 }, "ownership": {} @@ -607,7 +608,7 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "10", + "startValue": "10", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json b/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json index c3a3b60c..f4f4ce22 100644 --- a/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json +++ b/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json @@ -361,7 +361,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "5", + "start": 1, + "startFormula": "5", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Mountain_Pass_acMu9wJrMZZzLSTJ.json b/src/packs/environments/environment_Mountain_Pass_acMu9wJrMZZzLSTJ.json index 8f6a2bf3..3fa600f7 100644 --- a/src/packs/environments/environment_Mountain_Pass_acMu9wJrMZZzLSTJ.json +++ b/src/packs/environments/environment_Mountain_Pass_acMu9wJrMZZzLSTJ.json @@ -404,7 +404,8 @@ "progress": { "looping": "looping", "type": "actionRoll", - "max": "4", + "start": 1, + "startFormula": "4", "current": 1 }, "ownership": {} diff --git a/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json b/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json index 6ef44f84..78600149 100644 --- a/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json +++ b/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json @@ -183,7 +183,8 @@ "progress": { "looping": "noLooping", "type": "custom", - "max": "4", + "start": 1, + "startFormula": "4", "current": 1 }, "ownership": {} diff --git a/styles/less/ui/countdown/countdown-edit.less b/styles/less/ui/countdown/countdown-edit.less index 7a99f8d7..d6c4da93 100644 --- a/styles/less/ui/countdown/countdown-edit.less +++ b/styles/less/ui/countdown/countdown-edit.less @@ -129,12 +129,20 @@ } } } - .countdown-edit-subrow { + + .countdown-edit-row-container { display: flex; - gap: 8px; + flex-direction: column; + gap: 2px; + + .countdown-edit-subrow { + display: flex; + gap: 8px; + } } .countdown-edit-input { + position: relative; flex: 1; display: flex; flex-direction: column; @@ -151,11 +159,56 @@ &.tiny { flex: 0; + + label { + white-space: nowrap; + } + input { min-width: 2.5rem; } } + .countdown-random-input { + padding-right: var(--input-height); + } + + .countdown-random-button { + position: absolute; + right: 0px; + bottom: 0px; + border-radius: 0 6px 6px 0; + height: var(--input-height); + display: flex; + align-items: center; + justify-content: center; + padding: 0 8px; + + &[disabled] { + opacity: 0.5; + } + + i { + font-size: 18px; + } + } + + // .countdown-random-container { + // width: 100%; + // display: flex; + + // input { + // border-radius: 6px 0 0 6px; + // border-right: 0; + // } + + // button { + // border-radius: 0 6px 6px 0; + // height: var(--input-height); + // border: 1px solid white; + // } + // } + input, select { background: light-dark(@beige, @dark-blue); diff --git a/system.json b/system.json index 711a9dd9..bfcf2a31 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "1.2.5", + "version": "1.2.6", "compatibility": { "minimum": "13", "verified": "13.351", diff --git a/templates/actionTypes/countdown.hbs b/templates/actionTypes/countdown.hbs index 360b1172..904dde4a 100644 --- a/templates/actionTypes/countdown.hbs +++ b/templates/actionTypes/countdown.hbs @@ -16,7 +16,7 @@