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 @@ +
+
+ + {{localize "DAGGERHEART.SETTINGS.Homebrew.adversaryType.title"}} + + + +
+ {{#each settingFields.adversaryTypes as |type key|}} +
+ {{type.label}} +
+
+ {{/each}} +
+ + {{#if selectedAdversaryType}} +
+ {{formGroup settingFields.schema.fields.adversaryTypes.element.fields.label name=(concat "adversaryTypes." selectedAdversaryType.id ".label") value=selectedAdversaryType.label localize=true }} + +
+ {{/if}} +
+
\ 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 @@
- {{#with (lookup config.ACTOR.adversaryTypes item.system.type) as | type |}} + {{#with (lookup adversaryTypes item.system.type) as | type |}}
{{localize type.label}}
{{/with}}
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 = ` - `; diff --git a/styles/less/global/enrichment.less b/styles/less/global/enrichment.less new file mode 100644 index 00000000..2ad3975a --- /dev/null +++ b/styles/less/global/enrichment.less @@ -0,0 +1,14 @@ +.measured-template-button, +.enriched-damage-button, +.duality-roll-button { + display: inline; + + &.inline { + min-height: unset; + height: 18px; + } + + i { + font-size: 12px; + } +} diff --git a/styles/less/global/index.less b/styles/less/global/index.less index d6c8459e..5f955ce3 100644 --- a/styles/less/global/index.less +++ b/styles/less/global/index.less @@ -2,6 +2,7 @@ @import './dialog.less'; @import './chat.less'; @import './elements.less'; +@import './enrichment.less'; @import './tab-navigation.less'; @import './tab-form-footer.less'; @import './tab-actions.less'; From 0c3ebd6e11ed9ec57c5bbf4a04929609be055ee4 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 23 Aug 2025 13:55:31 +0200 Subject: [PATCH 09/22] Fixed description on Dracon and Orderborne (#1067) --- .../feature_Elemental_Breath_sRaE3CgkgjBF1UpV.json | 10 +++++----- .../feature_Dedicated_7aXWdH3gzaYREK0X.json | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/packs/ancestries/feature_Elemental_Breath_sRaE3CgkgjBF1UpV.json b/src/packs/ancestries/feature_Elemental_Breath_sRaE3CgkgjBF1UpV.json index ccd0f87e..9764c5b4 100644 --- a/src/packs/ancestries/feature_Elemental_Breath_sRaE3CgkgjBF1UpV.json +++ b/src/packs/ancestries/feature_Elemental_Breath_sRaE3CgkgjBF1UpV.json @@ -12,7 +12,7 @@ "type": "attack", "_id": "a6WROv0OKx0lbYVa", "systemPath": "actions", - "description": "", + "description": "

Choose an element for your breath (such as electricity, fire, or ice). You can use this breath against a target or group of targets within Very Close range, treating it as an Instinct weapon that deals d8 magic damage using your Proficiency.

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -95,12 +95,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1753994055921, - "modifiedTime": 1753994120065, - "lastModifiedBy": "MQSznptE5yLT7kj8" + "modifiedTime": 1755938895948, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!sRaE3CgkgjBF1UpV" } diff --git a/src/packs/communities/feature_Dedicated_7aXWdH3gzaYREK0X.json b/src/packs/communities/feature_Dedicated_7aXWdH3gzaYREK0X.json index c93811a9..11ac8208 100644 --- a/src/packs/communities/feature_Dedicated_7aXWdH3gzaYREK0X.json +++ b/src/packs/communities/feature_Dedicated_7aXWdH3gzaYREK0X.json @@ -12,7 +12,7 @@ "type": "effect", "_id": "ZBVqSlsDUKf8uGrI", "systemPath": "actions", - "description": "", + "description": "

Record three sayings or values your upbringing instilled in you. Once per rest, when you describe how you’re embodying one of these principles through your current action, you can roll a d20 as your Hope Die

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -41,12 +41,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754010247432, - "modifiedTime": 1754010247432, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755938935013, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "sort": 0, "ownership": { From a72d4583cd3167c72327f762a11b51bd2b0f0879 Mon Sep 17 00:00:00 2001 From: Dapoulp <74197441+Dapoulp@users.noreply.github.com> Date: Sat, 23 Aug 2025 14:54:57 +0200 Subject: [PATCH 10/22] [PR]Add custom formula to weapon base attack (#964) * Add custom formula to weapon base attack * Remove log * Update weapon custom damage formula label + update font-size in px --- lang/en.json | 9 ++++++ module/data/fields/action/damageField.mjs | 12 ++++---- module/data/item/weapon.mjs | 4 +-- styles/less/dialog/beastform/sheet.less | 4 +-- .../selections-container.less | 20 ++++++------- .../damage-reduction-container.less | 4 +-- .../less/dialog/dice-roll/roll-selection.less | 8 ++--- .../dialog/downtime/downtime-container.less | 6 ++-- .../dialog/level-up/selections-container.less | 8 ++--- .../dialog/level-up/summary-container.less | 6 ++-- .../less/dialog/level-up/tiers-container.less | 4 +-- styles/less/dialog/reroll-dialog/sheet.less | 6 ++-- styles/less/global/chat.less | 2 +- styles/less/global/dialog.less | 2 +- styles/less/global/elements.less | 18 ++++++------ styles/less/global/inventory-item.less | 29 ++++++++++--------- styles/less/global/item-header.less | 6 ++-- styles/less/global/prose-mirror.less | 8 ++--- .../character-settings/sheet.less | 2 +- styles/less/sheets-settings/header.less | 2 +- .../less/sheets/actors/adversary/header.less | 6 ++-- .../less/sheets/actors/adversary/sidebar.less | 12 ++++---- .../less/sheets/actors/character/header.less | 16 +++++----- .../sheets/actors/character/inventory.less | 2 +- .../less/sheets/actors/character/loadout.less | 2 +- .../less/sheets/actors/character/sidebar.less | 10 +++---- .../less/sheets/actors/companion/details.less | 6 ++-- .../less/sheets/actors/companion/header.less | 6 ++-- .../sheets/actors/environment/header.less | 8 ++--- styles/less/ui/chat/ability-use.less | 4 +-- styles/less/ui/chat/action.less | 4 +-- styles/less/ui/chat/chat.less | 4 +-- styles/less/ui/chat/downtime.less | 4 +-- .../less/ui/combat-sidebar/token-actions.less | 2 +- styles/less/ui/countdown/sheet.less | 2 +- styles/less/ui/item-browser/item-browser.less | 10 +++---- .../settings/homebrew-settings/domains.less | 4 +-- styles/less/ui/settings/settings.less | 6 ++-- styles/less/utils/mixin.less | 6 ++-- styles/less/ux/autocomplete/autocomplete.less | 4 +-- styles/less/ux/tooltip/tooltip.less | 2 +- templates/sheets/items/weapon/header.hbs | 6 +++- templates/sheets/items/weapon/settings.hbs | 15 +++++++--- 43 files changed, 161 insertions(+), 140 deletions(-) diff --git a/lang/en.json b/lang/en.json index 1c614fc2..beeffd41 100755 --- a/lang/en.json +++ b/lang/en.json @@ -72,6 +72,14 @@ "exactHint": "The Character's Tier is used if empty", "label": "Beastform" }, + "damage": { + "multiplier": "Multiplier", + "flatMultiplier": "Flat Multiplier" + }, + "general": { + "customFormula": "Custom Formula", + "formula": "Formula" + }, "displayInChat": "Display in chat" }, "RollField": { @@ -1929,6 +1937,7 @@ "continue": "Continue", "criticalSuccess": "Critical Success", "criticalShort": "Critical", + "custom": "Custom", "d20Roll": "D20 Roll", "damage": "Damage", "damageRoll": "Damage Roll", diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index cf327204..7f1b61e9 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -23,14 +23,14 @@ export class DHActionDiceData extends foundry.abstract.DataModel { multiplier: new fields.StringField({ choices: CONFIG.DH.GENERAL.multiplierTypes, initial: 'prof', - label: 'Multiplier' + label: "DAGGERHEART.ACTIONS.Config.damage.multiplier" }), - flatMultiplier: new fields.NumberField({ nullable: true, initial: 1, label: 'Flat Multiplier' }), - dice: new fields.StringField({ choices: CONFIG.DH.GENERAL.diceTypes, initial: 'd6', label: 'Dice' }), - bonus: new fields.NumberField({ nullable: true, initial: null, label: 'Bonus' }), + flatMultiplier: new fields.NumberField({ nullable: true, initial: 1, label: "DAGGERHEART.ACTIONS.Config.damage.flatMultiplier" }), + dice: new fields.StringField({ choices: CONFIG.DH.GENERAL.diceTypes, initial: 'd6', label: "DAGGERHEART.GENERAL.Dice.single" }), + bonus: new fields.NumberField({ nullable: true, initial: null, label: "DAGGERHEART.GENERAL.bonus" }), custom: new fields.SchemaField({ - enabled: new fields.BooleanField({ label: 'Custom Formula' }), - formula: new FormulaField({ label: 'Formula', initial: '' }) + enabled: new fields.BooleanField({ label: "DAGGERHEART.ACTIONS.Config.general.customFormula" }), + formula: new FormulaField({ label: "DAGGERHEART.ACTIONS.Config.general.formula", initial: '' }) }) }; } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 66025cc5..ee4b997c 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -199,8 +199,8 @@ export default class DHWeapon extends AttachableItem { ]; for (const { value, type } of attack.damage.parts) { - const parts = [value.dice]; - if (value.bonus) parts.push(value.bonus.signedString()); + const parts = value.custom.enabled ? [game.i18n.localize("DAGGERHEART.GENERAL.custom")] : [value.dice]; + if (!value.custom.enabled && value.bonus) parts.push(value.bonus.signedString()); if (type.size > 0) { const typeTags = Array.from(type) diff --git a/styles/less/dialog/beastform/sheet.less b/styles/less/dialog/beastform/sheet.less index c13ee95e..9e87f53b 100644 --- a/styles/less/dialog/beastform/sheet.less +++ b/styles/less/dialog/beastform/sheet.less @@ -41,7 +41,7 @@ display: flex; flex-wrap: wrap; text-align: center; - font-size: 16px; + font-size: var(--font-size-16); margin: 0 4px; border: 1px solid light-dark(@dark-blue, @golden); border-radius: 6px; @@ -135,7 +135,7 @@ align-items: center; i { - font-size: 24px; + font-size: var(--font-size-24); } } diff --git a/styles/less/dialog/character-creation/selections-container.less b/styles/less/dialog/character-creation/selections-container.less index bc7a6987..3b93313a 100644 --- a/styles/less/dialog/character-creation/selections-container.less +++ b/styles/less/dialog/character-creation/selections-container.less @@ -75,7 +75,7 @@ label { position: absolute; - font-size: 18px; + font-size: var(--font-size-18); font-weight: bold; padding: 0 2px; background-image: url(../assets/parchments/dh-parchment-light.png); @@ -141,7 +141,7 @@ .ancestry-preview-feature { flex: 1; - font-size: 14px; + font-size: var(--font-size-14); white-space: wrap; padding: 0 2px; border: 1px solid light-dark(@golden, @dark-blue); @@ -178,7 +178,7 @@ legend { margin-left: auto; margin-right: auto; - font-size: 28px; + font-size: var(--font-size-28); font-weight: bold; padding: 0 8px; } @@ -191,7 +191,7 @@ justify-content: center; legend { - font-size: 20px; + font-size: var(--font-size-20); white-space: nowrap; } @@ -343,7 +343,7 @@ border-radius: 50%; height: 20px; width: 20px; - font-size: 14px; + font-size: var(--font-size-14); display: flex; align-items: center; justify-content: center; @@ -358,7 +358,7 @@ .descriptor { position: absolute; bottom: -8px; - font-size: 12px; + font-size: var(--font-size-12); border-radius: 8px; width: 56px; text-align: center; @@ -400,7 +400,7 @@ legend { margin-left: auto; margin-right: auto; - font-size: 28px; + font-size: var(--font-size-28); font-weight: bold; padding: 0 8px; white-space: nowrap; @@ -444,7 +444,7 @@ label { position: absolute; top: -8px; - font-size: 12px; + font-size: var(--font-size-12); white-space: nowrap; border: 1px solid light-dark(@dark-blue, @golden); border-radius: 6px; @@ -472,7 +472,7 @@ legend { margin-left: auto; margin-right: auto; - font-size: 12px; + font-size: var(--font-size-12); } .suggestion-inner-container { @@ -490,7 +490,7 @@ label { position: absolute; top: -2px; - font-size: 12px; + font-size: var(--font-size-12); } img { diff --git a/styles/less/dialog/damage-reduction/damage-reduction-container.less b/styles/less/dialog/damage-reduction/damage-reduction-container.less index 9e1d1472..2f343fb3 100644 --- a/styles/less/dialog/damage-reduction/damage-reduction-container.less +++ b/styles/less/dialog/damage-reduction/damage-reduction-container.less @@ -76,7 +76,7 @@ border-radius: 6px; height: 26px; padding: 0 1px; - font-size: 18px; + font-size: var(--font-size-18); display: flex; align-items: center; justify-content: center; @@ -108,7 +108,7 @@ border-radius: 6px; height: 26px; padding: 0 4px; - font-size: 18px; + font-size: var(--font-size-18); display: flex; align-items: center; justify-content: center; diff --git a/styles/less/dialog/dice-roll/roll-selection.less b/styles/less/dialog/dice-roll/roll-selection.less index 9113bc03..a0ac42b6 100644 --- a/styles/less/dialog/dice-roll/roll-selection.less +++ b/styles/less/dialog/dice-roll/roll-selection.less @@ -23,7 +23,7 @@ width: auto; opacity: 0.3; border-radius: 50%; - font-size: 18px; + font-size: var(--font-size-18); font-weight: bold; &:hover { @@ -74,7 +74,7 @@ font-family: @font-subtitle; font-style: normal; font-weight: 700; - font-size: 16px; + font-size: var(--font-size-16); line-height: 19px; color: light-dark(@dark, @beige); @@ -102,7 +102,7 @@ .label { font-style: normal; font-weight: 400; - font-size: 14px; + font-size: var(--font-size-14); line-height: 17px; } @@ -127,7 +127,7 @@ .label { font-style: normal; font-weight: 400; - font-size: 14px; + font-size: var(--font-size-14); line-height: 17px; } diff --git a/styles/less/dialog/downtime/downtime-container.less b/styles/less/dialog/downtime/downtime-container.less index f9f8df17..16edd3b0 100644 --- a/styles/less/dialog/downtime/downtime-container.less +++ b/styles/less/dialog/downtime/downtime-container.less @@ -35,7 +35,7 @@ gap: 4px; .activity-marker { - font-size: 8px; + font-size: .5rem; flex: none; color: light-dark(@dark-blue, @golden); margin-right: 4px; @@ -54,7 +54,7 @@ } .activity-selected-marker { - font-size: 14px; + font-size: var(--font-size-14); border: 1px solid light-dark(@dark-blue, @golden); border-radius: 6px; color: light-dark(@dark, @beige); @@ -71,7 +71,7 @@ display: grid; grid-template-columns: 1fr 1fr; gap: 4px; - font-size: 12px; + font-size: var(--font-size-12); &.wide { grid-template-columns: 1fr 1fr 1fr 1fr; diff --git a/styles/less/dialog/level-up/selections-container.less b/styles/less/dialog/level-up/selections-container.less index 96cadd29..6a551865 100644 --- a/styles/less/dialog/level-up/selections-container.less +++ b/styles/less/dialog/level-up/selections-container.less @@ -21,7 +21,7 @@ background: light-dark(@dark-blue-40, @golden-40); border-radius: 3px; padding: 5px; - font-size: 16px; + font-size: var(--font-size-16); gap: 4px; width: 100%; @@ -38,7 +38,7 @@ display: flex; align-items: center; justify-content: center; - font-size: 12px; + font-size: var(--font-size-12); } } } @@ -96,7 +96,7 @@ width: 54px; border-radius: 50%; border: 2px solid; - font-size: 48px; + font-size: var(--font-size-48); display: flex; align-items: center; justify-content: center; @@ -133,7 +133,7 @@ .levelup-selections-title { margin-left: auto; margin-right: auto; - font-size: 22px; + font-size: 1.375rem; font-weight: bold; padding: 0 12px; } diff --git a/styles/less/dialog/level-up/summary-container.less b/styles/less/dialog/level-up/summary-container.less index f192d5ec..d67abff6 100644 --- a/styles/less/dialog/level-up/summary-container.less +++ b/styles/less/dialog/level-up/summary-container.less @@ -41,7 +41,7 @@ display: flex; align-items: center; gap: 4px; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); } @@ -49,7 +49,7 @@ display: flex; align-items: center; gap: 4px; - font-size: 16px; + font-size: var(--font-size-16); color: light-dark(@dark, @beige); margin-bottom: 5px; } @@ -62,7 +62,7 @@ border: 2px solid; border-radius: 3px; padding: 0 4px; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); } } diff --git a/styles/less/dialog/level-up/tiers-container.less b/styles/less/dialog/level-up/tiers-container.less index d4efa46b..270b9b80 100644 --- a/styles/less/dialog/level-up/tiers-container.less +++ b/styles/less/dialog/level-up/tiers-container.less @@ -21,7 +21,7 @@ legend { margin-left: auto; margin-right: auto; - font-size: 22px; + font-size: 1.375rem; font-weight: bold; padding: 0 12px; } @@ -60,7 +60,7 @@ } .checkbox-group-label { - font-size: 12px; + font-size: var(--font-size-12); font-style: italic; } } diff --git a/styles/less/dialog/reroll-dialog/sheet.less b/styles/less/dialog/reroll-dialog/sheet.less index f8687009..71c94d80 100644 --- a/styles/less/dialog/reroll-dialog/sheet.less +++ b/styles/less/dialog/reroll-dialog/sheet.less @@ -37,7 +37,7 @@ display: flex; align-items: center; justify-content: center; - font-size: 22px; + font-size: 1.375rem; opacity: 0.8; &.selected { @@ -99,12 +99,12 @@ &:before, &:after { line-height: 12px; - font-size: 12px; + font-size: var(--font-size-12); } } i { - font-size: 10px; + font-size: var(--font-size-10); } } } diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less index bf29a05c..d2822b1b 100644 --- a/styles/less/global/chat.less +++ b/styles/less/global/chat.less @@ -71,7 +71,7 @@ color: @beige; h4 { - font-size: 16px; + font-size: var(--font-size-16); font-weight: bold; margin-bottom: 0; font-family: @font-subtitle; diff --git a/styles/less/global/dialog.less b/styles/less/global/dialog.less index 42fdb07e..f164b701 100644 --- a/styles/less/global/dialog.less +++ b/styles/less/global/dialog.less @@ -50,7 +50,7 @@ .formula-label { font-style: normal; font-weight: 500; - font-size: 14px; + font-size: var(--font-size-14); line-height: 17px; white-space: nowrap; color: light-dark(@dark, @beige); diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 2f4912c5..397420b2 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -165,7 +165,7 @@ z-index: 1; .remove { - font-size: 10px; + font-size: var(--font-size-10); } } } @@ -400,7 +400,7 @@ display: flex; flex-direction: column; white-space: nowrap; - font-size: 14px; + font-size: var(--font-size-14); font-weight: 400; &.modifier-label { @@ -527,7 +527,7 @@ font-family: @font-body; margin-top: 4px; color: light-dark(#14142599, #efe6d850); - font-size: 12px; + font-size: var(--font-size-12); padding-left: 3px; } } @@ -541,7 +541,7 @@ text-align: center; } .title-hint { - font-size: 12px; + font-size: var(--font-size-12); font-variant: small-caps; text-align: center; } @@ -605,7 +605,7 @@ align-items: center; label { - font-size: 16px; + font-size: var(--font-size-16); } .form-fields { @@ -776,7 +776,7 @@ .preview-text-container { padding: 10px 0; text-align: center; - font-size: 16px; + font-size: var(--font-size-16); color: light-dark(@beige, @dark); background-image: url(../assets/parchments/dh-parchment-light.png); border-radius: 0 0 4px 4px; @@ -799,14 +799,14 @@ justify-content: center; .preview-add-icon { - font-size: 40px; + font-size: var(--font-size-40); color: light-dark(@dark-blue-50, @beige-50); } .preview-empty-subtext { position: absolute; bottom: 5%; - font-size: 10px; + font-size: var(--font-size-10); font-variant: small-caps; text-align: center; font-style: italic; @@ -821,7 +821,7 @@ width: 54px; border-radius: 50%; border: 2px solid; - font-size: 48px; + font-size: var(--font-size-48); display: flex; align-items: center; justify-content: center; diff --git a/styles/less/global/inventory-item.less b/styles/less/global/inventory-item.less index d63c658e..e221f4e7 100644 --- a/styles/less/global/inventory-item.less +++ b/styles/less/global/inventory-item.less @@ -105,7 +105,7 @@ align-self: center; .item-name { - font-size: 14px; + font-size: var(--font-size-14); .expanded-icon { display: none; @@ -121,9 +121,10 @@ .label { display: flex; flex-direction: row; - justify-content: center; align-items: center; - font-size: 12px; + font-size: var(--font-size-12); + flex-wrap: wrap; + justify-content: start; } .tag { @@ -179,18 +180,18 @@ overflow: hidden; h1 { - font-size: 32px; + font-size: var(--font-size-32); } h2 { - font-size: 28px; + font-size: var(--font-size-28); font-weight: 600; } h3 { - font-size: 20px; + font-size: var(--font-size-20); font-weight: 600; } h4 { - font-size: 16px; + font-size: var(--font-size-16); color: @beige; font-weight: 600; } @@ -231,7 +232,7 @@ label { color: light-dark(white, black); filter: drop-shadow(0 0 1px light-dark(@dark-blue, @golden)); - font-size: 18px; + font-size: var(--font-size-18); } img { @@ -243,7 +244,7 @@ text-shadow: 0 0 3px white; filter: drop-shadow(0 1px white); color: black; - font-size: 26px; + font-size: 1.625rem; } } } @@ -310,7 +311,7 @@ .card-name { font-style: normal; font-weight: 400; - font-size: 12px; + font-size: var(--font-size-12); line-height: 15px; color: @beige; @@ -351,7 +352,7 @@ gap: 4px; .resource-edit { - font-size: 14px; + font-size: var(--font-size-14); } } @@ -363,7 +364,7 @@ i { flex: none; - font-size: 14px; + font-size: var(--font-size-14); } input { @@ -383,7 +384,7 @@ color: light-dark(white, black); filter: drop-shadow(0 0 1px light-dark(@dark-blue, @golden)); z-index: 2; - font-size: 18px; + font-size: var(--font-size-18); cursor: pointer; } @@ -397,7 +398,7 @@ text-shadow: 0 0 3px white; filter: drop-shadow(0 1px white); color: black; - font-size: 26px; + font-size: 1.625rem; } } } diff --git a/styles/less/global/item-header.less b/styles/less/global/item-header.less index 7b2c907f..073762e0 100755 --- a/styles/less/global/item-header.less +++ b/styles/less/global/item-header.less @@ -35,7 +35,7 @@ width: 80%; .item-name input[type='text'] { - font-size: 32px; + font-size: var(--font-size-32); height: 42px; text-align: center; width: 90%; @@ -103,7 +103,7 @@ transition: all 0.3s ease; .recall-label { - font-size: 14px; + font-size: var(--font-size-14); opacity: 0; margin-right: 0.3rem; transition: all 0.3s ease; @@ -141,7 +141,7 @@ .item-name { input[type='text'] { - font-size: 32px; + font-size: var(--font-size-32); height: 42px; text-align: center; width: 90%; diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less index cb7933a4..506fb8b7 100644 --- a/styles/less/global/prose-mirror.less +++ b/styles/less/global/prose-mirror.less @@ -12,18 +12,18 @@ scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; h1 { - font-size: 32px; + font-size: var(--font-size-32); } h2 { - font-size: 28px; + font-size: var(--font-size-28); font-weight: 600; } h3 { - font-size: 20px; + font-size: var(--font-size-20); font-weight: 600; } h4 { - font-size: 16px; + font-size: var(--font-size-16); color: @beige; font-weight: 600; } diff --git a/styles/less/sheets-settings/character-settings/sheet.less b/styles/less/sheets-settings/character-settings/sheet.less index 78bbf9c5..f0c7c94e 100644 --- a/styles/less/sheets-settings/character-settings/sheet.less +++ b/styles/less/sheets-settings/character-settings/sheet.less @@ -33,7 +33,7 @@ div { filter: drop-shadow(0 0 3px black); text-shadow: 0 0 3px black; - font-size: 12px; + font-size: var(--font-size-12); } input { diff --git a/styles/less/sheets-settings/header.less b/styles/less/sheets-settings/header.less index 6ac2663f..82f3c488 100644 --- a/styles/less/sheets-settings/header.less +++ b/styles/less/sheets-settings/header.less @@ -10,7 +10,7 @@ font-family: @font-subtitle; font-style: normal; font-weight: 700; - font-size: 24px; + font-size: var(--font-size-24); margin: 0; text-align: center; color: light-dark(@dark-blue, @golden); diff --git a/styles/less/sheets/actors/adversary/header.less b/styles/less/sheets/actors/adversary/header.less index 22a769ae..d4a7812e 100644 --- a/styles/less/sheets/actors/adversary/header.less +++ b/styles/less/sheets/actors/adversary/header.less @@ -18,7 +18,7 @@ flex: 1; input[type='text'] { - font-size: 32px; + font-size: var(--font-size-32); height: 42px; text-align: start; border: 1px solid transparent; @@ -42,7 +42,7 @@ justify-content: center; align-items: center; padding: 3px 5px; - font-size: 12px; + font-size: var(--font-size-12); font: @font-body; background: light-dark(@dark-15, @beige-15); @@ -55,7 +55,7 @@ flex-direction: row; justify-content: center; align-items: center; - font-size: 12px; + font-size: var(--font-size-12); } } diff --git a/styles/less/sheets/actors/adversary/sidebar.less b/styles/less/sheets/actors/adversary/sidebar.less index 70cd92ed..ab15fa46 100644 --- a/styles/less/sheets/actors/adversary/sidebar.less +++ b/styles/less/sheets/actors/adversary/sidebar.less @@ -74,7 +74,7 @@ height: 30px; h4 { - font-size: 14px; + font-size: var(--font-size-14); font-weight: bold; text-transform: uppercase; color: light-dark(@dark-blue, @golden); @@ -255,7 +255,7 @@ font-weight: bold; text-align: center; line-height: 18px; - font-size: 12px; + font-size: var(--font-size-12); color: light-dark(@beige, @dark-blue); } } @@ -295,7 +295,7 @@ align-items: center; h3 { - font-size: 20px; + font-size: var(--font-size-20); } } .items-list { @@ -315,7 +315,7 @@ align-items: center; h3 { - font-size: 20px; + font-size: var(--font-size-20); } } @@ -337,7 +337,7 @@ .experience-name { width: 180px; text-align: start; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); } } @@ -345,7 +345,7 @@ .experience-value { height: 25px; width: 35px; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); align-content: center; text-align: center; diff --git a/styles/less/sheets/actors/character/header.less b/styles/less/sheets/actors/character/header.less index 2d261a6a..80089cf7 100644 --- a/styles/less/sheets/actors/character/header.less +++ b/styles/less/sheets/actors/character/header.less @@ -41,7 +41,7 @@ flex: 1; input[type='text'] { - font-size: 32px; + font-size: var(--font-size-32); height: 42px; text-align: start; border: 1px solid transparent; @@ -72,7 +72,7 @@ .level-button { color: light-dark(@dark, @beige); - font-size: 18px; + font-size: var(--font-size-18); line-height: 1; min-height: unset; height: min-content; @@ -97,7 +97,7 @@ justify-content: space-between; padding: 5px 0; margin-bottom: 10px; - font-size: 12px; + font-size: var(--font-size-12); color: light-dark(@dark-blue, @golden); .missing-header-feature { @@ -158,7 +158,7 @@ height: 30px; h4 { - font-size: 14px; + font-size: var(--font-size-14); font-weight: bold; text-transform: uppercase; color: light-dark(@dark-blue, @golden); @@ -170,7 +170,7 @@ gap: 5px; .label { - font-size: 14px; + font-size: var(--font-size-14); font-weight: bold; text-transform: uppercase; color: light-dark(@dark-blue, @golden); @@ -205,7 +205,7 @@ align-items: center; padding-top: 5px; color: light-dark(@dark-blue, @golden); - font-size: 14px; + font-size: var(--font-size-14); font-weight: 600; align-items: center; justify-content: center; @@ -213,14 +213,14 @@ i { line-height: 17px; - font-size: 10px; + font-size: var(--font-size-10); } } .trait-value { font-style: normal; font-weight: 400; - font-size: 20px; + font-size: var(--font-size-20); text-align: center; } } diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index 0870c0c3..9fd48921 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -41,7 +41,7 @@ height: 32px; position: absolute; right: 20px; - font-size: 16px; + font-size: var(--font-size-16); z-index: 1; color: light-dark(@dark-blue-50, @beige-50); } diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index 35dffb79..08246efb 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -41,7 +41,7 @@ height: 32px; position: absolute; right: 20px; - font-size: 16px; + font-size: var(--font-size-16); z-index: 1; color: light-dark(@dark-blue-50, @beige-50); } diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index 3ff8576d..3d244cdd 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -89,7 +89,7 @@ transition: all 0.3s ease; .spellcast-label { - font-size: 14px; + font-size: var(--font-size-14); opacity: 0; margin-right: 0.3rem; transition: all 0.3s ease; @@ -258,7 +258,7 @@ text-align: center; line-height: 18px; color: light-dark(@beige, @dark-blue); - font-size: 12px; + font-size: var(--font-size-12); } } .status-value { @@ -402,7 +402,7 @@ font-weight: bold; text-align: center; line-height: 18px; - font-size: 12px; + font-size: var(--font-size-12); color: light-dark(@beige, @dark-blue); } } @@ -424,7 +424,7 @@ height: 30px; h4 { - font-size: 14px; + font-size: var(--font-size-14); font-weight: bold; text-transform: uppercase; color: light-dark(@dark-blue, @golden); @@ -490,7 +490,7 @@ .experience-value { height: 25px; width: 35px; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); align-content: center; text-align: center; diff --git a/styles/less/sheets/actors/companion/details.less b/styles/less/sheets/actors/companion/details.less index 9823825f..2df14b23 100644 --- a/styles/less/sheets/actors/companion/details.less +++ b/styles/less/sheets/actors/companion/details.less @@ -16,7 +16,7 @@ width: 100%; h3 { - font-size: 20px; + font-size: var(--font-size-20); } } .items-list { @@ -58,7 +58,7 @@ .experience-name { width: 180px; text-align: start; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); } } @@ -66,7 +66,7 @@ .experience-value { height: 25px; width: 35px; - font-size: 14px; + font-size: var(--font-size-14); color: light-dark(@dark, @beige); align-content: center; text-align: center; diff --git a/styles/less/sheets/actors/companion/header.less b/styles/less/sheets/actors/companion/header.less index 240f9df8..b85a1819 100644 --- a/styles/less/sheets/actors/companion/header.less +++ b/styles/less/sheets/actors/companion/header.less @@ -24,7 +24,7 @@ margin-bottom: -30px; input[type='text'] { - font-size: 24px; + font-size: var(--font-size-24); height: 32px; text-align: center; border: 1px solid transparent; @@ -78,7 +78,7 @@ font-weight: bold; text-align: center; line-height: 18px; - font-size: 12px; + font-size: var(--font-size-12); color: light-dark(@beige, @dark-blue); } } @@ -209,7 +209,7 @@ .level-button { color: light-dark(@dark, @beige); - font-size: 18px; + font-size: var(--font-size-18); line-height: 1; min-height: unset; height: min-content; diff --git a/styles/less/sheets/actors/environment/header.less b/styles/less/sheets/actors/environment/header.less index 0ac361a1..670f6c92 100644 --- a/styles/less/sheets/actors/environment/header.less +++ b/styles/less/sheets/actors/environment/header.less @@ -39,7 +39,7 @@ justify-content: center; align-items: center; padding: 3px 5px; - font-size: 12px; + font-size: var(--font-size-12); font: @font-body; background: light-dark(@dark-15, @beige-15); @@ -52,7 +52,7 @@ flex-direction: row; justify-content: center; align-items: center; - font-size: 12px; + font-size: var(--font-size-12); } } @@ -100,7 +100,7 @@ font-weight: bold; text-align: center; line-height: 18px; - font-size: 12px; + font-size: var(--font-size-12); color: light-dark(@beige, @dark-blue); } } @@ -108,7 +108,7 @@ .item-name { input[type='text'] { - font-size: 32px; + font-size: var(--font-size-32); height: 42px; text-align: start; transition: all 0.3s ease; diff --git a/styles/less/ui/chat/ability-use.less b/styles/less/ui/chat/ability-use.less index 58897697..d313638f 100644 --- a/styles/less/ui/chat/ability-use.less +++ b/styles/less/ui/chat/ability-use.less @@ -87,7 +87,7 @@ gap: 5px; .title { - font-size: 20px; + font-size: var(--font-size-20); color: @golden; font-weight: 700; } @@ -103,7 +103,7 @@ justify-content: center; align-items: center; padding: 3px 5px; - font-size: 12px; + font-size: var(--font-size-12); background: @beige-15; border: 1px solid @beige; diff --git a/styles/less/ui/chat/action.less b/styles/less/ui/chat/action.less index 82cc3210..a849315a 100644 --- a/styles/less/ui/chat/action.less +++ b/styles/less/ui/chat/action.less @@ -81,13 +81,13 @@ gap: 5px; .title { - font-size: 20px; + font-size: var(--font-size-20); color: @golden; font-weight: 700; } .label { - font-size: 12px; + font-size: var(--font-size-12); color: @beige; margin: 0; } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index c6ed95ca..9eb35cd6 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -49,7 +49,7 @@ &.resource-roll { .reroll-message { text-align: center; - font-size: 18px; + font-size: var(--font-size-18); margin-bottom: 0; } } @@ -191,7 +191,7 @@ position: absolute; top: 0; right: 0; - font-size: 10px; + font-size: var(--font-size-10); z-index: 2; filter: drop-shadow(0 0 3px black); } diff --git a/styles/less/ui/chat/downtime.less b/styles/less/ui/chat/downtime.less index 8b898c43..ca29e85f 100644 --- a/styles/less/ui/chat/downtime.less +++ b/styles/less/ui/chat/downtime.less @@ -82,12 +82,12 @@ .header-label { padding: 8px; .title { - font-size: 16px; + font-size: var(--font-size-16); color: @golden; font-weight: 700; } .label { - font-size: 12px; + font-size: var(--font-size-12); color: @beige; margin: 0; } diff --git a/styles/less/ui/combat-sidebar/token-actions.less b/styles/less/ui/combat-sidebar/token-actions.less index 6fc84d29..41fb38ab 100644 --- a/styles/less/ui/combat-sidebar/token-actions.less +++ b/styles/less/ui/combat-sidebar/token-actions.less @@ -17,7 +17,7 @@ display: flex; align-items: center; justify-content: center; - font-size: 10px; + font-size: var(--font-size-10); padding: 8px; --button-size: 0; diff --git a/styles/less/ui/countdown/sheet.less b/styles/less/ui/countdown/sheet.less index 1692773e..0ce7c4af 100644 --- a/styles/less/ui/countdown/sheet.less +++ b/styles/less/ui/countdown/sheet.less @@ -47,7 +47,7 @@ position: absolute; top: 8px; right: 8px; - font-size: 18px; + font-size: var(--font-size-18); } .countdown-container { diff --git a/styles/less/ui/item-browser/item-browser.less b/styles/less/ui/item-browser/item-browser.less index 7be45b8c..d891e73d 100644 --- a/styles/less/ui/item-browser/item-browser.less +++ b/styles/less/ui/item-browser/item-browser.less @@ -161,7 +161,7 @@ height: 32px; position: absolute; right: 20px; - font-size: 16px; + font-size: var(--font-size-16); z-index: 1; color: light-dark(@dark-blue-50, @beige-50); } @@ -304,18 +304,18 @@ gap: 5px; h1 { - font-size: 32px; + font-size: var(--font-size-32); } h2 { - font-size: 28px; + font-size: var(--font-size-28); font-weight: 600; } h3 { - font-size: 20px; + font-size: var(--font-size-20); font-weight: 600; } h4 { - font-size: 16px; + font-size: var(--font-size-16); color: @beige; font-weight: 600; } diff --git a/styles/less/ui/settings/homebrew-settings/domains.less b/styles/less/ui/settings/homebrew-settings/domains.less index c2ba3ef7..84e013c2 100644 --- a/styles/less/ui/settings/homebrew-settings/domains.less +++ b/styles/less/ui/settings/homebrew-settings/domains.less @@ -44,7 +44,7 @@ border-radius: 50%; width: 24px; height: 24px; - font-size: 12px; + font-size: var(--font-size-12); } } } @@ -118,7 +118,7 @@ button { border-radius: 50%; - font-size: 12px; + font-size: var(--font-size-12); height: 24px; width: 24px; margin-right: 4px; diff --git a/styles/less/ui/settings/settings.less b/styles/less/ui/settings/settings.less index 8062ff73..cee5475f 100644 --- a/styles/less/ui/settings/settings.less +++ b/styles/less/ui/settings/settings.less @@ -53,7 +53,7 @@ } i { - font-size: 18px; + font-size: var(--font-size-18); } } } @@ -80,7 +80,7 @@ width: 80%; .item-name input[type='text'] { - font-size: 32px; + font-size: var(--font-size-32); height: 42px; text-align: center; width: 90%; @@ -117,7 +117,7 @@ label { position: absolute; top: -7px; - font-size: 12px; + font-size: var(--font-size-12); font-variant: petite-caps; z-index: 2; } diff --git a/styles/less/utils/mixin.less b/styles/less/utils/mixin.less index 2f1aa907..49e97a1f 100644 --- a/styles/less/utils/mixin.less +++ b/styles/less/utils/mixin.less @@ -30,7 +30,7 @@ align-items: center; h3 { - font-size: 20px; + font-size: var(--font-size-20); } } @@ -70,7 +70,7 @@ h4 { font-family: @font-body; - font-size: 14px; + font-size: var(--font-size-14); border: none; font-weight: 700; margin: 0; @@ -80,7 +80,7 @@ h5 { font-family: @font-body; - font-size: 14px; + font-size: var(--font-size-14); margin: 0; font-weight: normal; } diff --git a/styles/less/ux/autocomplete/autocomplete.less b/styles/less/ux/autocomplete/autocomplete.less index 868b4f43..808a8972 100644 --- a/styles/less/ux/autocomplete/autocomplete.less +++ b/styles/less/ux/autocomplete/autocomplete.less @@ -22,12 +22,12 @@ .group { font-weight: bold; - font-size: 14px; + font-size: var(--font-size-14); padding-left: 8px; } li[role='option'] { - font-size: 14px; + font-size: var(--font-size-14); padding-left: 10px; cursor: pointer; diff --git a/styles/less/ux/tooltip/tooltip.less b/styles/less/ux/tooltip/tooltip.less index 43f47da5..1d7079ee 100644 --- a/styles/less/ux/tooltip/tooltip.less +++ b/styles/less/ux/tooltip/tooltip.less @@ -85,7 +85,7 @@ gap: 8px; .tooltip-chip { - font-size: 18px; + font-size: var(--font-size-18); padding: 2px 4px; border: 1px solid light-dark(@dark-blue, @golden); border-radius: 6px; diff --git a/templates/sheets/items/weapon/header.hbs b/templates/sheets/items/weapon/header.hbs index ee0198ba..349a9516 100644 --- a/templates/sheets/items/weapon/header.hbs +++ b/templates/sheets/items/weapon/header.hbs @@ -14,7 +14,11 @@ - {{localize (concat 'DAGGERHEART.CONFIG.Range.' source.system.attack.range '.name')}} - - {{source.system.attack.damage.parts.0.value.dice}}{{#if source.system.attack.damage.parts.0.value.bonus}} + {{source.system.attack.damage.parts.0.value.bonus}}{{/if}} + {{#if source.system.attack.damage.parts.0.value.custom.enabled}} + {{localize "DAGGERHEART.GENERAL.custom"}} + {{else}} + {{source.system.attack.damage.parts.0.value.dice}}{{#if source.system.attack.damage.parts.0.value.bonus}} + {{source.system.attack.damage.parts.0.value.bonus}}{{/if}} + {{/if}} ( {{#each source.system.attack.damage.parts.0.type}} {{localize (concat 'DAGGERHEART.CONFIG.DamageType.' this '.abbreviation')}} diff --git a/templates/sheets/items/weapon/settings.hbs b/templates/sheets/items/weapon/settings.hbs index b2738c75..f9499221 100644 --- a/templates/sheets/items/weapon/settings.hbs +++ b/templates/sheets/items/weapon/settings.hbs @@ -21,10 +21,17 @@ {{#with systemFields.attack.fields.damage.fields.parts.element.fields as | fields | }} {{#with (lookup ../document.system.attack.damage.parts 0) as | source | }} {{localize "DAGGERHEART.GENERAL.damage"}} - {{localize "DAGGERHEART.GENERAL.Dice.single"}} - {{formInput fields.value.fields.dice value=source.value.dice name="system.attack.damage.parts.0.value.dice"}} - {{localize "DAGGERHEART.GENERAL.bonus"}} - {{formInput fields.value.fields.bonus value=source.value.bonus name="system.attack.damage.parts.0.value.bonus" localize=true}} + {{localize "DAGGERHEART.ACTIONS.Config.general.customFormula"}} + {{formInput fields.value.fields.custom.fields.enabled value=source.value.custom.enabled name="system.attack.damage.parts.0.value.custom.enabled"}} + {{#if source.value.custom.enabled}} + {{localize "DAGGERHEART.ACTIONS.Config.general.formula"}} + {{formInput fields.value.fields.custom.fields.formula value=source.value.custom.formula name="system.attack.damage.parts.0.value.custom.formula"}} + {{else}} + {{localize "DAGGERHEART.GENERAL.Dice.single"}} + {{formInput fields.value.fields.dice value=source.value.dice name="system.attack.damage.parts.0.value.dice"}} + {{localize "DAGGERHEART.GENERAL.bonus"}} + {{formInput fields.value.fields.bonus value=source.value.bonus name="system.attack.damage.parts.0.value.bonus" localize=true}} + {{/if}} {{localize "DAGGERHEART.GENERAL.type"}} {{formInput fields.type value=source.type name="system.attack.damage.parts.0.type" localize=true}} {{localize "DAGGERHEART.CONFIG.DamageType.direct.name"}} From 0b2694b007711444192f583bc0daf211f1a44e6b Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 23 Aug 2025 23:50:10 +0200 Subject: [PATCH 11/22] Improved feature request label (#1072) --- .../ISSUE_TEMPLATE/{feature_report.md => feature_request.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename .github/ISSUE_TEMPLATE/{feature_report.md => feature_request.md} (76%) diff --git a/.github/ISSUE_TEMPLATE/feature_report.md b/.github/ISSUE_TEMPLATE/feature_request.md similarity index 76% rename from .github/ISSUE_TEMPLATE/feature_report.md rename to .github/ISSUE_TEMPLATE/feature_request.md index df00ba37..35710e2b 100644 --- a/.github/ISSUE_TEMPLATE/feature_report.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,6 @@ --- -name: Feature report -about: Create a feature report for suggestions on improving the system +name: Feature request +about: Create a feature request for suggestions on improving the system title: "[Feature] " labels: enhancement, discussion, maybe type: feature From 46ea4addd0710708e7d27b82dbb817a49e8db0a6 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 02:13:15 +0200 Subject: [PATCH 12/22] [Fix] Subclass Links (#1069) * Attempt at making subclass aware of its class * Update compendium classes/subclasses * Fixed multiclass * Update compenidum browser subclass class filter * Added migration for subclass.linkedClass * Using foundry's isNewer function rather than custom one * Added migration for existing actor features --------- Co-authored-by: Dapoolp --- lang/en.json | 3 +- .../characterCreation/characterCreation.mjs | 7 +- module/applications/sheets/items/class.mjs | 15 + module/applications/ui/itemBrowser.mjs | 9 +- module/config/itemBrowserConfig.mjs | 484 +++++++++--------- module/data/actor/character.mjs | 6 +- module/data/item/base.mjs | 4 +- module/data/item/feature.mjs | 1 + module/data/item/subclass.mjs | 4 +- module/documents/actor.mjs | 8 +- module/helpers/utils.mjs | 11 - module/systemRegistration/migrations.mjs | 44 +- .../classes/class_Bard_vegl3bFOq3pcFTWT.json | 8 +- .../classes/class_Druid_ZNwUTCyGCEcidZFv.json | 8 +- .../class_Guardian_nRAyoC0fOzXPDa4z.json | 8 +- .../class_Ranger_BTyfve69LKqoOi9S.json | 8 +- .../classes/class_Rogue_CvHlkHZfpMiCz5uT.json | 8 +- .../class_Seraph_5ZnlJ5bEoyOTkUJv.json | 8 +- .../class_Sorcerer_DchOzHcWIJE9FKcR.json | 8 +- .../class_Warrior_xCUWwJz4WSthvLfy.json | 8 +- .../class_Wizard_5LwX4m8ziY3F1ZGC.json | 8 +- .../subclass_Beastbound_TIUsIlTS1WkK5vr2.json | 11 +- ...ss_Call_Of_The_Brave_NAFU9roaVG7f3RNJ.json | 11 +- ...s_Call_Of_The_Slayer_bcNe5qP3o6CKadhK.json | 11 +- ...class_Divine_Wielder_M5mpGoAj8LRkylrY.json | 11 +- ...ass_Elemental_Origin_wg1H0hROc2acHwZh.json | 11 +- ...subclass_Nightwalker_h161OSIK24Up4qNd.json | 11 +- ...bclass_Primal_Origin_GLpRVxnY5E82khxH.json | 11 +- ..._School_Of_Knowledge_qqQlgCqhOivUFoQn.json | 11 +- ...bclass_School_Of_War_4y9Ph7RsCIAbkwTk.json | 11 +- .../subclass_Stalwart_rKRxFBlkbh9cDK8K.json | 11 +- .../subclass_Syndicate_95QxNZwgyEm1LqdG.json | 11 +- .../subclass_Troubadour_ld8MIvk0xVJydSBz.json | 11 +- .../subclass_Vengeance_SUo8NPBPO8aN193u.json | 11 +- ...ss_Warden_of_Renewal_xp0XMjYT85Q7E90o.json | 11 +- ...rden_of_the_Elements_W9hs5kxOWeY7eA4Q.json | 11 +- .../subclass_Wayfinder_zsUglcU4NgZ8tNgZ.json | 11 +- ...lass_Winged_Sentinel_y7ERWRIpJsdP9Re4.json | 11 +- .../subclass_Wordsmith_XTSODVM8st75Os8M.json | 11 +- styles/less/ui/item-browser/item-browser.less | 2 + system.json | 2 +- 41 files changed, 479 insertions(+), 391 deletions(-) diff --git a/lang/en.json b/lang/en.json index 6a34037d..f310a01d 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2371,7 +2371,8 @@ "insufficientResources": "You have insufficient resources", "multiclassAlreadyPresent": "You already have a class and multiclass", "subclassesAlreadyPresent": "You already have a class and multiclass subclass", - "noDiceSystem": "Your selected dice {system} does not have a {faces} dice" + "noDiceSystem": "Your selected dice {system} does not have a {faces} dice", + "subclassAlreadyLinked": "{name} is already a subclass in the class {class}. Remove it from there if you want it to be a subclass to this class." }, "Tooltip": { "disableEffect": "Disable Effect", diff --git a/module/applications/characterCreation/characterCreation.mjs b/module/applications/characterCreation/characterCreation.mjs index f9f832e8..ccb6f7c0 100644 --- a/module/applications/characterCreation/characterCreation.mjs +++ b/module/applications/characterCreation/characterCreation.mjs @@ -432,12 +432,17 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl } }; - if (type == 'domains') + if (type === 'domains') presets.filter = { 'level.max': { key: 'level.max', value: 1 }, 'system.domain': { key: 'system.domain', value: this.setup.class?.system.domains ?? null } }; + if (type === 'subclasses') + presets.filter = { + 'system.linkedClass.uuid': { key: 'system.linkedClass.uuid', value: this.setup.class?.uuid } + }; + if (equipment.includes(type)) presets.filter = { 'system.tier': { key: 'system.tier', value: 1 }, diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index 01f4249a..033c63e6 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -119,6 +119,15 @@ export default class ClassSheet extends DHBaseItemSheet { const itemType = data.data ? data.type : item.type; const target = event.target.closest('fieldset.drop-section'); if (itemType === 'subclass') { + if (item.system.linkedClass) { + return ui.notifications.warn( + game.i18n.format('DAGGERHEART.UI.Notifications.subclassAlreadyLinked', { + name: item.name, + class: this.document.name + }) + ); + } + await item.update({ 'system.linkedClass': this.document.uuid }); await this.document.update({ 'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid] }); @@ -181,6 +190,12 @@ export default class ClassSheet extends DHBaseItemSheet { static async #removeItemFromCollection(_event, element) { const { uuid, target } = element.dataset; const prop = foundry.utils.getProperty(this.document.system, target); + + if (target === 'subclasses') { + const subclass = await foundry.utils.fromUuid(uuid); + await subclass.update({ 'system.linkedClass': null }); + } + await this.document.update({ [`system.${target}`]: prop.filter(i => i.uuid !== uuid).map(x => x.uuid) }); } diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index f0ad98db..9b9bef91 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -235,7 +235,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { filters.forEach(f => { if (typeof f.field === 'string') f.field = foundry.utils.getProperty(game, f.field); else if (typeof f.choices === 'function') { - f.choices = f.choices(); + f.choices = f.choices(this.items); } f.name ??= f.key; f.value = this.presets?.filter?.[f.name]?.value ?? null; @@ -248,11 +248,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { /* -------------------------------------------- */ /** - * Create and initialize search filter instances for the inventory and loadout sections. + * Create and initialize search filter instance. * - * Sets up two {@link foundry.applications.ux.SearchFilter} instances: - * - One for the inventory, which filters items in the inventory grid. - * - One for the loadout, which filters items in the loadout/card grid. * @private */ _createSearchFilter() { @@ -339,7 +336,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { item = this.items.find(i => i.uuid === itemUUID); if (!item) continue; - + const matchesMenu = this.fieldFilter.length === 0 || this.fieldFilter.every( diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs index 6e3c0dea..e40c989b 100644 --- a/module/config/itemBrowserConfig.mjs +++ b/module/config/itemBrowserConfig.mjs @@ -2,404 +2,422 @@ export const typeConfig = { adversaries: { columns: [ { - key: "system.tier", - label: "Tier" + key: 'system.tier', + label: 'Tier' }, { - key: "system.type", - label: "Type" + key: 'system.type', + label: 'Type' } ], filters: [ { - key: "system.tier", - label: "Tier", + key: 'system.tier', + label: 'Tier', field: 'system.api.models.actors.DhAdversary.schema.fields.tier' }, { - key: "system.type", - label: "Type", + key: 'system.type', + label: 'Type', field: 'system.api.models.actors.DhAdversary.schema.fields.type' }, { - key: "system.difficulty", - name: "difficulty.min", - label: "Difficulty (Min)", + key: 'system.difficulty', + name: 'difficulty.min', + label: 'Difficulty (Min)', field: 'system.api.models.actors.DhAdversary.schema.fields.difficulty', - operator: "gte" + operator: 'gte' }, { - key: "system.difficulty", - name: "difficulty.max", - label: "Difficulty (Max)", + key: 'system.difficulty', + name: 'difficulty.max', + label: 'Difficulty (Max)', field: 'system.api.models.actors.DhAdversary.schema.fields.difficulty', - operator: "lte" + operator: 'lte' }, { - key: "system.resources.hitPoints.max", - name: "hp.min", - label: "Hit Points (Min)", + key: 'system.resources.hitPoints.max', + name: 'hp.min', + label: 'Hit Points (Min)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.hitPoints.fields.max', - operator: "gte" + operator: 'gte' }, { - key: "system.resources.hitPoints.max", - name: "hp.max", - label: "Hit Points (Max)", + key: 'system.resources.hitPoints.max', + name: 'hp.max', + label: 'Hit Points (Max)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.hitPoints.fields.max', - operator: "lte" + operator: 'lte' }, { - key: "system.resources.stress.max", - name: "stress.min", - label: "Stress (Min)", + key: 'system.resources.stress.max', + name: 'stress.min', + label: 'Stress (Min)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.stress.fields.max', - operator: "gte" + operator: 'gte' }, { - key: "system.resources.stress.max", - name: "stress.max", - label: "Stress (Max)", + key: 'system.resources.stress.max', + name: 'stress.max', + label: 'Stress (Max)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.stress.fields.max', - operator: "lte" - }, + operator: 'lte' + } ] }, items: { columns: [ { - key: "type", - label: "Type" + key: 'type', + label: 'Type' }, { - key: "system.secondary", - label: "Subtype", - format: (isSecondary) => isSecondary ? "secondary" : (isSecondary === false ? "primary" : '-') + key: 'system.secondary', + label: 'Subtype', + format: isSecondary => (isSecondary ? 'secondary' : isSecondary === false ? 'primary' : '-') }, { - key: "system.tier", - label: "Tier" + key: 'system.tier', + label: 'Tier' } ], filters: [ { - key: "type", - label: "Type", - choices: () => CONFIG.Item.documentClass.TYPES.filter(t => ["armor", "weapon", "consumable", "loot"].includes(t)).map(t => ({ value: t, label: t })) + key: 'type', + label: 'Type', + choices: () => + CONFIG.Item.documentClass.TYPES.filter(t => + ['armor', 'weapon', 'consumable', 'loot'].includes(t) + ).map(t => ({ value: t, label: t })) }, { - key: "system.secondary", - label: "Subtype", + key: 'system.secondary', + label: 'Subtype', choices: [ - { value: false, label: "Primary Weapon"}, - { value: true, label: "Secondary Weapon"} + { value: false, label: 'Primary Weapon' }, + { value: true, label: 'Secondary Weapon' } ] }, { - key: "system.tier", - label: "Tier", - choices: [{ value: "1", label: "1"}, { value: "2", label: "2"}, { value: "3", label: "3"}, { value: "4", label: "4"}] + key: 'system.tier', + label: 'Tier', + choices: [ + { value: '1', label: '1' }, + { value: '2', label: '2' }, + { value: '3', label: '3' }, + { value: '4', label: '4' } + ] }, { - key: "system.burden", - label: "Burden", + key: 'system.burden', + label: 'Burden', field: 'system.api.models.items.DHWeapon.schema.fields.burden' }, { - key: "system.attack.roll.trait", - label: "Trait", + key: 'system.attack.roll.trait', + label: 'Trait', field: 'system.api.models.actions.actionsTypes.attack.schema.fields.roll.fields.trait' }, { - key: "system.attack.range", - label: "Range", + key: 'system.attack.range', + label: 'Range', field: 'system.api.models.actions.actionsTypes.attack.schema.fields.range' }, { - key: "system.baseScore", - name: "armor.min", - label: "Armor Score (Min)", + key: 'system.baseScore', + name: 'armor.min', + label: 'Armor Score (Min)', field: 'system.api.models.items.DHArmor.schema.fields.baseScore', - operator: "gte" + operator: 'gte' }, { - key: "system.baseScore", - name: "armor.max", - label: "Armor Score (Max)", + key: 'system.baseScore', + name: 'armor.max', + label: 'Armor Score (Max)', field: 'system.api.models.items.DHArmor.schema.fields.baseScore', - operator: "lte" + operator: 'lte' }, { - key: "system.itemFeatures", - label: "Features", - choices: () => [...Object.entries(CONFIG.DH.ITEM.weaponFeatures), ...Object.entries(CONFIG.DH.ITEM.armorFeatures)].map(([k,v]) => ({ value: k, label: v.label})), - operator: "contains3" + key: 'system.itemFeatures', + label: 'Features', + choices: () => + [ + ...Object.entries(CONFIG.DH.ITEM.weaponFeatures), + ...Object.entries(CONFIG.DH.ITEM.armorFeatures) + ].map(([k, v]) => ({ value: k, label: v.label })), + operator: 'contains3' } ] }, features: { - columns: [ - - ], - filters: [ - - ] + columns: [], + filters: [] }, cards: { columns: [ { - key: "system.type", - label: "Type" + key: 'system.type', + label: 'Type' }, { - key: "system.domain", - label: "Domain" + key: 'system.domain', + label: 'Domain' }, { - key: "system.level", - label: "Level" + key: 'system.level', + label: 'Level' } ], filters: [ { - key: "system.type", - label: "Type", + key: 'system.type', + label: 'Type', field: 'system.api.models.items.DHDomainCard.schema.fields.type' }, { - key: "system.domain", - label: "Domain", + key: 'system.domain', + label: 'Domain', field: 'system.api.models.items.DHDomainCard.schema.fields.domain', - operator: "contains2" + operator: 'contains2' }, { - key: "system.level", - name: "level.min", - label: "Level (Min)", + key: 'system.level', + name: 'level.min', + label: 'Level (Min)', field: 'system.api.models.items.DHDomainCard.schema.fields.level', - operator: "gte" + operator: 'gte' }, { - key: "system.level", - name: "level.max", - label: "Level (Max)", + key: 'system.level', + name: 'level.max', + label: 'Level (Max)', field: 'system.api.models.items.DHDomainCard.schema.fields.level', - operator: "lte" + operator: 'lte' }, { - key: "system.recallCost", - name: "recall.min", - label: "Recall Cost (Min)", + key: 'system.recallCost', + name: 'recall.min', + label: 'Recall Cost (Min)', field: 'system.api.models.items.DHDomainCard.schema.fields.recallCost', - operator: "gte" + operator: 'gte' }, { - key: "system.recallCost", - name: "recall.max", - label: "Recall Cost (Max)", + key: 'system.recallCost', + name: 'recall.max', + label: 'Recall Cost (Max)', field: 'system.api.models.items.DHDomainCard.schema.fields.recallCost', - operator: "lte" + operator: 'lte' } ] }, classes: { columns: [ { - key: "system.evasion", - label: "Evasion" + key: 'system.evasion', + label: 'Evasion' }, { - key: "system.hitPoints", - label: "Hit Points" + key: 'system.hitPoints', + label: 'Hit Points' }, { - key: "system.domains", - label: "Domains" + key: 'system.domains', + label: 'Domains' } ], filters: [ { - key: "system.evasion", - name: "evasion.min", - label: "Evasion (Min)", + key: 'system.evasion', + name: 'evasion.min', + label: 'Evasion (Min)', field: 'system.api.models.items.DHClass.schema.fields.evasion', - operator: "gte" + operator: 'gte' }, { - key: "system.evasion", - name: "evasion.max", - label: "Evasion (Max)", + key: 'system.evasion', + name: 'evasion.max', + label: 'Evasion (Max)', field: 'system.api.models.items.DHClass.schema.fields.evasion', - operator: "lte" + operator: 'lte' }, { - key: "system.hitPoints", - name: "hp.min", - label: "Hit Points (Min)", + key: 'system.hitPoints', + name: 'hp.min', + label: 'Hit Points (Min)', field: 'system.api.models.items.DHClass.schema.fields.hitPoints', - operator: "gte" + operator: 'gte' }, { - key: "system.hitPoints", - name: "hp.max", - label: "Hit Points (Max)", + key: 'system.hitPoints', + name: 'hp.max', + label: 'Hit Points (Max)', field: 'system.api.models.items.DHClass.schema.fields.hitPoints', - operator: "lte" + operator: 'lte' }, { - key: "system.domains", - label: "Domains", - choices: () => Object.values(CONFIG.DH.DOMAIN.domains).map(d => ({ value: d.id, label: d.label})), - operator: "contains2" + key: 'system.domains', + label: 'Domains', + choices: () => Object.values(CONFIG.DH.DOMAIN.domains).map(d => ({ value: d.id, label: d.label })), + operator: 'contains2' } ] }, subclasses: { columns: [ { - key: "id", - label: "Class", - format: (id) => { - return ""; - } + key: 'system.linkedClass', + label: 'Class', + format: linkedClass => linkedClass.name }, { - key: "system.spellcastingTrait", - label: "Spellcasting Trait" - } - ], - filters: [] - }, - beastforms: { - columns: [ - { - key: "system.tier", - label: "Tier" - }, - { - key: "system.mainTrait", - label: "Main Trait" + key: 'system.spellcastingTrait', + label: 'Spellcasting Trait' } ], filters: [ { - key: "system.tier", - label: "Tier", + key: 'system.linkedClass.uuid', + label: 'Class', + choices: (items) => { + const list = items.map(item => ({ value: item.system.linkedClass.uuid, label: item.system.linkedClass.name })); + return list.reduce((a,c) => { + if(!(a.find(i => i.value === c.value))) a.push(c); + return a; + }, []); + } + } + ] + }, + beastforms: { + columns: [ + { + key: 'system.tier', + label: 'Tier' + }, + { + key: 'system.mainTrait', + label: 'Main Trait' + } + ], + filters: [ + { + key: 'system.tier', + label: 'Tier', field: 'system.api.models.items.DHBeastform.schema.fields.tier' }, { - key: "system.mainTrait", - label: "Main Trait", + key: 'system.mainTrait', + label: 'Main Trait', field: 'system.api.models.items.DHBeastform.schema.fields.mainTrait' } ] } -} +}; export const compendiumConfig = { - "daggerheart": { - id: "daggerheart", - label: "DAGGERHEART", + daggerheart: { + id: 'daggerheart', + label: 'DAGGERHEART', folders: { - "adversaries": { - id: "adversaries", - keys: ["adversaries"], - label: "Adversaries", - type: ["adversary"], - listType: "adversaries" + adversaries: { + id: 'adversaries', + keys: ['adversaries'], + label: 'Adversaries', + type: ['adversary'], + listType: 'adversaries' }, - "ancestries": { - id: "ancestries", - keys: ["ancestries"], - label: "Ancestries", - type: ["ancestry"], + ancestries: { + id: 'ancestries', + keys: ['ancestries'], + label: 'Ancestries', + type: ['ancestry'], folders: { - "features": { - id: "features", - keys: ["ancestries"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['ancestries'], + label: 'Features', + type: ['feature'] } } }, - "equipments": { - id: "equipments", - keys: ["armors", "weapons", "consumables", "loot"], - label: "Equipment", - type: ["armor", "weapon", "consumable", "loot"], - listType: "items" + equipments: { + id: 'equipments', + keys: ['armors', 'weapons', 'consumables', 'loot'], + label: 'Equipment', + type: ['armor', 'weapon', 'consumable', 'loot'], + listType: 'items' }, - "classes": { - id: "classes", - keys: ["classes"], - label: "Classes", - type: ["class"], + classes: { + id: 'classes', + keys: ['classes'], + label: 'Classes', + type: ['class'], folders: { - "features": { - id: "features", - keys: ["classes"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['classes'], + label: 'Features', + type: ['feature'] }, - "items": { - id: "items", - keys: ["classes"], - label: "Items", - type: ["armor", "weapon", "consumable", "loot"], - listType: "items" + items: { + id: 'items', + keys: ['classes'], + label: 'Items', + type: ['armor', 'weapon', 'consumable', 'loot'], + listType: 'items' } }, - listType: "classes" + listType: 'classes' }, - "subclasses": { - id: "subclasses", - keys: ["subclasses"], - label: "Subclasses", - type: ["subclass"], - listType: "subclasses" + subclasses: { + id: 'subclasses', + keys: ['subclasses'], + label: 'Subclasses', + type: ['subclass'], + listType: 'subclasses' }, - "domains": { - id: "domains", - keys: ["domains"], - label: "Domain Cards", - type: ["domainCard"], - listType: "cards" + domains: { + id: 'domains', + keys: ['domains'], + label: 'Domain Cards', + type: ['domainCard'], + listType: 'cards' }, - "communities": { - id: "communities", - keys: ["communities"], - label: "Communities", - type: ["community"], + communities: { + id: 'communities', + keys: ['communities'], + label: 'Communities', + type: ['community'], folders: { - "features": { - id: "features", - keys: ["communities"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['communities'], + label: 'Features', + type: ['feature'] } } }, - "environments": { - id: "environments", - keys: ["environments"], - label: "Environments", - type: ["environment"] + environments: { + id: 'environments', + keys: ['environments'], + label: 'Environments', + type: ['environment'] }, - "beastforms": { - id: "beastforms", - keys: ["beastforms"], - label: "Beastforms", - type: ["beastform"], - listType: "beastforms", + beastforms: { + id: 'beastforms', + keys: ['beastforms'], + label: 'Beastforms', + type: ['beastform'], + listType: 'beastforms', folders: { - "features": { - id: "features", - keys: ["beastforms"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['beastforms'], + label: 'Features', + type: ['feature'] } } } } } -} \ No newline at end of file +}; diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 7dd7993c..ddcc5bf5 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,9 @@ 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 (!subclassState) continue; 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/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/data/item/subclass.mjs b/module/data/item/subclass.mjs index 46b83753..e16a15f7 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -1,3 +1,4 @@ +import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import ItemLinkFields from '../fields/itemLinkFields.mjs'; import BaseDataItem from './base.mjs'; @@ -25,7 +26,8 @@ export default class DHSubclass extends BaseDataItem { }), features: new ItemLinkFields(), featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }), - isMulticlass: new fields.BooleanField({ initial: false }) + isMulticlass: new fields.BooleanField({ initial: false }), + linkedClass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true, initial: null }) }; } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index e1dd93af..9a22eb44 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -1,7 +1,7 @@ import { emitAsGM, GMUpdateEvent } from '../systemRegistration/socket.mjs'; import { LevelOptionType } from '../data/levelTier.mjs'; import DHFeature from '../data/item/feature.mjs'; -import { damageKeyToNumber, versionCompare } from '../helpers/utils.mjs'; +import { damageKeyToNumber } from '../helpers/utils.mjs'; import DhCompanionLevelUp from '../applications/levelup/companionLevelup.mjs'; export default class DhpActor extends Actor { @@ -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( @@ -759,7 +759,7 @@ export default class DhpActor extends Actor { } const parsedJSON = JSON.parse(json); - if (versionCompare(parsedJSON._stats.systemVersion, '1.1.0')) { + if (foundry.utils.isNewerVersion('1.1.0', parsedJSON._stats.systemVersion)) { const confirmed = await foundry.applications.api.DialogV2.confirm({ window: { title: game.i18n.localize('DAGGERHEART.ACTORS.Character.InvalidOldCharacterImportTitle') diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index c8f4186f..6f4e5a26 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -420,14 +420,3 @@ export async function createEmbeddedItemsWithEffects(actor, baseData) { export const slugify = name => { return name.toLowerCase().replaceAll(' ', '-').replaceAll('.', ''); }; - -export const versionCompare = (current, target) => { - const currentSplit = current.split('.').map(x => Number.parseInt(x)); - const targetSplit = target.split('.').map(x => Number.parseInt(x)); - for (var i = 0; i < currentSplit.length; i++) { - if (currentSplit[i] < targetSplit[i]) return true; - if (currentSplit[i] > targetSplit[i]) return false; - } - - return false; -}; diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index e84018fa..da0dcb5d 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -1,10 +1,8 @@ -import { versionCompare } from '../helpers/utils.mjs'; - export async function runMigrations() { let lastMigrationVersion = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion); if (!lastMigrationVersion) lastMigrationVersion = '1.0.6'; - if (versionCompare(lastMigrationVersion, '1.1.0')) { + if (foundry.utils.isNewerVersion('1.1.0', lastMigrationVersion)) { const compendiumActors = []; for (let pack of game.packs) { const documents = await pack.getDocuments(); @@ -37,5 +35,45 @@ export async function runMigrations() { lastMigrationVersion = '1.1.0'; } + if (foundry.utils.isNewerVersion('1.1.1', lastMigrationVersion)) { + const compendiumClasses = []; + const compendiumActors = []; + for (let pack of game.packs) { + const documents = await pack.getDocuments(); + compendiumClasses.push(...documents.filter(x => x.type === 'class')); + compendiumActors.push(...documents.filter(x => x.type === 'character')); + } + + [...compendiumActors, ...game.actors.filter(x => x.type === 'character')].forEach(char => { + const multiclass = char.items.find(x => x.type === 'class' && x.system.isMulticlass); + const multiclassSubclass = multiclass.system.subclasses.length > 0 ? multiclass.system.subclasses[0] : null; + char.items.forEach(item => { + if (item.type === 'feature' && item.system.identifier === 'multiclass') { + const base = item.system.originItemType === 'class' ? multiclass : multiclassSubclass; + if (base) { + const baseFeature = base.system.features.find(x => x.item.name === item.name); + if (baseFeature) { + item.update({ + system: { + multiclassOrigin: true, + identifier: baseFeature.type + } + }); + } + } + } + }); + }); + + const worldClasses = game.items.filter(x => x.type === 'class'); + for (let classVal of [...compendiumClasses, ...worldClasses]) { + for (let subclass of classVal.system.subclasses) { + await subclass.update({ 'system.linkedClass': classVal.uuid }); + } + } + + lastMigrationVersion = '1.1.1'; + } + await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion); } diff --git a/src/packs/classes/class_Bard_vegl3bFOq3pcFTWT.json b/src/packs/classes/class_Bard_vegl3bFOq3pcFTWT.json index 836e49b5..5ffd8a11 100644 --- a/src/packs/classes/class_Bard_vegl3bFOq3pcFTWT.json +++ b/src/packs/classes/class_Bard_vegl3bFOq3pcFTWT.json @@ -70,12 +70,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754174600538, - "modifiedTime": 1754325498779, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943467705, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_id": "vegl3bFOq3pcFTWT", "sort": 300000, diff --git a/src/packs/classes/class_Druid_ZNwUTCyGCEcidZFv.json b/src/packs/classes/class_Druid_ZNwUTCyGCEcidZFv.json index 800598a6..086d363e 100644 --- a/src/packs/classes/class_Druid_ZNwUTCyGCEcidZFv.json +++ b/src/packs/classes/class_Druid_ZNwUTCyGCEcidZFv.json @@ -72,12 +72,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754222247012, - "modifiedTime": 1754325498779, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943479440, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!ZNwUTCyGCEcidZFv" } diff --git a/src/packs/classes/class_Guardian_nRAyoC0fOzXPDa4z.json b/src/packs/classes/class_Guardian_nRAyoC0fOzXPDa4z.json index 2d76ccfb..b50f86ef 100644 --- a/src/packs/classes/class_Guardian_nRAyoC0fOzXPDa4z.json +++ b/src/packs/classes/class_Guardian_nRAyoC0fOzXPDa4z.json @@ -68,12 +68,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754246931974, - "modifiedTime": 1754325498779, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943488697, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!nRAyoC0fOzXPDa4z" } diff --git a/src/packs/classes/class_Ranger_BTyfve69LKqoOi9S.json b/src/packs/classes/class_Ranger_BTyfve69LKqoOi9S.json index 17fb6b2d..62e51c7d 100644 --- a/src/packs/classes/class_Ranger_BTyfve69LKqoOi9S.json +++ b/src/packs/classes/class_Ranger_BTyfve69LKqoOi9S.json @@ -68,12 +68,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754268869310, - "modifiedTime": 1754325517617, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943505024, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!BTyfve69LKqoOi9S" } diff --git a/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json b/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json index 617ea0f0..146ad340 100644 --- a/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json +++ b/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json @@ -72,12 +72,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754325275832, - "modifiedTime": 1754500637635, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943515533, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!CvHlkHZfpMiCz5uT" } diff --git a/src/packs/classes/class_Seraph_5ZnlJ5bEoyOTkUJv.json b/src/packs/classes/class_Seraph_5ZnlJ5bEoyOTkUJv.json index b88da6c2..6a2b70a1 100644 --- a/src/packs/classes/class_Seraph_5ZnlJ5bEoyOTkUJv.json +++ b/src/packs/classes/class_Seraph_5ZnlJ5bEoyOTkUJv.json @@ -68,12 +68,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754351482530, - "modifiedTime": 1754355938087, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943523935, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!5ZnlJ5bEoyOTkUJv" } diff --git a/src/packs/classes/class_Sorcerer_DchOzHcWIJE9FKcR.json b/src/packs/classes/class_Sorcerer_DchOzHcWIJE9FKcR.json index 15e9bcce..0d3d71ac 100644 --- a/src/packs/classes/class_Sorcerer_DchOzHcWIJE9FKcR.json +++ b/src/packs/classes/class_Sorcerer_DchOzHcWIJE9FKcR.json @@ -76,12 +76,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754349743129, - "modifiedTime": 1754350005553, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943536635, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!DchOzHcWIJE9FKcR" } diff --git a/src/packs/classes/class_Warrior_xCUWwJz4WSthvLfy.json b/src/packs/classes/class_Warrior_xCUWwJz4WSthvLfy.json index 230c3a70..2d120f8e 100644 --- a/src/packs/classes/class_Warrior_xCUWwJz4WSthvLfy.json +++ b/src/packs/classes/class_Warrior_xCUWwJz4WSthvLfy.json @@ -72,12 +72,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754255776706, - "modifiedTime": 1754325510730, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943545980, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!xCUWwJz4WSthvLfy" } diff --git a/src/packs/classes/class_Wizard_5LwX4m8ziY3F1ZGC.json b/src/packs/classes/class_Wizard_5LwX4m8ziY3F1ZGC.json index 9a5790db..0955e68a 100644 --- a/src/packs/classes/class_Wizard_5LwX4m8ziY3F1ZGC.json +++ b/src/packs/classes/class_Wizard_5LwX4m8ziY3F1ZGC.json @@ -72,12 +72,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754253505323, - "modifiedTime": 1754325500455, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943555087, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!5LwX4m8ziY3F1ZGC" } diff --git a/src/packs/subclasses/subclass_Beastbound_TIUsIlTS1WkK5vr2.json b/src/packs/subclasses/subclass_Beastbound_TIUsIlTS1WkK5vr2.json index 824572e9..622fb36a 100644 --- a/src/packs/subclasses/subclass_Beastbound_TIUsIlTS1WkK5vr2.json +++ b/src/packs/subclasses/subclass_Beastbound_TIUsIlTS1WkK5vr2.json @@ -30,7 +30,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.BTyfve69LKqoOi9S" }, "effects": [], "sort": 0, @@ -43,12 +44,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754268237448, - "modifiedTime": 1754268308097, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943503629, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!TIUsIlTS1WkK5vr2" } diff --git a/src/packs/subclasses/subclass_Call_Of_The_Brave_NAFU9roaVG7f3RNJ.json b/src/packs/subclasses/subclass_Call_Of_The_Brave_NAFU9roaVG7f3RNJ.json index 51718237..46f7f2af 100644 --- a/src/packs/subclasses/subclass_Call_Of_The_Brave_NAFU9roaVG7f3RNJ.json +++ b/src/packs/subclasses/subclass_Call_Of_The_Brave_NAFU9roaVG7f3RNJ.json @@ -26,7 +26,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.xCUWwJz4WSthvLfy" }, "effects": [], "sort": 0, @@ -39,12 +40,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754256077777, - "modifiedTime": 1754256954656, - "lastModifiedBy": "MQSznptE5yLT7kj8" + "modifiedTime": 1755943544886, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!NAFU9roaVG7f3RNJ" } diff --git a/src/packs/subclasses/subclass_Call_Of_The_Slayer_bcNe5qP3o6CKadhK.json b/src/packs/subclasses/subclass_Call_Of_The_Slayer_bcNe5qP3o6CKadhK.json index ab0419d8..bbcf6ca6 100644 --- a/src/packs/subclasses/subclass_Call_Of_The_Slayer_bcNe5qP3o6CKadhK.json +++ b/src/packs/subclasses/subclass_Call_Of_The_Slayer_bcNe5qP3o6CKadhK.json @@ -22,7 +22,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.xCUWwJz4WSthvLfy" }, "effects": [], "sort": 0, @@ -35,12 +36,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754256112978, - "modifiedTime": 1754256959532, - "lastModifiedBy": "MQSznptE5yLT7kj8" + "modifiedTime": 1755943545973, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!bcNe5qP3o6CKadhK" } diff --git a/src/packs/subclasses/subclass_Divine_Wielder_M5mpGoAj8LRkylrY.json b/src/packs/subclasses/subclass_Divine_Wielder_M5mpGoAj8LRkylrY.json index e5f1f4c8..9a7b9c96 100644 --- a/src/packs/subclasses/subclass_Divine_Wielder_M5mpGoAj8LRkylrY.json +++ b/src/packs/subclasses/subclass_Divine_Wielder_M5mpGoAj8LRkylrY.json @@ -26,7 +26,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.5ZnlJ5bEoyOTkUJv" }, "effects": [], "sort": 0, @@ -39,12 +40,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754352806098, - "modifiedTime": 1754354057333, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943522722, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!M5mpGoAj8LRkylrY" } diff --git a/src/packs/subclasses/subclass_Elemental_Origin_wg1H0hROc2acHwZh.json b/src/packs/subclasses/subclass_Elemental_Origin_wg1H0hROc2acHwZh.json index b1e5f67e..f1f85e42 100644 --- a/src/packs/subclasses/subclass_Elemental_Origin_wg1H0hROc2acHwZh.json +++ b/src/packs/subclasses/subclass_Elemental_Origin_wg1H0hROc2acHwZh.json @@ -22,7 +22,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.DchOzHcWIJE9FKcR" }, "effects": [], "sort": 0, @@ -35,12 +36,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754349604941, - "modifiedTime": 1754349648910, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943535524, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!wg1H0hROc2acHwZh" } diff --git a/src/packs/subclasses/subclass_Nightwalker_h161OSIK24Up4qNd.json b/src/packs/subclasses/subclass_Nightwalker_h161OSIK24Up4qNd.json index 8da59a4c..49f9a520 100644 --- a/src/packs/subclasses/subclass_Nightwalker_h161OSIK24Up4qNd.json +++ b/src/packs/subclasses/subclass_Nightwalker_h161OSIK24Up4qNd.json @@ -30,7 +30,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.CvHlkHZfpMiCz5uT" }, "effects": [], "sort": 0, @@ -43,12 +44,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754322815758, - "modifiedTime": 1754323509061, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943514465, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!h161OSIK24Up4qNd" } diff --git a/src/packs/subclasses/subclass_Primal_Origin_GLpRVxnY5E82khxH.json b/src/packs/subclasses/subclass_Primal_Origin_GLpRVxnY5E82khxH.json index e3f38604..37619136 100644 --- a/src/packs/subclasses/subclass_Primal_Origin_GLpRVxnY5E82khxH.json +++ b/src/packs/subclasses/subclass_Primal_Origin_GLpRVxnY5E82khxH.json @@ -22,7 +22,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.DchOzHcWIJE9FKcR" }, "effects": [], "sort": 0, @@ -35,12 +36,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754349604941, - "modifiedTime": 1754349673276, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943536628, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!GLpRVxnY5E82khxH" } diff --git a/src/packs/subclasses/subclass_School_Of_Knowledge_qqQlgCqhOivUFoQn.json b/src/packs/subclasses/subclass_School_Of_Knowledge_qqQlgCqhOivUFoQn.json index 7dcbcf35..7ed07d06 100644 --- a/src/packs/subclasses/subclass_School_Of_Knowledge_qqQlgCqhOivUFoQn.json +++ b/src/packs/subclasses/subclass_School_Of_Knowledge_qqQlgCqhOivUFoQn.json @@ -34,7 +34,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.5LwX4m8ziY3F1ZGC" }, "effects": [], "sort": 0, @@ -47,12 +48,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754253538384, - "modifiedTime": 1754254543287, - "lastModifiedBy": "MQSznptE5yLT7kj8" + "modifiedTime": 1755943553625, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!qqQlgCqhOivUFoQn" } diff --git a/src/packs/subclasses/subclass_School_Of_War_4y9Ph7RsCIAbkwTk.json b/src/packs/subclasses/subclass_School_Of_War_4y9Ph7RsCIAbkwTk.json index 03af87fc..856031d8 100644 --- a/src/packs/subclasses/subclass_School_Of_War_4y9Ph7RsCIAbkwTk.json +++ b/src/packs/subclasses/subclass_School_Of_War_4y9Ph7RsCIAbkwTk.json @@ -34,7 +34,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.5LwX4m8ziY3F1ZGC" }, "effects": [], "sort": 0, @@ -47,12 +48,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754253587683, - "modifiedTime": 1754254721869, - "lastModifiedBy": "MQSznptE5yLT7kj8" + "modifiedTime": 1755943555081, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!4y9Ph7RsCIAbkwTk" } diff --git a/src/packs/subclasses/subclass_Stalwart_rKRxFBlkbh9cDK8K.json b/src/packs/subclasses/subclass_Stalwart_rKRxFBlkbh9cDK8K.json index 0e9ea4df..b75f88d0 100644 --- a/src/packs/subclasses/subclass_Stalwart_rKRxFBlkbh9cDK8K.json +++ b/src/packs/subclasses/subclass_Stalwart_rKRxFBlkbh9cDK8K.json @@ -34,7 +34,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.nRAyoC0fOzXPDa4z" }, "effects": [], "sort": 0, @@ -47,12 +48,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754245881893, - "modifiedTime": 1754245958817, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943487549, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!rKRxFBlkbh9cDK8K" } diff --git a/src/packs/subclasses/subclass_Syndicate_95QxNZwgyEm1LqdG.json b/src/packs/subclasses/subclass_Syndicate_95QxNZwgyEm1LqdG.json index 8d7285d4..2cef9bbd 100644 --- a/src/packs/subclasses/subclass_Syndicate_95QxNZwgyEm1LqdG.json +++ b/src/packs/subclasses/subclass_Syndicate_95QxNZwgyEm1LqdG.json @@ -22,7 +22,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.CvHlkHZfpMiCz5uT" }, "effects": [], "sort": 0, @@ -35,12 +36,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754323643089, - "modifiedTime": 1754323735227, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943515526, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!95QxNZwgyEm1LqdG" } diff --git a/src/packs/subclasses/subclass_Troubadour_ld8MIvk0xVJydSBz.json b/src/packs/subclasses/subclass_Troubadour_ld8MIvk0xVJydSBz.json index e50ecfa8..eb51d60e 100644 --- a/src/packs/subclasses/subclass_Troubadour_ld8MIvk0xVJydSBz.json +++ b/src/packs/subclasses/subclass_Troubadour_ld8MIvk0xVJydSBz.json @@ -21,7 +21,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.vegl3bFOq3pcFTWT" }, "effects": [], "ownership": { @@ -33,12 +34,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754174653653, - "modifiedTime": 1754236659263, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943465827, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_id": "ld8MIvk0xVJydSBz", "sort": 100000, diff --git a/src/packs/subclasses/subclass_Vengeance_SUo8NPBPO8aN193u.json b/src/packs/subclasses/subclass_Vengeance_SUo8NPBPO8aN193u.json index 53f7cf96..fedf5f1a 100644 --- a/src/packs/subclasses/subclass_Vengeance_SUo8NPBPO8aN193u.json +++ b/src/packs/subclasses/subclass_Vengeance_SUo8NPBPO8aN193u.json @@ -26,7 +26,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.nRAyoC0fOzXPDa4z" }, "effects": [], "sort": 0, @@ -39,12 +40,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754246011733, - "modifiedTime": 1754246076491, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943488691, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!SUo8NPBPO8aN193u" } diff --git a/src/packs/subclasses/subclass_Warden_of_Renewal_xp0XMjYT85Q7E90o.json b/src/packs/subclasses/subclass_Warden_of_Renewal_xp0XMjYT85Q7E90o.json index 08421469..abe97d5e 100644 --- a/src/packs/subclasses/subclass_Warden_of_Renewal_xp0XMjYT85Q7E90o.json +++ b/src/packs/subclasses/subclass_Warden_of_Renewal_xp0XMjYT85Q7E90o.json @@ -29,7 +29,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.ZNwUTCyGCEcidZFv" }, "effects": [], "folder": "AZWrSJzGXltzQhAJ", @@ -43,12 +44,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754221346981, - "modifiedTime": 1754236671909, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943479431, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!xp0XMjYT85Q7E90o" } diff --git a/src/packs/subclasses/subclass_Warden_of_the_Elements_W9hs5kxOWeY7eA4Q.json b/src/packs/subclasses/subclass_Warden_of_the_Elements_W9hs5kxOWeY7eA4Q.json index 0e4972f6..43642e89 100644 --- a/src/packs/subclasses/subclass_Warden_of_the_Elements_W9hs5kxOWeY7eA4Q.json +++ b/src/packs/subclasses/subclass_Warden_of_the_Elements_W9hs5kxOWeY7eA4Q.json @@ -21,7 +21,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.ZNwUTCyGCEcidZFv" }, "effects": [], "folder": "AZWrSJzGXltzQhAJ", @@ -35,12 +36,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754221102716, - "modifiedTime": 1754236671090, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943478132, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!W9hs5kxOWeY7eA4Q" } diff --git a/src/packs/subclasses/subclass_Wayfinder_zsUglcU4NgZ8tNgZ.json b/src/packs/subclasses/subclass_Wayfinder_zsUglcU4NgZ8tNgZ.json index 4f9a2289..a308d587 100644 --- a/src/packs/subclasses/subclass_Wayfinder_zsUglcU4NgZ8tNgZ.json +++ b/src/packs/subclasses/subclass_Wayfinder_zsUglcU4NgZ8tNgZ.json @@ -26,7 +26,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.BTyfve69LKqoOi9S" }, "effects": [], "sort": 0, @@ -39,12 +40,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754268318903, - "modifiedTime": 1754268377047, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943505016, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!zsUglcU4NgZ8tNgZ" } diff --git a/src/packs/subclasses/subclass_Winged_Sentinel_y7ERWRIpJsdP9Re4.json b/src/packs/subclasses/subclass_Winged_Sentinel_y7ERWRIpJsdP9Re4.json index 6da6a117..f71a1fcb 100644 --- a/src/packs/subclasses/subclass_Winged_Sentinel_y7ERWRIpJsdP9Re4.json +++ b/src/packs/subclasses/subclass_Winged_Sentinel_y7ERWRIpJsdP9Re4.json @@ -26,7 +26,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.5ZnlJ5bEoyOTkUJv" }, "effects": [], "sort": 0, @@ -39,12 +40,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754354451615, - "modifiedTime": 1754355901649, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1755943523928, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_key": "!items!y7ERWRIpJsdP9Re4" } diff --git a/src/packs/subclasses/subclass_Wordsmith_XTSODVM8st75Os8M.json b/src/packs/subclasses/subclass_Wordsmith_XTSODVM8st75Os8M.json index f4c35265..6c975ca6 100644 --- a/src/packs/subclasses/subclass_Wordsmith_XTSODVM8st75Os8M.json +++ b/src/packs/subclasses/subclass_Wordsmith_XTSODVM8st75Os8M.json @@ -25,7 +25,8 @@ } ], "featureState": 1, - "isMulticlass": false + "isMulticlass": false, + "linkedClass": "Compendium.daggerheart.classes.Item.vegl3bFOq3pcFTWT" }, "effects": [], "ownership": { @@ -37,12 +38,12 @@ "compendiumSource": null, "duplicateSource": null, "exportSource": null, - "coreVersion": "13.346", + "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "0.0.1", + "systemVersion": "1.1.0", "createdTime": 1754174655078, - "modifiedTime": 1754236660088, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1755943467695, + "lastModifiedBy": "tt3PwMBXcTLCtIQU" }, "_id": "XTSODVM8st75Os8M", "sort": 200000, diff --git a/styles/less/ui/item-browser/item-browser.less b/styles/less/ui/item-browser/item-browser.less index df35d60b..407a3116 100644 --- a/styles/less/ui/item-browser/item-browser.less +++ b/styles/less/ui/item-browser/item-browser.less @@ -356,6 +356,8 @@ display: grid; grid-template-rows: 0fr; transition: all 0.3s ease-in-out; + width: 100%; + .wrapper { overflow: hidden; display: grid; diff --git a/system.json b/system.json index d72c53d5..31130bb8 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.1.0", + "version": "1.1.1", "compatibility": { "minimum": "13", "verified": "13.347", From fbeff1b90863c1fecdc42b6ea65a7d433db47d86 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 02:21:00 +0200 Subject: [PATCH 13/22] The basic attack damage shown in the sidebar is modified if horde damage is active (#1071) --- module/data/action/attackAction.mjs | 8 +++++--- module/data/actor/adversary.mjs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs index 62463d15..68afc23b 100644 --- a/module/data/action/attackAction.mjs +++ b/module/data/action/attackAction.mjs @@ -51,11 +51,13 @@ export default class DHAttackAction extends DHDamageAction { const labels = []; const { roll, range, damage } = this; - if (roll.trait) labels.push(game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${roll.trait}.short`)) + if (roll.trait) labels.push(game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${roll.trait}.short`)); if (range) labels.push(game.i18n.localize(`DAGGERHEART.CONFIG.Range.${range}.short`)); - for (const { value, type } of damage.parts) { - const str = Roll.replaceFormulaData(value.getFormula(), this.actor?.getRollData() ?? {}); + const useAltDamage = this.actor?.effects?.find(x => x.type === 'horde')?.active; + for (const { value, valueAlt, type } of damage.parts) { + const usedValue = useAltDamage ? valueAlt : value; + const str = Roll.replaceFormulaData(usedValue.getFormula(), this.actor?.getRollData() ?? {}); const icons = Array.from(type) .map(t => CONFIG.DH.GENERAL.damageTypes[t]?.icon) diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index e64c64f3..a4dfddf5 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -129,7 +129,7 @@ export default class DhpAdversary extends BaseDataActor { CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation ).hordeDamage; - if (autoHordeDamage && changes.system?.resources?.hitPoints?.value) { + if (autoHordeDamage && changes.system?.resources?.hitPoints?.value !== undefined) { const hordeActiveEffect = this.parent.effects.find(x => x.type === 'horde'); if (hordeActiveEffect) { const halfHP = Math.ceil(this.resources.hitPoints.max / 2); From 16173363d4450f4e0c9856b2bc58a1317bd85f8e Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 02:24:57 +0200 Subject: [PATCH 14/22] [Feature] 687 - Companion Improvements (#1049) * Companions can't be put into CombatState anymore. Companions now have a Action Roll button * Added handling for multiselect toggleCombat --- module/applications/hud/tokenHUD.mjs | 25 +++++++++- .../applications/sheets/actors/companion.mjs | 47 +++++++++++++++++++ .../less/sheets/actors/companion/details.less | 13 +++++ templates/sheets/actors/companion/details.hbs | 3 ++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs index 5c29260b..48d5ac89 100644 --- a/module/applications/hud/tokenHUD.mjs +++ b/module/applications/hud/tokenHUD.mjs @@ -1,6 +1,9 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { static DEFAULT_OPTIONS = { - classes: ['daggerheart'] + classes: ['daggerheart'], + actions: { + combat: DHTokenHUD.#onToggleCombat + } }; /** @override */ @@ -11,8 +14,14 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { } }; + static #nonCombatTypes = ['environment', 'companion']; + async _prepareContext(options) { const context = await super._prepareContext(options); + + context.canToggleCombat = DHTokenHUD.#nonCombatTypes.includes(this.actor.type) + ? false + : context.canToggleCombat; context.systemStatusEffects = Object.keys(context.statusEffects).reduce((acc, key) => { const effect = context.statusEffects[key]; if (effect.systemEffect) acc[key] = effect; @@ -36,6 +45,20 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { return context; } + static async #onToggleCombat() { + const tokens = canvas.tokens.controlled + .filter(t => !t.actor || !DHTokenHUD.#nonCombatTypes.includes(t.actor.type)) + .map(t => t.document); + if (!this.object.controlled) tokens.push(this.document); + + try { + if (this.document.inCombat) await TokenDocument.implementation.deleteCombatants(tokens); + else await TokenDocument.implementation.createCombatants(tokens); + } catch (err) { + ui.notifications.warn(err.message); + } + } + _getStatusEffectChoices() { // Include all HUD-enabled status effects const choices = {}; diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index 2b82f50a..82aee312 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -8,6 +8,7 @@ export default class DhCompanionSheet extends DHBaseActorSheet { classes: ['actor', 'companion'], position: { width: 340 }, actions: { + actionRoll: DhCompanionSheet.#actionRoll, levelManagement: DhCompanionSheet.#levelManagement } }; @@ -45,6 +46,52 @@ export default class DhCompanionSheet extends DHBaseActorSheet { /* Application Clicks Actions */ /* -------------------------------------------- */ + /** + * + */ + static async #actionRoll(event) { + const partner = this.actor.system.partner; + const config = { + event, + title: `${game.i18n.localize('DAGGERHEART.GENERAL.Roll.action')}: ${this.actor.name}`, + headerTitle: `Companion ${game.i18n.localize('DAGGERHEART.GENERAL.Roll.action')}`, + roll: { + trait: partner.system.spellcastModifierTrait?.key + }, + hasRoll: true, + data: partner.getRollData() + }; + + const result = await partner.diceRoll(config); + this.consumeResource(result?.costs); + } + + // Remove when Action Refactor part #2 done + async consumeResource(costs) { + if (!costs?.length) return; + + const partner = this.actor.system.partner; + const usefulResources = { + ...foundry.utils.deepClone(partner.system.resources), + fear: { + value: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear), + max: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear, + reversed: false + } + }; + const resources = game.system.api.fields.ActionFields.CostField.getRealCosts(costs).map(c => { + const resource = usefulResources[c.key]; + return { + key: c.key, + value: (c.total ?? c.value) * (resource.isReversed ? 1 : -1), + target: resource.target, + keyIsID: resource.keyIsID + }; + }); + + await partner.modifyResource(resources); + } + /** * Opens the companions level management window. * @type {ApplicationClickAction} diff --git a/styles/less/sheets/actors/companion/details.less b/styles/less/sheets/actors/companion/details.less index 2df14b23..cbdc25e6 100644 --- a/styles/less/sheets/actors/companion/details.less +++ b/styles/less/sheets/actors/companion/details.less @@ -77,4 +77,17 @@ } } } + + .action-section { + display: flex; + padding: 0 10px; + margin-top: 20px; + width: 100%; + + button { + height: 40px; + width: 100%; + font-weight: 600; + } + } } diff --git a/templates/sheets/actors/companion/details.hbs b/templates/sheets/actors/companion/details.hbs index dd28e745..eee2122c 100644 --- a/templates/sheets/actors/companion/details.hbs +++ b/templates/sheets/actors/companion/details.hbs @@ -56,4 +56,7 @@ {{/each}} +
+ +
\ No newline at end of file From 661808b5f153522d3b4374ea99694633b949c86a Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 02:33:54 +0200 Subject: [PATCH 15/22] Fixed so observer permission doesn't allow using or editing anything (#1073) --- module/applications/sheets/actors/character.mjs | 9 +++++++++ styles/less/sheets/actors/character/sheet.less | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 0328f0dd..465da28d 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -15,6 +15,8 @@ export default class CharacterSheet extends DHBaseActorSheet { static DEFAULT_OPTIONS = { classes: ['character'], position: { width: 850, height: 800 }, + /* Foundry adds disabled to all buttons and inputs if editPermission is missing. This is not desired. */ + editPermission: CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, actions: { toggleVault: CharacterSheet.#toggleVault, rollAttribute: CharacterSheet.#rollAttribute, @@ -148,6 +150,13 @@ export default class CharacterSheet extends DHBaseActorSheet { .querySelector('.level-value') ?.addEventListener('change', event => this.document.updateLevel(Number(event.currentTarget.value))); + const observer = this.document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, { + exact: true + }); + if (observer) { + this.element.querySelector('.window-content').classList.add('viewMode'); + } + this._createFilterMenus(); this._createSearchFilter(); } diff --git a/styles/less/sheets/actors/character/sheet.less b/styles/less/sheets/actors/character/sheet.less index 68792c99..ee6580fd 100644 --- a/styles/less/sheets/actors/character/sheet.less +++ b/styles/less/sheets/actors/character/sheet.less @@ -11,6 +11,21 @@ padding-bottom: 0; overflow-x: auto; + &.viewMode { + button:not(.btn-toggle-view), + input:not(.search), + .controls, + .character-sidebar-sheet, + .img-portait, + .name-row, + .hope-section, + .downtime-section, + .character-traits, + .card-list { + pointer-events: none; + } + } + .character-sidebar-sheet { grid-row: 1 / span 2; grid-column: 1; From 2a0d748b5ee06133e3bfe9fb976b2ed59a6d46b3 Mon Sep 17 00:00:00 2001 From: Murilo Brito <91566541+moliloo@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:52:18 -0300 Subject: [PATCH 16/22] [Bugfix] Fix light theme to roll messages (#1066) * fix light theme to roll messages * fix light theme issues * finally fix issues --------- Co-authored-by: WBHarry --- lang/en.json | 2 +- module/canvas/placeables/measuredTemplate.mjs | 6 +- module/data/fields/action/damageField.mjs | 20 +- module/data/item/weapon.mjs | 2 +- .../dialog/downtime/downtime-container.less | 2 +- styles/less/ui/chat/ability-use.less | 288 +++++++++--------- styles/less/ui/chat/action.less | 249 +++++++-------- styles/less/ui/chat/chat.less | 137 +++++++-- styles/less/ui/chat/downtime.less | 220 ++++++------- styles/less/ui/chat/sheet.less | 14 +- templates/ui/chat/resource-roll.hbs | 6 +- 11 files changed, 523 insertions(+), 423 deletions(-) diff --git a/lang/en.json b/lang/en.json index beeffd41..26eec167 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2385,7 +2385,7 @@ "subtype": "Subtype", "folders": { "adversaries": "Adversaries", - "ancestries": "Ancestries", + "ancestries": "Ancestries", "equipment": "Equipment", "classes": "Classes", "subclasses": "Subclasses", diff --git a/module/canvas/placeables/measuredTemplate.mjs b/module/canvas/placeables/measuredTemplate.mjs index 83cddfe1..f3691bb8 100644 --- a/module/canvas/placeables/measuredTemplate.mjs +++ b/module/canvas/placeables/measuredTemplate.mjs @@ -11,19 +11,19 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur if (splitRulerText.length > 0) { const rulerValue = Number(splitRulerText[0]); const result = DhMeasuredTemplate.getRangeLabels(rulerValue, rangeMeasurementSettings); - this.ruler.text = result.distance + (result.units ? (' ' + result.units) : ''); + this.ruler.text = result.distance + (result.units ? ' ' + result.units : ''); } } } static getRangeLabels(distanceValue, settings) { - let result = { distance: distanceValue, units: '' } + let result = { distance: distanceValue, units: '' }; const rangeMeasurementOverride = canvas.scene.flags.daggerheart?.rangeMeasurementOverride; if (rangeMeasurementOverride === true) { result.distance = distanceValue; result.units = canvas.scene?.grid?.units; - return result + return result; } if (distanceValue <= settings.melee) { result.distance = game.i18n.localize('DAGGERHEART.CONFIG.Range.melee.name'); diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 7f1b61e9..4b4dee7d 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -23,14 +23,22 @@ export class DHActionDiceData extends foundry.abstract.DataModel { multiplier: new fields.StringField({ choices: CONFIG.DH.GENERAL.multiplierTypes, initial: 'prof', - label: "DAGGERHEART.ACTIONS.Config.damage.multiplier" + label: 'DAGGERHEART.ACTIONS.Config.damage.multiplier' }), - flatMultiplier: new fields.NumberField({ nullable: true, initial: 1, label: "DAGGERHEART.ACTIONS.Config.damage.flatMultiplier" }), - dice: new fields.StringField({ choices: CONFIG.DH.GENERAL.diceTypes, initial: 'd6', label: "DAGGERHEART.GENERAL.Dice.single" }), - bonus: new fields.NumberField({ nullable: true, initial: null, label: "DAGGERHEART.GENERAL.bonus" }), + flatMultiplier: new fields.NumberField({ + nullable: true, + initial: 1, + label: 'DAGGERHEART.ACTIONS.Config.damage.flatMultiplier' + }), + dice: new fields.StringField({ + choices: CONFIG.DH.GENERAL.diceTypes, + initial: 'd6', + label: 'DAGGERHEART.GENERAL.Dice.single' + }), + bonus: new fields.NumberField({ nullable: true, initial: null, label: 'DAGGERHEART.GENERAL.bonus' }), custom: new fields.SchemaField({ - enabled: new fields.BooleanField({ label: "DAGGERHEART.ACTIONS.Config.general.customFormula" }), - formula: new FormulaField({ label: "DAGGERHEART.ACTIONS.Config.general.formula", initial: '' }) + enabled: new fields.BooleanField({ label: 'DAGGERHEART.ACTIONS.Config.general.customFormula' }), + formula: new FormulaField({ label: 'DAGGERHEART.ACTIONS.Config.general.formula', initial: '' }) }) }; } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index ee4b997c..07a5c028 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -199,7 +199,7 @@ export default class DHWeapon extends AttachableItem { ]; for (const { value, type } of attack.damage.parts) { - const parts = value.custom.enabled ? [game.i18n.localize("DAGGERHEART.GENERAL.custom")] : [value.dice]; + const parts = value.custom.enabled ? [game.i18n.localize('DAGGERHEART.GENERAL.custom')] : [value.dice]; if (!value.custom.enabled && value.bonus) parts.push(value.bonus.signedString()); if (type.size > 0) { diff --git a/styles/less/dialog/downtime/downtime-container.less b/styles/less/dialog/downtime/downtime-container.less index 16edd3b0..eb615ef0 100644 --- a/styles/less/dialog/downtime/downtime-container.less +++ b/styles/less/dialog/downtime/downtime-container.less @@ -35,7 +35,7 @@ gap: 4px; .activity-marker { - font-size: .5rem; + font-size: 0.5rem; flex: none; color: light-dark(@dark-blue, @golden); margin-right: 4px; diff --git a/styles/less/ui/chat/ability-use.less b/styles/less/ui/chat/ability-use.less index d313638f..88302d0d 100644 --- a/styles/less/ui/chat/ability-use.less +++ b/styles/less/ui/chat/ability-use.less @@ -1,144 +1,144 @@ -@import '../../utils/colors.less'; -@import '../../utils/fonts.less'; -@import '../../utils/spacing.less'; - -.theme-light { - .daggerheart.chat.domain-card { - .domain-card-move .domain-card-header { - border-bottom: 1px solid @dark-blue; - - &:hover { - background: @dark-blue-10; - } - - .domain-label { - .title { - color: @dark-blue; - } - - .tags .tag { - background: @dark-15; - border: 1px solid @dark; - color: @dark; - } - } - - .fa-chevron-down { - color: @dark-blue; - } - } - - .description { - color: @dark; - } - } -} - -.daggerheart.chat { - &.domain-card { - display: flex; - flex-direction: column; - align-items: center; - - .card-img { - width: 100%; - height: 200px; - mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 90%, transparent 100%); - object-fit: cover; - } - - details[open] { - .fa-chevron-down { - transform: rotate(180deg); - transition: all 0.3s ease; - } - } - - .domain-card-move { - width: 100%; - - .fa-chevron-down { - transition: all 0.3s ease; - margin-left: auto; - } - - .domain-card-header { - display: flex; - flex-direction: row; - align-items: center; - margin: 8px; - padding-bottom: 5px; - width: -webkit-fill-available; - gap: 5px; - border-bottom: 1px solid @golden; - - &:hover { - background: @golden-10; - cursor: pointer; - transition: all 0.3s ease; - } - - .domain-label { - display: flex; - flex-direction: column; - width: 100%; - padding-bottom: 5px; - width: -webkit-fill-available; - gap: 5px; - - .title { - font-size: var(--font-size-20); - color: @golden; - font-weight: 700; - } - - .tags { - display: flex; - gap: 10px; - flex-wrap: wrap; - - .tag { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding: 3px 5px; - font-size: var(--font-size-12); - - background: @beige-15; - border: 1px solid @beige; - color: @beige; - border-radius: 3px; - } - } - } - } - } - - .description { - padding: 8px; - } - - .ability-card-footer { - display: flex; - flex-wrap: wrap; - gap: 5px; - width: 100%; - padding: 0 8px; - - button { - height: 40px; - flex: 1 1 calc(50% - 5px); - - &:nth-last-child(1):nth-child(odd) { - flex-basis: 100%; - } - } - - .ability-card-action-cost { - margin: auto; - font-size: 1.5em; - } - } - } -} +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; +@import '../../utils/spacing.less'; + +#interface.theme-light { + .daggerheart.chat.domain-card { + .domain-card-move .domain-card-header { + border-bottom: 1px solid @dark-blue; + + &:hover { + background: @dark-blue-10; + } + + .domain-label { + .title { + color: @dark-blue; + } + + .tags .tag { + background: @dark-15; + border: 1px solid @dark; + color: @dark; + } + } + + .fa-chevron-down { + color: @dark-blue; + } + } + + .description { + color: @dark; + } + } +} + +.daggerheart.chat { + &.domain-card { + display: flex; + flex-direction: column; + align-items: center; + + .card-img { + width: 100%; + height: 200px; + mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 90%, transparent 100%); + object-fit: cover; + } + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .domain-card-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .domain-card-header { + display: flex; + flex-direction: row; + align-items: center; + margin: 8px; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + border-bottom: 1px solid @golden; + + &:hover { + background: @golden-10; + cursor: pointer; + transition: all 0.3s ease; + } + + .domain-label { + display: flex; + flex-direction: column; + width: 100%; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + + .title { + font-size: var(--font-size-20); + color: @golden; + font-weight: 700; + } + + .tags { + display: flex; + gap: 10px; + flex-wrap: wrap; + + .tag { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 5px; + font-size: var(--font-size-12); + + background: @beige-15; + border: 1px solid @beige; + color: @beige; + border-radius: 3px; + } + } + } + } + } + + .description { + padding: 8px; + } + + .ability-card-footer { + display: flex; + flex-wrap: wrap; + gap: 5px; + width: 100%; + padding: 0 8px; + + button { + height: 40px; + flex: 1 1 calc(50% - 5px); + + &:nth-last-child(1):nth-child(odd) { + flex-basis: 100%; + } + } + + .ability-card-action-cost { + margin: auto; + font-size: 1.5em; + } + } + } +} diff --git a/styles/less/ui/chat/action.less b/styles/less/ui/chat/action.less index a849315a..817b0acd 100644 --- a/styles/less/ui/chat/action.less +++ b/styles/less/ui/chat/action.less @@ -1,124 +1,125 @@ -@import '../../utils/colors.less'; -@import '../../utils/fonts.less'; -@import '../../utils/spacing.less'; - -.theme-light { - .daggerheart.chat.action { - .action-move .action-section { - border-bottom: 1px solid @dark-blue; - - &:hover { - background: @dark-blue-10; - } - - .action-header { - .title { - color: @dark-blue; - } - .label { - color: @dark; - } - } - - .fa-chevron-down { - color: @dark-blue; - } - } - - .description { - color: @dark; - } - } -} - -.daggerheart.chat { - &.action { - display: flex; - flex-direction: column; - align-items: center; - - details[open] { - .fa-chevron-down { - transform: rotate(180deg); - transition: all 0.3s ease; - } - } - - .action-move { - width: 100%; - - .fa-chevron-down { - transition: all 0.3s ease; - margin-left: auto; - } - - .action-section { - display: flex; - flex-direction: row; - align-items: center; - margin: 8px 8px 0; - padding-bottom: 5px; - width: -webkit-fill-available; - gap: 5px; - border-bottom: 1px solid @golden; - - &:hover { - background: @golden-10; - cursor: pointer; - transition: all 0.3s ease; - } - - .action-img { - width: 40px; - height: 40px; - border-radius: 3px; - object-fit: cover; - } - - .action-header { - display: flex; - flex-direction: column; - gap: 5px; - - .title { - font-size: var(--font-size-20); - color: @golden; - font-weight: 700; - } - - .label { - font-size: var(--font-size-12); - color: @beige; - margin: 0; - } - } - } - } - - .description { - padding: 8px; - } - - .ability-card-footer { - display: flex; - flex-wrap: wrap; - gap: 5px; - width: 100%; - padding: 0 8px; - - button { - height: 40px; - flex: 1 1 calc(50% - 5px); - - &:nth-last-child(1):nth-child(odd) { - flex-basis: 100%; - } - } - - .ability-card-action-cost { - margin: auto; - font-size: 1.5em; - } - } - } -} +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; +@import '../../utils/spacing.less'; + +#interface.theme-light { + .daggerheart.chat.action { + .action-move .action-section { + border-bottom: 1px solid @dark-blue; + + &:hover { + background: @dark-blue-10; + } + + .action-header { + .title { + color: @dark-blue; + } + .label { + color: @dark; + } + } + + .fa-chevron-down { + color: @dark-blue; + } + } + + .description { + color: @dark; + } + } +} + +.daggerheart.chat { + &.action { + display: flex; + flex-direction: column; + align-items: center; + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .action-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .action-section { + display: flex; + flex-direction: row; + align-items: center; + margin: 8px 8px 0; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + border-bottom: 1px solid @golden; + + &:hover { + background: @golden-10; + cursor: pointer; + transition: all 0.3s ease; + } + + .action-img { + width: 40px; + height: 40px; + border-radius: 3px; + object-fit: cover; + } + + .action-header { + display: flex; + flex-direction: column; + gap: 5px; + color: @beige; + + .title { + font-size: var(--font-size-20); + color: @golden; + font-weight: 700; + } + + .label { + font-size: var(--font-size-12); + color: @beige; + margin: 0; + } + } + } + } + + .description { + padding: 8px; + } + + .ability-card-footer { + display: flex; + flex-wrap: wrap; + gap: 5px; + width: 100%; + padding: 0 8px; + + button { + height: 40px; + flex: 1 1 calc(50% - 5px); + + &:nth-last-child(1):nth-child(odd) { + flex-basis: 100%; + } + } + + .ability-card-action-cost { + margin: auto; + font-size: 1.5em; + } + } + } +} diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 9eb35cd6..828e2774 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -2,52 +2,137 @@ @import '../../utils/fonts.less'; @import '../../utils/spacing.less'; -.theme-light { - .daggerheart, - #chat-notifications { +#interface.theme-light { + .daggerheart.chat-sidebar .chat-log, + #chat-notifications .chat-log { --text-color: @dark-blue; --bg-color: @dark-blue-40; - .message-content .chat-roll { - .roll-part-header { - span, - span:before, - span:after { - color: @dark-blue; - } - &:before { - background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, @dark-blue 100%); - color: @dark-blue; + .chat-message { + .roll-formula { + background: @dark-15; + color: @dark; + } + + &.duality { + background-image: url(../assets/parchments/dh-parchment-dark.png); + + .message-content { + color: @beige; } - &:after { - background: linear-gradient(90deg, @dark-blue 0%, rgba(0, 0, 0, 0) 100%); - color: @dark-blue; + .roll-formula { + background: @dark-15; + color: @dark; + } + + .message-header { + .message-sub-header-container { + color: @beige; + h4 { + color: @golden; + } + } + .message-header-metadata { + .message-metadata { + color: @beige; + } + } + } + + &.hope { + --text-color: @golden; + --bg-color: @golden-40; + .message-header, + .message-content { + background-color: @golden-bg; + } + .roll-formula { + background: var(--bg-color); + color: var(--text-color); + } + } + + &.fear { + --text-color: @chat-blue; + --bg-color: @chat-blue-40; + .message-header, + .message-content { + background-color: @chat-blue-bg; + } + .roll-formula { + background: var(--bg-color); + color: var(--text-color); + } + } + + &.critical { + --text-color: @chat-purple; + --bg-color: @chat-purple-40; + .message-header, + .message-content { + background-color: @chat-purple-bg; + } + .roll-formula { + background: var(--bg-color); + color: var(--text-color); + } } } - .roll-section { - .roll-part-content { - .roll-result-value { + + &:not(.duality) { + .font-20 { + color: @dark; + } + + .roll-die { + color: @beige; + } + + fieldset { + color: @dark-blue; + border-color: @dark-blue; + + legend { color: @dark-blue; } + } + .chat-roll { + .roll-part-header { + color: @dark-blue; - .dice-tooltip .wrapper .roll-die { - color: @beige; + span::before, + span::after { + color: @dark-blue; + } + + &:before { + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, @dark-blue 100%); + } + + &:after { + background: linear-gradient(90deg, @dark-blue 0%, rgba(0, 0, 0, 0) 100%); + } + } + + .roll-part-content { + &.dice-result { + color: @dark; + } + .roll-result-container { + color: @dark-blue; + } } } } } - - .chat-message .roll-formula { - background: @dark-15; - color: @dark; - } } } .daggerheart.chat { &.resource-roll { .reroll-message { + color: @beige; text-align: center; font-size: var(--font-size-18); margin-bottom: 0; diff --git a/styles/less/ui/chat/downtime.less b/styles/less/ui/chat/downtime.less index ca29e85f..5496a2a3 100644 --- a/styles/less/ui/chat/downtime.less +++ b/styles/less/ui/chat/downtime.less @@ -1,110 +1,110 @@ -@import '../../utils/colors.less'; -@import '../../utils/fonts.less'; -@import '../../utils/spacing.less'; - -.theme-light { - .daggerheart.chat.downtime { - .downtime-moves-list .downtime-move { - &:hover { - background: @dark-blue-10; - } - - .downtime-label { - border-bottom: 1px solid @dark-blue; - - .header-label .title { - color: @dark-blue; - } - .header-label .label { - color: @dark; - } - } - - .fa-chevron-down { - color: @dark-blue; - } - } - - .description { - color: @dark; - } - } -} - -.daggerheart.chat { - &.downtime { - display: flex; - flex-direction: column; - align-items: center; - - details[open] { - .fa-chevron-down { - transform: rotate(180deg); - transition: all 0.3s ease; - } - } - - .downtime-moves-list { - display: flex; - flex-direction: column; - gap: 5px; - width: 100%; - - .fa-chevron-down { - transition: all 0.3s ease; - margin-left: auto; - } - - .downtime-move { - width: 100%; - - .downtime-label { - display: flex; - align-items: center; - gap: 5px; - border-bottom: 1px solid @golden; - margin: 0 8px; - padding-bottom: 5px; - width: -webkit-fill-available; - - &:hover { - background: light-dark(@dark-blue-10, @golden-10); - cursor: pointer; - transition: all 0.3s ease; - } - - .downtime-image { - width: 40px; - height: 40px; - border-radius: 3px; - } - - .header-label { - padding: 8px; - .title { - font-size: var(--font-size-16); - color: @golden; - font-weight: 700; - } - .label { - font-size: var(--font-size-12); - color: @beige; - margin: 0; - } - } - } - - .description { - padding: 8px; - } - } - - .action-use-button { - width: -webkit-fill-available; - margin: 0 8px; - font-weight: 600; - height: 40px; - } - } - } -} +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; +@import '../../utils/spacing.less'; + +#interface.theme-light { + .daggerheart.chat.downtime { + .downtime-moves-list .downtime-move { + &:hover { + background: @dark-blue-10; + } + + .downtime-label { + border-bottom: 1px solid @dark-blue; + + .header-label .title { + color: @dark-blue; + } + .header-label .label { + color: @dark; + } + } + + .fa-chevron-down { + color: @dark-blue; + } + } + + .description { + color: @dark; + } + } +} + +.daggerheart.chat { + &.downtime { + display: flex; + flex-direction: column; + align-items: center; + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .downtime-moves-list { + display: flex; + flex-direction: column; + gap: 5px; + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .downtime-move { + width: 100%; + + .downtime-label { + display: flex; + align-items: center; + gap: 5px; + border-bottom: 1px solid @golden; + margin: 0 8px; + padding-bottom: 5px; + width: -webkit-fill-available; + + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; + } + + .downtime-image { + width: 40px; + height: 40px; + border-radius: 3px; + } + + .header-label { + padding: 8px; + .title { + font-size: var(--font-size-16); + color: @golden; + font-weight: 700; + } + .label { + font-size: var(--font-size-12); + color: @beige; + margin: 0; + } + } + } + + .description { + padding: 8px; + } + } + + .action-use-button { + width: -webkit-fill-available; + margin: 0 8px; + font-weight: 600; + height: 40px; + } + } + } +} diff --git a/styles/less/ui/chat/sheet.less b/styles/less/ui/chat/sheet.less index 59fa39dc..3d47a9b5 100644 --- a/styles/less/ui/chat/sheet.less +++ b/styles/less/ui/chat/sheet.less @@ -1,8 +1,8 @@ @import '../../utils/colors.less'; @import '../../utils/fonts.less'; -.theme-light { - .chat-message .message-content { +#interface.theme-light { + .chat-message:not(.duality) .message-content { color: @dark; blockquote { @@ -58,6 +58,12 @@ font-family: @font-body; font-weight: bold; } + + .dice-roll .dice-formula, + .dice-roll .dice-total { + background: @dark-blue-40; + color: @dark-blue; + } } } @@ -158,8 +164,8 @@ .dice-roll .dice-total { box-shadow: none; border: none; - background: light-dark(@dark-blue-40, @golden-40); - color: light-dark(@dark-blue, @golden); + background: @golden-10; + color: @golden; font-weight: 600; align-content: center; } diff --git a/templates/ui/chat/resource-roll.hbs b/templates/ui/chat/resource-roll.hbs index b6e1f3b0..dc41d18c 100644 --- a/templates/ui/chat/resource-roll.hbs +++ b/templates/ui/chat/resource-roll.hbs @@ -1,3 +1,3 @@ -
-
{{localize "DAGGERHEART.UI.Chat.resourceRoll.playerMessage" user=user name=name }}
-
\ No newline at end of file +
    +
  • {{localize "DAGGERHEART.UI.Chat.resourceRoll.playerMessage" user=user name=name }}
  • +
\ No newline at end of file From afdffb672a660b114fa7f4ecf15e228c83182bf1 Mon Sep 17 00:00:00 2001 From: Chris Ryan <73275196+chrisryan10@users.noreply.github.com> Date: Sun, 24 Aug 2025 11:38:09 +1000 Subject: [PATCH 17/22] [PR] [Fix] Homebrew Settings, Initial Trait Modifiers improvements and clean up (#1035) * Remove old homebrew settings template file * Improve the Initial Trait Modifiers config display * Remove font setting --------- Co-authored-by: Chris Ryan --- styles/less/ui/settings/settings.less | 31 ++----- templates/settings/homebrew-settings.hbs | 90 ------------------- .../settings/homebrew-settings/settings.hbs | 17 ++-- 3 files changed, 19 insertions(+), 119 deletions(-) delete mode 100644 templates/settings/homebrew-settings.hbs diff --git a/styles/less/ui/settings/settings.less b/styles/less/ui/settings/settings.less index cee5475f..5dd203db 100644 --- a/styles/less/ui/settings/settings.less +++ b/styles/less/ui/settings/settings.less @@ -16,6 +16,12 @@ } } + &.six-columns { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; + gap: 2px; + } + &.start-align { align-self: flex-start; } @@ -103,28 +109,9 @@ gap: 4px; } - .trait-array-container { - display: flex; - justify-content: space-evenly; - gap: 8px; - margin-bottom: 16px; - - .trait-array-item { - position: relative; - display: flex; - justify-content: center; - - label { - position: absolute; - top: -7px; - font-size: var(--font-size-12); - font-variant: petite-caps; - z-index: 2; - } - - input { - text-align: center; - } + .trait-item { + input { + text-align: center; } } diff --git a/templates/settings/homebrew-settings.hbs b/templates/settings/homebrew-settings.hbs deleted file mode 100644 index 4e2c442f..00000000 --- a/templates/settings/homebrew-settings.hbs +++ /dev/null @@ -1,90 +0,0 @@ -
-
-

{{localize 'DAGGERHEART.SETTINGS.Menu.homebrew.name'}}

-
- {{formGroup settingFields.schema.fields.maxFear value=settingFields._source.maxFear localize=true}} - {{formGroup settingFields.schema.fields.maxDomains value=settingFields._source.maxDomains localize=true}} - {{formGroup settingFields.schema.fields.maxLoadout value=settingFields._source.maxLoadout localize=true}} -
- -

{{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.traitArray.label"}}

-
- {{#each settingFields._source.traitArray as |trait index|}} -
- - -
- {{/each}} -
- -
- - {{localize "DAGGERHEART.SETTINGS.Homebrew.currency.title"}} - - {{formGroup settingFields.schema.fields.currency.fields.enabled value=settingFields._source.currency.enabled localize=true}} - {{formGroup settingFields.schema.fields.currency.fields.title value=settingFields._source.currency.title localize=true}} - {{formGroup settingFields.schema.fields.currency.fields.coins value=settingFields._source.currency.coins localize=true}} - {{formGroup settingFields.schema.fields.currency.fields.handfuls value=settingFields._source.currency.handfuls localize=true}} - {{formGroup settingFields.schema.fields.currency.fields.bags value=settingFields._source.currency.bags localize=true}} - {{formGroup settingFields.schema.fields.currency.fields.chests value=settingFields._source.currency.chests localize=true}} - -
- -
- {{localize "DAGGERHEART.SETTINGS.Homebrew.downtimeMoves"}} - -
- - {{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}} - - - - -
- -
- -
-
- -
- {{#each settingFields._source.restMoves.longRest.moves as |move id|}} - {{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" this type="longRest" id=id }} - {{/each}} -
-
- -
- - {{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}} - - - - -
- -
- -
-
- -
- {{#each settingFields._source.restMoves.shortRest.moves as |move id|}} - {{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" this type="shortRest" id=id }} - {{/each}} -
-
-
- -
- - -
-
- \ No newline at end of file diff --git a/templates/settings/homebrew-settings/settings.hbs b/templates/settings/homebrew-settings/settings.hbs index 1c7c787d..893e1bc3 100644 --- a/templates/settings/homebrew-settings/settings.hbs +++ b/templates/settings/homebrew-settings/settings.hbs @@ -12,15 +12,18 @@ {{formGroup settingFields.schema.fields.maxLoadout value=settingFields._source.maxLoadout localize=true}}
-

{{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.traitArray.label"}}

-
+
+ + {{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.traitArray.label"}} + + {{#each settingFields._source.traitArray as |trait index|}} -
- - -
+
+ {{localize "DAGGERHEART.GENERAL.Modifier.single"}} {{add index 1}} + +
{{/each}} -
+
From 5a38e28a846b137de1db774d6e8bc82c5a058598 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:36:46 +0200 Subject: [PATCH 18/22] Fixed the migration to respect null for multiclass (#1075) --- module/systemRegistration/migrations.mjs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index da0dcb5d..134c8714 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -3,8 +3,13 @@ export async function runMigrations() { if (!lastMigrationVersion) lastMigrationVersion = '1.0.6'; if (foundry.utils.isNewerVersion('1.1.0', lastMigrationVersion)) { + const lockedPacks = []; const compendiumActors = []; for (let pack of game.packs) { + if (pack.locked) { + lockedPacks.push(pack.collection); + await pack.configure({ locked: false }); + } const documents = await pack.getDocuments(); compendiumActors.push(...documents.filter(x => x.type === 'character')); } @@ -32,13 +37,23 @@ export async function runMigrations() { actor.updateEmbeddedDocuments('Item', items); }); + for (let packId of lockedPacks) { + const pack = game.packs.get(packId); + await pack.configure({ locked: true }); + } + lastMigrationVersion = '1.1.0'; } if (foundry.utils.isNewerVersion('1.1.1', lastMigrationVersion)) { + const lockedPacks = []; const compendiumClasses = []; const compendiumActors = []; for (let pack of game.packs) { + if (pack.locked) { + lockedPacks.push(pack.collection); + await pack.configure({ locked: false }); + } const documents = await pack.getDocuments(); compendiumClasses.push(...documents.filter(x => x.type === 'class')); compendiumActors.push(...documents.filter(x => x.type === 'character')); @@ -46,7 +61,8 @@ export async function runMigrations() { [...compendiumActors, ...game.actors.filter(x => x.type === 'character')].forEach(char => { const multiclass = char.items.find(x => x.type === 'class' && x.system.isMulticlass); - const multiclassSubclass = multiclass.system.subclasses.length > 0 ? multiclass.system.subclasses[0] : null; + const multiclassSubclass = + multiclass?.system?.subclasses?.length > 0 ? multiclass.system.subclasses[0] : null; char.items.forEach(item => { if (item.type === 'feature' && item.system.identifier === 'multiclass') { const base = item.system.originItemType === 'class' ? multiclass : multiclassSubclass; @@ -72,6 +88,11 @@ export async function runMigrations() { } } + for (let packId of lockedPacks) { + const pack = game.packs.get(packId); + await pack.configure({ locked: true }); + } + lastMigrationVersion = '1.1.1'; } From d686ac1e0cdc1ce88a6952c3d9641bea12c3d951 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:40:06 +0200 Subject: [PATCH 19/22] . (#1056) --- module/data/actor/base.mjs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 5b225228..0e9dd2d8 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -115,11 +115,16 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { const typeForDefeated = ['character', 'adversary', 'companion'].find(x => x === this.parent.type); if (defeatedSettings.enabled && typeForDefeated) { const resource = typeForDefeated === 'companion' ? 'stress' : 'hitPoints'; - if (changes.system.resources[resource]) { - const becameMax = changes.system.resources[resource].value === this.resources[resource].max; + const resourceValue = changes.system.resources[resource]; + if ( + resourceValue && + this.resources[resource].max && + resourceValue.value !== this.resources[resource].value + ) { + const becameMax = resourceValue.value === this.resources[resource].max; const wasMax = this.resources[resource].value === this.resources[resource].max && - this.resources[resource].value !== changes.system.resources[resource].value; + this.resources[resource].value !== resourceValue.value; if (becameMax) { this.parent.toggleDefeated(true); } else if (wasMax) { From d24fef7494da497e8d94245287a43849c61a29c5 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 19:15:42 +0200 Subject: [PATCH 20/22] [Fix] Hints For Drag/Drop (#1076) * Added hints for drag-drop areas * Changed to drag-area style. Updated localization --- lang/en.json | 5 +++++ styles/less/global/global.less | 12 ++++++++++++ styles/less/global/index.less | 1 + .../environment-settings/adversaries.less | 13 ------------- .../less/sheets/actors/character/inventory.less | 4 ---- styles/less/sheets/actors/character/loadout.less | 4 ---- styles/less/ui/item-browser/item-browser.less | 8 ++------ .../environment-settings/adversaries.hbs | 2 +- templates/sheets/items/class/features.hbs | 3 +++ templates/sheets/items/class/settings.hbs | 15 +++++++++++++++ 10 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 styles/less/global/global.less diff --git a/lang/en.json b/lang/en.json index f310a01d..7efca151 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1894,6 +1894,7 @@ "amount": "Amount", "any": "Any", "armor": "Armor", + "armors": "Armors", "armorScore": "Armor Score", "activeEffects": "Active Effects", "armorSlots": "Armor Slots", @@ -1944,6 +1945,7 @@ "inactiveEffects": "Inactive Effects", "inventory": "Inventory", "itemResource": "Item Resource", + "items": "Items", "label": "Label", "level": "Level", "levelShort": "Lv", @@ -1955,6 +1957,7 @@ "plural": "Miss" }, "maxWithThing": "Max {thing}", + "missingDragDropThing": "Drop {thing} here", "multiclass": "Multiclass", "newCategory": "New Category", "none": "None", @@ -1976,6 +1979,7 @@ "scalable": "Scalable", "situationalBonus": "Situational Bonus", "stress": "Stress", + "subclasses": "Subclasses", "success": "Success", "take": "Take", "Target": { @@ -1993,6 +1997,7 @@ "used": "Used", "uses": "Uses", "value": "Value", + "weapons": "Weapons", "withThing": "With {thing}" }, "ITEMS": { diff --git a/styles/less/global/global.less b/styles/less/global/global.less new file mode 100644 index 00000000..5bf32746 --- /dev/null +++ b/styles/less/global/global.less @@ -0,0 +1,12 @@ +.drag-area { + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + width: 100%; + height: 40px; + border: 1px dashed light-dark(@dark-blue-50, @beige-50); + border-radius: 3px; + color: light-dark(@dark-blue-50, @beige-50); + font-family: @font-body; +} diff --git a/styles/less/global/index.less b/styles/less/global/index.less index 5f955ce3..db61304a 100644 --- a/styles/less/global/index.less +++ b/styles/less/global/index.less @@ -3,6 +3,7 @@ @import './chat.less'; @import './elements.less'; @import './enrichment.less'; +@import './global.less'; @import './tab-navigation.less'; @import './tab-form-footer.less'; @import './tab-actions.less'; diff --git a/styles/less/sheets-settings/environment-settings/adversaries.less b/styles/less/sheets-settings/environment-settings/adversaries.less index 8dc12c87..1a27eaca 100644 --- a/styles/less/sheets-settings/environment-settings/adversaries.less +++ b/styles/less/sheets-settings/environment-settings/adversaries.less @@ -34,18 +34,5 @@ width: 100%; } } - - .adversaries-dragger { - display: flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - width: 100%; - height: 40px; - border: 1px dashed light-dark(@dark-blue-50, @beige-50); - border-radius: 3px; - color: light-dark(@dark-blue-50, @beige-50); - font-family: @font-body; - } } } diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index 48bdd682..d8c225ad 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -27,10 +27,6 @@ outline: 2px solid light-dark(@dark, @golden); } - &:placeholder { - color: light-dark(@dark-blue-50, @beige-50); - } - &::-webkit-search-cancel-button { -webkit-appearance: none; display: none; diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index 98fe9eed..24a53959 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -27,10 +27,6 @@ outline: 2px solid light-dark(@dark, @golden); } - &:placeholder { - color: light-dark(@dark-blue-50, @beige-50); - } - &::-webkit-search-cancel-button { -webkit-appearance: none; display: none; diff --git a/styles/less/ui/item-browser/item-browser.less b/styles/less/ui/item-browser/item-browser.less index 407a3116..7d708e1f 100644 --- a/styles/less/ui/item-browser/item-browser.less +++ b/styles/less/ui/item-browser/item-browser.less @@ -148,10 +148,6 @@ outline: 2px solid light-dark(@dark, @golden); } - &:placeholder { - color: light-dark(@dark-blue-50, @beige-50); - } - &::-webkit-search-cancel-button { -webkit-appearance: none; display: none; @@ -187,7 +183,7 @@ } &:has(+ .subfolder-list):after { - content: "+"; + content: '+'; } } @@ -357,7 +353,7 @@ grid-template-rows: 0fr; transition: all 0.3s ease-in-out; width: 100%; - + .wrapper { overflow: hidden; display: grid; diff --git a/templates/sheets-settings/environment-settings/adversaries.hbs b/templates/sheets-settings/environment-settings/adversaries.hbs index 3464a745..4d8b5122 100644 --- a/templates/sheets-settings/environment-settings/adversaries.hbs +++ b/templates/sheets-settings/environment-settings/adversaries.hbs @@ -25,7 +25,7 @@ {{/each}} -
+
{{localize "DAGGERHEART.GENERAL.dropActorsHere"}}
diff --git a/templates/sheets/items/class/features.hbs b/templates/sheets/items/class/features.hbs index 4e6a7e6f..6ed449dc 100644 --- a/templates/sheets/items/class/features.hbs +++ b/templates/sheets/items/class/features.hbs @@ -27,6 +27,9 @@
{{localize "TYPES.Item.subclass"}}
+ {{#unless source.system.subclasses}} +
{{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.subclasses")}}
+ {{/unless}} {{#each source.system.subclasses as |subclass index|}}
  • diff --git a/templates/sheets/items/class/settings.hbs b/templates/sheets/items/class/settings.hbs index 9ac2b14f..8e8254ee 100644 --- a/templates/sheets/items/class/settings.hbs +++ b/templates/sheets/items/class/settings.hbs @@ -45,6 +45,8 @@ {{#unless (eq document.parent.type 'character')}}{{/unless}}
  • + {{else}} +
    {{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.weapons")}}
    {{/if}}
    @@ -60,6 +62,8 @@ {{#unless (eq document.parent.type 'character')}}{{/unless}} + {{else}} +
    {{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.weapons")}}
    {{/if}} @@ -75,6 +79,8 @@ {{#unless (eq document.parent.type 'character')}}{{/unless}} + {{else}} +
    {{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.armors")}}
    {{/if}} @@ -85,6 +91,9 @@
    {{localize "DAGGERHEART.GENERAL.take"}}
    + {{#unless source.system.inventory.take}} +
    {{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.items")}}
    + {{/unless}} {{#each source.system.inventory.take}} {{#if this}}
    @@ -102,6 +111,9 @@
    {{localize "DAGGERHEART.ITEMS.Class.guide.inventory.thenChoose"}}
    + {{#unless source.system.inventory.choiceA}} +
    {{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.items")}}
    + {{/unless}} {{#each source.system.inventory.choiceA}} {{#if this}}
    @@ -119,6 +131,9 @@
    {{localize "DAGGERHEART.ITEMS.Class.guide.inventory.andEither"}}
    + {{#unless source.system.inventory.choiceB}} +
    {{localize "DAGGERHEART.GENERAL.missingDragDropThing" thing=(localize "DAGGERHEART.GENERAL.items")}}
    + {{/unless}} {{#each source.system.inventory.choiceB}} {{#if this}}
    From 7a1d259e825300ee1bf5c154a37d280a2b42d773 Mon Sep 17 00:00:00 2001 From: Dapoulp <74197441+Dapoulp@users.noreply.github.com> Date: Sun, 24 Aug 2025 20:55:35 +0200 Subject: [PATCH 21/22] Fix/1022 (#1079) * Temp ActionField attack type missing * Move missing attack type to getModel * Show hit/miss to GM and hide to players if no OBSERVER permission --- module/data/chat-message/adversaryRoll.mjs | 5 +++-- templates/ui/chat/parts/target-part.hbs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index 1447acb8..de203a6e 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -112,7 +112,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { this.currentTargets = this.getTargetList(); // this.registerTargetHook(); - if (this.targetMode === true && this.hasRoll) { + if (this.hasRoll) { this.targetShort = this.targets.reduce( (a, c) => { if (c.hit) a.hit += 1; @@ -126,7 +126,8 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { } this.canViewSecret = this.parent.speakerActor?.testUserPermission(game.user, 'OBSERVER'); - this.canButtonApply = game.user.isGM; + this.canButtonApply = game.user.isGM; //temp + this.isGM = game.user.isGM; //temp } getTargetList() { diff --git a/templates/ui/chat/parts/target-part.hbs b/templates/ui/chat/parts/target-part.hbs index 82c71456..ec3ea997 100644 --- a/templates/ui/chat/parts/target-part.hbs +++ b/templates/ui/chat/parts/target-part.hbs @@ -1,6 +1,6 @@
    Target
    - {{#if (or (and targets.length (or (gt targetShort.hit 0) (gt targetShort.miss 0))) (and hasSave pendingSaves))}} + {{#if isGM}}
    {{#if (or (gt targetShort.hit 0) (gt targetShort.miss 0))}} @@ -30,8 +30,8 @@
    {{name}}
    - {{#if (and ../targetMode ../hasRoll)}} -
    + {{#if (and ../hasRoll (hasProperty this "hit"))}} +
    {{#if hit}} {{localize "DAGGERHEART.GENERAL.hit.single"}} {{else}} From f480027b9573e379768d85264985065d7f42c208 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:09:21 +0200 Subject: [PATCH 22/22] Improved text color on chat-message flavor texts (#1080) --- styles/less/global/chat.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less index 37ec993d..d7fee8e5 100644 --- a/styles/less/global/chat.less +++ b/styles/less/global/chat.less @@ -77,7 +77,7 @@ .flavor-text { font-size: var(--font-size-12); line-height: 20px; - color: var(--color-dark-4); + color: light-dark(@dark, @beige); text-align: center; display: block; }