From 175b07c0ff7d3661b968b88c677c279aac773a51 Mon Sep 17 00:00:00 2001 From: geckosoft Date: Mon, 15 Nov 2010 14:43:28 +0100 Subject: [PATCH] Added: StrategicProgressWidget to show the capturing progress (including custom gfx) Fixed: Sync on unsyncable field type Added: StrategicProgressWidget to both cnc & ra --- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 1 + .../Strategic/StrategicVictoryConditions.cs | 6 +- .../Widgets/StrategicProgressWidget.cs | 116 ++++++++++++++++++ mods/cnc/chrome.xml | 8 ++ mods/cnc/chrome/ingame.yaml | 4 + mods/cnc/uibits/strategic.png | Bin 0 -> 3461 bytes mods/ra/chrome.xml | 8 ++ mods/ra/chrome/ingame.yaml | 4 + mods/ra/uibits/strategic.png | Bin 0 -> 3461 bytes 9 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 OpenRA.Mods.RA/Widgets/StrategicProgressWidget.cs create mode 100644 mods/cnc/uibits/strategic.png create mode 100644 mods/ra/uibits/strategic.png diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 73311e8565..567dc468a0 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -263,6 +263,7 @@ + diff --git a/OpenRA.Mods.RA/Strategic/StrategicVictoryConditions.cs b/OpenRA.Mods.RA/Strategic/StrategicVictoryConditions.cs index 111b70b9fb..783f2c1fe3 100644 --- a/OpenRA.Mods.RA/Strategic/StrategicVictoryConditions.cs +++ b/OpenRA.Mods.RA/Strategic/StrategicVictoryConditions.cs @@ -31,12 +31,12 @@ namespace OpenRA.Mods.RA public class StrategicVictoryConditions : ITick { [Sync] public Actor Self; - [Sync] public StrategicVictoryConditionsInfo Info; + public StrategicVictoryConditionsInfo Info; [Sync] public int TicksToHold; [Sync] public bool ResetOnHoldLost; - [Sync] public float RatioRequired; - [Sync] public float CriticalRatioRequired; + public float RatioRequired; + public float CriticalRatioRequired; [Sync] public bool SplitHolds; [Sync] public int TicksLeft = 0; [Sync] public int CriticalTicksLeft = 0; diff --git a/OpenRA.Mods.RA/Widgets/StrategicProgressWidget.cs b/OpenRA.Mods.RA/Widgets/StrategicProgressWidget.cs new file mode 100644 index 0000000000..6255d19c57 --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/StrategicProgressWidget.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using OpenRA.Graphics; +using OpenRA.Traits; +using OpenRA.Widgets; + +namespace OpenRA.Mods.RA.Widgets +{ + public class StrategicProgressWidget : Widget + { + bool Initialised = false; + + public StrategicProgressWidget() { IsVisible = () => true; } + + public override void DrawInner(WorldRenderer wr) + { + if (!Initialised) + Init(wr); + + if (!IsVisible()) return; + int2 offset = int2.Zero; + + var svc = wr.world.players.Select(p => p.Value.PlayerActor.TraitOrDefault()).FirstOrDefault(); + + var totalWidth = (svc.Total + svc.TotalCritical)*32; + int curX = -(totalWidth / 2); + + foreach (var a in wr.world.Actors.Where(a => !a.Destroyed && a.HasTrait() && !a.TraitOrDefault().Critical)) + { + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "unowned"), offset + new float2(RenderBounds.Left + curX, RenderBounds.Top)); + + if (a.Owner == wr.world.LocalPlayer || (a.Owner.Stances[wr.world.LocalPlayer] == Stance.Ally && wr.world.LocalPlayer.Stances[a.Owner] == Stance.Ally)) + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "player_owned"), offset + new float2(RenderBounds.Left + curX, RenderBounds.Top)); + else if (!a.Owner.NonCombatant) + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "enemy_owned"), offset + new float2(RenderBounds.Left + curX, RenderBounds.Top)); + curX += 32; + } + + foreach (var a in wr.world.Actors.Where(a => !a.Destroyed && a.HasTrait() && a.TraitOrDefault().Critical)) + { + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "critical_unowned"), offset + new float2(RenderBounds.Left + curX, RenderBounds.Top)); + + if (a.Owner == wr.world.LocalPlayer || (a.Owner.Stances[wr.world.LocalPlayer] == Stance.Ally && wr.world.LocalPlayer.Stances[a.Owner] == Stance.Ally)) + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "player_owned"), offset + new float2(RenderBounds.Left + curX, RenderBounds.Top)); + else if (!a.Owner.NonCombatant) + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "enemy_owned"), offset + new float2(RenderBounds.Left + curX, RenderBounds.Top)); + + curX += 32; + } + offset += new int2(0, 32); + + var pendingWinner = FindFirstWinningPlayer(wr.world); + if (pendingWinner == null) return; + svc = pendingWinner.PlayerActor.TraitOrDefault(); + + if (wr.world.LocalPlayer == null) + { + }else + { + var tc = ""; + + if (pendingWinner != wr.world.LocalPlayer && (pendingWinner.Stances[wr.world.LocalPlayer] != Stance.Ally || wr.world.LocalPlayer.Stances[pendingWinner] != Stance.Ally)) + { + // losing + tc = "Strategic defeat in " + ((svc.CriticalTicksLeft > svc.TicksLeft) ? svc.CriticalTicksLeft / 25 : svc.TicksLeft / 25) + " second(s)"; + }else + { + // winning + tc = "Strategic victory in " + ((svc.CriticalTicksLeft > svc.TicksLeft) ? svc.CriticalTicksLeft / 25 : svc.TicksLeft / 25) + " second(s)"; + } + + var size = Game.Renderer.BoldFont.Measure(tc); + + Game.Renderer.BoldFont.DrawText(tc, offset + new float2(RenderBounds.Left - size.X / 2 + 1, RenderBounds.Top + 1), Color.Black); + Game.Renderer.BoldFont.DrawText(tc, offset + new float2(RenderBounds.Left - size.X / 2, RenderBounds.Top), Color.WhiteSmoke); + offset += new int2(0, size.Y + 1); + } + + } + + public Player FindFirstWinningPlayer(World world) + { + // loop through all players, see who is 'winning' and get the one with the shortest 'time to win' + int shortest = int.MaxValue; + Player shortestPlayer = null; + + foreach (var p in world.players.Select(p => p.Value).Where(p => !p.NonCombatant)) + { + var svc = p.PlayerActor.TraitOrDefault(); + + if (svc.HoldingCritical && svc.CriticalTicksLeft > 0 && svc.CriticalTicksLeft < shortest) + { + shortest = svc.CriticalTicksLeft; + shortestPlayer = p; + } + + if (svc.Holding && svc.TicksLeft > 0 && svc.TicksLeft < shortest) + { + shortest = svc.CriticalTicksLeft; + shortestPlayer = p; + } + } + + return shortestPlayer; + } + + private void Init(WorldRenderer wr) + { + IsVisible = () => (wr.world.Actors.Where(a => a.HasTrait()).Any() && wr.world.Actors.Where(a => a.HasTrait()).Any()); + Initialised = true; + } + } +} diff --git a/mods/cnc/chrome.xml b/mods/cnc/chrome.xml index c1c45660c0..66086c8446 100644 --- a/mods/cnc/chrome.xml +++ b/mods/cnc/chrome.xml @@ -209,4 +209,12 @@ + + + + + + + + diff --git a/mods/cnc/chrome/ingame.yaml b/mods/cnc/chrome/ingame.yaml index ca056a4278..5d10e5ab08 100644 --- a/mods/cnc/chrome/ingame.yaml +++ b/mods/cnc/chrome/ingame.yaml @@ -21,6 +21,10 @@ Container@INGAME_ROOT: Id:GAME_TIMER X: WINDOW_RIGHT/2 Y: 10 + StrategicProgress@STRATEGIC_PROGRESS: + Id:STRATEGIC_PROGRESS + X: WINDOW_RIGHT/2 + Y: 40 Background@POSTGAME_BG: Id:POSTGAME_BG X:(WINDOW_RIGHT - WIDTH)/2 diff --git a/mods/cnc/uibits/strategic.png b/mods/cnc/uibits/strategic.png new file mode 100644 index 0000000000000000000000000000000000000000..aec7756e769a836246598f71e602afb9e2395688 GIT binary patch literal 3461 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 + + + + + + + + diff --git a/mods/ra/chrome/ingame.yaml b/mods/ra/chrome/ingame.yaml index cbec32b27b..7062c727d2 100644 --- a/mods/ra/chrome/ingame.yaml +++ b/mods/ra/chrome/ingame.yaml @@ -22,6 +22,10 @@ Container@INGAME_ROOT: Id:GAME_TIMER X: WINDOW_RIGHT/2 Y: 10 + StrategicProgress@STRATEGIC_PROGRESS: + Id:STRATEGIC_PROGRESS + X: WINDOW_RIGHT/2 + Y: 40 Background@POSTGAME_BG: Id:POSTGAME_BG X:(WINDOW_RIGHT - WIDTH)/2 diff --git a/mods/ra/uibits/strategic.png b/mods/ra/uibits/strategic.png new file mode 100644 index 0000000000000000000000000000000000000000..aec7756e769a836246598f71e602afb9e2395688 GIT binary patch literal 3461 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