diff --git a/Libraries/Core/Helpers/AssortHelper.cs b/Libraries/Core/Helpers/AssortHelper.cs index 14b53e47..fbf03359 100644 --- a/Libraries/Core/Helpers/AssortHelper.cs +++ b/Libraries/Core/Helpers/AssortHelper.cs @@ -74,27 +74,27 @@ public class AssortHelper( Dictionary> mergedQuestAssorts, string assortId) { - if (mergedQuestAssorts.Get>("started").Contains(assortId)) + if (mergedQuestAssorts.TryGetValue("started", out var dict1) && dict1.Contains(assortId)) { // Assort unlocked by starting quest, assort is visible to player when : started or ready to hand in + handed in return new KeyValuePair>( - mergedQuestAssorts.Get>("started")[assortId], + mergedQuestAssorts["started"][assortId], [QuestStatusEnum.Started, QuestStatusEnum.AvailableForFinish, QuestStatusEnum.Success] ); } - if (mergedQuestAssorts.Get>("success").Contains(assortId)) + if (mergedQuestAssorts.TryGetValue("started", out var dict2) && dict2.Contains(assortId)) { return new KeyValuePair>( - mergedQuestAssorts.Get>("success")[assortId], + mergedQuestAssorts["success"][assortId], [QuestStatusEnum.Success] ); } - if (mergedQuestAssorts.Get>("fail").Contains(assortId)) + if (mergedQuestAssorts.TryGetValue("fail", out var dict3) && dict3.Contains(assortId)) { return new KeyValuePair>( - mergedQuestAssorts.Get>("success")[assortId], + mergedQuestAssorts["fail"][assortId], [QuestStatusEnum.Fail] ); } @@ -143,9 +143,9 @@ public class AssortHelper( { var idsToRemove = _itemHelper.FindAndReturnChildrenByItems(assort.Items, itemID); - if (assort.BarterScheme[itemID] is not null && flea) + if (assort.BarterScheme.TryGetValue(itemID, out var lisToUse) && lisToUse is not null && flea) { - foreach (var barterSchemes in assort.BarterScheme[itemID]) + foreach (var barterSchemes in lisToUse) { foreach (var barterScheme in barterSchemes) { diff --git a/Libraries/Core/Helpers/TraderAssortHelper.cs b/Libraries/Core/Helpers/TraderAssortHelper.cs index 8ad4a3d7..00941f95 100644 --- a/Libraries/Core/Helpers/TraderAssortHelper.cs +++ b/Libraries/Core/Helpers/TraderAssortHelper.cs @@ -72,7 +72,7 @@ public class TraderAssortHelper( traderId ); - foreach (var assortId in assortPurchasesfromTrader) + foreach (var assortId in assortPurchasesfromTrader ?? []) { // Find assort we want to update current buy count of var assortToAdjust = traderClone.Assort.Items.FirstOrDefault(x => x.Id == assortId.Key); @@ -159,24 +159,25 @@ public class TraderAssortHelper( { // Loop every trader var traders = _databaseService.GetTraders(); - foreach (var trader in traders) + foreach (var traderId in traders) { // Trader has quest assort data - if (trader.Value.QuestAssort is not null) + var trader = traders[traderId.Key]; + if (trader.QuestAssort is not null) { // Started/Success/fail - foreach (var assort in trader.Value.QuestAssort) + foreach (var questStatus in trader.QuestAssort) { // Each assort to quest id record - foreach (var assortId in assort.Value.Values) + foreach (var assortId in trader.QuestAssort[questStatus.Key]) { // Null guard - if (!_mergedQuestAssorts.TryGetValue(assortId, out var _)) + if (!_mergedQuestAssorts.TryGetValue(questStatus.Key, out var _)) { - _mergedQuestAssorts.TryAdd(assortId, new Dictionary()); + _mergedQuestAssorts.TryAdd(questStatus.Key, new Dictionary()); } - _mergedQuestAssorts[assort.Key][assortId] = trader.Value.QuestAssort[assort.Key][assortId]; + _mergedQuestAssorts[questStatus.Key][assortId.Key] = trader.QuestAssort[questStatus.Key][assortId.Key]; } } } diff --git a/Libraries/Core/Helpers/TraderHelper.cs b/Libraries/Core/Helpers/TraderHelper.cs index a275940e..25c61540 100644 --- a/Libraries/Core/Helpers/TraderHelper.cs +++ b/Libraries/Core/Helpers/TraderHelper.cs @@ -130,16 +130,22 @@ public class TraderHelper( ProfileTraderTemplate rawProfileTemplate = profiles[fullProfile.ProfileInfo.Edition][pmcData.Info.Side.ToLower()].Trader; - pmcData.TradersInfo[traderID] = new TraderInfo + var newTraderData = new TraderInfo { Disabled = false, - LoyaltyLevel = rawProfileTemplate.InitialLoyaltyLevel[traderID] ?? 1, + LoyaltyLevel = rawProfileTemplate.InitialLoyaltyLevel.TryGetValue(traderID, out var value) ? value : 4, SalesSum = rawProfileTemplate.InitialSalesSum, Standing = GetStartingStanding(traderID, rawProfileTemplate), NextResupply = trader.Base.NextResupply, Unlocked = trader.Base.UnlockedByDefault }; + if (!pmcData.TradersInfo.TryAdd(traderID, newTraderData)) + { + pmcData.TradersInfo[traderID] = newTraderData; + } + + // Check if trader should be locked by default if (rawProfileTemplate.LockedByDefaultOverride?.Contains(traderID) ?? false) { @@ -192,15 +198,20 @@ public class TraderHelper( /// Trader id to get standing for /// Raw profile from profiles.json to look up standing from /// Standing value - protected double GetStartingStanding(string traderId, ProfileTraderTemplate rawProfileTemplate) + protected double? GetStartingStanding(string traderId, ProfileTraderTemplate rawProfileTemplate) { - var initialStanding = rawProfileTemplate.InitialStanding[traderId] ?? 0D; - // Edge case for Lightkeeper, 0 standing means seeing `Make Amends - Buyout` quest - if (traderId == Traders.LIGHTHOUSEKEEPER && initialStanding == 0) { - return 0.01; + if (rawProfileTemplate.InitialStanding.TryGetValue(traderId, out var standing)) + { + // Edge case for Lightkeeper, 0 standing means seeing `Make Amends - Buyout` quest + if (traderId == Traders.LIGHTHOUSEKEEPER && standing == 0) + { + return 0.01; + } + + return standing; } - return initialStanding; + return null; } /// @@ -210,13 +221,16 @@ public class TraderHelper( /// Suit Ids to add protected void AddSuitsToProfile(SptProfile fullProfile, List suitIds) { - if (fullProfile.Suits is null) { + if (fullProfile.Suits is null) + { fullProfile.Suits = []; } - foreach (var suitId in suitIds) { + foreach (var suitId in suitIds) + { // Don't add dupes - if (!fullProfile.Suits.Contains(suitId)) { + if (!fullProfile.Suits.Contains(suitId)) + { fullProfile.Suits.Add(suitId); } } @@ -232,7 +246,8 @@ public class TraderHelper( { var pmcData = _profileHelper.GetPmcProfile(sessionId); var profileTraderData = pmcData.TradersInfo[traderId]; - if (profileTraderData is null) { + if (profileTraderData is null) + { _logger.Error($"Unable to set trader {traderId} unlocked state to: {status} as trader cannot be found in profile"); return; @@ -255,7 +270,8 @@ public class TraderHelper( // Add standing to trader pmcTraderInfo.Standing = AddStandingValuesTogether(pmcTraderInfo.Standing, standingToAdd); - if (traderId == Traders.FENCE) { + if (traderId == Traders.FENCE) + { // Must add rep to scav profile to ensure consistency fullProfile.CharacterData.ScavData.TradersInfo[traderId].Standing = pmcTraderInfo.Standing; } @@ -285,7 +301,8 @@ public class TraderHelper( { var profile = _profileHelper.GetPmcProfile(sessionId); var traders = _databaseService.GetTraders(); - foreach (var trader in traders) { + foreach (var trader in traders) + { this.LevelUp(trader.Key, profile); } } @@ -309,12 +326,14 @@ public class TraderHelper( // Round standing to 2 decimal places to address floating point inaccuracies pmcData.TradersInfo[traderID].Standing = Math.Round((pmcData.TradersInfo[traderID].Standing * 100) ?? 0) / 100; - foreach (var loyaltyLevel in loyaltyLevels) { + foreach (var loyaltyLevel in loyaltyLevels) + { if (loyaltyLevel.MinLevel <= pmcData.Info.Level && loyaltyLevel.MinSalesSum <= pmcData.TradersInfo[traderID].SalesSum && loyaltyLevel.MinStanding <= pmcData.TradersInfo[traderID].Standing && targetLevel < 4 - ) { + ) + { // level reached targetLevel++; } diff --git a/Libraries/Core/Services/FenceService.cs b/Libraries/Core/Services/FenceService.cs index 1f8a67f6..e7a12cf6 100644 --- a/Libraries/Core/Services/FenceService.cs +++ b/Libraries/Core/Services/FenceService.cs @@ -508,7 +508,7 @@ public class FenceService( var fenceLevels = fenceSettings.Levels.Select(x => x.Key); var minLevel = fenceLevels.Min(); var maxLevel = fenceLevels.Max(); - var pmcFenceLevel = Math.Floor(pmcFenceInfo.Standing.Value); + var pmcFenceLevel = Math.Floor(pmcFenceInfo.Standing ?? 0); if (pmcFenceLevel < int.Parse(minLevel)) { diff --git a/SptCommon/Extensions/ObjectExtensions.cs b/SptCommon/Extensions/ObjectExtensions.cs index 8881159c..dfd14f4a 100644 --- a/SptCommon/Extensions/ObjectExtensions.cs +++ b/SptCommon/Extensions/ObjectExtensions.cs @@ -21,8 +21,13 @@ namespace SptCommon.Extensions } } - public static bool Contains(this object obj, T key) + public static bool Contains(this object? obj, T key) { + if (obj == null) + { + throw new ArgumentNullException(nameof(obj)); + } + return TryGetCachedProperty(obj.GetType(), key.ToString(), out _); }