Role subtypes (#35359)
This commit is contained in:
@@ -6,6 +6,7 @@ using Content.Shared.Administration;
|
|||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
|
using Content.Shared.Roles;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.ResourceManagement;
|
using Robust.Client.ResourceManagement;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
@@ -22,10 +23,11 @@ internal sealed class AdminNameOverlay : Overlay
|
|||||||
private readonly IEyeManager _eyeManager;
|
private readonly IEyeManager _eyeManager;
|
||||||
private readonly EntityLookupSystem _entityLookup;
|
private readonly EntityLookupSystem _entityLookup;
|
||||||
private readonly IUserInterfaceManager _userInterfaceManager;
|
private readonly IUserInterfaceManager _userInterfaceManager;
|
||||||
|
private readonly SharedRoleSystem _roles;
|
||||||
private readonly Font _font;
|
private readonly Font _font;
|
||||||
private readonly Font _fontBold;
|
private readonly Font _fontBold;
|
||||||
private bool _overlayClassic;
|
private AdminOverlayAntagFormat _overlayFormat;
|
||||||
private bool _overlaySymbols;
|
private AdminOverlayAntagSymbolStyle _overlaySymbolStyle;
|
||||||
private bool _overlayPlaytime;
|
private bool _overlayPlaytime;
|
||||||
private bool _overlayStartingJob;
|
private bool _overlayStartingJob;
|
||||||
private float _ghostFadeDistance;
|
private float _ghostFadeDistance;
|
||||||
@@ -33,9 +35,10 @@ internal sealed class AdminNameOverlay : Overlay
|
|||||||
private int _overlayStackMax;
|
private int _overlayStackMax;
|
||||||
private float _overlayMergeDistance;
|
private float _overlayMergeDistance;
|
||||||
|
|
||||||
//TODO make this adjustable via GUI
|
//TODO make this adjustable via GUI?
|
||||||
private readonly ProtoId<RoleTypePrototype>[] _filter =
|
private readonly ProtoId<RoleTypePrototype>[] _filter =
|
||||||
["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"];
|
["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"];
|
||||||
|
|
||||||
private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic");
|
private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic");
|
||||||
|
|
||||||
public AdminNameOverlay(
|
public AdminNameOverlay(
|
||||||
@@ -45,20 +48,22 @@ internal sealed class AdminNameOverlay : Overlay
|
|||||||
IResourceCache resourceCache,
|
IResourceCache resourceCache,
|
||||||
EntityLookupSystem entityLookup,
|
EntityLookupSystem entityLookup,
|
||||||
IUserInterfaceManager userInterfaceManager,
|
IUserInterfaceManager userInterfaceManager,
|
||||||
IConfigurationManager config)
|
IConfigurationManager config,
|
||||||
|
SharedRoleSystem roles)
|
||||||
{
|
{
|
||||||
_system = system;
|
_system = system;
|
||||||
_entityManager = entityManager;
|
_entityManager = entityManager;
|
||||||
_eyeManager = eyeManager;
|
_eyeManager = eyeManager;
|
||||||
_entityLookup = entityLookup;
|
_entityLookup = entityLookup;
|
||||||
_userInterfaceManager = userInterfaceManager;
|
_userInterfaceManager = userInterfaceManager;
|
||||||
|
_roles = roles;
|
||||||
ZIndex = 200;
|
ZIndex = 200;
|
||||||
// Setting these to a specific ttf would break the antag symbols
|
// Setting these to a specific ttf would break the antag symbols
|
||||||
_font = resourceCache.NotoStack();
|
_font = resourceCache.NotoStack();
|
||||||
_fontBold = resourceCache.NotoStack(variation: "Bold");
|
_fontBold = resourceCache.NotoStack(variation: "Bold");
|
||||||
|
|
||||||
config.OnValueChanged(CCVars.AdminOverlayClassic, (show) => { _overlayClassic = show; }, true);
|
config.OnValueChanged(CCVars.AdminOverlayAntagFormat, (show) => { _overlayFormat = UpdateOverlayFormat(show); }, true);
|
||||||
config.OnValueChanged(CCVars.AdminOverlaySymbols, (show) => { _overlaySymbols = show; }, true);
|
config.OnValueChanged(CCVars.AdminOverlaySymbolStyle, (show) => { _overlaySymbolStyle = UpdateOverlaySymbolStyle(show); }, true);
|
||||||
config.OnValueChanged(CCVars.AdminOverlayPlaytime, (show) => { _overlayPlaytime = show; }, true);
|
config.OnValueChanged(CCVars.AdminOverlayPlaytime, (show) => { _overlayPlaytime = show; }, true);
|
||||||
config.OnValueChanged(CCVars.AdminOverlayStartingJob, (show) => { _overlayStartingJob = show; }, true);
|
config.OnValueChanged(CCVars.AdminOverlayStartingJob, (show) => { _overlayStartingJob = show; }, true);
|
||||||
config.OnValueChanged(CCVars.AdminOverlayGhostHideDistance, (f) => { _ghostHideDistance = f; }, true);
|
config.OnValueChanged(CCVars.AdminOverlayGhostHideDistance, (f) => { _ghostHideDistance = f; }, true);
|
||||||
@@ -67,6 +72,22 @@ internal sealed class AdminNameOverlay : Overlay
|
|||||||
config.OnValueChanged(CCVars.AdminOverlayMergeDistance, (f) => { _overlayMergeDistance = f; }, true);
|
config.OnValueChanged(CCVars.AdminOverlayMergeDistance, (f) => { _overlayMergeDistance = f; }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AdminOverlayAntagFormat UpdateOverlayFormat(string formatString)
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse<AdminOverlayAntagFormat>(formatString, out var format))
|
||||||
|
format = AdminOverlayAntagFormat.Binary;
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AdminOverlayAntagSymbolStyle UpdateOverlaySymbolStyle(string symbolString)
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse<AdminOverlayAntagSymbolStyle>(symbolString, out var symbolStyle))
|
||||||
|
symbolStyle = AdminOverlayAntagSymbolStyle.Off;
|
||||||
|
|
||||||
|
return symbolStyle;
|
||||||
|
}
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||||
|
|
||||||
protected override void Draw(in OverlayDrawArgs args)
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
@@ -183,33 +204,55 @@ internal sealed class AdminNameOverlay : Overlay
|
|||||||
currentOffset += lineoffset;
|
currentOffset += lineoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Classic Antag Label
|
// Determine antag symbol
|
||||||
if (_overlayClassic && playerInfo.Antag)
|
string? symbol;
|
||||||
|
switch (_overlaySymbolStyle)
|
||||||
{
|
{
|
||||||
var symbol = _overlaySymbols ? Loc.GetString("player-tab-antag-prefix") : string.Empty;
|
case AdminOverlayAntagSymbolStyle.Specific:
|
||||||
var label = _overlaySymbols
|
symbol = playerInfo.RoleProto.Symbol;
|
||||||
? Loc.GetString("player-tab-character-name-antag-symbol",
|
break;
|
||||||
("symbol", symbol),
|
case AdminOverlayAntagSymbolStyle.Basic:
|
||||||
("name", _antagLabelClassic))
|
symbol = Loc.GetString("player-tab-antag-prefix");
|
||||||
: _antagLabelClassic;
|
break;
|
||||||
color = Color.OrangeRed;
|
default:
|
||||||
color.A = alpha;
|
case AdminOverlayAntagSymbolStyle.Off:
|
||||||
args.ScreenHandle.DrawString(_fontBold, screenCoordinates + currentOffset, label, uiScale, color);
|
symbol = string.Empty;
|
||||||
currentOffset += lineoffset;
|
break;
|
||||||
}
|
}
|
||||||
// Role Type
|
|
||||||
else if (!_overlayClassic && _filter.Contains(playerInfo.RoleProto))
|
// Determine antag/role type name
|
||||||
|
string? text;
|
||||||
|
switch (_overlayFormat)
|
||||||
{
|
{
|
||||||
var symbol = _overlaySymbols && playerInfo.Antag ? playerInfo.RoleProto.Symbol : string.Empty;
|
case AdminOverlayAntagFormat.Roletype:
|
||||||
var role = Loc.GetString(playerInfo.RoleProto.Name).ToUpper();
|
|
||||||
var label = _overlaySymbols
|
|
||||||
? Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", role))
|
|
||||||
: role;
|
|
||||||
color = playerInfo.RoleProto.Color;
|
color = playerInfo.RoleProto.Color;
|
||||||
|
symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||||
|
text = _filter.Contains(playerInfo.RoleProto)
|
||||||
|
? Loc.GetString(playerInfo.RoleProto.Name).ToUpper()
|
||||||
|
: string.Empty;
|
||||||
|
break;
|
||||||
|
case AdminOverlayAntagFormat.Subtype:
|
||||||
|
color = playerInfo.RoleProto.Color;
|
||||||
|
symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||||
|
text = _filter.Contains(playerInfo.RoleProto)
|
||||||
|
? _roles.GetRoleSubtypeLabel(playerInfo.RoleProto.Name, playerInfo.Subtype).ToUpper()
|
||||||
|
: string.Empty;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case AdminOverlayAntagFormat.Binary:
|
||||||
|
color = Color.OrangeRed;
|
||||||
|
symbol = playerInfo.Antag ? symbol : string.Empty;
|
||||||
|
text = playerInfo.Antag ? _antagLabelClassic : string.Empty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw antag label
|
||||||
color.A = alpha;
|
color.A = alpha;
|
||||||
|
var label = !string.IsNullOrEmpty(symbol)
|
||||||
|
? Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", text))
|
||||||
|
: text;
|
||||||
args.ScreenHandle.DrawString(_fontBold, screenCoordinates + currentOffset, label, uiScale, color);
|
args.ScreenHandle.DrawString(_fontBold, screenCoordinates + currentOffset, label, uiScale, color);
|
||||||
currentOffset += lineoffset;
|
currentOffset += lineoffset;
|
||||||
}
|
|
||||||
|
|
||||||
//Save the coordinates and size of the text block, for stack merge check
|
//Save the coordinates and size of the text block, for stack merge check
|
||||||
drawnOverlays.Add((screenCoordinatesCenter, currentOffset));
|
drawnOverlays.Add((screenCoordinatesCenter, currentOffset));
|
||||||
|
|||||||
15
Content.Client/Administration/OverlayOptions.cs
Normal file
15
Content.Client/Administration/OverlayOptions.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Content.Client.Administration;
|
||||||
|
|
||||||
|
public enum AdminOverlayAntagFormat
|
||||||
|
{
|
||||||
|
Binary,
|
||||||
|
Roletype,
|
||||||
|
Subtype
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AdminOverlayAntagSymbolStyle
|
||||||
|
{
|
||||||
|
Off,
|
||||||
|
Basic,
|
||||||
|
Specific
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Client.Administration.Managers;
|
using Content.Client.Administration.Managers;
|
||||||
|
using Content.Shared.Roles;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.ResourceManagement;
|
using Robust.Client.ResourceManagement;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
@@ -15,6 +16,7 @@ namespace Content.Client.Administration.Systems
|
|||||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
|
|
||||||
private AdminNameOverlay _adminNameOverlay = default!;
|
private AdminNameOverlay _adminNameOverlay = default!;
|
||||||
|
|
||||||
@@ -30,7 +32,8 @@ namespace Content.Client.Administration.Systems
|
|||||||
_resourceCache,
|
_resourceCache,
|
||||||
_entityLookup,
|
_entityLookup,
|
||||||
_userInterfaceManager,
|
_userInterfaceManager,
|
||||||
_configurationManager);
|
_configurationManager,
|
||||||
|
_roles);
|
||||||
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +49,8 @@ namespace Content.Client.Administration.Systems
|
|||||||
|
|
||||||
public void AdminOverlayOn()
|
public void AdminOverlayOn()
|
||||||
{
|
{
|
||||||
if (_overlayManager.HasOverlay<AdminNameOverlay>()) return;
|
if (_overlayManager.HasOverlay<AdminNameOverlay>())
|
||||||
|
return;
|
||||||
_overlayManager.AddOverlay(_adminNameOverlay);
|
_overlayManager.AddOverlay(_adminNameOverlay);
|
||||||
OverlayEnabled?.Invoke();
|
OverlayEnabled?.Invoke();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ public sealed partial class PlayerTab : Control
|
|||||||
private bool _ascending = true;
|
private bool _ascending = true;
|
||||||
private bool _showDisconnected;
|
private bool _showDisconnected;
|
||||||
|
|
||||||
|
private AdminPlayerTabColorOption _playerTabColorSetting;
|
||||||
|
private AdminPlayerTabRoleTypeOption _playerTabRoleSetting;
|
||||||
|
private AdminPlayerTabSymbolOption _playerTabSymbolSetting;
|
||||||
|
|
||||||
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
|
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
|
||||||
|
|
||||||
public PlayerTab()
|
public PlayerTab()
|
||||||
@@ -44,9 +48,10 @@ public sealed partial class PlayerTab : Control
|
|||||||
_adminSystem.OverlayEnabled += OverlayEnabled;
|
_adminSystem.OverlayEnabled += OverlayEnabled;
|
||||||
_adminSystem.OverlayDisabled += OverlayDisabled;
|
_adminSystem.OverlayDisabled += OverlayDisabled;
|
||||||
|
|
||||||
_config.OnValueChanged(CCVars.AdminPlayerlistSeparateSymbols, PlayerListSettingsChanged);
|
_config.OnValueChanged(CCVars.AdminPlayerTabRoleSetting, RoleSettingChanged, true);
|
||||||
_config.OnValueChanged(CCVars.AdminPlayerlistHighlightedCharacterColor, PlayerListSettingsChanged);
|
_config.OnValueChanged(CCVars.AdminPlayerTabColorSetting, ColorSettingChanged, true);
|
||||||
_config.OnValueChanged(CCVars.AdminPlayerlistRoleTypeColor, PlayerListSettingsChanged);
|
_config.OnValueChanged(CCVars.AdminPlayerTabSymbolSetting, SymbolSettingChanged, true);
|
||||||
|
|
||||||
|
|
||||||
OverlayButton.OnPressed += OverlayButtonPressed;
|
OverlayButton.OnPressed += OverlayButtonPressed;
|
||||||
ShowDisconnectedButton.OnPressed += ShowDisconnectedPressed;
|
ShowDisconnectedButton.OnPressed += ShowDisconnectedPressed;
|
||||||
@@ -113,8 +118,27 @@ public sealed partial class PlayerTab : Control
|
|||||||
|
|
||||||
#region ListContainer
|
#region ListContainer
|
||||||
|
|
||||||
private void PlayerListSettingsChanged(bool _)
|
private void RoleSettingChanged(string s)
|
||||||
{
|
{
|
||||||
|
if (!Enum.TryParse<AdminPlayerTabRoleTypeOption>(s, out var format))
|
||||||
|
format = AdminPlayerTabRoleTypeOption.Subtype;
|
||||||
|
_playerTabRoleSetting = format;
|
||||||
|
RefreshPlayerList(_adminSystem.PlayerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ColorSettingChanged(string s)
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse<AdminPlayerTabColorOption>(s, out var format))
|
||||||
|
format = AdminPlayerTabColorOption.Both;
|
||||||
|
_playerTabColorSetting = format;
|
||||||
|
RefreshPlayerList(_adminSystem.PlayerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SymbolSettingChanged(string s)
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse<AdminPlayerTabSymbolOption>(s, out var format))
|
||||||
|
format = AdminPlayerTabSymbolOption.Specific;
|
||||||
|
_playerTabSymbolSetting = format;
|
||||||
RefreshPlayerList(_adminSystem.PlayerList);
|
RefreshPlayerList(_adminSystem.PlayerList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +164,12 @@ public sealed partial class PlayerTab : Control
|
|||||||
if (data is not PlayerListData { Info: var player})
|
if (data is not PlayerListData { Info: var player})
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var entry = new PlayerTabEntry(player, new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor));
|
var entry = new PlayerTabEntry(
|
||||||
|
player,
|
||||||
|
new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor),
|
||||||
|
_playerTabColorSetting,
|
||||||
|
_playerTabRoleSetting,
|
||||||
|
_playerTabSymbolSetting);
|
||||||
button.AddChild(entry);
|
button.AddChild(entry);
|
||||||
button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
|
button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,99 @@
|
|||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.Roles;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Configuration;
|
|
||||||
|
|
||||||
namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class PlayerTabEntry : PanelContainer
|
public sealed partial class PlayerTabEntry : PanelContainer
|
||||||
{
|
{
|
||||||
public NetEntity? PlayerEntity;
|
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||||
|
|
||||||
public PlayerTabEntry(PlayerInfo player, StyleBoxFlat styleBoxFlat)
|
public PlayerTabEntry(
|
||||||
|
PlayerInfo player,
|
||||||
|
StyleBoxFlat styleBoxFlat,
|
||||||
|
AdminPlayerTabColorOption colorOption,
|
||||||
|
AdminPlayerTabRoleTypeOption roleSetting,
|
||||||
|
AdminPlayerTabSymbolOption symbolSetting)
|
||||||
{
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
var config = IoCManager.Resolve<IConfigurationManager>();
|
var roles = _entMan.System<SharedRoleSystem>();
|
||||||
|
|
||||||
UsernameLabel.Text = player.Username;
|
UsernameLabel.Text = player.Username;
|
||||||
if (!player.Connected)
|
if (!player.Connected)
|
||||||
UsernameLabel.StyleClasses.Add("Disabled");
|
UsernameLabel.StyleClasses.Add("Disabled");
|
||||||
JobLabel.Text = player.StartingJob;
|
JobLabel.Text = player.StartingJob;
|
||||||
var separateAntagSymbols = config.GetCVar(CCVars.AdminPlayerlistSeparateSymbols);
|
|
||||||
var genericAntagSymbol = player.Antag ? Loc.GetString("player-tab-antag-prefix") : string.Empty;
|
var colorAntags = false;
|
||||||
var roleSymbol = player.Antag ? player.RoleProto.Symbol : string.Empty;
|
var colorRoles = false;
|
||||||
var symbol = separateAntagSymbols ? roleSymbol : genericAntagSymbol;
|
switch (colorOption)
|
||||||
|
{
|
||||||
|
case AdminPlayerTabColorOption.Off:
|
||||||
|
break;
|
||||||
|
case AdminPlayerTabColorOption.Character:
|
||||||
|
colorAntags = true;
|
||||||
|
break;
|
||||||
|
case AdminPlayerTabColorOption.Roletype:
|
||||||
|
colorRoles = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case AdminPlayerTabColorOption.Both:
|
||||||
|
colorAntags = true;
|
||||||
|
colorRoles = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var symbol = string.Empty;
|
||||||
|
switch (symbolSetting)
|
||||||
|
{
|
||||||
|
case AdminPlayerTabSymbolOption.Off:
|
||||||
|
break;
|
||||||
|
case AdminPlayerTabSymbolOption.Basic:
|
||||||
|
symbol = player.Antag ? Loc.GetString("player-tab-antag-prefix") : string.Empty;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case AdminPlayerTabSymbolOption.Specific:
|
||||||
|
symbol = player.Antag ? player.RoleProto.Symbol : string.Empty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
CharacterLabel.Text = Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", player.CharacterName));
|
CharacterLabel.Text = Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", player.CharacterName));
|
||||||
|
|
||||||
if (player.Antag && config.GetCVar(CCVars.AdminPlayerlistHighlightedCharacterColor))
|
if (player.Antag && colorAntags)
|
||||||
CharacterLabel.FontColorOverride = player.RoleProto.Color;
|
CharacterLabel.FontColorOverride = player.RoleProto.Color;
|
||||||
if (player.IdentityName != player.CharacterName)
|
if (player.IdentityName != player.CharacterName)
|
||||||
CharacterLabel.Text += $" [{player.IdentityName}]";
|
CharacterLabel.Text += $" [{player.IdentityName}]";
|
||||||
RoleTypeLabel.Text = Loc.GetString(player.RoleProto.Name);
|
|
||||||
if (config.GetCVar(CCVars.AdminPlayerlistRoleTypeColor))
|
var roletype = RoleTypeLabel.Text = Loc.GetString(player.RoleProto.Name);
|
||||||
|
var subtype = roles.GetRoleSubtypeLabel(player.RoleProto.Name, player.Subtype);
|
||||||
|
switch (roleSetting)
|
||||||
|
{
|
||||||
|
case AdminPlayerTabRoleTypeOption.RoleTypeSubtype:
|
||||||
|
RoleTypeLabel.Text = roletype != subtype
|
||||||
|
? roletype + " - " +subtype
|
||||||
|
: roletype;
|
||||||
|
break;
|
||||||
|
case AdminPlayerTabRoleTypeOption.SubtypeRoleType:
|
||||||
|
RoleTypeLabel.Text = roletype != subtype
|
||||||
|
? subtype + " - " + roletype
|
||||||
|
: roletype;
|
||||||
|
break;
|
||||||
|
case AdminPlayerTabRoleTypeOption.RoleType:
|
||||||
|
RoleTypeLabel.Text = roletype;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case AdminPlayerTabRoleTypeOption.Subtype:
|
||||||
|
RoleTypeLabel.Text = subtype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorRoles)
|
||||||
RoleTypeLabel.FontColorOverride = player.RoleProto.Color;
|
RoleTypeLabel.FontColorOverride = player.RoleProto.Color;
|
||||||
BackgroundColorPanel.PanelOverride = styleBoxFlat;
|
BackgroundColorPanel.PanelOverride = styleBoxFlat;
|
||||||
OverallPlaytimeLabel.Text = player.PlaytimeString;
|
OverallPlaytimeLabel.Text = player.PlaytimeString;
|
||||||
PlayerEntity = player.NetEntity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||||
|
|
||||||
|
public enum AdminPlayerTabColorOption
|
||||||
|
{
|
||||||
|
Off,
|
||||||
|
Character,
|
||||||
|
Roletype,
|
||||||
|
Both
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AdminPlayerTabRoleTypeOption
|
||||||
|
{
|
||||||
|
RoleType,
|
||||||
|
Subtype,
|
||||||
|
RoleTypeSubtype,
|
||||||
|
SubtypeRoleType
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AdminPlayerTabSymbolOption
|
||||||
|
{
|
||||||
|
Off,
|
||||||
|
Basic,
|
||||||
|
Specific
|
||||||
|
}
|
||||||
@@ -6,18 +6,18 @@
|
|||||||
<BoxContainer Orientation="Vertical" Margin="8">
|
<BoxContainer Orientation="Vertical" Margin="8">
|
||||||
<Label Text="{Loc 'ui-options-admin-player-panel'}"
|
<Label Text="{Loc 'ui-options-admin-player-panel'}"
|
||||||
StyleClasses="LabelKeyText"/>
|
StyleClasses="LabelKeyText"/>
|
||||||
<CheckBox Name="PlayerlistSeparateSymbolsCheckBox" Text="{Loc 'ui-options-admin-playerlist-separate-symbols'}" />
|
<ui:OptionDropDown Name="DropDownPlayerTabSymbolSetting" Title="{Loc 'ui-options-admin-player-tab-symbol-setting'}" />
|
||||||
<CheckBox Name="PlayerlistCharacterColorCheckBox" Text="{Loc 'ui-options-admin-playerlist-character-color'}" />
|
<ui:OptionDropDown Name="DropDownPlayerTabRoleSetting" Title="{Loc 'ui-options-admin-player-tab-role-setting'}" />
|
||||||
<CheckBox Name="PlayerlistRoleTypeColorCheckBox" Text="{Loc 'ui-options-admin-playerlist-roletype-color'}" />
|
<ui:OptionDropDown Name="DropDownPlayerTabColorSetting" Title="{Loc 'ui-options-admin-player-tab-color-setting'}" />
|
||||||
<Label Text="{Loc 'ui-options-admin-overlay-title'}"
|
<Label Text="{Loc 'ui-options-admin-overlay-title'}"
|
||||||
StyleClasses="LabelKeyText"/>
|
StyleClasses="LabelKeyText"/>
|
||||||
<CheckBox Name="EnableClassicOverlayCheckBox" Text="{Loc 'ui-options-enable-classic-overlay'}" />
|
<ui:OptionDropDown Name="DropDownOverlayAntagFormat" Title="{Loc 'ui-options-admin-overlay-antag-format'}" />
|
||||||
<CheckBox Name="EnableOverlaySymbolsCheckBox" Text="{Loc 'ui-options-enable-overlay-symbols'}" />
|
<ui:OptionDropDown Name="DropDownOverlayAntagSymbol" Title="{Loc 'ui-options-admin-overlay-antag-symbol'}" />
|
||||||
<CheckBox Name="EnableOverlayPlaytimeCheckBox" Text="{Loc 'ui-options-enable-overlay-playtime'}" />
|
<CheckBox Name="EnableOverlayPlaytimeCheckBox" Text="{Loc 'ui-options-admin-enable-overlay-playtime'}" />
|
||||||
<CheckBox Name="EnableOverlayStartingJobCheckBox" Text="{Loc 'ui-options-enable-overlay-starting-job'}" />
|
<CheckBox Name="EnableOverlayStartingJobCheckBox" Text="{Loc 'ui-options-admin-enable-overlay-starting-job'}" />
|
||||||
<ui:OptionSlider Name="OverlayMergeDistanceSlider" Title="{Loc 'ui-options-overlay-merge-distance'}"/>
|
<ui:OptionSlider Name="OverlayMergeDistanceSlider" Title="{Loc 'ui-options-admin-overlay-merge-distance'}"/>
|
||||||
<ui:OptionSlider Name="OverlayGhostFadeSlider" Title="{Loc 'ui-options-overlay-ghost-fade-distance'}"/>
|
<ui:OptionSlider Name="OverlayGhostFadeSlider" Title="{Loc 'ui-options-admin-overlay-ghost-fade-distance'}"/>
|
||||||
<ui:OptionSlider Name="OverlayGhostHideSlider" Title="{Loc 'ui-options-overlay-ghost-hide-distance'}"/>
|
<ui:OptionSlider Name="OverlayGhostHideSlider" Title="{Loc 'ui-options-admin-overlay-ghost-hide-distance'}"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
<ui:OptionsTabControlRow Name="Control" Access="Public" />
|
<ui:OptionsTabControlRow Name="Control" Access="Public" />
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Content.Client.Administration;
|
||||||
|
using Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
@@ -19,12 +21,43 @@ public sealed partial class AdminOptionsTab : Control
|
|||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
Control.AddOptionCheckBox(CCVars.AdminPlayerlistSeparateSymbols, PlayerlistSeparateSymbolsCheckBox);
|
var antagFormats = new List<OptionDropDownCVar<string>.ValueOption>();
|
||||||
Control.AddOptionCheckBox(CCVars.AdminPlayerlistHighlightedCharacterColor, PlayerlistCharacterColorCheckBox);
|
foreach (var format in Enum.GetValues(typeof(AdminOverlayAntagFormat)))
|
||||||
Control.AddOptionCheckBox(CCVars.AdminPlayerlistRoleTypeColor, PlayerlistRoleTypeColorCheckBox);
|
{
|
||||||
|
antagFormats.Add(new OptionDropDownCVar<string>.ValueOption(format.ToString()!, Loc.GetString($"ui-options-admin-overlay-antag-format-{format.ToString()!.ToLower()}")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var antagSymbolStyles = new List<OptionDropDownCVar<string>.ValueOption>();
|
||||||
|
foreach (var symbol in Enum.GetValues(typeof(AdminOverlayAntagSymbolStyle)))
|
||||||
|
{
|
||||||
|
antagSymbolStyles.Add(new OptionDropDownCVar<string>.ValueOption(symbol.ToString()!, Loc.GetString($"ui-options-admin-overlay-antag-symbol-{symbol.ToString()!.ToLower()}")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerTabColorSettings = new List<OptionDropDownCVar<string>.ValueOption>();
|
||||||
|
foreach (var setting in Enum.GetValues(typeof(AdminPlayerTabColorOption)))
|
||||||
|
{
|
||||||
|
playerTabColorSettings.Add(new OptionDropDownCVar<string>.ValueOption(setting.ToString()!, Loc.GetString($"ui-options-admin-player-tab-color-setting-{setting.ToString()!.ToLower()}")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerTabRoleSettings = new List<OptionDropDownCVar<string>.ValueOption>();
|
||||||
|
foreach (var setting in Enum.GetValues(typeof(AdminPlayerTabRoleTypeOption)))
|
||||||
|
{
|
||||||
|
playerTabRoleSettings.Add(new OptionDropDownCVar<string>.ValueOption(setting.ToString()!, Loc.GetString($"ui-options-admin-player-tab-role-setting-{setting.ToString()!.ToLower()}")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerTabSymbolSettings = new List<OptionDropDownCVar<string>.ValueOption>();
|
||||||
|
foreach (var setting in Enum.GetValues(typeof(AdminPlayerTabSymbolOption)))
|
||||||
|
{
|
||||||
|
playerTabSymbolSettings.Add(new OptionDropDownCVar<string>.ValueOption(setting.ToString()!, Loc.GetString($"ui-options-admin-player-tab-symbol-setting-{setting.ToString()!.ToLower()}")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Control.AddOptionDropDown(CCVars.AdminPlayerTabSymbolSetting, DropDownPlayerTabSymbolSetting, playerTabSymbolSettings);
|
||||||
|
Control.AddOptionDropDown(CCVars.AdminPlayerTabRoleSetting, DropDownPlayerTabRoleSetting, playerTabRoleSettings);
|
||||||
|
Control.AddOptionDropDown(CCVars.AdminPlayerTabColorSetting, DropDownPlayerTabColorSetting, playerTabColorSettings);
|
||||||
|
|
||||||
|
Control.AddOptionDropDown(CCVars.AdminOverlayAntagFormat, DropDownOverlayAntagFormat, antagFormats);
|
||||||
|
Control.AddOptionDropDown(CCVars.AdminOverlaySymbolStyle, DropDownOverlayAntagSymbol, antagSymbolStyles);
|
||||||
|
|
||||||
Control.AddOptionCheckBox(CCVars.AdminOverlayClassic, EnableClassicOverlayCheckBox);
|
|
||||||
Control.AddOptionCheckBox(CCVars.AdminOverlaySymbols, EnableOverlaySymbolsCheckBox);
|
|
||||||
Control.AddOptionCheckBox(CCVars.AdminOverlayPlaytime, EnableOverlayPlaytimeCheckBox);
|
Control.AddOptionCheckBox(CCVars.AdminOverlayPlaytime, EnableOverlayPlaytimeCheckBox);
|
||||||
Control.AddOptionCheckBox(CCVars.AdminOverlayStartingJob, EnableOverlayStartingJobCheckBox);
|
Control.AddOptionCheckBox(CCVars.AdminOverlayStartingJob, EnableOverlayStartingJobCheckBox);
|
||||||
|
|
||||||
|
|||||||
@@ -221,18 +221,11 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
|
|||||||
if (!_ent.TryGetComponent<MindComponent>(container.Mind.Value, out var mind))
|
if (!_ent.TryGetComponent<MindComponent>(container.Mind.Value, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var roleText = Loc.GetString("role-type-crew-aligned-name");
|
if (!_prototypeManager.TryIndex(mind.RoleType, out var proto))
|
||||||
var color = Color.White;
|
_sawmill.Error($"Player '{_player.LocalSession}' has invalid Role Type '{mind.RoleType}'. Displaying default instead");
|
||||||
if (_prototypeManager.TryIndex(mind.RoleType, out var proto))
|
|
||||||
{
|
|
||||||
roleText = Loc.GetString(proto.Name);
|
|
||||||
color = proto.Color;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_sawmill.Error($"{_player.LocalEntity} has invalid Role Type '{mind.RoleType}'. Displaying '{roleText}' instead");
|
|
||||||
|
|
||||||
_window.RoleType.Text = roleText;
|
_window.RoleType.Text = Loc.GetString(proto?.Name ?? "role-type-crew-aligned-name");
|
||||||
_window.RoleType.FontColorOverride = color;
|
_window.RoleType.FontColorOverride = proto?.Color ?? Color.White;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CharacterDetached(EntityUid uid)
|
private void CharacterDetached(EntityUid uid)
|
||||||
|
|||||||
@@ -235,12 +235,16 @@ public sealed class AdminSystem : EntitySystem
|
|||||||
// Starting role, antagonist status and role type
|
// Starting role, antagonist status and role type
|
||||||
RoleTypePrototype roleType = new();
|
RoleTypePrototype roleType = new();
|
||||||
var startingRole = string.Empty;
|
var startingRole = string.Empty;
|
||||||
|
LocId? subtype = null;
|
||||||
if (_minds.TryGetMind(session, out var mindId, out var mindComp) && mindComp is not null)
|
if (_minds.TryGetMind(session, out var mindId, out var mindComp) && mindComp is not null)
|
||||||
{
|
{
|
||||||
sortWeight = _role.GetRoleCompByTime(mindComp)?.Comp.SortWeight ?? 0;
|
sortWeight = _role.GetRoleCompByTime(mindComp)?.Comp.SortWeight ?? 0;
|
||||||
|
|
||||||
if (_proto.TryIndex(mindComp.RoleType, out var role))
|
if (_proto.TryIndex(mindComp.RoleType, out var role))
|
||||||
|
{
|
||||||
roleType = role;
|
roleType = role;
|
||||||
|
subtype = mindComp.Subtype;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(roleType.Name)}' instead");
|
Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(roleType.Name)}' instead");
|
||||||
|
|
||||||
@@ -269,6 +273,7 @@ public sealed class AdminSystem : EntitySystem
|
|||||||
startingRole,
|
startingRole,
|
||||||
antag,
|
antag,
|
||||||
roleType,
|
roleType,
|
||||||
|
subtype,
|
||||||
sortWeight,
|
sortWeight,
|
||||||
GetNetEntity(session?.AttachedEntity),
|
GetNetEntity(session?.AttachedEntity),
|
||||||
data.UserId,
|
data.UserId,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public sealed record PlayerInfo(
|
|||||||
string StartingJob,
|
string StartingJob,
|
||||||
bool Antag,
|
bool Antag,
|
||||||
RoleTypePrototype RoleProto,
|
RoleTypePrototype RoleProto,
|
||||||
|
LocId? Subtype,
|
||||||
int SortWeight,
|
int SortWeight,
|
||||||
NetEntity? NetEntity,
|
NetEntity? NetEntity,
|
||||||
NetUserId SessionId,
|
NetUserId SessionId,
|
||||||
|
|||||||
@@ -38,10 +38,13 @@ public sealed partial class CCVars
|
|||||||
CVarDef.Create("outline.enabled", true, CVar.CLIENTONLY);
|
CVarDef.Create("outline.enabled", true, CVar.CLIENTONLY);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the admin overlay will be displayed in the old style (showing only "ANTAG")
|
/// Determines how antagonist status/roletype is displayed. Based on AdminOverlayAntagFormats enum
|
||||||
|
/// Binary: Roletypes of interest get an "ANTAG" label
|
||||||
|
/// Roletype: Roletypes of interest will have their roletype name displayed in their specific color
|
||||||
|
/// Subtype: Roletypes of interest will have their subtype displayed. if subtype is not set, roletype will be shown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> AdminOverlayClassic =
|
public static readonly CVarDef<string> AdminOverlayAntagFormat =
|
||||||
CVarDef.Create("ui.admin_overlay_classic", false, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_overlay_antag_format", "Subtype", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the admin overlay will display the total time of the players
|
/// If true, the admin overlay will display the total time of the players
|
||||||
@@ -50,34 +53,48 @@ public sealed partial class CCVars
|
|||||||
CVarDef.Create("ui.admin_overlay_playtime", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_overlay_playtime", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the admin overlay will display the players starting position.
|
/// If true, the admin overlay will display the player's starting role.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> AdminOverlayStartingJob =
|
public static readonly CVarDef<bool> AdminOverlayStartingJob =
|
||||||
CVarDef.Create("ui.admin_overlay_starting_job", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_overlay_starting_job", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the admin window player tab will show different antag symbols for each role type
|
/// Determines how antagonist status/roletype is displayed Before character names on the Player Tab
|
||||||
|
/// Off: No symbol is shown.
|
||||||
|
/// Basic: The same antag symbol is shown for anyone marked as antag.
|
||||||
|
/// Specific: The roletype-specific symbol is shown for anyone marked as antag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> AdminPlayerlistSeparateSymbols =
|
public static readonly CVarDef<string> AdminPlayerTabSymbolSetting =
|
||||||
CVarDef.Create("ui.admin_playerlist_separate_symbols", false, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_player_tab_symbols", "Specific", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, characters with antag role types will have their names colored by their role type
|
/// Determines what columns are colorized
|
||||||
|
/// Off: None.
|
||||||
|
/// Character: The character names of "roletypes-of-interest" have their role type's color.
|
||||||
|
/// Roletype: Role types are shown in their respective colors.
|
||||||
|
/// Both: Both characters and role types are colorized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> AdminPlayerlistHighlightedCharacterColor =
|
public static readonly CVarDef<string> AdminPlayerTabColorSetting =
|
||||||
CVarDef.Create("ui.admin_playerlist_highlighted_character_color", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_player_tab_color", "Both", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the Role Types column will be colored
|
/// Determines what's displayed in the Role column - role type, subtype, or both.
|
||||||
|
/// RoleType
|
||||||
|
/// SubType
|
||||||
|
/// RoleTypeSubtype
|
||||||
|
/// SubtypeRoleType
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> AdminPlayerlistRoleTypeColor =
|
public static readonly CVarDef<string> AdminPlayerTabRoleSetting =
|
||||||
CVarDef.Create("ui.admin_playerlist_role_type_color", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_player_tab_role", "Subtype", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the admin overlay will show antag symbols
|
/// Determines how antagonist status/roletype is displayed. Based on AdminOverlayAntagSymbolStyles enum
|
||||||
|
/// Off: No symbol is shown.
|
||||||
|
/// Basic: The same antag symbol is shown for anyone marked as antag.
|
||||||
|
/// Specific: The roletype-specific symbol is shown for anyone marked as antag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> AdminOverlaySymbols =
|
public static readonly CVarDef<string> AdminOverlaySymbolStyle =
|
||||||
CVarDef.Create("ui.admin_overlay_symbols", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
CVarDef.Create("ui.admin_overlay_symbol_style", "Specific", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The range (in tiles) around the cursor within which the admin overlays of ghosts start to fade out
|
/// The range (in tiles) around the cursor within which the admin overlays of ghosts start to fade out
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ public sealed partial class MindComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public ProtoId<RoleTypePrototype> RoleType = "Neutral";
|
public ProtoId<RoleTypePrototype> RoleType = "Neutral";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The role's subtype, shown only to admins to help with antag categorization
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId? Subtype;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The session of the player owning this mind.
|
/// The session of the player owning this mind.
|
||||||
/// Can be null, in which case the player is currently not logged in.
|
/// Can be null, in which case the player is currently not logged in.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public sealed partial class RoleTypePrototype : IPrototype
|
|||||||
/// The role's displayed color.
|
/// The role's displayed color.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public Color Color { get; private set; } = Color.FromHex("#eeeeee");
|
public Color Color = Color.FromHex("#eeeeee");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A symbol used to represent the role type.
|
/// A symbol used to represent the role type.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public sealed partial class MindRoleComponent : BaseMindRoleComponent
|
|||||||
/// A single antag Mind Role is enough to make the owner mind count as Antagonist.
|
/// A single antag Mind Role is enough to make the owner mind count as Antagonist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public bool Antag { get; set; } = false;
|
public bool Antag;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The mind's current antagonist/special role, or lack thereof;
|
/// The mind's current antagonist/special role, or lack thereof;
|
||||||
@@ -23,11 +23,17 @@ public sealed partial class MindRoleComponent : BaseMindRoleComponent
|
|||||||
[DataField]
|
[DataField]
|
||||||
public ProtoId<RoleTypePrototype>? RoleType;
|
public ProtoId<RoleTypePrototype>? RoleType;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The role's subtype, shown only to admins to help with antag categorization
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId? Subtype;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if this mindrole is an exclusive antagonist. Antag setting is not checked if this is True.
|
/// True if this mindrole is an exclusive antagonist. Antag setting is not checked if this is True.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public bool ExclusiveAntag { get; set; } = false;
|
public bool ExclusiveAntag;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Mind that this role belongs to
|
/// The Mind that this role belongs to
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using Content.Shared.Database;
|
|||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Roles.Jobs;
|
using Content.Shared.Roles.Jobs;
|
||||||
using Content.Shared.Silicons.Borgs.Components;
|
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -202,22 +201,22 @@ public abstract class SharedRoleSystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
//get the most important/latest mind role
|
//get the most important/latest mind role
|
||||||
var roleType = GetRoleTypeByTime(ent.Comp);
|
var (roleType, subtype) = GetRoleTypeByTime(ent.Comp);
|
||||||
|
|
||||||
if (ent.Comp.RoleType == roleType)
|
if (ent.Comp.RoleType == roleType && ent.Comp.Subtype == subtype)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SetRoleType(ent.Owner, roleType);
|
SetRoleType(ent.Owner, roleType, subtype);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the most recently specified role type, or Neutral
|
/// Return the most recently specified role type and subtype, or Neutral
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ProtoId<RoleTypePrototype> GetRoleTypeByTime(MindComponent mind)
|
private (ProtoId<RoleTypePrototype>, LocId?) GetRoleTypeByTime(MindComponent mind)
|
||||||
{
|
{
|
||||||
var role = GetRoleCompByTime(mind);
|
var role = GetRoleCompByTime(mind);
|
||||||
return role?.Comp?.RoleType ?? "Neutral";
|
return (role?.Comp?.RoleType ?? "Neutral", role?.Comp?.Subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -238,21 +237,22 @@ public abstract class SharedRoleSystem : EntitySystem
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetRoleType(EntityUid mind, ProtoId<RoleTypePrototype> roleTypeId)
|
private void SetRoleType(EntityUid mind, ProtoId<RoleTypePrototype> roleTypeId, LocId? subtype)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindComponent>(mind, out var comp))
|
if (!TryComp<MindComponent>(mind, out var comp))
|
||||||
{
|
{
|
||||||
Log.Error($"Failed to update Role Type of mind entity {ToPrettyString(mind)} to {roleTypeId}. MindComponent not found.");
|
Log.Error($"Failed to update Role Type of mind entity {ToPrettyString(mind)} to {roleTypeId}, {subtype}. MindComponent not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_prototypes.HasIndex(roleTypeId))
|
if (!_prototypes.HasIndex(roleTypeId))
|
||||||
{
|
{
|
||||||
Log.Error($"Failed to change Role Type of {_minds.MindOwnerLoggingString(comp)} to {roleTypeId}. Invalid role");
|
Log.Error($"Failed to change Role Type of {_minds.MindOwnerLoggingString(comp)} to {roleTypeId}, {subtype}. Invalid role");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.RoleType = roleTypeId;
|
comp.RoleType = roleTypeId;
|
||||||
|
comp.Subtype = subtype;
|
||||||
Dirty(mind, comp);
|
Dirty(mind, comp);
|
||||||
|
|
||||||
// Update player character window
|
// Update player character window
|
||||||
@@ -269,13 +269,13 @@ public abstract class SharedRoleSystem : EntitySystem
|
|||||||
Log.Error($"{ToPrettyString(mind)} does not have an OwnedEntity!");
|
Log.Error($"{ToPrettyString(mind)} does not have an OwnedEntity!");
|
||||||
_adminLogger.Add(LogType.Mind,
|
_adminLogger.Add(LogType.Mind,
|
||||||
LogImpact.Medium,
|
LogImpact.Medium,
|
||||||
$"Role Type of {ToPrettyString(mind)} changed to {roleTypeId}");
|
$"Role Type of {ToPrettyString(mind)} changed to {roleTypeId}, {subtype}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Mind,
|
_adminLogger.Add(LogType.Mind,
|
||||||
LogImpact.High,
|
LogImpact.High,
|
||||||
$"Role Type of {ToPrettyString(comp.OwnedEntity)} changed to {roleTypeId}");
|
$"Role Type of {ToPrettyString(comp.OwnedEntity)} changed to {roleTypeId}, {subtype}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -630,6 +630,14 @@ public abstract class SharedRoleSystem : EntitySystem
|
|||||||
|
|
||||||
return antag.Requirements;
|
return antag.Requirements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the localized name of a role type's subtype. If the provided subtype parameter turns out to be empty, it returns the localized name of the role type instead.
|
||||||
|
/// </summary>
|
||||||
|
public string GetRoleSubtypeLabel(LocId roleType, LocId? subtype)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(subtype) ? Loc.GetString(roleType) : Loc.GetString(subtype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -339,15 +339,37 @@ ui-options-censor-nudity = Censor character nudity
|
|||||||
|
|
||||||
ui-options-admin-player-panel = Admin Menu Players List
|
ui-options-admin-player-panel = Admin Menu Players List
|
||||||
|
|
||||||
ui-options-admin-playerlist-separate-symbols = Show separate symbols for each antag role type
|
ui-options-admin-player-tab-symbol-setting = Character column antag symbols
|
||||||
ui-options-admin-playerlist-character-color = Color names of antagonist characters
|
ui-options-admin-player-tab-symbol-setting-off = No antag symbol
|
||||||
ui-options-admin-playerlist-roletype-color = Color role types
|
ui-options-admin-player-tab-symbol-setting-basic = Show standard antag symbol
|
||||||
|
ui-options-admin-player-tab-symbol-setting-specific = Show specific antag symbol
|
||||||
|
|
||||||
|
ui-options-admin-player-tab-role-setting = Role display settings
|
||||||
|
ui-options-admin-player-tab-role-setting-roletype = Show role type
|
||||||
|
ui-options-admin-player-tab-role-setting-subtype = Show subtype
|
||||||
|
ui-options-admin-player-tab-role-setting-roletypesubtype = Show role type and subtype
|
||||||
|
ui-options-admin-player-tab-role-setting-subtyperoletype = Show subtype and role type
|
||||||
|
|
||||||
|
ui-options-admin-player-tab-color-setting = Color settings
|
||||||
|
ui-options-admin-player-tab-color-setting-off = I hate colors
|
||||||
|
ui-options-admin-player-tab-color-setting-character = Colorize antag character names
|
||||||
|
ui-options-admin-player-tab-color-setting-roletype = Colorize all role types
|
||||||
|
ui-options-admin-player-tab-color-setting-both = Colorize both
|
||||||
|
|
||||||
ui-options-admin-overlay-title = Admin Overlay
|
ui-options-admin-overlay-title = Admin Overlay
|
||||||
ui-options-enable-classic-overlay = Revert overlay to classic mode
|
|
||||||
ui-options-enable-overlay-symbols = Add antag symbol to text
|
ui-options-admin-overlay-antag-format = Antag label style
|
||||||
ui-options-enable-overlay-playtime = Show playtime
|
ui-options-admin-overlay-antag-format-binary = Show antag status
|
||||||
ui-options-enable-overlay-starting-job = Show starting job
|
ui-options-admin-overlay-antag-format-roletype = Show role type
|
||||||
ui-options-overlay-merge-distance = Stack merge distance
|
ui-options-admin-overlay-antag-format-subtype = Show subtype
|
||||||
ui-options-overlay-ghost-fade-distance = Ghost overlay fade range from mouse
|
|
||||||
ui-options-overlay-ghost-hide-distance = Ghost overlay hide range from mouse
|
ui-options-admin-overlay-antag-symbol = Antag symbol style
|
||||||
|
ui-options-admin-overlay-antag-symbol-off = No antag symbol
|
||||||
|
ui-options-admin-overlay-antag-symbol-basic = Show standard antag symbol
|
||||||
|
ui-options-admin-overlay-antag-symbol-specific = Show specific antag symbol
|
||||||
|
|
||||||
|
ui-options-admin-enable-overlay-playtime = Show playtime
|
||||||
|
ui-options-admin-enable-overlay-starting-job = Show starting job
|
||||||
|
ui-options-admin-overlay-merge-distance = Stack merge distance
|
||||||
|
ui-options-admin-overlay-ghost-fade-distance = Ghost overlay fade range from mouse
|
||||||
|
ui-options-admin-overlay-ghost-hide-distance = Ghost overlay hide range from mouse
|
||||||
|
|||||||
@@ -17,3 +17,19 @@ role-type-free-agent-color = #ffff00
|
|||||||
role-type-familiar-color = #6495ed
|
role-type-familiar-color = #6495ed
|
||||||
role-type-silicon-color = #6495ed
|
role-type-silicon-color = #6495ed
|
||||||
role-type-silicon-antagonist-color =#c832e6
|
role-type-silicon-antagonist-color =#c832e6
|
||||||
|
|
||||||
|
# Ideally, subtype names should be short
|
||||||
|
role-subtype-traitor = Traitor
|
||||||
|
role-subtype-thief = Thief
|
||||||
|
role-subtype-ninja = Ninja
|
||||||
|
role-subtype-nukie = Nukie
|
||||||
|
role-subtype-traitor-reinforcement = Reinforcement
|
||||||
|
role-subtype-revolutionary = Rev
|
||||||
|
role-subtype-head-revolutionary = Head Rev
|
||||||
|
role-subtype-initial-infected = Infected
|
||||||
|
role-subtype-zombie = Zombie
|
||||||
|
role-subtype-dragon = Dragon
|
||||||
|
role-subtype-survivor = Survivor
|
||||||
|
role-subtype-subverted = Subverted
|
||||||
|
role-subtype-paradox-clone = Paradox
|
||||||
|
role-subtype-wizard = Wizard
|
||||||
|
|||||||
@@ -95,7 +95,6 @@
|
|||||||
antagPrototype: GenericTeamAntagonist
|
antagPrototype: GenericTeamAntagonist
|
||||||
|
|
||||||
# This should be used (or inherited) for team antags that are summoned or converted in large quantities, and are "secondary" to other antags
|
# This should be used (or inherited) for team antags that are summoned or converted in large quantities, and are "secondary" to other antags
|
||||||
# TODO: sort weight
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: MindRoleGhostRoleTeamAntagonist
|
parent: MindRoleGhostRoleTeamAntagonist
|
||||||
id: MindRoleGhostRoleTeamAntagonistFlock
|
id: MindRoleGhostRoleTeamAntagonistFlock
|
||||||
@@ -130,6 +129,7 @@
|
|||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: SubvertedSilicon
|
antagPrototype: SubvertedSilicon
|
||||||
roleType: SiliconAntagonist
|
roleType: SiliconAntagonist
|
||||||
|
subtype: role-subtype-subverted
|
||||||
- type: SubvertedSiliconRole
|
- type: SubvertedSiliconRole
|
||||||
|
|
||||||
# Dragon
|
# Dragon
|
||||||
@@ -141,6 +141,7 @@
|
|||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Dragon
|
antagPrototype: Dragon
|
||||||
roleType: TeamAntagonist
|
roleType: TeamAntagonist
|
||||||
|
subtype: role-subtype-dragon
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
- type: DragonRole
|
- type: DragonRole
|
||||||
- type: RoleBriefing
|
- type: RoleBriefing
|
||||||
@@ -154,6 +155,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: SpaceNinja
|
antagPrototype: SpaceNinja
|
||||||
|
subtype: role-subtype-ninja
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
- type: NinjaRole
|
- type: NinjaRole
|
||||||
|
|
||||||
@@ -165,7 +167,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: ParadoxClone
|
antagPrototype: ParadoxClone
|
||||||
roleType: SoloAntagonist
|
subtype: role-subtype-paradox-clone
|
||||||
- type: ParadoxCloneRole
|
- type: ParadoxCloneRole
|
||||||
|
|
||||||
# Nukies
|
# Nukies
|
||||||
@@ -176,6 +178,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: MindRole
|
- type: MindRole
|
||||||
roleType: TeamAntagonist
|
roleType: TeamAntagonist
|
||||||
|
subtype: role-subtype-nukie
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
antagPrototype: Nukeops
|
antagPrototype: Nukeops
|
||||||
- type: NukeopsRole
|
- type: NukeopsRole
|
||||||
@@ -206,6 +209,7 @@
|
|||||||
antagPrototype: HeadRev
|
antagPrototype: HeadRev
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
roleType: TeamAntagonist
|
roleType: TeamAntagonist
|
||||||
|
subtype: role-subtype-head-revolutionary
|
||||||
- type: RevolutionaryRole
|
- type: RevolutionaryRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -215,6 +219,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Rev
|
antagPrototype: Rev
|
||||||
|
subtype: role-subtype-revolutionary
|
||||||
|
|
||||||
# Survivors (Wizard)
|
# Survivors (Wizard)
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -225,6 +230,7 @@
|
|||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Survivor
|
antagPrototype: Survivor
|
||||||
roleType: FreeAgent
|
roleType: FreeAgent
|
||||||
|
subtype: role-subtype-survivor
|
||||||
- type: SurvivorRole
|
- type: SurvivorRole
|
||||||
|
|
||||||
# Thief
|
# Thief
|
||||||
@@ -235,6 +241,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Thief
|
antagPrototype: Thief
|
||||||
|
subtype: role-subtype-thief
|
||||||
- type: ThiefRole
|
- type: ThiefRole
|
||||||
|
|
||||||
# Traitors
|
# Traitors
|
||||||
@@ -246,6 +253,7 @@
|
|||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Traitor
|
antagPrototype: Traitor
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
|
subtype: role-subtype-traitor
|
||||||
- type: TraitorRole
|
- type: TraitorRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -263,6 +271,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: MindRole
|
- type: MindRole
|
||||||
roleType: TeamAntagonist
|
roleType: TeamAntagonist
|
||||||
|
subtype: role-subtype-traitor-reinforcement
|
||||||
antagPrototype: GenericTeamAntagonist
|
antagPrototype: GenericTeamAntagonist
|
||||||
|
|
||||||
# Wizards
|
# Wizards
|
||||||
@@ -274,6 +283,7 @@
|
|||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Wizard
|
antagPrototype: Wizard
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
|
subtype: role-subtype-wizard
|
||||||
- type: WizardRole
|
- type: WizardRole
|
||||||
|
|
||||||
# Zombie Squad
|
# Zombie Squad
|
||||||
@@ -286,6 +296,7 @@
|
|||||||
antagPrototype: InitialInfected
|
antagPrototype: InitialInfected
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
roleType: TeamAntagonist
|
roleType: TeamAntagonist
|
||||||
|
subtype: role-subtype-initial-infected
|
||||||
- type: InitialInfectedRole
|
- type: InitialInfectedRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -296,5 +307,5 @@
|
|||||||
- type: MindRole
|
- type: MindRole
|
||||||
antagPrototype: Zombie
|
antagPrototype: Zombie
|
||||||
exclusiveAntag: true
|
exclusiveAntag: true
|
||||||
roleType: TeamAntagonist
|
subtype: role-subtype-zombie
|
||||||
- type: ZombieRole
|
- type: ZombieRole
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# For use by Role Types
|
# The primary role types are referenced by RP Rules, and were specified based on head admin input.
|
||||||
# Do not touch these
|
# Do not create new ones without discussion.
|
||||||
|
# You probably want a Subtype instead, anyway. Use MindRoleComponent.Subtype
|
||||||
|
|
||||||
|
# Any new primary role types must be listed in RoleTypes.xml
|
||||||
|
|
||||||
# If you change/add a color here, also change it in role-types.ftl!
|
# If you change/add a color here, also change it in role-types.ftl!
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user