]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Cleans up StatusIconSystem and fixing some bugs (#28270)
authorAJCM-git <60196617+AJCM-git@users.noreply.github.com>
Mon, 3 Jun 2024 16:12:21 +0000 (12:12 -0400)
committerGitHub <noreply@github.com>
Mon, 3 Jun 2024 16:12:21 +0000 (12:12 -0400)
49 files changed:
Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs
Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
Content.Client/Antag/AntagStatusIconSystem.cs [deleted file]
Content.Client/Commands/ShowHealthBarsCommand.cs
Content.Client/LateJoin/LateJoinGui.cs
Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
Content.Client/Overlays/EntityHealthBarOverlay.cs
Content.Client/Overlays/ShowCriminalRecordIconsSystem.cs
Content.Client/Overlays/ShowHealthBarsSystem.cs
Content.Client/Overlays/ShowHealthIconsSystem.cs
Content.Client/Overlays/ShowHungerIconsSystem.cs
Content.Client/Overlays/ShowJobIconsSystem.cs
Content.Client/Overlays/ShowMindShieldIconsSystem.cs
Content.Client/Overlays/ShowSyndicateIconsSystem.cs
Content.Client/Overlays/ShowThirstIconsSystem.cs
Content.Client/Revolutionary/RevolutionarySystem.cs
Content.Client/SSDIndicator/SSDIndicatorSystem.cs
Content.Client/StatusIcon/StatusIconOverlay.cs
Content.Client/StatusIcon/StatusIconSystem.cs
Content.Client/Stealth/StealthSystem.cs
Content.Client/Zombies/ZombieSystem.cs
Content.Server/Access/Components/AgentIDCardComponent.cs
Content.Server/Access/Systems/AgentIDCardSystem.cs
Content.Server/Access/Systems/IdCardConsoleSystem.cs
Content.Server/Access/Systems/PresetIdCardSystem.cs
Content.Server/Revolutionary/RevolutionarySystem.cs [new file with mode: 0644]
Content.Server/Station/Systems/StationSpawningSystem.cs
Content.Shared/Access/SharedAgentIDCardSystem.cs
Content.Shared/Antag/IAntagStatusIconComponent.cs [deleted file]
Content.Shared/Antag/ShowAntagIconsComponent.cs [new file with mode: 0644]
Content.Shared/Overlays/ShowHealthBarsComponent.cs
Content.Shared/Revolutionary/Components/HeadRevolutionaryComponent.cs
Content.Shared/Revolutionary/Components/RevolutionaryComponent.cs
Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs [deleted file]
Content.Shared/Revolutionary/SharedRevolutionarySystem.cs
Content.Shared/Roles/JobPrototype.cs
Content.Shared/SSDIndicator/SSDIndicatorComponent.cs
Content.Shared/StatusIcon/Components/StatusIconComponent.cs
Content.Shared/StatusIcon/StatusIconPrototype.cs
Content.Shared/Zombies/InitialInfectedComponent.cs
Content.Shared/Zombies/ShowZombieIconsComponent.cs [deleted file]
Content.Shared/Zombies/ZombieComponent.cs
Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml
Resources/Prototypes/StatusIcon/StatusEffects/health.yml [moved from Resources/Prototypes/StatusEffects/health.yml with 100% similarity]
Resources/Prototypes/StatusIcon/StatusEffects/hunger.yml [moved from Resources/Prototypes/StatusEffects/hunger.yml with 100% similarity]
Resources/Prototypes/StatusIcon/StatusEffects/ssd.yml [moved from Resources/Prototypes/StatusEffects/ssd.yml with 100% similarity]
Resources/Prototypes/StatusIcon/antag.yml
Resources/Prototypes/StatusIcon/job.yml [moved from Resources/Prototypes/StatusEffects/job.yml with 100% similarity]
Resources/Prototypes/StatusIcon/security.yml [moved from Resources/Prototypes/StatusEffects/security.yml with 100% similarity]

index c3fac8cb92a587cb97b21570a6b6bb555ad4c2f3..761f52988a9da43c5788cc2a8e54bdbc212d9b11 100644 (file)
@@ -1,5 +1,7 @@
 using Content.Shared.Access.Systems;
+using Content.Shared.StatusIcon;
 using Robust.Client.GameObjects;
+using Robust.Shared.Prototypes;
 
 namespace Content.Client.Access.UI
 {
@@ -40,7 +42,7 @@ namespace Content.Client.Access.UI
             SendMessage(new AgentIDCardJobChangedMessage(newJob));
         }
 
-        public void OnJobIconChanged(string newJobIconId)
+        public void OnJobIconChanged(ProtoId<StatusIconPrototype> newJobIconId)
         {
             SendMessage(new AgentIDCardJobIconChangedMessage(newJobIconId));
         }
index 9a38c0c485309df96f54a9715056cf697fff5460..6d0b2a184f49d29fbfae11116d82c0b2bab4a52d 100644 (file)
@@ -38,7 +38,7 @@ namespace Content.Client.Access.UI
             JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text);
         }
 
-        public void SetAllowedIcons(HashSet<string> icons, string currentJobIconId)
+        public void SetAllowedIcons(HashSet<ProtoId<StatusIconPrototype>> icons, string currentJobIconId)
         {
             IconGrid.DisposeAllChildren();
 
@@ -46,10 +46,8 @@ namespace Content.Client.Access.UI
             var i = 0;
             foreach (var jobIconId in icons)
             {
-                if (!_prototypeManager.TryIndex<StatusIconPrototype>(jobIconId, out var jobIcon))
-                {
+                if (!_prototypeManager.TryIndex(jobIconId, out var jobIcon))
                     continue;
-                }
 
                 String styleBase = StyleBase.ButtonOpenBoth;
                 var modulo = i % JobIconColumnCount;
@@ -77,7 +75,7 @@ namespace Content.Client.Access.UI
                 };
 
                 jobIconButton.AddChild(jobIconTexture);
-                jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIcon.ID);
+                jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIconId);
                 IconGrid.AddChild(jobIconButton);
 
                 if (jobIconId.Equals(currentJobIconId))
diff --git a/Content.Client/Antag/AntagStatusIconSystem.cs b/Content.Client/Antag/AntagStatusIconSystem.cs
deleted file mode 100644 (file)
index 804ae21..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-using Content.Shared.Antag;
-using Content.Shared.Revolutionary.Components;
-using Content.Shared.StatusIcon;
-using Content.Shared.StatusIcon.Components;
-using Content.Shared.Zombies;
-using Robust.Client.Player;
-using Robust.Shared.Prototypes;
-
-namespace Content.Client.Antag;
-
-/// <summary>
-/// Used for assigning specified icons for antags.
-/// </summary>
-public sealed class AntagStatusIconSystem : SharedStatusIconSystem
-{
-    [Dependency] private readonly IPrototypeManager _prototype = default!;
-    [Dependency] private readonly IPlayerManager _player = default!;
-    public override void Initialize()
-    {
-        base.Initialize();
-
-        SubscribeLocalEvent<RevolutionaryComponent, GetStatusIconsEvent>(GetRevIcon);
-        SubscribeLocalEvent<ZombieComponent, GetStatusIconsEvent>(GetIcon);
-        SubscribeLocalEvent<HeadRevolutionaryComponent, GetStatusIconsEvent>(GetIcon);
-        SubscribeLocalEvent<InitialInfectedComponent, GetStatusIconsEvent>(GetIcon);
-    }
-
-    /// <summary>
-    /// Adds a Status Icon on an entity if the player is supposed to see it.
-    /// </summary>
-    private void GetIcon<T>(EntityUid uid, T comp, ref GetStatusIconsEvent ev) where T: IAntagStatusIconComponent
-    {
-        var ent = _player.LocalSession?.AttachedEntity;
-
-        var canEv = new CanDisplayStatusIconsEvent(ent);
-        RaiseLocalEvent(uid, ref canEv);
-
-        if (!canEv.Cancelled)
-            ev.StatusIcons.Add(_prototype.Index(comp.StatusIcon));
-    }
-
-
-    /// <summary>
-    /// Adds the Rev Icon on an entity if the player is supposed to see it. This additional function is needed to deal
-    /// with a special case where if someone is a head rev we only want to display the headrev icon.
-    /// </summary>
-    private void GetRevIcon(EntityUid uid, RevolutionaryComponent comp, ref GetStatusIconsEvent ev)
-    {
-        if (HasComp<HeadRevolutionaryComponent>(uid))
-            return;
-
-        GetIcon(uid, comp, ref ev);
-
-    }
-}
index bd3e21718f0a265335efb70c082ff51c2f61e58a..ef918313a0d13b1dfa3457d96f4640f355719961 100644 (file)
@@ -35,6 +35,7 @@ public sealed class ShowHealthBarsCommand : LocalizedCommands
             var showHealthBarsComponent = new ShowHealthBarsComponent
             {
                 DamageContainers = args.ToList(),
+                HealthStatusIcon = "",
                 NetSyncEnabled = false
             };
 
index ba9351d6746bb32a5cc92eb1a7eba3d84b8946f3..252aa9aafad48b46f24436e6c2b6dfc58a8b5638 100644 (file)
@@ -244,7 +244,7 @@ namespace Content.Client.LateJoin
                             VerticalAlignment = VAlignment.Center
                         };
 
-                        var jobIcon = _prototypeManager.Index<StatusIconPrototype>(prototype.Icon);
+                        var jobIcon = _prototypeManager.Index(prototype.Icon);
                         icon.Texture = _sprites.Frame0(jobIcon.Icon);
                         jobSelector.AddChild(icon);
 
index eb182c83ee115f45870ebe916eada9237170be30..53c332c1857f0a3f2a4a60b1df722801ab2db1f9 100644 (file)
@@ -806,7 +806,7 @@ namespace Content.Client.Lobby.UI
                         TextureScale = new Vector2(2, 2),
                         VerticalAlignment = VAlignment.Center
                     };
-                    var jobIcon = _prototypeManager.Index<StatusIconPrototype>(job.Icon);
+                    var jobIcon = _prototypeManager.Index(job.Icon);
                     icon.Texture = jobIcon.Icon.Frame0();
                     selector.Setup(items, job.LocalizedName, 200, job.LocalizedDescription, icon);
 
index 758bb562f92af3805cf15426aec70c6a0c45214b..55978d98f7e2480773d56cbec9969ba355d0b953 100644 (file)
@@ -1,14 +1,17 @@
 using System.Numerics;
+using Content.Client.StatusIcon;
 using Content.Client.UserInterface.Systems;
 using Content.Shared.Damage;
 using Content.Shared.FixedPoint;
 using Content.Shared.Mobs;
 using Content.Shared.Mobs.Components;
 using Content.Shared.Mobs.Systems;
+using Content.Shared.StatusIcon;
 using Content.Shared.StatusIcon.Components;
 using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
 using Robust.Shared.Enums;
+using Robust.Shared.Prototypes;
 using static Robust.Shared.Maths.Color;
 
 namespace Content.Client.Overlays;
@@ -19,19 +22,27 @@ namespace Content.Client.Overlays;
 public sealed class EntityHealthBarOverlay : Overlay
 {
     private readonly IEntityManager _entManager;
+    private readonly IPrototypeManager _prototype;
+
     private readonly SharedTransformSystem _transform;
     private readonly MobStateSystem _mobStateSystem;
     private readonly MobThresholdSystem _mobThresholdSystem;
+    private readonly StatusIconSystem _statusIconSystem;
     private readonly ProgressColorSystem _progressColor;
+
+
     public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
     public HashSet<string> DamageContainers = new();
+    public ProtoId<StatusIconPrototype> StatusIcon;
 
-    public EntityHealthBarOverlay(IEntityManager entManager)
+    public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager prototype)
     {
         _entManager = entManager;
+        _prototype = prototype;
         _transform = _entManager.System<SharedTransformSystem>();
         _mobStateSystem = _entManager.System<MobStateSystem>();
         _mobThresholdSystem = _entManager.System<MobThresholdSystem>();
+        _statusIconSystem = _entManager.System<StatusIconSystem>();
         _progressColor = _entManager.System<ProgressColorSystem>();
     }
 
@@ -44,6 +55,7 @@ public sealed class EntityHealthBarOverlay : Overlay
         const float scale = 1f;
         var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale));
         var rotationMatrix = Matrix3Helpers.CreateRotation(-rotation);
+        _prototype.TryIndex(StatusIcon, out var statusIcon);
 
         var query = _entManager.AllEntityQueryEnumerator<MobThresholdsComponent, MobStateComponent, DamageableComponent, SpriteComponent>();
         while (query.MoveNext(out var uid,
@@ -52,31 +64,23 @@ public sealed class EntityHealthBarOverlay : Overlay
             out var damageableComponent,
             out var spriteComponent))
         {
-            if (_entManager.TryGetComponent<MetaDataComponent>(uid, out var metaDataComponent) &&
-                metaDataComponent.Flags.HasFlag(MetaDataFlags.InContainer))
-            {
+            if (statusIcon != null && !_statusIconSystem.IsVisible((uid, _entManager.GetComponent<MetaDataComponent>(uid)), statusIcon))
                 continue;
-            }
 
+            // We want the stealth user to still be able to see his health bar himself
             if (!xformQuery.TryGetComponent(uid, out var xform) ||
                 xform.MapID != args.MapId)
-            {
                 continue;
-            }
 
             if (damageableComponent.DamageContainerID == null || !DamageContainers.Contains(damageableComponent.DamageContainerID))
-            {
                 continue;
-            }
 
             // we use the status icon component bounds if specified otherwise use sprite
             var bounds = _entManager.GetComponentOrNull<StatusIconComponent>(uid)?.Bounds ?? spriteComponent.Bounds;
             var worldPos = _transform.GetWorldPosition(xform, xformQuery);
 
             if (!bounds.Translated(worldPos).Intersects(args.WorldAABB))
-            {
                 continue;
-            }
 
             // we are all progressing towards death every day
             if (CalcProgress(uid, mobStateComponent, damageableComponent, mobThresholdsComponent) is not { } deathProgress)
index 8f23cd510cb347476d9c157f9e339a75b6a8ff22..c353b1727295c4739f59cffe48595dbad38d9ffc 100644 (file)
@@ -19,10 +19,10 @@ public sealed class ShowCriminalRecordIconsSystem : EquipmentHudSystem<ShowCrimi
 
     private void OnGetStatusIconsEvent(EntityUid uid, CriminalRecordComponent component, ref GetStatusIconsEvent ev)
     {
-        if (!IsActive || ev.InContainer)
+        if (!IsActive)
             return;
 
-        if (_prototype.TryIndex<StatusIconPrototype>(component.StatusIcon.Id, out var iconPrototype))
+        if (_prototype.TryIndex(component.StatusIcon, out var iconPrototype))
             ev.StatusIcons.Add(iconPrototype);
     }
 }
index 170f552cf3ff31a6a8ffa9e6fbc419a61c0e0ad4..1eb712a8988f3e53945f30e84590703b0f74e74b 100644 (file)
@@ -2,6 +2,8 @@ using Content.Shared.Inventory.Events;
 using Content.Shared.Overlays;
 using Robust.Client.Graphics;
 using System.Linq;
+using Robust.Client.Player;
+using Robust.Shared.Prototypes;
 
 namespace Content.Client.Overlays;
 
@@ -11,6 +13,7 @@ namespace Content.Client.Overlays;
 public sealed class ShowHealthBarsSystem : EquipmentHudSystem<ShowHealthBarsComponent>
 {
     [Dependency] private readonly IOverlayManager _overlayMan = default!;
+    [Dependency] private readonly IPrototypeManager _prototype = default!;
 
     private EntityHealthBarOverlay _overlay = default!;
 
@@ -18,16 +21,21 @@ public sealed class ShowHealthBarsSystem : EquipmentHudSystem<ShowHealthBarsComp
     {
         base.Initialize();
 
-        _overlay = new(EntityManager);
+        _overlay = new(EntityManager, _prototype);
     }
 
     protected override void UpdateInternal(RefreshEquipmentHudEvent<ShowHealthBarsComponent> component)
     {
         base.UpdateInternal(component);
 
-        foreach (var damageContainerId in component.Components.SelectMany(x => x.DamageContainers))
+        foreach (var comp in component.Components)
         {
-            _overlay.DamageContainers.Add(damageContainerId);
+            foreach (var damageContainerId in comp.DamageContainers)
+            {
+                _overlay.DamageContainers.Add(damageContainerId);
+            }
+
+            _overlay.StatusIcon = comp.HealthStatusIcon;
         }
 
         if (!_overlayMan.HasOverlay<EntityHealthBarOverlay>())
index a546cf4d8281ae2559bdc11a3456ecd9797ef67a..d8af91482b3efad2aaaae13cef7840d8773add66 100644 (file)
@@ -24,7 +24,6 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem<ShowHealthIconsCo
         base.Initialize();
 
         SubscribeLocalEvent<DamageableComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
-
     }
 
     protected override void UpdateInternal(RefreshEquipmentHudEvent<ShowHealthIconsComponent> component)
@@ -46,7 +45,7 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem<ShowHealthIconsCo
 
     private void OnGetStatusIconsEvent(Entity<DamageableComponent> entity, ref GetStatusIconsEvent args)
     {
-        if (!IsActive || args.InContainer)
+        if (!IsActive)
             return;
 
         var healthIcons = DecideHealthIcons(entity);
index b1c0f3a1a0c9acba5b55f4da691e9294bee65838..6b0d575a81021bf342b16789d65336e6a97e909c 100644 (file)
@@ -18,7 +18,7 @@ public sealed class ShowHungerIconsSystem : EquipmentHudSystem<ShowHungerIconsCo
 
     private void OnGetStatusIconsEvent(EntityUid uid, HungerComponent component, ref GetStatusIconsEvent ev)
     {
-        if (!IsActive || ev.InContainer)
+        if (!IsActive)
             return;
 
         if (_hunger.TryGetStatusIconPrototype(component, out var iconPrototype))
index e24b99f3e87d21f4eb8f52b6cc79a82ffff0d740..a6d4f70af6b4c7df14d260639f8137ef719f475a 100644 (file)
@@ -25,7 +25,7 @@ public sealed class ShowJobIconsSystem : EquipmentHudSystem<ShowJobIconsComponen
 
     private void OnGetStatusIconsEvent(EntityUid uid, StatusIconComponent _, ref GetStatusIconsEvent ev)
     {
-        if (!IsActive || ev.InContainer)
+        if (!IsActive)
             return;
 
         var iconId = JobIconForNoId;
index 8bf39b875f66308ede403c014e8af03cb1ccef41..cdb9c54fdfa41a56c35c4c4b45952d641c079617 100644 (file)
@@ -19,10 +19,10 @@ public sealed class ShowMindShieldIconsSystem : EquipmentHudSystem<ShowMindShiel
 
     private void OnGetStatusIconsEvent(EntityUid uid, MindShieldComponent component, ref GetStatusIconsEvent ev)
     {
-        if (!IsActive || ev.InContainer)
+        if (!IsActive)
             return;
 
-        if (_prototype.TryIndex<StatusIconPrototype>(component.MindShieldStatusIcon.Id, out var iconPrototype))
+        if (_prototype.TryIndex(component.MindShieldStatusIcon, out var iconPrototype))
             ev.StatusIcons.Add(iconPrototype);
     }
 }
index 660ef198e14709f08f1671ed6e8054eb64b81cd2..782178a29dbecc468669ab2c1796a5ee146238f6 100644 (file)
@@ -19,11 +19,10 @@ public sealed class ShowSyndicateIconsSystem : EquipmentHudSystem<ShowSyndicateI
 
     private void OnGetStatusIconsEvent(EntityUid uid, NukeOperativeComponent component, ref GetStatusIconsEvent ev)
     {
-        if (!IsActive || ev.InContainer)
+        if (!IsActive)
             return;
 
         if (_prototype.TryIndex<StatusIconPrototype>(component.SyndStatusIcon, out var iconPrototype))
             ev.StatusIcons.Add(iconPrototype);
     }
 }
-
index b08aa4340b215f0b0c11146e8e634732f98dff23..44be1f7a67f53fb2c1403d4cd60d6b8cb5ec42c4 100644 (file)
@@ -18,7 +18,7 @@ public sealed class ShowThirstIconsSystem : EquipmentHudSystem<ShowThirstIconsCo
 
     private void OnGetStatusIconsEvent(EntityUid uid, ThirstComponent component, ref GetStatusIconsEvent ev)
     {
-        if (!IsActive || ev.InContainer)
+        if (!IsActive)
             return;
 
         if (_thirst.TryGetStatusIconPrototype(component, out var iconPrototype))
index 682c73f93e784adc3927127ce63ab54187053c05..8e7e687fa8fcfba4859b7e444d27ef029162ac33 100644 (file)
@@ -1,44 +1,37 @@
-using Content.Shared.Antag;
 using Content.Shared.Revolutionary.Components;
-using Content.Shared.Ghost;
+using Content.Shared.Revolutionary;
 using Content.Shared.StatusIcon.Components;
+using Robust.Shared.Prototypes;
 
 namespace Content.Client.Revolutionary;
 
 /// <summary>
 /// Used for the client to get status icons from other revs.
 /// </summary>
-public sealed class RevolutionarySystem : EntitySystem
+public sealed class RevolutionarySystem : SharedRevolutionarySystem
 {
+    [Dependency] private readonly IPrototypeManager _prototype = default!;
 
     public override void Initialize()
     {
         base.Initialize();
 
-        SubscribeLocalEvent<RevolutionaryComponent, CanDisplayStatusIconsEvent>(OnCanShowRevIcon);
-        SubscribeLocalEvent<HeadRevolutionaryComponent, CanDisplayStatusIconsEvent>(OnCanShowRevIcon);
+        SubscribeLocalEvent<RevolutionaryComponent, GetStatusIconsEvent>(GetRevIcon);
+        SubscribeLocalEvent<HeadRevolutionaryComponent, GetStatusIconsEvent>(GetHeadRevIcon);
     }
 
-    /// <summary>
-    /// Determine whether a client should display the rev icon.
-    /// </summary>
-    private void OnCanShowRevIcon<T>(EntityUid uid, T comp, ref CanDisplayStatusIconsEvent args) where T : IAntagStatusIconComponent
+    private void GetRevIcon(Entity<RevolutionaryComponent> ent, ref GetStatusIconsEvent args)
     {
-        args.Cancelled = !CanDisplayIcon(args.User, comp.IconVisibleToGhost);
+        if (HasComp<HeadRevolutionaryComponent>(ent))
+            return;
+
+        if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype))
+            args.StatusIcons.Add(iconPrototype);
     }
 
-    /// <summary>
-    /// The criteria that determine whether a client should see Rev/Head rev icons.
-    /// </summary>
-    private bool CanDisplayIcon(EntityUid? uid, bool visibleToGhost)
+    private void GetHeadRevIcon(Entity<HeadRevolutionaryComponent> ent, ref GetStatusIconsEvent args)
     {
-        if (HasComp<HeadRevolutionaryComponent>(uid) || HasComp<RevolutionaryComponent>(uid))
-            return true;
-
-        if (visibleToGhost && HasComp<GhostComponent>(uid))
-            return true;
-
-        return HasComp<ShowRevIconsComponent>(uid);
+        if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype))
+            args.StatusIcons.Add(iconPrototype);
     }
-
 }
index 587450a2f66bfce515a0a3e9175b6c39730283a8..e7311953170b7dd930ed059308f38721110d59b7 100644 (file)
@@ -30,13 +30,12 @@ public sealed class SSDIndicatorSystem : EntitySystem
     {
         if (component.IsSSD &&
             _cfg.GetCVar(CCVars.ICShowSSDIndicator) &&
-            !args.InContainer &&
             !_mobState.IsDead(uid) &&
             !HasComp<ActiveNPCComponent>(uid) &&
             TryComp<MindContainerComponent>(uid, out var mindContainer) &&
             mindContainer.ShowExamineInfo)
         {
-            args.StatusIcons.Add(_prototype.Index<StatusIconPrototype>(component.Icon));
+            args.StatusIcons.Add(_prototype.Index(component.Icon));
         }
     }
 }
index f1473bda7a2ab3bdd1f3392376c3f7534c93764e..4b3daae22fd84b9c52ca472f19b3603bec6a7d73 100644 (file)
@@ -45,7 +45,7 @@ public sealed class StatusIconOverlay : Overlay
         var query = _entity.AllEntityQueryEnumerator<StatusIconComponent, SpriteComponent, TransformComponent, MetaDataComponent>();
         while (query.MoveNext(out var uid, out var comp, out var sprite, out var xform, out var meta))
         {
-            if (xform.MapID != args.MapId)
+            if (xform.MapID != args.MapId || !sprite.Visible)
                 continue;
 
             var bounds = comp.Bounds ?? sprite.Bounds;
@@ -72,6 +72,8 @@ public sealed class StatusIconOverlay : Overlay
 
             foreach (var proto in icons)
             {
+                if (!_statusIcon.IsVisible((uid, meta), proto))
+                    continue;
 
                 var curTime = _timing.RealTime;
                 var texture = _sprite.GetFrame(proto.Icon, curTime);
index 980fd9f2a929c10b821bbac356eb6737f84aa4ce..63f57767695edcb2a66ab1874e9cdc6ea74b4520 100644 (file)
@@ -1,7 +1,11 @@
 using Content.Shared.CCVar;
+using Content.Shared.Ghost;
 using Content.Shared.StatusIcon;
 using Content.Shared.StatusIcon.Components;
+using Content.Shared.Stealth.Components;
+using Content.Shared.Whitelist;
 using Robust.Client.Graphics;
+using Robust.Client.Player;
 using Robust.Shared.Configuration;
 
 namespace Content.Client.StatusIcon;
@@ -13,6 +17,8 @@ public sealed class StatusIconSystem : SharedStatusIconSystem
 {
     [Dependency] private readonly IConfigurationManager _configuration = default!;
     [Dependency] private readonly IOverlayManager _overlay = default!;
+    [Dependency] private readonly IPlayerManager _playerManager = default!;
+    [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
 
     private bool _globalEnabled;
     private bool _localEnabled;
@@ -54,10 +60,34 @@ public sealed class StatusIconSystem : SharedStatusIconSystem
         if (meta.EntityLifeStage >= EntityLifeStage.Terminating)
             return list;
 
-        var inContainer = (meta.Flags & MetaDataFlags.InContainer) != 0;
-        var ev = new GetStatusIconsEvent(list, inContainer);
+        var ev = new GetStatusIconsEvent(list);
         RaiseLocalEvent(uid, ref ev);
         return ev.StatusIcons;
     }
-}
 
+    /// <summary>
+    /// For overlay to check if an entity can be seen.
+    /// </summary>
+    public bool IsVisible(Entity<MetaDataComponent> ent, StatusIconData data)
+    {
+        var viewer = _playerManager.LocalSession?.AttachedEntity;
+
+        // Always show our icons to our entity
+        if (viewer == ent.Owner)
+            return true;
+
+        if (data.VisibleToGhosts && HasComp<GhostComponent>(viewer))
+            return true;
+
+        if (data.HideInContainer && (ent.Comp.Flags & MetaDataFlags.InContainer) != 0)
+            return false;
+
+        if (data.HideOnStealth && TryComp<StealthComponent>(ent, out var stealth) && stealth.Enabled)
+            return false;
+
+        if (data.ShowTo != null && !_entityWhitelist.IsValid(data.ShowTo, viewer))
+            return false;
+
+        return true;
+    }
+}
index b60ffc2a4089645dac8da5e2060de539ac767aed..0b94e41f6bc6ffc026793a323d673765eeb05f0d 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Client.Interactable.Components;
+using Content.Client.StatusIcon;
 using Content.Shared.Stealth;
 using Content.Shared.Stealth.Components;
 using Robust.Client.GameObjects;
@@ -18,6 +19,7 @@ public sealed class StealthSystem : SharedStealthSystem
         base.Initialize();
 
         _shader = _protoMan.Index<ShaderPrototype>("Stealth").InstanceUnique();
+
         SubscribeLocalEvent<StealthComponent, ComponentShutdown>(OnShutdown);
         SubscribeLocalEvent<StealthComponent, ComponentStartup>(OnStartup);
         SubscribeLocalEvent<StealthComponent, BeforePostShaderRenderEvent>(OnShaderRender);
@@ -93,4 +95,3 @@ public sealed class StealthSystem : SharedStealthSystem
         args.Sprite.Color = new Color(visibility, visibility, 1, 1);
     }
 }
-
index 49b5d6aec184e4c53812dbdf8cd1ab076bd20e3f..d250e418504f6fde22852ad3fcbc8bee59a49b43 100644 (file)
@@ -1,59 +1,53 @@
 using System.Linq;
 using Content.Shared.Ghost;
 using Content.Shared.Humanoid;
+using Content.Shared.StatusIcon;
 using Content.Shared.StatusIcon.Components;
 using Content.Shared.Zombies;
 using Robust.Client.GameObjects;
+using Robust.Shared.Prototypes;
 
 namespace Content.Client.Zombies;
 
-public sealed class ZombieSystem : EntitySystem
+public sealed class ZombieSystem : SharedZombieSystem
 {
+    [Dependency] private readonly IPrototypeManager _prototype = default!;
+
     public override void Initialize()
     {
         base.Initialize();
 
         SubscribeLocalEvent<ZombieComponent, ComponentStartup>(OnStartup);
-        SubscribeLocalEvent<ZombieComponent, CanDisplayStatusIconsEvent>(OnCanDisplayStatusIcons);
-        SubscribeLocalEvent<InitialInfectedComponent, CanDisplayStatusIconsEvent>(OnCanDisplayStatusIcons);
+        SubscribeLocalEvent<ZombieComponent, GetStatusIconsEvent>(GetZombieIcon);
+        SubscribeLocalEvent<InitialInfectedComponent, GetStatusIconsEvent>(GetInitialInfectedIcon);
     }
 
-    private void OnStartup(EntityUid uid, ZombieComponent component, ComponentStartup args)
+    private void GetZombieIcon(Entity<ZombieComponent> ent, ref GetStatusIconsEvent args)
     {
-        if (HasComp<HumanoidAppearanceComponent>(uid))
-            return;
-
-        if (!TryComp<SpriteComponent>(uid, out var sprite))
-            return;
-
-        for (var i = 0; i < sprite.AllLayers.Count(); i++)
-        {
-            sprite.LayerSetColor(i, component.SkinColor);
-        }
+        var iconPrototype = _prototype.Index(ent.Comp.StatusIcon);
+        args.StatusIcons.Add(iconPrototype);
     }
 
-    /// <summary>
-    /// Determines whether a player should be able to see the StatusIcon for zombies.
-    /// </summary>
-    private void OnCanDisplayStatusIcons(EntityUid uid, ZombieComponent component, ref CanDisplayStatusIconsEvent args)
+    private void GetInitialInfectedIcon(Entity<InitialInfectedComponent> ent, ref GetStatusIconsEvent args)
     {
-        if (HasComp<ZombieComponent>(args.User) || HasComp<InitialInfectedComponent>(args.User) || HasComp<ShowZombieIconsComponent>(args.User))
-            return;
-
-        if (component.IconVisibleToGhost && HasComp<GhostComponent>(args.User))
+        if (HasComp<ZombieComponent>(ent))
             return;
 
-        args.Cancelled = true;
+        var iconPrototype = _prototype.Index(ent.Comp.StatusIcon);
+        args.StatusIcons.Add(iconPrototype);
     }
 
-    private void OnCanDisplayStatusIcons(EntityUid uid, InitialInfectedComponent component, ref CanDisplayStatusIconsEvent args)
+    private void OnStartup(EntityUid uid, ZombieComponent component, ComponentStartup args)
     {
-        if (HasComp<InitialInfectedComponent>(args.User) && !HasComp<ZombieComponent>(args.User))
+        if (HasComp<HumanoidAppearanceComponent>(uid))
             return;
 
-        if (component.IconVisibleToGhost && HasComp<GhostComponent>(args.User))
+        if (!TryComp<SpriteComponent>(uid, out var sprite))
             return;
 
-        args.Cancelled = true;
+        for (var i = 0; i < sprite.AllLayers.Count(); i++)
+        {
+            sprite.LayerSetColor(i, component.SkinColor);
+        }
     }
 }
index 4b92b43ea99211f046f326b751a8e0bb3cba7531..7a97c5f5653f549d5027a69dbc32148de0ff544c 100644 (file)
@@ -1,5 +1,5 @@
 using Content.Shared.StatusIcon;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+using Robust.Shared.Prototypes;
 
 namespace Content.Server.Access.Components
 {
@@ -9,7 +9,7 @@ namespace Content.Server.Access.Components
         /// <summary>
         /// Set of job icons that the agent ID card can show.
         /// </summary>
-        [DataField("icons", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<StatusIconPrototype>))]
-        public HashSet<string> Icons = new();
+        [DataField]
+        public HashSet<ProtoId<StatusIconPrototype>> Icons;
     }
 }
index d5e9dc357ddf6c04ba2ec0a0c36cfb77afdf9d01..f0ce3acbdb886a0e06af18ae1f79f5f2f37e4d9e 100644 (file)
@@ -90,14 +90,10 @@ namespace Content.Server.Access.Systems
         private void OnJobIconChanged(EntityUid uid, AgentIDCardComponent comp, AgentIDCardJobIconChangedMessage args)
         {
             if (!TryComp<IdCardComponent>(uid, out var idCard))
-            {
                 return;
-            }
 
-            if (!_prototypeManager.TryIndex<StatusIconPrototype>(args.JobIconId, out var jobIcon))
-            {
+            if (!_prototypeManager.TryIndex(args.JobIconId, out var jobIcon))
                 return;
-            }
 
             _cardSystem.TryChangeJobIcon(uid, jobIcon, idCard);
 
@@ -109,7 +105,7 @@ namespace Content.Server.Access.Systems
         {
             foreach (var jobPrototype in _prototypeManager.EnumeratePrototypes<JobPrototype>())
             {
-                if(jobPrototype.Icon == jobIcon.ID)
+                if (jobPrototype.Icon == jobIcon.ID)
                 {
                     job = jobPrototype;
                     return true;
index 4e63c93a837d23ccd94fdbe51d973443b05aec9a..e02664f2bbdfb979c44beb93ed69a8f6633f098f 100644 (file)
@@ -129,7 +129,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
         _idCard.TryChangeJobTitle(targetId, newJobTitle, player: player);
 
         if (_prototype.TryIndex<JobPrototype>(newJobProto, out var job)
-            && _prototype.TryIndex<StatusIconPrototype>(job.Icon, out var jobIcon))
+            && _prototype.TryIndex(job.Icon, out var jobIcon))
         {
             _idCard.TryChangeJobIcon(targetId, jobIcon, player: player);
             _idCard.TryChangeJobDepartment(targetId, job);
index 3e775b9c35da4a43726e20cccb511ede386f43c9..426e523243c3208b03bcfb571ca07f2af519b734 100644 (file)
@@ -82,9 +82,7 @@ public sealed class PresetIdCardSystem : EntitySystem
         _cardSystem.TryChangeJobTitle(uid, job.LocalizedName);
         _cardSystem.TryChangeJobDepartment(uid, job);
 
-        if (_prototypeManager.TryIndex<StatusIconPrototype>(job.Icon, out var jobIcon))
-        {
+        if (_prototypeManager.TryIndex(job.Icon, out var jobIcon))
             _cardSystem.TryChangeJobIcon(uid, jobIcon);
-        }
     }
 }
diff --git a/Content.Server/Revolutionary/RevolutionarySystem.cs b/Content.Server/Revolutionary/RevolutionarySystem.cs
new file mode 100644 (file)
index 0000000..597c489
--- /dev/null
@@ -0,0 +1,5 @@
+using Content.Shared.Revolutionary;
+
+namespace Content.Server.Revolutionary;
+
+public sealed class RevolutionarySystem : SharedRevolutionarySystem;
index f175565a5a0e8b5124c260836063a4334f68d8ea..557a1f95662eb0021d4e53f8f58bb1aedc5e69c2 100644 (file)
@@ -257,10 +257,8 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
         _cardSystem.TryChangeFullName(cardId, characterName, card);
         _cardSystem.TryChangeJobTitle(cardId, jobPrototype.LocalizedName, card);
 
-        if (_prototypeManager.TryIndex<StatusIconPrototype>(jobPrototype.Icon, out var jobIcon))
-        {
+        if (_prototypeManager.TryIndex(jobPrototype.Icon, out var jobIcon))
             _cardSystem.TryChangeJobIcon(cardId, jobIcon, card);
-        }
 
         var extendedAccess = false;
         if (station != null)
index d027a3937f5accd7b3539fc8cb3b8b4543ede285..91aa626fe3986d5cae09d485f7f70686ce642b75 100644 (file)
@@ -1,3 +1,5 @@
+using Content.Shared.StatusIcon;
+using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization;
 
 namespace Content.Shared.Access.Systems
@@ -23,12 +25,12 @@ namespace Content.Shared.Access.Systems
     [Serializable, NetSerializable]
     public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState
     {
-        public readonly HashSet<string> Icons;
+        public readonly HashSet<ProtoId<StatusIconPrototype>> Icons;
         public string CurrentName { get; }
         public string CurrentJob { get; }
         public string CurrentJobIconId { get; }
 
-        public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId, HashSet<string> icons)
+        public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId, HashSet<ProtoId<StatusIconPrototype>> icons)
         {
             Icons = icons;
             CurrentName = currentName;
@@ -62,9 +64,9 @@ namespace Content.Shared.Access.Systems
     [Serializable, NetSerializable]
     public sealed class AgentIDCardJobIconChangedMessage : BoundUserInterfaceMessage
     {
-        public string JobIconId { get; }
+        public ProtoId<StatusIconPrototype> JobIconId { get; }
 
-        public AgentIDCardJobIconChangedMessage(string jobIconId)
+        public AgentIDCardJobIconChangedMessage(ProtoId<StatusIconPrototype> jobIconId)
         {
             JobIconId = jobIconId;
         }
diff --git a/Content.Shared/Antag/IAntagStatusIconComponent.cs b/Content.Shared/Antag/IAntagStatusIconComponent.cs
deleted file mode 100644 (file)
index 981937c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-using Content.Shared.StatusIcon;
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Antag;
-
-public interface IAntagStatusIconComponent
-{
-    public ProtoId<StatusIconPrototype> StatusIcon { get; set; }
-
-    public bool IconVisibleToGhost { get; set; }
-}
-
diff --git a/Content.Shared/Antag/ShowAntagIconsComponent.cs b/Content.Shared/Antag/ShowAntagIconsComponent.cs
new file mode 100644 (file)
index 0000000..c451b69
--- /dev/null
@@ -0,0 +1,9 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Antag;
+
+/// <summary>
+/// Determines whether Someone can see antags icons
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ShowAntagIconsComponent: Component;
index 48e3162269a633d3f0b91594c6ac6e696c194d46..1297d5683854f934317746751ae067ca0baf257c 100644 (file)
@@ -1,5 +1,7 @@
 using Content.Shared.Damage.Prototypes;
+using Content.Shared.StatusIcon;
 using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
 
 namespace Content.Shared.Overlays;
@@ -15,4 +17,7 @@ public sealed partial class ShowHealthBarsComponent : Component
     /// </summary>
     [DataField("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer<DamageContainerPrototype>))]
     public List<string> DamageContainers = new();
+
+    [DataField]
+    public ProtoId<StatusIconPrototype> HealthStatusIcon = "HealthIconFine";
 }
index d2c8374fefee064cf0bf6202029c8d94e0a2ba71..ef2bad65e0dec2d3736b568d3fb3388f1a2bc6d3 100644 (file)
@@ -9,7 +9,7 @@ namespace Content.Shared.Revolutionary.Components;
 /// Component used for marking a Head Rev for conversion and winning/losing.
 /// </summary>
 [RegisterComponent, NetworkedComponent, Access(typeof(SharedRevolutionarySystem))]
-public sealed partial class HeadRevolutionaryComponent : Component, IAntagStatusIconComponent
+public sealed partial class HeadRevolutionaryComponent : Component
 {
     /// <summary>
     /// The status icon corresponding to the head revolutionary.
@@ -24,7 +24,4 @@ public sealed partial class HeadRevolutionaryComponent : Component, IAntagStatus
     public TimeSpan StunTime = TimeSpan.FromSeconds(3);
 
     public override bool SessionSpecific => true;
-
-    [DataField]
-    public bool IconVisibleToGhost { get; set; } = true;
 }
index 73f533cf6906b0b8cf8af092f14038ae5f211fbc..1f6b45ddea19d2a2fe8c8f2b0e1e63c19aa4d7fe 100644 (file)
@@ -10,7 +10,7 @@ namespace Content.Shared.Revolutionary.Components;
 /// Used for marking regular revs as well as storing icon prototypes so you can see fellow revs.
 /// </summary>
 [RegisterComponent, NetworkedComponent, Access(typeof(SharedRevolutionarySystem))]
-public sealed partial class RevolutionaryComponent : Component, IAntagStatusIconComponent
+public sealed partial class RevolutionaryComponent : Component
 {
     /// <summary>
     /// The status icon prototype displayed for revolutionaries
@@ -25,7 +25,4 @@ public sealed partial class RevolutionaryComponent : Component, IAntagStatusIcon
     public SoundSpecifier RevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/headrev_start.ogg");
 
     public override bool SessionSpecific => true;
-
-    [DataField]
-    public bool IconVisibleToGhost { get; set; }  = true;
 }
diff --git a/Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs b/Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs
deleted file mode 100644 (file)
index 11e20db..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Revolutionary.Components;
-
-/// <summary>
-/// Determines whether Someone can see rev/headrev icons on revs.
-/// </summary>
-[RegisterComponent, NetworkedComponent]
-public sealed partial class ShowRevIconsComponent: Component
-{
-}
index ddaf73fcc9f967e141eec0007f030d6b66a03075..bbf91193cc3112f7d5b1eeab6524ca04e88213e6 100644 (file)
@@ -1,4 +1,3 @@
-using Content.Shared.Ghost;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Mindshield.Components;
 using Content.Shared.Popups;
@@ -6,10 +5,11 @@ using Content.Shared.Revolutionary.Components;
 using Content.Shared.Stunnable;
 using Robust.Shared.GameStates;
 using Robust.Shared.Player;
+using Content.Shared.Antag;
 
 namespace Content.Shared.Revolutionary;
 
-public sealed class SharedRevolutionarySystem : EntitySystem
+public abstract class SharedRevolutionarySystem : EntitySystem
 {
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
     [Dependency] private readonly SharedStunSystem _sharedStun = default!;
@@ -23,7 +23,7 @@ public sealed class SharedRevolutionarySystem : EntitySystem
         SubscribeLocalEvent<HeadRevolutionaryComponent, ComponentGetStateAttemptEvent>(OnRevCompGetStateAttempt);
         SubscribeLocalEvent<RevolutionaryComponent, ComponentStartup>(DirtyRevComps);
         SubscribeLocalEvent<HeadRevolutionaryComponent, ComponentStartup>(DirtyRevComps);
-        SubscribeLocalEvent<ShowRevIconsComponent, ComponentStartup>(DirtyRevComps);
+        SubscribeLocalEvent<ShowAntagIconsComponent, ComponentStartup>(DirtyRevComps);
     }
 
     /// <summary>
@@ -52,7 +52,7 @@ public sealed class SharedRevolutionarySystem : EntitySystem
     /// </summary>
     private void OnRevCompGetStateAttempt(EntityUid uid, HeadRevolutionaryComponent comp, ref ComponentGetStateAttemptEvent args)
     {
-        args.Cancelled = !CanGetState(args.Player, comp.IconVisibleToGhost);
+        args.Cancelled = !CanGetState(args.Player);
     }
 
     /// <summary>
@@ -60,30 +60,24 @@ public sealed class SharedRevolutionarySystem : EntitySystem
     /// </summary>
     private void OnRevCompGetStateAttempt(EntityUid uid, RevolutionaryComponent comp, ref ComponentGetStateAttemptEvent args)
     {
-        args.Cancelled = !CanGetState(args.Player, comp.IconVisibleToGhost);
+        args.Cancelled = !CanGetState(args.Player);
     }
 
     /// <summary>
     /// The criteria that determine whether a Rev/HeadRev component should be sent to a client.
     /// </summary>
     /// <param name="player"> The Player the component will be sent to.</param>
-    /// <param name="visibleToGhosts"> Whether the component permits the icon to be visible to observers. </param>
     /// <returns></returns>
-    private bool CanGetState(ICommonSession? player, bool visibleToGhosts)
+    private bool CanGetState(ICommonSession? player)
     {
         //Apparently this can be null in replays so I am just returning true.
-        if (player is null)
+        if (player?.AttachedEntity is not {} uid)
             return true;
 
-        var uid = player.AttachedEntity;
-
         if (HasComp<RevolutionaryComponent>(uid) || HasComp<HeadRevolutionaryComponent>(uid))
             return true;
 
-        if (visibleToGhosts && HasComp<GhostComponent>(uid))
-            return true;
-
-        return HasComp<ShowRevIconsComponent>(uid);
+        return HasComp<ShowAntagIconsComponent>(uid);
     }
     /// <summary>
     /// Dirties all the Rev components so they are sent to clients.
index 2959b564972aa8a21d33151b2a3c711d980b13d4..0b3bfb44384cb8de1bd32e6a99a3f478cefe1ffa 100644 (file)
@@ -97,8 +97,8 @@ namespace Content.Shared.Roles
         [DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
         public string? JobEntity = null;
 
-        [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
-        public string Icon { get; private set; } = "JobIconUnknown";
+        [DataField]
+        public ProtoId<StatusIconPrototype> Icon { get; private set; } = "JobIconUnknown";
 
         [DataField("special", serverOnly: true)]
         public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();
index 66310505a1a42d45c3066d39453b424825350185..ee67e3296f68eea241a2a989f6cfd81609e4484d 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.StatusIcon;
 using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
 
 namespace Content.Shared.SSDIndicator;
@@ -16,6 +17,6 @@ public sealed partial class SSDIndicatorComponent : Component
     public bool IsSSD = true;
 
     [ViewVariables(VVAccess.ReadWrite)]
-    [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
-    public string Icon = "SSDIcon";
+    [DataField]
+    public ProtoId<StatusIconPrototype> Icon = "SSDIcon";
 }
index 385f9760c659ff6a46deb5dd4236a51953964d57..c56be7c96a52e4c5fb986e59e97fbff04e051dac 100644 (file)
@@ -24,16 +24,4 @@ public sealed partial class StatusIconComponent : Component
 /// </summary>
 /// <param name="StatusIcons"></param>
 [ByRefEvent]
-public record struct GetStatusIconsEvent(List<StatusIconData> StatusIcons, bool InContainer);
-
-/// <summary>
-/// Event raised on the Client-side to determine whether to display a status icon on an entity.
-/// </summary>
-/// <param name="User">The player that will see the icons</param>
-[ByRefEvent]
-public record struct CanDisplayStatusIconsEvent(EntityUid? User = null)
-{
-    public EntityUid? User = User;
-
-    public bool Cancelled = false;
-}
+public record struct GetStatusIconsEvent(List<StatusIconData> StatusIcons);
index 2bd13b9361d354542830aadb0fbda355446aefe4..29a1b60114f2635e7bd22c0be2d64b2dab430872 100644 (file)
@@ -1,3 +1,5 @@
+using Content.Shared.Stealth.Components;
+using Content.Shared.Whitelist;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
@@ -15,26 +17,45 @@ public partial class StatusIconData : IComparable<StatusIconData>
     /// <summary>
     /// The icon that's displayed on the entity.
     /// </summary>
-    [DataField("icon", required: true)]
+    [DataField(required: true)]
     public SpriteSpecifier Icon = default!;
 
     /// <summary>
     /// A priority for the order in which the icons will be displayed.
     /// </summary>
-    [DataField("priority")]
+    [DataField]
     public int Priority = 10;
 
+    /// <summary>
+    /// Whether or not to hide the icon to ghosts
+    /// </summary>
+    [DataField]
+    public bool VisibleToGhosts = true;
+
+    /// <summary>
+    /// Whether or not to hide the icon when we are inside a container like a locker or a crate.
+    /// </summary>
+    [DataField]
+    public bool HideInContainer = true;
+
+    /// <summary>
+    /// Whether or not to hide the icon when the entity has an active <see cref="StealthComponent"/>
+    /// </summary>
+    [DataField]
+    public bool HideOnStealth = true;
+
+    /// <summary>
+    /// Specifies what entities and components/tags this icon can be shown to.
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? ShowTo;
+
     /// <summary>
     /// A preference for where the icon will be displayed. None | Left | Right
     /// </summary>
-    [DataField("locationPreference")]
+    [DataField]
     public StatusIconLocationPreference LocationPreference = StatusIconLocationPreference.None;
 
-    public int CompareTo(StatusIconData? other)
-    {
-        return Priority.CompareTo(other?.Priority ?? int.MaxValue);
-    }
-
     /// <summary>
     /// The layer the icon is displayed on. Mod is drawn above Base. Base | Mod
     /// </summary>
@@ -52,6 +73,11 @@ public partial class StatusIconData : IComparable<StatusIconData>
     /// </summary>
     [DataField]
     public bool IsShaded = false;
+
+    public int CompareTo(StatusIconData? other)
+    {
+        return Priority.CompareTo(other?.Priority ?? int.MaxValue);
+    }
 }
 
 /// <summary>
index 3200dd7f5ee74fa466efcfe0408a50bcfeeaedd9..3149de63bddf4c4c821335bc2a893386245af65c 100644 (file)
@@ -1,4 +1,3 @@
-using Content.Shared.Antag;
 using Content.Shared.StatusIcon;
 using Robust.Shared.GameStates;
 using Robust.Shared.Prototypes;
@@ -6,11 +5,8 @@ using Robust.Shared.Prototypes;
 namespace Content.Shared.Zombies;
 
 [RegisterComponent, NetworkedComponent]
-public sealed partial class InitialInfectedComponent : Component, IAntagStatusIconComponent
+public sealed partial class InitialInfectedComponent : Component
 {
-    [DataField("initialInfectedStatusIcon")]
-    public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "InitialInfectedFaction";
-
     [DataField]
-    public bool IconVisibleToGhost { get; set; } = true;
+    public ProtoId<StatusIconPrototype> StatusIcon = "InitialInfectedFaction";
 }
diff --git a/Content.Shared/Zombies/ShowZombieIconsComponent.cs b/Content.Shared/Zombies/ShowZombieIconsComponent.cs
deleted file mode 100644 (file)
index a2bc85c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Zombies;
-
-/// <summary>
-/// Makes it so an entity can view ZombieAntagIcons.
-/// </summary>
-[RegisterComponent, NetworkedComponent]
-public sealed partial class ShowZombieIconsComponent: Component
-{
-
-}
index 3673a2c51d58858d62d4020a005ada38eae95cbc..2cd0cdb96d77615226b6401cad4bebfdad5faf61 100644 (file)
@@ -14,7 +14,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
 namespace Content.Shared.Zombies;
 
 [RegisterComponent, NetworkedComponent]
-public sealed partial class ZombieComponent : Component, IAntagStatusIconComponent
+public sealed partial class ZombieComponent : Component
 {
     /// <summary>
     /// The baseline infection chance you have if you are completely nude
@@ -97,9 +97,6 @@ public sealed partial class ZombieComponent : Component, IAntagStatusIconCompone
     [DataField("zombieStatusIcon")]
     public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "ZombieFaction";
 
-    [DataField]
-    public bool IconVisibleToGhost { get; set; } = true;
-
     /// <summary>
     /// Healing each second
     /// </summary>
index 4a83593bc34256245a7d22fb24e7e532d1b614e4..8b0f60ca58aadd51ce1046a274c77edfaf2cf9c9 100644 (file)
@@ -84,8 +84,7 @@
   - type: Stripping
   - type: SolutionScanner
   - type: IgnoreUIRange
-  - type: ShowRevIcons
-  - type: ShowZombieIcons
+  - type: ShowAntagIcons
   - type: Inventory
     templateId: aghost
   - type: InventorySlots
index 0dbdfce4f97cbacb6aa84dd5a66179582bad4287..0da545b8a203c82e6da35d046eee2b8850ee208f 100644 (file)
@@ -1,6 +1,11 @@
 - type: statusIcon
   id: ZombieFaction
   priority: 11
+  showTo:
+    components:
+    - ShowAntagIcons
+    - Zombie
+    - InitialInfected
   icon:
     sprite: /Textures/Interface/Misc/job_icons.rsi
     state: Zombie
@@ -8,6 +13,10 @@
 - type: statusIcon
   id: InitialInfectedFaction
   priority: 11
+  showTo:
+    components:
+    - ShowAntagIcons
+    - InitialInfected
   icon:
     sprite: /Textures/Interface/Misc/job_icons.rsi
     state: InitialInfected
 - type: statusIcon
   id: RevolutionaryFaction
   priority: 11
+  showTo:
+    components:
+      - ShowAntagIcons
+      - Revolutionary
   icon:
     sprite: /Textures/Interface/Misc/job_icons.rsi
     state: Revolutionary
 - type: statusIcon
   id: HeadRevolutionaryFaction
   priority: 11
+  showTo:
+    components:
+      - ShowAntagIcons
+      - Revolutionary
   icon:
     sprite: /Textures/Interface/Misc/job_icons.rsi
     state: HeadRevolutionary