Implemented more of BotLootCacheService and related areas

This commit is contained in:
Chomp
2025-01-15 14:37:56 +00:00
parent 4faa92e05a
commit 655d559abd
4 changed files with 313 additions and 20 deletions
+4 -4
View File
@@ -1,4 +1,4 @@
using Core.Annotations;
using Core.Annotations;
using Core.Models.Eft.Common.Tables;
namespace Core.Generators;
@@ -15,7 +15,7 @@ public class PMCLootGenerator
/// </summary>
/// <param name="botRole"></param>
/// <returns>Dictionary of string and number</returns>
public Dictionary<string, int> GeneratePMCPocketLootPool(string botRole)
public Dictionary<string, double> GeneratePMCPocketLootPool(string botRole)
{
throw new NotImplementedException();
}
@@ -25,7 +25,7 @@ public class PMCLootGenerator
/// </summary>
/// <param name="botRole"></param>
/// <returns>Dictionary of string and number</returns>
public Dictionary<string, int> GeneratePMCVestLootPool(string botRole)
public Dictionary<string, double> GeneratePMCVestLootPool(string botRole)
{
throw new NotImplementedException();
}
@@ -57,7 +57,7 @@ public class PMCLootGenerator
/// </summary>
/// <param name="botRole"></param>
/// <returns>Dictionary of string and number</returns>
public Dictionary<string, int> GeneratePMCBackpackLootPool(string botRole)
public Dictionary<string, double> GeneratePMCBackpackLootPool(string botRole)
{
throw new NotImplementedException();
}
+6 -1
View File
@@ -1044,7 +1044,12 @@ public class ItemHelper
throw new NotImplementedException();
}
public bool IsOfBaseclass(string tpl, List<string> baseClassTpls)
public bool IsOfBaseclass(string tpl, string baseClassTpl)
{
return _itemBaseClassService.ItemHasBaseClass(tpl, [baseClassTpl]);
}
public bool isOfBaseclasses(string tpl, List<string> baseClassTpls)
{
return _itemBaseClassService.ItemHasBaseClass(tpl, baseClassTpls);
}
+13 -13
View File
@@ -5,43 +5,43 @@ namespace Core.Models.Spt.Bots;
public class BotLootCache
{
[JsonPropertyName("backpackLoot")]
public Dictionary<string, int>? BackpackLoot { get; set; }
public Dictionary<string, double>? BackpackLoot { get; set; }
[JsonPropertyName("pocketLoot")]
public Dictionary<string, int>? PocketLoot { get; set; }
public Dictionary<string, double>? PocketLoot { get; set; }
[JsonPropertyName("vestLoot")]
public Dictionary<string, int>? VestLoot { get; set; }
public Dictionary<string, double>? VestLoot { get; set; }
[JsonPropertyName("secureLoot")]
public Dictionary<string, int>? SecureLoot { get; set; }
public Dictionary<string, double>? SecureLoot { get; set; }
[JsonPropertyName("combinedPoolLoot")]
public Dictionary<string, int>? CombinedPoolLoot { get; set; }
public Dictionary<string, double>? CombinedPoolLoot { get; set; }
[JsonPropertyName("specialItems")]
public Dictionary<string, int>? SpecialItems { get; set; }
public Dictionary<string, double>? SpecialItems { get; set; }
[JsonPropertyName("healingItems")]
public Dictionary<string, int>? HealingItems { get; set; }
public Dictionary<string, double>? HealingItems { get; set; }
[JsonPropertyName("drugItems")]
public Dictionary<string, int>? DrugItems { get; set; }
public Dictionary<string, double>? DrugItems { get; set; }
[JsonPropertyName("foodItems")]
public Dictionary<string, int>? FoodItems { get; set; }
public Dictionary<string, double>? FoodItems { get; set; }
[JsonPropertyName("drinkItems")]
public Dictionary<string, int>? DrinkItems { get; set; }
public Dictionary<string, double>? DrinkItems { get; set; }
[JsonPropertyName("currencyItems")]
public Dictionary<string, int>? CurrencyItems { get; set; }
public Dictionary<string, double>? CurrencyItems { get; set; }
[JsonPropertyName("stimItems")]
public Dictionary<string, int>? StimItems { get; set; }
public Dictionary<string, double>? StimItems { get; set; }
[JsonPropertyName("grenadeItems")]
public Dictionary<string, int>? GrenadeItems { get; set; }
public Dictionary<string, double>? GrenadeItems { get; set; }
}
public class LootCacheType
+290 -2
View File
@@ -3,6 +3,7 @@ using Core.Generators;
using Core.Helpers;
using Core.Models.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Enums;
using Core.Models.Spt.Bots;
using Core.Utils.Cloners;
using ILogger = Core.Models.Utils.ILogger;
@@ -69,7 +70,294 @@ public class BotLootCacheService
/// <param name="botJsonTemplate">db template for bot having its loot generated</param>
protected void AddLootToCache(string botRole, bool isPmc, BotType botJsonTemplate)
{
throw new NotImplementedException();
// Full pool of loot we use to create the various sub-categories with
var lootPool = botJsonTemplate.BotInventory.Items;
// Flatten all individual slot loot pools into one big pool, while filtering out potentially missing templates
Dictionary<string, double> specialLootPool = new();
Dictionary<string, double> backpackLootPool= new();
Dictionary<string, double> pocketLootPool = new();
Dictionary<string, double> vestLootPool = new();
Dictionary<string, double> secureLootTPool = new();
Dictionary<string, double> combinedLootPool = new();
if (isPmc)
{
// Replace lootPool from bot json with our own generated list for PMCs
lootPool.Backpack = _cloner.Clone(_pmcLootGenerator.GeneratePMCBackpackLootPool(botRole));
lootPool.Pockets = _cloner.Clone(_pmcLootGenerator.GeneratePMCPocketLootPool(botRole));
lootPool.TacticalVest = _cloner.Clone(_pmcLootGenerator.GeneratePMCVestLootPool(botRole));
}
// Backpack/Pockets etc
var poolsToProcess =
new Dictionary<string, Dictionary<string, double>>
{
{ "Backpack", lootPool.Backpack },
{ "Pockets", lootPool.Pockets },
{ "SecuredContainer", lootPool.SecuredContainer },
{ "SpecialLoot", lootPool.SpecialLoot },
{ "TacticalVest", lootPool.TacticalVest }
};
foreach (var kvp in poolsToProcess)
{
// No items to add, skip
if (kvp.Value.Count == 0)
{
continue;
}
// Sort loot pool into separate buckets
switch (kvp.Key)
{
case "specialloot":
AddItemsToPool(specialLootPool, kvp.Value);
break;
case "pockets":
AddItemsToPool(pocketLootPool, kvp.Value);
break;
case "tacticalvest":
AddItemsToPool(vestLootPool, kvp.Value);
break;
case "securedcontainer":
AddItemsToPool(secureLootTPool, kvp.Value);
break;
case "backpack":
AddItemsToPool(backpackLootPool, kvp.Value);
break;
default:
_logger.Warning($"How did you get here {kvp.Key}");
break;
}
// Add all items (if any) to combined pool (excluding secure)
if (kvp.Value.Count > 0 && kvp.Key.ToLower() != "securedcontainer")
{
AddItemsToPool(combinedLootPool, kvp.Value);
}
}
// Assign whitelisted special items to bot if any exist
var specialLootItems =
botJsonTemplate.BotGeneration.Items.SpecialItems.Whitelist.Count > 0
? botJsonTemplate.BotGeneration.Items.SpecialItems.Whitelist
: new Dictionary<string, double>();
// no whitelist, find and assign from combined item pool
if (!specialLootItems.Any())
{
// key = tpl, value = weight
foreach (var itemKvP in specialLootPool) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (!(IsBulletOrGrenade(itemTemplate.Properties) || IsMagazine(itemTemplate.Properties)))
{
specialLootItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted healing items to bot if any exist
var healingItems =
botJsonTemplate.BotGeneration.Items.Healing.Whitelist.Count > 0
? botJsonTemplate.BotGeneration.Items.Healing.Whitelist
: new Dictionary<string, double>();
// No whitelist, find and assign from combined item pool
if (!healingItems.Any())
{
// key = tpl, value = weight
foreach (var itemKvP in combinedLootPool) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (
IsMedicalItem(itemTemplate.Properties) &&
itemTemplate.Parent != BaseClasses.STIMULATOR &&
itemTemplate.Parent != BaseClasses.DRUGS
)
{
healingItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted drugs to bot if any exist
var drugItems = botJsonTemplate.BotGeneration.Items.Drugs.Whitelist ?? new Dictionary<string, double>();
// no drugs whitelist, find and assign from combined item pool
if (!drugItems.Any())
{
foreach (var itemKvP in (combinedLootPool)) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (IsMedicalItem(itemTemplate.Properties) && itemTemplate.Parent == BaseClasses.DRUGS)
{
drugItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted food to bot if any exist
var foodItems = botJsonTemplate.BotGeneration.Items.Food.Whitelist ?? new Dictionary<string, double>();
// No food whitelist, find and assign from combined item pool
if (!foodItems.Any())
{
foreach (var itemKvP in (combinedLootPool)) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (_itemHelper.IsOfBaseclass(itemTemplate.Id, BaseClasses.FOOD))
{
foodItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted drink to bot if any exist
var drinkItems = botJsonTemplate.BotGeneration.Items.Food.Whitelist ?? new Dictionary<string, double>();
// No drink whitelist, find and assign from combined item pool
if (!drinkItems.Any())
{
foreach (var itemKvP in combinedLootPool) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (_itemHelper.IsOfBaseclass(itemTemplate.Id, BaseClasses.DRINK))
{
drinkItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted currency to bot if any exist
var currencyItems = botJsonTemplate.BotGeneration.Items.Currency.Whitelist ?? new Dictionary<string, double>();
// No currency whitelist, find and assign from combined item pool
if (!currencyItems.Any())
{
foreach (var itemKvP in combinedLootPool) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (_itemHelper.IsOfBaseclass(itemTemplate.Id, BaseClasses.MONEY))
{
currencyItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted stims to bot if any exist
var stimItems = botJsonTemplate.BotGeneration.Items.Stims.Whitelist ?? new Dictionary<string, double>();
// No whitelist, find and assign from combined item pool
if (!stimItems.Any())
{
foreach (var itemKvP in combinedLootPool) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (IsMedicalItem(itemTemplate.Properties) && itemTemplate.Parent == BaseClasses.STIMULATOR)
{
stimItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Assign whitelisted grenades to bot if any exist
var grenadeItems = botJsonTemplate.BotGeneration.Items.Grenades.Whitelist ?? new Dictionary<string, double>();
// no whitelist, find and assign from combined item pool
if (!grenadeItems.Any())
{
foreach (var itemKvP in combinedLootPool) {
var itemTemplate = _itemHelper.GetItem(itemKvP.Key).Value;
if (IsGrenade(itemTemplate.Properties))
{
grenadeItems[itemKvP.Key] = itemKvP.Value;
}
}
}
// Get backpack loot (excluding magazines, bullets, grenades, drink, food and healing/stim items)
var filteredBackpackItems = new Dictionary<string, double>();
foreach (var itemKvP in backpackLootPool) {
var itemResult = _itemHelper.GetItem(itemKvP.Key);
if (itemResult.Value is null)
{
continue;
}
var itemTemplate = itemResult.Value;
if (
IsBulletOrGrenade(itemTemplate.Properties) ||
IsMagazine(itemTemplate.Properties) ||
IsMedicalItem(itemTemplate.Properties) ||
IsGrenade(itemTemplate.Properties) ||
IsFood(itemTemplate.Id) ||
IsDrink(itemTemplate.Id) ||
IsCurrency(itemTemplate.Id)
)
{
// Is type we don't want as backpack loot, skip
continue;
}
filteredBackpackItems[itemKvP.Key] = itemKvP.Value;
}
// Get pocket loot (excluding magazines, bullets, grenades, drink, food medical and healing/stim items)
var filteredPocketItems = new Dictionary<string, double>();
foreach (var itemKvP in pocketLootPool) {
var itemResult = _itemHelper.GetItem(itemKvP.Key);
if (itemResult.Value is null)
{
continue;
}
var itemTemplate = itemResult.Value;
if (
IsBulletOrGrenade(itemTemplate.Properties) ||
IsMagazine(itemTemplate.Properties) ||
IsMedicalItem(itemTemplate.Properties) ||
IsGrenade(itemTemplate.Properties) ||
IsFood(itemTemplate.Id) ||
IsDrink(itemTemplate.Id) ||
IsCurrency(itemTemplate.Id) ||
itemTemplate.Properties.Height is null || // lacks height
itemTemplate.Properties.Width is null // lacks width
) {
continue;
}
filteredPocketItems[itemKvP.Key] = itemKvP.Value;
}
// Get vest loot (excluding magazines, bullets, grenades, medical and healing/stim items)
var filteredVestItems = new Dictionary<string, double>();
foreach (var itemKvP in vestLootPool) {
var itemResult = _itemHelper.GetItem(itemKvP.Key);
if (itemResult.Value is null)
{
continue;
}
var itemTemplate = itemResult.Value;
if (
IsBulletOrGrenade(itemTemplate.Properties) ||
IsMagazine(itemTemplate.Properties) ||
IsMedicalItem(itemTemplate.Properties) ||
IsGrenade(itemTemplate.Properties) ||
IsFood(itemTemplate.Id) ||
IsDrink(itemTemplate.Id) ||
IsCurrency(itemTemplate.Id)
)
{
continue;
}
filteredVestItems[itemKvP.Key] = itemKvP.Value;
}
var cacheForRole = _lootCache[botRole];
cacheForRole.HealingItems = healingItems;
cacheForRole.DrugItems = drugItems;
cacheForRole.FoodItems = foodItems;
cacheForRole.DrinkItems = drinkItems;
cacheForRole.CurrencyItems = currencyItems;
cacheForRole.StimItems = stimItems;
cacheForRole.GrenadeItems = grenadeItems;
cacheForRole.SpecialItems = specialLootItems;
cacheForRole.BackpackLoot = filteredBackpackItems;
cacheForRole.PocketLoot = filteredPocketItems;
cacheForRole.VestLoot = filteredVestItems;
cacheForRole.SecureLoot = secureLootTPool;
}
/// <summary>
@@ -82,7 +370,7 @@ public class BotLootCacheService
throw new NotImplementedException();
}
protected void AddItemsToPool(Dictionary<string, int> poolToAddTo, Dictionary<string, int> poolOfItemsToAdd)
protected void AddItemsToPool(Dictionary<string, double> poolToAddTo, Dictionary<string, double> poolOfItemsToAdd)
{
throw new NotImplementedException();
}