diff --git a/Core/Generators/BotEquipmentModGenerator.cs b/Core/Generators/BotEquipmentModGenerator.cs index dac8ba8a..7de3f160 100644 --- a/Core/Generators/BotEquipmentModGenerator.cs +++ b/Core/Generators/BotEquipmentModGenerator.cs @@ -15,75 +15,29 @@ using Core.Utils.Cloners; namespace Core.Generators; [Injectable] -public class BotEquipmentModGenerator +public class BotEquipmentModGenerator( + ISptLogger _logger, + HashUtil _hashUtil, + RandomUtil _randomUtil, + ProbabilityHelper _probabilityHelper, + DatabaseService _databaseService, + ItemHelper _itemHelper, + BotEquipmentFilterService _botEquipmentFilterService, + ItemFilterService _itemFilterService, + ProfileHelper _profileHelper, + BotWeaponModLimitService _botWeaponModLimitService, + BotHelper _botHelper, + BotGeneratorHelper _botGeneratorHelper, + BotWeaponGeneratorHelper _botWeaponGeneratorHelper, + WeightedRandomHelper _weightedRandomHelper, + PresetHelper _presetHelper, + LocalisationService _localisationService, + BotEquipmentModPoolService _botEquipmentModPoolService, + ConfigServer _configServer, + ICloner _cloner +) { - private readonly ISptLogger _logger; - private readonly HashUtil _hashUtil; - private readonly RandomUtil _randomUtil; - private readonly ProbabilityHelper _probabilityHelper; - private readonly DatabaseService _databaseService; - private readonly ItemHelper _itemHelper; - private readonly BotEquipmentFilterService _botEquipmentFilterService; - private readonly ItemFilterService _itemFilterService; - private readonly ProfileHelper _profileHelper; - private readonly BotWeaponModLimitService _botWeaponModLimitService; - private readonly BotHelper _botHelper; - private readonly BotGeneratorHelper _botGeneratorHelper; - private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper; - private readonly WeightedRandomHelper _weightedRandomHelper; - private readonly PresetHelper _presetHelper; - private readonly LocalisationService _localisationService; - private readonly BotEquipmentModPoolService _botEquipmentModPoolService; - private readonly ConfigServer _configServer; - private readonly ICloner _cloner; - - private BotConfig _botConfig; - - public BotEquipmentModGenerator - ( - ISptLogger logger, - HashUtil hashUtil, - RandomUtil randomUtil, - ProbabilityHelper probabilityHelper, - DatabaseService databaseService, - ItemHelper itemHelper, - BotEquipmentFilterService botEquipmentFilterService, - ItemFilterService itemFilterService, - ProfileHelper profileHelper, - BotWeaponModLimitService botWeaponModLimitService, - BotHelper botHelper, - BotGeneratorHelper botGeneratorHelper, - BotWeaponGeneratorHelper botWeaponGeneratorHelper, - WeightedRandomHelper weightedRandomHelper, - PresetHelper presetHelper, - LocalisationService localisationService, - BotEquipmentModPoolService botEquipmentModPoolService, - ConfigServer configServer, - ICloner cloner - ) - { - _logger = logger; - _hashUtil = hashUtil; - _randomUtil = randomUtil; - _probabilityHelper = probabilityHelper; - _databaseService = databaseService; - _itemHelper = itemHelper; - _botEquipmentFilterService = botEquipmentFilterService; - _itemFilterService = itemFilterService; - _profileHelper = profileHelper; - _botWeaponModLimitService = botWeaponModLimitService; - _botHelper = botHelper; - _botGeneratorHelper = botGeneratorHelper; - _botWeaponGeneratorHelper = botWeaponGeneratorHelper; - _weightedRandomHelper = weightedRandomHelper; - _presetHelper = presetHelper; - _localisationService = localisationService; - _botEquipmentModPoolService = botEquipmentModPoolService; - _configServer = configServer; - _cloner = cloner; - - _botConfig = _configServer.GetConfig(); - } + protected BotConfig _botConfig = _configServer.GetConfig(); /// /// Check mods are compatible and add to array @@ -174,7 +128,9 @@ public class BotEquipmentModGenerator switch (plateSlotFilteringOutcome.Result) { case Result.UNKNOWN_FAILURE or Result.NO_DEFAULT_FILTER: - _logger.Debug($"Plate slot: {modSlotName} selection for armor: {parentTemplate.Id} failed: {plateSlotFilteringOutcome.Result}, skipping"); + _logger.Debug( + $"Plate slot: {modSlotName} selection for armor: {parentTemplate.Id} failed: {plateSlotFilteringOutcome.Result}, skipping" + ); continue; case Result.LACKS_PLATE_WEIGHTS: @@ -275,7 +231,8 @@ public class BotEquipmentModGenerator * @param modSlot front/back * @returns Tpl of plate */ - protected string GetDefaultPlateTpl(TemplateItem armorItem, string modSlot ) { + protected string GetDefaultPlateTpl(TemplateItem armorItem, string modSlot) + { var relatedItemDbModSlot = armorItem.Properties.Slots?.FirstOrDefault(slot => slot.Name.ToLower() == modSlot); return relatedItemDbModSlot?.Props.Filters[0].Plate; @@ -287,20 +244,21 @@ public class BotEquipmentModGenerator * @param modSlot front/back * @returns Armor IItem */ - protected Item GetDefaultPresetArmorSlot(string armorItemTpl, string modSlot) { + protected Item GetDefaultPresetArmorSlot(string armorItemTpl, string modSlot) + { var defaultPreset = _presetHelper.GetDefaultPreset(armorItemTpl); return defaultPreset?.Items.FirstOrDefault((item) => item.SlotId?.ToLower() == modSlot); } -/// -/// Add mods to a weapon using the provided mod pool -/// -/// Session id -/// Data used to generate the weapon -/// Weapon + mods array -public List GenerateModsForWeapon(string sessionId, GenerateWeaponRequest request) + /// + /// Add mods to a weapon using the provided mod pool + /// + /// Session id + /// Data used to generate the weapon + /// Weapon + mods array + public List GenerateModsForWeapon(string sessionId, GenerateWeaponRequest request) { var pmcProfile = _profileHelper.GetPmcProfile(sessionId); @@ -1399,14 +1357,16 @@ public List GenerateModsForWeapon(string sessionId, GenerateWeaponRequest var filteredMods = FilterModsByBlacklist(supportedSubMods, botEquipBlacklist, desiredSlotName); if (!filteredMods.Any()) { - _logger.Warning(_localisationService - .GetText("bot-unable_to_filter_mods_all_blacklisted", - new - { - slotName = desiredSlotObject.Name, - itemName = modTemplate.Name, - } - ) + _logger.Warning( + _localisationService + .GetText( + "bot-unable_to_filter_mods_all_blacklisted", + new + { + slotName = desiredSlotObject.Name, + itemName = modTemplate.Name, + } + ) ); } diff --git a/Core/Generators/BotGenerator.cs b/Core/Generators/BotGenerator.cs index b867fff6..8cec1e8d 100644 --- a/Core/Generators/BotGenerator.cs +++ b/Core/Generators/BotGenerator.cs @@ -18,69 +18,28 @@ using BodyPart = Core.Models.Eft.Common.Tables.BodyPart; namespace Core.Generators; [Injectable] -public class BotGenerator +public class BotGenerator( + ISptLogger _logger, + HashUtil _hashUtil, + RandomUtil _randomUtil, + TimeUtil _timeUtil, + ProfileHelper _profileHelper, + DatabaseService _databaseService, + BotInventoryGenerator _botInventoryGenerator, + BotLevelGenerator _botLevelGenerator, + BotEquipmentFilterService _botEquipmentFilterService, + WeightedRandomHelper _weightedRandomHelper, + BotHelper _botHelper, + BotGeneratorHelper _botGeneratorHelper, + SeasonalEventService _seasonalEventService, + ItemFilterService _itemFilterService, + BotNameService _botNameService, + ConfigServer _configServer, + ICloner _cloner +) { - protected ISptLogger _logger; - protected HashUtil _hashUtil; - protected RandomUtil _randomUtil; - protected TimeUtil _timeUtil; - protected ProfileHelper _profileHelper; - protected DatabaseService _databaseService; - protected BotInventoryGenerator _botInventoryGenerator; - protected BotLevelGenerator _botLevelGenerator; - protected BotEquipmentFilterService _botEquipmentFilterService; - protected WeightedRandomHelper _weightedRandomHelper; - protected BotHelper _botHelper; - protected BotGeneratorHelper _botGeneratorHelper; - protected SeasonalEventService _seasonalEventService; - protected ItemFilterService _itemFilterService; - protected BotNameService _botNameService; - protected ConfigServer _configServer; - protected ICloner _cloner; - private BotConfig _botConfig; - private PmcConfig _pmcConfig; - - public BotGenerator( - ISptLogger logger, - HashUtil hashUtil, - RandomUtil randomUtil, - TimeUtil timeUtil, - ProfileHelper profileHelper, - DatabaseService databaseService, - BotInventoryGenerator botInventoryGenerator, - BotLevelGenerator botLevelGenerator, - BotEquipmentFilterService botEquipmentFilterService, - WeightedRandomHelper weightedRandomHelper, - BotHelper botHelper, - BotGeneratorHelper botGeneratorHelper, - SeasonalEventService seasonalEventService, - ItemFilterService itemFilterService, - BotNameService botNameService, - ConfigServer configServer, - ICloner cloner - ) - { - _logger = logger; - _hashUtil = hashUtil; - _randomUtil = randomUtil; - _timeUtil = timeUtil; - _profileHelper = profileHelper; - _databaseService = databaseService; - _botInventoryGenerator = botInventoryGenerator; - _botLevelGenerator = botLevelGenerator; - _botEquipmentFilterService = botEquipmentFilterService; - _weightedRandomHelper = weightedRandomHelper; - _botHelper = botHelper; - _botGeneratorHelper = botGeneratorHelper; - _seasonalEventService = seasonalEventService; - _itemFilterService = itemFilterService; - _botNameService = botNameService; - _configServer = configServer; - _cloner = cloner; - - _botConfig = _configServer.GetConfig(); - _pmcConfig = _configServer.GetConfig(); - } + protected BotConfig _botConfig = _configServer.GetConfig(); + protected PmcConfig _pmcConfig = _configServer.GetConfig(); /// /// Generate a player scav bot object @@ -223,7 +182,8 @@ public class BotGenerator var botLevel = _botLevelGenerator.GenerateBotLevel( botJsonTemplate.BotExperience.Level, botGenerationDetails, - bot); + bot + ); // Only filter bot equipment, never players if (!botGenerationDetails.IsPlayerScav.GetValueOrDefault(false)) @@ -232,14 +192,16 @@ public class BotGenerator sessionId, botJsonTemplate, botLevel.Level.Value, - botGenerationDetails); + botGenerationDetails + ); } bot.Info.Nickname = _botNameService.GenerateUniqueBotNickname( botJsonTemplate, botGenerationDetails, botRoleLowercase, - _botConfig.BotRolesThatMustHaveUniqueName); + _botConfig.BotRolesThatMustHaveUniqueName + ); bot.Info.LowerNickname = bot.Info.Nickname.ToLower(); // Only run when generating a 'fake' playerscav, not actual player scav @@ -256,7 +218,8 @@ public class BotGenerator { _seasonalEventService.RemoveChristmasItemsFromBotInventory( botJsonTemplate.BotInventory, - botGenerationDetails.Role); + botGenerationDetails.Role + ); } } @@ -273,15 +236,18 @@ public class BotGenerator bot.Info.Settings.Experience = GetExperienceRewardForKillByDifficulty( botJsonTemplate.BotExperience.Reward, botGenerationDetails.BotDifficulty, - botGenerationDetails.Role); + botGenerationDetails.Role + ); bot.Info.Settings.StandingForKill = GetStandingChangeForKillByDifficulty( botJsonTemplate.BotExperience.StandingForKill, botGenerationDetails.BotDifficulty, - botGenerationDetails.Role); + botGenerationDetails.Role + ); bot.Info.Settings.AggressorBonus = GetAgressorBonusByDifficulty( botJsonTemplate.BotExperience.StandingForKill, botGenerationDetails.BotDifficulty, - botGenerationDetails.Role); + botGenerationDetails.Role + ); bot.Info.Settings.UseSimpleAnimator = botJsonTemplate.BotExperience.UseSimpleAnimator ?? false; bot.Info.Voice = _weightedRandomHelper.GetWeightedValue(botJsonTemplate.BotAppearance.Voice); bot.Health = GenerateHealth(botJsonTemplate.BotHealth, botGenerationDetails.IsPlayerScav.GetValueOrDefault(false)); @@ -309,7 +275,8 @@ public class BotGenerator botRoleLowercase, botGenerationDetails.IsPmc.GetValueOrDefault(false), botLevel.Level.Value, - bot.Info.GameVersion); + bot.Info.GameVersion + ); if (_botConfig.BotRolesWithDogTags.Contains(botRoleLowercase)) { @@ -408,7 +375,8 @@ public class BotGenerator { var blacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist( _botGeneratorHelper.GetBotEquipmentRole(botGenerationDetails.Role), - botGenerationDetails.PlayerLevel.GetValueOrDefault(1)); + botGenerationDetails.PlayerLevel.GetValueOrDefault(1) + ); if (blacklist?.Gear is null) { @@ -683,31 +651,35 @@ public class BotGenerator if (skills is null) return []; - return skills.Select(kvp => - { - // Get skill from dict, skip if not found - var skill = kvp.Value; - if (skill == null) - { - return null; - } + return skills.Select( + kvp => + { + // Get skill from dict, skip if not found + var skill = kvp.Value; + if (skill == null) + { + return null; + } - // All skills have id and progress props - var skillToAdd = new BaseSkill - { - Id = kvp.Key, - Progress = _randomUtil.GetInt((int)skill.Min, (int)skill.Max) - }; + // All skills have id and progress props + var skillToAdd = new BaseSkill + { + Id = kvp.Key, + Progress = _randomUtil.GetInt((int)skill.Min, (int)skill.Max) + }; - // Common skills have additional props - if (isCommonSkills) - { - ((Common)skillToAdd).PointsEarnedDuringSession = 0; - ((Common)skillToAdd).LastAccess = 0; - } + // Common skills have additional props + if (isCommonSkills) + { + ((Common)skillToAdd).PointsEarnedDuringSession = 0; + ((Common)skillToAdd).LastAccess = 0; + } - return skillToAdd; - }).Where(baseSkill => baseSkill != null).ToList(); + return skillToAdd; + } + ) + .Where(baseSkill => baseSkill != null) + .ToList(); } /// @@ -718,7 +690,7 @@ public class BotGenerator public void AddIdsToBot(BotBase bot) { var botId = _hashUtil.Generate(); - + bot.Id = botId; bot.Aid = _hashUtil.GenerateAccountId(); } @@ -732,9 +704,11 @@ public class BotGenerator { var newInventoryItemId = _hashUtil.Generate(); - foreach (var item in profile.Inventory.Items) { + foreach (var item in profile.Inventory.Items) + { // Root item found, update its _id value to newly generated id - if (item.Template == ItemTpl.INVENTORY_DEFAULT) { + if (item.Template == ItemTpl.INVENTORY_DEFAULT) + { item.Id = newInventoryItemId; continue; @@ -742,12 +716,14 @@ public class BotGenerator // Optimisation - skip items without a parentId // They are never linked to root inventory item + we already handled root item above - if (item.ParentId is null) { + if (item.ParentId is null) + { continue; } // Item is a child of root inventory item, update its parentId value to newly generated id - if (item.ParentId == profile.Inventory.Equipment) { + if (item.ParentId == profile.Inventory.Equipment) + { item.ParentId = newInventoryItemId; } } @@ -766,7 +742,8 @@ public class BotGenerator public string SetRandomisedGameVersionAndCategory(Info botInfo) { // Special case - if (botInfo.Nickname?.ToLower() == "nikita") { + if (botInfo.Nickname?.ToLower() == "nikita") + { botInfo.GameVersion = GameEditions.UNHEARD; botInfo.MemberCategory = MemberCategory.DEVELOPER; @@ -777,7 +754,8 @@ public class BotGenerator botInfo.GameVersion = _weightedRandomHelper.GetWeightedValue(_pmcConfig.GameVersionWeight); // Choose appropriate member category value - switch (botInfo.GameVersion) { + switch (botInfo.GameVersion) + { case GameEditions.EDGE_OF_DARKNESS: botInfo.MemberCategory = MemberCategory.UNIQUE_ID; break; @@ -803,12 +781,14 @@ public class BotGenerator /// public void AddDogtagToBot(BotBase bot) { - Item inventoryItem = new () { + Item inventoryItem = new() + { Id = _hashUtil.Generate(), Template = GetDogtagTplByGameVersionAndSide(bot.Info.Side, bot.Info.GameVersion), ParentId = bot.Inventory.Equipment, SlotId = "Dogtag", - Upd = new () { + Upd = new() + { SpawnedInSession = true, }, }; @@ -824,8 +804,10 @@ public class BotGenerator /// item tpl public string GetDogtagTplByGameVersionAndSide(string side, string gameVersion) { - if (side.ToLower() == "usec") { - switch (gameVersion) { + if (side.ToLower() == "usec") + { + switch (gameVersion) + { case GameEditions.EDGE_OF_DARKNESS: return ItemTpl.BARTER_DOGTAG_USEC_EOD; case GameEditions.UNHEARD: @@ -835,7 +817,8 @@ public class BotGenerator } } - switch (gameVersion) { + switch (gameVersion) + { case GameEditions.EDGE_OF_DARKNESS: return ItemTpl.BARTER_DOGTAG_BEAR_EOD; case GameEditions.UNHEARD: @@ -851,7 +834,8 @@ public class BotGenerator /// Pmc object to adjust public void SetPmcPocketsByGameVersion(BotBase bot) { - if (bot.Info.GameVersion == GameEditions.UNHEARD) { + if (bot.Info.GameVersion == GameEditions.UNHEARD) + { var pockets = bot.Inventory.Items.FirstOrDefault((item) => item.SlotId == "Pockets"); pockets.Template = ItemTpl.POCKETS_1X4_TUE; } diff --git a/Core/Generators/BotInventoryGenerator.cs b/Core/Generators/BotInventoryGenerator.cs index 460b2eab..3a7cd59a 100644 --- a/Core/Generators/BotInventoryGenerator.cs +++ b/Core/Generators/BotInventoryGenerator.cs @@ -16,71 +16,28 @@ using Equipment = Core.Models.Eft.Common.Tables.Equipment; namespace Core.Generators; [Injectable] -public class BotInventoryGenerator +public class BotInventoryGenerator( + ISptLogger _logger, + HashUtil _hashUtil, + RandomUtil _randomUtil, + DatabaseService _databaseService, + ApplicationContext _applicationContext, + BotWeaponGenerator _botWeaponGenerator, + BotLootGenerator _botLootGenerator, + BotGeneratorHelper _botGeneratorHelper, + ProfileHelper _profileHelper, + BotHelper _botHelper, + WeightedRandomHelper _weightedRandomHelper, + ItemHelper _itemHelper, + WeatherHelper _weatherHelper, + LocalisationService _localisationService, + BotEquipmentFilterService _botEquipmentFilterService, + BotEquipmentModPoolService _botEquipmentModPoolService, + BotEquipmentModGenerator _botEquipmentModGenerator, + ConfigServer _configServer +) { - protected ISptLogger _logger; - protected HashUtil _hashUtil; - protected RandomUtil _randomUtil; - protected DatabaseService _databaseService; - protected ApplicationContext _applicationContext; - protected BotWeaponGenerator _botWeaponGenerator; - protected BotLootGenerator _botLootGenerator; - protected BotGeneratorHelper _botGeneratorHelper; - protected ProfileHelper _profileHelper; - protected BotHelper _botHelper; - protected WeightedRandomHelper _weightedRandomHelper; - protected ItemHelper _itemHelper; - protected WeatherHelper _weatherHelper; - protected LocalisationService _localisationService; - protected BotEquipmentFilterService _botEquipmentFilterService; - protected BotEquipmentModPoolService _botEquipmentModPoolService; - protected BotEquipmentModGenerator _botEquipmentModGenerator; - protected ConfigServer _configServer; - - private BotConfig _botConfig; - - public BotInventoryGenerator( - ISptLogger logger, - HashUtil hashUtil, - RandomUtil randomUtil, - DatabaseService databaseService, - ApplicationContext applicationContext, - BotWeaponGenerator botWeaponGenerator, - BotLootGenerator botLootGenerator, - BotGeneratorHelper botGeneratorHelper, - ProfileHelper profileHelper, - BotHelper botHelper, - WeightedRandomHelper weightedRandomHelper, - ItemHelper itemHelper, - WeatherHelper weatherHelper, - LocalisationService localisationService, - BotEquipmentFilterService botEquipmentFilterService, - BotEquipmentModPoolService botEquipmentModPoolService, - BotEquipmentModGenerator botEquipmentModGenerator, - ConfigServer configServer - ) - { - _logger = logger; - _hashUtil = hashUtil; - _randomUtil = randomUtil; - _databaseService = databaseService; - _applicationContext = applicationContext; - _botWeaponGenerator = botWeaponGenerator; - _botLootGenerator = botLootGenerator; - _botGeneratorHelper = botGeneratorHelper; - _profileHelper = profileHelper; - _botHelper = botHelper; - _weightedRandomHelper = weightedRandomHelper; - _itemHelper = itemHelper; - _weatherHelper = weatherHelper; - _localisationService = localisationService; - _botEquipmentFilterService = botEquipmentFilterService; - _botEquipmentModPoolService = botEquipmentModPoolService; - _botEquipmentModGenerator = botEquipmentModGenerator; - _configServer = configServer; - - _botConfig = _configServer.GetConfig(); - } + private BotConfig _botConfig = _configServer.GetConfig(); /// /// Add equipment/weapons/loot to bot @@ -114,7 +71,8 @@ public class BotInventoryGenerator botInventory, botLevel, chosenGameVersion, - raidConfig); + raidConfig + ); // Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed GenerateAndAddWeaponsToBot( @@ -125,7 +83,8 @@ public class BotInventoryGenerator botRole, isPmc, itemGenerationLimitsMinMax, - botLevel); + botLevel + ); // Pick loot and add to bots containers (rig/backpack/pockets/secure) _botLootGenerator.GenerateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel); @@ -209,7 +168,9 @@ public class BotInventoryGenerator { // Never let mod chance go outside of 0 - 100 randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] = Math.Min( - Math.Max(randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] + equipmentSlotKvP.Value, 0), 100); + Math.Max(randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] + equipmentSlotKvP.Value, 0), + 100 + ); } } @@ -230,10 +191,48 @@ public class BotInventoryGenerator continue; } - GenerateEquipment(new GenerateEquipmentProperties + GenerateEquipment( + new GenerateEquipmentProperties + { + RootEquipmentSlot = equipmentSlot, + RootEquipmentPool = value, + ModPool = templateInventory.Mods, + SpawnChances = wornItemChances, + BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, + Inventory = botInventory, + BotEquipmentConfig = botEquipConfig, + RandomisationDetails = randomistionDetails, + GeneratingPlayerLevel = pmcProfile.Info.Level, + } + ); + } + + // Generate below in specific order + GenerateEquipment( + new GenerateEquipmentProperties { - RootEquipmentSlot = equipmentSlot, - RootEquipmentPool = value, + RootEquipmentSlot = EquipmentSlots.Pockets, + // Unheard profiles have unique sized pockets, TODO - handle this somewhere else in a better way + RootEquipmentPool = + chosenGameVersion == GameEditions.UNHEARD + ? new Dictionary { [ItemTpl.POCKETS_1X4_TUE] = 1 } + : templateInventory.Equipment[EquipmentSlots.Pockets], + ModPool = templateInventory.Mods, + SpawnChances = wornItemChances, + BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, + Inventory = botInventory, + BotEquipmentConfig = botEquipConfig, + RandomisationDetails = randomistionDetails, + GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE], + GeneratingPlayerLevel = pmcProfile.Info.Level, + } + ); + + GenerateEquipment( + new GenerateEquipmentProperties + { + RootEquipmentSlot = EquipmentSlots.FaceCover, + RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.FaceCover], ModPool = templateInventory.Mods, SpawnChances = wornItemChances, BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, @@ -241,79 +240,53 @@ public class BotInventoryGenerator BotEquipmentConfig = botEquipConfig, RandomisationDetails = randomistionDetails, GeneratingPlayerLevel = pmcProfile.Info.Level, - }); - } + } + ); - // Generate below in specific order - GenerateEquipment(new GenerateEquipmentProperties - { - RootEquipmentSlot = EquipmentSlots.Pockets, - // Unheard profiles have unique sized pockets, TODO - handle this somewhere else in a better way - RootEquipmentPool = - chosenGameVersion == GameEditions.UNHEARD - ? new Dictionary { [ItemTpl.POCKETS_1X4_TUE] = 1 } - : templateInventory.Equipment[EquipmentSlots.Pockets], - ModPool = templateInventory.Mods, - SpawnChances = wornItemChances, - BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, - Inventory = botInventory, - BotEquipmentConfig = botEquipConfig, - RandomisationDetails = randomistionDetails, - GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE], - GeneratingPlayerLevel = pmcProfile.Info.Level, - }); + GenerateEquipment( + new GenerateEquipmentProperties + { + RootEquipmentSlot = EquipmentSlots.Headwear, + RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Headwear], + ModPool = templateInventory.Mods, + SpawnChances = wornItemChances, + BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, + Inventory = botInventory, + BotEquipmentConfig = botEquipConfig, + RandomisationDetails = randomistionDetails, + GeneratingPlayerLevel = pmcProfile.Info.Level, + } + ); - GenerateEquipment(new GenerateEquipmentProperties - { - RootEquipmentSlot = EquipmentSlots.FaceCover, - RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.FaceCover], - ModPool = templateInventory.Mods, - SpawnChances = wornItemChances, - BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, - Inventory = botInventory, - BotEquipmentConfig = botEquipConfig, - RandomisationDetails = randomistionDetails, - GeneratingPlayerLevel = pmcProfile.Info.Level, - }); + GenerateEquipment( + new GenerateEquipmentProperties + { + RootEquipmentSlot = EquipmentSlots.Earpiece, + RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece], + ModPool = templateInventory.Mods, + SpawnChances = wornItemChances, + BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, + Inventory = botInventory, + BotEquipmentConfig = botEquipConfig, + RandomisationDetails = randomistionDetails, + GeneratingPlayerLevel = pmcProfile.Info.Level, + } + ); - GenerateEquipment(new GenerateEquipmentProperties - { - RootEquipmentSlot = EquipmentSlots.Headwear, - RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Headwear], - ModPool = templateInventory.Mods, - SpawnChances = wornItemChances, - BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, - Inventory = botInventory, - BotEquipmentConfig = botEquipConfig, - RandomisationDetails = randomistionDetails, - GeneratingPlayerLevel = pmcProfile.Info.Level, - }); - - GenerateEquipment(new GenerateEquipmentProperties - { - RootEquipmentSlot = EquipmentSlots.Earpiece, - RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece], - ModPool = templateInventory.Mods, - SpawnChances = wornItemChances, - BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, - Inventory = botInventory, - BotEquipmentConfig = botEquipConfig, - RandomisationDetails = randomistionDetails, - GeneratingPlayerLevel = pmcProfile.Info.Level, - }); - - var hasArmorVest = GenerateEquipment(new GenerateEquipmentProperties - { - RootEquipmentSlot = EquipmentSlots.ArmorVest, - RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.ArmorVest], - ModPool = templateInventory.Mods, - SpawnChances = wornItemChances, - BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, - Inventory = botInventory, - BotEquipmentConfig = botEquipConfig, - RandomisationDetails = randomistionDetails, - GeneratingPlayerLevel = pmcProfile.Info.Level, - }); + var hasArmorVest = GenerateEquipment( + new GenerateEquipmentProperties + { + RootEquipmentSlot = EquipmentSlots.ArmorVest, + RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.ArmorVest], + ModPool = templateInventory.Mods, + SpawnChances = wornItemChances, + BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, + Inventory = botInventory, + BotEquipmentConfig = botEquipConfig, + RandomisationDetails = randomistionDetails, + GeneratingPlayerLevel = pmcProfile.Info.Level, + } + ); // Bot has no armor vest and flagged to be forced to wear armored rig in this event if (botEquipConfig.ForceOnlyArmoredRigWhenNoArmor.GetValueOrDefault(false) && !hasArmorVest) @@ -335,18 +308,20 @@ public class BotInventoryGenerator wornItemChances.EquipmentChances["TacticalVest"] = 100; } - GenerateEquipment(new GenerateEquipmentProperties - { - RootEquipmentSlot = EquipmentSlots.Earpiece, - RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece], - ModPool = templateInventory.Mods, - SpawnChances = wornItemChances, - BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, - Inventory = botInventory, - BotEquipmentConfig = botEquipConfig, - RandomisationDetails = randomistionDetails, - GeneratingPlayerLevel = pmcProfile.Info.Level, - }); + GenerateEquipment( + new GenerateEquipmentProperties + { + RootEquipmentSlot = EquipmentSlots.Earpiece, + RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece], + ModPool = templateInventory.Mods, + SpawnChances = wornItemChances, + BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole }, + Inventory = botInventory, + BotEquipmentConfig = botEquipConfig, + RandomisationDetails = randomistionDetails, + GeneratingPlayerLevel = pmcProfile.Info.Level, + } + ); } /// @@ -356,7 +331,8 @@ public class BotInventoryGenerator /// Role of bot vests are being filtered for public void FilterRigsToThoseWithProtection(Dictionary> templateEquipment, string botRole) { - var tacVestsWithArmor = templateEquipment[EquipmentSlots.TacticalVest].Where(kvp => _itemHelper.ItemHasSlots(kvp.Key)) + var tacVestsWithArmor = templateEquipment[EquipmentSlots.TacticalVest] + .Where(kvp => _itemHelper.ItemHasSlots(kvp.Key)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); if (!tacVestsWithArmor.Any()) @@ -375,9 +351,11 @@ public class BotInventoryGenerator /// Equipment to filter TacticalVest by /// Role of bot vests are being filtered for /// Should the function return all rigs when 0 unarmored are found - public void FilterRigsToThoseWithoutProtection(Dictionary> templateEquipment, string botRole, bool allowEmptyResult = true) + public void FilterRigsToThoseWithoutProtection(Dictionary> templateEquipment, string botRole, + bool allowEmptyResult = true) { - var tacVestsWithoutArmor = templateEquipment[EquipmentSlots.TacticalVest].Where(kvp => !_itemHelper.ItemHasSlots(kvp.Key)) + var tacVestsWithoutArmor = templateEquipment[EquipmentSlots.TacticalVest] + .Where(kvp => !_itemHelper.ItemHasSlots(kvp.Key)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); if (!allowEmptyResult && !tacVestsWithoutArmor.Any()) @@ -404,8 +382,12 @@ public class BotInventoryGenerator if (!spawnChance.HasValue) { - _logger.Warning(_localisationService.GetText("bot-no_spawn_chance_defined_for_equipment_slot", - settings.RootEquipmentSlot)); + _logger.Warning( + _localisationService.GetText( + "bot-no_spawn_chance_defined_for_equipment_slot", + settings.RootEquipmentSlot + ) + ); return false; } @@ -637,14 +619,15 @@ public class BotInventoryGenerator isPmc, botLevel ); - + botInventory.Items.AddRange(generatedWeapon.Weapon); - + _botWeaponGenerator.AddExtraMagazinesToInventory( generatedWeapon, itemGenerationWeights.Items.Magazines, botInventory, - botRole); + botRole + ); } } diff --git a/Core/Generators/BotLevelGenerator.cs b/Core/Generators/BotLevelGenerator.cs index 95a977a2..2ae56f7b 100644 --- a/Core/Generators/BotLevelGenerator.cs +++ b/Core/Generators/BotLevelGenerator.cs @@ -11,25 +11,13 @@ using Core.Utils; namespace Core.Generators; [Injectable] -public class BotLevelGenerator +public class BotLevelGenerator( + ISptLogger _logger, + RandomUtil _randomUtil, + MathUtil _mathUtil, + DatabaseService _databaseService +) { - protected ISptLogger _logger; - protected RandomUtil _randomUtil; - protected MathUtil _mathUtil; - protected DatabaseService _databaseService; - - public BotLevelGenerator( - ISptLogger logger, - RandomUtil randomUtil, - MathUtil mathUtil, - DatabaseService databaseService) - { - _logger = logger; - _randomUtil = randomUtil; - _mathUtil = mathUtil; - _databaseService = databaseService; - } - /// /// Return a randomised bot level and exp value /// @@ -44,8 +32,10 @@ public class BotLevelGenerator // Get random level based on the exp table. int exp = 0; - var level = int.Parse(ChooseBotLevel(botLevelRange.Min.Value, botLevelRange.Max.Value, 1, 1.15) - .ToString()); // TODO - nasty double to string to int conversion + var level = int.Parse( + ChooseBotLevel(botLevelRange.Min.Value, botLevelRange.Max.Value, 1, 1.15) + .ToString() + ); // TODO - nasty double to string to int conversion for (var i = 0; i < level; i++) { exp += expTable[i].Experience.Value; diff --git a/Core/Generators/BotLootGenerator.cs b/Core/Generators/BotLootGenerator.cs index c871299d..06213e17 100644 --- a/Core/Generators/BotLootGenerator.cs +++ b/Core/Generators/BotLootGenerator.cs @@ -13,63 +13,26 @@ using Core.Utils.Cloners; namespace Core.Generators; [Injectable] -public class BotLootGenerator +public class BotLootGenerator( + ISptLogger _logger, + HashUtil _hashUtil, + RandomUtil _randomUtil, + ItemHelper _itemHelper, + InventoryHelper _inventoryHelper, + DatabaseService _databaseService, + HandbookHelper _handbookHelper, + BotGeneratorHelper _botGeneratorHelper, + BotWeaponGenerator _botWeaponGenerator, + WeightedRandomHelper _weightedRandomHelper, + BotHelper _botHelper, + BotLootCacheService _botLootCacheService, + LocalisationService _localisationService, + ConfigServer _configServer, + ICloner _cloner +) { - private readonly ISptLogger _logger; - private readonly HashUtil _hashUtil; - private readonly RandomUtil _randomUtil; - private readonly ItemHelper _itemHelper; - private readonly InventoryHelper _inventoryHelper; - private readonly DatabaseService _databaseService; - private readonly HandbookHelper _handbookHelper; - private readonly BotGeneratorHelper _botGeneratorHelper; - private readonly BotWeaponGenerator _botWeaponGenerator; - private readonly WeightedRandomHelper _weightedRandomHelper; - private readonly BotHelper _botHelper; - private readonly BotLootCacheService _botLootCacheService; - private readonly LocalisationService _localisationService; - private readonly ConfigServer _configServer; - private readonly ICloner _cloner; - - private readonly BotConfig _botConfig; - private readonly PmcConfig _pmcConfig; - - public BotLootGenerator( - ISptLogger logger, - HashUtil hashUtil, - RandomUtil randomUtil, - ItemHelper itemHelper, - InventoryHelper inventoryHelper, - DatabaseService databaseService, - HandbookHelper handbookHelper, - BotGeneratorHelper botGeneratorHelper, - BotWeaponGenerator botWeaponGenerator, - WeightedRandomHelper weightedRandomHelper, - BotHelper botHelper, - BotLootCacheService botLootCacheService, - LocalisationService localisationService, - ConfigServer configServer, - ICloner cloner) - { - _logger = logger; - _hashUtil = hashUtil; - _randomUtil = randomUtil; - _itemHelper = itemHelper; - _inventoryHelper = inventoryHelper; - _databaseService = databaseService; - _handbookHelper = handbookHelper; - _botGeneratorHelper = botGeneratorHelper; - _botWeaponGenerator = botWeaponGenerator; - _weightedRandomHelper = weightedRandomHelper; - _botHelper = botHelper; - _botLootCacheService = botLootCacheService; - _localisationService = localisationService; - _configServer = configServer; - _cloner = cloner; - - _botConfig = _configServer.GetConfig(); - _pmcConfig = _configServer.GetConfig(); - } + protected BotConfig _botConfig = _configServer.GetConfig(); + protected PmcConfig _pmcConfig = _configServer.GetConfig(); /// /// @@ -361,13 +324,12 @@ public class BotLootGenerator { // TODO - extend to other bot types if (!isPmc) return null; - + var matchingValue = _pmcConfig?.LootItemLimitsRub?.FirstOrDefault( minMaxValue => botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max ); return matchingValue; - } /// @@ -380,12 +342,11 @@ public class BotLootGenerator private double? GetBackpackRoubleTotalByLevel(int botLevel, bool isPmc) { if (!isPmc) return 0; - + var matchingValue = _pmcConfig.MaxBackpackLootTotalRub.FirstOrDefault( (minMaxValue) => botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max ); return matchingValue?.Value; - } /// @@ -471,9 +432,9 @@ public class BotLootGenerator { // Loot pool has items var poolSize = pool.Count; - + if (poolSize <= 0) return; - + double currentTotalRub = 0; var fitItemIntoContainerAttempts = 0; @@ -487,7 +448,7 @@ public class BotLootGenerator var weightedItemTpl = _weightedRandomHelper.GetWeightedValue(pool); var (key, itemToAddTemplate) = _itemHelper.GetItem(weightedItemTpl); - + if (!key) { _logger.Warning($"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}"); @@ -628,7 +589,6 @@ public class BotLootGenerator var chosenStackCount = _weightedRandomHelper.GetWeightedValue(_botConfig.WalletLoot.StackSizeWeight); List items = [ - new Item { Id = _hashUtil.Generate(), @@ -639,8 +599,6 @@ public class BotLootGenerator StackObjectsCount = double.Parse(chosenStackCount) } } - - ]; result.Add(items); } @@ -773,18 +731,21 @@ public class BotLootGenerator private bool ItemHasReachedSpawnLimit(TemplateItem? itemTemplate, string botRole, ItemSpawnLimitSettings? itemSpawnLimits) { // PMCs and scavs have different sections of bot config for spawn limits - if (itemSpawnLimits is not null && itemSpawnLimits.GlobalLimits?.Count == 0) { + if (itemSpawnLimits is not null && itemSpawnLimits.GlobalLimits?.Count == 0) + { // No items found in spawn limit, drop out return false; } // No spawn limits, skipping - if (itemSpawnLimits is null) { + if (itemSpawnLimits is null) + { return false; } var idToCheckFor = GetMatchingIdFromSpawnLimits(itemTemplate, itemSpawnLimits.GlobalLimits); - if (idToCheckFor is null) { + if (idToCheckFor is null) + { // ParentId or tplid not found in spawnLimits, not a spawn limited item, skip return false; } @@ -793,15 +754,21 @@ public class BotLootGenerator itemSpawnLimits.CurrentLimits[idToCheckFor]++; // Check if over limit - if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.GlobalLimits[idToCheckFor]) { + if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.GlobalLimits[idToCheckFor]) + { // Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely - if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.CurrentLimits[idToCheckFor] * 10) { + if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.CurrentLimits[idToCheckFor] * 10) + { _logger.Debug( - _localisationService.GetText("bot-item_spawn_limit_reached_skipping_item", new { - botRole = botRole, - itemName = itemTemplate.Name, - attempts = itemSpawnLimits.CurrentLimits[idToCheckFor] - }) + _localisationService.GetText( + "bot-item_spawn_limit_reached_skipping_item", + new + { + botRole = botRole, + itemName = itemTemplate.Name, + attempts = itemSpawnLimits.CurrentLimits[idToCheckFor] + } + ) ); return false; @@ -823,8 +790,9 @@ public class BotLootGenerator { // Get all currency weights for this bot type var currencyWeights = _botConfig.CurrencyStackSize[botRole]; - if (currencyWeights is null) { - currencyWeights = new (); + if (currencyWeights is null) + { + currencyWeights = new(); } var currencyWeight = currencyWeights[moneyItem.Template]; @@ -856,17 +824,19 @@ public class BotLootGenerator /// Dictionary of tplIds and limit public Dictionary GetItemSpawnLimitsForBotType(string botRole) { - if (_botHelper.IsBotPmc(botRole)) { + if (_botHelper.IsBotPmc(botRole)) + { return _botConfig.ItemSpawnLimits["pmc"]; } - if (_botConfig.ItemSpawnLimits[botRole.ToLower()] is not null) { + if (_botConfig.ItemSpawnLimits[botRole.ToLower()] is not null) + { return _botConfig.ItemSpawnLimits[botRole.ToLower()]; } _logger.Warning(_localisationService.GetText("bot-unable_to_find_spawn_limits_fallback_to_defaults", botRole)); - - return new (); + + return new(); } /// @@ -877,12 +847,14 @@ public class BotLootGenerator /// id as string, otherwise undefined public string? GetMatchingIdFromSpawnLimits(TemplateItem itemTemplate, Dictionary spawnLimits) { - if (spawnLimits.ContainsKey(itemTemplate.Id)) { + if (spawnLimits.ContainsKey(itemTemplate.Id)) + { return itemTemplate.Id; } // tplId not found in spawnLimits, check if parentId is - if (spawnLimits.ContainsKey(itemTemplate.Parent)) { + if (spawnLimits.ContainsKey(itemTemplate.Parent)) + { return itemTemplate.Parent; } diff --git a/Core/Generators/BotWeaponGenerator.cs b/Core/Generators/BotWeaponGenerator.cs index cd7bde51..d77b1105 100644 --- a/Core/Generators/BotWeaponGenerator.cs +++ b/Core/Generators/BotWeaponGenerator.cs @@ -16,74 +16,40 @@ using Core.Utils.Cloners; namespace Core.Generators; [Injectable(InjectionType.Singleton)] -public class BotWeaponGenerator +public class BotWeaponGenerator( + ISptLogger _logger, + HashUtil _hashUtil, + DatabaseService _databaseService, + ItemHelper _itemHelper, + WeightedRandomHelper _weightedRandomHelper, + BotGeneratorHelper _botGeneratorHelper, + RandomUtil _randomUtil, + BotWeaponGeneratorHelper _botWeaponGeneratorHelper, + BotWeaponModLimitService _botWeaponModLimitService, + BotEquipmentModGenerator _botEquipmentModGenerator, + LocalisationService _localisationService, + RepairService _repairService, + ICloner _cloner, + ConfigServer _configServer, + IEnumerable inventoryMagGenComponents +) { - private readonly ISptLogger _logger; - private readonly HashUtil _hashUtil; - private readonly DatabaseService _databaseService; - private readonly ItemHelper _itemHelper; - private readonly WeightedRandomHelper _weightedRandomHelper; - private readonly BotGeneratorHelper _botGeneratorHelper; - private readonly RandomUtil _randomUtil; - private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper; - private readonly BotWeaponModLimitService _botWeaponModLimitService; - private readonly BotEquipmentModGenerator _botEquipmentModGenerator; - private readonly LocalisationService _localisationService; - private readonly RepairService _repairService; - private readonly ICloner _cloner; - private readonly ConfigServer _configServer; - private List _inventoryMagGenComponents; + protected List _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents); + protected BotConfig _botConfig = _configServer.GetConfig(); + protected PmcConfig _pmcConfig = _configServer.GetConfig(); + protected RepairConfig _repairConfig = _configServer.GetConfig(); + protected const string _modMagazineSlotId = "mod_magazine"; - private BotConfig _botConfig; - private PmcConfig _pmcConfig; - private RepairConfig _repairConfig; - private const string _modMagazineSlotId = "mod_magazine"; - - public BotWeaponGenerator - ( - ISptLogger logger, - HashUtil hashUtil, - DatabaseService databaseService, - ItemHelper itemHelper, - WeightedRandomHelper weightedRandomHelper, - BotGeneratorHelper botGeneratorHelper, - RandomUtil randomUtil, - BotWeaponGeneratorHelper botWeaponGeneratorHelper, - BotWeaponModLimitService botWeaponModLimitService, - BotEquipmentModGenerator botEquipmentModGenerator, - LocalisationService localisationService, - RepairService repairService, - ICloner cloner, - ConfigServer configServer, - IEnumerable inventoryMagGenComponents - ) + private static List MagGenSetUp(IEnumerable components) { - _logger = logger; - _hashUtil = hashUtil; - _databaseService = databaseService; - _itemHelper = itemHelper; - _weightedRandomHelper = weightedRandomHelper; - _botGeneratorHelper = botGeneratorHelper; - _randomUtil = randomUtil; - _botWeaponGeneratorHelper = botWeaponGeneratorHelper; - _botWeaponModLimitService = botWeaponModLimitService; - _botEquipmentModGenerator = botEquipmentModGenerator; - _localisationService = localisationService; - _repairService = repairService; - _cloner = cloner; - _configServer = configServer; - - inventoryMagGenComponents.ToList() + var inventoryMagGens = components.ToList(); + inventoryMagGens.ToList() .Sort( (a, b) => a.GetPriority() - b.GetPriority() ); - _inventoryMagGenComponents = inventoryMagGenComponents.ToList(); - - _botConfig = _configServer.GetConfig(); - _pmcConfig = _configServer.GetConfig(); - _repairConfig = _configServer.GetConfig(); + return inventoryMagGens.ToList(); } /// diff --git a/Core/Generators/FenceBaseAssortGenerator.cs b/Core/Generators/FenceBaseAssortGenerator.cs index 30feb25c..9b23a45f 100644 --- a/Core/Generators/FenceBaseAssortGenerator.cs +++ b/Core/Generators/FenceBaseAssortGenerator.cs @@ -1,17 +1,16 @@ using Core.Annotations; using Core.Models.Eft.Common.Tables; using Core.Models.Spt.Config; +using Core.Servers; namespace Core.Generators; [Injectable] -public class FenceBaseAssortGenerator +public class FenceBaseAssortGenerator( + ConfigServer _configServer +) { - private TraderConfig _traderConfig; - - public FenceBaseAssortGenerator() - { - } + protected TraderConfig _traderConfig = _configServer.GetConfig(); /// /// Create base fence assorts dynamically and store in memory diff --git a/Core/Generators/LocationLootGenerator.cs b/Core/Generators/LocationLootGenerator.cs index 16eed7a6..ac51d665 100644 --- a/Core/Generators/LocationLootGenerator.cs +++ b/Core/Generators/LocationLootGenerator.cs @@ -7,15 +7,13 @@ using Core.Models.Spt.Config; namespace Core.Generators; [Injectable] -public class LocationLootGenerator +public class LocationLootGenerator( + + ) { private LocationConfig _locationConfig; private SeasonalEventConfig _seasonalEventConfig; - public LocationLootGenerator() - { - } - /// Create a list of container objects with randomised loot /// /// Map base to generate containers for diff --git a/Core/Generators/LootGenerator.cs b/Core/Generators/LootGenerator.cs index 77a8c167..00fa2c1c 100644 --- a/Core/Generators/LootGenerator.cs +++ b/Core/Generators/LootGenerator.cs @@ -9,11 +9,9 @@ using Core.Models.Spt.Services; namespace Core.Generators; [Injectable] -public class LootGenerator +public class LootGenerator( + ) { - public LootGenerator() - { - } /// /// Generate a list of items based on configuration options parameter diff --git a/Core/Generators/PMCLootGenerator.cs b/Core/Generators/PMCLootGenerator.cs index 2e0748f6..855d3cad 100644 --- a/Core/Generators/PMCLootGenerator.cs +++ b/Core/Generators/PMCLootGenerator.cs @@ -4,11 +4,8 @@ using Core.Models.Eft.Common.Tables; namespace Core.Generators; [Injectable] -public class PMCLootGenerator +public class PMCLootGenerator() { - public PMCLootGenerator() - { - } /// /// Create a List of loot items a PMC can have in their pockets diff --git a/Core/Generators/PlayerScavGenerator.cs b/Core/Generators/PlayerScavGenerator.cs index 387e8a21..f2486bf3 100644 --- a/Core/Generators/PlayerScavGenerator.cs +++ b/Core/Generators/PlayerScavGenerator.cs @@ -14,66 +14,26 @@ using Core.Utils.Cloners; namespace Core.Generators; [Injectable] -public class PlayerScavGenerator +public class PlayerScavGenerator( + ISptLogger _logger, + RandomUtil _randomUtil, + DatabaseService _databaseService, + HashUtil _hashUtil, + ItemHelper _itemHelper, + BotGeneratorHelper _botGeneratorHelper, + SaveServer _saveServer, + ProfileHelper _profileHelper, + BotHelper _botHelper, + FenceService _fenceService, + BotLootCacheService _botLootCacheService, + LocalisationService _localisationService, + BotGenerator _botGenerator, + ConfigServer _configServer, + ICloner _cloner, + TimeUtil _timeUtil +) { - protected ISptLogger _logger; - protected RandomUtil _randomUtil; - protected DatabaseService _databaseService; - protected HashUtil _hashUtil; - protected ItemHelper _itemHelper; - protected BotGeneratorHelper _botGeneratorHelper; - protected SaveServer _saveServer; - protected ProfileHelper _profileHelper; - protected BotHelper _botHelper; - protected FenceService _fenceService; - protected BotLootCacheService _botLootCacheService; - protected LocalisationService _localisationService; - protected BotGenerator _botGenerator; - protected ConfigServer _configServer; - protected ICloner _cloner; - protected TimeUtil _timeUtil; - - private PlayerScavConfig _playerScavConfig; - - public PlayerScavGenerator - ( - ISptLogger logger, - RandomUtil randomUtil, - DatabaseService databaseService, - HashUtil hashUtil, - ItemHelper itemHelper, - BotGeneratorHelper botGeneratorHelper, - SaveServer saveServer, - ProfileHelper profileHelper, - BotHelper botHelper, - FenceService fenceService, - BotLootCacheService botLootCacheService, - LocalisationService localisationService, - BotGenerator botGenerator, - ConfigServer configServer, - ICloner cloner, - TimeUtil timeUtil - ) - { - _logger = logger; - _randomUtil = randomUtil; - _databaseService = databaseService; - _hashUtil = hashUtil; - _itemHelper = itemHelper; - _botGeneratorHelper = botGeneratorHelper; - _saveServer = saveServer; - _profileHelper = profileHelper; - _botHelper = botHelper; - _fenceService = fenceService; - _botLootCacheService = botLootCacheService; - _localisationService = localisationService; - _botGenerator = botGenerator; - _configServer = configServer; - _cloner = cloner; - _timeUtil = timeUtil; - - _playerScavConfig = configServer.GetConfig(); - } + protected PlayerScavConfig _playerScavConfig = _configServer.GetConfig(); /// /// Update a player profile to include a new player scav profile @@ -106,7 +66,8 @@ public class PlayerScavGenerator playerScavKarmaSettings.BotTypeForLoot.ToLower(), "easy", baseBotNode, - pmcDataClone); + pmcDataClone + ); // Remove cached bot data after scav was generated _botLootCacheService.ClearCache(); @@ -138,11 +99,15 @@ public class PlayerScavGenerator scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? new(); // Add additional items to player scav as loot - AddAdditionalLootToPlayerScavContainers(playerScavKarmaSettings.LootItemsToAddChancePercent, scavData, [ - EquipmentSlots.TacticalVest, - EquipmentSlots.Pockets, - EquipmentSlots.Backpack - ]); + AddAdditionalLootToPlayerScavContainers( + playerScavKarmaSettings.LootItemsToAddChancePercent, + scavData, + [ + EquipmentSlots.TacticalVest, + EquipmentSlots.Pockets, + EquipmentSlots.Backpack + ] + ); // Remove secure container scavData = _profileHelper.RemoveSecureContainer(scavData); @@ -162,7 +127,8 @@ public class PlayerScavGenerator /// dict of tpl + % chance to be added /// /// Possible slotIds to add loot to - protected void AddAdditionalLootToPlayerScavContainers(Dictionary possibleItemsToAdd, BotBase scavData, List containersToAddTo) + protected void AddAdditionalLootToPlayerScavContainers(Dictionary possibleItemsToAdd, BotBase scavData, + List containersToAddTo) { foreach (var tpl in possibleItemsToAdd) { @@ -193,7 +159,8 @@ public class PlayerScavGenerator itemsToAdd[0].Id, itemTemplate.Id, itemsToAdd, - scavData.Inventory); + scavData.Inventory + ); if (result != ItemAddedResult.SUCCESS) _logger.Debug($"Unable to add keycard to bot. Reason: {result.ToString()}"); @@ -252,8 +219,8 @@ public class PlayerScavGenerator protected void AdjustBotTemplateWithKarmaSpecificSettings(KarmaLevel karmaSettings, BotType baseBotNode) { // Adjust equipment chance values - foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment) { - + foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment) + { // Adjustment value zero, nothing to do if (equipmentKvP.Value == 0) { @@ -287,7 +254,8 @@ public class PlayerScavGenerator } // Blacklist equipment, keyed by equipment slot - foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist) { + foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist) + { baseBotNode.BotInventory.Equipment.TryGetValue(equipmentBlacklistKvP.Key, out var equipmentDict); foreach (var itemToRemove in equipmentBlacklistKvP.Value) { @@ -309,7 +277,7 @@ public class PlayerScavGenerator return new() { Common = new(), - Mastering = new (), + Mastering = new(), Points = 0 }; } diff --git a/Core/Generators/RagfairAssortGenerator.cs b/Core/Generators/RagfairAssortGenerator.cs index 7796f8b1..e133b98d 100644 --- a/Core/Generators/RagfairAssortGenerator.cs +++ b/Core/Generators/RagfairAssortGenerator.cs @@ -5,11 +5,8 @@ using Core.Models.Eft.Common.Tables; namespace Core.Generators; [Injectable] -public class RagfairAssortGenerator +public class RagfairAssortGenerator() { - public RagfairAssortGenerator() - { - } /// /// Get an array of arrays that can be sold on the flea diff --git a/Core/Generators/RagfairOfferGenerator.cs b/Core/Generators/RagfairOfferGenerator.cs index 8db0df07..62af8b9b 100644 --- a/Core/Generators/RagfairOfferGenerator.cs +++ b/Core/Generators/RagfairOfferGenerator.cs @@ -7,11 +7,8 @@ using Core.Models.Spt.Ragfair; namespace Core.Generators; [Injectable] -public class RagfairOfferGenerator +public class RagfairOfferGenerator() { - public RagfairOfferGenerator() - { - } /// /// Create a flea offer and store it in the Ragfair server offers list diff --git a/Core/Generators/RepeatableQuestGenerator.cs b/Core/Generators/RepeatableQuestGenerator.cs index ada78075..b6c90b67 100644 --- a/Core/Generators/RepeatableQuestGenerator.cs +++ b/Core/Generators/RepeatableQuestGenerator.cs @@ -16,43 +16,19 @@ using BodyPart = Core.Models.Spt.Config.BodyPart; namespace Core.Generators; [Injectable] -public class RepeatableQuestGenerator +public class RepeatableQuestGenerator( + ISptLogger _logger, + RandomUtil _randomUtil, + HashUtil _hashUtil, + MathUtil _mathUtil, + RepeatableQuestHelper _repeatableQuestHelper, + ItemHelper _itemHelper, + RepeatableQuestRewardGenerator _repeatableQuestRewardGenerator, + DatabaseService _databaseService, + ConfigServer _configServer +) { - protected ISptLogger _logger; - protected RandomUtil _randomUtil; - protected HashUtil _hashUtil; - protected MathUtil _mathUtil; - protected RepeatableQuestHelper _repeatableQuestHelper; - protected ItemHelper _itemHelper; - protected RepeatableQuestRewardGenerator _repeatableQuestRewardGenerator; - protected DatabaseService _databaseService; - protected ConfigServer _configServer; - protected QuestConfig _questConfig; - - public RepeatableQuestGenerator( - ISptLogger logger, - RandomUtil randomUtil, - HashUtil hashUtil, - MathUtil mathUtil, - RepeatableQuestHelper repeatableQuestHelper, - ItemHelper itemHelper, - RepeatableQuestRewardGenerator repeatableQuestRewardGenerator, - DatabaseService databaseService, - ConfigServer configServer - ) - { - _logger = logger; - _randomUtil = randomUtil; - _hashUtil = hashUtil; - _mathUtil = mathUtil; - _repeatableQuestHelper = repeatableQuestHelper; - _itemHelper = itemHelper; - _repeatableQuestRewardGenerator = repeatableQuestRewardGenerator; - _databaseService = databaseService; - _configServer = configServer; - - _questConfig = _configServer.GetConfig(); - } + protected QuestConfig _questConfig = _configServer.GetConfig(); /// /// This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). @@ -77,7 +53,8 @@ public class RepeatableQuestGenerator // Get traders from whitelist and filter by quest type availability var traders = repeatableConfig.TraderWhitelist .Where(x => x.QuestTypes.Contains(questType)) - .Select(x => x.TraderId).ToList(); + .Select(x => x.TraderId) + .ToList(); // filter out locked traders traders = traders.Where(x => pmcTraderInfo[x].Unlocked.GetValueOrDefault(false)).ToList(); var traderId = _randomUtil.DrawRandomFromList(traders).FirstOrDefault(); @@ -115,8 +92,10 @@ public class RepeatableQuestGenerator var locationsConfig = repeatableConfig.Locations; var targetsConfig = _repeatableQuestHelper.ProbabilityObjectArray(eliminationConfig.Targets); var bodyPartsConfig = _repeatableQuestHelper.ProbabilityObjectArray>(eliminationConfig.BodyParts); - var weaponCategoryRequirementConfig = _repeatableQuestHelper.ProbabilityObjectArray>(eliminationConfig.WeaponCategoryRequirements); - var weaponRequirementConfig = _repeatableQuestHelper.ProbabilityObjectArray>(eliminationConfig.WeaponRequirements); + var weaponCategoryRequirementConfig = + _repeatableQuestHelper.ProbabilityObjectArray>(eliminationConfig.WeaponCategoryRequirements); + var weaponRequirementConfig = + _repeatableQuestHelper.ProbabilityObjectArray>(eliminationConfig.WeaponRequirements); // the difficulty of the quest varies in difficulty depending on the condition // possible conditions are @@ -171,7 +150,7 @@ public class RepeatableQuestGenerator var locationKey = "any"; if (locations.Contains("any") && (eliminationConfig.SpecificLocationProbability < rand.Next() || locations.Count <= 1) - ) + ) { locationKey = "any"; questTypePool.Pool.Elimination.Targets.Remove(targetKey); @@ -183,7 +162,9 @@ public class RepeatableQuestGenerator { locationKey = _randomUtil.DrawRandomFromList(locations).FirstOrDefault(); questTypePool.Pool.Elimination.Targets.Get(targetKey).Locations = locations.Where( - (l) => l != locationKey).ToList(); + (l) => l != locationKey + ) + .ToList(); if (questTypePool.Pool.Elimination.Targets.Get(targetKey).Locations.Count == 0) { questTypePool.Pool.Elimination.Targets.Remove(targetKey); @@ -216,6 +197,7 @@ public class RepeatableQuestGenerator bodyPartsToClient.Add(biClient); } } + bodyPartDifficulty = 1 / probability; } @@ -227,17 +209,21 @@ public class RepeatableQuestGenerator if (targetsConfig.Data(targetKey).IsBoss.GetValueOrDefault(false)) { // Get all boss spawn information - var bossSpawns = _databaseService.GetLocations().GetDictionary() + var bossSpawns = _databaseService.GetLocations() + .GetDictionary() .Select(x => x.Value) .Where(x => x.Base?.Id != null) .Select(x => (new { x.Base.Id, BossSpawn = x.Base.BossLocationSpawn })); // filter for the current boss to spawn on map var thisBossSpawns = bossSpawns - .Select(x => new { - x.Id, - BossSpawn = x.BossSpawn - .Where(e => e.BossName == targetKey) - }) + .Select( + x => new + { + x.Id, + BossSpawn = x.BossSpawn + .Where(e => e.BossName == targetKey) + } + ) .Where((x) => x.BossSpawn.Count() > 0); // remove blacklisted locations var allowedSpawns = thisBossSpawns.Where((x) => !eliminationConfig.DistLocationBlacklist.Contains(x.Id)); @@ -250,7 +236,8 @@ public class RepeatableQuestGenerator // Random distance with lower values more likely; simple distribution for starters... distance = (int)Math.Floor( (decimal)(Math.Abs(rand.Next(0, 1) - rand.Next(0, 1)) * (1 + eliminationConfig.MaxDistance - eliminationConfig.MinDistance) + - eliminationConfig.MinDistance)); + eliminationConfig.MinDistance) + ); distance = (int)Math.Ceiling((decimal)(distance / 5)) * 5; distanceDifficulty = (int)(maxDistDifficulty * distance / eliminationConfig.MaxDistance); } @@ -263,16 +250,20 @@ public class RepeatableQuestGenerator { List weaponTypes = ["Shotgun", "Pistol"]; weaponCategoryRequirementConfig = (ProbabilityObjectArray>)weaponCategoryRequirementConfig - .Where((category) => weaponTypes - .Contains(category.Key)); + .Where( + (category) => weaponTypes + .Contains(category.Key) + ); } else if (distance < 20) { List weaponTypes = ["MarksmanRifle", "DMR"]; // Filter out far range weapons from close distance requirement weaponCategoryRequirementConfig = (ProbabilityObjectArray>)weaponCategoryRequirementConfig - .Where((category) => weaponTypes - .Contains(category.Key)); + .Where( + (category) => weaponTypes + .Contains(category.Key) + ); } // Pick a weighted weapon category @@ -304,7 +295,8 @@ public class RepeatableQuestGenerator bodyPartDifficulty / maxBodyPartsDifficulty.Value, distanceDifficulty / maxDistDifficulty, killDifficulty / maxKillDifficulty.Value, - allowedWeaponsCategory is not null || allowedWeapon is not null ? 1 : 0); + allowedWeaponsCategory is not null || allowedWeapon is not null ? 1 : 0 + ); // Aforementioned issue makes it a bit crazy since now all easier quests give significantly lower rewards than Completion / Exploration // I therefore moved the mapping a bit up (from 0.2...1 to 0.5...2) so that normal difficulty still gives good reward and having the @@ -326,16 +318,18 @@ public class RepeatableQuestGenerator // Only add specific location condition if specific map selected if (locationKey != "any") { - Enum.TryParse(typeof (ELocationName), locationKey, true, out var locationId); + Enum.TryParse(typeof(ELocationName), locationKey, true, out var locationId); availableForFinishCondition.Counter.Conditions.Add(GenerateEliminationLocation(locationsConfig[(ELocationName)locationId])); } + availableForFinishCondition.Counter.Conditions.Add( GenerateEliminationCondition( targetKey, bodyPartsToClient, distance.Value, allowedWeapon, - allowedWeaponsCategory) + allowedWeaponsCategory + ) ); availableForFinishCondition.Value = desiredKillCount; availableForFinishCondition.Id = _hashUtil.Generate(); @@ -346,7 +340,8 @@ public class RepeatableQuestGenerator Math.Min(difficulty, 1), traderId, repeatableConfig, - eliminationConfig); + eliminationConfig + ); return quest; } @@ -377,11 +372,11 @@ public class RepeatableQuestGenerator } protected double DifficultyWeighing( - double target, - double bodyPart, - int dist, - int kill, - int weaponRequirement) + double target, + double bodyPart, + int dist, + int kill, + int weaponRequirement) { return Math.Sqrt(Math.Sqrt(target) + bodyPart + dist + weaponRequirement) * kill; } @@ -430,15 +425,17 @@ public class RepeatableQuestGenerator string? allowedWeaponCategory ) { - var killConditionProps = new QuestConditionCounterCondition{ + var killConditionProps = new QuestConditionCounterCondition + { Id = _hashUtil.Generate(), DynamicLocale = true, Target = target, // e,g, "AnyPmc" Value = 1, ResetOnSessionEnd = false, EnemyHealthEffects = [], - Daytime = new DaytimeCounter(){ From = 0, To = 0 }, - ConditionType = "Kills"}; + Daytime = new DaytimeCounter() { From = 0, To = 0 }, + ConditionType = "Kills" + }; if (target.StartsWith("boss")) { @@ -455,7 +452,7 @@ public class RepeatableQuestGenerator // Don't allow distance + melee requirement if (distance is not null && allowedWeaponCategory != "5b5f7a0886f77409407a7f96") { - killConditionProps.Distance = new CounterConditionDistance{ CompareMethod = ">=", Value = distance.Value }; + killConditionProps.Distance = new CounterConditionDistance { CompareMethod = ">=", Value = distance.Value }; } // Has specific weapon requirement diff --git a/Core/Generators/RepeatableQuestRewardGenerator.cs b/Core/Generators/RepeatableQuestRewardGenerator.cs index d741e0c5..3362c508 100644 --- a/Core/Generators/RepeatableQuestRewardGenerator.cs +++ b/Core/Generators/RepeatableQuestRewardGenerator.cs @@ -10,327 +10,302 @@ using Core.Services; using Core.Utils; using Core.Utils.Cloners; -namespace Core.Generators +namespace Core.Generators; + +[Injectable] +public class RepeatableQuestRewardGenerator( + ISptLogger _logger, + RandomUtil _randomUtil, + HashUtil _hashUtil, + MathUtil _mathUtil, + DatabaseService _databaseService, + ItemHelper _itemHelper, + PresetHelper _presetHelper, + HandbookHelper _handbookHelper, + LocalisationService _localisationService, + ItemFilterService _itemFilterService, + SeasonalEventService _seasonalEventService, + ConfigServer _configServer, + ICloner _cloner +) { - [Injectable] - public class RepeatableQuestRewardGenerator + protected QuestConfig _questConfig = _configServer.GetConfig(); + + /** + * Generate the reward for a mission. A reward can consist of: + * - Experience + * - Money + * - GP coins + * - Weapon preset + * - Items + * - Trader Reputation + * - Skill level experience + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config + * + * Additionally, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * @param pmcLevel Level of player reward is being generated for + * @param difficulty Reward scaling factor from 0.2 to 1 + * @param traderId Trader reward will be given by + * @param repeatableConfig Config for quest type (daily, weekly) + * @param questConfig + * @param rewardTplBlacklist OPTIONAL: list of tpls to NOT use when picking a reward + * @returns IQuestRewards + */ + public QuestRewards GenerateReward( + int pmcLevel, + double difficulty, + string traderId, + RepeatableQuestConfig repeatableConfig, + EliminationConfig eliminationConfig, + List? rewardTplBlacklist = null) { - #region Ctor & Params + // Get vars to configure rewards with + var rewardParams = GetQuestRewardValues(repeatableConfig.RewardScaling, difficulty, pmcLevel); - private readonly ISptLogger _logger; - private readonly RandomUtil _randomUtil; - private readonly HashUtil _hashUtil; - private readonly MathUtil _mathUtil; - private readonly DatabaseService _databaseService; - private readonly ItemHelper _itemHelper; - private readonly PresetHelper _presetHelper; - private readonly HandbookHelper _handbookHelper; - private readonly LocalisationService _localisationService; - private readonly ItemFilterService _itemFilterService; - private readonly SeasonalEventService _seasonalEventService; - private readonly ConfigServer _configServer; - private readonly ICloner _cloner; - private readonly QuestConfig _questConfig; + // Get budget to spend on item rewards (copy of raw roubles given) + var itemRewardBudget = rewardParams.RewardRoubles; - public RepeatableQuestRewardGenerator - ( - ISptLogger logger, - RandomUtil randomUtil, - HashUtil hashUtil, - MathUtil mathUtil, - DatabaseService databaseService, - ItemHelper itemHelper, - PresetHelper presetHelper, - HandbookHelper handbookHelper, - LocalisationService localisationService, - ItemFilterService itemFilterService, - SeasonalEventService seasonalEventService, - ConfigServer configServer, - ICloner cloner - ) + // Possible improvement -> draw trader-specific items e.g. with this.itemHelper.isOfBaseclass(val._id, ItemHelper.BASECLASS.FoodDrink) + QuestRewards rewards = new() { Started = [], Success = [], Fail = [] }; + + // Start reward index to keep track + var rewardIndex = -1; + + // Add xp reward + if (rewardParams.RewardXP > 0) { - _logger = logger; - _randomUtil = randomUtil; - _hashUtil = hashUtil; - _mathUtil = mathUtil; - _databaseService = databaseService; - _itemHelper = itemHelper; - _presetHelper = presetHelper; - _handbookHelper = handbookHelper; - _localisationService = localisationService; - _itemFilterService = itemFilterService; - _seasonalEventService = seasonalEventService; - _configServer = configServer; - _cloner = cloner; - - _questConfig = _configServer.GetConfig(); - } - - #endregion - - /** - * Generate the reward for a mission. A reward can consist of: - * - Experience - * - Money - * - GP coins - * - Weapon preset - * - Items - * - Trader Reputation - * - Skill level experience - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config - * - * Additionally, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * @param pmcLevel Level of player reward is being generated for - * @param difficulty Reward scaling factor from 0.2 to 1 - * @param traderId Trader reward will be given by - * @param repeatableConfig Config for quest type (daily, weekly) - * @param questConfig - * @param rewardTplBlacklist OPTIONAL: list of tpls to NOT use when picking a reward - * @returns IQuestRewards - */ - public QuestRewards GenerateReward( - int pmcLevel, - double difficulty, - string traderId, - RepeatableQuestConfig repeatableConfig, - EliminationConfig eliminationConfig, - List? rewardTplBlacklist = null) - { - // Get vars to configure rewards with - var rewardParams = GetQuestRewardValues(repeatableConfig.RewardScaling, difficulty, pmcLevel); - - // Get budget to spend on item rewards (copy of raw roubles given) - var itemRewardBudget = rewardParams.RewardRoubles; - - // Possible improvement -> draw trader-specific items e.g. with this.itemHelper.isOfBaseclass(val._id, ItemHelper.BASECLASS.FoodDrink) - QuestRewards rewards = new() { Started = [], Success = [], Fail = [] }; - - // Start reward index to keep track - var rewardIndex = -1; - - // Add xp reward - if (rewardParams.RewardXP > 0) - { - rewards.Success.Add( - new() - { - Id = _hashUtil.Generate(), - Unknown = false, - GameMode = [], - AvailableInGameEditions = [], - Index = rewardIndex, - Value = rewardParams.RewardXP, - Type = RewardType.Experience - } - ); - rewardIndex++; - } - - // Add money reward - rewards.Success.Add(GetMoneyReward(traderId, rewardParams.RewardRoubles, rewardIndex)); - rewardIndex++; - - // Add GP coin reward - rewards.Success.Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount, rewardIndex)); - rewardIndex++; - - // Add preset weapon to reward if checks pass - var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault( - (traderWhitelist) => traderWhitelist.TraderId == traderId - ); - if (traderWhitelistDetails?.RewardCanBeWeapon ?? false && _randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent ?? 0) - ) - { - var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex); - if (chosenWeapon is not null) - { - rewards.Success.Add(chosenWeapon.Value.Key); - - // Subtract price of preset from item budget so we dont give player too much stuff - itemRewardBudget -= (int)chosenWeapon.Value.Value; - rewardIndex++; - } - } - - var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(repeatableConfig, itemRewardBudget, traderId); - if (rewardTplBlacklist is not null) - { - // Filter reward pool of items from blacklist, only use if there's at least 1 item remaining - var filteredRewardItemPool = inBudgetRewardItemPool.Where( - (item) => !rewardTplBlacklist.Contains(item.Id) - ); - if (filteredRewardItemPool.Count() > 0) - { - inBudgetRewardItemPool = filteredRewardItemPool.ToList(); - } - } - - - _logger.Debug( - $"Generating: {repeatableConfig.Name} quest for: {traderId} with budget: {itemRewardBudget} totalling: {rewardParams.RewardNumItems} items" - ); - if (inBudgetRewardItemPool.Count > 0) - { - var itemsToReward = GetRewardableItemsFromPoolWithinBudget( - inBudgetRewardItemPool, - rewardParams.RewardNumItems, - itemRewardBudget, - repeatableConfig - ); - - // Add item rewards - foreach (var itemReward in itemsToReward) - { - rewards.Success.Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex)); - rewardIndex++; - } - } - - // Add rep reward to rewards array - if (rewardParams.RewardReputation > 0) - { - Reward reward = new() + rewards.Success.Add( + new() { Id = _hashUtil.Generate(), Unknown = false, GameMode = [], AvailableInGameEditions = [], - Target = traderId, - Value = rewardParams.RewardReputation, - Type = RewardType.TraderStanding, - Index = rewardIndex - }; - rewards.Success.Add(reward); - rewardIndex++; - - _logger.Debug($"Adding: {rewardParams.RewardReputation} {traderId} trader reputation reward"); - } - - // Chance of adding skill reward - if (_randomUtil.GetChance100((double)rewardParams.SkillRewardChance * 100)) - { - var targetSkill = _randomUtil.GetArrayValue(eliminationConfig.PossibleSkillRewards); - Reward reward = new() - { - Id = _hashUtil.Generate(), - Unknown = false, - GameMode = [], - AvailableInGameEditions = [], - Target = targetSkill, - Value = rewardParams.SkillPointReward, - Type = RewardType.Skill, - Index = rewardIndex - }; - rewards.Success.Add(reward); - - _logger.Debug($"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}"); - } - - return rewards; + Index = rewardIndex, + Value = rewardParams.RewardXP, + Type = RewardType.Experience + } + ); + rewardIndex++; } - private QuestRewardValues GetQuestRewardValues(RewardScaling? rewardScaling, double? difficulty, int pmcLevel) + // Add money reward + rewards.Success.Add(GetMoneyReward(traderId, rewardParams.RewardRoubles, rewardIndex)); + rewardIndex++; + + // Add GP coin reward + rewards.Success.Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount, rewardIndex)); + rewardIndex++; + + // Add preset weapon to reward if checks pass + var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault( + (traderWhitelist) => traderWhitelist.TraderId == traderId + ); + if (traderWhitelistDetails?.RewardCanBeWeapon ?? false && _randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent ?? 0) + ) { - // difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward - var levelsConfig = rewardScaling.Levels; - var roublesConfig = rewardScaling.Roubles; - var gpCoinConfig = rewardScaling.GpCoins; - var xpConfig = rewardScaling.Experience; - var itemsConfig = rewardScaling.Items; - var rewardSpreadConfig = rewardScaling.RewardSpread; - var skillRewardChanceConfig = rewardScaling.SkillRewardChance; - var skillPointRewardConfig = rewardScaling.SkillPointReward; - var reputationConfig = rewardScaling.Reputation; - - var effectiveDifficulty = difficulty is null ? 1 : difficulty; - if (difficulty is null) + var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex); + if (chosenWeapon is not null) { - _logger.Warning(_localisationService.GetText("repeatable-difficulty_was_nan")); - } + rewards.Success.Add(chosenWeapon.Value.Key); - return new () { - SkillPointReward = _mathUtil.Interp1(pmcLevel, levelsConfig, skillPointRewardConfig), - SkillRewardChance = _mathUtil.Interp1(pmcLevel, levelsConfig, skillRewardChanceConfig), - RewardReputation = GetRewardRep(effectiveDifficulty, pmcLevel, levelsConfig, reputationConfig, rewardSpreadConfig), - RewardNumItems = GetRewardNumItems(pmcLevel, levelsConfig, itemsConfig), - RewardRoubles = GetRewardRoubles(effectiveDifficulty, pmcLevel, levelsConfig, roublesConfig, rewardSpreadConfig), - GpCoinRewardCount = GetGpCoinRewardCount(effectiveDifficulty, pmcLevel, levelsConfig, gpCoinConfig, rewardSpreadConfig), - RewardXP = GetRewardXp(effectiveDifficulty, pmcLevel, levelsConfig, xpConfig, rewardSpreadConfig), + // Subtract price of preset from item budget so we dont give player too much stuff + itemRewardBudget -= (int)chosenWeapon.Value.Value; + rewardIndex++; + } + } + + var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(repeatableConfig, itemRewardBudget, traderId); + if (rewardTplBlacklist is not null) + { + // Filter reward pool of items from blacklist, only use if there's at least 1 item remaining + var filteredRewardItemPool = inBudgetRewardItemPool.Where( + (item) => !rewardTplBlacklist.Contains(item.Id) + ); + if (filteredRewardItemPool.Count() > 0) + { + inBudgetRewardItemPool = filteredRewardItemPool.ToList(); + } + } + + + _logger.Debug( + $"Generating: {repeatableConfig.Name} quest for: {traderId} with budget: {itemRewardBudget} totalling: {rewardParams.RewardNumItems} items" + ); + if (inBudgetRewardItemPool.Count > 0) + { + var itemsToReward = GetRewardableItemsFromPoolWithinBudget( + inBudgetRewardItemPool, + rewardParams.RewardNumItems, + itemRewardBudget, + repeatableConfig + ); + + // Add item rewards + foreach (var itemReward in itemsToReward) + { + rewards.Success.Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex)); + rewardIndex++; + } + } + + // Add rep reward to rewards array + if (rewardParams.RewardReputation > 0) + { + Reward reward = new() + { + Id = _hashUtil.Generate(), + Unknown = false, + GameMode = [], + AvailableInGameEditions = [], + Target = traderId, + Value = rewardParams.RewardReputation, + Type = RewardType.TraderStanding, + Index = rewardIndex }; + rewards.Success.Add(reward); + rewardIndex++; + + _logger.Debug($"Adding: {rewardParams.RewardReputation} {traderId} trader reputation reward"); } - private double GetRewardXp(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? xpConfig, double? rewardSpreadConfig) + // Chance of adding skill reward + if (_randomUtil.GetChance100((double)rewardParams.SkillRewardChance * 100)) { - return Math.Floor((effectiveDifficulty - * _mathUtil.Interp1(pmcLevel, levelsConfig, xpConfig) - * _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) - ?? 0); + var targetSkill = _randomUtil.GetArrayValue(eliminationConfig.PossibleSkillRewards); + Reward reward = new() + { + Id = _hashUtil.Generate(), + Unknown = false, + GameMode = [], + AvailableInGameEditions = [], + Target = targetSkill, + Value = rewardParams.SkillPointReward, + Type = RewardType.Skill, + Index = rewardIndex + }; + rewards.Success.Add(reward); + + _logger.Debug($"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}"); } - private double GetGpCoinRewardCount(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? gpCoinConfig, - double? rewardSpreadConfig) + return rewards; + } + + private QuestRewardValues GetQuestRewardValues(RewardScaling? rewardScaling, double? difficulty, int pmcLevel) + { + // difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward + var levelsConfig = rewardScaling.Levels; + var roublesConfig = rewardScaling.Roubles; + var gpCoinConfig = rewardScaling.GpCoins; + var xpConfig = rewardScaling.Experience; + var itemsConfig = rewardScaling.Items; + var rewardSpreadConfig = rewardScaling.RewardSpread; + var skillRewardChanceConfig = rewardScaling.SkillRewardChance; + var skillPointRewardConfig = rewardScaling.SkillPointReward; + var reputationConfig = rewardScaling.Reputation; + + var effectiveDifficulty = difficulty is null ? 1 : difficulty; + if (difficulty is null) { - return Math.Ceiling((effectiveDifficulty - * _mathUtil.Interp1(pmcLevel, levelsConfig, gpCoinConfig) - * _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) - ?? 0); + _logger.Warning(_localisationService.GetText("repeatable-difficulty_was_nan")); } - private double GetRewardRep(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? reputationConfig, double? rewardSpreadConfig) + return new() { - return Math.Round(100 * effectiveDifficulty - * _mathUtil.Interp1(pmcLevel, levelsConfig, reputationConfig) - * _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig)) - ?? 0) / 100; - } + SkillPointReward = _mathUtil.Interp1(pmcLevel, levelsConfig, skillPointRewardConfig), + SkillRewardChance = _mathUtil.Interp1(pmcLevel, levelsConfig, skillRewardChanceConfig), + RewardReputation = GetRewardRep(effectiveDifficulty, pmcLevel, levelsConfig, reputationConfig, rewardSpreadConfig), + RewardNumItems = GetRewardNumItems(pmcLevel, levelsConfig, itemsConfig), + RewardRoubles = GetRewardRoubles(effectiveDifficulty, pmcLevel, levelsConfig, roublesConfig, rewardSpreadConfig), + GpCoinRewardCount = GetGpCoinRewardCount(effectiveDifficulty, pmcLevel, levelsConfig, gpCoinConfig, rewardSpreadConfig), + RewardXP = GetRewardXp(effectiveDifficulty, pmcLevel, levelsConfig, xpConfig, rewardSpreadConfig), + }; + } - private double GetRewardNumItems(int pmcLevel, List? levelsConfig, List? itemsConfig) - { - return _randomUtil.RandInt(1, (int)Math.Round(_mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig) ?? 0) + 1); - } + private double GetRewardXp(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? xpConfig, double? rewardSpreadConfig) + { + return Math.Floor( + (effectiveDifficulty * + _mathUtil.Interp1(pmcLevel, levelsConfig, xpConfig) * + _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) ?? + 0 + ); + } - private double GetRewardRoubles(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? roublesConfig, double? rewardSpreadConfig) - { - return Math.Floor((effectiveDifficulty - * _mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) - * _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) - ?? 0); - } + private double GetGpCoinRewardCount(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? gpCoinConfig, + double? rewardSpreadConfig) + { + return Math.Ceiling( + (effectiveDifficulty * + _mathUtil.Interp1(pmcLevel, levelsConfig, gpCoinConfig) * + _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) ?? + 0 + ); + } - private List> GetRewardableItemsFromPoolWithinBudget(List inBudgetRewardItemPool, - object rewardNumItems, double? itemRewardBudget, RepeatableQuestConfig repeatableConfig) - { - throw new NotImplementedException(); - } + private double GetRewardRep(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? reputationConfig, + double? rewardSpreadConfig) + { + return Math.Round( + 100 * + effectiveDifficulty * + _mathUtil.Interp1(pmcLevel, levelsConfig, reputationConfig) * + _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig)) ?? + 0 + ) / + 100; + } - private List ChooseRewardItemsWithinBudget(RepeatableQuestConfig repeatableConfig, double? itemRewardBudget, string traderId) - { - throw new NotImplementedException(); - } + private double GetRewardNumItems(int pmcLevel, List? levelsConfig, List? itemsConfig) + { + return _randomUtil.RandInt(1, (int)Math.Round(_mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig) ?? 0) + 1); + } - private KeyValuePair? GetRandomWeaponPresetWithinBudget(double? itemRewardBudget, double rewardIndex) - { - throw new NotImplementedException(); - } + private double GetRewardRoubles(double? effectiveDifficulty, int pmcLevel, List? levelsConfig, List? roublesConfig, + double? rewardSpreadConfig) + { + return Math.Floor( + (effectiveDifficulty * + _mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) * + _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) ?? + 0 + ); + } - private Reward GenerateItemReward(string d235b4d86f7742e017bc88a, object gpCoinRewardCount, double rewardIndex) - { - throw new NotImplementedException(); - } + private List> GetRewardableItemsFromPoolWithinBudget(List inBudgetRewardItemPool, + object rewardNumItems, double? itemRewardBudget, RepeatableQuestConfig repeatableConfig) + { + throw new NotImplementedException(); + } - private Reward GetMoneyReward(string traderId, object rewardRoubles, double rewardIndex) - { - throw new NotImplementedException(); - } + private List ChooseRewardItemsWithinBudget(RepeatableQuestConfig repeatableConfig, double? itemRewardBudget, string traderId) + { + throw new NotImplementedException(); + } + + private KeyValuePair? GetRandomWeaponPresetWithinBudget(double? itemRewardBudget, double rewardIndex) + { + throw new NotImplementedException(); + } + + private Reward GenerateItemReward(string d235b4d86f7742e017bc88a, object gpCoinRewardCount, double rewardIndex) + { + throw new NotImplementedException(); + } + + private Reward GetMoneyReward(string traderId, object rewardRoubles, double rewardIndex) + { + throw new NotImplementedException(); + } - public Dictionary> GetRewardableItems(RepeatableQuestConfig repeatableConfig, string traderId) - { - throw new NotImplementedException(); - } + public Dictionary> GetRewardableItems(RepeatableQuestConfig repeatableConfig, string traderId) + { + throw new NotImplementedException(); } } diff --git a/Core/Generators/ScavCaseRewardGenerator.cs b/Core/Generators/ScavCaseRewardGenerator.cs index cbfe2b9c..5bf2095f 100644 --- a/Core/Generators/ScavCaseRewardGenerator.cs +++ b/Core/Generators/ScavCaseRewardGenerator.cs @@ -6,11 +6,8 @@ using Core.Models.Spt.Hideout; namespace Core.Generators; [Injectable] -public class ScavCaseRewardGenerator +public class ScavCaseRewardGenerator() { - public ScavCaseRewardGenerator() - { - } /// /// Create an array of rewards that will be given to the player upon completing their scav case build diff --git a/Core/Generators/WeaponGen/Implementations/BarrelInvetoryMagGen.cs b/Core/Generators/WeaponGen/Implementations/BarrelInvetoryMagGen.cs index 0571f149..b30c9d18 100644 --- a/Core/Generators/WeaponGen/Implementations/BarrelInvetoryMagGen.cs +++ b/Core/Generators/WeaponGen/Implementations/BarrelInvetoryMagGen.cs @@ -5,21 +5,11 @@ using Core.Utils; namespace Core.Generators.WeaponGen.Implementations; [Injectable] -public class BarrelInvetoryMagGen : InventoryMagGen, IInventoryMagGen +public class BarrelInvetoryMagGen( + RandomUtil _randomUtil, + BotWeaponGeneratorHelper _botWeaponGeneratorHelper +) : InventoryMagGen, IInventoryMagGen { - private readonly RandomUtil _randomUtil; - private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper; - - public BarrelInvetoryMagGen - ( - RandomUtil randomUtil, - BotWeaponGeneratorHelper botWeaponGeneratorHelper - ) - { - _randomUtil = randomUtil; - _botWeaponGeneratorHelper = botWeaponGeneratorHelper; - } - public int GetPriority() { return 50; diff --git a/Core/Generators/WeaponGen/Implementations/ExternalInventoryMagGen.cs b/Core/Generators/WeaponGen/Implementations/ExternalInventoryMagGen.cs index 52234784..53fba2fd 100644 --- a/Core/Generators/WeaponGen/Implementations/ExternalInventoryMagGen.cs +++ b/Core/Generators/WeaponGen/Implementations/ExternalInventoryMagGen.cs @@ -9,32 +9,15 @@ using Core.Utils; namespace Core.Generators.WeaponGen.Implementations; [Injectable] -public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen +public class ExternalInventoryMagGen( + ISptLogger _logger, + ItemHelper _itemHelper, + LocalisationService _localisationService, + BotWeaponGeneratorHelper _botWeaponGeneratorHelper, + BotGeneratorHelper _botGeneratorHelper, + RandomUtil _randomUtil +) : InventoryMagGen, IInventoryMagGen { - private readonly ISptLogger _logger; - private readonly ItemHelper _itemHelper; - private readonly LocalisationService _localisationService; - private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper; - private readonly BotGeneratorHelper _botGeneratorHelper; - private readonly RandomUtil _randomUtil; - - public ExternalInventoryMagGen - ( - ISptLogger logger, - ItemHelper itemHelper, - LocalisationService localisationService, - BotWeaponGeneratorHelper botWeaponGeneratorHelper, - BotGeneratorHelper botGeneratorHelper, - RandomUtil randomUtil - ) - { - _logger = logger; - _itemHelper = itemHelper; - _localisationService = localisationService; - _botWeaponGeneratorHelper = botWeaponGeneratorHelper; - _botGeneratorHelper = botGeneratorHelper; - _randomUtil = randomUtil; - } public int GetPriority() { @@ -58,7 +41,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen List attemptedMagBlacklist = []; var defaultMagazineTpl = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(weapon); var randomizedMagazineCount = _botWeaponGeneratorHelper.GetRandomizedMagazineCount(inventoryMagGen.GetMagCount()); - for (var i = 0; i < randomizedMagazineCount; i++) { + for (var i = 0; i < randomizedMagazineCount; i++) + { var magazineWithAmmo = _botWeaponGeneratorHelper.CreateMagazineWithAmmo( magazineTpl, inventoryMagGen.GetAmmoTemplate().Id, @@ -73,15 +57,18 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen inventoryMagGen.GetPmcInventory() ); - if (fitsIntoInventory == ItemAddedResult.NO_CONTAINERS) { + if (fitsIntoInventory == ItemAddedResult.NO_CONTAINERS) + { // No containers to fit magazines, stop trying break; } // No space for magazine and we haven't reached desired magazine count - if (fitsIntoInventory == ItemAddedResult.NO_SPACE && i < randomizedMagazineCount) { + if (fitsIntoInventory == ItemAddedResult.NO_SPACE && i < randomizedMagazineCount) + { // Prevent infinite loop by only allowing 5 attempts at fitting a magazine into inventory - if (fitAttempts > 5) { + if (fitAttempts > 5) + { _logger.Debug($"Failed {fitAttempts} times to add magazine {magazineTpl} to bot inventory, stopping"); break; @@ -91,7 +78,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen * so we fallback to default magazine and try again. * Temporary workaround to Killa spawning with no extra mags if he spawns with a drum mag */ - if (magazineTpl == defaultMagazineTpl) { + if (magazineTpl == defaultMagazineTpl) + { // We were already on default - stop here to prevent infinite looping break; } @@ -102,7 +90,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen // Set chosen magazine tpl to the weapons default magazine tpl and try to fit into inventory next loop magazineTpl = defaultMagazineTpl; magTemplate = _itemHelper.GetItem(magazineTpl).Value; - if (magTemplate is null) { + if (magTemplate is null) + { _logger.Error( _localisationService.GetText("bot-unable_to_find_default_magazine_item", magazineTpl) ); @@ -111,12 +100,14 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen } // Edge case - some weapons (SKS) have an internal magazine as default, choose random non-internal magazine to add to bot instead - if (magTemplate.Properties.ReloadMagType == "InternalMagazine") { + if (magTemplate.Properties.ReloadMagType == "InternalMagazine") + { var result = GetRandomExternalMagazineForInternalMagazineGun( inventoryMagGen.GetWeaponTemplate().Id, attemptedMagBlacklist ); - if (result?.Id is null) { + if (result?.Id is null) + { _logger.Debug($"Unable to add additional magazine into bot inventory for weapon: {weapon.Name}, attempted: {fitAttempts} times"); break; @@ -131,7 +122,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen i--; } - if (fitsIntoInventory == ItemAddedResult.SUCCESS) { + if (fitsIntoInventory == ItemAddedResult.SUCCESS) + { // Reset fit counter now it succeeded fitAttempts = 0; } @@ -142,21 +134,26 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen { // The mag Slot data for the weapon var magSlot = _itemHelper.GetItem(weaponTpl).Value.Properties.Slots.FirstOrDefault((x) => x.Name == "mod_magazine"); - if (magSlot is null) { + if (magSlot is null) + { return null; } // All possible mags that fit into the weapon excluding blacklisted - var magazinePool = magSlot.Props.Filters[0].Filter.Where((x) => !magazineBlacklist.Contains(x)).Select( - (x) => _itemHelper.GetItem(x).Value - ); - if (magazinePool is null) { + var magazinePool = magSlot.Props.Filters[0] + .Filter.Where((x) => !magazineBlacklist.Contains(x)) + .Select( + (x) => _itemHelper.GetItem(x).Value + ); + if (magazinePool is null) + { return null; } // Non-internal magazines that fit into the weapon var externalMagazineOnlyPool = magazinePool.Where((x) => x.Properties.ReloadMagType != "InternalMagazine"); - if (externalMagazineOnlyPool is null || externalMagazineOnlyPool?.Count() == 0) { + if (externalMagazineOnlyPool is null || externalMagazineOnlyPool?.Count() == 0) + { return null; } diff --git a/Core/Generators/WeaponGen/Implementations/InternalMagazineInventoryMagGen.cs b/Core/Generators/WeaponGen/Implementations/InternalMagazineInventoryMagGen.cs index 76991706..b38d0acf 100644 --- a/Core/Generators/WeaponGen/Implementations/InternalMagazineInventoryMagGen.cs +++ b/Core/Generators/WeaponGen/Implementations/InternalMagazineInventoryMagGen.cs @@ -4,18 +4,10 @@ using Core.Helpers; namespace Core.Generators.WeaponGen.Implementations; [Injectable] -public class InternalMagazineInventoryMagGen : InventoryMagGen, IInventoryMagGen +public class InternalMagazineInventoryMagGen( + BotWeaponGeneratorHelper _botWeaponGeneratorHelper +) : InventoryMagGen, IInventoryMagGen { - private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper; - - public InternalMagazineInventoryMagGen - ( - BotWeaponGeneratorHelper botWeaponGeneratorHelper - ) - { - _botWeaponGeneratorHelper = botWeaponGeneratorHelper; - } - public int GetPriority() { return 0; @@ -35,7 +27,7 @@ public class InternalMagazineInventoryMagGen : InventoryMagGen, IInventoryMagGen _botWeaponGeneratorHelper.AddAmmoIntoEquipmentSlots( inventoryMagGen.GetAmmoTemplate().Id, (int)bulletCount, - inventoryMagGen.GetPmcInventory(), + inventoryMagGen.GetPmcInventory(), null ); } diff --git a/Core/Generators/WeaponGen/Implementations/UbglExternalMagGen.cs b/Core/Generators/WeaponGen/Implementations/UbglExternalMagGen.cs index 1045918c..ae48579f 100644 --- a/Core/Generators/WeaponGen/Implementations/UbglExternalMagGen.cs +++ b/Core/Generators/WeaponGen/Implementations/UbglExternalMagGen.cs @@ -5,18 +5,11 @@ using Core.Models.Enums; namespace Core.Generators.WeaponGen.Implementations; [Injectable] -public class UbglExternalMagGen : InventoryMagGen, IInventoryMagGen +public class UbglExternalMagGen( + BotWeaponGeneratorHelper _botWeaponGeneratorHelper + +) : InventoryMagGen, IInventoryMagGen { - private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper; - - public UbglExternalMagGen - ( - BotWeaponGeneratorHelper botWeaponGeneratorHelper - ) - { - _botWeaponGeneratorHelper = botWeaponGeneratorHelper; - } - public int GetPriority() { return 1; diff --git a/Core/Generators/WeaponGen/InventoryMagGen.cs b/Core/Generators/WeaponGen/InventoryMagGen.cs index e2ed2bd2..bf7788c8 100644 --- a/Core/Generators/WeaponGen/InventoryMagGen.cs +++ b/Core/Generators/WeaponGen/InventoryMagGen.cs @@ -4,7 +4,7 @@ using Core.Models.Eft.Common.Tables; namespace Core.Generators.WeaponGen; [Injectable] -public class InventoryMagGen +public class InventoryMagGen() { private GenerationData _magCounts; private TemplateItem _magazineTemplate; @@ -12,10 +12,6 @@ public class InventoryMagGen private TemplateItem _ammoTemplate; private BotBaseInventory _pmcInventory; - public InventoryMagGen() - { - } - public InventoryMagGen ( GenerationData magCounts, @@ -23,7 +19,7 @@ public class InventoryMagGen TemplateItem weaponTemplate, TemplateItem ammoTemplate, BotBaseInventory pmcInventory - ) + ) : this() { _magCounts = magCounts; _magazineTemplate = magazineTemplate; diff --git a/Core/Generators/WeatherGenerator.cs b/Core/Generators/WeatherGenerator.cs index d7fb519c..8ff4dabc 100644 --- a/Core/Generators/WeatherGenerator.cs +++ b/Core/Generators/WeatherGenerator.cs @@ -10,34 +10,16 @@ using Core.Utils; namespace Core.Generators; [Injectable] -public class WeatherGenerator +public class WeatherGenerator( + TimeUtil _timeUtil, + SeasonalEventService _seasonalEventService, + WeatherHelper _weatherHelper, + ConfigServer _configServer, + WeightedRandomHelper _weightedRandomHelper, + RandomUtil _randomUtil +) { - protected TimeUtil _timeUtil; - protected SeasonalEventService _seasonalEventService; - protected WeatherHelper _weatherHelper; - protected ConfigServer _configServer; - protected WeightedRandomHelper _weightedRandomHelper; - protected RandomUtil _randomUtil; - protected WeatherConfig _weatherConfig; - - public WeatherGenerator( - TimeUtil timeUtil, - SeasonalEventService seasonalEventService, - WeatherHelper weatherHelper, - ConfigServer configServer, - WeightedRandomHelper weightedRandomHelper, - RandomUtil randomUtil - ) - { - _timeUtil = timeUtil; - _seasonalEventService = seasonalEventService; - _weatherHelper = weatherHelper; - _configServer = configServer; - _weightedRandomHelper = weightedRandomHelper; - _randomUtil = randomUtil; - - _weatherConfig = _configServer.GetConfig(); - } + protected WeatherConfig _weatherConfig = _configServer.GetConfig(); /** * Get current + raid datetime and format into correct BSG format and return @@ -47,13 +29,13 @@ public class WeatherGenerator public void CalculateGameTime(WeatherData data) { var computedDate = DateTime.Now; - var formattedDate = this._timeUtil.FormatDate(computedDate); + var formattedDate = _timeUtil.FormatDate(computedDate); data.Date = formattedDate; data.Time = GetBsgFormattedInRaidTime(); - data.Acceleration = this._weatherConfig.Acceleration; + data.Acceleration = _weatherConfig.Acceleration; - data.Season = this._seasonalEventService.GetActiveWeatherSeason(); + data.Season = _seasonalEventService.GetActiveWeatherSeason(); } /** @@ -64,7 +46,7 @@ public class WeatherGenerator */ protected string GetBsgFormattedInRaidTime() { - var clientAcceleratedDate = this._weatherHelper.GetInRaidTime(); + var clientAcceleratedDate = _weatherHelper.GetInRaidTime(); return GetBsgFormattedTime(clientAcceleratedDate); } @@ -121,10 +103,10 @@ public class WeatherGenerator protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason) { - var result = this._weatherConfig.Weather.SeasonValues.TryGetValue(currentSeason.ToString(), out var value); + var result = _weatherConfig.Weather.SeasonValues.TryGetValue(currentSeason.ToString(), out var value); if (!result) { - return this._weatherConfig.Weather.SeasonValues["default"]; + return _weatherConfig.Weather.SeasonValues["default"]; } return value!; @@ -158,7 +140,7 @@ public class WeatherGenerator var normalTime = GetBsgFormattedTime(inRaidTime); var formattedDate = _timeUtil.FormatDate(timestamp.HasValue ? _timeUtil.GetDateTimeFromTimeStamp(timestamp.Value) : DateTime.UtcNow); var datetimeBsgFormat = $"{formattedDate} {normalTime}"; - + weather.Timestamp = timestamp ?? _timeUtil.GetTimeStampFromEpoch(inRaidTime) / 1000; // matches weather.date weather.Date = formattedDate; // matches weather.timestamp weather.Time = datetimeBsgFormat; // matches weather.timestamp