From 4a63836c0d57a4be028052d08faf9eeb699e7f27 Mon Sep 17 00:00:00 2001 From: Dapoolp Date: Tue, 2 Sep 2025 16:39:02 +0200 Subject: [PATCH] Add multiple conditions handler + update Bare Bones domain card --- lang/en.json | 11 ++- .../sheets-configs/activeEffectConfig.mjs | 49 ++++++++++- module/data/activeEffect/baseEffect.mjs | 13 ++- module/documents/activeEffect.mjs | 8 +- ...omainCard_Bare_Bones_l5D9kq901JDESaXw.json | 81 +++++++++++++++++-- styles/less/global/elements.less | 33 ++++++++ styles/less/global/sheet.less | 14 ++-- templates/sheets/activeEffect/changes.hbs | 42 ++++++---- 8 files changed, 213 insertions(+), 38 deletions(-) diff --git a/lang/en.json b/lang/en.json index ce29377a..38e14a5d 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1935,6 +1935,7 @@ }, "actorName": "Actor Name", "amount": "Amount", + "and": "AND", "any": "Any", "armor": "Armor", "armors": "Armors", @@ -1947,9 +1948,12 @@ "bonus": "Bonus", "burden": "Burden", "conditional": { - "label": "Condition", - "hint": "(Optionnal) Set a condition that need to be verified to apply effects below.", - "notMet": "Condition Not Met" + "label": { + "single": "Condition", + "plural": "Conditions" + }, + "hint": "(Optionnal) Set one or more conditions that need to be verified to apply effects below.", + "notMet": "Conditions Not Met" }, "continue": "Continue", "criticalSuccess": "Critical Success", @@ -2014,6 +2018,7 @@ "newCategory": "New Category", "none": "None", "noTarget": "No current target", + "or": "OR", "partner": "Partner", "player": { "single": "Player", diff --git a/module/applications/sheets-configs/activeEffectConfig.mjs b/module/applications/sheets-configs/activeEffectConfig.mjs index 25f7d2b5..c55da05b 100644 --- a/module/applications/sheets-configs/activeEffectConfig.mjs +++ b/module/applications/sheets-configs/activeEffectConfig.mjs @@ -20,7 +20,12 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac } static DEFAULT_OPTIONS = { - classes: ['daggerheart', 'sheet', 'dh-style'] + classes: ['daggerheart', 'sheet', 'dh-style'], + actions: { + addCondition: DhActiveEffectConfig.#onAddCondition, + deleteCondition: DhActiveEffectConfig.#onDeleteCondition, + setAndOr: DhActiveEffectConfig.#setAndOr + } }; static PARTS = { @@ -115,4 +120,46 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac return partContext; } + + /* ----------------------------------------- */ + + /** + * Add a new condition to the effect's conditions array. + * @this {DhActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onAddCondition() { + const submitData = this._processFormData(null, this.form, new foundry.applications.ux.FormDataExtended(this.form)); + const conditions = Object.values(submitData.system.conditional?.condition ?? {}); + conditions.push({}); + return this.submit({updateData: {'system.conditional.condition': conditions}}); + } + + /* ----------------------------------------- */ + + /** + * Add a new condition to the effect's conditions array. + * @this {DhActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #onDeleteCondition(event) { + const submitData = this._processFormData(null, this.form, new FormDataExtended(this.form)); + const conditions = Object.values(submitData.system.conditional.condition ?? {}); + const row = event.target.closest("li"); + const index = Number(row.dataset.index) || 0; + conditions.splice(index, 1); + return this.submit({updateData: {'system.conditional.condition': conditions}}); + } + + /* ----------------------------------------- */ + + /** + * Add a new condition to the effect's conditions array. + * @this {DhActiveEffectConfig} + * @type {ApplicationClickAction} + */ + static async #setAndOr(event) { + const value = event.target.dataset.value; + return this.submit({updateData: {'system.conditional.andOr': value === 'true'}}); + } } diff --git a/module/data/activeEffect/baseEffect.mjs b/module/data/activeEffect/baseEffect.mjs index 88a1e515..96935f33 100644 --- a/module/data/activeEffect/baseEffect.mjs +++ b/module/data/activeEffect/baseEffect.mjs @@ -4,10 +4,15 @@ export default class BaseEffect extends foundry.abstract.TypeDataModel { return { conditional: new fields.SchemaField({ - field: new fields.StringField({required: true, nullable: true}), - operator: new fields.StringField({required: true, choices: CONFIG.DH.EFFECTS.conditionalTypes(), initial: 'equals'}), - value: new fields.StringField({required: true}), - negate: new fields.BooleanField({initial: false}) + andOr: new fields.BooleanField({ initial: true }), + condition: new fields.ArrayField( + new fields.SchemaField({ + field: new fields.StringField({required: true, nullable: true}), + operator: new fields.StringField({required: true, choices: CONFIG.DH.EFFECTS.conditionalTypes(), initial: 'equals'}), + value: new fields.StringField({required: true}), + negate: new fields.BooleanField({initial: false}) + }) + ) }), rangeDependence: new fields.SchemaField({ enabled: new fields.BooleanField({ diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index ab206d4d..59aa5058 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -112,8 +112,12 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { } verifyCondition(actor) { - if(!this.system.conditional?.field) return true; - return foundry.applications.ux.SearchFilter.evaluateFilter(actor, this.system.conditional); + if(!this.system.conditional?.condition.length) return true; + return this.system.conditional.condition.filter(c => c.field).map(c => { + if(!isNaN(c.value)) + c.value = Number(c.value); + return c; + })[this.system.conditional.andOr ? 'every' : 'some'](c => foundry.applications.ux.SearchFilter.evaluateFilter(actor, c)); } /** diff --git a/src/packs/domains/domainCard_Bare_Bones_l5D9kq901JDESaXw.json b/src/packs/domains/domainCard_Bare_Bones_l5D9kq901JDESaXw.json index 0509faff..d9742dd3 100644 --- a/src/packs/domains/domainCard_Bare_Bones_l5D9kq901JDESaXw.json +++ b/src/packs/domains/domainCard_Bare_Bones_l5D9kq901JDESaXw.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "QpOL7jPbMBzH96qR", "system": { - "description": "

When you choose not to equip armor, you have a base Armor Score of 3 + your Strength and use the following as your base damage thresholds:

Equip the below armor to use Bare Bones.

@UUID[Compendium.daggerheart.armors.Item.ITAjcigTcUw5pMCN]{Bare Bones}

", + "description": "

When you choose not to equip armor, you have a base Armor Score of 3 + your Strength and use the following as your base damage thresholds:

", "domain": "valor", "recallCost": 0, "level": 1, @@ -25,12 +25,83 @@ "exportSource": null, "coreVersion": "13.347", "systemId": "daggerheart", - "systemVersion": "1.0.5", + "systemVersion": "1.1.2", "createdTime": 1754067006722, - "modifiedTime": 1755429823165, - "lastModifiedBy": "VZIeX2YDvX338Zvr" + "modifiedTime": 1756823636026, + "lastModifiedBy": "8iAdslq1c1LfHXVb" }, - "effects": [], + "effects": [ + { + "name": "Bare Bones", + "type": "base", + "system": { + "conditional": { + "andOr": true, + "condition": [ + { + "field": "system.armor", + "operator": "is_empty", + "value": "", + "negate": false + } + ] + }, + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } + }, + "_id": "c8XXojizrnP1IHHK", + "img": "systems/daggerheart/assets/icons/domains/domain-card/valor.png", + "changes": [ + { + "key": "system.armorScore", + "mode": 5, + "value": "3 + @system.traits.strength.value", + "priority": 0 + }, + { + "key": "system.damageThresholds.major", + "mode": 5, + "value": "9 + (@tier -1)*2", + "priority": 0 + }, + { + "key": "system.damageThresholds.severe", + "mode": 5, + "value": "19 + (@tier - 1) * 5 + max(0, (@tier -2) * 2 )", + "priority": 0 + } + ], + "disabled": false, + "duration": { + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null + }, + "description": "

When you choose not to equip armor, you have a base Armor Score of 3 + your Strength and use the following as your base damage thresholds:

", + "origin": null, + "tint": "#ffffff", + "transfer": true, + "statuses": [], + "sort": 0, + "flags": {}, + "_stats": { + "coreVersion": "13.347", + "systemId": "daggerheart", + "systemVersion": "1.1.2", + "createdTime": 1756823269943, + "modifiedTime": 1756823587199, + "lastModifiedBy": "8iAdslq1c1LfHXVb" + } + } + ], "ownership": { "default": 0, "MQSznptE5yLT7kj8": 3 diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index e4a2128c..5b96f423 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -530,6 +530,39 @@ font-size: var(--font-size-12); padding-left: 3px; } + + .double-buttons { + display: grid; + grid-template-columns: 1fr 1fr; + margin-left: auto; + margin-bottom: .5rem; + margin-right: .5rem; + + > button { + height: calc(var(--input-height) / 1.5); + min-height: calc(var(--input-height) / 1.5); + font-size: var(--font-size-12); + + &:hover { + background-color: light-dark(transparent, #f3c267); + color: light-dark(#18162e, #18162e); + } + + &.inactive { + background-color: @medium-red; + } + + &:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } } .application.setting.dh-style { diff --git a/styles/less/global/sheet.less b/styles/less/global/sheet.less index 5ec5efb1..01bff890 100755 --- a/styles/less/global/sheet.less +++ b/styles/less/global/sheet.less @@ -74,13 +74,13 @@ body.game:is(.performance-low, .noblur) { grid-template-columns: 12fr 7fr 7fr 4fr 1fr; } - &.conditional { - header, ol { - grid-template-columns: 12fr 7fr 10fr 3fr; - scrollbar-gutter: unset; - overflow: unset; - } - } + // &.conditional { + // header, ol { + // grid-template-columns: 12fr 7fr 10fr 3fr; + // scrollbar-gutter: unset; + // overflow: unset; + // } + // } } } } diff --git a/templates/sheets/activeEffect/changes.hbs b/templates/sheets/activeEffect/changes.hbs index 3ff28faf..cba6ba6f 100644 --- a/templates/sheets/activeEffect/changes.hbs +++ b/templates/sheets/activeEffect/changes.hbs @@ -1,28 +1,38 @@
- {{localize "DAGGERHEART.GENERAL.conditional.label"}} + {{localize "DAGGERHEART.GENERAL.conditional.label.plural"}}

{{localize "DAGGERHEART.GENERAL.conditional.hint"}}

+
+ + +
{{localize "EFFECT.ChangeKey"}}
{{localize "EFFECT.ChangeFilter"}}
{{localize "EFFECT.ChangeValue"}}
{{localize "EFFECT.ChangeNegate"}}
+
-
    -
  1. -
    - {{formInput document.system.schema.fields.conditional.fields.field value=source.system.conditional.field localize=true }} -
    -
    - {{formInput document.system.schema.fields.conditional.fields.operator value=source.system.conditional.operator localize=true }} -
    -
    - {{formInput document.system.schema.fields.conditional.fields.value value=source.system.conditional.value localize=true }} -
    -
    - {{formInput document.system.schema.fields.conditional.fields.negate value=source.system.conditional.negate localize=true }} -
    -
  2. +
      + {{#each source.system.conditional.condition as |condition i|}} + {{#with ../document.system.schema.fields.conditional.fields.condition.element.fields as |conditionFields|}} +
    1. +
      + {{formInput conditionFields.field value=condition.field name=(concat "system.conditional.condition." i ".field") localize=true }} +
      +
      + {{formInput conditionFields.operator value=condition.operator name=(concat "system.conditional.condition." i ".operator") localize=true }} +
      +
      + {{formInput conditionFields.value value=condition.value name=(concat "system.conditional.condition." i ".value") localize=true }} +
      +
      + {{formInput conditionFields.negate value=condition.negate name=(concat "system.conditional.condition." i ".negate") localize=true }} +
      +
      +
    2. + {{/with}} + {{/each}}