From 4e304adde7e3342fdfa4387d120d3130ba522c9a Mon Sep 17 00:00:00 2001 From: psitacus Date: Tue, 8 Jul 2025 22:35:57 -0600 Subject: [PATCH] add attachment only flag and logic --- lang/en.json | 6 ++- module/applications/sheets/items/armor.mjs | 18 +++++-- module/data/item/armor.mjs | 1 + module/documents/activeEffect.mjs | 58 +++++++++++++++++----- templates/sheets/activeEffect/details.hbs | 7 +++ 5 files changed, 72 insertions(+), 18 deletions(-) diff --git a/lang/en.json b/lang/en.json index 91d0fa52..53fd6113 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1026,7 +1026,11 @@ }, "Effect": { "single": "Effect", - "plural": "Effects" + "plural": "Effects", + "AttachmentOnly": { + "Label": "Attachment Only", + "Hint": "When checked, this effect will only apply to the actor when this item is attached to another item (e.g., attached to armor). If unchecked, the effect applies normally based on item equipped status." + } }, "Experience": { "single": "Experience", diff --git a/module/applications/sheets/items/armor.mjs b/module/applications/sheets/items/armor.mjs index c26c6514..ffeeffef 100644 --- a/module/applications/sheets/items/armor.mjs +++ b/module/applications/sheets/items/armor.mjs @@ -132,14 +132,15 @@ export default class ArmorSheet extends DHBaseItemSheet { 'system.attached': updatedAttached }); - // Copy effects from attached item to actor (only if armor is equipped) + // Copy ALL effects from attached item to actor (only if armor is equipped) + // Both attachment-only and regular effects should be copied when attached const actor = this.document.parent; if (actor && item.effects.size > 0 && this.document.system.equipped) { - console.log(`Copying ${item.effects.size} effects from attached item ${item.name} to actor ${actor.name} (armor is equipped)`); + console.log(`Checking ${item.effects.size} effects from attached item ${item.name}`); const effectsToCreate = []; for (const effect of item.effects) { - // Create a copy of the effect with metadata to track its source + // Copy ALL effects when item is attached - attachment-only flag only matters for non-attached items const effectData = effect.toObject(); effectData.origin = `${this.document.uuid}:${newUUID}`; // Track which armor and which item this came from effectData.flags = { @@ -154,10 +155,17 @@ export default class ArmorSheet extends DHBaseItemSheet { } }; effectsToCreate.push(effectData); + + const isAttachmentOnly = effect.flags?.daggerheart?.attachmentOnly === true; + console.log(`Effect ${effect.name} (attachment-only: ${isAttachmentOnly}) will be copied to actor`); } - const createdEffects = await actor.createEmbeddedDocuments('ActiveEffect', effectsToCreate); - console.log(`Created ${createdEffects.length} effects on actor from attached item`); + if (effectsToCreate.length > 0) { + const createdEffects = await actor.createEmbeddedDocuments('ActiveEffect', effectsToCreate); + console.log(`Created ${createdEffects.length} effects on actor from attached item`); + } else { + console.log(`No effects found on ${item.name}, no effects copied to actor`); + } } else if (item.effects.size > 0 && !this.document.system.equipped) { console.log(`Armor ${this.document.name} is not equipped, attachment effects will be applied when equipped`); } diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index 5ba96310..afcac000 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -115,6 +115,7 @@ export default class DHArmor extends BaseDataItem { const attachedItem = await fromUuid(attachedUuid); if (attachedItem && attachedItem.effects.size > 0) { for (const effect of attachedItem.effects) { + // Copy ALL effects when item is attached - attachment-only flag only matters for non-attached items const effectData = effect.toObject(); effectData.origin = `${this.parent.uuid}:${attachedUuid}`; effectData.flags = { diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 23ba81a7..7e0f43ae 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -1,16 +1,60 @@ export default class DhActiveEffect extends ActiveEffect { get isSuppressed() { - if (['weapon', 'armor'].includes(this.parent.type)) { + // If this is a copied effect from an attachment, never suppress it + // (These effects have attachmentSource metadata) + if (this.flags?.daggerheart?.attachmentSource) { + return false; + } + + // First check for attachment-only effects - these should be suppressed unless attached + if (this.isAttachmentOnly && !this.isAttached) { + return true; + } + + // Then apply the standard suppression rules + if (['weapon', 'armor'].includes(this.parent?.type)) { return !this.parent.system.equipped; } - if (this.parent.type === 'domainCard') { + if (this.parent?.type === 'domainCard') { return this.parent.system.inVault; } return super.isSuppressed; } + /** + * Check if this effect is marked as attachment-only + * @returns {boolean} + */ + get isAttachmentOnly() { + return this.flags?.daggerheart?.attachmentOnly === true; + } + + /** + * Check if the parent item is currently attached to another item + * @returns {boolean} + */ + get isAttached() { + if (!this.parent || !this.parent.parent) return false; + + // Check if this item's UUID is in any actor's armor attachment lists + const actor = this.parent.parent; + if (!actor || !actor.items) return false; + + try { + return actor.items.some(item => { + return item.type === 'armor' && + item.system?.attached && + Array.isArray(item.system.attached) && + item.system.attached.includes(this.parent.uuid); + }); + } catch (error) { + console.warn('Error checking if item is attached:', error); + return false; + } + } + async _preCreate(data, options, user) { const update = {}; if (!data.img) { @@ -51,14 +95,4 @@ export default class DhActiveEffect extends ActiveEffect { cls.create(msg.toObject()); } - - /** - * Retrieve the Document that this ActiveEffect targets for modification. - * @type {Document|null} - */ - get target() { - if (this.parent instanceof Actor) return this.parent; - if (CONFIG.ActiveEffect.legacyTransferral) return this.transfer ? null : this.parent; - return this.transfer ? (this.parent.parent ?? null) : this.parent; - } } diff --git a/templates/sheets/activeEffect/details.hbs b/templates/sheets/activeEffect/details.hbs index 8ff72b98..e36b48f3 100644 --- a/templates/sheets/activeEffect/details.hbs +++ b/templates/sheets/activeEffect/details.hbs @@ -8,6 +8,13 @@ {{/if}} {{#if isItemEffect}} {{formGroup fields.transfer value=source.transfer rootId=rootId label=legacyTransfer.label hint=legacyTransfer.hint}} + + {{!-- Attachment-only flag for item effects --}} +
+ + +

{{localize "DAGGERHEART.Effect.AttachmentOnly.Hint"}}

+
{{/if}} {{formGroup fields.statuses value=source.statuses options=statuses rootId=rootId classes="statuses"}}