Ienumerable changes

This commit is contained in:
Chomp
2025-07-23 13:06:48 +01:00
parent 839e154adc
commit 1320f7d0ab
27 changed files with 176 additions and 158 deletions
@@ -379,7 +379,7 @@ public class RagfairController(
var offers = ragfairOfferService.GetOffersOfType(getPriceRequest.TemplateId); var offers = ragfairOfferService.GetOffersOfType(getPriceRequest.TemplateId);
// Offers exist for item, get averages of what's listed // Offers exist for item, get averages of what's listed
if (offers?.Count > 0) if (offers.Any())
{ {
// These get calculated while iterating through the list below // These get calculated while iterating through the list below
var minMax = new MinMax<double>(int.MaxValue, 0); var minMax = new MinMax<double>(int.MaxValue, 0);
@@ -412,7 +412,7 @@ public class RagfairController(
} }
protected double GetAveragePriceFromOffers( protected double GetAveragePriceFromOffers(
List<RagfairOffer> offers, IEnumerable<RagfairOffer> offers,
MinMax<double> minMax, MinMax<double> minMax,
bool ignoreTraderOffers bool ignoreTraderOffers
) )
@@ -197,7 +197,8 @@ public class BotEquipmentModGenerator(
); );
switch (plateSlotFilteringOutcome.Result) switch (plateSlotFilteringOutcome.Result)
{ {
case Result.UNKNOWN_FAILURE or Result.NO_DEFAULT_FILTER: case Result.UNKNOWN_FAILURE
or Result.NO_DEFAULT_FILTER:
if (logger.IsLogEnabled(LogLevel.Debug)) if (logger.IsLogEnabled(LogLevel.Debug))
{ {
logger.Debug( logger.Debug(
@@ -692,6 +693,7 @@ public class BotEquipmentModGenerator(
// Force spawn chance to be 100% to ensure it gets added // Force spawn chance to be 100% to ensure it gets added
if ( if (
modSlot == "mod_handguard" modSlot == "mod_handguard"
&& modToAddTemplate.Properties?.Slots is not null
&& modToAddTemplate.Properties.Slots.Any(slot => slot.Name == "mod_handguard") && modToAddTemplate.Properties.Slots.Any(slot => slot.Name == "mod_handguard")
&& !request.Weapon.Any(item => item.SlotId == "mod_launcher") && !request.Weapon.Any(item => item.SlotId == "mod_launcher")
) )
@@ -772,6 +774,7 @@ public class BotEquipmentModGenerator(
if ( if (
isRandomisableSlot isRandomisableSlot
&& !containsModInPool && !containsModInPool
&& modToAddTemplate.Properties?.Slots is not null
&& modToAddTemplate.Properties.Slots.Any() && modToAddTemplate.Properties.Slots.Any()
) )
{ {
@@ -835,9 +838,15 @@ public class BotEquipmentModGenerator(
/// <returns>True it lacks cartridges/chamber slots</returns> /// <returns>True it lacks cartridges/chamber slots</returns>
protected bool ItemLacksSlotsCartridgesAndChambers(TemplateItem item) protected bool ItemLacksSlotsCartridgesAndChambers(TemplateItem item)
{ {
return item.Properties.Slots?.Count == 0 if (item.Properties is null)
&& item.Properties.Cartridges?.Count == 0 {
&& item.Properties.Chambers?.Count == 0; return true;
}
return item.Properties.Slots is null
|| !item.Properties.Slots.Any()
&& item.Properties.Cartridges?.Count == 0
&& item.Properties.Chambers?.Count == 0;
} }
/// <summary> /// <summary>
@@ -854,7 +863,9 @@ public class BotEquipmentModGenerator(
) )
{ {
// Can the stock hold child items // Can the stock hold child items
var hasSubSlots = modToAddTemplate.Properties.Slots?.Count > 0; var hasSubSlots =
modToAddTemplate.Properties?.Slots is not null
&& modToAddTemplate.Properties.Slots.Any();
return (_stockSlots.Contains(modSlot) && hasSubSlots) return (_stockSlots.Contains(modSlot) && hasSubSlots)
|| botEquipConfig.ForceStock.GetValueOrDefault(false); || botEquipConfig.ForceStock.GetValueOrDefault(false);
@@ -1280,8 +1291,8 @@ public class BotEquipmentModGenerator(
var desiredMagazineTpls = modPool.Where(magTpl => var desiredMagazineTpls = modPool.Where(magTpl =>
{ {
var magazineDb = itemHelper.GetItem(magTpl).Value; var magazineDb = itemHelper.GetItem(magTpl).Value;
return magazineDb.Properties is not null return magazineDb.Properties?.Cartridges is not null
&& magazineDb.Properties.Cartridges.FirstOrDefault().MaxCount && magazineDb.Properties.Cartridges.FirstOrDefault()?.MaxCount
>= minMagSizeFromSettings; >= minMagSizeFromSettings;
}); });
@@ -1546,7 +1557,7 @@ public class BotEquipmentModGenerator(
// Mod isn't in existing pool, only add if it has no children and exists inside parent filter // Mod isn't in existing pool, only add if it has no children and exists inside parent filter
if ( if (
(parentSlotCompatibleItems?.Contains(matchingModFromPreset.Template) ?? false) (parentSlotCompatibleItems?.Contains(matchingModFromPreset.Template) ?? false)
&& itemHelper.GetItem(matchingModFromPreset.Template).Value.Properties.Slots?.Count == 0 && !itemHelper.GetItem(matchingModFromPreset.Template).Value.Properties.Slots.Any()
) )
{ {
// Chosen mod has no conflicts + no children + is in parent compat list // Chosen mod has no conflicts + no children + is in parent compat list
@@ -2070,22 +2081,23 @@ 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 // Filter items that are not directly scopes OR mounts that do not hold the type of scope we allow for this weapon type
HashSet<MongoId> filteredScopesAndMods = []; HashSet<MongoId> filteredScopesAndMods = [];
foreach (var item in scopes) foreach (var scopeTpl in scopes)
{ {
// Mods is a scope, check base class is allowed // Mods is a scope, check base class is allowed
if (itemHelper.IsOfBaseclasses(item, whitelistedSightTypes)) if (itemHelper.IsOfBaseclasses(scopeTpl, whitelistedSightTypes))
{ {
// Add mod to allowed list // Add mod to allowed list
filteredScopesAndMods.Add(item); filteredScopesAndMods.Add(scopeTpl);
continue; continue;
} }
// Edge case, what if item is a mount for a scope and not directly a scope? // Edge case, what if item is a mount for a scope and not directly a scope?
// Check item is mount + has child items // Check item is mount + has child items
var itemDetails = itemHelper.GetItem(item).Value; var itemDetails = itemHelper.GetItem(scopeTpl).Value;
if ( if (
itemHelper.IsOfBaseclass(item, BaseClasses.MOUNT) itemDetails?.Properties?.Slots is not null
&& itemDetails.Properties.Slots.Any() && itemDetails.Properties.Slots.Any()
&& itemHelper.IsOfBaseclass(scopeTpl, BaseClasses.MOUNT)
) )
{ {
// Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots) // Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots)
@@ -2107,7 +2119,7 @@ public class BotEquipmentModGenerator(
) )
// Add mod to allowed list // Add mod to allowed list
{ {
filteredScopesAndMods.Add(item); filteredScopesAndMods.Add(scopeTpl);
} }
} }
} }
@@ -615,7 +615,11 @@ public class BotInventoryGenerator(
settings.GenerateModsBlacklist != null settings.GenerateModsBlacklist != null
&& settings.GenerateModsBlacklist.Contains(pickedItemDb.Id); && settings.GenerateModsBlacklist.Contains(pickedItemDb.Id);
// Does item have slots for sub-mods to be inserted into // Does item have slots for sub-mods to be inserted into
if (pickedItemDb.Properties?.Slots?.Count > 0 && !itemIsOnGenerateModBlacklist) if (
pickedItemDb.Properties?.Slots is not null
&& pickedItemDb.Properties.Slots.Any()
&& !itemIsOnGenerateModBlacklist
)
{ {
var childItemsToAdd = botEquipmentModGenerator.GenerateModsForEquipment( var childItemsToAdd = botEquipmentModGenerator.GenerateModsForEquipment(
[item], [item],
@@ -285,7 +285,7 @@ public class BotLootGenerator(
var itemPriceLimits = GetSingleItemLootPriceLimits(botLevel, isPmc); var itemPriceLimits = GetSingleItemLootPriceLimits(botLevel, isPmc);
// Backpack - generate loot if they have one // Backpack - generate loot if they have one
if (containersBotHasAvailable.Contains(EquipmentSlots.Backpack)) if (containersBotHasAvailable.Contains(EquipmentSlots.Backpack) && backpackLootCount > 0)
{ {
// Add randomly generated weapon to PMC backpacks // Add randomly generated weapon to PMC backpacks
if (isPmc && randomUtil.GetChance100(_pmcConfig.LooseWeaponInBackpackChancePercent)) if (isPmc && randomUtil.GetChance100(_pmcConfig.LooseWeaponInBackpackChancePercent))
@@ -506,9 +506,7 @@ public class BotLootGenerator(
) )
{ {
// Loot pool has items // Loot pool has items
var poolSize = pool.Count; if (pool.Count <= 0)
if (poolSize <= 0)
{ {
return; return;
} }
@@ -905,9 +905,9 @@ public class BotWeaponGenerator(
/// <param name="weaponMods">Weapon with children.</param> /// <param name="weaponMods">Weapon with children.</param>
/// <param name="ubglMod">Underbarrrel grenade launcher item.</param> /// <param name="ubglMod">Underbarrrel grenade launcher item.</param>
/// <param name="ubglAmmoTpl">Grenade ammo template.</param> /// <param name="ubglAmmoTpl">Grenade ammo template.</param>
protected void FillUbgl(IEnumerable<Item> weaponMods, Item ubglMod, MongoId ubglAmmoTpl) protected void FillUbgl(List<Item> weaponMods, Item ubglMod, MongoId ubglAmmoTpl)
{ {
weaponMods.Append( weaponMods.Add(
new Item new Item
{ {
Id = new MongoId(), Id = new MongoId(),
@@ -77,7 +77,7 @@ public class FenceBaseAssortGenerator(
// Only allow rigs with no slots (carrier rigs) // Only allow rigs with no slots (carrier rigs)
if ( if (
itemHelper.IsOfBaseclass(itemId, BaseClasses.VEST) itemHelper.IsOfBaseclass(itemId, BaseClasses.VEST)
&& (rootItemDb.Properties?.Slots?.Count ?? 0) > 0 && (rootItemDb.Properties?.Slots is not null && rootItemDb.Properties.Slots.Any())
) )
{ {
continue; continue;
@@ -271,7 +271,8 @@ public class FenceBaseAssortGenerator(
protected void AddChildrenToArmorModSlots(List<Item> armor, TemplateItem itemDbDetails) protected void AddChildrenToArmorModSlots(List<Item> armor, TemplateItem itemDbDetails)
{ {
// Armor has no mods, make no additions // Armor has no mods, make no additions
var hasMods = itemDbDetails.Properties.Slots.Count > 0; var hasMods =
itemDbDetails.Properties?.Slots is not null && itemDbDetails.Properties.Slots.Any();
if (!hasMods) if (!hasMods)
{ {
return; return;
@@ -171,7 +171,7 @@ public class LocationLootGenerator(
// Find all 100% spawn containers // Find all 100% spawn containers
var staticLootDist = mapData.StaticLoot; var staticLootDist = mapData.StaticLoot;
var guaranteedContainers = GetGuaranteedContainers(allStaticContainersOnMapClone); var guaranteedContainers = GetGuaranteedContainers(allStaticContainersOnMapClone);
staticContainerCount += guaranteedContainers.Count; staticContainerCount += guaranteedContainers.Count();
// Add loot to guaranteed containers and add to result // Add loot to guaranteed containers and add to result
foreach ( foreach (
@@ -188,12 +188,12 @@ public class LocationLootGenerator(
{ {
result.Add(containerWithLoot.Template); result.Add(containerWithLoot.Template);
staticLootItemCount += containerWithLoot.Template.Items.Count; staticLootItemCount += containerWithLoot.Template.Items.Count();
} }
if (_logger.IsLogEnabled(LogLevel.Debug)) if (_logger.IsLogEnabled(LogLevel.Debug))
{ {
_logger.Debug($"Added {guaranteedContainers.Count} guaranteed containers"); _logger.Debug($"Added {guaranteedContainers.Count()} guaranteed containers");
} }
// Randomisation is turned off for location / globally // Randomisation is turned off for location / globally
@@ -202,7 +202,7 @@ public class LocationLootGenerator(
if (_logger.IsLogEnabled(LogLevel.Debug)) if (_logger.IsLogEnabled(LogLevel.Debug))
{ {
_logger.Debug( _logger.Debug(
$"Container randomisation disabled, Adding: {staticRandomisableContainersOnMap.Count} containers to: {locationId}" $"Container randomisation disabled, Adding: {staticRandomisableContainersOnMap.Count()} containers to: {locationId}"
); );
} }
@@ -217,7 +217,7 @@ public class LocationLootGenerator(
); );
result.Add(containerWithLoot.Template); result.Add(containerWithLoot.Template);
staticLootItemCount += containerWithLoot.Template.Items.Count; staticLootItemCount += containerWithLoot.Template.Items.Count();
} }
_logger.Success($"A total of {staticLootItemCount} static items spawned"); _logger.Success($"A total of {staticLootItemCount} static items spawned");
@@ -320,7 +320,7 @@ public class LocationLootGenerator(
result.Add(containerWithLoot.Template); result.Add(containerWithLoot.Template);
staticContainerCount++; staticContainerCount++;
staticLootItemCount += containerWithLoot.Template.Items.Count; staticLootItemCount += containerWithLoot.Template.Items.Count();
} }
} }
@@ -346,19 +346,17 @@ public class LocationLootGenerator(
/// </summary> /// </summary>
/// <param name="staticContainers"></param> /// <param name="staticContainers"></param>
/// <returns>StaticContainerData array</returns> /// <returns>StaticContainerData array</returns>
protected List<StaticContainerData> GetRandomisableContainersOnMap( protected IEnumerable<StaticContainerData> GetRandomisableContainersOnMap(
List<StaticContainerData> staticContainers IEnumerable<StaticContainerData> staticContainers
) )
{ {
return staticContainers return staticContainers.Where(staticContainer =>
.Where(staticContainer => staticContainer.Probability != 1
staticContainer.Probability != 1 && !staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false)
&& !staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false) && !_locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains(
&& !_locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains( staticContainer.Template.Items.FirstOrDefault().Template
staticContainer.Template.Items.FirstOrDefault().Template
)
) )
.ToList(); );
} }
/// <summary> /// <summary>
@@ -366,19 +364,17 @@ public class LocationLootGenerator(
/// </summary> /// </summary>
/// <param name="staticContainersOnMap"></param> /// <param name="staticContainersOnMap"></param>
/// <returns>IStaticContainerData array</returns> /// <returns>IStaticContainerData array</returns>
protected List<StaticContainerData> GetGuaranteedContainers( protected IEnumerable<StaticContainerData> GetGuaranteedContainers(
List<StaticContainerData> staticContainersOnMap IEnumerable<StaticContainerData> staticContainersOnMap
) )
{ {
return staticContainersOnMap return staticContainersOnMap.Where(staticContainer =>
.Where(staticContainer => staticContainer.Probability == 1
staticContainer.Probability == 1 || staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false)
|| staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false) || _locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains(
|| _locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains( staticContainer.Template.Items.FirstOrDefault().Template
staticContainer.Template.Items.FirstOrDefault().Template
)
) )
.ToList(); );
} }
/// <summary> /// <summary>
@@ -395,7 +391,7 @@ public class LocationLootGenerator(
{ {
var chosenContainerIds = new List<string>(); var chosenContainerIds = new List<string>();
var containerIds = containerData.ContainerIdsWithProbability.Keys.ToList(); var containerIds = containerData.ContainerIdsWithProbability.Keys;
if (containerData.ChosenCount > containerIds.Count) if (containerData.ChosenCount > containerIds.Count)
{ {
if (_logger.IsLogEnabled(LogLevel.Debug)) if (_logger.IsLogEnabled(LogLevel.Debug))
@@ -405,7 +401,7 @@ public class LocationLootGenerator(
); );
} }
return containerIds; return containerIds.ToList();
} }
// Create probability array with all possible container ids in this group and their relative probability of spawning // Create probability array with all possible container ids in this group and their relative probability of spawning
@@ -429,7 +425,7 @@ public class LocationLootGenerator(
/// <returns>dictionary keyed by groupId</returns> /// <returns>dictionary keyed by groupId</returns>
protected Dictionary<string, ContainerGroupCount> GetGroupIdToContainerMappings( protected Dictionary<string, ContainerGroupCount> GetGroupIdToContainerMappings(
StaticContainer staticContainerGroupData, StaticContainer staticContainerGroupData,
List<StaticContainerData> staticContainersOnMap IEnumerable<StaticContainerData> staticContainersOnMap
) )
{ {
// Create dictionary of all group ids and choose a count of containers the map will spawn of that group // Create dictionary of all group ids and choose a count of containers the map will spawn of that group
@@ -532,7 +528,7 @@ public class LocationLootGenerator(
/// <returns>StaticContainerData</returns> /// <returns>StaticContainerData</returns>
protected StaticContainerData AddLootToContainer( protected StaticContainerData AddLootToContainer(
StaticContainerData staticContainer, StaticContainerData staticContainer,
List<StaticForced>? staticForced, IEnumerable<StaticForced>? staticForced,
Dictionary<string, StaticLootDetails> staticLootDist, Dictionary<string, StaticLootDetails> staticLootDist,
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist, Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
string locationName string locationName
@@ -639,9 +635,8 @@ public class LocationLootGenerator(
}; };
// Add loot to container before returning // Add loot to container before returning
containerClone.Template.Items.AddRange( var itemsToAdd = items.Select(item => item.ToLootItem()); // Convert into correct output type first
items.Select(item => item.ToLootItem()).ToList() // Convert into correct output type first containerClone.Template.Items = containerClone.Template.Items.Union(itemsToAdd);
);
} }
return containerClone; return containerClone;
@@ -776,16 +771,12 @@ public class LocationLootGenerator(
// Remove christmas items from loot data // Remove christmas items from loot data
if (!_seasonalEventService.ChristmasEventEnabled()) if (!_seasonalEventService.ChristmasEventEnabled())
{ {
dynamicLootDist.Spawnpoints = dynamicLootDist dynamicLootDist.Spawnpoints = dynamicLootDist.Spawnpoints.Where(point =>
.Spawnpoints.Where(point => !point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
!point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase) );
) dynamicLootDist.SpawnpointsForced = dynamicLootDist.SpawnpointsForced.Where(point =>
.ToList(); !point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
dynamicLootDist.SpawnpointsForced = dynamicLootDist );
.SpawnpointsForced.Where(point =>
!point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
)
.ToList();
} }
// Build the list of forced loot from both `SpawnpointsForced` and any point marked `IsAlwaysSpawn` // Build the list of forced loot from both `SpawnpointsForced` and any point marked `IsAlwaysSpawn`
@@ -929,7 +920,7 @@ public class LocationLootGenerator(
} }
// Spawn point has no items after filtering, skip // Spawn point has no items after filtering, skip
if (spawnPoint.Template.Items is null || spawnPoint.Template.Items.Count == 0) if (spawnPoint.Template.Items is null || !spawnPoint.Template.Items.Any())
{ {
if (_logger.IsLogEnabled(LogLevel.Debug)) if (_logger.IsLogEnabled(LogLevel.Debug))
{ {
@@ -1031,7 +1022,7 @@ public class LocationLootGenerator(
/// <param name="staticAmmoDist"></param> /// <param name="staticAmmoDist"></param>
/// <returns>Collection of spawn points with forced loot in them</returns> /// <returns>Collection of spawn points with forced loot in them</returns>
protected List<SpawnpointTemplate> GetForcedDynamicLoot( protected List<SpawnpointTemplate> GetForcedDynamicLoot(
List<Spawnpoint> forcedSpawnPoints, IEnumerable<Spawnpoint> forcedSpawnPoints,
string locationName, string locationName,
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist
) )
@@ -1105,7 +1096,7 @@ public class LocationLootGenerator(
/// <returns> ContainerItem object </returns> /// <returns> ContainerItem object </returns>
protected ContainerItem CreateDynamicLootItem( protected ContainerItem CreateDynamicLootItem(
SptLootItem chosenItem, SptLootItem chosenItem,
List<SptLootItem> lootItems, IEnumerable<SptLootItem> lootItems,
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist
) )
{ {
@@ -1282,17 +1273,20 @@ public class LocationLootGenerator(
var defaultPreset = _presetHelper.GetDefaultPreset(chosenTpl); var defaultPreset = _presetHelper.GetDefaultPreset(chosenTpl);
if (defaultPreset is not null) if (defaultPreset is not null)
{ {
var presetAndModsClone = _cloner.Clone(defaultPreset.Items).ReplaceIDs().ToList(); var presetAndModsClone = _cloner.Clone(defaultPreset.Items).ReplaceIDs();
presetAndModsClone.RemapRootItemId(); presetAndModsClone.RemapRootItemId();
// Use original items parentId otherwise item doesn't get added to container correctly // Use original items parentId otherwise item doesn't get added to container correctly
presetAndModsClone.FirstOrDefault().ParentId = rootItem.ParentId; presetAndModsClone.FirstOrDefault().ParentId = rootItem.ParentId;
items = presetAndModsClone; items = presetAndModsClone.ToList();
} }
else else
{ {
// We make base item in calling method, no need to do it here // We make base item in calling method, no need to do it here
if ((armorDbTemplate.Properties.Slots?.Count ?? 0) > 0) if (
armorDbTemplate.Properties?.Slots is not null
&& armorDbTemplate.Properties.Slots.Any()
)
{ {
items = _itemHelper.AddChildSlotItems( items = _itemHelper.AddChildSlotItems(
items, items,
@@ -343,9 +343,9 @@ public class RagfairOfferGenerator(
/// Create multiple offers for items by using a unique list of items we've generated previously /// Create multiple offers for items by using a unique list of items we've generated previously
/// </summary> /// </summary>
/// <param name="expiredOffers"> Optional, expired offers to regenerate </param> /// <param name="expiredOffers"> Optional, expired offers to regenerate </param>
public void GenerateDynamicOffers(List<List<Item>>? expiredOffers = null) public void GenerateDynamicOffers(IEnumerable<List<Item>>? expiredOffers = null)
{ {
var replacingExpiredOffers = (expiredOffers?.Count ?? 0) > 0; var replacingExpiredOffers = expiredOffers is not null && expiredOffers.Any();
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
// get assort items from param if they exist, otherwise grab freshly generated assorts // get assort items from param if they exist, otherwise grab freshly generated assorts
@@ -356,7 +356,7 @@ public class RagfairOfferGenerator(
if (logger.IsLogEnabled(LogLevel.Debug) && stopwatch.ElapsedMilliseconds > 0) if (logger.IsLogEnabled(LogLevel.Debug) && stopwatch.ElapsedMilliseconds > 0)
{ {
logger.Debug( logger.Debug(
$"Took {stopwatch.ElapsedMilliseconds}ms to GetRagfairAssorts - {assortItemsToProcess.Count} items" $"Took {stopwatch.ElapsedMilliseconds}ms to GetRagfairAssorts - {assortItemsToProcess.Count()} items"
); );
} }
@@ -209,11 +209,14 @@ public class ExplorationQuestGenerator(
/// <param name="locationKey">Map id (e.g. factory4_day)</param> /// <param name="locationKey">Map id (e.g. factory4_day)</param>
/// <param name="playerGroup">Pmc/Scav</param> /// <param name="playerGroup">Pmc/Scav</param>
/// <returns>List of Exit objects</returns> /// <returns>List of Exit objects</returns>
protected List<Exit>? GetLocationExitsForSide(string locationKey, PlayerGroup playerGroup) protected IEnumerable<Exit>? GetLocationExitsForSide(
string locationKey,
PlayerGroup playerGroup
)
{ {
var mapExtracts = databaseService.GetLocation(locationKey.ToLowerInvariant())?.AllExtracts; var mapExtracts = databaseService.GetLocation(locationKey.ToLowerInvariant())?.AllExtracts;
return mapExtracts?.Where(exit => exit.Side == Enum.GetName(playerGroup)).ToList(); return mapExtracts?.Where(exit => exit.Side == Enum.GetName(playerGroup));
} }
/// <summary> /// <summary>
@@ -308,18 +311,16 @@ public class ExplorationQuestGenerator(
} }
// Only get exits that have a greater than 0% chance to spawn // Only get exits that have a greater than 0% chance to spawn
var exitPool = mapExits.Where(exit => exit.Chance > 0).ToList(); var exitPool = mapExits.Where(exit => exit.Chance > 0);
// Exclude exits with a requirement to leave (e.g. car extracts) // Exclude exits with a requirement to leave (e.g. car extracts)
var possibleExits = exitPool var possibleExits = exitPool.Where(exit =>
.Where(exit => repeatableConfig.QuestConfig.Exploration.SpecificExits.PassageRequirementWhitelist.Contains(
repeatableConfig.QuestConfig.Exploration.SpecificExits.PassageRequirementWhitelist.Contains( "PassageRequirement"
"PassageRequirement"
)
) )
.ToList(); );
if (possibleExits.Count == 0) if (!possibleExits.Any())
{ {
logger.Error( logger.Error(
localisationService.GetText( localisationService.GetText(
@@ -332,7 +333,7 @@ public class ExplorationQuestGenerator(
} }
// Choose one of the exits we filtered above // Choose one of the exits we filtered above
var chosenExit = randomUtil.DrawRandomFromList(possibleExits)[0]; var chosenExit = randomUtil.DrawRandomFromList(possibleExits.ToList())[0];
// Create a quest condition to leave raid via chosen exit // Create a quest condition to leave raid via chosen exit
var exitCondition = GenerateQuestConditionCounter(chosenExit); var exitCondition = GenerateQuestConditionCounter(chosenExit);
@@ -596,7 +596,7 @@ public class BotGeneratorHelper(
continue; continue;
} }
if (itemDbDetails?.Properties?.Grids?.Count == 0) if (itemDbDetails?.Properties?.Grids is null || !itemDbDetails.Properties.Grids.Any())
// Container has no slots to hold items // Container has no slots to hold items
{ {
continue; continue;
@@ -611,15 +611,11 @@ public class BotGeneratorHelper(
// Iterate over each grid in the container and look for a big enough space for the item to be placed in // Iterate over each grid in the container and look for a big enough space for the item to be placed in
var currentGridCount = 1; var currentGridCount = 1;
var totalSlotGridCount = itemDbDetails?.Properties?.Grids?.Count; var totalSlotGridCount = itemDbDetails?.Properties?.Grids?.Count();
foreach (var slotGrid in itemDbDetails?.Properties?.Grids ?? []) foreach (var slotGrid in itemDbDetails?.Properties?.Grids ?? [])
{ {
// Grid is empty, skip or item size is bigger than grid // Grid is empty, skip or item size is bigger than grid
if ( if (IsGridSmallerThanItem(slotGrid, itemWidth, itemHeight))
slotGrid.Props?.CellsH == 0
|| slotGrid.Props?.CellsV == 0
|| itemWidth * itemHeight > slotGrid.Props?.CellsV * slotGrid.Props?.CellsH
)
{ {
continue; continue;
} }
@@ -711,6 +707,13 @@ public class BotGeneratorHelper(
return ItemAddedResult.NO_SPACE; return ItemAddedResult.NO_SPACE;
} }
protected static bool IsGridSmallerThanItem(Grid slotGrid, int itemWidth, int itemHeight)
{
return slotGrid.Props?.CellsH == 0
|| slotGrid.Props?.CellsV == 0
|| itemWidth * itemHeight > slotGrid.Props?.CellsV * slotGrid.Props?.CellsH;
}
/// <summary> /// <summary>
/// Take a list of items and check if they need children + add them /// Take a list of items and check if they need children + add them
/// </summary> /// </summary>
@@ -44,7 +44,7 @@ public class BotWeaponGeneratorHelper(
chamberBulletCount = chamberBulletCount =
ammoMaxStackSize == 1 ammoMaxStackSize == 1
? 1 // Rotating grenade launcher ? 1 // Rotating grenade launcher
: magTemplate.Properties.Slots.Count; // Shotguns/revolvers. We count the number of camoras as the _max_count of the magazine is 0 : magTemplate.Properties.Slots.Count(); // Shotguns/revolvers. We count the number of camoras as the _max_count of the magazine is 0
} }
else if (parentItem.Id == BaseClasses.UBGL) else if (parentItem.Id == BaseClasses.UBGL)
{ {
@@ -369,9 +369,10 @@ public class ItemHelper(
{ {
var itemTemplate = GetItem(itemTpl); var itemTemplate = GetItem(itemTpl);
return itemTemplate.Value.Properties.Slots.Any(slot => return itemTemplate.Value?.Properties?.Slots is not null
_removablePlateSlotIds.Contains(slot.Name.ToLowerInvariant()) && itemTemplate.Value.Properties.Slots.Any(slot =>
); _removablePlateSlotIds.Contains(slot.Name.ToLowerInvariant())
);
} }
/// <summary> /// <summary>
@@ -543,7 +544,7 @@ public class ItemHelper(
{ {
if (databaseService.GetItems().TryGetValue(itemTpl, out var item)) if (databaseService.GetItems().TryGetValue(itemTpl, out var item))
{ {
return item?.Properties?.Slots?.Count > 0; return item.Properties?.Slots is not null && item.Properties.Slots.Any();
} }
return false; return false;
@@ -1534,7 +1535,7 @@ public class ItemHelper(
magTemplate.Id, magTemplate.Id,
BaseClasses.SPRING_DRIVEN_CYLINDER BaseClasses.SPRING_DRIVEN_CYLINDER
) )
? magProps?.Slots?.Count // Edge case for rotating grenade launcher magazine ? magProps?.Slots?.Count() // Edge case for rotating grenade launcher magazine
: magProps?.Cartridges?.FirstOrDefault()?.MaxCount; : magProps?.Cartridges?.FirstOrDefault()?.MaxCount;
if (magazineCartridgeMaxCount is null) if (magazineCartridgeMaxCount is null)
@@ -2001,8 +2002,8 @@ public class ItemHelper(
var containerTemplate = GetItem(containerTpl).Value; var containerTemplate = GetItem(containerTpl).Value;
// Get height/width // Get height/width
var height = containerTemplate.Properties.Grids[0].Props.CellsV; var height = containerTemplate.Properties.Grids.First().Props.CellsV;
var width = containerTemplate.Properties.Grids[0].Props.CellsH; var width = containerTemplate.Properties.Grids.First().Props.CellsH;
return GetBlankContainerMap(width.Value, height.Value); return GetBlankContainerMap(width.Value, height.Value);
} }
@@ -225,7 +225,7 @@ public class RagfairOfferHelper(
PmcData pmcData PmcData pmcData
) )
{ {
var offersMap = new Dictionary<string, List<RagfairOffer>>(); var offersMap = new Dictionary<MongoId, List<RagfairOffer>>();
var offersToReturn = new List<RagfairOffer>(); var offersToReturn = new List<RagfairOffer>();
var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(timeUtil.GetTimeStamp()); var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(timeUtil.GetTimeStamp());
var tieredFlea = _ragfairConfig.TieredFlea; var tieredFlea = _ragfairConfig.TieredFlea;
@@ -720,7 +720,7 @@ public record PveSettings
[JsonExtensionData] [JsonExtensionData]
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
public List<string> AvailableVersions { get; set; } public IEnumerable<string> AvailableVersions { get; set; }
public bool ModeEnabled { get; set; } public bool ModeEnabled { get; set; }
} }
@@ -730,7 +730,7 @@ public record CoopSettings
[JsonExtensionData] [JsonExtensionData]
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
public List<string> AvailableVersions { get; set; } public IEnumerable<string> AvailableVersions { get; set; }
} }
public record RunddansSettings public record RunddansSettings
@@ -739,7 +739,7 @@ public record RunddansSettings
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
[JsonPropertyName("accessKeys")] [JsonPropertyName("accessKeys")]
public List<string> AccessKeys { get; set; } public IEnumerable<string> AccessKeys { get; set; }
[JsonPropertyName("active")] [JsonPropertyName("active")]
public bool Active { get; set; } public bool Active { get; set; }
@@ -751,7 +751,7 @@ public record RunddansSettings
public double ApplyFrozenEverySec { get; set; } public double ApplyFrozenEverySec { get; set; }
[JsonPropertyName("consumables")] [JsonPropertyName("consumables")]
public List<string> Consumables { get; set; } public IEnumerable<string> Consumables { get; set; }
[JsonPropertyName("drunkImmunitySec")] [JsonPropertyName("drunkImmunitySec")]
public double DrunkImmunitySec { get; set; } public double DrunkImmunitySec { get; set; }
@@ -772,13 +772,13 @@ public record RunddansSettings
public double KnifeCritChanceToBreak { get; set; } public double KnifeCritChanceToBreak { get; set; }
[JsonPropertyName("locations")] [JsonPropertyName("locations")]
public List<string> Locations { get; set; } public IEnumerable<string> Locations { get; set; }
[JsonPropertyName("multitoolRepairSec")] [JsonPropertyName("multitoolRepairSec")]
public double MultitoolRepairSec { get; set; } public double MultitoolRepairSec { get; set; }
[JsonPropertyName("nonExitsLocations")] [JsonPropertyName("nonExitsLocations")]
public List<string> NonExitsLocations { get; set; } public IEnumerable<string> NonExitsLocations { get; set; }
[JsonPropertyName("rainForFrozen")] [JsonPropertyName("rainForFrozen")]
public double RainForFrozen { get; set; } public double RainForFrozen { get; set; }
@@ -790,7 +790,7 @@ public record RunddansSettings
public XY SecToBreak { get; set; } public XY SecToBreak { get; set; }
[JsonPropertyName("sleighLocations")] [JsonPropertyName("sleighLocations")]
public List<string> SleighLocations { get; set; } public IEnumerable<string> SleighLocations { get; set; }
} }
public record SeasonActivity public record SeasonActivity
@@ -1627,7 +1627,7 @@ public record CustomizationVoice
public string Voice { get; set; } public string Voice { get; set; }
[JsonPropertyName("side")] [JsonPropertyName("side")]
public List<string> Side { get; set; } public IEnumerable<string> Side { get; set; }
[JsonPropertyName("isNotRandom")] [JsonPropertyName("isNotRandom")]
public bool IsNotRandom { get; set; } public bool IsNotRandom { get; set; }
@@ -2310,7 +2310,7 @@ public record Buff
[JsonPropertyName("SkillName")] [JsonPropertyName("SkillName")]
public string SkillName { get; set; } public string SkillName { get; set; }
public List<string> AppliesTo { get; set; } public IEnumerable<string> AppliesTo { get; set; }
} }
public record Tremor public record Tremor
@@ -3287,7 +3287,7 @@ public record BTRSettings
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
[JsonPropertyName("LocationsWithBTR")] [JsonPropertyName("LocationsWithBTR")]
public List<string> LocationsWithBTR { get; set; } public IEnumerable<string> LocationsWithBTR { get; set; }
[JsonPropertyName("BasePriceTaxi")] [JsonPropertyName("BasePriceTaxi")]
public double BasePriceTaxi { get; set; } public double BasePriceTaxi { get; set; }
@@ -3422,7 +3422,7 @@ public record PathConfig
public string ExitPoint { get; set; } public string ExitPoint { get; set; }
[JsonPropertyName("pathPoints")] [JsonPropertyName("pathPoints")]
public List<string> PathPoints { get; set; } public IEnumerable<string> PathPoints { get; set; }
[JsonPropertyName("once")] [JsonPropertyName("once")]
public bool Once { get; set; } public bool Once { get; set; }
@@ -3434,7 +3434,7 @@ public record PathConfig
public double CircleCount { get; set; } public double CircleCount { get; set; }
[JsonPropertyName("skinType")] [JsonPropertyName("skinType")]
public List<string> SkinType { get; set; } public IEnumerable<string> SkinType { get; set; }
} }
public record SquadSettings public record SquadSettings
@@ -4927,10 +4927,10 @@ public record RepairStrategy
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
[JsonPropertyName("BuffTypes")] [JsonPropertyName("BuffTypes")]
public List<string> BuffTypes { get; set; } public IEnumerable<string> BuffTypes { get; set; }
[JsonPropertyName("Filter")] [JsonPropertyName("Filter")]
public List<string> Filter { get; set; } public IEnumerable<string> Filter { get; set; }
} }
public record BotPreset public record BotPreset
@@ -46,7 +46,7 @@ public record Location
/// All possible map extracts /// All possible map extracts
/// </summary> /// </summary>
[JsonPropertyName("allExtracts")] [JsonPropertyName("allExtracts")]
public Exit[] AllExtracts { get; set; } public IEnumerable<Exit> AllExtracts { get; set; }
} }
public record StaticContainer public record StaticContainer
@@ -133,10 +133,10 @@ public record StaticContainerDetails
public List<SpawnpointTemplate> StaticWeapons { get; set; } public List<SpawnpointTemplate> StaticWeapons { get; set; }
[JsonPropertyName("staticContainers")] [JsonPropertyName("staticContainers")]
public List<StaticContainerData> StaticContainers { get; set; } public IEnumerable<StaticContainerData> StaticContainers { get; set; }
[JsonPropertyName("staticForced")] [JsonPropertyName("staticForced")]
public List<StaticForced> StaticForced { get; set; } public IEnumerable<StaticForced> StaticForced { get; set; }
} }
public record StaticForced public record StaticForced
@@ -12,10 +12,10 @@ public record LooseLoot
public SpawnpointCount? SpawnpointCount { get; set; } public SpawnpointCount? SpawnpointCount { get; set; }
[JsonPropertyName("spawnpointsForced")] [JsonPropertyName("spawnpointsForced")]
public List<Spawnpoint>? SpawnpointsForced { get; set; } public IEnumerable<Spawnpoint>? SpawnpointsForced { get; set; }
[JsonPropertyName("spawnpoints")] [JsonPropertyName("spawnpoints")]
public List<Spawnpoint>? Spawnpoints { get; set; } public IEnumerable<Spawnpoint>? Spawnpoints { get; set; }
} }
public record SpawnpointCount public record SpawnpointCount
@@ -65,7 +65,7 @@ public record SpawnpointTemplate
public bool? IsGroupPosition { get; set; } public bool? IsGroupPosition { get; set; }
[JsonPropertyName("GroupPositions")] [JsonPropertyName("GroupPositions")]
public List<GroupPosition>? GroupPositions { get; set; } public IEnumerable<GroupPosition>? GroupPositions { get; set; }
[JsonPropertyName("Root")] [JsonPropertyName("Root")]
public string? Root public string? Root
@@ -75,7 +75,7 @@ public record SpawnpointTemplate
} }
[JsonPropertyName("Items")] [JsonPropertyName("Items")]
public List<SptLootItem>? Items { get; set; } public IEnumerable<SptLootItem>? Items { get; set; }
} }
public record SptLootItem : Item public record SptLootItem : Item
@@ -123,7 +123,7 @@ public record Spawnpoint
public SpawnpointTemplate? Template { get; set; } public SpawnpointTemplate? Template { get; set; }
[JsonPropertyName("itemDistribution")] [JsonPropertyName("itemDistribution")]
public List<LooseLootItemDistribution>? ItemDistribution { get; set; } public IEnumerable<LooseLootItemDistribution>? ItemDistribution { get; set; }
} }
public record LooseLootItemDistribution public record LooseLootItemDistribution
@@ -199,7 +199,7 @@ public record LockableComponent
[JsonExtensionData] [JsonExtensionData]
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
public List<string>? KeyIds { get; set; } public IEnumerable<string>? KeyIds { get; set; }
public bool? Locked { get; set; } public bool? Locked { get; set; }
public LockableKeyComponent? KeyComponent { get; set; } public LockableKeyComponent? KeyComponent { get; set; }
} }
@@ -327,10 +327,10 @@ public record UpdSight
public Dictionary<string, object>? ExtensionData { get; set; } public Dictionary<string, object>? ExtensionData { get; set; }
[JsonPropertyName("ScopesCurrentCalibPointIndexes")] [JsonPropertyName("ScopesCurrentCalibPointIndexes")]
public List<int>? ScopesCurrentCalibPointIndexes { get; set; } public IEnumerable<int>? ScopesCurrentCalibPointIndexes { get; set; }
[JsonPropertyName("ScopesSelectedModes")] [JsonPropertyName("ScopesSelectedModes")]
public List<int>? ScopesSelectedModes { get; set; } public IEnumerable<int>? ScopesSelectedModes { get; set; }
[JsonPropertyName("SelectedScope")] [JsonPropertyName("SelectedScope")]
public int? SelectedScope { get; set; } public int? SelectedScope { get; set; }
@@ -353,10 +353,10 @@ public record Props
public bool? DogTagQualities { get; set; } public bool? DogTagQualities { get; set; }
[JsonPropertyName("Grids")] [JsonPropertyName("Grids")]
public List<Grid>? Grids { get; set; } public IEnumerable<Grid>? Grids { get; set; }
[JsonPropertyName("Slots")] [JsonPropertyName("Slots")]
public List<Slot>? Slots { get; set; } public IEnumerable<Slot>? Slots { get; set; }
[JsonPropertyName("CanPutIntoDuringTheRaid")] [JsonPropertyName("CanPutIntoDuringTheRaid")]
public bool? CanPutIntoDuringTheRaid { get; set; } public bool? CanPutIntoDuringTheRaid { get; set; }
@@ -89,8 +89,8 @@ public class BotEquipmentModPoolService(
continue; continue;
} }
// Skip item without slots // No slots
if (item.Properties.Slots is null || item.Properties.Slots.Count == 0) if (item.Properties?.Slots is null || !item.Properties.Slots.Any())
{ {
continue; continue;
} }
@@ -120,7 +120,9 @@ public class BotEquipmentModPoolService(
} }
var subItemDetails = itemHelper.GetItem(itemToAddTpl).Value; var subItemDetails = itemHelper.GetItem(itemToAddTpl).Value;
var hasSubItemsToAdd = (subItemDetails?.Properties?.Slots?.Count ?? 0) > 0; var hasSubItemsToAdd =
subItemDetails.Properties?.Slots is not null
&& subItemDetails.Properties.Slots.Any();
// Item has Slots + pool doesn't have value // Item has Slots + pool doesn't have value
if (hasSubItemsToAdd && !pool.ContainsKey(subItemDetails.Id)) if (hasSubItemsToAdd && !pool.ContainsKey(subItemDetails.Id))
@@ -221,7 +223,7 @@ public class BotEquipmentModPoolService(
// Get item from db // Get item from db
var itemDb = itemHelper.GetItem(itemTpl).Value; var itemDb = itemHelper.GetItem(itemTpl).Value;
if (itemDb.Properties.Slots is not null) if (itemDb.Properties?.Slots is not null)
// Loop over slots flagged as 'required' // Loop over slots flagged as 'required'
{ {
foreach ( foreach (
@@ -122,7 +122,7 @@ public class BotWeaponModLimitService(
// Mount has one slot and it is for a mod_scope // Mount has one slot and it is for a mod_scope
if ( if (
modLimits.Scope.Count >= modLimits.ScopeMax modLimits.Scope.Count >= modLimits.ScopeMax
&& modTemplate.Properties.Slots?.Count == 1 && modTemplate.Properties?.Slots?.Count() == 1
&& itemHelper.IsOfBaseclass(modTemplate.Id, BaseClasses.MOUNT) && itemHelper.IsOfBaseclass(modTemplate.Id, BaseClasses.MOUNT)
&& !itemHelper.IsOfBaseclass(modsParent.Id, BaseClasses.MOUNT) && !itemHelper.IsOfBaseclass(modsParent.Id, BaseClasses.MOUNT)
&& modTemplate.Properties.Slots.Any(slot => slot.Name == "mod_scope") && modTemplate.Properties.Slots.Any(slot => slot.Name == "mod_scope")
@@ -149,7 +149,7 @@ public class BotWeaponModLimitService(
// Mod is a mount that can hold only flashlights ad limit is reached (don't want to add empty mounts if limit is reached) // Mod is a mount that can hold only flashlights ad limit is reached (don't want to add empty mounts if limit is reached)
if ( if (
modLimits.Scope.Count >= modLimits.ScopeMax modLimits.Scope.Count >= modLimits.ScopeMax
&& modTemplate.Properties.Slots?.Count == 1 && modTemplate.Properties?.Slots?.Count() == 1
&& itemHelper.IsOfBaseclass(modTemplate.Id, BaseClasses.MOUNT) && itemHelper.IsOfBaseclass(modTemplate.Id, BaseClasses.MOUNT)
&& modTemplate.Properties.Slots.Any(slot => slot.Name == "mod_flashlight") && modTemplate.Properties.Slots.Any(slot => slot.Name == "mod_flashlight")
) )
@@ -951,7 +951,8 @@ public class FenceService(
rootItemBeingAdded.Template, rootItemBeingAdded.Template,
[BaseClasses.ARMORED_EQUIPMENT, BaseClasses.SEARCHABLE_ITEM] [BaseClasses.ARMORED_EQUIPMENT, BaseClasses.SEARCHABLE_ITEM]
) )
&& (itemDbDetails.Properties.Slots?.Count ?? 0) > 0; && itemDbDetails?.Properties?.Slots is not null
&& itemDbDetails.Properties.Slots.Any();
// Only one match and it's not medical or armored gear // Only one match and it's not medical or armored gear
if (matchingItems.Count == 1 && !(isMedical || isGearAndHasSlots)) if (matchingItems.Count == 1 && !(isMedical || isGearAndHasSlots))
@@ -288,7 +288,7 @@ public class CustomItemService(
protected void AddToWeaponShelf(string newItemId) protected void AddToWeaponShelf(string newItemId)
{ {
// Ids for wall stashes in db // Ids for wall stashes in db
List<string> wallStashIds = List<MongoId> wallStashIds =
[ [
ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_1, ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_1,
ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_2, ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_2,
@@ -299,7 +299,7 @@ public class CustomItemService(
var wall = itemHelper.GetItem(wallId); var wall = itemHelper.GetItem(wallId);
if (wall.Key) if (wall.Key)
{ {
wall.Value.Properties.Grids[0].Props.Filters[0].Filter.Add(newItemId); wall.Value.Properties.Grids.First().Props.Filters[0].Filter.Add(newItemId);
} }
} }
} }
@@ -391,18 +391,21 @@ public class PostDbLoadService(
if (existingLootPosition is not null) if (existingLootPosition is not null)
{ {
existingLootPosition.Template.Items.AddRange( existingLootPosition.Template.Items =
positionToAdd.Template.Items existingLootPosition.Template.Items.Union(
); positionToAdd.Template.Items
existingLootPosition.ItemDistribution.AddRange( );
positionToAdd.ItemDistribution
); existingLootPosition.ItemDistribution =
existingLootPosition.ItemDistribution.Union(
positionToAdd.ItemDistribution
);
continue; continue;
} }
// New position, add entire object // New position, add entire object
looselootData.Spawnpoints.Add(positionToAdd); looselootData.Spawnpoints = looselootData.Spawnpoints.Append(positionToAdd);
} }
return looselootData; return looselootData;
@@ -153,7 +153,7 @@ public class RagfairLinkedItemService(
var result = new HashSet<MongoId>(); var result = new HashSet<MongoId>();
var slots = item.Properties?.Slots; var slots = item.Properties?.Slots;
if (slots is null || slots.Count == 0) if (slots is null || !slots.Any())
{ {
// No slots, skip // No slots, skip
return result; return result;
@@ -49,7 +49,7 @@ public class RagfairOfferService(
return ragfairOfferHolder.GetOfferById(offerId); return ragfairOfferHolder.GetOfferById(offerId);
} }
public List<RagfairOffer>? GetOffersOfType(MongoId templateId) public IEnumerable<RagfairOffer>? GetOffersOfType(MongoId templateId)
{ {
return ragfairOfferHolder.GetOffersByTemplate(templateId); return ragfairOfferHolder.GetOffersByTemplate(templateId);
} }
@@ -68,7 +68,7 @@ public class RagfairOfferHolder(
/// </summary> /// </summary>
/// <param name="templateId">Tpl to get offers for</param> /// <param name="templateId">Tpl to get offers for</param>
/// <returns>RagfairOffer list</returns> /// <returns>RagfairOffer list</returns>
public List<RagfairOffer>? GetOffersByTemplate(MongoId templateId) public IEnumerable<RagfairOffer>? GetOffersByTemplate(MongoId templateId)
{ {
// Get the offerIds we want to return // Get the offerIds we want to return
if (!_offersByTemplate.TryGetValue(templateId, out var offerIds)) if (!_offersByTemplate.TryGetValue(templateId, out var offerIds))
@@ -76,7 +76,7 @@ public class RagfairOfferHolder(
return null; return null;
} }
var result = _offersById.Where(x => offerIds.Contains(x.Key)).Select(x => x.Value).ToList(); var result = _offersById.Where(x => offerIds.Contains(x.Key)).Select(x => x.Value);
return result; return result;
} }
@@ -86,7 +86,7 @@ public class RagfairOfferHolder(
/// </summary> /// </summary>
/// <param name="traderId">Id of trader to get offers for</param> /// <param name="traderId">Id of trader to get offers for</param>
/// <returns>RagfairOffer list</returns> /// <returns>RagfairOffer list</returns>
public List<RagfairOffer> GetOffersByTrader(MongoId traderId) public IEnumerable<RagfairOffer> GetOffersByTrader(MongoId traderId)
{ {
if (!_offersByTrader.TryGetValue(traderId, out var offerIds)) if (!_offersByTrader.TryGetValue(traderId, out var offerIds))
{ {
@@ -95,8 +95,7 @@ public class RagfairOfferHolder(
return offerIds return offerIds
.Select(offerId => _offersById.GetValueOrDefault(offerId)) .Select(offerId => _offersById.GetValueOrDefault(offerId))
.Where(offer => offer != null) .Where(offer => offer != null);
.ToList();
} }
/// <summary> /// <summary>
@@ -117,7 +116,7 @@ public class RagfairOfferHolder(
/// Add a collection of offers to ragfair /// Add a collection of offers to ragfair
/// </summary> /// </summary>
/// <param name="offers">Offers to add</param> /// <param name="offers">Offers to add</param>
public void AddOffers(List<RagfairOffer> offers) public void AddOffers(IEnumerable<RagfairOffer> offers)
{ {
foreach (var offer in offers) foreach (var offer in offers)
{ {
@@ -326,7 +325,7 @@ public class RagfairOfferHolder(
/// Get an array of arrays of expired offer items + children /// Get an array of arrays of expired offer items + children
/// </summary> /// </summary>
/// <returns>Expired offer assorts</returns> /// <returns>Expired offer assorts</returns>
public List<List<Item>> GetExpiredOfferItems() public IEnumerable<List<Item>> GetExpiredOfferItems()
{ {
lock (_expiredOfferIdsLock) lock (_expiredOfferIdsLock)
{ {
@@ -1,7 +1,6 @@
using MongoIdTplGenerator.Utils; using MongoIdTplGenerator.Utils;
using SPTarkov.Common.Extensions; using SPTarkov.Common.Extensions;
using SPTarkov.DI.Annotations; using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.DI;
using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Helpers;
using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Common.Tables;
@@ -498,7 +497,7 @@ public class ItemTplMongoIdGenerator(
// Add grid size for lootable containers // Add grid size for lootable containers
if (itemHelper.IsOfBaseclass(item.Id, BaseClasses.LOOT_CONTAINER)) if (itemHelper.IsOfBaseclass(item.Id, BaseClasses.LOOT_CONTAINER))
{ {
return $"{item.Properties.Grids[0]?.Props.CellsH}X{item.Properties.Grids[0]?.Props.CellsV}"; return $"{item.Properties.Grids.First()?.Props.CellsH}X{item.Properties.Grids.First()?.Props.CellsV}";
} }
// Add ammo caliber to conflicting weapons // Add ammo caliber to conflicting weapons