Skip to content

Commit

Permalink
Better Lying Down System (From White Dream) (#815)
Browse files Browse the repository at this point in the history
# Description

Port of WWhiteDreamProject/wwdpublic#2
And now also WWhiteDreamProject/wwdpublic#8
Because Lying Down System is dependent on the Telescope System.

# TODO

- [x] Reconcile the code with core code, do code cleanup. I'll undraft
this when I'm done. Probably not going to be tonight, because I will
have to get some sleep soon to get up early for my calculus classes.

# Changelog

:cl: Spatison (White Dream)
- add: Added lying down system / Добавлена система лежания
- tweak: Lying down now uses do-afters that are visible to other people
to indicate what is going on.
- add: Added telescope system / Добавлена система прицеливания
- tweak: Now you can aim from Hristov / Теперь можно прицеливаться из
Христова

---------

Signed-off-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: Spatison <137375981+Spatison@users.noreply.github.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 19, 2024
1 parent 4d4afb6 commit d5f0c55
Show file tree
Hide file tree
Showing 22 changed files with 742 additions and 287 deletions.
12 changes: 3 additions & 9 deletions Content.Client/Buckle/BuckleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,11 @@ private void OnBuckleAfterAutoHandleState(EntityUid uid, BuckleComponent compone

private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args)
{
if (!TryComp<RotationVisualsComponent>(uid, out var rotVisuals))
if (!TryComp<RotationVisualsComponent>(uid, out var rotVisuals)
|| !Appearance.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component)
|| !buckled || args.Sprite == null)
return;

if (!Appearance.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component) ||
!buckled ||
args.Sprite == null)
{
_rotationVisualizerSystem.SetHorizontalAngle((uid, rotVisuals), rotVisuals.DefaultRotation);
return;
}

// Animate strapping yourself to something at a given angle
// TODO: Dump this when buckle is better
_rotationVisualizerSystem.AnimateSpriteRotation(uid, args.Sprite, rotVisuals.HorizontalRotation, 0.125f);
Expand Down
1 change: 1 addition & 0 deletions Content.Client/Input/ContentContexts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public static void SetupContexts(IInputContextContainer contexts)
human.AddFunction(ContentKeyFunctions.Arcade1);
human.AddFunction(ContentKeyFunctions.Arcade2);
human.AddFunction(ContentKeyFunctions.Arcade3);
human.AddFunction(ContentKeyFunctions.LookUp);

// actions should be common (for ghosts, mobs, etc)
common.AddFunction(ContentKeyFunctions.OpenActionsMenu);
Expand Down
15 changes: 15 additions & 0 deletions Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ private void HandleToggleWalk(BaseButton.ButtonToggledEventArgs args)
_deferCommands.Add(_inputManager.SaveToUserData);
}

private void HandleHoldLookUp(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.HoldLookUp, args.Pressed);
_cfg.SaveToFile();
}

private void HandleDefaultWalk(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.DefaultWalk, args.Pressed);
Expand All @@ -109,6 +115,12 @@ private void HandleStaticStorageUI(BaseButton.ButtonToggledEventArgs args)
_cfg.SaveToFile();
}

private void HandleToggleAutoGetUp(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.AutoGetUp, args.Pressed);
_cfg.SaveToFile();
}

public KeyRebindTab()
{
IoCManager.InjectDependencies(this);
Expand Down Expand Up @@ -193,6 +205,9 @@ void AddCheckBox(string checkBoxName, bool currentState, Action<BaseButton.Butto
AddButton(ContentKeyFunctions.OfferItem);
AddButton(ContentKeyFunctions.SaveItemLocation);
AddButton(ContentKeyFunctions.ToggleStanding);
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);

AddHeader("ui-options-header-interaction-adv");
AddButton(ContentKeyFunctions.SmartEquipBackpack);
Expand Down
69 changes: 69 additions & 0 deletions Content.Client/Standing/LayingDownSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Content.Shared.ActionBlocker;
using Content.Shared.Rotation;
using Content.Shared.Standing;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Timing;

namespace Content.Client.Standing;

public sealed class LayingDownSystem : SharedLayingDownSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<LayingDownComponent, MoveEvent>(OnMovementInput);

SubscribeNetworkEvent<CheckAutoGetUpEvent>(OnCheckAutoGetUp);
}

private void OnMovementInput(EntityUid uid, LayingDownComponent component, MoveEvent args)
{
if (!_timing.IsFirstTimePredicted
|| !_actionBlocker.CanMove(uid)
|| _animation.HasRunningAnimation(uid, "rotate")
|| !TryComp<TransformComponent>(uid, out var transform)
|| !TryComp<SpriteComponent>(uid, out var sprite)
|| !TryComp<RotationVisualsComponent>(uid, out var rotationVisuals))
return;

var rotation = transform.LocalRotation + (_eyeManager.CurrentEye.Rotation - (transform.LocalRotation - transform.WorldRotation));

if (rotation.GetDir() is Direction.SouthEast or Direction.East or Direction.NorthEast or Direction.North)
{
rotationVisuals.HorizontalRotation = Angle.FromDegrees(270);
sprite.Rotation = Angle.FromDegrees(270);
return;
}

rotationVisuals.HorizontalRotation = Angle.FromDegrees(90);
sprite.Rotation = Angle.FromDegrees(90);
}

private void OnCheckAutoGetUp(CheckAutoGetUpEvent ev, EntitySessionEventArgs args)
{
if (!_timing.IsFirstTimePredicted)
return;

var uid = GetEntity(ev.User);

if (!TryComp<TransformComponent>(uid, out var transform) || !TryComp<RotationVisualsComponent>(uid, out var rotationVisuals))
return;

var rotation = transform.LocalRotation + (_eyeManager.CurrentEye.Rotation - (transform.LocalRotation - transform.WorldRotation));

if (rotation.GetDir() is Direction.SouthEast or Direction.East or Direction.NorthEast or Direction.North)
{
rotationVisuals.HorizontalRotation = Angle.FromDegrees(270);
return;
}

rotationVisuals.HorizontalRotation = Angle.FromDegrees(90);
}
}
128 changes: 128 additions & 0 deletions Content.Client/Telescope/TelescopeSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
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<EyeComponent>(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
});
}
}
14 changes: 0 additions & 14 deletions Content.Server/Standing/LayingDownComponent.cs

This file was deleted.

95 changes: 11 additions & 84 deletions Content.Server/Standing/LayingDownSystem.cs
Original file line number Diff line number Diff line change
@@ -1,101 +1,28 @@
using Content.Shared.ActionBlocker;
using Content.Shared.Input;
using Content.Shared.Movement.Systems;
using Content.Shared.Popups;
using Content.Shared.Standing;
using Robust.Shared.Input.Binding;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Content.Shared.CCVar;
using Robust.Shared.Configuration;

namespace Content.Server.Standing;

/// <remarks>Unfortunately cannot be shared because some standing conditions are server-side only</remarks>
public sealed class LayingDownSystem : EntitySystem
public sealed class LayingDownSystem : SharedLayingDownSystem
{
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly SharedPopupSystem _popups = default!;
[Dependency] private readonly Shared.Standing.StandingStateSystem _standing = default!; // WHY IS THERE TWO DIFFERENT STANDING SYSTEMS?!
[Dependency] private readonly IGameTiming _timing = default!;

[Dependency] private readonly INetConfigurationManager _cfg = default!;

public override void Initialize()
{
CommandBinds.Builder
.Bind(ContentKeyFunctions.ToggleStanding, InputCmdHandler.FromDelegate(ToggleStanding, handle: false, outsidePrediction: false))
.Register<LayingDownSystem>();

SubscribeLocalEvent<LayingDownComponent, StoodEvent>(DoRefreshMovementSpeed);
SubscribeLocalEvent<LayingDownComponent, DownedEvent>(DoRefreshMovementSpeed);
SubscribeLocalEvent<LayingDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeed);
SubscribeLocalEvent<LayingDownComponent, EntParentChangedMessage>(OnParentChanged);
}

public override void Shutdown()
{
base.Shutdown();

CommandBinds.Unregister<LayingDownSystem>();
}
base.Initialize();

private void DoRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, object args)
{
_movement.RefreshMovementSpeedModifiers(uid);
SubscribeNetworkEvent<CheckAutoGetUpEvent>(OnCheckAutoGetUp);
}

private void OnRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, RefreshMovementSpeedModifiersEvent args)
private void OnCheckAutoGetUp(CheckAutoGetUpEvent ev, EntitySessionEventArgs args)
{
if (TryComp<StandingStateComponent>(uid, out var standingState) && standingState.Standing)
return;
var uid = GetEntity(ev.User);

args.ModifySpeed(component.DownedSpeedMultiplier, component.DownedSpeedMultiplier, bypassImmunity: true);
}

private void OnParentChanged(EntityUid uid, LayingDownComponent component, EntParentChangedMessage args)
{
// If the entity is not on a grid, try to make it stand up to avoid issues
if (!TryComp<StandingStateComponent>(uid, out var standingState)
|| standingState.Standing
|| Transform(uid).GridUid != null)
if (!TryComp(uid, out LayingDownComponent? layingDown))
return;

_standing.Stand(uid, standingState);
}

private void ToggleStanding(ICommonSession? session)
{
if (session is not { AttachedEntity: { Valid: true } uid } playerSession
|| !Exists(uid)
|| !TryComp<StandingStateComponent>(uid, out var standingState)
|| !TryComp<LayingDownComponent>(uid, out var layingDown))
return;

// If successful, show popup to self and others. Otherwise, only to self.
if (ToggleStandingImpl(uid, standingState, layingDown, out var popupBranch))
{
_popups.PopupEntity(Loc.GetString($"laying-comp-{popupBranch}-other", ("entity", uid)), uid, Filter.PvsExcept(uid), true);
layingDown.NextToggleAttempt = _timing.CurTime + layingDown.Cooldown;
}

_popups.PopupEntity(Loc.GetString($"laying-comp-{popupBranch}-self", ("entity", uid)), uid, uid);
}

private bool ToggleStandingImpl(EntityUid uid, StandingStateComponent standingState, LayingDownComponent layingDown, out string popupBranch)
{
var success = layingDown.NextToggleAttempt <= _timing.CurTime;

if (_standing.IsDown(uid, standingState))
{
success = success && _standing.Stand(uid, standingState, force: false);
popupBranch = success ? "stand-success" : "stand-fail";
}
else
{
success = success && Transform(uid).GridUid != null; // Do not allow laying down when not on a surface.
success = success && _standing.Down(uid, standingState: standingState, playSound: true, dropHeldItems: false);
popupBranch = success ? "lay-success" : "lay-fail";
}

return success;
layingDown.AutoGetUp = _cfg.GetClientCVar(args.SenderSession.Channel, CCVars.AutoGetUp);
Dirty(uid, layingDown);
}
}
5 changes: 5 additions & 0 deletions Content.Server/Telescope/TelescopeSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Content.Shared.Telescope;

namespace Content.Server.Telescope;

public sealed class TelescopeSystem : SharedTelescopeSystem;
Loading

0 comments on commit d5f0c55

Please sign in to comment.