diff --git a/OpenRA.Game/Widgets/WidgetUtils.cs b/OpenRA.Game/Widgets/WidgetUtils.cs index 6f3f1ac19f..ae4a42fb91 100644 --- a/OpenRA.Game/Widgets/WidgetUtils.cs +++ b/OpenRA.Game/Widgets/WidgetUtils.cs @@ -141,21 +141,31 @@ namespace OpenRA.Widgets DrawRGBA(ss[7], new float2(bounds.Right - ss[7].size.X, bounds.Bottom - ss[7].size.Y)); } - public static string FormatTime(int ticks) + { + return FormatTime(ticks, true); + } + + public static string FormatTime(int ticks, bool leadingMinuteZero) { var seconds = (int)Math.Ceiling(ticks / 25f); - return FormatTimeSeconds( seconds ); + return FormatTimeSeconds(seconds, leadingMinuteZero); } public static string FormatTimeSeconds(int seconds) + { + return FormatTimeSeconds(seconds, true); + } + + public static string FormatTimeSeconds(int seconds, bool leadingMinuteZero) { var minutes = seconds / 60; if (minutes >= 60) return "{0:D}:{1:D2}:{2:D2}".F(minutes / 60, minutes % 60, seconds % 60); - else + if (leadingMinuteZero) return "{0:D2}:{1:D2}".F(minutes, seconds % 60); + return "{0:D}:{1:D2}".F(minutes, seconds % 60); } public static string WrapText(string text, int width, SpriteFont font) diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/SupportPowerTooltipLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/SupportPowerTooltipLogic.cs index e54cf36e36..85060a45a3 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/SupportPowerTooltipLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/SupportPowerTooltipLogic.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic var baseHeight = widget.Bounds.Height; var timeOffset = timeLabel.Bounds.X; - SupportPowerManager.SupportPowerInstance lastPower = null; + SupportPowerInstance lastPower = null; tooltipContainer.BeforeRender = () => { var sp = palette.TooltipPower; diff --git a/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs b/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs index 375ec3ee97..3f6b20a2a4 100755 --- a/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs +++ b/OpenRA.Mods.Cnc/Widgets/SupportPowersWidget.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc.Widgets public readonly string TooltipContainer; public readonly string TooltipTemplate = "SUPPORT_POWER_TOOLTIP"; - public SupportPowerManager.SupportPowerInstance TooltipPower { get; private set; } + public SupportPowerInstance TooltipPower { get; private set; } Lazy tooltipContainer; Rectangle eventBounds; @@ -61,7 +61,7 @@ namespace OpenRA.Mods.Cnc.Widgets public class SupportPowerIcon { - public SupportPowerManager.SupportPowerInstance Power; + public SupportPowerInstance Power; public float2 Pos; public Sprite Sprite; } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 17ab4884c0..7073279bc8 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -410,6 +410,7 @@ + diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPower.cs b/OpenRA.Mods.RA/SupportPowers/SupportPower.cs index 8ae0f094b2..e7fecd849e 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPower.cs @@ -28,6 +28,8 @@ namespace OpenRA.Mods.RA public readonly string SelectTargetSound = null; public readonly string LaunchSound = null; + public readonly bool DisplayTimer = false; + public readonly string OrderName; public abstract object Create(ActorInitializer init); diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs index c3c34b4f2c..bb9ba10718 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs @@ -83,7 +83,7 @@ namespace OpenRA.Mods.RA public void Tick(Actor self) { - foreach(var power in Powers.Values) + foreach (var power in Powers.Values) power.Tick(); } @@ -100,7 +100,7 @@ namespace OpenRA.Mods.RA Powers[key].Target(); } - static readonly SupportPowerInstance[] NoInstances = {}; + static readonly SupportPowerInstance[] NoInstances = { }; public IEnumerable GetPowersForActor(Actor a) { @@ -110,85 +110,85 @@ namespace OpenRA.Mods.RA return a.TraitsImplementing() .Select(t => Powers[MakeKey(t)]); } + } - public class SupportPowerInstance + public class SupportPowerInstance + { + readonly SupportPowerManager Manager; + readonly string Key; + + public List Instances; + public int RemainingTime; + public int TotalTime; + public bool Active { get; private set; } + public bool Disabled { get; private set; } + + public SupportPowerInfo Info { get { return Instances.Select(i => i.Info).FirstOrDefault(); } } + public bool Ready { get { return Active && RemainingTime == 0; } } + + public SupportPowerInstance(string key, SupportPowerManager manager) { - readonly SupportPowerManager Manager; - readonly string Key; + Manager = manager; + Key = key; + } - public List Instances; - public int RemainingTime; - public int TotalTime; - public bool Active { get; private set; } - public bool Disabled { get; private set; } + static bool InstanceDisabled(SupportPower sp) + { + return sp.self.TraitsImplementing().Any(d => d.Disabled); + } - public SupportPowerInfo Info { get { return Instances.Select(i => i.Info).FirstOrDefault(); } } - public bool Ready { get { return Active && RemainingTime == 0; } } + bool notifiedCharging; + bool notifiedReady; + public void Tick() + { + Active = !Disabled && Instances.Any(i => !i.self.IsDisabled()); + if (!Active) + return; - public SupportPowerInstance(string key, SupportPowerManager manager) + if (Active) { - Manager = manager; - Key = key; - } + var power = Instances.First(); + if (Manager.devMode.FastCharge && RemainingTime > 25) + RemainingTime = 25; - static bool InstanceDisabled(SupportPower sp) - { - return sp.self.TraitsImplementing().Any(d => d.Disabled); - } - - bool notifiedCharging; - bool notifiedReady; - public void Tick() - { - Active = !Disabled && Instances.Any(i => !i.self.IsDisabled()); - if (!Active) - return; - - if (Active) + if (RemainingTime > 0) --RemainingTime; + if (!notifiedCharging) { - var power = Instances.First(); - if (Manager.devMode.FastCharge && RemainingTime > 25) - RemainingTime = 25; + power.Charging(power.self, Key); + notifiedCharging = true; + } - if (RemainingTime > 0) --RemainingTime; - if (!notifiedCharging) - { - power.Charging(power.self, Key); - notifiedCharging = true; - } - - if (RemainingTime == 0 - && !notifiedReady) - { - power.Charged(power.self, Key); - notifiedReady = true; - } + if (RemainingTime == 0 + && !notifiedReady) + { + power.Charged(power.self, Key); + notifiedReady = true; } } + } - public void Target() - { - if (!Ready) - return; + public void Target() + { + if (!Ready) + return; - Manager.self.World.OrderGenerator = Instances.First().OrderGenerator(Key, Manager); - } + Manager.self.World.OrderGenerator = Instances.First().OrderGenerator(Key, Manager); + } - public void Activate(Order order) - { - if (!Ready) - return; + public void Activate(Order order) + { + if (!Ready) + return; - var power = Instances.First(i => !InstanceDisabled(i)); + var power = Instances.First(i => !InstanceDisabled(i)); - // Note: order.Subject is the *player* actor - power.Activate(power.self, order); - RemainingTime = TotalTime; - notifiedCharging = notifiedReady = false; + // Note: order.Subject is the *player* actor + power.Activate(power.self, order); + RemainingTime = TotalTime; + notifiedCharging = notifiedReady = false; - if (Info.OneShot) - Disabled = true; - } + if (Info.OneShot) + Disabled = true; } } diff --git a/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs b/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs index a95cd6756b..5b1a03aca7 100644 --- a/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs +++ b/OpenRA.Mods.RA/Widgets/ObserverSupportPowerIconsWidget.cs @@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA.Widgets } } - static string GetOverlayForItem(SupportPowerManager.SupportPowerInstance item) + static string GetOverlayForItem(SupportPowerInstance item) { if (item.Disabled) return "ON HOLD"; if (item.Ready) return "READY"; diff --git a/OpenRA.Mods.RA/Widgets/SupportPowerTimerWidget.cs b/OpenRA.Mods.RA/Widgets/SupportPowerTimerWidget.cs new file mode 100644 index 0000000000..f8465d6529 --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/SupportPowerTimerWidget.cs @@ -0,0 +1,65 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Traits; +using OpenRA.Widgets; + +namespace OpenRA.Mods.RA.Widgets +{ + public class SupportPowerTimerWidget : Widget + { + public readonly string Font = "Bold"; + public readonly string Format = "{0}: {1}"; + public readonly TimerOrder Order = TimerOrder.Descending; + + readonly IEnumerable powers; + Pair[] texts; + + [ObjectCreator.UseCtor] + public SupportPowerTimerWidget(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); + } + + public override void Tick() + { + texts = powers.Select(p => + { + var time = WidgetUtils.FormatTime(p.RemainingTime, false); + 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); + }).ToArray(); + } + + public override void Draw() + { + if (!IsVisible() || texts == null) + return; + + var y = 0; + foreach (var t in texts) + { + var font = Game.Renderer.Fonts[Font]; + font.DrawTextWithContrast(t.First, new float2(Bounds.Location) + new float2(0, y), t.Second, Color.Black, 1); + y += (font.Measure(t.First).Y + 5) * (int)Order; + } + } + + public enum TimerOrder { Ascending = -1, Descending = 1 } + } +} diff --git a/mods/ra/chrome/ingame.yaml b/mods/ra/chrome/ingame.yaml index 761cc1b247..52a556b481 100644 --- a/mods/ra/chrome/ingame.yaml +++ b/mods/ra/chrome/ingame.yaml @@ -52,6 +52,10 @@ Container@INGAME_ROOT: Width:170 Height:40 TooltipContainer@TOOLTIP_CONTAINER: + SupportPowerTimer@SUPPORT_POWER_TIMER: + X:15 + Y:WINDOW_BOTTOM-30 + Order:Ascending Container@PLAYER_WIDGETS: Children: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 8b8eba74fe..8dd771b30a 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -35,6 +35,7 @@ MSLO: LaunchSound: alaunch1.aud MissileWeapon: atomic SpawnOffset: 0,427,0 + DisplayTimer: True CanPowerDown: RequiresPower: SupportPowerChargeBar: @@ -849,9 +850,10 @@ ATEK: OneShot: yes ChargeTime: 480 Description: GPS Satellite - LongDesc: Reveals the entire map + LongDesc: Reveals the entire map. RevealDelay: 15 LaunchSound: satlnch1.aud + DisplayTimer: True SupportPowerChargeBar: WEAP: