]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Fix pinpointer flicker (#15452)
authorSlava0135 <40753025+Slava0135@users.noreply.github.com>
Sun, 7 May 2023 08:20:43 +0000 (11:20 +0300)
committerGitHub <noreply@github.com>
Sun, 7 May 2023 08:20:43 +0000 (18:20 +1000)
Content.Client/Pinpointer/PinpointerSystem.cs
Content.Client/Pinpointer/PinpointerVisualizerSystem.cs [deleted file]
Content.Server/Pinpointer/PinpointerSystem.cs
Content.Shared/Pinpointer/PinpointerComponent.cs
Content.Shared/Pinpointer/SharedPinpointerSystem.cs
Resources/Prototypes/Entities/Objects/Devices/pinpointer.yml

index 1266cbe452c69e1dce38a499f417639f77dd4a06..486241b56b32dd0aa95a95b627f28fbaaae8c111 100644 (file)
@@ -1,78 +1,41 @@
 using Content.Shared.Pinpointer;
 using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
-using Robust.Shared.GameStates;
 
-namespace Content.Client.Pinpointer
+namespace Content.Client.Pinpointer;
+
+public sealed class PinpointerSystem : SharedPinpointerSystem
 {
-    public sealed class PinpointerSystem : SharedPinpointerSystem
+    [Dependency] private readonly IEyeManager _eyeManager = default!;
+
+    public override void Update(float frameTime)
     {
-        [Dependency] private readonly IEyeManager _eyeManager = default!;
-        [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+        base.Update(frameTime);
 
-        public override void Initialize()
-        {
-            base.Initialize();
-            SubscribeLocalEvent<PinpointerComponent, ComponentHandleState>(HandleCompState);
-        }
+        // we want to show pinpointers arrow direction relative
+        // to players eye rotation (like it was in SS13)
 
-        public override void FrameUpdate(float frameTime)
+        // because eye can change it rotation anytime
+        // we need to update this arrow in a update loop
+        var query = EntityQueryEnumerator<PinpointerComponent, SpriteComponent>();
+        while (query.MoveNext(out var _, out var pinpointer, out var sprite))
         {
-            base.FrameUpdate(frameTime);
-
-            // we want to show pinpointers arrow direction relative
-            // to players eye rotation (like it was in SS13)
+            if (!pinpointer.HasTarget)
+                continue;
+            var eye = _eyeManager.CurrentEye;
+            var angle = pinpointer.ArrowAngle + eye.Rotation;
 
-            // because eye can change it rotation anytime
-            // we need to update this arrow in a update loop
-            foreach (var pinpointer in EntityQuery<PinpointerComponent>())
+            switch (pinpointer.DistanceToTarget)
             {
-                UpdateAppearance(pinpointer.Owner, pinpointer);
-                UpdateEyeDir(pinpointer.Owner, pinpointer);
+                case Distance.Close:
+                case Distance.Medium:
+                case Distance.Far:
+                    sprite.LayerSetRotation(PinpointerLayers.Screen, angle);
+                    break;
+                default:
+                    sprite.LayerSetRotation(PinpointerLayers.Screen, Angle.Zero);
+                    break;
             }
         }
-
-        private void HandleCompState(EntityUid uid, PinpointerComponent pinpointer, ref ComponentHandleState args)
-        {
-            if (args.Current is not PinpointerComponentState state)
-                return;
-
-            pinpointer.IsActive = state.IsActive;
-            pinpointer.ArrowAngle = state.ArrowAngle;
-            pinpointer.DistanceToTarget = state.DistanceToTarget;
-        }
-
-        private void UpdateAppearance(EntityUid uid, PinpointerComponent? pinpointer = null,
-            AppearanceComponent? appearance = null)
-        {
-            if (!Resolve(uid, ref pinpointer, ref appearance))
-                return;
-
-            _appearance.SetData(uid, PinpointerVisuals.IsActive, pinpointer.IsActive, appearance);
-            _appearance.SetData(uid, PinpointerVisuals.TargetDistance, pinpointer.DistanceToTarget, appearance);
-        }
-
-        private void UpdateArrowAngle(EntityUid uid, Angle angle, PinpointerComponent? pinpointer = null,
-            AppearanceComponent? appearance = null)
-        {
-            if (!Resolve(uid, ref pinpointer, ref appearance))
-                return;
-
-            _appearance.SetData(uid, PinpointerVisuals.ArrowAngle, angle, appearance);
-        }
-
-        /// <summary>
-        ///     Transform pinpointer arrow from world space to eye space
-        ///     And send it to the appearance component
-        /// </summary>
-        private void UpdateEyeDir(EntityUid uid, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer) || !pinpointer.HasTarget)
-                return;
-
-            var eye = _eyeManager.CurrentEye;
-            var angle = pinpointer.ArrowAngle + eye.Rotation;
-            UpdateArrowAngle(uid, angle, pinpointer);
-        }
     }
 }
diff --git a/Content.Client/Pinpointer/PinpointerVisualizerSystem.cs b/Content.Client/Pinpointer/PinpointerVisualizerSystem.cs
deleted file mode 100644 (file)
index b59a2ab..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-using Content.Shared.Pinpointer;
-using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-
-namespace Content.Client.Pinpointer
-{
-    [UsedImplicitly]
-    public sealed class PinpointerVisualizerSystem : VisualizerSystem<PinpointerComponent>
-    {
-        protected override void OnAppearanceChange(EntityUid uid, PinpointerComponent component, ref AppearanceChangeEvent args)
-        {
-            base.OnAppearanceChange(uid, component, ref args);
-
-            if (!TryComp(component.Owner, out SpriteComponent? sprite))
-                return;
-
-            // check if pinpointer screen is active
-            if (!AppearanceSystem.TryGetData<bool>(uid, PinpointerVisuals.IsActive, out var isActive, args.Component) || !isActive)
-            {
-                sprite.LayerSetVisible(PinpointerLayers.Screen, false);
-                return;
-            }
-
-            sprite.LayerSetVisible(PinpointerLayers.Screen, true);
-
-            // check distance and direction to target
-            if (!AppearanceSystem.TryGetData<Distance>(uid, PinpointerVisuals.TargetDistance, out var dis, args.Component) ||
-                !AppearanceSystem.TryGetData<Angle>(uid, PinpointerVisuals.ArrowAngle, out var angle, args.Component))
-            {
-                sprite.LayerSetState(PinpointerLayers.Screen, "pinonnull");
-                sprite.LayerSetRotation(PinpointerLayers.Screen, Angle.Zero);
-                return;
-            }
-
-            switch (dis)
-            {
-                case Distance.Reached:
-                    sprite.LayerSetState(PinpointerLayers.Screen, "pinondirect");
-                    sprite.LayerSetRotation(PinpointerLayers.Screen, Angle.Zero);
-                    break;
-                case Distance.Close:
-                    sprite.LayerSetState(PinpointerLayers.Screen, "pinonclose");
-                    sprite.LayerSetRotation(PinpointerLayers.Screen, angle);
-                    break;
-                case Distance.Medium:
-                    sprite.LayerSetState(PinpointerLayers.Screen, "pinonmedium");
-                    sprite.LayerSetRotation(PinpointerLayers.Screen, angle);
-                    break;
-                case Distance.Far:
-                    sprite.LayerSetState(PinpointerLayers.Screen, "pinonfar");
-                    sprite.LayerSetRotation(PinpointerLayers.Screen, angle);
-                    break;
-                case Distance.Unknown:
-                    sprite.LayerSetState(PinpointerLayers.Screen, "pinonnull");
-                    sprite.LayerSetRotation(PinpointerLayers.Screen, Angle.Zero);
-                    break;
-            }
-        }
-    }
-}
index 21b96a98e31ca67c3e2a79700218a505f49b3ce6..e0b5af31922b14a460c1b3e6e2da3d5a5d3be969 100644 (file)
@@ -4,183 +4,201 @@ using System.Linq;
 using Robust.Shared.Utility;
 using Content.Server.Shuttles.Events;
 
-namespace Content.Server.Pinpointer
+namespace Content.Server.Pinpointer;
+
+public sealed class PinpointerSystem : SharedPinpointerSystem
 {
-    public sealed class PinpointerSystem : SharedPinpointerSystem
+    [Dependency] private readonly SharedTransformSystem _transform = default!;
+    [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+
+    public override void Initialize()
     {
-        [Dependency] private readonly SharedTransformSystem _transform = default!;
+        base.Initialize();
+        SubscribeLocalEvent<PinpointerComponent, ActivateInWorldEvent>(OnActivate);
+        SubscribeLocalEvent<FTLCompletedEvent>(OnLocateTarget);
+    }
 
-        public override void Initialize()
-        {
-            base.Initialize();
-            SubscribeLocalEvent<PinpointerComponent, ActivateInWorldEvent>(OnActivate);
-            SubscribeLocalEvent<FTLCompletedEvent>(OnLocateTarget);
-        }
+    private void OnActivate(EntityUid uid, PinpointerComponent component, ActivateInWorldEvent args)
+    {
+        TogglePinpointer(uid, component);
+        LocateTarget(uid, component);
+    }
 
-        private void OnActivate(EntityUid uid, PinpointerComponent component, ActivateInWorldEvent args)
-        {
-            TogglePinpointer(uid, component);
-            LocateTarget(uid, component);
-        }
+    public bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
+    {
+        if (!Resolve(uid, ref pinpointer))
+            return false;
 
-        private void OnLocateTarget(ref FTLCompletedEvent ev)
-        {
-            // This feels kind of expensive, but it only happens once per hyperspace jump
+        var isActive = !pinpointer.IsActive;
+        SetActive(uid, isActive, pinpointer);
+        UpdateAppearance(uid, pinpointer);
+        return isActive;
+    }
 
-            // todo: ideally, you would need to raise this event only on jumped entities
-            // this code update ALL pinpointers in game
-            foreach (var pinpointer in EntityQuery<PinpointerComponent>())
-            {
-                LocateTarget(pinpointer.Owner, pinpointer);
-            }
-        }
+    private void UpdateAppearance(EntityUid uid, PinpointerComponent pinpointer, AppearanceComponent? appearance = null)
+    {
+        if (!Resolve(uid, ref appearance))
+            return;
+        _appearance.SetData(uid, PinpointerVisuals.IsActive, pinpointer.IsActive, appearance);
+        _appearance.SetData(uid, PinpointerVisuals.TargetDistance, pinpointer.DistanceToTarget, appearance);
+    }
 
-        private void LocateTarget(EntityUid uid, PinpointerComponent component)
+    private void OnLocateTarget(ref FTLCompletedEvent ev)
+    {
+        // This feels kind of expensive, but it only happens once per hyperspace jump
+
+        // todo: ideally, you would need to raise this event only on jumped entities
+        // this code update ALL pinpointers in game
+        var query = EntityQueryEnumerator<PinpointerComponent>();
+        while (query.MoveNext(out var uid, out var pinpointer))
         {
-            // try to find target from whitelist
-            if (component.IsActive && component.Component != null)
-            {
-                if (!EntityManager.ComponentFactory.TryGetRegistration(component.Component, out var reg))
-                {
-                    Logger.Error($"Unable to find component registration for {component.Component} for pinpointer!");
-                    DebugTools.Assert(false);
-                    return;
-                }
-
-                var target = FindTargetFromComponent(uid, reg.Type);
-                SetTarget(uid, target, component);
-            }
+            LocateTarget(uid, pinpointer);
         }
+    }
 
-        public override void Update(float frameTime)
+    private void LocateTarget(EntityUid uid, PinpointerComponent component)
+    {
+        // try to find target from whitelist
+        if (component.IsActive && component.Component != null)
         {
-            base.Update(frameTime);
-
-            // because target or pinpointer can move
-            // we need to update pinpointers arrow each frame
-            foreach (var pinpointer in EntityQuery<PinpointerComponent>())
+            if (!EntityManager.ComponentFactory.TryGetRegistration(component.Component, out var reg))
             {
-                UpdateDirectionToTarget(pinpointer.Owner, pinpointer);
+                Logger.Error($"Unable to find component registration for {component.Component} for pinpointer!");
+                DebugTools.Assert(false);
+                return;
             }
+
+            var target = FindTargetFromComponent(uid, reg.Type);
+            SetTarget(uid, target, component);
         }
+    }
+
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
 
-        /// <summary>
-        ///     Try to find the closest entity from whitelist on a current map
-        ///     Will return null if can't find anything
-        /// </summary>
-        private EntityUid? FindTargetFromComponent(EntityUid uid, Type whitelist, TransformComponent? transform = null)
+        // because target or pinpointer can move
+        // we need to update pinpointers arrow each frame
+        var query = EntityQueryEnumerator<PinpointerComponent>();
+        while (query.MoveNext(out var uid, out var pinpointer))
         {
-            var xformQuery = GetEntityQuery<TransformComponent>();
+            UpdateDirectionToTarget(uid, pinpointer);
+        }
+    }
 
-            if (transform == null)
-                xformQuery.TryGetComponent(uid, out transform);
+    /// <summary>
+    ///     Try to find the closest entity from whitelist on a current map
+    ///     Will return null if can't find anything
+    /// </summary>
+    private EntityUid? FindTargetFromComponent(EntityUid uid, Type whitelist, TransformComponent? transform = null)
+    {
+        var xformQuery = GetEntityQuery<TransformComponent>();
 
-            if (transform == null)
-                return null;
+        if (transform == null)
+            xformQuery.TryGetComponent(uid, out transform);
 
-            // sort all entities in distance increasing order
-            var mapId = transform.MapID;
-            var l = new SortedList<float, EntityUid>();
-            var worldPos = _transform.GetWorldPosition(transform, xformQuery);
+        if (transform == null)
+            return null;
 
-            foreach (var comp in EntityManager.GetAllComponents(whitelist))
-            {
-                if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId)
-                    continue;
+        // sort all entities in distance increasing order
+        var mapId = transform.MapID;
+        var l = new SortedList<float, EntityUid>();
+        var worldPos = _transform.GetWorldPosition(transform, xformQuery);
 
-                var dist = (_transform.GetWorldPosition(compXform, xformQuery) - worldPos).LengthSquared;
-                l.TryAdd(dist, comp.Owner);
-            }
+        foreach (var comp in EntityManager.GetAllComponents(whitelist))
+        {
+            if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId)
+                continue;
 
-            // return uid with a smallest distance
-            return l.Count > 0 ? l.First().Value : null;
+            var dist = (_transform.GetWorldPosition(compXform, xformQuery) - worldPos).LengthSquared;
+            l.TryAdd(dist, comp.Owner);
         }
 
-        /// <summary>
-        ///     Set pinpointers target to track
-        /// </summary>
-        public void SetTarget(EntityUid uid, EntityUid? target, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return;
+        // return uid with a smallest distance
+        return l.Count > 0 ? l.First().Value : null;
+    }
 
-            if (pinpointer.Target == target)
-                return;
+    /// <summary>
+    ///     Set pinpointers target to track
+    /// </summary>
+    public void SetTarget(EntityUid uid, EntityUid? target, PinpointerComponent? pinpointer = null)
+    {
+        if (!Resolve(uid, ref pinpointer))
+            return;
 
-            pinpointer.Target = target;
-            if (pinpointer.IsActive)
-                UpdateDirectionToTarget(uid, pinpointer);
-        }
+        if (pinpointer.Target == target)
+            return;
 
-        /// <summary>
-        ///     Update direction from pinpointer to selected target (if it was set)
-        /// </summary>
-        private void UpdateDirectionToTarget(EntityUid uid, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return;
-
-            if (!pinpointer.IsActive)
-                return;
+        pinpointer.Target = target;
+        if (pinpointer.IsActive)
+            UpdateDirectionToTarget(uid, pinpointer);
+    }
 
-            var target = pinpointer.Target;
-            if (target == null || !EntityManager.EntityExists(target.Value))
-            {
-                SetDistance(uid, Distance.Unknown, pinpointer);
-                return;
-            }
+    /// <summary>
+    ///     Update direction from pinpointer to selected target (if it was set)
+    /// </summary>
+    private void UpdateDirectionToTarget(EntityUid uid, PinpointerComponent pinpointer)
+    {
+        if (!pinpointer.IsActive)
+            return;
 
-            var dirVec = CalculateDirection(uid, target.Value);
-            if (dirVec != null)
-            {
-                var angle = dirVec.Value.ToWorldAngle();
-                TrySetArrowAngle(uid, angle, pinpointer);
-                var dist = CalculateDistance(uid, dirVec.Value, pinpointer);
-                SetDistance(uid, dist, pinpointer);
-            }
-            else
-            {
-                SetDistance(uid, Distance.Unknown, pinpointer);
-            }
+        var target = pinpointer.Target;
+        if (target == null || !EntityManager.EntityExists(target.Value))
+        {
+            SetDistance(uid, Distance.Unknown, pinpointer);
+            return;
         }
 
-        /// <summary>
-        ///     Calculate direction from pinUid to trgUid
-        /// </summary>
-        /// <returns>Null if failed to calculate distance between two entities</returns>
-        private Vector2? CalculateDirection(EntityUid pinUid, EntityUid trgUid)
+        var dirVec = CalculateDirection(uid, target.Value);
+        var oldDist = pinpointer.DistanceToTarget;
+        if (dirVec != null)
+        {
+            var angle = dirVec.Value.ToWorldAngle();
+            TrySetArrowAngle(uid, angle, pinpointer);
+            var dist = CalculateDistance(dirVec.Value, pinpointer);
+            SetDistance(uid, dist, pinpointer);
+        }
+        else
         {
-            var xformQuery = GetEntityQuery<TransformComponent>();
+            SetDistance(uid, Distance.Unknown, pinpointer);
+        }
+        if (oldDist != pinpointer.DistanceToTarget)
+            UpdateAppearance(uid, pinpointer);
+    }
 
-            // check if entities have transform component
-            if (!xformQuery.TryGetComponent(pinUid, out var pin))
-                return null;
-            if (!xformQuery.TryGetComponent(trgUid, out var trg))
-                return null;
+    /// <summary>
+    ///     Calculate direction from pinUid to trgUid
+    /// </summary>
+    /// <returns>Null if failed to calculate distance between two entities</returns>
+    private Vector2? CalculateDirection(EntityUid pinUid, EntityUid trgUid)
+    {
+        var xformQuery = GetEntityQuery<TransformComponent>();
 
-            // check if they are on same map
-            if (pin.MapID != trg.MapID)
-                return null;
+        // check if entities have transform component
+        if (!xformQuery.TryGetComponent(pinUid, out var pin))
+            return null;
+        if (!xformQuery.TryGetComponent(trgUid, out var trg))
+            return null;
 
-            // get world direction vector
-            var dir = (_transform.GetWorldPosition(trg, xformQuery) - _transform.GetWorldPosition(pin, xformQuery));
-            return dir;
-        }
+        // check if they are on same map
+        if (pin.MapID != trg.MapID)
+            return null;
 
-        private Distance CalculateDistance(EntityUid uid, Vector2 vec, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return Distance.Unknown;
-
-            var dist = vec.Length;
-            if (dist <= pinpointer.ReachedDistance)
-                return Distance.Reached;
-            else if (dist <= pinpointer.CloseDistance)
-                return Distance.Close;
-            else if (dist <= pinpointer.MediumDistance)
-                return Distance.Medium;
-            else
-                return Distance.Far;
-        }
+        // get world direction vector
+        var dir = _transform.GetWorldPosition(trg, xformQuery) - _transform.GetWorldPosition(pin, xformQuery);
+        return dir;
+    }
+
+    private static Distance CalculateDistance(Vector2 vec, PinpointerComponent pinpointer)
+    {
+        var dist = vec.Length;
+        if (dist <= pinpointer.ReachedDistance)
+            return Distance.Reached;
+        else if (dist <= pinpointer.CloseDistance)
+            return Distance.Close;
+        else if (dist <= pinpointer.MediumDistance)
+            return Distance.Medium;
+        else
+            return Distance.Far;
     }
 }
index 7e467f14b06b64417868e16423258f2be1c0af95..0b49ad5e99cde48cbb47d61945896240fb9b475c 100644 (file)
@@ -1,57 +1,60 @@
 using Robust.Shared.GameStates;
 using Robust.Shared.Serialization;
 
-namespace Content.Shared.Pinpointer
+namespace Content.Shared.Pinpointer;
+
+/// <summary>
+/// Displays a sprite on the item that points towards the target component.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+[AutoGenerateComponentState]
+[Access(typeof(SharedPinpointerSystem))]
+public sealed partial class PinpointerComponent : Component
 {
+    // TODO: Type serializer oh god
+    [DataField("component")]
+    public string? Component;
+
+    [DataField("mediumDistance"), ViewVariables(VVAccess.ReadWrite)]
+    public float MediumDistance = 16f;
+
+    [DataField("closeDistance"), ViewVariables(VVAccess.ReadWrite)]
+    public float CloseDistance = 8f;
+
+    [DataField("reachedDistance"), ViewVariables(VVAccess.ReadWrite)]
+    public float ReachedDistance = 1f;
+
     /// <summary>
-    /// Displays a sprite on the item that points towards the target component.
+    ///     Pinpointer arrow precision in radians.
     /// </summary>
-    [RegisterComponent]
-    [NetworkedComponent]
-    [Access(typeof(SharedPinpointerSystem))]
-    public sealed class PinpointerComponent : Component
-    {
-        // TODO: Type serializer oh god
-        [DataField("component")]
-        public string? Component;
-
-        [DataField("mediumDistance")]
-        public float MediumDistance = 16f;
-
-        [DataField("closeDistance")]
-        public float CloseDistance = 8f;
-
-        [DataField("reachedDistance")]
-        public float ReachedDistance = 1f;
-
-        /// <summary>
-        ///     Pinpointer arrow precision in radians.
-        /// </summary>
-        [DataField("precision")]
-        public double Precision = 0.09;
-
-        public EntityUid? Target = null;
-        public bool IsActive = false;
-        public Angle ArrowAngle;
-        public Distance DistanceToTarget = Distance.Unknown;
-        public bool HasTarget => DistanceToTarget != Distance.Unknown;
-    }
-
-    [Serializable, NetSerializable]
-    public sealed class PinpointerComponentState : ComponentState
-    {
-        public bool IsActive;
-        public Angle ArrowAngle;
-        public Distance DistanceToTarget;
-    }
-
-    [Serializable, NetSerializable]
-    public enum Distance : byte
-    {
-        Unknown,
-        Reached,
-        Close,
-        Medium,
-        Far
-    }
+    [DataField("precision"), ViewVariables(VVAccess.ReadWrite)]
+    public double Precision = 0.09;
+
+    [ViewVariables]
+    public EntityUid? Target = null;
+
+    [ViewVariables]
+    [AutoNetworkedField]
+    public bool IsActive = false;
+
+    [ViewVariables]
+    [AutoNetworkedField]
+    public Angle ArrowAngle;
+
+    [ViewVariables]
+    [AutoNetworkedField]
+    public Distance DistanceToTarget = Distance.Unknown;
+
+    [ViewVariables]
+    public bool HasTarget => DistanceToTarget != Distance.Unknown;
+}
+
+[Serializable, NetSerializable]
+public enum Distance : byte
+{
+    Unknown,
+    Reached,
+    Close,
+    Medium,
+    Far
 }
index 17e5de8cfdb0a5494d1610289598cad3299758c3..5491e53dd2f9e7903c38f777bd1ec9c58b592a30 100644 (file)
@@ -1,86 +1,52 @@
-using Robust.Shared.GameStates;
+namespace Content.Shared.Pinpointer;
 
-namespace Content.Shared.Pinpointer
+public abstract class SharedPinpointerSystem : EntitySystem
 {
-    public abstract class SharedPinpointerSystem : EntitySystem
+    /// <summary>
+    ///     Manually set distance from pinpointer to target
+    /// </summary>
+    public void SetDistance(EntityUid uid, Distance distance, PinpointerComponent? pinpointer = null)
     {
-        public override void Initialize()
-        {
-            base.Initialize();
-            SubscribeLocalEvent<PinpointerComponent, ComponentGetState>(GetCompState);
-        }
+        if (!Resolve(uid, ref pinpointer))
+            return;
 
-        private void GetCompState(EntityUid uid, PinpointerComponent pinpointer, ref ComponentGetState args)
-        {
-            args.State = new PinpointerComponentState
-            {
-                IsActive = pinpointer.IsActive,
-                ArrowAngle = pinpointer.ArrowAngle,
-                DistanceToTarget = pinpointer.DistanceToTarget
-            };
-        }
+        if (distance == pinpointer.DistanceToTarget)
+            return;
 
-        /// <summary>
-        ///     Manually set distance from pinpointer to target
-        /// </summary>
-        public void SetDistance(EntityUid uid, Distance distance, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return;
-
-            if (distance == pinpointer.DistanceToTarget)
-                return;
-
-            pinpointer.DistanceToTarget = distance;
-            Dirty(pinpointer);
-        }
-
-        /// <summary>
-        ///     Try to manually set pinpointer arrow direction.
-        ///     If difference between current angle and new angle is smaller than
-        ///     pinpointer precision, new value will be ignored and it will return false.
-        /// </summary>
-        public bool TrySetArrowAngle(EntityUid uid, Angle arrowAngle, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return false;
-
-            if (pinpointer.ArrowAngle.EqualsApprox(arrowAngle, pinpointer.Precision))
-                return false;
+        pinpointer.DistanceToTarget = distance;
+        Dirty(pinpointer);
+    }
 
-            pinpointer.ArrowAngle = arrowAngle;
-            Dirty(pinpointer);
+    /// <summary>
+    ///     Try to manually set pinpointer arrow direction.
+    ///     If difference between current angle and new angle is smaller than
+    ///     pinpointer precision, new value will be ignored and it will return false.
+    /// </summary>
+    public bool TrySetArrowAngle(EntityUid uid, Angle arrowAngle, PinpointerComponent? pinpointer = null)
+    {
+        if (!Resolve(uid, ref pinpointer))
+            return false;
 
-            return true;
-        }
+        if (pinpointer.ArrowAngle.EqualsApprox(arrowAngle, pinpointer.Precision))
+            return false;
 
-        /// <summary>
-        ///     Activate/deactivate pinpointer screen. If it has target it will start tracking it.
-        /// </summary>
-        public void SetActive(EntityUid uid, bool isActive, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return;
-            if (isActive == pinpointer.IsActive)
-                return;
-            
-            pinpointer.IsActive = isActive;
-            Dirty(pinpointer);
-        }
+        pinpointer.ArrowAngle = arrowAngle;
+        Dirty(pinpointer);
 
+        return true;
+    }
 
-        /// <summary>
-        ///     Toggle Pinpointer screen. If it has target it will start tracking it.
-        /// </summary>
-        /// <returns>True if pinpointer was activated, false otherwise</returns>
-        public bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
-        {
-            if (!Resolve(uid, ref pinpointer))
-                return false;
+    /// <summary>
+    ///     Activate/deactivate pinpointer screen. If it has target it will start tracking it.
+    /// </summary>
+    public void SetActive(EntityUid uid, bool isActive, PinpointerComponent? pinpointer = null)
+    {
+        if (!Resolve(uid, ref pinpointer))
+            return;
+        if (isActive == pinpointer.IsActive)
+            return;
 
-            var isActive = !pinpointer.IsActive;
-            SetActive(uid, isActive, pinpointer);
-            return isActive;
-        }
+        pinpointer.IsActive = isActive;
+        Dirty(pinpointer);
     }
 }
index 48682b4547d25d7d5af0dac18d8f7bbfbca9052d..054bb26ea6558cc5eb586f8804c245a471a46c33 100644 (file)
@@ -8,7 +8,6 @@
   - type: Transform
     noRot: True
   - type: Sprite
-    netsync: false
     noRot: True
     sprite: Objects/Devices/pinpointer.rsi
     layers:
       map: ["enum.PinpointerLayers.Base"]
     - state: pinonnull
       map: ["enum.PinpointerLayers.Screen"]
+      shader: unshaded
+      visible: false
   - type: Item
     sprite: Objects/Devices/pinpointer.rsi
   - type: Pinpointer
   - type: Appearance
+  - type: GenericVisualizer
+    visuals:
+      enum.PinpointerVisuals.IsActive:
+        enum.PinpointerLayers.Screen:
+          True: { visible: True }
+          False: { visible: False }
+      enum.PinpointerVisuals.TargetDistance:
+        enum.PinpointerLayers.Screen:
+          Unknown: { state: pinonnull }
+          Reached: { state: pinondirect }
+          Close: { state: pinonclose }
+          Medium: { state: pinonmedium }
+          Far: { state: pinonfar }
+  - type: AnimationPlayer
 
 - type: entity
   name: pinpointer