diff --git a/Core/Controllers/CustomizationController.cs b/Core/Controllers/CustomizationController.cs
index 10b34c00..cdcc8071 100644
--- a/Core/Controllers/CustomizationController.cs
+++ b/Core/Controllers/CustomizationController.cs
@@ -1,25 +1,71 @@
using Core.Annotations;
+using Core.Helpers;
using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.Customization;
using Core.Models.Eft.Hideout;
using Core.Models.Eft.ItemEvent;
using Core.Models.Eft.Profile;
+using Core.Models.Enums;
+using Core.Routers;
+using Core.Servers;
+using Core.Services;
+using Core.Utils.Cloners;
+using ILogger = Core.Models.Utils.ILogger;
+using Product = Core.Models.Eft.ItemEvent.Product;
namespace Core.Controllers;
[Injectable]
public class CustomizationController
{
+ protected ILogger _logger;
+ protected EventOutputHolder _eventOutputHolder;
+ protected DatabaseService _databaseService;
+ protected SaveServer _saveServer;
+ protected LocalisationService _localisationService;
+ protected ProfileHelper _profileHelper;
+ protected ICloner _cloner;
+
+ public CustomizationController
+ (
+ ILogger logger,
+ EventOutputHolder eventOutputHolder,
+ DatabaseService databaseService,
+ SaveServer saveServer,
+ LocalisationService localisationService,
+ ProfileHelper profileHelper,
+ ICloner cloner
+ )
+ {
+ _logger = logger;
+ _eventOutputHolder = eventOutputHolder;
+ _databaseService = databaseService;
+ _saveServer = saveServer;
+ _localisationService = localisationService;
+ _profileHelper = profileHelper;
+ _cloner = cloner;
+ }
+
///
/// Get purchasable clothing items from trader that match players side (usec/bear)
///
/// trader to look up clothing for
/// Session id
/// Suit array
- public Suit GetTraderSuits(string traderId, string sessionId)
+ public List GetTraderSuits(string traderId, string sessionId)
{
- throw new NotImplementedException();
+ var pmcData = _profileHelper.GetPmcProfile(sessionId);
+ var clothing = _databaseService.GetCustomization();
+ var suits = _databaseService.GetTrader(traderId).Suits;
+
+ var matchingSuits = suits.Where(s => clothing.ContainsKey(s.SuiteId)).ToList();
+ matchingSuits = matchingSuits?.Where(s => clothing[s.SuiteId].Properties.Side.Contains(pmcData.Info.Side)).ToList();
+
+ if (matchingSuits == null)
+ throw new Exception(_localisationService.GetText("customisation-unable_to_get_trader_suits", traderId));
+
+ return matchingSuits;
}
///
@@ -35,7 +81,41 @@ public class CustomizationController
BuyClothingRequestData buyClothingRequest,
string sessionId)
{
- throw new NotImplementedException();
+ var output = _eventOutputHolder.GetOutput(sessionId);
+
+ var traderOffer = GetTraderClothingOffer(sessionId, buyClothingRequest.Offer);
+ if (traderOffer == null)
+ {
+ _logger.Error(_localisationService.GetText("customisation-unable_to_find_suit_by_id", buyClothingRequest.Offer));
+ return output;
+ }
+
+ var suitId = traderOffer.SuiteId;
+ if (OutfitAlreadyPurchased(suitId, sessionId))
+ {
+ var suitDetails = _databaseService.GetCustomization()[suitId];
+ _logger.Error(_localisationService.GetText("customisation-item_already_purchased", new
+ {
+ ItemId = suitDetails.Id,
+ ItemName = suitDetails.Name,
+ }));
+ }
+
+ return output;
+ }
+
+ private bool OutfitAlreadyPurchased(object suitId, string sessionId)
+ {
+ return _saveServer.GetProfile(sessionId).Suits.Contains(suitId);
+ }
+
+ private Suit GetTraderClothingOffer(string sessionId, string? offerId)
+ {
+ var foundSuit = GetAllTraderSuits(sessionId).FirstOrDefault(s => s.Id == offerId);
+ if (foundSuit == null)
+ throw new Exception(_localisationService.GetText("customisation-unable_to_find_suit_with_id", offerId));
+
+ return foundSuit;
}
///
@@ -45,13 +125,13 @@ public class CustomizationController
/// Player profile
/// Clothing purchased
/// Client response
- private void PayForClothingItems(
- string sessionId,
- PmcData pmcData,
- List itemsToPayForClothingWith,
+ private void PayForClothingItems(string sessionId, PmcData pmcData, List itemsToPayForClothingWith,
ItemEventRouterResponse output)
{
- throw new NotImplementedException();
+ foreach (var inventoryItemToProcess in itemsToPayForClothingWith)
+ {
+ PayForClothingItem(sessionId, pmcData, inventoryItemToProcess, output);
+ }
}
///
@@ -61,13 +141,65 @@ public class CustomizationController
/// Player profile
/// Payment details
/// Client response
- private void PayForClothingItem(
- string sessionId,
- PmcData pmcData,
- PaymentItemForClothing paymentItemDetails,
- ItemEventRouterResponse output)
+ private void PayForClothingItem(string sessionId, PmcData pmcData, PaymentItemForClothing paymentItemDetails, ItemEventRouterResponse output)
{
- throw new NotImplementedException();
+ var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(x => x.Id == paymentItemDetails.Id);
+ if (inventoryItem == null)
+ {
+ _logger.Error(_localisationService.GetText("customisation-unable_to_find_clothing_item_in_inventory", paymentItemDetails.Id));
+ return;
+ }
+
+ if (paymentItemDetails.Del != null)
+ {
+ output.ProfileChanges[sessionId].Items.DeletedItems.Add(new Product
+ {
+ Id = inventoryItem.Id,
+ Template = inventoryItem.Template,
+ ParentId = inventoryItem.ParentId,
+ SlotId = inventoryItem.SlotId,
+ Location = (ItemLocation)inventoryItem.Location,
+ Upd = inventoryItem.Upd
+ });
+
+ pmcData.Inventory.Items.Remove(inventoryItem);
+ }
+
+ if (inventoryItem.Upd == null)
+ inventoryItem.Upd = new() { StackObjectsCount = 1 };
+
+ if (inventoryItem.Upd.StackObjectsCount == null)
+ inventoryItem.Upd.StackObjectsCount = 1;
+
+ if (inventoryItem.Upd.StackObjectsCount == paymentItemDetails.Count)
+ {
+ output.ProfileChanges[sessionId].Items.DeletedItems.Add(new Product
+ {
+ Id = inventoryItem.Id,
+ Template = inventoryItem.Template,
+ ParentId = inventoryItem.ParentId,
+ SlotId = inventoryItem.SlotId,
+ Location = (ItemLocation)inventoryItem.Location,
+ Upd = inventoryItem.Upd
+ });
+
+ pmcData.Inventory.Items.Remove(inventoryItem);
+ return;
+ }
+
+ if (inventoryItem.Upd.StackObjectsCount > paymentItemDetails.Count)
+ {
+ inventoryItem.Upd.StackObjectsCount -= paymentItemDetails.Count;
+ output.ProfileChanges[sessionId].Items.ChangedItems.Add(new Product
+ {
+ Id = inventoryItem.Id,
+ Template = inventoryItem.Template,
+ ParentId = inventoryItem.ParentId,
+ SlotId = inventoryItem.SlotId,
+ Location = (ItemLocation)inventoryItem.Location,
+ Upd = inventoryItem.Upd
+ });
+ }
}
///
@@ -77,7 +209,16 @@ public class CustomizationController
///
private List GetAllTraderSuits(string sessionId)
{
- throw new NotImplementedException();
+ var traders = _databaseService.GetTraders();
+ var result = new List();
+
+ foreach (var trader in traders)
+ {
+ if (trader.Value.Base.CustomizationSeller.Value)
+ result.AddRange(GetTraderSuits(trader.Key, sessionId));
+ }
+
+ return result;
}
///
@@ -86,11 +227,9 @@ public class CustomizationController
///
///
///
- public HideoutCustomisation GetHideoutCustomisation(
- string sessionId,
- EmptyRequestData info)
+ public HideoutCustomisation GetHideoutCustomisation(string sessionId, EmptyRequestData info)
{
- throw new NotImplementedException();
+ return _databaseService.GetHideout().Customisation;
}
///
@@ -103,7 +242,79 @@ public class CustomizationController
string sessionId,
EmptyRequestData info)
{
- throw new NotImplementedException();
+ var customisationResultsClone = _cloner.Clone(_databaseService.GetTemplates().CustomisationStorage);
+
+ var profile = _profileHelper.GetFullProfile(sessionId);
+ switch (GetGameEdition(profile))
+ {
+ case GameEditions.EDGE_OF_DARKNESS:
+ customisationResultsClone.Add(new ()
+ {
+ Id = "6746fd09bafff85008048838",
+ Source = "default",
+ Type = "dogTag"
+ });
+ customisationResultsClone.Add(new ()
+ {
+ Id = "67471938bafff850080488b7",
+ Source = "default",
+ Type = "dogTag"
+ });
+ break;
+ case GameEditions.UNHEARD:
+ customisationResultsClone.Add(new ()
+ {
+ Id = "6746fd09bafff85008048838",
+ Source = "default",
+ Type = "dogTag"
+ });
+ customisationResultsClone.Add(new ()
+ {
+ Id = "67471938bafff850080488b7",
+ Source = "default",
+ Type = "dogTag"
+ });
+ customisationResultsClone.Add(new ()
+ {
+ Id = "67471928d17d6431550563b5",
+ Source = "default",
+ Type = "dogTag"
+ });
+ customisationResultsClone.Add(new ()
+ {
+ Id = "6747193f170146228c0d2226",
+ Source = "default",
+ Type = "dogTag"
+ });
+ break;
+ default:
+ throw new Exception($"Unknown game edition given from profile {profile}");
+ }
+
+ var prestigeLevel = profile.CharacterData.PmcData.Info.PrestigeLevel;
+ if (prestigeLevel != null)
+ {
+ if (prestigeLevel >= 1)
+ {
+ customisationResultsClone.Add(new ()
+ {
+ Id = "674dbf593bee1152d407f005",
+ Source = "default",
+ Type = "dogTag"
+ });
+ }
+ if (prestigeLevel >= 2)
+ {
+ customisationResultsClone.Add(new ()
+ {
+ Id = "675dcfea7ae1a8792107ca99",
+ Source = "default",
+ Type = "dogTag"
+ });
+ }
+ }
+
+ return customisationResultsClone;
}
///
@@ -113,7 +324,22 @@ public class CustomizationController
///
private string GetGameEdition(SptProfile profile)
{
- throw new NotImplementedException();
+ var edition = profile.CharacterData.PmcData.Info.GameVersion;
+ if (edition == null)
+ {
+ var launcherEdition = profile.ProfileInfo.Edition;
+ switch (launcherEdition.ToLower())
+ {
+ case "edge of darkness":
+ return GameEditions.EDGE_OF_DARKNESS;
+ case "unheard":
+ return GameEditions.UNHEARD;
+ default:
+ return GameEditions.STANDARD;
+ }
+ }
+
+ return edition;
}
///
@@ -123,12 +349,25 @@ public class CustomizationController
///
///
///
- public ItemEventRouterResponse SetClothing(
- string sessionId,
- CustomizationSetRequest request,
- PmcData pmcData)
+ public ItemEventRouterResponse SetClothing(string sessionId, CustomizationSetRequest request, PmcData pmcData)
{
- throw new NotImplementedException();
+ foreach (var customisation in request.Customizations)
+ {
+ switch (customisation.Id)
+ {
+ case "dogTag":
+ pmcData.Customization.DogTag = customisation.Id;
+ break;
+ case "suite":
+ ApplyClothingItemToProfile(customisation, pmcData);
+ break;
+ default:
+ _logger.Error($"Unhandled customisation type: {customisation.Type}");
+ break;
+ }
+ }
+
+ return _eventOutputHolder.GetOutput(sessionId);
}
///
@@ -136,10 +375,26 @@ public class CustomizationController
///
/// Suit to apply to profile
/// Profile to update
- private void ApplyClothingItemToProfile(
- CustomizationSetOption customization,
- PmcData pmcData)
+ private void ApplyClothingItemToProfile(CustomizationSetOption customisation, PmcData pmcData)
{
- throw new NotImplementedException();
+ var dbSuit = _databaseService.GetCustomization()[customisation.Id];
+ if (dbSuit == null)
+ {
+ _logger.Error($"Unable to find suit customisation id: {customisation.Id}, cannot apply clothing to player profile: {pmcData.Id}");
+ return;
+ }
+
+ if (dbSuit.Parent == "5cd944d01388ce000a659df9")
+ {
+ pmcData.Customization.Body = dbSuit.Properties.Body;
+ pmcData.Customization.Hands = dbSuit.Properties.Hands;
+
+ return;
+ }
+
+ if (dbSuit.Parent == "5cd944ca1388ce03a44dc2a4")
+ {
+ pmcData.Customization.Feet = dbSuit.Properties.Feet;
+ }
}
}
diff --git a/Core/Controllers/GameController.cs b/Core/Controllers/GameController.cs
index 08cbfb46..38b8d18a 100644
--- a/Core/Controllers/GameController.cs
+++ b/Core/Controllers/GameController.cs
@@ -1,10 +1,15 @@
using Core.Annotations;
+using Core.Context;
+using Core.Helpers;
using Core.Models.Eft.Common;
using Core.Models.Eft.Game;
using Core.Models.Eft.Profile;
using Core.Models.Enums;
using Core.Models.Spt.Config;
using Core.Servers;
+using Core.Services;
+using Core.Utils;
+using Core.Utils.Cloners;
using ILogger = Core.Models.Utils.ILogger;
namespace Core.Controllers;
@@ -12,19 +17,86 @@ namespace Core.Controllers;
[Injectable]
public class GameController
{
- private readonly ConfigServer _configServer;
private readonly ILogger _logger;
+ private readonly ConfigServer _configServer;
+ private readonly DatabaseService _databaseService;
+ private readonly TimeUtil _timeUtil;
+ // private readonly PreSptModLoader _preSptModLoader;
+ private readonly HttpServerHelper _httpServerHelper;
+ private readonly InventoryHelper _inventoryHelper;
+ private readonly RandomUtil _randomUtil;
+ private readonly HideoutHelper _hideoutHelper;
+ private readonly ProfileHelper _profileHelper;
+ private readonly ProfileFixerService _profileFixerService;
+ private readonly LocalisationService _localisationService;
+ private readonly PostDbLoadService _postDbLoadService;
+ private readonly CustomLocationWaveService _customLocationWaveService;
+ private readonly OpenZoneService _openZoneService;
+ private readonly SeasonalEventService _seasonalEventService;
+ private readonly ItemBaseClassService _itemBaseClassService;
+ private readonly GiftService _giftService;
+ private readonly RaidTimeAdjustmentService _raidTimeAdjustmentService;
+ private readonly ProfileActivityService _profileActivityService;
+ private readonly ApplicationContext _applicationContext;
+ private readonly ICloner _cloner;
+
private readonly CoreConfig _coreConfig;
-
+ private readonly HttpConfig _httpConfig;
+ private readonly RagfairConfig _ragfairConfig;
+ private readonly HideoutConfig _hideoutConfig;
+ private readonly BotConfig _botConfig;
public GameController(
ILogger logger,
- ConfigServer configServer)
+ ConfigServer configServer,
+ DatabaseService databaseService,
+ TimeUtil timeUtil,
+ HttpServerHelper httpServerHelper,
+ InventoryHelper inventoryHelper,
+ RandomUtil randomUtil,
+ HideoutHelper hideoutHelper,
+ ProfileHelper profileHelper,
+ ProfileFixerService profileFixerService,
+ LocalisationService localisationService,
+ PostDbLoadService postDbLoadService,
+ CustomLocationWaveService customLocationWaveService,
+ OpenZoneService openZoneService,
+ SeasonalEventService seasonalEventService,
+ ItemBaseClassService itemBaseClassService,
+ GiftService giftService,
+ RaidTimeAdjustmentService raidTimeAdjustmentService,
+ ProfileActivityService profileActivityService,
+ ApplicationContext applicationContext,
+ ICloner cloner
+ )
{
_logger = logger;
_configServer = configServer;
+ _databaseService = databaseService;
+ _timeUtil = timeUtil;
+ _httpServerHelper = httpServerHelper;
+ _inventoryHelper = inventoryHelper;
+ _randomUtil = randomUtil;
+ _hideoutHelper = hideoutHelper;
+ _profileHelper = profileHelper;
+ _profileFixerService = profileFixerService;
+ _localisationService = localisationService;
+ _postDbLoadService = postDbLoadService;
+ _customLocationWaveService = customLocationWaveService;
+ _openZoneService = openZoneService;
+ _seasonalEventService = seasonalEventService;
+ _itemBaseClassService = itemBaseClassService;
+ _giftService = giftService;
+ _raidTimeAdjustmentService = raidTimeAdjustmentService;
+ _profileActivityService = profileActivityService;
+ _applicationContext = applicationContext;
+ _cloner = cloner;
_coreConfig = configServer.GetConfig(ConfigTypes.CORE);
+ _httpConfig = configServer.GetConfig(ConfigTypes.HTTP);
+ _ragfairConfig = configServer.GetConfig(ConfigTypes.RAGFAIR);
+ _hideoutConfig = configServer.GetConfig(ConfigTypes.HIDEOUT);
+ _botConfig = configServer.GetConfig(ConfigTypes.BOT);
}
///
@@ -34,11 +106,93 @@ public class GameController
///
///
///
- public void GameStart(
- string url,
- EmptyRequestData info,
- string sessionId,
- long startTimeStampMs)
+ public void GameStart(string url, EmptyRequestData info, string sessionId, long startTimeStampMs)
+ {
+ // Store client start time in app context
+ _applicationContext.AddValue(ContextVariableType.CLIENT_START_TIMESTAMP, $"{sessionId}_{startTimeStampMs}");
+
+ _profileActivityService.SetActivityTimestamp(sessionId);
+
+ // repeatableQuests are stored by in profile.Quests due to the responses of the client (e.g. Quests in
+ // offraidData). Since we don't want to clutter the Quests list, we need to remove all completed (failed or
+ // successful) repeatable quests. We also have to remove the Counters from the repeatableQuests
+ if (sessionId != null)
+ {
+ var fullProfile = _profileHelper.GetFullProfile(sessionId);
+ if (fullProfile.ProfileInfo.IsWiped.Value)
+ return;
+
+ if (fullProfile.SptData.Migrations == null)
+ fullProfile.SptData.Migrations = new();
+
+ if (fullProfile.FriendProfileIds == null)
+ fullProfile.FriendProfileIds = new();
+
+ if (fullProfile.SptData.Version.Contains("3.9.") && !fullProfile.SptData.Migrations.Any(m => m.Key == "39x"))
+ {
+ _inventoryHelper.ValidateInventoryUsesMongoIds(fullProfile.CharacterData.PmcData.Inventory.Items);
+ Migrate39xProfile(fullProfile);
+
+ // flag as migrated
+ fullProfile.SptData.Migrations.Add("39x", _timeUtil.GetTimeStamp());
+ _logger.Success($"Migration of 3.9.x profile: {fullProfile.ProfileInfo.Username} completed successfully");
+ }
+
+ // with our method of converting type from array for this prop, we *might* not need this?
+ // if (Array.isArray(fullProfile.characters.pmc.WishList)) {
+ // fullProfile.characters.pmc.WishList = {};
+ // }
+ //
+ // if (Array.isArray(fullProfile.characters.scav.WishList)) {
+ // fullProfile.characters.scav.WishList = {};
+ // }
+
+ if (fullProfile.DialogueRecords != null)
+ _profileFixerService.CheckForAndFixDialogueAttachments(fullProfile);
+
+ _logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo.Username}");
+
+ var pmcProfile = fullProfile.CharacterData.PmcData;
+
+ if (_coreConfig.Fixes.FixProfileBreakingInventoryItemIssues)
+ _profileFixerService.FixProfileBreakingInventoryItemIssues(pmcProfile);
+
+ if (pmcProfile.Health != null)
+ UpdateProfileHealthValues(pmcProfile);
+
+ if (pmcProfile.Inventory != null)
+ {
+ SendPraporGiftsToNewProfiles(pmcProfile);
+ _profileFixerService.CheckForOrphanedModdedItems(sessionId, fullProfile);
+ }
+
+ _profileFixerService.CheckForAndRemoveInvalidTraders(fullProfile);
+ _profileFixerService.CheckForAndFixPmcProfileIssues(pmcProfile);
+
+ if (pmcProfile.Hideout != null)
+ {
+ _profileFixerService.AddMissingHideoutBonusesToProfile(pmcProfile);
+ _hideoutHelper.SetHideoutImprovementsToCompleted(pmcProfile);
+ _hideoutHelper.UnlockHideoutWallInProfile(pmcProfile);
+ }
+
+ LogProfileDetails(fullProfile);
+ SaveActiveModsToProfile(fullProfile);
+
+ if (pmcProfile.Info != null)
+ {
+ AddPlayerToPmcNames(pmcProfile);
+ CheckForAndRemoveUndefinedDialogues(fullProfile);
+ }
+
+ if (pmcProfile.Skills.Common != null)
+ WarnOnActiveBotReloadSkill(pmcProfile);
+
+ _seasonalEventService.GivePlayerSeasonalGifts(sessionId);
+ }
+ }
+
+ private void Migrate39xProfile(SptProfile fullProfile)
{
throw new NotImplementedException();
}
@@ -210,6 +364,6 @@ public class GameController
public void Load()
{
- return; // TODO: actually implement
+ _postDbLoadService.PerformPostDbLoadActions();
}
}
diff --git a/Core/Controllers/LauncherController.cs b/Core/Controllers/LauncherController.cs
index 2c44cc39..c154717a 100644
--- a/Core/Controllers/LauncherController.cs
+++ b/Core/Controllers/LauncherController.cs
@@ -106,7 +106,7 @@ public class LauncherController
{
foreach (var sessionID in _saveServer.GetProfiles()) {
var account = _saveServer.GetProfile(sessionID.Key).ProfileInfo;
- if (info.Username == account.UserName) {
+ if (info.Username == account.Username) {
return sessionID.Key;
}
}
@@ -117,7 +117,7 @@ public class LauncherController
public string Register(RegisterData info)
{
foreach (var sessionID in _saveServer.GetProfiles()) {
- if (info.Username == _saveServer.GetProfile(sessionID.Key).ProfileInfo.UserName) {
+ if (info.Username == _saveServer.GetProfile(sessionID.Key).ProfileInfo.Username) {
return "";
}
}
@@ -133,7 +133,7 @@ public class LauncherController
ProfileId = profileId,
ScavengerId = scavId,
Aid = _hashUtil.GenerateAccountId(),
- UserName = info.Username,
+ Username = info.Username,
Password = info.Password,
IsWiped = true,
Edition = info.Edition,
@@ -167,7 +167,7 @@ public class LauncherController
var sessionID = Login(info);
if (!string.IsNullOrEmpty(sessionID)) {
- _saveServer.GetProfile(sessionID).ProfileInfo.UserName = info.Change;
+ _saveServer.GetProfile(sessionID).ProfileInfo.Username = info.Change;
}
return sessionID;
diff --git a/Core/Controllers/ProfileController.cs b/Core/Controllers/ProfileController.cs
index 0cfbfc2b..8485f208 100644
--- a/Core/Controllers/ProfileController.cs
+++ b/Core/Controllers/ProfileController.cs
@@ -107,7 +107,7 @@ public class ProfileController
{
return new MiniProfile()
{
- Username = profile.ProfileInfo?.UserName ?? "",
+ Username = profile.ProfileInfo?.Username ?? "",
Nickname = "unknown",
Side = "unknown",
CurrentLevel = 0,
@@ -125,7 +125,7 @@ public class ProfileController
var nextlvl = _profileHelper.GetExperience((int)(currlvl + 1));
return new MiniProfile()
{
- Username = profile.ProfileInfo.UserName,
+ Username = profile.ProfileInfo.Username,
Nickname = pmc.Info.Nickname,
Side = pmc.Info.Side,
CurrentLevel = (int)(pmc.Info.Level),
@@ -167,7 +167,7 @@ public class ProfileController
pmcData.Savage = account.ScavengerId;
pmcData.SessionId = sessionID;
pmcData.Info.Nickname = info.Nickname;
- pmcData.Info.LowerNickname = account.UserName.ToLower();
+ pmcData.Info.LowerNickname = account.Username.ToLower();
pmcData.Info.RegistrationDate = _timeUtil.GetTimeStamp();
pmcData.Info.Voice = _databaseService.GetCustomization()[info.VoiceId].Name;
pmcData.Stats = _profileHelper.GetDefaultCounters();
diff --git a/Core/Helpers/PresetHelper.cs b/Core/Helpers/PresetHelper.cs
index 95b85d8a..08bee62d 100644
--- a/Core/Helpers/PresetHelper.cs
+++ b/Core/Helpers/PresetHelper.cs
@@ -77,12 +77,12 @@ public class PresetHelper
_itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia)).ToDictionary();
}
- return _defaultWeaponPresets;
+ return _defaultEquipmentPresets;
}
public bool IsPreset(string id)
{
- throw new NotImplementedException();
+ return _databaseService.GetGlobals().ItemPresets.ContainsKey(id);
}
/**
diff --git a/Core/Models/Eft/Common/Tables/Item.cs b/Core/Models/Eft/Common/Tables/Item.cs
index e018f0ad..f4e885f5 100644
--- a/Core/Models/Eft/Common/Tables/Item.cs
+++ b/Core/Models/Eft/Common/Tables/Item.cs
@@ -23,7 +23,7 @@ public class Item
public string? Desc { get; set; }
[JsonPropertyName("upd")]
- public Upd? Update { get; set; }
+ public Upd? Upd { get; set; }
}
public class ItemLocation
diff --git a/Core/Models/Eft/Common/Tables/TemplateItem.cs b/Core/Models/Eft/Common/Tables/TemplateItem.cs
index 4b2ec2ed..6b2e2ef7 100644
--- a/Core/Models/Eft/Common/Tables/TemplateItem.cs
+++ b/Core/Models/Eft/Common/Tables/TemplateItem.cs
@@ -1350,6 +1350,9 @@ public class Props
[JsonPropertyName("Hands")]
public string? Hands { get; set; }
+ [JsonPropertyName("Feet")]
+ public string? Feet { get; set; }
+
[JsonExtensionData]
public Dictionary OtherProperties { get; set; }
}
diff --git a/Core/Models/Eft/Profile/SptProfile.cs b/Core/Models/Eft/Profile/SptProfile.cs
index 265070eb..44ff731e 100644
--- a/Core/Models/Eft/Profile/SptProfile.cs
+++ b/Core/Models/Eft/Profile/SptProfile.cs
@@ -71,7 +71,7 @@ public class Info
public int? Aid { get; set; }
[JsonPropertyName("username")]
- public string? UserName { get; set; }
+ public string? Username { get; set; }
[JsonPropertyName("password")]
public string? Password { get; set; }
diff --git a/Core/Models/Enums/GameEditions.cs b/Core/Models/Enums/GameEditions.cs
new file mode 100644
index 00000000..a89d3a4e
--- /dev/null
+++ b/Core/Models/Enums/GameEditions.cs
@@ -0,0 +1,11 @@
+namespace Core.Models.Enums;
+
+public class GameEditions
+{
+ public const string STANDARD = "standard";
+ public const string LEFT_BEHIND = "left_behind";
+ public const string PREPARE_FOR_ESCAPE = "prepare_for_escape";
+ public const string EDGE_OF_DARKNESS = "edge_of_darkness";
+ public const string UNHEARD = "unheard_edition";
+ public const string TOURNAMENT = "tournament_live";
+}
diff --git a/Core/Routers/Dynamic/CustomizationDynamicRouter.cs b/Core/Routers/Dynamic/CustomizationDynamicRouter.cs
index cd91d78b..73f84379 100644
--- a/Core/Routers/Dynamic/CustomizationDynamicRouter.cs
+++ b/Core/Routers/Dynamic/CustomizationDynamicRouter.cs
@@ -18,7 +18,7 @@ public class CustomizationDynamicRouter : DynamicRouter
jsonUtil,
[
new RouteAction(
- "",
+ "/client/trading/customization/",
(
url,
info,