diff --git a/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs b/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs
index 0ad314fa..586cd55b 100644
--- a/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs
+++ b/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs
@@ -128,14 +128,10 @@ public class CustomizationController(
/// true if already purchased
protected bool OutfitAlreadyPurchased(object suitId, string sessionId)
{
- var suits = _saveServer.GetProfile(sessionId).Suits;
+ var fullProfile = _profileHelper.GetFullProfile(sessionId);
- if (suits is null || suits.Count == 0)
- {
- return false;
- }
-
- return suits.Contains(suitId);
+ // Check if clothing can be found by id
+ return fullProfile.CustomisationUnlocks.Exists(customisation => Equals(customisation.Id, suitId));
}
///
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs
index 5850172d..d8f487c6 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs
@@ -230,21 +230,23 @@ public class TraderHelper(
///
/// Add a list of suit ids to a profiles suit list, no duplicates
///
- /// Profile to add to
- /// Suit Ids to add
- protected void AddSuitsToProfile(SptProfile fullProfile, List suitIds)
+ /// Profile to add clothing to
+ /// Clothing Ids to add to profile
+ public void AddSuitsToProfile(SptProfile fullProfile, List clothingIds)
{
- if (fullProfile.Suits is null)
- {
- fullProfile.Suits = [];
- }
+ fullProfile.CustomisationUnlocks ??= [];
- foreach (var suitId in suitIds)
- // Don't add dupes
+ foreach (var suitId in clothingIds)
{
- if (!fullProfile.Suits.Contains(suitId))
+ if (!fullProfile.CustomisationUnlocks.Exists((customisation) => customisation.Id == suitId))
{
- fullProfile.Suits.Add(suitId);
+ // Clothing item doesn't exist in profile, add it
+ fullProfile.CustomisationUnlocks.Add(new CustomisationStorage
+ {
+ Id = suitId,
+ Source = CustomisationSource.UNLOCKED_IN_GAME,
+ Type = CustomisationType.SUITE
+ });
}
}
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/CustomisationStorage.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/CustomisationStorage.cs
index 69927900..2591680d 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/CustomisationStorage.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/CustomisationStorage.cs
@@ -6,7 +6,7 @@ public record CustomisationStorage
{
// Customisation.json/itemId
[JsonPropertyName("id")]
- public string? Id
+ public string Id
{
get;
set;
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs
index 7647084f..c1db3aaa 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs
@@ -24,8 +24,9 @@ public record SptProfile
}
///
- /// Clothing purchases
+ /// No longer used as of 4.0.0
///
+ [Obsolete("Replaced with CustomisationUnlocks")]
[JsonPropertyName("suits")]
public List? Suits
{
@@ -95,6 +96,9 @@ public record SptProfile
set;
}
+ ///
+ /// Stores profile-related customisation, e.g. clothing / hideout walls / floors
+ ///
[JsonPropertyName("customisationUnlocks")]
public List? CustomisationUnlocks
{
diff --git a/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs b/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs
index 0ac248e4..9752fa38 100644
--- a/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs
+++ b/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs
@@ -43,10 +43,10 @@ public class CreateProfileService(
public string CreateProfile(string sessionId, ProfileCreateRequestData request)
{
var account = _cloner.Clone(_saveServer.GetProfile(sessionId));
- var profileTemplate = _cloner.Clone(
+ var profileTemplateClone = _cloner.Clone(
_databaseService.GetProfiles()?.GetByJsonProp(account.ProfileInfo.Edition)?.GetByJsonProp(request.Side.ToLower())
);
- var pmcData = profileTemplate.Character;
+ var pmcData = profileTemplateClone.Character;
// Delete existing profile
DeleteProfileBySessionId(sessionId);
@@ -113,9 +113,8 @@ public class CreateProfileService(
PmcData = pmcData,
ScavData = new PmcData()
},
- Suits = profileTemplate.Suits,
- UserBuildData = profileTemplate.UserBuilds,
- DialogueRecords = profileTemplate.Dialogues,
+ UserBuildData = profileTemplateClone.UserBuilds,
+ DialogueRecords = profileTemplateClone.Dialogues,
SptData = _profileHelper.GetDefaultSptDataObject(),
VitalityData = new Vitality(),
InraidData = new Inraid(),
@@ -127,6 +126,8 @@ public class CreateProfileService(
AddCustomisationUnlocksToProfile(profileDetails);
+ _traderHelper.AddSuitsToProfile(profileDetails, profileTemplateClone.Suits);
+
_profileFixerService.CheckForAndFixPmcProfileIssues(profileDetails.CharacterData.PmcData);
if (profileDetails.CharacterData.PmcData.Achievements.Count > 0)
@@ -176,13 +177,13 @@ public class CreateProfileService(
_saveServer.AddProfile(profileDetails);
- if (profileTemplate.Trader.SetQuestsAvailableForStart ?? false)
+ if (profileTemplateClone.Trader.SetQuestsAvailableForStart ?? false)
{
_questHelper.AddAllQuestsToProfile(profileDetails.CharacterData.PmcData, [QuestStatusEnum.AvailableForStart]);
}
// Profile is flagged as wanting quests set to ready to hand in and collect rewards
- if (profileTemplate.Trader.SetQuestsAvailableForFinish ?? false)
+ if (profileTemplateClone.Trader.SetQuestsAvailableForFinish ?? false)
{
_questHelper.AddAllQuestsToProfile(
profileDetails.CharacterData.PmcData,
diff --git a/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs b/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs
index 29ec207e..21aae322 100644
--- a/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs
+++ b/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs
@@ -650,13 +650,18 @@ public class ProfileFixerService(
}
var clothingDb = _databaseService.GetTemplates().Customization;
- foreach (var suitId in fullProfile.Suits.Where(suitId => !clothingDb.ContainsKey(suitId)))
+ foreach (var clothingItem in fullProfile.CustomisationUnlocks.Where(customisation => customisation.Type == CustomisationType.SUITE))
{
- _logger.Error(_localisationService.GetText("fixer-clothing_item_found", suitId));
- if (_coreConfig.Fixes.RemoveModItemsFromProfile)
+ if (!clothingDb.ContainsKey(clothingItem.Id))
{
- fullProfile.Suits.Remove(suitId);
- _logger.Warning($"Non-default suit purchase: {suitId} removed from profile");
+ // Item in profile not found in db, not good
+ _logger.Error(_localisationService.GetText("fixer-clothing_item_found", clothingItem));
+
+ if (_coreConfig.Fixes.RemoveModItemsFromProfile)
+ {
+ fullProfile.CustomisationUnlocks.Remove(clothingItem);
+ _logger.Warning($"Non-default clothing purchase: {clothingItem} removed from profile");
+ }
}
}