예제 #1
0
        Widget MakeHistoryWidget(object o)
        {
            var message = (ChatMessage)o;
            var from    = message.Type == ChatMessageType.Notification ? "Battlefield Control" : message.Nick;
            var color   = message.Type == ChatMessageType.Notification ? ChromeMetrics.Get <Color>("GlobalChatNotificationColor")
                                : ChromeMetrics.Get <Color>("GlobalChatPlayerNameColor");
            var template = (ContainerWidget)chatTemplate.Clone();

            LobbyUtils.SetupChatLine(template, color, message.Time, from, message.Message);

            template.Id = message.UID;
            return(template);
        }
예제 #2
0
        void AddChatLine(Color c, string from, string text, bool replayCache)
        {
            if (!replayCache && chatOverlayDisplay != null)
            {
                chatOverlayDisplay.AddLine(c, from, text);
            }

            var template  = chatTemplate.Clone();
            var nameLabel = template.Get <LabelWidget>("NAME");
            var textLabel = template.Get <LabelWidget>("TEXT");

            var name = "";

            if (!string.IsNullOrEmpty(from))
            {
                name = from + ":";
            }

            var font     = Game.Renderer.Fonts[nameLabel.Font];
            var nameSize = font.Measure(from);

            nameLabel.GetColor      = () => c;
            nameLabel.GetText       = () => name;
            nameLabel.Bounds.Width  = nameSize.X;
            textLabel.Bounds.X     += nameSize.X;
            textLabel.Bounds.Width -= nameSize.X;

            // Hack around our hacky wordwrap behavior: need to resize the widget to fit the text
            text = WidgetUtils.WrapText(text, textLabel.Bounds.Width, font);
            textLabel.GetText = () => text;
            var dh = font.Measure(text).Y - textLabel.Bounds.Height;

            if (dh > 0)
            {
                textLabel.Bounds.Height += dh;
                template.Bounds.Height  += dh;
            }

            var scrolledToBottom = chatScrollPanel.ScrolledToBottom;

            chatScrollPanel.AddChild(template);
            if (scrolledToBottom)
            {
                chatScrollPanel.ScrollToBottom(smooth: true);
            }

            if (!replayCache)
            {
                Game.Sound.PlayNotification(modRules, null, "Sounds", "ChatLine", null);
            }
        }
예제 #3
0
        void AddChatLine(TextNotification chatLine, bool suppressSound)
        {
            var template  = chatTemplate.Clone();
            var nameLabel = template.Get <LabelWidget>("NAME");
            var textLabel = template.Get <LabelWidget>("TEXT");

            var name = "";

            if (!string.IsNullOrEmpty(chatLine.Prefix))
            {
                name = chatLine.Prefix + ":";
            }

            var font     = Game.Renderer.Fonts[nameLabel.Font];
            var nameSize = font.Measure(chatLine.Prefix);

            nameLabel.GetColor     = () => chatLine.PrefixColor;
            nameLabel.GetText      = () => name;
            nameLabel.Bounds.Width = nameSize.X;

            textLabel.GetColor      = () => chatLine.TextColor;
            textLabel.Bounds.X     += nameSize.X;
            textLabel.Bounds.Width -= nameSize.X;

            // Hack around our hacky wordwrap behavior: need to resize the widget to fit the text
            var text = WidgetUtils.WrapText(chatLine.Text, textLabel.Bounds.Width, font);

            textLabel.GetText = () => text;
            var dh = font.Measure(text).Y - textLabel.Bounds.Height;

            if (dh > 0)
            {
                textLabel.Bounds.Height += dh;
                template.Bounds.Height  += dh;
            }

            var scrolledToBottom = chatScrollPanel.ScrolledToBottom;

            chatScrollPanel.AddChild(template);
            if (scrolledToBottom)
            {
                chatScrollPanel.ScrollToBottom(smooth: true);
            }

            if (!suppressSound)
            {
                Game.Sound.PlayNotification(modRules, null, "Sounds", chatLineSound, null);
            }
        }
예제 #4
0
        void PopulateObjectivesList(MissionObjectives mo, ScrollPanelWidget parent, ContainerWidget template)
        {
            parent.RemoveChildren();

            foreach (var objective in mo.Objectives.OrderBy(o => o.Type))
            {
                var widget = template.Clone();
                var label  = widget.Get <LabelWidget>("OBJECTIVE_TYPE");
                label.GetText = () => objective.Type;

                var checkbox = widget.Get <CheckboxWidget>("OBJECTIVE_STATUS");
                checkbox.IsChecked    = () => objective.State != ObjectiveState.Incomplete;
                checkbox.GetCheckType = () => objective.State == ObjectiveState.Completed ? "checked" : "crossed";
                checkbox.GetText      = () => objective.Description;

                parent.AddChild(widget);
            }
        }
예제 #5
0
        void PopulateObjectivesList(MissionObjectives mo, ScrollPanelWidget parent, ContainerWidget template)
        {
            parent.RemoveChildren();

            foreach (var o in mo.Objectives.OrderBy(o => o.Type))
            {
                var objective = o; // Work around the loop closure issue in older versions of C#
                var widget = template.Clone();

                var label = widget.Get<LabelWidget>("OBJECTIVE_TYPE");
                label.GetText = () => objective.Type == ObjectiveType.Primary ? "Primary" : "Secondary";

                var checkbox = widget.Get<CheckboxWidget>("OBJECTIVE_STATUS");
                checkbox.IsChecked = () => objective.State != ObjectiveState.Incomplete;
                checkbox.GetCheckType = () => objective.State == ObjectiveState.Completed ? "checked" : "crossed";
                checkbox.GetText = () => objective.Description;

                parent.AddChild(widget);
            }
        }
예제 #6
0
        void PopulateObjectivesList(MissionObjectives mo, ScrollPanelWidget parent, ContainerWidget template)
        {
            parent.RemoveChildren();

            foreach (var o in mo.Objectives.OrderBy(o => o.Type))
            {
                var objective = o;                 // Work around the loop closure issue in older versions of C#
                var widget    = template.Clone();

                var label = widget.Get <LabelWidget>("OBJECTIVE_TYPE");
                label.GetText = () => objective.Type == ObjectiveType.Primary ? "Primary" : "Secondary";

                var checkbox = widget.Get <CheckboxWidget>("OBJECTIVE_STATUS");
                checkbox.IsChecked    = () => objective.State != ObjectiveState.Incomplete;
                checkbox.GetCheckType = () => objective.State == ObjectiveState.Completed ? "checked" : "crossed";
                checkbox.GetText      = () => objective.Description;

                parent.AddChild(widget);
            }
        }
예제 #7
0
        public ObserverStatsLogic(World world, ModData modData, WorldRenderer worldRenderer, Widget widget,
                                  Action onExit, ObserverStatsPanel activePanel, Dictionary <string, MiniYaml> logicArgs)
        {
            this.world         = world;
            this.worldRenderer = worldRenderer;

            MiniYaml yaml;

            string[] keyNames     = Enum.GetNames(typeof(ObserverStatsPanel));
            var      statsHotkeys = new HotkeyReference[keyNames.Length];

            for (var i = 0; i < keyNames.Length; i++)
            {
                statsHotkeys[i] = logicArgs.TryGetValue("Statistics" + keyNames[i] + "Key", out yaml) ? modData.Hotkeys[yaml.Value] : new HotkeyReference();
            }

            players = world.Players.Where(p => !p.NonCombatant);

            basicStatsHeaders            = widget.Get <ContainerWidget>("BASIC_STATS_HEADERS");
            economyStatsHeaders          = widget.Get <ContainerWidget>("ECONOMY_STATS_HEADERS");
            productionStatsHeaders       = widget.Get <ContainerWidget>("PRODUCTION_STATS_HEADERS");
            combatStatsHeaders           = widget.Get <ContainerWidget>("COMBAT_STATS_HEADERS");
            earnedThisMinuteGraphHeaders = widget.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_HEADERS");

            playerStatsPanel        = widget.Get <ScrollPanelWidget>("PLAYER_STATS_PANEL");
            playerStatsPanel.Layout = new GridLayout(playerStatsPanel);

            basicPlayerTemplate           = playerStatsPanel.Get <ScrollItemWidget>("BASIC_PLAYER_TEMPLATE");
            economyPlayerTemplate         = playerStatsPanel.Get <ScrollItemWidget>("ECONOMY_PLAYER_TEMPLATE");
            productionPlayerTemplate      = playerStatsPanel.Get <ScrollItemWidget>("PRODUCTION_PLAYER_TEMPLATE");
            combatPlayerTemplate          = playerStatsPanel.Get <ScrollItemWidget>("COMBAT_PLAYER_TEMPLATE");
            earnedThisMinuteGraphTemplate = playerStatsPanel.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_TEMPLATE");

            teamTemplate = playerStatsPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE");

            var statsDropDown = widget.Get <DropDownButtonWidget>("STATS_DROPDOWN");
            Func <string, ContainerWidget, Action, StatsDropDownOption> createStatsOption = (title, headers, a) =>
            {
                return(new StatsDropDownOption
                {
                    Title = title,
                    IsSelected = () => headers.Visible,
                    OnClick = () =>
                    {
                        ClearStats();
                        statsDropDown.GetText = () => title;
                        a();
                    }
                });
            };

            var statsDropDownOptions = new StatsDropDownOption[]
            {
                createStatsOption("Basic", basicStatsHeaders, () => DisplayStats(BasicStats)),
                createStatsOption("Economy", economyStatsHeaders, () => DisplayStats(EconomyStats)),
                createStatsOption("Production", productionStatsHeaders, () => DisplayStats(ProductionStats)),
                createStatsOption("Combat", combatStatsHeaders, () => DisplayStats(CombatStats)),
                createStatsOption("Earnings (graph)", earnedThisMinuteGraphHeaders, () => EarnedThisMinuteGraph())
            };

            Func <StatsDropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
            {
                var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
                item.Get <LabelWidget>("LABEL").GetText = () => option.Title;
                return(item);
            };

            statsDropDown.OnMouseDown = _ => statsDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, statsDropDownOptions, setupItem);
            statsDropDownOptions[(int)activePanel].OnClick();

            var close = widget.GetOrNull <ButtonWidget>("CLOSE");

            if (close != null)
            {
                close.OnClick = () =>
                {
                    Ui.CloseWindow();
                    Ui.Root.RemoveChild(widget);
                    onExit();
                }
            }
            ;

            var keyListener = statsDropDown.Get <LogicKeyListenerWidget>("STATS_DROPDOWN_KEYHANDLER");

            keyListener.AddHandler(e =>
            {
                if (e.Event == KeyInputEvent.Down && !e.IsRepeat)
                {
                    for (var i = 0; i < statsHotkeys.Length; i++)
                    {
                        if (statsHotkeys[i].IsActivatedBy(e))
                        {
                            Game.Sound.PlayNotification(modData.DefaultRules, null, "Sounds", "ClickSound", null);
                            statsDropDownOptions[i].OnClick();
                            return(true);
                        }
                    }
                }

                return(false);
            });
        }

        void ClearStats()
        {
            playerStatsPanel.Children.Clear();
            basicStatsHeaders.Visible            = false;
            economyStatsHeaders.Visible          = false;
            productionStatsHeaders.Visible       = false;
            combatStatsHeaders.Visible           = false;
            earnedThisMinuteGraphHeaders.Visible = false;
        }

        void EarnedThisMinuteGraph()
        {
            earnedThisMinuteGraphHeaders.Visible = true;
            var template = earnedThisMinuteGraphTemplate.Clone();

            var graph = template.Get <LineGraphWidget>("EARNED_THIS_MIN_GRAPH");

            graph.GetSeries = () =>
                              players.Select(p => new LineGraphSeries(
                                                 p.PlayerName,
                                                 p.Color.RGB,
                                                 (p.PlayerActor.TraitOrDefault <PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).EarnedSamples.Select(s => (float)s)));

            playerStatsPanel.AddChild(template);
            playerStatsPanel.ScrollToTop();
        }

        void DisplayStats(Func <Player, ScrollItemWidget> createItem)
        {
            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 <LabelWidget>("TEAM").GetText = () => team.Key == 0 ? "No Team" : "Team " + team.Key;
                playerStatsPanel.AddChild(tt);
                foreach (var p in team)
                {
                    var player = p;
                    playerStatsPanel.AddChild(createItem(player));
                }
            }
        }

        ScrollItemWidget CombatStats(Player player)
        {
            combatStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("UNITS_KILLED").GetText     = () => stats.UnitsKilled.ToString();
            template.Get <LabelWidget>("UNITS_DEAD").GetText       = () => stats.UnitsDead.ToString();
            template.Get <LabelWidget>("BUILDINGS_KILLED").GetText = () => stats.BuildingsKilled.ToString();
            template.Get <LabelWidget>("BUILDINGS_DEAD").GetText   = () => stats.BuildingsDead.ToString();

            return(template);
        }

        ScrollItemWidget ProductionStats(Player player)
        {
            productionStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(productionPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            template.Get <ObserverProductionIconsWidget>("PRODUCTION_ICONS").GetPlayer      = () => player;
            template.Get <ObserverSupportPowerIconsWidget>("SUPPORT_POWER_ICONS").GetPlayer = () => player;
            template.IgnoreChildMouseOver = false;

            return(template);
        }

        ScrollItemWidget EconomyStats(Player player)
        {
            economyStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(economyPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res   = player.PlayerActor.Trait <PlayerResources>();
            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }

            template.Get <LabelWidget>("CASH").GetText            = () => "$" + (res.Cash + res.Resources);
            template.Get <LabelWidget>("EARNED_MIN").GetText      = () => AverageEarnedPerMinute(res.Earned);
            template.Get <LabelWidget>("EARNED_THIS_MIN").GetText = () => "$" + stats.EarnedThisMinute;
            template.Get <LabelWidget>("EARNED").GetText          = () => "$" + res.Earned;
            template.Get <LabelWidget>("SPENT").GetText           = () => "$" + res.Spent;

            var assets = template.Get <LabelWidget>("ASSETS");

            assets.GetText = () => "$" + world.ActorsHavingTrait <Valued>()
                             .Where(a => a.Owner == player && !a.IsDead)
                             .Sum(a => a.Info.TraitInfos <ValuedInfo>().First().Cost);

            var harvesters = template.Get <LabelWidget>("HARVESTERS");

            harvesters.GetText = () => world.ActorsHavingTrait <Harvester>().Count(a => a.Owner == player && !a.IsDead).ToString();

            return(template);
        }

        ScrollItemWidget BasicStats(Player player)
        {
            basicStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(basicPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res = player.PlayerActor.Trait <PlayerResources>();

            template.Get <LabelWidget>("CASH").GetText       = () => "$" + (res.Cash + res.Resources);
            template.Get <LabelWidget>("EARNED_MIN").GetText = () => AverageEarnedPerMinute(res.Earned);

            var powerRes = player.PlayerActor.Trait <PowerManager>();
            var power    = template.Get <LabelWidget>("POWER");

            power.GetText  = () => powerRes.PowerDrained + "/" + powerRes.PowerProvided;
            power.GetColor = () => GetPowerColor(powerRes.PowerState);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS").GetText            = () => (stats.UnitsKilled + stats.BuildingsKilled).ToString();
            template.Get <LabelWidget>("DEATHS").GetText           = () => (stats.UnitsDead + stats.BuildingsDead).ToString();
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("EXPERIENCE").GetText       = () => stats.Experience.ToString();
            template.Get <LabelWidget>("ACTIONS_MIN").GetText      = () => AverageOrdersPerMinute(stats.OrderCount);

            return(template);
        }

        ScrollItemWidget SetupPlayerScrollItemWidget(ScrollItemWidget template, Player player)
        {
            return(ScrollItemWidget.Setup(template, () => false, () =>
            {
                var playerBase = world.ActorsHavingTrait <BaseBuilding>().FirstOrDefault(a => !a.IsDead && a.Owner == player);
                if (playerBase != null)
                {
                    worldRenderer.Viewport.Center(playerBase.CenterPosition);
                }
            }));
        }
예제 #8
0
        public ObserverStatsLogic(World world, WorldRenderer worldRenderer, Widget widget, Action onExit)
        {
            this.world         = world;
            this.worldRenderer = worldRenderer;
            players            = world.Players.Where(p => !p.NonCombatant);

            basicStatsHeaders            = widget.Get <ContainerWidget>("BASIC_STATS_HEADERS");
            economyStatsHeaders          = widget.Get <ContainerWidget>("ECONOMY_STATS_HEADERS");
            productionStatsHeaders       = widget.Get <ContainerWidget>("PRODUCTION_STATS_HEADERS");
            combatStatsHeaders           = widget.Get <ContainerWidget>("COMBAT_STATS_HEADERS");
            earnedThisMinuteGraphHeaders = widget.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_HEADERS");

            playerStatsPanel        = widget.Get <ScrollPanelWidget>("PLAYER_STATS_PANEL");
            playerStatsPanel.Layout = new GridLayout(playerStatsPanel);

            basicPlayerTemplate           = playerStatsPanel.Get <ScrollItemWidget>("BASIC_PLAYER_TEMPLATE");
            economyPlayerTemplate         = playerStatsPanel.Get <ScrollItemWidget>("ECONOMY_PLAYER_TEMPLATE");
            productionPlayerTemplate      = playerStatsPanel.Get <ScrollItemWidget>("PRODUCTION_PLAYER_TEMPLATE");
            combatPlayerTemplate          = playerStatsPanel.Get <ScrollItemWidget>("COMBAT_PLAYER_TEMPLATE");
            earnedThisMinuteGraphTemplate = playerStatsPanel.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_TEMPLATE");

            teamTemplate = playerStatsPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE");

            statsDropDown             = widget.Get <DropDownButtonWidget>("STATS_DROPDOWN");
            statsDropDown.GetText     = () => "Basic";
            statsDropDown.OnMouseDown = _ =>
            {
                var options = new List <StatsDropDownOption>
                {
                    new StatsDropDownOption
                    {
                        Title      = "Basic",
                        IsSelected = () => basicStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Basic";
                            DisplayStats(BasicStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Economy",
                        IsSelected = () => economyStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Economy";
                            DisplayStats(EconomyStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Production",
                        IsSelected = () => productionStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Production";
                            DisplayStats(ProductionStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Combat",
                        IsSelected = () => combatStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Combat";
                            DisplayStats(CombatStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Earnings (graph)",
                        IsSelected = () => earnedThisMinuteGraphHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Earnings (graph)";
                            EarnedThisMinuteGraph();
                        }
                    }
                };
                Func <StatsDropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                {
                    var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
                    item.Get <LabelWidget>("LABEL").GetText = () => option.Title;
                    return(item);
                };
                statsDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, setupItem);
            };

            ClearStats();
            DisplayStats(BasicStats);

            var close = widget.GetOrNull <ButtonWidget>("CLOSE");

            if (close != null)
            {
                close.OnClick = () =>
                {
                    Ui.CloseWindow();
                    Ui.Root.RemoveChild(widget);
                    onExit();
                }
            }
            ;
        }

        void ClearStats()
        {
            playerStatsPanel.Children.Clear();
            basicStatsHeaders.Visible            = false;
            economyStatsHeaders.Visible          = false;
            productionStatsHeaders.Visible       = false;
            combatStatsHeaders.Visible           = false;
            earnedThisMinuteGraphHeaders.Visible = false;
        }

        void EarnedThisMinuteGraph()
        {
            earnedThisMinuteGraphHeaders.Visible = true;
            var template = earnedThisMinuteGraphTemplate.Clone();

            var graph = template.Get <LineGraphWidget>("EARNED_THIS_MIN_GRAPH");

            graph.GetSeries = () =>
                              players.Select(p => new LineGraphSeries(
                                                 p.PlayerName,
                                                 p.Color.RGB,
                                                 (p.PlayerActor.TraitOrDefault <PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).EarnedSamples.Select(s => (float)s)));

            playerStatsPanel.AddChild(template);
        }

        void DisplayStats(Func <Player, ScrollItemWidget> createItem)
        {
            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 <LabelWidget>("TEAM").GetText = () => team.Key == 0 ? "No Team" : "Team " + team.Key;
                playerStatsPanel.AddChild(tt);
                foreach (var p in team)
                {
                    var player = p;
                    playerStatsPanel.AddChild(createItem(player));
                }
            }
        }

        ScrollItemWidget CombatStats(Player player)
        {
            combatStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS_COST").GetText       = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("DEATHS_COST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("UNITS_KILLED").GetText     = () => stats.UnitsKilled.ToString();
            template.Get <LabelWidget>("UNITS_DEAD").GetText       = () => stats.UnitsDead.ToString();
            template.Get <LabelWidget>("BUILDINGS_KILLED").GetText = () => stats.BuildingsKilled.ToString();
            template.Get <LabelWidget>("BUILDINGS_DEAD").GetText   = () => stats.BuildingsDead.ToString();

            return(template);
        }

        ScrollItemWidget ProductionStats(Player player)
        {
            productionStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(productionPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            template.Get <ObserverProductionIconsWidget>("PRODUCTION_ICONS").GetPlayer      = () => player;
            template.Get <ObserverSupportPowerIconsWidget>("SUPPORT_POWER_ICONS").GetPlayer = () => player;

            return(template);
        }

        ScrollItemWidget EconomyStats(Player player)
        {
            economyStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(economyPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res   = player.PlayerActor.Trait <PlayerResources>();
            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }

            template.Get <LabelWidget>("CASH").GetText            = () => "$" + (res.DisplayCash + res.DisplayResources);
            template.Get <LabelWidget>("EARNED_MIN").GetText      = () => AverageEarnedPerMinute(res.Earned);
            template.Get <LabelWidget>("EARNED_THIS_MIN").GetText = () => "$" + stats.EarnedThisMinute;
            template.Get <LabelWidget>("EARNED").GetText          = () => "$" + res.Earned;
            template.Get <LabelWidget>("SPENT").GetText           = () => "$" + res.Spent;

            var assets = template.Get <LabelWidget>("ASSETS");

            assets.GetText = () => "$" + world.Actors
                             .Where(a => a.Owner == player && !a.IsDead && a.Info.HasTraitInfo <ValuedInfo>())
                             .Sum(a => a.Info.TraitInfos <ValuedInfo>().First().Cost);

            var harvesters = template.Get <LabelWidget>("HARVESTERS");

            harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.Info.HasTraitInfo <HarvesterInfo>()).ToString();

            return(template);
        }

        ScrollItemWidget BasicStats(Player player)
        {
            basicStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(basicPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res = player.PlayerActor.Trait <PlayerResources>();

            template.Get <LabelWidget>("CASH").GetText       = () => "$" + (res.DisplayCash + res.DisplayResources);
            template.Get <LabelWidget>("EARNED_MIN").GetText = () => AverageEarnedPerMinute(res.Earned);

            var powerRes = player.PlayerActor.Trait <PowerManager>();
            var power    = template.Get <LabelWidget>("POWER");

            power.GetText  = () => powerRes.PowerDrained + "/" + powerRes.PowerProvided;
            power.GetColor = () => GetPowerColor(powerRes.PowerState);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS").GetText       = () => (stats.UnitsKilled + stats.BuildingsKilled).ToString();
            template.Get <LabelWidget>("DEATHS").GetText      = () => (stats.UnitsDead + stats.BuildingsDead).ToString();
            template.Get <LabelWidget>("KD_RATIO").GetText    = () => KillDeathRatio(stats.UnitsKilled + stats.BuildingsKilled, stats.UnitsDead + stats.BuildingsDead);
            template.Get <LabelWidget>("ACTIONS_MIN").GetText = () => AverageOrdersPerMinute(stats.OrderCount);

            return(template);
        }

        ScrollItemWidget SetupPlayerScrollItemWidget(ScrollItemWidget template, Player player)
        {
            return(ScrollItemWidget.Setup(template, () => false, () =>
            {
                var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.Info.HasTraitInfo <BaseBuildingInfo>() && a.Owner == player);
                if (playerBase != null)
                {
                    worldRenderer.Viewport.Center(playerBase.CenterPosition);
                }
            }));
        }