From 71ee9a006573b3a8eb2ea93de6da29aef59d8806 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Tue, 2 Dec 2025 03:40:28 -0500 Subject: [PATCH] Add ability to sort inventories in player and party sheets --- .../applications/sheets/actors/character.mjs | 48 +------ module/applications/sheets/actors/party.mjs | 34 +---- .../sheets/api/application-mixin.mjs | 6 +- module/applications/sheets/api/base-actor.mjs | 125 ++++++++++-------- .../sheets/actors/character/inventory.hbs | 8 +- templates/sheets/actors/party/inventory.hbs | 8 +- 6 files changed, 86 insertions(+), 143 deletions(-) diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 7da49eb7..ea875b2a 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -214,34 +214,8 @@ export default class CharacterSheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; - context.inventory = { currencies: {} }; - const { title, ...currencies } = game.settings.get( - CONFIG.DH.id, - CONFIG.DH.SETTINGS.gameSettings.Homebrew - ).currency; - for (let key in currencies) { - context.inventory.currencies[key] = { - ...currencies[key], - field: context.systemFields.gold.fields[key], - value: context.source.system.gold[key] - }; - } - // context.inventory = { - // currency: { - // title: game.i18n.localize('DAGGERHEART.CONFIG.Gold.title'), - // coins: game.i18n.localize('DAGGERHEART.CONFIG.Gold.coins'), - // handfuls: game.i18n.localize('DAGGERHEART.CONFIG.Gold.handfuls'), - // bags: game.i18n.localize('DAGGERHEART.CONFIG.Gold.bags'), - // chests: game.i18n.localize('DAGGERHEART.CONFIG.Gold.chests') - // } - // }; - context.beastformActive = this.document.effects.find(x => x.type === 'beastform'); - // if (context.inventory.length === 0) { - // context.inventory = Array(1).fill(Array(5).fill([])); - // } - return context; } @@ -918,20 +892,11 @@ export default class CharacterSheet extends DHBaseActorSheet { super._onDragStart(event); } - async _onDrop(event) { - // Prevent event bubbling to avoid duplicate handling - event.preventDefault(); - event.stopPropagation(); - const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); + async _onDropItem(event, item) { + if (this.document.uuid === item.parent?.uuid) { + return this._onSortItem(event, item); + } - const { cancel } = await super._onDrop(event); - if (cancel) return; - - this._onDropItem(event, data); - } - - async _onDropItem(event, data) { - const item = await Item.implementation.fromDropData(data); const itemData = item.toObject(); if (item.type === 'domainCard' && !this.document.system.loadoutSlot.available) { @@ -963,10 +928,7 @@ export default class CharacterSheet extends DHBaseActorSheet { } } - if (this.document.uuid === item.parent?.uuid) return this._onSortItem(event, itemData); - const createdItem = await this._onDropItemCreate(itemData); - - return createdItem; + return await this._onDropItemCreate(itemData); } async _onDropItemCreate(itemData, event) { diff --git a/module/applications/sheets/actors/party.mjs b/module/applications/sheets/actors/party.mjs index 8a0b756d..2dfaeb1d 100644 --- a/module/applications/sheets/actors/party.mjs +++ b/module/applications/sheets/actors/party.mjs @@ -93,25 +93,6 @@ export default class Party extends DHBaseActorSheet { /* Prepare Context */ /* -------------------------------------------- */ - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - - context.inventory = { currencies: {} }; - const { title, ...currencies } = game.settings.get( - CONFIG.DH.id, - CONFIG.DH.SETTINGS.gameSettings.Homebrew - ).currency; - for (let key in currencies) { - context.inventory.currencies[key] = { - ...currencies[key], - field: context.systemFields.gold.fields[key], - value: context.source.system.gold[key] - }; - } - - return context; - } - async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); switch (partId) { @@ -451,17 +432,8 @@ export default class Party extends DHBaseActorSheet { super._onDragStart(event); } - async _onDrop(event) { - // Prevent event bubbling to avoid duplicate handling - event.preventDefault(); - event.stopPropagation(); + async _onDropActor(event, document) { const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - - const { cancel } = await super._onDrop(event); - if (cancel) return; - - const document = await foundry.utils.fromUuid(data.uuid); - if (document instanceof DhpActor && Party.ALLOWED_ACTOR_TYPES.includes(document.type)) { const currentMembers = this.document.system.partyMembers.map(x => x.uuid); if (currentMembers.includes(data.uuid)) { @@ -469,11 +441,11 @@ export default class Party extends DHBaseActorSheet { } await this.document.update({ 'system.partyMembers': [...currentMembers, document.uuid] }); - } else if (document instanceof DHItem) { - this.document.createEmbeddedDocuments('Item', [document.toObject()]); } else { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.onlyCharactersInPartySheet')); } + + return null; } static async #deletePartyMember(event, target) { diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index b229d249..761f509e 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -322,10 +322,10 @@ export default function DHApplicationMixin(Base) { _onDrop(event) { event.stopPropagation(); const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - if (data.fromInternal === this.document.uuid) return; - - if (data.type === 'ActiveEffect') { + if (data.type === 'ActiveEffect' && data.fromInternal !== this.document.uuid) { this.document.createEmbeddedDocuments('ActiveEffect', [data.data]); + } else { + return super._onDrop(event); } } diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 348ffa99..14cd1696 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -69,6 +69,28 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { context.showAttribution = !game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance) .hideAttribution; + // Prepare inventory data + if (["party", "character"].includes(this.document.type)) { + context.inventory = { + currencies: {}, + weapons: this.document.itemTypes.weapon.sort((a, b) => a.sort - b.sort), + armor: this.document.itemTypes.armor.sort((a, b) => a.sort - b.sort), + consumables: this.document.itemTypes.consumable.sort((a, b) => a.sort - b.sort), + loot: this.document.itemTypes.loot.sort((a, b) => a.sort - b.sort), + }; + const { title, ...currencies } = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.Homebrew + ).currency; + for (const key in currencies) { + context.inventory.currencies[key] = { + ...currencies[key], + field: context.systemFields.gold.fields[key], + value: context.source.system.gold[key] + }; + } + } + return context; } @@ -218,68 +240,55 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { /* Application Drag/Drop */ /* -------------------------------------------- */ - async _onDrop(event) { + async _onDropItem(event, item) { const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - if (data.originActor === this.document.uuid) return { cancel: true }; - - /* Handling transfer of inventoryItems */ - let cancel = false; const physicalActorTypes = ['character', 'party']; - if (physicalActorTypes.includes(this.document.type)) { - const originActor = data.originActor ? await foundry.utils.fromUuid(data.originActor) : null; - if (data.originId && originActor && physicalActorTypes.includes(originActor.type)) { - const dropDocument = await foundry.utils.fromUuid(data.uuid); - - if (dropDocument.system.metadata.isInventoryItem) { - cancel = true; - if (dropDocument.system.metadata.isQuantifiable) { - const actorItem = originActor.items.get(data.originId); - const quantityTransfered = - actorItem.system.quantity === 1 - ? 1 - : await game.system.api.applications.dialogs.ItemTransferDialog.configure(dropDocument); - - if (quantityTransfered) { - if (quantityTransfered === actorItem.system.quantity) { - await originActor.deleteEmbeddedDocuments('Item', [data.originId]); - } else { - cancel = true; - await actorItem.update({ - 'system.quantity': actorItem.system.quantity - quantityTransfered - }); - } - - const existingItem = this.document.items.find(x => itemIsIdentical(x, dropDocument)); - if (existingItem) { - cancel = true; - await existingItem.update({ - 'system.quantity': existingItem.system.quantity + quantityTransfered - }); - } else { - const createData = dropDocument.toObject(); - await this.document.createEmbeddedDocuments('Item', [ - { - ...createData, - system: { - ...createData.system, - quantity: quantityTransfered - } - } - ]); - } - } else { - cancel = true; - } - } else { - await originActor.deleteEmbeddedDocuments('Item', [data.originId]); - const createData = dropDocument.toObject(); - await this.document.createEmbeddedDocuments('Item', [createData]); - } - } - } + const originActor = item.actor; + if (item.actor?.uuid === this.document.uuid || !originActor || !physicalActorTypes.includes(this.document.type)) { + return super._onDropItem(event, item); } - return { cancel }; + /* Handling transfer of inventoryItems */ + if (item.system.metadata.isInventoryItem) { + if (item.system.metadata.isQuantifiable) { + const actorItem = originActor.items.get(data.originId); + const quantityTransfered = + actorItem.system.quantity === 1 + ? 1 + : await game.system.api.applications.dialogs.ItemTransferDialog.configure(item); + + if (quantityTransfered) { + if (quantityTransfered === actorItem.system.quantity) { + await originActor.deleteEmbeddedDocuments('Item', [data.originId]); + } else { + await actorItem.update({ + 'system.quantity': actorItem.system.quantity - quantityTransfered + }); + } + + const existingItem = this.document.items.find(x => itemIsIdentical(x, item)); + if (existingItem) { + await existingItem.update({ + 'system.quantity': existingItem.system.quantity + quantityTransfered + }); + } else { + const createData = item.toObject(); + await this.document.createEmbeddedDocuments('Item', [ + { + ...createData, + system: { + ...createData.system, + quantity: quantityTransfered + } + } + ]); + } + } + } else { + await originActor.deleteEmbeddedDocuments('Item', [data.originId]); + await this.document.createEmbeddedDocuments('Item', [item.toObject()]); + } + } } /** diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index ff595737..52de7f3c 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -27,7 +27,7 @@ {{> 'daggerheart.inventory-items' title='TYPES.Item.weapon' type='weapon' - collection=document.itemTypes.weapon + collection=@root.inventory.weapons isGlassy=true canCreate=true hideResources=true @@ -35,7 +35,7 @@ {{> 'daggerheart.inventory-items' title='TYPES.Item.armor' type='armor' - collection=document.itemTypes.armor + collection=@root.inventory.armor isGlassy=true canCreate=true hideResources=true @@ -43,14 +43,14 @@ {{> 'daggerheart.inventory-items' title='TYPES.Item.consumable' type='consumable' - collection=document.itemTypes.consumable + collection=@root.inventory.consumables isGlassy=true canCreate=true }} {{> 'daggerheart.inventory-items' title='TYPES.Item.loot' type='loot' - collection=document.itemTypes.loot + collection=@root.inventory.loot isGlassy=true canCreate=true showActions=true diff --git a/templates/sheets/actors/party/inventory.hbs b/templates/sheets/actors/party/inventory.hbs index 9a299536..1596d47e 100644 --- a/templates/sheets/actors/party/inventory.hbs +++ b/templates/sheets/actors/party/inventory.hbs @@ -52,7 +52,7 @@ title='TYPES.Item.weapon' type='weapon' actorType='party' - collection=document.itemTypes.weapon + collection=@root.inventory.weapons isGlassy=true canCreate=true hideResources=true @@ -62,7 +62,7 @@ title='TYPES.Item.armor' type='armor' actorType='party' - collection=document.itemTypes.armor + collection=@root.inventory.armor isGlassy=true canCreate=true hideResources=true @@ -72,7 +72,7 @@ title='TYPES.Item.consumable' type='consumable' actorType='party' - collection=document.itemTypes.consumable + collection=@root.inventory.consumables isGlassy=true canCreate=true hideContextMenu=true @@ -81,7 +81,7 @@ title='TYPES.Item.loot' type='loot' actorType='party' - collection=document.itemTypes.loot + collection=@root.inventory.loot isGlassy=true canCreate=true hideContextMenu=true