BotGen fixes
This commit is contained in:
@@ -147,7 +147,7 @@ public class BotEquipmentModGenerator(
|
||||
// Choose random mod from pool and check its compatibility
|
||||
string modTpl = null;
|
||||
var found = false;
|
||||
var exhaustableModPool = CreateExhaustableArray(modPoolToChooseFrom);
|
||||
var exhaustableModPool = CreateExhaustableArray(modPoolToChooseFrom.ToList());
|
||||
while (exhaustableModPool.HasValues())
|
||||
{
|
||||
modTpl = exhaustableModPool.GetRandomValue();
|
||||
@@ -220,7 +220,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="armorItem">The armor items db template</param>
|
||||
/// <returns>Array of plate tpls to choose from</returns>
|
||||
public FilterPlateModsForSlotByLevelResult FilterPlateModsForSlotByLevel(GenerateEquipmentProperties settings, string modSlot,
|
||||
List<string> existingPlateTplPool, TemplateItem armorItem)
|
||||
HashSet<string> existingPlateTplPool, TemplateItem armorItem)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -359,8 +359,7 @@ public class BotEquipmentModGenerator(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
IsModValidForSlot(modToAdd, modsParentSlot, modSlot, request.ParentTemplate, request.BotData.Role)
|
||||
if (!IsModValidForSlot(modToAdd, modsParentSlot, modSlot, request.ParentTemplate, request.BotData.Role)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
@@ -837,7 +836,7 @@ public class BotEquipmentModGenerator(
|
||||
);
|
||||
if (onlyLowProfileGasBlocks.Count() > 0)
|
||||
{
|
||||
modPool = onlyLowProfileGasBlocks.ToList();
|
||||
modPool = onlyLowProfileGasBlocks.ToHashSet();
|
||||
}
|
||||
}
|
||||
else if (request.WeaponStats.HasRearIronSight ?? false && modPool.Count() > 1)
|
||||
@@ -848,7 +847,7 @@ public class BotEquipmentModGenerator(
|
||||
);
|
||||
if (onlyHighProfileGasBlocks.Count() > 0)
|
||||
{
|
||||
modPool = onlyHighProfileGasBlocks.ToList();
|
||||
modPool = onlyHighProfileGasBlocks.ToHashSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -860,7 +859,7 @@ public class BotEquipmentModGenerator(
|
||||
request.RandomisationSettings.MinimumMagazineSize is not null
|
||||
)
|
||||
{
|
||||
modPool = GetFilterdMagazinePoolByCapacity(request, modPool).ToList();
|
||||
modPool = GetFilterdMagazinePoolByCapacity(request, modPool).ToHashSet();
|
||||
}
|
||||
|
||||
// Pick random mod that's compatible
|
||||
@@ -919,7 +918,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="modPool">Pool of magazine tpls to filter</param>
|
||||
/// <returns>Filtered pool of magazine tpls</returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public IEnumerable<string> GetFilterdMagazinePoolByCapacity(ModToSpawnRequest modSpawnRequest, List<string> modPool)
|
||||
public IEnumerable<string> GetFilterdMagazinePoolByCapacity(ModToSpawnRequest modSpawnRequest, HashSet<string> modPool)
|
||||
{
|
||||
var weaponTpl = modSpawnRequest.Weapon[0].Template;
|
||||
modSpawnRequest.RandomisationSettings.MinimumMagazineSize.TryGetValue(weaponTpl, out var minMagSizeFromSettings);
|
||||
@@ -950,7 +949,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="weapon">Array of weapon items chosen item will be added to</param>
|
||||
/// <param name="modSlotName">Name of slot picked mod will be placed into</param>
|
||||
/// <returns>Chosen weapon details</returns>
|
||||
public ChooseRandomCompatibleModResult GetCompatibleWeaponModTplForSlotFromPool(ModToSpawnRequest request, List<string> modPool, Slot parentSlot,
|
||||
public ChooseRandomCompatibleModResult GetCompatibleWeaponModTplForSlotFromPool(ModToSpawnRequest request, HashSet<string> modPool, Slot parentSlot,
|
||||
ModSpawn? choiceTypeEnum, List<Item> weapon, string modSlotName)
|
||||
{
|
||||
// Filter out incompatible mods from pool
|
||||
@@ -985,7 +984,7 @@ public class BotEquipmentModGenerator(
|
||||
public ChooseRandomCompatibleModResult GetCompatibleModFromPool(List<string> modPool, ModSpawn? modSpawnType, List<Item> weapon)
|
||||
{
|
||||
// Create exhaustable pool to pick mod item from
|
||||
var exhaustableModPool = CreateExhaustableArray(modPool);
|
||||
var exhaustableModPool = CreateExhaustableArray(modPool.ToList());
|
||||
|
||||
// Create default response if no compatible item is found below
|
||||
ChooseRandomCompatibleModResult chosenModResult = new()
|
||||
@@ -1063,9 +1062,9 @@ public class BotEquipmentModGenerator(
|
||||
return chosenModResult;
|
||||
}
|
||||
|
||||
public ExhaustableArray<T> CreateExhaustableArray<T>(List<T> itemsToAddToArray) // TODO: this wont likely be needed, reimplement for C#
|
||||
public ExhaustableArray<T> CreateExhaustableArray<T>(List<T> itemsToAddToArray)
|
||||
{
|
||||
return new ExhaustableArray<T>(itemsToAddToArray, _randomUtil, _cloner);
|
||||
return new ExhaustableArray<T>(itemsToAddToArray.ToList(), _randomUtil, _cloner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1074,7 +1073,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="modPool"></param>
|
||||
/// <param name="tplBlacklist">Tpls that are incompatible and should not be used</param>
|
||||
/// <returns>string array of compatible mod tpls with weapon</returns>
|
||||
public List<string> GetFilteredModPool(List<string> modPool, List<string> tplBlacklist)
|
||||
public List<string> GetFilteredModPool(HashSet<string> modPool, List<string> tplBlacklist)
|
||||
{
|
||||
return modPool.Where((tpl) => !tplBlacklist.Contains(tpl)).ToList();
|
||||
}
|
||||
@@ -1088,7 +1087,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="request"></param>
|
||||
/// <param name="weaponTemplate">Mods root parent (weapon/equipment)</param>
|
||||
/// <returns>Array of mod tpls</returns>
|
||||
public List<string> GetModPoolForSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
|
||||
public HashSet<string> GetModPoolForSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
|
||||
{
|
||||
// Mod is flagged as being default only, try and find it in globals
|
||||
if (request.ModSpawnResult == ModSpawn.DEFAULT_MOD)
|
||||
@@ -1105,7 +1104,7 @@ public class BotEquipmentModGenerator(
|
||||
return request.ItemModPool[request.ModSlot];
|
||||
}
|
||||
|
||||
public List<string> GetModPoolForDefaultSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
|
||||
public HashSet<string> GetModPoolForDefaultSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
|
||||
{
|
||||
var matchingModFromPreset = GetMatchingModFromPreset(request, weaponTemplate);
|
||||
if (matchingModFromPreset is null)
|
||||
@@ -1166,7 +1165,7 @@ public class BotEquipmentModGenerator(
|
||||
var newListOfModsForSlot = parentSlotCompatibleItems.Where((tpl) => !request.ConflictingItemTpls.Contains(tpl));
|
||||
if (newListOfModsForSlot.Count() > 0)
|
||||
{
|
||||
return newListOfModsForSlot.ToList();
|
||||
return newListOfModsForSlot.ToHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1353,7 +1352,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="modTemplate">db object for modItem we get compatible mods from</param>
|
||||
/// <param name="modPool">Pool of mods we are adding to</param>
|
||||
/// <param name="botEquipBlacklist">A blacklist of items that cannot be picked</param>
|
||||
public void AddCompatibleModsForProvidedMod(string desiredSlotName, TemplateItem modTemplate, Dictionary<string, Dictionary<string, List<string>>> modPool,
|
||||
public void AddCompatibleModsForProvidedMod(string desiredSlotName, TemplateItem modTemplate, Dictionary<string, Dictionary<string, HashSet<string>>> modPool,
|
||||
EquipmentFilterDetails botEquipBlacklist)
|
||||
{
|
||||
var desiredSlotObject = modTemplate.Properties.Slots?.FirstOrDefault((slot) => slot.Name.Contains(desiredSlotName));
|
||||
@@ -1369,7 +1368,7 @@ public class BotEquipmentModGenerator(
|
||||
}
|
||||
|
||||
// Filter mods
|
||||
var filteredMods = FilterModsByBlacklist(supportedSubMods, botEquipBlacklist, desiredSlotName);
|
||||
var filteredMods = FilterModsByBlacklist(supportedSubMods.ToHashSet(), botEquipBlacklist, desiredSlotName);
|
||||
if (!filteredMods.Any())
|
||||
{
|
||||
_logger.Warning(
|
||||
@@ -1390,7 +1389,7 @@ public class BotEquipmentModGenerator(
|
||||
modPool[modTemplate.Id] = new();
|
||||
}
|
||||
|
||||
modPool[modTemplate.Id][desiredSlotObject.Name] = supportedSubMods;
|
||||
modPool[modTemplate.Id][desiredSlotObject.Name] = supportedSubMods.ToHashSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1400,7 +1399,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="modSlot">Slot item should fit in</param>
|
||||
/// <param name="botEquipBlacklist">Equipment that should not be picked</param>
|
||||
/// <returns>Array of compatible items for that slot</returns>
|
||||
public List<string> GetDynamicModPool(string parentItemId, string modSlot, EquipmentFilterDetails botEquipBlacklist)
|
||||
public HashSet<string> GetDynamicModPool(string parentItemId, string modSlot, EquipmentFilterDetails botEquipBlacklist)
|
||||
{
|
||||
var modsFromDynamicPool = _cloner.Clone(
|
||||
_botEquipmentModPoolService.GetCompatibleModsForWeaponSlot(parentItemId, modSlot)
|
||||
@@ -1424,7 +1423,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="botEquipBlacklist">Equipment blacklist</param>
|
||||
/// <param name="modSlot">Slot mods belong to</param>
|
||||
/// <returns>Filtered array of mod tpls</returns>
|
||||
public List<string> FilterModsByBlacklist(List<string> allowedMods, EquipmentFilterDetails? botEquipBlacklist, string modSlot)
|
||||
public HashSet<string> FilterModsByBlacklist(HashSet<string> allowedMods, EquipmentFilterDetails? botEquipBlacklist, string modSlot)
|
||||
{
|
||||
// No blacklist, nothing to filter out
|
||||
if (botEquipBlacklist is null)
|
||||
@@ -1432,12 +1431,12 @@ public class BotEquipmentModGenerator(
|
||||
return allowedMods;
|
||||
}
|
||||
|
||||
var result = new List<string>();
|
||||
var result = new HashSet<string>();
|
||||
|
||||
// Get item blacklist and mod equipment blacklist as one array
|
||||
botEquipBlacklist.Equipment.TryGetValue(modSlot, out var equipmentBlacklistValues);
|
||||
var blacklist = _itemFilterService.GetBlacklistedItems().Concat(equipmentBlacklistValues ?? []);
|
||||
result = allowedMods.Where((tpl) => !blacklist.Contains(tpl)).ToList();
|
||||
result = allowedMods.Where((tpl) => !blacklist.Contains(tpl)).ToHashSet();
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1452,7 +1451,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="modPool">ModPool which should include available cartridges</param>
|
||||
/// <param name="cylinderMagParentId">The CylinderMagazine's UID</param>
|
||||
/// <param name="cylinderMagTemplate">The CylinderMagazine's template</param>
|
||||
public void FillCamora(List<Item> items, Dictionary<string, Dictionary<string, List<string>>> modPool, string cylinderMagParentId,
|
||||
public void FillCamora(List<Item> items, Dictionary<string, Dictionary<string, HashSet<string>>> modPool, string cylinderMagParentId,
|
||||
TemplateItem cylinderMagTemplate)
|
||||
{
|
||||
var itemModPool = modPool[cylinderMagTemplate.Id];
|
||||
@@ -1474,7 +1473,7 @@ public class BotEquipmentModGenerator(
|
||||
modPool[cylinderMagTemplate.Id] = new();
|
||||
foreach (var camora in camoraSlots)
|
||||
{
|
||||
modPool[cylinderMagTemplate.Id][camora.Name] = camora.Props.Filters?[0].Filter;
|
||||
modPool[cylinderMagTemplate.Id][camora.Name] = camora.Props.Filters?[0].Filter.ToHashSet();
|
||||
}
|
||||
|
||||
itemModPool = modPool[cylinderMagTemplate.Id];
|
||||
@@ -1485,12 +1484,12 @@ public class BotEquipmentModGenerator(
|
||||
var camoraFirstSlot = "camora_000";
|
||||
if (itemModPool.TryGetValue(modSlot, out var value))
|
||||
{
|
||||
exhaustableModPool = CreateExhaustableArray(value);
|
||||
exhaustableModPool = CreateExhaustableArray(value.ToList());
|
||||
}
|
||||
else if (itemModPool.ContainsKey(camoraFirstSlot))
|
||||
{
|
||||
modSlot = camoraFirstSlot;
|
||||
exhaustableModPool = CreateExhaustableArray(MergeCamoraPools(itemModPool));
|
||||
exhaustableModPool = CreateExhaustableArray(MergeCamoraPools(itemModPool).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1531,12 +1530,12 @@ public class BotEquipmentModGenerator(
|
||||
/// </summary>
|
||||
/// <param name="camorasWithShells">Dictionary of camoras we want to merge into one array</param>
|
||||
/// <returns>String array of shells for multiple camora sources</returns>
|
||||
public List<string> MergeCamoraPools(Dictionary<string, List<string>> camorasWithShells)
|
||||
public HashSet<string> MergeCamoraPools(Dictionary<string, HashSet<string>> camorasWithShells)
|
||||
{
|
||||
return camorasWithShells
|
||||
.SelectMany(shellKvP => shellKvP.Value)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
.ToHashSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1548,7 +1547,7 @@ public class BotEquipmentModGenerator(
|
||||
/// <param name="scopes">Full scope pool</param>
|
||||
/// <param name="botWeaponSightWhitelist">Whitelist of scope types by weapon base type</param>
|
||||
/// <returns>Array of scope tpls that have been filtered to just ones allowed for that weapon type</returns>
|
||||
public List<string> FilterSightsByWeaponType(Item weapon, List<string> scopes, Dictionary<string, List<string>> botWeaponSightWhitelist)
|
||||
public HashSet<string> FilterSightsByWeaponType(Item weapon, HashSet<string> scopes, Dictionary<string, List<string>> botWeaponSightWhitelist)
|
||||
{
|
||||
var weaponDetails = _itemHelper.GetItem(weapon.Template);
|
||||
|
||||
@@ -1562,7 +1561,7 @@ public class BotEquipmentModGenerator(
|
||||
}
|
||||
|
||||
// Filter items that are not directly scopes OR mounts that do not hold the type of scope we allow for this weapon type
|
||||
List<string> filteredScopesAndMods = [];
|
||||
HashSet<string> filteredScopesAndMods = [];
|
||||
foreach (var item in scopes)
|
||||
{
|
||||
// Mods is a scope, check base class is allowed
|
||||
|
||||
@@ -201,7 +201,7 @@ public class BotInventoryGenerator(
|
||||
Inventory = botInventory,
|
||||
BotEquipmentConfig = botEquipConfig,
|
||||
RandomisationDetails = randomistionDetails,
|
||||
GeneratingPlayerLevel = pmcProfile.Info.Level,
|
||||
GeneratingPlayerLevel = pmcProfile.Info.Level
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -222,7 +222,7 @@ public class BotInventoryGenerator(
|
||||
Inventory = botInventory,
|
||||
BotEquipmentConfig = botEquipConfig,
|
||||
RandomisationDetails = randomistionDetails,
|
||||
GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE],
|
||||
GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE, ItemTpl.POCKETS_LARGE],
|
||||
GeneratingPlayerLevel = pmcProfile.Info.Level,
|
||||
}
|
||||
);
|
||||
@@ -483,7 +483,7 @@ public class BotInventoryGenerator(
|
||||
// Does item have slots for sub-mods to be inserted into
|
||||
if (pickedItemDb.Properties?.Slots?.Count > 0
|
||||
&& settings?.GenerateModsBlacklist is not null
|
||||
&& settings.GenerateModsBlacklist.Contains(pickedItemDb.Id))
|
||||
&& !settings.GenerateModsBlacklist.Contains(pickedItemDb.Id))
|
||||
{
|
||||
var childItemsToAdd = _botEquipmentModGenerator.GenerateModsForEquipment(
|
||||
[item],
|
||||
@@ -512,17 +512,20 @@ public class BotInventoryGenerator(
|
||||
/// <param name="itemTpl">Item mod pool is being retrieved and filtered</param>
|
||||
/// <param name="equipmentBlacklist">Blacklist to filter mod pool with</param>
|
||||
/// <returns>Filtered pool of mods</returns>
|
||||
public Dictionary<string, List<string>> GetFilteredDynamicModsForItem(string itemTpl, Dictionary<string, List<string>> equipmentBlacklist)
|
||||
public Dictionary<string, HashSet<string>> GetFilteredDynamicModsForItem(string itemTpl, Dictionary<string, List<string>> equipmentBlacklist)
|
||||
{
|
||||
var modPool = _botEquipmentModPoolService.GetModsForGearSlot(itemTpl);
|
||||
foreach (var modSlot in modPool.Keys ?? Enumerable.Empty<string>())
|
||||
foreach (var modSlot in modPool)
|
||||
{
|
||||
var blacklistedMods = equipmentBlacklist[modSlot] ?? [];
|
||||
var filteredMods = modPool[modSlot].Where((slotName) => !blacklistedMods.Contains(slotName));
|
||||
// Get blacklist
|
||||
equipmentBlacklist.TryGetValue(modSlot.Key, out var blacklistedMods);
|
||||
|
||||
// Get mods not on blacklist
|
||||
var filteredMods = modPool[modSlot.Key].Where((slotName) => !(blacklistedMods ?? []).Contains(slotName));
|
||||
|
||||
if (filteredMods.Any())
|
||||
{
|
||||
modPool[modSlot] = filteredMods.ToList();
|
||||
modPool[modSlot.Key] = filteredMods.ToHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -446,7 +446,7 @@ public class BotLootGenerator(
|
||||
return;
|
||||
}
|
||||
|
||||
var weightedItemTpl = _weightedRandomHelper.GetWeightedValue<string>(pool);
|
||||
var weightedItemTpl = _weightedRandomHelper.GetWeightedValue(pool);
|
||||
var (key, itemToAddTemplate) = _itemHelper.GetItem(weightedItemTpl);
|
||||
|
||||
if (!key)
|
||||
@@ -456,16 +456,13 @@ public class BotLootGenerator(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemSpawnLimits is not null)
|
||||
if (itemSpawnLimits is not null && ItemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits))
|
||||
{
|
||||
if (ItemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits))
|
||||
{
|
||||
// Remove item from pool to prevent it being picked again
|
||||
pool.Remove(weightedItemTpl);
|
||||
// Remove item from pool to prevent it being picked again
|
||||
pool.Remove(weightedItemTpl);
|
||||
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
var newRootItemId = _hashUtil.Generate();
|
||||
@@ -541,9 +538,9 @@ public class BotLootGenerator(
|
||||
if (fitItemIntoContainerAttempts >= 4)
|
||||
{
|
||||
_logger.Debug(
|
||||
$"Failed placing item: {i} of: {totalItemCount} items into: {botRole} " +
|
||||
$"Failed placing item: {itemToAddTemplate.Name}: {i} of: {totalItemCount} items into: {botRole} " +
|
||||
$"containers: {string.Join(",", equipmentSlots)}. Tried: {fitItemIntoContainerAttempts} " +
|
||||
$"times, reason: {itemAddedResult.ToString()}, skipping"
|
||||
$"times, reason: {itemAddedResult}, skipping"
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
@@ -348,7 +348,7 @@ public class BotWeaponGenerator(
|
||||
}
|
||||
|
||||
// Iterate over required slots in db item, check mod exists for that slot
|
||||
foreach (var modSlotTemplate in modTemplate.Properties.Slots.Where((slot) => slot.Required ?? false))
|
||||
foreach (var modSlotTemplate in modTemplate.Properties.Slots?.Where((slot) => slot.Required.GetValueOrDefault(false)) ?? [])
|
||||
{
|
||||
var slotName = modSlotTemplate.Name;
|
||||
var hasWeaponSlotItem = weaponItemList.Any(
|
||||
@@ -553,9 +553,7 @@ public class BotWeaponGenerator(
|
||||
protected string GetWeightedCompatibleAmmo(Dictionary<string, Dictionary<string, double>> cartridgePool, TemplateItem weaponTemplate)
|
||||
{
|
||||
var desiredCaliber = GetWeaponCaliber(weaponTemplate);
|
||||
|
||||
var cartridgePoolForWeapon = cartridgePool[desiredCaliber];
|
||||
if (cartridgePoolForWeapon is null || cartridgePoolForWeapon?.Count == 0)
|
||||
if (!cartridgePool.TryGetValue(desiredCaliber, out var cartridgePoolForWeapon) && cartridgePoolForWeapon.Keys.Count > 0)
|
||||
{
|
||||
_logger.Debug(
|
||||
_localisationService.GetText(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using SptCommon.Annotations;
|
||||
using SptCommon.Annotations;
|
||||
using Core.Helpers;
|
||||
using Core.Models.Eft.Common.Tables;
|
||||
using Core.Models.Enums;
|
||||
@@ -31,7 +31,7 @@ public class ExternalInventoryMagGen(
|
||||
|
||||
public void Process(InventoryMagGen inventoryMagGen)
|
||||
{
|
||||
// Cout of attempts to fit a magazine into bot inventory
|
||||
// Count of attempts to fit a magazine into bot inventory
|
||||
var fitAttempts = 0;
|
||||
|
||||
// Magazine Db template
|
||||
@@ -41,6 +41,7 @@ public class ExternalInventoryMagGen(
|
||||
List<string> attemptedMagBlacklist = [];
|
||||
var defaultMagazineTpl = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(weapon);
|
||||
var randomizedMagazineCount = _botWeaponGeneratorHelper.GetRandomizedMagazineCount(inventoryMagGen.GetMagCount());
|
||||
var isShotgun = _itemHelper.IsOfBaseclass(weapon.Id, BaseClasses.SHOTGUN);
|
||||
for (var i = 0; i < randomizedMagazineCount; i++)
|
||||
{
|
||||
var magazineWithAmmo = _botWeaponGeneratorHelper.CreateMagazineWithAmmo(
|
||||
@@ -99,16 +100,23 @@ public class ExternalInventoryMagGen(
|
||||
break;
|
||||
}
|
||||
|
||||
// Edge case - some weapons (SKS) have an internal magazine as default, choose random non-internal magazine to add to bot instead
|
||||
// Edge case - some weapons (SKS + shotguns) have an internal magazine as default, choose random non-internal magazine to add to bot instead
|
||||
if (magTemplate.Properties.ReloadMagType == "InternalMagazine")
|
||||
{
|
||||
var result = GetRandomExternalMagazineForInternalMagazineGun(
|
||||
inventoryMagGen.GetWeaponTemplate().Id,
|
||||
attemptedMagBlacklist
|
||||
);
|
||||
|
||||
if (result?.Id is null)
|
||||
{
|
||||
_logger.Debug($"Unable to add additional magazine into bot inventory for weapon: {weapon.Name}, attempted: {fitAttempts} times");
|
||||
// Highly likely shotgun has no external mags
|
||||
if (isShotgun)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_logger.Debug($"Unable to add additional magazine into bot inventory: vest/pockets for weapon: {weapon.Name}, attempted: {fitAttempts} times. Reason: {fitsIntoInventory}");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -582,7 +582,7 @@ public class BotGeneratorHelper(
|
||||
{
|
||||
parentItem.ParentId = container.Id;
|
||||
parentItem.SlotId = slotGrid.Name;
|
||||
parentItem.Location = new ItemLocation()
|
||||
parentItem.Location = new ItemLocation
|
||||
{
|
||||
X = findSlotResult.X,
|
||||
Y = findSlotResult.Y,
|
||||
|
||||
@@ -28,39 +28,38 @@ public class ContainerHelper
|
||||
return new FindSlotResult(false);
|
||||
}
|
||||
|
||||
// Down
|
||||
// Down = y
|
||||
for (var y = 0; y < limitY; y++)
|
||||
{
|
||||
// Across
|
||||
|
||||
if (container2D[y].All((x) => x == 1))
|
||||
{
|
||||
// Every item in row is full, skip row
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try each slot on the row (across = x)
|
||||
for (var x = 0; x < limitX; x++)
|
||||
{
|
||||
var foundSlot = LocateSlot(container2D, containerX, containerY, x, y, itemWidth, itemHeight);
|
||||
if (foundSlot)
|
||||
{
|
||||
return new FindSlotResult(true, x, y, rotation);
|
||||
}
|
||||
|
||||
// Failed to find slot, rotate item and try again
|
||||
if (!foundSlot && itemWidth * itemHeight > 1)
|
||||
if (!foundSlot && ItemBiggerThan1X1(itemWidth, itemHeight))
|
||||
{
|
||||
// Bigger than 1x1
|
||||
// Bigger than 1x1, try rotating
|
||||
foundSlot = LocateSlot(container2D, containerX, containerY, x, y, itemHeight, itemWidth); // Height/Width swapped
|
||||
if (foundSlot)
|
||||
{
|
||||
// Found a slot for it when rotated
|
||||
rotation = true;
|
||||
|
||||
return new FindSlotResult(true, x, y, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSlot)
|
||||
{
|
||||
// Didn't fit this hole, try again
|
||||
continue;
|
||||
}
|
||||
|
||||
return new FindSlotResult(true, x, y, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +67,11 @@ public class ContainerHelper
|
||||
return new FindSlotResult(false);
|
||||
}
|
||||
|
||||
private bool ItemBiggerThan1X1(int itemWidth, int itemHeight)
|
||||
{
|
||||
return itemWidth * itemHeight > 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a slot inside a container an item can be placed in
|
||||
/// </summary>
|
||||
|
||||
@@ -163,6 +163,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Weapon.LowestMax;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Weapon.LowestMax;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var durability);
|
||||
return durability.Weapon.LowestMax;
|
||||
}
|
||||
@@ -174,6 +179,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Weapon.HighestMax;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Weapon.HighestMax;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var durability);
|
||||
return durability.Weapon.HighestMax;
|
||||
}
|
||||
@@ -211,6 +221,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Weapon.MinDelta;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Weapon.MinDelta;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value);
|
||||
|
||||
return value.Weapon.MinDelta;
|
||||
@@ -223,6 +238,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Weapon.HighestMax;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Weapon.HighestMax;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value);
|
||||
|
||||
return value.Weapon.HighestMax;
|
||||
@@ -235,6 +255,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Armor.MinDelta;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Armor.MinDelta;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value);
|
||||
|
||||
return value.Armor.MinDelta;
|
||||
@@ -247,6 +272,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Armor.MaxDelta;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Armor.MaxDelta;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value);
|
||||
|
||||
return value.Armor.MaxDelta;
|
||||
@@ -259,6 +289,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Armor.MinLimitPercent;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Armor.MinLimitPercent;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value);
|
||||
|
||||
return value.Armor.MinLimitPercent;
|
||||
@@ -271,6 +306,11 @@ public class DurabilityLimitsHelper(
|
||||
return _botConfig.Durability.Default.Weapon.MinLimitPercent;
|
||||
}
|
||||
|
||||
if (botRole == "pmc")
|
||||
{
|
||||
return _botConfig.Durability.Pmc.Weapon.MinLimitPercent;
|
||||
}
|
||||
|
||||
_botConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value);
|
||||
|
||||
return value.Weapon.MinLimitPercent;
|
||||
|
||||
@@ -336,7 +336,17 @@ public class InventoryHelper(
|
||||
/// <returns>Two-dimensional representation of container</returns>
|
||||
protected int[][] GetBlankContainerMap(int containerH, int containerY)
|
||||
{
|
||||
return Enumerable.Repeat(Enumerable.Repeat(0, containerH).ToArray(), containerY).ToArray();
|
||||
//var x = new int[containerY][];
|
||||
//for (int i = 0; i < containerY; i++)
|
||||
//{
|
||||
// x[i] = new int[containerH];
|
||||
//}
|
||||
|
||||
//return x;
|
||||
|
||||
return Enumerable.Range(0, containerY)
|
||||
.Select(i => new int[containerH])
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -395,12 +405,12 @@ public class InventoryHelper(
|
||||
}
|
||||
|
||||
// Fill the corresponding cells in the container map to show the slot is taken
|
||||
Array.Fill(containerRow, 1, itemLocation.X.Value, fillTo.Value);
|
||||
Array.Fill(containerRow, 1, itemLocation.X.Value, fW);
|
||||
} catch (Exception ex) {
|
||||
_logger.Error(
|
||||
_localisationService.GetText("inventory-unable_to_fill_container", new {
|
||||
id = item.Id,
|
||||
error = ex.Message
|
||||
error = $"{ex.Message} {ex.StackTrace}"
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
global using GlobalAmmo = System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<string, double>>;
|
||||
global using GlobalMods = System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>>;
|
||||
global using GlobalAmmo = System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<string, double>>;
|
||||
global using GlobalMods = System.Collections.Generic.Dictionary<string, System.Collections.Generic.Dictionary<string, System.Collections.Generic.HashSet<string>>>;
|
||||
|
||||
@@ -8,7 +8,7 @@ public record FilterPlateModsForSlotByLevelResult
|
||||
public Result? Result { get; set; }
|
||||
|
||||
[JsonPropertyName("plateModTpls")]
|
||||
public List<string>? PlateModTemplates { get; set; }
|
||||
public HashSet<string>? PlateModTemplates { get; set; }
|
||||
}
|
||||
|
||||
public enum Result
|
||||
|
||||
@@ -38,7 +38,7 @@ public record ModToSpawnRequest
|
||||
/// Pool of items to pick from
|
||||
/// </summary>
|
||||
[JsonPropertyName("itemModPool")]
|
||||
public Dictionary<string, List<string>>? ItemModPool { get; set; }
|
||||
public Dictionary<string, HashSet<string>>? ItemModPool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List with only weapon tpl in it, ready for mods to be added
|
||||
|
||||
@@ -5,7 +5,6 @@ using Core.Helpers;
|
||||
using Core.Servers;
|
||||
using Core.Models.Enums;
|
||||
using Core.Models.Spt.Config;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.Services;
|
||||
|
||||
@@ -18,7 +17,8 @@ public class BotEquipmentModPoolService
|
||||
protected LocalisationService _localisationService;
|
||||
protected ConfigServer _configServer;
|
||||
|
||||
protected bool _weaponPoolGenerated = false;
|
||||
protected bool _weaponPoolGenerated;
|
||||
protected bool _armorPoolGenerated;
|
||||
protected Dictionary<string, Dictionary<string, HashSet<string>>> _weaponModPool;
|
||||
protected Dictionary<string, Dictionary<string, HashSet<string>>> _gearModPool;
|
||||
protected BotConfig _botConfig;
|
||||
@@ -110,34 +110,6 @@ public class BotEquipmentModPoolService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//foreach (var slot in item.Properties.Slots)
|
||||
//{
|
||||
// var itemsThatFit = slot.Props.Filters[0].Filter;
|
||||
// foreach (var itemToAddTpl in itemsThatFit)
|
||||
// {
|
||||
// // Ensure key/value exists
|
||||
// pool.TryAdd(slot.Name, new Dictionary<string, List<string>>());
|
||||
// pool.TryGetValue(item.Id, out var poolToAddTo);
|
||||
// poolToAddTo ??= new Dictionary<string, List<string>>();
|
||||
|
||||
// // only add item to pool if it doesn't already exist
|
||||
// poolToAddTo.TryAdd(slot.Name, []);
|
||||
// if (!poolToAddTo[slot.Name].Any(x => x == itemToAddTpl))
|
||||
// {
|
||||
// poolToAddTo[slot.Name].Add(itemToAddTpl);
|
||||
|
||||
// // Check item added into array for slots, need to iterate over those
|
||||
// var subItemDetails = _itemHelper.GetItem(itemToAddTpl).Value;
|
||||
// var hasSubItemsToAdd = (subItemDetails?.Properties?.Slots?.Count ?? 0) > 0;
|
||||
// if (hasSubItemsToAdd && !pool.ContainsKey(subItemDetails.Id))
|
||||
// {
|
||||
// // Recursive call
|
||||
// GeneratePool([subItemDetails], poolType);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,12 +122,12 @@ public class BotEquipmentModPoolService
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of compatible mods for an items mod slot (generate pool if it doesnt exist already)
|
||||
* Get array of compatible mods for an items mod slot (generate pool if it doesn't exist already)
|
||||
* @param itemTpl item to look up
|
||||
* @param slotName slot to get compatible mods for
|
||||
* @returns tpls that fit the slot
|
||||
*/
|
||||
public List<string> GetCompatibleModsForWeaponSlot(string itemTpl, string slotName)
|
||||
public HashSet<string> GetCompatibleModsForWeaponSlot(string itemTpl, string slotName)
|
||||
{
|
||||
if (!_weaponPoolGenerated)
|
||||
{
|
||||
@@ -163,18 +135,7 @@ public class BotEquipmentModPoolService
|
||||
GenerateWeaponPool();
|
||||
}
|
||||
|
||||
return _weaponModPool[itemTpl][slotName].ToList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of compatible mods for an items mod slot (generate pool if it doesnt exist already)
|
||||
* @param itemTpl item to look up
|
||||
* @param slotName slot to get compatible mods for
|
||||
* @returns tpls that fit the slot
|
||||
*/
|
||||
public List<string> GetCompatibleModsForGearSlot(string itemTpl, string slotName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _weaponModPool[itemTpl][slotName];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,9 +143,16 @@ public class BotEquipmentModPoolService
|
||||
* @param itemTpl items tpl to look up mods for
|
||||
* @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value
|
||||
*/
|
||||
public Dictionary<string, List<string>> GetModsForGearSlot(string itemTpl)
|
||||
public Dictionary<string, HashSet<string>>? GetModsForGearSlot(string itemTpl)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (!_armorPoolGenerated)
|
||||
{
|
||||
GenerateGearPool();
|
||||
}
|
||||
|
||||
return _gearModPool.TryGetValue(itemTpl, out var value)
|
||||
? value
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,9 +160,14 @@ public class BotEquipmentModPoolService
|
||||
* @param itemTpl Weapons tpl to look up mods for
|
||||
* @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value
|
||||
*/
|
||||
public Dictionary<string, List<string>> GetModsForWeaponSlot(string itemTpl)
|
||||
public Dictionary<string, HashSet<string>> GetModsForWeaponSlot(string itemTpl)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (!_weaponPoolGenerated)
|
||||
{
|
||||
GenerateWeaponPool();
|
||||
}
|
||||
|
||||
return _weaponModPool[itemTpl];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,6 +188,17 @@ public class BotEquipmentModPoolService
|
||||
*/
|
||||
protected void GenerateGearPool()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var gear = _databaseService.GetItems().Values.Where(
|
||||
(item) => item.Type == "Item"
|
||||
&& _itemHelper.IsOfBaseclasses(item.Id, [
|
||||
BaseClasses.ARMORED_EQUIPMENT,
|
||||
BaseClasses.VEST,
|
||||
BaseClasses.ARMOR,
|
||||
BaseClasses.HEADWEAR,
|
||||
]));
|
||||
GeneratePool(gear, "gear");
|
||||
|
||||
// Flag pool as being complete
|
||||
_armorPoolGenerated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Core.Models.Eft.Common.Tables;
|
||||
using Core.Models.Eft.ItemEvent;
|
||||
using Core.Models.Eft.Repair;
|
||||
using Core.Models.Enums;
|
||||
using Core.Models.Utils;
|
||||
using Core.Utils;
|
||||
|
||||
namespace Core.Services;
|
||||
@@ -13,13 +14,16 @@ namespace Core.Services;
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class RepairService
|
||||
{
|
||||
private readonly ISptLogger<RepairService> _logger;
|
||||
private readonly RandomUtil _randomUtil;
|
||||
private readonly WeightedRandomHelper _weightedRandomHelper;
|
||||
|
||||
public RepairService(
|
||||
ISptLogger<RepairService> _logger,
|
||||
RandomUtil randomUtil,
|
||||
WeightedRandomHelper weightedRandomHelper)
|
||||
{
|
||||
this._logger = _logger;
|
||||
_randomUtil = randomUtil;
|
||||
_weightedRandomHelper = weightedRandomHelper;
|
||||
}
|
||||
@@ -165,10 +169,26 @@ public class RepairService
|
||||
/// Add random buff to item
|
||||
/// </summary>
|
||||
/// <param name="itemConfig">weapon/armor config</param>
|
||||
/// <param name="repairDetails">Details for item to repair</param>
|
||||
public void AddBuff(Core.Models.Spt.Config.BonusSettings itemConfig, Item item)
|
||||
/// <param name="item">Item to repair</param>
|
||||
public void AddBuff(Models.Spt.Config.BonusSettings itemConfig, Item item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_logger.Error("NOT IMPLEMENTED - AddBuff");
|
||||
//var bonusRarity = _weightedRandomHelper.GetWeightedValue<string>(itemConfig.RarityWeight);
|
||||
//var bonusType = _weightedRandomHelper.GetWeightedValue<string>(itemConfig.BonusTypeWeight);
|
||||
|
||||
//var bonusValues = itemConfig[bonusRarity][bonusType].valuesMinMax;
|
||||
//var bonusValue = _randomUtil.GetFloat(bonusValues.min, bonusValues.max);
|
||||
|
||||
//var bonusThresholdPercents = itemConfig[bonusRarity][bonusType].activeDurabilityPercentMinMax;
|
||||
//var bonusThresholdPercent = _randomUtil.GetInt(bonusThresholdPercents.min, bonusThresholdPercents.max);
|
||||
|
||||
//item.Upd.Buff = new UpdBuff {
|
||||
// Rarity = bonusRarity,
|
||||
// BuffType = bonusType,
|
||||
// Value = bonusValue,
|
||||
// ThresholdDurability = _randomUtil.GetPercentOfValue(bonusThresholdPercent, item.Upd.Repairable.Durability, 2).toFixed(2),
|
||||
// )
|
||||
//};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user