diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 9c41d37d09..ed0ad3a5c5 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -372,6 +372,7 @@ + diff --git a/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs index 7fb99de8fe..888404372b 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs @@ -45,6 +45,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic optionsBG.Get("MUSIC").OnClick = () => Ui.OpenWindow("MUSIC_MENU"); optionsBG.Get("RESUME").OnClick = () => optionsBG.Visible = false; optionsBG.Get("SURRENDER").IsVisible = () => false; + + Ui.Root.Get("INGAME_STATS_BUTTON").OnClick = () => + { + var stats = gameRoot.Get("OBSERVER_STATS"); + stats.Visible = !stats.Visible; + }; } void UnregisterEvents() diff --git a/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs new file mode 100644 index 0000000000..be4d6062a3 --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/Logic/ObserverStatsLogic.cs @@ -0,0 +1,100 @@ +#region Copyright & License Information +/* + * Copyright 2007-2012 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.Linq; +using OpenRA.Traits; +using OpenRA.Widgets; +using OpenRA.Network; +using System.Collections.Generic; +using OpenRA.Mods.RA.Buildings; +using System.Drawing; +using OpenRA.Graphics; +using System; + +namespace OpenRA.Mods.RA.Widgets.Logic +{ + public class ObserverStatsLogic + { + ScrollPanelWidget playersPanel; + ScrollItemWidget playerTemplate; + ScrollItemWidget teamTemplate; + + [ObjectCreator.UseCtor] + public ObserverStatsLogic(World world, Widget widget) + { + playersPanel = widget.Get("PLAYERS"); + playerTemplate = playersPanel.Get("PLAYER_TEMPLATE"); + teamTemplate = playersPanel.Get("TEAM_TEMPLATE"); + playersPanel.RemoveChildren(); + playersPanel.Layout = new GridLayout(playersPanel); + + var players = world.Players.Where(p => !p.NonCombatant); + + widget.Height = (200 + (Math.Min(8, players.Count()) * 25)).ToString(); + var args = new WidgetArgs(); + widget.Initialize(args); + widget.Get("BACKGROUND").Initialize(args); + widget.Get("PLAYERS").Initialize(args); + + var teams = players.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.ClientIndex) ?? new Session.Client()).Team).OrderBy(g => g.Key); + foreach (var t in teams) + { + var team = t; + var tt = ScrollItemWidget.Setup(teamTemplate, () => false, () => { }); + tt.IgnoreMouseOver = true; + tt.Get("TEAM").GetText = () => team.Key == 0 ? "No team" : "Team " + team.Key; + playersPanel.AddChild(tt); + foreach (var p in team) + { + var player = p; + var template = ScrollItemWidget.Setup(playerTemplate, () => false, null); + template.OnClick = () => + { + var index = playersPanel.Children.Where(c => c.GetOrNull("PLAYER") != null).ToList().FindIndex(w => w == template); + var selectedPlayer = teams.SelectMany(x => x).ElementAt(index); + var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead() && a.HasTrait() && a.Owner == selectedPlayer); + if (playerBase != null) + { + Game.MoveViewport(playerBase.Location.ToFloat2()); + } + }; + + var flag = template.Get("FACTION_FLAG"); + flag.GetImageName = () => player.Country.Race; + flag.GetImageCollection = () => "flags"; + + var playerName = template.Get("PLAYER"); + playerName.GetText = () => player.PlayerName + (player.WinState == WinState.Undefined ? "" : " (" + player.WinState + ")"); + playerName.GetColor = () => player.ColorRamp.GetColor(0); + + var res = player.PlayerActor.Trait(); + template.Get("CASH").GetText = () => "$" + (res.DisplayCash + res.DisplayOre); + + var powerRes = player.PlayerActor.Trait(); + var power = template.Get("POWER"); + power.GetText = () => powerRes.PowerDrained + "/" + powerRes.PowerProvided; + power.GetColor = () => GetPowerColor(powerRes.PowerState); + + template.Get("KILLS").GetText = () => player.Kills.ToString(); + template.Get("DEATHS").GetText = () => player.Deaths.ToString(); + + playersPanel.AddChild(template); + } + } + } + + static Color GetPowerColor(PowerState state) + { + if (state == PowerState.Critical) return Color.Red; + if (state == PowerState.Low) return Color.Orange; + return Color.LimeGreen; + } + } +} diff --git a/mods/ra/chrome/ingame.yaml b/mods/ra/chrome/ingame.yaml index 57d5d0a6ea..464dcb8aa9 100644 --- a/mods/ra/chrome/ingame.yaml +++ b/mods/ra/chrome/ingame.yaml @@ -287,6 +287,13 @@ Container@OBSERVER_ROOT: Text:Options Font:Bold Key:escape + Button@INGAME_STATS_BUTTON: + X:162 + Y:0 + Width:160 + Height:25 + Text:Players + Font:Bold Background@RADAR_BG: X:WINDOW_RIGHT-255 Y:5 @@ -384,6 +391,124 @@ Container@OBSERVER_ROOT: Y:205 Width:170 Height:40 + Container@OBSERVER_STATS: + Logic:ObserverStatsLogic + X:25 + Y:50 + Width:565 + Height:400 + Visible:false + Children: + Background@BACKGROUND: + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Background:dialog + Children: + Label@TITLE: + X:0 + Y:15 + Width:PARENT_RIGHT + Height:25 + Font:Bold + Align:Center + Text:Players + Label@PLAYER_HEADER: + X:85 + Y:40 + Width:160 + Height:25 + Font:Bold + Text:Player + Label@CASH_HEADER: + X:245 + Y:40 + Width:80 + Height:25 + Font:Bold + Text:Cash + Label@POWER_HEADER + X:325 + Y:40 + Width:80 + Height:25 + Font:Bold + Text:Power + Label@KILLS_HEADER: + X:405 + Y:40 + Width:40 + Height:25 + Font:Bold + Text:Kills + Align:Right + Label@DEATHS_HEADER: + X:465 + Y:40 + Width:40 + Height:25 + Font:Bold + Text:Deaths + Align:Right + ScrollPanel@PLAYERS: + X:25 + Y:70 + Width:PARENT_RIGHT-50 + Height:PARENT_BOTTOM-45-50 + ItemSpacing:5 + Children: + ScrollItem@TEAM_TEMPLATE: + X:0 + Y:0 + Width:PARENT_RIGHT-30 + Height:25 + Children: + Label@TEAM: + X:0 + Y:0 + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Font:Bold + ScrollItem@PLAYER_TEMPLATE: + X:0 + Y:0 + Width:PARENT_RIGHT-30 + Height:25 + Children: + Image@FACTION_FLAG: + X:15 + Y:5 + Width:40 + Height:PARENT_BOTTOM + ImageName:random + ImageCollection:flags + Label@PLAYER: + X:55 + Y:0 + Width:160 + Height:PARENT_BOTTOM + Font:Bold + Label@CASH: + X:215 + Y:0 + Width:80 + Height:PARENT_BOTTOM + Label@POWER: + X:295 + Y:0 + Width:80 + Height:PARENT_BOTTOM + Label@KILLS: + X:375 + Y:0 + Width:40 + Height:PARENT_BOTTOM + Align:Right + Label@DEATHS: + X:415 + Y:0 + Width:40 + Height:PARENT_BOTTOM + Align:Right Background@FMVPLAYER: Width:WINDOW_RIGHT Height:WINDOW_BOTTOM