From aa6e0e7539c5c04942115342fb709077e3cd614c Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Fri, 9 Oct 2020 18:57:09 +0200 Subject: [PATCH] Add SSS traitor label and fix ally sync (#2200) --- .../Suspicion/SuspicionRoleComponent.cs | 106 +++++++++++++++- .../Components/Suspicion/TraitorOverlay.cs | 120 ++++++++++++++++++ .../UserInterface/Suspicion/SuspicionGui.cs | 10 +- .../EntitySystems/ExamineSystemShared.cs | 2 +- 4 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs diff --git a/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs b/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs index 82cf727f90..f805fc59f1 100644 --- a/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs +++ b/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs @@ -1,15 +1,19 @@ #nullable enable using System.Collections.Generic; -using System.Linq; using Content.Client.UserInterface; using Content.Client.UserInterface.Suspicion; using Content.Shared.GameObjects.Components.Suspicion; using Robust.Client.GameObjects; +using Robust.Client.Interfaces.Graphics.ClientEye; +using Robust.Client.Interfaces.Graphics.Overlays; +using Robust.Client.Interfaces.Input; +using Robust.Client.Interfaces.ResourceManagement; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; using Robust.Shared.Players; +using Robust.Shared.Prototypes; namespace Content.Client.GameObjects.Components.Suspicion { @@ -18,6 +22,12 @@ namespace Content.Client.GameObjects.Components.Suspicion { [Dependency] private readonly IGameHud _gameHud = default!; [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IOverlayManager _overlayManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IResourceCache _resourceCache = default!; + [Dependency] private readonly IComponentManager _componentManager = default!; + [Dependency] private readonly IInputManager _inputManager = default!; + [Dependency] private readonly IEyeManager _eyeManager = default!; private SuspicionGui? _gui; private string? _role; @@ -28,6 +38,11 @@ namespace Content.Client.GameObjects.Components.Suspicion get => _role; set { + if (_role == value) + { + return; + } + _role = value; _gui?.UpdateLabel(); Dirty(); @@ -39,13 +54,70 @@ namespace Content.Client.GameObjects.Components.Suspicion get => _antagonist; set { + if (_antagonist == value) + { + return; + } + _antagonist = value; _gui?.UpdateLabel(); + + if (value ?? false) + { + AddTraitorOverlay(); + } + Dirty(); } } - public HashSet Allies { get; } = new HashSet(); + public HashSet Allies { get; } = new HashSet(); + + private bool AddAlly(EntityUid ally) + { + if (!Allies.Add(ally)) + { + return false; + } + + if (!_overlayManager.TryGetOverlay(nameof(TraitorOverlay), out var overlay)) + { + return false; + } + + return overlay.AddAlly(ally); + } + + private bool RemoveAlly(EntityUid ally) + { + if (!Allies.Remove(ally)) + { + return false; + } + + if (!_overlayManager.TryGetOverlay(nameof(TraitorOverlay), out var overlay)) + { + return false; + } + + return overlay.RemoveAlly(ally); + } + + private void AddTraitorOverlay() + { + if (_overlayManager.HasOverlay(nameof(TraitorOverlay))) + { + return; + } + + var overlay = new TraitorOverlay(Owner, _entityManager, _resourceCache, _eyeManager); + _overlayManager.AddOverlay(overlay); + } + + private void RemoveTraitorOverlay() + { + _overlayManager.RemoveOverlay(nameof(TraitorOverlay)); + } public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { @@ -56,8 +128,8 @@ namespace Content.Client.GameObjects.Components.Suspicion return; } - _role = state.Role; - _antagonist = state.Antagonist; + Role = state.Role; + Antagonist = state.Antagonist; } public override void HandleMessage(ComponentMessage message, IComponent? component) @@ -79,9 +151,15 @@ namespace Content.Client.GameObjects.Components.Suspicion _gameHud.SuspicionContainer.AddChild(_gui); _gui.UpdateLabel(); + if (_antagonist ?? false) + { + AddTraitorOverlay(); + } + break; case PlayerDetachedMsg _: _gui?.Parent?.RemoveChild(_gui); + RemoveTraitorOverlay(); break; } } @@ -93,9 +171,26 @@ namespace Content.Client.GameObjects.Components.Suspicion switch (message) { case SuspicionAlliesMessage msg: + { Allies.Clear(); - Allies.UnionWith(msg.Allies.Select(_entityManager.GetEntity)); + + foreach (var uid in msg.Allies) + { + AddAlly(uid); + } + break; + } + case SuspicionAllyAddedMessage msg: + { + AddAlly(msg.Ally); + break; + } + case SuspicionAllyRemovedMessage msg: + { + RemoveAlly(msg.Ally); + break; + } } } @@ -104,6 +199,7 @@ namespace Content.Client.GameObjects.Components.Suspicion base.OnRemove(); _gui?.Dispose(); + RemoveTraitorOverlay(); } } } diff --git a/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs b/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs new file mode 100644 index 0000000000..3ada7a1fff --- /dev/null +++ b/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs @@ -0,0 +1,120 @@ +using System.Collections.Generic; +using Content.Shared.GameObjects.EntitySystems; +using Robust.Client.Graphics; +using Robust.Client.Graphics.Drawing; +using Robust.Client.Graphics.Overlays; +using Robust.Client.Interfaces.Graphics.ClientEye; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.ResourceManagement; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Localization; +using Robust.Shared.Maths; + +namespace Content.Client.GameObjects.Components.Suspicion +{ + public class TraitorOverlay : Overlay + { + private readonly IEntityManager _entityManager; + private readonly IEyeManager _eyeManager; + + public override OverlaySpace Space => OverlaySpace.ScreenSpace; + private readonly Font _font; + + private readonly IEntity _user; + private readonly HashSet _allies = new HashSet(); + private readonly string _traitorText = Loc.GetString("Traitor"); + + public TraitorOverlay( + IEntity user, + IEntityManager entityManager, + IResourceCache resourceCache, + IEyeManager eyeManager) + : base(nameof(TraitorOverlay)) + { + _entityManager = entityManager; + _eyeManager = eyeManager; + + _font = new VectorFont(resourceCache.GetResource("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10); + + _user = user; + } + + public bool AddAlly(EntityUid ally) + { + return _allies.Add(ally); + } + + public bool RemoveAlly(EntityUid ally) + { + return _allies.Remove(ally); + } + + protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) + { + switch (currentSpace) + { + case OverlaySpace.ScreenSpace: + DrawScreen((DrawingHandleScreen) handle); + break; + } + } + + private void DrawScreen(DrawingHandleScreen screen) + { + var viewport = _eyeManager.GetWorldViewport(); + + foreach (var uid in _allies) + { + // Otherwise the entity can not exist yet + if (!_entityManager.TryGetEntity(uid, out var ally)) + { + return; + } + + if (!ally.TryGetComponent(out ICollidableComponent collidable)) + { + return; + } + + if (!ExamineSystemShared.InRangeUnOccluded(_user.Transform.MapPosition, ally.Transform.MapPosition, 15, + entity => entity == _user || entity == ally)) + { + return; + } + + // all entities have a TransformComponent + var transform = collidable.Entity.Transform; + + // if not on the same map, continue + if (transform.MapID != _eyeManager.CurrentMap || !transform.IsMapTransform) + { + continue; + } + + var worldBox = collidable.WorldAABB; + + // if not on screen, or too small, continue + if (!worldBox.Intersects(in viewport) || worldBox.IsEmpty()) + { + continue; + } + + var screenCoordinates = _eyeManager.WorldToScreen(collidable.WorldAABB.TopLeft + (0, 0.5f)); + DrawString(screen, _font, screenCoordinates, _traitorText, Color.OrangeRed); + } + } + + private static void DrawString(DrawingHandleScreen handle, Font font, Vector2 pos, string str, Color color) + { + var baseLine = new Vector2(pos.X, font.GetAscent(1) + pos.Y); + + foreach (var chr in str) + { + var advance = font.DrawChar(handle, chr, baseLine, 1, color); + baseLine += new Vector2(advance, 0); + } + } + } +} diff --git a/Content.Client/UserInterface/Suspicion/SuspicionGui.cs b/Content.Client/UserInterface/Suspicion/SuspicionGui.cs index 5d8c5361b8..d42d9337d3 100644 --- a/Content.Client/UserInterface/Suspicion/SuspicionGui.cs +++ b/Content.Client/UserInterface/Suspicion/SuspicionGui.cs @@ -1,10 +1,12 @@ using System; using System.Globalization; +using System.Linq; using Content.Client.GameObjects.Components.Suspicion; using Content.Shared.Interfaces; using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; @@ -15,9 +17,8 @@ namespace Content.Client.UserInterface.Suspicion { public class SuspicionGui : Control { -#pragma warning disable 0649 - [Dependency] private readonly IPlayerManager _playerManager; -#pragma warning restore 0649 + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; private readonly VBoxContainer _container; private readonly Button _roleButton; @@ -57,7 +58,8 @@ namespace Content.Client.UserInterface.Suspicion return; } - var allies = string.Join(", ", role.Allies); + var allies = string.Join(", ", + role.Allies.Select(uid => _entityManager.GetEntity(uid).Name)); var message = role.Allies.Count switch { 0 => Loc.GetString("You have no allies"), diff --git a/Content.Shared/GameObjects/EntitySystems/ExamineSystemShared.cs b/Content.Shared/GameObjects/EntitySystems/ExamineSystemShared.cs index a7f35d84bd..dae1d9b96e 100644 --- a/Content.Shared/GameObjects/EntitySystems/ExamineSystemShared.cs +++ b/Content.Shared/GameObjects/EntitySystems/ExamineSystemShared.cs @@ -66,7 +66,7 @@ namespace Content.Shared.GameObjects.EntitySystems ignoreInsideBlocker: true); } - private static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored predicate, bool ignoreInsideBlocker = true) + public static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored predicate, bool ignoreInsideBlocker = true) { var occluderSystem = Get(); if (!origin.InRange(other, range)) return false;