diff --git a/Core/Controllers/GameController.cs b/Core/Controllers/GameController.cs index ec0d79da..3731442d 100644 --- a/Core/Controllers/GameController.cs +++ b/Core/Controllers/GameController.cs @@ -3,6 +3,7 @@ using Core.Context; using Core.Helpers; using Core.Models.Eft.Common; using Core.Models.Eft.Game; +using Core.Models.Eft.Match; using Core.Models.Eft.Profile; using Core.Models.Enums; using Core.Models.External; @@ -12,6 +13,8 @@ using Core.Servers; using Core.Services; using Core.Utils; using Core.Utils.Cloners; +using static System.Runtime.InteropServices.JavaScript.JSType; +using System.Diagnostics; namespace Core.Controllers; @@ -570,7 +573,11 @@ public class GameController /// Profile to check for dialog in private void CheckForAndRemoveUndefinedDialogues(SptProfile fullProfile) { - throw new NotImplementedException(); + + if (fullProfile.DialogueRecords.TryGetValue("undefined", out var undefinedDialog)) + { + fullProfile.DialogueRecords.Remove("undefined"); + } } /// @@ -579,7 +586,12 @@ public class GameController /// private void LogProfileDetails(SptProfile fullProfile) { - throw new NotImplementedException(); + _logger.Error("NOT IMPLEMENTED LogProfileDetails"); + _logger.Debug($"Profile made with: ${ fullProfile.SptData.Version}"); + _logger.Debug($"{fullProfile.SptData.Mods.Count} Mods used"); + //_logger.Debug($"Server version: ${ ProgramStatics.SPT_VERSION || _coreConfig.SptVersion} ${ ProgramStatics.COMMIT}"); + //_logger.Debug($"Debug enabled: ${ ProgramStatics.DEBUG}"); + //_logger.Debug($"Mods enabled: ${ ProgramStatics.MODS}"); } public void Load() diff --git a/Core/Helpers/HideoutHelper.cs b/Core/Helpers/HideoutHelper.cs index fe4f82a8..ea26eac3 100644 --- a/Core/Helpers/HideoutHelper.cs +++ b/Core/Helpers/HideoutHelper.cs @@ -1,15 +1,32 @@ -using Core.Annotations; +using Core.Annotations; using Core.Models.Eft.Common; using Core.Models.Eft.Common.Tables; using Core.Models.Eft.Hideout; using Core.Models.Eft.ItemEvent; using Core.Models.Enums; +using Core.Models.Utils; +using Core.Services; +using Core.Utils; namespace Core.Helpers; [Injectable] public class HideoutHelper { + private readonly ISptLogger _logger; + protected TimeUtil _timeUtil; + private readonly LocalisationService _localisationService; + + public HideoutHelper( + ISptLogger logger, + TimeUtil timeUtil, + LocalisationService localisationService) + { + _logger = logger; + _timeUtil = timeUtil; + _localisationService = localisationService; + } + /// /// Add production to profiles' Hideout.Production array /// @@ -52,9 +69,41 @@ public class HideoutHelper /// /// Profile to add bonus to /// Bonus to add to profile - public void ApplyPlayerUpgradesBonuses(PmcData profileData, StageBonus bonus) + public void ApplyPlayerUpgradesBonuses(PmcData profileData, Bonus bonus) { - throw new NotImplementedException(); + // Handle additional changes some bonuses need before being added + var bonusToAdd = new Bonus(); + switch (bonus.Type) + { + case BonusType.StashSize: + { + // Find stash item and adjust tpl to new tpl from bonus + var stashItem = profileData.Inventory.Items.FirstOrDefault((x) => x.Id == profileData.Inventory.Stash); + if (stashItem is null) + { + _logger.Warning(_localisationService.GetText("hideout-unable_to_apply_stashsize_bonus_no_stash_found", profileData.Inventory.Stash)); + } + + stashItem.Template = bonus.TemplateId; + + break; + } + case BonusType.MaximumEnergyReserve: + // Amend max energy in profile + profileData.Health.Energy.Maximum += bonus.Value; + break; + case BonusType.TextBonus: + // Delete values before they're added to profile + bonus.IsPassive = null; + bonus.IsProduction = null; + bonus.IsVisible = null; + break; + } + + // Add bonus to player bonuses array in profile + // EnergyRegeneration, HealthRegeneration, RagfairCommission, ScavCooldownTimer, SkillGroupLevelingBoost, ExperienceRate, QuestMoneyReward etc + _logger.Debug($"Adding bonus: {bonus.Type} to profile, value: {bonus.Value}"); + profileData.Bonuses.Add(bonus); } /// @@ -420,7 +469,22 @@ public class HideoutHelper /// Profile to upgrade wall in public void UnlockHideoutWallInProfile(PmcData profileData) { - throw new NotImplementedException(); + var profileHideoutAreas = profileData.Hideout.Areas; + var waterCollector = profileHideoutAreas.FirstOrDefault((x) => x.Type == HideoutAreas.WATER_COLLECTOR); + var medStation = profileHideoutAreas.FirstOrDefault((x) => x.Type == HideoutAreas.MEDSTATION); + var wall = profileHideoutAreas.FirstOrDefault((x) => x.Type == HideoutAreas.EMERGENCY_WALL); + + // No collector or med station, skip + if ((waterCollector is null && medStation is null)) + { + return; + } + + // If med-station > level 1 AND water collector > level 1 AND wall is level 0 + if (waterCollector?.Level >= 1 && medStation?.Level >= 1 && wall?.Level <= 0) + { + wall.Level = 3; + } } /// @@ -439,7 +503,20 @@ public class HideoutHelper /// Profile to adjust public void SetHideoutImprovementsToCompleted(PmcData profileData) { - throw new NotImplementedException(); + foreach (var improvementId in profileData.Hideout.Improvements) + { + if (!profileData.Hideout.Improvements.TryGetValue(improvementId.Key, out var improvementDetails)) + { + continue; + } + + if (improvementDetails.Completed == false + && improvementDetails.ImproveCompleteTimestamp < _timeUtil.GetTimeStamp() + ) + { + improvementDetails.Completed = true; + } + } } /// diff --git a/Core/Models/Eft/Hideout/HideoutArea.cs b/Core/Models/Eft/Hideout/HideoutArea.cs index 04e7fe39..99ea612f 100644 --- a/Core/Models/Eft/Hideout/HideoutArea.cs +++ b/Core/Models/Eft/Hideout/HideoutArea.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using Core.Models.Eft.Common.Tables; using Core.Models.Enums; namespace Core.Models.Eft.Hideout; @@ -9,7 +10,7 @@ public class HideoutArea public string? Id { get; set; } [JsonPropertyName("type")] - public int? Type { get; set; } + public HideoutAreas? Type { get; set; } [JsonPropertyName("enabled")] public bool? IsEnabled { get; set; } @@ -57,7 +58,7 @@ public class Stage public bool? AutoUpgrade { get; set; } [JsonPropertyName("bonuses")] - public List? Bonuses { get; set; } + public List? Bonuses { get; set; } [JsonPropertyName("constructionTime")] public double? ConstructionTime { get; set; } @@ -181,39 +182,3 @@ public class StageRequirement : RequirementBase [JsonPropertyName("skillLevel")] public int? SkillLevel { get; set; } } - -public class StageBonus -{ - [JsonPropertyName("value")] - public int? Value { get; set; } - - [JsonPropertyName("passive")] - public bool? Passive { get; set; } - - [JsonPropertyName("production")] - public bool? Production { get; set; } - - [JsonPropertyName("visible")] - public bool? Visible { get; set; } - - [JsonPropertyName("skillType")] - [JsonConverter(typeof(JsonStringEnumConverter))] - public BonusSkillType? SkillType { get; set; } - - [JsonPropertyName("type")] - [JsonConverter(typeof(JsonStringEnumConverter))] - public BonusType? Type { get; set; } - - [JsonPropertyName("filter")] - public List? Filter { get; set; } - - [JsonPropertyName("icon")] - public string? Icon { get; set; } - - /** CHANGES PER DUMP */ - [JsonPropertyName("id")] - public string? Id { get; set; } - - [JsonPropertyName("templateId")] - public string? TemplateId { get; set; } -} \ No newline at end of file diff --git a/Core/Services/ProfileFixerService.cs b/Core/Services/ProfileFixerService.cs index 8e48dcaa..b1af922b 100644 --- a/Core/Services/ProfileFixerService.cs +++ b/Core/Services/ProfileFixerService.cs @@ -11,6 +11,10 @@ using Core.Utils; using System.Text.RegularExpressions; using Core.Models.Spt.Config; using Core.Models.Utils; +using Core.Models.Spt.Bots; +using static System.Runtime.InteropServices.JavaScript.JSType; +using System.Reflection.Emit; +using System.Security.AccessControl; namespace Core.Services; @@ -23,6 +27,7 @@ public class ProfileFixerService protected ItemHelper _itemHelper; protected QuestRewardHelper _questRewardHelper; protected TraderHelper _traderHelper; + protected HideoutHelper _hideoutHelper; protected DatabaseService _databaseService; protected LocalisationService _localisationService; protected ConfigServer _configServer; @@ -36,6 +41,7 @@ public class ProfileFixerService ItemHelper itemHelper, QuestRewardHelper questRewardHelper, TraderHelper traderHelper, + HideoutHelper hideoutHelper, DatabaseService databaseService, LocalisationService localisationService, ConfigServer configServer, @@ -48,6 +54,7 @@ public class ProfileFixerService _itemHelper = itemHelper; _questRewardHelper = questRewardHelper; _traderHelper = traderHelper; + _hideoutHelper = hideoutHelper; _databaseService = databaseService; _localisationService = localisationService; _configServer = configServer; @@ -690,7 +697,54 @@ public class ProfileFixerService */ public void AddMissingHideoutBonusesToProfile(PmcData pmcProfile) { - throw new NotImplementedException(); + var dbHideoutAreas = _databaseService.GetHideout().Areas; + + foreach (var profileArea in pmcProfile.Hideout.Areas) { + var areaType = profileArea.Type; + var level = profileArea.Level; + + if (level.GetValueOrDefault(0) == 0) + { + continue; + } + + // Get array of hideout area upgrade levels to check for bonuses + // Zero indexed + var areaLevelsToCheck = new List(); + for (var index = 0; index < level + 1; index++) + { + // Stage key is saved as string in db + areaLevelsToCheck.Add(index.ToString()); + } + + // Iterate over area levels, check for bonuses, add if needed + var dbArea = dbHideoutAreas.FirstOrDefault((area) => area.Type == areaType); + if (dbArea is null) + { + continue; + } + + foreach (var areaLevel in areaLevelsToCheck) { + // Get areas level bonuses from db + var levelBonuses = dbArea.Stages[areaLevel]?.Bonuses; + if (levelBonuses is null || levelBonuses.Count == 0) + { + continue; + } + + // Iterate over each bonus for the areas level + foreach (var bonus in levelBonuses) { + // Check if profile has bonus + var profileBonus = GetBonusFromProfile(pmcProfile.Bonuses, bonus); + if (profileBonus is null) + { + // no bonus, add to profile + _logger.Debug($"Profile has level {level} area {profileArea.Type} but no bonus found, adding { bonus.Type}"); + _hideoutHelper.ApplyPlayerUpgradesBonuses(pmcProfile, bonus); + } + } + } + } } /** @@ -698,9 +752,24 @@ public class ProfileFixerService * @param bonus bonus to find * @returns matching bonus */ - protected Bonus GetBonusFromProfile(List profileBonuses, StageBonus bonus) + protected Bonus? GetBonusFromProfile(List profileBonuses, Bonus bonus) { - throw new NotImplementedException(); + // match by id first, used by "TextBonus" bonuses + if (bonus.Id is null) + { + return profileBonuses.FirstOrDefault((x) => x.Id == bonus.Id); + } + + return bonus.Type switch + { + BonusType.StashSize => profileBonuses.FirstOrDefault( + (x) => x.Type == bonus.Type && x.TemplateId == bonus.TemplateId + ), + BonusType.AdditionalSlots => profileBonuses.FirstOrDefault( + (x) => x.Type == bonus.Type && x.Value == bonus.Value && x.IsVisible == bonus.IsVisible + ), + _ => profileBonuses.FirstOrDefault((x) => x.Type == bonus.Type && x.Value == bonus.Value) + }; } public void CheckForAndRemoveInvalidTraders(SptProfile fullProfile)