From 70239ec06a506558672859ccb17749bb4a449e95 Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Thu, 10 Jul 2025 13:28:51 +0200
Subject: [PATCH 01/12] [BUG] DiceSoNice fix (#312)
* Fixed DiceSoNice integration again
* PR fixes
* Improved with tertiary
---
module/dice/d20Roll.mjs | 8 +-------
module/dice/dhRoll.mjs | 2 +-
module/dice/dualityRoll.mjs | 4 +++-
module/helpers/utils.mjs | 10 ++++------
4 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs
index c344231f..9c784084 100644
--- a/module/dice/d20Roll.mjs
+++ b/module/dice/d20Roll.mjs
@@ -1,5 +1,4 @@
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
-import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
import DHRoll from './dhRoll.mjs';
export default class D20Roll extends DHRoll {
@@ -137,12 +136,7 @@ export default class D20Roll extends DHRoll {
static async buildEvaluate(roll, config = {}, message = {}) {
if (config.evaluate !== false) await roll.evaluate();
- const advantageState =
- config.roll.advantage == this.ADV_MODE.ADVANTAGE
- ? true
- : config.roll.advantage == this.ADV_MODE.DISADVANTAGE
- ? false
- : null;
+
this.postEvaluate(roll, config);
}
diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs
index 13246ac9..46e7374e 100644
--- a/module/dice/dhRoll.mjs
+++ b/module/dice/dhRoll.mjs
@@ -154,7 +154,7 @@ export const registerRollDiceHooks = () => {
if (updates.length) actor.modifyResource(updates);
- if (!config.roll.hasOwnProperty('success') && !config.targets.length) return;
+ if (!config.roll.hasOwnProperty('success') && !config.targets?.length) return;
const rollResult = config.roll.success || config.targets.some(t => t.hit),
looseSpotlight = !rollResult || config.roll.result.duality === -1;
diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs
index 4d0e99a3..6c1d0fe4 100644
--- a/module/dice/dualityRoll.mjs
+++ b/module/dice/dualityRoll.mjs
@@ -1,5 +1,6 @@
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
import D20Roll from './d20Roll.mjs';
+import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
export default class DualityRoll extends D20Roll {
_advantageFaces = 6;
@@ -80,7 +81,6 @@ export default class DualityRoll extends D20Roll {
}
static getHooks(hooks) {
-
return [...(hooks ?? []), 'Duality'];
}
@@ -142,5 +142,7 @@ export default class DualityRoll extends D20Roll {
total: roll.dHope.total + roll.dFear.total,
label: roll.totalLabel
};
+
+ setDiceSoNiceForDualityRoll(roll, config.roll.advantage.type);
}
}
diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs
index 0bb2088e..8156736d 100644
--- a/module/helpers/utils.mjs
+++ b/module/helpers/utils.mjs
@@ -126,12 +126,10 @@ export const setDiceSoNiceForDualityRoll = (rollResult, advantageState) => {
const diceSoNicePresets = getDiceSoNicePresets();
rollResult.dice[0].options = { appearance: diceSoNicePresets.hope };
rollResult.dice[1].options = { appearance: diceSoNicePresets.fear }; //diceSoNicePresets.fear;
- if (rollResult.dice[2]) {
- if (advantageState === true) {
- rollResult.dice[2].options = { appearance: diceSoNicePresets.advantage };
- } else if (advantageState === false) {
- rollResult.dice[2].options = { appearance: diceSoNicePresets.disadvantage };
- }
+ if (rollResult.dice[2] && advantageState) {
+ rollResult.dice[2].options = {
+ appearance: advantageState === 1 ? diceSoNicePresets.advantage : diceSoNicePresets.disadvantage
+ };
}
};
From e6126d81045a85eebd37c52fe9ba77027b8e24d7 Mon Sep 17 00:00:00 2001
From: Dapoulp <74197441+Dapoulp@users.noreply.github.com>
Date: Fri, 11 Jul 2025 17:36:51 +0200
Subject: [PATCH 02/12] Fix to make Cosmo happy (#318)
---
module/data/action/baseAction.mjs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs
index e193aefe..e2eafbf2 100644
--- a/module/data/action/baseAction.mjs
+++ b/module/data/action/baseAction.mjs
@@ -180,8 +180,8 @@ export default class DHBaseAction extends foundry.abstract.DataModel {
const actorData = this.actor.getRollData(false);
// Remove when included directly in Actor getRollData
- actorData.prof = actorData.proficiency?.value ?? 1;
- actorData.cast = actorData.spellcast?.value ?? 1;
+ actorData.prof = actorData.proficiency?.total ?? 1;
+ actorData.cast = actorData.spellcast?.total ?? 1;
actorData.result = data.roll?.total ?? 1;
/* actorData.scale = data.costs?.length
? data.costs.reduce((a, c) => {
From 85ca0e6b603659a4ba53cc9a6b334e433e34ce16 Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Fri, 11 Jul 2025 18:09:06 +0200
Subject: [PATCH 03/12] Fixed so companion damage uses partner proficiency for
scaling (#319)
---
module/data/actor/companion.mjs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs
index 1203cc96..88b149e3 100644
--- a/module/data/actor/companion.mjs
+++ b/module/data/actor/companion.mjs
@@ -66,10 +66,9 @@ export default class DhCompanion extends BaseDataActor {
damage: {
parts: [
{
- multiplier: 'flat',
value: {
dice: 'd6',
- multiplier: 'flat'
+ multiplier: 'prof'
}
}
]
@@ -87,6 +86,12 @@ export default class DhCompanion extends BaseDataActor {
};
}
+ get proficiency() {
+ return {
+ total: this.partner?.system?.proficiency?.total ?? 1
+ };
+ }
+
prepareBaseData() {
const partnerSpellcastingModifier = this.partner?.system?.spellcastingModifiers?.main;
const spellcastingModifier = this.partner?.system?.traits?.[partnerSpellcastingModifier]?.total;
From d4cc8e5a49e3d574d70b9df49dff9e164ad1c8e4 Mon Sep 17 00:00:00 2001
From: IrkTheImp <41175833+IrkTheImp@users.noreply.github.com>
Date: Fri, 11 Jul 2025 14:50:08 -0500
Subject: [PATCH 04/12] set to use dh ranges by default and made setting world,
not client. (#323)
---
module/data/settings/RangeMeasurement.mjs | 2 +-
module/systemRegistration/settings.mjs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/module/data/settings/RangeMeasurement.mjs b/module/data/settings/RangeMeasurement.mjs
index 71fb7787..552963f0 100644
--- a/module/data/settings/RangeMeasurement.mjs
+++ b/module/data/settings/RangeMeasurement.mjs
@@ -2,7 +2,7 @@ export default class DhRangeMeasurement extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
- enabled: new fields.BooleanField({ required: true, initial: false, label: 'DAGGERHEART.GENERAL.enabled' }),
+ enabled: new fields.BooleanField({ required: true, initial: true, label: 'DAGGERHEART.GENERAL.enabled' }),
melee: new fields.NumberField({ required: true, initial: 5, label: 'DAGGERHEART.CONFIG.Range.melee.name' }),
veryClose: new fields.NumberField({
required: true,
diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs
index a4ed05c8..fea12acd 100644
--- a/module/systemRegistration/settings.mjs
+++ b/module/systemRegistration/settings.mjs
@@ -60,7 +60,7 @@ const registerMenuSettings = () => {
});
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement, {
- scope: 'client',
+ scope: 'world',
config: false,
type: DhRangeMeasurement
});
From 5b9db88d501f4ee664a269ee7a33967727788cc0 Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Fri, 11 Jul 2025 21:53:22 +0200
Subject: [PATCH 05/12] Added a separation of system effects and generic
effects on token status effects. Can be turned off in settings. (#317)
---
daggerheart.mjs | 14 ++--
lang/en.json | 8 ++-
module/applications/_module.mjs | 1 +
module/applications/hud/_module.mjs | 1 +
module/applications/hud/tokenHUD.mjs | 84 ++++++++++++++++++++++
module/data/settings/Appearance.mjs | 4 ++
styles/daggerheart.less | 2 +
styles/less/hud/index.less | 1 +
styles/less/hud/token-hud/token-hud.less | 10 +++
templates/hud/tokenHUD.hbs | 78 ++++++++++++++++++++
templates/settings/appearance-settings.hbs | 1 +
11 files changed, 199 insertions(+), 5 deletions(-)
create mode 100644 module/applications/hud/_module.mjs
create mode 100644 module/applications/hud/tokenHUD.mjs
create mode 100644 styles/less/hud/index.less
create mode 100644 styles/less/hud/token-hud/token-hud.less
create mode 100644 templates/hud/tokenHUD.hbs
diff --git a/daggerheart.mjs b/daggerheart.mjs
index 4f411b0f..5a6d8193 100644
--- a/daggerheart.mjs
+++ b/daggerheart.mjs
@@ -41,10 +41,14 @@ Hooks.once('init', () => {
]
);
- CONFIG.statusEffects = Object.values(SYSTEM.GENERAL.conditions).map(x => ({
- ...x,
- name: game.i18n.localize(x.name)
- }));
+ CONFIG.statusEffects = [
+ ...CONFIG.statusEffects,
+ ...Object.values(SYSTEM.GENERAL.conditions).map(x => ({
+ ...x,
+ name: game.i18n.localize(x.name),
+ systemEffect: true
+ }))
+ ];
CONFIG.Dice.daggerheart = {
DualityDie: DualityDie,
@@ -108,6 +112,8 @@ Hooks.once('init', () => {
}
);
+ CONFIG.Token.hudClass = applications.hud.DHTokenHUD;
+
CONFIG.Combat.dataModels = {
base: models.DhCombat
};
diff --git a/lang/en.json b/lang/en.json
index 02ea41eb..db420652 100755
--- a/lang/en.json
+++ b/lang/en.json
@@ -279,6 +279,11 @@
}
}
},
+ "HUD": {
+ "tokenHUD": {
+ "genericEffects": "Foundry Effects"
+ }
+ },
"Levelup": {
"actions": {
"creatureComfort": {
@@ -1180,7 +1185,8 @@
"SETTINGS": {
"Appearance": {
"FIELDS": {
- "displayFear": { "label": "Fear Display" }
+ "displayFear": { "label": "Fear Display" },
+ "showGenericStatusEffects": { "label": "Show Foundry Status Effects" }
},
"fearDisplay": {
"token": "Tokens",
diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs
index 82c2866c..d4ceb229 100644
--- a/module/applications/_module.mjs
+++ b/module/applications/_module.mjs
@@ -1,5 +1,6 @@
export * as characterCreation from './characterCreation/_module.mjs';
export * as dialogs from './dialogs/_module.mjs';
+export * as hud from './hud/_module.mjs';
export * as levelup from './levelup/_module.mjs';
export * as settings from './settings/_module.mjs';
export * as sheets from './sheets/_module.mjs';
diff --git a/module/applications/hud/_module.mjs b/module/applications/hud/_module.mjs
new file mode 100644
index 00000000..70edaf8f
--- /dev/null
+++ b/module/applications/hud/_module.mjs
@@ -0,0 +1 @@
+export { default as DHTokenHUD } from './tokenHud.mjs';
diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs
new file mode 100644
index 00000000..9a58bab2
--- /dev/null
+++ b/module/applications/hud/tokenHUD.mjs
@@ -0,0 +1,84 @@
+export default class DHTokenHUD extends TokenHUD {
+ static DEFAULT_OPTIONS = {
+ classes: ['daggerheart']
+ };
+
+ /** @override */
+ static PARTS = {
+ hud: {
+ root: true,
+ template: 'systems/daggerheart/templates/hud/tokenHUD.hbs'
+ }
+ };
+
+ async _prepareContext(options) {
+ const context = await super._prepareContext(options);
+ context.systemStatusEffects = Object.keys(context.statusEffects).reduce((acc, key) => {
+ const effect = context.statusEffects[key];
+ if (effect.systemEffect) acc[key] = effect;
+
+ return acc;
+ }, {});
+
+ const useGeneric = game.settings.get(
+ CONFIG.DH.id,
+ CONFIG.DH.SETTINGS.gameSettings.appearance
+ ).showGenericStatusEffects;
+ context.genericStatusEffects = useGeneric
+ ? Object.keys(context.statusEffects).reduce((acc, key) => {
+ const effect = context.statusEffects[key];
+ if (!effect.systemEffect) acc[key] = effect;
+
+ return acc;
+ }, {})
+ : null;
+
+ return context;
+ }
+
+ _getStatusEffectChoices() {
+ // Include all HUD-enabled status effects
+ const choices = {};
+ for (const status of CONFIG.statusEffects) {
+ if (
+ status.hud === false ||
+ (foundry.utils.getType(status.hud) === 'Object' &&
+ status.hud.actorTypes?.includes(this.document.actor.type) === false)
+ ) {
+ continue;
+ }
+ choices[status.id] = {
+ _id: status._id,
+ id: status.id,
+ systemEffect: status.systemEffect,
+ title: game.i18n.localize(status.name ?? /** @deprecated since v12 */ status.label),
+ src: status.img ?? /** @deprecated since v12 */ status.icon,
+ isActive: false,
+ isOverlay: false
+ };
+ }
+
+ // Update the status of effects which are active for the token actor
+ const activeEffects = this.actor?.effects || [];
+ for (const effect of activeEffects) {
+ for (const statusId of effect.statuses) {
+ const status = choices[statusId];
+ if (!status) continue;
+ if (status._id) {
+ if (status._id !== effect.id) continue;
+ } else {
+ if (effect.statuses.size !== 1) continue;
+ }
+ status.isActive = true;
+ if (effect.getFlag('core', 'overlay')) status.isOverlay = true;
+ break;
+ }
+ }
+
+ // Flag status CSS class
+ for (const status of Object.values(choices)) {
+ status.cssClass = [status.isActive ? 'active' : null, status.isOverlay ? 'overlay' : null].filterJoin(' ');
+ }
+ return choices;
+ }
+}
diff --git a/module/data/settings/Appearance.mjs b/module/data/settings/Appearance.mjs
index 8b04f558..d8b4c687 100644
--- a/module/data/settings/Appearance.mjs
+++ b/module/data/settings/Appearance.mjs
@@ -40,6 +40,10 @@ export default class DhAppearance extends foundry.abstract.DataModel {
outline: new fields.ColorField({ required: true, initial: '#ffffff' }),
edge: new fields.ColorField({ required: true, initial: '#000000' })
})
+ }),
+ showGenericStatusEffects: new fields.BooleanField({
+ initial: true,
+ label: 'DAGGERHEART.SETTINGS.Appearance.FIELDS.showGenericStatusEffects.label'
})
};
}
diff --git a/styles/daggerheart.less b/styles/daggerheart.less
index 86b504b2..a48131c3 100755
--- a/styles/daggerheart.less
+++ b/styles/daggerheart.less
@@ -3,6 +3,8 @@
@import './less/dialog/index.less';
+@import './less//hud/index.less';
+
@import './less/utils/colors.less';
@import './less/utils/fonts.less';
diff --git a/styles/less/hud/index.less b/styles/less/hud/index.less
new file mode 100644
index 00000000..459f8fd7
--- /dev/null
+++ b/styles/less/hud/index.less
@@ -0,0 +1 @@
+@import './token-hud/token-hud.less';
diff --git a/styles/less/hud/token-hud/token-hud.less b/styles/less/hud/token-hud/token-hud.less
new file mode 100644
index 00000000..7d231e8c
--- /dev/null
+++ b/styles/less/hud/token-hud/token-hud.less
@@ -0,0 +1,10 @@
+.daggerheart.placeable-hud {
+ .col.right {
+ .palette {
+ .palette-category-title {
+ grid-column: span var(--effect-columns);
+ font-weight: bold;
+ }
+ }
+ }
+}
diff --git a/templates/hud/tokenHUD.hbs b/templates/hud/tokenHUD.hbs
new file mode 100644
index 00000000..58d13267
--- /dev/null
+++ b/templates/hud/tokenHUD.hbs
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+ {{#if canConfigure}}
+
+ {{/if}}
+
+
+
+
+
+ {{#if isGM}}
+
+ {{/if}}
+
+
+
+ {{#each systemStatusEffects as |status|}}
+

+ {{/each}}
+ {{#if genericStatusEffects}}
+
+ {{#each genericStatusEffects as |status|}}
+

+ {{/each}}
+ {{/if}}
+
+
+
+
+
+
+
+ {{#if canToggleCombat}}
+
+ {{/if}}
+
diff --git a/templates/settings/appearance-settings.hbs b/templates/settings/appearance-settings.hbs
index 5aa6d28d..da435c75 100644
--- a/templates/settings/appearance-settings.hbs
+++ b/templates/settings/appearance-settings.hbs
@@ -1,5 +1,6 @@
{{formGroup settingFields.schema.fields.displayFear value=settingFields._source.displayFear localize=true}}
+ {{formGroup settingFields.schema.fields.showGenericStatusEffects value=settingFields._source.showGenericStatusEffects localize=true}}