diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index c1c0ae93ec..0d06e0b5b6 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -7,6 +7,7 @@ using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Shared.Enums; using System.Numerics; +using Content.Client.StatusIcon; using Content.Shared.StatusIcon.Components; using Content.Client.UserInterface.Systems; using Robust.Shared.Prototypes; @@ -24,6 +25,7 @@ public sealed class EntityHealthBarOverlay : Overlay private readonly MobStateSystem _mobStateSystem; private readonly MobThresholdSystem _mobThresholdSystem; private readonly ProgressColorSystem _progressColor; + private readonly StatusIconSystem _statusIcon; public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; public HashSet DamageContainers = new(); @@ -34,6 +36,7 @@ public sealed class EntityHealthBarOverlay : Overlay _mobStateSystem = _entManager.System(); _mobThresholdSystem = _entManager.System(); _progressColor = _entManager.System(); + _statusIcon = entManager.System(); } protected override void Draw(in OverlayDrawArgs args) @@ -70,6 +73,9 @@ public sealed class EntityHealthBarOverlay : Overlay continue; } + if (!_statusIcon.IsVisible(uid)) + continue; + // we use the status icon component bounds if specified otherwise use sprite var bounds = _entManager.GetComponentOrNull(uid)?.Bounds ?? spriteComponent.Bounds; var worldPos = _transform.GetWorldPosition(xform, xformQuery); diff --git a/Content.Client/SSDIndicator/SSDIndicatorSystem.cs b/Content.Client/SSDIndicator/SSDIndicatorSystem.cs index 587450a2f6..5757f74213 100644 --- a/Content.Client/SSDIndicator/SSDIndicatorSystem.cs +++ b/Content.Client/SSDIndicator/SSDIndicatorSystem.cs @@ -1,4 +1,6 @@ using Content.Shared.CCVar; +using Content.Shared.Ghost; +using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Mobs.Systems; using Content.Shared.NPC; @@ -34,9 +36,18 @@ public sealed class SSDIndicatorSystem : EntitySystem !_mobState.IsDead(uid) && !HasComp(uid) && TryComp(uid, out var mindContainer) && - mindContainer.ShowExamineInfo) + mindContainer.ShowExamineInfo && + !IsAghosted(mindContainer)) // WD EDIT { args.StatusIcons.Add(_prototype.Index(component.Icon)); } } + + private bool IsAghosted(MindContainerComponent mindContainer) // WD + { + if (!TryComp(mindContainer.Mind, out MindComponent? mindComp)) + return false; + + return TryComp(mindComp.VisitingEntity, out GhostComponent? ghost) && ghost.CanGhostInteract; + } } diff --git a/Content.Client/StatusIcon/StatusIconOverlay.cs b/Content.Client/StatusIcon/StatusIconOverlay.cs index 471f0b8753..dc3f3c6bb3 100644 --- a/Content.Client/StatusIcon/StatusIconOverlay.cs +++ b/Content.Client/StatusIcon/StatusIconOverlay.cs @@ -59,6 +59,9 @@ public sealed class StatusIconOverlay : Overlay if (icons.Count == 0) continue; + if (!_statusIcon.IsVisible(uid)) + continue; + var worldMatrix = Matrix3.CreateTranslation(worldPos); Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld); Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty); diff --git a/Content.Client/StatusIcon/StatusIconSystem.cs b/Content.Client/StatusIcon/StatusIconSystem.cs index 980fd9f2a9..1eec788387 100644 --- a/Content.Client/StatusIcon/StatusIconSystem.cs +++ b/Content.Client/StatusIcon/StatusIconSystem.cs @@ -1,7 +1,10 @@ using Content.Shared.CCVar; +using Content.Shared.Ghost; using Content.Shared.StatusIcon; using Content.Shared.StatusIcon.Components; +using Robust.Client.GameObjects; using Robust.Client.Graphics; +using Robust.Client.Player; using Robust.Shared.Configuration; namespace Content.Client.StatusIcon; @@ -13,6 +16,10 @@ public sealed class StatusIconSystem : SharedStatusIconSystem { [Dependency] private readonly IConfigurationManager _configuration = default!; [Dependency] private readonly IOverlayManager _overlay = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + + private EntityQuery _ghostQuery; + private EntityQuery _spriteQuery; private bool _globalEnabled; private bool _localEnabled; @@ -20,6 +27,9 @@ public sealed class StatusIconSystem : SharedStatusIconSystem /// public override void Initialize() { + _ghostQuery = GetEntityQuery(); + _spriteQuery = GetEntityQuery(); + Subs.CVar(_configuration, CCVars.LocalStatusIconsEnabled, OnLocalStatusIconChanged, true); Subs.CVar(_configuration, CCVars.GlobalStatusIconsEnabled, OnGlobalStatusIconChanged, true); } @@ -59,5 +69,29 @@ public sealed class StatusIconSystem : SharedStatusIconSystem RaiseLocalEvent(uid, ref ev); return ev.StatusIcons; } + + /// + /// For overlay to check if an entity can be seen. + /// + public bool IsVisible(EntityUid uid) + { + // ghosties can always see them + var viewer = _playerMan.LocalSession?.AttachedEntity; + if (_ghostQuery.HasComponent(viewer)) + return true; + + if (_spriteQuery.TryGetComponent(uid, out var sprite) && !sprite.Visible) + return false; + + var ev = new StatusIconVisibleEvent(true); + RaiseLocalEvent(uid, ref ev); + return ev.Visible; + } } +/// +/// Raised on an entity to check if it should draw hud icons. +/// Used to check invisibility etc inside the screen bounds. +/// +[ByRefEvent] +public record struct StatusIconVisibleEvent(bool Visible); diff --git a/Content.Client/Stealth/StealthSystem.cs b/Content.Client/Stealth/StealthSystem.cs index b60ffc2a40..3e5df79192 100644 --- a/Content.Client/Stealth/StealthSystem.cs +++ b/Content.Client/Stealth/StealthSystem.cs @@ -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,9 +19,12 @@ public sealed class StealthSystem : SharedStealthSystem base.Initialize(); _shader = _protoMan.Index("Stealth").InstanceUnique(); + SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnShaderRender); + + SubscribeLocalEvent(OnStatusIconVisible); } public override void SetEnabled(EntityUid uid, bool value, StealthComponent? component = null) @@ -92,5 +96,12 @@ public sealed class StealthSystem : SharedStealthSystem visibility = MathF.Max(0, visibility); args.Sprite.Color = new Color(visibility, visibility, 1, 1); } + + private void OnStatusIconVisible(EntityUid uid, StealthComponent comp, ref StatusIconVisibleEvent args) + { + // no sechud seing invisible ninjas + if (comp.Enabled) + args.Visible = false; + } } diff --git a/Content.Client/Storage/Systems/EntityStorageSystem.cs b/Content.Client/Storage/Systems/EntityStorageSystem.cs index dd3f8d3860..05962b4e32 100644 --- a/Content.Client/Storage/Systems/EntityStorageSystem.cs +++ b/Content.Client/Storage/Systems/EntityStorageSystem.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Content.Client.StatusIcon; using Content.Client.Storage.Components; using Content.Shared.Destructible; using Content.Shared.Foldable; @@ -29,6 +30,8 @@ public sealed class EntityStorageSystem : SharedEntityStorageSystem SubscribeLocalEvent(OnGetState); SubscribeLocalEvent(OnHandleState); + + SubscribeLocalEvent(OnStatusIconVisible); } public override bool ResolveStorage(EntityUid uid, [NotNullWhen(true)] ref SharedEntityStorageComponent? component) @@ -40,4 +43,9 @@ public sealed class EntityStorageSystem : SharedEntityStorageSystem component = storage; return component != null; } + + private void OnStatusIconVisible(EntityUid uid, InsideEntityStorageComponent comp, ref StatusIconVisibleEvent args) + { + args.Visible = false; + } } diff --git a/Content.Server/Administration/Commands/AGhost.cs b/Content.Server/Administration/Commands/AGhost.cs index 4f0c49bd95..77f2c028ab 100644 --- a/Content.Server/Administration/Commands/AGhost.cs +++ b/Content.Server/Administration/Commands/AGhost.cs @@ -85,6 +85,8 @@ public sealed class AGhost : LocalizedCommands return; } + _entities.Dirty(mindId, mind); // WD + if (mind.VisitingEntity != default && _entities.TryGetComponent(mind.VisitingEntity, out var oldGhostComponent)) { mindSystem.UnVisit(mindId, mind); diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index 5e82959c4e..db00905ea6 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -113,7 +113,7 @@ - type: ContainerContainer containers: toggleable-clothing: !type:ContainerSlot {} - + - type: entity parent: ClothingOuterBaseLarge id: ClothingOuterSuitSpaceNinja @@ -125,7 +125,7 @@ - type: Clothing sprite: Clothing/OuterClothing/Suits/spaceninja.rsi - type: StealthClothing - visibility: 1.1 + visibility: 0.5 toggleAction: ActionTogglePhaseCloak - type: PressureProtection highPressureMultiplier: 0.6