diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index df476b2874..e83a42a2fb 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -75,6 +75,7 @@ public sealed partial class AdminVerbSystem [Dependency] private readonly TabletopSystem _tabletopSystem = default!; [Dependency] private readonly VomitSystem _vomitSystem = default!; [Dependency] private readonly WeldableSystem _weldableSystem = default!; + [Dependency] private readonly SharedContentEyeSystem _eyeSystem = default!; // All smite verbs have names so invokeverb works. private void AddSmiteVerbs(GetVerbsEvent args) @@ -704,11 +705,8 @@ public sealed partial class AdminVerbSystem Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/zoom.png")), Act = () => { - var eye = EnsureComp(args.Target); - - eye.Zoom *= Vector2.One * 0.2f; - - Dirty(eye); + var eye = EnsureComp(args.Target); + _eyeSystem.SetZoom(args.Target, eye.TargetZoom * 0.2f, ignoreLimits: true); }, Impact = LogImpact.Extreme, Message = Loc.GetString("admin-smite-zoom-in-description"), @@ -722,11 +720,8 @@ public sealed partial class AdminVerbSystem Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/flip.png")), Act = () => { - var eye = EnsureComp(args.Target); - - eye.Zoom *= -1; - - Dirty(eye); + var eye = EnsureComp(args.Target); + _eyeSystem.SetZoom(args.Target, eye.TargetZoom * -1, ignoreLimits: true); }, Impact = LogImpact.Extreme, Message = Loc.GetString("admin-smite-flip-eye-description"), diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs index c3c49018de..16b55e70e5 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Shuttles.Components; using Content.Shared.Shuttles.Events; using Content.Shared.Shuttles.Systems; using Content.Shared.Tag; +using Content.Shared.Movement.Systems; using Robust.Server.GameObjects; using Robust.Shared.Collections; using Robust.Shared.GameStates; @@ -33,6 +34,7 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem [Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly TagSystem _tags = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly SharedContentEyeSystem _eyeSystem = default!; public override void Initialize() { @@ -69,7 +71,8 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem RefreshShuttleConsoles(); } - private void OnDestinationMessage(EntityUid uid, ShuttleConsoleComponent component, ShuttleConsoleFTLRequestMessage args) + private void OnDestinationMessage(EntityUid uid, ShuttleConsoleComponent component, + ShuttleConsoleFTLRequestMessage args) { if (!TryComp(args.Destination, out var dest)) { @@ -157,7 +160,7 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem /// private void OnConsoleUIClose(EntityUid uid, ShuttleConsoleComponent component, BoundUIClosedEvent args) { - if ((ShuttleConsoleUiKey) args.UiKey != ShuttleConsoleUiKey.Key || + if ((ShuttleConsoleUiKey)args.UiKey != ShuttleConsoleUiKey.Key || args.Session.AttachedEntity is not { } user) { return; @@ -172,13 +175,15 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem RemovePilot(user); } - private void OnConsoleUIOpenAttempt(EntityUid uid, ShuttleConsoleComponent component, ActivatableUIOpenAttemptEvent args) + private void OnConsoleUIOpenAttempt(EntityUid uid, ShuttleConsoleComponent component, + ActivatableUIOpenAttemptEvent args) { if (!TryPilot(args.User, uid)) args.Cancel(); } - private void OnConsoleAnchorChange(EntityUid uid, ShuttleConsoleComponent component, ref AnchorStateChangedEvent args) + private void OnConsoleAnchorChange(EntityUid uid, ShuttleConsoleComponent component, + ref AnchorStateChangedEvent args) { UpdateState(uid); } @@ -398,10 +403,7 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem return; } - if (TryComp(entity, out var eye)) - { - eye.Zoom = component.Zoom; - } + _eyeSystem.SetZoom(entity, component.Zoom, ignoreLimits:true); component.SubscribedPilots.Add(pilotComponent); @@ -422,11 +424,7 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem pilotComponent.Console = null; pilotComponent.Position = null; - - if (TryComp(pilotUid, out var eye)) - { - eye.Zoom = new(1.0f, 1.0f); - } + _eyeSystem.ResetZoom(pilotUid); if (!helmsman.SubscribedPilots.Remove(pilotComponent)) return; diff --git a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs index 9c749695a9..ab3a1e79a9 100644 --- a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs +++ b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs @@ -6,6 +6,7 @@ using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Players; using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic; namespace Content.Shared.Movement.Systems; @@ -16,12 +17,9 @@ public abstract class SharedContentEyeSystem : EntitySystem { [Dependency] private readonly ISharedAdminManager _admin = default!; - private const float ZoomMod = 1.2f; - private const byte ZoomMultiple = 10; - - protected static readonly Vector2 MinZoom = new(MathF.Pow(ZoomMod, -ZoomMultiple), MathF.Pow(ZoomMod, -ZoomMultiple)); - - protected ISawmill Sawmill = Logger.GetSawmill("ceye"); + public const float ZoomMod = 1.5f; + public static readonly Vector2 DefaultZoom = Vector2.One; + public static readonly Vector2 MinZoom = DefaultZoom * (float)Math.Pow(ZoomMod, -3); public override void Initialize() { @@ -31,22 +29,60 @@ public abstract class SharedContentEyeSystem : EntitySystem SubscribeAllEvent(OnRequestFov); CommandBinds.Builder - .Bind(ContentKeyFunctions.ZoomIn, new ScrollInputCmdHandler(true, this)) - .Bind(ContentKeyFunctions.ZoomOut, new ScrollInputCmdHandler(false, this)) - .Bind(ContentKeyFunctions.ResetZoom, new ResetZoomInputCmdHandler(this)) + .Bind(ContentKeyFunctions.ZoomIn, InputCmdHandler.FromDelegate(ZoomIn, handle:false)) + .Bind(ContentKeyFunctions.ZoomOut, InputCmdHandler.FromDelegate(ZoomOut, handle:false)) + .Bind(ContentKeyFunctions.ResetZoom, InputCmdHandler.FromDelegate(ResetZoom, handle:false)) .Register(); - Sawmill.Level = LogLevel.Info; + Log.Level = LogLevel.Info; UpdatesOutsidePrediction = true; } + public override void Shutdown() + { + base.Shutdown(); + CommandBinds.Unregister(); + } + + private void ResetZoom(ICommonSession? session) + { + if (TryComp(session?.AttachedEntity, out ContentEyeComponent? eye)) + ResetZoom(session.AttachedEntity.Value, eye); + } + + private void ZoomOut(ICommonSession? session) + { + if (TryComp(session?.AttachedEntity, out ContentEyeComponent? eye)) + SetZoom(session.AttachedEntity.Value, eye.TargetZoom * ZoomMod, eye: eye); + } + + private void ZoomIn(ICommonSession? session) + { + if (TryComp(session?.AttachedEntity, out ContentEyeComponent? eye)) + SetZoom(session.AttachedEntity.Value, eye.TargetZoom / ZoomMod, eye: eye); + } + + private Vector2 Clamp(Vector2 zoom, ContentEyeComponent component) + { + return Vector2.Clamp(zoom, MinZoom, component.MaxZoom); + } + + /// + /// Sets the target zoom, optionally ignoring normal zoom limits. + /// + public void SetZoom(EntityUid uid, Vector2 zoom, bool ignoreLimits = false, ContentEyeComponent? eye = null) + { + if (!Resolve(uid, ref eye, false)) + return; + + eye.TargetZoom = ignoreLimits ? zoom : Clamp(zoom, eye); + Dirty(eye); + } + private void OnContentZoomRequest(RequestTargetZoomEvent msg, EntitySessionEventArgs args) { - if (!TryComp(args.SenderSession.AttachedEntity, out var content)) - return; - - content.TargetZoom = msg.TargetZoom; - Dirty(content); + if (TryComp(args.SenderSession.AttachedEntity, out var content)) + SetZoom(args.SenderSession.AttachedEntity.Value, msg.TargetZoom, eye: content); } private void OnRequestFov(RequestFovEvent msg, EntitySessionEventArgs args) @@ -64,12 +100,6 @@ public abstract class SharedContentEyeSystem : EntitySystem } } - public override void Shutdown() - { - base.Shutdown(); - CommandBinds.Unregister(); - } - private void OnContentEyeStartup(EntityUid uid, ContentEyeComponent component, ComponentStartup args) { if (!TryComp(uid, out var eyeComp)) @@ -83,7 +113,7 @@ public abstract class SharedContentEyeSystem : EntitySystem { var diff = content.TargetZoom - eye.Zoom; - if (diff.LengthSquared < 0.0000001f) + if (diff.LengthSquared < 0.00001f) { eye.Zoom = content.TargetZoom; Dirty(eye); @@ -96,106 +126,19 @@ public abstract class SharedContentEyeSystem : EntitySystem Dirty(eye); } - private bool CanZoom(EntityUid uid, ContentEyeComponent? component = null) + public void ResetZoom(EntityUid uid, ContentEyeComponent? component = null) { - return Resolve(uid, ref component, false); - } - - private void ResetZoom(EntityUid uid, ContentEyeComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - if (component.TargetZoom.Equals(Vector2.One)) - return; - - component.TargetZoom = Vector2.One; - Dirty(component); + SetZoom(uid, DefaultZoom, eye: component); } public void SetMaxZoom(EntityUid uid, Vector2 value, ContentEyeComponent? component = null) - { - if (Resolve(uid, ref component)) - component.MaxZoom = value; - } - - private void Zoom(EntityUid uid, bool zoomIn, ContentEyeComponent? component = null) { if (!Resolve(uid, ref component)) return; - var actual = component.TargetZoom; - - if (zoomIn) - { - actual /= ZoomMod; - } - else - { - actual *= ZoomMod; - } - - actual = Vector2.ComponentMax(MinZoom, actual); - actual = Vector2.ComponentMin(component.MaxZoom, actual); - - if (actual.Equals(component.TargetZoom)) - return; - - component.TargetZoom = actual; + component.MaxZoom = value; + component.TargetZoom = Clamp(component.TargetZoom, component); Dirty(component); - Sawmill.Debug($"Set target zoom to {actual}"); - } - - private sealed class ResetZoomInputCmdHandler : InputCmdHandler - { - private readonly SharedContentEyeSystem _system; - - public ResetZoomInputCmdHandler(SharedContentEyeSystem system) - { - _system = system; - } - - public override bool HandleCmdMessage(ICommonSession? session, InputCmdMessage message) - { - ContentEyeComponent? component = null; - - if (message is not FullInputCmdMessage full || session?.AttachedEntity == null || - full.State != BoundKeyState.Down || - !_system.CanZoom(session.AttachedEntity.Value, component)) - { - return false; - } - - _system.ResetZoom(session.AttachedEntity.Value, component); - return false; - } - } - - private sealed class ScrollInputCmdHandler : InputCmdHandler - { - private readonly bool _zoomIn; - private readonly SharedContentEyeSystem _system; - - public ScrollInputCmdHandler(bool zoomIn, SharedContentEyeSystem system) - { - _zoomIn = zoomIn; - _system = system; - } - - public override bool HandleCmdMessage(ICommonSession? session, InputCmdMessage message) - { - ContentEyeComponent? component = null; - - if (message is not FullInputCmdMessage full || session?.AttachedEntity == null || - full.State != BoundKeyState.Down || - !_system.CanZoom(session.AttachedEntity.Value, component)) - { - return false; - } - - _system.Zoom(session.AttachedEntity.Value, _zoomIn, component); - return false; - } } /// diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index 1d8ba8dc8c..ead6519761 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -44,6 +44,8 @@ - type: Actions - type: Eye drawFov: false + - type: ContentEye + maxZoom: 1.2, 1.2 - type: DoAfter - type: Alerts - type: NameIdentifier diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 7392202ae6..e55c7ba5eb 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -300,6 +300,7 @@ - type: MobPrice price: 1500 # Kidnapping a living person and selling them for cred is a good move. deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. + - type: ContentEye - type: entity save: false