refactor code for review comments

This commit is contained in:
psitacus 2025-07-12 02:33:13 -06:00
parent 001abcadf4
commit 5065a609ac
6 changed files with 128 additions and 438 deletions

View file

@ -8,26 +8,60 @@ export default class AttachableItem extends BaseDataItem {
attached: new fields.ArrayField(new fields.DocumentUUIDField({ type: "Item", nullable: true }))
};
}
async copyAttachmentEffectsToActor({ parentItem, attachedItem, attachedUuid, parentType }) {
const actor = parentItem.parent;
if (!actor || !attachedItem.effects.size > 0 || !parentItem.system.equipped) {
async _preUpdate(changes, options, user) {
const allowed = await super._preUpdate(changes, options, user);
if (allowed === false) return false;
// Handle equipped status changes for attachment effects
if (changes.system?.equipped !== undefined && changes.system.equipped !== this.equipped) {
await this.#handleAttachmentEffectsOnEquipChange(changes.system.equipped);
}
}
async #handleAttachmentEffectsOnEquipChange(newEquippedStatus) {
const actor = this.parent.parent?.type === 'character' ? this.parent.parent : this.parent.parent?.parent;
const parentType = this.parent.type;
if (!actor || !this.attached?.length) {
return;
}
if (newEquippedStatus) {
// Item is being equipped - add attachment effects
for (const attachedUuid of this.attached) {
const attachedItem = await fromUuid(attachedUuid);
if (attachedItem && attachedItem.effects.size > 0) {
await this.#copyAttachmentEffectsToActor({
attachedItem,
attachedUuid,
parentType
});
}
}
} else {
// Item is being unequipped - remove attachment effects
await this.#removeAllAttachmentEffects(parentType);
}
}
async #copyAttachmentEffectsToActor({ attachedItem, attachedUuid, parentType }) {
const actor = this.parent.parent;
if (!actor || !attachedItem.effects.size > 0 || !this.equipped) {
return [];
}
const effectsToCreate = [];
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 = `${parentItem.uuid}:${attachedUuid}`;
// Set up attachment source metadata with the appropriate property name
effectData.origin = `${this.parent.uuid}:${attachedUuid}`;
const attachmentSource = {
itemUuid: attachedUuid,
originalEffectId: effect.id
};
attachmentSource[`${parentType}Uuid`] = parentItem.uuid;
attachmentSource[`${parentType}Uuid`] = this.parent.uuid;
effectData.flags = {
...effectData.flags,
[CONFIG.DH.id]: {
@ -41,56 +75,78 @@ export default class AttachableItem extends BaseDataItem {
if (effectsToCreate.length > 0) {
return await actor.createEmbeddedDocuments('ActiveEffect', effectsToCreate);
}
return [];
}
async handleAttachmentEffectsOnEquipChange({ parentItem, newEquippedStatus, parentType }) {
// Try to get the actor - it might be parentItem.parent instead of parentItem.parent.parent
const actor = parentItem.parent?.type === 'character' ? parentItem.parent : parentItem.parent?.parent;
if (!actor || !parentItem.system.attached?.length) {
return;
}
async #removeAllAttachmentEffects(parentType) {
const actor = this.parent.parent;
if (!actor) return;
if (newEquippedStatus) {
// Item is being equipped - add attachment effects
for (const attachedUuid of parentItem.system.attached) {
const attachedItem = await fromUuid(attachedUuid);
if (attachedItem && attachedItem.effects.size > 0) {
this.copyAttachmentEffectsToActor({
parentItem,
attachedItem,
attachedUuid,
parentType
});
}
}
} else {
// Item is being unequipped - remove attachment effects
const parentUuidProperty = `${parentType}Uuid`;
const effectsToRemove = actor.effects.filter(effect => {
const attachmentSource = effect.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.itemAttachmentSource);
return attachmentSource && attachmentSource[parentUuidProperty] === parentItem.uuid;
});
const parentUuidProperty = `${parentType}Uuid`;
const effectsToRemove = actor.effects.filter(effect => {
const attachmentSource = effect.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.itemAttachmentSource);
return attachmentSource && attachmentSource[parentUuidProperty] === this.parent.uuid;
});
if (effectsToRemove.length > 0) {
await actor.deleteEmbeddedDocuments('ActiveEffect', effectsToRemove.map(e => e.id));
}
if (effectsToRemove.length > 0) {
await actor.deleteEmbeddedDocuments('ActiveEffect', effectsToRemove.map(e => e.id));
}
}
async _preUpdate(changes, options, user) {
const allowed = await super._preUpdate(changes, options, user);
if (allowed === false) return false;
/**
* Public method for adding an attachment
*/
async addAttachment(droppedItem) {
const newUUID = droppedItem.uuid;
// Handle equipped status changes for attachment effects
if (changes.system?.equipped !== undefined && changes.system.equipped !== this.equipped) {
await this.handleAttachmentEffectsOnEquipChange({
parentItem: this.parent,
newEquippedStatus: changes.system.equipped,
if (this.attached.includes(newUUID)) {
ui.notifications.warn(`${droppedItem.name} is already attached to this ${this.parent.type}.`);
return;
}
const updatedAttached = [...this.attached, newUUID];
await this.parent.update({
'system.attached': updatedAttached
});
// Copy effects if equipped
if (this.equipped && droppedItem.effects.size > 0) {
await this.#copyAttachmentEffectsToActor({
attachedItem: droppedItem,
attachedUuid: newUUID,
parentType: this.parent.type
});
}
}
/**
* Public method for removing an attachment
*/
async removeAttachment(attachedUuid) {
await this.parent.update({
'system.attached': this.attached.filter(uuid => uuid !== attachedUuid)
});
// Remove effects
await this.#removeAttachmentEffects(attachedUuid);
}
async #removeAttachmentEffects(attachedUuid) {
const actor = this.parent.parent;
if (!actor) return;
const parentType = this.parent.type;
const parentUuidProperty = `${parentType}Uuid`;
const effectsToRemove = actor.effects.filter(effect => {
const attachmentSource = effect.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.itemAttachmentSource);
return attachmentSource &&
attachmentSource[parentUuidProperty] === this.parent.uuid &&
attachmentSource.itemUuid === attachedUuid;
});
if (effectsToRemove.length > 0) {
await actor.deleteEmbeddedDocuments('ActiveEffect', effectsToRemove.map(e => e.id));
}
}
}

View file

@ -1,7 +1,6 @@
import AttachableItem from './attachableItem.mjs';
import { actionsTypes } from '../action/_module.mjs';
import ActionField from '../fields/actionField.mjs';
import { handleAttachmentEffectsOnEquipChange } from '../../helpers/attachmentHelper.mjs';
export default class DHWeapon extends AttachableItem {
/** @inheritDoc */
@ -39,7 +38,7 @@ export default class DHWeapon extends AttachableItem {
actionIds: new fields.ArrayField(new fields.StringField({ required: true }))
})
),
attack: new ActionField({
attack: new ActionField({
initial: {
name: 'Attack',
img: 'icons/skills/melee/blood-slash-foam-red.webp',