From 86d451f0d722665a030da4b23734007f0b0a09ba Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Sat, 23 Aug 2025 01:55:18 +0200
Subject: [PATCH 01/22] . (#1060)
---
module/documents/activeEffect.mjs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs
index f46cc9db..b2896513 100644
--- a/module/documents/activeEffect.mjs
+++ b/module/documents/activeEffect.mjs
@@ -167,13 +167,11 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
if (subclass) {
const featureState = subclass.system.featureState;
- const featureType = subclass
- ? (subclass.system.features.find(x => x.item?.uuid === this.parent.uuid)?.type ?? null)
- : null;
if (
- (featureType === CONFIG.DH.ITEM.featureSubTypes.specialization && featureState < 2) ||
- (featureType === CONFIG.DH.ITEM.featureSubTypes.mastery && featureState < 3)
+ (this.parent.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization &&
+ featureState < 2) ||
+ (this.parent.system.identifier === CONFIG.DH.ITEM.featureSubTypes.mastery && featureState < 3)
) {
this.transfer = false;
}
From 7016f71da7b810eb34a7ef32a333ead69e9c7159 Mon Sep 17 00:00:00 2001
From: Dapoulp <74197441+Dapoulp@users.noreply.github.com>
Date: Sat, 23 Aug 2025 02:05:16 +0200
Subject: [PATCH 02/22] Fix/spellcast modifier (#1061)
* Temp ActionField attack type missing
* Move missing attack type to getModel
* Fix spellcast modifier bonus
---
module/data/action/baseAction.mjs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs
index 5d3f7721..2f5935da 100644
--- a/module/data/action/baseAction.mjs
+++ b/module/data/action/baseAction.mjs
@@ -172,7 +172,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
dialog: {
configure: hasRoll
},
- type: this.type,
+ type: this.roll?.type ?? this.type,
hasRoll: hasRoll,
hasDamage: this.damage?.parts?.length && this.type !== 'healing',
hasHealing: this.damage?.parts?.length && this.type === 'healing',
From d5f7e17339dd0b24490be12064fe06f4fbebdf1c Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Sat, 23 Aug 2025 02:18:25 +0200
Subject: [PATCH 03/22] Added Custom Adversary Types (#1048)
---
lang/en.json | 7 ++-
.../settings/homebrewSettings.mjs | 54 +++++++++++++++++--
.../applications/sheets/actors/adversary.mjs | 4 ++
module/config/actorConfig.mjs | 5 ++
module/data/actor/adversary.mjs | 2 +-
module/data/settings/Homebrew.mjs | 7 +++
styles/less/ui/index.less | 1 +
.../ui/settings/homebrew-settings/types.less | 52 ++++++++++++++++++
.../settings/homebrew-settings/types.hbs | 28 ++++++++++
templates/sheets/actors/adversary/header.hbs | 4 +-
templates/ui/tooltip/adversary.hbs | 2 +-
11 files changed, 156 insertions(+), 10 deletions(-)
create mode 100644 styles/less/ui/settings/homebrew-settings/types.less
create mode 100644 templates/settings/homebrew-settings/types.hbs
diff --git a/lang/en.json b/lang/en.json
index 1bddbad3..1c614fc2 100755
--- a/lang/en.json
+++ b/lang/en.json
@@ -1900,7 +1900,8 @@
"tier4": "tier 4",
"domains": "Domains",
"downtime": "Downtime",
- "rules": "Rules"
+ "rules": "Rules",
+ "types": "Types"
},
"Tiers": {
"singular": "Tier",
@@ -2230,6 +2231,10 @@
"deleteDomain": "Delete Domain",
"deleteDomainText": "Are you sure you want to delete the {name} domain? It will be immediately removed from all Actors in this world where it's currently used. Compendiums are not cleared.",
"duplicateDomain": "There is already a domain with this identification."
+ },
+ "adversaryType": {
+ "title": "Custom Adversary Types",
+ "newType": "Adversary Type"
}
},
"Menu": {
diff --git a/module/applications/settings/homebrewSettings.mjs b/module/applications/settings/homebrewSettings.mjs
index 3fa42afd..c2ac4a89 100644
--- a/module/applications/settings/homebrewSettings.mjs
+++ b/module/applications/settings/homebrewSettings.mjs
@@ -1,5 +1,6 @@
import { DhHomebrew } from '../../data/settings/_module.mjs';
import { slugify } from '../../helpers/utils.mjs';
+
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhHomebrewSettings extends HandlebarsApplicationMixin(ApplicationV2) {
@@ -10,11 +11,14 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).toObject()
);
- this.selected = {
- domain: null
- };
+ this.selected = this.#getDefaultAdversaryType();
}
+ #getDefaultAdversaryType = () => ({
+ domain: null,
+ adversaryType: null
+ });
+
get title() {
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
}
@@ -35,6 +39,9 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
addDomain: this.addDomain,
toggleSelectedDomain: this.toggleSelectedDomain,
deleteDomain: this.deleteDomain,
+ addAdversaryType: this.addAdversaryType,
+ deleteAdversaryType: this.deleteAdversaryType,
+ selectAdversaryType: this.selectAdversaryType,
save: this.save,
reset: this.reset
},
@@ -45,6 +52,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
settings: { template: 'systems/daggerheart/templates/settings/homebrew-settings/settings.hbs' },
domains: { template: 'systems/daggerheart/templates/settings/homebrew-settings/domains.hbs' },
+ types: { template: 'systems/daggerheart/templates/settings/homebrew-settings/types.hbs' },
downtime: { template: 'systems/daggerheart/templates/settings/homebrew-settings/downtime.hbs' },
footer: { template: 'systems/daggerheart/templates/settings/homebrew-settings/footer.hbs' }
};
@@ -52,12 +60,19 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
/** @inheritdoc */
static TABS = {
main: {
- tabs: [{ id: 'settings' }, { id: 'domains' }, { id: 'downtime' }],
+ tabs: [{ id: 'settings' }, { id: 'domains' }, { id: 'types' }, { id: 'downtime' }],
initial: 'settings',
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
}
};
+ changeTab(tab, group, options) {
+ super.changeTab(tab, group, options);
+ this.selected = this.#getDefaultAdversaryType();
+
+ this.render();
+ }
+
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.settingFields = this.settings;
@@ -79,6 +94,11 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
context.configDomains = CONFIG.DH.DOMAIN.domains;
context.homebrewDomains = this.settings.domains;
break;
+ case 'types':
+ context.selectedAdversaryType = this.selected.adversaryType
+ ? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
+ : null;
+ break;
}
return context;
@@ -301,6 +321,32 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
this.render();
}
+ static async addAdversaryType(_, target) {
+ const newId = foundry.utils.randomID();
+ await this.settings.updateSource({
+ [`adversaryTypes.${newId}`]: {
+ id: newId,
+ label: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.adversaryType.newType')
+ }
+ });
+
+ this.selected.adversaryType = newId;
+ this.render();
+ }
+
+ static async deleteAdversaryType(_, target) {
+ const { key } = target.dataset;
+ await this.settings.updateSource({ [`adversaryTypes.-=${key}`]: null });
+
+ this.selected.adversaryType = this.selected.adversaryType === key ? null : this.selected.adversaryType;
+ this.render();
+ }
+
+ static async selectAdversaryType(_, target) {
+ this.selected.adversaryType = this.selected.adversaryType === target.dataset.type ? null : target.dataset.type;
+ this.render();
+ }
+
static async save() {
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
this.close();
diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs
index b47cb85a..f575a2f2 100644
--- a/module/applications/sheets/actors/adversary.mjs
+++ b/module/applications/sheets/actors/adversary.mjs
@@ -56,6 +56,7 @@ export default class AdversarySheet extends DHBaseActorSheet {
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.systemFields.attack.fields = this.document.system.attack.schema.fields;
+
return context;
}
@@ -65,6 +66,9 @@ export default class AdversarySheet extends DHBaseActorSheet {
switch (partId) {
case 'header':
await this._prepareHeaderContext(context, options);
+
+ const adversaryTypes = CONFIG.DH.ACTOR.allAdversaryTypes();
+ context.adversaryType = game.i18n.localize(adversaryTypes[this.document.system.type].label);
break;
case 'notes':
await this._prepareNotesContext(context, options);
diff --git a/module/config/actorConfig.mjs b/module/config/actorConfig.mjs
index 6453cd78..55f03789 100644
--- a/module/config/actorConfig.mjs
+++ b/module/config/actorConfig.mjs
@@ -157,6 +157,11 @@ export const adversaryTypes = {
}
};
+export const allAdversaryTypes = () => ({
+ ...adversaryTypes,
+ ...game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).adversaryTypes
+});
+
export const environmentTypes = {
exploration: {
label: 'DAGGERHEART.CONFIG.EnvironmentType.exploration.label',
diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs
index 80bcb43e..ba0693f7 100644
--- a/module/data/actor/adversary.mjs
+++ b/module/data/actor/adversary.mjs
@@ -27,7 +27,7 @@ export default class DhpAdversary extends BaseDataActor {
}),
type: new fields.StringField({
required: true,
- choices: CONFIG.DH.ACTOR.adversaryTypes,
+ choices: CONFIG.DH.ACTOR.allAdversaryTypes,
initial: CONFIG.DH.ACTOR.adversaryTypes.standard.id
}),
motivesAndTactics: new fields.StringField(),
diff --git a/module/data/settings/Homebrew.mjs b/module/data/settings/Homebrew.mjs
index e18fee39..0719b085 100644
--- a/module/data/settings/Homebrew.mjs
+++ b/module/data/settings/Homebrew.mjs
@@ -108,6 +108,13 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
}),
description: new fields.HTMLField()
})
+ ),
+ adversaryTypes: new fields.TypedObjectField(
+ new fields.SchemaField({
+ id: new fields.StringField({ required: true }),
+ label: new fields.StringField({ required: true, label: 'DAGGERHEART.GENERAL.label' }),
+ description: new fields.StringField()
+ })
)
};
}
diff --git a/styles/less/ui/index.less b/styles/less/ui/index.less
index 4a93feb6..49d1e009 100644
--- a/styles/less/ui/index.less
+++ b/styles/less/ui/index.less
@@ -21,3 +21,4 @@
@import './settings/settings.less';
@import './settings/homebrew-settings/domains.less';
+@import './settings/homebrew-settings/types.less';
diff --git a/styles/less/ui/settings/homebrew-settings/types.less b/styles/less/ui/settings/homebrew-settings/types.less
new file mode 100644
index 00000000..d09431f7
--- /dev/null
+++ b/styles/less/ui/settings/homebrew-settings/types.less
@@ -0,0 +1,52 @@
+.theme-light .daggerheart.dh-style.setting.homebrew-settings .types.tab {
+ .adversary-types-container .adversary-type-container {
+ background-image: url('../assets/parchments/dh-parchment-light.png');
+ }
+}
+
+.daggerheart.dh-style.setting.homebrew-settings {
+ .types.tab {
+ .adversary-types-container {
+ width: 100%;
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ gap: 4px;
+
+ .adversary-type-container {
+ height: 2em;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ border: 1px solid;
+ border-radius: 6px;
+ padding: 0 8px;
+ border: 1px solid light-dark(@dark-blue, @golden);
+ color: light-dark(@dark, @beige);
+ background-image: url('../assets/parchments/dh-parchment-dark.png');
+ cursor: pointer;
+ opacity: 0.6;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ &.active {
+ opacity: 1;
+ background: var(--color-warm-2);
+ }
+ }
+ }
+
+ .type-edit-container {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ textarea {
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/templates/settings/homebrew-settings/types.hbs b/templates/settings/homebrew-settings/types.hbs
new file mode 100644
index 00000000..f9d3bba3
--- /dev/null
+++ b/templates/settings/homebrew-settings/types.hbs
@@ -0,0 +1,28 @@
+
+
+
\ No newline at end of file
diff --git a/templates/sheets/actors/adversary/header.hbs b/templates/sheets/actors/adversary/header.hbs
index 8411dd93..e6f829b8 100644
--- a/templates/sheets/actors/adversary/header.hbs
+++ b/templates/sheets/actors/adversary/header.hbs
@@ -13,9 +13,7 @@
-
- {{localize (concat 'DAGGERHEART.CONFIG.AdversaryType.' source.system.type '.label')}}
-
+ {{adversaryType}}
{{#if (eq source.system.type 'horde')}}
diff --git a/templates/ui/tooltip/adversary.hbs b/templates/ui/tooltip/adversary.hbs
index b400bd29..86c399c5 100644
--- a/templates/ui/tooltip/adversary.hbs
+++ b/templates/ui/tooltip/adversary.hbs
@@ -12,7 +12,7 @@
From b83adbf09ba0b427d1c0db739c57e102f800bf30 Mon Sep 17 00:00:00 2001
From: Chris Ryan <73275196+chrisryan10@users.noreply.github.com>
Date: Sat, 23 Aug 2025 18:32:17 +1000
Subject: [PATCH 04/22] Fixed the Cult Initiate Group Attack to use Fear
instead of marking Stress (#1062)
Co-authored-by: Chris Ryan
---
.../adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json b/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json
index fe8d090f..b46dc3a0 100644
--- a/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json
+++ b/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json
@@ -265,7 +265,7 @@
"cost": [
{
"scalable": false,
- "key": "stress",
+ "key": "fear",
"value": 1,
"keyIsID": false,
"step": null
@@ -281,7 +281,7 @@
"type": "self",
"amount": null
},
- "name": "Mark Stress",
+ "name": "Spend Fear",
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
"range": ""
}
From 2d20fb0df447ba50fbe8b545f6f0a6c736489407 Mon Sep 17 00:00:00 2001
From: WBHarry
Date: Sat, 23 Aug 2025 13:18:14 +0200
Subject: [PATCH 05/22] Fixed multiclass
---
module/data/actor/character.mjs | 5 +++--
module/data/item/base.mjs | 4 ++--
module/data/item/class.mjs | 9 ---------
module/data/item/feature.mjs | 1 +
module/documents/actor.mjs | 4 ++--
5 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs
index 7dd7993c..7ddd878c 100644
--- a/module/data/actor/character.mjs
+++ b/module/data/actor/character.mjs
@@ -317,7 +317,7 @@ export default class DhCharacter extends BaseDataActor {
}
get multiclass() {
- const value = this.parent.items.find(x => x.type === 'Class' && x.system.isMulticlass);
+ const value = this.parent.items.find(x => x.type === 'class' && x.system.isMulticlass);
const subclass = this.parent.items.find(x => x.type === 'subclass' && x.system.isMulticlass);
return {
@@ -443,7 +443,8 @@ export default class DhCharacter extends BaseDataActor {
classFeatures.push(item);
} else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.subclass.id) {
if (this.class.subclass) {
- const subclassState = this.class.subclass.system.featureState;
+ const prop = item.system.multiclassOrigin ? 'multiclass' : 'class';
+ const subclassState = this[prop].subclass.system.featureState;
if (
item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.foundation ||
diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs
index f333537b..f8eae265 100644
--- a/module/data/item/base.mjs
+++ b/module/data/item/base.mjs
@@ -148,7 +148,6 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
for (let f of this.features) {
const fBase = f.item ?? f;
const feature = fBase.system ? fBase : await foundry.utils.fromUuid(fBase.uuid);
- const multiclass = this.isMulticlass ? 'multiclass' : null;
features.push(
foundry.utils.mergeObject(
feature.toObject(),
@@ -156,7 +155,8 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
_stats: { compendiumSource: fBase.uuid },
system: {
originItemType: this.parent.type,
- identifier: multiclass ?? (f.item ? f.type : null)
+ identifier: f.item ? f.type : null,
+ multiclassOrigin: this.isMulticlass
}
},
{ inplace: false }
diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs
index 5e92d2fc..157f70c5 100644
--- a/module/data/item/class.mjs
+++ b/module/data/item/class.mjs
@@ -102,15 +102,6 @@ export default class DHClass extends BaseDataItem {
if (allowed === false) return;
}
- _onDelete(options, userId) {
- super._onDelete(options, userId);
-
- if (options.parent?.type === 'character') {
- const path = `system.${this.isMulticlass ? 'multiclass' : 'class'}`;
- foundry.utils.getProperty(options.parent, `${path}.subclass`)?.delete();
- }
- }
-
async _preUpdate(changed, options, userId) {
const allowed = await super._preUpdate(changed, options, userId);
if (allowed === false) return false;
diff --git a/module/data/item/feature.mjs b/module/data/item/feature.mjs
index 6e1aab41..3b8fe064 100644
--- a/module/data/item/feature.mjs
+++ b/module/data/item/feature.mjs
@@ -29,6 +29,7 @@ export default class DHFeature extends BaseDataItem {
nullable: true,
initial: null
}),
+ multiclassOrigin: new fields.BooleanField({ initial: false }),
identifier: new fields.StringField()
};
}
diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs
index e1dd93af..3325547c 100644
--- a/module/documents/actor.mjs
+++ b/module/documents/actor.mjs
@@ -164,10 +164,10 @@ export default class DhpActor extends Actor {
if (multiclass) {
const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid);
const multiclassFeatures = this.items.filter(
- x => x.system.originItemType === 'class' && x.system.identifier === 'multiclass'
+ x => x.system.originItemType === 'class' && x.system.multiclassOrigin
);
const subclassFeatures = this.items.filter(
- x => x.system.originItemType === 'subclass' && x.system.identifier === 'multiclass'
+ x => x.system.originItemType === 'subclass' && x.system.multiclassOrigin
);
this.deleteEmbeddedDocuments(
From f76515eac1dddc2fca6c5f34ad574ed174089bb4 Mon Sep 17 00:00:00 2001
From: WBHarry
Date: Sat, 23 Aug 2025 13:20:02 +0200
Subject: [PATCH 06/22] Revert "Fixed multiclass"
This reverts commit 2d20fb0df447ba50fbe8b545f6f0a6c736489407.
---
module/data/actor/character.mjs | 5 ++---
module/data/item/base.mjs | 4 ++--
module/data/item/class.mjs | 9 +++++++++
module/data/item/feature.mjs | 1 -
module/documents/actor.mjs | 4 ++--
5 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs
index 7ddd878c..7dd7993c 100644
--- a/module/data/actor/character.mjs
+++ b/module/data/actor/character.mjs
@@ -317,7 +317,7 @@ export default class DhCharacter extends BaseDataActor {
}
get multiclass() {
- const value = this.parent.items.find(x => x.type === 'class' && x.system.isMulticlass);
+ const value = this.parent.items.find(x => x.type === 'Class' && x.system.isMulticlass);
const subclass = this.parent.items.find(x => x.type === 'subclass' && x.system.isMulticlass);
return {
@@ -443,8 +443,7 @@ export default class DhCharacter extends BaseDataActor {
classFeatures.push(item);
} else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.subclass.id) {
if (this.class.subclass) {
- const prop = item.system.multiclassOrigin ? 'multiclass' : 'class';
- const subclassState = this[prop].subclass.system.featureState;
+ const subclassState = this.class.subclass.system.featureState;
if (
item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.foundation ||
diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs
index f8eae265..f333537b 100644
--- a/module/data/item/base.mjs
+++ b/module/data/item/base.mjs
@@ -148,6 +148,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
for (let f of this.features) {
const fBase = f.item ?? f;
const feature = fBase.system ? fBase : await foundry.utils.fromUuid(fBase.uuid);
+ const multiclass = this.isMulticlass ? 'multiclass' : null;
features.push(
foundry.utils.mergeObject(
feature.toObject(),
@@ -155,8 +156,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
_stats: { compendiumSource: fBase.uuid },
system: {
originItemType: this.parent.type,
- identifier: f.item ? f.type : null,
- multiclassOrigin: this.isMulticlass
+ identifier: multiclass ?? (f.item ? f.type : null)
}
},
{ inplace: false }
diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs
index 157f70c5..5e92d2fc 100644
--- a/module/data/item/class.mjs
+++ b/module/data/item/class.mjs
@@ -102,6 +102,15 @@ export default class DHClass extends BaseDataItem {
if (allowed === false) return;
}
+ _onDelete(options, userId) {
+ super._onDelete(options, userId);
+
+ if (options.parent?.type === 'character') {
+ const path = `system.${this.isMulticlass ? 'multiclass' : 'class'}`;
+ foundry.utils.getProperty(options.parent, `${path}.subclass`)?.delete();
+ }
+ }
+
async _preUpdate(changed, options, userId) {
const allowed = await super._preUpdate(changed, options, userId);
if (allowed === false) return false;
diff --git a/module/data/item/feature.mjs b/module/data/item/feature.mjs
index 3b8fe064..6e1aab41 100644
--- a/module/data/item/feature.mjs
+++ b/module/data/item/feature.mjs
@@ -29,7 +29,6 @@ export default class DHFeature extends BaseDataItem {
nullable: true,
initial: null
}),
- multiclassOrigin: new fields.BooleanField({ initial: false }),
identifier: new fields.StringField()
};
}
diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs
index 3325547c..e1dd93af 100644
--- a/module/documents/actor.mjs
+++ b/module/documents/actor.mjs
@@ -164,10 +164,10 @@ export default class DhpActor extends Actor {
if (multiclass) {
const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid);
const multiclassFeatures = this.items.filter(
- x => x.system.originItemType === 'class' && x.system.multiclassOrigin
+ x => x.system.originItemType === 'class' && x.system.identifier === 'multiclass'
);
const subclassFeatures = this.items.filter(
- x => x.system.originItemType === 'subclass' && x.system.multiclassOrigin
+ x => x.system.originItemType === 'subclass' && x.system.identifier === 'multiclass'
);
this.deleteEmbeddedDocuments(
From 471cbd55df7aaf53430846b890848c33ffba84c9 Mon Sep 17 00:00:00 2001
From: Chris Ryan <73275196+chrisryan10@users.noreply.github.com>
Date: Sat, 23 Aug 2025 21:24:28 +1000
Subject: [PATCH 07/22] Fixes some measurement issues with templates (#1065)
Co-authored-by: Chris Ryan
---
module/canvas/placeables/measuredTemplate.mjs | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/module/canvas/placeables/measuredTemplate.mjs b/module/canvas/placeables/measuredTemplate.mjs
index 49142685..83cddfe1 100644
--- a/module/canvas/placeables/measuredTemplate.mjs
+++ b/module/canvas/placeables/measuredTemplate.mjs
@@ -10,38 +10,38 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur
const splitRulerText = this.ruler.text.split(' ');
if (splitRulerText.length > 0) {
const rulerValue = Number(splitRulerText[0]);
- const result = this.constructor.getRangeLabels(rulerValue, rangeMeasurementSettings);
- this.ruler.text = result.distance + result.units ? (' ' + result.units) : '';
+ const result = DhMeasuredTemplate.getRangeLabels(rulerValue, rangeMeasurementSettings);
+ this.ruler.text = result.distance + (result.units ? (' ' + result.units) : '');
}
}
}
- static getRangeLabels(distance, settings) {
- let result = { distance: '', units: null }
+ static getRangeLabels(distanceValue, settings) {
+ let result = { distance: distanceValue, units: '' }
const rangeMeasurementOverride = canvas.scene.flags.daggerheart?.rangeMeasurementOverride;
if (rangeMeasurementOverride === true) {
- result.distance = distance;
+ result.distance = distanceValue;
result.units = canvas.scene?.grid?.units;
return result
}
- if (distance <= settings.melee) {
+ if (distanceValue <= settings.melee) {
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.melee.name');
return result;
}
- if (distance <= settings.veryClose) {
+ if (distanceValue <= settings.veryClose) {
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.veryClose.name');
return result;
}
- if (distance <= settings.close) {
+ if (distanceValue <= settings.close) {
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.close.name');
return result;
}
- if (distance <= settings.far) {
+ if (distanceValue <= settings.far) {
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.far.name');
return result;
}
- if (distance > settings.far) {
+ if (distanceValue > settings.far) {
result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.veryFar.name');
}
From 936c96a1bed04e9de4254bcd317fc6d8403cbbc3 Mon Sep 17 00:00:00 2001
From: WBHarry <89362246+WBHarry@users.noreply.github.com>
Date: Sat, 23 Aug 2025 13:49:10 +0200
Subject: [PATCH 08/22] Fixed so enriched buttons are inline by default. Can be
set to 'inline:true' to make them fit with the text better (#1068)
---
module/enrichers/DamageEnricher.mjs | 12 ++++++++----
module/enrichers/DualityRollEnricher.mjs | 2 +-
module/enrichers/TemplateEnricher.mjs | 8 ++++++--
styles/less/global/enrichment.less | 14 ++++++++++++++
styles/less/global/index.less | 1 +
5 files changed, 30 insertions(+), 7 deletions(-)
create mode 100644 styles/less/global/enrichment.less
diff --git a/module/enrichers/DamageEnricher.mjs b/module/enrichers/DamageEnricher.mjs
index 918edc39..a859be9f 100644
--- a/module/enrichers/DamageEnricher.mjs
+++ b/module/enrichers/DamageEnricher.mjs
@@ -2,7 +2,8 @@ export default function DhDamageEnricher(match, _options) {
const parts = match[1].split('|').map(x => x.trim());
let value = null,
- type = null;
+ type = null,
+ inline = false;
parts.forEach(part => {
const split = part.split(':').map(x => x.toLowerCase().trim());
@@ -14,16 +15,19 @@ export default function DhDamageEnricher(match, _options) {
case 'type':
type = split[1];
break;
+ case 'inline':
+ inline = true;
+ break;
}
}
});
if (!value || !value) return match[0];
- return getDamageMessage(value, type, match[0]);
+ return getDamageMessage(value, type, inline, match[0]);
}
-function getDamageMessage(damage, type, defaultElement) {
+function getDamageMessage(damage, type, inline, defaultElement) {
const typeIcons = type
.replace('[', '')
.replace(']', '')
@@ -40,7 +44,7 @@ function getDamageMessage(damage, type, defaultElement) {
const dualityElement = document.createElement('span');
dualityElement.innerHTML = `
-