From 961e124ef2fdfde1881769e11042defaae22034c Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Thu, 18 Jun 2026 19:05:26 -0400 Subject: [PATCH 01/13] Fade adversary notes tab when notes are empty (#2015) --- module/applications/sheets/actors/adversary.mjs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index c8d5a299..f39bec0c 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -131,6 +131,15 @@ export default class AdversarySheet extends DHBaseActorSheet { return context; } + /** @inheritdoc */ + _prepareTabs(group) { + const result = super._prepareTabs(group); + if (group === 'primary') { + result.notes.empty = !this.document.system.notes?.trim(); + } + return result; + } + /**@inheritdoc */ _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); From 0b7ae8a76c1dfd92d3459d17005b540389622e17 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Fri, 19 Jun 2026 04:46:20 -0400 Subject: [PATCH 02/13] Increase size of pause image and text (#2012) --- styles/less/ui/game-pause/game-pause.less | 17 ++++++++++++++--- styles/less/utils/fonts.less | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/styles/less/ui/game-pause/game-pause.less b/styles/less/ui/game-pause/game-pause.less index 60d08bec..daf9a1e4 100644 --- a/styles/less/ui/game-pause/game-pause.less +++ b/styles/less/ui/game-pause/game-pause.less @@ -1,23 +1,34 @@ @import '../../utils/mixin.less'; #pause.dh-style { + animation: none; + + img { + width: 125px; + height: 125px; + } + figcaption { + --base-shadow: drop-shadow(2px 2px 2px black); position: absolute; margin-top: 24px; animation: pause-pulse 3s ease-in-out infinite; + font-size: var(--font-size-30); + letter-spacing: 0.18em; + filter: var(--base-shadow); } @keyframes pause-pulse { 0% { - filter: drop-shadow(0 0 5px @secondary-blue); + filter: var(--base-shadow) drop-shadow(0 0 5px @secondary-blue); } 50% { - filter: drop-shadow(0 0 5px @golden); + filter: var(--base-shadow) drop-shadow(0 0 5px @golden-secondary); } 100% { - filter: drop-shadow(0 0 5px @secondary-blue); + filter: var(--base-shadow) drop-shadow(0 0 5px @secondary-blue); } } } \ No newline at end of file diff --git a/styles/less/utils/fonts.less b/styles/less/utils/fonts.less index 07da3389..72ee1a85 100755 --- a/styles/less/utils/fonts.less +++ b/styles/less/utils/fonts.less @@ -10,6 +10,7 @@ --font-size-8: 0.5rem; --font-size-9: 0.5625rem; --font-size-22: 1.375rem; + --font-size-30: 1.875rem; } @font-title: ~"var(--dh-font-title, 'Cinzel Decorative'), serif"; From b64e600a6b667620b4165c56f2fe8291a0dd51e6 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sat, 20 Jun 2026 13:44:39 -0400 Subject: [PATCH 03/13] Fix old armorscore AEs clobbering data (#2018) --- module/data/actor/character.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 8ae78ff8..3b12da6f 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -315,7 +315,12 @@ export default class DhCharacter extends DhCreature { label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' }) }) - }) + }), + /** Accumulated armor score from all sources */ + armorScore: new fields.SchemaField({ + value: new fields.NumberField(), + max: new fields.NumberField() + }, { persisted: false }) }; } From 6f1da427352a55f4eedc7642b6155bd4f8035431 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sat, 20 Jun 2026 13:48:12 -0400 Subject: [PATCH 04/13] Make dragging features work more seamlessly (#2016) --- .../sheets-configs/adversary-settings.mjs | 2 +- .../applications/sheets/actors/adversary.mjs | 2 +- .../sheets/api/application-mixin.mjs | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/module/applications/sheets-configs/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs index 57405675..cd627f1c 100644 --- a/module/applications/sheets-configs/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -54,7 +54,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - const featureForms = ['passive', 'action', 'reaction']; + const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); context.features = context.document.system.features.sort((a, b) => a.system.featureForm !== b.system.featureForm ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index f39bec0c..85380392 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -103,7 +103,7 @@ export default class AdversarySheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; - const featureForms = ['passive', 'action', 'reaction']; + const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); context.features = this.document.system.features.sort((a, b) => a.system.featureForm !== b.system.featureForm ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 752dc80b..876278fa 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -387,6 +387,30 @@ export default function DHApplicationMixin(Base) { return super._onDrop?.(event); } + /** @inheritdoc */ + _onSortItem(event, item) { + // If we are dragging a feature past its allowed feature form, put it in the front or in the back + const doc = this.actor.items.get(item.id); + const dropTargetEl = event.target.closest('[data-item-id]'); + const dropTarget = this.actor.items.get(dropTargetEl?.dataset.itemId); + if (doc?.type === 'feature' && dropTarget?.type === 'feature' && doc.system.featureForm !== dropTarget.system.featureForm) { + const siblings = this.actor.itemTypes.feature + .filter(f => f.system.featureForm === doc.system.featureForm) + .sort((a, b) => a.sort - b.sort); + if (siblings.length > 1) { + const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); + const thisFeatureIdx = featureForms.indexOf(doc.system.featureForm); + const targetFeatureIdx = featureForms.indexOf(dropTarget.system.featureForm); + const target = targetFeatureIdx < thisFeatureIdx ? siblings[0] : siblings.at(-1); + const sortUpdates = foundry.utils.performIntegerSort(doc, { target, siblings }); + const updateData = sortUpdates.map(u => ({ ...u.update, _id: u.target._id })); + return this.actor.updateEmbeddedDocuments('Item', updateData); + } + } + + return super._onSortItem?.(event, item); + } + /* -------------------------------------------- */ /* Context Menu */ /* -------------------------------------------- */ From 6b80a6243c81f2d550353ae57fe7552c14ddcd95 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sat, 20 Jun 2026 13:55:51 -0400 Subject: [PATCH 05/13] Support drag resort on features in actor setting sheets (#2023) --- .../sheets-configs/adversary-settings.mjs | 28 -------------- .../sheets-configs/environment-settings.mjs | 35 ++++++++---------- .../sheets-configs/npc-settings.mjs | 30 --------------- .../sheets/actors/environment.mjs | 1 - .../applications/sheets/api/actor-setting.mjs | 37 ++++++++++++++++--- .../sheets/api/application-mixin.mjs | 3 +- .../adversary-settings/features.hbs | 2 +- .../environment-settings/features.hbs | 2 +- .../sheets-settings/npc-settings/features.hbs | 2 +- 9 files changed, 52 insertions(+), 88 deletions(-) diff --git a/module/applications/sheets-configs/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs index cd627f1c..583f37b7 100644 --- a/module/applications/sheets-configs/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -97,32 +97,4 @@ export default class DHAdversarySettings extends DHBaseActorSettings { await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del }); } - - async _onDragStart(event) { - const featureItem = event.currentTarget.closest('.feature-item'); - - if (featureItem) { - const feature = this.actor.items.get(featureItem.id); - const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true }; - event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); - event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); - } - } - - async _onDrop(event) { - event.stopPropagation(); - const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - - const item = await fromUuid(data.uuid); - if (item?.type === 'feature') { - if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { - return; - } - - const itemData = item.toObject(); - delete itemData._id; - - await this.actor.createEmbeddedDocuments('Item', [itemData]); - } - } } diff --git a/module/applications/sheets-configs/environment-settings.mjs b/module/applications/sheets-configs/environment-settings.mjs index 6d74f9c6..d6744eb8 100644 --- a/module/applications/sheets-configs/environment-settings.mjs +++ b/module/applications/sheets-configs/environment-settings.mjs @@ -15,7 +15,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { dragDrop: [ { dragSelector: null, dropSelector: '.category-container' }, { dragSelector: null, dropSelector: '.tab.features' }, - { dragSelector: '.feature-item', dropSelector: null } + { dragSelector: '.feature-item, .inventory-item[data-type="adversary"]', dropSelector: null } ] }; @@ -110,33 +110,30 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { } async _onDragStart(event) { - const featureItem = event.currentTarget.closest('.feature-item'); - - if (featureItem) { - const feature = this.actor.items.get(featureItem.id); - const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true }; - event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); - event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); + const element = event.currentTarget.closest('.inventory-item[data-type=adversary]'); + if (element) { + const adversaryData = { type: 'Actor', uuid: element.dataset.itemUuid }; + event.dataTransfer.setData('text/plain', JSON.stringify(adversaryData)); + event.dataTransfer.setDragImage(element, 60, 0); + } else { + return super._onDragStart(event); } } async _onDrop(event) { event.stopPropagation(); const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (data.fromInternal && item?.parent?.uuid === this.actor.uuid) return; - - if (item.type === 'adversary' && event.target.closest('.category-container')) { + const doc = await fromUuid(data.uuid); + if (doc?.type === 'adversary' && event.target.closest('.category-container')) { const target = event.target.closest('.category-container'); const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`; const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid); - await this.actor.update({ - [path]: [...current, item.uuid] - }); - this.render(); - } else if (item.type === 'feature' && event.target.closest('.tab.features')) { - await this.actor.createEmbeddedDocuments('Item', [item]); - this.render(); + if (!current.includes(doc.uuid)) { + await this.actor.update({ [path]: [...current, doc.uuid] }); + } + return; } + + return super._onDrop(event); } } diff --git a/module/applications/sheets-configs/npc-settings.mjs b/module/applications/sheets-configs/npc-settings.mjs index c187877c..d2132a91 100644 --- a/module/applications/sheets-configs/npc-settings.mjs +++ b/module/applications/sheets-configs/npc-settings.mjs @@ -52,34 +52,4 @@ export default class DHNPCSettings extends DHBaseActorSettings { return context; } - - /* -------------------------------------------- */ - - async _onDragStart(event) { - const featureItem = event.currentTarget.closest('.feature-item'); - - if (featureItem) { - const feature = this.actor.items.get(featureItem.id); - const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true }; - event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); - event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); - } - } - - async _onDrop(event) { - event.stopPropagation(); - const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - - const item = await fromUuid(data.uuid); - if (item?.type === 'feature') { - if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { - return; - } - - const itemData = item.toObject(); - delete itemData._id; - - await this.actor.createEmbeddedDocuments('Item', [itemData]); - } - } } diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index f8ff74a6..9a88dba6 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -78,7 +78,6 @@ export default class DhpEnvironment extends DHBaseActorSheet { switch (partId) { case 'header': await this._prepareHeaderContext(context, options); - break; case 'features': await this._prepareFeaturesContext(context, options); diff --git a/module/applications/sheets/api/actor-setting.mjs b/module/applications/sheets/api/actor-setting.mjs index 738f7002..65497cec 100644 --- a/module/applications/sheets/api/actor-setting.mjs +++ b/module/applications/sheets/api/actor-setting.mjs @@ -1,13 +1,15 @@ import DHApplicationMixin from './application-mixin.mjs'; -const { DocumentSheetV2 } = foundry.applications.api; +const { ActorSheetV2 } = foundry.applications.sheets; -/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ +/** + * @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction + */ /** * Base settings sheet for Daggerheart actors. - * @extends {DHApplicationMixin} + * @extends {DHApplicationMixin} */ -export default class DHBaseActorSettings extends DHApplicationMixin(DocumentSheetV2) { +export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2) { /**@inheritdoc */ static DEFAULT_OPTIONS = { classes: ['dialog'], @@ -34,7 +36,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee return options; } - /**@returns {foundry.documents.Actor} */ + /** @returns {foundry.documents.Actor} */ get actor() { return this.document; } @@ -73,4 +75,29 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee return context; } + + async _onDragStart(event) { + const featureItemEl = event.currentTarget.closest('.feature-item'); + const feature = this.actor.items.get(featureItemEl?.dataset.itemId); + if (feature && event.target.closest('.tab.features')) { + const featureData = { ...feature.toDragData(), fromInternal: true }; + event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); + event.dataTransfer.setDragImage(featureItemEl.querySelector('img'), 60, 0); + } + } + + async _onDrop(event) { + event.stopPropagation(); + const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); + const item = await fromUuid(data.uuid); + if (item?.type === 'feature') { + if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { + return super._onDrop(event); + } + + const itemData = item.toObject(); + delete itemData._id; + await this.actor.createEmbeddedDocuments('Item', [itemData]); + } + } } diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 876278fa..f3d612e9 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -381,8 +381,7 @@ export default function DHApplicationMixin(Base) { * @protected */ _onDrop(event) { - // Fallback to super, but note that config sheets don't have this option - // We still need this to avoid setting apps having issues + // Potentially handle subclasses that dont descend from actor/item sheet. event.stopPropagation(); return super._onDrop?.(event); } diff --git a/templates/sheets-settings/adversary-settings/features.hbs b/templates/sheets-settings/adversary-settings/features.hbs index 2f2f5f47..3e0ed654 100644 --- a/templates/sheets-settings/adversary-settings/features.hbs +++ b/templates/sheets-settings/adversary-settings/features.hbs @@ -10,7 +10,7 @@ {{localize tabs.features.label}}
    {{#each @root.features as |feature|}} -
  • +
  • {{feature.name}} diff --git a/templates/sheets-settings/environment-settings/features.hbs b/templates/sheets-settings/environment-settings/features.hbs index 579fe74e..ecda0e6b 100644 --- a/templates/sheets-settings/environment-settings/features.hbs +++ b/templates/sheets-settings/environment-settings/features.hbs @@ -10,7 +10,7 @@ {{localize tabs.features.label}}
      {{#each @root.features as |feature|}} -
    • +
    • {{feature.name}} diff --git a/templates/sheets-settings/npc-settings/features.hbs b/templates/sheets-settings/npc-settings/features.hbs index 2f2f5f47..3e0ed654 100644 --- a/templates/sheets-settings/npc-settings/features.hbs +++ b/templates/sheets-settings/npc-settings/features.hbs @@ -10,7 +10,7 @@ {{localize tabs.features.label}}
        {{#each @root.features as |feature|}} -
      • +
      • {{feature.name}} From 29be8c139538a3f543535c390ed7b18c227e8d65 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 21 Jun 2026 00:13:45 +0200 Subject: [PATCH 06/13] Removed the unused ResourceMap total property (#2024) --- module/applications/dialogs/groupRollDialog.mjs | 8 ++++---- module/applications/dialogs/tagTeamDialog.mjs | 8 ++++---- module/applications/sheets/actors/character.mjs | 2 +- module/data/action/baseAction.mjs | 3 +-- module/dice/dualityRoll.mjs | 12 ++++++------ module/dice/helpers.mjs | 6 +++--- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index 7196d848..58ed03b4 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -483,13 +483,13 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat const resourceMap = new ResourceUpdateMap(actor); if (totalRoll.isCritical) { resourceMap.addResources([ - { key: 'stress', value: -1, total: 1 }, - { key: 'hope', value: 1, total: 1 } + { key: 'stress', value: -1 }, + { key: 'hope', value: 1 } ]); } else if (totalRoll.withHope) { - resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]); + resourceMap.addResources([{ key: 'hope', value: 1 }]); } else { - resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]); + resourceMap.addResources([{ key: 'fear', value: 1 }]); } resourceMap.updateResources(); diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index b2ce0258..5c83f075 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -752,7 +752,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio /* Handle resource updates from the finished TagTeamRoll */ const tagTeamData = this.party.system.tagTeam; - const fearUpdate = { key: 'fear', value: null, total: null, enabled: true }; + const fearUpdate = { key: 'fear', value: null, enabled: true }; for (let memberId in tagTeamData.members) { const resourceUpdates = []; const rollGivesHope = finalRoll.isCritical || finalRoll.withHope; @@ -762,11 +762,11 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio ? 1 - tagTeamData.initiator.cost : -tagTeamData.initiator.cost : 1; - resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true }); + resourceUpdates.push({ key: 'hope', value: value, enabled: true }); } else if (rollGivesHope) { - resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true }); + resourceUpdates.push({ key: 'hope', value: 1, enabled: true }); } - if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true }); + if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, enabled: true }); if (finalRoll.withFear) { fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1; fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1; diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index f0f8326f..3a60e7ca 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -809,7 +809,7 @@ export default class CharacterSheet extends DHBaseActorSheet { /* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */ const costResources = - result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value, total: -cost.total })) || + result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value })) || {}; result.resourceUpdates.addResources(costResources); await result.resourceUpdates.updateResources(); diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index c71f5ef9..ea4361b9 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -459,8 +459,7 @@ export class ResourceUpdateMap extends Map { } else if (!existing?.clear) { this.set(resource.key, { ...existing, - value: existing.value + (resource.value ?? 0), - total: existing.total + (resource.total ?? 0) + value: existing.value + (resource.value ?? 0) }); } } diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 1cfed094..70e98242 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -334,15 +334,15 @@ export default class DualityRoll extends D20Roll { const fear = (config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0); - if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); + if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true }); } } else { if (config.roll.isCritical || config.roll.result.duality === 1) - updates.push({ key: 'hope', value: 1, total: -1, enabled: true }); - if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, total: 1, enabled: true }); - if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, total: -1, enabled: true }); + updates.push({ key: 'hope', value: 1, enabled: true }); + if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, enabled: true }); + if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, enabled: true }); } if (updates.length) { diff --git a/module/dice/helpers.mjs b/module/dice/helpers.mjs index 35adb8b7..5f8a7bbb 100644 --- a/module/dice/helpers.mjs +++ b/module/dice/helpers.mjs @@ -9,9 +9,9 @@ export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) { const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); - if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); + if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true }); const resourceUpdates = new ResourceUpdateMap(actor); resourceUpdates.addResources(updates); From 08b95e48d6190b1c1853009104410f0cf13f2133 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 21 Jun 2026 04:50:09 +0200 Subject: [PATCH 07/13] [Fix] TagTag/GroupRoll Resource Handling (#2022) --- .../applications/dialogs/groupRollDialog.mjs | 28 ++++--- module/applications/dialogs/tagTeamDialog.mjs | 73 ++++++++++++------- module/dice/dualityRoll.mjs | 6 +- module/helpers/utils.mjs | 5 ++ .../tag-team-dialog/initialization.less | 14 +++- .../dialogs/tagTeamDialog/initialization.hbs | 13 +++- 6 files changed, 92 insertions(+), 47 deletions(-) diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index 58ed03b4..ebc80d39 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -1,4 +1,5 @@ import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; +import { shouldUseHopeFearAutomation } from '../../helpers/utils.mjs'; import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; import Party from '../sheets/actors/party.mjs'; @@ -480,19 +481,22 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat await cls.create(msgData); - const resourceMap = new ResourceUpdateMap(actor); - if (totalRoll.isCritical) { - resourceMap.addResources([ - { key: 'stress', value: -1 }, - { key: 'hope', value: 1 } - ]); - } else if (totalRoll.withHope) { - resourceMap.addResources([{ key: 'hope', value: 1 }]); - } else { - resourceMap.addResources([{ key: 'fear', value: 1 }]); - } + /* Handle resource updates for the finished GroupRoll */ + if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) { + const resourceMap = new ResourceUpdateMap(actor); + if (totalRoll.isCritical) { + resourceMap.addResources([ + { key: 'stress', value: -1 }, + { key: 'hope', value: 1 } + ]); + } else if (totalRoll.withHope) { + resourceMap.addResources([{ key: 'hope', value: 1 }]); + } else { + resourceMap.addResources([{ key: 'fear', value: 1 }]); + } - resourceMap.updateResources(); + resourceMap.updateResources(); + } /* Fin */ this.cancelRoll({ confirm: false }); diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 5c83f075..19869a00 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -1,5 +1,6 @@ +import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; import { MemberData } from '../../data/tagTeamData.mjs'; -import { getCritDamageBonus } from '../../helpers/utils.mjs'; +import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs'; import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; import Party from '../sheets/actors/party.mjs'; @@ -9,6 +10,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio constructor(party) { super({ id: `TagTeamDialog-${party.id}` }); + this.usesTagTeamHopeCost = true; this.party = party; this.partyMembers = party.system.partyMembers .filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type)) @@ -20,7 +22,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) })); - this.initiator = { cost: 3 }; + this.initiator = { cost: + this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial + }; this.openForAllPlayers = true; this.tabGroups.application = Object.keys(party.system.tagTeam.members).length @@ -94,9 +98,13 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio ?.addEventListener('input', this.updateInitiatorMemberField.bind(this)); htmlElement - .querySelector('.initiator-cost-field') + .querySelector('.initiator-cost-input') ?.addEventListener('input', this.updateInitiatorCostField.bind(this)); + htmlElement + .querySelector('.initiator-cost-enabled-checkbox') + ?.addEventListener('change', this.toggleInitiatorCostEnabled.bind(this)); + htmlElement .querySelector('.openforall-field') ?.addEventListener('change', this.updateOpenForAllField.bind(this)); @@ -156,6 +164,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio .map(x => ({ value: x.id, label: x.name })); partContext.initiatorDisabled = !selectedMembers.length; partContext.openForAllPlayers = this.openForAllPlayers; + partContext.usesTagTeamHopeCost = this.usesTagTeamHopeCost; break; case 'tagTeamRoll': @@ -397,6 +406,13 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio this.render(); } + toggleInitiatorCostEnabled(_event) { + this.usesTagTeamHopeCost = !this.usesTagTeamHopeCost; + this.initiator.cost = this.usesTagTeamHopeCost ? + this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial : 0; + this.render(); + } + updateOpenForAllField(event) { this.openForAllPlayers = event.target.checked; this.render(); @@ -752,32 +768,37 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio /* Handle resource updates from the finished TagTeamRoll */ const tagTeamData = this.party.system.tagTeam; - const fearUpdate = { key: 'fear', value: null, enabled: true }; - for (let memberId in tagTeamData.members) { - const resourceUpdates = []; - const rollGivesHope = finalRoll.isCritical || finalRoll.withHope; - if (memberId === tagTeamData.initiator.memberId) { - const value = tagTeamData.initiator.cost - ? rollGivesHope - ? 1 - tagTeamData.initiator.cost - : -tagTeamData.initiator.cost - : 1; - resourceUpdates.push({ key: 'hope', value: value, enabled: true }); - } else if (rollGivesHope) { - resourceUpdates.push({ key: 'hope', value: 1, enabled: true }); - } - if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, enabled: true }); - if (finalRoll.withFear) { - fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1; - fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1; - } - game.actors.get(memberId).modifyResource(resourceUpdates); + const actorResourceMaps = Object.keys(tagTeamData.members).reduce((acc, key) => { + acc[key] = new ResourceUpdateMap(game.actors.get(key)); + return acc; + }, {}); + + if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) { + const fearResourceMap = actorResourceMaps[tagTeamData.initiator.memberId]; + for (const memberId in tagTeamData.members) { + const resourceMap = actorResourceMaps[memberId]; + if (finalRoll.isCritical) { + resourceMap.addResources([ + { key: 'stress', value: -1, enabled: true }, + { key: 'hope', value: 1, enabled: true } + ]); + } else if (finalRoll.withHope) { + resourceMap.addResources([{ key: 'hope', value: 1, enabled: true }]); + } else if (finalRoll.withFear) { + fearResourceMap.addResources([{ key: 'fear', value: 1, enabled: true }]); + } + } + } + + /* Even with Hope/Fear automation off, the hope cost of performing the TagTeamRoll can still optionally be subtracted */ + if (tagTeamData.initiator.cost) { + const resourceMap = actorResourceMaps[tagTeamData.initiator.memberId]; + resourceMap.addResources([{ key: 'hope', value: -tagTeamData.initiator.cost, enabled: true }]); } - if (fearUpdate.value) { - mainActor.modifyResource([fearUpdate]); - } + for (const resourceMap of Object.values(actorResourceMaps)) + resourceMap.updateResources(); /* Fin */ this.cancelRoll({ confirm: false }); diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 70e98242..e2d967a3 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -1,6 +1,6 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import D20Roll from './d20Roll.mjs'; -import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; +import { parseRallyDice, setDiceSoNiceForDualityRoll, shouldUseHopeFearAutomation } from '../helpers/utils.mjs'; import { getDiceSoNicePresets } from '../config/generalConfig.mjs'; import { updateResourcesForDualityReroll } from './helpers.mjs'; @@ -312,11 +312,9 @@ export default class DualityRoll extends D20Roll { } static async addDualityResourceUpdates(config) { - const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); - const hopeFearAutomation = automationSettings.hopeFear; if ( !config.source?.actor || - (game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) || + !shouldUseHopeFearAutomation() || config.actionType === 'reaction' || config.skips?.resources ) diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 3c5192be..6467edd7 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -885,3 +885,8 @@ export async function triggerChatRollFx(rolls, options = { whisper: false, blind foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); } } + +export function shouldUseHopeFearAutomation(options = { gmAsPlayer: true }) { + const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + return (!game.user.isGM || options.gmAsPlayer) ? hopeFear.players : hopeFear.gm; +} \ No newline at end of file diff --git a/styles/less/dialog/tag-team-dialog/initialization.less b/styles/less/dialog/tag-team-dialog/initialization.less index d6f7ad29..e79ed65c 100644 --- a/styles/less/dialog/tag-team-dialog/initialization.less +++ b/styles/less/dialog/tag-team-dialog/initialization.less @@ -88,9 +88,21 @@ grid-template-columns: 1fr 1fr; gap: 8px; - &.inactive { + .inactive { opacity: 0.4; } + + .initiator-cost-fields { + display: flex; + flex-direction: column; + align-items: flex-start; + + .initiator-cost-inputs { + display: grid; + grid-template-columns: auto 1fr; + align-items: center; + } + } } footer { diff --git a/templates/dialogs/tagTeamDialog/initialization.hbs b/templates/dialogs/tagTeamDialog/initialization.hbs index 0b92e68e..40491e1b 100644 --- a/templates/dialogs/tagTeamDialog/initialization.hbs +++ b/templates/dialogs/tagTeamDialog/initialization.hbs @@ -26,11 +26,16 @@
      -
      +
      -
      - -
      +
      + + +
      From 7237a3651d168338c47f9acf9bd4c56e72cf7d5d Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sun, 21 Jun 2026 05:29:07 -0400 Subject: [PATCH 08/13] Fix svg sizing on firefox (#2027) --- assets/icons/documents/actors/capybara.svg | 2 +- assets/icons/documents/actors/dark-squad.svg | 2 +- assets/icons/documents/actors/dragon-head.svg | 2 +- assets/icons/documents/actors/drama-masks.svg | 2 +- assets/icons/documents/actors/forest.svg | 2 +- assets/icons/documents/items/battered-axe.svg | 2 +- assets/icons/documents/items/card-play.svg | 2 +- assets/icons/documents/items/chest-armor.svg | 2 +- assets/icons/documents/items/family-tree.svg | 2 +- assets/icons/documents/items/laurel-crown.svg | 2 +- assets/icons/documents/items/laurels.svg | 2 +- assets/icons/documents/items/open-treasure-chest.svg | 2 +- assets/icons/documents/items/round-potion.svg | 2 +- assets/icons/documents/items/stars-stack.svg | 2 +- assets/icons/documents/items/village.svg | 2 +- assets/icons/documents/items/wolf-head.svg | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/assets/icons/documents/actors/capybara.svg b/assets/icons/documents/actors/capybara.svg index 90deb64a..8fbe2c06 100644 --- a/assets/icons/documents/actors/capybara.svg +++ b/assets/icons/documents/actors/capybara.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/dark-squad.svg b/assets/icons/documents/actors/dark-squad.svg index f21b4c5b..39ca794a 100644 --- a/assets/icons/documents/actors/dark-squad.svg +++ b/assets/icons/documents/actors/dark-squad.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/dragon-head.svg b/assets/icons/documents/actors/dragon-head.svg index d9e008f5..324ffbbb 100644 --- a/assets/icons/documents/actors/dragon-head.svg +++ b/assets/icons/documents/actors/dragon-head.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/drama-masks.svg b/assets/icons/documents/actors/drama-masks.svg index 84307da0..98b9b68b 100644 --- a/assets/icons/documents/actors/drama-masks.svg +++ b/assets/icons/documents/actors/drama-masks.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/forest.svg b/assets/icons/documents/actors/forest.svg index 8f7117e8..fcdb8a9d 100644 --- a/assets/icons/documents/actors/forest.svg +++ b/assets/icons/documents/actors/forest.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/battered-axe.svg b/assets/icons/documents/items/battered-axe.svg index 5d7be27d..436884bd 100644 --- a/assets/icons/documents/items/battered-axe.svg +++ b/assets/icons/documents/items/battered-axe.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/card-play.svg b/assets/icons/documents/items/card-play.svg index 587cb1c1..5c29fc43 100644 --- a/assets/icons/documents/items/card-play.svg +++ b/assets/icons/documents/items/card-play.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/chest-armor.svg b/assets/icons/documents/items/chest-armor.svg index 2cef80a6..03b82d48 100644 --- a/assets/icons/documents/items/chest-armor.svg +++ b/assets/icons/documents/items/chest-armor.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/family-tree.svg b/assets/icons/documents/items/family-tree.svg index d95c935d..031f23da 100644 --- a/assets/icons/documents/items/family-tree.svg +++ b/assets/icons/documents/items/family-tree.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/laurel-crown.svg b/assets/icons/documents/items/laurel-crown.svg index 34a54d2a..38dbcd04 100644 --- a/assets/icons/documents/items/laurel-crown.svg +++ b/assets/icons/documents/items/laurel-crown.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/laurels.svg b/assets/icons/documents/items/laurels.svg index 2c3cdf63..ae7398ec 100644 --- a/assets/icons/documents/items/laurels.svg +++ b/assets/icons/documents/items/laurels.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/open-treasure-chest.svg b/assets/icons/documents/items/open-treasure-chest.svg index 172a8003..d66399f4 100644 --- a/assets/icons/documents/items/open-treasure-chest.svg +++ b/assets/icons/documents/items/open-treasure-chest.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/round-potion.svg b/assets/icons/documents/items/round-potion.svg index 7f981914..0c235732 100644 --- a/assets/icons/documents/items/round-potion.svg +++ b/assets/icons/documents/items/round-potion.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/stars-stack.svg b/assets/icons/documents/items/stars-stack.svg index 19c197f6..2d446683 100644 --- a/assets/icons/documents/items/stars-stack.svg +++ b/assets/icons/documents/items/stars-stack.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/village.svg b/assets/icons/documents/items/village.svg index c28d742b..b7c776a1 100644 --- a/assets/icons/documents/items/village.svg +++ b/assets/icons/documents/items/village.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/wolf-head.svg b/assets/icons/documents/items/wolf-head.svg index 2be500c1..7e57bbad 100644 --- a/assets/icons/documents/items/wolf-head.svg +++ b/assets/icons/documents/items/wolf-head.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 3840f39c9791d441073a02e83a1252d7fc438460 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sun, 21 Jun 2026 05:34:49 -0400 Subject: [PATCH 09/13] Fade environment adversaries and notes tabs when empty (#2028) --- module/applications/sheets/actors/environment.mjs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 9a88dba6..60fb9071 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -72,6 +72,16 @@ export default class DhpEnvironment extends DHBaseActorSheet { return applicationOptions; } + /** @inheritdoc */ + _prepareTabs(group) { + const result = super._prepareTabs(group); + if (group === 'primary') { + result.potentialAdversaries.empty = foundry.utils.isEmpty(this.document.system.potentialAdversaries); + result.notes.empty = !this.document.system.notes?.trim(); + } + return result; + } + /**@inheritdoc */ async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); From f3859829878545f7793c2bd2257af23cc979f5af Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 21 Jun 2026 23:04:28 +0200 Subject: [PATCH 10/13] [Fix] Action Uses Not Spent (#2029) --- module/applications/dialogs/d20RollDialog.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index e9140b56..048797d8 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -160,7 +160,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } if (rest.hasOwnProperty('trait')) { this.config.roll.trait = rest.trait; - if (!this.config.source.item) + if (!this.config.source.item && this.config.roll.trait) this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { ability: game.i18n.localize(abilities[this.config.roll.trait]?.label) }); @@ -225,7 +225,6 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } static async submitRoll(event) { - event.preventDefault(); await this.close({ submitted: true }); } From 0d59e37a806d71b7daa6faef7229d942709abf01 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 21 Jun 2026 23:35:38 +0200 Subject: [PATCH 11/13] [Fix] Trigger Error Info (#2030) * Made trigger errors more informative * . --- lang/en.json | 2 +- module/data/registeredTriggers.mjs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lang/en.json b/lang/en.json index 5bab0e64..a4a5edf0 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1451,7 +1451,7 @@ }, "triggerType": "Trigger Type", "triggeringActorType": "Triggering Actor Type", - "triggerError": "{trigger} trigger failed for {actor}. It's probably configured wrong." + "triggerError": "{trigger} trigger on {item}({itemUuid}) failed for {actor}. It's probably configured wrong." }, "WeaponFeature": { "barrier": { diff --git a/module/data/registeredTriggers.mjs b/module/data/registeredTriggers.mjs index 0b637930..64e7f93e 100644 --- a/module/data/registeredTriggers.mjs +++ b/module/data/registeredTriggers.mjs @@ -150,11 +150,14 @@ export default class RegisteredTriggers extends Map { const result = await command(...args); if (result?.updates?.length) updates.push(...result.updates); } catch { + const item = await foundry.utils.fromUuid(itemUuid); const triggerName = game.i18n.localize(triggerData.label); - ui.notifications.error( + console.error( game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', { trigger: triggerName, - actor: currentActor?.name + actor: currentActor?.name, + item: item?.name ?? '', + itemUuid: item?.uuid ?? '' }) ); } From cc16a726bffb9bb4bd0a9f12f1d8e68b76bdc556 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sun, 21 Jun 2026 17:53:41 -0400 Subject: [PATCH 12/13] [Feature] In setting sheets, split by feature type and include descriptions (#2026) --- .../sheets-configs/adversary-settings.mjs | 25 +++++----- .../sheets-configs/environment-settings.mjs | 22 +++++--- .../sheets-configs/npc-settings.mjs | 19 ++++--- .../applications/sheets/api/actor-setting.mjs | 7 ++- .../sheets/api/application-mixin.mjs | 9 ++-- .../adversary-settings/features.hbs | 50 ++++++++++--------- .../environment-settings/features.hbs | 47 +++++++++-------- .../sheets-settings/npc-settings/features.hbs | 50 ++++++++++--------- .../global/partials/inventory-item-V2.hbs | 24 ++++----- 9 files changed, 143 insertions(+), 110 deletions(-) diff --git a/module/applications/sheets-configs/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs index 583f37b7..ff3f3039 100644 --- a/module/applications/sheets-configs/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -10,11 +10,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings { actions: { addExperience: DHAdversarySettings.#addExperience, removeExperience: DHAdversarySettings.#removeExperience - }, - dragDrop: [ - { dragSelector: null, dropSelector: '.tab.features' }, - { dragSelector: '.feature-item', dropSelector: null } - ] + } }; /**@override */ @@ -38,7 +34,8 @@ export default class DHAdversarySettings extends DHBaseActorSettings { }, features: { id: 'features', - template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs' + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs', + scrollable: [''] } }; @@ -54,12 +51,16 @@ export default class DHAdversarySettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); - context.features = context.document.system.features.sort((a, b) => - a.system.featureForm !== b.system.featureForm - ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) - : a.sort - b.sort - ); + // Get feature groups. Uncategorized go to actions + const featureFormsTypes = ['passive', 'action', 'reaction']; + const features = this.document.system.features.sort((a, b) => a.sort - b.sort); + const featureGroups = featureFormsTypes.map(t => ({ + featureForm: t, + label: _loc(CONFIG.DH.ITEM.featureForm[t]), + features: features.filter(f => f.system.featureForm === t) + })); + featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm))); + context.featureGroups = featureGroups; return context; } diff --git a/module/applications/sheets-configs/environment-settings.mjs b/module/applications/sheets-configs/environment-settings.mjs index d6744eb8..954d6381 100644 --- a/module/applications/sheets-configs/environment-settings.mjs +++ b/module/applications/sheets-configs/environment-settings.mjs @@ -32,11 +32,13 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { }, features: { id: 'features', - template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs' + template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs', + scrollable: [''] }, adversaries: { id: 'adversaries', - template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs' + template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs', + scrollable: [''] } }; @@ -52,12 +54,16 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - const featureForms = ['passive', 'action', 'reaction']; - context.features = context.document.system.features.sort((a, b) => - a.system.featureForm !== b.system.featureForm - ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) - : a.sort - b.sort - ); + // Get feature groups. Uncategorized go to actions + const featureFormsTypes = ['passive', 'action', 'reaction']; + const features = this.document.system.features.sort((a, b) => a.sort - b.sort); + const featureGroups = featureFormsTypes.map(t => ({ + featureForm: t, + label: _loc(CONFIG.DH.ITEM.featureForm[t]), + features: features.filter(f => f.system.featureForm === t) + })); + featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm))); + context.featureGroups = featureGroups; return context; } diff --git a/module/applications/sheets-configs/npc-settings.mjs b/module/applications/sheets-configs/npc-settings.mjs index d2132a91..33cbc270 100644 --- a/module/applications/sheets-configs/npc-settings.mjs +++ b/module/applications/sheets-configs/npc-settings.mjs @@ -27,7 +27,8 @@ export default class DHNPCSettings extends DHBaseActorSettings { }, features: { id: 'features', - template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs' + template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs', + scrollable: [''] } }; @@ -43,12 +44,16 @@ export default class DHNPCSettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - const featureForms = ['passive', 'action', 'reaction']; - context.features = context.document.system.features.sort((a, b) => - a.system.featureForm !== b.system.featureForm - ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) - : a.sort - b.sort - ); + // Get feature groups. Uncategorized go to actions + const featureFormsTypes = ['passive', 'action', 'reaction']; + const features = this.document.system.features.sort((a, b) => a.sort - b.sort); + const featureGroups = featureFormsTypes.map(t => ({ + featureForm: t, + label: _loc(CONFIG.DH.ITEM.featureForm[t]), + features: features.filter(f => f.system.featureForm === t) + })); + featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm))); + context.featureGroups = featureGroups; return context; } diff --git a/module/applications/sheets/api/actor-setting.mjs b/module/applications/sheets/api/actor-setting.mjs index 65497cec..fa434034 100644 --- a/module/applications/sheets/api/actor-setting.mjs +++ b/module/applications/sheets/api/actor-setting.mjs @@ -25,7 +25,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 }, dragDrop: [ { dragSelector: null, dropSelector: '.tab.features' }, - { dragSelector: '.feature-item', dropSelector: null } + { dragSelector: '.feature-item, .inventory-item[data-type="feature"]', dropSelector: null } ] }; @@ -77,7 +77,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 } async _onDragStart(event) { - const featureItemEl = event.currentTarget.closest('.feature-item'); + const featureItemEl = event.currentTarget.closest('.feature-item, .inventory-item[data-type="feature"]'); const feature = this.actor.items.get(featureItemEl?.dataset.itemId); if (feature && event.target.closest('.tab.features')) { const featureData = { ...feature.toDragData(), fromInternal: true }; @@ -100,4 +100,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 await this.actor.createEmbeddedDocuments('Item', [itemData]); } } + + /** Setting sheets do not auto extend */ + async _autoExpandDescriptions() {} } diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index f3d612e9..d89237df 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -4,6 +4,7 @@ import { getDocFromElement, getDocFromElementSync, tagifyElement } from '../../. const typeSettingsMap = { character: 'extendCharacterDescriptions', adversary: 'extendAdversaryDescriptions', + npc: 'extendAdversaryDescriptions', environment: 'extendEnvironmentDescriptions', ancestry: 'extendItemDescriptions', community: 'extendItemDescriptions', @@ -262,7 +263,7 @@ export default function DHApplicationMixin(Base) { if (!!this.options.contextMenus.length) this._createContextMenus(); - this.#autoExtendDescriptions(context); + this._autoExpandDescriptions(context); } /** @inheritDoc */ @@ -630,8 +631,9 @@ export default function DHApplicationMixin(Base) { /** * Extend inventory description when enabled in settings. * @returns {Promise} + * @protected */ - async #autoExtendDescriptions(context) { + async _autoExpandDescriptions(context) { const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]'); for (const el of inventoryItems) { // Get the doc uuid from the element @@ -734,7 +736,7 @@ export default function DHApplicationMixin(Base) { * @type {ApplicationClickAction} */ static async #onCreateDoc(event, target) { - const { documentClass, type, inVault, disabled } = target.dataset; + const { documentClass, type, inVault, disabled, featureForm } = target.dataset; const parentIsItem = this.document.documentName === 'Item'; const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature'; const parent = featureOnCharacter @@ -752,6 +754,7 @@ export default function DHApplicationMixin(Base) { identifier: this.document.system.isMulticlass ? 'multiclass' : null }; } + if (featureForm) systemData.featureForm = featureForm; const cls = type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass); diff --git a/templates/sheets-settings/adversary-settings/features.hbs b/templates/sheets-settings/adversary-settings/features.hbs index 3e0ed654..1cab8cfe 100644 --- a/templates/sheets-settings/adversary-settings/features.hbs +++ b/templates/sheets-settings/adversary-settings/features.hbs @@ -3,27 +3,31 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > - -
      - {{localize tabs.features.label}} -
        - {{#each @root.features as |feature|}} -
      • - -
        - {{feature.name}} -
        -
        - - -
        -
      • - {{/each}} -
      -
      - {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} -
      -
      + {{#each featureGroups as |group|}} +
      + + {{group.label}} + + + + +
        + {{#each group.features as |feature|}} + {{> 'daggerheart.inventory-item' + item=feature + type='feature' + actorType=@root.document.type + hideTags=true + hideContextMenu=true + hideResources=true + showActions=false + hideTooltip=true + }} + {{/each}} +
      +
      + {{/each}} +
      + {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} +
      \ No newline at end of file diff --git a/templates/sheets-settings/environment-settings/features.hbs b/templates/sheets-settings/environment-settings/features.hbs index ecda0e6b..1cab8cfe 100644 --- a/templates/sheets-settings/environment-settings/features.hbs +++ b/templates/sheets-settings/environment-settings/features.hbs @@ -3,24 +3,31 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > - -
      - {{localize tabs.features.label}} -
        - {{#each @root.features as |feature|}} -
      • - -
        - {{feature.name}} -
        -
        - - -
        -
      • - {{/each}} -
      -
      + {{#each featureGroups as |group|}} +
      + + {{group.label}} + + + + +
        + {{#each group.features as |feature|}} + {{> 'daggerheart.inventory-item' + item=feature + type='feature' + actorType=@root.document.type + hideTags=true + hideContextMenu=true + hideResources=true + showActions=false + hideTooltip=true + }} + {{/each}} +
      +
      + {{/each}} +
      + {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} +
      \ No newline at end of file diff --git a/templates/sheets-settings/npc-settings/features.hbs b/templates/sheets-settings/npc-settings/features.hbs index 3e0ed654..1cab8cfe 100644 --- a/templates/sheets-settings/npc-settings/features.hbs +++ b/templates/sheets-settings/npc-settings/features.hbs @@ -3,27 +3,31 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > - -
      - {{localize tabs.features.label}} -
        - {{#each @root.features as |feature|}} -
      • - -
        - {{feature.name}} -
        -
        - - -
        -
      • - {{/each}} -
      -
      - {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} -
      -
      + {{#each featureGroups as |group|}} +
      + + {{group.label}} + + + + +
        + {{#each group.features as |feature|}} + {{> 'daggerheart.inventory-item' + item=feature + type='feature' + actorType=@root.document.type + hideTags=true + hideContextMenu=true + hideResources=true + showActions=false + hideTooltip=true + }} + {{/each}} +
      +
      + {{/each}} +
      + {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} +
      \ No newline at end of file diff --git a/templates/sheets/global/partials/inventory-item-V2.hbs b/templates/sheets/global/partials/inventory-item-V2.hbs index 523e9304..f7d22a30 100644 --- a/templates/sheets/global/partials/inventory-item-V2.hbs +++ b/templates/sheets/global/partials/inventory-item-V2.hbs @@ -27,17 +27,17 @@ Parameters: >
      {{!-- Image --}} -
      - - {{#if item.usable}} - {{#if @root.isNPC}} - d20 - {{else}} - 2d12 +
      + + {{#if (and item.usable (ne showActions false))}} + {{#if @root.isNPC}} + d20 + {{else}} + 2d12 + {{/if}} {{/if}} - {{/if}}
      {{!-- Name & Tags --}} @@ -46,10 +46,10 @@ Parameters: {{localize item.name}} {{#unless (or noExtensible (not item.system.description))}}{{/unless}} {{!-- Tags Start --}} - {{#if (not ../hideTags)}} + {{#if (not hideTags)}} {{#> "systems/daggerheart/templates/sheets/global/partials/item-tags.hbs" item}} {{#if (eq ../type 'feature')}} - {{#if (and system.featureForm (or (eq @root.document.type "adversary") (eq @root.document.type "environment")))}} + {{#if (and system.featureForm (ne @root.document.type "character"))}}
      {{localize (concat "DAGGERHEART.CONFIG.FeatureForm." system.featureForm)}}
      From f490c00171a0a136880debb9402a3ffdfec499a5 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Fri, 29 May 2026 05:41:22 -0400 Subject: [PATCH 13/13] Styling pass for scrollbars, fieldsets, and scroll shadows --- styles/less/global/elements.less | 2 +- styles/less/global/sheet.less | 2 +- .../sheets/actors/actor-sheet-shared.less | 3 +- .../less/sheets/actors/adversary/effects.less | 2 +- .../sheets/actors/adversary/features.less | 8 +++- .../less/sheets/actors/adversary/index.less | 5 +-- .../less/sheets/actors/adversary/notes.less | 6 ++- .../less/sheets/actors/adversary/sheet.less | 39 ++++++++++-------- .../sheets/actors/character/biography.less | 3 +- .../sheets/actors/character/features.less | 1 + .../less/sheets/actors/character/index.less | 2 +- .../sheets/actors/character/inventory.less | 7 +++- .../less/sheets/actors/character/loadout.less | 4 +- .../less/sheets/actors/character/sheet.less | 41 ++++++++++--------- .../less/sheets/actors/companion/effects.less | 6 ++- .../sheets/actors/environment/features.less | 4 +- .../less/sheets/actors/environment/index.less | 3 +- .../less/sheets/actors/environment/notes.less | 11 +++++ .../environment/potentialAdversaries.less | 4 +- .../less/sheets/actors/environment/sheet.less | 2 + styles/less/sheets/actors/party/index.less | 3 +- .../less/sheets/actors/party/inventory.less | 6 +++ styles/less/sheets/actors/party/notes.less | 12 ++++++ .../sheets/actors/party/party-members.less | 1 + styles/less/sheets/actors/party/sheet.less | 2 + .../sheets/actors/adversary/features.hbs | 21 +++++----- templates/sheets/actors/adversary/notes.hbs | 5 +-- .../sheets/actors/environment/features.hbs | 19 +++++---- templates/sheets/actors/environment/notes.hbs | 5 +-- templates/sheets/actors/party/notes.hbs | 5 +-- 30 files changed, 147 insertions(+), 87 deletions(-) create mode 100644 styles/less/sheets/actors/environment/notes.less create mode 100644 styles/less/sheets/actors/party/notes.less diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index e57ba50d..9c074fb5 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -501,7 +501,7 @@ height: 1px; width: 100%; border-bottom: 1px solid @color-border; - mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); + mask-image: linear-gradient(270deg, transparent 0%, black 35%,black 50%, black 65%, transparent 100%); } side-line-div { diff --git a/styles/less/global/sheet.less b/styles/less/global/sheet.less index e3072da1..8381c7c3 100755 --- a/styles/less/global/sheet.less +++ b/styles/less/global/sheet.less @@ -54,7 +54,7 @@ body.game:is(.performance-low, .noblur) { position: relative; min-height: -webkit-fill-available; transition: opacity 0.3s ease; - padding-bottom: 20px; + padding-bottom: 16px; .tab { padding: 0 10px; diff --git a/styles/less/sheets/actors/actor-sheet-shared.less b/styles/less/sheets/actors/actor-sheet-shared.less index 89617103..6015047b 100644 --- a/styles/less/sheets/actors/actor-sheet-shared.less +++ b/styles/less/sheets/actors/actor-sheet-shared.less @@ -39,6 +39,7 @@ .window-header > .attribution-header-label { margin-right: var(--spacer-4); + pointer-events: none; } .tab.inventory { @@ -46,7 +47,7 @@ display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 10px; - padding: 10px 10px 0; + padding: 12px 12px 0 10px; .input { color: light-dark(@dark, @beige); diff --git a/styles/less/sheets/actors/adversary/effects.less b/styles/less/sheets/actors/adversary/effects.less index 4aa44e51..ce843b35 100644 --- a/styles/less/sheets/actors/adversary/effects.less +++ b/styles/less/sheets/actors/adversary/effects.less @@ -8,7 +8,7 @@ flex-direction: column; gap: 10px; overflow-y: auto; - padding-bottom: 20px; + scrollbar-gutter: stable; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/adversary/features.less b/styles/less/sheets/actors/adversary/features.less index 447d050e..f5bbd8aa 100644 --- a/styles/less/sheets/actors/adversary/features.less +++ b/styles/less/sheets/actors/adversary/features.less @@ -3,13 +3,17 @@ @import '../../../utils/mixin.less'; .application.sheet.daggerheart.actor.dh-style.adversary { - .tab.features { + .tab.features.active { + position: relative; + padding-left: 12px; .feature-section { display: flex; flex-direction: column; gap: 10px; + padding-top: 4px; + padding-right: 2px; overflow-y: auto; - padding-bottom: 20px; + scrollbar-gutter: stable; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/adversary/index.less b/styles/less/sheets/actors/adversary/index.less index 28ff9d22..a05af854 100644 --- a/styles/less/sheets/actors/adversary/index.less +++ b/styles/less/sheets/actors/adversary/index.less @@ -1,7 +1,6 @@ -@import './features.less'; -@import './header.less'; @import './sheet.less'; +@import './header.less'; +@import './features.less'; @import './sidebar.less'; @import './effects.less'; @import './notes.less'; - diff --git a/styles/less/sheets/actors/adversary/notes.less b/styles/less/sheets/actors/adversary/notes.less index a95d070e..006f7865 100644 --- a/styles/less/sheets/actors/adversary/notes.less +++ b/styles/less/sheets/actors/adversary/notes.less @@ -1,3 +1,7 @@ .application.sheet.daggerheart.actor.dh-style.adversary .tab.notes.active { - padding-bottom: 20px; + padding-top: 6px; + .editor-content { + scrollbar-gutter: stable; + .with-scroll-shadows(); + } } diff --git a/styles/less/sheets/actors/adversary/sheet.less b/styles/less/sheets/actors/adversary/sheet.less index 0bd845fa..ec6a3879 100644 --- a/styles/less/sheets/actors/adversary/sheet.less +++ b/styles/less/sheets/actors/adversary/sheet.less @@ -9,28 +9,31 @@ height: 100%; width: 100%; padding-bottom: 0; + } - .adversary-sidebar-sheet { - grid-row: 1 / span 2; - grid-column: 1; + .adversary-sidebar-sheet { + grid-row: 1 / span 2; + grid-column: 1; + overflow: hidden; + display: flex; + flex-direction: column; + } + + .adversary-header-sheet { + grid-row: 1; + grid-column: 2; + } + + .tab { + grid-row: 2; + grid-column: 2; + &.active { overflow: hidden; display: flex; flex-direction: column; - } - - .adversary-header-sheet { - grid-row: 1; - grid-column: 2; - } - - .tab { - grid-row: 2; - grid-column: 2; - &.active { - overflow: hidden; - display: flex; - flex-direction: column; - } + padding-right: 0; + margin-right: 1px; + margin-bottom: 12px; } } } diff --git a/styles/less/sheets/actors/character/biography.less b/styles/less/sheets/actors/character/biography.less index 8548a2fb..ce52c5af 100644 --- a/styles/less/sheets/actors/character/biography.less +++ b/styles/less/sheets/actors/character/biography.less @@ -11,8 +11,9 @@ height: 100%; overflow-y: auto; padding-top: 8px; - padding-bottom: 20px; + padding-bottom: 4px; height: 100%; + scrollbar-gutter: stable; .with-scroll-shadows(); } diff --git a/styles/less/sheets/actors/character/features.less b/styles/less/sheets/actors/character/features.less index 52b41826..f81f0e32 100644 --- a/styles/less/sheets/actors/character/features.less +++ b/styles/less/sheets/actors/character/features.less @@ -10,6 +10,7 @@ gap: 10px; overflow-y: auto; padding-bottom: 20px; + scrollbar-gutter: stable; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/character/index.less b/styles/less/sheets/actors/character/index.less index edefe0a1..f196d5bf 100644 --- a/styles/less/sheets/actors/character/index.less +++ b/styles/less/sheets/actors/character/index.less @@ -1,8 +1,8 @@ +@import './sheet.less'; @import './biography.less'; @import './effects.less'; @import './features.less'; @import './header.less'; @import './inventory.less'; @import './loadout.less'; -@import './sheet.less'; @import './sidebar.less'; diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index fcfbbee9..b07bb6fe 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -4,13 +4,18 @@ .application.sheet.daggerheart.actor.dh-style.character { .tab.inventory { + padding-right: 0; + .search-section { + padding-right: 14px; + } .items-section { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; + scrollbar-gutter: stable; margin-top: 20px; - padding-bottom: 20px; + padding-bottom: 4px; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index fa3e0176..67b2914b 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -5,6 +5,7 @@ .application.sheet.daggerheart.actor.dh-style.character { .tab.loadout { .search-section { + padding-right: 14px; .btn-toggle-view { background: light-dark(@dark-blue-10, @dark-blue); border: 1px solid @color-border; @@ -52,8 +53,9 @@ gap: 10px; height: 100%; overflow-y: auto; + scrollbar-gutter: stable; margin-top: 20px; - padding-bottom: 20px; + padding-bottom: 4px; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/character/sheet.less b/styles/less/sheets/actors/character/sheet.less index 68792c99..aebcb9b9 100644 --- a/styles/less/sheets/actors/character/sheet.less +++ b/styles/less/sheets/actors/character/sheet.less @@ -10,28 +10,31 @@ width: 100%; padding-bottom: 0; overflow-x: auto; + } + + .character-sidebar-sheet { + grid-row: 1 / span 2; + grid-column: 1; + display: flex; + flex-direction: column; + } - .character-sidebar-sheet { - grid-row: 1 / span 2; - grid-column: 1; + .character-header-sheet { + position: relative; + grid-row: 1; + grid-column: 2; + } + + .tab { + grid-row: 2; + grid-column: 2; + padding-right: 0; + margin-right: 2px; + margin-bottom: 12px; + &.active { display: flex; flex-direction: column; - } - - .character-header-sheet { - position: relative; - grid-row: 1; - grid-column: 2; - } - - .tab { - grid-row: 2; - grid-column: 2; - &.active { - display: flex; - flex-direction: column; - overflow: hidden; - } + overflow: hidden; } } } diff --git a/styles/less/sheets/actors/companion/effects.less b/styles/less/sheets/actors/companion/effects.less index c0cac669..40973196 100644 --- a/styles/less/sheets/actors/companion/effects.less +++ b/styles/less/sheets/actors/companion/effects.less @@ -1,13 +1,17 @@ @import '../../../utils/colors.less'; +@import '../../../utils/mixin.less'; .application.sheet.daggerheart.actor.dh-style.companion { .tab.effects { + margin-right: 2px; + padding-right: 0; .effects-sections { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; - padding-bottom: 20px; + padding-bottom: 4px; + scrollbar-gutter: stable; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/environment/features.less b/styles/less/sheets/actors/environment/features.less index 84cf26f8..295636a7 100644 --- a/styles/less/sheets/actors/environment/features.less +++ b/styles/less/sheets/actors/environment/features.less @@ -4,12 +4,14 @@ .application.sheet.daggerheart.actor.dh-style.environment { .tab.features { + position: relative; .feature-section { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; - padding-bottom: 4px; + padding: 4px 8px; + scrollbar-gutter: stable; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/environment/index.less b/styles/less/sheets/actors/environment/index.less index 211c8e60..db35eabc 100644 --- a/styles/less/sheets/actors/environment/index.less +++ b/styles/less/sheets/actors/environment/index.less @@ -1,4 +1,5 @@ +@import './sheet.less'; @import './features.less'; @import './header.less'; @import './potentialAdversaries.less'; -@import './sheet.less'; +@import './notes.less'; diff --git a/styles/less/sheets/actors/environment/notes.less b/styles/less/sheets/actors/environment/notes.less new file mode 100644 index 00000000..58447c88 --- /dev/null +++ b/styles/less/sheets/actors/environment/notes.less @@ -0,0 +1,11 @@ +@import '../../../utils/mixin.less'; + +.application.sheet.daggerheart.actor.dh-style.environment { + .tab.notes { + padding: 6px 0 4px 15px; + .editor-content { + scrollbar-gutter: stable; + .with-scroll-shadows(); + } + } +} \ No newline at end of file diff --git a/styles/less/sheets/actors/environment/potentialAdversaries.less b/styles/less/sheets/actors/environment/potentialAdversaries.less index f112c0d2..e66ff34d 100644 --- a/styles/less/sheets/actors/environment/potentialAdversaries.less +++ b/styles/less/sheets/actors/environment/potentialAdversaries.less @@ -1,4 +1,5 @@ @import '../../../utils/colors.less'; +@import '../../../utils/mixin.less'; .application.sheet.daggerheart.actor.dh-style.environment { .tab.potentialAdversaries { @@ -7,7 +8,8 @@ flex-direction: column; gap: 10px; overflow-y: auto; - padding-bottom: 4px; + padding: 0 4px 4px 4px; + scrollbar-gutter: stable; .with-scroll-shadows(); } } diff --git a/styles/less/sheets/actors/environment/sheet.less b/styles/less/sheets/actors/environment/sheet.less index 2d9cc188..02489cac 100644 --- a/styles/less/sheets/actors/environment/sheet.less +++ b/styles/less/sheets/actors/environment/sheet.less @@ -16,6 +16,8 @@ .tab { flex: 1; overflow-y: auto; + padding-right: 0; + margin-right: 2px; &.active { overflow: hidden; diff --git a/styles/less/sheets/actors/party/index.less b/styles/less/sheets/actors/party/index.less index 56f7a457..279c9db2 100644 --- a/styles/less/sheets/actors/party/index.less +++ b/styles/less/sheets/actors/party/index.less @@ -1,4 +1,5 @@ +@import './sheet.less'; @import './header.less'; @import './party-members.less'; -@import './sheet.less'; @import './inventory.less'; +@import './notes.less'; \ No newline at end of file diff --git a/styles/less/sheets/actors/party/inventory.less b/styles/less/sheets/actors/party/inventory.less index 444c6a57..4b14e112 100644 --- a/styles/less/sheets/actors/party/inventory.less +++ b/styles/less/sheets/actors/party/inventory.less @@ -4,11 +4,17 @@ .application.sheet.daggerheart.actor.dh-style.party { .tab.inventory { + padding-right: 0; + .search-section { + padding-right: 14px; + } + .items-section { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; + scrollbar-gutter: stable; margin-top: 20px; padding-bottom: 4px; .with-scroll-shadows(); diff --git a/styles/less/sheets/actors/party/notes.less b/styles/less/sheets/actors/party/notes.less new file mode 100644 index 00000000..4ef51caa --- /dev/null +++ b/styles/less/sheets/actors/party/notes.less @@ -0,0 +1,12 @@ +@import '../../../utils/mixin.less'; + +.application.sheet.daggerheart.actor.dh-style.party { + .tab.notes { + padding: 16px 0 4px 15px; + .editor-content { + scrollbar-gutter: stable; + padding-left: 8px; + .with-scroll-shadows(); + } + } +} \ No newline at end of file diff --git a/styles/less/sheets/actors/party/party-members.less b/styles/less/sheets/actors/party/party-members.less index dc464291..7b85eb35 100644 --- a/styles/less/sheets/actors/party/party-members.less +++ b/styles/less/sheets/actors/party/party-members.less @@ -4,6 +4,7 @@ .application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers { overflow: auto; + .with-scroll-shadows(); .actors-list { display: flex; diff --git a/styles/less/sheets/actors/party/sheet.less b/styles/less/sheets/actors/party/sheet.less index 852b6cfc..33aa64a3 100644 --- a/styles/less/sheets/actors/party/sheet.less +++ b/styles/less/sheets/actors/party/sheet.less @@ -21,6 +21,8 @@ flex: 1; overflow-y: auto; scrollbar-gutter: stable; + margin-right: 2px; + padding-right: 8px; &.active { overflow: auto; diff --git a/templates/sheets/actors/adversary/features.hbs b/templates/sheets/actors/adversary/features.hbs index 3b495e74..8430d454 100644 --- a/templates/sheets/actors/adversary/features.hbs +++ b/templates/sheets/actors/adversary/features.hbs @@ -1,14 +1,15 @@
      - {{> 'daggerheart.inventory-items' - title=tabs.features.label - type='feature' - collection=@root.features - hideContextMenu=true - hideModifyControls=true - canCreate=@root.editable - showActions=@root.editable - }} + {{#each @root.features as |item|}} + {{> 'daggerheart.inventory-item' + item=item + type='feature' + actorType=@root.document.type + hideContextMenu=true + hideModifyControls=true + showActions=@root.editable + }} + {{/each}}
      -
      \ No newline at end of file + diff --git a/templates/sheets/actors/adversary/notes.hbs b/templates/sheets/actors/adversary/notes.hbs index a5c3f706..28df7f8e 100644 --- a/templates/sheets/actors/adversary/notes.hbs +++ b/templates/sheets/actors/adversary/notes.hbs @@ -3,10 +3,7 @@ data-tab='{{tabs.notes.id}}' data-group='{{tabs.notes.group}}' > -
      - {{localize tabs.notes.label}} - {{formInput notes.field value=notes.value enriched=notes.enriched toggled=true}} -
      + {{formInput notes.field value=notes.value enriched=notes.enriched class="aaa" toggled=true}} {{#if (and showAttribution document.system.attribution.artist)}} diff --git a/templates/sheets/actors/environment/features.hbs b/templates/sheets/actors/environment/features.hbs index 35fcb038..264d6bf5 100644 --- a/templates/sheets/actors/environment/features.hbs +++ b/templates/sheets/actors/environment/features.hbs @@ -4,14 +4,15 @@ data-group='{{tabs.features.group}}' >
      - {{> 'daggerheart.inventory-items' - title=tabs.features.label - type='feature' - collection=@root.features - hideContextMenu=true - hideModifyControls=true - canCreate=@root.editable - showActions=@root.editable - }} + {{#each @root.features as |item|}} + {{> 'daggerheart.inventory-item' + item=item + type='feature' + actorType=@root.document.type + hideContextMenu=true + hideModifyControls=true + showActions=@root.editable + }} + {{/each}}
      \ No newline at end of file diff --git a/templates/sheets/actors/environment/notes.hbs b/templates/sheets/actors/environment/notes.hbs index 4f6b131e..1acf0e93 100644 --- a/templates/sheets/actors/environment/notes.hbs +++ b/templates/sheets/actors/environment/notes.hbs @@ -3,10 +3,7 @@ data-tab='{{tabs.notes.id}}' data-group='{{tabs.notes.group}}' > -
      - {{localize tabs.notes.label}} - {{formInput notes.field value=notes.value enriched=notes.value toggled=true}} -
      + {{formInput notes.field value=notes.value enriched=notes.value toggled=true}} {{#if (and showAttribution document.system.attribution.artist)}} diff --git a/templates/sheets/actors/party/notes.hbs b/templates/sheets/actors/party/notes.hbs index 663a484a..0972bee9 100644 --- a/templates/sheets/actors/party/notes.hbs +++ b/templates/sheets/actors/party/notes.hbs @@ -3,8 +3,5 @@ data-tab='{{tabs.notes.id}}' data-group='{{tabs.notes.group}}' > -
      - {{localize tabs.notes.label}} - {{formInput notes.field value=notes.value enriched=notes.value toggled=true}} -
      + {{formInput notes.field value=notes.value enriched=notes.value toggled=true}} \ No newline at end of file