From 5f001a9f83ff5f89f2312401ccb1d11de9792741 Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sun, 28 Dec 2025 09:26:39 -0700 Subject: [PATCH 1/8] Adding scrollable to various tabs in the homebrew settings (#1483) --- templates/settings/homebrew-settings/domains.hbs | 2 +- templates/settings/homebrew-settings/downtime.hbs | 2 +- templates/settings/homebrew-settings/itemFeatures.hbs | 2 +- templates/settings/homebrew-settings/settings.hbs | 2 +- templates/settings/homebrew-settings/types.hbs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/settings/homebrew-settings/domains.hbs b/templates/settings/homebrew-settings/domains.hbs index 0946f211..b65422c5 100644 --- a/templates/settings/homebrew-settings/domains.hbs +++ b/templates/settings/homebrew-settings/domains.hbs @@ -1,5 +1,5 @@
diff --git a/templates/settings/homebrew-settings/downtime.hbs b/templates/settings/homebrew-settings/downtime.hbs index 890afddc..8612f3d5 100644 --- a/templates/settings/homebrew-settings/downtime.hbs +++ b/templates/settings/homebrew-settings/downtime.hbs @@ -1,5 +1,5 @@
diff --git a/templates/settings/homebrew-settings/itemFeatures.hbs b/templates/settings/homebrew-settings/itemFeatures.hbs index 1f8595de..22c23af6 100644 --- a/templates/settings/homebrew-settings/itemFeatures.hbs +++ b/templates/settings/homebrew-settings/itemFeatures.hbs @@ -1,5 +1,5 @@
diff --git a/templates/settings/homebrew-settings/settings.hbs b/templates/settings/homebrew-settings/settings.hbs index 5da053f4..cdcbd461 100644 --- a/templates/settings/homebrew-settings/settings.hbs +++ b/templates/settings/homebrew-settings/settings.hbs @@ -1,5 +1,5 @@
diff --git a/templates/settings/homebrew-settings/types.hbs b/templates/settings/homebrew-settings/types.hbs index f9d3bba3..bdb92ba0 100644 --- a/templates/settings/homebrew-settings/types.hbs +++ b/templates/settings/homebrew-settings/types.hbs @@ -1,5 +1,5 @@
From 3405b53900fe9be2ac4afc7a69ec49d3689a6e65 Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sun, 28 Dec 2025 10:31:48 -0700 Subject: [PATCH 2/8] [PR] Adding recall functionality to the loadout tab (#1482) * Adding a Recall button that doesn't yet show a popup * Adding an action with a cost dialog for stress - if there is a stress cost --- lang/en.json | 1 + .../applications/sheets/actors/character.mjs | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lang/en.json b/lang/en.json index 828b2303..68ab0a12 100755 --- a/lang/en.json +++ b/lang/en.json @@ -326,6 +326,7 @@ "equip": "Equip", "sendToChat": "Send To Chat", "toLoadout": "Send to Loadout", + "recall": "Recall", "toVault": "Send to Vault", "unequip": "Unequip", "useItem": "Use Item" diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 66ed6315..b48d459d 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -318,6 +318,40 @@ export default class CharacterSheet extends DHBaseActorSheet { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.loadoutMaxReached')); } }, + { + name: 'recall', + icon: 'fa-solid fa-bolt-lightning', + condition: target => { + const doc = getDocFromElementSync(target); + return doc && doc.system.inVault; + }, + callback: async (target, event) => { + const doc = await getDocFromElement(target); + const actorLoadout = doc.actor.system.loadoutSlot; + if (!actorLoadout.available) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.loadoutMaxReached')); + return; + } + if (doc.system.recallCost == 0) { + return doc.update({ 'system.inVault': false }); + } + const type = 'effect'; + const cls = game.system.api.models.actions.actionsTypes[type]; + const action = new cls({ + ...cls.getSourceConfig(doc.system), + type: type, + chatDisplay: false, + cost: [{ + key: 'stress', + value: doc.system.recallCost + }] + }, { parent: doc.system }); + const config = await action.use(event); + if (config) { + return doc.update({ 'system.inVault': false }); + } + } + }, { name: 'toVault', icon: 'fa-solid fa-arrow-down', From c83fe25a476b25bc7e1bdb395f77c7021c984142 Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sun, 28 Dec 2025 10:50:26 -0700 Subject: [PATCH 3/8] Using the same drag-drop approach in environments and adversaries as in the character sheet (#1481) --- module/applications/sheets/actors/adversary.mjs | 17 ++++++++++++++++- .../applications/sheets/actors/environment.mjs | 7 ++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index 345f6fed..789543cf 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -26,7 +26,12 @@ export default class AdversarySheet extends DHBaseActorSheet { } ] }, - dragDrop: [{ dragSelector: '[data-item-id]', dropSelector: null }] + dragDrop: [ + { + dragSelector: '[data-item-id][draggable="true"], [data-item-id] [draggable="true"]', + dropSelector: null + } + ], }; static PARTS = { @@ -164,6 +169,16 @@ export default class AdversarySheet extends DHBaseActorSheet { }); } + /** @inheritdoc */ + async _onDragStart(event) { + const inventoryItem = event.currentTarget.closest('.inventory-item'); + if (inventoryItem) { + event.dataTransfer.setDragImage(inventoryItem.querySelector('img'), 60, 0); + } + super._onDragStart(event); + } + + /* -------------------------------------------- */ /* Application Clicks Actions */ /* -------------------------------------------- */ diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 9a09cd94..01a60ec1 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -25,7 +25,12 @@ export default class DhpEnvironment extends DHBaseActorSheet { toggleResourceDice: DhpEnvironment.#toggleResourceDice, handleResourceDice: DhpEnvironment.#handleResourceDice }, - dragDrop: [{ dragSelector: '.inventory-item', dropSelector: null }] + dragDrop: [ + { + dragSelector: '[data-item-id][draggable="true"], [data-item-id] [draggable="true"]', + dropSelector: null + } + ], }; /**@override */ From f11b018bd727e1e348124b47f765d404f3afd35e Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sun, 28 Dec 2025 13:07:12 -0500 Subject: [PATCH 4/8] Support drag/drop resorting of adversary features (#1469) --- module/applications/sheets/actors/adversary.mjs | 7 +++++++ templates/sheets/actors/adversary/features.hbs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index 789543cf..98282d9f 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -93,6 +93,13 @@ export default class AdversarySheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; + const featureForms = ['passive', 'action', 'reaction']; + context.features = this.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); + return context; } diff --git a/templates/sheets/actors/adversary/features.hbs b/templates/sheets/actors/adversary/features.hbs index 98c1cedb..a24342fc 100644 --- a/templates/sheets/actors/adversary/features.hbs +++ b/templates/sheets/actors/adversary/features.hbs @@ -4,7 +4,7 @@ {{> 'daggerheart.inventory-items' title=tabs.features.label type='feature' - collection=document.system.features + collection=@root.features hideContextMenu=true canCreate=true showActions=true From d0e55aeb8d6bf989439dc5a3ce0a2d7c0905f0ff Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sun, 28 Dec 2025 21:16:24 +0100 Subject: [PATCH 5/8] Resource Generation Fix --- module/dice/dualityRoll.mjs | 2 +- module/documents/actor.mjs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 91c0a197..d2e20213 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -298,7 +298,7 @@ export default class DualityRoll extends D20Roll { if (looseSpotlight && game.combat?.active) { const currentCombatant = game.combat.combatants.get(game.combat.current?.combatantId); - if (currentCombatant?.actorId == actor.id) ui.combat.setCombatantSpotlight(currentCombatant.id); + if (currentCombatant?.actorId == config.data.id) ui.combat.setCombatantSpotlight(currentCombatant.id); } } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 9f4db5e2..6080eb87 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -543,6 +543,7 @@ export default class DhpActor extends Actor { /* system gets repeated infinately which causes issues when trying to use the data for document creation */ delete rollData.system; + rollData.id = this.id; rollData.name = this.name; rollData.system = this.system.getRollData(); rollData.prof = this.system.proficiency ?? 1; From c070c6cc2d2f9378c340e30f6cab21b847689696 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 29 Dec 2025 04:44:49 +0100 Subject: [PATCH 6/8] [Fix] Evolved Beastform Wildcard (#1486) * Fixed so picking an evolved beastform will properly handle wildcard images * . --- module/applications/dialogs/beastformDialog.mjs | 15 +++++++++++---- module/data/fields/action/beastformField.mjs | 2 +- system.json | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/module/applications/dialogs/beastformDialog.mjs b/module/applications/dialogs/beastformDialog.mjs index 3dd88d6c..09a9222b 100644 --- a/module/applications/dialogs/beastformDialog.mjs +++ b/module/applications/dialogs/beastformDialog.mjs @@ -278,19 +278,26 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat 'close', async () => { const selected = app.selected.toObject(); + const evolved = app.evolved.form ? app.evolved.form.toObject() : null; const data = await game.system.api.data.items.DHBeastform.getWildcardImage( app.configData.data.parent, - app.selected + evolved ?? app.selected ); if (data) { if (!data.selectedImage) selected = null; else { - if (data.usesDynamicToken) selected.system.tokenRingImg = data.selectedImage; - else selected.system.tokenImg = data.selectedImage; + const imageSource = evolved ?? selected; + if (imageSource.usesDynamicToken) imageSource.system.tokenRingImg = data.selectedImage; + else imageSource.system.tokenImg = data.selectedImage; } } - resolve({ selected: selected, evolved: app.evolved, hybrid: app.hybrid, item: featureItem }); + resolve({ + selected: selected, + evolved: { ...app.evolved, form: evolved }, + hybrid: app.hybrid, + item: featureItem + }); }, { once: true } ); diff --git a/module/data/fields/action/beastformField.mjs b/module/data/fields/action/beastformField.mjs index 6185f0f8..e19807c7 100644 --- a/module/data/fields/action/beastformField.mjs +++ b/module/data/fields/action/beastformField.mjs @@ -76,7 +76,7 @@ export default class BeastformField extends fields.SchemaField { * @returns */ static async transform(selectedForm, evolvedData, hybridData) { - const formData = evolvedData?.form ? evolvedData.form.toObject() : selectedForm; + const formData = evolvedData?.form ?? selectedForm; const beastformEffect = formData.effects.find(x => x.type === 'beastform'); if (!beastformEffect) { ui.notifications.error('DAGGERHEART.UI.Notifications.beastformMissingEffect'); diff --git a/system.json b/system.json index 0dcbc398..ce361568 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "1.4.2", + "version": "1.4.3", "compatibility": { "minimum": "13.346", "verified": "13.351", From f6bd1430e3e6763afd524e9b0477a4a62e1f3085 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:02:22 +0100 Subject: [PATCH 7/8] Fixed drag/drop of features for environments (#1488) --- .../sheets-configs/adversary-settings.mjs | 19 ++++++++++++++--- .../sheets-configs/environment-settings.mjs | 13 ++++++++++++ .../sheets/actors/environment.mjs | 21 ++++++++++++++++++- .../adversary-settings/features.hbs | 2 +- .../environment-settings/features.hbs | 2 +- .../sheets/actors/environment/features.hbs | 2 +- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/module/applications/sheets-configs/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs index bcc8b1c9..d3d215be 100644 --- a/module/applications/sheets-configs/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -51,6 +51,19 @@ export default class DHAdversarySettings extends DHBaseActorSettings { } }; + async _prepareContext(options) { + const context = await super._prepareContext(options); + + const featureForms = ['passive', 'action', 'reaction']; + context.features = context.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); + + return context; + } + /* -------------------------------------------- */ /** @@ -98,16 +111,16 @@ export default class DHAdversarySettings extends DHBaseActorSettings { async _onDrop(event) { const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - + const item = await fromUuid(data.uuid); if (item?.type === 'feature') { if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { return; } - + const itemData = item.toObject(); delete itemData._id; - + await this.actor.createEmbeddedDocuments('Item', [itemData]); } } diff --git a/module/applications/sheets-configs/environment-settings.mjs b/module/applications/sheets-configs/environment-settings.mjs index 2efa3b38..15f5701d 100644 --- a/module/applications/sheets-configs/environment-settings.mjs +++ b/module/applications/sheets-configs/environment-settings.mjs @@ -49,6 +49,19 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { } }; + async _prepareContext(options) { + const context = await super._prepareContext(options); + + const featureForms = ['passive', 'action', 'reaction']; + context.features = context.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); + + return context; + } + /** * Adds a new category entry to the actor. * @type {ApplicationClickAction} diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 01a60ec1..f8ff74a6 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -30,7 +30,7 @@ export default class DhpEnvironment extends DHBaseActorSheet { dragSelector: '[data-item-id][draggable="true"], [data-item-id] [draggable="true"]', dropSelector: null } - ], + ] }; /**@override */ @@ -79,6 +79,9 @@ export default class DhpEnvironment extends DHBaseActorSheet { case 'header': await this._prepareHeaderContext(context, options); + break; + case 'features': + await this._prepareFeaturesContext(context, options); break; case 'notes': await this._prepareNotesContext(context, options); @@ -115,6 +118,22 @@ export default class DhpEnvironment extends DHBaseActorSheet { } } + /** + * Prepare render context for the features part. + * @param {ApplicationRenderContext} context + * @param {ApplicationRenderOptions} options + * @returns {Promise} + * @protected + */ + async _prepareFeaturesContext(context, _options) { + const featureForms = ['passive', 'action', 'reaction']; + context.features = this.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); + } + /** * Prepare render context for the Header part. * @param {ApplicationRenderContext} context diff --git a/templates/sheets-settings/adversary-settings/features.hbs b/templates/sheets-settings/adversary-settings/features.hbs index bc6a1ddf..2f2f5f47 100644 --- a/templates/sheets-settings/adversary-settings/features.hbs +++ b/templates/sheets-settings/adversary-settings/features.hbs @@ -9,7 +9,7 @@
{{localize tabs.features.label}}
    - {{#each document.system.features as |feature|}} + {{#each @root.features as |feature|}}
  • diff --git a/templates/sheets-settings/environment-settings/features.hbs b/templates/sheets-settings/environment-settings/features.hbs index 13a76f06..579fe74e 100644 --- a/templates/sheets-settings/environment-settings/features.hbs +++ b/templates/sheets-settings/environment-settings/features.hbs @@ -9,7 +9,7 @@
    {{localize tabs.features.label}}
      - {{#each document.system.features as |feature|}} + {{#each @root.features as |feature|}}
    • diff --git a/templates/sheets/actors/environment/features.hbs b/templates/sheets/actors/environment/features.hbs index 4c0e3519..3ad36023 100644 --- a/templates/sheets/actors/environment/features.hbs +++ b/templates/sheets/actors/environment/features.hbs @@ -7,7 +7,7 @@ {{> 'daggerheart.inventory-items' title=tabs.features.label type='feature' - collection=document.system.features + collection=@root.features hideContextMenu=true canCreate=true showActions=true From e8c541c0020cbbaeeb3753d16f7db01278d60f45 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Mon, 29 Dec 2025 14:00:40 +0100 Subject: [PATCH 8/8] Added damage reduction rules (#1491) --- module/data/actor/adversary.mjs | 22 ++-------- module/data/actor/base.mjs | 30 ++++++++++--- module/data/actor/character.mjs | 77 +++++++++++++++------------------ module/documents/actor.mjs | 15 ++++++- 4 files changed, 77 insertions(+), 67 deletions(-) diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index 32f5c979..16e7e37a 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -1,6 +1,6 @@ import DHAdversarySettings from '../../applications/sheets-configs/adversary-settings.mjs'; import { ActionField } from '../fields/actionField.mjs'; -import BaseDataActor from './base.mjs'; +import BaseDataActor, { commonActorRules } from './base.mjs'; import { resourceField, bonusField } from '../fields/actorField.mjs'; export default class DhpAdversary extends BaseDataActor { @@ -56,25 +56,11 @@ export default class DhpAdversary extends BaseDataActor { }) }), resources: new fields.SchemaField({ - hitPoints: resourceField( - 0, - 0, - 'DAGGERHEART.GENERAL.HitPoints.plural', - true - ), - stress: resourceField( - 0, - 0, - 'DAGGERHEART.GENERAL.stress', - true - ) + hitPoints: resourceField(0, 0, 'DAGGERHEART.GENERAL.HitPoints.plural', true), + stress: resourceField(0, 0, 'DAGGERHEART.GENERAL.stress', true) }), rules: new fields.SchemaField({ - conditionImmunities: new fields.SchemaField({ - hidden: new fields.BooleanField({ initial: false }), - restrained: new fields.BooleanField({ initial: false }), - vulnerable: new fields.BooleanField({ initial: false }) - }) + ...commonActorRules() }), attack: new ActionField({ initial: { diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 29b0af28..b90361e2 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -2,21 +2,23 @@ import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs import DHItem from '../../documents/item.mjs'; import { getScrollTextData } from '../../helpers/utils.mjs'; +const fields = foundry.data.fields; + const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) => - new foundry.data.fields.SchemaField({ - resistance: new foundry.data.fields.BooleanField({ + new fields.SchemaField({ + resistance: new fields.BooleanField({ initial: false, label: `${resistanceLabel}.label`, hint: `${resistanceLabel}.hint`, isAttributeChoice: true }), - immunity: new foundry.data.fields.BooleanField({ + immunity: new fields.BooleanField({ initial: false, label: `${immunityLabel}.label`, hint: `${immunityLabel}.hint`, isAttributeChoice: true }), - reduction: new foundry.data.fields.NumberField({ + reduction: new fields.NumberField({ integer: true, initial: 0, label: `${reductionLabel}.label`, @@ -24,6 +26,25 @@ const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) => }) }); +/* Common rules applying to Characters and Adversaries */ +export const commonActorRules = (extendedData = { damageReduction: {} }) => ({ + conditionImmunities: new fields.SchemaField({ + hidden: new fields.BooleanField({ initial: false }), + restrained: new fields.BooleanField({ initial: false }), + vulnerable: new fields.BooleanField({ initial: false }) + }), + damageReduction: new fields.SchemaField({ + thresholdImmunities: new fields.SchemaField({ + minor: new fields.BooleanField({ initial: false }) + }), + reduceSeverity: new fields.SchemaField({ + magical: new fields.NumberField({ initial: 0, min: 0 }), + physical: new fields.NumberField({ initial: 0, min: 0 }) + }), + ...extendedData.damageReduction + }) +}); + /** * Describes metadata about the actor data model type * @typedef {Object} ActorDataModelMetadata @@ -54,7 +75,6 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { /** @inheritDoc */ static defineSchema() { - const fields = foundry.data.fields; const schema = {}; if (this.metadata.hasAttribution) { diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 5bce5c55..eba46f10 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -1,7 +1,7 @@ import { burden } from '../../config/generalConfig.mjs'; import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import DhLevelData from '../levelData.mjs'; -import BaseDataActor from './base.mjs'; +import BaseDataActor, { commonActorRules } from './base.mjs'; import { attributeField, resourceField, stressDamageReductionRule, bonusField } from '../fields/actorField.mjs'; import { ActionField } from '../fields/actionField.mjs'; import DHCharacterSettings from '../../applications/sheets-configs/character-settings.mjs'; @@ -217,44 +217,41 @@ export default class DhCharacter extends BaseDataActor { }), companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }), rules: new fields.SchemaField({ - damageReduction: new fields.SchemaField({ - maxArmorMarked: new fields.SchemaField({ - value: new fields.NumberField({ - required: true, + ...commonActorRules({ + damageReduction: { + magical: new fields.BooleanField({ initial: false }), + physical: new fields.BooleanField({ initial: false }), + maxArmorMarked: new fields.SchemaField({ + value: new fields.NumberField({ + required: true, + integer: true, + initial: 1, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedBonus' + }), + stressExtra: new fields.NumberField({ + required: true, + integer: true, + initial: 0, + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedStress.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedStress.hint' + }) + }), + stressDamageReduction: new fields.SchemaField({ + severe: stressDamageReductionRule( + 'DAGGERHEART.GENERAL.Rules.damageReduction.stress.severe' + ), + major: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.major'), + minor: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.minor'), + any: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.any') + }), + increasePerArmorMark: new fields.NumberField({ integer: true, initial: 1, - label: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedBonus' + label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.label', + hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint' }), - stressExtra: new fields.NumberField({ - required: true, - integer: true, - initial: 0, - label: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedStress.label', - hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.maxArmorMarkedStress.hint' - }) - }), - stressDamageReduction: new fields.SchemaField({ - severe: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.severe'), - major: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.major'), - minor: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.minor'), - any: stressDamageReductionRule('DAGGERHEART.GENERAL.Rules.damageReduction.stress.any') - }), - increasePerArmorMark: new fields.NumberField({ - integer: true, - initial: 1, - label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.label', - hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint' - }), - magical: new fields.BooleanField({ initial: false }), - physical: new fields.BooleanField({ initial: false }), - thresholdImmunities: new fields.SchemaField({ - minor: new fields.BooleanField({ initial: false }) - }), - reduceSeverity: new fields.SchemaField({ - magical: new fields.NumberField({ initial: 0, min: 0 }), - physical: new fields.NumberField({ initial: 0, min: 0 }) - }), - disabledArmor: new fields.BooleanField({ intial: false }) + disabledArmor: new fields.BooleanField({ intial: false }) + } }), attack: new fields.SchemaField({ damage: new fields.SchemaField({ @@ -283,11 +280,6 @@ export default class DhCharacter extends BaseDataActor { }) }) }), - conditionImmunities: new fields.SchemaField({ - hidden: new fields.BooleanField({ initial: false }), - restrained: new fields.BooleanField({ initial: false }), - vulnerable: new fields.BooleanField({ initial: false }) - }), runeWard: new fields.BooleanField({ initial: false }), burden: new fields.SchemaField({ ignore: new fields.BooleanField() @@ -453,8 +445,7 @@ export default class DhCharacter extends BaseDataActor { if ( item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.foundation || - (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization && - subclassState >= 2) || + (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization && subclassState >= 2) || (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3) ) { return true; diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 6080eb87..f6666a5e 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -1,7 +1,7 @@ import { emitAsGM, GMUpdateEvent } from '../systemRegistration/socket.mjs'; import { LevelOptionType } from '../data/levelTier.mjs'; import DHFeature from '../data/item/feature.mjs'; -import { createScrollText, damageKeyToNumber } from '../helpers/utils.mjs'; +import { createScrollText, damageKeyToNumber, getDamageKey } from '../helpers/utils.mjs'; import DhCompanionLevelUp from '../applications/levelup/companionLevelup.mjs'; import { ResourceUpdateMap } from '../data/action/baseAction.mjs'; @@ -631,6 +631,19 @@ export default class DhpActor extends Actor { } } } + if (this.type === 'adversary') { + const reducedSeverity = hpDamage.damageTypes.reduce((value, curr) => { + return Math.max(this.system.rules.damageReduction.reduceSeverity[curr], value); + }, 0); + hpDamage.value = Math.max(hpDamage.value - reducedSeverity, 0); + + if ( + hpDamage.value && + this.system.rules.damageReduction.thresholdImmunities[getDamageKey(hpDamage.value)] + ) { + hpDamage.value -= 1; + } + } } updates.forEach(