From 5e7201bfe990a4c4df8eb91d4c12cae66bb59cd4 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:59:08 +0100 Subject: [PATCH 01/10] [Fix]Environment Attack Error (#1647) * Fixed so that environment attacks don't error * Fixed for companion aswell --- module/data/fields/action/damageField.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 56eb51e5..efad726c 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -109,8 +109,8 @@ export default class DamageField extends fields.SchemaField { ); else { const configDamage = foundry.utils.deepClone(config.damage); - const hpDamageMultiplier = config.actionActor?.system.rules.attack.damage.hpDamageMultiplier ?? 1; - const hpDamageTakenMultiplier = actor.system.rules.attack.damage.hpDamageTakenMultiplier; + const hpDamageMultiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1; + const hpDamageTakenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier; if (configDamage.hitPoints) { for (const part of configDamage.hitPoints.parts) { part.total = Math.ceil(part.total * hpDamageMultiplier * hpDamageTakenMultiplier); From 202e624a068718757088cf5a013499c748ce7fce Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:00:09 +0100 Subject: [PATCH 02/10] Fixed so that SecondWind has a decreasing resource (#1642) --- src/packs/domains/domainCard_Second_Wind_ffPbSEvLuFrFsMxl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packs/domains/domainCard_Second_Wind_ffPbSEvLuFrFsMxl.json b/src/packs/domains/domainCard_Second_Wind_ffPbSEvLuFrFsMxl.json index a8a21ec3..8dc535cc 100644 --- a/src/packs/domains/domainCard_Second_Wind_ffPbSEvLuFrFsMxl.json +++ b/src/packs/domains/domainCard_Second_Wind_ffPbSEvLuFrFsMxl.json @@ -170,7 +170,8 @@ "value": 1, "recovery": "shortRest", "max": "1", - "icon": "" + "icon": "", + "progression": "decreasing" }, "attribution": { "source": "Daggerheart SRD", From 44131d21a6170879a4cc6418c562636ea4a5cbee Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:01:30 +0100 Subject: [PATCH 03/10] [Fix] Beastform Effects (#1635) * Fixed so that beastform items always have a beastformEffect on them that can't be removed * Fixed so that you can drag an active effect onto a character --- .../sheets/api/application-mixin.mjs | 8 ++++++-- module/data/item/beastform.mjs | 16 ++++++++++++++++ module/documents/activeEffect.mjs | 5 +++-- .../sheets/global/partials/inventory-item-V2.hbs | 2 +- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 3c0444eb..49f7dcf0 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -433,7 +433,7 @@ export default function DHApplicationMixin(Base) { icon: 'fa-solid fa-lightbulb', condition: target => { const doc = getDocFromElementSync(target); - return doc && !doc.disabled; + return doc && !doc.disabled && doc.type !== 'beastform'; }, callback: async target => (await getDocFromElement(target)).update({ disabled: true }) }, @@ -442,7 +442,7 @@ export default function DHApplicationMixin(Base) { icon: 'fa-regular fa-lightbulb', condition: target => { const doc = getDocFromElementSync(target); - return doc && doc.disabled; + return doc && doc.disabled && doc.type !== 'beastform'; }, callback: async target => (await getDocFromElement(target)).update({ disabled: false }) } @@ -536,6 +536,10 @@ export default function DHApplicationMixin(Base) { options.push({ name: 'CONTROLS.CommonDelete', icon: 'fa-solid fa-trash', + condition: target => { + const doc = getDocFromElementSync(target); + return doc && doc.type !== 'beastform'; + }, callback: async (target, event) => { const doc = await getDocFromElement(target); if (event.shiftKey) return doc.delete(); diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index dd491169..3a41aa7e 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -253,4 +253,20 @@ export default class DHBeastform extends BaseDataItem { return false; } + + _onCreate(_data, _options, userId) { + if (!this.actor && game.user.id === userId) { + const hasBeastformEffect = this.parent.effects.some(x => x.type === 'beastform'); + if (!hasBeastformEffect) + this.parent.createEmbeddedDocuments('ActiveEffect', [ + { + type: 'beastform', + name: game.i18n.localize('DAGGERHEART.ITEMS.Beastform.beastformEffect'), + img: 'icons/creatures/abilities/paw-print-pair-purple.webp' + } + ]); + + return; + } + } } diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 5e9b0c3b..d0e329ff 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -61,14 +61,15 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { update.img = 'icons/magic/life/heart-cross-blue.webp'; } + const statuses = Object.keys(data.statuses ?? {}); const immuneStatuses = - data.statuses?.filter( + statuses.filter( status => this.parent.system.rules?.conditionImmunities && this.parent.system.rules.conditionImmunities[status] ) ?? []; if (immuneStatuses.length > 0) { - update.statuses = data.statuses.filter(x => !immuneStatuses.includes(x)); + update.statuses = statuses.filter(x => !immuneStatuses.includes(x)); const conditions = CONFIG.DH.GENERAL.conditions(); const scrollingTexts = immuneStatuses.map(status => ({ text: game.i18n.format('DAGGERHEART.ACTIVEEFFECT.immuneStatusText', { diff --git a/templates/sheets/global/partials/inventory-item-V2.hbs b/templates/sheets/global/partials/inventory-item-V2.hbs index dbacd1e4..76e13a5c 100644 --- a/templates/sheets/global/partials/inventory-item-V2.hbs +++ b/templates/sheets/global/partials/inventory-item-V2.hbs @@ -113,7 +113,7 @@ Parameters: data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.system.inVault 'sendToLoadout' 'sendToVault' }}"> - {{else if (eq type 'effect')}} + {{else if (and (eq type 'effect') (not (eq item.type 'beastform')))}} From f7e4c5346effe775250db51770cf4a6ae22cfb5d Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:03:35 +0100 Subject: [PATCH 04/10] [Fix] ActiveEffect Autocomplete (#1641) * Added rules and bonuses to ActiveEffect-autocomplete * . --- lang/en.json | 49 +++++++++++++++++++ .../sheets-configs/activeEffectConfig.mjs | 23 ++++++++- module/data/actor/base.mjs | 43 +++++++++++++--- module/data/actor/character.mjs | 25 +++++++--- module/data/actor/companion.mjs | 15 ++++-- 5 files changed, 137 insertions(+), 18 deletions(-) diff --git a/lang/en.json b/lang/en.json index 86b4323c..81408c66 100755 --- a/lang/en.json +++ b/lang/en.json @@ -192,6 +192,9 @@ }, "age": "Age", "backgroundQuestions": "Backgrounds", + "burden": { + "ignore": { "label": "Burden: Ignore", "hint": "Ignore burden rules" } + }, "companionFeatures": "Companion Features", "connections": "Connections", "contextMenu": { @@ -214,6 +217,12 @@ "maxEvasionBonus": "Max Evasion Increase", "maxHPBonus": "Max HP Increase", "pronouns": "Pronouns", + "roll": { + "guaranteedCritical": { + "label": "Guaranteed Critical", + "hint": "Set to 1 to always roll a critical" + } + }, "story": { "backgroundTitle": "Background", "characteristics": "Characteristics", @@ -1840,6 +1849,16 @@ "singular": "Adversary", "plural": "Adversaries" }, + "Attack": { + "hpDamageMultiplier": { + "label": "HP Damage Multiplier", + "hint": "Multiply any damage you deal by this number" + }, + "hpDamageTakenMultiplier": { + "label": "HP Damage Taken Multiplier", + "hint": "Multiply any damage dealt to you by this number" + } + }, "Bonuses": { "rest": { "downtimeAction": "Downtime Action", @@ -2024,16 +2043,40 @@ "reaction": "Reaction Roll" }, "Rules": { + "conditionImmunities": { + "hidden": "Condition Immunity: Hidden", + "restrained": "Condition Immunity: Restrained", + "vulnerable": "Condition Immunity: Vulnerable" + }, "damageReduction": { + "disabledArmor": { "label": "Disabled Armorslots" }, "increasePerArmorMark": { "label": "Damage Reduction per Armor Slot", "hint": "A used armor slot normally reduces damage by one step. This value increases the number of steps damage is reduced by." }, + "magical": { + "label": "Daamge Reduction: Only Magical", + "hint": "Armor can only be used to reduce magical damage" + }, "maxArmorMarkedBonus": "Max Armor Used", "maxArmorMarkedStress": { "label": "Max Armor Used With Stress", "hint": "If this value is set you can use up to that much stress to spend additional Armor Marks beyond your normal maximum." }, + "reduceSeverity": { + "magical": { + "label": "Reduce Damage Severity: Magical", + "hint": "Lowers any magical damage received by the set amount of severity degrees" + }, + "physical": { + "label": "Reduce Damage Severity: Physical", + "hint": "Lowers any physical damage received by the set amount of severity degrees" + } + }, + "physical": { + "label": "Damage Reduction: Only Physical", + "hint": "Armor can only be used to reduce physical damage" + }, "stress": { "any": { "label": "Stress Damage Reduction: Any", @@ -2051,6 +2094,12 @@ "label": "Stress Damage Reduction: Minor", "hint": "The cost in stress you can pay to reduce minor damage to none." } + }, + "thresholdImmunities": { + "minor": { + "label": "Threshold Immunities: Minor", + "hint": "Automatically ignores minor damage" + } } }, "attack": { diff --git a/module/applications/sheets-configs/activeEffectConfig.mjs b/module/applications/sheets-configs/activeEffectConfig.mjs index 9b8edd8a..8abc0b79 100644 --- a/module/applications/sheets-configs/activeEffectConfig.mjs +++ b/module/applications/sheets-configs/activeEffectConfig.mjs @@ -5,6 +5,24 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac super(options); const ignoredActorKeys = ['config', 'DhEnvironment', 'DhParty']; + + const getAllLeaves = (root, group, parentPath = '') => { + const leaves = []; + const rootKey = `${parentPath ? `${parentPath}.` : ''}${root.name}`; + for (const field of Object.values(root.fields)) { + if (field instanceof foundry.data.fields.SchemaField) + leaves.push(...getAllLeaves(field, group, rootKey)); + else + leaves.push({ + value: `${rootKey}.${field.name}`, + label: game.i18n.localize(field.label), + hint: game.i18n.localize(field.hint), + group + }); + } + + return leaves; + }; this.changeChoices = Object.keys(game.system.api.models.actors).reduce((acc, key) => { if (ignoredActorKeys.includes(key)) return acc; @@ -30,7 +48,10 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac return { value: joined, label: getLabel(joined), group }; }); - acc.push(...bars, ...values); + const bonuses = getAllLeaves(model.schema.fields.bonuses, group); + const rules = getAllLeaves(model.schema.fields.rules, group); + + acc.push(...bars, ...values, ...rules, ...bonuses); return acc; }, []); diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 08308eab..5e16bac9 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -29,17 +29,40 @@ const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) => /* Common rules applying to Characters and Adversaries */ export const commonActorRules = (extendedData = { damageReduction: {}, attack: { damage: {} } }) => ({ conditionImmunities: new fields.SchemaField({ - hidden: new fields.BooleanField({ initial: false }), - restrained: new fields.BooleanField({ initial: false }), - vulnerable: new fields.BooleanField({ initial: false }) + hidden: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.hidden' + }), + restrained: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.restrained' + }), + vulnerable: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable' + }) }), damageReduction: new fields.SchemaField({ thresholdImmunities: new fields.SchemaField({ - minor: new fields.BooleanField({ initial: false }) + minor: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.thresholdImmunities.minor.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.thresholdImmunities.minor.hint' + }) }), reduceSeverity: new fields.SchemaField({ - magical: new fields.NumberField({ initial: 0, min: 0 }), - physical: new fields.NumberField({ initial: 0, min: 0 }) + magical: new fields.NumberField({ + initial: 0, + min: 0, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.magical.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.magical.hint' + }), + physical: new fields.NumberField({ + initial: 0, + min: 0, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.physical.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.physical.hint' + }) }), ...(extendedData.damageReduction ?? {}) }), @@ -49,12 +72,16 @@ export const commonActorRules = (extendedData = { damageReduction: {}, attack: { hpDamageMultiplier: new fields.NumberField({ required: true, nullable: false, - initial: 1 + initial: 1, + label: 'DAGGERHEART.GENERAL.Attack.hpDamageMultiplier.label', + hint: 'DAGGERHEART.GENERAL.Attack.hpDamageMultiplier.hint' }), hpDamageTakenMultiplier: new fields.NumberField({ required: true, nullable: false, - initial: 1 + initial: 1, + label: 'DAGGERHEART.GENERAL.Attack.hpDamageTakenMultiplier.label', + hint: 'DAGGERHEART.GENERAL.Attack.hpDamageTakenMultiplier.hint' }), ...(extendedData.attack?.damage ?? {}) }) diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 3913d426..c79bb078 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -225,8 +225,16 @@ export default class DhCharacter extends BaseDataActor { rules: new fields.SchemaField({ ...commonActorRules({ damageReduction: { - magical: new fields.BooleanField({ initial: false }), - physical: new fields.BooleanField({ initial: false }), + magical: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.magical.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.magical.hint' + }), + physical: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.physical.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.physical.hint' + }), maxArmorMarked: new fields.SchemaField({ value: new fields.NumberField({ required: true, @@ -256,7 +264,10 @@ export default class DhCharacter extends BaseDataActor { label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.label', hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint' }), - disabledArmor: new fields.BooleanField({ intial: false }) + disabledArmor: new fields.BooleanField({ + intial: false, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.disabledArmor.label' + }) }, attack: { damage: { @@ -304,12 +315,14 @@ export default class DhCharacter extends BaseDataActor { label: 'DAGGERHEART.ACTORS.Character.defaultFearDice' }) }), - runeWard: new fields.BooleanField({ initial: false }), burden: new fields.SchemaField({ - ignore: new fields.BooleanField() + ignore: new fields.BooleanField({ label: 'DAGGERHEART.ACTORS.Character.burden.ignore.label' }) }), roll: new fields.SchemaField({ - guaranteedCritical: new fields.BooleanField() + guaranteedCritical: new fields.BooleanField({ + label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label', + hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint' + }) }) }) }; diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 1c25b48c..40cece72 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -53,9 +53,18 @@ export default class DhCompanion extends BaseDataActor { ), rules: new fields.SchemaField({ conditionImmunities: new fields.SchemaField({ - hidden: new fields.BooleanField({ initial: false }), - restrained: new fields.BooleanField({ initial: false }), - vulnerable: new fields.BooleanField({ initial: false }) + hidden: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.hidden' + }), + restrained: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.restrained' + }), + vulnerable: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable' + }) }) }), attack: new ActionField({ From 4ad8b960b53cf23f8e56e1906aafb5050cbb46c6 Mon Sep 17 00:00:00 2001 From: alterNERDtive <53827887+alterNERDtive@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:30:32 +0000 Subject: [PATCH 05/10] fix: adds actions to prepare downtime actions (#1646) --- lang/en.json | 8 +++ module/config/generalConfig.mjs | 102 +++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/lang/en.json b/lang/en.json index 81408c66..0eab2dbc 100755 --- a/lang/en.json +++ b/lang/en.json @@ -455,6 +455,10 @@ "description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.", "name": "Prepare" }, + "prepareWithFriends": { + "description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.", + "name": "Prepare (with Friends)" + }, "repairArmor": { "description": "Describe how you spend time repairing your armor and clear all of its Armor Slots. You may also do this to an ally's armor instead.", "name": "Repair Armor" @@ -486,6 +490,10 @@ "prepare": { "name": "Prepare", "description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope." + }, + "prepareWithFriends": { + "name": "Prepare (with Friends)", + "description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope." } }, "refreshable": { diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 5e5eecfb..a38d1c8a 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -331,7 +331,56 @@ export const defaultRestOptions = { icon: 'fa-solid fa-dumbbell', img: 'icons/skills/trades/academics-merchant-scribe.webp', description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.description'), - actions: {}, + actions: { + prepare: { + type: 'healing', + systemPath: 'restMoves.shortRest.moves.prepare.actions', + name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.name'), + img: 'icons/skills/trades/academics-merchant-scribe.webp', + actionType: 'action', + chatDisplay: false, + target: { + type: 'self' + }, + damage: { + parts: [ + { + applyTo: healingTypes.hope.id, + value: { + custom: { + enabled: true, + formula: '1' + } + } + } + ] + } + }, + prepareWithFriends: { + type: 'healing', + systemPath: 'restMoves.shortRest.moves.prepare.actions', + name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepareWithFriends.name'), + img: 'icons/skills/trades/academics-merchant-scribe.webp', + actionType: 'action', + chatDisplay: false, + target: { + type: 'self' + }, + damage: { + parts: [ + { + applyTo: healingTypes.hope.id, + value: { + custom: { + enabled: true, + formula: '2' + } + } + } + ] + } + } + }, effects: [] } }), @@ -446,7 +495,56 @@ export const defaultRestOptions = { icon: 'fa-solid fa-dumbbell', img: 'icons/skills/trades/academics-merchant-scribe.webp', description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.description'), - actions: {}, + actions: { + prepare: { + type: 'healing', + systemPath: 'restMoves.longRest.moves.prepare.actions', + name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.name'), + img: 'icons/skills/trades/academics-merchant-scribe.webp', + actionType: 'action', + chatDisplay: false, + target: { + type: 'self' + }, + damage: { + parts: [ + { + applyTo: healingTypes.hope.id, + value: { + custom: { + enabled: true, + formula: '1' + } + } + } + ] + } + }, + prepareWithFriends: { + type: 'healing', + systemPath: 'restMoves.longRest.moves.prepare.actions', + name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepareWithFriends.name'), + img: 'icons/skills/trades/academics-merchant-scribe.webp', + actionType: 'action', + chatDisplay: false, + target: { + type: 'self' + }, + damage: { + parts: [ + { + applyTo: healingTypes.hope.id, + value: { + custom: { + enabled: true, + formula: '2' + } + } + } + ] + } + } + }, effects: [] }, workOnAProject: { From 78012be6e42a5ee53726684235dde9bf41b8b2ce Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 8 Feb 2026 19:14:04 +0100 Subject: [PATCH 06/10] Added delete confirmation to homebrew items --- lang/en.json | 2 ++ module/applications/settings/homebrewSettings.mjs | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lang/en.json b/lang/en.json index 0eab2dbc..9b2b4872 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2613,6 +2613,8 @@ "resetMovesTitle": "Reset {type} Downtime Moves", "resetItemFeaturesTitle": "Reset {type}", "resetMovesText": "Are you sure you want to reset?", + "deleteItemTitle": "Delete Homebrew Item", + "deleteItemText": "Are you sure you want to delete the item?", "FIELDS": { "maxFear": { "label": "Max Fear" }, "maxHope": { "label": "Max Hope" }, diff --git a/module/applications/settings/homebrewSettings.mjs b/module/applications/settings/homebrewSettings.mjs index add3c9e1..51bf439e 100644 --- a/module/applications/settings/homebrewSettings.mjs +++ b/module/applications/settings/homebrewSettings.mjs @@ -103,6 +103,12 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli ? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] } : null; break; + case 'downtime': + context.restOptions = { + shortRest: CONFIG.DH.GENERAL.defaultRestOptions.shortRest(), + longRest: CONFIG.DH.GENERAL.defaultRestOptions.longRest() + }; + break; } return context; @@ -225,6 +231,15 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli } static async removeItem(_, target) { + const confirmed = await foundry.applications.api.DialogV2.confirm({ + window: { + title: game.i18n.localize(`DAGGERHEART.SETTINGS.Homebrew.deleteItemTitle`) + }, + content: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.deleteItemText') + }); + + if (!confirmed) return; + const { type, id } = target.dataset; const isDowntime = ['shortRest', 'longRest'].includes(type); const path = isDowntime ? `restMoves.${type}.moves` : `itemFeatures.${type}`; From f9f252c7a6f9d6de4d86d19c9990dd8d18b38daa Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:22:48 +0100 Subject: [PATCH 07/10] Fixed so that node start can accept escaped spaces in the path (#1649) --- tools/run-start.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run-start.mjs b/tools/run-start.mjs index e620d13f..3f6b25cb 100644 --- a/tools/run-start.mjs +++ b/tools/run-start.mjs @@ -18,7 +18,7 @@ const foundryPath = process.env.FOUNDRY_MAIN_PATH || '../../../../FoundryDev/mai const dataPath = process.env.FOUNDRY_DATA_PATH || '../../../'; // Run the original command with proper environment -const args = ['rollup -c --watch', `node "${foundryPath}" --dataPath="${dataPath}" --noupnp`, 'gulp']; +const args = ['rollup -c --watch', `node "\"${foundryPath}\"" --dataPath="${dataPath}" --noupnp`, 'gulp']; spawn('npx', ['concurrently', ...args.map(arg => `"${arg}"`)], { stdio: 'inherit', From d96e72505a7941e991d3771e5fd07d1e43fb10e2 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 8 Feb 2026 22:21:36 +0100 Subject: [PATCH 08/10] Fixed Armor/Weapon sheet showing double 'Configure Attribution' options --- module/applications/sheets/api/item-attachment-sheet.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/module/applications/sheets/api/item-attachment-sheet.mjs b/module/applications/sheets/api/item-attachment-sheet.mjs index 2898f5ac..bcf2fc3c 100644 --- a/module/applications/sheets/api/item-attachment-sheet.mjs +++ b/module/applications/sheets/api/item-attachment-sheet.mjs @@ -1,7 +1,6 @@ export default function ItemAttachmentSheet(Base) { return class extends Base { static DEFAULT_OPTIONS = { - ...super.DEFAULT_OPTIONS, dragDrop: [ ...(super.DEFAULT_OPTIONS.dragDrop || []), { dragSelector: null, dropSelector: '.attachments-section' } From 5413730108f4efbc5824347948a4855dd80d41a6 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Mon, 9 Feb 2026 00:25:18 +0100 Subject: [PATCH 09/10] Corrected experience value display to handle negative values aswell --- templates/dialogs/dice-roll/rollSelection.hbs | 2 +- templates/sheets/actors/character/sidebar.hbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/dialogs/dice-roll/rollSelection.hbs b/templates/dialogs/dice-roll/rollSelection.hbs index f31a4fa8..5139c58a 100644 --- a/templates/dialogs/dice-roll/rollSelection.hbs +++ b/templates/dialogs/dice-roll/rollSelection.hbs @@ -118,7 +118,7 @@ {{#if name}}
- {{name}} +{{value}} + {{name}} {{numberFormat value sign=true}}
{{/if}} {{/each}} diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index 24e68e02..b2757b55 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -145,7 +145,7 @@ {{#each document.system.experiences as |experience id|}}
- +{{experience.value}} + {{numberFormat experience.value sign=true}} {{experience.name}}
From c7431d16a75dfab7a55dee592ecbdafc59dc7e45 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 9 Feb 2026 01:02:59 +0100 Subject: [PATCH 10/10] Improved the Reaction toggle in dice rolls (#1643) --- .../less/dialog/dice-roll/roll-selection.less | 27 ++++++++++++++++++- templates/dialogs/dice-roll/header.hbs | 19 +++++-------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/styles/less/dialog/dice-roll/roll-selection.less b/styles/less/dialog/dice-roll/roll-selection.less index 0f082460..7fdae77a 100644 --- a/styles/less/dialog/dice-roll/roll-selection.less +++ b/styles/less/dialog/dice-roll/roll-selection.less @@ -17,7 +17,9 @@ .dialog-header-inner { display: flex; - justify-content: center; + flex-direction: column; + align-items: center; + gap: 2px; } h1 { @@ -45,6 +47,29 @@ } } + .reaction-chip { + display: flex; + align-items: center; + border-radius: 5px; + width: fit-content; + gap: 5px; + cursor: pointer; + padding: 5px; + background: light-dark(@dark-blue-10, @golden-10); + color: light-dark(@dark-blue, @golden); + + .label { + font-style: normal; + font-weight: 400; + font-size: var(--font-size-14); + line-height: 17px; + } + + &.selected { + background: light-dark(@dark-blue-40, @golden-40); + } + } + .tag-team-controller { display: flex; align-items: center; diff --git a/templates/dialogs/dice-roll/header.hbs b/templates/dialogs/dice-roll/header.hbs index 21967655..0cb58a01 100644 --- a/templates/dialogs/dice-roll/header.hbs +++ b/templates/dialogs/dice-roll/header.hbs @@ -1,17 +1,12 @@
-

- {{#if reactionOverride}} - {{localize "DAGGERHEART.CONFIG.FeatureForm.reaction"}} - {{else}} - {{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}} - {{/if}} - {{#if showReaction}} - - {{/if}} -

+

{{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}}

+ {{#if showReaction}} +
+ + {{localize "DAGGERHEART.GENERAL.reactionRoll"}} +
+ {{/if}}
{{#if (and @root.hasRoll @root.activeTagTeamRoll)}}