From 3a117ef117f9de1d712076eae5235023c550477d Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Fri, 3 Apr 2026 23:32:30 +0200
Subject: [PATCH 1/4] Added evasion to party resources (#1771)
---
.../less/sheets/actors/party/resources.less | 20 +++++++++++++++++++
system.json | 2 +-
templates/sheets/actors/party/resources.hbs | 6 ++++++
3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/styles/less/sheets/actors/party/resources.less b/styles/less/sheets/actors/party/resources.less
index 4db254bf..68628295 100644
--- a/styles/less/sheets/actors/party/resources.less
+++ b/styles/less/sheets/actors/party/resources.less
@@ -155,6 +155,26 @@ body.game:is(.performance-low, .noblur) {
}
}
+ .stat-section {
+ position: relative;
+ display: flex;
+ gap: 10px;
+ background-color: light-dark(transparent, @dark-blue);
+ color: light-dark(@dark-blue, @golden);
+ padding: 5px 10px;
+ border: 1px solid light-dark(@dark-blue, @golden);
+ border-radius: 3px;
+ align-items: center;
+ width: fit-content;
+
+ h4 {
+ font-size: var(--font-size-12);
+ font-weight: bold;
+ text-transform: uppercase;
+ color: light-dark(@dark-blue, @golden);
+ }
+ }
+
.threshold-section {
display: flex;
align-self: center;
diff --git a/system.json b/system.json
index ea71aaba..78355364 100644
--- a/system.json
+++ b/system.json
@@ -2,7 +2,7 @@
"id": "daggerheart",
"title": "Daggerheart",
"description": "An unofficial implementation of the Daggerheart system",
- "version": "2.0.1",
+ "version": "2.0.2",
"compatibility": {
"minimum": "14.359",
"verified": "14.359",
diff --git a/templates/sheets/actors/party/resources.hbs b/templates/sheets/actors/party/resources.hbs
index bfbfb578..b53282ca 100644
--- a/templates/sheets/actors/party/resources.hbs
+++ b/templates/sheets/actors/party/resources.hbs
@@ -87,6 +87,12 @@
{{/unless}}
+ {{#if (eq actor.type 'character')}}
+
+
{{localize "DAGGERHEART.GENERAL.evasion"}}: {{actor.system.evasion}}
+
+ {{/if}}
+
{{#unless (eq actor.type 'companion')}}
{{localize "DAGGERHEART.GENERAL.DamageThresholds.minor"}}
From f91c140d34eaf8da276e14f29d1456666edfed18 Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Sat, 4 Apr 2026 11:48:41 +0200
Subject: [PATCH 2/4] Fixed so that multi term expressions get evaluated into a
single number (#1772)
---
module/data/activeEffect/changeTypes/armor.mjs | 3 ++-
system.json | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/module/data/activeEffect/changeTypes/armor.mjs b/module/data/activeEffect/changeTypes/armor.mjs
index f400d41b..713ef03d 100644
--- a/module/data/activeEffect/changeTypes/armor.mjs
+++ b/module/data/activeEffect/changeTypes/armor.mjs
@@ -44,7 +44,8 @@ export default class ArmorChange extends foundry.abstract.DataModel {
label: 'Armor',
defaultPriority: 20,
handler: (actor, change, _options, _field, replacementData) => {
- const parsedMax = itemAbleRollParse(change.value.max, actor, change.effect.parent);
+ const baseParsedMax = itemAbleRollParse(change.value.max, actor, change.effect.parent);
+ const parsedMax = new Roll(baseParsedMax).evaluateSync().total;
game.system.api.documents.DhActiveEffect.applyChange(
actor,
{
diff --git a/system.json b/system.json
index 78355364..63dc33c2 100644
--- a/system.json
+++ b/system.json
@@ -2,7 +2,7 @@
"id": "daggerheart",
"title": "Daggerheart",
"description": "An unofficial implementation of the Daggerheart system",
- "version": "2.0.2",
+ "version": "2.0.3",
"compatibility": {
"minimum": "14.359",
"verified": "14.359",
From 331f1ebf75a2221beaec7985f47dc642aeef8fa7 Mon Sep 17 00:00:00 2001
From: WBHarry
Date: Sat, 4 Apr 2026 12:42:50 +0200
Subject: [PATCH 3/4] Fixed prose-mirror width
---
styles/less/global/prose-mirror.less | 1 +
1 file changed, 1 insertion(+)
diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less
index 506fb8b7..3523dc89 100644
--- a/styles/less/global/prose-mirror.less
+++ b/styles/less/global/prose-mirror.less
@@ -4,6 +4,7 @@
.application.daggerheart {
prose-mirror {
height: 100% !important;
+ width: 100%;
.editor-menu {
background-color: transparent;
From 7057504a9eb3684b268617cf6e6ea73b699f659c Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Sat, 4 Apr 2026 13:01:24 +0200
Subject: [PATCH 4/4] Fixes (#1774)
---
module/dice/dhRoll.mjs | 6 +++---
module/dice/die/_module.mjs | 4 ++++
module/dice/die/dualityDie.mjs | 14 +++++++++++---
module/dice/die/fearDie.mjs | 9 +++++++++
module/dice/die/hopeDie.mjs | 9 +++++++++
module/dice/dualityRoll.mjs | 20 ++++++++++----------
6 files changed, 46 insertions(+), 16 deletions(-)
create mode 100644 module/dice/die/fearDie.mjs
create mode 100644 module/dice/die/hopeDie.mjs
diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs
index e4a34bd4..aa4dd75f 100644
--- a/module/dice/dhRoll.mjs
+++ b/module/dice/dhRoll.mjs
@@ -246,7 +246,7 @@ export default class DHRoll extends Roll {
return (this._formula = this.constructor.getFormula(this.terms));
}
- /**
+ /**
* Calculate total modifiers of any rolls, including non-dh rolls.
* This exists because damage rolls still may receive base roll classes
*/
@@ -256,7 +256,7 @@ export default class DHRoll extends Roll {
if (!roll.terms[i].isDeterministic) continue;
const termTotal = roll.terms[i].total;
if (typeof termTotal === 'number') {
- const multiplier = roll.terms[i - 1]?.operator === " - " ? -1 : 1;
+ const multiplier = roll.terms[i - 1]?.operator === ' - ' ? -1 : 1;
modifierTotal += multiplier * termTotal;
}
}
@@ -272,7 +272,7 @@ export default class DHRoll extends Roll {
const changeKeys = this.getActionChangeKeys();
return (
this.options.effects?.reduce((acc, effect) => {
- if (effect.system.changes.some(x => changeKeys.some(key => x.key.includes(key)))) {
+ if (effect.system.changes.some(x => changeKeys.some(key => x.key?.includes(key)))) {
acc[effect.id] = {
id: effect.id,
name: effect.name,
diff --git a/module/dice/die/_module.mjs b/module/dice/die/_module.mjs
index ed892f6a..19ca951a 100644
--- a/module/dice/die/_module.mjs
+++ b/module/dice/die/_module.mjs
@@ -1,9 +1,13 @@
import DualityDie from './dualityDie.mjs';
+import HopeDie from './hopeDie.mjs';
+import FearDie from './fearDie.mjs';
import AdvantageDie from './advantageDie.mjs';
import DisadvantageDie from './disadvantageDie.mjs';
export const diceTypes = {
DualityDie,
+ HopeDie,
+ FearDie,
AdvantageDie,
DisadvantageDie
};
diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs
index e9deb77f..83229425 100644
--- a/module/dice/die/dualityDie.mjs
+++ b/module/dice/die/dualityDie.mjs
@@ -43,9 +43,10 @@ export default class DualityDie extends foundry.dice.terms.Die {
options: { appearance: {} }
};
- const preset = await getDiceSoNicePreset(diceSoNice[key], faces);
- diceSoNiceRoll.dice[0].options.appearance = preset.appearance;
- diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile;
+ const diceAppearance = await this.getDiceSoNiceAppearance(options.liveRoll.roll);
+ diceSoNiceRoll.dice[0].options.appearance = diceAppearance.appearance;
+ diceSoNiceRoll.dice[0].options.modelFile = diceAppearance.modelFile;
+ diceSoNiceRoll.dice[0].results = diceSoNiceRoll.dice[0].results.filter(x => x.active);
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
} else {
@@ -59,4 +60,11 @@ export default class DualityDie extends foundry.dice.terms.Die {
this.#updateResources(oldDuality, newDuality, options.liveRoll.actor);
}
}
+
+ /**
+ * Overridden by extending classes HopeDie and FearDie
+ */
+ async getDiceSoNiceAppearance() {
+ return {};
+ }
}
diff --git a/module/dice/die/fearDie.mjs b/module/dice/die/fearDie.mjs
new file mode 100644
index 00000000..2a09d432
--- /dev/null
+++ b/module/dice/die/fearDie.mjs
@@ -0,0 +1,9 @@
+import { getDiceSoNicePresets } from '../../config/generalConfig.mjs';
+import DualityDie from './dualityDie.mjs';
+
+export default class FearDie extends DualityDie {
+ async getDiceSoNiceAppearance(roll) {
+ const { fear } = await getDiceSoNicePresets(roll, this.denomination, this.denomination);
+ return fear;
+ }
+}
diff --git a/module/dice/die/hopeDie.mjs b/module/dice/die/hopeDie.mjs
new file mode 100644
index 00000000..af5a4425
--- /dev/null
+++ b/module/dice/die/hopeDie.mjs
@@ -0,0 +1,9 @@
+import { getDiceSoNicePresets } from '../../config/generalConfig.mjs';
+import DualityDie from './dualityDie.mjs';
+
+export default class HopeDie extends DualityDie {
+ async getDiceSoNiceAppearance(roll) {
+ const { hope } = await getDiceSoNicePresets(roll, this.denomination, this.denomination);
+ return hope;
+ }
+}
diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs
index bc381f07..f9a06d37 100644
--- a/module/dice/dualityRoll.mjs
+++ b/module/dice/dualityRoll.mjs
@@ -24,7 +24,7 @@ export default class DualityRoll extends D20Roll {
}
get dHope() {
- if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice();
+ if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie)) this.createBaseDice();
return this.dice[0];
}
@@ -34,7 +34,7 @@ export default class DualityRoll extends D20Roll {
}
get dFear() {
- if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice();
+ if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie)) this.createBaseDice();
return this.dice[1];
}
@@ -68,8 +68,8 @@ export default class DualityRoll extends D20Roll {
}
get extraDice() {
- const { DualityDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes;
- return this.dice.filter(x => ![DualityDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die));
+ const { HopeDie, FearDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes;
+ return this.dice.filter(x => ![HopeDie, FearDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die));
}
setRallyChoices() {
@@ -125,8 +125,8 @@ export default class DualityRoll extends D20Roll {
/** @inheritDoc */
static fromData(data) {
- data.terms[0].class = 'DualityDie';
- data.terms[2].class = 'DualityDie';
+ data.terms[0].class = 'HopeDie';
+ data.terms[2].class = 'FearDie';
if (data.options.roll.advantage?.type && data.terms[4]?.faces) {
data.terms[4].class = data.options.roll.advantage.type === 1 ? 'AdvantageDie' : 'DisadvantageDie';
}
@@ -135,18 +135,18 @@ export default class DualityRoll extends D20Roll {
createBaseDice() {
if (
- this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie &&
- this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie
+ this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie &&
+ this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie
) {
this.terms = [this.terms[0], this.terms[1], this.terms[2]];
return;
}
- this.terms[0] = new game.system.api.dice.diceTypes.DualityDie({
+ this.terms[0] = new game.system.api.dice.diceTypes.HopeDie({
faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12
});
this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' });
- this.terms[2] = new game.system.api.dice.diceTypes.DualityDie({
+ this.terms[2] = new game.system.api.dice.diceTypes.FearDie({
faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12
});
}