diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs index a935e9ed..492af49f 100644 --- a/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs +++ b/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs @@ -1,5 +1,6 @@ using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.DI; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; @@ -114,7 +115,7 @@ public class BtrDeliveryCallbacks( var rootItemParentId = _hashUtil.Generate(); // Update the delivery items to have the new root parent ID for root/orphaned items - package.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, package.Items); + package.Items = package.Items.AdoptOrphanedItems(rootItemParentId); _btrDeliveryService.SendBTRDelivery(sessionId, package.Items); diff --git a/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs b/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs index 7b91e529..97c8c744 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs @@ -305,7 +305,7 @@ public class GameController( /// Player profile protected void WarnOnActiveBotReloadSkill(PmcData pmcProfile) { - var botReloadSkill = _profileHelper.GetSkillFromProfile(pmcProfile, SkillTypes.BotReload); + var botReloadSkill = pmcProfile.GetSkillFromProfile(SkillTypes.BotReload); if (botReloadSkill?.Progress > 0) { _logger.Warning( diff --git a/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs b/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs index 4ab43697..c892a0a9 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; @@ -123,7 +124,7 @@ public class InsuranceController( var rootItemParentId = _hashUtil.Generate(); // Update the insured items to have the new root parent ID for root/orphaned items - insured.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, insured.Items); + insured.Items = insured.Items.AdoptOrphanedItems(rootItemParentId); var simulateItemsBeingTaken = _insuranceConfig.SimulateItemsBeingTaken; if (simulateItemsBeingTaken) @@ -135,7 +136,7 @@ public class InsuranceController( RemoveItemsFromInsurance(insured, itemsToDelete); // There's a chance we've orphaned weapon attachments, so adopt any orphaned items again - insured.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, insured.Items); + insured.Items = insured.Items.AdoptOrphanedItems(rootItemParentId); } SendMail(sessionId, insured); @@ -192,7 +193,7 @@ public class InsuranceController( // Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items // and each of their attachments. For example, a gun mapped to each of its attachments. - var itemsMap = _itemHelper.GenerateItemsMap(insured.Items); + var itemsMap = insured.Items.GenerateItemsMap(); var parentAttachmentsMap = PopulateParentAttachmentsMap( rootItemParentId, insured, diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs index 0c3f737e..6c9136d0 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Generators.RepeatableQuestGeneration; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; @@ -222,8 +223,7 @@ public class RepeatableQuestController( var traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId]; traderOfReplacedQuest.Standing -= previousChangeRequirement.ChangeStandingCost; - var charismaBonus = - _profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Charisma)?.Progress ?? 0; + var charismaBonus = pmcData.GetSkillFromProfile(SkillTypes.Charisma)?.Progress ?? 0; foreach (var cost in previousChangeRequirement.ChangeCost) { // Not free, Charge player + apply charisma bonus to cost of replacement diff --git a/Libraries/SPTarkov.Server.Core/Extensions/ItemExtensions.cs b/Libraries/SPTarkov.Server.Core/Extensions/ItemExtensions.cs new file mode 100644 index 00000000..7be8b784 --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Extensions/ItemExtensions.cs @@ -0,0 +1,195 @@ +using SPTarkov.Server.Core.Models.Eft.Common.Tables; + +namespace SPTarkov.Server.Core.Extensions +{ + public static class ItemExtensions + { + /// + /// This method will compare two items and see if they are equivalent + /// This method will NOT compare IDs on the items + /// + /// first item to compare + /// second item to compare + /// Upd properties to compare between the items + /// true if they are the same + public static bool IsSameItem( + this Item item1, + Item item2, + HashSet? compareUpdProperties = null + ) + { + // Different tpl == different item + if (item1.Template != item2.Template) + { + return false; + } + + // Both lack upd object + same tpl = same + if (item1.Upd is null && item2.Upd is null) + { + return true; + } + + // item1 lacks upd, item2 has one + if (item1.Upd is null && item2.Upd is not null) + { + return false; + } + + // item1 has upd, item2 lacks one + if (item1.Upd is not null && item2.Upd is null) + { + return false; + } + + // key = Upd property Type as string, value = comparison function that returns bool + var comparers = new Dictionary> + { + { "Key", (upd1, upd2) => upd1.Key?.NumberOfUsages == upd2.Key?.NumberOfUsages }, + { + "Buff", + (upd1, upd2) => + upd1.Buff?.Value == upd2.Buff?.Value + && upd1.Buff?.BuffType == upd2.Buff?.BuffType + }, + { + "CultistAmulet", + (upd1, upd2) => + upd1.CultistAmulet?.NumberOfUsages == upd2.CultistAmulet?.NumberOfUsages + }, + { "Dogtag", (upd1, upd2) => upd1.Dogtag?.ProfileId == upd2.Dogtag?.ProfileId }, + { "FaceShield", (upd1, upd2) => upd1.FaceShield?.Hits == upd2.FaceShield?.Hits }, + { + "Foldable", + (upd1, upd2) => + upd1.Foldable?.Folded.GetValueOrDefault(false) + == upd2.Foldable?.Folded.GetValueOrDefault(false) + }, + { + "FoodDrink", + (upd1, upd2) => upd1.FoodDrink?.HpPercent == upd2.FoodDrink?.HpPercent + }, + { "MedKit", (upd1, upd2) => upd1.MedKit?.HpResource == upd2.MedKit?.HpResource }, + { + "RecodableComponent", + (upd1, upd2) => + upd1.RecodableComponent?.IsEncoded == upd2.RecodableComponent?.IsEncoded + }, + { + "RepairKit", + (upd1, upd2) => upd1.RepairKit?.Resource == upd2.RepairKit?.Resource + }, + { + "Resource", + (upd1, upd2) => upd1.Resource?.UnitsConsumed == upd2.Resource?.UnitsConsumed + }, + }; + + // Choose above keys or passed in keys to compare items with + var valuesToCompare = + compareUpdProperties?.Count > 0 ? compareUpdProperties : comparers.Keys.ToHashSet(); + foreach (var propertyName in valuesToCompare) + { + if (!comparers.TryGetValue(propertyName, out var comparer)) + // Key not found, skip + { + continue; + } + + if (!comparer(item1.Upd, item2.Upd)) + { + return false; + } + } + + return true; + } + + /// + /// Check if item is stored inside a container + /// + /// Item to check is inside of container + /// Name of slot to check item is in e.g. SecuredContainer/Backpack + /// Inventory with child parent items to check + /// True when item is in container + public static bool ItemIsInsideContainer( + this Item itemToCheck, + string desiredContainerSlotId, + IEnumerable items + ) + { + // Get items parent + var parent = items.FirstOrDefault(item => + item.Id.Equals(itemToCheck.ParentId, StringComparison.OrdinalIgnoreCase) + ); + if (parent is null) + // No parent, end of line, not inside container + { + return false; + } + + if (parent.SlotId == desiredContainerSlotId) + { + return true; + } + + return parent.ItemIsInsideContainer(desiredContainerSlotId, items); + } + + /// + /// Get the size of a stack, return 1 if no stack object count property found + /// + /// Item to get stack size of + /// size of stack + public static int GetItemStackSize(this Item item) + { + if (item.Upd?.StackObjectsCount is not null) + { + return (int)item.Upd.StackObjectsCount; + } + + return 1; + } + + /// + /// Create a dictionary from a collection of items, keyed by item id + /// + /// Collection of items + /// Dictionary of items + public static Dictionary GenerateItemsMap(this IEnumerable items) + { + // Convert list to dictionary, keyed by items Id + return items.ToDictionary(item => item.Id); + } + + /// + /// Adopts orphaned items by resetting them as root "hideout" items. Helpful in situations where a parent has been + /// deleted from a group of items and there are children still referencing the missing parent. This method will + /// remove the reference from the children to the parent and set item properties to root values. + /// + /// The ID of the "root" of the container + /// Array of Items that should be adjusted + /// Returns Array of Items that have been adopted + public static List AdoptOrphanedItems(this List items, string rootId) + { + foreach (var item in items) + { + // Check if the item's parent exists. + var parentExists = items.Any(parentItem => + parentItem.Id.Equals(item.ParentId, StringComparison.OrdinalIgnoreCase) + ); + + // If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item by + // setting the parent ID to the PMCs inventory equipment ID, the slot ID to 'hideout', and remove the location. + if (!parentExists && item.ParentId != rootId && item.SlotId != "hideout") + { + item.ParentId = rootId; + item.SlotId = "hideout"; + item.Location = null; + } + } + + return items; + } + } +} diff --git a/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs b/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs index 70e11eb7..97a9daef 100644 --- a/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs +++ b/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs @@ -62,5 +62,16 @@ namespace SPTarkov.Server.Core.Extensions return profile.TaskConditionCounters.Count > 0; } + + /// + /// Get a specific common skill from supplied profile + /// + /// Player profile + /// Skill to look up and return value from + /// Common skill object from desired profile + public static CommonSkill? GetSkillFromProfile(this PmcData profile, SkillTypes skill) + { + return profile?.Skills?.Common?.FirstOrDefault(s => s.Id == skill); + } } } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/HideoutHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/HideoutHelper.cs index eb4c5251..909ce837 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/HideoutHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/HideoutHelper.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Hideout; @@ -1349,10 +1350,7 @@ public class HideoutHelper( /// Consumption bonus protected double? GetHideoutManagementConsumptionBonus(PmcData pmcData) { - var hideoutManagementSkill = _profileHelper.GetSkillFromProfile( - pmcData, - SkillTypes.HideoutManagement - ); + var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement); if (hideoutManagementSkill is null || hideoutManagementSkill.Progress == 0) { return 0; @@ -1384,7 +1382,7 @@ public class HideoutHelper( double valuePerLevel ) { - var profileSkill = _profileHelper.GetSkillFromProfile(pmcData, skill); + var profileSkill = pmcData.GetSkillFromProfile(skill); if (profileSkill is null || profileSkill.Progress == 0) { return 0; @@ -1563,10 +1561,7 @@ public class HideoutHelper( .ToList(); // Calculate bonus percent (apply hideoutManagement bonus) - var hideoutManagementSkill = _profileHelper.GetSkillFromProfile( - pmcData, - SkillTypes.HideoutManagement - ); + var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement); var hideoutManagementSkillBonusPercent = 1 + hideoutManagementSkill.Progress / 10000; // 5100 becomes 0.51, add 1 to it, 1.51 var bonus = GetDogtagCombatSkillBonusPercent(pmcData, activeDogtags) diff --git a/Libraries/SPTarkov.Server.Core/Helpers/InRaidHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/InRaidHelper.cs index d22008c1..1bbdc3a7 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/InRaidHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/InRaidHelper.cs @@ -1,5 +1,6 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Spt.Config; @@ -25,8 +26,9 @@ public class InRaidHelper( "pocket3", "pocket4", ]; - protected InRaidConfig _inRaidConfig = _configServer.GetConfig(); - protected LostOnDeathConfig _lostOnDeathConfig = _configServer.GetConfig(); + protected readonly InRaidConfig _inRaidConfig = _configServer.GetConfig(); + protected readonly LostOnDeathConfig _lostOnDeathConfig = + _configServer.GetConfig(); /// /// Deprecated. Reset the skill points earned in a raid to 0, ready for next raid. @@ -116,7 +118,7 @@ public class InRaidHelper( && !(dbItems[item.Template].Properties.QuestItem ?? false) && !( _inRaidConfig.KeepFiRSecureContainerOnDeath - && _itemHelper.ItemIsInsideContainer(item, "SecuredContainer", items) + && item.ItemIsInsideContainer("SecuredContainer", items) ); }); @@ -201,13 +203,7 @@ public class InRaidHelper( ) ) { - if ( - _itemHelper.ItemIsInsideContainer( - inventoryItem, - secureContainerSlotId, - pmcData.Inventory.Items - ) - ) + if (inventoryItem.ItemIsInsideContainer(secureContainerSlotId, pmcData.Inventory.Items)) { itemsInsideContainer.Add(inventoryItem); } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs index a7a029ac..e3fdacf3 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Inventory; @@ -27,7 +28,6 @@ public class InventoryHelper( HttpResponseUtil _httpResponseUtil, DialogueHelper _dialogueHelper, ContainerHelper _containerHelper, - DatabaseServer _databaseServer, EventOutputHolder _eventOutputHolder, ProfileHelper _profileHelper, ItemHelper _itemHelper, @@ -42,7 +42,8 @@ public class InventoryHelper( BaseClasses.FUNCTIONAL_MOD, BaseClasses.MOD, ]; - protected InventoryConfig _inventoryConfig = _configServer.GetConfig(); + protected readonly InventoryConfig _inventoryConfig = + _configServer.GetConfig(); /// /// Add multiple items to player stash (assuming they all fit) @@ -655,7 +656,7 @@ public class InventoryHelper( var remainingCount = countToRemove; foreach (var itemToReduce in itemsToReduce) { - var itemStackSize = _itemHelper.GetItemStackSize(itemToReduce); + var itemStackSize = itemToReduce.GetItemStackSize(); // Remove whole stack if (remainingCount >= itemStackSize) diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs index cb08b267..76b811d1 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs @@ -1,5 +1,6 @@ using System.Collections.Frozen; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Enums; @@ -178,98 +179,7 @@ public class ItemHelper( return false; } - if (!IsSameItem(itemOf1, itemOf2, compareUpdProperties)) - { - return false; - } - } - - return true; - } - - /// - /// This method will compare two items and see if they are equivalent - /// This method will NOT compare IDs on the items - /// - /// first item to compare - /// second item to compare - /// Upd properties to compare between the items - /// true if they are the same - public bool IsSameItem(Item item1, Item item2, HashSet? compareUpdProperties = null) - { - // Different tpl == different item - if (item1.Template != item2.Template) - { - return false; - } - - // Both lack upd object + same tpl = same - if (item1.Upd is null && item2.Upd is null) - { - return true; - } - - // item1 lacks upd, item2 has one - if (item1.Upd is null && item2.Upd is not null) - { - return false; - } - - // item1 has upd, item2 lacks one - if (item1.Upd is not null && item2.Upd is null) - { - return false; - } - - // key = Upd property Type as string, value = comparison function that returns bool - var comparers = new Dictionary> - { - { "Key", (upd1, upd2) => upd1.Key?.NumberOfUsages == upd2.Key?.NumberOfUsages }, - { - "Buff", - (upd1, upd2) => - upd1.Buff?.Value == upd2.Buff?.Value - && upd1.Buff?.BuffType == upd2.Buff?.BuffType - }, - { - "CultistAmulet", - (upd1, upd2) => - upd1.CultistAmulet?.NumberOfUsages == upd2.CultistAmulet?.NumberOfUsages - }, - { "Dogtag", (upd1, upd2) => upd1.Dogtag?.ProfileId == upd2.Dogtag?.ProfileId }, - { "FaceShield", (upd1, upd2) => upd1.FaceShield?.Hits == upd2.FaceShield?.Hits }, - { - "Foldable", - (upd1, upd2) => - upd1.Foldable?.Folded.GetValueOrDefault(false) - == upd2.Foldable?.Folded.GetValueOrDefault(false) - }, - { "FoodDrink", (upd1, upd2) => upd1.FoodDrink?.HpPercent == upd2.FoodDrink?.HpPercent }, - { "MedKit", (upd1, upd2) => upd1.MedKit?.HpResource == upd2.MedKit?.HpResource }, - { - "RecodableComponent", - (upd1, upd2) => - upd1.RecodableComponent?.IsEncoded == upd2.RecodableComponent?.IsEncoded - }, - { "RepairKit", (upd1, upd2) => upd1.RepairKit?.Resource == upd2.RepairKit?.Resource }, - { - "Resource", - (upd1, upd2) => upd1.Resource?.UnitsConsumed == upd2.Resource?.UnitsConsumed - }, - }; - - // Choose above keys or passed in keys to compare items with - var valuesToCompare = - compareUpdProperties?.Count > 0 ? compareUpdProperties : comparers.Keys.ToHashSet(); - foreach (var propertyName in valuesToCompare) - { - if (!comparers.TryGetValue(propertyName, out var comparer)) - // Key not found, skip - { - continue; - } - - if (!comparer(item1.Upd, item2.Upd)) + if (!itemOf1.IsSameItem(itemOf2, compareUpdProperties)) { return false; } @@ -1709,37 +1619,6 @@ public class ItemHelper( ); } - /// - /// Check if item is stored inside a container - /// - /// Item to check is inside of container - /// Name of slot to check item is in e.g. SecuredContainer/Backpack - /// Inventory with child parent items to check - /// True when item is in container - public bool ItemIsInsideContainer( - Item itemToCheck, - string desiredContainerSlotId, - List items - ) - { - // Get items parent - var parent = items.FirstOrDefault(item => - item.Id.Equals(itemToCheck.ParentId, StringComparison.OrdinalIgnoreCase) - ); - if (parent is null) - // No parent, end of line, not inside container - { - return false; - } - - if (parent.SlotId == desiredContainerSlotId) - { - return true; - } - - return ItemIsInsideContainer(parent, desiredContainerSlotId, items); - } - /// /// Add child items (cartridges) to a magazine /// @@ -1987,21 +1866,6 @@ public class ItemHelper( }; } - /// - /// Get the size of a stack, return 1 if no stack object count property found - /// - /// Item to get stack size of - /// size of stack - public int GetItemStackSize(Item item) - { - if (item.Upd?.StackObjectsCount is not null) - { - return (int)item.Upd.StackObjectsCount; - } - - return 1; - } - /// /// Get the name of an item from the locale file using the item tpl /// @@ -2256,45 +2120,6 @@ public class ItemHelper( return newId; } - // Adopts orphaned items by resetting them as root "hideout" items. Helpful in situations where a parent has been - // deleted from a group of items and there are children still referencing the missing parent. This method will - // remove the reference from the children to the parent and set item properties to root values. - // - // The ID of the "root" of the container. - // Array of Items that should be adjusted. - // Returns Array of Items that have been adopted. - public List AdoptOrphanedItems(string rootId, List items) - { - foreach (var item in items) - { - // Check if the item's parent exists. - var parentExists = items.Any(parentItem => - parentItem.Id.Equals(item.ParentId, StringComparison.OrdinalIgnoreCase) - ); - - // If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item by - // setting the parent ID to the PMCs inventory equipment ID, the slot ID to 'hideout', and remove the location. - if (!parentExists && item.ParentId != rootId && item.SlotId != "hideout") - { - item.ParentId = rootId; - item.SlotId = "hideout"; - item.Location = null; - } - } - - return items; - } - - // Populate a Map object of items for quick lookup using their ID. - // - // An array of Items that should be added to a Map. - // Returns A Map where the keys are the item IDs and the values are the corresponding Item objects. - public Dictionary GenerateItemsMap(List items) - { - // Convert list to dictionary, keyed by items Id - return items.ToDictionary(item => item.Id); - } - // Add a blank upd object to passed in item if it does not exist already // item to add upd to // text to write to log when upd object was not found @@ -2372,19 +2197,6 @@ public class ItemHelper( return null; } - // Remove FiR status from passed in items - // Items to update FiR status of - public void RemoveSpawnedInSessionPropertyFromItems(List items) - { - foreach (var item in items) - { - if (item.Upd is not null) - { - item.Upd.SpawnedInSession = null; - } - } - } - /// /// Get a 2D grid of a container's item slots /// diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs index ed2ed23e..889578f8 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs @@ -565,25 +565,6 @@ public class ProfileHelper( profileSkill.LastAccess = _timeUtil.GetTimeStamp(); } - /// - /// Get a specific common skill from supplied profile - /// - /// Player profile - /// Skill to look up and return value from - /// Common skill object from desired profile - public CommonSkill? GetSkillFromProfile(PmcData pmcData, SkillTypes skill) - { - var skillToReturn = pmcData?.Skills?.Common.FirstOrDefault(s => s.Id == skill); - if (skillToReturn == null) - { - _logger.Warning( - $"Profile {pmcData.SessionId} does not have a skill named: {skill.ToString()}" - ); - } - - return skillToReturn; - } - /// /// Is the provided session id for a developer account /// diff --git a/Libraries/SPTarkov.Server.Core/Helpers/QuestRewardHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/QuestRewardHelper.cs index b2562bf2..bb2cef75 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/QuestRewardHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/QuestRewardHelper.cs @@ -1,14 +1,12 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.ItemEvent; using SPTarkov.Server.Core.Models.Enums; -using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; -using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Services; -using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Helpers; @@ -16,23 +14,14 @@ namespace SPTarkov.Server.Core.Helpers; [Injectable] public class QuestRewardHelper( ISptLogger _logger, - HashUtil _hashUtil, - TimeUtil _timeUtil, - ItemHelper _itemHelper, PaymentHelper _paymentHelper, - TraderHelper _traderHelper, DatabaseService _databaseService, - QuestConditionHelper _questConditionHelper, ProfileHelper _profileHelper, - PresetHelper _presetHelper, RewardHelper _rewardHelper, LocalisationService _localisationService, - ICloner _cloner, - ConfigServer _configServer + ICloner _cloner ) { - protected QuestConfig _questConfig = _configServer.GetConfig(); - /// /// Value for in game reward traders to not duplicate quest rewards. /// Value can be modified by modders by overriding this value with new traders. @@ -161,10 +150,7 @@ public class QuestRewardHelper( ); // Calculate hideout management bonus as a percentage (up to 51% bonus) - var hideoutManagementSkill = _profileHelper.GetSkillFromProfile( - pmcData, - SkillTypes.HideoutManagement - ); + var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement); // 5100 becomes 0.51, add 1 to it, 1.51 // We multiply the money reward bonuses by the hideout management skill multiplier, giving the new result diff --git a/Libraries/SPTarkov.Server.Core/Services/CircleOfCultistService.cs b/Libraries/SPTarkov.Server.Core/Services/CircleOfCultistService.cs index 1ec06090..117dc3b0 100644 --- a/Libraries/SPTarkov.Server.Core/Services/CircleOfCultistService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/CircleOfCultistService.cs @@ -1,5 +1,6 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; @@ -42,7 +43,7 @@ public class CircleOfCultistService( ) { protected const string CircleOfCultistSlotId = "CircleOfCultistsGrid1"; - protected HideoutConfig _hideoutConfig = _configServer.GetConfig(); + protected readonly HideoutConfig _hideoutConfig = _configServer.GetConfig(); /// /// Start a sacrifice event @@ -176,10 +177,7 @@ public class CircleOfCultistService( ); // Adjust value generated by the players hideout management skill - var hideoutManagementSkill = _profileHelper.GetSkillFromProfile( - pmcData, - SkillTypes.HideoutManagement - ); + var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement); if (hideoutManagementSkill is not null) { rewardAmountMultiplier *= (float)(1 + hideoutManagementSkill.Progress / 10000); // 5100 becomes 0.51, add 1 to it, 1.51, multiply the bonus by it (e.g. 1.2 x 1.51) diff --git a/Libraries/SPTarkov.Server.Core/Services/InsuranceService.cs b/Libraries/SPTarkov.Server.Core/Services/InsuranceService.cs index a466bd28..bdc3f741 100644 --- a/Libraries/SPTarkov.Server.Core/Services/InsuranceService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/InsuranceService.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; @@ -21,7 +22,6 @@ public class InsuranceService( DatabaseService _databaseService, RandomUtil _randomUtil, ItemHelper _itemHelper, - HashUtil _hashUtil, TimeUtil _timeUtil, SaveServer _saveServer, TraderHelper _traderHelper, @@ -32,7 +32,8 @@ public class InsuranceService( ICloner _cloner ) { - protected InsuranceConfig _insuranceConfig = _configServer.GetConfig(); + protected readonly InsuranceConfig _insuranceConfig = + _configServer.GetConfig(); protected Dictionary>?> _insured = new(); /// @@ -302,13 +303,13 @@ public class InsuranceService( /// True if item protected bool ItemCannotBeLostOnDeath(Item lostItem, List inventoryItems) { - if (lostItem.SlotId?.ToLower().StartsWith("specialslot") ?? false) + if (lostItem.SlotId?.StartsWith("specialslot", StringComparison.OrdinalIgnoreCase) ?? false) { return true; } // We check secure container items even tho they are omitted from lostInsuredItems, just in case - if (_itemHelper.ItemIsInsideContainer(lostItem, "SecuredContainer", inventoryItems)) + if (lostItem.ItemIsInsideContainer("SecuredContainer", inventoryItems)) { return true; } diff --git a/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs b/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs index fe6cfe0c..a21b82da 100644 --- a/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Profile; @@ -195,7 +196,7 @@ public class MailSendService( { var rootItemParentId = _hashUtil.Generate(); - details.Items.AddRange(_itemHelper.AdoptOrphanedItems(rootItemParentId, items)); + details.Items.AddRange(items.AdoptOrphanedItems(rootItemParentId)); details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds; } diff --git a/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs b/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs index 0416461d..d89d8e14 100644 --- a/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs @@ -1,5 +1,6 @@ using System.Text.RegularExpressions; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; @@ -88,10 +89,7 @@ public class ProfileFixerService( // Otherwise we need to generate a new unique stash ID for this message's attachments message.Items.Stash = _hashUtil.Generate(); - message.Items.Data = _itemHelper.AdoptOrphanedItems( - message.Items.Stash, - message.Items.Data - ); + message.Items.Data = message.Items.Data.AdoptOrphanedItems(message.Items.Stash); // Because `adoptOrphanedItems` sets the slotId to `hideout`, we need to re-set it to `main` to work with mail foreach (var item in message.Items.Data.Where(item => item.SlotId == "hideout")) diff --git a/Libraries/SPTarkov.Server.Core/Services/RepairService.cs b/Libraries/SPTarkov.Server.Core/Services/RepairService.cs index 441f4952..5534b4b1 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RepairService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RepairService.cs @@ -1,6 +1,7 @@ using System.Text.Json.Serialization; using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; @@ -420,7 +421,7 @@ public class RepairService( .Intellect .RepairPointsCostReduction; var profileIntellectLevel = - _profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Intellect)?.Progress ?? 0; + pmcData.GetSkillFromProfile(SkillTypes.Intellect)?.Progress ?? 0; var intellectPointReduction = intellectRepairPointsPerLevel * Math.Truncate(profileIntellectLevel / 100); @@ -629,8 +630,7 @@ public class RepairService( // Skill < level 10 + repairing weapon if ( itemSkillType == SkillTypes.WeaponTreatment - && _profileHelper.GetSkillFromProfile(pmcData, SkillTypes.WeaponTreatment)?.Progress - < 1000 + && pmcData.GetSkillFromProfile(SkillTypes.WeaponTreatment)?.Progress < 1000 ) { return false; @@ -641,7 +641,7 @@ public class RepairService( new HashSet { SkillTypes.LightVests, SkillTypes.HeavyVests }.Contains( itemSkillType.Value ) - && _profileHelper.GetSkillFromProfile(pmcData, itemSkillType.Value)?.Progress < 1000 + && pmcData.GetSkillFromProfile(itemSkillType.Value)?.Progress < 1000 ) { return false; @@ -670,7 +670,7 @@ public class RepairService( var receivedDurabilityMaxPercent = buffSettings.ReceivedDurabilityMaxPercent; var skillLevel = Math.Truncate( - (_profileHelper.GetSkillFromProfile(pmcData, itemSkillType.Value)?.Progress ?? 0) / 100 + (pmcData.GetSkillFromProfile(itemSkillType.Value)?.Progress ?? 0) / 100 ); if (repairDetails.RepairPoints is null)