From a4f8c67707e19b843913c8a09d2d3a458a0ec1df Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:32:36 +0100 Subject: [PATCH] Added vulnerable condition automation (#1704) --- lang/en.json | 7 +++- module/config/generalConfig.mjs | 3 +- module/data/actor/creature.mjs | 41 +++++++++++++++++++ module/data/settings/Automation.mjs | 4 ++ module/documents/actor.mjs | 13 ++++++ .../settings/automation-settings/general.hbs | 1 + 6 files changed, 67 insertions(+), 2 deletions(-) diff --git a/lang/en.json b/lang/en.json index 82193133..c9d21944 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1031,7 +1031,8 @@ }, "vulnerable": { "name": "Vulnerable", - "description": "While a creature is Vulnerable, all rolls targeting them have advantage.\nA creature who is already Vulnerable can’t be made to take the condition again." + "description": "While a creature is Vulnerable, all rolls targeting them have advantage.\nA creature who is already Vulnerable can’t be made to take the condition again.", + "autoAppliedByLabel": "Max Stress" } }, "CountdownType": { @@ -2556,6 +2557,10 @@ "gm": { "label": "GM" }, "players": { "label": "Players" } }, + "vulnerableAutomation": { + "label": "Vulnerable Automation", + "hint": "Automatically apply the Vulnerable condition when a actor reaches max stress" + }, "countdownAutomation": { "label": "Countdown Automation", "hint": "Automatically progress countdowns based on their progression settings" diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index a38d1c8a..d46db23a 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -202,7 +202,8 @@ export const conditions = () => ({ id: 'vulnerable', name: 'DAGGERHEART.CONFIG.Condition.vulnerable.name', img: 'icons/magic/control/silhouette-fall-slip-prone.webp', - description: 'DAGGERHEART.CONFIG.Condition.vulnerable.description' + description: 'DAGGERHEART.CONFIG.Condition.vulnerable.description', + autoApplyFlagId: 'auto-vulnerable' }, hidden: { id: 'hidden', diff --git a/module/data/actor/creature.mjs b/module/data/actor/creature.mjs index 4b927aed..c8bf8448 100644 --- a/module/data/actor/creature.mjs +++ b/module/data/actor/creature.mjs @@ -17,4 +17,45 @@ export default class DhCreature extends BaseDataActor { }) }; } + + get isAutoVulnerableActive() { + const vulnerableAppliedByOther = this.parent.effects.some( + x => x.statuses.has('vulnerable') && !x.flags.daggerheart?.autoApplyFlagId + ); + return !vulnerableAppliedByOther; + } + + async _preUpdate(changes, options, userId) { + const allowed = await super._preUpdate(changes, options, userId); + if (allowed === false) return; + + const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + if ( + automationSettings.vulnerableAutomation && + this.parent.type !== 'companion' && + changes.system?.resources?.stress?.value + ) { + const { name, description, img, autoApplyFlagId } = CONFIG.DH.GENERAL.conditions().vulnerable; + const autoEffects = this.parent.effects.filter( + x => x.flags.daggerheart?.autoApplyFlagId === autoApplyFlagId + ); + if (changes.system.resources.stress.value >= this.resources.stress.max) { + if (!autoEffects.length) + this.parent.createEmbeddedDocuments('ActiveEffect', [ + { + name: game.i18n.localize(name), + description: game.i18n.localize(description), + img: img, + statuses: ['vulnerable'], + flags: { daggerheart: { autoApplyFlagId } } + } + ]); + } else if (this.resources.stress.value >= this.resources.stress.max) { + this.parent.deleteEmbeddedDocuments( + 'ActiveEffect', + autoEffects.map(x => x.id) + ); + } + } + } } diff --git a/module/data/settings/Automation.mjs b/module/data/settings/Automation.mjs index e9952b1c..20fe0baf 100644 --- a/module/data/settings/Automation.mjs +++ b/module/data/settings/Automation.mjs @@ -18,6 +18,10 @@ export default class DhAutomation extends foundry.abstract.DataModel { label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.hopeFear.players.label' }) }), + vulnerableAutomation: new fields.BooleanField({ + initial: true, + label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.vulnerableAutomation.label' + }), countdownAutomation: new fields.BooleanField({ required: true, initial: true, diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index e8bea0bf..787797ff 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -934,10 +934,23 @@ export default class DhpActor extends Actor { /** Get active effects */ getActiveEffects() { + const conditions = CONFIG.DH.GENERAL.conditions(); const statusMap = new Map(foundry.CONFIG.statusEffects.map(status => [status.id, status])); + const autoVulnerableActive = this.system.isAutoVulnerableActive; return this.effects .filter(x => !x.disabled) .reduce((acc, effect) => { + /* Could be generalized if needed. Currently just related to Vulnerable */ + const isAutoVulnerableEffect = + effect.flags.daggerheart?.autoApplyFlagId === conditions.vulnerable.autoApplyFlagId; + if (isAutoVulnerableEffect) { + if (!autoVulnerableActive) return acc; + + effect.appliedBy = game.i18n.localize('DAGGERHEART.CONFIG.Condition.vulnerable.autoAppliedByLabel'); + effect.isLockedCondition = true; + effect.condition = 'vulnerable'; + } + acc.push(effect); const currentStatusActiveEffects = acc.filter( diff --git a/templates/settings/automation-settings/general.hbs b/templates/settings/automation-settings/general.hbs index c5f4d871..65bafab8 100644 --- a/templates/settings/automation-settings/general.hbs +++ b/templates/settings/automation-settings/general.hbs @@ -14,6 +14,7 @@ {{formGroup settingFields.schema.fields.summaryMessages.fields.effects value=settingFields._source.summaryMessages.effects localize=true}} + {{formGroup settingFields.schema.fields.vulnerableAutomation value=settingFields._source.vulnerableAutomation localize=true}} {{formGroup settingFields.schema.fields.countdownAutomation value=settingFields._source.countdownAutomation localize=true}} {{formGroup settingFields.schema.fields.actionPoints value=settingFields._source.actionPoints localize=true}} {{formGroup settingFields.schema.fields.hordeDamage value=settingFields._source.hordeDamage localize=true}}