diff --git a/Libraries/SPTarkov.Server.Core/Generators/PlayerScavGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/PlayerScavGenerator.cs index 26ca760f..c0a991a2 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/PlayerScavGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/PlayerScavGenerator.cs @@ -1,3 +1,4 @@ +using System.Globalization; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; @@ -55,7 +56,7 @@ public class PlayerScavGenerator( // use karma level to get correct karmaSettings if ( !_playerScavConfig.KarmaLevel.TryGetValue( - scavKarmaLevel.ToString(), + scavKarmaLevel.ToString(CultureInfo.InvariantCulture), out var playerScavKarmaSettings ) ) @@ -72,6 +73,7 @@ public class PlayerScavGenerator( // Edit baseBotNode values var baseBotNode = ConstructBotBaseTemplate(playerScavKarmaSettings.BotTypeForLoot); + AdjustBotTemplateWithKarmaSpecificSettings(playerScavKarmaSettings, baseBotNode); var scavData = _botGenerator.GeneratePlayerScav( @@ -247,69 +249,151 @@ public class PlayerScavGenerator( /// Adjust equipment/mod/item generation values based on scav karma levels /// /// Values to modify the bot template with - /// bot template to modify according to karama level settings + /// bot template to modify according to karma level settings protected void AdjustBotTemplateWithKarmaSpecificSettings( KarmaLevel karmaSettings, BotType baseBotNode ) { // Adjust equipment chance values - foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment) - { - // Adjustment value zero, nothing to do - if (equipmentKvP.Value == 0) - { - continue; - } - - // Try add new key with value - if ( - !baseBotNode.BotChances.EquipmentChances.TryAdd( - equipmentKvP.Key, - equipmentKvP.Value - ) - ) - // Unable to add new, update existing - { - baseBotNode.BotChances.EquipmentChances[equipmentKvP.Key] += equipmentKvP.Value; - } - } + AdjustEquipmentWeights( + karmaSettings.Modifiers.Equipment, + baseBotNode.BotChances.EquipmentChances + ); // Adjust mod chance values - foreach (var modKvP in karmaSettings.Modifiers.Mod) + AdjustWeaponModWeights( + karmaSettings.Modifiers.Mod, + baseBotNode.BotChances.WeaponModsChances + ); + + // Adjust item spawn quantity values + AdjustItemWeights(karmaSettings.ItemLimits, baseBotNode.BotGeneration.Items); + + // Blacklist equipment, keyed by equipment slot + BlacklistEquipment(karmaSettings, baseBotNode); + } + + protected static void AdjustEquipmentWeights( + Dictionary equipmentChangesToApply, + Dictionary botEquipmentChances + ) + { + foreach (var (equipmentSlot, chanceToAdd) in equipmentChangesToApply) { // Adjustment value zero, nothing to do - if (modKvP.Value == 0) + if (chanceToAdd == 0) { continue; } - if (karmaSettings.Modifiers.Mod.TryGetValue(modKvP.Key, out var value)) + // Try and add new key with value + if (!botEquipmentChances.TryAdd(equipmentSlot, chanceToAdd)) { - baseBotNode.BotChances.WeaponModsChances.TryAdd(modKvP.Key, 0); - baseBotNode.BotChances.WeaponModsChances[modKvP.Key] += value; + // Unable to add new, update existing + botEquipmentChances[equipmentSlot] += chanceToAdd; } - ; } + } - // Adjust item spawn quantity values - var props = baseBotNode.BotGeneration.Items.GetType().GetProperties(); - foreach (var itemLimitKvP in karmaSettings.ItemLimits) + /// + /// Get a bots item type weightings based on the desired key + /// + /// e.g. "healing" / "looseLoot" + /// + /// GenerationData + protected GenerationData? GetKarmaLimitValuesByKey( + string key, + GenerationWeightingItems botItemWeights + ) + { + switch (key) { - var prop = props.FirstOrDefault(x => - string.Equals(x.Name, itemLimitKvP.Key, StringComparison.OrdinalIgnoreCase) - ); - prop.SetValue(baseBotNode.BotGeneration.Items, itemLimitKvP.Value); + case "healing": + return botItemWeights.Healing; + case "drugs": + return botItemWeights.Drugs; + case "stims": + return botItemWeights.Stims; + case "looseLoot": + return botItemWeights.LooseLoot; + case "magazines": + return botItemWeights.Magazines; + case "grenades": + return botItemWeights.Grenades; + case "backpackLoot": + return botItemWeights.BackpackLoot; + case "drink": + return botItemWeights.Drink; + case "currency": + return botItemWeights.Currency; + case "pocketLoot": + return botItemWeights.PocketLoot; + case "vestLoot": + return botItemWeights.VestLoot; + case "specialItems": + return botItemWeights.SpecialItems; + default: + _logger.Error($"Subtype: {key} not found"); + return null; } + } - // Blacklist equipment, keyed by equipment slot - foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist) + protected static void AdjustWeaponModWeights( + Dictionary modChangesToApply, + Dictionary weaponModChances + ) + { + foreach (var (modSlot, weight) in modChangesToApply) { - baseBotNode.BotInventory.Equipment.TryGetValue( - equipmentBlacklistKvP.Key, - out var equipmentDict - ); - foreach (var itemToRemove in equipmentBlacklistKvP.Value) + // Adjustment value zero, nothing to do + if (weight == 0) + { + continue; + } + + if (modChangesToApply.TryGetValue(modSlot, out var value)) + { + weaponModChances.TryAdd(modSlot, 0); + weaponModChances[modSlot] += value; + } + } + } + + protected void AdjustItemWeights( + Dictionary karmaSettingsItemLimits, + GenerationWeightingItems? botGenerationItems + ) + { + foreach (var (subType, limitData) in karmaSettingsItemLimits) + { + var playerValues = GetKarmaLimitValuesByKey(subType, botGenerationItems); + if (playerValues is null) + { + continue; + } + + if (limitData.Weights is not null) + { + playerValues.Weights = limitData.Weights; + } + + if (limitData.Whitelist is not null) + { + playerValues.Whitelist = limitData.Whitelist; + } + } + } + + protected static void BlacklistEquipment(KarmaLevel karmaSettings, BotType baseBotNode) + { + foreach (var (slot, blacklist) in karmaSettings.EquipmentBlacklist) + { + if (!baseBotNode.BotInventory.Equipment.TryGetValue(slot, out var equipmentDict)) + { + continue; + } + foreach (var itemToRemove in blacklist) { equipmentDict.Remove(itemToRemove); }