Fix most warnings inside ItemHelper.cs (#541)

This commit is contained in:
Chomp
2025-08-10 11:15:06 +00:00
committed by GitHub
2 changed files with 144 additions and 99 deletions
@@ -0,0 +1,10 @@
namespace SPTarkov.Server.Core.Exceptions.Items;
public class ItemHelperException : Exception
{
public ItemHelperException(string message)
: base(message) { }
public ItemHelperException(string message, Exception innerException)
: base(message, innerException) { }
}
@@ -1,5 +1,6 @@
using System.Collections.Frozen;
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Exceptions.Items;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common;
@@ -128,7 +129,7 @@ public class ItemHelper(
/// <param name="tpl">Item tpl to find</param>
/// <param name="slotId">OPTIONAL - slotId of desired item</param>
/// <returns>Item or null if no item found</returns>
public Item GetItemFromPoolByTpl(IEnumerable<Item> itemPool, MongoId tpl, string slotId = "")
public Item? GetItemFromPoolByTpl(IEnumerable<Item> itemPool, MongoId tpl, string slotId = "")
{
// Filter the pool by slotId if provided
var filteredPool = string.IsNullOrEmpty(slotId)
@@ -182,7 +183,7 @@ public class ItemHelper(
Upd itemProperties = new();
// Armors, etc
if (itemTemplate.Properties.MaxDurability is not null)
if (itemTemplate.Properties?.MaxDurability is not null)
{
itemProperties.Repairable = new UpdRepairable
{
@@ -191,43 +192,34 @@ public class ItemHelper(
};
}
if (itemTemplate.Properties.HasHinge ?? false)
if (itemTemplate.Properties?.HasHinge ?? false)
{
itemProperties.Togglable = new UpdTogglable { On = true };
}
if (itemTemplate.Properties.Foldable ?? false)
if (itemTemplate.Properties?.Foldable ?? false)
{
itemProperties.Foldable = new UpdFoldable { Folded = false };
}
if (itemTemplate.Properties.WeapFireType?.Any() ?? false)
if (itemTemplate.Properties?.WeapFireType?.Count == 0)
{
if (itemTemplate.Properties.WeapFireType.Contains("fullauto"))
{
itemProperties.FireMode = new UpdFireMode { FireMode = "fullauto" };
}
else
{
itemProperties.FireMode = new UpdFireMode { FireMode = randomUtil.GetArrayValue(itemTemplate.Properties.WeapFireType) };
}
itemProperties.FireMode = itemTemplate.Properties.WeapFireType.Contains("fullauto")
? new UpdFireMode { FireMode = "fullauto" }
: new UpdFireMode { FireMode = randomUtil.GetArrayValue(itemTemplate.Properties.WeapFireType) };
}
if (itemTemplate.Properties.MaxHpResource is not null)
if (itemTemplate.Properties?.MaxHpResource is not null)
{
itemProperties.MedKit = new UpdMedKit { HpResource = itemTemplate.Properties.MaxHpResource };
}
if (itemTemplate.Properties.MaxResource is not null && itemTemplate.Properties.FoodUseTime is not null)
if (itemTemplate.Properties?.MaxResource is not null && itemTemplate.Properties.FoodUseTime is not null)
{
itemProperties.FoodDrink = new UpdFoodDrink { HpPercent = itemTemplate.Properties.MaxResource };
}
if (itemTemplate.Parent == BaseClasses.FLASHLIGHT)
{
itemProperties.Light = new UpdLight { IsActive = false, SelectedMode = 0 };
}
else if (itemTemplate.Parent == BaseClasses.TACTICAL_COMBO)
if (itemTemplate.Parent == BaseClasses.FLASHLIGHT || itemTemplate.Parent == BaseClasses.TACTICAL_COMBO)
{
itemProperties.Light = new UpdLight { IsActive = false, SelectedMode = 0 };
}
@@ -238,7 +230,7 @@ public class ItemHelper(
}
// Toggleable face shield
if ((itemTemplate.Properties.HasHinge ?? false) && (itemTemplate.Properties.FaceShieldComponent ?? false))
if ((itemTemplate.Properties?.HasHinge ?? false) && (itemTemplate.Properties.FaceShieldComponent ?? false))
{
itemProperties.Togglable = new UpdTogglable { On = false };
}
@@ -248,11 +240,17 @@ public class ItemHelper(
/// <summary>
/// Checks if a tpl is a valid item. Valid meaning that it's an item that can be stored in stash
/// <br/><br/>
/// Valid means:
/// <br/>
/// Not quest item
/// <br/>
/// 'Item' type
/// <br/>
/// Not on the invalid base types array
/// <br/>
/// Price above 0 roubles
/// <br/>
/// </summary>
/// <param name="tpl">Template id to check</param>
/// <param name="invalidBaseTypes">OPTIONAL - Base types deemed invalid</param>
@@ -262,6 +260,11 @@ public class ItemHelper(
var baseTypes = invalidBaseTypes ?? _defaultInvalidBaseTypes;
var itemDetails = GetItem(tpl);
if (itemDetails.Value is null)
{
return false;
}
return itemDetails.Key && IsValidItem(itemDetails.Value, baseTypes);
}
@@ -280,7 +283,7 @@ public class ItemHelper(
{
var baseTypes = invalidBaseTypes ?? _defaultInvalidBaseTypes;
return !(item.Properties.QuestItem ?? false)
return !(item.Properties?.QuestItem ?? false)
&& string.Equals(item.Type, "Item", StringComparison.OrdinalIgnoreCase)
&& GetItemPrice(item.Id) > 0
&& !itemFilterService.IsItemBlacklisted(item.Id)
@@ -346,7 +349,9 @@ public class ItemHelper(
var itemTemplate = GetItem(itemTpl);
return itemTemplate.Value?.Properties?.Slots is not null
&& itemTemplate.Value.Properties.Slots.Any(slot => _removablePlateSlotIds.Contains(slot.Name.ToLowerInvariant()));
&& itemTemplate.Value.Properties.Slots.Any(slot =>
_removablePlateSlotIds.Contains(slot.Name?.ToLowerInvariant() ?? string.Empty)
);
}
/// <summary>
@@ -370,18 +375,13 @@ public class ItemHelper(
}
// Has no slots
if (!(itemDbDetails.Value.Properties.Slots ?? []).Any())
if (!(itemDbDetails.Value?.Properties?.Slots ?? []).Any())
{
return false;
}
// Check if item has slots that match soft insert name ids
if (itemDbDetails.Value.Properties.Slots.Any(slot => IsSoftInsertId(slot.Name.ToLowerInvariant())))
{
return true;
}
return false;
return itemDbDetails.Value?.Properties?.Slots?.Any(slot => IsSoftInsertId(slot.Name?.ToLowerInvariant() ?? string.Empty)) ?? false;
}
/// <summary>
@@ -481,7 +481,7 @@ public class ItemHelper(
/// Get cloned copy of all item data from items.json
/// </summary>
/// <returns>List of TemplateItem objects</returns>
public List<TemplateItem> GetItemsClone()
public List<TemplateItem>? GetItemsClone()
{
return cloner.Clone(databaseService.GetItems().Values.ToList());
}
@@ -588,7 +588,7 @@ public class ItemHelper(
if (
skipArmorItemsWithoutDurability
&& IsOfBaseclass(item.Template, BaseClasses.ARMOR)
&& itemDetails?.Properties?.MaxDurability == 0
&& itemDetails.Properties?.MaxDurability == 0
)
{
return -1;
@@ -599,7 +599,7 @@ public class ItemHelper(
if (item.Upd.MedKit is not null)
{
// Meds
result = (item.Upd.MedKit.HpResource ?? 0) / (itemDetails.Properties.MaxHpResource ?? 0);
result = (item.Upd.MedKit.HpResource ?? 0) / (itemDetails.Properties?.MaxHpResource ?? 0);
}
else if (item.Upd.Repairable is not null)
{
@@ -607,9 +607,9 @@ public class ItemHelper(
}
else if (item.Upd.FoodDrink is not null)
{
result = (item.Upd.FoodDrink.HpPercent ?? 0) / (itemDetails.Properties.MaxResource ?? 0);
result = (item.Upd.FoodDrink.HpPercent ?? 0) / (itemDetails.Properties?.MaxResource ?? 0);
}
else if (item.Upd.Key?.NumberOfUsages > 0 && itemDetails.Properties.MaximumNumberOfUsage > 0)
else if (item.Upd.Key?.NumberOfUsages > 0 && itemDetails.Properties?.MaximumNumberOfUsage > 0)
{
// keys - keys count upwards, not down like everything else
var maxNumOfUsages = itemDetails.Properties.MaximumNumberOfUsage;
@@ -618,11 +618,11 @@ public class ItemHelper(
else if (item.Upd.Resource?.UnitsConsumed > 0)
{
// E.g. fuel tank
result = (item.Upd.Resource.Value ?? 0) / (itemDetails.Properties.MaxResource ?? 0);
result = (item.Upd.Resource.Value ?? 0) / (itemDetails.Properties?.MaxResource ?? 0);
}
else if (item.Upd.RepairKit is not null)
{
result = (item.Upd.RepairKit.Resource ?? 0) / (itemDetails.Properties.MaxRepairResource ?? 0);
result = (item.Upd.RepairKit.Resource ?? 0) / (itemDetails.Properties?.MaxRepairResource ?? 0);
}
if (result == 0)
@@ -732,7 +732,7 @@ public class ItemHelper(
return null;
}
return item.Properties.StackMaxSize > 1;
return item.Properties?.StackMaxSize > 1;
}
/// <summary>
@@ -742,12 +742,12 @@ public class ItemHelper(
/// <returns>List of root item + children.</returns>
public List<Item> SplitStack(Item itemToSplit)
{
if (itemToSplit?.Upd?.StackObjectsCount is null)
if (itemToSplit.Upd?.StackObjectsCount is null)
{
return [itemToSplit];
}
var maxStackSize = GetItem(itemToSplit.Template).Value.Properties.StackMaxSize;
var maxStackSize = GetItem(itemToSplit.Template).Value?.Properties?.StackMaxSize;
var remainingCount = itemToSplit.Upd.StackObjectsCount;
List<Item> rootAndChildren = [];
@@ -755,7 +755,7 @@ public class ItemHelper(
// return the item as is.
if (remainingCount <= maxStackSize)
{
rootAndChildren.Add(cloner.Clone(itemToSplit));
rootAndChildren.Add(cloner.Clone(itemToSplit)!);
return rootAndChildren;
}
@@ -765,8 +765,8 @@ public class ItemHelper(
var amount = Math.Min(remainingCount.Value, maxStackSize ?? 0);
var newStackClone = cloner.Clone(itemToSplit);
newStackClone.Id = new MongoId();
newStackClone.Upd.StackObjectsCount = amount;
newStackClone!.Id = new MongoId();
newStackClone.Upd!.StackObjectsCount = amount;
remainingCount -= amount;
rootAndChildren.Add(newStackClone);
}
@@ -788,7 +788,7 @@ public class ItemHelper(
return [itemWithChildren];
}
var maxStackSize = GetItem(originRootItem.Template).Value.Properties.StackMaxSize;
var maxStackSize = GetItem(originRootItem.Template).Value?.Properties?.StackMaxSize;
var remainingCount = originRootItem.Upd.StackObjectsCount;
List<List<Item>> result = [];
@@ -804,11 +804,11 @@ public class ItemHelper(
while (remainingCount > 0)
{
// Clone item and make IDs unique
var itemWithChildrenClone = cloner.Clone(itemWithChildren).ReplaceIDs().ToList();
var itemWithChildrenClone = cloner.Clone(itemWithChildren)!.ReplaceIDs().ToList();
// Set stack count to new value
var amount = Math.Min(remainingCount.Value, maxStackSize ?? 0);
itemWithChildrenClone[0].Upd.StackObjectsCount = amount;
itemWithChildrenClone[0].Upd!.StackObjectsCount = amount;
remainingCount -= amount;
result.Add(itemWithChildrenClone);
}
@@ -824,7 +824,7 @@ public class ItemHelper(
public List<List<Item>> SplitStackIntoSeparateItems(Item itemToSplit)
{
var itemTemplate = GetItem(itemToSplit.Template).Value;
var itemMaxStackSize = itemTemplate.Properties.StackMaxSize ?? 1;
var itemMaxStackSize = itemTemplate?.Properties?.StackMaxSize ?? 1;
// item already within bounds of stack size, return it
if (itemToSplit.Upd?.StackObjectsCount <= itemMaxStackSize)
@@ -837,14 +837,14 @@ public class ItemHelper(
// Split items stack into chunks
List<List<Item>> result = [];
var remainingCount = itemToSplit.Upd.StackObjectsCount;
var remainingCount = itemToSplit.Upd?.StackObjectsCount;
while (remainingCount != 0)
{
var amount = Math.Min(remainingCount ?? 0, itemMaxStackSize);
var newItemClone = cloner.Clone(itemToSplit);
var newItemClone = cloner.Clone(itemToSplit)!;
newItemClone.Id = new MongoId();
newItemClone.Upd.StackObjectsCount = amount;
newItemClone.Upd!.StackObjectsCount = amount;
remainingCount -= amount;
result.Add([newItemClone]);
}
@@ -885,7 +885,7 @@ public class ItemHelper(
/// </summary>
/// <param name="itemWithChildren">Item with mods to update.</param>
/// <param name="newId">New id to add on children of base item.</param>
public void ReplaceRootItemID(IEnumerable<Item> itemWithChildren, MongoId newId)
public void ReplaceRootItemId(IEnumerable<Item> itemWithChildren, MongoId newId)
{
// original id on base item
var oldId = itemWithChildren.First().Id;
@@ -931,6 +931,11 @@ public class ItemHelper(
itemIdBlacklist.UnionWith(insuredItems.Select(x => x.ItemId.Value));
}
if (inventory.Items is null)
{
return;
}
foreach (var item in inventory.Items)
{
if (itemIdBlacklist.Contains(item.Id))
@@ -948,7 +953,7 @@ public class ItemHelper(
item.Id = newId;
// Find all children of item and update their parent ids to match
var childItems = inventory.Items.Where(x => x.ParentId == originalId);
var childItems = inventory.Items.Where(x => x.ParentId is not null && x.ParentId == originalId);
foreach (var childItem in childItems)
{
childItem.ParentId = newId;
@@ -960,7 +965,7 @@ public class ItemHelper(
continue;
}
// Update quickslot id
// Update quick-slot id
if (inventory.FastPanel.ContainsKey(originalId))
{
inventory.FastPanel[originalId] = newId;
@@ -975,14 +980,8 @@ public class ItemHelper(
/// <param name="originalItems">Items to adjust the IDs of</param>
/// <param name="pmcData">Player profile</param>
/// <param name="insuredItems">Insured items that should not have their IDs replaced</param>
/// <param name="fastPanel">Quick slot panel</param>
/// <returns>Items</returns>
public IEnumerable<Item> ReplaceIDs(
IEnumerable<Item> originalItems,
PmcData? pmcData,
IEnumerable<InsuredItem>? insuredItems = null,
Dictionary<string, string>? fastPanel = null
)
public IEnumerable<Item> ReplaceIDs(IEnumerable<Item> originalItems, PmcData? pmcData, IEnumerable<InsuredItem>? insuredItems = null)
{
// Blacklist
var itemIdBlacklist = new HashSet<MongoId>();
@@ -1033,12 +1032,12 @@ public class ItemHelper(
}
// Also replace in quick slot if the old ID exists.
if (pmcData.Inventory.FastPanel is null)
if (pmcData?.Inventory?.FastPanel is null)
{
continue;
}
// Update quickslot id
// Update quick-slot id
// TODO: i dont think the fast panel key is a mongoid, it should be e.g. "Item4"
if (pmcData.Inventory.FastPanel.ContainsKey(originalId))
{
@@ -1184,7 +1183,7 @@ public class ItemHelper(
while (currentItem != null && IsAttachmentAttached(currentItem))
{
currentItem = itemsMap.FirstOrDefault(x => x.Key == currentItem.ParentId).Value;
currentItem = itemsMap.FirstOrDefault(kvp => kvp.Key == currentItem.ParentId).Value;
if (currentItem == null)
{
return null;
@@ -1203,9 +1202,11 @@ public class ItemHelper(
{
HashSet<string> check = ["hideout", "main"];
var slotId = item.SlotId ?? string.Empty;
return !(
check.Contains(item.SlotId) // Is root item
|| _slotsAsStrings.Contains(item.SlotId) // Is root item in equipment slot e.g. `Headwear`
check.Contains(slotId) // Is root item
|| _slotsAsStrings.Contains(slotId) // Is root item in equipment slot e.g. `Headwear`
|| int.TryParse(item.SlotId, out _)
); // Has int as slotId, is inside container. e.g. cartridges
}
@@ -1228,9 +1229,9 @@ public class ItemHelper(
{
var currentItem = itemsMap.GetValueOrDefault(itemId);
while (currentItem is not null && !_slotsAsStrings.Contains(currentItem.SlotId))
while (currentItem is not null && !_slotsAsStrings.Contains(currentItem.SlotId ?? string.Empty))
{
currentItem = itemsMap.GetValueOrDefault(currentItem.ParentId);
currentItem = itemsMap.GetValueOrDefault(currentItem.ParentId ?? string.Empty);
if (currentItem is null)
{
return null;
@@ -1246,11 +1247,22 @@ public class ItemHelper(
/// <param name="items">Item with children</param>
/// <param name="rootItemId">The base items root id</param>
/// <returns>ItemSize object (width and height)</returns>
public ItemSize GetItemSize(ICollection<Item> items, MongoId rootItemId)
public ItemSize? GetItemSize(ICollection<Item> items, MongoId rootItemId)
{
var rootTemplate = GetItem(items.FirstOrDefault(x => x.Id == rootItemId).Template).Value;
var width = rootTemplate.Properties.Width;
var height = rootTemplate.Properties.Height;
var itemTemplate = items.FirstOrDefault(x => x.Id == rootItemId)?.Template;
if (itemTemplate is null)
{
return null;
}
var rootTemplate = GetItem(itemTemplate.Value).Value;
if (rootTemplate is null)
{
return null;
}
var width = rootTemplate.Properties?.Width;
var height = rootTemplate.Properties?.Height;
var sizeUp = 0;
var sizeDown = 0;
@@ -1268,7 +1280,7 @@ public class ItemHelper(
var itemDbTemplate = GetItem(item.Template).Value;
// Calculating child ExtraSize
if (itemDbTemplate.Properties.ExtraSizeForceAdd ?? false)
if (itemDbTemplate?.Properties?.ExtraSizeForceAdd ?? false)
{
forcedUp += itemDbTemplate.Properties.ExtraSizeUp.Value;
forcedDown += itemDbTemplate.Properties.ExtraSizeDown.Value;
@@ -1277,11 +1289,11 @@ public class ItemHelper(
}
else
{
sizeUp = sizeUp < itemDbTemplate.Properties.ExtraSizeUp ? itemDbTemplate.Properties.ExtraSizeUp.Value : sizeUp;
sizeDown = sizeDown < itemDbTemplate.Properties.ExtraSizeDown ? itemDbTemplate.Properties.ExtraSizeDown.Value : sizeDown;
sizeLeft = sizeLeft < itemDbTemplate.Properties.ExtraSizeLeft ? itemDbTemplate.Properties.ExtraSizeLeft.Value : sizeLeft;
sizeUp = sizeUp < itemDbTemplate?.Properties?.ExtraSizeUp ? itemDbTemplate.Properties.ExtraSizeUp.Value : sizeUp;
sizeDown = sizeDown < itemDbTemplate?.Properties?.ExtraSizeDown ? itemDbTemplate.Properties.ExtraSizeDown.Value : sizeDown;
sizeLeft = sizeLeft < itemDbTemplate?.Properties?.ExtraSizeLeft ? itemDbTemplate.Properties.ExtraSizeLeft.Value : sizeLeft;
sizeRight =
sizeRight < itemDbTemplate.Properties.ExtraSizeRight ? itemDbTemplate.Properties.ExtraSizeRight.Value : sizeRight;
sizeRight < itemDbTemplate?.Properties?.ExtraSizeRight ? itemDbTemplate.Properties.ExtraSizeRight.Value : sizeRight;
}
}
@@ -1316,10 +1328,10 @@ public class ItemHelper(
/// <param name="ammoBoxDetails">Item template from items db</param>
public void AddCartridgesToAmmoBox(List<Item> ammoBox, TemplateItem ammoBoxDetails)
{
var ammoBoxMaxCartridgeCount = ammoBoxDetails.Properties.StackSlots.First().MaxCount;
var cartridgeTpl = ammoBoxDetails.Properties.StackSlots.First().Props.Filters.First().Filter.FirstOrDefault();
var cartridgeDetails = GetItem(cartridgeTpl);
var cartridgeMaxStackSize = cartridgeDetails.Value.Properties.StackMaxSize;
var ammoBoxMaxCartridgeCount = ammoBoxDetails.Properties?.StackSlots?.First().MaxCount;
var cartridgeTpl = ammoBoxDetails.Properties?.StackSlots?.First().Props?.Filters?.First().Filter?.FirstOrDefault();
var cartridgeDetails = GetItem(cartridgeTpl.Value);
var cartridgeMaxStackSize = cartridgeDetails.Value?.Properties?.StackMaxSize;
// Exit early if ammo already exists in box
if (ammoBox.Any(item => item.Template.Equals(cartridgeTpl)))
@@ -1339,7 +1351,7 @@ public class ItemHelper(
var cartridgeCountToAdd = remainingSpace < maxPerStack ? remainingSpace : maxPerStack;
// Add cartridge item into items array
var cartridgeItemToAdd = CreateCartridges(ammoBox[0].Id, cartridgeTpl, (int)cartridgeCountToAdd, location);
var cartridgeItemToAdd = CreateCartridges(ammoBox[0].Id, cartridgeTpl.Value, (int)cartridgeCountToAdd, location);
// In live no ammo box has the first cartridge item with a location
if (location == 0)
@@ -1387,11 +1399,14 @@ public class ItemHelper(
)
{
var chosenCaliber = caliber ?? GetRandomValidCaliber(magTemplate);
// Edge case - Klin pp-9 has a typo in its ammo caliber
if (chosenCaliber == "Caliber9x18PMM")
switch (chosenCaliber)
{
chosenCaliber = "Caliber9x18PM";
case null:
throw new ItemHelperException("Chosen caliber is null when trying to fill magazine with random cartridge");
// Edge case - Klin pp-9 has a typo in its ammo caliber
case "Caliber9x18PMM":
chosenCaliber = "Caliber9x18PM";
break;
}
// Chose a randomly weighted cartridge that fits
@@ -1405,7 +1420,7 @@ public class ItemHelper(
{
if (logger.IsLogEnabled(LogLevel.Debug))
{
logger.Debug($"Unable to fill item: {magazine.FirstOrDefault().Id} {magTemplate.Name} with cartridges, none found.");
logger.Debug($"Unable to fill item: {magazine.FirstOrDefault()?.Id} {magTemplate.Name} with cartridges, none found.");
}
return;
@@ -1428,8 +1443,8 @@ public class ItemHelper(
double minSizeMultiplier = 0.25
)
{
var isUBGL = IsOfBaseclass(magTemplate.Id, BaseClasses.LAUNCHER);
if (isUBGL)
var isUbgl = IsOfBaseclass(magTemplate.Id, BaseClasses.LAUNCHER);
if (isUbgl)
// UBGL don't have mags
{
return;
@@ -1509,8 +1524,13 @@ public class ItemHelper(
/// <returns>Tpl of cartridge</returns>
protected string? GetRandomValidCaliber(TemplateItem magTemplate)
{
var ammoTpls = magTemplate.Properties.Cartridges.First().Props.Filters.First().Filter;
var calibers = ammoTpls.Where(x => GetItem(x).Key).Select(x => GetItem(x).Value.Properties.Caliber).ToList();
var ammoTpls = magTemplate.Properties?.Cartridges?.First().Props?.Filters?.First().Filter;
var calibers = ammoTpls?.Where(x => GetItem(x).Key).Select(x => GetItem(x).Value?.Properties?.Caliber).ToList();
if (calibers is null)
{
throw new ItemHelperException("Calibers is null when trying to generate random valid caliber");
}
return randomUtil.DrawRandomFromList(calibers).FirstOrDefault();
}
@@ -1548,16 +1568,22 @@ public class ItemHelper(
}
var ammoArray = new ProbabilityObjectArray<MongoId, float?>(cloner);
foreach (var icd in ammos)
foreach (var ammoDetails in ammos)
{
if (ammoDetails.Tpl is null)
{
logger.Error("Ammo details tpl is null when trying to draw ammo from pool");
continue;
}
// Whitelist exists and tpl not inside it, skip
// Fixes 9x18mm kedr issues
if (cartridgeWhitelist is not null && !cartridgeWhitelist.Contains(icd.Tpl.Value))
if (cartridgeWhitelist is not null && !cartridgeWhitelist.Contains(ammoDetails.Tpl.Value))
{
continue;
}
ammoArray.Add(new ProbabilityObject<MongoId, float?>(icd.Tpl.Value, (double)icd.RelativeProbability, null));
ammoArray.Add(new ProbabilityObject<MongoId, float?>(ammoDetails.Tpl.Value, (double)ammoDetails.RelativeProbability, null));
}
return ammoArray.Draw().FirstOrDefault();
@@ -1635,7 +1661,7 @@ public class ItemHelper(
{
var result = itemToAdd;
HashSet<MongoId> incompatibleModTpls = [];
foreach (var slot in itemToAddTemplate.Properties.Slots)
foreach (var slot in itemToAddTemplate.Properties?.Slots ?? [])
{
// If only required mods is requested, skip non-essential
if (requiredOnly && !(slot.Required ?? false))
@@ -1647,16 +1673,16 @@ public class ItemHelper(
if (modSpawnChanceDict is not null && !(slot.Required ?? false))
{
// only roll chance to not include mod if dict exists and has value for this mod type (e.g. front_plate)
if (modSpawnChanceDict.ContainsKey(slot.Name.ToLowerInvariant()))
if (modSpawnChanceDict.TryGetValue(slot.Name?.ToLowerInvariant() ?? string.Empty, out var value))
{
if (!randomUtil.GetChance100(modSpawnChanceDict[slot.Name.ToLowerInvariant()]))
if (!randomUtil.GetChance100(value))
{
continue;
}
}
}
var itemPool = slot.Props.Filters.FirstOrDefault().Filter ?? [];
var itemPool = slot.Props?.Filters?.FirstOrDefault()?.Filter ?? [];
if (itemPool.Count == 0)
{
if (logger.IsLogEnabled(LogLevel.Debug))
@@ -1695,6 +1721,10 @@ public class ItemHelper(
result.Add(modItemToAdd);
var modItemDbDetails = GetItem(modItemToAdd.Template).Value;
if (modItemDbDetails?.Properties?.ConflictingItems is null)
{
continue;
}
// Include conflicting items of newly added mod in pool to be used for next mod choice
incompatibleModTpls.UnionWith(modItemDbDetails.Properties.ConflictingItems);
@@ -1842,8 +1872,13 @@ public class ItemHelper(
var containerTemplate = GetItem(containerTpl).Value;
// Get height/width
var height = containerTemplate.Properties.Grids.First().Props.CellsV;
var width = containerTemplate.Properties.Grids.First().Props.CellsH;
var height = containerTemplate?.Properties?.Grids?.First().Props?.CellsV;
var width = containerTemplate?.Properties?.Grids?.First().Props?.CellsH;
if (height is null || width is null)
{
throw new ItemHelperException("Height or width is null when trying to calculate container mapping");
}
return GetBlankContainerMap(width.Value, height.Value);
}