From bf07137cf7c30840f24c7c3e7abcc73c4dcd4f11 Mon Sep 17 00:00:00 2001 From: DanW Date: Thu, 21 Dec 2023 22:31:33 +0000 Subject: [PATCH] Improve Robustness of RaidChangesUtil and RaidTimeUtil (!45) While continuing mod development with SPT 3.7.4 (namely for Questing Bots and SAIN), I found that the API I added to SPT 3.7.4 is unintuitive and clunky to use after the raid is done loading but before the countdown timer expires. With the current SPT code, calling `GetRemainingRaidSeconds()` or `GetRaidTimeRemainingFraction()` will result in an exception during this time unless you check `HasRaidStarted()` first. These changes will prevent those methods from throwing an exception unless you try calling them before a raid has finished loading (which should rarely happen). This allows mods to more easily do things using `GetRemainingRaidSeconds()` or `GetRaidTimeRemainingFraction()` before the countdown timer expires (i.e. cache bots). These changes only improve the robustness of the existing code and will not break any mods that use the existing API. Co-authored-by: dwesterwick Co-authored-by: chomp Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Modules/pulls/45 Co-authored-by: DanW Co-committed-by: DanW --- .../Utils/InRaid/RaidChangesUtil.cs | 24 ++++++++++++++----- .../Utils/InRaid/RaidTimeUtil.cs | 21 ++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/project/Aki.SinglePlayer/Utils/InRaid/RaidChangesUtil.cs b/project/Aki.SinglePlayer/Utils/InRaid/RaidChangesUtil.cs index 0fb2510..65faf50 100644 --- a/project/Aki.SinglePlayer/Utils/InRaid/RaidChangesUtil.cs +++ b/project/Aki.SinglePlayer/Utils/InRaid/RaidChangesUtil.cs @@ -59,10 +59,25 @@ namespace Aki.SinglePlayer.Utils.InRaid /// public static int RaidTimeReductionSeconds => RaidTimeReductionMinutes * 60; + /// + /// The fraction of raid time that will be remaining when you spawn into the map + /// + public static float RaidTimeRemainingFraction => (float)NewEscapeTimeMinutes / OriginalEscapeTimeMinutes; + + /// + /// The original minimum time (in seconds) you must stay in the raid to get a "Survived" status (unless your XP is high enough) for the current (or most recent) raid + /// + public static int OriginalSurvivalTimeSeconds { get; private set; } = int.MaxValue; + + /// + /// The updated minimum time (in seconds) you must stay in the raid to get a "Survived" status (unless your XP is high enough) for the current (or most recent) raid + /// + public static int NewSurvivalTimeSeconds { get; private set; } = int.MaxValue; + /// /// The reduction in the minimum time you must stay in the raid to get a "Survived" status (unless your XP is high enough) for the current (or most recent) raid /// - public static int SurvivalTimeReductionSeconds { get; private set; } = 0; + public static int SurvivalTimeReductionSeconds => OriginalSurvivalTimeSeconds - NewSurvivalTimeSeconds; /// /// Update the changes that will be made for the raid. This should be called just before applying changes. @@ -81,11 +96,8 @@ namespace Aki.SinglePlayer.Utils.InRaid OriginalEscapeTimeMinutes = raidSettings.SelectedLocation.EscapeTimeLimit; NewEscapeTimeMinutes = raidChanges.RaidTimeMinutes; - SurvivalTimeReductionSeconds = 0; - if (raidChanges.NewSurviveTimeSeconds.HasValue) - { - SurvivalTimeReductionSeconds += raidChanges.OriginalSurvivalTimeSeconds - raidChanges.NewSurviveTimeSeconds.Value; - } + OriginalSurvivalTimeSeconds = raidChanges.OriginalSurvivalTimeSeconds; + NewSurvivalTimeSeconds = raidChanges.NewSurviveTimeSeconds ?? OriginalSurvivalTimeSeconds; } /// diff --git a/project/Aki.SinglePlayer/Utils/InRaid/RaidTimeUtil.cs b/project/Aki.SinglePlayer/Utils/InRaid/RaidTimeUtil.cs index b0f3598..1d5248f 100644 --- a/project/Aki.SinglePlayer/Utils/InRaid/RaidTimeUtil.cs +++ b/project/Aki.SinglePlayer/Utils/InRaid/RaidTimeUtil.cs @@ -9,6 +9,14 @@ namespace Aki.SinglePlayer.Utils.InRaid /// public static class RaidTimeUtil { + /// + /// Determines if a raid has loaded by checking if a GameTimer instance has been created for one + /// + public static bool HasRaidLoaded() + { + return Singleton.Instance?.GameTimer != null; + } + /// /// Determines if a raid is in-progress by checking if the GameTimer has started /// @@ -19,17 +27,22 @@ namespace Aki.SinglePlayer.Utils.InRaid /// /// Calculates the seconds remaining in the current raid. - /// Please ensure is true, or this will throw an exception. + /// Please ensure is true, or this will throw an exception. /// /// Seconds remaining in the raid /// Thrown if there is no raid in progress public static float GetRemainingRaidSeconds() { - if (!HasRaidStarted()) + if (!HasRaidLoaded()) { throw new InvalidOperationException("The raid-time remaining can only be calculated when a raid is in-progress"); } - + + if (!HasRaidStarted()) + { + return RaidChangesUtil.NewEscapeTimeSeconds; + } + float remainingTimeSeconds = Singleton.Instance.GameTimer.EscapeTimeSeconds(); // Until the raid starts, remainingTimeSeconds is TimeSpan.MaxValue, so it needs to be reduced to the actual starting raid time @@ -39,7 +52,7 @@ namespace Aki.SinglePlayer.Utils.InRaid /// /// Calculates the fraction of raid-time remaining relative to the original escape time for the map. /// 1.0 = the raid just started, and 0.0 = the raid is over (and you're MIA). - /// Please ensure is true, or this will throw an exception. + /// Please ensure is true, or this will throw an exception. /// /// The fraction of raid-time remaining (0.0 - 1.0) relative to the original escape time for the map /// Thrown if there is no raid in progress