diff --git a/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs b/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs index ef0f1a88..73f6b26c 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs @@ -923,7 +923,7 @@ public class HideoutController( var addToolsRequest = new AddItemsDirectRequest { ItemsWithModsToAdd = [toolItem], - FoundInRaid = toolItem[0].Upd?.SpawnedInSession ?? false, + FoundInRaid = toolItem.FirstOrDefault()?.Upd?.SpawnedInSession ?? false, UseSortingTable = false, Callback = null }; diff --git a/Libraries/SPTarkov.Server.Core/Controllers/PresetController.cs b/Libraries/SPTarkov.Server.Core/Controllers/PresetController.cs index 1fd14ced..9c3d17b3 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/PresetController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/PresetController.cs @@ -25,7 +25,7 @@ public class PresetController( if (presetId != preset.Id) { _logger.Error( - $"Preset for template tpl: '{preset.Items[0].Template} {preset.Name}' has invalid key: ({presetId} != {preset.Id}). Skipping" + $"Preset for template tpl: '{preset.Items.FirstOrDefault()?.Template} {preset.Name}' has invalid key: ({presetId} != {preset.Id}). Skipping" ); continue; diff --git a/Libraries/SPTarkov.Server.Core/Controllers/QuestController.cs b/Libraries/SPTarkov.Server.Core/Controllers/QuestController.cs index 7713f2df..1c271e4a 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/QuestController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/QuestController.cs @@ -146,7 +146,7 @@ public class QuestController( { foreach (var condition in questConditions) { - if (pmcData.TaskConditionCounters.TryGetValue(condition.Id, out var counter)) + if (pmcData.TaskConditionCounters.TryGetValue(condition.Id, out _)) { _logger.Error( $"Unable to add new task condition counter: {condition.ConditionType} for quest: {questId} to profile: {pmcData.SessionId} as it already exists" diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs index fe3c51fa..8d3d2d7a 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs @@ -708,7 +708,7 @@ public class RagfairController // multi-offers are all the same item, // Get first item and its children and use as template - var firstListingAndChidren = _itemHelper.FindAndReturnChildrenAsItems( + var firstListingAndChildren = _itemHelper.FindAndReturnChildrenAsItems( pmcData.Inventory.Items, offerRequest.Items[0] ); @@ -725,11 +725,12 @@ public class RagfairController // When listing identical items on flea, condense separate items into one stack with a merged stack count // e.g. 2 ammo items, stackObjectCount = 3 for each, will result in 1 stack of 6 - firstListingAndChidren[0].Upd ??= new Upd(); - firstListingAndChidren[0].Upd.StackObjectsCount = stackCountTotal; + var firstListingRootItem = firstListingAndChildren.FirstOrDefault(); + firstListingRootItem.Upd ??= new Upd(); + firstListingRootItem.Upd.StackObjectsCount = stackCountTotal; // Create flea object - var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, firstListingAndChidren, true); + var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, firstListingAndChildren, true); // This is the item that will be listed on flea, has merged stackObjectCount var newRootOfferItem = offer.Items[0]; // TODO: add logic like single/multi offers to find root item @@ -738,7 +739,7 @@ public class RagfairController var averages = GetItemMinAvgMaxFleaPriceValues( new GetMarketPriceRequestData { - TemplateId = firstListingAndChidren[0].Template + TemplateId = firstListingRootItem.Template } ); var singleItemPrice = averages.Avg; @@ -765,7 +766,7 @@ public class RagfairController qualityMultiplier ); - // Create array of sell times for items listed + sell all at once as its a pack + // Create array of sell times for items listed + sell all at once as it's a pack offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int) stackCountTotal, true); // Subtract flea market fee from stash diff --git a/Libraries/SPTarkov.Server.Core/Controllers/TraderController.cs b/Libraries/SPTarkov.Server.Core/Controllers/TraderController.cs index 76956c0c..b82461fa 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/TraderController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/TraderController.cs @@ -140,7 +140,7 @@ public class TraderController( { var traders = new List(); var pmcData = _profileHelper.GetPmcProfile(sessionId); - foreach (var (traderId, data) in _databaseService.GetTables().Traders) + foreach (var (traderId, _) in _databaseService.GetTables().Traders) { traders.Add(_traderHelper.GetTrader(traderId, sessionId)); diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs index 63784d99..22a4675d 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs @@ -1018,7 +1018,7 @@ public class BotEquipmentModGenerator( return null; } - // Filter out non-whitelisted scopes, use full modpool if filtered pool would have no elements + // Filter out non-whitelisted scopes, use the full mod pool if filtered pool would have no elements if (request.ModSlot.Contains("mod_scope") && request.BotWeaponSightWhitelist is not null) // scope pool has more than one scope { @@ -1030,7 +1030,7 @@ public class BotEquipmentModGenerator( if (request.ModSlot == "mod_gas_block") { - if ((request.WeaponStats.HasOptic ?? false) && modPool.Count > 1) + if ((request.WeaponStats?.HasOptic ?? false) && modPool.Count > 1) { // Attempt to limit modpool to low profile gas blocks when weapon has an optic var onlyLowProfileGasBlocks = modPool.Where(tpl => @@ -1041,7 +1041,7 @@ public class BotEquipmentModGenerator( modPool = onlyLowProfileGasBlocks.ToHashSet(); } } - else if ((request.WeaponStats.HasRearIronSight ?? false) && modPool.Count > 1) + else if ((request.WeaponStats?.HasRearIronSight ?? false) && modPool.Count > 1) { // Attempt to limit modpool to high profile gas blocks when weapon has rear iron sight + no front iron sight var onlyHighProfileGasBlocks = modPool.Where(tpl => !_botConfig.LowProfileGasBlockTpls.Contains(tpl) @@ -1060,7 +1060,7 @@ public class BotEquipmentModGenerator( request.RandomisationSettings.MinimumMagazineSize is not null ) { - modPool = GetFilterdMagazinePoolByCapacity(request, modPool).ToHashSet(); + modPool = GetFilteredMagazinePoolByCapacity(request, modPool).ToHashSet(); } // Pick random mod that's compatible @@ -1116,26 +1116,25 @@ public class BotEquipmentModGenerator( } /// - /// Given the passed in array of magaizne tpls, look up the min size set in config and return only those that have that size or larger + /// Given the passed in array of magazine tpls, look up the min size set in config and return only those that have that size or larger /// /// Request data /// Pool of magazine tpls to filter /// Filtered pool of magazine tpls - public IEnumerable GetFilterdMagazinePoolByCapacity(ModToSpawnRequest modSpawnRequest, HashSet modPool) + public IEnumerable GetFilteredMagazinePoolByCapacity(ModToSpawnRequest modSpawnRequest, HashSet modPool) { - var weaponTpl = modSpawnRequest.Weapon[0].Template; + var weaponTpl = modSpawnRequest.Weapon.FirstOrDefault().Template; modSpawnRequest.RandomisationSettings.MinimumMagazineSize.TryGetValue(weaponTpl, out var minMagSizeFromSettings); - var minMagazineSize = minMagSizeFromSettings; var desiredMagazineTpls = modPool.Where(magTpl => { var magazineDb = _itemHelper.GetItem(magTpl).Value; - return magazineDb.Properties is not null && magazineDb.Properties.Cartridges.FirstOrDefault().MaxCount >= minMagazineSize; + return magazineDb.Properties is not null && magazineDb.Properties.Cartridges.FirstOrDefault().MaxCount >= minMagSizeFromSettings; } ); if (!desiredMagazineTpls.Any()) { - _logger.Warning($"Magazine size filter for {weaponTpl} was too strict, ignoring filter"); + _logger.Warning($"Magazine size filter for: {weaponTpl} was too strict, ignoring filter"); return modPool; } @@ -1169,7 +1168,7 @@ public class BotEquipmentModGenerator( }; } - // Filter mod pool to only items that appear in parents allowed list + // Filter modpool to only items that appear in parents allowed list preFilteredModPool = preFilteredModPool.Where(tpl => parentSlot.Props.Filters[0].Filter.Contains(tpl)).ToHashSet(); if (preFilteredModPool.Count == 0) { @@ -1590,21 +1589,17 @@ public class BotEquipmentModGenerator( /// /// Find mod tpls of a provided type and add to its modPool /// - /// Slot to look up and add we are adding tpls for (e.g mod_scope) + /// Slot to look up and add we are adding tpls for (e.g. mod_scope) /// db object for modItem we get compatible mods from /// Pool of mods we are adding to /// A blacklist of items that cannot be picked public void AddCompatibleModsForProvidedMod(string desiredSlotName, TemplateItem modTemplate, - Dictionary>> modPool, + IDictionary>> modPool, EquipmentFilterDetails botEquipBlacklist) { - var desiredSlotObject = modTemplate.Properties.Slots?.FirstOrDefault(slot => slot.Name.Contains(desiredSlotName)); - if (desiredSlotObject is null) - { - return; - } + var desiredSlotObject = modTemplate.Properties?.Slots?.FirstOrDefault(slot => slot.Name.Contains(desiredSlotName)); - var supportedSubMods = desiredSlotObject.Props.Filters[0].Filter; + var supportedSubMods = desiredSlotObject?.Props?.Filters?.FirstOrDefault()?.Filter; if (supportedSubMods is null) { return; diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotLootGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotLootGenerator.cs index 617407be..f30401fb 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotLootGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotLootGenerator.cs @@ -712,10 +712,18 @@ public class BotLootGenerator( isPmc, botLevel ); + + var weaponRootItem = generatedWeapon.Weapon?.FirstOrDefault(); + if (weaponRootItem is null) + { + _logger.Error($"Generated loose weapon: {chosenWeaponType} for: {botRole} level: {botLevel} was null, skipping"); + + continue; + } var result = _botGeneratorHelper.AddItemWithChildrenToEquipmentSlot( [equipmentSlot], - generatedWeapon.Weapon[0].Id, - generatedWeapon.Weapon[0].Template, + weaponRootItem.Id, + weaponRootItem.Template, generatedWeapon.Weapon, botInventory, containersIdFull @@ -725,7 +733,7 @@ public class BotLootGenerator( { if (_logger.IsLogEnabled(LogLevel.Debug)) { - _logger.Debug($"Failed to add additional weapon {generatedWeapon.Weapon[0].Id} to bot backpack, reason: {result.ToString()}"); + _logger.Debug($"Failed to add additional weapon: {weaponRootItem.Id} to bot backpack, reason: {result.ToString()}"); } } } diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs index bef7cc41..d7abaf12 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs @@ -200,7 +200,7 @@ public class BotWeaponGenerator( // Add cartridge(s) to gun chamber(s) if (weaponItemTemplate.Properties?.Chambers?.Count > 0 && - weaponItemTemplate.Properties.Chambers[0].Props.Filters[0].Filter.Contains(ammoTpl)) + weaponItemTemplate.Properties.Chambers.FirstOrDefault().Props.Filters.FirstOrDefault().Filter.Contains(ammoTpl)) { // Guns have variety of possible Chamber ids, patron_in_weapon/patron_in_weapon_000/patron_in_weapon_001 var chamberSlotNames = weaponItemTemplate.Properties.Chambers.Select(chamberSlot => chamberSlot.Name); @@ -214,7 +214,7 @@ public class BotWeaponGenerator( { var ubglTemplate = _itemHelper.GetItem(ubglMod.Template).Value; ubglAmmoTpl = GetWeightedCompatibleAmmo(botTemplateInventory.Ammo, ubglTemplate); - // this can be null - example - FollowerBoarClose2 can have an UBGL but doesnt have the ammo caliber defined in its json + // this can be null - example - FollowerBoarClose2 can have an UBGL but doesn't have the ammo caliber defined in its json // the default ammo passed from GetWeightCompatibleAmmo can be null if (ubglAmmoTpl is not null) { @@ -315,7 +315,7 @@ public class BotWeaponGenerator( List weaponMods = []; // TODO: Preset weapons trigger a lot of warnings regarding missing ammo in magazines & such - Preset preset = null; + Preset? preset = null; foreach (var (_, itemPreset) in _databaseService.GetGlobals().ItemPresets) { if (itemPreset.Items[0].Template == weaponTemplate) @@ -363,8 +363,7 @@ public class BotWeaponGenerator( foreach (var modSlotTemplate in modTemplate.Properties.Slots?.Where(slot => slot.Required.GetValueOrDefault(false)) ?? []) { var slotName = modSlotTemplate.Name; - var hasWeaponSlotItem = weaponItemList.Any(weaponItem => weaponItem.ParentId == mod.Id && weaponItem.SlotId == slotName - ); + var hasWeaponSlotItem = weaponItemList.Any(weaponItem => weaponItem.ParentId == mod.Id && weaponItem.SlotId == slotName); if (!hasWeaponSlotItem) { _logger.Warning( diff --git a/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs index 89de09dd..b93e9946 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs @@ -1162,7 +1162,6 @@ public class LocationLootGenerator( protected Item? CreateWeaponItems(string chosenTpl, Dictionary> staticAmmoDist, string? parentId, ref List items) { - Item? rootItem; List children = []; var defaultPreset = _cloner.Clone(_presetHelper.GetDefaultPreset(chosenTpl)); if (defaultPreset?.Items is not null) @@ -1188,6 +1187,7 @@ public class LocationLootGenerator( } ) ); + _logger.Error(e.StackTrace); throw; } @@ -1201,7 +1201,7 @@ public class LocationLootGenerator( } } - rootItem = items[0]; + var rootItem = items.FirstOrDefault(); if (rootItem is null) { _logger.Error( @@ -1237,6 +1237,7 @@ public class LocationLootGenerator( } ) ); + _logger.Error(e.StackTrace); throw; } diff --git a/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs index 03110b84..d478ea49 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs @@ -555,7 +555,11 @@ public class RagfairOfferGenerator( barterScheme = CreateBarterBarterScheme(itemWithChildren, ragfairConfig.Dynamic.Barter); if (ragfairConfig.Dynamic.Barter.MakeSingleStackOnly) { - itemWithChildren[0].Upd.StackObjectsCount = 1; + var rootItem = itemWithChildren.FirstOrDefault(); + if (rootItem?.Upd != null) + { + rootItem.Upd.StackObjectsCount = 1; + } } } else @@ -565,7 +569,7 @@ public class RagfairOfferGenerator( barterScheme = CreateCurrencyBarterScheme(itemWithChildren, isPackOffer); } - var offer = CreateAndAddFleaOffer( + CreateAndAddFleaOffer( sellerId, timeUtil.GetTimeStamp(), itemWithChildren, @@ -654,7 +658,7 @@ public class RagfairOfferGenerator( var barterSchemeItems = barterScheme[0]; var loyalLevel = assortsClone.LoyalLevelItems[item.Id]; - var offer = CreateAndAddFleaOffer(traderID, time, items, barterSchemeItems, loyalLevel, (int?) item.Upd.StackObjectsCount ?? 1); + CreateAndAddFleaOffer(traderID, time, items, barterSchemeItems, loyalLevel, (int?) item.Upd.StackObjectsCount ?? 1); // Refresh complete, reset flag to false trader.Base.RefreshTraderRagfairOffers = false; diff --git a/Libraries/SPTarkov.Server.Core/Generators/RepeatableQuestGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/RepeatableQuestGenerator.cs index 0f06aff1..031062f2 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/RepeatableQuestGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/RepeatableQuestGenerator.cs @@ -155,9 +155,9 @@ public class RepeatableQuestGenerator( // the actual difficulty we calculate the minimum and maximum difficulty (max being the sum of max of each condition type // times the number of kills we have to perform): - // the minimum difficulty is the difficulty for the most probable (= easiest target) with no additional conditions + // The minimum difficulty is the difficulty for the most probable (= easiest target) with no additional conditions var minDifficulty = - 1 / targetsConfig.MaxProbability(); // min difficulty is lowest amount of scavs without any constraints + 1 / targetsConfig.MaxProbability(); // min difficulty is the lowest amount of scavs without any constraints // Target on bodyPart max. difficulty is that of the least probable element var maxTargetDifficulty = 1 / targetsConfig.MinProbability(); @@ -169,7 +169,7 @@ public class RepeatableQuestGenerator( var maxKillDifficulty = eliminationConfig.MaxKills; var targetPool = questTypePool.Pool.Elimination; - targetsConfig = targetsConfig.Filter(x => questTypePool.Pool.Elimination.Targets.ContainsKey(x.Key)); + targetsConfig = targetsConfig.Filter(x => targetPool.Targets.ContainsKey(x.Key)); if (targetsConfig.Count == 0 || targetsConfig.All(x => x.Data.IsBoss.GetValueOrDefault(false))) { @@ -183,10 +183,10 @@ public class RepeatableQuestGenerator( var botTypeToEliminate = targetsConfig.Draw()[0]; var targetDifficulty = 1 / targetsConfig.Probability(botTypeToEliminate); - questTypePool.Pool.Elimination.Targets.TryGetValue(botTypeToEliminate, out var targetLocationPool); + targetPool.Targets.TryGetValue(botTypeToEliminate, out var targetLocationPool); var locations = targetLocationPool.Locations; - // we use any as location if "any" is in the pool and we don't hit the specific location random + // we use any as location if "any" is in the pool, and we don't hit the specific location random // we use any also if the random condition is not met in case only "any" was in the pool var locationKey = "any"; if (locations.Contains("any") && @@ -194,7 +194,7 @@ public class RepeatableQuestGenerator( ) { locationKey = "any"; - questTypePool.Pool.Elimination.Targets.Remove(botTypeToEliminate); + targetPool.Targets.Remove(botTypeToEliminate); } else { @@ -206,7 +206,7 @@ public class RepeatableQuestGenerator( locationKey = _randomUtil.DrawRandomFromList(locations).FirstOrDefault(); // Get a pool of locations the chosen bot type can be eliminated on - if (!questTypePool.Pool.Elimination.Targets.TryGetValue( + if (!targetPool.Targets.TryGetValue( botTypeToEliminate, out var possibleLocationPool )) @@ -224,7 +224,7 @@ public class RepeatableQuestGenerator( { // TODO: Why do any of this?! // Remove chosen bot to eliminate from pool - questTypePool.Pool.Elimination.Targets.Remove(botTypeToEliminate); + targetPool.Targets.Remove(botTypeToEliminate); } } else diff --git a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs index 12029b92..245d5d3a 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs @@ -847,9 +847,6 @@ public class InventoryHelper( var fH = IsVertical(itemLocation) ? iW : iH; var fW = IsVertical(itemLocation) ? iH : iW; - // Find the ending x coord of container - var fillTo = itemLocation.X + fW; - for (var y = 0; y < fH; y++) { try diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs index 87632a81..71fc56a9 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs @@ -618,7 +618,7 @@ public class ItemHelper( { if (_databaseService.GetItems().TryGetValue(itemTpl, out var item)) { - return GetItem(itemTpl).Value?.Properties?.Slots?.Count > 0; + return item?.Properties?.Slots?.Count > 0; } return false; @@ -2226,8 +2226,8 @@ public class ItemHelper( /// /// Get a blank two-dimensional representation of a container /// - /// Horizontal size of container - /// Vertical size of container + /// Horizontal size of container + /// Vertical size of container /// Two-dimensional representation of container public int[][] GetBlankContainerMap(int containerY, int containerX) { @@ -2240,7 +2240,7 @@ public class ItemHelper( //return x; return Enumerable.Range(0, containerY) - .Select(i => new int[containerX]) + .Select(_ => new int[containerX]) .ToArray(); } } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/QuestHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/QuestHelper.cs index b0758ab8..be33d201 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/QuestHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/QuestHelper.cs @@ -1077,7 +1077,7 @@ public class QuestHelper( } // Player can use trader mods then remove them, leaving quests behind - if (!profile.TradersInfo.TryGetValue(quest.TraderId, out var trader)) + if (!profile.TradersInfo.ContainsKey(quest.TraderId)) { if (_logger.IsLogEnabled(LogLevel.Debug)) { diff --git a/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs index a462acd0..797878c4 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs @@ -333,22 +333,24 @@ public class RagfairOfferHelper( return offersToReturn; } - /** - * Should a ragfair offer be visible to the player - * @param searchRequest Search request - * @param itemsToAdd ? - * @param traderAssorts Trader assort items - used for filtering out locked trader items - * @param offer The flea offer - * @param pmcProfile Player profile - * @returns True = should be shown to player - */ + /// + /// Should a ragfair offer be visible to the player + /// + /// Client request + /// + /// Trader assort items - used for filtering out locked trader items + /// Flea offer + /// Player profile + /// Player cannot view flea yet/ever + /// True = should be shown to player private bool IsDisplayableOffer(SearchRequestData searchRequest, List itemsToAdd, Dictionary traderAssorts, RagfairOffer offer, PmcData pmcProfile, bool playerIsFleaBanned = false) { - var offerRootItem = offer.Items[0]; + var offerRootItem = offer.Items.FirstOrDefault(); + // Currency offer is sold for - var moneyTypeTpl = offer.Requirements[0].Template; + var moneyTypeTpl = offer.Requirements.FirstOrDefault().Template; var isTraderOffer = _databaseService.GetTraders().ContainsKey(offer.User.Id); if (!isTraderOffer && playerIsFleaBanned) @@ -496,7 +498,7 @@ public class RagfairOfferHelper( // } //} - foreach (var item in offer.Items) + foreach (var _ in offer.Items) { traderAssorts.TryGetValue(offer.User.Id, out var assorts); if (assorts.BarterScheme diff --git a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs index 33912f6a..4ee1c70d 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs @@ -146,7 +146,6 @@ public class TraderHelper( } // Get matching profile 'type' e.g. 'standard' - profiles.TryGetValue(fullProfile.ProfileInfo.Edition, out var matchingProfileTemplate); var pmcData = fullProfile.CharacterData.PmcData; var matchingSide = _profileHelper.GetProfileTemplateForSide(fullProfile.ProfileInfo.Edition, pmcData.Info.Side); diff --git a/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs b/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs index 55d91e56..ba3006c4 100644 --- a/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs @@ -320,12 +320,10 @@ public class BotEquipmentFilterService if (blacklist is not null) { - foreach (var ammoCaliberKvP in baseBotNode.BotInventory.Ammo) + foreach (var (caliber, cartridgesAndWeights) in baseBotNode.BotInventory.Ammo) { - var botAmmo = baseBotNode.BotInventory.Ammo[ammoCaliberKvP.Key]; - // Skip cartridge slot if blacklist doesn't exist / is empty - blacklist.Cartridge.TryGetValue(ammoCaliberKvP.Key, out var cartridgeCaliberBlacklist); + blacklist.Cartridge.TryGetValue(caliber, out var cartridgeCaliberBlacklist); if (cartridgeCaliberBlacklist is null || cartridgeCaliberBlacklist.Count == 0) { continue; @@ -333,9 +331,9 @@ public class BotEquipmentFilterService // Filter cartridge slot items to just items not in blacklist foreach (var blacklistedTpl in cartridgeCaliberBlacklist - .Where(blacklistedTpl => ammoCaliberKvP.Value.ContainsKey(blacklistedTpl))) + .Where(blacklistedTpl => cartridgesAndWeights.ContainsKey(blacklistedTpl))) { - ammoCaliberKvP.Value.Remove(blacklistedTpl); + cartridgesAndWeights.Remove(blacklistedTpl); } } } diff --git a/Libraries/SPTarkov.Server.Core/Services/BotGenerationCacheService.cs b/Libraries/SPTarkov.Server.Core/Services/BotGenerationCacheService.cs index 16a57781..5c4f95a7 100644 --- a/Libraries/SPTarkov.Server.Core/Services/BotGenerationCacheService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/BotGenerationCacheService.cs @@ -48,9 +48,10 @@ public class BotGenerationCacheService( { return bots.PopLast(); } - catch (Exception _) + catch (Exception e) { _logger.Error(_localisationService.GetText("bot-cache_has_zero_bots_of_requested_type", key)); + _logger.Error(e.StackTrace); } } diff --git a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs index f2cdd727..72191c99 100644 --- a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs @@ -420,10 +420,6 @@ public class LocationLifecycleService var pmcProfile = fullProfile.CharacterData.PmcData; var scavProfile = fullProfile.CharacterData.ScavData; - // TODO: - // Quest status? - // stats/eft/aggressor - weird values (EFT.IProfileDataContainer.Nickname) - if (_logger.IsLogEnabled(LogLevel.Debug)) { _logger.Debug($"Raid: {request.ServerId} outcome: {request.Results.Result}"); @@ -438,7 +434,6 @@ public class LocationLifecycleService var locationName = serverDetails[0].ToLower(); var isPmc = serverDetails[1].ToLower().Contains("pmc"); - var mapBase = _databaseService.GetLocation(locationName).Base; var isDead = IsPlayerDead(request.Results); var isTransfer = IsMapToMapTransfer(request.Results); var isSurvived = IsPlayerSurvived(request.Results); diff --git a/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs b/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs index b0f1683e..aab4a7a3 100644 --- a/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs @@ -518,7 +518,7 @@ public class PostDbLoadService( } foreach (var area in _databaseService.GetHideout().Areas) - foreach (var (key, stage) in area.Stages) + foreach (var (_, stage) in area.Stages) // Only adjust crafts ABOVE the override { stage.ConstructionTime = Math.Min(stage.ConstructionTime.Value, overrideSeconds); diff --git a/SPTarkov.Server/Modding/ModValidator.cs b/SPTarkov.Server/Modding/ModValidator.cs index f8bb434d..485b9a8c 100644 --- a/SPTarkov.Server/Modding/ModValidator.cs +++ b/SPTarkov.Server/Modding/ModValidator.cs @@ -250,7 +250,7 @@ public class ModValidator( } /// - /// Read loadorder.json (create if doesnt exist) and return sorted list of mods + /// Read loadorder.json (create if doesn't exist) and return sorted list of mods /// /// string array of sorted mod names public List SortModsLoadOrder() diff --git a/Tools/JsonExtensionDataGenerator/JsonExtensionDataGeneratorLauncher.cs b/Tools/JsonExtensionDataGenerator/JsonExtensionDataGeneratorLauncher.cs index c973b6b9..df44713f 100644 --- a/Tools/JsonExtensionDataGenerator/JsonExtensionDataGeneratorLauncher.cs +++ b/Tools/JsonExtensionDataGenerator/JsonExtensionDataGeneratorLauncher.cs @@ -39,8 +39,8 @@ public class JsonExtensionDataGeneratorLauncher var content = File.ReadAllText(modelFile); if (!content.Contains("public record ") && !content.Contains("public class ")) { - Console.WriteLine($"File {fileName} doesnt contain any records or classes, skipping..."); - // probably an enum or interface + Console.WriteLine($"File {fileName} doesn't contain any records or classes, skipping..."); + // Probably an enum or interface return; } @@ -76,7 +76,7 @@ public class JsonExtensionDataGeneratorLauncher { if (!content.Contains("using System.Text.Json.Serialization;")) { - Console.WriteLine($"Class index {i} for {fileName} doesnt contain using for Json.Serialization. Adding."); + Console.WriteLine($"Class index {i} for {fileName} doesn't contain using for Json.Serialization. Adding."); // insert the using and adjust the indexes content = Using + content; startIndex += Using.Length;