Added CreateProfileService Implementation

This commit is contained in:
Chomp
2025-01-12 23:15:55 +00:00
parent abba3f915d
commit 61ebc570e4
4 changed files with 361 additions and 280 deletions
+5 -244
View File
@@ -2,8 +2,6 @@ using Core.Annotations;
using Core.Generators;
using Core.Helpers;
using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.ItemEvent;
using Core.Models.Eft.Launcher;
using Core.Models.Eft.Profile;
using Core.Models.Enums;
@@ -28,6 +26,7 @@ public class ProfileController
protected ItemHelper _itemHelper;
protected ProfileFixerService _profileFixerService;
protected LocalisationService _localisationService;
private readonly CreateProfileService _createProfileService;
protected SeasonalEventService _seasonalEventService;
@@ -51,6 +50,7 @@ public class ProfileController
ItemHelper itemHelper,
ProfileFixerService profileFixerService,
LocalisationService localisationService,
CreateProfileService createProfileService,
SeasonalEventService seasonalEventService,
// TODO: MailSendService mailSendService,
PlayerScavGenerator playerScavGenerator,
@@ -71,6 +71,7 @@ public class ProfileController
_itemHelper = itemHelper;
_profileFixerService = profileFixerService;
_localisationService = localisationService;
_createProfileService = createProfileService;
_seasonalEventService = seasonalEventService;
_playerScavGenerator = playerScavGenerator;
_eventOutputHolder = eventOutputHolder;
@@ -154,249 +155,9 @@ public class ProfileController
* @param sessionID Player id
* @returns Profiles _id value
*/
public string CreateProfile(ProfileCreateRequestData info, string sessionID)
public string CreateProfile(ProfileCreateRequestData request, string sessionID)
{
var account = _saveServer.GetProfile(sessionID).ProfileInfo;
var profileTemplate = _cloner.Clone(_databaseService.GetProfiles()?[account.Edition]?[info.Side.ToLower()]);
var pmcData = profileTemplate.Character;
// Delete existing profile
DeleteProfileBySessionId(sessionID);
// PMC
pmcData.Id = account.ProfileId;
pmcData.Aid = account.Aid;
pmcData.Savage = account.ScavengerId;
pmcData.SessionId = sessionID;
pmcData.Info.Nickname = info.Nickname;
pmcData.Info.LowerNickname = account.Username.ToLower();
pmcData.Info.RegistrationDate = _timeUtil.GetTimeStamp();
pmcData.Info.Voice = _databaseService.GetCustomization()[info.VoiceId].Name;
pmcData.Stats = _profileHelper.GetDefaultCounters();
pmcData.Info.NeedWipeOptions = [];
pmcData.Customization.Head = info.HeadId;
pmcData.Health.UpdateTime = _timeUtil.GetTimeStamp();
pmcData.Quests = [];
pmcData.Hideout.Seed = _timeUtil.GetTimeStamp() + 8 * 60 * 60 * 24 * 365; // 8 years in future why? who knows, we saw it in live
pmcData.RepeatableQuests = [];
pmcData.CarExtractCounts = new();
pmcData.CoopExtractCounts = new();
pmcData.Achievements = new();
UpdateInventoryEquipmentId(pmcData);
if (pmcData.UnlockedInfo == null)
{
pmcData.UnlockedInfo = new UnlockedInfo { UnlockedProductionRecipe = [] };
}
// Add required items to pmc stash
AddMissingInternalContainersToProfile(pmcData);
// Change item IDs to be unique
pmcData.Inventory.Items = _itemHelper.ReplaceIDs(
pmcData.Inventory.Items,
pmcData,
null,
pmcData.Inventory.FastPanel
);
// Create profile
var profileDetails = new SptProfile
{
ProfileInfo = account,
CharacterData = new Characters { PmcData = pmcData, ScavData = new() },
Suits = profileTemplate.Suits,
UserBuildData = profileTemplate.UserBuilds,
DialogueRecords = profileTemplate.Dialogues,
SptData = _profileHelper.GetDefaultSptDataObject(),
VitalityData = new(),
InraidData = new(),
InsuranceList = [],
TraderPurchases = new(),
PlayerAchievements = new(),
FriendProfileIds = [],
};
_profileFixerService.CheckForAndFixPmcProfileIssues(profileDetails.CharacterData.PmcData);
_saveServer.AddProfile(profileDetails);
if (profileTemplate.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)
{
_questHelper.AddAllQuestsToProfile(profileDetails.CharacterData.PmcData, [
QuestStatusEnum.AvailableForStart,
QuestStatusEnum.Started,
QuestStatusEnum.AvailableForFinish,
]);
// Make unused response so applyQuestReward works
ItemEventRouterResponse? response = _eventOutputHolder.GetOutput(sessionID);
// Add rewards for starting quests to profile
GivePlayerStartingQuestRewards(profileDetails, sessionID, response);
}
ResetAllTradersInProfile(sessionID);
_saveServer.GetProfile(sessionID).CharacterData.ScavData = GeneratePlayerScav(sessionID);
// Store minimal profile and reload it
_saveServer.SaveProfile(sessionID);
_saveServer.LoadProfile(sessionID);
// Completed account creation
_saveServer.GetProfile(sessionID).ProfileInfo.IsWiped = false;
_saveServer.SaveProfile(sessionID);
return pmcData.Id;
}
/**
* make profiles pmcData.Inventory.equipment unique
* @param pmcData Profile to update
*/
protected void UpdateInventoryEquipmentId(PmcData pmcData)
{
var oldEquipmentId = pmcData.Inventory.Equipment;
pmcData.Inventory.Equipment = _hashUtil.Generate();
foreach (var item in pmcData.Inventory.Items)
{
if (item.ParentId == oldEquipmentId)
{
item.ParentId = pmcData.Inventory.Equipment;
continue;
}
if (item.Id == oldEquipmentId)
{
item.Id = pmcData.Inventory.Equipment;
}
}
}
/**
* Ensure a profile has the necessary internal containers e.g. questRaidItems / sortingTable
* DOES NOT check that stash exists
* @param pmcData Profile to check
*/
protected void AddMissingInternalContainersToProfile(PmcData pmcData)
{
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.HideoutCustomizationStashId))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.HideoutCustomizationStashId,
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.SortingTable))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.SortingTable,
Template = ItemTpl.SORTINGTABLE_SORTING_TABLE,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestStashItems))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.QuestStashItems,
Template = ItemTpl.STASH_QUESTOFFLINE,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestRaidItems))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.QuestRaidItems,
Template = ItemTpl.STASH_QUESTRAID,
});
}
}
/**
* Delete a profile
* @param sessionID Id of profile to delete
*/
protected void DeleteProfileBySessionId(string sessionID)
{
if (_saveServer.GetProfiles().ContainsKey(sessionID))
{
_saveServer.DeleteProfileById(sessionID);
}
else
{
_logger.Warning(
_localisationService.GetText("profile-unable_to_find_profile_by_id_cannot_delete", sessionID)
);
}
}
/**
* Iterate over all quests in player profile, inspect rewards for the quests current state (accepted/completed)
* and send rewards to them in mail
* @param profileDetails Player profile
* @param sessionID Session id
* @param response Event router response
*/
protected void GivePlayerStartingQuestRewards(
SptProfile profileDetails,
string sessionID,
ItemEventRouterResponse response
)
{
foreach (var quest in profileDetails.CharacterData.PmcData.Quests)
{
var questFromDb = _questHelper.GetQuestFromDb(quest.QId, profileDetails.CharacterData.PmcData);
// Get messageId of text to send to player as text message in game
// Copy of code from QuestController.acceptQuest()
var messageId = _questHelper.GetMessageIdForQuestStart(
questFromDb.StartedMessageText,
questFromDb.Description
);
var itemRewards = _questRewardHelper.ApplyQuestReward(
profileDetails.CharacterData.PmcData,
quest.QId,
QuestStatusEnum.Started,
sessionID,
response
);
/* TODO:
_mailSendService.sendLocalisedNpcMessageToPlayer(
sessionID,
this.traderHelper.getTraderById(questFromDb.traderId),
MessageType.QUEST_START,
messageId,
itemRewards,
this.timeUtil.getHoursAsSeconds(100),
);
*/
}
}
/**
* For each trader reset their state to what a level 1 player would see
* @param sessionId Session id of profile to reset
*/
protected void ResetAllTradersInProfile(string sessionId)
{
foreach (var traderId in _databaseService.GetTraders().Keys)
{
_traderHelper.ResetTrader(sessionId, traderId);
}
return _createProfileService.CreateProfile(sessionID, request);
}
/**
@@ -1,4 +1,4 @@
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Core.Models.Eft.Common.Tables;
@@ -12,4 +12,32 @@ public class CustomisationStorage
[JsonPropertyName("type")]
public string? Type { get; set; }
}
}
public class CustomisationType
{
public const string SUITE = "suite";
public const string DOG_TAG = "dogTag";
public const string HEAD = "head";
public const string VOICE = "voice";
public const string GESTURE = "gesture";
public const string ENVIRONMENT = "environment";
public const string WALL = "wall";
public const string FLOOR = "floor";
public const string CEILING = "ceiling";
public const string LIGHT = "light";
public const string SHOOTING_RANGE_MARK = "shootingRangeMark";
public const string CAT = "cat";
public const string MANNEQUIN_POSE = "mannequinPose";
}
public class CustomisationSource
{
public const string QUEST = "quest";
public const string PRESTIGE = "prestige";
public const string ACHIEVEMENT = "achievement";
public const string UNLOCKED_IN_GAME = "unlockedInGame";
public const string PAID = "paid";
public const string DROP = "drop";
public const string DEFAULT = "default";
}
+4 -1
View File
@@ -1,4 +1,4 @@
using Core.Models.Eft.Common;
using Core.Models.Eft.Common;
using System.Text.Json.Serialization;
using Core.Models.Eft.Common.Tables;
using Core.Models.Enums;
@@ -47,6 +47,9 @@ public class SptProfile
/** List of friend profile IDs */
[JsonPropertyName("friends")]
public List<string>? FriendProfileIds { get; set; }
[JsonPropertyName("customisationUnlocks")]
public List<CustomisationStorage> CustomisationUnlocks { get; set; }
}
public class TraderPurchaseData
+322 -33
View File
@@ -10,78 +10,335 @@ using ILogger = Core.Models.Utils.ILogger;
using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.ItemEvent;
using Core.Models.Enums;
using Core.Routers;
[Injectable]
public class CreateProfileService
{
private readonly ILogger _logger;
private readonly TimeUtil _timeUtil;
private readonly HashUtil _hashUtil;
private readonly DatabaseService _databaseService;
private readonly LocalisationService _localisationService;
private readonly ProfileHelper _profileHelper;
private readonly ItemHelper _itemHelper;
private readonly TraderHelper _traderHelper;
private readonly QuestHelper _questHelper;
private readonly QuestRewardHelper _questRewardHelper;
private readonly ProfileFixerService _profileFixerService;
private readonly SaveServer _saveServer;
private readonly EventOutputHolder _eventOutputHolder;
private readonly PlayerScavGenerator _playerScavGenerator;
private readonly ICloner _cloner;
public CreateProfileService(
ILogger logger,
TimeUtil timeUtil,
HashUtil hashUtil,
DatabaseService databaseService,
TraderAssortHelper traderAssortHelper,
TraderAssortService traderAssortService,
LocalisationService localisationService,
ProfileHelper profileHelper,
ItemHelper itemHelper,
TraderHelper traderHelper,
PaymentHelper paymentHelper,
RagfairPriceService ragfairPriceService,
TraderPurchasePersisterService traderPurchasePersisterService,
FenceBaseAssortGenerator fenceBaseAssortGenerator,
ConfigServer configServer,
QuestHelper questHelper,
QuestRewardHelper questRewardHelper,
ProfileFixerService profileFixerService,
SaveServer saveServer,
EventOutputHolder eventOutputHolder,
PlayerScavGenerator playerScavGenerator,
ICloner cloner)
{
_logger = logger;
_timeUtil = timeUtil;
_hashUtil = hashUtil;
_databaseService = databaseService;
_localisationService = localisationService;
_profileHelper = profileHelper;
_itemHelper = itemHelper;
_traderHelper = traderHelper;
_questHelper = questHelper;
_questRewardHelper = questRewardHelper;
_profileFixerService = profileFixerService;
_saveServer = saveServer;
_eventOutputHolder = eventOutputHolder;
_playerScavGenerator = playerScavGenerator;
_cloner = cloner;
}
public string CreateProfile(string sessionID, ProfileCreateRequestData request)
public string CreateProfile(string sessionId, ProfileCreateRequestData request)
{
var account = _saveServer.GetProfile(sessionID).ProfileInfo;
var profileTemplateClone =
_cloner.Clone(_databaseService.GetProfiles()[account.Edition][request.Side.ToLower()]);
var pmcData = profileTemplateClone.Character;
var account = _saveServer.GetProfile(sessionId).ProfileInfo;
var profileTemplate = _cloner.Clone(_databaseService.GetProfiles()?[account.Edition]?[request.Side.ToLower()]);
var pmcData = profileTemplate.Character;
// Delete existing profile
DeleteProfileBySessionId(sessionID);
}
DeleteProfileBySessionId(sessionId);
// PMC
pmcData.Id = account.ProfileId;
pmcData.Aid = account.Aid;
pmcData.Savage = account.ScavengerId;
pmcData.SessionId = sessionId;
pmcData.Info.Nickname = request.Nickname;
pmcData.Info.LowerNickname = account.Username.ToLower();
pmcData.Info.RegistrationDate = _timeUtil.GetTimeStamp();
pmcData.Info.Voice = _databaseService.GetCustomization()[request.VoiceId].Name;
pmcData.Stats = _profileHelper.GetDefaultCounters();
pmcData.Info.NeedWipeOptions = [];
pmcData.Customization.Head = request.HeadId;
pmcData.Health.UpdateTime = _timeUtil.GetTimeStamp();
pmcData.Quests = [];
pmcData.Hideout.Seed = _timeUtil.GetTimeStamp() + 8 * 60 * 60 * 24 * 365; // 8 years in future why? who knows, we saw it in live
pmcData.RepeatableQuests = [];
pmcData.CarExtractCounts = new();
pmcData.CoopExtractCounts = new();
pmcData.Achievements = new();
private void DeleteProfileBySessionId(string sessionId)
{
UpdateInventoryEquipmentId(pmcData);
}
if (pmcData.UnlockedInfo == null)
{
pmcData.UnlockedInfo = new UnlockedInfo { UnlockedProductionRecipe = [] };
}
private void UpdateInventoryEquipmentId(PmcData pmcData)
{
// Add required items to pmc stash
AddMissingInternalContainersToProfile(pmcData);
}
// Change item IDs to be unique
pmcData.Inventory.Items = _itemHelper.ReplaceIDs(
pmcData.Inventory.Items,
pmcData,
null,
pmcData.Inventory.FastPanel
);
private void ResetAllTradersInProfile(string sessionId)
{
// Create profile
var profileDetails = new SptProfile
{
ProfileInfo = account,
CharacterData = new Characters { PmcData = pmcData, ScavData = new() },
Suits = profileTemplate.Suits,
UserBuildData = profileTemplate.UserBuilds,
DialogueRecords = profileTemplate.Dialogues,
SptData = _profileHelper.GetDefaultSptDataObject(),
VitalityData = new(),
InraidData = new(),
InsuranceList = [],
TraderPurchases = new(),
PlayerAchievements = new(),
FriendProfileIds = [],
CustomisationUnlocks = []
};
AddCustomisationUnlocksToProfile(profileDetails);
_profileFixerService.CheckForAndFixPmcProfileIssues(profileDetails.CharacterData.PmcData);
_saveServer.AddProfile(profileDetails);
if (profileTemplate.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)
{
_questHelper.AddAllQuestsToProfile(profileDetails.CharacterData.PmcData, [
QuestStatusEnum.AvailableForStart,
QuestStatusEnum.Started,
QuestStatusEnum.AvailableForFinish,
]);
// Make unused response so applyQuestReward works
ItemEventRouterResponse? response = _eventOutputHolder.GetOutput(sessionId);
// Add rewards for starting quests to profile
GivePlayerStartingQuestRewards(profileDetails, sessionId, response);
}
ResetAllTradersInProfile(sessionId);
_saveServer.GetProfile(sessionId).CharacterData.ScavData = _playerScavGenerator.Generate(sessionId);
// Store minimal profile and reload it
_saveServer.SaveProfile(sessionId);
_saveServer.LoadProfile(sessionId);
// Completed account creation
_saveServer.GetProfile(sessionId).ProfileInfo.IsWiped = false;
_saveServer.SaveProfile(sessionId);
return pmcData.Id;
}
/**
* Ensure a profile has the necessary internal containers e.g. questRaidItems / sortingTable
* DOES NOT check that stash exists
* @param pmcData Profile to check
* Delete a profile
* @param sessionID Id of profile to delete
*/
private void AddMissingInternalContainersToProfile(PmcData pmcData)
protected void DeleteProfileBySessionId(string sessionID)
{
if (_saveServer.GetProfiles().ContainsKey(sessionID))
{
_saveServer.DeleteProfileById(sessionID);
}
else
{
_logger.Warning(
_localisationService.GetText("profile-unable_to_find_profile_by_id_cannot_delete", sessionID)
);
}
}
/**
* make profiles pmcData.Inventory.equipment unique
* @param pmcData Profile to update
*/
protected void UpdateInventoryEquipmentId(PmcData pmcData)
{
var oldEquipmentId = pmcData.Inventory.Equipment;
pmcData.Inventory.Equipment = _hashUtil.Generate();
foreach (var item in pmcData.Inventory.Items)
{
if (item.ParentId == oldEquipmentId)
{
item.ParentId = pmcData.Inventory.Equipment;
continue;
}
if (item.Id == oldEquipmentId)
{
item.Id = pmcData.Inventory.Equipment;
}
}
}
/**
* For each trader reset their state to what a level 1 player would see
* @param sessionId Session id of profile to reset
*/
protected void ResetAllTradersInProfile(string sessionId)
{
foreach (var traderId in _databaseService.GetTraders().Keys)
{
_traderHelper.ResetTrader(sessionId, traderId);
}
}
/**
* Ensure a profile has the necessary internal containers e.g. questRaidItems / sortingTable
* DOES NOT check that stash exists
* @param pmcData Profile to check
*/
protected void AddMissingInternalContainersToProfile(PmcData pmcData)
{
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.HideoutCustomizationStashId))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.HideoutCustomizationStashId,
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.SortingTable))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.SortingTable,
Template = ItemTpl.SORTINGTABLE_SORTING_TABLE,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestStashItems))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.QuestStashItems,
Template = ItemTpl.STASH_QUESTOFFLINE,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestRaidItems))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.QuestRaidItems,
Template = ItemTpl.STASH_QUESTRAID,
});
}
}
private void AddCustomisationUnlocksToProfile(SptProfile fullProfile)
{
// Some game versions have additional dogtag variants, add them
switch (GetGameEdition(fullProfile))
{
case GameEditions.EDGE_OF_DARKNESS:
// Gets EoD tags
fullProfile.CustomisationUnlocks.Add( new CustomisationStorage {
Id = "6746fd09bafff85008048838",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "67471938bafff850080488b7",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
break;
case GameEditions.UNHEARD:
// Gets EoD+Unheard tags
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "6746fd09bafff85008048838",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "67471938bafff850080488b7",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "67471928d17d6431550563b5",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "6747193f170146228c0d2226",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
break;
}
var pretigeLevel = fullProfile?.CharacterData?.PmcData?.Info?.PrestigeLevel;
if (pretigeLevel is not null)
{
if (pretigeLevel >= 1)
{
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "674dbf593bee1152d407f005",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
}
if (pretigeLevel >= 2)
{
fullProfile.CustomisationUnlocks.Add(new CustomisationStorage {
Id = "675dcfea7ae1a8792107ca99",
Source = CustomisationSource.DEFAULT,
Type = CustomisationType.DOG_TAG,
});
}
}
}
private string GetGameEdition(SptProfile profile)
@@ -90,14 +347,46 @@ public class CreateProfileService
}
/**
* Iterate over all quests in player profile, inspect rewards for the quests current state (accepted/completed)
* and send rewards to them in mail
* @param profileDetails Player profile
* @param sessionID Session id
* @param response Event router response
*/
private void GivePlayerStartingQuestRewards( SptProfile fullProfile, string sessionId, ItemEventRouterResponse response)
* Iterate over all quests in player profile, inspect rewards for the quests current state (accepted/completed)
* and send rewards to them in mail
* @param profileDetails Player profile
* @param sessionID Session id
* @param response Event router response
*/
protected void GivePlayerStartingQuestRewards(
SptProfile profileDetails,
string sessionID,
ItemEventRouterResponse response
)
{
foreach (var quest in profileDetails.CharacterData.PmcData.Quests)
{
var questFromDb = _questHelper.GetQuestFromDb(quest.QId, profileDetails.CharacterData.PmcData);
// Get messageId of text to send to player as text message in game
// Copy of code from QuestController.acceptQuest()
var messageId = _questHelper.GetMessageIdForQuestStart(
questFromDb.StartedMessageText,
questFromDb.Description
);
var itemRewards = _questRewardHelper.ApplyQuestReward(
profileDetails.CharacterData.PmcData,
quest.QId,
QuestStatusEnum.Started,
sessionID,
response
);
/* TODO:
_mailSendService.sendLocalisedNpcMessageToPlayer(
sessionID,
this.traderHelper.getTraderById(questFromDb.traderId),
MessageType.QUEST_START,
messageId,
itemRewards,
this.timeUtil.getHoursAsSeconds(100),
);
*/
}
}
}