diff --git a/Content.Server/Actions/ServerActionsComponent.cs b/Content.Server/Actions/ServerActionsComponent.cs index afc860891e..d5ff96d40e 100644 --- a/Content.Server/Actions/ServerActionsComponent.cs +++ b/Content.Server/Actions/ServerActionsComponent.cs @@ -4,6 +4,7 @@ using Content.Shared.Actions; using Content.Shared.Actions.Components; using Content.Shared.Actions.Prototypes; using Content.Shared.Interaction.Events; +using Content.Shared.Interaction; using Robust.Server.GameObjects; using Robust.Server.GameStates; using Robust.Shared.GameObjects; @@ -186,15 +187,7 @@ namespace Content.Server.Actions return false; } - if (!EntitySystem.Get().CanChangeDirection(player)) return true; - - // don't set facing unless they clicked far enough away - var diff = targetWorldPos - player.Transform.WorldPosition; - if (diff.LengthSquared > 0.01f) - { - player.Transform.LocalRotation = Angle.FromWorldVec(diff); - } - + EntitySystem.Get().TryFaceCoordinates(player, targetWorldPos); return true; } } diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs index 38be774e3e..1578e53f5c 100644 --- a/Content.Server/Interaction/InteractionSystem.cs +++ b/Content.Server/Interaction/InteractionSystem.cs @@ -44,6 +44,7 @@ namespace Content.Server.Interaction [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly PullingSystem _pullSystem = default!; + [Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!; public override void Initialize() { @@ -357,38 +358,11 @@ namespace Content.Server.Interaction return false; } - FaceClickCoordinates(user, coordinates); + _rotateToFaceSystem.TryFaceCoordinates(user, coordinates.ToMapPos(EntityManager)); return true; } - private void FaceClickCoordinates(IEntity user, EntityCoordinates coordinates) - { - var diff = coordinates.ToMapPos(EntityManager) - user.Transform.MapPosition.Position; - if (diff.LengthSquared <= 0.01f) - return; - var diffAngle = Angle.FromWorldVec(diff); - if (_actionBlockerSystem.CanChangeDirection(user)) - { - user.Transform.WorldRotation = diffAngle; - } - else - { - if (user.TryGetComponent(out BuckleComponent? buckle) && (buckle.BuckledTo != null)) - { - // We're buckled to another object. Is that object rotatable? - if (buckle.BuckledTo!.Owner.TryGetComponent(out RotatableComponent? rotatable) && rotatable.RotateWhileAnchored) - { - // Note the assumption that even if unanchored, user can only do spinnychair with an "independent wheel". - // (Since the user being buckled to it holds it down with their weight.) - // This is logically equivalent to RotateWhileAnchored. - // Barstools and office chairs have independent wheels, while regular chairs don't. - rotatable.Owner.Transform.LocalRotation = diffAngle; - } - } - } - } - /// /// Uses an empty hand on an entity /// Finds components with the InteractHand interface and calls their function diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index 803eb90b67..b0cae3f09c 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Pointing.Components; using Content.Server.Visible; using Content.Shared.ActionBlocker; using Content.Shared.Input; +using Content.Shared.Interaction; using Content.Shared.Interaction.Helpers; using Content.Shared.Popups; using Content.Shared.Verbs; @@ -32,6 +33,7 @@ namespace Content.Server.Pointing.EntitySystems [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; + [Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!; private static readonly TimeSpan PointDelay = TimeSpan.FromSeconds(0.5f); @@ -114,14 +116,7 @@ namespace Content.Server.Pointing.EntitySystems return false; } - if (_actionBlockerSystem.CanChangeDirection(player)) - { - var diff = mapCoords.Position - player.Transform.MapPosition.Position; - if (diff.LengthSquared > 0.01f) - { - player.Transform.WorldRotation = Angle.FromWorldVec(diff); - } - } + _rotateToFaceSystem.TryFaceCoordinates(player, mapCoords.Position); var arrow = EntityManager.SpawnEntity("pointingarrow", mapCoords); diff --git a/Content.Shared/Interaction/RotateToFaceSystem.cs b/Content.Shared/Interaction/RotateToFaceSystem.cs new file mode 100644 index 0000000000..a430cffddf --- /dev/null +++ b/Content.Shared/Interaction/RotateToFaceSystem.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Content.Shared.ActionBlocker; +using Content.Shared.Hands; +using Content.Shared.Hands.Components; +using Content.Shared.Buckle.Components; +using Content.Shared.Rotatable; +using Content.Shared.Inventory; +using Content.Shared.Physics; +using Content.Shared.Popups; +using Content.Shared.Throwing; +using Content.Shared.Timing; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Random; +using Robust.Shared.Serialization; + +namespace Content.Shared.Interaction +{ + /// + /// Contains common code used to rotate a player to face a given target or direction. + /// This interaction in itself is useful for various roleplay purposes. + /// But it needs specialized code to handle chairs and such. + /// Doesn't really fit with SharedInteractionSystem so it's not there. + /// + [UsedImplicitly] + public class RotateToFaceSystem : EntitySystem + { + [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; + public bool TryFaceCoordinates(IEntity user, Vector2 coordinates) + { + var diff = coordinates - user.Transform.MapPosition.Position; + if (diff.LengthSquared <= 0.01f) + return true; + var diffAngle = Angle.FromWorldVec(diff); + return TryFaceAngle(user, diffAngle); + } + + public bool TryFaceAngle(IEntity user, Angle diffAngle) + { + if (_actionBlockerSystem.CanChangeDirection(user)) + { + user.Transform.WorldRotation = diffAngle; + return true; + } + else + { + if (user.TryGetComponent(out SharedBuckleComponent? buckle) && buckle.Buckled) + { + var suid = buckle.LastEntityBuckledTo; + if (suid != null) + { + // We're buckled to another object. Is that object rotatable? + if (EntityManager.TryGetComponent(suid.Value!, out var rotatable) && rotatable.RotateWhileAnchored) + { + // Note the assumption that even if unanchored, user can only do spinnychair with an "independent wheel". + // (Since the user being buckled to it holds it down with their weight.) + // This is logically equivalent to RotateWhileAnchored. + // Barstools and office chairs have independent wheels, while regular chairs don't. + rotatable.Owner.Transform.WorldRotation = diffAngle; + return true; + } + } + } + } + return false; + } + } +}