using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Exceptions.Helpers; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Utils; namespace SPTarkov.Server.Core.Helpers; [Injectable] public class DurabilityLimitsHelper( ISptLogger logger, RandomUtil randomUtil, BotHelper botHelper, ConfigServer configServer ) { protected readonly BotConfig BotConfig = configServer.GetConfig(); /// /// Get max durability for a weapon based on bot role /// /// Role of bot to get max durability for /// Max durability of weapon public double GetRandomizedMaxWeaponDurability(string? botRole = null) { var durabilityRole = GetDurabilityRole(botRole); return GenerateMaxWeaponDurability(durabilityRole); } /// /// Get max durability value for armor based on bot role /// /// Item to get max durability for /// Role of bot to get max durability for /// max durability public double GetRandomizedMaxArmorDurability(TemplateItem? itemTemplate, string? botRole = null) { var itemMaxDurability = itemTemplate?.Properties?.MaxDurability; if (!itemMaxDurability.HasValue) { const string message = "Item max durability amount is null when trying to get max armor durability"; logger.Error(message); throw new DurabilityHelperException(message); } if (botRole is null) { return itemMaxDurability.Value; } if (botHelper.IsBotPmc(botRole)) { return GenerateMaxPmcArmorDurability(itemMaxDurability.Value); } // Everyone else (Boss/follower etc) return itemMaxDurability.Value; } /// /// Get randomised current weapon durability by bot role /// /// Role of bot to get current durability for /// Max durability of weapon /// Current weapon durability public double GetRandomizedWeaponDurability(string? botRole, double maxDurability) { var durabilityRole = GetDurabilityRole(botRole); return GenerateWeaponDurability(durabilityRole, maxDurability); } /// /// Convert a bots role into a durability role used for looking up durability values with /// /// Role to convert /// protected string GetDurabilityRole(string? botRole) { if (botRole is null) { return "default"; } if (botHelper.IsBotPmc(botRole)) { return "pmc"; } if (botHelper.IsBotBoss(botRole)) { return "boss"; } if (botHelper.IsBotFollower(botRole)) { return "follower"; } if (botHelper.IsBotZombie(botRole)) { return "zombie"; } var roleExistsInConfig = BotConfig.Durability.BotDurabilities.ContainsKey(botRole); if (roleExistsInConfig) { return botRole; } logger.Debug($"{botRole} doesn't exist in bot config durability values, using default fallback"); return "default"; } /// /// Get randomised current armor durability by bot role /// /// Unused - Item to get current durability of /// Role of bot to get current durability for /// Max durability of armor /// Current armor durability public double GetRandomizedArmorDurability(TemplateItem? itemTemplate, string? botRole, double maxDurability) { var durabilityRole = GetDurabilityRole(botRole); return GenerateArmorDurability(durabilityRole, maxDurability); } protected double GenerateMaxWeaponDurability(string? botRole = null) { var lowestMax = GetLowestMaxWeaponFromConfig(botRole); var highestMax = GetHighestMaxWeaponDurabilityFromConfig(botRole); return randomUtil.GetInt(lowestMax, highestMax); } protected double GenerateMaxPmcArmorDurability(double itemMaxDurability) { var lowestMaxPercent = BotConfig.Durability.Pmc.Armor.LowestMaxPercent; var highestMaxPercent = BotConfig.Durability.Pmc.Armor.HighestMaxPercent; var multiplier = randomUtil.GetDouble(lowestMaxPercent, highestMaxPercent); return itemMaxDurability * (multiplier / 100); } protected int GetLowestMaxWeaponFromConfig(string? botRole = null) { switch (botRole) { case null: case "default": return BotConfig.Durability.Default.Weapon.LowestMax; case "pmc": return BotConfig.Durability.Pmc.Weapon.LowestMax; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var durability)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return durability.Weapon.LowestMax; } protected int GetHighestMaxWeaponDurabilityFromConfig(string? botRole = null) { switch (botRole) { case null: case "default": return BotConfig.Durability.Default.Weapon.HighestMax; case "pmc": return BotConfig.Durability.Pmc.Weapon.HighestMax; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var durability)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return durability.Weapon.HighestMax; } protected double GenerateWeaponDurability(string? botRole, double maxDurability) { var minDelta = GetMinWeaponDeltaFromConfig(botRole); var maxDelta = GetMaxWeaponDeltaFromConfig(botRole); var delta = randomUtil.GetInt(minDelta, maxDelta); var result = maxDurability - delta; var durabilityValueMinLimit = Math.Round(GetMinWeaponLimitPercentFromConfig(botRole) / 100 * maxDurability); // Don't let weapon durability go below the percent defined in config return result >= durabilityValueMinLimit ? result : durabilityValueMinLimit; } protected double GenerateArmorDurability(string? botRole, double maxDurability) { var minDelta = GetMinArmorDeltaFromConfig(botRole); var maxDelta = GetMaxArmorDeltaFromConfig(botRole); var delta = randomUtil.GetInt(minDelta, maxDelta); var result = maxDurability - delta; var durabilityValueMinLimit = Math.Round(GetMinArmorLimitPercentFromConfig(botRole) / 100 * maxDurability); // Don't let armor durability go below the percent defined in config return result >= durabilityValueMinLimit ? result : durabilityValueMinLimit; } protected int GetMinWeaponDeltaFromConfig(string? botRole = null) { if (botRole is null or "default") { return BotConfig.Durability.Default.Weapon.MinDelta; } if (botRole == "pmc") { return BotConfig.Durability.Pmc.Weapon.MinDelta; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var durability)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return durability.Weapon.MinDelta; } protected int GetMaxWeaponDeltaFromConfig(string? botRole = null) { if (botRole is null or "default") { return BotConfig.Durability.Default.Weapon.MaxDelta; } if (botRole == "pmc") { return BotConfig.Durability.Pmc.Weapon.MaxDelta; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return value.Weapon.MaxDelta; } protected int GetMinArmorDeltaFromConfig(string? botRole = null) { if (botRole is null or "default") { return BotConfig.Durability.Default.Armor.MinDelta; } if (botRole == "pmc") { return BotConfig.Durability.Pmc.Armor.MinDelta; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return value.Armor.MinDelta; } protected int GetMaxArmorDeltaFromConfig(string? botRole = null) { if (botRole is null or "default") { return BotConfig.Durability.Default.Armor.MaxDelta; } if (botRole == "pmc") { return BotConfig.Durability.Pmc.Armor.MaxDelta; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return value.Armor.MaxDelta; } protected double GetMinArmorLimitPercentFromConfig(string? botRole = null) { if (botRole is null or "default") { return BotConfig.Durability.Default.Armor.MinLimitPercent; } if (botRole == "pmc") { return BotConfig.Durability.Pmc.Armor.MinLimitPercent; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return value.Armor.MinLimitPercent; } protected double GetMinWeaponLimitPercentFromConfig(string? botRole = null) { if (botRole is null or "default") { return BotConfig.Durability.Default.Weapon.MinLimitPercent; } if (botRole == "pmc") { return BotConfig.Durability.Pmc.Weapon.MinLimitPercent; } if (!BotConfig.Durability.BotDurabilities.TryGetValue(botRole, out var value)) { var message = $"Bot role {botRole} durability doesn't exist"; logger.Error(message); throw new DurabilityHelperException(message); } return value.Weapon.MinLimitPercent; } }