mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 13:37:47 +03:00
# Description Adds a way to lay down/crawl using a keybind (R by default) similarly to ss13. It has the same effects as falling down after slipping or buckling to a bed, except you don't drop items while doing so and can (very slowly) move around. This opens new gameplay and roleplay possibilities. You can only toggle standing/laying once in 2.5 seconds (this cooldown is to prevent pro gamers from spamming it). It shows a small popup to everyone. If the attempt fails for whatever reason - being buckled, sleeping, stunned, or anything else - another popup is shown that's only visible to you. It's been tested and made sure that the system works correctly with buckling, sleeping, being stunned, and shocked. <details><summary><h1>Media</h1></summary> <p> 18 mb recording won't fit on github: https://cdn.discordapp.com/attachments/1255902264309321851/1260354667578261504/weeee-2024-07-10_00.57.23.mp4?ex=668f0441&is=668db2c1&hm=d338a3499bf47780a66b7ba96d5e8830d8cb4167064423b8983b2d0144b7aa88& </p> </details> --- # Changelog 🆑 - add: You can now lie down and stand up at will! The default keybind for it is "R", but it can be changed in settings. --------- Signed-off-by: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
102 lines
4.2 KiB
C#
102 lines
4.2 KiB
C#
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;
|
|
|
|
namespace Content.Server.Standing;
|
|
|
|
/// <remarks>Unfortunately cannot be shared because some standing conditions are server-side only</remarks>
|
|
public sealed class LayingDownSystem : EntitySystem
|
|
{
|
|
[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!;
|
|
|
|
|
|
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>();
|
|
}
|
|
|
|
private void DoRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, object args)
|
|
{
|
|
_movement.RefreshMovementSpeedModifiers(uid);
|
|
}
|
|
|
|
private void OnRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, RefreshMovementSpeedModifiersEvent args)
|
|
{
|
|
if (TryComp<StandingStateComponent>(uid, out var standingState) && standingState.Standing)
|
|
return;
|
|
|
|
args.ModifySpeed(component.DownedSpeedMultiplier, component.DownedSpeedMultiplier);
|
|
}
|
|
|
|
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)
|
|
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;
|
|
}
|
|
}
|