From 2b1535333a3e2623a9b51e2ec3334b952de7b933 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Mon, 8 Dec 2025 21:01:29 +0100 Subject: [PATCH 01/15] . --- module/applications/ui/combatTracker.mjs | 4 +-- module/config/encounterConfig.mjs | 2 +- module/documents/tooltipManager.mjs | 17 ++++++------ styles/less/ux/tooltip/battlepoints.less | 7 ++++- styles/less/ux/tooltip/bordered-tooltip.less | 4 ++- styles/less/ux/tooltip/tooltip.less | 4 +++ templates/ui/tooltip/battlepoints.hbs | 28 +++++++++++--------- 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/module/applications/ui/combatTracker.mjs b/module/applications/ui/combatTracker.mjs index b1e658a5..23bede60 100644 --- a/module/applications/ui/combatTracker.mjs +++ b/module/applications/ui/combatTracker.mjs @@ -42,13 +42,13 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C const modifierBP = this.combats .find(x => x.active) - ?.system?.extendedBattleToggles?.reduce((acc, toggle) => acc + toggle.category, 0) ?? 0; + ?.system?.extendedBattleToggles?.reduce((acc, toggle) => (acc ?? 0) + toggle.category, null) ?? null; const maxBP = CONFIG.DH.ENCOUNTER.BaseBPPerEncounter(context.characters.length) + modifierBP; const currentBP = AdversaryBPPerEncounter(context.adversaries, context.characters); Object.assign(context, { fear: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear), - battlepoints: { max: maxBP, current: currentBP, hasModifierBP: Boolean(modifierBP) } + battlepoints: { max: maxBP, current: currentBP, hasModifierBP: modifierBP !== null } }); } diff --git a/module/config/encounterConfig.mjs b/module/config/encounterConfig.mjs index 96efd745..0269b5c1 100644 --- a/module/config/encounterConfig.mjs +++ b/module/config/encounterConfig.mjs @@ -21,7 +21,7 @@ export const AdversaryBPPerEncounter = (adversaries, characters) => { if (type.partyAmountPerBP) { acc += characters.length === 0 ? 0 : Math.ceil(entry.nr / characters.length); } else { - acc += bpCost; + acc += bpCost * entry.nr; } return acc; diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index 23e04ac1..1784698a 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -10,6 +10,7 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti let html = options.html; if (element.dataset.tooltip?.startsWith('#battlepoints#')) { this.#wide = true; + this.#bordered = true; html = await this.getBattlepointHTML(element.dataset.combatId); options.direction = this._determineItemTooltipDirection(element); @@ -22,6 +23,7 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti return; } else { this.#wide = false; + this.#bordered = false; } if (element.dataset.tooltip === '#effect-display#') { @@ -168,14 +170,6 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti super.activate(element, { ...options, html: html }); } - _setStyle(position = {}) { - super._setStyle(position); - - if (this.#bordered) { - this.tooltip.classList.add('bordered-tooltip'); - } - } - _determineItemTooltipDirection(element, prefered = this.constructor.TOOLTIP_DIRECTIONS.LEFT) { const pos = element.getBoundingClientRect(); const dirs = this.constructor.TOOLTIP_DIRECTIONS; @@ -247,12 +241,17 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti if (this.#wide) { this.tooltip.classList.add('wide'); } + + if (this.#bordered) { + this.tooltip.classList.add('bordered-tooltip'); + } } /**@inheritdoc */ lockTooltip() { const clone = super.lockTooltip(); - clone.classList.add('wide'); + if (this.#wide) clone.classList.add('wide'); + if (this.#bordered) clone.classList.add('bordered-tooltip'); return clone; } diff --git a/styles/less/ux/tooltip/battlepoints.less b/styles/less/ux/tooltip/battlepoints.less index 61c7083d..9fe43a75 100644 --- a/styles/less/ux/tooltip/battlepoints.less +++ b/styles/less/ux/tooltip/battlepoints.less @@ -3,7 +3,12 @@ display: flex; flex-direction: column; gap: 8px; - margin-bottom: 16px; + + .battlepoint-categories-inner-container { + display: flex; + flex-direction: column; + gap: 8px; + } .battlepoint-grouping-container { display: flex; diff --git a/styles/less/ux/tooltip/bordered-tooltip.less b/styles/less/ux/tooltip/bordered-tooltip.less index a4779d71..78622377 100644 --- a/styles/less/ux/tooltip/bordered-tooltip.less +++ b/styles/less/ux/tooltip/bordered-tooltip.less @@ -1,4 +1,5 @@ -#tooltip.bordered-tooltip { +#tooltip.bordered-tooltip, +.locked-tooltip.bordered-tooltip { border: 1px solid @golden; background-image: url('../assets/parchments/dh-parchment-dark.png'); @@ -14,6 +15,7 @@ .tooltip-header { display: flex; flex-direction: column; + align-items: center; text-align: start; padding: 5px; gap: 0px; diff --git a/styles/less/ux/tooltip/tooltip.less b/styles/less/ux/tooltip/tooltip.less index 4579a3d8..2aa1c2c7 100644 --- a/styles/less/ux/tooltip/tooltip.less +++ b/styles/less/ux/tooltip/tooltip.less @@ -2,6 +2,10 @@ .locked-tooltip { &.wide { max-width: 480px; + + .daggerheart.dh-style.tooltip { + align-items: start; + } } .daggerheart.dh-style.tooltip { diff --git a/templates/ui/tooltip/battlepoints.hbs b/templates/ui/tooltip/battlepoints.hbs index ec8bbb1c..d793fe8c 100644 --- a/templates/ui/tooltip/battlepoints.hbs +++ b/templates/ui/tooltip/battlepoints.hbs @@ -1,20 +1,24 @@
+ +

{{localize "Adversaries"}} ({{currentBP}}/{{maxBP}})

-

{{localize "Adversaries"}} ({{currentBP}}/{{maxBP}})

- {{#each categories as |category key|}} - {{#each category as |grouping index|}} -
- {{#if grouping.nr}} - - {{else}} - - {{/if}} -
+
+ {{#each categories as |category key|}} + {{#each category as |grouping index|}} +
+ {{#if grouping.nr}} + + {{else}} + + {{/if}} +
+ {{/each}} {{/each}} - {{/each}} +
+ +

{{localize "Modifiers"}}

-

{{localize "Modifiers"}}

{{#each toggles as |toggle|}}
{{#if toggle.disabled}} From 8eae1c0763484be172ae29b1a0936eaa037753d5 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:43:36 +0100 Subject: [PATCH 02/15] Loosened checks on statuses to make module compatible (#1407) --- module/applications/hud/tokenHUD.mjs | 2 ++ module/documents/actor.mjs | 2 +- system.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs index f90c26be..b1136995 100644 --- a/module/applications/hud/tokenHUD.mjs +++ b/module/applications/hud/tokenHUD.mjs @@ -197,6 +197,8 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { for (const effect of activeEffects) { for (const statusId of effect.statuses) { const status = choices[statusId]; + if (!status) continue; + status.instances = 1 + (status.instances ?? 0); status.locked = status.locked || effect.condition || status.instances > 1; if (!status) continue; diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 20339375..8999fdd8 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -854,7 +854,7 @@ export default class DhpActor extends Actor { acc.push(effect); const currentStatusActiveEffects = acc.filter( - x => x.statuses.size === 1 && x.name === game.i18n.localize(statusMap.get(x.statuses.first()).name) + x => x.statuses.size === 1 && x.name === game.i18n.localize(statusMap.get(x.statuses.first())?.name) ); for (var status of effect.statuses) { diff --git a/system.json b/system.json index 7e3c6b07..14a4efc8 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.3.1", + "version": "1.3.2", "compatibility": { "minimum": "13.346", "verified": "13.351", From 7f7536ee06ec17e3c7377ae54e888f2eca0c358c Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Thu, 11 Dec 2025 13:32:43 -0700 Subject: [PATCH 03/15] Adding stress cost to wings of light (#1413) --- .../feature_Wings_of_Light_KkQH0tYhagIqe2MT.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json b/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json index 2fa32bec..f7157194 100644 --- a/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json +++ b/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json @@ -15,7 +15,16 @@ "description": "

Mark a Stress to pick up and carry another willing creature approximately your size or smaller.

", "chatDisplay": true, "actionType": "action", - "cost": [], + "cost": [ + { + "scalable": false, + "key": "stress", + "value": 1, + "itemId": null, + "step": null, + "consumeOnSuccess": false + } + ], "uses": { "value": null, "max": "", From 00e9436fe0dad8c0bba93e76be3f762c734bbab4 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Thu, 11 Dec 2025 12:39:07 -0800 Subject: [PATCH 04/15] Implement delta input for gold fields (#1400) --- .../sheets/api/application-mixin.mjs | 54 +++++++++++++++++++ .../sheets/actors/character/inventory.hbs | 2 +- templates/sheets/actors/party/inventory.hbs | 2 +- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 449d6723..b11fc779 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -178,6 +178,60 @@ export default function DHApplicationMixin(Base) { _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); this._dragDrop.forEach(d => d.bind(htmlElement)); + + for (const deltaInput of htmlElement.querySelectorAll('input[data-allow-delta]')) { + deltaInput.dataset.numValue = deltaInput.value; + deltaInput.inputMode = 'numeric'; + deltaInput.pattern = '^[+=\\-]?\d*'; + + const handleUpdate = (delta = 0) => { + const min = Number(deltaInput.min) || 0; + const max = Number(deltaInput.max) || Infinity; + const current = Number(deltaInput.dataset.numValue); + const rawNumber = Number(deltaInput.value); + if (Number.isNaN(rawNumber)) { + deltaInput.value = delta ? Math.clamp(current + delta, min, max) : current; + return; + } + + const newValue = + deltaInput.value.startsWith('+') || deltaInput.value.startsWith('-') + ? Math.clamp(current + rawNumber + delta, min, max) + : Math.clamp(rawNumber + delta, min, max); + deltaInput.value = deltaInput.dataset.numValue = newValue; + }; + + // Force valid characters while inputting + deltaInput.addEventListener('input', () => { + deltaInput.value = /[+=\-]?\d*/.exec(deltaInput.value)?.at(0) ?? deltaInput.value; + }); + + // Recreate Keyup/Keydown support + deltaInput.addEventListener('keydown', event => { + const step = event.key === 'ArrowUp' ? 1 : event.key === 'ArrowDown' ? -1 : 0; + if (step !== 0) { + handleUpdate(step); + deltaInput.dispatchEvent(new Event("change", { bubbles: true })); + } + }); + + // Mousewheel while focused support + deltaInput.addEventListener( + 'wheel', + event => { + if (deltaInput === document.activeElement) { + event.preventDefault(); + handleUpdate(Math.sign(-1 * event.deltaY)); + deltaInput.dispatchEvent(new Event("change", { bubbles: true })); + } + }, + { passive: false } + ); + + deltaInput.addEventListener('change', () => { + handleUpdate(); + }); + } } /**@inheritdoc */ diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index e96d597c..71b3696c 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -18,7 +18,7 @@ {{#if currency.enabled}}
{{localize currency.label}} - {{formInput currency.field value=currency.value enriched=currency.value toggled=true}} +
{{/if}} {{/each}} diff --git a/templates/sheets/actors/party/inventory.hbs b/templates/sheets/actors/party/inventory.hbs index a3397145..17c5f486 100644 --- a/templates/sheets/actors/party/inventory.hbs +++ b/templates/sheets/actors/party/inventory.hbs @@ -21,7 +21,7 @@ {{#if currency.enabled}}
{{localize currency.label}} - {{formInput currency.field value=currency.value enriched=currency.value toggled=true}} +
{{/if}} {{/each}} From f4dd9dc5c1061129d551858dc844bb30374a549f Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Fri, 12 Dec 2025 04:36:30 -0800 Subject: [PATCH 05/15] Minor tweaks to effect attributes (#1408) * Minor tweaks to effect attributes * Fix removing --- module/applications/ui/effectsDisplay.mjs | 2 +- templates/ui/effects-display.hbs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/module/applications/ui/effectsDisplay.mjs b/module/applications/ui/effectsDisplay.mjs index 7f90e30b..0875e783 100644 --- a/module/applications/ui/effectsDisplay.mjs +++ b/module/applications/ui/effectsDisplay.mjs @@ -87,7 +87,7 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica async removeEffect(event) { const element = event.target.closest('.effect-container'); const effects = DhEffectsDisplay.getTokenEffects(); - const effect = effects.find(x => x.id === element.id); + const effect = effects.find(x => x.id === element.dataset.effectId); await effect.delete(); this.render(); } diff --git a/templates/ui/effects-display.hbs b/templates/ui/effects-display.hbs index da37d8eb..95c6023c 100644 --- a/templates/ui/effects-display.hbs +++ b/templates/ui/effects-display.hbs @@ -1,8 +1,9 @@
{{#each effects as | effect |}} - From 360b9034376b05f746eab1e43cfdd14248e6391e Mon Sep 17 00:00:00 2001 From: "Josh Q." Date: Fri, 12 Dec 2025 23:42:44 -0500 Subject: [PATCH 06/15] domain lookup fix for tooltipo (#1420) --- module/documents/tooltipManager.mjs | 3 ++- templates/ui/tooltip/domainCard.hbs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index 1784698a..b0a107b9 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -75,7 +75,8 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti { item: item, description: item.system?.enrichedDescription ?? item.enrichedDescription, - config: CONFIG.DH + config: CONFIG.DH, + allDomains: CONFIG.DH.DOMAIN.allDomains() } ); diff --git a/templates/ui/tooltip/domainCard.hbs b/templates/ui/tooltip/domainCard.hbs index c209f29d..80d2b208 100644 --- a/templates/ui/tooltip/domainCard.hbs +++ b/templates/ui/tooltip/domainCard.hbs @@ -6,7 +6,7 @@
- {{#with (lookup config.DOMAIN.domains item.system.domain) as | domain |}} + {{#with (lookup allDomains item.system.domain) as | domain |}}
{{localize domain.label}}
{{/with}}
From 46a9aea0294ba638a938fe9e1e808ce8a6940b26 Mon Sep 17 00:00:00 2001 From: Murilo Brito <91566541+moliloo@users.noreply.github.com> Date: Sat, 13 Dec 2025 10:58:41 -0300 Subject: [PATCH 07/15] [BUGFIX] Fix game system conflict css font vars with foundry (#1421) * bugfix: fix game system conflict css font vars with foundry * bugfix: fix typo --- styles/less/utils/fonts.less | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/styles/less/utils/fonts.less b/styles/less/utils/fonts.less index 7d84366a..5c1e597a 100755 --- a/styles/less/utils/fonts.less +++ b/styles/less/utils/fonts.less @@ -2,14 +2,14 @@ @import './mixin.less'; :root { - --font-title: 'Cinzel Decorative'; - --font-subtitle: 'Cinzel'; - --font-body: 'Montserrat'; + --dh-font-title: 'Cinzel Decorative'; + --dh-font-subtitle: 'Cinzel'; + --dh-font-body: 'Montserrat'; } -@font-title: ~"var(--font-title, 'Cinzel Decorative'), serif"; -@font-subtitle: ~"var(--font-subtitle, 'Cinzel'), serif"; -@font-body: ~"var(--font-body, 'Montserrat'), sans-serif"; +@font-title: ~"var(--dh-font-title, 'Cinzel Decorative'), serif"; +@font-subtitle: ~"var(--dh-font-subtitle, 'Cinzel'), serif"; +@font-body: ~"var(--dh-font-body, 'Montserrat'), sans-serif"; .dh-style { .dh-typography(); From 64caff6fb21d5af65e57fbf2123466586147f862 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sat, 13 Dec 2025 06:05:44 -0800 Subject: [PATCH 08/15] Make the spotlight queue feature a toggle (default off) (#1418) --- lang/en.json | 5 +++++ module/applications/ui/combatTracker.mjs | 6 +++--- module/config/settingsConfig.mjs | 3 ++- module/systemRegistration/settings.mjs | 10 ++++++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lang/en.json b/lang/en.json index d2386744..af139100 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2504,6 +2504,11 @@ "hint": "Apply variant rules from the Daggerheart system", "name": "Variant Rules", "actionTokens": "Action Tokens" + }, + "SpotlightRequestQueue": { + "name": "Spotlight Request Queue", + "label": "Spotlight Request Queue", + "hint": "Adds more structure to spotlight requests by ordering them from oldest to newest" } }, "Resources": { diff --git a/module/applications/ui/combatTracker.mjs b/module/applications/ui/combatTracker.mjs index 23bede60..37b4953c 100644 --- a/module/applications/ui/combatTracker.mjs +++ b/module/applications/ui/combatTracker.mjs @@ -57,21 +57,21 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C const adversaries = context.turns?.filter(x => x.isNPC) ?? []; const characters = context.turns?.filter(x => !x.isNPC) ?? []; + const spotlightQueueEnabled = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightRequestQueue); const spotlightRequests = characters - ?.filter(x => !x.isNPC) + ?.filter(x => !x.isNPC && spotlightQueueEnabled) .filter(x => x.system.spotlight.requestOrderIndex > 0) .sort((a, b) => { const valueA = a.system.spotlight.requestOrderIndex; const valueB = b.system.spotlight.requestOrderIndex; - return valueA - valueB; }); Object.assign(context, { actionTokens: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).actionTokens, adversaries, - characters: characters?.filter(x => !x.isNPC).filter(x => x.system.spotlight.requestOrderIndex == 0), + characters: characters?.filter(x => !x.isNPC).filter(x => !spotlightQueueEnabled || x.system.spotlight.requestOrderIndex == 0), spotlightRequests }); } diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index aea9bc48..3d993949 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -28,7 +28,8 @@ export const gameSettings = { LevelTiers: 'LevelTiers', Countdowns: 'Countdowns', LastMigrationVersion: 'LastMigrationVersion', - TagTeamRoll: 'TagTeamRoll' + TagTeamRoll: 'TagTeamRoll', + SpotlightRequestQueue: 'SpotlightRequestQueue', }; export const actionAutomationChoices = { diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index 6954730f..d08d65d1 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -13,6 +13,16 @@ export const registerDHSettings = () => { registerMenuSettings(); registerMenus(); registerNonConfigSettings(); + + game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightRequestQueue, { + name: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.SpotlightRequestQueue.name'), + label: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.SpotlightRequestQueue.label'), + hint: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.SpotlightRequestQueue.hint'), + scope: 'world', + config: true, + type: Boolean, + onChange: () => ui.combat.render(), + }) }; const registerMenuSettings = () => { From 7a50d7795270d19251bff416126a8ee44a11f98f Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sat, 13 Dec 2025 07:18:21 -0700 Subject: [PATCH 09/15] Pulling out hope method and always updating the resources. (#1417) Making sure stress decreases on critical. --- .../applications/sheets/actors/character.mjs | 2 - module/applications/ui/chatLog.mjs | 1 - module/dice/dhRoll.mjs | 80 +++++++++++-------- module/dice/dualityRoll.mjs | 3 +- module/documents/actor.mjs | 4 + 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 016cff13..953a0cf6 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -685,8 +685,6 @@ export default class CharacterSheet extends DHBaseActorSheet { ability: abilityLabel }) }); - - if (result) game.system.api.fields.ActionFields.CostField.execute.call(this, result); } //TODO: redo toggleEquipItem method diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 871ff173..47dfe500 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -245,7 +245,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo }); if (!result) return; - await game.system.api.fields.ActionFields.CostField.execute.call({ actor }, result); const newMessageData = foundry.utils.deepClone(message.system); foundry.utils.setProperty(newMessageData, `${path}.result`, result.roll); diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index e6856dab..abb75fd5 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -237,6 +237,51 @@ export default class DHRoll extends Roll { } } +async function automateHopeFear(config) { + const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + const hopeFearAutomation = automationSettings.hopeFear; + if (!config.source?.actor || + (game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) || + config.actionType === 'reaction' || + config.tagTeamSelected || + config.skips?.resources) + return; + const actor = await fromUuid(config.source.actor); + let updates = []; + if (!actor) return; + + if (config.rerolledRoll) { + if (config.roll.result.duality != config.rerolledRoll.result.duality) { + const hope = (config.roll.isCritical || config.roll.result.duality === 1 ? 1 : 0) + - (config.rerolledRoll.isCritical || config.rerolledRoll.result.duality === 1 ? 1 : 0); + const stress = (config.roll.isCritical ? 1 : 0) - (config.rerolledRoll.isCritical ? 1 : 0); + const fear = (config.roll.result.duality === -1 ? 1 : 0) + - (config.rerolledRoll.result.duality === -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 }); + } + } else { + if (config.roll.isCritical || config.roll.result.duality === 1) + updates.push({ key: 'hope', value: 1, total: -1, enabled: true }); + if (config.roll.isCritical) + updates.push({ key: 'stress', value: -1, total: 1, enabled: true }); + if (config.roll.result.duality === -1) + updates.push({ key: 'fear', value: 1, total: -1, enabled: true }); + } + + if (updates.length) { + const target = actor.system.partner ?? actor; + if (!['dead', 'defeated', 'unconscious'].some(x => actor.statuses.has(x))) { + await target.modifyResource(updates); + } + } +} + export const registerRollDiceHooks = () => { Hooks.on(`${CONFIG.DH.id}.postRollDuality`, async (config, message) => { const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); @@ -254,38 +299,7 @@ export const registerRollDiceHooks = () => { } } - const hopeFearAutomation = automationSettings.hopeFear; - if ( - !config.source?.actor || - (game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) || - config.actionType === 'reaction' || - config.tagTeamSelected || - config.skips?.resources - ) - return; - const actor = await fromUuid(config.source.actor); - let updates = []; - if (!actor) return; - if (config.roll.isCritical || config.roll.result.duality === 1) - updates.push({ key: 'hope', value: 1, total: -1, enabled: true }); - if (config.roll.isCritical) updates.push({ key: 'stress', value: 1, total: -1, enabled: true }); - if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, total: -1, enabled: true }); - - if (config.rerolledRoll) { - if (config.rerolledRoll.isCritical || config.rerolledRoll.result.duality === 1) - updates.push({ key: 'hope', value: -1, total: 1, enabled: true }); - if (config.rerolledRoll.isCritical) updates.push({ key: 'stress', value: -1, total: 1, enabled: true }); - if (config.rerolledRoll.result.duality === -1) - updates.push({ key: 'fear', value: -1, total: 1, enabled: true }); - } - - if (updates.length) { - const target = actor.system.partner ?? actor; - if (!['dead', 'defeated', 'unconscious'].some(x => actor.statuses.has(x))) { - if (config.rerolledRoll) target.modifyResource(updates); - else config.costs = [...(config.costs ?? []), ...updates]; - } - } + await automateHopeFear(config); if (!config.roll.hasOwnProperty('success') && !config.targets?.length) return; @@ -296,7 +310,5 @@ export const registerRollDiceHooks = () => { const currentCombatant = game.combat.combatants.get(game.combat.current?.combatantId); if (currentCombatant?.actorId == actor.id) ui.combat.setCombatantSpotlight(currentCombatant.id); } - - return; }); }; diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 813c913b..59cb6e02 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -262,8 +262,7 @@ export default class DualityRoll extends D20Roll { targets: message.system.targets, tagTeamSelected: Object.values(tagTeamSettings.members).some(x => x.messageId === message._id), roll: newRoll, - rerolledRoll: - newRoll.result.duality !== message.system.roll.result.duality ? message.system.roll : undefined + rerolledRoll: message.system.roll }); return { newRoll, parsedRoll }; } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 8999fdd8..5ffaf744 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -679,6 +679,10 @@ export default class DhpActor extends Actor { return updates; } + /** + * Resources are modified asynchronously, so be careful not to update the same resource in + * quick succession. + */ async modifyResource(resources) { if (!resources?.length) return; From a8c120be8e5a5e5db1e1c2f8f1ff9263da92195b Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sat, 13 Dec 2025 08:09:53 -0700 Subject: [PATCH 10/15] Allowing coundown automations to work for players on action rolls (#1416) --- module/applications/ui/combatTracker.mjs | 6 ++++-- module/applications/ui/countdowns.mjs | 24 ++++++++++++++---------- module/dice/dhRoll.mjs | 6 ++++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/module/applications/ui/combatTracker.mjs b/module/applications/ui/combatTracker.mjs index 37b4953c..2ed0e52b 100644 --- a/module/applications/ui/combatTracker.mjs +++ b/module/applications/ui/combatTracker.mjs @@ -161,9 +161,11 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C if (this.viewed.turn !== toggleTurn) { const { updateCountdowns } = game.system.api.applications.ui.DhCountdowns; - await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.spotlight.id); if (combatant.actor.type === 'character') { - await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.characterSpotlight.id); + await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.spotlight.id, + CONFIG.DH.GENERAL.countdownProgressionTypes.characterSpotlight.id); + } else { + await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.spotlight.id); } const autoPoints = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).actionPoints; diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 96315b17..42920a4a 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -245,14 +245,20 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application return super.close(options); } - static async updateCountdowns(progressType) { + /** + * Sends updates of the countdowns to the GM player. Since this is asynchronous, be sure to + * update all the countdowns at the same time. + * + * @param {...any} progressTypes Countdowns to be updated + */ + static async updateCountdowns(...progressTypes) { const { countdownAutomation } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); if (!countdownAutomation) return; const countdownSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); const updatedCountdowns = Object.keys(countdownSetting.countdowns).reduce((acc, key) => { const countdown = countdownSetting.countdowns[key]; - if (countdown.progress.type === progressType && countdown.progress.current > 0) { + if (progressTypes.indexOf(countdown.progress.type) !== -1 && countdown.progress.current > 0) { acc.push(key); } @@ -260,7 +266,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application }, []); const countdownData = countdownSetting.toObject(); - await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, { + const settings = { ...countdownData, countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => { const countdown = foundry.utils.deepClone(countdownData.countdowns[key]); @@ -271,14 +277,12 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application acc[key] = countdown; return acc; }, {}) + }; + await emitAsGM(GMUpdateEvent.UpdateCountdowns, + DhCountdowns.gmSetSetting.bind(settings), + settings, null, { + refreshType: RefreshType.Countdown }); - - const data = { refreshType: RefreshType.Countdown }; - await game.socket.emit(`system.${CONFIG.DH.id}`, { - action: socketEvent.Refresh, - data - }); - Hooks.callAll(socketEvent.Refresh, data); } async _onRender(context, options) { diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index abb75fd5..ce39ed6a 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -292,10 +292,12 @@ export const registerRollDiceHooks = () => { !config.skips?.updateCountdowns ) { const { updateCountdowns } = game.system.api.applications.ui.DhCountdowns; - await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.actionRoll.id); if (config.roll.result.duality === -1) { - await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.fear.id); + await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.actionRoll.id, + CONFIG.DH.GENERAL.countdownProgressionTypes.fear.id); + } else { + await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.actionRoll.id); } } From 6cb635901f7d974bbf538a3224b33b32209e7d96 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 13 Dec 2025 16:10:44 +0100 Subject: [PATCH 11/15] Made the effect-hud more foundry standard to work better for modules (#1414) --- styles/less/hud/token-hud/token-hud.less | 2 +- templates/hud/tokenHUD.hbs | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/styles/less/hud/token-hud/token-hud.less b/styles/less/hud/token-hud/token-hud.less index ac269172..46003975 100644 --- a/styles/less/hud/token-hud/token-hud.less +++ b/styles/less/hud/token-hud/token-hud.less @@ -56,7 +56,7 @@ .effect-locked { position: absolute; bottom: 2px; - right: 2px; + left: 11.5px; font-size: 12px; color: @golden; filter: drop-shadow(0 0 3px black); diff --git a/templates/hud/tokenHUD.hbs b/templates/hud/tokenHUD.hbs index 09259d4a..f079e5d9 100644 --- a/templates/hud/tokenHUD.hbs +++ b/templates/hud/tokenHUD.hbs @@ -46,8 +46,12 @@
{{#each systemStatusEffects as |status|}} -
- +
+ {{#if status.disabled}} / {{/if}} @@ -57,8 +61,12 @@ {{#if genericStatusEffects}} {{#each genericStatusEffects as |status|}} -
- +
+ {{#if status.locked}}{{/if}}
{{/each}} From 315f1ef8e0980b07ec878d026282afc9944b5292 Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sat, 13 Dec 2025 08:24:22 -0700 Subject: [PATCH 12/15] Adding direct damage to adversaries and environments (#1412) --- ...ary_Adult_Flickerfly_G7jiltRjgvVhZewm.json | 3 +- ...ersary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json | 5 +- .../adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json | 20 +++-- ...ry_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json | 3 +- ...rsary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json | 6 +- .../adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json | 3 +- ...sary_Master_Assassin_dNta0cUzr96xcFhf.json | 84 ++++++++++++++++++- ...ary_Minotaur_Wrecker_rM9qCIYeWg9I0B4l.json | 3 +- ...ersary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json | 81 ++++++++++++++++++ ...Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json | 11 ++- ...agon__Molten_Scourge_eArAPuB38CNR0ZIM.json | 3 +- ...g_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json | 3 +- 12 files changed, 203 insertions(+), 22 deletions(-) diff --git a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json index 95e6c243..0e3a89c6 100644 --- a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json +++ b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json @@ -427,7 +427,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", diff --git a/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json b/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json index d77d3379..cf6583e4 100644 --- a/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json +++ b/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json @@ -307,7 +307,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", @@ -319,7 +320,7 @@ "trait": null, "difficulty": null, "bonus": null, - "advState": "neutral", + "advState": "advantage", "diceRolling": { "multiplier": "prof", "flatMultiplier": 1, diff --git a/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json b/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json index 3ccac5dd..fd73ee36 100644 --- a/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json +++ b/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json @@ -39,7 +39,8 @@ "experiences": { "7GpgCWSe6hNwnOO7": { "name": "Throw", - "value": 2 + "value": 2, + "description": "" } }, "bonuses": { @@ -105,7 +106,8 @@ }, "base": false } - ] + ], + "direct": true }, "name": "Club", "img": "icons/weapons/clubs/club-banded-barbed-black.webp", @@ -337,10 +339,11 @@ { "value": { "custom": { - "enabled": false + "enabled": false, + "formula": "" }, "flatMultiplier": 1, - "dice": "d12", + "dice": "d10", "bonus": 2, "multiplier": "flat" }, @@ -356,12 +359,14 @@ "dice": "d6", "bonus": null, "custom": { - "enabled": false + "enabled": false, + "formula": "" } } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", @@ -528,7 +533,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", diff --git a/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json b/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json index 08b22a0b..7ea12036 100644 --- a/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json +++ b/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json @@ -107,7 +107,8 @@ }, "base": false } - ] + ], + "direct": true }, "img": "icons/magic/symbols/rune-sigil-rough-white-teal.webp", "type": "attack", diff --git a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json index 13b9d624..72ec986d 100644 --- a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json +++ b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json @@ -108,7 +108,8 @@ }, "base": false } - ] + ], + "direct": true }, "type": "attack", "chatDisplay": false @@ -358,7 +359,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", diff --git a/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json b/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json index e3b34aea..a900aa7b 100644 --- a/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json +++ b/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json @@ -377,7 +377,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", diff --git a/src/packs/adversaries/adversary_Master_Assassin_dNta0cUzr96xcFhf.json b/src/packs/adversaries/adversary_Master_Assassin_dNta0cUzr96xcFhf.json index 943559e1..557ef607 100644 --- a/src/packs/adversaries/adversary_Master_Assassin_dNta0cUzr96xcFhf.json +++ b/src/packs/adversaries/adversary_Master_Assassin_dNta0cUzr96xcFhf.json @@ -233,7 +233,89 @@ "system": { "description": "

The Assassin deals direct damage while they’re Hidden.

", "resource": null, - "actions": {}, + "actions": { + "xFBE0jLf96fbCY7K": { + "type": "attack", + "_id": "xFBE0jLf96fbCY7K", + "systemPath": "actions", + "baseAction": false, + "description": "

The Assassin deals direct damage while they’re Hidden.

", + "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, + "actionType": "action", + "cost": [], + "uses": { + "value": null, + "max": "", + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": [ + { + "value": { + "custom": { + "enabled": false, + "formula": "" + }, + "flatMultiplier": 2, + "dice": "d10", + "bonus": 2, + "multiplier": "flat" + }, + "applyTo": "hitPoints", + "type": [ + "physical" + ], + "base": false, + "resultBased": false, + "valueAlt": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + } + } + ], + "includeBase": false, + "direct": true + }, + "target": { + "type": "any", + "amount": null + }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, + "name": "Hidden attack", + "img": "icons/magic/perception/silhouette-stealth-shadow.webp", + "range": "close" + } + }, "originItemType": null, "originId": null }, diff --git a/src/packs/adversaries/adversary_Minotaur_Wrecker_rM9qCIYeWg9I0B4l.json b/src/packs/adversaries/adversary_Minotaur_Wrecker_rM9qCIYeWg9I0B4l.json index 10f48d17..570db804 100644 --- a/src/packs/adversaries/adversary_Minotaur_Wrecker_rM9qCIYeWg9I0B4l.json +++ b/src/packs/adversaries/adversary_Minotaur_Wrecker_rM9qCIYeWg9I0B4l.json @@ -478,7 +478,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", diff --git a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json index 74d7e2c3..721d8973 100644 --- a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json +++ b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json @@ -340,6 +340,87 @@ "name": "Curse", "img": "icons/magic/unholy/hand-marked-pink.webp", "range": "veryClose" + }, + "zLKfwa8a2YBRLKAF": { + "type": "attack", + "_id": "zLKfwa8a2YBRLKAF", + "systemPath": "actions", + "baseAction": false, + "description": "

Attacks made by the Hunter against a Deathlocked target deal direct damage.

", + "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, + "actionType": "action", + "cost": [], + "uses": { + "value": null, + "max": "", + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": [ + { + "value": { + "custom": { + "enabled": false, + "formula": "" + }, + "flatMultiplier": 2, + "dice": "d12", + "bonus": 1, + "multiplier": "flat" + }, + "applyTo": "hitPoints", + "type": [ + "physical" + ], + "base": false, + "resultBased": false, + "valueAlt": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + } + } + ], + "includeBase": false, + "direct": true + }, + "target": { + "type": "any", + "amount": null + }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, + "name": "Deathlocked attack", + "img": "icons/magic/unholy/hand-marked-pink.webp", + "range": "veryClose" } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json b/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json index d5f30dda..2a753812 100644 --- a/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json +++ b/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json @@ -312,9 +312,10 @@ { "value": { "custom": { - "enabled": false + "enabled": false, + "formula": "" }, - "flatMultiplier": 1, + "flatMultiplier": 2, "dice": "d6", "bonus": 8, "multiplier": "flat" @@ -331,12 +332,14 @@ "dice": "d6", "bonus": null, "custom": { - "enabled": false + "enabled": false, + "formula": "" } } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", diff --git a/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json b/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json index 056bf848..d04dab50 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json @@ -804,7 +804,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", 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 81ce16f9..39070236 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 @@ -457,7 +457,8 @@ } } ], - "includeBase": false + "includeBase": false, + "direct": true }, "target": { "type": "any", From d5b8431f8826dd9d04c6a50ab0631fc829815770 Mon Sep 17 00:00:00 2001 From: Nikhil Nagarajan Date: Sat, 13 Dec 2025 10:38:07 -0500 Subject: [PATCH 13/15] Massive Damage incoming. Over 9000. (#1419) --- lang/en.json | 5 +++++ module/data/settings/VariantRules.mjs | 7 +++++++ module/documents/actor.mjs | 4 ++++ module/helpers/utils.mjs | 5 +++-- templates/settings/variant-rules.hbs | 7 +++++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lang/en.json b/lang/en.json index af139100..6464547b 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1801,6 +1801,7 @@ "plural": "Costs" }, "Damage": { + "massive": "Massive", "severe": "Severe", "major": "Major", "minor": "Minor", @@ -2522,6 +2523,10 @@ "actionTokens": { "enabled": { "label": "Enabled" }, "tokens": { "label": "Tokens" } + }, + "massiveDamage":{ + "title":"Massive Damage", + "enabled": { "label": "Enabled" } } } }, diff --git a/module/data/settings/VariantRules.mjs b/module/data/settings/VariantRules.mjs index ad7d707a..41c63be2 100644 --- a/module/data/settings/VariantRules.mjs +++ b/module/data/settings/VariantRules.mjs @@ -39,6 +39,13 @@ export default class DhVariantRules extends foundry.abstract.DataModel { label: 'DAGGERHEART.CONFIG.Range.close.name' }), far: new fields.NumberField({ required: true, initial: 60, label: 'DAGGERHEART.CONFIG.Range.far.name' }) + }), + massiveDamage: new fields.SchemaField({ + enabled: new fields.BooleanField({ + required: true, + initial: false, + label: 'DAGGERHEART.SETTINGS.VariantRules.FIELDS.massiveDamage.enabled.label' + }) }) }; } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 5ffaf744..c269b686 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -765,6 +765,10 @@ export default class DhpActor extends Actor { } convertDamageToThreshold(damage) { + const massiveDamageEnabled=game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).massiveDamage.enabled; + if (massiveDamageEnabled && damage >= (this.system.damageThresholds.severe * 2)) { + return 4; + } return damage >= this.system.damageThresholds.severe ? 3 : damage >= this.system.damageThresholds.major ? 2 : 1; } diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 39d5298d..396ed2fa 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -198,7 +198,7 @@ foundry.dice.terms.Die.prototype.selfCorrecting = function (modifier) { }; export const getDamageKey = damage => { - return ['none', 'minor', 'major', 'severe', 'any'][damage]; + return ['none', 'minor', 'major', 'severe', 'massive','any'][damage]; }; export const getDamageLabel = damage => { @@ -211,7 +211,8 @@ export const damageKeyToNumber = key => { minor: 1, major: 2, severe: 3, - any: 4 + massive: 4, + any: 5 }[key]; }; diff --git a/templates/settings/variant-rules.hbs b/templates/settings/variant-rules.hbs index 5cc5c90c..df7accb3 100644 --- a/templates/settings/variant-rules.hbs +++ b/templates/settings/variant-rules.hbs @@ -22,6 +22,13 @@
+
+ +
+ {{formGroup settingFields.schema.fields.massiveDamage.fields.enabled value=settingFields._source.massiveDamage.enabled localize=true}} +
+
+
+
+
diff --git a/templates/settings/homebrew-settings/settings.hbs b/templates/settings/homebrew-settings/settings.hbs index 35e2a786..e7340323 100644 --- a/templates/settings/homebrew-settings/settings.hbs +++ b/templates/settings/homebrew-settings/settings.hbs @@ -33,18 +33,22 @@ {{formGroup settingFields.schema.fields.currency.fields.title value=settingFields._source.currency.title localize=true}}
+ {{formGroup settingFields.schema.fields.currency.fields.coins.fields.label value=settingFields._source.currency.coins.label localize=true}}
+ {{formGroup settingFields.schema.fields.currency.fields.handfuls.fields.label value=settingFields._source.currency.handfuls.label localize=true}}
+ {{formGroup settingFields.schema.fields.currency.fields.bags.fields.label value=settingFields._source.currency.bags.label localize=true}}
+ {{formGroup settingFields.schema.fields.currency.fields.chests.fields.label value=settingFields._source.currency.chests.label localize=true}}
diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index 71b3696c..f9dee872 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -17,7 +17,9 @@ {{#each this.inventory.currencies as | currency |}} {{#if currency.enabled}}
- {{localize currency.label}} + + {{localize currency.label}} +
{{/if}} diff --git a/templates/sheets/actors/party/inventory.hbs b/templates/sheets/actors/party/inventory.hbs index 17c5f486..09f3ba62 100644 --- a/templates/sheets/actors/party/inventory.hbs +++ b/templates/sheets/actors/party/inventory.hbs @@ -20,7 +20,9 @@ {{#each this.inventory.currencies as | currency |}} {{#if currency.enabled}}
- {{localize currency.label}} + + {{localize currency.label}} +
{{/if}}