From bd28f7f0dd3273eb80101aeb8d64bdf779198e8b Mon Sep 17 00:00:00 2001
From: SlamBamActionman <83650252+slambamactionman@users.noreply.github.com>
Date: Tue, 28 Jan 2025 02:20:45 +0300
Subject: [PATCH] Add conditional camera offset based on cursor - Hristov
Rework, Part 1 (#31626)
(cherry picked from commit 5c782d30283d5e3661e1ce6ebc6d972f12671c41)
---
Content.Client/Input/ContentContexts.cs | 2 +-
.../Components/EyeCursorOffsetComponent.cs | 19 +++
.../Movement/Systems/ContentEyeSystem.cs | 11 ++
.../Movement/Systems/EyeCursorOffsetSystem.cs | 127 +++++++++++++++++
.../Options/UI/Tabs/KeyRebindTab.xaml.cs | 55 +++++++-
Content.Client/Telescope/TelescopeSystem.cs | 128 ------------------
Content.Client/Wieldable/WieldableSystem.cs | 49 +++++++
.../Components/EyeCursorOffsetComponent.cs | 12 ++
Content.Server/Telescope/TelescopeSystem.cs | 5 -
Content.Server/Wieldable/WieldableSystem.cs | 45 ++++++
.../Components/ImmersiveAspectComponent.cs | 6 -
.../GameTicking/Aspects/ImmersiveAspect.cs | 16 +--
Content.Shared/CCVar/CCVars.LayingDown.cs | 3 -
Content.Shared/Camera/GetEyeOffsetEvent.cs | 13 ++
Content.Shared/Camera/GetEyePvsScaleEvent.cs | 33 +++++
.../Camera/SharedCameraRecoilSystem.cs | 8 +-
.../EntitySystems/SharedHandsSystem.Relay.cs | 3 +
Content.Shared/Input/ContentKeyFunctions.cs | 2 +-
.../CursorOffsetRequiresWieldComponent.cs | 13 ++
.../Components/EyeCursorOffsetComponent.cs | 32 +++++
.../Systems/SharedContentEyeSystem.cs | 22 ++-
.../Telescope/SharedTelescopeSystem.cs | 110 ---------------
.../Telescope/TelescopeComponent.cs | 16 ---
.../Components/MeleeRequiresWieldComponent.cs | 2 +-
.../Components/GunRequiresWieldComponent.cs | 2 +-
.../Components/GunWieldBonusComponent.cs | 2 +-
.../IncreaseDamageOnWieldComponent.cs | 2 +-
.../Components/WieldableComponent.cs | 2 +-
...ableSystem.cs => SharedWieldableSystem.cs} | 5 +-
.../FoldingWeapon/FoldingWeaponSystem.cs | 2 +-
.../Weapons/Wielding/UnwieldOnShootSystem.cs | 2 +-
Content.Shared/_White/CCVar/WhiteCVars.Eye.cs | 9 ++
.../_white/escape-menu/ui/options-menu.ftl | 2 +
.../en-US/escape-menu/ui/options-menu.ftl | 2 -
.../_white/escape-menu/ui/options-menu.ftl | 2 +
.../ru-RU/escape-menu/ui/options-menu.ftl | 6 +-
.../Objects/Weapons/Guns/Snipers/snipers.yml | 13 +-
.../Weapons/Guns/Turrets/ship_turrets.yml | 3 +-
Resources/keybinds.yml | 2 +
39 files changed, 473 insertions(+), 315 deletions(-)
create mode 100644 Content.Client/Movement/Components/EyeCursorOffsetComponent.cs
create mode 100644 Content.Client/Movement/Systems/EyeCursorOffsetSystem.cs
delete mode 100644 Content.Client/Telescope/TelescopeSystem.cs
create mode 100644 Content.Client/Wieldable/WieldableSystem.cs
create mode 100644 Content.Server/Movement/Components/EyeCursorOffsetComponent.cs
delete mode 100644 Content.Server/Telescope/TelescopeSystem.cs
create mode 100644 Content.Server/Wieldable/WieldableSystem.cs
create mode 100644 Content.Shared/Camera/GetEyePvsScaleEvent.cs
create mode 100644 Content.Shared/Movement/Components/CursorOffsetRequiresWieldComponent.cs
create mode 100644 Content.Shared/Movement/Components/EyeCursorOffsetComponent.cs
delete mode 100644 Content.Shared/Telescope/SharedTelescopeSystem.cs
delete mode 100644 Content.Shared/Telescope/TelescopeComponent.cs
rename Content.Shared/Wieldable/{WieldableSystem.cs => SharedWieldableSystem.cs} (99%)
create mode 100644 Content.Shared/_White/CCVar/WhiteCVars.Eye.cs
create mode 100644 Resources/Locale/en-US/_white/escape-menu/ui/options-menu.ftl
create mode 100644 Resources/Locale/ru-RU/_white/escape-menu/ui/options-menu.ftl
diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs
index bc4a1da940..1fef54ddce 100644
--- a/Content.Client/Input/ContentContexts.cs
+++ b/Content.Client/Input/ContentContexts.cs
@@ -89,7 +89,7 @@ namespace Content.Client.Input
human.AddFunction(ContentKeyFunctions.Arcade1);
human.AddFunction(ContentKeyFunctions.Arcade2);
human.AddFunction(ContentKeyFunctions.Arcade3);
- human.AddFunction(ContentKeyFunctions.LookUp);
+ human.AddFunction(ContentKeyFunctions.LookUp); // WD EDIT
// Shitmed Change Start - TODO: Add groin targeting.
human.AddFunction(ContentKeyFunctions.TargetHead);
human.AddFunction(ContentKeyFunctions.TargetTorso);
diff --git a/Content.Client/Movement/Components/EyeCursorOffsetComponent.cs b/Content.Client/Movement/Components/EyeCursorOffsetComponent.cs
new file mode 100644
index 0000000000..5ed1bf4a6c
--- /dev/null
+++ b/Content.Client/Movement/Components/EyeCursorOffsetComponent.cs
@@ -0,0 +1,19 @@
+using System.Numerics;
+using Content.Client.Movement.Systems;
+using Content.Shared.Movement.Components;
+
+namespace Content.Client.Movement.Components;
+
+[RegisterComponent]
+public sealed partial class EyeCursorOffsetComponent : SharedEyeCursorOffsetComponent
+{
+ ///
+ /// The location the offset will attempt to pan towards; based on the cursor's position in the game window.
+ ///
+ public Vector2 TargetPosition = Vector2.Zero;
+
+ ///
+ /// The current positional offset being applied. Used to enable gradual panning.
+ ///
+ public Vector2 CurrentPosition = Vector2.Zero;
+}
diff --git a/Content.Client/Movement/Systems/ContentEyeSystem.cs b/Content.Client/Movement/Systems/ContentEyeSystem.cs
index 9fbd4b5c37..518a4a1bd4 100644
--- a/Content.Client/Movement/Systems/ContentEyeSystem.cs
+++ b/Content.Client/Movement/Systems/ContentEyeSystem.cs
@@ -1,6 +1,7 @@
using System.Numerics;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
+using Robust.Client.GameObjects;
using Robust.Client.Player;
namespace Content.Client.Movement.Systems;
@@ -52,4 +53,14 @@ public sealed class ContentEyeSystem : SharedContentEyeSystem
{
RaisePredictiveEvent(new RequestEyeEvent(drawFov, drawLight));
}
+
+ public override void FrameUpdate(float frameTime)
+ {
+ base.FrameUpdate(frameTime);
+ var eyeEntities = AllEntityQuery();
+ while (eyeEntities.MoveNext(out var entity, out ContentEyeComponent? contentComponent, out EyeComponent? eyeComponent))
+ {
+ UpdateEyeOffset((entity, eyeComponent));
+ }
+ }
}
diff --git a/Content.Client/Movement/Systems/EyeCursorOffsetSystem.cs b/Content.Client/Movement/Systems/EyeCursorOffsetSystem.cs
new file mode 100644
index 0000000000..a8f78a9093
--- /dev/null
+++ b/Content.Client/Movement/Systems/EyeCursorOffsetSystem.cs
@@ -0,0 +1,127 @@
+using System.Numerics;
+using Content.Client.Movement.Components;
+using Content.Shared.Camera;
+using Content.Shared.Input;
+using Content.Shared.Inventory;
+using Content.Shared.Movement.Systems;
+using Robust.Client.Graphics;
+using Robust.Client.Input;
+using Robust.Shared.Map;
+using Robust.Client.Player;
+using Robust.Shared.Input;
+using Robust.Shared.Input.Binding;
+using Robust.Shared.Player;
+
+
+namespace Content.Client.Movement.Systems;
+
+public partial class EyeCursorOffsetSystem : EntitySystem
+{
+ [Dependency] private readonly IEyeManager _eyeManager = default!;
+ [Dependency] private readonly IInputManager _inputManager = default!;
+ [Dependency] private readonly IPlayerManager _player = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly SharedContentEyeSystem _contentEye = default!;
+ [Dependency] private readonly IMapManager _mapManager = default!;
+ [Dependency] private readonly IClyde _clyde = default!;
+
+ // This value is here to make sure the user doesn't have to move their mouse
+ // all the way out to the edge of the screen to get the full offset.
+ static private float _edgeOffset = 0.9f;
+
+ private static bool _toggled; // WD EDIT
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnGetEyeOffsetEvent);
+
+ // WD EDIT START
+ CommandBinds.Builder
+ .Bind(ContentKeyFunctions.LookUp, new EyeOffsetInputCmdHandler())
+ .Register();
+ // WD EDIT END
+ }
+
+ private void OnGetEyeOffsetEvent(EntityUid uid, EyeCursorOffsetComponent component, ref GetEyeOffsetEvent args)
+ {
+ var offset = OffsetAfterMouse(uid, component);
+ if (offset == null)
+ return;
+
+ args.Offset += offset.Value;
+ }
+
+ public Vector2? OffsetAfterMouse(EntityUid uid, EyeCursorOffsetComponent? component)
+ {
+ // WD EDIT START
+ if (!_toggled)
+ return null;
+ // WD EDIT END
+
+ var localPlayer = _player.LocalPlayer?.ControlledEntity;
+ var mousePos = _inputManager.MouseScreenPosition;
+ var screenSize = _clyde.MainWindow.Size;
+ var minValue = MathF.Min(screenSize.X / 2, screenSize.Y / 2) * _edgeOffset;
+
+ var mouseNormalizedPos = new Vector2(-(mousePos.X - screenSize.X / 2) / minValue, (mousePos.Y - screenSize.Y / 2) / minValue); // X needs to be inverted here for some reason, otherwise it ends up flipped.
+
+ if (localPlayer == null)
+ return null;
+
+ var playerPos = _transform.GetWorldPosition(localPlayer.Value);
+
+ if (component == null)
+ {
+ component = EnsureComp(uid);
+ }
+
+ // Doesn't move the offset if the mouse has left the game window!
+ if (mousePos.Window != WindowId.Invalid)
+ {
+ // The offset must account for the in-world rotation.
+ var eyeRotation = _eyeManager.CurrentEye.Rotation;
+ var mouseActualRelativePos = Vector2.Transform(mouseNormalizedPos, System.Numerics.Quaternion.CreateFromAxisAngle(-System.Numerics.Vector3.UnitZ, (float)(eyeRotation.Opposite().Theta))); // I don't know, it just works.
+
+ // Caps the offset into a circle around the player.
+ mouseActualRelativePos *= component.MaxOffset;
+ if (mouseActualRelativePos.Length() > component.MaxOffset)
+ {
+ mouseActualRelativePos = mouseActualRelativePos.Normalized() * component.MaxOffset;
+ }
+
+ component.TargetPosition = mouseActualRelativePos;
+
+ //Makes the view not jump immediately when moving the cursor fast.
+ if (component.CurrentPosition != component.TargetPosition)
+ {
+ Vector2 vectorOffset = component.TargetPosition - component.CurrentPosition;
+ if (vectorOffset.Length() > component.OffsetSpeed)
+ {
+ vectorOffset = vectorOffset.Normalized() * component.OffsetSpeed;
+ }
+ component.CurrentPosition += vectorOffset;
+ }
+ }
+ return component.CurrentPosition;
+ }
+
+ // WD EDIT START
+ private sealed class EyeOffsetInputCmdHandler : InputCmdHandler
+ {
+ public override bool HandleCmdMessage(
+ IEntityManager entManager,
+ ICommonSession? session,
+ IFullInputCmdMessage message
+ )
+ {
+ if (session?.AttachedEntity == null)
+ return false;
+
+ _toggled = message.State == BoundKeyState.Down;
+ return false;
+ }
+ }
+ // WD EDIT END
+}
diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
index 50bfe871d1..feecf54859 100644
--- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
+++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
@@ -1,6 +1,6 @@
using System.Numerics;
using Content.Client.Stylesheets;
-using Content.Shared._White;
+using Content.Shared._White.CCVar;
using Content.Shared.CCVar;
using Content.Shared.Input;
using Robust.Client.AutoGenerated;
@@ -57,6 +57,16 @@ namespace Content.Client.Options.UI.Tabs
}
}
+ // WD EDIT START
+ private void InitToggleLookUp()
+ {
+ if (_cfg.GetCVar(WhiteCVars.ToggleLookUp))
+ ToggleFunctions.Add(ContentKeyFunctions.LookUp);
+ else
+ ToggleFunctions.Remove(ContentKeyFunctions.LookUp);
+ }
+ // WD EDIT END
+
private void HandleToggleWalk(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.ToggleWalk, args.Pressed);
@@ -100,16 +110,51 @@ namespace Content.Client.Options.UI.Tabs
_deferCommands.Add(_inputManager.SaveToUserData);
}
- private void HandleHoldLookUp(BaseButton.ButtonToggledEventArgs args)
+ // WD EDIT START
+ private void HandleToggleLookUp(BaseButton.ButtonToggledEventArgs args)
{
- _cfg.SetCVar(CCVars.HoldLookUp, args.Pressed);
+ _cfg.SetCVar(WhiteCVars.ToggleLookUp, args.Pressed);
_cfg.SaveToFile();
+ InitToggleLookUp();
+
+ if (!_keyControls.TryGetValue(ContentKeyFunctions.LookUp, out var keyControl))
+ return;
+
+ var bindingType = args.Pressed ? KeyBindingType.Toggle : KeyBindingType.State;
+ for (var i = 0; i <= 1; i++)
+ {
+ var binding = (i == 0 ? keyControl.BindButton1 : keyControl.BindButton2).Binding;
+ if (binding == null)
+ continue;
+
+ var registration = new KeyBindingRegistration
+ {
+ Function = ContentKeyFunctions.LookUp,
+ BaseKey = binding.BaseKey,
+ Mod1 = binding.Mod1,
+ Mod2 = binding.Mod2,
+ Mod3 = binding.Mod3,
+ Priority = binding.Priority,
+ Type = bindingType,
+ CanFocus = binding.CanFocus,
+ CanRepeat = binding.CanRepeat,
+ };
+
+ _deferCommands.Add(() =>
+ {
+ _inputManager.RemoveBinding(binding);
+ _inputManager.RegisterBinding(registration);
+ });
+ }
+
+ _deferCommands.Add(_inputManager.SaveToUserData);
}
+ // WD EDIT END
private void HandleDefaultWalk(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.DefaultWalk, args.Pressed);
- _cfg.SaveToFile();
+ _cfg.SaveToFile();
}
private void HandleStaticStorageUI(BaseButton.ButtonToggledEventArgs args)
@@ -252,7 +297,7 @@ namespace Content.Client.Options.UI.Tabs
AddButton(ContentKeyFunctions.ToggleCombatMode); // WD EDIT
AddButton(ContentKeyFunctions.LookUp);
AddCheckBox("ui-options-function-auto-get-up", _cfg.GetCVar(CCVars.AutoGetUp), HandleToggleAutoGetUp);
- AddCheckBox("ui-options-function-hold-look-up", _cfg.GetCVar(CCVars.HoldLookUp), HandleHoldLookUp);
+ AddCheckBox("ui-options-function-toggle-look-up", _cfg.GetCVar(WhiteCVars.ToggleLookUp), HandleToggleLookUp); // WD EDIT
AddHeader("ui-options-header-interaction-adv");
AddButton(ContentKeyFunctions.SmartEquipBackpack);
diff --git a/Content.Client/Telescope/TelescopeSystem.cs b/Content.Client/Telescope/TelescopeSystem.cs
deleted file mode 100644
index ac2270aa97..0000000000
--- a/Content.Client/Telescope/TelescopeSystem.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-using System.Numerics;
-using Content.Client.Viewport;
-using Content.Shared.CCVar;
-using Content.Shared.Telescope;
-using Content.Shared.Input;
-using Robust.Client.GameObjects;
-using Robust.Client.Graphics;
-using Robust.Client.Input;
-using Robust.Client.Player;
-using Robust.Client.UserInterface;
-using Robust.Shared.Configuration;
-using Robust.Shared.Input;
-using Robust.Shared.Input.Binding;
-using Robust.Shared.Timing;
-
-namespace Content.Client.Telescope;
-
-public sealed class TelescopeSystem : SharedTelescopeSystem
-{
- [Dependency] private readonly InputSystem _inputSystem = default!;
- [Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly IPlayerManager _player = default!;
- [Dependency] private readonly IInputManager _input = default!;
- [Dependency] private readonly IEyeManager _eyeManager = default!;
- [Dependency] private readonly IUserInterfaceManager _uiManager = default!;
- [Dependency] private readonly IConfigurationManager _cfg = default!;
-
- private ScalingViewport? _viewport;
- private bool _holdLookUp;
- private bool _toggled;
-
- public override void Initialize()
- {
- base.Initialize();
-
- _cfg.OnValueChanged(CCVars.HoldLookUp,
- val =>
- {
- var input = val ? null : InputCmdHandler.FromDelegate(_ => _toggled = !_toggled);
- _input.SetInputCommand(ContentKeyFunctions.LookUp, input);
- _holdLookUp = val;
- _toggled = false;
- },
- true);
- }
-
- public override void FrameUpdate(float frameTime)
- {
- base.FrameUpdate(frameTime);
-
- if (_timing.ApplyingState
- || !_timing.IsFirstTimePredicted
- || !_input.MouseScreenPosition.IsValid)
- return;
-
- var player = _player.LocalEntity;
-
- var telescope = GetRightTelescope(player);
-
- if (telescope == null)
- {
- _toggled = false;
- return;
- }
-
- if (!TryComp(player, out var eye))
- return;
-
- var offset = Vector2.Zero;
-
- if (_holdLookUp)
- {
- if (_inputSystem.CmdStates.GetState(ContentKeyFunctions.LookUp) != BoundKeyState.Down)
- {
- RaiseEvent(offset);
- return;
- }
- }
- else if (!_toggled)
- {
- RaiseEvent(offset);
- return;
- }
-
- var mousePos = _input.MouseScreenPosition;
-
- if (_uiManager.MouseGetControl(mousePos) as ScalingViewport is { } viewport)
- _viewport = viewport;
-
- if (_viewport == null)
- return;
-
- var centerPos = _eyeManager.WorldToScreen(eye.Eye.Position.Position + eye.Offset);
-
- var diff = mousePos.Position - centerPos;
- var len = diff.Length();
-
- var size = _viewport.PixelSize;
-
- var maxLength = Math.Min(size.X, size.Y) * 0.4f;
- var minLength = maxLength * 0.2f;
-
- if (len > maxLength)
- {
- diff *= maxLength / len;
- len = maxLength;
- }
-
- var divisor = maxLength * telescope.Divisor;
-
- if (len > minLength)
- {
- diff -= diff * minLength / len;
- offset = new Vector2(diff.X / divisor, -diff.Y / divisor);
- offset = new Angle(-eye.Rotation.Theta).RotateVec(offset);
- }
-
- RaiseEvent(offset);
- }
-
- private void RaiseEvent(Vector2 offset)
- {
- RaisePredictiveEvent(new EyeOffsetChangedEvent
- {
- Offset = offset
- });
- }
-}
diff --git a/Content.Client/Wieldable/WieldableSystem.cs b/Content.Client/Wieldable/WieldableSystem.cs
new file mode 100644
index 0000000000..2de837923c
--- /dev/null
+++ b/Content.Client/Wieldable/WieldableSystem.cs
@@ -0,0 +1,49 @@
+using System.Numerics;
+using Content.Client.Movement.Components;
+using Content.Client.Movement.Systems;
+using Content.Shared.Camera;
+using Content.Shared.Hands;
+using Content.Shared.Movement.Components;
+using Content.Shared.Wieldable;
+using Content.Shared.Wieldable.Components;
+using Robust.Client.Timing;
+
+namespace Content.Client.Wieldable;
+
+public sealed class WieldableSystem : SharedWieldableSystem
+{
+ [Dependency] private readonly EyeCursorOffsetSystem _eyeOffset = default!;
+ [Dependency] private readonly IClientGameTiming _gameTiming = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnEyeOffsetUnwielded);
+ SubscribeLocalEvent>(OnGetEyeOffset);
+ }
+
+ public void OnEyeOffsetUnwielded(Entity entity, ref ItemUnwieldedEvent args)
+ {
+ if (!TryComp(entity.Owner, out EyeCursorOffsetComponent? cursorOffsetComp))
+ return;
+
+ if (_gameTiming.IsFirstTimePredicted)
+ cursorOffsetComp.CurrentPosition = Vector2.Zero;
+ }
+
+ public void OnGetEyeOffset(Entity entity, ref HeldRelayedEvent args)
+ {
+ if (!TryComp(entity.Owner, out WieldableComponent? wieldableComp))
+ return;
+
+ if (!wieldableComp.Wielded)
+ return;
+
+ var offset = _eyeOffset.OffsetAfterMouse(entity.Owner, null);
+ if (offset == null)
+ return;
+
+ args.Args.Offset += offset.Value;
+ }
+}
diff --git a/Content.Server/Movement/Components/EyeCursorOffsetComponent.cs b/Content.Server/Movement/Components/EyeCursorOffsetComponent.cs
new file mode 100644
index 0000000000..b3809fe794
--- /dev/null
+++ b/Content.Server/Movement/Components/EyeCursorOffsetComponent.cs
@@ -0,0 +1,12 @@
+using System.Numerics;
+using Content.Shared.Movement.Components;
+using Content.Shared.Movement.Systems;
+using Robust.Shared.GameStates;
+
+namespace Content.Server.Movement.Components;
+
+[RegisterComponent]
+public sealed partial class EyeCursorOffsetComponent : SharedEyeCursorOffsetComponent
+{
+
+}
diff --git a/Content.Server/Telescope/TelescopeSystem.cs b/Content.Server/Telescope/TelescopeSystem.cs
deleted file mode 100644
index 0e53cc15a2..0000000000
--- a/Content.Server/Telescope/TelescopeSystem.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-using Content.Shared.Telescope;
-
-namespace Content.Server.Telescope;
-
-public sealed class TelescopeSystem : SharedTelescopeSystem;
diff --git a/Content.Server/Wieldable/WieldableSystem.cs b/Content.Server/Wieldable/WieldableSystem.cs
new file mode 100644
index 0000000000..35f75276a8
--- /dev/null
+++ b/Content.Server/Wieldable/WieldableSystem.cs
@@ -0,0 +1,45 @@
+using Content.Server.Movement.Components;
+using Content.Server.Movement.Systems;
+using Content.Shared.Camera;
+using Content.Shared.Hands;
+using Content.Shared.Movement.Components;
+using Content.Shared.Wieldable;
+using Content.Shared.Wieldable.Components;
+
+namespace Content.Server.Wieldable;
+
+public sealed class WieldableSystem : SharedWieldableSystem
+{
+ [Dependency] private readonly ContentEyeSystem _eye = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnEyeOffsetUnwielded);
+ SubscribeLocalEvent(OnEyeOffsetWielded);
+ SubscribeLocalEvent>(OnGetEyePvsScale);
+ }
+
+ private void OnEyeOffsetUnwielded(Entity entity, ref ItemUnwieldedEvent args)
+ {
+ _eye.UpdatePvsScale(args.User);
+ }
+
+ private void OnEyeOffsetWielded(Entity entity, ref ItemWieldedEvent args)
+ {
+ _eye.UpdatePvsScale(args.User);
+ }
+
+ private void OnGetEyePvsScale(Entity entity,
+ ref HeldRelayedEvent args)
+ {
+ if (!TryComp(entity, out EyeCursorOffsetComponent? eyeCursorOffset) || !TryComp(entity.Owner, out WieldableComponent? wieldableComp))
+ return;
+
+ if (!wieldableComp.Wielded)
+ return;
+
+ args.Args.Scale += eyeCursorOffset.PvsIncrease;
+ }
+}
diff --git a/Content.Server/_White/GameTicking/Aspects/Components/ImmersiveAspectComponent.cs b/Content.Server/_White/GameTicking/Aspects/Components/ImmersiveAspectComponent.cs
index e6c563e3b4..759440b095 100644
--- a/Content.Server/_White/GameTicking/Aspects/Components/ImmersiveAspectComponent.cs
+++ b/Content.Server/_White/GameTicking/Aspects/Components/ImmersiveAspectComponent.cs
@@ -5,10 +5,4 @@ public sealed partial class ImmersiveAspectComponent : Component
{
[DataField]
public float EyeModifier = 0.6f;
-
- [DataField]
- public float TelescopeDivisor = 0.15f;
-
- [DataField]
- public float TelescopeLerpAmount = 0.07f;
}
diff --git a/Content.Server/_White/GameTicking/Aspects/ImmersiveAspect.cs b/Content.Server/_White/GameTicking/Aspects/ImmersiveAspect.cs
index 98bf1a9df5..de2cb34a38 100644
--- a/Content.Server/_White/GameTicking/Aspects/ImmersiveAspect.cs
+++ b/Content.Server/_White/GameTicking/Aspects/ImmersiveAspect.cs
@@ -1,17 +1,16 @@
using System.Numerics;
using Content.Server._White.GameTicking.Aspects.Components;
+using Content.Server.Movement.Components;
using Content.Shared.GameTicking;
using Content.Shared.GameTicking.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
-using Content.Shared.Telescope;
namespace Content.Server._White.GameTicking.Aspects;
public sealed class ImmersiveAspect : AspectSystem
{
[Dependency] private readonly SharedContentEyeSystem _eye = default!;
- [Dependency] private readonly SharedTelescopeSystem _telescope = default!;
public override void Initialize()
{
@@ -39,7 +38,7 @@ public sealed class ImmersiveAspect : AspectSystem
while (query.MoveNext(out var entity, out _))
{
SetEyeZoom(entity, component.EyeModifier);
- AddTelescope(entity, component.TelescopeDivisor, component.TelescopeLerpAmount);
+ EnsureComp(entity);
}
}
@@ -49,13 +48,6 @@ public sealed class ImmersiveAspect : AspectSystem
_eye.SetZoom(human, new Vector2(modifier));
}
- private void AddTelescope(EntityUid human, float divisor, float lerpAmount)
- {
- var telescope = EnsureComp(human);
-
- _telescope.SetParameters((human, telescope), divisor, lerpAmount);
- }
-
private void OnPlayerSpawn(PlayerSpawnCompleteEvent ev)
{
if (!HasComp(ev.Mob))
@@ -68,7 +60,7 @@ public sealed class ImmersiveAspect : AspectSystem
continue;
SetEyeZoom(ev.Mob, immersiveAspect.EyeModifier);
- AddTelescope(ev.Mob, immersiveAspect.TelescopeDivisor, immersiveAspect.TelescopeLerpAmount);
+ EnsureComp(ev.Mob);
}
}
@@ -87,7 +79,7 @@ public sealed class ImmersiveAspect : AspectSystem
{
SetEyeZoom(entity, 1f);
- RemComp(entity);
+ RemComp(entity);
}
}
}
diff --git a/Content.Shared/CCVar/CCVars.LayingDown.cs b/Content.Shared/CCVar/CCVars.LayingDown.cs
index ee8c4a3037..a078d6a3d2 100644
--- a/Content.Shared/CCVar/CCVars.LayingDown.cs
+++ b/Content.Shared/CCVar/CCVars.LayingDown.cs
@@ -7,9 +7,6 @@ public sealed partial class CCVars
public static readonly CVarDef AutoGetUp =
CVarDef.Create("rest.auto_get_up", true, CVar.CLIENT | CVar.ARCHIVE | CVar.REPLICATED);
- public static readonly CVarDef HoldLookUp =
- CVarDef.Create("rest.hold_look_up", false, CVar.CLIENT | CVar.ARCHIVE);
-
///
/// When true, players can choose to crawl under tables while laying down, using the designated keybind.
///
diff --git a/Content.Shared/Camera/GetEyeOffsetEvent.cs b/Content.Shared/Camera/GetEyeOffsetEvent.cs
index de9c7c9e17..0e3c00110a 100644
--- a/Content.Shared/Camera/GetEyeOffsetEvent.cs
+++ b/Content.Shared/Camera/GetEyeOffsetEvent.cs
@@ -1,4 +1,5 @@
using System.Numerics;
+using Content.Shared.Inventory;
using Content.Shared.Movement.Systems;
namespace Content.Shared.Camera;
@@ -17,3 +18,15 @@ namespace Content.Shared.Camera;
///
[ByRefEvent]
public record struct GetEyeOffsetEvent(Vector2 Offset);
+
+///
+/// Raised on any equipped and in-hand items that may modify the eye offset.
+/// Pockets and suitstorage are excluded.
+///
+[ByRefEvent]
+public sealed class GetEyeOffsetRelayedEvent : EntityEventArgs, IInventoryRelayEvent
+{
+ public SlotFlags TargetSlots { get; } = ~(SlotFlags.POCKET & SlotFlags.SUITSTORAGE);
+
+ public Vector2 Offset;
+}
diff --git a/Content.Shared/Camera/GetEyePvsScaleEvent.cs b/Content.Shared/Camera/GetEyePvsScaleEvent.cs
new file mode 100644
index 0000000000..482b755db8
--- /dev/null
+++ b/Content.Shared/Camera/GetEyePvsScaleEvent.cs
@@ -0,0 +1,33 @@
+using System.Numerics;
+using Content.Shared.Inventory;
+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 PVS scale,
+/// so that they do not override each other. Keep in mind that this should be done serverside;
+/// the client may set a new PVS scale, but the server won't provide the data if it isn't done on the server.
+///
+///
+/// The total scale 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 GetEyePvsScaleEvent(float Scale);
+
+///
+/// Raised on any equipped and in-hand items that may modify the eye offset.
+/// Pockets and suitstorage are excluded.
+///
+[ByRefEvent]
+public sealed class GetEyePvsScaleRelayedEvent : EntityEventArgs, IInventoryRelayEvent
+{
+ public SlotFlags TargetSlots { get; } = ~(SlotFlags.POCKET & SlotFlags.SUITSTORAGE);
+
+ public float Scale;
+}
diff --git a/Content.Shared/Camera/SharedCameraRecoilSystem.cs b/Content.Shared/Camera/SharedCameraRecoilSystem.cs
index a2ce0e77e2..a497016c46 100644
--- a/Content.Shared/Camera/SharedCameraRecoilSystem.cs
+++ b/Content.Shared/Camera/SharedCameraRecoilSystem.cs
@@ -1,4 +1,6 @@
using System.Numerics;
+using Content.Shared.Movement.Components;
+using Content.Shared.Movement.Systems;
using JetBrains.Annotations;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
@@ -28,7 +30,7 @@ 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()
@@ -81,9 +83,7 @@ public abstract class SharedCameraRecoilSystem : EntitySystem
continue;
recoil.LastKick = recoil.CurrentKick;
- var ev = new GetEyeOffsetEvent();
- RaiseLocalEvent(uid, ref ev);
- _eye.SetOffset(uid, ev.Offset, eye);
+ _eye.UpdateEyeOffset((uid, eye));
}
}
diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs
index 59f0722867..447b87c66a 100644
--- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs
+++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Relay.cs
@@ -1,4 +1,5 @@
using Content.Shared._White.Move;
+using Content.Shared.Camera;
using Content.Shared.Hands.Components;
using Content.Shared.Movement.Systems;
@@ -8,6 +9,8 @@ public abstract partial class SharedHandsSystem
{
private void InitializeRelay()
{
+ SubscribeLocalEvent(RelayEvent);
+ SubscribeLocalEvent(RelayEvent);
SubscribeLocalEvent(RelayEvent);
SubscribeLocalEvent(RelayEvent);
}
diff --git a/Content.Shared/Input/ContentKeyFunctions.cs b/Content.Shared/Input/ContentKeyFunctions.cs
index c8a82c406d..aa9dba9e8c 100644
--- a/Content.Shared/Input/ContentKeyFunctions.cs
+++ b/Content.Shared/Input/ContentKeyFunctions.cs
@@ -64,7 +64,7 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction ToggleStanding = "ToggleStanding";
public static readonly BoundKeyFunction ToggleCrawlingUnder = "ToggleCrawlingUnder";
public static readonly BoundKeyFunction ToggleCombatMode = "ToggleCombatMode"; // WD EDIT
- public static readonly BoundKeyFunction LookUp = "LookUp";
+ public static readonly BoundKeyFunction LookUp = "LookUp"; // WD EDIT
public static readonly BoundKeyFunction TargetHead = "TargetHead";
public static readonly BoundKeyFunction TargetTorso = "TargetTorso";
public static readonly BoundKeyFunction TargetLeftArm = "TargetLeftArm";
diff --git a/Content.Shared/Movement/Components/CursorOffsetRequiresWieldComponent.cs b/Content.Shared/Movement/Components/CursorOffsetRequiresWieldComponent.cs
new file mode 100644
index 0000000000..3f5a12874b
--- /dev/null
+++ b/Content.Shared/Movement/Components/CursorOffsetRequiresWieldComponent.cs
@@ -0,0 +1,13 @@
+using Content.Shared.Wieldable;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Movement.Components;
+
+///
+/// Indicates that this item requires wielding for the cursor offset effect to be active.
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedWieldableSystem))]
+public sealed partial class CursorOffsetRequiresWieldComponent : Component
+{
+
+}
diff --git a/Content.Shared/Movement/Components/EyeCursorOffsetComponent.cs b/Content.Shared/Movement/Components/EyeCursorOffsetComponent.cs
new file mode 100644
index 0000000000..e0884222f2
--- /dev/null
+++ b/Content.Shared/Movement/Components/EyeCursorOffsetComponent.cs
@@ -0,0 +1,32 @@
+using System.Numerics;
+using Content.Shared.Movement.Systems;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Movement.Components;
+
+///
+/// Displaces SS14 eye data when given to an entity.
+///
+[ComponentProtoName("EyeCursorOffset"), NetworkedComponent]
+public abstract partial class SharedEyeCursorOffsetComponent : Component
+{
+ ///
+ /// The amount the view will be displaced when the cursor is positioned at/beyond the max offset distance.
+ /// Measured in tiles.
+ ///
+ [DataField]
+ public float MaxOffset = 3f;
+
+ ///
+ /// The speed which the camera adjusts to new positions. 0.5f seems like a good value, but can be changed if you want very slow/instant adjustments.
+ ///
+ [DataField]
+ public float OffsetSpeed = 0.5f;
+
+ ///
+ /// The amount the PVS should increase to account for the max offset.
+ /// Should be 1/10 of MaxOffset most of the time.
+ ///
+ [DataField]
+ public float PvsIncrease = 0.3f;
+}
diff --git a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs
index b2c6a45b4d..67e2f5af24 100644
--- a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs
+++ b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs
@@ -161,11 +161,29 @@ public abstract class SharedContentEyeSystem : EntitySystem
Dirty(uid, component);
}
- public void UpdateEyeOffset(Entity eye)
+ public void UpdateEyeOffset(Entity eye)
{
var ev = new GetEyeOffsetEvent();
RaiseLocalEvent(eye, ref ev);
- _eye.SetOffset(eye, ev.Offset, eye);
+
+ var evRelayed = new GetEyeOffsetRelayedEvent();
+ RaiseLocalEvent(eye, ref evRelayed);
+
+ _eye.SetOffset(eye, ev.Offset + evRelayed.Offset, eye);
+ }
+
+ public void UpdatePvsScale(EntityUid uid, ContentEyeComponent? contentEye = null, EyeComponent? eye = null)
+ {
+ if (!Resolve(uid, ref contentEye) || !Resolve(uid, ref eye))
+ return;
+
+ var ev = new GetEyePvsScaleEvent();
+ RaiseLocalEvent(uid, ref ev);
+
+ var evRelayed = new GetEyePvsScaleRelayedEvent();
+ RaiseLocalEvent(uid, ref evRelayed);
+
+ _eye.SetPvsScale((uid, eye), 1 + ev.Scale + evRelayed.Scale);
}
///
diff --git a/Content.Shared/Telescope/SharedTelescopeSystem.cs b/Content.Shared/Telescope/SharedTelescopeSystem.cs
deleted file mode 100644
index 5f9896cc35..0000000000
--- a/Content.Shared/Telescope/SharedTelescopeSystem.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-using System.Numerics;
-using Content.Shared.Camera;
-using Content.Shared.Hands;
-using Content.Shared.Hands.Components;
-using Content.Shared.Item;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Telescope;
-
-public abstract class SharedTelescopeSystem : EntitySystem
-{
- [Dependency] private readonly SharedEyeSystem _eye = default!;
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeAllEvent(OnEyeOffsetChanged);
- SubscribeLocalEvent(OnUnequip);
- SubscribeLocalEvent(OnHandDeselected);
- SubscribeLocalEvent(OnShutdown);
- }
-
- private void OnShutdown(Entity ent, ref ComponentShutdown args)
- {
- if (!TryComp(ent.Comp.LastEntity, out EyeComponent? eye)
- || ent.Comp.LastEntity == ent && TerminatingOrDeleted(ent))
- return;
-
- SetOffset((ent.Comp.LastEntity.Value, eye), Vector2.Zero, ent);
- }
-
- private void OnHandDeselected(Entity ent, ref HandDeselectedEvent args)
- {
- if (!TryComp(args.User, out EyeComponent? eye))
- return;
-
- SetOffset((args.User, eye), Vector2.Zero, ent);
- }
-
- private void OnUnequip(Entity ent, ref GotUnequippedHandEvent args)
- {
- if (!TryComp(args.User, out EyeComponent? eye)
- || !HasComp(ent.Owner))
- return;
-
- SetOffset((args.User, eye), Vector2.Zero, ent);
- }
-
- public TelescopeComponent? GetRightTelescope(EntityUid? ent)
- {
- TelescopeComponent? telescope = null;
-
- if (TryComp(ent, out var hands)
- && hands.ActiveHandEntity.HasValue
- && TryComp(hands.ActiveHandEntity, out var handTelescope))
- telescope = handTelescope;
- else if (TryComp(ent, out var entityTelescope))
- telescope = entityTelescope;
-
- return telescope;
- }
-
- private void OnEyeOffsetChanged(EyeOffsetChangedEvent msg, EntitySessionEventArgs args)
- {
- if (args.SenderSession.AttachedEntity is not { } ent
- || !TryComp(ent, out var eye))
- return;
-
- var telescope = GetRightTelescope(ent);
-
- if (telescope == null)
- return;
-
- var offset = Vector2.Lerp(eye.Offset, msg.Offset, telescope.LerpAmount);
-
- SetOffset((ent, eye), offset, telescope);
- }
-
- private void SetOffset(Entity ent, Vector2 offset, TelescopeComponent telescope)
- {
- telescope.LastEntity = ent;
-
- if (TryComp(ent, out CameraRecoilComponent? recoil))
- {
- recoil.BaseOffset = offset;
- _eye.SetOffset(ent, offset + recoil.CurrentKick, ent);
- }
- else
- {
- _eye.SetOffset(ent, offset, ent);
- }
- }
-
- public void SetParameters(Entity ent, float? divisor = null, float? lerpAmount = null)
- {
- var telescope = ent.Comp;
-
- telescope.Divisor = divisor ?? telescope.Divisor;
- telescope.LerpAmount = lerpAmount ?? telescope.LerpAmount;
-
- Dirty(ent.Owner, telescope);
- }
-}
-
-[Serializable, NetSerializable]
-public sealed class EyeOffsetChangedEvent : EntityEventArgs
-{
- public Vector2 Offset;
-}
diff --git a/Content.Shared/Telescope/TelescopeComponent.cs b/Content.Shared/Telescope/TelescopeComponent.cs
deleted file mode 100644
index 529cc58324..0000000000
--- a/Content.Shared/Telescope/TelescopeComponent.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Telescope;
-
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-public sealed partial class TelescopeComponent : Component
-{
- [DataField, AutoNetworkedField]
- public float Divisor = 0.1f;
-
- [DataField, AutoNetworkedField]
- public float LerpAmount = 0.1f;
-
- [ViewVariables]
- public EntityUid? LastEntity;
-}
diff --git a/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs b/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs
index b92431be19..d62b482c06 100644
--- a/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs
+++ b/Content.Shared/Weapons/Melee/Components/MeleeRequiresWieldComponent.cs
@@ -6,7 +6,7 @@ namespace Content.Shared.Weapons.Melee.Components;
///
/// Indicates that this meleeweapon requires wielding to be useable.
///
-[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem))]
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedWieldableSystem))]
public sealed partial class MeleeRequiresWieldComponent : Component
{
// Lavaland Change: The player will slip if they try to use the weapon without wielding it.
diff --git a/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
index 2016459b9d..d5016c90e7 100644
--- a/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
+++ b/Content.Shared/Weapons/Ranged/Components/GunRequiresWieldComponent.cs
@@ -7,7 +7,7 @@ namespace Content.Shared.Weapons.Ranged.Components;
/// Indicates that this gun requires wielding to be useable.
///
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-[Access(typeof(WieldableSystem))]
+[Access(typeof(SharedWieldableSystem))]
public sealed partial class GunRequiresWieldComponent : Component
{
[DataField, AutoNetworkedField]
diff --git a/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
index 522319ccbd..bd2e9d4dd1 100644
--- a/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
+++ b/Content.Shared/Weapons/Ranged/Components/GunWieldBonusComponent.cs
@@ -6,7 +6,7 @@ namespace Content.Shared.Weapons.Ranged.Components;
///
/// Applies an accuracy bonus upon wielding.
///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(WieldableSystem))]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedWieldableSystem))]
public sealed partial class GunWieldBonusComponent : Component
{
[ViewVariables(VVAccess.ReadWrite), DataField("minAngle"), AutoNetworkedField]
diff --git a/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs b/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
index 3336923b02..86afe1897b 100644
--- a/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
+++ b/Content.Shared/Wieldable/Components/IncreaseDamageOnWieldComponent.cs
@@ -2,7 +2,7 @@ using Content.Shared.Damage;
namespace Content.Shared.Wieldable.Components;
-[RegisterComponent, Access(typeof(WieldableSystem))]
+[RegisterComponent, Access(typeof(SharedWieldableSystem))]
public sealed partial class IncreaseDamageOnWieldComponent : Component
{
[DataField("damage", required: true)]
diff --git a/Content.Shared/Wieldable/Components/WieldableComponent.cs b/Content.Shared/Wieldable/Components/WieldableComponent.cs
index f65452f424..73f76ed63e 100644
--- a/Content.Shared/Wieldable/Components/WieldableComponent.cs
+++ b/Content.Shared/Wieldable/Components/WieldableComponent.cs
@@ -7,7 +7,7 @@ namespace Content.Shared.Wieldable.Components;
///
/// Used for objects that can be wielded in two or more hands,
///
-[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem)), AutoGenerateComponentState]
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedWieldableSystem)), AutoGenerateComponentState]
public sealed partial class WieldableComponent : Component
{
[DataField("wieldSound")]
diff --git a/Content.Shared/Wieldable/WieldableSystem.cs b/Content.Shared/Wieldable/SharedWieldableSystem.cs
similarity index 99%
rename from Content.Shared/Wieldable/WieldableSystem.cs
rename to Content.Shared/Wieldable/SharedWieldableSystem.cs
index b91c6ea0ae..eccf219b7d 100644
--- a/Content.Shared/Wieldable/WieldableSystem.cs
+++ b/Content.Shared/Wieldable/SharedWieldableSystem.cs
@@ -1,5 +1,5 @@
using System.Linq;
-using Content.Shared._White.Resomi.Abilities;
+using Content.Shared.Camera;
using Content.Shared.Examine;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
@@ -8,6 +8,7 @@ using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Item;
+using Content.Shared.Movement.Components;
using Content.Shared.Popups;
using Content.Shared.StatusEffect;
using Content.Shared.Stunnable;
@@ -27,7 +28,7 @@ using Robust.Shared.Timing;
namespace Content.Shared.Wieldable;
-public sealed class WieldableSystem : EntitySystem
+public abstract class SharedWieldableSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _netManager = default!;
diff --git a/Content.Shared/_Goobstation/Weapons/FoldingWeapon/FoldingWeaponSystem.cs b/Content.Shared/_Goobstation/Weapons/FoldingWeapon/FoldingWeaponSystem.cs
index ece3dfa469..d4a5d870cc 100644
--- a/Content.Shared/_Goobstation/Weapons/FoldingWeapon/FoldingWeaponSystem.cs
+++ b/Content.Shared/_Goobstation/Weapons/FoldingWeapon/FoldingWeaponSystem.cs
@@ -9,7 +9,7 @@ namespace Content.Shared._Goobstation.Weapons.FoldingWeapon;
public sealed class FoldingWeaponSystem : EntitySystem
{
- [Dependency] private readonly WieldableSystem _wieldable = default!;
+ [Dependency] private readonly SharedWieldableSystem _wieldable = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
diff --git a/Content.Shared/_Goobstation/Weapons/Wielding/UnwieldOnShootSystem.cs b/Content.Shared/_Goobstation/Weapons/Wielding/UnwieldOnShootSystem.cs
index bfead771d5..9e29f59c8d 100644
--- a/Content.Shared/_Goobstation/Weapons/Wielding/UnwieldOnShootSystem.cs
+++ b/Content.Shared/_Goobstation/Weapons/Wielding/UnwieldOnShootSystem.cs
@@ -6,7 +6,7 @@ namespace Content.Shared._Goobstation.Weapons.Wielding;
public sealed class UnwieldOnShootSystem : EntitySystem
{
- [Dependency] private readonly WieldableSystem _wieldable = default!;
+ [Dependency] private readonly SharedWieldableSystem _wieldable = default!;
public override void Initialize()
{
diff --git a/Content.Shared/_White/CCVar/WhiteCVars.Eye.cs b/Content.Shared/_White/CCVar/WhiteCVars.Eye.cs
new file mode 100644
index 0000000000..0b257e7c6d
--- /dev/null
+++ b/Content.Shared/_White/CCVar/WhiteCVars.Eye.cs
@@ -0,0 +1,9 @@
+using Robust.Shared.Configuration;
+
+namespace Content.Shared._White.CCVar;
+
+public sealed partial class WhiteCVars
+{
+ public static readonly CVarDef ToggleLookUp =
+ CVarDef.Create("eye.toggle_look_up", false, CVar.CLIENT | CVar.ARCHIVE);
+}
diff --git a/Resources/Locale/en-US/_white/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/_white/escape-menu/ui/options-menu.ftl
new file mode 100644
index 0000000000..e4251e2ce7
--- /dev/null
+++ b/Resources/Locale/en-US/_white/escape-menu/ui/options-menu.ftl
@@ -0,0 +1,2 @@
+ui-options-function-look-up = Look up/Take aim
+ui-options-function-toggle-look-up = Hold down the key to aim
diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
index 62c4e2d6f0..6b755cf18e 100644
--- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
+++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
@@ -297,6 +297,4 @@ cmd-options-desc = Opens options menu, optionally with a specific tab selected.
cmd-options-help = Usage: options [tab]
## Combat Options
-ui-options-function-look-up = Look up/Take aim
ui-options-function-auto-get-up = Automatically get up after falling
-ui-options-function-hold-look-up = Hold down the key to aim
diff --git a/Resources/Locale/ru-RU/_white/escape-menu/ui/options-menu.ftl b/Resources/Locale/ru-RU/_white/escape-menu/ui/options-menu.ftl
new file mode 100644
index 0000000000..da429c5573
--- /dev/null
+++ b/Resources/Locale/ru-RU/_white/escape-menu/ui/options-menu.ftl
@@ -0,0 +1,2 @@
+ui-options-function-look-up = Присмотреться/Прицелиться
+ui-options-function-toggle-look-up = Удерживать клавишу для прицеливания
diff --git a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl
index eb255f612c..3eb1fb67a0 100644
--- a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl
+++ b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl
@@ -308,12 +308,10 @@ ui-options-net-pvs-leave-tooltip =
привести к неправильным предугадываниям и другим проблемам.
## Toggle window console command
-## Toggle window console command
+
cmd-options-desc = Открывает меню опций, опционально с конкретно выбранной вкладкой.
cmd-options-help = Использование: options [tab]
## Combat Options
-## Combat Options
-ui-options-function-look-up = Присмотреться/Прицелиться
+
ui-options-function-auto-get-up = Автоматически вставать при падении
-ui-options-function-hold-look-up = Удерживать клавишу для прицеливания
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
index 5f099b8c92..47cce978d9 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
@@ -183,12 +183,15 @@
capacity: 5
proto: CartridgeAntiMateriel
- type: Gun
- angleDecay: 1 # WWDP
- bonusAngleDecay: 10 # WWDP
- bonusAngleIncreaseTurn: 1 # wwdp
- fireRate: 0.6
+ angleDecay: 1
+ bonusAngleDecay: 10
+ bonusAngleIncreaseTurn: 1
+ fireRate: 0.5
- type: Wieldable
- - type: Telescope
+ - type: CursorOffsetRequiresWield
+ - type: EyeCursorOffset
+ maxOffset: 3
+ pvsIncrease: 0.3
- type: MagazineVisuals
magState: mag
steps: 1
diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml
index 7090502ecc..17a26679ac 100644
--- a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml
+++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Turrets/ship_turrets.yml
@@ -118,8 +118,7 @@
powerLoad: 5
- type: ExtensionCableReceiver
- type: Alerts
- - type: Telescope
- lerpAmount: 0.25
+ - type: EyeCursorOffset
- type: Silicon
entityType: enum.SiliconType.Player
batteryPowered: true
diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml
index 60dff5cf06..6b52c03b5a 100644
--- a/Resources/keybinds.yml
+++ b/Resources/keybinds.yml
@@ -561,9 +561,11 @@ binds:
- function: Hotbar9
type: State
key: Num9
+# WD EDIT START
- function: LookUp
type: State
key: Space
+# WD EDIT END
- function: MappingUnselect
type: State
key: MouseRight