Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
"profiles-prestige-no-data": "No prestige data is available.",
"profiles-quest-queued-once": "A quest can only be queued once.",
"profiles-reloaded": "Reloaded {0}.",
"profiles-clear-messages": "Cleared {1} dialogues for {0}.",
"profiles-no-messages": "No dialogues for {0}.",
"profiles-saved": "Saved {0}.",
"profiles-selected-profile-missing": "Could not identify the selected profile.",
"profiles-skill-range": "Skill levels must be 0-51 and progress must be 0-99.99.",
Expand Down
52 changes: 50 additions & 2 deletions Libraries/SPTarkov.Server.Core/Helpers/Profile/ProfileHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ public void RemoveQuestConditionFromProfile(PmcData pmcData, Dictionary<string,
}
}

/// <summary>
/// Removes all trader/pmc/etc dialogues from a profile.
/// Useful in scenarios where the profile has too many dialogues to properly handle saving/loading due to size
/// </summary>
/// <param name="sessionId">Player profile</param>
/// <returns>Whether anything was cleared and the number of dialogues removed</returns>
public (bool Cleared, int Count) RemoveAllDialoguesFromProfile(MongoId sessionId)
{
var profile = GetFullProfile(sessionId);
var dialogues = profile.DialogueRecords ?? (profile.DialogueRecords = new Dictionary<MongoId, Models.Eft.Profile.Dialogue>());

var count = dialogues.Count;
if (count == 0)
{
return (false, 0);
}

dialogues.Clear();
return (true, count);
}

/// <summary>
/// Get all profiles from server
/// </summary>
Expand Down Expand Up @@ -177,9 +198,9 @@ public void AddExperienceToPmc(MongoId sessionId, int experienceToAdd)
var expTable = globalTable.Configuration.Exp.Level.ExperienceTable;
int? exp = 0;

if (playerLevel >= expTable.Length) // make sure to not go out of bounds
if (playerLevel > expTable.Length)
{
playerLevel = expTable.Length - 1;
playerLevel = expTable.Length;
}

for (var i = 0; i < playerLevel; i++)
Expand All @@ -190,6 +211,33 @@ public void AddExperienceToPmc(MongoId sessionId, int experienceToAdd)
return exp;
}

/// <summary>
/// Get level from an expected experience value
/// </summary>
/// <param name="experience">Experience number to get level for</param>
/// <returns>Level expected</returns>
public int GetLevelFromExperience(int experience)
{
var expTable = globalTable.Configuration.Exp.Level.ExperienceTable;

var cumulative = 0;

for (var level = 1; level <= expTable.Length; level++)
{
if (level > 1)
{
cumulative += expTable[level - 1].Experience;
}

if (experience < cumulative)
{
return level - 1;
}
}

return expTable.Length;
}

/// <summary>
/// Get the max level a player can be
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
@using System.Globalization
@using SPTarkov.Server.Core.Helpers.Profile
@using SPTarkov.Server.Core.Models.Spt.Tables
@using SPTarkov.Server.Web.Models.Database
@using SPTarkov.Server.Web.Models.Profiles
@using SPTarkov.Server.Web.Services
@inject GlobalTable GlobalTable
@inject ProfileHelper ProfileHelper
@inject WebLocalizationService WebLocalizationService

<MudPaper Elevation="0" Class="profiles-details spt-panel pa-5">
Expand Down Expand Up @@ -198,7 +199,8 @@
Step="1000"
Immediate="true"
Disabled="@(!_editModel.HasCharacter)"
@bind-Value="_editModel.PmcExperience" />
Value="_editModel.PmcExperience"
ValueChanged="@(v => SetCharacterExperience(CharacterTarget.Pmc, v))" />

<MudNumericField T="int?"
Label="Scav level"
Expand All @@ -216,7 +218,8 @@
Min="0"
Step="1000"
Immediate="true"
@bind-Value="_editModel.ScavExperience" />
Value="_editModel.ScavExperience"
ValueChanged="@(v => SetCharacterExperience(CharacterTarget.Scav, v))" />

</div>

Expand Down Expand Up @@ -401,8 +404,8 @@
Color="Color.Secondary"
Size="Size.Small"
StartIcon="@Icons.Material.Filled.Done"
OnClick="@(() => SetQuestAction(context, ProfileQuestEditAction.Complete))">
Complete
OnClick="@(() => SetQuestAction(context, ProfileQuestEditAction.AvailableForFinish))">
Ready To Finish
</MudButton>

<MudButton Variant="Variant.Outlined"
Expand Down Expand Up @@ -531,7 +534,7 @@
public EventCallback OnClose { get; set; }

private const int MaxSkillLevel = 51;
private int MaxCharacterLevel => GlobalTable.Configuration.Exp.Level.ExperienceTable.Length - 1;
private int MaxCharacterLevel => GlobalTable.Configuration.Exp.Level.ExperienceTable.Length;

private ProfileDetails? _detailsReference;
private ProfileEditModel? _editModel;
Expand Down Expand Up @@ -597,26 +600,33 @@
if (target == CharacterTarget.Pmc)
{
_editModel.PmcLevel = clamped;
_editModel.PmcExperience = GetLevelStartXp(clamped);
_editModel.PmcExperience = ProfileHelper.GetExperience(clamped);
}
else
{
_editModel.ScavLevel = clamped;
_editModel.ScavExperience = GetLevelStartXp(clamped);
_editModel.ScavExperience = ProfileHelper.GetExperience(clamped);
}
}

private int GetLevelStartXp(int level)
private void SetCharacterExperience(CharacterTarget target, int? experience)
{
var table = GlobalTable.Configuration.Exp.Level.ExperienceTable;

level = Math.Clamp(level, 1, table.Length - 1);
if (_editModel is null || !experience.HasValue)
return;

var exp = 0;
for (var i = 0; i < level; i++)
exp += table[i].Experience;
var exp = Math.Max(0, experience.Value);
var level = ProfileHelper.GetLevelFromExperience(exp);

return exp;
if (target == CharacterTarget.Pmc)
{
_editModel.PmcExperience = exp;
_editModel.PmcLevel = level;
}
else
{
_editModel.ScavExperience = exp;
_editModel.ScavLevel = level;
}
}

private static void SetSkillLevel(ProfileSkillEditModel skill, int value)
Expand Down Expand Up @@ -712,9 +722,9 @@

private static string GetQuestPendingLabel(ProfileQuestEditModel quest)
{
if (quest.PendingAction == ProfileQuestEditAction.Complete)
if (quest.PendingAction == ProfileQuestEditAction.AvailableForFinish)
{
return quest.IsNew ? "Add and complete" : "Complete";
return quest.IsNew ? "Add and mark ready to finish" : "Available For Finish";
}

if (quest.PendingAction == ProfileQuestEditAction.Restart)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@
</MudTd>
<MudTd>
<MudStack Row Spacing="1" Justify="Justify.FlexEnd">
<MudTooltip Text="Clear Messages">
<span @onclick:stopPropagation="true">
<MudIconButton Icon="@Icons.Material.Filled.Mail"
Size="Size.Small"
Color="Color.Secondary"
Disabled="@IsBusy"
OnClick="@(() => OnClearMessages.InvokeAsync(context))"
AriaLabel="Clear Messages" />
</span>
</MudTooltip>
<MudTooltip Text="Save profile">
<span @onclick:stopPropagation="true">
<MudIconButton Icon="@Icons.Material.Filled.Save"
Expand Down Expand Up @@ -122,6 +132,9 @@
[Parameter]
public EventCallback OnSaveAll { get; set; }

[Parameter]
public EventCallback<ProfileSummary> OnClearMessages { get; set; }

[Parameter]
public EventCallback<ProfileSummary> OnSaveProfile { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public ProfileQuestEditModel Clone()
public enum ProfileQuestEditAction
{
None,
Complete,
AvailableForFinish,
Restart,
}
32 changes: 25 additions & 7 deletions Libraries/SPTarkov.Server.Web/Pages/ProfileControlPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
IsBusy="@_isBusy"
OnRefresh="@(() => RefreshProfiles())"
OnSaveAll="SaveAllProfiles"
OnClearMessages="ClearMessages"
OnSaveProfile="SaveProfile"
OnReloadProfile="ReloadProfile"
SelectedProfileChanged="SelectProfile" />
Expand Down Expand Up @@ -201,6 +202,22 @@
});
}

private async Task ClearMessages(ProfileSummary profile)
{
await RunProfileAction(async () =>
{
var result = ProfileHelper.RemoveAllDialoguesFromProfile(profile.Id);
if (result.Cleared)
{
await SaveServer.SaveProfileAsync(new MongoId(profile.Id));
Snackbar.Add(string.Format(L("profiles-clear-messages"), profile.Username, result.Count), Severity.Success);
return;
}

Snackbar.Add(string.Format(L("profiles-no-messages"), profile.Username), Severity.Warning);
});
}

private async Task SaveProfile(ProfileSummary profile)
{
await RunProfileAction(async () =>
Expand Down Expand Up @@ -446,14 +463,15 @@
return false;
}

var maxLevel = GlobalTable.Configuration.Exp.Level.ExperienceTable.Length - 1;
var maxLevel = GlobalTable.Configuration.Exp.Level.ExperienceTable.Length;
if (editModel.PmcLevel < 1 || editModel.PmcLevel > maxLevel || editModel.ScavLevel < 1 || editModel.ScavLevel > maxLevel)
{
Snackbar.Add(string.Format(L("profiles-character-level-range"), maxLevel), Severity.Warning);
return false;
}

if (editModel.PmcExperience != ProfileHelper.GetExperience(editModel.PmcLevel.Value) || editModel.ScavExperience != ProfileHelper.GetExperience(editModel.ScavLevel.Value))
if (ProfileHelper.GetLevelFromExperience(editModel.PmcExperience.Value) != editModel.PmcLevel.Value ||
ProfileHelper.GetLevelFromExperience(editModel.ScavExperience.Value) != editModel.ScavLevel.Value)
{
Snackbar.Add(L("profiles-experience-mismatch-level"), Severity.Warning);
return false;
Expand Down Expand Up @@ -617,8 +635,8 @@

switch (questEdit.PendingAction)
{
case ProfileQuestEditAction.Complete:
CompleteQuestStatus(quest, now);
case ProfileQuestEditAction.AvailableForFinish:
AvailableForFinishQuestStatus(quest, now);
break;
case ProfileQuestEditAction.Restart:
RestartQuestStatus(quest, now);
Expand Down Expand Up @@ -646,12 +664,12 @@
};
}

private static void CompleteQuestStatus(ProfileQuestStatus quest, long timestamp)
private static void AvailableForFinishQuestStatus(ProfileQuestStatus quest, long timestamp)
{
quest.Status = QuestStatusEnum.Success;
quest.Status = QuestStatusEnum.AvailableForFinish;
quest.AvailableAfter = null;
quest.StatusTimers ??= [];
quest.StatusTimers[QuestStatusEnum.Success] = timestamp;
quest.StatusTimers[QuestStatusEnum.AvailableForFinish] = timestamp;
}

private static void RestartQuestStatus(ProfileQuestStatus quest, long timestamp)
Expand Down
Loading