diff --git a/Content.Client/Administration/AdminNameOverlay.cs b/Content.Client/Administration/AdminNameOverlay.cs index 0d424cbff047f..c0f31f1e3d063 100644 --- a/Content.Client/Administration/AdminNameOverlay.cs +++ b/Content.Client/Administration/AdminNameOverlay.cs @@ -6,7 +6,6 @@ using Content.Shared.CCVar; using Content.Shared.Ghost; using Content.Shared.Mind; -using Content.Shared.Roles; using Robust.Client.Graphics; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; @@ -23,11 +22,10 @@ internal sealed class AdminNameOverlay : Overlay private readonly IEyeManager _eyeManager; private readonly EntityLookupSystem _entityLookup; private readonly IUserInterfaceManager _userInterfaceManager; - private readonly SharedRoleSystem _roles; private readonly Font _font; private readonly Font _fontBold; - private AdminOverlayAntagFormat _overlayFormat; - private AdminOverlayAntagSymbolStyle _overlaySymbolStyle; + private bool _overlayClassic; + private bool _overlaySymbols; private bool _overlayPlaytime; private bool _overlayStartingJob; private float _ghostFadeDistance; @@ -35,10 +33,9 @@ internal sealed class AdminNameOverlay : Overlay private int _overlayStackMax; private float _overlayMergeDistance; - //TODO make this adjustable via GUI? + //TODO make this adjustable via GUI private readonly ProtoId[] _filter = ["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"]; - private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic"); public AdminNameOverlay( @@ -48,22 +45,20 @@ public AdminNameOverlay( IResourceCache resourceCache, EntityLookupSystem entityLookup, IUserInterfaceManager userInterfaceManager, - IConfigurationManager config, - SharedRoleSystem roles) + IConfigurationManager config) { _system = system; _entityManager = entityManager; _eyeManager = eyeManager; _entityLookup = entityLookup; _userInterfaceManager = userInterfaceManager; - _roles = roles; ZIndex = 200; // Setting these to a specific ttf would break the antag symbols _font = resourceCache.NotoStack(); _fontBold = resourceCache.NotoStack(variation: "Bold"); - config.OnValueChanged(CCVars.AdminOverlayAntagFormat, (show) => { _overlayFormat = UpdateOverlayFormat(show); }, true); - config.OnValueChanged(CCVars.AdminOverlaySymbolStyle, (show) => { _overlaySymbolStyle = UpdateOverlaySymbolStyle(show); }, true); + config.OnValueChanged(CCVars.AdminOverlayClassic, (show) => { _overlayClassic = show; }, true); + config.OnValueChanged(CCVars.AdminOverlaySymbols, (show) => { _overlaySymbols = show; }, true); config.OnValueChanged(CCVars.AdminOverlayPlaytime, (show) => { _overlayPlaytime = show; }, true); config.OnValueChanged(CCVars.AdminOverlayStartingJob, (show) => { _overlayStartingJob = show; }, true); config.OnValueChanged(CCVars.AdminOverlayGhostHideDistance, (f) => { _ghostHideDistance = f; }, true); @@ -72,22 +67,6 @@ public AdminNameOverlay( config.OnValueChanged(CCVars.AdminOverlayMergeDistance, (f) => { _overlayMergeDistance = f; }, true); } - private AdminOverlayAntagFormat UpdateOverlayFormat(string formatString) - { - if (!Enum.TryParse(formatString, out var format)) - format = AdminOverlayAntagFormat.Binary; - - return format; - } - - private AdminOverlayAntagSymbolStyle UpdateOverlaySymbolStyle(string symbolString) - { - if (!Enum.TryParse(symbolString, out var symbolStyle)) - symbolStyle = AdminOverlayAntagSymbolStyle.Off; - - return symbolStyle; - } - public override OverlaySpace Space => OverlaySpace.ScreenSpace; protected override void Draw(in OverlayDrawArgs args) @@ -204,56 +183,34 @@ protected override void Draw(in OverlayDrawArgs args) currentOffset += lineoffset; } - // Determine antag symbol - string? symbol; - switch (_overlaySymbolStyle) + // Classic Antag Label + if (_overlayClassic && playerInfo.Antag) { - case AdminOverlayAntagSymbolStyle.Specific: - symbol = playerInfo.RoleProto.Symbol; - break; - case AdminOverlayAntagSymbolStyle.Basic: - symbol = Loc.GetString("player-tab-antag-prefix"); - break; - default: - case AdminOverlayAntagSymbolStyle.Off: - symbol = string.Empty; - break; + var symbol = _overlaySymbols ? Loc.GetString("player-tab-antag-prefix") : string.Empty; + var label = _overlaySymbols + ? Loc.GetString("player-tab-character-name-antag-symbol", + ("symbol", symbol), + ("name", _antagLabelClassic)) + : _antagLabelClassic; + color = Color.OrangeRed; + color.A = alpha; + args.ScreenHandle.DrawString(_fontBold, screenCoordinates + currentOffset, label, uiScale, color); + currentOffset += lineoffset; } - - // Determine antag/role type name - string? text; - switch (_overlayFormat) + // Role Type + else if (!_overlayClassic && _filter.Contains(playerInfo.RoleProto)) { - case AdminOverlayAntagFormat.Roletype: - 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; + var symbol = _overlaySymbols && playerInfo.Antag ? playerInfo.RoleProto.Symbol : string.Empty; + 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.A = alpha; + args.ScreenHandle.DrawString(_fontBold, screenCoordinates + currentOffset, label, uiScale, color); + currentOffset += lineoffset; } - // Draw antag label - 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); - currentOffset += lineoffset; - //Save the coordinates and size of the text block, for stack merge check drawnOverlays.Add((screenCoordinatesCenter, currentOffset)); } diff --git a/Content.Client/Administration/UI/AdminUIHelpers.cs b/Content.Client/Administration/UI/AdminUIHelpers.cs new file mode 100644 index 0000000000000..89ab33e931da0 --- /dev/null +++ b/Content.Client/Administration/UI/AdminUIHelpers.cs @@ -0,0 +1,59 @@ +using System.Threading; +using Content.Client.Stylesheets; +using Robust.Client.UserInterface.Controls; +using Timer = Robust.Shared.Timing.Timer; + +namespace Content.Client.Administration.UI; + +public static class AdminUIHelpers +{ + private static void ResetButton(Button button, ConfirmationData data) + { + data.Cancellation.Cancel(); + button.ModulateSelfOverride = null; + button.Text = data.OriginalText; + } + + public static bool RemoveConfirm(Button button, Dictionary confirmations) + { + if (confirmations.Remove(button, out var data)) + { + ResetButton(button, data); + return true; + } + + return false; + } + + public static void RemoveAllConfirms(Dictionary confirmations) + { + foreach (var (button, confirmation) in confirmations) + { + ResetButton(button, confirmation); + } + + confirmations.Clear(); + } + + public static bool TryConfirm(Button button, Dictionary confirmations) + { + if (RemoveConfirm(button, confirmations)) + return true; + + var data = new ConfirmationData(new CancellationTokenSource(), button.Text); + confirmations[button] = data; + + Timer.Spawn(TimeSpan.FromSeconds(5), () => + { + confirmations.Remove(button); + button.ModulateSelfOverride = null; + button.Text = data.OriginalText; + }, data.Cancellation.Token); + + button.ModulateSelfOverride = StyleNano.ButtonColorCautionDefault; + button.Text = Loc.GetString("admin-player-actions-confirm"); + return false; + } +} + +public readonly record struct ConfirmationData(CancellationTokenSource Cancellation, string? OriginalText); diff --git a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs index 2a25d9e0aabc1..b5b2b0e345611 100644 --- a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs @@ -32,10 +32,6 @@ public sealed partial class PlayerTab : Control private bool _ascending = true; private bool _showDisconnected; - private AdminPlayerTabColorOption _playerTabColorSetting; - private AdminPlayerTabRoleTypeOption _playerTabRoleSetting; - private AdminPlayerTabSymbolOption _playerTabSymbolSetting; - public event Action? OnEntryKeyBindDown; public PlayerTab() @@ -48,10 +44,9 @@ public PlayerTab() _adminSystem.OverlayEnabled += OverlayEnabled; _adminSystem.OverlayDisabled += OverlayDisabled; - _config.OnValueChanged(CCVars.AdminPlayerTabRoleSetting, RoleSettingChanged, true); - _config.OnValueChanged(CCVars.AdminPlayerTabColorSetting, ColorSettingChanged, true); - _config.OnValueChanged(CCVars.AdminPlayerTabSymbolSetting, SymbolSettingChanged, true); - + _config.OnValueChanged(CCVars.AdminPlayerlistSeparateSymbols, PlayerListSettingsChanged); + _config.OnValueChanged(CCVars.AdminPlayerlistHighlightedCharacterColor, PlayerListSettingsChanged); + _config.OnValueChanged(CCVars.AdminPlayerlistRoleTypeColor, PlayerListSettingsChanged); OverlayButton.OnPressed += OverlayButtonPressed; ShowDisconnectedButton.OnPressed += ShowDisconnectedPressed; @@ -118,27 +113,8 @@ protected override void Dispose(bool disposing) #region ListContainer - private void RoleSettingChanged(string s) - { - if (!Enum.TryParse(s, out var format)) - format = AdminPlayerTabRoleTypeOption.Subtype; - _playerTabRoleSetting = format; - RefreshPlayerList(_adminSystem.PlayerList); - } - - private void ColorSettingChanged(string s) - { - if (!Enum.TryParse(s, out var format)) - format = AdminPlayerTabColorOption.Both; - _playerTabColorSetting = format; - RefreshPlayerList(_adminSystem.PlayerList); - } - - private void SymbolSettingChanged(string s) + private void PlayerListSettingsChanged(bool _) { - if (!Enum.TryParse(s, out var format)) - format = AdminPlayerTabSymbolOption.Specific; - _playerTabSymbolSetting = format; RefreshPlayerList(_adminSystem.PlayerList); } @@ -164,12 +140,7 @@ private void GenerateButton(ListData data, ListContainerButton button) if (data is not PlayerListData { Info: var player}) return; - var entry = new PlayerTabEntry( - player, - new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor), - _playerTabColorSetting, - _playerTabRoleSetting, - _playerTabSymbolSetting); + var entry = new PlayerTabEntry(player, new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor)); button.AddChild(entry); button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}"; } diff --git a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs index 41e3fca76121e..7c32d2e6bd2dc 100644 --- a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs @@ -96,4 +96,9 @@ public PlayerTabEntry( BackgroundColorPanel.PanelOverride = styleBoxFlat; OverallPlaytimeLabel.Text = player.PlaytimeString; } + + public PlayerTabEntry(PlayerInfo player, StyleBoxFlat styleBoxFlat) + { + throw new NotImplementedException(); + } } diff --git a/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml b/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml index ca22d7206b65e..449c16ad91319 100644 --- a/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml +++ b/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml @@ -6,18 +6,18 @@ diff --git a/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml.cs b/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml.cs index a25d83d337d67..d2e56d80ed38f 100644 --- a/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml.cs @@ -1,5 +1,3 @@ -using Content.Client.Administration; -using Content.Client.Administration.UI.Tabs.PlayerTab; using Content.Shared.CCVar; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface; @@ -21,43 +19,12 @@ public AdminOptionsTab() { RobustXamlLoader.Load(this); - var antagFormats = new List.ValueOption>(); - foreach (var format in Enum.GetValues(typeof(AdminOverlayAntagFormat))) - { - antagFormats.Add(new OptionDropDownCVar.ValueOption(format.ToString()!, Loc.GetString($"ui-options-admin-overlay-antag-format-{format.ToString()!.ToLower()}"))); - } - - var antagSymbolStyles = new List.ValueOption>(); - foreach (var symbol in Enum.GetValues(typeof(AdminOverlayAntagSymbolStyle))) - { - antagSymbolStyles.Add(new OptionDropDownCVar.ValueOption(symbol.ToString()!, Loc.GetString($"ui-options-admin-overlay-antag-symbol-{symbol.ToString()!.ToLower()}"))); - } - - var playerTabColorSettings = new List.ValueOption>(); - foreach (var setting in Enum.GetValues(typeof(AdminPlayerTabColorOption))) - { - playerTabColorSettings.Add(new OptionDropDownCVar.ValueOption(setting.ToString()!, Loc.GetString($"ui-options-admin-player-tab-color-setting-{setting.ToString()!.ToLower()}"))); - } - - var playerTabRoleSettings = new List.ValueOption>(); - foreach (var setting in Enum.GetValues(typeof(AdminPlayerTabRoleTypeOption))) - { - playerTabRoleSettings.Add(new OptionDropDownCVar.ValueOption(setting.ToString()!, Loc.GetString($"ui-options-admin-player-tab-role-setting-{setting.ToString()!.ToLower()}"))); - } - - var playerTabSymbolSettings = new List.ValueOption>(); - foreach (var setting in Enum.GetValues(typeof(AdminPlayerTabSymbolOption))) - { - playerTabSymbolSettings.Add(new OptionDropDownCVar.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.AdminPlayerlistSeparateSymbols, PlayerlistSeparateSymbolsCheckBox); + Control.AddOptionCheckBox(CCVars.AdminPlayerlistHighlightedCharacterColor, PlayerlistCharacterColorCheckBox); + Control.AddOptionCheckBox(CCVars.AdminPlayerlistRoleTypeColor, PlayerlistRoleTypeColorCheckBox); + Control.AddOptionCheckBox(CCVars.AdminOverlayClassic, EnableClassicOverlayCheckBox); + Control.AddOptionCheckBox(CCVars.AdminOverlaySymbols, EnableOverlaySymbolsCheckBox); Control.AddOptionCheckBox(CCVars.AdminOverlayPlaytime, EnableOverlayPlaytimeCheckBox); Control.AddOptionCheckBox(CCVars.AdminOverlayStartingJob, EnableOverlayStartingJobCheckBox); diff --git a/Content.Client/_DV/CosmicCult/CosmicCultSystem.cs b/Content.Client/_DV/CosmicCult/CosmicCultSystem.cs new file mode 100644 index 0000000000000..e849fdfcaa84f --- /dev/null +++ b/Content.Client/_DV/CosmicCult/CosmicCultSystem.cs @@ -0,0 +1,189 @@ +using Content.Shared._DV.CosmicCult.Components; +using Content.Shared._DV.CosmicCult; +using Content.Shared.StatusIcon.Components; +using Robust.Shared.Prototypes; +using Robust.Client.GameObjects; +using Robust.Shared.Utility; +using Content.Shared._DV.CosmicCult.Components.Examine; +using System.Numerics; +using Timer = Robust.Shared.Timing.Timer; +using Robust.Client.Audio; +using Robust.Shared.Audio; +using Content.Client.Alerts; +using Content.Client.UserInterface.Systems.Alerts.Controls; + +namespace Content.Client._DV.CosmicCult; + +public sealed partial class CosmicCultSystem : SharedCosmicCultSystem +{ + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private readonly ResPath _rsiPath = new("/Textures/_DV/CosmicCult/Effects/ability_siphonvfx.rsi"); + + private readonly SoundSpecifier _siphonSFX = new SoundPathSpecifier("/Audio/_DV/CosmicCult/ability_siphon.ogg"); + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAscendedInfectionAdded); + SubscribeLocalEvent(OnAscendedInfectionRemoved); + + SubscribeLocalEvent(OnAscendedAuraAdded); + SubscribeLocalEvent(OnAscendedAuraRemoved); + + SubscribeLocalEvent(OnCosmicStarMarkAdded); + SubscribeLocalEvent(OnCosmicStarMarkRemoved); + + SubscribeLocalEvent(OnCosmicImpositionAdded); + SubscribeLocalEvent(OnCosmicImpositionRemoved); + + SubscribeLocalEvent(GetCosmicCultIcon); + SubscribeLocalEvent(GetCosmicCultLeadIcon); + SubscribeLocalEvent(GetCosmicSSDIcon); + + SubscribeNetworkEvent(OnSiphon); + SubscribeLocalEvent(OnUpdateAlert); + } + + #region Siphon Visuals + private void OnSiphon(CosmicSiphonIndicatorEvent args) + { + var ent = GetEntity(args.Target); + if (!TryComp(ent, out var sprite)) + return; + var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(_rsiPath, "vfx")); + sprite.LayerMapSet(CultSiphonedVisuals.Key, layer); + sprite.LayerSetOffset(layer, new Vector2(0, 0.8f)); + sprite.LayerSetScale(layer, new Vector2(0.65f, 0.65f)); + sprite.LayerSetShader(layer, "unshaded"); + + Timer.Spawn(TimeSpan.FromSeconds(2), () => sprite.RemoveLayer(CultSiphonedVisuals.Key)); + _audio.PlayLocal(_siphonSFX, ent, ent, AudioParams.Default.WithVariation(0.1f)); + } + + private void OnUpdateAlert(Entity ent, ref UpdateAlertSpriteEvent args) + { + if (args.Alert.ID != ent.Comp.EntropyAlert) + return; + var entropy = Math.Clamp(ent.Comp.EntropyStored, 0, 14); + var sprite = args.SpriteViewEnt.Comp; + sprite.LayerSetState(AlertVisualLayers.Base, $"base{entropy}"); + sprite.LayerSetState(CultAlertVisualLayers.Counter, $"num{entropy}"); + } + #endregion + + #region Layer Additions + private void OnAscendedInfectionAdded(Entity uid, ref ComponentStartup args) + { + if (!TryComp(uid, out var sprite) || sprite.LayerMapTryGet(AscendedInfectionKey.Key, out _)) + return; + + var layer = sprite.AddLayer(uid.Comp.Sprite); + + sprite.LayerMapSet(AscendedInfectionKey.Key, layer); + sprite.LayerSetShader(layer, "unshaded"); + } + + private void OnAscendedAuraAdded(Entity uid, ref ComponentStartup args) + { + if (!TryComp(uid, out var sprite) || sprite.LayerMapTryGet(AscendedAuraKey.Key, out _)) + return; + + var layer = sprite.AddLayer(uid.Comp.Sprite); + + sprite.LayerMapSet(AscendedAuraKey.Key, layer); + sprite.LayerSetShader(layer, "unshaded"); + } + + private void OnCosmicStarMarkAdded(Entity uid, ref ComponentStartup args) + { + if (!TryComp(uid, out var sprite) || sprite.LayerMapTryGet(CosmicRevealedKey.Key, out _)) + return; + + var layer = sprite.AddLayer(uid.Comp.Sprite); + sprite.LayerMapSet(CosmicRevealedKey.Key, layer); + sprite.LayerSetShader(layer, "unshaded"); + + //offset the mark if the mob has an offset comp, needed for taller species like Thaven + if (TryComp(uid, out var offset)) + { + sprite.LayerSetOffset(CosmicRevealedKey.Key, offset.Offset); + } + } + + private void OnCosmicImpositionAdded(Entity uid, ref ComponentStartup args) + { + if (!TryComp(uid, out var sprite) || sprite.LayerMapTryGet(CosmicImposingKey.Key, out _)) + return; + + var layer = sprite.AddLayer(uid.Comp.Sprite); + + sprite.LayerMapSet(CosmicImposingKey.Key, layer); + sprite.LayerSetShader(layer, "unshaded"); + } + #endregion + + #region Layer Removals + private void OnAscendedInfectionRemoved(Entity uid, ref ComponentShutdown args) + { + if (!TryComp(uid, out var sprite)) + return; + + sprite.RemoveLayer(AscendedInfectionKey.Key); + } + + private void OnAscendedAuraRemoved(Entity uid, ref ComponentShutdown args) + { + if (!TryComp(uid, out var sprite)) + return; + + sprite.RemoveLayer(AscendedAuraKey.Key); + } + + private void OnCosmicStarMarkRemoved(Entity uid, ref ComponentShutdown args) + { + if (!TryComp(uid, out var sprite)) + return; + + sprite.RemoveLayer(CosmicRevealedKey.Key); + } + + private void OnCosmicImpositionRemoved(Entity uid, ref ComponentShutdown args) + { + if (!TryComp(uid, out var sprite)) + return; + + sprite.RemoveLayer(CosmicImposingKey.Key); + } + #endregion + + #region Icons + private void GetCosmicCultIcon(Entity ent, ref GetStatusIconsEvent args) + { + if (HasComp(ent)) + return; + + if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); + } + + private void GetCosmicCultLeadIcon(Entity ent, ref GetStatusIconsEvent args) + { + if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); + } + + private void GetCosmicSSDIcon(Entity ent, ref GetStatusIconsEvent args) + { + if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); + } + #endregion +} + +public enum CultSiphonedVisuals : byte +{ + Key +} diff --git a/Content.Client/_DV/CosmicCult/MonumentSystem.cs b/Content.Client/_DV/CosmicCult/MonumentSystem.cs new file mode 100644 index 0000000000000..f21b0b7f28a9d --- /dev/null +++ b/Content.Client/_DV/CosmicCult/MonumentSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._DV.CosmicCult; + +namespace Content.Client._DV.CosmicCult; + +public sealed class MonumentSystem : SharedMonumentSystem; diff --git a/Content.Client/_DV/CosmicCult/MonumentVisualsSystem.cs b/Content.Client/_DV/CosmicCult/MonumentVisualsSystem.cs new file mode 100644 index 0000000000000..15d5e6fd17c96 --- /dev/null +++ b/Content.Client/_DV/CosmicCult/MonumentVisualsSystem.cs @@ -0,0 +1,44 @@ +using Robust.Client.GameObjects; +using Content.Shared._DV.CosmicCult.Components; + +namespace Content.Client._DV.CosmicCult; + +/// +/// Visualizer for The Monument of the Cosmic Cult. +/// +public sealed class MonumentVisualizerSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAppearanceChanged); + } + + private void OnAppearanceChanged(Entity ent, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + args.Sprite.LayerMapTryGet(MonumentVisualLayers.TransformLayer, out var transformLayer); + args.Sprite.LayerMapTryGet(MonumentVisualLayers.MonumentLayer, out var baseLayer); + _appearance.TryGetData(ent, MonumentVisuals.Transforming, out var transforming, args.Component); + _appearance.TryGetData(ent, MonumentVisuals.Tier3, out var tier3, args.Component); + if (!tier3) + args.Sprite.LayerSetState(transformLayer, "transform-stage2"); + else + args.Sprite.LayerSetState(transformLayer, "transform-stage3"); + if (transforming && HasComp(ent)) + { + args.Sprite.LayerSetAnimationTime(transformLayer, 0f); + args.Sprite.LayerSetVisible(transformLayer, true); + args.Sprite.LayerSetVisible(baseLayer, false); + } + else + { + args.Sprite.LayerSetVisible(transformLayer, false); + args.Sprite.LayerSetVisible(baseLayer, true); + } + } +} diff --git a/Content.Client/_DV/CosmicCult/UI/CosmicConvertedEui.cs b/Content.Client/_DV/CosmicCult/UI/CosmicConvertedEui.cs new file mode 100644 index 0000000000000..503cdfd51d711 --- /dev/null +++ b/Content.Client/_DV/CosmicCult/UI/CosmicConvertedEui.cs @@ -0,0 +1,25 @@ +using Content.Client.Eui; + +namespace Content.Client._DV.CosmicCult.UI; + +public sealed class CosmicConvertedEui : BaseEui +{ + private readonly CosmicConvertedMenu _menu; + + public CosmicConvertedEui() + { + _menu = new CosmicConvertedMenu(); + } + + public override void Opened() + { + _menu.OpenCentered(); + } + + public override void Closed() + { + base.Closed(); + + _menu.Close(); + } +} diff --git a/Content.Client/_DV/CosmicCult/UI/CosmicConvertedMenu.xaml b/Content.Client/_DV/CosmicCult/UI/CosmicConvertedMenu.xaml new file mode 100644 index 0000000000000..3a97b7cd88afc --- /dev/null +++ b/Content.Client/_DV/CosmicCult/UI/CosmicConvertedMenu.xaml @@ -0,0 +1,11 @@ + + +