Implemented more of BotLootCacheService and related areas
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user