diff --git a/OpenRA.Game/Traits/RevealsShroud.cs b/OpenRA.Game/Traits/RevealsShroud.cs index 64408e0ddb..17a9de7fe9 100644 --- a/OpenRA.Game/Traits/RevealsShroud.cs +++ b/OpenRA.Game/Traits/RevealsShroud.cs @@ -10,13 +10,13 @@ namespace OpenRA.Traits { - class RevealsShroudInfo : ITraitInfo + public class RevealsShroudInfo : ITraitInfo { public readonly int Range = 0; public object Create(ActorInitializer init) { return new RevealsShroud(this); } } - class RevealsShroud : ITick + public class RevealsShroud : ITick { RevealsShroudInfo Info; CPos previousLocation; diff --git a/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs index 58093544db..5adb5dc2bf 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs @@ -24,13 +24,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic ContainerWidget basicStatsHeaders; ContainerWidget economicStatsHeaders; ContainerWidget productionStatsHeaders; + ContainerWidget combatStatsHeaders; ScrollPanelWidget playerStatsPanel; ScrollItemWidget basicPlayerTemplate; ScrollItemWidget economicPlayerTemplate; ScrollItemWidget productionPlayerTemplate; + ScrollItemWidget combatPlayerTemplate; ScrollItemWidget teamTemplate; DropDownButtonWidget statsDropDown; - LabelWidget title; IEnumerable players; World world; @@ -40,11 +41,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic this.world = world; players = world.Players.Where(p => !p.NonCombatant); - title = widget.Get("TITLE"); - basicStatsHeaders = widget.Get("BASIC_STATS_HEADERS"); economicStatsHeaders = widget.Get("ECONOMIC_STATS_HEADERS"); productionStatsHeaders = widget.Get("PRODUCTION_STATS_HEADERS"); + combatStatsHeaders = widget.Get("COMBAT_STATS_HEADERS"); playerStatsPanel = widget.Get("PLAYER_STATS_PANEL"); playerStatsPanel.Layout = new GridLayout(playerStatsPanel); @@ -52,6 +52,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic basicPlayerTemplate = playerStatsPanel.Get("BASIC_PLAYER_TEMPLATE"); economicPlayerTemplate = playerStatsPanel.Get("ECONOMIC_PLAYER_TEMPLATE"); productionPlayerTemplate = playerStatsPanel.Get("PRODUCTION_PLAYER_TEMPLATE"); + combatPlayerTemplate = playerStatsPanel.Get("COMBAT_PLAYER_TEMPLATE"); teamTemplate = playerStatsPanel.Get("TEAM_TEMPLATE"); @@ -93,6 +94,17 @@ namespace OpenRA.Mods.RA.Widgets.Logic statsDropDown.GetText = () => "Production"; LoadStats(ProductionStats); } + }, + new StatsDropDownOption + { + Title = "Combat", + IsSelected = () => combatStatsHeaders.Visible, + OnClick = () => + { + ClearStats(); + statsDropDown.GetText = () => "Combat"; + LoadStats(CombatStats); + } } }; Func setupItem = (option, template) => @@ -101,7 +113,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic item.Get("LABEL").GetText = () => option.Title; return item; }; - statsDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 100, options, setupItem); + statsDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, setupItem); }; widget.Height = (200 + (Math.Min(8, players.Count()) * 25)).ToString(); @@ -117,6 +129,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic basicStatsHeaders.Visible = false; economicStatsHeaders.Visible = false; productionStatsHeaders.Visible = false; + combatStatsHeaders.Visible = false; } void LoadStats(Func forEachPlayer) @@ -137,6 +150,27 @@ namespace OpenRA.Mods.RA.Widgets.Logic } } + ScrollItemWidget CombatStats(Player player) + { + combatStatsHeaders.Visible = true; + var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player); + + AddPlayerFlagAndName(template, player); + + template.Get("MAP_CONTROL").GetText = () => + { + var total = world.Map.Bounds.Width * world.Map.Bounds.Height; + var controlled = world.Actors + .Where(a => !a.IsDead() && a.IsInWorld && a.Owner == player && a.HasTrait()) + .SelectMany(a => world.FindTilesInCircle(a.Location, a.Trait().RevealRange)) + .Distinct() + .Count(); + return Round((double)controlled / total * 100).ToString("F1") + "%"; + }; + + return template; + } + ScrollItemWidget ProductionStats(Player player) { productionStatsHeaders.Visible = true; @@ -164,10 +198,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic template.Get("CASH").GetText = () => "$" + (res.DisplayCash + res.DisplayOre); template.Get("INCOME").GetText = () => "$" + res.IncomePerMinute; var change = template.Get("INCOME_CHANGE"); - change.GetText = () => Math.Round(res.IncomeChange * 100, 1, MidpointRounding.AwayFromZero) + "%"; + change.GetText = () => Round(res.IncomeChange * 100) + "%"; change.GetColor = () => { - var c = Math.Round(res.IncomeChange * 100, 1, MidpointRounding.AwayFromZero); + var c = Round(res.IncomeChange * 100); if (c < 0) return Color.Red; if (c > 0) return Color.LimeGreen; return Color.White; @@ -222,6 +256,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic }); } + static double Round(double value) + { + return Math.Round(value, 1, MidpointRounding.AwayFromZero); + } + static void AddPlayerFlagAndName(ScrollItemWidget template, Player player) { var flag = template.Get("FLAG"); diff --git a/mods/ra/chrome/ingame.yaml b/mods/ra/chrome/ingame.yaml index 81c3e18e08..8c07e27480 100644 --- a/mods/ra/chrome/ingame.yaml +++ b/mods/ra/chrome/ingame.yaml @@ -559,6 +559,26 @@ Container@OBSERVER_ROOT: Height:25 Font:Bold Text:Support Powers + Container@COMBAT_STATS_HEADERS: + X:0 + Y:0 + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Children: + Label@PLAYER_HEADER: + X:85 + Y:40 + Width:160 + Height:25 + Font:Bold + Text:Player + Label@MAP_CONTROL_HEADER: + X:245 + Y:40 + Width:60 + Height:25 + Font:Bold + Text:Map Control ScrollPanel@PLAYER_STATS_PANEL: X:25 Y:70 @@ -714,6 +734,30 @@ Container@OBSERVER_ROOT: Y:0 Width:320 Height:PARENT_BOTTOM + ScrollItem@COMBAT_PLAYER_TEMPLATE: + X:0 + Y:0 + Width:PARENT_RIGHT-35 + Height:25 + Children: + Image@FLAG: + X:20 + Y:5 + Width:35 + Height:PARENT_BOTTOM-5 + ImageName:random + ImageCollection:flags + Label@PLAYER: + X:55 + Y:0 + Width:160 + Height:PARENT_BOTTOM + Font:Bold + Label@MAP_CONTROL + X:215 + Y:0 + Width:60 + Height:PARENT_BOTTOM Background@FMVPLAYER: Width:WINDOW_RIGHT Height:WINDOW_BOTTOM