diff --git a/Content.Shared/Camera/GetEyeOffsetEvent.cs b/Content.Shared/Camera/GetEyeOffsetEvent.cs new file mode 100644 index 0000000000..de9c7c9e17 --- /dev/null +++ b/Content.Shared/Camera/GetEyeOffsetEvent.cs @@ -0,0 +1,19 @@ +using System.Numerics; +using Content.Shared.Movement.Systems; + +namespace Content.Shared.Camera; + +/// +/// Raised directed by-ref when is called. +/// Should be subscribed to by any systems that want to modify an entity's eye offset, +/// so that they do not override each other. +/// +/// +/// The total offset to apply. +/// +/// +/// Note that in most cases should be incremented or decremented by subscribers, not set. +/// Otherwise, any offsets applied by previous subscribing systems will be overridden. +/// +[ByRefEvent] +public record struct GetEyeOffsetEvent(Vector2 Offset); diff --git a/Content.Shared/Camera/SharedCameraRecoilSystem.cs b/Content.Shared/Camera/SharedCameraRecoilSystem.cs index 3507bf1023..d42fe9dcee 100644 --- a/Content.Shared/Camera/SharedCameraRecoilSystem.cs +++ b/Content.Shared/Camera/SharedCameraRecoilSystem.cs @@ -1,6 +1,7 @@ using System.Numerics; +using Content.Shared.Movement.Systems; using JetBrains.Annotations; -using Robust.Shared.Player; +using Robust.Shared.Network; using Robust.Shared.Serialization; namespace Content.Shared.Camera; @@ -28,7 +29,18 @@ public abstract class SharedCameraRecoilSystem : EntitySystem /// protected const float KickMagnitudeMax = 1f; - [Dependency] private readonly SharedEyeSystem _eye = default!; + [Dependency] private readonly SharedContentEyeSystem _eye = default!; + [Dependency] private readonly INetManager _net = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnCameraRecoilGetEyeOffset); + } + + private void OnCameraRecoilGetEyeOffset(Entity ent, ref GetEyeOffsetEvent args) + { + args.Offset += ent.Comp.BaseOffset + ent.Comp.CurrentKick; + } /// /// Applies explosion/recoil/etc kickback to the view of the entity. @@ -39,10 +51,8 @@ public abstract class SharedCameraRecoilSystem : EntitySystem /// public abstract void KickCamera(EntityUid euid, Vector2 kickback, CameraRecoilComponent? component = null); - public override void FrameUpdate(float frameTime) + private void UpdateEyes(float frameTime) { - base.FrameUpdate(frameTime); - var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var eye, out var recoil)) @@ -51,7 +61,7 @@ public abstract class SharedCameraRecoilSystem : EntitySystem if (magnitude <= 0.005f) { recoil.CurrentKick = Vector2.Zero; - _eye.SetOffset(uid, recoil.BaseOffset + recoil.CurrentKick, eye); + _eye.UpdateEyeOffset((uid, eye)); } else // Continually restore camera to 0. { @@ -60,16 +70,28 @@ public abstract class SharedCameraRecoilSystem : EntitySystem var restoreRate = MathHelper.Lerp(RestoreRateMin, RestoreRateMax, Math.Min(1, recoil.LastKickTime / RestoreRateRamp)); var restore = normalized * restoreRate * frameTime; var (x, y) = recoil.CurrentKick - restore; - if (Math.Sign(x) != Math.Sign(recoil.CurrentKick.X)) x = 0; + if (Math.Sign(x) != Math.Sign(recoil.CurrentKick.X)) + x = 0; - if (Math.Sign(y) != Math.Sign(recoil.CurrentKick.Y)) y = 0; + if (Math.Sign(y) != Math.Sign(recoil.CurrentKick.Y)) + y = 0; recoil.CurrentKick = new Vector2(x, y); - - _eye.SetOffset(uid, recoil.BaseOffset + recoil.CurrentKick, eye); + _eye.UpdateEyeOffset((uid, eye)); } } } + + public override void Update(float frameTime) + { + if (_net.IsServer) + UpdateEyes(frameTime); + } + + public override void FrameUpdate(float frameTime) + { + UpdateEyes(frameTime); + } } [Serializable] diff --git a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs index 207f14a258..0c4304d374 100644 --- a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs +++ b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs @@ -1,6 +1,7 @@ using System.Numerics; using Content.Shared.Administration; using Content.Shared.Administration.Managers; +using Content.Shared.Camera; using Content.Shared.Ghost; using Content.Shared.Input; using Content.Shared.Movement.Components; @@ -128,6 +129,13 @@ public abstract class SharedContentEyeSystem : EntitySystem Dirty(uid, component); } + public void UpdateEyeOffset(Entity eye) + { + var ev = new GetEyeOffsetEvent(); + RaiseLocalEvent(eye, ref ev); + _eye.SetOffset(eye, ev.Offset, eye); + } + /// /// Sendable from client to server to request a target zoom. ///