diff --git a/Core/Generators/BotLootGenerator.cs b/Core/Generators/BotLootGenerator.cs
index c644034d..309e477c 100644
--- a/Core/Generators/BotLootGenerator.cs
+++ b/Core/Generators/BotLootGenerator.cs
@@ -462,7 +462,7 @@ public class BotLootGenerator
///
public void AddLootFromPool
(
- Dictionary pool,
+ Dictionary pool,
List equipmentSlots,
double totalItemCount,
BotBaseInventory inventoryToAddItemsTo, // TODO: type for containersIdFull was Set
@@ -473,7 +473,137 @@ public class BotLootGenerator
List containersIdFull = null
)
{
- throw new NotImplementedException();
+ // Loot pool has items
+ var poolSize = pool.Count;
+ if (poolSize > 0)
+ {
+ double currentTotalRub = 0;
+
+ var fitItemIntoContainerAttempts = 0;
+ for (var i = 0; i < totalItemCount; i++)
+ {
+ // Pool can become empty if item spawn limits keep removing items
+ if (pool.Count == 0)
+ {
+ return;
+ }
+
+ var weightedItemTpl = _weightedRandomHelper.GetWeightedValue(pool);
+ var itemResult = _itemHelper.GetItem(weightedItemTpl);
+ var itemToAddTemplate = itemResult.Value;
+ if (!itemResult.Key)
+ {
+ _logger.Warning($"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}");
+
+ continue;
+ }
+
+ if (itemSpawnLimits is not null)
+ {
+ if (ItemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits))
+ {
+ // Remove item from pool to prevent it being picked again
+ pool.Remove(weightedItemTpl);
+
+ i--;
+ continue;
+ }
+ }
+
+ var newRootItemId = _hashUtil.Generate();
+ List- itemWithChildrenToAdd =
+ [
+ new()
+ {
+ Id = newRootItemId,
+ Template = itemToAddTemplate.Id,
+ Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(itemToAddTemplate, botRole)
+ },
+ ];
+
+ // Is Simple-Wallet / WZ wallet
+ if (_botConfig.WalletLoot.WalletTplPool.Contains(weightedItemTpl))
+ {
+ var addCurrencyToWallet = _randomUtil.GetChance100(_botConfig.WalletLoot.ChancePercent);
+ if (addCurrencyToWallet)
+ {
+ // Create the currency items we want to add to wallet
+ var itemsToAdd = CreateWalletLoot(newRootItemId);
+
+ // Get the container grid for the wallet
+ var containerGrid = _inventoryHelper.GetContainerSlotMap(weightedItemTpl);
+
+ // Check if all the chosen currency items fit into wallet
+ var canAddToContainer = _inventoryHelper.CanPlaceItemsInContainer(
+ _cloner.Clone(containerGrid), // MUST clone grid before passing in as function modifies grid
+ itemsToAdd
+ );
+ if (canAddToContainer)
+ {
+ // Add each currency to wallet
+ foreach ( var itemToAdd in itemsToAdd) {
+ _inventoryHelper.PlaceItemInContainer(
+ containerGrid,
+ itemToAdd,
+ itemWithChildrenToAdd[0].Id,
+ "main"
+ );
+ }
+
+ itemWithChildrenToAdd.AddRange(itemsToAdd.SelectMany(x => x));
+ }
+ }
+ }
+
+ // Some items (ammoBox/ammo) need extra changes
+ AddRequiredChildItemsToParent(itemToAddTemplate, itemWithChildrenToAdd, isPmc, botRole);
+
+ // Attempt to add item to container(s)
+ var itemAddedResult = _botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
+ equipmentSlots,
+ newRootItemId,
+ itemToAddTemplate.Id,
+ itemWithChildrenToAdd,
+ inventoryToAddItemsTo,
+ containersIdFull
+ );
+
+ // Handle when item cannot be added
+ if (itemAddedResult != ItemAddedResult.SUCCESS)
+ {
+ if (itemAddedResult == ItemAddedResult.NO_CONTAINERS)
+ {
+ // Bot has no container to put item in, exit
+ _logger.Debug($"Unable to add: {totalItemCount} items to bot as it lacks a container to include them");
+ break;
+ }
+
+ fitItemIntoContainerAttempts++;
+ if (fitItemIntoContainerAttempts >= 4)
+ {
+ _logger.Debug($"Failed placing item: { i } of: { totalItemCount } items into: { botRole } containers: { string.Join(",", equipmentSlots) }. Tried: { fitItemIntoContainerAttempts } times, reason: { itemAddedResult.ToString() }, skipping");
+
+ break;
+ }
+
+ // Try again, failed but still under attempt limit
+ continue;
+ }
+
+ // Item added okay, reset counter for next item
+ fitItemIntoContainerAttempts = 0;
+
+ // Stop adding items to bots pool if rolling total is over total limit
+ if (totalValueLimitRub > 0)
+ {
+ currentTotalRub += _handbookHelper.GetTemplatePrice(itemToAddTemplate.Id);
+ if (currentTotalRub > totalValueLimitRub)
+ {
+ break;
+ }
+ }
+ }
+ }
}
///
@@ -482,7 +612,7 @@ public class BotLootGenerator
///
///
///
- public List
> CrateWalletLoot(string walletId)
+ public List> CreateWalletLoot(string walletId)
{
throw new NotImplementedException();
}
diff --git a/Core/Helpers/BotGeneratorHelper.cs b/Core/Helpers/BotGeneratorHelper.cs
index cd3b4a26..dbc8128a 100644
--- a/Core/Helpers/BotGeneratorHelper.cs
+++ b/Core/Helpers/BotGeneratorHelper.cs
@@ -504,24 +504,24 @@ public class BotGeneratorHelper
/// Inventory to add item+children into
/// ItemAddedResult result object
public ItemAddedResult AddItemWithChildrenToEquipmentSlot(
- List equipmentSlots,
+ List equipmentSlots,
string rootItemId,
string rootItemTplId,
List- itemWithChildren,
BotBaseInventory inventory,
- HashSet containersIdFull = null)
+ List containersIdFull = null)
{
/** Track how many containers are unable to be found */
var missingContainerCount = 0;
foreach (var equipmentSlotId in equipmentSlots)
{
- if (containersIdFull?.Contains(equipmentSlotId) ?? false)
+ if (containersIdFull?.Contains(equipmentSlotId.ToString()) ?? false)
{
continue;
}
// Get container to put item into
- var container = inventory.Items.FirstOrDefault((item) => item.SlotId == equipmentSlotId);
+ var container = inventory.Items.FirstOrDefault((item) => item.SlotId == equipmentSlotId.ToString());
if (container is null)
{
missingContainerCount++;
@@ -642,7 +642,7 @@ public class BotGeneratorHelper
// if the item was a one by one, we know it must be full. Or if the maps cant find a slot for a one by one
if (itemSize[0] == 1 && itemSize[1] == 1)
{
- containersIdFull.Add(equipmentSlotId);
+ containersIdFull.Add(equipmentSlotId.ToString());
}
}
}
diff --git a/Core/Helpers/InventoryHelper.cs b/Core/Helpers/InventoryHelper.cs
index 6724b9f1..10a50dda 100644
--- a/Core/Helpers/InventoryHelper.cs
+++ b/Core/Helpers/InventoryHelper.cs
@@ -69,7 +69,7 @@ public class InventoryHelper
/// Player id
/// Array of items with children to try and fit
/// True all items fit
- public bool CanPlaceItemsInInventory(string sessionId, Item[][] itemsWithChildren)
+ public bool CanPlaceItemsInInventory(string sessionId, List
> itemsWithChildren)
{
throw new NotImplementedException();
}
@@ -80,7 +80,7 @@ public class InventoryHelper
/// Container grid to fit items into
/// Items to try and fit into grid
/// True all fit
- public bool CanPlaceItemsInContainer(int[][] containerFS2D, Item[][] itemsWithChildren)
+ public bool CanPlaceItemsInContainer(List> containerFS2D, List> itemsWithChildren)
{
throw new NotImplementedException();
}
@@ -91,7 +91,7 @@ public class InventoryHelper
/// Container grid
/// Item to check fits
/// True it fits
- public bool CanPlaceItemInContainer(int[][] containerFS2D, Item[] itemWithChildren)
+ public bool CanPlaceItemInContainer(List> containerFS2D, List- itemWithChildren)
{
throw new NotImplementedException();
}
@@ -104,8 +104,8 @@ public class InventoryHelper
/// Id of the container we're fitting item into
/// Slot id value to use, default is "hideout"
public void PlaceItemInContainer(
- int[][] containerFS2D,
- Item[] itemWithChildren,
+ List
> containerFS2D,
+ List- itemWithChildren,
string containerId,
string desiredSlotId = "hideout")
{
@@ -122,9 +122,9 @@ public class InventoryHelper
/// Should sorting table to be used if main stash has no space
/// Output to send back to client
protected void PlaceItemInInventory(
- int[][] stashFS2D,
- int[][] sortingTableFS2D,
- Item[] itemWithChildren,
+ List
> stashFS2D,
+ List> sortingTableFS2D,
+ List- itemWithChildren,
BotBaseInventory playerInventory,
bool useSortingTable,
ItemEventRouterResponse output)
@@ -262,7 +262,7 @@ public class InventoryHelper
///
/// Container to get data for
/// blank two-dimensional array
- public int[,] GetContainerSlotMap(string containerTpl)
+ public List> GetContainerSlotMap(string containerTpl)
{
throw new NotImplementedException();
}
@@ -272,7 +272,7 @@ public class InventoryHelper
///
/// Player profile
/// two-dimensional array
- protected int[,] GetSortingTableSlotMap(PmcData pmcData)
+ protected List> GetSortingTableSlotMap(PmcData pmcData)
{
throw new NotImplementedException();
}
@@ -282,7 +282,7 @@ public class InventoryHelper
///
/// Players id
/// Dictionary of 2 values, horizontal and vertical stash size
- protected Dictionary GetPlayerStashSize(string sessionID)
+ protected Dictionary GetPlayerStashSize(string sessionID)
{
throw new NotImplementedException();
}
diff --git a/Core/Services/BotLootCacheService.cs b/Core/Services/BotLootCacheService.cs
index fc638975..d62669eb 100644
--- a/Core/Services/BotLootCacheService.cs
+++ b/Core/Services/BotLootCacheService.cs
@@ -53,7 +53,7 @@ public class BotLootCacheService
/// what type of loot is needed (backpack/pocket/stim/vest etc)
/// Base json db file for the bot having its loot generated
/// Dictionary
- public Dictionary GetLootFromCache(
+ public Dictionary GetLootFromCache(
string botRole,
bool isPmc,
string lootType,