From 6eaab5cba252c511e1a9ab78de8c550f279de655 Mon Sep 17 00:00:00 2001 From: RuKira Date: Sat, 7 Jun 2025 03:14:12 -0400 Subject: [PATCH 1/7] Added Missing Cultist Recipes, Shadow of Tagilla Helmet (Replica) & Fleece Fabric --- .../Assets/configs/hideout.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Libraries/SPTarkov.Server.Assets/Assets/configs/hideout.json b/Libraries/SPTarkov.Server.Assets/Assets/configs/hideout.json index 2bbabea5..05bf1c75 100644 --- a/Libraries/SPTarkov.Server.Assets/Assets/configs/hideout.json +++ b/Libraries/SPTarkov.Server.Assets/Assets/configs/hideout.json @@ -148,6 +148,12 @@ "craftTimeSeconds": 3960, "repeatable": false }, + { + "reward": ["5e2af47786f7746d404f3aaa"], + "requiredItems": ["5448fee04bdc2dbc018b4567"], + "craftTimeSeconds": 3960, + "repeatable": false + }, { "reward": ["590c346786f77423e50ed342"], "requiredItems": ["679b9d55708cfcb2060b9ae3"], @@ -178,6 +184,18 @@ "craftTimeSeconds": 3960, "repeatable": false }, + { + "reward": ["67ea616a74f765cefd009fb7"], + "requiredItems": [ + "679b9d4b3374fb14f40efe6d", + "679b9d6390622daf9708da76", + "679b9cce4e4ed4b3b40ae5c5", + "679b9d43597ba2ed120c3d44", + "679b9d55708cfcb2060b9ae3" + ], + "craftTimeSeconds": 3960, + "repeatable": false + }, { "reward": ["5d1b376e86f774252519444e"], "requiredItems": ["6582dbf0b8d7830efc45016f"], From 3df2fdfc0f39c6063a27e5a5a30d01442d4ab2dc Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 10:19:24 +0100 Subject: [PATCH 2/7] Added edge-case handling to flea offer results pagination, stops server trying to get offers starting at a higher index than the end position Moved pagination code into own function Resolved various IDE warnings Added comments --- .../Controllers/RagfairController.cs | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs index 6900caec..1880e9d4 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs @@ -125,14 +125,14 @@ public class RagfairController /// /// Handles client/ragfair/find + /// Returns an object containing an array of flea offers to show to player /// /// Session/Player id - /// Search request data + /// Search request data from client /// Flea offers that match required search parameters public GetOffersResult GetOffers(string sessionID, SearchRequestData searchRequest) { var profile = _profileHelper.GetFullProfile(sessionID); - var itemsToAdd = _ragfairHelper.FilterCategories(sessionID, searchRequest); var traderAssorts = _ragfairHelper.GetDisplayableAssorts(sessionID); var result = new GetOffersResult @@ -150,6 +150,7 @@ public class RagfairController result.Categories = GetSpecificCategories(profile.CharacterData.PmcData, searchRequest, result.Offers); } + // Adjust index value of offers found to start at 0 AddIndexValueToOffers(result.Offers); // Sort offers @@ -176,17 +177,52 @@ public class RagfairController result.OffersCount = result.Offers.Count; - // Handle paging before returning results only if searching for general items, not preset items + // Handle paging before returning results if searching for general items, not preset items if (searchRequest.BuildCount == 0) { - var start = searchRequest.Page * searchRequest.Limit; - var end = Math.Min((searchRequest.Page.Value + 1) * searchRequest.Limit.Value, result.Offers.Count); - result.Offers = result.Offers.Slice(start.Value, end - start.Value); + PaginateOffers(searchRequest, result); } return result; } + /// + /// Paginate offers based on search request properties + /// + /// Client request + /// Object to return to client + protected void PaginateOffers(SearchRequestData searchRequest, GetOffersResult result) + { + // Number of items to show per page + var perPageLimit = searchRequest.Limit.GetValueOrDefault(15); // Client defaults to 15 items per page + + // Total pages to show player + var totalPages = result.Offers.Count / perPageLimit; + + // Page player was just on before clicking new page + var previousPage = searchRequest.Page.GetValueOrDefault(0); + + // Assumed page player is moving to + var nextPage = searchRequest.Page.GetValueOrDefault(0) + 1; + + // Get start/end item indexes + var startIndex = previousPage * perPageLimit; + var endIndex = Math.Min(nextPage * perPageLimit, result.Offers.Count); + + // Edge case + if (previousPage > totalPages) + { + // Occurs when player edits "item count shown per page" value when on page near end of offer list + // The page no longer exists due to the larger number of items on each page, show them the very end of the offer list instead + _logger.Warning("Ragfair page no longer exists, showing end of offers list"); + startIndex = result.Offers.Count - perPageLimit; + endIndex = result.Offers.Count; + } + + //result.Offers = result.Offers.Slice(start, end - start); + result.Offers = result.Offers.Skip(startIndex).Take(endIndex - startIndex).ToList(); + } + /// /// Adjust ragfair offer stack count to match same value as traders assort stack count /// From 5b29ce761b268e6eb6c2aea17741306a7002f1fa Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 10:31:22 +0100 Subject: [PATCH 3/7] Added resasonable defaults for call to `_ragfairSortHelper.SortOffers` --- .../SPTarkov.Server.Core/Controllers/RagfairController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs index 1880e9d4..29200e59 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs @@ -156,8 +156,8 @@ public class RagfairController // Sort offers result.Offers = _ragfairSortHelper.SortOffers( result.Offers, - searchRequest.SortType.Value, - searchRequest.SortDirection.Value + searchRequest.SortType.GetValueOrDefault(RagfairSort.ID), + searchRequest.SortDirection.GetValueOrDefault(0) ); // Match offers with quests and lock unfinished quests - get offers from traders From e444a9a3b65eb76e3fd652070561bb46cb484a4f Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 10:40:27 +0100 Subject: [PATCH 4/7] Small optimisation of `GetOffers()` Only process the paginated trader offers before sending to client --- .../Controllers/RagfairController.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs index 29200e59..fe3c51fa 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs @@ -142,6 +142,7 @@ public class RagfairController SelectedCategory = searchRequest.HandbookId }; + // Get all offers ready for sorting/filtering below result.Offers = GetOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, profile.CharacterData.PmcData); // Client requested a category refresh @@ -160,7 +161,16 @@ public class RagfairController searchRequest.SortDirection.GetValueOrDefault(0) ); - // Match offers with quests and lock unfinished quests - get offers from traders + // Must occur prior to pagination + result.OffersCount = result.Offers.Count; + + // Handle paging before returning results if searching for general items, not preset items + if (searchRequest.BuildCount == 0) + { + PaginateOffers(searchRequest, result); + } + + // Update trader offers' values, Lock quest-linked offers + adjust offer buy limits foreach (var traderOffer in result.Offers.Where(offer => _ragfairOfferHelper.OfferIsFromTrader(offer))) { // For the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked @@ -175,14 +185,6 @@ public class RagfairController SetTraderOfferStackSize(traderOffer); } - result.OffersCount = result.Offers.Count; - - // Handle paging before returning results if searching for general items, not preset items - if (searchRequest.BuildCount == 0) - { - PaginateOffers(searchRequest, result); - } - return result; } @@ -219,7 +221,6 @@ public class RagfairController endIndex = result.Offers.Count; } - //result.Offers = result.Offers.Slice(start, end - start); result.Offers = result.Offers.Skip(startIndex).Take(endIndex - startIndex).ToList(); } From fb31786ee2724117485cd409a916e431f629bfd0 Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 12:17:28 +0100 Subject: [PATCH 5/7] Updated profile templates to be a dictionary, cleaned up all uses of it throughout code Added `profileHelper.GetProfileTemplateForSide` --- .../Controllers/LauncherController.cs | 32 +++------ .../Controllers/LauncherV2Controller.cs | 18 +---- .../Helpers/HealthHelper.cs | 22 +++--- .../Helpers/ProfileHelper.cs | 19 +++++ .../Helpers/TraderHelper.cs | 40 ++++++----- .../Eft/Common/Tables/ProfileTemplate.cs | 69 ------------------- .../Models/Spt/Templates/Templates.cs | 2 +- .../Services/CreateProfileService.cs | 5 +- .../Services/DatabaseService.cs | 2 +- 9 files changed, 64 insertions(+), 145 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs index 21bf90ab..1b6ffb44 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs @@ -1,4 +1,3 @@ -using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common.Tables; @@ -38,43 +37,30 @@ public class LauncherController( public ConnectResponse Connect() { // Get all possible profile types + filter out any that are blacklisted - - var profiles = typeof(ProfileTemplates).GetProperties() - .Where(p => p.CanWrite) - .Select(p => p.GetJsonName()) - .Where(profileName => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profileName)) - .ToList(); + var profileTemplates = _databaseService.GetProfileTemplates() + .Where(profile => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key)) + .ToDictionary(); return new ConnectResponse { BackendUrl = _httpServerHelper.GetBackendUrl(), Name = _coreConfig.ServerName, - Editions = profiles, - ProfileDescriptions = GetProfileDescriptions() + Editions = profileTemplates.Select(x => x.Key).ToList(), + ProfileDescriptions = GetProfileDescriptions(profileTemplates) }; } /// /// Get descriptive text for each of the profile editions a player can choose, keyed by profile.json profile type e.g. "Edge Of Darkness" /// + /// Profiles to get descriptions of /// Dictionary of profile types with related descriptive text - protected Dictionary GetProfileDescriptions() + protected Dictionary GetProfileDescriptions(Dictionary profileTemplates) { var result = new Dictionary(); - var dbProfiles = _databaseService.GetProfiles(); - foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties() - .Where(p => p.CanWrite - && !string.Equals(p.Name, "extensiondata", StringComparison.InvariantCultureIgnoreCase))) + foreach (var (profileKey, profile) in profileTemplates) { - var propertyValue = templatesProperty.GetValue(dbProfiles); - if (propertyValue == null) - { - _logger.Warning(_localisationService.GetText("launcher-missing_property", templatesProperty.Name)); - continue; - } - - var casterPropertyValue = propertyValue as ProfileSides; - result[templatesProperty.GetJsonName()] = _localisationService.GetText(casterPropertyValue?.DescriptionLocaleKey!); + result.TryAdd(profileKey, _localisationService.GetText(profile.DescriptionLocaleKey)); } return result; diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs index 9e8a69df..9d5ea553 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs @@ -1,6 +1,4 @@ -using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Launcher; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; @@ -46,21 +44,11 @@ public class LauncherV2Controller( public Dictionary Types() { var result = new Dictionary(); - var dbProfiles = _databaseService.GetProfiles(); + var dbProfiles = _databaseService.GetProfileTemplates(); - foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties() - .Where(p => p.CanWrite - && !string.Equals(p.Name, "extensiondata", StringComparison.InvariantCultureIgnoreCase))) + foreach (var profileKvP in dbProfiles) { - var propertyValue = templatesProperty.GetValue(dbProfiles); - if (propertyValue == null) - { - _logger.Warning(_localisationService.GetText("launcher-missing_property", templatesProperty.Name)); - continue; - } - - var casterPropertyValue = propertyValue as ProfileSides; - result[templatesProperty.GetJsonName()] = _localisationService.GetText(casterPropertyValue?.DescriptionLocaleKey!); + result.TryAdd(profileKvP.Key, _localisationService.GetText(profileKvP.Value.DescriptionLocaleKey)); } return result; diff --git a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs index aa91c8e3..8470b119 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs @@ -1,11 +1,9 @@ -using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Servers; -using SPTarkov.Server.Core.Services; using SPTarkov.Server.Core.Utils; using BodyPartHealth = SPTarkov.Server.Core.Models.Eft.Common.Tables.BodyPartHealth; using Vitality = SPTarkov.Server.Core.Models.Eft.Profile.Vitality; @@ -16,7 +14,7 @@ namespace SPTarkov.Server.Core.Helpers; public class HealthHelper( TimeUtil _timeUtil, SaveServer _saveServer, - DatabaseService _databaseService, + ProfileHelper _profileHelper, ConfigServer _configServer ) { @@ -128,8 +126,6 @@ public class HealthHelper( /// Post raid data /// Session id /// Is player dead - /// Should effects be added to profile (default - true) - /// Should all prior effects be removed before apply new ones (default - true) public void UpdateProfileHealthPostRaid( PmcData pmcData, BotBaseHealth postRaidHealth, @@ -139,16 +135,14 @@ public class HealthHelper( var fullProfile = _saveServer.GetProfile(sessionID); var profileEdition = fullProfile.ProfileInfo.Edition; var profileSide = fullProfile.CharacterData.PmcData.Info.Side; + + // Get matching 'side e.g. USEC + var matchingSide = _profileHelper.GetProfileTemplateForSide(profileEdition, profileSide); - var defaultTemperature = - _databaseService.GetProfiles() - .GetByJsonProp(profileEdition) - .GetByJsonProp(profileSide.ToLower()) - ?.Character?.Health?.Temperature ?? - new CurrentMinMax - { - Current = 36.6 - }; + var defaultTemperature = matchingSide?.Character?.Health?.Temperature ?? new CurrentMinMax + { + Current = 36.6 + }; StoreHydrationEnergyTempInProfile( fullProfile, diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs index a1cd6f26..431ce184 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs @@ -754,4 +754,23 @@ public class ProfileHelper( fullProfile.SptData.ExtraRepeatableQuests[repeatableId] += rewardValue; } } + + /// + /// Get a profile template by the account and side + /// + /// Edition of profile desired, e.g. "Standard" + /// Side of profile desired, e.g. "Bear" + /// + public TemplateSide GetProfileTemplateForSide(string accountEdition, string side) + { + var profileTemplates = _databaseService.GetProfileTemplates(); + + // Get matching profile 'type' e.g. 'standard' + profileTemplates.TryGetValue(accountEdition, out var matchingProfileTemplate); + + // Get matching profile by 'side' e.g. USEC + return string.Equals(side, "bear", StringComparison.OrdinalIgnoreCase) + ? matchingProfileTemplate.Bear + : matchingProfileTemplate.Usec; + } } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs index 7f42f161..33912f6a 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs @@ -1,4 +1,4 @@ -using SPTarkov.Common.Extensions; +using System.Security.Principal; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; @@ -136,7 +136,7 @@ public class TraderHelper( /// trader id to reset public void ResetTrader(string sessionID, string traderID) { - var profiles = _databaseService.GetProfiles(); + var profiles = _databaseService.GetProfileTemplates(); var trader = _databaseService.GetTrader(traderID); var fullProfile = _profileHelper.GetFullProfile(sessionID); @@ -145,34 +145,34 @@ public class TraderHelper( throw new Exception(_localisationService.GetText("trader-unable_to_find_profile_by_id", sessionID)); } + // Get matching profile 'type' e.g. 'standard' + profiles.TryGetValue(fullProfile.ProfileInfo.Edition, out var matchingProfileTemplate); var pmcData = fullProfile.CharacterData.PmcData; - var rawProfileTemplate = profiles.GetByJsonProp(fullProfile.ProfileInfo.Edition) - .GetByJsonProp(pmcData.Info.Side.ToLower()) - .Trader; + var matchingSide = _profileHelper.GetProfileTemplateForSide(fullProfile.ProfileInfo.Edition, pmcData.Info.Side); + + // Profiles trader settings + var profileTemplateTraderData = matchingSide.Trader; var newTraderData = new TraderInfo { Disabled = false, - LoyaltyLevel = rawProfileTemplate.InitialLoyaltyLevel.GetValueOrDefault(traderID, 1), - SalesSum = rawProfileTemplate.InitialSalesSum, - Standing = GetStartingStanding(traderID, rawProfileTemplate), + LoyaltyLevel = profileTemplateTraderData.InitialLoyaltyLevel.GetValueOrDefault(traderID, 1), + SalesSum = profileTemplateTraderData.InitialSalesSum, + Standing = GetStartingStanding(traderID, profileTemplateTraderData), NextResupply = trader.Base.NextResupply, Unlocked = trader.Base.UnlockedByDefault }; - if (!pmcData.TradersInfo.TryAdd(traderID, newTraderData)) - { - pmcData.TradersInfo[traderID] = newTraderData; - } - + // Add trader to profile if it doesn't already + pmcData.TradersInfo.TryAdd(traderID, newTraderData); // Check if trader should be locked by default - if (rawProfileTemplate.LockedByDefaultOverride?.Contains(traderID) ?? false) + if (profileTemplateTraderData.LockedByDefaultOverride?.Contains(traderID) ?? false) { pmcData.TradersInfo[traderID].Unlocked = true; } - if (rawProfileTemplate.PurchaseAllClothingByDefaultForTrader?.Contains(traderID) ?? false) + if (profileTemplateTraderData.PurchaseAllClothingByDefaultForTrader?.Contains(traderID) ?? false) { // Get traders clothing var clothing = _databaseService.GetTrader(traderID).Suits; @@ -186,16 +186,18 @@ public class TraderHelper( } } - if ((rawProfileTemplate.FleaBlockedDays ?? 0) > 0) + // Template has flea block + if ((profileTemplateTraderData.FleaBlockedDays ?? 0) > 0) { - var newBanDateTime = _timeUtil.GetTimeStampFromNowDays(rawProfileTemplate.FleaBlockedDays ?? 0); - var existingBan = pmcData.Info.Bans.FirstOrDefault(ban => ban.BanType == BanType.RagFair); + var newBanDateTime = _timeUtil.GetTimeStampFromNowDays(profileTemplateTraderData.FleaBlockedDays ?? 0); + var existingBan = pmcData.Info.Bans?.FirstOrDefault(ban => ban.BanType == BanType.RagFair); if (existingBan is not null) { existingBan.DateTime = newBanDateTime; } else { + pmcData.Info.Bans ??= []; pmcData.Info.Bans.Add( new Ban { @@ -208,7 +210,7 @@ public class TraderHelper( if (traderID == Traders.JAEGER) { - pmcData.TradersInfo[traderID].Unlocked = rawProfileTemplate.JaegerUnlocked; + pmcData.TradersInfo[traderID].Unlocked = profileTemplateTraderData.JaegerUnlocked; } } diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs index 39e5b498..8a15511e 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs @@ -3,75 +3,6 @@ using SPTarkov.Server.Core.Models.Eft.Profile; namespace SPTarkov.Server.Core.Models.Eft.Common.Tables; -public record ProfileTemplates -{ - [JsonExtensionData] - public Dictionary ExtensionData { get; set; } - - [JsonPropertyName("Standard")] - public ProfileSides? Standard - { - get; - set; - } - - [JsonPropertyName("Left Behind")] - public ProfileSides? LeftBehind - { - get; - set; - } - - [JsonPropertyName("Prepare To Escape")] - public ProfileSides? PrepareToEscape - { - get; - set; - } - - [JsonPropertyName("Edge Of Darkness")] - public ProfileSides? EdgeOfDarkness - { - get; - set; - } - - [JsonPropertyName("Unheard")] - public ProfileSides? Unheard - { - get; - set; - } - - [JsonPropertyName("Tournament")] - public ProfileSides? Tournament - { - get; - set; - } - - [JsonPropertyName("SPT Developer")] - public ProfileSides? SPTDeveloper - { - get; - set; - } - - [JsonPropertyName("SPT Easy start")] - public ProfileSides? SPTEasyStart - { - get; - set; - } - - [JsonPropertyName("SPT Zero to hero")] - public ProfileSides? SPTZeroToHero - { - get; - set; - } -} - public record ProfileSides { [JsonExtensionData] diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs index c984ebd1..cbe3206d 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs @@ -69,7 +69,7 @@ public record Templates /// The profile templates listed in the launcher on profile creation, split by account type (e.g. Standard) then side (e.g. bear/usec) /// [JsonPropertyName("profiles")] - public ProfileTemplates? Profiles + public Dictionary? Profiles { get; set; diff --git a/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs b/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs index 941fbc23..93050ffd 100644 --- a/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs @@ -43,9 +43,8 @@ public class CreateProfileService( public string CreateProfile(string sessionId, ProfileCreateRequestData request) { var account = _cloner.Clone(_saveServer.GetProfile(sessionId)); - var profileTemplateClone = _cloner.Clone( - _databaseService.GetProfiles()?.GetByJsonProp(account.ProfileInfo.Edition)?.GetByJsonProp(request.Side.ToLower()) - ); + var profileTemplateClone = _cloner.Clone(_profileHelper.GetProfileTemplateForSide(account.ProfileInfo.Edition, request.Side)); + var pmcData = profileTemplateClone.Character; // Delete existing profile diff --git a/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs b/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs index cdc06e1b..12d073c7 100644 --- a/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs @@ -257,7 +257,7 @@ public class DatabaseService( } /// assets/database/templates/profiles.json - public ProfileTemplates GetProfiles() + public Dictionary GetProfileTemplates() { if (_databaseServer.GetTables().Templates?.Profiles == null) { From 941a4f188dfdec29ff39be7241868b3fefdbff82 Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 14:16:55 +0100 Subject: [PATCH 6/7] Added missing soft inserts to ref assort #370 --- .../6617beeaa9cfa777ca915b7c/assort.json | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json b/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json index c88da83f..e72f1e1c 100644 --- a/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json +++ b/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json @@ -385,6 +385,54 @@ "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Right_side_plate" }, + { + "_id": "68443b9497c1f7706ca9db19", + "_tpl": "6575ce3716c2762fba0057fd", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b94c3b834e691c8ba1c", + "_tpl": "6575ce45dc9932aed601c616", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443b95dedb8031be15460a", + "_tpl": "6575ce5016c2762fba005802", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443b95862f89f16f36234a", + "_tpl": "6575ce5befc786cd9101a671", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "soft_armor_right" + }, + { + "_id": "68443b951e9847665b682fc1", + "_tpl": "6575ce6f16c2762fba005806", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Collar" + }, + { + "_id": "68443b955341d23924fa1969", + "_tpl": "6575ce9db15fef3dd4051628", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Shoulder_l" + }, + { + "_id": "68443b9566c3cd7334832f6f", + "_tpl": "6575cea8b15fef3dd405162c", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Shoulder_r" + }, + { + "_id": "68443b95f7e19bb91afee43d", + "_tpl": "6575ce8bdc9932aed601c61e", + "parentId": "6808b1a4c25caf3a4305d44c", + "slotId": "Groin" + }, { "_id": "6808b1a7c25caf3a4305d61f", "_tpl": "558022b54bdc2dac148b458d", @@ -1445,6 +1493,24 @@ "parentId": "6808b1a6c25caf3a4305d57c", "slotId": "mod_equipment" }, + { + "_id": "68443b95d9a6e4dbb2d5e844", + "_tpl": "657bc06daab96fccee08be9b", + "parentId": "6808b1a6c25caf3a4305d57c", + "slotId": "Helmet_top" + }, + { + "_id": "68443b95489362945e897d25", + "_tpl": "657bc0d8a1c61ee0c303632f", + "parentId": "6808b1a6c25caf3a4305d57c", + "slotId": "Helmet_back" + }, + { + "_id": "68443b9551a5e1e5c9c5b700", + "_tpl": "657bc107aab96fccee08be9f", + "parentId": "6808b1a6c25caf3a4305d57c", + "slotId": "Helmet_ears" + }, { "_id": "6808b1a5c25caf3a4305d53e", "_tpl": "5aafbcd986f7745e590fff23", @@ -1825,6 +1891,48 @@ "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Back_plate" }, + { + "_id": "68443b950418f006ece79394", + "_tpl": "6575c342efc786cd9101a5e5", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b953fe534ccea287d36", + "_tpl": "6575c34bc6700bd6b40e8a84", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443b957c72e770e3abc882", + "_tpl": "6575c35bc6700bd6b40e8a88", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443b95ad2526c75189a317", + "_tpl": "6575c366c6700bd6b40e8a8c", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "soft_armor_right" + }, + { + "_id": "68443b95982889c2f04f3ea7", + "_tpl": "6575c373dc9932aed601c5ec", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "Collar" + }, + { + "_id": "68443b9511abe04faced841d", + "_tpl": "6575c385dc9932aed601c5f0", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "Groin" + }, + { + "_id": "68443b9562b1362ba4ec4fb5", + "_tpl": "6575c390efc786cd9101a5e9", + "parentId": "6808b1a2c25caf3a4305d2d5", + "slotId": "Groin_back" + }, { "_id": "6808b1a2c25caf3a4305d2a9", "_tpl": "5b6d9ce188a4501afc1b2b25", @@ -1977,6 +2085,36 @@ "parentId": "6808b1a5c25caf3a4305d51b", "slotId": "Back_plate" }, + { + "_id": "68443b95d1f859cb4afa93ab", + "_tpl": "6571dbd388ead79fcf091d71", + "parentId": "6808b1a5c25caf3a4305d51b", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b955d190886ebdeee7e", + "_tpl": "6571dbda88ead79fcf091d75", + "parentId": "6808b1a5c25caf3a4305d51b", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443b95aabdfcf23caec5d2", + "_tpl": "6571dbe07c02ae206002502e", + "parentId": "6808b1a5c25caf3a4305d51b", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443b9567ef03e5c380d4ba", + "_tpl": "6571dbeaee8ec43d520cf89e", + "parentId": "6808b1a5c25caf3a4305d51b", + "slotId": "soft_armor_right" + }, + { + "_id": "68443b9502c08eeb821410d4", + "_tpl": "6571dbef88ead79fcf091d79", + "parentId": "6808b1a5c25caf3a4305d51b", + "slotId": "Collar" + }, { "_id": "6808b1a5c25caf3a4305d4e7", "_tpl": "5c0e625a86f7742d77340f62", @@ -2011,6 +2149,18 @@ "parentId": "6808b1a2c25caf3a4305d24e", "slotId": "Back_plate" }, + { + "_id": "68443b95c1c5d1af7f767352", + "_tpl": "6570e025615f54368b04fcb0", + "parentId": "6808b1a2c25caf3a4305d24e", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b9532dadd4c79c31668", + "_tpl": "6570e0610b57c03ec90b96ef", + "parentId": "6808b1a2c25caf3a4305d24e", + "slotId": "Soft_armor_back" + }, { "_id": "6808b1a7c25caf3a4305d657", "_tpl": "5c127c4486f7745625356c13", @@ -3630,6 +3780,30 @@ "parentId": "6808b1a3c25caf3a4305d34e", "slotId": "Back_plate" }, + { + "_id": "68443b9520e792db66597bad", + "_tpl": "6570f30b0921c914bf07964c", + "parentId": "6808b1a3c25caf3a4305d34e", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b9578e42618a2559427", + "_tpl": "6570f35cd67d0309980a7acb", + "parentId": "6808b1a3c25caf3a4305d34e", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443b95ce1fcd9b1ed9673e", + "_tpl": "6570f3890b4ae5847f060dad", + "parentId": "6808b1a3c25caf3a4305d34e", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443b953567aabc8c20beec", + "_tpl": "6570f3bb0b4ae5847f060db2", + "parentId": "6808b1a3c25caf3a4305d34e", + "slotId": "soft_armor_right" + }, { "_id": "6808b1a4c25caf3a4305d480", "_tpl": "64acea16c4eda9354b0226b0", @@ -4744,6 +4918,36 @@ "parentId": "6808b1a4c25caf3a4305d43c", "slotId": "Back_plate" }, + { + "_id": "68443b95e8789863cf236086", + "_tpl": "65704de13e7bba58ea0285c8", + "parentId": "6808b1a4c25caf3a4305d43c", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b9529045aaeef790710", + "_tpl": "65705c3c14f2ed6d7d0b7738", + "parentId": "6808b1a4c25caf3a4305d43c", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443b959e294b038e889e82", + "_tpl": "65705c777260e1139e091408", + "parentId": "6808b1a4c25caf3a4305d43c", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443b9597b76378e06d3156", + "_tpl": "65705cb314f2ed6d7d0b773c", + "parentId": "6808b1a4c25caf3a4305d43c", + "slotId": "soft_armor_right" + }, + { + "_id": "68443b95e9efc3bb6f564c5c", + "_tpl": "65705cea4916448ae1050897", + "parentId": "6808b1a4c25caf3a4305d43c", + "slotId": "Collar" + }, { "_id": "6808b1a2c25caf3a4305d2b8", "_tpl": "67ab2f5adafe3b22670c911f", @@ -4767,6 +4971,48 @@ "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Back_plate" }, + { + "_id": "68443b952917a0392364f324", + "_tpl": "6575dd3e9e27f4a85e081142", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b957a4eb8dde539dcd7", + "_tpl": "6575dd519e27f4a85e081146", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443b958543d5eef61a594c", + "_tpl": "6575dd64945bf78edd04c438", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443b95031547bb83d71c1e", + "_tpl": "6575dd6e9d3a0ddf660b9047", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "soft_armor_right" + }, + { + "_id": "68443b956f73ac68cd68429c", + "_tpl": "6575dd769d3a0ddf660b904b", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "Collar" + }, + { + "_id": "68443b958a4cdf9f76dbc851", + "_tpl": "6575dd800546f8b1de093df6", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "Groin" + }, + { + "_id": "68443b95ee56936137b1c31d", + "_tpl": "6575dd94945bf78edd04c43c", + "parentId": "6808b1a2c25caf3a4305d2b8", + "slotId": "Groin_back" + }, { "_id": "6808b1a5c25caf3a4305d532", "_tpl": "67ab2f94dafe3b22670c912c", @@ -4790,6 +5036,18 @@ "parentId": "6808b1a5c25caf3a4305d532", "slotId": "Back_plate" }, + { + "_id": "68443b95e1ca79d35b37e538", + "_tpl": "6570e025615f54368b04fcb0", + "parentId": "6808b1a5c25caf3a4305d532", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443b95559f195a4119581f", + "_tpl": "6570e0610b57c03ec90b96ef", + "parentId": "6808b1a5c25caf3a4305d532", + "slotId": "Soft_armor_back" + }, { "_id": "6808b1a3c25caf3a4305d3c8", "_tpl": "67ab3ea96d7ece17bf0096f6", From 9fd09f6128fcb0183b662566e2a30dcc2a4b9ef5 Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 14:32:47 +0100 Subject: [PATCH 7/7] Added additional missing soft inserts --- .../6617beeaa9cfa777ca915b7c/assort.json | 290 +++++++++++++++--- 1 file changed, 247 insertions(+), 43 deletions(-) diff --git a/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json b/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json index e72f1e1c..6216d2ce 100644 --- a/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json +++ b/Libraries/SPTarkov.Server.Assets/Assets/database/traders/6617beeaa9cfa777ca915b7c/assort.json @@ -386,49 +386,49 @@ "slotId": "Right_side_plate" }, { - "_id": "68443b9497c1f7706ca9db19", + "_id": "68443f58e819155390903319", "_tpl": "6575ce3716c2762fba0057fd", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Soft_armor_front" }, { - "_id": "68443b94c3b834e691c8ba1c", + "_id": "68443f58e9af9f254a78868e", "_tpl": "6575ce45dc9932aed601c616", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Soft_armor_back" }, { - "_id": "68443b95dedb8031be15460a", + "_id": "68443f58daf66c22f3a67da8", "_tpl": "6575ce5016c2762fba005802", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Soft_armor_left" }, { - "_id": "68443b95862f89f16f36234a", + "_id": "68443f58bf0113fb0354d5a5", "_tpl": "6575ce5befc786cd9101a671", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "soft_armor_right" }, { - "_id": "68443b951e9847665b682fc1", + "_id": "68443f5869582b58ba3681be", "_tpl": "6575ce6f16c2762fba005806", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Collar" }, { - "_id": "68443b955341d23924fa1969", + "_id": "68443f58f96fc647bc6d586b", "_tpl": "6575ce9db15fef3dd4051628", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Shoulder_l" }, { - "_id": "68443b9566c3cd7334832f6f", + "_id": "68443f588802579fd65d37be", "_tpl": "6575cea8b15fef3dd405162c", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Shoulder_r" }, { - "_id": "68443b95f7e19bb91afee43d", + "_id": "68443f58ac75d4d6d5f55675", "_tpl": "6575ce8bdc9932aed601c61e", "parentId": "6808b1a4c25caf3a4305d44c", "slotId": "Groin" @@ -1494,19 +1494,19 @@ "slotId": "mod_equipment" }, { - "_id": "68443b95d9a6e4dbb2d5e844", + "_id": "68443f58ef6803b75880da93", "_tpl": "657bc06daab96fccee08be9b", "parentId": "6808b1a6c25caf3a4305d57c", "slotId": "Helmet_top" }, { - "_id": "68443b95489362945e897d25", + "_id": "68443f58cd8d1ea8c7472a53", "_tpl": "657bc0d8a1c61ee0c303632f", "parentId": "6808b1a6c25caf3a4305d57c", "slotId": "Helmet_back" }, { - "_id": "68443b9551a5e1e5c9c5b700", + "_id": "68443f58c72bd8fcd1f0ce2c", "_tpl": "657bc107aab96fccee08be9f", "parentId": "6808b1a6c25caf3a4305d57c", "slotId": "Helmet_ears" @@ -1558,6 +1558,30 @@ "parentId": "6808b1a4c25caf3a4305d3ee", "slotId": "Back_plate" }, + { + "_id": "68443f58888080c634a51d73", + "_tpl": "6570f6e774d84423df065f21", + "parentId": "6808b1a4c25caf3a4305d3ee", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443f58fa7c08483b87c9be", + "_tpl": "6570f71dd67d0309980a7af8", + "parentId": "6808b1a4c25caf3a4305d3ee", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443f589d15b0a064267a74", + "_tpl": "6570f74774d84423df065f25", + "parentId": "6808b1a4c25caf3a4305d3ee", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443f58e9abc3e55f614390", + "_tpl": "6570f79c4c65ab77a6015121", + "parentId": "6808b1a4c25caf3a4305d3ee", + "slotId": "soft_armor_right" + }, { "_id": "6808b1a3c25caf3a4305d3cf", "_tpl": "5ac66d725acfc43b321d4b60", @@ -1868,6 +1892,24 @@ "BuyRestrictionCurrent": 0 } }, + { + "_id": "68443f5a25c169bf7456207f", + "_tpl": "657112234269e9a568089eac", + "parentId": "6808b1a3c25caf3a4305d35c", + "slotId": "Helmet_top" + }, + { + "_id": "68443f5a7e90980375bc4528", + "_tpl": "657112a4818110db4600aa66", + "parentId": "6808b1a3c25caf3a4305d35c", + "slotId": "Helmet_back" + }, + { + "_id": "68443f5a4f5126cb14a660f7", + "_tpl": "657112ce22996eaf110881fb", + "parentId": "6808b1a3c25caf3a4305d35c", + "slotId": "Helmet_ears" + }, { "_id": "6808b1a2c25caf3a4305d2d5", "_tpl": "5b44d0de86f774503d30cba8", @@ -1892,43 +1934,43 @@ "slotId": "Back_plate" }, { - "_id": "68443b950418f006ece79394", + "_id": "68443f5a7e729f77a4e3fc09", "_tpl": "6575c342efc786cd9101a5e5", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Soft_armor_front" }, { - "_id": "68443b953fe534ccea287d36", + "_id": "68443f5ae102c7d1b540eb24", "_tpl": "6575c34bc6700bd6b40e8a84", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Soft_armor_back" }, { - "_id": "68443b957c72e770e3abc882", + "_id": "68443f5af577ef03c301fe5c", "_tpl": "6575c35bc6700bd6b40e8a88", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Soft_armor_left" }, { - "_id": "68443b95ad2526c75189a317", + "_id": "68443f5a5f04bc0a19ca5a77", "_tpl": "6575c366c6700bd6b40e8a8c", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "soft_armor_right" }, { - "_id": "68443b95982889c2f04f3ea7", + "_id": "68443f5a5486768017aa7520", "_tpl": "6575c373dc9932aed601c5ec", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Collar" }, { - "_id": "68443b9511abe04faced841d", + "_id": "68443f5a26452590fee3914f", "_tpl": "6575c385dc9932aed601c5f0", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Groin" }, { - "_id": "68443b9562b1362ba4ec4fb5", + "_id": "68443f5a3dc4960abc60048f", "_tpl": "6575c390efc786cd9101a5e9", "parentId": "6808b1a2c25caf3a4305d2d5", "slotId": "Groin_back" @@ -2086,31 +2128,31 @@ "slotId": "Back_plate" }, { - "_id": "68443b95d1f859cb4afa93ab", + "_id": "68443f5aac477472aa728d30", "_tpl": "6571dbd388ead79fcf091d71", "parentId": "6808b1a5c25caf3a4305d51b", "slotId": "Soft_armor_front" }, { - "_id": "68443b955d190886ebdeee7e", + "_id": "68443f5a6a49b0c7e7f2998c", "_tpl": "6571dbda88ead79fcf091d75", "parentId": "6808b1a5c25caf3a4305d51b", "slotId": "Soft_armor_back" }, { - "_id": "68443b95aabdfcf23caec5d2", + "_id": "68443f5af36a8ebc575c5db8", "_tpl": "6571dbe07c02ae206002502e", "parentId": "6808b1a5c25caf3a4305d51b", "slotId": "Soft_armor_left" }, { - "_id": "68443b9567ef03e5c380d4ba", + "_id": "68443f5a5c8b5e0766211846", "_tpl": "6571dbeaee8ec43d520cf89e", "parentId": "6808b1a5c25caf3a4305d51b", "slotId": "soft_armor_right" }, { - "_id": "68443b9502c08eeb821410d4", + "_id": "68443f5a8469a02867d69249", "_tpl": "6571dbef88ead79fcf091d79", "parentId": "6808b1a5c25caf3a4305d51b", "slotId": "Collar" @@ -2126,6 +2168,36 @@ "BuyRestrictionCurrent": 0 } }, + { + "_id": "68443f5a597b642e830c2285", + "_tpl": "65764275d8537eb26a0355e9", + "parentId": "6808b1a5c25caf3a4305d4e7", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443f5a436bd1709a688e8e", + "_tpl": "657642b0e6d5dd75f40688a5", + "parentId": "6808b1a5c25caf3a4305d4e7", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443f5a6443172b19106d5e", + "_tpl": "6576434820cc24d17102b148", + "parentId": "6808b1a5c25caf3a4305d4e7", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443f5a009817c6db22f632", + "_tpl": "657643732bc38ef78e076477", + "parentId": "6808b1a5c25caf3a4305d4e7", + "slotId": "soft_armor_right" + }, + { + "_id": "68443f5a655908e29af980ce", + "_tpl": "657643a220cc24d17102b14c", + "parentId": "6808b1a5c25caf3a4305d4e7", + "slotId": "Collar" + }, { "_id": "6808b1a2c25caf3a4305d24e", "_tpl": "5c0e655586f774045612eeb2", @@ -2150,13 +2222,13 @@ "slotId": "Back_plate" }, { - "_id": "68443b95c1c5d1af7f767352", + "_id": "68443f5af76e65abf505a492", "_tpl": "6570e025615f54368b04fcb0", "parentId": "6808b1a2c25caf3a4305d24e", "slotId": "Soft_armor_front" }, { - "_id": "68443b9532dadd4c79c31668", + "_id": "68443f5ad1f1e6ebadf3a742", "_tpl": "6570e0610b57c03ec90b96ef", "parentId": "6808b1a2c25caf3a4305d24e", "slotId": "Soft_armor_back" @@ -2696,6 +2768,30 @@ "parentId": "6808b1a4c25caf3a4305d40d", "slotId": "right_side_plate" }, + { + "_id": "68443f5a804f50deefe8f657", + "_tpl": "6575ef599c7cad336508e453", + "parentId": "6808b1a4c25caf3a4305d40d", + "slotId": "soft_armor_front" + }, + { + "_id": "68443f5a4a78aad797b75f65", + "_tpl": "6575ef6bf6a13a7b7100b093", + "parentId": "6808b1a4c25caf3a4305d40d", + "slotId": "soft_armor_back" + }, + { + "_id": "68443f5a26ea2758b18bd173", + "_tpl": "6575ef78da698a4e980677eb", + "parentId": "6808b1a4c25caf3a4305d40d", + "slotId": "soft_armor_left" + }, + { + "_id": "68443f5a41618b96846132fe", + "_tpl": "6575ef7f9c7cad336508e457", + "parentId": "6808b1a4c25caf3a4305d40d", + "slotId": "soft_armor_right" + }, { "_id": "6808b1a4c25caf3a4305d400", "_tpl": "5e4bfc1586f774264f7582d3", @@ -2707,6 +2803,18 @@ "BuyRestrictionCurrent": 0 } }, + { + "_id": "68443f5aa1c30086f6915672", + "_tpl": "657f9c78ada5fadd1f07a58d", + "parentId": "6808b1a4c25caf3a4305d400", + "slotId": "Helmet_top" + }, + { + "_id": "68443f5ae1477179289ff74f", + "_tpl": "657f9cb587e11c61f70bfaca", + "parentId": "6808b1a4c25caf3a4305d400", + "slotId": "Helmet_back" + }, { "_id": "6808b1a5c25caf3a4305d518", "_tpl": "5e81ebcd8e146c7080625e15", @@ -3158,6 +3266,48 @@ "parentId": "6808b1a4c25caf3a4305d425", "slotId": "Back_plate" }, + { + "_id": "68443f5a25dac4e3eeefb147", + "_tpl": "6570fae34c65ab77a6015146", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443f5ac1ce9ca11d874d69", + "_tpl": "6570fa1f4c65ab77a601512f", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443f5a65ba0cfdbecba92f", + "_tpl": "6570fb22584a51c23e03251f", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "Soft_armor_left" + }, + { + "_id": "68443f5ae1e85b37029ca381", + "_tpl": "6570fb6ad3eefd23430f8c7c", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "soft_armor_right" + }, + { + "_id": "68443f5a31197f3f23b09fb1", + "_tpl": "6570fb8f4c65ab77a601514d", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "Collar" + }, + { + "_id": "68443f5ae83c301dd5a6c2b4", + "_tpl": "6570fbdd74d84423df065f60", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "Shoulder_l" + }, + { + "_id": "68443f5a2b2a2ad5354c0538", + "_tpl": "6570fc41d3eefd23430f8c83", + "parentId": "6808b1a4c25caf3a4305d425", + "slotId": "Shoulder_r" + }, { "_id": "6808b1a4c25caf3a4305d494", "_tpl": "615d8f8567085e45ef1409ca", @@ -3441,6 +3591,18 @@ "BuyRestrictionCurrent": 0 } }, + { + "_id": "68443f5a82beb801d9af1bd4", + "_tpl": "657bbcc9a1c61ee0c3036327", + "parentId": "6808b1a2c25caf3a4305d2fc", + "slotId": "Helmet_top" + }, + { + "_id": "68443f5a5a6669182e8774a5", + "_tpl": "657bbcffbbd440df880b2dd5", + "parentId": "6808b1a2c25caf3a4305d2fc", + "slotId": "Helmet_back" + }, { "_id": "6808b1a2c25caf3a4305d2ea", "_tpl": "620109578d82e67e7911abf2", @@ -3781,25 +3943,25 @@ "slotId": "Back_plate" }, { - "_id": "68443b9520e792db66597bad", + "_id": "68443f5a5cd7b7a9adab7adc", "_tpl": "6570f30b0921c914bf07964c", "parentId": "6808b1a3c25caf3a4305d34e", "slotId": "Soft_armor_front" }, { - "_id": "68443b9578e42618a2559427", + "_id": "68443f5a5830849109209a5e", "_tpl": "6570f35cd67d0309980a7acb", "parentId": "6808b1a3c25caf3a4305d34e", "slotId": "Soft_armor_back" }, { - "_id": "68443b95ce1fcd9b1ed9673e", + "_id": "68443f5a98c6e07164b69dce", "_tpl": "6570f3890b4ae5847f060dad", "parentId": "6808b1a3c25caf3a4305d34e", "slotId": "Soft_armor_left" }, { - "_id": "68443b953567aabc8c20beec", + "_id": "68443f5ac56ffeec0e8d9164", "_tpl": "6570f3bb0b4ae5847f060db2", "parentId": "6808b1a3c25caf3a4305d34e", "slotId": "soft_armor_right" @@ -3837,6 +3999,18 @@ "BuyRestrictionCurrent": 0 } }, + { + "_id": "68443f5a0b5853d147be365d", + "_tpl": "6570495b45d573133d0d6adb", + "parentId": "6808b1a6c25caf3a4305d59c", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443f5a6b460b99c4e82804", + "_tpl": "657049d23425b19bbc0502f0", + "parentId": "6808b1a6c25caf3a4305d59c", + "slotId": "Soft_armor_back" + }, { "_id": "6808b1a7c25caf3a4305d5fb", "_tpl": "6516e91f609aaf354b34b3e2", @@ -4919,31 +5093,31 @@ "slotId": "Back_plate" }, { - "_id": "68443b95e8789863cf236086", + "_id": "68443f5a3c97a85aa6a3b088", "_tpl": "65704de13e7bba58ea0285c8", "parentId": "6808b1a4c25caf3a4305d43c", "slotId": "Soft_armor_front" }, { - "_id": "68443b9529045aaeef790710", + "_id": "68443f5a460b5f42e2e1134c", "_tpl": "65705c3c14f2ed6d7d0b7738", "parentId": "6808b1a4c25caf3a4305d43c", "slotId": "Soft_armor_back" }, { - "_id": "68443b959e294b038e889e82", + "_id": "68443f5a33c73db4e5c355f5", "_tpl": "65705c777260e1139e091408", "parentId": "6808b1a4c25caf3a4305d43c", "slotId": "Soft_armor_left" }, { - "_id": "68443b9597b76378e06d3156", + "_id": "68443f5a75abca920288b0fa", "_tpl": "65705cb314f2ed6d7d0b773c", "parentId": "6808b1a4c25caf3a4305d43c", "slotId": "soft_armor_right" }, { - "_id": "68443b95e9efc3bb6f564c5c", + "_id": "68443f5a5b1b43ab7f6f265f", "_tpl": "65705cea4916448ae1050897", "parentId": "6808b1a4c25caf3a4305d43c", "slotId": "Collar" @@ -4972,43 +5146,43 @@ "slotId": "Back_plate" }, { - "_id": "68443b952917a0392364f324", + "_id": "68443f5ae1877f5ca4edd3b0", "_tpl": "6575dd3e9e27f4a85e081142", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Soft_armor_front" }, { - "_id": "68443b957a4eb8dde539dcd7", + "_id": "68443f5a23422b5e71856440", "_tpl": "6575dd519e27f4a85e081146", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Soft_armor_back" }, { - "_id": "68443b958543d5eef61a594c", + "_id": "68443f5ab6ed311310425dab", "_tpl": "6575dd64945bf78edd04c438", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Soft_armor_left" }, { - "_id": "68443b95031547bb83d71c1e", + "_id": "68443f5a77c1ee0ffd5811d2", "_tpl": "6575dd6e9d3a0ddf660b9047", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "soft_armor_right" }, { - "_id": "68443b956f73ac68cd68429c", + "_id": "68443f5aa4b6963a64ac603a", "_tpl": "6575dd769d3a0ddf660b904b", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Collar" }, { - "_id": "68443b958a4cdf9f76dbc851", + "_id": "68443f5a95c9a2b6073ebdec", "_tpl": "6575dd800546f8b1de093df6", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Groin" }, { - "_id": "68443b95ee56936137b1c31d", + "_id": "68443f5accc5cfbdb8da89f9", "_tpl": "6575dd94945bf78edd04c43c", "parentId": "6808b1a2c25caf3a4305d2b8", "slotId": "Groin_back" @@ -5037,13 +5211,13 @@ "slotId": "Back_plate" }, { - "_id": "68443b95e1ca79d35b37e538", + "_id": "68443f5a105b07028342318e", "_tpl": "6570e025615f54368b04fcb0", "parentId": "6808b1a5c25caf3a4305d532", "slotId": "Soft_armor_front" }, { - "_id": "68443b95559f195a4119581f", + "_id": "68443f5a43a3bce0ac18efa8", "_tpl": "6570e0610b57c03ec90b96ef", "parentId": "6808b1a5c25caf3a4305d532", "slotId": "Soft_armor_back" @@ -5095,6 +5269,24 @@ "parentId": "6808b1a6c25caf3a4305d58c", "slotId": "Back_plate" }, + { + "_id": "68443f5a002c9d8d5bdc97f9", + "_tpl": "6570e83223c1f638ef0b0ede", + "parentId": "6808b1a6c25caf3a4305d58c", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443f5ac430343763e1ff97", + "_tpl": "6570e87c23c1f638ef0b0ee2", + "parentId": "6808b1a6c25caf3a4305d58c", + "slotId": "Soft_armor_back" + }, + { + "_id": "68443f5a8a2e2874f4cca6ac", + "_tpl": "6570e90b3a5689d85f08db97", + "parentId": "6808b1a6c25caf3a4305d58c", + "slotId": "Groin" + }, { "_id": "6808b1a3c25caf3a4305d326", "_tpl": "67ab4b2d6f7ae4aa550bbcf6", @@ -5118,6 +5310,18 @@ "parentId": "6808b1a3c25caf3a4305d326", "slotId": "Back_plate" }, + { + "_id": "68443f5a614bfd290f63dcbe", + "_tpl": "6575bc88c6700bd6b40e8a57", + "parentId": "6808b1a3c25caf3a4305d326", + "slotId": "Soft_armor_front" + }, + { + "_id": "68443f5a43515340e25e5e75", + "_tpl": "6575bca0dc9932aed601c5d7", + "parentId": "6808b1a3c25caf3a4305d326", + "slotId": "Soft_armor_back" + }, { "_id": "6808b1a4c25caf3a4305d4aa", "_tpl": "67af41dd1eb308667602db4a",