diff --git a/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs b/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs index 36ce304728..1fc59fafe1 100644 --- a/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs @@ -20,11 +20,11 @@ namespace OpenRA.Mods.Common.Widgets { public class ObserverSupportPowerIconsWidget : Widget { - public Func GetPlayer; - Animation icon; - World world; - WorldRenderer worldRenderer; - Dictionary clocks; + readonly Animation icon; + readonly World world; + readonly WorldRenderer worldRenderer; + readonly Dictionary clocks; + readonly int timestep; public int IconWidth = 32; public int IconHeight = 24; @@ -33,6 +33,7 @@ namespace OpenRA.Mods.Common.Widgets public string ClockAnimation = "clock"; public string ClockSequence = "idle"; public string ClockPalette = "chrome"; + public Func GetPlayer; [ObjectCreator.UseCtor] public ObserverSupportPowerIconsWidget(World world, WorldRenderer worldRenderer) @@ -41,6 +42,14 @@ namespace OpenRA.Mods.Common.Widgets this.worldRenderer = worldRenderer; clocks = new Dictionary(); icon = new Animation(world, "icon"); + + // Timers should be synced to the effective game time, not the playback time. + GameSpeed speed; + var gameSpeeds = Game.ModData.Manifest.Get(); + if (gameSpeeds.Speeds.TryGetValue(world.LobbyInfo.GlobalSettings.GameSpeedType, out speed)) + timestep = speed.Timestep; + else + timestep = world.Timestep; } protected ObserverSupportPowerIconsWidget(ObserverSupportPowerIconsWidget other) @@ -51,6 +60,7 @@ namespace OpenRA.Mods.Common.Widgets world = other.world; worldRenderer = other.worldRenderer; clocks = other.clocks; + timestep = other.timestep; IconWidth = other.IconWidth; IconHeight = other.IconHeight; @@ -94,7 +104,7 @@ namespace OpenRA.Mods.Common.Widgets WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(ClockPalette), 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; - var text = GetOverlayForItem(item, world.Timestep); + var text = GetOverlayForItem(item, timestep); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); diff --git a/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs index 6ea4c8ef1b..0fc8037baa 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs @@ -23,25 +23,34 @@ namespace OpenRA.Mods.Common.Widgets public readonly string Format = "{0}: {1}"; public readonly TimerOrder Order = TimerOrder.Descending; - readonly World world; + readonly int timestep; readonly IEnumerable powers; Pair[] texts; [ObjectCreator.UseCtor] public SupportPowerTimerWidget(World world) { - this.world = world; powers = world.ActorsWithTrait() .Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant) .SelectMany(s => s.Trait.Powers.Values) .Where(p => p.Instances.Any() && p.Info.DisplayTimer && !p.Disabled); + + // Timers in replays should be synced to the effective game time, not the playback time. + timestep = world.Timestep; + if (world.IsReplay) + { + GameSpeed speed; + var gameSpeeds = Game.ModData.Manifest.Get(); + if (gameSpeeds.Speeds.TryGetValue(world.LobbyInfo.GlobalSettings.GameSpeedType, out speed)) + timestep = speed.Timestep; + } } public override void Tick() { texts = powers.Select(p => { - var time = WidgetUtils.FormatTime(p.RemainingTime, false, world.Timestep); + var time = WidgetUtils.FormatTime(p.RemainingTime, false, timestep); var text = Format.F(p.Info.Description, time); var color = !p.Ready || Game.LocalTick % 50 < 25 ? p.Instances[0].Self.Owner.Color.RGB : Color.White; return Pair.New(text, color);