From a2c1687260f8b89753cb82cde0f74ca7fe97c211 Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Thu, 18 Jul 2024 05:33:16 +0300 Subject: [PATCH] Lay Down via Keybind (#530) # 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.

Media

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&

--- # Changelog :cl: - 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> --- Content.Client/Input/ContentContexts.cs | 1 + .../Options/UI/Tabs/KeyRebindTab.xaml.cs | 1 + .../NPC/Systems/NPCCombatSystem.Ranged.cs | 1 + .../Standing/LayingDownComponent.cs | 14 +++ Content.Server/Standing/LayingDownSystem.cs | 101 ++++++++++++++++++ Content.Shared/Input/ContentKeyFunctions.cs | 1 + .../Weapons/Ranged/Systems/SharedGunSystem.cs | 8 ++ .../en-US/escape-menu/ui/options-menu.ftl | 1 + Resources/Locale/en-US/movement/laying.ftl | 7 ++ .../Prototypes/Entities/Mobs/Species/base.yml | 1 + Resources/keybinds.yml | 3 + 11 files changed, 139 insertions(+) create mode 100644 Content.Server/Standing/LayingDownComponent.cs create mode 100644 Content.Server/Standing/LayingDownSystem.cs create mode 100644 Resources/Locale/en-US/movement/laying.ftl diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs index ca22ab095d6..07c1349aac7 100644 --- a/Content.Client/Input/ContentContexts.cs +++ b/Content.Client/Input/ContentContexts.cs @@ -69,6 +69,7 @@ public static void SetupContexts(IInputContextContainer contexts) human.AddFunction(ContentKeyFunctions.OpenBackpack); human.AddFunction(ContentKeyFunctions.OpenBelt); human.AddFunction(ContentKeyFunctions.OfferItem); + human.AddFunction(ContentKeyFunctions.ToggleStanding); human.AddFunction(ContentKeyFunctions.MouseMiddle); human.AddFunction(ContentKeyFunctions.ArcadeUp); human.AddFunction(ContentKeyFunctions.ArcadeDown); diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs index 9daca74dd3a..1ab092c2ddd 100644 --- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs @@ -184,6 +184,7 @@ void AddCheckBox(string checkBoxName, bool currentState, ActionUnfortunately cannot be shared because some standing conditions are server-side only +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(); + + SubscribeLocalEvent(DoRefreshMovementSpeed); + SubscribeLocalEvent(DoRefreshMovementSpeed); + SubscribeLocalEvent(OnRefreshMovementSpeed); + SubscribeLocalEvent(OnParentChanged); + } + + public override void Shutdown() + { + base.Shutdown(); + + CommandBinds.Unregister(); + } + + private void DoRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, object args) + { + _movement.RefreshMovementSpeedModifiers(uid); + } + + private void OnRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, RefreshMovementSpeedModifiersEvent args) + { + if (TryComp(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(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(uid, out var standingState) + || !TryComp(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; + } +} diff --git a/Content.Shared/Input/ContentKeyFunctions.cs b/Content.Shared/Input/ContentKeyFunctions.cs index 19514a4ee0f..323fd048238 100644 --- a/Content.Shared/Input/ContentKeyFunctions.cs +++ b/Content.Shared/Input/ContentKeyFunctions.cs @@ -55,6 +55,7 @@ public static class ContentKeyFunctions public static readonly BoundKeyFunction ZoomIn = "ZoomIn"; public static readonly BoundKeyFunction ResetZoom = "ResetZoom"; public static readonly BoundKeyFunction OfferItem = "OfferItem"; + public static readonly BoundKeyFunction ToggleStanding = "ToggleStanding"; public static readonly BoundKeyFunction ArcadeUp = "ArcadeUp"; public static readonly BoundKeyFunction ArcadeDown = "ArcadeDown"; diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index ff8b102bb57..1dfdede1afa 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -205,6 +205,14 @@ private void StopShooting(EntityUid uid, GunComponent gun) Dirty(uid, gun); } + /// + /// Sets the targeted entity of the gun. Should be called before attempting to shoot to avoid shooting over the target. + /// + public void SetTarget(GunComponent gun, EntityUid target) + { + gun.Target = target; + } + /// /// Attempts to shoot at the target coordinates. Resets the shot counter after every shot. /// 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 e438512b553..23446b2b847 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -138,6 +138,7 @@ ui-options-function-swap-hands = Swap hands ui-options-function-move-stored-item = Move stored item ui-options-function-rotate-stored-item = Rotate stored item ui-options-function-offer-item = Offer something +ui-options-function-toggle-standing = Toggle standing ui-options-static-storage-ui = Lock storage window to hotbar ui-options-function-smart-equip-backpack = Smart-equip to backpack diff --git a/Resources/Locale/en-US/movement/laying.ftl b/Resources/Locale/en-US/movement/laying.ftl new file mode 100644 index 00000000000..f75061d6a75 --- /dev/null +++ b/Resources/Locale/en-US/movement/laying.ftl @@ -0,0 +1,7 @@ +laying-comp-lay-success-self = You lay down. +laying-comp-lay-success-other = {THE($entity)} lays down. +laying-comp-lay-fail-self = You can't lay down right now. + +laying-comp-stand-success-self = You stand up. +laying-comp-stand-success-other = {THE($entity)} stands up. +laying-comp-stand-fail-self = You can't stand up right now. diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 9f3269abda6..1b9e9674f44 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -311,6 +311,7 @@ - type: FireVisuals alternateState: Standing - type: OfferItem + - type: LayingDown - type: entity save: false diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml index 14d5d68091a..8fa26542caa 100644 --- a/Resources/keybinds.yml +++ b/Resources/keybinds.yml @@ -258,6 +258,9 @@ binds: - function: OfferItem type: State key: F +- function: ToggleStanding + type: State + key: R - function: ShowDebugConsole type: State key: Tilde