diff --git a/Content.Client/Backmen/Standing/LayingDownSystem.cs b/Content.Client/Backmen/Standing/LayingDownSystem.cs new file mode 100644 index 00000000000..e6ed3423b18 --- /dev/null +++ b/Content.Client/Backmen/Standing/LayingDownSystem.cs @@ -0,0 +1,124 @@ +using Content.Shared.Backmen.CCVar; +using Content.Shared.Backmen.Standing; +using Content.Shared.Buckle; +using Content.Shared.Rotation; +using Content.Shared.Standing; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Shared.Configuration; +using Robust.Shared.Player; +using Robust.Shared.Timing; + +namespace Content.Client.Backmen.Standing; + +public sealed class LayingDownSystem : SharedLayingDownSystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IEyeManager _eyeManager = default!; + [Dependency] private readonly StandingStateSystem _standing = default!; + [Dependency] private readonly AnimationPlayerSystem _animation = default!; + [Dependency] private readonly SharedBuckleSystem _buckle = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMovementInput); + + _cfg.OnValueChanged(CCVars.AutoGetUp, b => _autoGetUp = b, true); + + //SubscribeNetworkEvent(OnCheckAutoGetUp); + } + + private bool _autoGetUp; + + protected override bool GetAutoGetUp(Entity ent, ICommonSession session) + { + return _autoGetUp; + } + + private void OnMovementInput(EntityUid uid, LayingDownComponent component, MoveEvent args) + { + if (!_timing.IsFirstTimePredicted) + return; + + if (!_standing.IsDown(uid)) + return; + + if (_buckle.IsBuckled(uid)) + return; + + if (_animation.HasRunningAnimation(uid, "rotate")) + return; + + if(TerminatingOrDeleted(uid)) + return; + + var transform = Transform(uid); + + if (!TryComp(uid, out var sprite) + || !TryComp(uid, out var rotationVisuals)) + { + return; + } + + ProcessVisuals((uid, transform, sprite, rotationVisuals)); + } + + private void ProcessVisuals(Entity entity) + { + var rotation = entity.Comp1.LocalRotation + (_eyeManager.CurrentEye.Rotation - (entity.Comp1.LocalRotation - _transform.GetWorldRotation(entity.Comp1))); + + if (rotation.GetDir() is Direction.SouthEast or Direction.East or Direction.NorthEast or Direction.North) + { + entity.Comp3.HorizontalRotation = Angle.FromDegrees(270); + if(entity.Comp2 != null) + entity.Comp2.Rotation = Angle.FromDegrees(270); + return; + } + + entity.Comp3.HorizontalRotation = Angle.FromDegrees(90); + if(entity.Comp2 != null) + entity.Comp2.Rotation = Angle.FromDegrees(90); + } + + public override void AutoGetUp(Entity ent) + { + if (!_timing.IsFirstTimePredicted) + return; + + if(TerminatingOrDeleted(ent)) + return; + + var transform = Transform(ent); + + if (!TryComp(ent, out var rotationVisuals)) + return; + + ProcessVisuals((ent.Owner, transform, null, rotationVisuals)); + } + + /* + private void OnCheckAutoGetUp(CheckAutoGetUpEvent ev, EntitySessionEventArgs args) + { + if (!_timing.IsFirstTimePredicted) + return; + + var uid = GetEntity(ev.User); + + if (!TryComp(uid, out var transform) || !TryComp(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); + }*/ +} diff --git a/Content.Client/Buckle/BuckleSystem.cs b/Content.Client/Buckle/BuckleSystem.cs index 6770899e0aa..2a0f02ceea0 100644 --- a/Content.Client/Buckle/BuckleSystem.cs +++ b/Content.Client/Buckle/BuckleSystem.cs @@ -81,7 +81,8 @@ private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref Ap !buckled || args.Sprite == null) { - _rotationVisualizerSystem.SetHorizontalAngle((uid, rotVisuals), rotVisuals.DefaultRotation); + // backmen: Laying System + //_rotationVisualizerSystem.SetHorizontalAngle((uid, rotVisuals), rotVisuals.DefaultRotation); return; } diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs index 60649fd3a52..d1618937205 100644 --- a/Content.Client/Input/ContentContexts.cs +++ b/Content.Client/Input/ContentContexts.cs @@ -85,7 +85,9 @@ public static void SetupContexts(IInputContextContainer contexts) human.AddFunction(ContentKeyFunctions.Arcade1); human.AddFunction(ContentKeyFunctions.Arcade2); human.AddFunction(ContentKeyFunctions.Arcade3); + human.AddFunction(ContentKeyFunctions.ToggleStanding); // Ataraxia human.AddFunction(ContentKeyFunctions.LookUp); // WD EDIT + human.AddFunction(CMKeyFunctions.CMUniqueAction); // backmen // actions should be common (for ghosts, mobs, etc) common.AddFunction(ContentKeyFunctions.OpenActionsMenu); @@ -125,15 +127,6 @@ public static void SetupContexts(IInputContextContainer contexts) common.AddFunction(ContentKeyFunctions.OpenDecalSpawnWindow); common.AddFunction(ContentKeyFunctions.OpenAdminMenu); common.AddFunction(ContentKeyFunctions.OpenGuidebook); - - - CMFunctions(contexts); - } - - private static void CMFunctions(IInputContextContainer contexts) - { - var human = contexts.GetContext("human"); - human.AddFunction(CMKeyFunctions.CMUniqueAction); } } } diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs index a9b8f31986d..8ae40c0778f 100644 --- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs @@ -159,6 +159,14 @@ void AddCheckBox(string checkBoxName, bool currentState, Action RequestWarpsPressed?.Invoke(); ReturnToBodyButton.OnPressed += _ => ReturnToBodyPressed?.Invoke(); GhostRolesButton.OnPressed += _ => GhostRolesPressed?.Invoke(); + ReturnToRound.OnPressed += _ => ReturnToRoundPressed?.Invoke(); } public void Hide() diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index 156f42aac33..7314078a6b9 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -2,6 +2,7 @@ using Content.Server.Body.Systems; using Content.Shared.Buckle; using Content.Shared.ActionBlocker; +using Content.Shared.Backmen.Standing; using Content.Shared.Body.Components; using Content.Shared.Body.Part; using Content.Shared.Buckle.Components; @@ -297,7 +298,6 @@ await server.WaitAssertion(() => { Assert.That(hand.HeldEntity, Is.Not.Null); } - var bodySystem = entityManager.System(); var legs = bodySystem.GetBodyChildrenOfType(human, BodyPartType.Leg, body); @@ -310,10 +310,16 @@ await server.WaitAssertion(() => await server.WaitRunTicks(10); + // start-backmen: Laying System await server.WaitAssertion(() => { - // Still buckled - Assert.That(buckle.Buckled); + // Unbuckled and laydown + Assert.That(buckle.Buckled, Is.False); + + var comp = entityManager.GetComponentOrNull(human); + Assert.That(comp, Is.Not.Null); + + Assert.That(comp.CurrentState, Is.EqualTo(StandingState.Lying)); // Now with no item in any hand foreach (var hand in hands.Hands.Values) @@ -321,9 +327,15 @@ await server.WaitAssertion(() => Assert.That(hand.HeldEntity, Is.Null); } - buckleSystem.Unbuckle(human, human); + entityManager.System().Stand(human); + + Assert.That(comp.CurrentState, Is.EqualTo(StandingState.Standing)); + //buckleSystem.Unbuckle(human, human); Assert.That(buckle.Buckled, Is.False); + + }); + // end-backmen: Laying System await pair.CleanReturnAsync(); } diff --git a/Content.Server/Backmen/Ghost/GhostReJoinSystem.cs b/Content.Server/Backmen/Ghost/GhostReJoinSystem.cs index f5017170bc3..3ac2dbfd587 100644 --- a/Content.Server/Backmen/Ghost/GhostReJoinSystem.cs +++ b/Content.Server/Backmen/Ghost/GhostReJoinSystem.cs @@ -260,7 +260,7 @@ private CompletionResult ReturnToRoundCompletion(IConsoleShell shell, string[] a [AnyCommand] private void ReturnToRoundCommand(IConsoleShell shell, string argstr, string[] args) { - if (shell.Player?.AttachedEntity is not { } entity || !TryComp(entity, out var ghostComponent)) + if (shell.Player?.AttachedEntity is not { } ghost || !TryComp(ghost, out var ghostComponent)) { shell.WriteError("This command can only be ran by a player with an attached entity."); return; @@ -282,6 +282,12 @@ private void ReturnToRoundCommand(IConsoleShell shell, string argstr, string[] a deathTime = ghostComponent.TimeOfDeath; } + if (deathTime != ghostComponent.TimeOfDeath) + { + _ghostSystem.SetTimeOfDeath(ghost, deathTime, ghostComponent); + Dirty(ghost, ghostComponent); + } + var timeOffset = _gameTiming.CurTime - deathTime; if (timeOffset >= _ghostRespawnTime) @@ -291,21 +297,10 @@ private void ReturnToRoundCommand(IConsoleShell shell, string argstr, string[] a _euiManager.CloseEui(_eUi[userId]); _eUi.Remove(userId); } - _eUi.Add(userId, new GhostReJoinEui(this, (entity, ghostComponent))); + _eUi.Add(userId, new GhostReJoinEui(this, (ghost, ghostComponent))); _euiManager.OpenEui(_eUi[userId], shell.Player); _eUi[userId].StateDirty(); - /* - _deathTime.Remove(userId); - _adminLogger.Add(LogType.Mind, - LogImpact.Extreme, - $"{shell.Player.Channel.UserName} вернулся в лобби посредством гост респавна."); - - SendChatMsg(shell.Player, - Loc.GetString("ghost-respawn-window-rules-footer") - ); - _gameTicker.Respawn(shell.Player); - */ return; } @@ -337,7 +332,7 @@ private void SendChatMsg(ICommonSession sess, string message) Color.Red); } - public void AttachGhost(EntityUid? ghost, ICommonSession? mindSession) + public void AttachGhost(EntityUid ghost, ICommonSession? mindSession) { if(mindSession == null) return; @@ -349,8 +344,8 @@ public void AttachGhost(EntityUid? ghost, ICommonSession? mindSession) if (TryComp(ghost, out var ghostComponent)) { - _ghostSystem.SetTimeOfDeath(ghost.Value, _deathTime[mindSession.UserId], ghostComponent); - Dirty(ghost.Value, ghostComponent); + _ghostSystem.SetTimeOfDeath(ghost, _deathTime[mindSession.UserId], ghostComponent); + Dirty(ghost, ghostComponent); } } } diff --git a/Content.Server/Backmen/Standing/LayingDownSystem.cs b/Content.Server/Backmen/Standing/LayingDownSystem.cs new file mode 100644 index 00000000000..9d90fb46bef --- /dev/null +++ b/Content.Server/Backmen/Standing/LayingDownSystem.cs @@ -0,0 +1,55 @@ +using Content.Shared.Backmen.CCVar; +using Content.Shared.Backmen.Standing; +using Content.Shared.Rotation; +using Robust.Shared.Configuration; +using Robust.Shared.Player; + +namespace Content.Server.Backmen.Standing; + +public sealed class LayingDownSystem : SharedLayingDownSystem // WD EDIT +{ + [Dependency] private readonly INetConfigurationManager _cfg = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + + public override void Initialize() + { + base.Initialize(); + + //SubscribeNetworkEvent(OnCheckAutoGetUp); + } + + public override void AutoGetUp(Entity ent) + { + if(!TryComp(ent, out var eyeComp) || !TryComp(ent, out var rotationVisualsComp)) + return; + + var xform = Transform(ent); + + var rotation = xform.LocalRotation + (eyeComp.Rotation - (xform.LocalRotation - _transform.GetWorldRotation(xform))); + + if (rotation.GetDir() is Direction.SouthEast or Direction.East or Direction.NorthEast or Direction.North) + { + rotationVisualsComp.HorizontalRotation = Angle.FromDegrees(270); + return; + } + + rotationVisualsComp.HorizontalRotation = Angle.FromDegrees(90); + } + + protected override bool GetAutoGetUp(Entity ent, ICommonSession session) + { + return _cfg.GetClientCVar(session.Channel, CCVars.AutoGetUp); + } +/* + private void OnCheckAutoGetUp(CheckAutoGetUpEvent ev, EntitySessionEventArgs args) + { + var uid = GetEntity(ev.User); + + if (!TryComp(uid, out LayingDownComponent? layingDown)) + return; + + layingDown.AutoGetUp = _cfg.GetClientCVar(args.SenderSession.Channel, CCVars.AutoGetUp); + Dirty(uid, layingDown); + } + */ +} diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index dd2a7e4ca86..a2acbc7a964 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -580,7 +580,7 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma if (ghost == null) return false; - EntityManager.SystemOrNull()?.AttachGhost(ghost, mind.Session); // backmen: ReturnToRound + EntityManager.SystemOrNull()?.AttachGhost(ghost.Value, mind.Session); // backmen: ReturnToRound return true; } diff --git a/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs b/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs index d7196ea73c7..c6eab1e4bc7 100644 --- a/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs +++ b/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs @@ -201,7 +201,7 @@ private void UpdateRanged(float frameTime) { return; } - + _gun.SetTarget(gun, comp.Target); // backmen: Laying System _gun.AttemptShoot(uid, gunUid, gun, targetCordinates); } } diff --git a/Content.Shared/Backmen/CCVar/CCVars.cs b/Content.Shared/Backmen/CCVar/CCVars.cs index 329bac1ed82..6200faa2a69 100644 --- a/Content.Shared/Backmen/CCVar/CCVars.cs +++ b/Content.Shared/Backmen/CCVar/CCVars.cs @@ -170,4 +170,12 @@ public static readonly CVarDef public static readonly CVarDef GhostRespawnMaxPlayers = CVarDef.Create("ghost.respawn_max_players", 40, CVar.SERVERONLY); + + + /* + * Bind Standing - Ataraxia + */ + + public static readonly CVarDef AutoGetUp = + CVarDef.Create("laying.auto_get_up", true, CVar.CLIENT | CVar.ARCHIVE | CVar.REPLICATED); } diff --git a/Content.Shared/Backmen/Standing/LayingDownComponent.cs b/Content.Shared/Backmen/Standing/LayingDownComponent.cs new file mode 100644 index 00000000000..11b9005cd32 --- /dev/null +++ b/Content.Shared/Backmen/Standing/LayingDownComponent.cs @@ -0,0 +1,24 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Backmen.Standing; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class LayingDownComponent : Component +{ + [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] + public float StandingUpTime { get; set; } = 1f; + + [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] + public float SpeedModify { get; set; } = 0.4f; +} +[Serializable, NetSerializable] +public sealed class ChangeLayingDownEvent : CancellableEntityEventArgs; + +/* +[Serializable, NetSerializable] +public sealed class CheckAutoGetUpEvent(NetEntity user) : CancellableEntityEventArgs +{ + public NetEntity User = user; +} +*/ diff --git a/Content.Shared/Backmen/Standing/SharedLayingDownSystem.cs b/Content.Shared/Backmen/Standing/SharedLayingDownSystem.cs new file mode 100644 index 00000000000..c78e8980888 --- /dev/null +++ b/Content.Shared/Backmen/Standing/SharedLayingDownSystem.cs @@ -0,0 +1,183 @@ +using Content.Shared.DoAfter; +using Content.Shared.Gravity; +using Content.Shared.Input; +using Content.Shared.Mobs.Systems; +using Content.Shared.Movement.Systems; +using Content.Shared.Standing; +using Content.Shared.Stunnable; +using Robust.Shared.Containers; +using Robust.Shared.Input.Binding; +using Robust.Shared.Player; +using Robust.Shared.Serialization; + +namespace Content.Shared.Backmen.Standing; + +public abstract class SharedLayingDownSystem : EntitySystem +{ + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly StandingStateSystem _standing = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedGravitySystem _gravity = default!; + [Dependency] private readonly ISharedPlayerManager _playerManager = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + + public override void Initialize() + { + CommandBinds.Builder + .Bind(ContentKeyFunctions.ToggleStanding, InputCmdHandler.FromDelegate(ToggleStanding)) + .Register(); + + SubscribeNetworkEvent(OnChangeState); + + SubscribeLocalEvent(OnStandingUpDoAfter); + SubscribeLocalEvent(OnRefreshMovementSpeed); + SubscribeLocalEvent(OnParentChanged); + } + + protected abstract bool GetAutoGetUp(Entity ent, ICommonSession session); + + public void TryProcessAutoGetUp(Entity ent) + { + var autoUp = false; + if (_playerManager.TryGetSessionByEntity(ent, out var player)) + { + autoUp = GetAutoGetUp(ent, session: player); + } + if (autoUp && !_container.IsEntityInContainer(ent)) + TryStandUp(ent, ent); + } + + public override void Shutdown() + { + base.Shutdown(); + CommandBinds.Unregister(); + } + + private void ToggleStanding(ICommonSession? session) + { + if (session?.AttachedEntity == null || + !HasComp(session.AttachedEntity) || + _gravity.IsWeightless(session.AttachedEntity.Value)) + { + return; + } + + RaiseNetworkEvent(new ChangeLayingDownEvent()); + } + + public virtual void AutoGetUp(Entity ent) + { + + } + + private void OnChangeState(ChangeLayingDownEvent ev, EntitySessionEventArgs args) + { + if (!args.SenderSession.AttachedEntity.HasValue) + return; + + var uid = args.SenderSession.AttachedEntity.Value; + + // TODO: Wizard + //if (HasComp(uid)) + // return; + + if (!TryComp(uid, out StandingStateComponent? standing) || + !TryComp(uid, out LayingDownComponent? layingDown)) + { + return; + } + + //RaiseNetworkEvent(new CheckAutoGetUpEvent(GetNetEntity(uid))); + AutoGetUp((uid,layingDown)); + + if (HasComp(uid) || !_mobState.IsAlive(uid)) + return; + + if (_standing.IsDown(uid, standing)) + TryStandUp(uid, layingDown, standing); + else + TryLieDown(uid, layingDown, standing); + } + + private void OnStandingUpDoAfter(EntityUid uid, StandingStateComponent component, StandingUpDoAfterEvent args) + { + if (args.Handled || args.Cancelled || HasComp(uid) || + _mobState.IsIncapacitated(uid) || !_standing.Stand(uid)) + { + component.CurrentState = StandingState.Lying; + } + + component.CurrentState = StandingState.Standing; + } + + private void OnRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, RefreshMovementSpeedModifiersEvent args) + { + if (_standing.IsDown(uid)) + args.ModifySpeed(component.SpeedModify, component.SpeedModify); + else + args.ModifySpeed(1f, 1f); + } + + 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.CurrentState is StandingState.Standing + || Transform(uid).GridUid != null) + { + return; + } + + _standing.Stand(uid, standingState); + } + + public bool TryStandUp(EntityUid uid, LayingDownComponent? layingDown = null, StandingStateComponent? standingState = null) + { + if (!Resolve(uid, ref standingState, false) || + !Resolve(uid, ref layingDown, false) || + standingState.CurrentState is not StandingState.Lying || + !_mobState.IsAlive(uid) || + TerminatingOrDeleted(uid)) + { + return false; + } + + var args = new DoAfterArgs(EntityManager, uid, layingDown.StandingUpTime, new StandingUpDoAfterEvent(), uid) + { + BreakOnHandChange = false, + RequireCanInteract = false + }; + + if (!_doAfter.TryStartDoAfter(args)) + return false; + + standingState.CurrentState = StandingState.GettingUp; + return true; + } + + public bool TryLieDown(EntityUid uid, LayingDownComponent? layingDown = null, StandingStateComponent? standingState = null, DropHeldItemsBehavior behavior = DropHeldItemsBehavior.NoDrop) + { + if (!Resolve(uid, ref standingState, false) || + !Resolve(uid, ref layingDown, false) || + standingState.CurrentState is not StandingState.Standing) + { + if (behavior == DropHeldItemsBehavior.AlwaysDrop) + RaiseLocalEvent(uid, new DropHandItemsEvent()); + + return false; + } + + _standing.Down(uid, true, behavior != DropHeldItemsBehavior.NoDrop, standingState); + return true; + } +} + +[Serializable, NetSerializable] +public sealed partial class StandingUpDoAfterEvent : SimpleDoAfterEvent; + +public enum DropHeldItemsBehavior : byte +{ + NoDrop, + DropIfStanding, + AlwaysDrop +} diff --git a/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs b/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs index 83c24016ceb..aa19ef27277 100644 --- a/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs +++ b/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs @@ -380,7 +380,7 @@ private void Buckle(Entity buckle, Entity strap _standing.Stand(buckle, force: true); break; case StrapPosition.Down: - _standing.Down(buckle, false, false, force: true); + _standing.Down(buckle, false, false); break; } diff --git a/Content.Shared/Ghost/SharedGhostSystem.cs b/Content.Shared/Ghost/SharedGhostSystem.cs index b2a8ca1e3e4..1e8ad501e23 100644 --- a/Content.Shared/Ghost/SharedGhostSystem.cs +++ b/Content.Shared/Ghost/SharedGhostSystem.cs @@ -158,6 +158,11 @@ public GhostUpdateGhostRoleCountEvent(int availableGhostRoleCount) AvailableGhostRoles = availableGhostRoleCount; } } + + [Serializable, NetSerializable] + public sealed class GhostReturnToRoundRequest : EntityEventArgs + { + } } diff --git a/Content.Shared/Input/ContentKeyFunctions.cs b/Content.Shared/Input/ContentKeyFunctions.cs index f960c003eb7..7619889f90c 100644 --- a/Content.Shared/Input/ContentKeyFunctions.cs +++ b/Content.Shared/Input/ContentKeyFunctions.cs @@ -56,6 +56,7 @@ public static class ContentKeyFunctions public static readonly BoundKeyFunction TakeScreenshotNoUI = "TakeScreenshotNoUI"; public static readonly BoundKeyFunction ToggleFullscreen = "ToggleFullscreen"; public static readonly BoundKeyFunction Point = "Point"; + public static readonly BoundKeyFunction ToggleStanding = "ToggleStanding"; //Ataraxia public static readonly BoundKeyFunction ZoomOut = "ZoomOut"; public static readonly BoundKeyFunction ZoomIn = "ZoomIn"; public static readonly BoundKeyFunction ResetZoom = "ResetZoom"; diff --git a/Content.Shared/Standing/StandingStateComponent.cs b/Content.Shared/Standing/StandingStateComponent.cs index 02708722355..3a7cb2a008f 100644 --- a/Content.Shared/Standing/StandingStateComponent.cs +++ b/Content.Shared/Standing/StandingStateComponent.cs @@ -1,24 +1,35 @@ using Robust.Shared.Audio; using Robust.Shared.GameStates; -namespace Content.Shared.Standing +namespace Content.Shared.Standing; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class StandingStateComponent : Component { - [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] - [Access(typeof(StandingStateSystem))] - public sealed partial class StandingStateComponent : Component - { - [ViewVariables(VVAccess.ReadWrite)] - [DataField] - public SoundSpecifier? DownSound { get; private set; } = new SoundCollectionSpecifier("BodyFall"); + [ViewVariables(VVAccess.ReadWrite)] + [DataField] + public SoundSpecifier DownSound { get; private set; } = new SoundCollectionSpecifier("BodyFall"); + + // WD EDIT START + [DataField, AutoNetworkedField] + public StandingState CurrentState { get; set; } = StandingState.Standing; + // WD EDIT END - [DataField, AutoNetworkedField] - public bool Standing { get; set; } = true; + [DataField, AutoNetworkedField] + public bool Standing { get; set; } = true; - /// - /// List of fixtures that had their collision mask changed when the entity was downed. - /// Required for re-adding the collision mask. - /// - [DataField, AutoNetworkedField] - public List ChangedFixtures = new(); - } + /// + /// List of fixtures that had their collision mask changed when the entity was downed. + /// Required for re-adding the collision mask. + /// + [DataField, AutoNetworkedField] + public List ChangedFixtures = new(); +} +// WD EDIT START +public enum StandingState +{ + Lying, + GettingUp, + Standing, } +// WD EDIT END diff --git a/Content.Shared/Standing/StandingStateSystem.cs b/Content.Shared/Standing/StandingStateSystem.cs index 8d9be9ab776..cfec80ddbdd 100644 --- a/Content.Shared/Standing/StandingStateSystem.cs +++ b/Content.Shared/Standing/StandingStateSystem.cs @@ -1,7 +1,9 @@ +using Content.Shared.Buckle; +using Content.Shared.Buckle.Components; using Content.Shared.Hands.Components; +using Content.Shared.Movement.Systems; using Content.Shared.Physics; using Content.Shared.Rotation; -using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Physics; using Robust.Shared.Physics.Systems; @@ -13,6 +15,8 @@ public sealed class StandingStateSystem : EntitySystem [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; // WD EDIT + [Dependency] private readonly SharedBuckleSystem _buckle = default!; // WD EDIT // If StandingCollisionLayer value is ever changed to more than one layer, the logic needs to be edited. private const int StandingCollisionLayer = (int) CollisionGroup.MidImpassable; @@ -22,13 +26,10 @@ public bool IsDown(EntityUid uid, StandingStateComponent? standingState = null) if (!Resolve(uid, ref standingState, false)) return false; - return !standingState.Standing; + return standingState.CurrentState is StandingState.Lying or StandingState.GettingUp; } - public bool Down(EntityUid uid, - bool playSound = true, - bool dropHeldItems = true, - bool force = false, + public bool Down(EntityUid uid, bool playSound = true, bool dropHeldItems = true, StandingStateComponent? standingState = null, AppearanceComponent? appearance = null, HandsComponent? hands = null) @@ -40,7 +41,7 @@ public bool Down(EntityUid uid, // Optional component. Resolve(uid, ref appearance, ref hands, false); - if (!standingState.Standing) + if (standingState.CurrentState is StandingState.Lying or StandingState.GettingUp) return true; // This is just to avoid most callers doing this manually saving boilerplate @@ -52,17 +53,17 @@ public bool Down(EntityUid uid, RaiseLocalEvent(uid, new DropHandItemsEvent(), false); } - if (!force) - { - var msg = new DownAttemptEvent(); - RaiseLocalEvent(uid, msg, false); + if (TryComp(uid, out BuckleComponent? buckle) && buckle.Buckled && !_buckle.TryUnbuckle(uid, uid, buckleComp: buckle)) // WD EDIT + return false; - if (msg.Cancelled) - return false; - } + var msg = new DownAttemptEvent(); + RaiseLocalEvent(uid, msg, false); - standingState.Standing = false; - Dirty(uid, standingState); + if (msg.Cancelled) + return false; + + standingState.CurrentState = StandingState.Lying; + // Dirty(standingState); RaiseLocalEvent(uid, new DownedEvent(), false); // Seemed like the best place to put it @@ -88,9 +89,10 @@ public bool Down(EntityUid uid, if (playSound) { - _audio.PlayPredicted(standingState.DownSound, uid, uid); + _audio.PlayPredicted(standingState.DownSound, uid, null); } + _movement.RefreshMovementSpeedModifiers(uid); // WD EDIT return true; } @@ -106,9 +108,12 @@ public bool Stand(EntityUid uid, // Optional component. Resolve(uid, ref appearance, false); - if (standingState.Standing) + if (standingState.CurrentState is StandingState.Standing) return true; + if (TryComp(uid, out BuckleComponent? buckle) && buckle.Buckled && !_buckle.TryUnbuckle(uid, uid, buckleComp: buckle)) // WD EDIT + return false; + if (!force) { var msg = new StandAttemptEvent(); @@ -118,7 +123,7 @@ public bool Stand(EntityUid uid, return false; } - standingState.Standing = true; + standingState.CurrentState = StandingState.Standing; Dirty(uid, standingState); RaiseLocalEvent(uid, new StoodEvent(), false); @@ -133,6 +138,7 @@ public bool Stand(EntityUid uid, } } standingState.ChangedFixtures.Clear(); + _movement.RefreshMovementSpeedModifiers(uid); // WD EDIT return true; } diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 8f828131f5c..87ebcc9bb1b 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -19,7 +19,7 @@ using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; - +using Content.Shared.Backmen.Standing; namespace Content.Shared.Stunnable; public abstract class SharedStunSystem : EntitySystem @@ -32,6 +32,7 @@ public abstract class SharedStunSystem : EntitySystem [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!; [Dependency] private readonly StandingStateSystem _standingState = default!; [Dependency] private readonly StatusEffectsSystem _statusEffect = default!; + [Dependency] private readonly SharedLayingDownSystem _layingDown = default!; // Ataraxia EDIT /// /// Friction modifier for knocked down players. @@ -137,11 +138,31 @@ private void OnStunOnContactCollide(Entity ent, ref Star private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args) { _standingState.Down(uid); + // start-backmen: Laying System + if (TryComp(uid, out var layingDownComponent)) + { + _layingDown.AutoGetUp((uid, layingDownComponent)); + _layingDown.TryLieDown(uid, layingDownComponent, null, DropHeldItemsBehavior.DropIfStanding); // Ataraxia EDIT + } + // end-backmen: Laying System + } + private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args) { - _standingState.Stand(uid); + // start-backmen: Laying System + if (!TryComp(uid, out StandingStateComponent? standing)) + return; + + if (TryComp(uid, out LayingDownComponent? layingDown)) + { + _layingDown.TryProcessAutoGetUp((uid,layingDown)); + return; + } + + _standingState.Stand(uid, standing); + // end-backmen: Laying System } private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args) diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 794237b145a..18aa6972c97 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -224,6 +224,14 @@ public void AttemptShoot(EntityUid gunUid, GunComponent gun) gun.ShotCounter = 0; } + /// + /// 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; + } + private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) { if (gun.FireRateModified <= 0f || diff --git a/Resources/Locale/ru-RU/backmen/escape-menu/options-menu.ftl b/Resources/Locale/ru-RU/backmen/escape-menu/options-menu.ftl index 038fbb9edd2..f8932e8f465 100644 --- a/Resources/Locale/ru-RU/backmen/escape-menu/options-menu.ftl +++ b/Resources/Locale/ru-RU/backmen/escape-menu/options-menu.ftl @@ -1,3 +1,6 @@ ui-options-header-rmc = *Что-то на зарубежном* ui-options-function-cm-unique-action = Необычное взаимодействие + +ui-options-hotkey-auto-up = Автоматически вставать при падении +ui-options-function-toggle-standing = Встать или лечь 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 30417ce5613..ea237189404 100644 --- a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl @@ -94,7 +94,6 @@ ui-options-parallax-low-quality = Низкокачественный парал ui-options-fps-counter = Показать счётчик FPS ui-options-vp-width = Ширина окна игры: ui-options-hud-layout = Тип HUD: - ## Controls menu ui-options-binds-reset-all = Сбросить ВСЕ привязки diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 512fb571f42..ef0805f3489 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -222,6 +222,7 @@ - CanPilot - FootstepSound - DoorBumpOpener + - type: LayingDown # backmen: LayingDown - type: entity save: false diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml index 8f295c3f938..1f623bc8ffb 100644 --- a/Resources/keybinds.yml +++ b/Resources/keybinds.yml @@ -588,3 +588,6 @@ binds: - function: LookUp type: State key: Space +- function: ToggleStanding # Ataraxia-edit + type: State + key: R