diff --git a/Source/Client/AsyncTime/AsyncTimeComp.cs b/Source/Client/AsyncTime/AsyncTimeComp.cs index 837d28f1..07066e16 100644 --- a/Source/Client/AsyncTime/AsyncTimeComp.cs +++ b/Source/Client/AsyncTime/AsyncTimeComp.cs @@ -20,15 +20,10 @@ public class AsyncTimeComp : IExposable, ITickable public float TickRateMultiplier(TimeSpeed speed) { - var comp = map.MpComp(); - - var enforcePause = comp.sessionManager.IsAnySessionCurrentlyPausing(map) || - Multiplayer.WorldComp.sessionManager.IsAnySessionCurrentlyPausing(map); - - if (enforcePause) + if (IsForcePaused) return 0f; - if (mapTicks < slower.forceNormalSpeedUntil) + if (IsForceSlowdown) return speed == TimeSpeed.Paused ? 0 : 1; switch (speed) @@ -57,6 +52,11 @@ public void SetDesiredTimeSpeed(TimeSpeed speed) timeSpeedInt = speed; } + public bool IsForcePaused => map.MpComp().sessionManager.IsAnySessionCurrentlyPausing(map) || + Multiplayer.WorldComp.sessionManager.IsAnySessionCurrentlyPausing(map); + + public bool IsForceSlowdown => mapTicks < slower.forceNormalSpeedUntil; + public bool Paused => this.ActualRateMultiplier(DesiredTimeSpeed) == 0f; public float TimeToTickThrough { get; set; } diff --git a/Source/Client/AsyncTime/AsyncWorldTimeComp.cs b/Source/Client/AsyncTime/AsyncWorldTimeComp.cs index 6859309e..b86de425 100644 --- a/Source/Client/AsyncTime/AsyncWorldTimeComp.cs +++ b/Source/Client/AsyncTime/AsyncWorldTimeComp.cs @@ -25,13 +25,12 @@ public class AsyncWorldTimeComp : IExposable, ITickable public float TickRateMultiplier(TimeSpeed speed) { - if (Multiplayer.GameComp.asyncTime) - { - var enforcePause = Multiplayer.WorldComp.sessionManager.IsAnySessionCurrentlyPausing(null); + if (IsForcePaused) + return 0f; - if (enforcePause) - return 0f; - } + // Could just skip, as it currently can not be true unless a mod makes a Harmony patch. + if (IsForceSlowdown) + return speed == TimeSpeed.Paused ? 0 : 1; return speed switch { @@ -44,6 +43,11 @@ public float TickRateMultiplier(TimeSpeed speed) }; } + public bool IsForcePaused => Multiplayer.GameComp.asyncTime && + Multiplayer.WorldComp.sessionManager.IsAnySessionCurrentlyPausing(null); + + public bool IsForceSlowdown => false; + // Run at the speed of the fastest map or at chosen speed if there are no maps public TimeSpeed DesiredTimeSpeed => !Find.Maps.Any() ? timeSpeedInt : diff --git a/Source/Client/AsyncTime/ITickable.cs b/Source/Client/AsyncTime/ITickable.cs index 3b9dd6f4..b83a2338 100644 --- a/Source/Client/AsyncTime/ITickable.cs +++ b/Source/Client/AsyncTime/ITickable.cs @@ -21,5 +21,9 @@ public interface ITickable void Tick(); void ExecuteCmd(ScheduledCommand cmd); + + bool IsForcePaused { get; } + + bool IsForceSlowdown { get; } } } diff --git a/Source/Client/AsyncTime/TimeControlUI.cs b/Source/Client/AsyncTime/TimeControlUI.cs index c4edd005..6d37b320 100644 --- a/Source/Client/AsyncTime/TimeControlUI.cs +++ b/Source/Client/AsyncTime/TimeControlUI.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; using HarmonyLib; @@ -106,12 +106,11 @@ private static void DoTimeControlsGUI(Rect timerRect) rect.x += rect.width; } - float normalSpeed = Tickable.ActualRateMultiplier(TimeSpeed.Normal); - float fastSpeed = Tickable.ActualRateMultiplier(TimeSpeed.Fast); + ForcedTickRate info = Tickable.GetForcedTickRate(); - if (normalSpeed == 0f) // Completely paused + if (info == ForcedTickRate.Paused) // Completely paused Widgets.DrawLineHorizontal(rect.width, rect.height / 2f, rect.width * 3f); - else if (normalSpeed == fastSpeed) // Slowed down + else if (info == ForcedTickRate.Slowdown) // Slowed down Widgets.DrawLineHorizontal(rect.width * 2f, rect.height / 2f, rect.width * 2f); Widgets.EndGroup(); @@ -314,12 +313,12 @@ static void DrawButtons() { if (curGroup == entry.group) continue; - ITickable entryTickable = entry.map?.AsyncTime(); - if (entryTickable == null) entryTickable = Multiplayer.AsyncWorldTime; + ITickable entryTickable = entry.map?.AsyncTime() ?? (ITickable)Multiplayer.AsyncWorldTime; Rect groupBar = bar.drawer.GroupFrameRect(entry.group); float drawXPos = groupBar.x; - Color bgColor = (entryTickable.ActualRateMultiplier(TimeSpeed.Normal) == 0f) ? pauseBgColor : normalBgColor; + bool paused = entryTickable.IsForcePaused; + Color bgColor = paused ? pauseBgColor : normalBgColor; Vector2 flashPos = new Vector2(drawXPos + btnWidth / 2, groupBar.yMax + btnHeight / 2); if (Multiplayer.GameComp.asyncTime) @@ -331,7 +330,7 @@ static void DrawButtons() MpTimeControls.TimeControlButton(button, bgColor, entryTickable); drawXPos += TimeControls.TimeButSize.x; } - else if (entryTickable.ActualRateMultiplier(TimeSpeed.Normal) == 0f) + else if (paused) { MpTimeControls.TimeIndicateBlockingPause(button, bgColor); drawXPos += TimeControls.TimeButSize.x; @@ -351,7 +350,7 @@ static void DrawButtons() } else { - // There is a new blocking pause + // There is a new blocking pause flashDict.Add(flashPos, Time.time); } } diff --git a/Source/Client/Patches/TickPatch.cs b/Source/Client/Patches/TickPatch.cs index f3740f8a..612926a4 100644 --- a/Source/Client/Patches/TickPatch.cs +++ b/Source/Client/Patches/TickPatch.cs @@ -270,9 +270,10 @@ private static float ReplayMultiplier() public static float TimePerTick(this ITickable tickable, TimeSpeed speed) { - if (tickable.ActualRateMultiplier(speed) == 0f) + var mult = tickable.ActualRateMultiplier(speed); + if (mult == 0f) return 0f; - return 1f / tickable.ActualRateMultiplier(speed); + return 1f / mult; } public static float ActualRateMultiplier(this ITickable tickable, TimeSpeed speed) @@ -287,6 +288,39 @@ public static float ActualRateMultiplier(this ITickable tickable, TimeSpeed spee return rate; } + public static ForcedTickRate GetForcedTickRate(this ITickable tickable) + { + if (Multiplayer.GameComp.asyncTime) + { + if (tickable.IsForcePaused) + return ForcedTickRate.Paused; + if (tickable.IsForceSlowdown) + return ForcedTickRate.Slowdown; + return ForcedTickRate.Normal; + } + + if (Multiplayer.AsyncWorldTime.IsForcePaused) + return ForcedTickRate.Paused; + + // Could just use false as default, as it currently can + // not be true unless a mod makes a Harmony patch. + var isForceSlowdown = Multiplayer.AsyncWorldTime.IsForceSlowdown; + + foreach (var map in Find.Maps) + { + var comp = map.AsyncTime(); + + if (comp.IsForcePaused) + return ForcedTickRate.Paused; + if (!isForceSlowdown) + isForceSlowdown = comp.IsForceSlowdown; + } + + if (isForceSlowdown) + return ForcedTickRate.Slowdown; + return ForcedTickRate.Normal; + } + public static void ClearSimulating() { simulating = null; @@ -327,4 +361,6 @@ public class SimulatingData public string cancelButtonKey; public string simTextKey; } + + public enum ForcedTickRate { Normal, Paused, Slowdown, } }