From 582a15be77971e28e82a33414b35e3add646c32a Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 11:23:57 +0200 Subject: [PATCH 01/27] Fixed scene-navigation styling for levels --- .../ui/sceneNavigation/scene-navigation.hbs | 61 +++++-------------- 1 file changed, 15 insertions(+), 46 deletions(-) diff --git a/templates/ui/sceneNavigation/scene-navigation.hbs b/templates/ui/sceneNavigation/scene-navigation.hbs index 68df761e..5bdbbdad 100644 --- a/templates/ui/sceneNavigation/scene-navigation.hbs +++ b/templates/ui/sceneNavigation/scene-navigation.hbs @@ -11,19 +11,21 @@ {{> ".scene" }} {{/with}} - - {{#each scenes.levels}} -
  • - {{#with button}} - - {{/with}} -
    - {{ name }} -
    -
  • - {{/each}} -
    + {{#if scenes.levels}} + + {{#each scenes.levels}} +
  • + {{#with button}} + + {{/with}} +
    + {{ name }} +
    +
  • + {{/each}} +
    + {{/if}} {{#each scenes.active}} {{> ".scene" }} @@ -34,39 +36,6 @@ {{> ".scene" }} {{/each}} - {{!-- - {{#each scenes.active as |scene|}} -
  • -
      -
    • - {{scene.name}} - {{#if scene.users}} -
        - {{#each scene.users as |user|}} -
      • {{user.letter}}
      • - {{/each}} -
      - {{/if}} -
    • -
    - {{#if scene.hasEnvironments}} - - {{/if}} -
  • - {{/each}} -
    - - {{#each scenes.inactive as |scene|}} -
  • -
      -
    • - {{scene.name}} -
    • -
    -
  • - {{/each}} -
    --}} {{#*inline ".scene"}} From e8ac3012ad390f2e0a9c36bd3e8206db20cc40cc Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 11:24:17 +0200 Subject: [PATCH 02/27] Raised version --- system.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system.json b/system.json index b1fe74d8..ea71aaba 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.0.0", + "version": "2.0.1", "compatibility": { "minimum": "14.359", "verified": "14.359", From 0f1ac406df4a4e866ea089798d131ef73af827eb Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 12:22:31 +0200 Subject: [PATCH 03/27] Fixed adding a new damage instance to an action default to prof, which doesn't work for adversaries --- .../applications/sheets-configs/action-config.mjs | 1 - module/data/fields/action/damageField.mjs | 4 ++-- templates/actionTypes/effect.hbs | 15 --------------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/module/applications/sheets-configs/action-config.mjs b/module/applications/sheets-configs/action-config.mjs index e15b0391..e073cfa6 100644 --- a/module/applications/sheets-configs/action-config.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -21,7 +21,6 @@ export default class DHActionConfig extends DHActionBaseConfig { static async addEffect(_event) { if (!this.action.effects) return; - const effectData = this._addEffectData.bind(this)(); const data = this.action.toObject(); const created = await this.action.item.createEmbeddedDocuments('ActiveEffect', [ diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index d41d2d4a..5d40a470 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -232,7 +232,7 @@ export class DHActionDiceData extends foundry.abstract.DataModel { return { multiplier: new fields.StringField({ choices: CONFIG.DH.GENERAL.multiplierTypes, - initial: 'prof', + initial: 'flat', label: 'DAGGERHEART.ACTIONS.Config.damage.multiplier', nullable: false, required: true @@ -244,7 +244,7 @@ export class DHActionDiceData extends foundry.abstract.DataModel { }), dice: new fields.StringField({ choices: CONFIG.DH.GENERAL.diceTypes, - initial: 'd6', + initial: CONFIG.DH.GENERAL.diceTypes.d6, label: 'DAGGERHEART.GENERAL.Dice.single', nullable: false, required: true diff --git a/templates/actionTypes/effect.hbs b/templates/actionTypes/effect.hbs index dd6a7974..8c5e6e68 100644 --- a/templates/actionTypes/effect.hbs +++ b/templates/actionTypes/effect.hbs @@ -4,21 +4,6 @@
      - {{!-- {{#each source as | effect index |}} -
      - {{#with (@root.getEffectDetails effect._id) as | details |}} - -
      - {{name}} -
      - {{/with}} - - {{#if @root.source.save.trait}}{{formInput ../fields.onSave value=effect.onSave name=(concat "effects." index ".onSave") dataset=(object tooltip=(localize "DAGGERHEART.UI.Tooltip.appliedEvenIfSuccessful") tooltipDirection="UP")}}{{/if}} -
      - -
      -
      - {{/each}} --}} {{#each source as | effect index |}}
      From 56dc9afe8fe0c650e4a47098f93aaaea0378ac9d Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 13:37:38 +0200 Subject: [PATCH 04/27] Corrected some action labels and missing translations --- lang/en.json | 6 ++++-- templates/actionTypes/roll.hbs | 8 ++++---- templates/actionTypes/save.hbs | 6 +++--- templates/sheets-settings/adversary-settings/attack.hbs | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lang/en.json b/lang/en.json index 9bcf02b5..d19dfb58 100755 --- a/lang/en.json +++ b/lang/en.json @@ -113,7 +113,9 @@ }, "displayInChat": "Display in chat", "deleteTriggerTitle": "Delete Trigger", - "deleteTriggerContent": "Are you sure you want to delete the {trigger} trigger?" + "deleteTriggerContent": "Are you sure you want to delete the {trigger} trigger?", + "advantageState": "Advantage State", + "damageOnSave": "Damage on Save" }, "RollField": { "diceRolling": { @@ -125,7 +127,7 @@ } }, "Settings": { - "attackBonus": "Attack Bonus", + "attackModifier": "Attack Modifier", "attackName": "Attack Name", "criticalThreshold": "Critical Threshold", "includeBase": { "label": "Include Item Damage" }, diff --git a/templates/actionTypes/roll.hbs b/templates/actionTypes/roll.hbs index 3e25b9c8..2f257768 100644 --- a/templates/actionTypes/roll.hbs +++ b/templates/actionTypes/roll.hbs @@ -17,13 +17,13 @@
      {{#unless (eq source.type 'spellcast')}} {{#if @root.isNPC}} - {{formField fields.bonus label="Bonus" name="roll.bonus" value=source.bonus placeholder=@root.baseAttackBonus disabled=(not source.type)}} + {{formField fields.bonus label="DAGGERHEART.GENERAL.Modifier.single" name="roll.bonus" value=source.bonus placeholder=@root.baseAttackBonus disabled=(not source.type)}} {{else}} - {{formField fields.trait label="Trait" name="roll.trait" value=source.trait localize=true disabled=(not source.type)}} + {{formField fields.trait label="DAGGERHEART.GENERAL.Trait.single" name="roll.trait" value=source.trait localize=true disabled=(not source.type)}} {{/if}} {{/unless}} - {{formField fields.difficulty label="Difficulty" name="roll.difficulty" value=source.difficulty disabled=(not source.type)}} - {{formField fields.advState label= "Advantage State" name="roll.advState" value=source.advState localize=true disabled=(not source.type)}} + {{formField fields.difficulty label="DAGGERHEART.GENERAL.difficulty" name="roll.difficulty" value=source.difficulty disabled=(not source.type)}} + {{formField fields.advState label="DAGGERHEART.ACTIONS.Config.advantageState" name="roll.advState" value=source.advState localize=true disabled=(not source.type)}}
      {{/if}} \ No newline at end of file diff --git a/templates/actionTypes/save.hbs b/templates/actionTypes/save.hbs index 85536c87..fdadba54 100644 --- a/templates/actionTypes/save.hbs +++ b/templates/actionTypes/save.hbs @@ -2,8 +2,8 @@ {{localize "DAGGERHEART.GENERAL.Roll.reaction"}}

      {{localize "DAGGERHEART.ACTIONS.Settings.saveHint"}}

      - {{formField fields.trait label="Trait" name="save.trait" value=source.trait localize=true}} - {{formField fields.difficulty label="Difficulty" name="save.difficulty" value=source.difficulty disabled=(not source.trait) placeholder=@root.baseSaveDifficulty}} - {{formField fields.damageMod label="Damage on Save" name="save.damageMod" value=source.damageMod localize=true disabled=(not source.trait)}} + {{formField fields.trait label="DAGGERHEART.GENERAL.Trait.single" name="save.trait" value=source.trait localize=true}} + {{formField fields.difficulty label="DAGGERHEART.GENERAL.difficulty" name="save.difficulty" value=source.difficulty disabled=(not source.trait) placeholder=@root.baseSaveDifficulty}} + {{formField fields.damageMod label="DAGGERHEART.ACTIONS.Config.damageOnSave" name="save.damageMod" value=source.damageMod localize=true disabled=(not source.trait)}}
      \ No newline at end of file diff --git a/templates/sheets-settings/adversary-settings/attack.hbs b/templates/sheets-settings/adversary-settings/attack.hbs index c3ee21f6..f829338f 100644 --- a/templates/sheets-settings/adversary-settings/attack.hbs +++ b/templates/sheets-settings/adversary-settings/attack.hbs @@ -11,7 +11,7 @@
      {{localize "DAGGERHEART.GENERAL.attack"}}
      - {{formField systemFields.attack.fields.roll.fields.bonus value=document._source.system.attack.roll.bonus label="DAGGERHEART.ACTIONS.Settings.attackBonus" name="system.attack.roll.bonus" localize=true}} + {{formField systemFields.attack.fields.roll.fields.bonus value=document._source.system.attack.roll.bonus label="DAGGERHEART.ACTIONS.Settings.attackModifier" name="system.attack.roll.bonus" localize=true}} {{formField systemFields.attack.fields.range value=document._source.system.attack.range label="DAGGERHEART.GENERAL.range" name="system.attack.range" localize=true}} {{#if systemFields.attack.fields.target.fields}} {{ formField systemFields.attack.fields.target.fields.type value=document._source.system.attack.target.type label="DAGGERHEART.GENERAL.Target.single" name="system.attack.target.type" localize=true }} From 07479946867f42d5ed4c0513aaf05de23c2506aa Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 16:00:04 +0200 Subject: [PATCH 05/27] Improved TagTeamRoll initialization when done by a player --- module/applications/dialogs/tagTeamDialog.mjs | 49 ++++++++++++++++--- .../dialogs/tagTeamDialog/initialization.hbs | 11 +++-- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 2d363471..5236afb8 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -16,9 +16,11 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio ...member.toObject(), uuid: member.uuid, id: member.id, - selected: false + selected: false, + owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) })); - this.intiator = null; + + this.initiator = null; this.openForAllPlayers = true; this.tabGroups.application = Object.keys(party.system.tagTeam.members).length @@ -80,6 +82,18 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio for (const element of htmlElement.querySelectorAll('.roll-type-select')) element.addEventListener('change', this.updateRollType.bind(this)); + + htmlElement + .querySelector('.initiator-member-field') + ?.addEventListener('input', this.updateInitiatorMemberField.bind(this)); + + htmlElement + .querySelector('.initiator-cost-field') + ?.addEventListener('input', this.updateInitiatorCostField.bind(this)); + + htmlElement + .querySelector('.openforall-field') + ?.addEventListener('change', this.updateOpenForAllField.bind(this)); } _configureRenderParts(options) { @@ -135,9 +149,12 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const selectedMembers = partContext.memberSelection.filter(x => x.selected); partContext.allSelected = selectedMembers.length === 2; - partContext.canStartTagTeam = partContext.allSelected && this.initiator; + partContext.canStartTagTeam = + partContext.allSelected && this.initiator?.memberId && typeof this.initiator?.cost === 'number'; partContext.initiator = this.initiator; - partContext.initiatorOptions = selectedMembers.map(x => ({ value: x.id, label: x.name })); + partContext.initiatorOptions = selectedMembers + .filter(actor => actor.owned) + .map(x => ({ value: x.id, label: x.name })); partContext.initiatorDisabled = !selectedMembers.length; partContext.openForAllPlayers = this.openForAllPlayers; @@ -230,14 +247,15 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio } static async updateData(event, _, formData) { - const { initiator, openForAllPlayers, ...partyData } = foundry.utils.expandObject(formData.object); - this.initiator = initiator; - this.openForAllPlayers = openForAllPlayers !== undefined ? openForAllPlayers : this.openForAllPlayers; + const partyData = foundry.utils.expandObject(formData.object); this.updatePartyData(partyData, this.getUpdatingParts(event.target)); } async updatePartyData(update, updatingParts, options = { render: true }) { + if (!game.users.activeGM) + return ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.gmRequired')); + const gmUpdate = async update => { await this.party.update(update); this.render({ parts: updatingParts }); @@ -374,6 +392,23 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio ); } + updateInitiatorMemberField(event) { + if (!this.initiator) this.initiator = {}; + this.initiator.memberId = event.target.value; + this.render(); + } + + updateInitiatorCostField(event) { + if (!this.initiator) this.initiator = {}; + this.initiator.cost = event.target.value ? Number.parseInt(event.target.value) : null; + this.render(); + } + + updateOpenForAllField(event) { + this.openForAllPlayers = event.target.checked; + this.render(); + } + static async #removeRoll(_, button) { this.updatePartyData( { diff --git a/templates/dialogs/tagTeamDialog/initialization.hbs b/templates/dialogs/tagTeamDialog/initialization.hbs index 604d06c0..d25e8f6c 100644 --- a/templates/dialogs/tagTeamDialog/initialization.hbs +++ b/templates/dialogs/tagTeamDialog/initialization.hbs @@ -17,19 +17,24 @@
      - {{selectOptions initiatorOptions selected=initiator.memberId blank="" }}
      - {{formGroup tagTeamFields.initiator.fields.cost name="initiator.cost" value=initiator.cost disabled=initiatorDisabled localize=true }} +
      + +
      + +
      +
      {{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.openDialogForAll"}} - +
      \ No newline at end of file From f92f9f7132a1a8d3d8265647bb8191104d9c131b Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 17:10:13 +0200 Subject: [PATCH 06/27] Fixed so that tokens with vision range set to Infinity doesn't make summon actions error out --- module/documents/tokenManager.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/documents/tokenManager.mjs b/module/documents/tokenManager.mjs index be5467da..f766a677 100644 --- a/module/documents/tokenManager.mjs +++ b/module/documents/tokenManager.mjs @@ -95,7 +95,7 @@ export default class DhTokenManager { : this.#actor; const tokenData = await actor.getTokenDocument(); const result = await canvas.scene.createEmbeddedDocuments('Token', [ - { ...tokenData, x: this.#activePreview.document.x, y: this.#activePreview.document.y } + { ...tokenData.toObject(), x: this.#activePreview.document.x, y: this.#activePreview.document.y } ]); this.#activePreview = undefined; From 96eba49dc19524b6aee7386a4f73d2acf0b2a235 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 22:04:07 +0200 Subject: [PATCH 07/27] Fixed RainofBlades --- ...nCard_Rain_of_Blades_Ucenef6JpjQxwXni.json | 55 +------------------ 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/src/packs/domains/domainCard_Rain_of_Blades_Ucenef6JpjQxwXni.json b/src/packs/domains/domainCard_Rain_of_Blades_Ucenef6JpjQxwXni.json index 080dd67f..293490e3 100644 --- a/src/packs/domains/domainCard_Rain_of_Blades_Ucenef6JpjQxwXni.json +++ b/src/packs/domains/domainCard_Rain_of_Blades_Ucenef6JpjQxwXni.json @@ -44,7 +44,9 @@ "flatMultiplier": 1 }, "applyTo": "hitPoints", - "type": [], + "type": [ + "magical" + ], "base": false, "valueAlt": { "multiplier": "prof", @@ -87,57 +89,6 @@ "name": "Cast", "img": "icons/skills/melee/spear-tips-three-green.webp", "range": "veryClose" - }, - "CUKoYyDxQhNc0pLs": { - "type": "damage", - "_id": "CUKoYyDxQhNc0pLs", - "systemPath": "actions", - "description": "

      If a target you hit is Vulnerable, they take an extra 1d8 damage.

      ", - "chatDisplay": true, - "actionType": "action", - "cost": [], - "uses": { - "value": null, - "max": "", - "recovery": null - }, - "damage": { - "parts": { - "hitPoints": { - "value": { - "custom": { - "enabled": false - }, - "multiplier": "flat", - "flatMultiplier": 1, - "dice": "d8", - "bonus": null - }, - "applyTo": "hitPoints", - "type": [], - "base": false, - "resultBased": false, - "valueAlt": { - "multiplier": "prof", - "flatMultiplier": 1, - "dice": "d6", - "bonus": null, - "custom": { - "enabled": false - } - } - } - }, - "includeBase": false - }, - "target": { - "type": "any", - "amount": null - }, - "effects": [], - "name": "Damage Against Vulnerable", - "img": "icons/skills/melee/spear-tips-three-purple.webp", - "range": "" } }, "attribution": { From 36ffe8a23a7149b3451746a12d12a14a6db20c78 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 2 Apr 2026 22:18:18 +0200 Subject: [PATCH 08/27] Fixed labrys axe and unneccessary hr separations in enrichedItemDescriptions when prefix is empty --- .../weapon_Labrys_Axe_ijWppQzSOqVCb3rE.json | 18 +++++------------- templates/sheets/items/armor/description.hbs | 8 ++++---- templates/sheets/items/weapon/description.hbs | 8 ++++---- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/packs/items/weapons/weapon_Labrys_Axe_ijWppQzSOqVCb3rE.json b/src/packs/items/weapons/weapon_Labrys_Axe_ijWppQzSOqVCb3rE.json index 11994d3e..d5af9b14 100644 --- a/src/packs/items/weapons/weapon_Labrys_Axe_ijWppQzSOqVCb3rE.json +++ b/src/packs/items/weapons/weapon_Labrys_Axe_ijWppQzSOqVCb3rE.json @@ -5,22 +5,14 @@ "_id": "ijWppQzSOqVCb3rE", "img": "icons/weapons/axes/axe-battle-jagged.webp", "system": { - "description": "", + "description": "Protective: +1 to Armor Score", "actions": {}, "attached": [], "tier": 3, "equipped": false, "secondary": false, "burden": "twoHanded", - "weaponFeatures": [ - { - "value": "protective", - "effectIds": [ - "qTxADRsQnKiYfOiQ" - ], - "actionIds": [] - } - ], + "weaponFeatures": [], "attack": { "name": "Attack", "img": "icons/skills/melee/blood-slash-foam-red.webp", @@ -111,8 +103,8 @@ "effects": [ { "name": "Protective", - "description": "Add your character's Tier to your Armor Score", - "img": "icons/skills/melee/shield-block-gray-orange.webp", + "description": "+1 to Armor Score", + "img": "icons/magic/defensive/shield-barrier-deflect-teal.webp", "_id": "vnR4Zhnb0rOqwrFw", "type": "base", "system": { @@ -122,7 +114,7 @@ "phase": "initial", "priority": 20, "value": { - "max": "ITEM.@system.tier" + "max": "1" } } ] diff --git a/templates/sheets/items/armor/description.hbs b/templates/sheets/items/armor/description.hbs index af2698ef..74e4e234 100644 --- a/templates/sheets/items/armor/description.hbs +++ b/templates/sheets/items/armor/description.hbs @@ -1,9 +1,9 @@ -
      - {{#if features.length}} +{{#if features.length}} +
      {{#each features as | feature |}}
      {{localize feature.label}}: {{{localize feature.description}}}
      {{/each}}
      - {{/if}} -
      \ No newline at end of file +
      +{{/if}} \ No newline at end of file diff --git a/templates/sheets/items/weapon/description.hbs b/templates/sheets/items/weapon/description.hbs index af2698ef..74e4e234 100644 --- a/templates/sheets/items/weapon/description.hbs +++ b/templates/sheets/items/weapon/description.hbs @@ -1,9 +1,9 @@ -
      - {{#if features.length}} +{{#if features.length}} +
      {{#each features as | feature |}}
      {{localize feature.label}}: {{{localize feature.description}}}
      {{/each}}
      - {{/if}} -
      \ No newline at end of file +
      +{{/if}} \ No newline at end of file From 32656137670acd507754ed94ab5c78be98a9a800 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Thu, 2 Apr 2026 23:22:09 +0200 Subject: [PATCH 09/27] [Fix] Template Scene Awareness (#1769) * . * Using foundry values from schema for fallback gridSize and gridDistance * . --- module/canvas/placeables/measuredTemplate.mjs | 2 +- module/enrichers/TemplateEnricher.mjs | 27 ++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/module/canvas/placeables/measuredTemplate.mjs b/module/canvas/placeables/measuredTemplate.mjs index e1ea79f5..e439dadc 100644 --- a/module/canvas/placeables/measuredTemplate.mjs +++ b/module/canvas/placeables/measuredTemplate.mjs @@ -18,7 +18,7 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur static getRangeLabels(distanceValue, settings) { let result = { distance: distanceValue, units: '' }; - if (!settings.enabled) return result; + if (!settings.enabled || !canvas.scene) return result; const sceneRangeMeasurement = canvas.scene.flags.daggerheart?.rangeMeasurement; const { disable, custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting; diff --git a/module/enrichers/TemplateEnricher.mjs b/module/enrichers/TemplateEnricher.mjs index fd0e78eb..1a075518 100644 --- a/module/enrichers/TemplateEnricher.mjs +++ b/module/enrichers/TemplateEnricher.mjs @@ -63,14 +63,12 @@ export const renderMeasuredTemplate = async event => { const usedAngle = type === CONE ? (angle ?? CONFIG.MeasuredTemplate.defaults.angle) : type === INFRONT ? '180' : undefined; - let baseDistance = range; - if (Number.isNaN(Number(range))) { - baseDistance = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement[ - range - ]; - } + let baseDistance = getTemplateDistance(range); - const dimensionConstant = game.scenes.active.grid.size / game.scenes.active.grid.distance; + const { grid, distance } = CONFIG.Scene.documentClass.schema.fields.grid.fields; + const sceneGridSize = canvas.scene?.grid.size ?? grid.size.initial; + const sceneGridDistance = canvas.scene?.grid.distance ?? distance.getInitialValue(); + const dimensionConstant = sceneGridSize / sceneGridDistance; baseDistance *= dimensionConstant; @@ -115,3 +113,18 @@ export const renderMeasuredTemplate = async event => { { create: true } ); }; + +const getTemplateDistance = range => { + const rangeNumber = Number(range); + if (!Number.isNaN(rangeNumber)) return rangeNumber; + + const { custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting; + const sceneMeasurements = canvas.scene?.flags.daggerheart?.rangeMeasurement; + const globalMeasurements = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.variantRules + ).rangeMeasurement; + + const settings = sceneMeasurements?.setting === custom.id ? sceneMeasurements : globalMeasurements; + return settings[range]; +}; From 02cca277da4f8de7b23bd1565c38122f81b61817 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Fri, 3 Apr 2026 00:13:07 +0200 Subject: [PATCH 10/27] Updated github deploy manifest to be the latest on the main branch --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index aef0ddd1..80b84704 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,7 +35,7 @@ jobs: env: version: ${{steps.get_version.outputs.version-without-v}} url: https://github.com/${{github.repository}} - manifest: https://github.com/${{github.repository}}/releases/latest/download/system.json + manifest: https://raw.githubusercontent.com/{{github.repository}}/main/system.json download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip # Create a zip file with all files required by the module to add to the release From 622b38ac08e280c0a254adfcf4184940018fd553 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Fri, 3 Apr 2026 19:05:49 +0200 Subject: [PATCH 11/27] Fixed certain fields in actionConfig not getting translated --- templates/actionTypes/range-target.hbs | 6 +++--- templates/actionTypes/roll.hbs | 8 ++++---- templates/actionTypes/save.hbs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/templates/actionTypes/range-target.hbs b/templates/actionTypes/range-target.hbs index 143acdf8..114c76a6 100644 --- a/templates/actionTypes/range-target.hbs +++ b/templates/actionTypes/range-target.hbs @@ -1,12 +1,12 @@
      {{localize "DAGGERHEART.GENERAL.range"}}{{#if fields.target}} & {{localize "DAGGERHEART.GENERAL.Target.single"}}{{/if}} - {{formField fields.range value=source.range label="DAGGERHEART.GENERAL.range" name=(concat path "range") localize=true}} + {{formField fields.range value=source.range label=(localize "DAGGERHEART.GENERAL.range") name=(concat path "range") localize=true}} {{#if fields.target}}
      {{#if (and source.target.type (not (eq source.target.type 'self')))}} - {{ formField fields.target.amount value=source.target.amount label="DAGGERHEART.GENERAL.amount" name=(concat path "target.amount") localize=true}} + {{ formField fields.target.amount value=source.target.amount label=(localize "DAGGERHEART.GENERAL.amount") name=(concat path "target.amount") localize=true}} {{/if}} - {{ formField fields.target.type value=source.target.type label="DAGGERHEART.GENERAL.Target.single" name=(concat path "target.type") localize=true }} + {{ formField fields.target.type value=source.target.type label=(localize "DAGGERHEART.GENERAL.Target.single") name=(concat path "target.type") localize=true }}
      {{/if}}
      \ No newline at end of file diff --git a/templates/actionTypes/roll.hbs b/templates/actionTypes/roll.hbs index 2f257768..9784fc08 100644 --- a/templates/actionTypes/roll.hbs +++ b/templates/actionTypes/roll.hbs @@ -4,7 +4,7 @@ {{#if @root.hasBaseDamage}}{{formInput fields.useDefault name="roll.useDefault" value=source.useDefault dataset=(object tooltip="Use default Item values" tooltipDirection="UP")}}{{/if}} - {{formField fields.type label="Type" name="roll.type" value=source.type localize=true choices=@root.getRollTypeOptions}} + {{formField fields.type label="DAGGERHEART.GENERAL.type" name="roll.type" value=source.type localize=true choices=@root.getRollTypeOptions localize=true}} {{#if (eq source.type "diceSet")}}
      {{formField fields.diceRolling.fields.multiplier name="roll.diceRolling.multiplier" value=source.diceRolling.multiplier localize=true}} @@ -17,13 +17,13 @@
      {{#unless (eq source.type 'spellcast')}} {{#if @root.isNPC}} - {{formField fields.bonus label="DAGGERHEART.GENERAL.Modifier.single" name="roll.bonus" value=source.bonus placeholder=@root.baseAttackBonus disabled=(not source.type)}} + {{formField fields.bonus label="DAGGERHEART.GENERAL.Modifier.single" name="roll.bonus" value=source.bonus placeholder=@root.baseAttackBonus disabled=(not source.type) localize=true}} {{else}} {{formField fields.trait label="DAGGERHEART.GENERAL.Trait.single" name="roll.trait" value=source.trait localize=true disabled=(not source.type)}} {{/if}} {{/unless}} - {{formField fields.difficulty label="DAGGERHEART.GENERAL.difficulty" name="roll.difficulty" value=source.difficulty disabled=(not source.type)}} - {{formField fields.advState label="DAGGERHEART.ACTIONS.Config.advantageState" name="roll.advState" value=source.advState localize=true disabled=(not source.type)}} + {{formField fields.difficulty label="DAGGERHEART.GENERAL.difficulty" name="roll.difficulty" value=source.difficulty localize=true disabled=(not source.type)}} + {{formField fields.advState label="DAGGERHEART.ACTIONS.Config.advantageState" name="roll.advState" value=source.advState localize=true localize=true disabled=(not source.type)}}
      {{/if}}
      \ No newline at end of file diff --git a/templates/actionTypes/save.hbs b/templates/actionTypes/save.hbs index fdadba54..865991c7 100644 --- a/templates/actionTypes/save.hbs +++ b/templates/actionTypes/save.hbs @@ -3,7 +3,7 @@

      {{localize "DAGGERHEART.ACTIONS.Settings.saveHint"}}

      {{formField fields.trait label="DAGGERHEART.GENERAL.Trait.single" name="save.trait" value=source.trait localize=true}} - {{formField fields.difficulty label="DAGGERHEART.GENERAL.difficulty" name="save.difficulty" value=source.difficulty disabled=(not source.trait) placeholder=@root.baseSaveDifficulty}} - {{formField fields.damageMod label="DAGGERHEART.ACTIONS.Config.damageOnSave" name="save.damageMod" value=source.damageMod localize=true disabled=(not source.trait)}} + {{formField fields.difficulty label="DAGGERHEART.GENERAL.difficulty" name="save.difficulty" value=source.difficulty disabled=(not source.trait) placeholder=@root.baseSaveDifficulty localize=true}} + {{formField fields.damageMod label="DAGGERHEART.ACTIONS.Config.damageOnSave" name="save.damageMod" value=source.damageMod localize=true localize=true disabled=(not source.trait)}}
      \ No newline at end of file From 01619ef0672ef913f41af05f81b25d49d8131309 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Fri, 3 Apr 2026 19:15:20 +0200 Subject: [PATCH 12/27] Corrected github deploy manifest path --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 80b84704..e245c7fa 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,7 +35,7 @@ jobs: env: version: ${{steps.get_version.outputs.version-without-v}} url: https://github.com/${{github.repository}} - manifest: https://raw.githubusercontent.com/{{github.repository}}/main/system.json + manifest: https://raw.githubusercontent.com/${{github.repository}}/main/system.json download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip # Create a zip file with all files required by the module to add to the release From 3a117ef117f9de1d712076eae5235023c550477d Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Fri, 3 Apr 2026 23:32:30 +0200 Subject: [PATCH 13/27] Added evasion to party resources (#1771) --- .../less/sheets/actors/party/resources.less | 20 +++++++++++++++++++ system.json | 2 +- templates/sheets/actors/party/resources.hbs | 6 ++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/styles/less/sheets/actors/party/resources.less b/styles/less/sheets/actors/party/resources.less index 4db254bf..68628295 100644 --- a/styles/less/sheets/actors/party/resources.less +++ b/styles/less/sheets/actors/party/resources.less @@ -155,6 +155,26 @@ body.game:is(.performance-low, .noblur) { } } + .stat-section { + position: relative; + display: flex; + gap: 10px; + background-color: light-dark(transparent, @dark-blue); + color: light-dark(@dark-blue, @golden); + padding: 5px 10px; + border: 1px solid light-dark(@dark-blue, @golden); + border-radius: 3px; + align-items: center; + width: fit-content; + + h4 { + font-size: var(--font-size-12); + font-weight: bold; + text-transform: uppercase; + color: light-dark(@dark-blue, @golden); + } + } + .threshold-section { display: flex; align-self: center; diff --git a/system.json b/system.json index ea71aaba..78355364 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.0.1", + "version": "2.0.2", "compatibility": { "minimum": "14.359", "verified": "14.359", diff --git a/templates/sheets/actors/party/resources.hbs b/templates/sheets/actors/party/resources.hbs index bfbfb578..b53282ca 100644 --- a/templates/sheets/actors/party/resources.hbs +++ b/templates/sheets/actors/party/resources.hbs @@ -87,6 +87,12 @@
      {{/unless}} + {{#if (eq actor.type 'character')}} +
      +

      {{localize "DAGGERHEART.GENERAL.evasion"}}: {{actor.system.evasion}}

      +
      + {{/if}} + {{#unless (eq actor.type 'companion')}}

      {{localize "DAGGERHEART.GENERAL.DamageThresholds.minor"}}

      From f91c140d34eaf8da276e14f29d1456666edfed18 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 4 Apr 2026 11:48:41 +0200 Subject: [PATCH 14/27] Fixed so that multi term expressions get evaluated into a single number (#1772) --- module/data/activeEffect/changeTypes/armor.mjs | 3 ++- system.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/data/activeEffect/changeTypes/armor.mjs b/module/data/activeEffect/changeTypes/armor.mjs index f400d41b..713ef03d 100644 --- a/module/data/activeEffect/changeTypes/armor.mjs +++ b/module/data/activeEffect/changeTypes/armor.mjs @@ -44,7 +44,8 @@ export default class ArmorChange extends foundry.abstract.DataModel { label: 'Armor', defaultPriority: 20, handler: (actor, change, _options, _field, replacementData) => { - const parsedMax = itemAbleRollParse(change.value.max, actor, change.effect.parent); + const baseParsedMax = itemAbleRollParse(change.value.max, actor, change.effect.parent); + const parsedMax = new Roll(baseParsedMax).evaluateSync().total; game.system.api.documents.DhActiveEffect.applyChange( actor, { diff --git a/system.json b/system.json index 78355364..63dc33c2 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.0.2", + "version": "2.0.3", "compatibility": { "minimum": "14.359", "verified": "14.359", From 331f1ebf75a2221beaec7985f47dc642aeef8fa7 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sat, 4 Apr 2026 12:42:50 +0200 Subject: [PATCH 15/27] Fixed prose-mirror width --- styles/less/global/prose-mirror.less | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less index 506fb8b7..3523dc89 100644 --- a/styles/less/global/prose-mirror.less +++ b/styles/less/global/prose-mirror.less @@ -4,6 +4,7 @@ .application.daggerheart { prose-mirror { height: 100% !important; + width: 100%; .editor-menu { background-color: transparent; From 7057504a9eb3684b268617cf6e6ea73b699f659c Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 4 Apr 2026 13:01:24 +0200 Subject: [PATCH 16/27] Fixes (#1774) --- module/dice/dhRoll.mjs | 6 +++--- module/dice/die/_module.mjs | 4 ++++ module/dice/die/dualityDie.mjs | 14 +++++++++++--- module/dice/die/fearDie.mjs | 9 +++++++++ module/dice/die/hopeDie.mjs | 9 +++++++++ module/dice/dualityRoll.mjs | 20 ++++++++++---------- 6 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 module/dice/die/fearDie.mjs create mode 100644 module/dice/die/hopeDie.mjs diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index e4a34bd4..aa4dd75f 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -246,7 +246,7 @@ export default class DHRoll extends Roll { return (this._formula = this.constructor.getFormula(this.terms)); } - /** + /** * Calculate total modifiers of any rolls, including non-dh rolls. * This exists because damage rolls still may receive base roll classes */ @@ -256,7 +256,7 @@ export default class DHRoll extends Roll { if (!roll.terms[i].isDeterministic) continue; const termTotal = roll.terms[i].total; if (typeof termTotal === 'number') { - const multiplier = roll.terms[i - 1]?.operator === " - " ? -1 : 1; + const multiplier = roll.terms[i - 1]?.operator === ' - ' ? -1 : 1; modifierTotal += multiplier * termTotal; } } @@ -272,7 +272,7 @@ export default class DHRoll extends Roll { const changeKeys = this.getActionChangeKeys(); return ( this.options.effects?.reduce((acc, effect) => { - if (effect.system.changes.some(x => changeKeys.some(key => x.key.includes(key)))) { + if (effect.system.changes.some(x => changeKeys.some(key => x.key?.includes(key)))) { acc[effect.id] = { id: effect.id, name: effect.name, diff --git a/module/dice/die/_module.mjs b/module/dice/die/_module.mjs index ed892f6a..19ca951a 100644 --- a/module/dice/die/_module.mjs +++ b/module/dice/die/_module.mjs @@ -1,9 +1,13 @@ import DualityDie from './dualityDie.mjs'; +import HopeDie from './hopeDie.mjs'; +import FearDie from './fearDie.mjs'; import AdvantageDie from './advantageDie.mjs'; import DisadvantageDie from './disadvantageDie.mjs'; export const diceTypes = { DualityDie, + HopeDie, + FearDie, AdvantageDie, DisadvantageDie }; diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs index e9deb77f..83229425 100644 --- a/module/dice/die/dualityDie.mjs +++ b/module/dice/die/dualityDie.mjs @@ -43,9 +43,10 @@ export default class DualityDie extends foundry.dice.terms.Die { options: { appearance: {} } }; - const preset = await getDiceSoNicePreset(diceSoNice[key], faces); - diceSoNiceRoll.dice[0].options.appearance = preset.appearance; - diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile; + const diceAppearance = await this.getDiceSoNiceAppearance(options.liveRoll.roll); + diceSoNiceRoll.dice[0].options.appearance = diceAppearance.appearance; + diceSoNiceRoll.dice[0].options.modelFile = diceAppearance.modelFile; + diceSoNiceRoll.dice[0].results = diceSoNiceRoll.dice[0].results.filter(x => x.active); await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true); } else { @@ -59,4 +60,11 @@ export default class DualityDie extends foundry.dice.terms.Die { this.#updateResources(oldDuality, newDuality, options.liveRoll.actor); } } + + /** + * Overridden by extending classes HopeDie and FearDie + */ + async getDiceSoNiceAppearance() { + return {}; + } } diff --git a/module/dice/die/fearDie.mjs b/module/dice/die/fearDie.mjs new file mode 100644 index 00000000..2a09d432 --- /dev/null +++ b/module/dice/die/fearDie.mjs @@ -0,0 +1,9 @@ +import { getDiceSoNicePresets } from '../../config/generalConfig.mjs'; +import DualityDie from './dualityDie.mjs'; + +export default class FearDie extends DualityDie { + async getDiceSoNiceAppearance(roll) { + const { fear } = await getDiceSoNicePresets(roll, this.denomination, this.denomination); + return fear; + } +} diff --git a/module/dice/die/hopeDie.mjs b/module/dice/die/hopeDie.mjs new file mode 100644 index 00000000..af5a4425 --- /dev/null +++ b/module/dice/die/hopeDie.mjs @@ -0,0 +1,9 @@ +import { getDiceSoNicePresets } from '../../config/generalConfig.mjs'; +import DualityDie from './dualityDie.mjs'; + +export default class HopeDie extends DualityDie { + async getDiceSoNiceAppearance(roll) { + const { hope } = await getDiceSoNicePresets(roll, this.denomination, this.denomination); + return hope; + } +} diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index bc381f07..f9a06d37 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -24,7 +24,7 @@ export default class DualityRoll extends D20Roll { } get dHope() { - if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice(); + if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie)) this.createBaseDice(); return this.dice[0]; } @@ -34,7 +34,7 @@ export default class DualityRoll extends D20Roll { } get dFear() { - if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice(); + if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie)) this.createBaseDice(); return this.dice[1]; } @@ -68,8 +68,8 @@ export default class DualityRoll extends D20Roll { } get extraDice() { - const { DualityDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes; - return this.dice.filter(x => ![DualityDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die)); + const { HopeDie, FearDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes; + return this.dice.filter(x => ![HopeDie, FearDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die)); } setRallyChoices() { @@ -125,8 +125,8 @@ export default class DualityRoll extends D20Roll { /** @inheritDoc */ static fromData(data) { - data.terms[0].class = 'DualityDie'; - data.terms[2].class = 'DualityDie'; + data.terms[0].class = 'HopeDie'; + data.terms[2].class = 'FearDie'; if (data.options.roll.advantage?.type && data.terms[4]?.faces) { data.terms[4].class = data.options.roll.advantage.type === 1 ? 'AdvantageDie' : 'DisadvantageDie'; } @@ -135,18 +135,18 @@ export default class DualityRoll extends D20Roll { createBaseDice() { if ( - this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie && - this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie + this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie && + this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie ) { this.terms = [this.terms[0], this.terms[1], this.terms[2]]; return; } - this.terms[0] = new game.system.api.dice.diceTypes.DualityDie({ + this.terms[0] = new game.system.api.dice.diceTypes.HopeDie({ faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12 }); this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' }); - this.terms[2] = new game.system.api.dice.diceTypes.DualityDie({ + this.terms[2] = new game.system.api.dice.diceTypes.FearDie({ faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12 }); } From 70e21f34db33f884d315af0c2729d17723f2b44f Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sat, 4 Apr 2026 13:21:17 +0200 Subject: [PATCH 17/27] Corrected system.json --- system.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system.json b/system.json index 63dc33c2..28d849b3 100644 --- a/system.json +++ b/system.json @@ -297,7 +297,7 @@ "background": "systems/daggerheart/assets/logos/FoundrybornBackgroundLogo.png", "primaryTokenAttribute": "resources.hitPoints", "secondaryTokenAttribute": "resources.stress", - "url": "https://your/hosted/system/repo/", - "manifest": "https://your/hosted/system/repo/system.json", - "download": "https://your/packaged/download/archive.zip" + "url": "https://github.com/Foundryborne/daggerheart", + "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/main/system.json", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.0.3/system.zip" } From 0d7469801e7123588f736b43debdaa6e29eccd4e Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 4 Apr 2026 23:22:25 +0200 Subject: [PATCH 18/27] Updated the longrest repair armor to the new armor max path along with a migration (#1777) --- module/config/generalConfig.mjs | 2 +- module/systemRegistration/migrations.mjs | 13 +++++++++++++ system.json | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index f3484e43..24f1de92 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -484,7 +484,7 @@ export const defaultRestOptions = { value: { custom: { enabled: true, - formula: '@system.armorScore' + formula: '@system.armorScore.max' } } } diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index 458ee6ef..2851f7d4 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -1,3 +1,4 @@ +import { defaultRestOptions } from '../config/generalConfig.mjs'; import { RefreshType, socketEvent } from './socket.mjs'; export async function runMigrations() { @@ -341,6 +342,18 @@ export async function runMigrations() { lastMigrationVersion = '2.0.0'; } + + if (foundry.utils.isNewerVersion('2.0.4', lastMigrationVersion)) { + const downtimeMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew); + if (restMoves.longRest.moves.repairArmor) { + await downtimeMoves.updateSource({ + 'restMoves.longRest.moves.repairArmor': defaultRestOptions.longRest().repairArmor + }); + game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, downtimeMoves.toObject()); + } + + lastMigrationVersion = '2.0.4'; + } //#endregion await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion); diff --git a/system.json b/system.json index 28d849b3..e237f538 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.0.3", + "version": "2.0.4", "compatibility": { "minimum": "14.359", "verified": "14.359", From 90f433989810d7a9098023a9f279a06c43d32788 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 5 Apr 2026 10:23:02 +0200 Subject: [PATCH 19/27] Restoring current version number --- system.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system.json b/system.json index e237f538..28d849b3 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.0.4", + "version": "2.0.3", "compatibility": { "minimum": "14.359", "verified": "14.359", From dbcef140a263297c0783dcea4dd1489d33ad40d7 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 5 Apr 2026 11:09:00 +0200 Subject: [PATCH 20/27] Fixed armorEffects erroring on isSuppressed when not on an actor --- module/data/activeEffect/changeTypes/armor.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/data/activeEffect/changeTypes/armor.mjs b/module/data/activeEffect/changeTypes/armor.mjs index 713ef03d..2f3b9765 100644 --- a/module/data/activeEffect/changeTypes/armor.mjs +++ b/module/data/activeEffect/changeTypes/armor.mjs @@ -111,6 +111,8 @@ export default class ArmorChange extends foundry.abstract.DataModel { }; get isSuppressed() { + if (!this.parent.parent?.actor) return false; + switch (this.value.interaction) { case CONFIG.DH.GENERAL.activeEffectArmorInteraction.active.id: return !this.parent.parent?.actor.system.armor; From fdfd8c5a8d40cc1eb99b84fbfe8cf29dd6d89ab5 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 5 Apr 2026 11:28:41 +0200 Subject: [PATCH 21/27] Fixed selecting which roll to use in TagTeamRolls becoming impossible when using an Ability option --- module/applications/dialogs/tagTeamDialog.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 5236afb8..054331b5 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -366,8 +366,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio let rollIsSelected = false; for (const member of Object.values(members)) { const rollFinished = Boolean(member.rollData); - const damageFinished = - member.rollData?.options?.hasDamage !== undefined ? member.rollData.options.damage : true; + const damageFinished = member.rollData?.options?.hasDamage ? Boolean(member.rollData.options.damage) : true; rollsAreFinished = rollsAreFinished && rollFinished && damageFinished; rollIsSelected = rollIsSelected || member.selected; From 67d142df3d5ae908293fbae74da8d35cb96f5b4b Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 5 Apr 2026 17:27:02 +0200 Subject: [PATCH 22/27] Fixed migration --- module/systemRegistration/migrations.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index 2851f7d4..c2c53f4e 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -345,7 +345,7 @@ export async function runMigrations() { if (foundry.utils.isNewerVersion('2.0.4', lastMigrationVersion)) { const downtimeMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew); - if (restMoves.longRest.moves.repairArmor) { + if (downtimeMoves.restMoves.longRest.moves.repairArmor) { await downtimeMoves.updateSource({ 'restMoves.longRest.moves.repairArmor': defaultRestOptions.longRest().repairArmor }); From 4c2d31b2f4dd7b76e4c6374bd6af3cf40a1cf56a Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 5 Apr 2026 19:28:27 +0200 Subject: [PATCH 23/27] Fixed so that expanded damage info without any dice will show the correct value (#1780) --- templates/ui/chat/parts/damage-part.hbs | 41 +++++++++++++------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/templates/ui/chat/parts/damage-part.hbs b/templates/ui/chat/parts/damage-part.hbs index 02519a86..45b09b72 100644 --- a/templates/ui/chat/parts/damage-part.hbs +++ b/templates/ui/chat/parts/damage-part.hbs @@ -33,31 +33,32 @@
      {{total}}
      {{/if}}
      - {{#each dice}} - {{#each results}} - {{#unless discarded}} -
      -
      - {{#if hasRerolls}}{{/if}} - {{result}} + {{#if dice.length}} + {{#each dice}} + {{#each results}} + {{#unless discarded}} +
      +
      + {{#if hasRerolls}}{{/if}} + {{result}} +
      -
      - {{/unless}} + {{/unless}} + {{/each}} {{/each}} - {{/each}} - {{#if modifierTotal}} -
      -
      {{modifierTotal}}
      -
      - {{/if}} - {{#unless dice.length}} + {{#if modifierTotal}} +
      +
      {{modifierTotal}}
      +
      + {{/if}} + {{else}}
      {{total}}
      - {{/unless}} + {{/if}}
      {{/each}} From fad830580ccdde5347aaeb7364449f1ff6a29494 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 6 Apr 2026 00:18:43 +0200 Subject: [PATCH 24/27] Added checkboxes for muting the sounds of dice animations (#1781) --- lang/en.json | 1 + module/config/generalConfig.mjs | 4 ++-- module/data/settings/Appearance.mjs | 3 +++ .../appearance-settings/diceSoNice.less | 24 +++++++++++++++++++ .../appearance-settings/diceSoNice.hbs | 11 +++++++-- .../appearance-settings/diceSoNiceTab.hbs | 10 ++++++-- 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lang/en.json b/lang/en.json index d19dfb58..7b1e5744 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2857,6 +2857,7 @@ "system": "Dice Preset", "font": "Font", "critical": "Duality Critical Animation", + "muted": "Muted", "diceAppearance": "Dice Appearance", "animations": "Animations", "defaultAnimations": "Set Animations As Player Defaults", diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 24f1de92..918cb417 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -708,14 +708,14 @@ const getDiceSoNiceSFX = sfxOptions => { if (sfxOptions.critical && criticalAnimationData.class) { return { specialEffect: criticalAnimationData.class, - options: {} + options: { ...criticalAnimationData.options } }; } if (sfxOptions.higher && sfxOptions.data.higher) { return { specialEffect: sfxOptions.data.higher.class, - options: {} + options: { ...sfxOptions.data.higher.options } }; } diff --git a/module/data/settings/Appearance.mjs b/module/data/settings/Appearance.mjs index 9da3afac..4db27be0 100644 --- a/module/data/settings/Appearance.mjs +++ b/module/data/settings/Appearance.mjs @@ -8,6 +8,9 @@ export default class DhAppearance extends foundry.abstract.DataModel { initial: null, blank: true, choices: CONFIG.DH.GENERAL.diceSoNiceSFXClasses + }), + options: new foundry.data.fields.SchemaField({ + muteSound: new foundry.data.fields.BooleanField() }) }); diff --git a/styles/less/ui/settings/appearance-settings/diceSoNice.less b/styles/less/ui/settings/appearance-settings/diceSoNice.less index 079bebc5..a4846596 100644 --- a/styles/less/ui/settings/appearance-settings/diceSoNice.less +++ b/styles/less/ui/settings/appearance-settings/diceSoNice.less @@ -68,5 +68,29 @@ text-align: center; white-space: nowrap; } + + color-picker { + gap: 4px; + background: inherit; + } + } + + .animation-container { + display: flex; + align-items: center; + justify-content: space-between; + + .animation-inner-container { + display: flex; + align-items: center; + justify-content: right; + gap: 8px; + + .animation-control { + display: flex; + align-items: center; + gap: 2px; + } + } } } diff --git a/templates/settings/appearance-settings/diceSoNice.hbs b/templates/settings/appearance-settings/diceSoNice.hbs index afe7dd5a..6cd4e52e 100644 --- a/templates/settings/appearance-settings/diceSoNice.hbs +++ b/templates/settings/appearance-settings/diceSoNice.hbs @@ -9,9 +9,16 @@ {{/if}}
      +
      - {{formInput fields.diceSoNice.fields.sfx.fields.critical.fields.class value=setting.diceSoNice.sfx.critical.class blank="" localize=true}} -
      +
      + {{formInput fields.diceSoNice.fields.sfx.fields.critical.fields.class value=setting.diceSoNice.sfx.critical.class blank="" localize=true}} +
      + +
      + {{formInput fields.diceSoNice.fields.sfx.fields.critical.fields.options.fields.muteSound value=setting.diceSoNice.sfx.critical.options.muteSound localize=true}} +
      +
      diff --git a/templates/settings/appearance-settings/diceSoNiceTab.hbs b/templates/settings/appearance-settings/diceSoNiceTab.hbs index a15b63ec..89b587af 100644 --- a/templates/settings/appearance-settings/diceSoNiceTab.hbs +++ b/templates/settings/appearance-settings/diceSoNiceTab.hbs @@ -42,9 +42,15 @@ {{#if animations}}

      {{localize "DAGGERHEART.SETTINGS.Menu.appearance.diceSoNice.animations"}}

      -
      +
      - {{formInput fields.sfx.fields.higher.fields.class value=values.sfx.higher.class blank="" localize=true}} +
      + {{formInput fields.sfx.fields.higher.fields.class value=values.sfx.higher.class blank="" localize=true}} +
      + + {{formInput fields.sfx.fields.higher.fields.options.fields.muteSound value=values.sfx.higher.options.muteSound localize=true}} +
      +
      {{/if}} From 087e69694cc9cfe0ba0ad63df34bc725be7b7cb7 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 6 Apr 2026 11:40:57 +0200 Subject: [PATCH 25/27] Changed the character setup button to be more obvious (#1782) --- lang/en.json | 2 +- templates/sheets/actors/character/header.hbs | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lang/en.json b/lang/en.json index 7b1e5744..55ffc5ad 100755 --- a/lang/en.json +++ b/lang/en.json @@ -353,7 +353,7 @@ "selectSecondaryWeapon": "Select Secondary Weapon", "selectSubclass": "Select Subclass", "setupSkipTitle": "Skipping Character Setup", - "setupSkipContent": "You are skipping the Character Setup by adding this manually. The character setup is the blinking arrows in the top-right. Are you sure you want to continue?", + "setupSkipContent": "You are skipping the Character Setup by adding this manually. The character setup is the blinking button in the top-right. Are you sure you want to continue?", "startingItems": "Starting Items", "story": "Story", "storyExplanation": "Select which background and connection prompts you want to copy into your character's background.", diff --git a/templates/sheets/actors/character/header.hbs b/templates/sheets/actors/character/header.hbs index 06f464fa..4ceba54d 100644 --- a/templates/sheets/actors/character/header.hbs +++ b/templates/sheets/actors/character/header.hbs @@ -4,17 +4,27 @@

      {{source.name}}

      - {{#if (or document.system.needsCharacterSetup document.system.levelData.canLevelUp)}} + {{#if document.system.needsCharacterSetup}} + {{else if document.system.levelData.canLevelUp}} + {{/if}} - {{localize 'DAGGERHEART.GENERAL.level'}} - + {{#unless document.system.needsCharacterSetup}} + {{localize 'DAGGERHEART.GENERAL.level'}} + + {{/unless}}

      From b505e15eb2cfbd62427d3ad387e01d48493c10c3 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Thu, 9 Apr 2026 15:36:48 -0400 Subject: [PATCH 26/27] Fix editing of bar attributes in v14 (#1786) --- module/data/fields/actorField.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/data/fields/actorField.mjs b/module/data/fields/actorField.mjs index 7a57aa46..ae6f060c 100644 --- a/module/data/fields/actorField.mjs +++ b/module/data/fields/actorField.mjs @@ -89,13 +89,13 @@ class ResourcesField extends fields.TypedObjectField { */ _getField(path) { if (path.length === 0) return this; - const first = path.shift(); - if (first === this.element.name) return this.element_getField(path); + const name = path.pop(); + if (name === this.element.name) return this.element_getField(path); const resources = CONFIG.DH.RESOURCE[this.actorType].all; - if (first in resources) { + if (name in resources) { const field = this.element._getField(path); - field.label = resources[first].label; + field.label = resources[name].label; return field; } From ae480157d1649767ac2c967d8b023a74a44703dd Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Thu, 9 Apr 2026 22:07:51 +0200 Subject: [PATCH 27/27] [Feature] 1766 - Group Attack (#1770) * Implemented group attack logic * Updated all minions in the SRD to use the group attack functionality * . * Renamed groupAttack.nr to groupAttack.numAttackers * Moved the flag vs global setting logic to documents/scene * . --- lang/en.json | 4 +- module/applications/dialogs/damageDialog.mjs | 34 ++++++- module/config/generalConfig.mjs | 8 ++ module/data/action/baseAction.mjs | 20 +++++ module/data/chat-message/actorRoll.mjs | 1 + module/data/fields/action/damageField.mjs | 23 ++++- module/dice/damageRoll.mjs | 12 ++- module/documents/scene.mjs | 10 +++ module/enrichers/TemplateEnricher.mjs | 11 +-- ..._Apprentice_Assassin_vNIbYQ4YSzNf0WPE.json | 84 +++++++++++++++--- .../adversary_Conscript_99TqczuQipBmaB8i.json | 84 +++++++++++++++--- ...ersary_Cult_Initiate_zx99sOGTXicP4SSD.json | 86 +++++++++++++++--- ...sary_Elemental_Spark_P7h54ZePFPHpYwvB.json | 86 +++++++++++++++--- ...y_Fallen_Shock_Troop_OsLG2BjaEdTZUJU9.json | 86 +++++++++++++++--- .../adversary_Giant_Rat_4PfLnaCrOcMdb4dK.json | 44 ++++++++-- ...ersary_Giant_Recruit_5s8wSvpyC5rxY5aD.json | 88 +++++++++++++++---- ...ary_Hallowed_Soldier_VENwg7xEFcYObjmT.json | 86 +++++++++++++++--- ..._Jagged_Knife_Lackey_C0OMQqV7pN6t7ouR.json | 82 ++++++++++++++--- ...versary_Minor_Treant_G62k4oSkhkoXEs2D.json | 86 +++++++++++++++--- ..._Outer_Realms_Thrall_moJhHgKqTKPS2WYS.json | 84 +++++++++++++++--- ...ersary_Rotted_Zombie_gP3fWTLzSFnpA8EJ.json | 86 +++++++++++++++--- .../adversary_Sellsword_bgreCaQ6ap2DVpCr.json | 84 +++++++++++++++--- ...sary_Skeleton_Dredge_6l1a3Fazq8BoKIcc.json | 86 +++++++++++++++--- ...rsary_Tangle_Bramble_XcAGOSmtCFLT1unN.json | 84 +++++++++++++++--- ...rsary_Treant_Sapling_o63nS0k3wHu6EgKP.json | 86 +++++++++++++++--- .../less/dialog/damage-selection/sheet.less | 22 ++++- styles/less/global/elements.less | 8 ++ templates/actionTypes/damage.hbs | 7 +- .../dialogs/dice-roll/damageSelection.hbs | 18 ++++ .../action-settings/effect.hbs | 2 +- .../adversary-settings/attack.hbs | 2 +- .../companion-settings/attack.hbs | 2 +- 32 files changed, 1286 insertions(+), 220 deletions(-) diff --git a/lang/en.json b/lang/en.json index 55ffc5ad..36532e4d 100755 --- a/lang/en.json +++ b/lang/en.json @@ -131,6 +131,7 @@ "attackName": "Attack Name", "criticalThreshold": "Critical Threshold", "includeBase": { "label": "Include Item Damage" }, + "groupAttack": { "label": "Group Attack" }, "multiplier": "Multiplier", "saveHint": "Set a default Trait to enable Reaction Roll. It can be changed later in Reaction Roll Dialog.", "resultBased": { @@ -3143,7 +3144,8 @@ "tokenActorsMissing": "[{names}] missing Actors", "domainTouchRequirement": "This domain card requires {nr} {domain} cards in the loadout to be used", "knowTheTide": "Know The Tide gained a token", - "lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}" + "lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}", + "noTokenTargeted": "No token is targeted" }, "Progress": { "migrationLabel": "Performing system migration. Please wait and do not close Foundry." diff --git a/module/applications/dialogs/damageDialog.mjs b/module/applications/dialogs/damageDialog.mjs index 97f1c538..46d3d41f 100644 --- a/module/applications/dialogs/damageDialog.mjs +++ b/module/applications/dialogs/damageDialog.mjs @@ -22,6 +22,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application }, actions: { toggleSelectedEffect: this.toggleSelectedEffect, + updateGroupAttack: this.updateGroupAttack, toggleCritical: this.toggleCritical, submitRoll: this.submitRoll }, @@ -64,15 +65,40 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application context.hasSelectedEffects = Boolean(Object.keys(this.selectedEffects).length); context.selectedEffects = this.selectedEffects; + context.damageOptions = this.config.damageOptions; + context.rangeOptions = CONFIG.DH.GENERAL.groupAttackRange; + return context; } static updateRollConfiguration(_event, _, formData) { - const { ...rest } = foundry.utils.expandObject(formData.object); - foundry.utils.mergeObject(this.config.roll, rest.roll); - foundry.utils.mergeObject(this.config.modifiers, rest.modifiers); - this.config.selectedMessageMode = rest.selectedMessageMode; + const data = foundry.utils.expandObject(formData.object); + foundry.utils.mergeObject(this.config.roll, data.roll); + foundry.utils.mergeObject(this.config.modifiers, data.modifiers); + this.config.selectedMessageMode = data.selectedMessageMode; + if (data.damageOptions) { + const numAttackers = data.damageOptions.groupAttack?.numAttackers; + if (typeof numAttackers !== 'number' || numAttackers % 1 !== 0) { + data.damageOptions.groupAttack.numAttackers = null; + } + + foundry.utils.mergeObject(this.config.damageOptions, data.damageOptions); + } + + this.render(); + } + + static updateGroupAttack() { + const targets = Array.from(game.user.targets); + if (targets.length === 0) + return ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noTokenTargeted')); + + const actorId = this.roll.data.parent.id; + const range = this.config.damageOptions.groupAttack.range; + const groupAttackTokens = game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(actorId, range); + + this.config.damageOptions.groupAttack.numAttackers = groupAttackTokens.length; this.render(); } diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 918cb417..4a3d672d 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -70,6 +70,14 @@ export const range = { } }; +export const groupAttackRange = { + melee: range.melee, + veryClose: range.veryClose, + close: range.close, + far: range.far, + veryFar: range.veryFar +}; + /* circle|cone|rect|ray used to be CONST.MEASURED_TEMPLATE_TYPES. Hardcoded for now */ export const templateTypes = { CIRCLE: 'circle', diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index 1f75d382..0992350b 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -280,6 +280,26 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel } }; + if (this.damage) { + config.isDirect = this.damage.direct; + + const groupAttackTokens = this.damage.groupAttack + ? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens( + this.actor.id, + this.damage.groupAttack + ) + : null; + + config.damageOptions = { + groupAttack: this.damage.groupAttack + ? { + numAttackers: Math.max(groupAttackTokens.length, 1), + range: this.damage.groupAttack + } + : null + }; + } + DHBaseAction.applyKeybindings(config); return config; } diff --git a/module/data/chat-message/actorRoll.mjs b/module/data/chat-message/actorRoll.mjs index 89f34949..eaa1cdc2 100644 --- a/module/data/chat-message/actorRoll.mjs +++ b/module/data/chat-message/actorRoll.mjs @@ -48,6 +48,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { action: new fields.StringField() }), damage: new fields.ObjectField(), + damageOptions: new fields.ObjectField(), costs: new fields.ArrayField(new fields.ObjectField()), successConsumed: new fields.BooleanField({ initial: false }) }; diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 5d40a470..7839bf5a 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -18,7 +18,12 @@ export default class DamageField extends fields.SchemaField { initial: false, label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label' }), - direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }) + direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }), + groupAttack: new fields.StringField({ + choices: CONFIG.DH.GENERAL.groupAttackRange, + blank: true, + label: 'DAGGERHEART.ACTIONS.Settings.groupAttack.label' + }) }; super(damageFields, options, context); } @@ -224,6 +229,22 @@ export default class DamageField extends fields.SchemaField { game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).roll.damageApply.players) ); } + + static getGroupAttackTokens(actorId, range) { + if (!canvas.scene) return []; + + const targets = Array.from(game.user.targets); + const rangeSettings = canvas.scene?.rangeSettings; + if (!rangeSettings) return []; + + const maxDistance = rangeSettings[range]; + return canvas.scene.tokens.filter(x => { + if (x.actor?.id !== actorId) return false; + if (targets.every(target => x.object.distanceTo(target) > maxDistance)) return false; + + return true; + }); + } } export class DHActionDiceData extends foundry.abstract.DataModel { diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 1d680a1b..98fd8401 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -144,6 +144,7 @@ export default class DamageRoll extends DHRoll { constructFormula(config) { this.options.isCritical = config.isCritical; for (const [index, part] of this.options.roll.entries()) { + const isHitpointPart = part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id; part.roll = new Roll(Roll.replaceFormulaData(part.formula, config.data)); part.roll.terms = Roll.parse(part.roll.formula, config.data); if (part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) { @@ -169,7 +170,16 @@ export default class DamageRoll extends DHRoll { ); } - if (config.isCritical && part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) { + if (config.damageOptions.groupAttack?.numAttackers > 1 && isHitpointPart) { + const damageTypes = [foundry.dice.terms.Die, foundry.dice.terms.NumericTerm]; + for (const term of part.roll.terms) { + if (damageTypes.some(type => term instanceof type)) { + term.number *= config.damageOptions.groupAttack.numAttackers; + } + } + } + + if (config.isCritical && isHitpointPart) { const total = part.roll.dice.reduce((acc, term) => acc + term._faces * term._number, 0); if (total > 0) { part.roll.terms.push(...this.formatModifier(total)); diff --git a/module/documents/scene.mjs b/module/documents/scene.mjs index 1c2faa34..59b8091f 100644 --- a/module/documents/scene.mjs +++ b/module/documents/scene.mjs @@ -1,6 +1,16 @@ import DHToken from './token.mjs'; export default class DhScene extends Scene { + get rangeSettings() { + const { custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting; + const sceneMeasurements = this.flags.daggerheart?.rangeMeasurement; + const globalMeasurements = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.variantRules + ).rangeMeasurement; + return sceneMeasurements?.setting === custom.id ? sceneMeasurements : globalMeasurements; + } + /** A map of `TokenDocument` IDs embedded in this scene long with new dimensions from actor size-category changes */ #sizeSyncBatch = new Map(); diff --git a/module/enrichers/TemplateEnricher.mjs b/module/enrichers/TemplateEnricher.mjs index 1a075518..cd0e7d9c 100644 --- a/module/enrichers/TemplateEnricher.mjs +++ b/module/enrichers/TemplateEnricher.mjs @@ -118,13 +118,6 @@ const getTemplateDistance = range => { const rangeNumber = Number(range); if (!Number.isNaN(rangeNumber)) return rangeNumber; - const { custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting; - const sceneMeasurements = canvas.scene?.flags.daggerheart?.rangeMeasurement; - const globalMeasurements = game.settings.get( - CONFIG.DH.id, - CONFIG.DH.SETTINGS.gameSettings.variantRules - ).rangeMeasurement; - - const settings = sceneMeasurements?.setting === custom.id ? sceneMeasurements : globalMeasurements; - return settings[range]; + const settings = canvas.scene?.rangeSettings; + return settings ? settings[range] : 0; }; diff --git a/src/packs/adversaries/adversary_Apprentice_Assassin_vNIbYQ4YSzNf0WPE.json b/src/packs/adversaries/adversary_Apprentice_Assassin_vNIbYQ4YSzNf0WPE.json index 4c63297d..12ec35ae 100644 --- a/src/packs/adversaries/adversary_Apprentice_Assassin_vNIbYQ4YSzNf0WPE.json +++ b/src/packs/adversaries/adversary_Apprentice_Assassin_vNIbYQ4YSzNf0WPE.json @@ -131,12 +131,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -187,7 +184,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -213,7 +210,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -249,33 +247,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "vgguNWz8vG8aoLXR": { - "type": "effect", - "_id": "vgguNWz8vG8aoLXR", + "SrNyZgPvCXMpbCLG": { + "type": "attack", + "_id": "SrNyZgPvCXMpbCLG", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "4" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/magic/unholy/orb-hands-pink.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json b/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json index 5cbc1f82..38e7ceab 100644 --- a/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json +++ b/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -242,33 +240,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "cbAvPSIhwBMBTI3D": { - "type": "effect", - "_id": "cbAvPSIhwBMBTI3D", + "FCeTuf71gCzRiO5N": { + "type": "attack", + "_id": "FCeTuf71gCzRiO5N", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "6" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json b/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json index 4f04a85a..db26605d 100644 --- a/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json +++ b/src/packs/adversaries/adversary_Cult_Initiate_zx99sOGTXicP4SSD.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -242,33 +240,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all Cult @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "EH1preaTWBD4rOvx": { - "type": "effect", - "_id": "EH1preaTWBD4rOvx", + "4M2MvVzEgIQEQHBS": { + "type": "attack", + "_id": "4M2MvVzEgIQEQHBS", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "5" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": null, + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Elemental_Spark_P7h54ZePFPHpYwvB.json b/src/packs/adversaries/adversary_Elemental_Spark_P7h54ZePFPHpYwvB.json index 2c2633ea..5b8fa7b2 100644 --- a/src/packs/adversaries/adversary_Elemental_Spark_P7h54ZePFPHpYwvB.json +++ b/src/packs/adversaries/adversary_Elemental_Spark_P7h54ZePFPHpYwvB.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -242,33 +240,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "vXHZVb0Y7Hqu3uso": { - "type": "effect", - "_id": "vXHZVb0Y7Hqu3uso", + "S3dYxRclyhYINRi8": { + "type": "attack", + "_id": "S3dYxRclyhYINRi8", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "5" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/magic/unholy/orb-hands-pink.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Fallen_Shock_Troop_OsLG2BjaEdTZUJU9.json b/src/packs/adversaries/adversary_Fallen_Shock_Troop_OsLG2BjaEdTZUJU9.json index 8c0d7b95..484e161a 100644 --- a/src/packs/adversaries/adversary_Fallen_Shock_Troop_OsLG2BjaEdTZUJU9.json +++ b/src/packs/adversaries/adversary_Fallen_Shock_Troop_OsLG2BjaEdTZUJU9.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -320,33 +318,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "QHNRSEQmqOcaoXq4": { - "type": "effect", - "_id": "QHNRSEQmqOcaoXq4", + "G0DVft7h55pBnwJA": { + "type": "attack", + "_id": "G0DVft7h55pBnwJA", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "12" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/magic/unholy/orb-hands-pink.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Giant_Rat_4PfLnaCrOcMdb4dK.json b/src/packs/adversaries/adversary_Giant_Rat_4PfLnaCrOcMdb4dK.json index 822ee035..746806d9 100644 --- a/src/packs/adversaries/adversary_Giant_Rat_4PfLnaCrOcMdb4dK.json +++ b/src/packs/adversaries/adversary_Giant_Rat_4PfLnaCrOcMdb4dK.json @@ -131,12 +131,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -187,7 +184,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -213,7 +210,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -272,8 +270,38 @@ "recovery": null }, "damage": { - "parts": {}, - "includeBase": false + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "1" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "groupAttack": "close" }, "target": { "type": "any", @@ -300,7 +328,7 @@ "difficulty": null, "damageMod": "none" }, - "name": "Attack", + "name": "Spend Fear", "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } diff --git a/src/packs/adversaries/adversary_Giant_Recruit_5s8wSvpyC5rxY5aD.json b/src/packs/adversaries/adversary_Giant_Recruit_5s8wSvpyC5rxY5aD.json index 376ebace..6611496f 100644 --- a/src/packs/adversaries/adversary_Giant_Recruit_5s8wSvpyC5rxY5aD.json +++ b/src/packs/adversaries/adversary_Giant_Recruit_5s8wSvpyC5rxY5aD.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -242,35 +240,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "DjbPQowW1OdBD9Zn": { - "type": "effect", - "_id": "DjbPQowW1OdBD9Zn", + "wez1xgy9vScux9wi": { + "type": "attack", + "_id": "wez1xgy9vScux9wi", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { + "consumeOnSuccess": false, "scalable": false, "key": "fear", "value": 1, - "keyIsID": false, - "step": null, - "consumeOnSuccess": false + "itemId": null, + "step": null } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "5" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Hallowed_Soldier_VENwg7xEFcYObjmT.json b/src/packs/adversaries/adversary_Hallowed_Soldier_VENwg7xEFcYObjmT.json index 6a131c86..3e1ab854 100644 --- a/src/packs/adversaries/adversary_Hallowed_Soldier_VENwg7xEFcYObjmT.json +++ b/src/packs/adversaries/adversary_Hallowed_Soldier_VENwg7xEFcYObjmT.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -297,33 +295,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "eo7J0v1B5zPHul1M": { - "type": "effect", - "_id": "eo7J0v1B5zPHul1M", + "irZGPKPpGLA6sP2y": { + "type": "attack", + "_id": "irZGPKPpGLA6sP2y", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "10" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Jagged_Knife_Lackey_C0OMQqV7pN6t7ouR.json b/src/packs/adversaries/adversary_Jagged_Knife_Lackey_C0OMQqV7pN6t7ouR.json index cfcdea8b..076318c6 100644 --- a/src/packs/adversaries/adversary_Jagged_Knife_Lackey_C0OMQqV7pN6t7ouR.json +++ b/src/packs/adversaries/adversary_Jagged_Knife_Lackey_C0OMQqV7pN6t7ouR.json @@ -131,12 +131,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -187,7 +184,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -213,7 +210,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -251,33 +249,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name] within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "aoQDb2m32NDxE6ZP": { - "type": "effect", - "_id": "aoQDb2m32NDxE6ZP", + "ferZO3BuiP9zU46m": { + "type": "attack", + "_id": "ferZO3BuiP9zU46m", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { + "consumeOnSuccess": false, "scalable": false, "key": "fear", "value": 1, + "itemId": null, "step": null } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "2" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Minor_Treant_G62k4oSkhkoXEs2D.json b/src/packs/adversaries/adversary_Minor_Treant_G62k4oSkhkoXEs2D.json index b2217e66..163556e9 100644 --- a/src/packs/adversaries/adversary_Minor_Treant_G62k4oSkhkoXEs2D.json +++ b/src/packs/adversaries/adversary_Minor_Treant_G62k4oSkhkoXEs2D.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -245,33 +243,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "xTMNAHcoErKuR6TZ": { - "type": "effect", - "_id": "xTMNAHcoErKuR6TZ", + "xFlhxnQWmVvDqQ55": { + "type": "attack", + "_id": "xFlhxnQWmVvDqQ55", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "4" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Outer_Realms_Thrall_moJhHgKqTKPS2WYS.json b/src/packs/adversaries/adversary_Outer_Realms_Thrall_moJhHgKqTKPS2WYS.json index 5a7a605a..0bb3a44c 100644 --- a/src/packs/adversaries/adversary_Outer_Realms_Thrall_moJhHgKqTKPS2WYS.json +++ b/src/packs/adversaries/adversary_Outer_Realms_Thrall_moJhHgKqTKPS2WYS.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -242,33 +240,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "tvQetauskZoHDR5y": { - "type": "effect", - "_id": "tvQetauskZoHDR5y", + "6VKv71tPUIGGIfkZ": { + "type": "attack", + "_id": "6VKv71tPUIGGIfkZ", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { + "consumeOnSuccess": false, "scalable": false, "key": "fear", "value": 1, + "itemId": null, "step": null } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "11" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Rotted_Zombie_gP3fWTLzSFnpA8EJ.json b/src/packs/adversaries/adversary_Rotted_Zombie_gP3fWTLzSFnpA8EJ.json index 6755d27f..f1c7f470 100644 --- a/src/packs/adversaries/adversary_Rotted_Zombie_gP3fWTLzSFnpA8EJ.json +++ b/src/packs/adversaries/adversary_Rotted_Zombie_gP3fWTLzSFnpA8EJ.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -245,33 +243,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "DJBNtd3hWjwsjPwq": { - "type": "effect", - "_id": "DJBNtd3hWjwsjPwq", + "8wRrAWHU0xHW4zuE": { + "type": "attack", + "_id": "8wRrAWHU0xHW4zuE", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "2" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Sellsword_bgreCaQ6ap2DVpCr.json b/src/packs/adversaries/adversary_Sellsword_bgreCaQ6ap2DVpCr.json index ed6d7775..46bed122 100644 --- a/src/packs/adversaries/adversary_Sellsword_bgreCaQ6ap2DVpCr.json +++ b/src/packs/adversaries/adversary_Sellsword_bgreCaQ6ap2DVpCr.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -245,33 +243,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "ghgFZskDiizJDjcn": { - "type": "effect", - "_id": "ghgFZskDiizJDjcn", + "K3pF2DBnR9zJ90W8": { + "type": "attack", + "_id": "K3pF2DBnR9zJ90W8", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { + "consumeOnSuccess": false, "scalable": false, "key": "fear", "value": 1, + "itemId": null, "step": null } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "3" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Skeleton_Dredge_6l1a3Fazq8BoKIcc.json b/src/packs/adversaries/adversary_Skeleton_Dredge_6l1a3Fazq8BoKIcc.json index e4cbab5e..1a82abb8 100644 --- a/src/packs/adversaries/adversary_Skeleton_Dredge_6l1a3Fazq8BoKIcc.json +++ b/src/packs/adversaries/adversary_Skeleton_Dredge_6l1a3Fazq8BoKIcc.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -245,33 +243,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "Sz55uB8xkoNytLwJ": { - "type": "effect", - "_id": "Sz55uB8xkoNytLwJ", + "6rdwJKwsSCO4R0Ty": { + "type": "attack", + "_id": "6rdwJKwsSCO4R0Ty", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "1" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Tangle_Bramble_XcAGOSmtCFLT1unN.json b/src/packs/adversaries/adversary_Tangle_Bramble_XcAGOSmtCFLT1unN.json index c36502de..d635b2ca 100644 --- a/src/packs/adversaries/adversary_Tangle_Bramble_XcAGOSmtCFLT1unN.json +++ b/src/packs/adversaries/adversary_Tangle_Bramble_XcAGOSmtCFLT1unN.json @@ -164,12 +164,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -220,7 +217,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -246,7 +243,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -284,33 +282,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "ZC5pKIb9N82vgMWu": { - "type": "effect", - "_id": "ZC5pKIb9N82vgMWu", + "V58Ry90tvIjvfDTZ": { + "type": "attack", + "_id": "V58Ry90tvIjvfDTZ", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { + "consumeOnSuccess": false, "scalable": false, "key": "fear", "value": 1, + "itemId": null, "step": null } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "2" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/creatures/abilities/tail-strike-bone-orange.webp", "range": "" } }, diff --git a/src/packs/adversaries/adversary_Treant_Sapling_o63nS0k3wHu6EgKP.json b/src/packs/adversaries/adversary_Treant_Sapling_o63nS0k3wHu6EgKP.json index c6c11d36..c03a1b52 100644 --- a/src/packs/adversaries/adversary_Treant_Sapling_o63nS0k3wHu6EgKP.json +++ b/src/packs/adversaries/adversary_Treant_Sapling_o63nS0k3wHu6EgKP.json @@ -125,12 +125,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -181,7 +178,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -207,7 +204,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -242,33 +240,95 @@ "description": "

      Spend a Fear to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.

      ", "resource": null, "actions": { - "euP8VA4wvfsCpwN1": { - "type": "effect", - "_id": "euP8VA4wvfsCpwN1", + "Itubbr63irPJcbXG": { + "type": "attack", + "_id": "Itubbr63irPJcbXG", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null + "recovery": null, + "consumeOnSuccess": false + }, + "damage": { + "parts": { + "hitPoints": { + "applyTo": "hitPoints", + "resultBased": false, + "value": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": true, + "formula": "8" + } + }, + "valueAlt": { + "multiplier": "flat", + "flatMultiplier": 1, + "dice": "d6", + "bonus": null, + "custom": { + "enabled": false, + "formula": "" + } + }, + "base": false, + "type": [ + "physical" + ] + } + }, + "includeBase": false, + "direct": false, + "groupAttack": "close" }, - "effects": [], "target": { - "type": "self", + "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Fear", - "img": "icons/magic/unholy/orb-hands-pink.webp", "range": "" } }, diff --git a/styles/less/dialog/damage-selection/sheet.less b/styles/less/dialog/damage-selection/sheet.less index 0f765748..9f8cfc8a 100644 --- a/styles/less/dialog/damage-selection/sheet.less +++ b/styles/less/dialog/damage-selection/sheet.less @@ -21,7 +21,7 @@ gap: 4px; .critical-chip { flex: 0; - + display: flex; align-items: center; border-radius: 5px; @@ -41,6 +41,26 @@ } } + .group-attack-container { + margin: 0; + + .group-attack-inner-container { + display: flex; + align-items: center; + gap: 16px; + + > * { + flex: 1; + } + + .group-attack-tools { + display: flex; + align-items: center; + gap: 4px; + } + } + } + .damage-section-controls { display: flex; align-items: center; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 793c8164..c5bca1da 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -419,11 +419,19 @@ width: fit-content; display: flex; align-items: center; + .form-fields { height: 32px; align-content: center; } } + + &.select { + width: fit-content; + display: flex; + align-items: center; + gap: 4px; + } } .scalable-input { diff --git a/templates/actionTypes/damage.hbs b/templates/actionTypes/damage.hbs index 9e7c2884..192c5be5 100644 --- a/templates/actionTypes/damage.hbs +++ b/templates/actionTypes/damage.hbs @@ -8,13 +8,16 @@ {{/if}} {{#unless (eq path 'system.attack.')}}{{/unless}} -
      +
      {{#if @root.hasBaseDamage}} {{formField @root.fields.damage.fields.includeBase value=@root.source.damage.includeBase name="damage.includeBase" classes="checkbox" localize=true }} {{/if}} {{#unless (eq @root.source.type 'healing')}} - {{formField directField value=source.direct name=(concat path "damage.direct") localize=true classes="checkbox"}} + {{formField baseFields.direct value=source.direct name=(concat path "damage.direct") localize=true classes="checkbox"}} {{/unless}} + {{#if (and @root.isNPC (not (eq path 'system.attack.')))}} + {{formField baseFields.groupAttack value=source.groupAttack name=(concat path "damage.groupAttack") localize=true classes="select"}} + {{/if}}
      {{!-- Handlebars uses Symbol.Iterator to produce index|key. This isn't compatible with our parts object, so we instead use applyTo, which is the same value --}} diff --git a/templates/dialogs/dice-roll/damageSelection.hbs b/templates/dialogs/dice-roll/damageSelection.hbs index b2d1a895..915061a0 100644 --- a/templates/dialogs/dice-roll/damageSelection.hbs +++ b/templates/dialogs/dice-roll/damageSelection.hbs @@ -42,6 +42,24 @@
      {{/each}} + + {{#if damageOptions.groupAttack}} +
      + {{localize "DAGGERHEART.ACTIONS.Settings.groupAttack.label"}} + +
      + + +
      + + +
      +
      +
      + {{/if}} + {{#unless (empty @root.modifiers)}}
      {{localize "DAGGERHEART.GENERAL.Modifier.plural"}} diff --git a/templates/sheets-settings/action-settings/effect.hbs b/templates/sheets-settings/action-settings/effect.hbs index 1bdd0304..567cb81c 100644 --- a/templates/sheets-settings/action-settings/effect.hbs +++ b/templates/sheets-settings/action-settings/effect.hbs @@ -5,7 +5,7 @@ > {{#if fields.roll}}{{> 'systems/daggerheart/templates/actionTypes/roll.hbs' fields=fields.roll.fields source=source.roll}}{{/if}} {{#if fields.save}}{{> 'systems/daggerheart/templates/actionTypes/save.hbs' fields=fields.save.fields source=source.save}}{{/if}} - {{#if fields.damage}}{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage directField=fields.damage.fields.direct }}{{/if}} + {{#if fields.damage}}{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage baseFields=fields.damage.fields }}{{/if}} {{#if fields.macro}}{{> 'systems/daggerheart/templates/actionTypes/macro.hbs' fields=fields.macro source=source.macro}}{{/if}} {{#if fields.effects}}{{> 'systems/daggerheart/templates/actionTypes/effect.hbs' fields=fields.effects.element.fields source=source.effects}}{{/if}} {{#if fields.beastform}}{{> 'systems/daggerheart/templates/actionTypes/beastform.hbs' fields=fields.beastform.fields source=source.beastform}}{{/if}} diff --git a/templates/sheets-settings/adversary-settings/attack.hbs b/templates/sheets-settings/adversary-settings/attack.hbs index f829338f..41960032 100644 --- a/templates/sheets-settings/adversary-settings/attack.hbs +++ b/templates/sheets-settings/adversary-settings/attack.hbs @@ -22,5 +22,5 @@
      {{formGroup systemFields.criticalThreshold value=document._source.system.criticalThreshold label="DAGGERHEART.ACTIONS.Settings.criticalThreshold" name="system.criticalThreshold" localize=true}} - {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." directField=systemFields.attack.fields.damage.fields.direct horde=(eq document._source.system.type 'horde')}} + {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." baseFields=systemFields.attack.fields.damage.fields horde=(eq document._source.system.type 'horde')}} \ No newline at end of file diff --git a/templates/sheets-settings/companion-settings/attack.hbs b/templates/sheets-settings/companion-settings/attack.hbs index f99f7d8c..41451ef0 100644 --- a/templates/sheets-settings/companion-settings/attack.hbs +++ b/templates/sheets-settings/companion-settings/attack.hbs @@ -18,5 +18,5 @@ {{/if}} {{/if}} - {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." directField=systemFields.attack.fields.damage.fields.direct}} + {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." baseFields=systemFields.attack.fields.damage.fields}} \ No newline at end of file