diff --git a/project/src/helpers/InRaidHelper.ts b/project/src/helpers/InRaidHelper.ts index 5ddf1875..659e02a7 100644 --- a/project/src/helpers/InRaidHelper.ts +++ b/project/src/helpers/InRaidHelper.ts @@ -61,7 +61,7 @@ export class InRaidHelper { isSurvived: boolean, isTransfer: boolean, ): void { - // Store insurance (as removeItem() removes insurance also) + // Store insurance (as removeItem() removes insured items) const insured = this.cloner.clone(serverProfile.InsuredItems); // Remove possible equipped items from before the raid @@ -69,46 +69,50 @@ export class InRaidHelper { this.inventoryHelper.removeItem(serverProfile, serverProfile.Inventory.questRaidItems, sessionID); this.inventoryHelper.removeItem(serverProfile, serverProfile.Inventory.sortingTable, sessionID); - // Handle Removing of FIR status if did not survive. + // Get all items that have a parent of `serverProfile.Inventory.equipment` (All items player had on them at end of raid) + const postRaidInventoryItems = this.itemHelper.findAndReturnChildrenAsItems( + postRaidProfile.Inventory.items, + postRaidProfile.Inventory.equipment, + ); + + // Handle Removing of FIR status if player did not survive + not transferring + // Do after above filtering code to reduce work done if (!isSurvived && !isTransfer && !this.inRaidConfig.alwaysKeepFoundInRaidonRaidEnd) { - this.removeSpawnedInSessionPropertyFromItems(postRaidProfile); + const dbItems = this.databaseService.getItems(); + + const itemsToRemovePropertyFrom = postRaidProfile.Inventory.items.filter((item) => { + // Has upd object + upd.SpawnedInSession property + not a quest item + return ( + item.upd?.SpawnedInSession && + !dbItems[item._tpl]._props.QuestItem && + !( + this.inRaidConfig.keepFiRSecureContainerOnDeath && + this.itemHelper.itemIsInsideContainer(item, "SecuredContainer", postRaidProfile.Inventory.items) + ) + ); + }); + + this.itemHelper.removeSpawnedInSessionPropertyFromItems(itemsToRemovePropertyFrom); + } + + for (const item of postRaidInventoryItems) { + // Try to find index of item to determine if we should add or replace + const existingItemIndex = serverProfile.Inventory.items.findIndex( + (inventoryItem) => inventoryItem._id === item._id, + ); + if (existingItemIndex === -1) { + // Not found, add + serverProfile.Inventory.items.push(item); + } else { + // Replace item with one from client + postRaidProfile.Inventory.items.splice(existingItemIndex, 1, item); + } } - // Add the new items - serverProfile.Inventory.items = [...postRaidProfile.Inventory.items, ...serverProfile.Inventory.items]; serverProfile.Inventory.fastPanel = postRaidProfile.Inventory.fastPanel; // Quick access items bar serverProfile.InsuredItems = insured; } - /** - * Iterate over inventory items and remove the property that defines an item as Found in Raid - * Only removes property if item had FiR when entering raid - * @param postRaidProfile profile to update items for - * @returns Updated profile with SpawnedInSession removed - */ - public removeSpawnedInSessionPropertyFromItems(postRaidProfile: IPmcData): IPmcData { - const dbItems = this.databaseService.getItems(); - const itemsToRemovePropertyFrom = postRaidProfile.Inventory.items.filter((item) => { - // Has upd object + upd.SpawnedInSession property + not a quest item - return ( - "upd" in item && - "SpawnedInSession" in item.upd && - !dbItems[item._tpl]._props.QuestItem && - !( - this.inRaidConfig.keepFiRSecureContainerOnDeath && - this.itemHelper.itemIsInsideContainer(item, "SecuredContainer", postRaidProfile.Inventory.items) - ) - ); - }); - - for (const item of itemsToRemovePropertyFrom) { - // biome-ignore lint/performance/noDelete: - delete item.upd.SpawnedInSession; - } - - return postRaidProfile; - } - /** * Clear PMC inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/project/src/helpers/InventoryHelper.ts b/project/src/helpers/InventoryHelper.ts index 329079e3..e8c5fb7f 100644 --- a/project/src/helpers/InventoryHelper.ts +++ b/project/src/helpers/InventoryHelper.ts @@ -450,33 +450,43 @@ export class InventoryHelper { } // Get children of item, they get deleted too - const itemToRemoveWithChildren = this.itemHelper.findAndReturnChildrenByItems(profile.Inventory.items, itemId); + const itemAndChildrenToRemove = this.itemHelper.findAndReturnChildrenAsItems(profile.Inventory.items, itemId); + if (itemAndChildrenToRemove.length === 0) { + this.logger.debug( + this.localisationService.getText("inventory-unable_to_remove_item_id_not_found", { + childId: itemId, + profileId: profile._id, + }), + ); + + return; + } const inventoryItems = profile.Inventory.items; const insuredItems = profile.InsuredItems; - // We have output object, inform client of item deletion + // We have output object, inform client of root item deletion, not children if (output) { output.profileChanges[sessionID].items.del.push({ _id: itemId }); } - for (const childId of itemToRemoveWithChildren) { + for (const item of itemAndChildrenToRemove) { // We expect that each inventory item and each insured item has unique "_id", respective "itemId". // Therefore we want to use a NON-Greedy function and escape the iteration as soon as we find requested item. - const inventoryIndex = inventoryItems.findIndex((item) => item._id === childId); + const inventoryIndex = inventoryItems.findIndex((inventoryItem) => inventoryItem._id === item._id); if (inventoryIndex !== -1) { inventoryItems.splice(inventoryIndex, 1); } else { this.logger.warning( this.localisationService.getText("inventory-unable_to_remove_item_id_not_found", { - childId: childId, + childId: item._id, profileId: profile._id, }), ); } - const insuredIndex = insuredItems.findIndex((item) => item.itemId === childId); - if (insuredIndex !== -1) { - insuredItems.splice(insuredIndex, 1); + const insuredItemIndex = insuredItems.findIndex((insuredItem) => insuredItem.itemId === item._id); + if (insuredItemIndex !== -1) { + insuredItems.splice(insuredItemIndex, 1); } } } diff --git a/project/src/helpers/ItemHelper.ts b/project/src/helpers/ItemHelper.ts index 528b3ee6..b9f82f37 100644 --- a/project/src/helpers/ItemHelper.ts +++ b/project/src/helpers/ItemHelper.ts @@ -1794,6 +1794,16 @@ export class ItemHelper { currentItem = this.getItem(tpl)[1]; } } + + /** + * Remove FiR status from passed in items + * @param items Items to update FiR status of + */ + public removeSpawnedInSessionPropertyFromItems(items: IItem[]): void { + for (const item of items) { + delete item.upd.SpawnedInSession; + } + } } namespace ItemHelper {