From 8a0c66fd44ea985a3b8e800530744af697779d6c Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 23 Jan 2025 22:33:13 +0000 Subject: [PATCH] implement inraidHelper --- Libraries/Core/Helpers/InRaidHelper.cs | 198 +++++++++++++++++++++++-- 1 file changed, 189 insertions(+), 9 deletions(-) diff --git a/Libraries/Core/Helpers/InRaidHelper.cs b/Libraries/Core/Helpers/InRaidHelper.cs index 61db6c9c..b4c1153a 100644 --- a/Libraries/Core/Helpers/InRaidHelper.cs +++ b/Libraries/Core/Helpers/InRaidHelper.cs @@ -1,19 +1,37 @@ using SptCommon.Annotations; using Core.Models.Eft.Common; using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Config; +using Core.Servers; +using Core.Services; +using Core.Utils.Cloners; +using SptCommon.Extensions; namespace Core.Helpers; [Injectable] -public class InRaidHelper +public class InRaidHelper( + InventoryHelper _inventoryHelper, + ItemHelper _itemHelper, + ConfigServer _configServer, + ICloner _cloner, + DatabaseService _databaseService +) { + protected LostOnDeathConfig _lostOnDeathConfig = _configServer.GetConfig(); + protected InRaidConfig _inRaidConfig = _configServer.GetConfig(); + protected List _pocketSlots = ["pocket1", "pocket2", "pocket3", "pocket4"]; + /// /// Deprecated. Reset the skill points earned in a raid to 0, ready for next raid. /// /// Profile to update protected void ResetSkillPointsEarnedDuringRaid(PmcData profile) { - throw new NotImplementedException(); + foreach (var skill in profile.Skills.Common) + { + skill.PointsEarnedDuringSession = 0.0; + } } /// @@ -34,7 +52,42 @@ public class InRaidHelper bool isSurvived, bool isTransfer) { - throw new NotImplementedException(); + // Store insurance (as removeItem() removes insured items) + var insured = _cloner.Clone(serverProfile.InsuredItems); + + // Remove equipment and loot items stored on player from server profile in preparation for data from client being added + _inventoryHelper.RemoveItem(serverProfile, serverProfile.Inventory.Equipment, sessionID); + + // Remove quest items stored on player from server profile in preparation for data from client being added + _inventoryHelper.RemoveItem(serverProfile, serverProfile.Inventory.QuestRaidItems, sessionID); + + // Get all items that have a parent of `serverProfile.Inventory.equipment` (All items player had on them at end of raid) + var postRaidInventoryItems = _itemHelper.FindAndReturnChildrenAsItems( + postRaidProfile.Inventory.Items, + postRaidProfile.Inventory.Equipment + ); + + // Get all items that have a parent of `serverProfile.Inventory.questRaidItems` (Quest items player had on them at end of raid) + var postRaidQuestItems = _itemHelper.FindAndReturnChildrenAsItems( + postRaidProfile.Inventory.Items, + postRaidProfile.Inventory.QuestRaidItems + ); + + // Handle Removing of FIR status if player did not survive + not transferring + // Do after above filtering code to reduce work done + if (!isSurvived && !isTransfer && !_inRaidConfig.AlwaysKeepFoundInRaidOnRaidEnd) + { + RemoveFiRStatusFromCertainItems(postRaidProfile.Inventory.Items); + } + + // Add items from client profile into server profile + AddItemsToInventory(postRaidInventoryItems, serverProfile.Inventory.Items); + + // Add quest items from client profile into server profile + AddItemsToInventory(postRaidQuestItems, serverProfile.Inventory.Items); + + serverProfile.Inventory.FastPanel = postRaidProfile.Inventory.FastPanel; // Quick access items bar + serverProfile.InsuredItems = insured; } /// @@ -43,7 +96,30 @@ public class InRaidHelper /// Items to process protected void RemoveFiRStatusFromCertainItems(List items) { - throw new NotImplementedException(); + var dbItems = _databaseService.GetItems(); + + var itemsToRemovePropertyFrom = items.Where( + item => + { + // Has upd object + upd.SpawnedInSession property + not a quest item + return ( + (item.Upd?.SpawnedInSession ?? false) && + !(dbItems[item.Template].Properties.QuestItem ?? false) && + !( + _inRaidConfig.KeepFiRSecureContainerOnDeath && + _itemHelper.ItemIsInsideContainer(item, "SecuredContainer", items) + ) + ); + } + ); + + foreach (var item in itemsToRemovePropertyFrom) + { + if (item.Upd is not null) + { + item.Upd.SpawnedInSession = false; + } + } } /// @@ -53,7 +129,24 @@ public class InRaidHelper /// Location to add items to protected void AddItemsToInventory(List itemsToAdd, List serverInventoryItems) { - throw new NotImplementedException(); + foreach (var itemToAdd in itemsToAdd) + { + // Try to find index of item to determine if we should add or replace + var existingItemIndex = serverInventoryItems.FindIndex( + inventoryItem => inventoryItem.Id == itemToAdd.Id + ); + if (existingItemIndex == -1) + { + // Not found, add + serverInventoryItems.Add(itemToAdd); + } + else + { + // Replace item with one from client + serverInventoryItems.RemoveAt(existingItemIndex); + serverInventoryItems.Add(itemToAdd); + } + } } /// @@ -64,7 +157,16 @@ public class InRaidHelper /// Session id public void DeleteInventory(PmcData pmcData, string sessionId) { - throw new NotImplementedException(); + // Get inventory item ids to remove from players profile + var itemIdsToDeleteFromProfile = GetInventoryItemsLostOnDeath(pmcData).Select(item => item.Id); + foreach (var itemIdToDelete in itemIdsToDeleteFromProfile) + { + // Items inside containers are handled as part of function + _inventoryHelper.RemoveItem(pmcData, itemIdToDelete, sessionId); + } + + // Remove contents of fast panel + pmcData.Inventory.FastPanel = new Dictionary(); } /// @@ -78,7 +180,27 @@ public class InRaidHelper PmcData pmcData, string secureContainerSlotId) { - throw new NotImplementedException(); + if (!pmcData.Inventory.Items.Any(item => item.SlotId == secureContainerSlotId)) + { + return; + } + + List itemsInsideContainer = []; + foreach (var inventoryItem in pmcData.Inventory.Items.Where(item => item.Upd is not null && item.SlotId != "hideout")) + { + if (_itemHelper.ItemIsInsideContainer(inventoryItem, secureContainerSlotId, pmcData.Inventory.Items)) + { + itemsInsideContainer.Add(inventoryItem); + } + } + + foreach (var item in itemsInsideContainer) + { + if (item.Upd.SpawnedInSession ?? false) + { + item.Upd.SpawnedInSession = false; + } + } } /// @@ -88,7 +210,32 @@ public class InRaidHelper /// List of items lost on death protected List GetInventoryItemsLostOnDeath(PmcData pmcProfile) { - throw new NotImplementedException(); + var inventoryItems = pmcProfile.Inventory.Items ?? []; + var equipmentRootId = pmcProfile?.Inventory?.Equipment; + var questRaidItemContainerId = pmcProfile?.Inventory?.QuestRaidItems; + + return inventoryItems.Where(item => { + // Keep items flagged as kept after death + if (IsItemKeptAfterDeath(pmcProfile, item)) { + return false; + } + + // Remove normal items or quest raid items + if (item.ParentId == equipmentRootId || item.ParentId == questRaidItemContainerId) { + return true; + } + + // Pocket items are lost on death + // Ensure we dont pick up pocket items from manniquins + if ( + item.SlotId.StartsWith("pocket") && + _inventoryHelper.DoesItemHaveRootId(pmcProfile, item, pmcProfile.Inventory.Equipment) + ) { + return true; + } + + return false; + }).ToList(); } /// @@ -99,6 +246,39 @@ public class InRaidHelper /// true if item is kept after death protected bool IsItemKeptAfterDeath(PmcData pmcData, Item itemToCheck) { - throw new NotImplementedException(); + // Base inventory items are always kept + if (itemToCheck.ParentId is null) { + return true; + } + + // Is item equipped on player + if (itemToCheck.ParentId == pmcData.Inventory.Equipment) { + // Check slot id against config, true = delete, false = keep, undefined = delete + bool discard = _lostOnDeathConfig.Equipment.GetByJsonProp(itemToCheck.SlotId); + if (discard) { + // Lost on death + return false; + } + + return true; + } + + // Should we keep items in pockets on death + if (!_lostOnDeathConfig.Equipment.PocketItems && _pocketSlots.Contains(itemToCheck.SlotId)) { + return true; + } + + // Is quest item + quest item not lost on death + if (itemToCheck.ParentId == pmcData.Inventory.QuestRaidItems && !_lostOnDeathConfig.QuestItems) { + return true; + } + + // special slots are always kept after death + if ((itemToCheck.SlotId?.Contains("SpecialSlot") ?? false) && _lostOnDeathConfig.SpecialSlotItems) { + return true; + } + + // All other cases item is lost + return false; } }