using System.Linq; using Content.Shared._White.Antag; using Content.Shared.Ghost; using Content.Shared.Roles; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; namespace Content.Client.UserInterface.Systems.Ghost.Controls { [GenerateTypedNameReferences] public sealed partial class GhostTargetWindow : DefaultWindow { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private List _playerWarps = new(); private List _placeWarps = new(); private List _globalAntagonists = new(); private readonly List _alivePlayers = new(); private readonly List _leftPlayers = new(); private readonly List _deadPlayers = new(); private readonly List _ghostPlayers = new(); public event Action? WarpClicked; public GhostTargetWindow() { IoCManager.InjectDependencies(this); RobustXamlLoader.Load(this); } public void Populate() { GhostTeleportContainter.DisposeAllChildren(); _playerWarps = GetSortedPlayers(_playerWarps); _placeWarps = GetSortedPlaces(_placeWarps); _globalAntagonists = GetSortedAntagonists(_globalAntagonists); PlayersAllocation(); AddButtons(); } public void UpdateWarps(List players, List places, List antagonists) { _playerWarps = players; _placeWarps = places; _globalAntagonists = antagonists; } private void AddButtons() { AddAntagButtons(_globalAntagonists, "ghost-teleport-menu-antagonists-label", "ButtonColorAntagonistDepartment"); AddPlayerButtons(_alivePlayers, "ghost-teleport-menu-alive-label", string.Empty, true); // Alive AddPlayerButtons(_deadPlayers, "ghost-teleport-menu-dead-label", string.Empty, true); // Dead AddPlayerButtons(_ghostPlayers, "ghost-teleport-menu-ghosts-label", string.Empty, true); // Ghost AddPlayerButtons(_leftPlayers, "ghost-teleport-menu-left-label", string.Empty, true); // Left AddPlaceButtons(_placeWarps, "ghost-teleport-menu-locations-label", "ButtonColorSpecificDepartment"); } private void AddPlayerButtons(List players, string text, string styleClass, bool enableByDepartmentColorSheet) { if (players.Count == 0) return; var bigGrid = new GridContainer(); var bigLabel = new Label { Text = Loc.GetString(text), StyleClasses = { "LabelBig" } }; bigGrid.AddChild(bigLabel); var sortedPlayers = SortPlayersByDepartment(players); foreach (var departmentList in sortedPlayers) { if (departmentList.Count == 0) continue; var departmentGrid = new GridContainer { Columns = 5 }; if (enableByDepartmentColorSheet) styleClass = _prototypeManager.Index(departmentList[0].DepartmentID).ButtonStyle; var labelText = _prototypeManager.Index(departmentList[0].DepartmentID).Name; var departmentLabel = new Label { Text = Loc.GetString(labelText) + ": " + departmentList.Count, StyleClasses = { "LabelSecondaryColor" } }; foreach (var player in departmentList) { var playerButton = new Button { Text = player.Name, TextAlign = Label.AlignMode.Right, HorizontalAlignment = HAlignment.Center, VerticalAlignment = VAlignment.Center, SizeFlagsStretchRatio = 1, StyleClasses = { styleClass }, ToolTip = player.JobName, TooltipDelay = 0.1f, SetWidth = 180, }; playerButton.OnPressed += _ => WarpClicked?.Invoke(player.Entity); departmentGrid.AddChild(playerButton); } bigGrid.AddChild(departmentLabel); bigGrid.AddChild(departmentGrid); } GhostTeleportContainter.AddChild(bigGrid); } private void AddPlaceButtons(List places, string text, string styleClass) { if (places.Count == 0) return; var bigGrid = new GridContainer(); var bigLabel = new Label { Text = Loc.GetString(text), StyleClasses = { "LabelBig" } }; bigGrid.AddChild(bigLabel); var placesGrid = new GridContainer { Columns = 5, }; var countLabel = new Label { Text = Loc.GetString("ghost-teleport-menu-count-label") + ": " + places.Count, StyleClasses = { "LabelSecondaryColor" } }; foreach (var place in places) { var placeButton = new Button { Text = place.Name, TextAlign = Label.AlignMode.Right, HorizontalAlignment = HAlignment.Center, VerticalAlignment = VAlignment.Center, SizeFlagsStretchRatio = 1, StyleClasses = { styleClass }, ToolTip = place.Description, TooltipDelay = 0.1f, SetWidth = 180, }; placeButton.OnPressed += _ => WarpClicked?.Invoke(place.Entity); placesGrid.AddChild(placeButton); } bigGrid.AddChild(countLabel); bigGrid.AddChild(placesGrid); GhostTeleportContainter.AddChild(bigGrid); } private void AddAntagButtons(List antags, string text, string styleClass) { if (antags.Count == 0) return; var bigGrid = new GridContainer(); var bigLabel = new Label { Text = Loc.GetString(text), StyleClasses = { "LabelBig" } }; bigGrid.AddChild(bigLabel); var sortedAntags = SortAntagsByWeight(antags); foreach (var antagList in sortedAntags) { if (antagList.Count == 0) continue; var departmentGrid = new GridContainer { Columns = 5 }; var labelText = "ghost-teleport-menu-count-label"; foreach (var antag in antagList) { var playerButton = new Button { Text = antag.Name, TextAlign = Label.AlignMode.Right, HorizontalAlignment = HAlignment.Center, VerticalAlignment = VAlignment.Center, SizeFlagsStretchRatio = 1, StyleClasses = { styleClass }, ToolTip = Loc.GetString(antag.AntagonistDescription), TooltipDelay = 0.1f, SetWidth = 180, }; playerButton.OnPressed += _ => WarpClicked?.Invoke(antag.Entity); departmentGrid.AddChild(playerButton); labelText = antag.AntagonistName; } var departmentLabel = new Label { Text = Loc.GetString(labelText) + ": " + antagList.Count, StyleClasses = { "LabelSecondaryColor" } }; bigGrid.AddChild(departmentLabel); bigGrid.AddChild(departmentGrid); } GhostTeleportContainter.AddChild(bigGrid); } private List> SortPlayersByDepartment(List players) { var sortedPlayers = new List>(); players = players.OrderBy(p => _prototypeManager.Index(p.DepartmentID).Weight).ToList(); var currentList = new List(); var currentWeight = _prototypeManager.Index(players[0].DepartmentID).Weight; foreach (var player in players) { var weight = _prototypeManager.Index(player.DepartmentID).Weight; if (weight == currentWeight) { currentList.Add(player); } else { sortedPlayers.Add(currentList); currentList = new List { player }; currentWeight = weight; } } if (!sortedPlayers.Contains(currentList)) sortedPlayers.Add(currentList); sortedPlayers.Reverse(); return sortedPlayers; } private List> SortAntagsByWeight(List antagonists) { var sortedAntags = new List>(); antagonists = antagonists.OrderBy(a => _prototypeManager.Index(a.PrototypeID).Weight).ToList(); var currentList = new List(); var currentWeight = _prototypeManager.Index(antagonists[0].PrototypeID).Weight; foreach (var antagonist in antagonists) { var weight = _prototypeManager.Index(antagonist.PrototypeID).Weight; if (weight == currentWeight) { currentList.Add(antagonist); } else { sortedAntags.Add(currentList); currentList = new List { antagonist }; currentWeight = weight; } } if (!sortedAntags.Contains(currentList)) sortedAntags.Add(currentList); return sortedAntags; } private List GetSortedPlaces(List places) { return places .OrderBy(w => w.Name) .ToList(); } private List GetSortedPlayers(List players) { return players .OrderBy(w => w.Name) .ToList(); } private List GetSortedAntagonists(List antagonists) { return antagonists .OrderBy(w => w.Name) .ToList(); } private void PlayersAllocation() { _alivePlayers.Clear(); _deadPlayers.Clear(); _leftPlayers.Clear(); _ghostPlayers.Clear(); foreach (var warp in _playerWarps) { if (warp.IsDead) _deadPlayers.Add(warp); else if (warp.IsLeft) _leftPlayers.Add(warp); else if (warp.IsAlive) _alivePlayers.Add(warp); else if (warp.IsGhost) _ghostPlayers.Add(warp); } } } }