diff --git a/OpenRA.Game/Widgets/WidgetUtils.cs b/OpenRA.Game/Widgets/WidgetUtils.cs index fc093a1f61..ac8c1ac7b2 100644 --- a/OpenRA.Game/Widgets/WidgetUtils.cs +++ b/OpenRA.Game/Widgets/WidgetUtils.cs @@ -158,14 +158,14 @@ namespace OpenRA.Widgets DrawRGBA(cornerBottomRight, new float2(bounds.Right - cornerBottomRight.Size.X, bounds.Bottom - cornerBottomRight.Size.Y)); } - public static string FormatTime(int ticks) + public static string FormatTime(int ticks, int timestep) { - return FormatTime(ticks, true); + return FormatTime(ticks, true, timestep); } - public static string FormatTime(int ticks, bool leadingMinuteZero) + public static string FormatTime(int ticks, bool leadingMinuteZero, int timestep) { - var seconds = (int)Math.Ceiling(ticks / 25f); + var seconds = (int)Math.Ceiling(ticks * timestep / 1000f); return FormatTimeSeconds(seconds, leadingMinuteZero); } diff --git a/OpenRA.Mods.Common/Scripting/Global/UtilsGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/UtilsGlobal.cs index 08acf4219e..c5aba7459b 100644 --- a/OpenRA.Mods.Common/Scripting/Global/UtilsGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/UtilsGlobal.cs @@ -19,7 +19,12 @@ namespace OpenRA.Mods.Common.Scripting [ScriptGlobal("Utils")] public class UtilsGlobal : ScriptGlobal { - public UtilsGlobal(ScriptContext context) : base(context) { } + readonly World world; + public UtilsGlobal(ScriptContext context) + : base(context) + { + world = context.World; + } [Desc("Calls a function on every element in a collection.")] public void Do(LuaValue[] collection, LuaFunction func) @@ -101,7 +106,7 @@ namespace OpenRA.Mods.Common.Scripting [Desc("Returns the ticks formatted to HH:MM:SS.")] public string FormatTime(int ticks, bool leadingMinuteZero = true) { - return WidgetUtils.FormatTime(ticks, leadingMinuteZero); + return WidgetUtils.FormatTime(ticks, leadingMinuteZero, world.Timestep); } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs index 4de3ed228b..bf2c8d8564 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (status == null && shouldShowStatus()) return statusText(); - return WidgetUtils.FormatTime(world.WorldTick); + return WidgetUtils.FormatTime(world.WorldTick, world.Timestep); }; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ProductionTooltipLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ProductionTooltipLogic.cs index 5ddcfd5733..13f05dceaa 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ProductionTooltipLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ProductionTooltipLogic.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class ProductionTooltipLogic { [ObjectCreator.UseCtor] - public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette) + public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette, World world) { var mapRules = palette.World.Map.Rules; var pm = palette.World.LocalPlayer.PlayerActor.Trait(); @@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var lowpower = pm.PowerState != PowerState.Normal; var time = palette.CurrentQueue == null ? 0 : palette.CurrentQueue.GetBuildTime(actor.Name) * (lowpower ? palette.CurrentQueue.Info.LowPowerSlowdown : 1); - var timeString = WidgetUtils.FormatTime(time); + var timeString = WidgetUtils.FormatTime(time, world.Timestep); timeLabel.GetText = () => timeString; timeLabel.GetColor = () => lowpower ? Color.Red : Color.White; diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs index acd3a781cd..be92013d90 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using OpenRA.Network; using OpenRA.Widgets; @@ -18,12 +19,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic { enum PlaybackSpeed { Regular, Slow, Fast, Maximum } - readonly Dictionary timesteps = new Dictionary() + readonly Dictionary multipliers = new Dictionary() { - { PlaybackSpeed.Regular, Game.Timestep }, - { PlaybackSpeed.Slow, Game.Timestep * 2 }, - { PlaybackSpeed.Fast, Game.Timestep / 2 }, - { PlaybackSpeed.Maximum, 1 }, + { PlaybackSpeed.Regular, 1 }, + { PlaybackSpeed.Slow, 2 }, + { PlaybackSpeed.Fast, 0.5f }, + { PlaybackSpeed.Maximum, 0.001f }, }; [ObjectCreator.UseCtor] @@ -41,6 +42,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic container.Visible = true; var speed = PlaybackSpeed.Regular; + var originalTimestep = world.Timestep; var pauseButton = widget.Get("BUTTON_PAUSE"); pauseButton.IsVisible = () => world.Timestep != 0 && orderManager.NetFrameNumber < replayNetTicks; @@ -48,7 +50,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var playButton = widget.Get("BUTTON_PLAY"); playButton.IsVisible = () => world.Timestep == 0 || orderManager.NetFrameNumber >= replayNetTicks; - playButton.OnClick = () => world.Timestep = timesteps[speed]; + playButton.OnClick = () => world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]); playButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks; var slowButton = widget.Get("BUTTON_SLOW"); @@ -58,7 +60,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { speed = PlaybackSpeed.Slow; if (world.Timestep != 0) - world.Timestep = timesteps[speed]; + world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]); }; var normalSpeedButton = widget.Get("BUTTON_REGULAR"); @@ -68,7 +70,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { speed = PlaybackSpeed.Regular; if (world.Timestep != 0) - world.Timestep = timesteps[speed]; + world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]); }; var fastButton = widget.Get("BUTTON_FAST"); @@ -78,7 +80,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { speed = PlaybackSpeed.Fast; if (world.Timestep != 0) - world.Timestep = timesteps[speed]; + world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]); }; var maximumButton = widget.Get("BUTTON_MAXIMUM"); @@ -88,7 +90,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { speed = PlaybackSpeed.Maximum; if (world.Timestep != 0) - world.Timestep = timesteps[speed]; + world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]); }; } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs index f55aae2244..28de306f92 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class SupportPowerTooltipLogic { [ObjectCreator.UseCtor] - public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette) + public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette, World world) { widget.IsVisible = () => palette.TooltipIcon != null; var nameLabel = widget.Get("NAME"); @@ -46,8 +46,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (sp.Info == null) return; // no instances actually exist (race with destroy) - time = "{0} / {1}".F(WidgetUtils.FormatTime(sp.RemainingTime), - WidgetUtils.FormatTime(sp.Info.ChargeTime * 25)); + var remaining = WidgetUtils.FormatTime(sp.RemainingTime, world.Timestep); + var total = WidgetUtils.FormatTime(sp.Info.ChargeTime * 25, world.Timestep); + time = "{0} / {1}".F(remaining, total); if (sp == lastPower) return; diff --git a/OpenRA.Mods.Common/Widgets/ObserverProductionIconsWidget.cs b/OpenRA.Mods.Common/Widgets/ObserverProductionIconsWidget.cs index d44c9ab2bf..8acaa27032 100644 --- a/OpenRA.Mods.Common/Widgets/ObserverProductionIconsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ObserverProductionIconsWidget.cs @@ -92,18 +92,18 @@ namespace OpenRA.Mods.Common.Widgets WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(bi.IconPalette), 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; - var text = GetOverlayForItem(current); + var text = GetOverlayForItem(current, world.Timestep); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } } - static string GetOverlayForItem(ProductionItem item) + static string GetOverlayForItem(ProductionItem item, int timestep) { if (item.Paused) return "ON HOLD"; if (item.Done) return "READY"; - return WidgetUtils.FormatTime(item.RemainingTimeActual); + return WidgetUtils.FormatTime(item.RemainingTimeActual, timestep); } public override Widget Clone() diff --git a/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs b/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs index 7541c3cf64..c167828722 100644 --- a/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs @@ -82,18 +82,18 @@ namespace OpenRA.Mods.Common.Widgets WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(item.Info.IconPalette), 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; - var text = GetOverlayForItem(item); + var text = GetOverlayForItem(item, world.Timestep); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } } - static string GetOverlayForItem(SupportPowerInstance item) + static string GetOverlayForItem(SupportPowerInstance item, int timestep) { if (item.Disabled) return "ON HOLD"; if (item.Ready) return "READY"; - return WidgetUtils.FormatTime(item.RemainingTime); + return WidgetUtils.FormatTime(item.RemainingTime, timestep); } public override Widget Clone() diff --git a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs index a3ca17598d..5fad243947 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs @@ -162,7 +162,7 @@ namespace OpenRA.Mods.Common.Widgets { if (TooltipContainer != null) tooltipContainer.Value.SetTooltip(TooltipTemplate, - new WidgetArgs() { { "palette", this } }); + new WidgetArgs() { { "world", World }, { "palette", this } }); } public override void MouseExited() @@ -353,7 +353,7 @@ namespace OpenRA.Mods.Common.Widgets var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset; overlayFont = Game.Renderer.Fonts["TinyBold"]; - timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; + timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2; queuedOffset = new float2(4, 2); holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; @@ -400,7 +400,7 @@ namespace OpenRA.Mods.Common.Widgets var waiting = first != CurrentQueue.CurrentItem() && !first.Done; if (first.Done) { - if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber / 9 % 2 == 0) + if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber * worldRenderer.World.Timestep / 360 % 2 == 0) overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, Color.Black, 1); @@ -410,7 +410,7 @@ namespace OpenRA.Mods.Common.Widgets icon.Pos + holdOffset, Color.White, Color.Black, 1); else if (!waiting) - overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.RemainingTimeActual), + overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.RemainingTimeActual, World.Timestep), icon.Pos + timeOffset, Color.White, Color.Black, 1); diff --git a/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs b/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs index ef46e7dd28..2f60452728 100644 --- a/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs +++ b/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Widgets var isVictory = pendingWinner == world.LocalPlayer || !WorldUtils.AreMutualAllies(pendingWinner, world.LocalPlayer); var tc = "Strategic {0} in {1}".F( isVictory ? "victory" : "defeat", - WidgetUtils.FormatTime(winnerSvc.TicksLeft)); + WidgetUtils.FormatTime(winnerSvc.TicksLeft, world.Timestep)); var font = Game.Renderer.Fonts["Bold"]; diff --git a/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs index e53fb129d1..6ea4c8ef1b 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs @@ -23,12 +23,14 @@ namespace OpenRA.Mods.Common.Widgets public readonly string Format = "{0}: {1}"; public readonly TimerOrder Order = TimerOrder.Descending; + readonly World world; 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) @@ -39,7 +41,7 @@ namespace OpenRA.Mods.Common.Widgets { texts = powers.Select(p => { - var time = WidgetUtils.FormatTime(p.RemainingTime, false); + var time = WidgetUtils.FormatTime(p.RemainingTime, false, world.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); diff --git a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs index bbbe88f62b..6c1a4accaa 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs @@ -142,7 +142,7 @@ namespace OpenRA.Mods.Common.Widgets holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; - timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; + timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, worldRenderer.World.Timestep)) / 2; // Icons foreach (var p in icons.Values) @@ -171,7 +171,7 @@ namespace OpenRA.Mods.Common.Widgets p.Pos + holdOffset, Color.White, Color.Black, 1); else - overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime), + overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime, worldRenderer.World.Timestep), p.Pos + timeOffset, Color.White, Color.Black, 1); } @@ -189,7 +189,7 @@ namespace OpenRA.Mods.Common.Widgets return; tooltipContainer.Value.SetTooltip(TooltipTemplate, - new WidgetArgs() { { "palette", this } }); + new WidgetArgs() { { "world", worldRenderer.World }, { "palette", this } }); } public override void MouseExited()