* fix: constructs are cultists now * rename: announcementPrototype -> arrivalNotificationPrototype * fix: fix naming * fix: hop became head * resprite: cult bola looks like cult stuff now * add: repsrite files * translation: translation for cult bola * tweak: now bola fits in belt * refactor: refactor KnockDownOnCollideSystem * tweak: bolas knockdown on hit * add: energy bola * cleanup: less components
347 lines
12 KiB
C#
347 lines
12 KiB
C#
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<GhostWarpPlayer> _playerWarps = new();
|
|
private List<GhostWarpPlace> _placeWarps = new();
|
|
private List<GhostWarpGlobalAntagonist> _globalAntagonists = new();
|
|
|
|
private readonly List<GhostWarpPlayer> _alivePlayers = new();
|
|
private readonly List<GhostWarpPlayer> _leftPlayers = new();
|
|
private readonly List<GhostWarpPlayer> _deadPlayers = new();
|
|
private readonly List<GhostWarpPlayer> _ghostPlayers = new();
|
|
|
|
public event Action<NetEntity>? 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<GhostWarpPlayer> players, List<GhostWarpPlace> places, List<GhostWarpGlobalAntagonist> 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<GhostWarpPlayer> 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<DepartmentPrototype>(departmentList[0].DepartmentID).ButtonStyle;
|
|
|
|
var labelText = _prototypeManager.Index<DepartmentPrototype>(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<GhostWarpPlace> 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<GhostWarpGlobalAntagonist> 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<List<GhostWarpPlayer>> SortPlayersByDepartment(List<GhostWarpPlayer> players)
|
|
{
|
|
var sortedPlayers = new List<List<GhostWarpPlayer>>();
|
|
|
|
players = players.OrderBy(p => _prototypeManager.Index<DepartmentPrototype>(p.DepartmentID).Weight).ToList();
|
|
|
|
var currentList = new List<GhostWarpPlayer>();
|
|
var currentWeight = _prototypeManager.Index<DepartmentPrototype>(players[0].DepartmentID).Weight;
|
|
|
|
foreach (var player in players)
|
|
{
|
|
var weight = _prototypeManager.Index<DepartmentPrototype>(player.DepartmentID).Weight;
|
|
|
|
if (weight == currentWeight)
|
|
{
|
|
currentList.Add(player);
|
|
}
|
|
else
|
|
{
|
|
sortedPlayers.Add(currentList);
|
|
currentList = new List<GhostWarpPlayer> { player };
|
|
currentWeight = weight;
|
|
}
|
|
}
|
|
|
|
if (!sortedPlayers.Contains(currentList))
|
|
sortedPlayers.Add(currentList);
|
|
|
|
sortedPlayers.Reverse();
|
|
return sortedPlayers;
|
|
}
|
|
|
|
private List<List<GhostWarpGlobalAntagonist>> SortAntagsByWeight(List<GhostWarpGlobalAntagonist> antagonists)
|
|
{
|
|
var sortedAntags = new List<List<GhostWarpGlobalAntagonist>>();
|
|
|
|
antagonists = antagonists.OrderBy(a => _prototypeManager.Index<AntagonistPrototype>(a.PrototypeID).Weight).ToList();
|
|
|
|
var currentList = new List<GhostWarpGlobalAntagonist>();
|
|
var currentWeight = _prototypeManager.Index<AntagonistPrototype>(antagonists[0].PrototypeID).Weight;
|
|
|
|
foreach (var antagonist in antagonists)
|
|
{
|
|
var weight = _prototypeManager.Index<AntagonistPrototype>(antagonist.PrototypeID).Weight;
|
|
|
|
if (weight == currentWeight)
|
|
{
|
|
currentList.Add(antagonist);
|
|
}
|
|
else
|
|
{
|
|
sortedAntags.Add(currentList);
|
|
currentList = new List<GhostWarpGlobalAntagonist> { antagonist };
|
|
currentWeight = weight;
|
|
}
|
|
}
|
|
|
|
if (!sortedAntags.Contains(currentList))
|
|
sortedAntags.Add(currentList);
|
|
|
|
return sortedAntags;
|
|
}
|
|
|
|
private List<GhostWarpPlace> GetSortedPlaces(List<GhostWarpPlace> places)
|
|
{
|
|
return places
|
|
.OrderBy(w => w.Name)
|
|
.ToList();
|
|
}
|
|
|
|
private List<GhostWarpPlayer> GetSortedPlayers(List<GhostWarpPlayer> players)
|
|
{
|
|
return players
|
|
.OrderBy(w => w.Name)
|
|
.ToList();
|
|
}
|
|
|
|
private List<GhostWarpGlobalAntagonist> GetSortedAntagonists(List<GhostWarpGlobalAntagonist> 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);
|
|
}
|
|
}
|
|
}
|
|
}
|