diff --git a/Libraries/SPTarkov.Server.Core/Services/BotEquipmentModPoolService.cs b/Libraries/SPTarkov.Server.Core/Services/BotEquipmentModPoolService.cs
index f2c6ba23..5b493e90 100644
--- a/Libraries/SPTarkov.Server.Core/Services/BotEquipmentModPoolService.cs
+++ b/Libraries/SPTarkov.Server.Core/Services/BotEquipmentModPoolService.cs
@@ -44,7 +44,7 @@ public class BotEquipmentModPoolService(
}
///
- /// Get dictionary of mods for each item passed in
+ /// Create a dictionary of mods for each item passed in
///
/// Items to find related mods and store in modPool
/// Mod pool to choose from e.g. "weapon" for weaponModPool
@@ -53,6 +53,7 @@ public class BotEquipmentModPoolService(
string poolType
)
{
+ // Null guard bad input
if (inputItems is null || !inputItems.Any())
{
logger.Error(localisationService.GetText("bot-unable_to_generate_item_pool_no_items", poolType));
@@ -61,43 +62,45 @@ public class BotEquipmentModPoolService(
}
var pool = new ConcurrentDictionary>>();
- foreach (var item in inputItems)
+ foreach (var dbItem in inputItems)
{
- if (item.Properties is null)
+ if (dbItem.Properties is null)
{
- logger.Error(localisationService.GetText("bot-item_missing_props_property", new { itemTpl = item.Id, name = item.Name }));
+ logger.Error(
+ localisationService.GetText("bot-item_missing_props_property", new { itemTpl = dbItem.Id, name = dbItem.Name })
+ );
continue;
}
- // No slots
- if (item.Properties?.Slots is null || !item.Properties.Slots.Any())
+ // No slots for mods
+ if (dbItem.Properties.Slots is null || !dbItem.Properties.Slots.Any())
{
continue;
}
- // Add base item (weapon/armor) to pool
- pool.TryAdd(item.Id, new ConcurrentDictionary>());
+ // Add base item (weapon/armor) to pool if it doesn't exist
+ var itemPool = pool.GetOrAdd(dbItem.Id, new ConcurrentDictionary>());
- // Iterate over each items mod slots e.g. mod_muzzle
- foreach (var slot in item.Properties.Slots)
+ // Look for slots on item that hold mods
+ foreach (var slot in dbItem.Properties.Slots)
{
- // Get mods that fit into the current mod slot
- var itemsThatFit = slot.Properties.Filters.FirstOrDefault().Filter;
+ // Get whitelist of mods that fit into mod slot
+ var itemsThatFit = slot?.Properties?.Filters?.FirstOrDefault()?.Filter ?? [];
+ if (!itemsThatFit.Any())
+ {
+ continue;
+ }
- // Get weapon/armor pool to add mod slots + mod tpls to
-
- var itemModPool = pool[item.Id];
+ // Ensure Mod slot key + blank dict exist in pool
+ var modItemPool = GetSetModItemPool(itemPool, slot.Name);
foreach (var itemToAddTpl in itemsThatFit)
{
- // Ensure Mod slot key + blank dict value exist
- InitSetInDict(itemModPool, slot.Name);
-
- // Does tpl exist inside mod_slots hashset
- if (!SetContainsTpl(itemModPool[slot.Name], itemToAddTpl))
+ // Does tpl exist inside mods' slots' hashset
+ if (!SetContainsTpl(modItemPool, itemToAddTpl))
// Keyed by mod slot
{
- AddTplToSet(itemModPool[slot.Name], itemToAddTpl);
+ AddTplToSet(modItemPool, itemToAddTpl);
}
var subItemDetails = itemHelper.GetItem(itemToAddTpl).Value;
@@ -105,8 +108,8 @@ public class BotEquipmentModPoolService(
// Item has Slots + pool doesn't have value
if (hasSubItemsToAdd && !pool.ContainsKey(subItemDetails.Id))
- // Recursive call
{
+ // Recursive call
GeneratePool([subItemDetails], poolType);
}
}
@@ -116,6 +119,14 @@ public class BotEquipmentModPoolService(
return pool;
}
+ private HashSet GetSetModItemPool(ConcurrentDictionary> dictionary, string slotName)
+ {
+ lock (_lockObject)
+ {
+ return dictionary.GetOrAdd(slotName, []);
+ }
+ }
+
private bool SetContainsTpl(HashSet itemSet, MongoId tpl)
{
lock (_lockObject)
@@ -132,14 +143,6 @@ public class BotEquipmentModPoolService(
}
}
- private bool InitSetInDict(ConcurrentDictionary> dictionary, string slotName)
- {
- lock (_lockObject)
- {
- return dictionary.TryAdd(slotName, []);
- }
- }
-
///
/// Empty the mod pool
///