diff --git a/Content.Client/Pointing/Components/PointingArrowComponent.cs b/Content.Client/Pointing/Components/PointingArrowComponent.cs index cbc1527482..3c82e62588 100644 --- a/Content.Client/Pointing/Components/PointingArrowComponent.cs +++ b/Content.Client/Pointing/Components/PointingArrowComponent.cs @@ -1,12 +1,7 @@ using Content.Shared.Pointing.Components; -using Robust.Client.GameObjects; -using DrawDepth = Content.Shared.DrawDepth.DrawDepth; namespace Content.Client.Pointing.Components { [RegisterComponent] - [ComponentReference(typeof(SharedPointingArrowComponent))] - public sealed class PointingArrowComponent : SharedPointingArrowComponent - { - } + public sealed class PointingArrowComponent : SharedPointingArrowComponent {} } diff --git a/Content.Client/Pointing/PointingSystem.cs b/Content.Client/Pointing/PointingSystem.cs index 2cc4a2b5bc..53082c3d27 100644 --- a/Content.Client/Pointing/PointingSystem.cs +++ b/Content.Client/Pointing/PointingSystem.cs @@ -2,23 +2,66 @@ using Content.Client.Pointing.Components; using Content.Shared.MobState.EntitySystems; using Content.Shared.Pointing; using Content.Shared.Verbs; +using Robust.Client.Animations; using Robust.Client.GameObjects; +using Robust.Shared.Animations; using DrawDepth = Content.Shared.DrawDepth.DrawDepth; namespace Content.Client.Pointing; -public sealed class PointingSystem : EntitySystem +public sealed class PointingSystem : SharedPointingSystem { + [Dependency] private readonly AnimationPlayerSystem _player = default!; [Dependency] private readonly SharedMobStateSystem _mobState = default!; + private const string AnimationKey = "pointingarrow"; + + /// + /// How far it goes in any direction. + /// + private const float Offset = 0.25f; + + /// + /// How long it takes to go from the bottom of the animation to the top. + /// + private const float UpTime = 0.5f; + + /// + /// Starts at the bottom then goes up and comes back down. Seems to look nicer than starting in the middle. + /// + private static readonly Animation PointingAnimation = new Animation() + { + Length = TimeSpan.FromSeconds(2 * UpTime), + AnimationTracks = + { + new AnimationTrackComponentProperty() + { + ComponentType = typeof(SpriteComponent), + Property = nameof(SpriteComponent.Offset), + InterpolationMode = AnimationInterpolationMode.Linear, + KeyFrames = + { + new AnimationTrackProperty.KeyFrame(Vector2.Zero, 0f), + new AnimationTrackProperty.KeyFrame(new Vector2(0f, Offset), UpTime), + new AnimationTrackProperty.KeyFrame(Vector2.Zero, UpTime), + } + } + } + }; + public override void Initialize() { base.Initialize(); SubscribeLocalEvent>(AddPointingVerb); SubscribeLocalEvent(OnArrowStartup); + SubscribeLocalEvent(OnArrowAnimation); SubscribeLocalEvent(OnRogueArrowStartup); + } + private void OnArrowAnimation(EntityUid uid, PointingArrowComponent component, AnimationCompletedEvent args) + { + _player.Play(uid, PointingAnimation, AnimationKey); } private void AddPointingVerb(GetVerbsEvent args) @@ -58,6 +101,8 @@ public sealed class PointingSystem : EntitySystem { sprite.DrawDepth = (int) DrawDepth.Overlays; } + + _player.Play(uid, PointingAnimation, AnimationKey); } private void OnRogueArrowStartup(EntityUid uid, RoguePointingArrowComponent arrow, ComponentStartup args) @@ -65,6 +110,7 @@ public sealed class PointingSystem : EntitySystem if (EntityManager.TryGetComponent(uid, out SpriteComponent? sprite)) { sprite.DrawDepth = (int) DrawDepth.Overlays; + sprite.NoRotation = false; } } } diff --git a/Content.Client/Pointing/RoguePointingArrowVisualizer.cs b/Content.Client/Pointing/RoguePointingArrowVisualizer.cs deleted file mode 100644 index fe8e359563..0000000000 --- a/Content.Client/Pointing/RoguePointingArrowVisualizer.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using Content.Shared.Pointing.Components; -using JetBrains.Annotations; -using Robust.Client.Animations; -using Robust.Client.GameObjects; -using Robust.Shared.Animations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Maths; - -namespace Content.Client.Pointing -{ - [UsedImplicitly] - public sealed class RoguePointingArrowVisualizer : AppearanceVisualizer - { - [Obsolete("Subscribe to AppearanceChangeEvent instead.")] - public override void OnChangeData(AppearanceComponent component) - { - base.OnChangeData(component); - - if (component.TryGetData(RoguePointingArrowVisuals.Rotation, out var degrees)) - { - SetRotation(component, Angle.FromDegrees(degrees)); - } - } - - private void SetRotation(AppearanceComponent component, Angle rotation) - { - var sprite = IoCManager.Resolve().GetComponent(component.Owner); - - if (!IoCManager.Resolve().TryGetComponent(sprite.Owner, out AnimationPlayerComponent? animation)) - { - sprite.Rotation = rotation; - return; - } - - if (animation.HasRunningAnimation("rotate")) - { - animation.Stop("rotate"); - } - - animation.Play(new Animation - { - Length = TimeSpan.FromSeconds(0.125), - AnimationTracks = - { - new AnimationTrackComponentProperty - { - ComponentType = typeof(ISpriteComponent), - Property = nameof(ISpriteComponent.Rotation), - InterpolationMode = AnimationInterpolationMode.Linear, - KeyFrames = - { - new AnimationTrackProperty.KeyFrame(sprite.Rotation, 0), - new AnimationTrackProperty.KeyFrame(rotation, 0.125f) - } - } - } - }, "rotate"); - } - } -} diff --git a/Content.Server/Pointing/Components/PointingArrowComponent.cs b/Content.Server/Pointing/Components/PointingArrowComponent.cs index 34e4178447..309440aea1 100644 --- a/Content.Server/Pointing/Components/PointingArrowComponent.cs +++ b/Content.Server/Pointing/Components/PointingArrowComponent.cs @@ -1,84 +1,18 @@ +using Content.Server.Pointing.EntitySystems; using Content.Shared.Pointing.Components; -using Robust.Server.GameObjects; -using DrawDepth = Content.Shared.DrawDepth.DrawDepth; namespace Content.Server.Pointing.Components { [RegisterComponent] - [ComponentReference(typeof(SharedPointingArrowComponent))] + [Access(typeof(PointingSystem))] public sealed class PointingArrowComponent : SharedPointingArrowComponent { - [Dependency] private readonly IEntityManager _entMan = default!; - - /// - /// The current amount of seconds left on this arrow. - /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("duration")] - private float _duration = 4; - - /// - /// The amount of seconds before the arrow changes movement direction. - /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("step")] - private float _step = 0.5f; - - /// - /// The amount of units that this arrow will move by when multiplied - /// by the frame time. - /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("speed")] - private float _speed = 1; - - /// - /// The current amount of seconds left before the arrow changes - /// movement direction. - /// - [ViewVariables(VVAccess.ReadWrite)] - private float _currentStep; - - /// - /// Whether or not this arrow is currently going up. - /// - [ViewVariables(VVAccess.ReadWrite)] - private bool _up; - /// /// Whether or not this arrow will convert into a /// when its duration runs out. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("rogue")] - public bool Rogue = false; - - public void Update(float frameTime) - { - var movement = _speed * frameTime * (_up ? 1 : -1); - _entMan.GetComponent(Owner).LocalPosition += (0, movement); - - _duration -= frameTime; - _currentStep -= frameTime; - - if (_duration <= 0) - { - if (Rogue) - { - _entMan.RemoveComponent(Owner); - _entMan.AddComponent(Owner); - return; - } - - _entMan.DeleteEntity(Owner); - return; - } - - if (_currentStep <= 0) - { - _currentStep = _step; - _up ^= true; - } - } + public bool Rogue; } } diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index c7d09fe9a5..2dcbcd248d 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -24,7 +24,7 @@ using Robust.Shared.Timing; namespace Content.Server.Pointing.EntitySystems { [UsedImplicitly] - internal sealed class PointingSystem : EntitySystem + internal sealed class PointingSystem : SharedPointingSystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; @@ -128,7 +128,12 @@ namespace Content.Server.Pointing.EntitySystems _rotateToFaceSystem.TryFaceCoordinates(player, mapCoords.Position); - var arrow = EntityManager.SpawnEntity("pointingarrow", mapCoords); + var arrow = EntityManager.SpawnEntity("PointingArrow", mapCoords); + + if (TryComp(arrow, out var pointing)) + { + pointing.EndTime = _gameTiming.CurTime + TimeSpan.FromSeconds(4); + } if (EntityQuery().FirstOrDefault() != null) { @@ -231,10 +236,28 @@ namespace Content.Server.Pointing.EntitySystems public override void Update(float frameTime) { - foreach (var component in EntityManager.EntityQuery(true)) + var currentTime = _gameTiming.CurTime; + + foreach (var component in EntityQuery(true)) { - component.Update(frameTime); + Update(component, currentTime); } } + + private void Update(PointingArrowComponent component, TimeSpan currentTime) + { + // TODO: That pause PR + if (component.EndTime > currentTime) + return; + + if (component.Rogue) + { + RemComp(component.Owner); + EnsureComp(component.Owner); + return; + } + + Del(component.Owner); + } } } diff --git a/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs b/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs index d7439c5157..45ccb0cefb 100644 --- a/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs @@ -61,7 +61,7 @@ namespace Content.Server.Pointing.EntitySystems if (component.Chasing is not {Valid: true} chasing || Deleted(chasing)) { EntityManager.QueueDeleteEntity(uid); - return; + continue; } component.TurningDelay -= frameTime; @@ -73,10 +73,10 @@ namespace Content.Server.Pointing.EntitySystems var adjusted = angle.Degrees + 90; var newAngle = Angle.FromDegrees(adjusted); - transform.LocalRotation = newAngle; + transform.WorldRotation = newAngle; UpdateAppearance(uid, component, transform); - return; + continue; } transform.WorldRotation += Angle.FromDegrees(20); @@ -91,8 +91,10 @@ namespace Content.Server.Pointing.EntitySystems if (component.ChasingTime > 0) { - return; + continue; } + + _explosion.QueueExplosion(uid, ExplosionSystem.DefaultExplosionPrototypeId, 50, 3, 10); EntityManager.QueueDeleteEntity(uid); } diff --git a/Content.Shared/Pointing/Components/SharedPointingArrowComponent.cs b/Content.Shared/Pointing/Components/SharedPointingArrowComponent.cs index 615f93ee6c..09b5157aa5 100644 --- a/Content.Shared/Pointing/Components/SharedPointingArrowComponent.cs +++ b/Content.Shared/Pointing/Components/SharedPointingArrowComponent.cs @@ -1,5 +1,13 @@ +using Robust.Shared.GameStates; + namespace Content.Shared.Pointing.Components; +[NetworkedComponent] public abstract class SharedPointingArrowComponent : Component { + /// + /// When the pointing arrow ends + /// + [ViewVariables(VVAccess.ReadWrite), DataField("endTime")] + public TimeSpan EndTime; } diff --git a/Content.Shared/Pointing/Components/SharedRoguePointingArrowComponent.cs b/Content.Shared/Pointing/Components/SharedRoguePointingArrowComponent.cs index e54892c86b..4d6de3a90d 100644 --- a/Content.Shared/Pointing/Components/SharedRoguePointingArrowComponent.cs +++ b/Content.Shared/Pointing/Components/SharedRoguePointingArrowComponent.cs @@ -1,13 +1,15 @@ -using Robust.Shared.Serialization; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; namespace Content.Shared.Pointing.Components { + [NetworkedComponent] public abstract class SharedRoguePointingArrowComponent : Component { } [Serializable, NetSerializable] - public enum RoguePointingArrowVisuals + public enum RoguePointingArrowVisuals : byte { Rotation } diff --git a/Content.Shared/Pointing/SharedPointingSystem.cs b/Content.Shared/Pointing/SharedPointingSystem.cs new file mode 100644 index 0000000000..05e4b4aa27 --- /dev/null +++ b/Content.Shared/Pointing/SharedPointingSystem.cs @@ -0,0 +1,17 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Pointing; + +public abstract class SharedPointingSystem : EntitySystem +{ + [Serializable, NetSerializable] + protected sealed class PointingArrowComponentState : ComponentState + { + public TimeSpan EndTime; + + public PointingArrowComponentState(TimeSpan endTime) + { + EndTime = endTime; + } + } +} diff --git a/Resources/Prototypes/Entities/Markers/pointing.yml b/Resources/Prototypes/Entities/Markers/pointing.yml index fe94471bbf..de0f7057d3 100644 --- a/Resources/Prototypes/Entities/Markers/pointing.yml +++ b/Resources/Prototypes/Entities/Markers/pointing.yml @@ -1,6 +1,6 @@ - type: entity name: pointing arrow - id: pointingarrow + id: PointingArrow save: false components: - type: Tag @@ -11,10 +11,9 @@ sprite: Interface/Misc/pointing.rsi state: pointing drawDepth: Overlays + noRot: true - type: PointingArrow duration: 4 step: 0.5 speed: 1 - type: Appearance - visuals: - - type: RoguePointingArrowVisualizer