From 8de6a8be94a4d9e47b2ed1b738ed94863733a731 Mon Sep 17 00:00:00 2001 From: CWX Date: Sat, 25 Jan 2025 21:25:03 +0000 Subject: [PATCH] FixieWixie --- .../Generators/BotEquipmentModGenerator.cs | 167 +++++++++++------- 1 file changed, 102 insertions(+), 65 deletions(-) diff --git a/Libraries/Core/Generators/BotEquipmentModGenerator.cs b/Libraries/Core/Generators/BotEquipmentModGenerator.cs index dab34590..fc6a45fc 100644 --- a/Libraries/Core/Generators/BotEquipmentModGenerator.cs +++ b/Libraries/Core/Generators/BotEquipmentModGenerator.cs @@ -37,7 +37,8 @@ public class BotEquipmentModGenerator( BotEquipmentModPoolService _botEquipmentModPoolService, ConfigServer _configServer, ICloner _cloner -) { +) +{ protected BotConfig _botConfig = _configServer.GetConfig(); /// @@ -51,23 +52,28 @@ public class BotEquipmentModGenerator( /// should this mod be forced to spawn /// Item + compatible mods as an array public List GenerateModsForEquipment(List equipment, string parentId, TemplateItem parentTemplate, GenerateEquipmentProperties settings, - EquipmentFilterDetails specificBlacklist, bool shouldForceSpawn = false) { + EquipmentFilterDetails specificBlacklist, bool shouldForceSpawn = false) + { var forceSpawn = shouldForceSpawn; // Get mod pool for the desired item - if (!settings.ModPool.TryGetValue(parentTemplate.Id, out var compatibleModsPool)) { + if (!settings.ModPool.TryGetValue(parentTemplate.Id, out var compatibleModsPool)) + { _logger.Warning($"bot: {settings.BotData.Role} lacks a mod slot pool for item: {parentTemplate.Id} {parentTemplate.Name}"); } // Iterate over mod pool and choose mods to add to item - foreach (var (modSlotName, modPool) in compatibleModsPool ?? []) { + foreach (var (modSlotName, modPool) in compatibleModsPool ?? []) + { // Get the templates slot object from db var itemSlotTemplate = GetModItemSlotFromDb(modSlotName, parentTemplate); - if (itemSlotTemplate is null) { + if (itemSlotTemplate is null) + { _logger.Error( _localisationService.GetText( "bot-mod_slot_missing_from_item", - new { + new + { modSlot = modSlotName, parentId = parentTemplate.Id, parentName = parentTemplate.Name, @@ -87,12 +93,14 @@ public class BotEquipmentModGenerator( ); // Rolled to skip mod and it shouldn't be force-spawned - if (modSpawnResult == ModSpawn.SKIP && !forceSpawn) { + if (modSpawnResult == ModSpawn.SKIP && !forceSpawn) + { continue; } // Ensure submods for nvgs all spawn together - if (modSlotName == "mod_nvg") { + if (modSlotName == "mod_nvg") + { forceSpawn = true; } @@ -101,7 +109,8 @@ public class BotEquipmentModGenerator( // Filter the pool of items in blacklist var filteredModPool = FilterModsByBlacklist(modPoolToChooseFrom, specificBlacklist, modSlotName); - if (filteredModPool.Count > 0) { + if (filteredModPool.Count > 0) + { // use filtered pool as it has items in it modPoolToChooseFrom = filteredModPool; } @@ -110,14 +119,16 @@ public class BotEquipmentModGenerator( if ( settings.BotEquipmentConfig.FilterPlatesByLevel.GetValueOrDefault(false) && _itemHelper.IsRemovablePlateSlot(modSlotName.ToLower()) - ) { + ) + { var plateSlotFilteringOutcome = FilterPlateModsForSlotByLevel( settings, modSlotName.ToLower(), compatibleModsPool[modSlotName], parentTemplate ); - switch (plateSlotFilteringOutcome.Result) { + 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" @@ -139,23 +150,27 @@ public class BotEquipmentModGenerator( string modTpl = null; var found = false; var exhaustableModPool = CreateExhaustableArray(modPoolToChooseFrom.ToList()); - while (exhaustableModPool.HasValues()) { + while (exhaustableModPool.HasValues()) + { modTpl = exhaustableModPool.GetRandomValue(); if (modTpl is not null && - !_botGeneratorHelper.IsItemIncompatibleWithCurrentItems(equipment, modTpl, modSlotName).Incompatible.GetValueOrDefault(false)) { + !_botGeneratorHelper.IsItemIncompatibleWithCurrentItems(equipment, modTpl, modSlotName).Incompatible.GetValueOrDefault(false)) + { found = true; break; } } // Compatible item not found but slot REQUIRES item, get random item from db - if (!found && itemSlotTemplate.Required.GetValueOrDefault(false)) { + if (!found && itemSlotTemplate.Required.GetValueOrDefault(false)) + { modTpl = GetRandomModTplFromItemDb(modTpl, itemSlotTemplate, modSlotName, equipment); found = modTpl is not null; } // Compatible item not found + not required - skip - if (!(found || itemSlotTemplate.Required.GetValueOrDefault(false))) { + if (!(found || itemSlotTemplate.Required.GetValueOrDefault(false))) + { continue; } @@ -169,7 +184,8 @@ public class BotEquipmentModGenerator( parentTemplate, settings.BotData.Role ) - ) { + ) + { continue; } @@ -180,7 +196,8 @@ public class BotEquipmentModGenerator( ); // Does item being added exist in mod pool - has its own mod pool - if (settings.ModPool.ContainsKey(modTpl)) { + if (settings.ModPool.ContainsKey(modTpl)) + { // Call self again with mod being added as item to add child mods to GenerateModsForEquipment( equipment, @@ -205,14 +222,17 @@ public class BotEquipmentModGenerator( /// The armor items db template /// Array of plate tpls to choose from public FilterPlateModsForSlotByLevelResult FilterPlateModsForSlotByLevel(GenerateEquipmentProperties settings, string modSlot, - HashSet existingPlateTplPool, TemplateItem armorItem) { - var result = new FilterPlateModsForSlotByLevelResult { + HashSet existingPlateTplPool, TemplateItem armorItem) + { + var result = new FilterPlateModsForSlotByLevelResult + { Result = Result.UNKNOWN_FAILURE, PlateModTemplates = null, }; // Not pmc or not a plate slot, return original mod pool array - if (!_itemHelper.IsRemovablePlateSlot(modSlot)) { + if (!_itemHelper.IsRemovablePlateSlot(modSlot)) + { result.Result = Result.NOT_PLATE_HOLDING_SLOT; result.PlateModTemplates = existingPlateTplPool; @@ -224,8 +244,10 @@ public class BotEquipmentModGenerator( (armorWeight) => settings.BotData.Level >= armorWeight.LevelRange.Min && settings.BotData.Level <= armorWeight.LevelRange.Max - ); - if (plateSlotWeights is null) { + ); + + if (plateSlotWeights is null) + { // No weights, return original array of plate tpls result.Result = Result.LACKS_PLATE_WEIGHTS; result.PlateModTemplates = existingPlateTplPool; @@ -235,7 +257,8 @@ public class BotEquipmentModGenerator( // Get the specific plate slot weights (front/back/side) var plateWeights = plateSlotWeights[modSlot]; - if (plateWeights is null) { + if (plateWeights is null) + { // No weights, return original array of plate tpls result.Result = Result.LACKS_PLATE_WEIGHTS; result.PlateModTemplates = existingPlateTplPool; @@ -251,7 +274,8 @@ public class BotEquipmentModGenerator( // Filter plates to the chosen level based on its armorClass property var platesOfDesiredLevel = platesFromDb.Filter((item) => item._props.armorClass == chosenArmorPlateLevel); - if (platesOfDesiredLevel.length > 0) { + if (platesOfDesiredLevel.length > 0) + { // Plates found result.Result = Result.SUCCESS; result.PlateModTemplates = platesOfDesiredLevel.map((item) => item._id); @@ -262,65 +286,73 @@ public class BotEquipmentModGenerator( // no plates found that fit requirements, lets get creative // Get lowest and highest plate classes available for this armor - const minMaxArmorPlateClass = this.getMinMaxArmorPlateClass(platesFromDb); + const minMaxArmorPlateClass = this.getMinMaxArmorPlateClass(platesFromDb); // Increment plate class level in attempt to get useable plate let findCompatiblePlateAttempts = 0; - const maxAttempts = 3; - for (let i = 0; i < maxAttempts; i++) { + const maxAttempts = 3; + for (let i = 0; i < maxAttempts; i++) + { chosenArmorPlateLevel = (Number.parseInt(chosenArmorPlateLevel) + 1).toString(); // New chosen plate class is higher than max, then set to min and check if valid - if (Number(chosenArmorPlateLevel) > minMaxArmorPlateClass.max) { + if (Number(chosenArmorPlateLevel) > minMaxArmorPlateClass.max) + { chosenArmorPlateLevel = minMaxArmorPlateClass.min.toString(); } findCompatiblePlateAttempts++; - platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel); + platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass == = chosenArmorPlateLevel); // Valid plates found, exit - if (platesOfDesiredLevel.length > 0) { + if (platesOfDesiredLevel.length > 0) + { break; } // No valid plate class found in 3 tries, attempt default plates - if (findCompatiblePlateAttempts >= maxAttempts) { + if (findCompatiblePlateAttempts >= maxAttempts) + { this.logger.debug( - `Plate filter too restrictive for armor: ${ armorItem._name} ${ armorItem._id}, unable to find plates of level: ${ chosenArmorPlateLevel}, using items default plate`, + $"Plate filter too restrictive for armor: ${{ armorItem._name}} ${{ armorItem._id}}, unable to find plates of level: ${{ chosenArmorPlateLevel}}, using items default plate" ); - const defaultPlate = this.getDefaultPlateTpl(armorItem, modSlot); - if (defaultPlate) { - // Return Default Plates cause couldn't get lowest level available from original selection - result.result = Result.SUCCESS; - result.plateModTpls = [defaultPlate]; + const defaultPlate = this.getDefaultPlateTpl(armorItem, modSlot); + if (defaultPlate) + { + // Return Default Plates cause couldn't get lowest level available from original selection + result.result = Result.SUCCESS; + result.plateModTpls = [defaultPlate]; - return result; + return result; + } + + // No plate found after filtering AND no default plate + + // Last attempt, get default preset and see if it has a plate default + const defaultPresetPlateSlot = this.getDefaultPresetArmorSlot(armorItem._id, modSlot); + if (defaultPresetPlateSlot) + { + // Found a plate, exit + const plateItem = this.itemHelper.getItem(defaultPresetPlateSlot._tpl); + platesOfDesiredLevel = [plateItem[1]]; + + break; + } + + // Everything failed, no default plate or no default preset armor plate + result.result = Result.NO_DEFAULT_FILTER; + + return result; + } } - - // No plate found after filtering AND no default plate - - // Last attempt, get default preset and see if it has a plate default - const defaultPresetPlateSlot = this.getDefaultPresetArmorSlot(armorItem._id, modSlot); - if (defaultPresetPlateSlot) { - // Found a plate, exit - const plateItem = this.itemHelper.getItem(defaultPresetPlateSlot._tpl); - platesOfDesiredLevel = [plateItem[1]]; - - break; - } - - // Everything failed, no default plate or no default preset armor plate - result.result = Result.NO_DEFAULT_FILTER; - - return result; - } - + // Only return the items ids result.result = Result.SUCCESS; result.plateModTpls = platesOfDesiredLevel.map((item) => item._id); return result; + } /** * Get the default plate an armor has in its db item @@ -457,7 +489,7 @@ public class BotEquipmentModGenerator( } if (!IsModValidForSlot(modToAdd, modsParentSlot, modSlot, request.ParentTemplate, request.BotData.Role) - ) + ) { continue; } @@ -608,7 +640,6 @@ public class BotEquipmentModGenerator( request.ModPool[modToAddTemplate.Value.Id] = modFromService; containsModInPool = true; } - } if (containsModInPool) @@ -1033,10 +1064,13 @@ public class BotEquipmentModGenerator( var weaponTpl = modSpawnRequest.Weapon[0].Template; modSpawnRequest.RandomisationSettings.MinimumMagazineSize.TryGetValue(weaponTpl, out var minMagSizeFromSettings); var minMagazineSize = minMagSizeFromSettings; - var desiredMagazineTpls = modPool.Where((magTpl) => { - var magazineDb = _itemHelper.GetItem(magTpl).Value; - return magazineDb.Properties is not null && magazineDb.Properties.Cartridges.FirstOrDefault().MaxCount >= minMagazineSize; - }); + var desiredMagazineTpls = modPool.Where( + (magTpl) => + { + var magazineDb = _itemHelper.GetItem(magTpl).Value; + return magazineDb.Properties is not null && magazineDb.Properties.Cartridges.FirstOrDefault().MaxCount >= minMagazineSize; + } + ); if (!desiredMagazineTpls.Any()) { @@ -1467,7 +1501,8 @@ public class BotEquipmentModGenerator( /// db object for modItem we get compatible mods from /// Pool of mods we are adding to /// A blacklist of items that cannot be picked - public void AddCompatibleModsForProvidedMod(string desiredSlotName, TemplateItem modTemplate, Dictionary>> modPool, + public void AddCompatibleModsForProvidedMod(string desiredSlotName, TemplateItem modTemplate, + Dictionary>> modPool, EquipmentFilterDetails botEquipBlacklist) { var desiredSlotObject = modTemplate.Properties.Slots?.FirstOrDefault((slot) => slot.Name.Contains(desiredSlotName)); @@ -1670,7 +1705,9 @@ public class BotEquipmentModGenerator( var whitelistedSightTypes = botWeaponSightWhitelist[weaponDetails.Value.Parent]; if (whitelistedSightTypes is null) { - _logger.Debug($"Unable to find whitelist for weapon type: {weaponDetails.Value.Parent} {weaponDetails.Value.Name}, skipping sight filtering"); + _logger.Debug( + $"Unable to find whitelist for weapon type: {weaponDetails.Value.Parent} {weaponDetails.Value.Name}, skipping sight filtering" + ); return scopes; }