From d7f27820c840fcdafa2aaaef5f5fc0e45ea85fdb Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 Jan 2025 17:11:32 +0000 Subject: [PATCH] start more botLootGen and fix types --- Core/Generators/BotLootGenerator.cs | 136 ++++++++++++++++++++++++++- Core/Helpers/BotGeneratorHelper.cs | 10 +- Core/Helpers/InventoryHelper.cs | 22 ++--- Core/Services/BotLootCacheService.cs | 2 +- 4 files changed, 150 insertions(+), 20 deletions(-) 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,