Files
wwdpublic/Content.Shared/Standing/SharedLayingDownSystem.cs
VMSolidus e3639f793a Better Lying Down System (From White Dream) (#815)
# Description

Port of https://github.com/WWhiteDreamProject/wwdpublic/pull/2
And now also https://github.com/WWhiteDreamProject/wwdpublic/pull/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

🆑 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>
# Conflicts:
#	Content.Client/Input/ContentContexts.cs
#	Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
#	Content.Shared/Input/ContentKeyFunctions.cs
#	Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
#	Resources/keybinds.yml
2024-10-19 13:02:04 +07:00

156 lines
5.3 KiB
C#

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.Input.Binding;
using Robust.Shared.Player;
using Robust.Shared.Serialization;
namespace Content.Shared.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!;
public override void Initialize()
{
CommandBinds.Builder
.Bind(ContentKeyFunctions.ToggleStanding, InputCmdHandler.FromDelegate(ToggleStanding))
.Register<SharedLayingDownSystem>();
SubscribeNetworkEvent<ChangeLayingDownEvent>(OnChangeState);
SubscribeLocalEvent<StandingStateComponent, StandingUpDoAfterEvent>(OnStandingUpDoAfter);
SubscribeLocalEvent<LayingDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeed);
SubscribeLocalEvent<LayingDownComponent, EntParentChangedMessage>(OnParentChanged);
}
public override void Shutdown()
{
base.Shutdown();
CommandBinds.Unregister<SharedLayingDownSystem>();
}
private void ToggleStanding(ICommonSession? session)
{
if (session?.AttachedEntity == null
|| !HasComp<LayingDownComponent>(session.AttachedEntity)
|| _gravity.IsWeightless(session.AttachedEntity.Value))
return;
RaiseNetworkEvent(new ChangeLayingDownEvent());
}
private void OnChangeState(ChangeLayingDownEvent ev, EntitySessionEventArgs args)
{
if (!args.SenderSession.AttachedEntity.HasValue)
return;
var uid = args.SenderSession.AttachedEntity.Value;
// TODO: Wizard
//if (HasComp<FrozenComponent>(uid))
// return;
if (!TryComp(uid, out StandingStateComponent? standing)
|| !TryComp(uid, out LayingDownComponent? layingDown))
return;
RaiseNetworkEvent(new CheckAutoGetUpEvent(GetNetEntity(uid)));
if (HasComp<KnockedDownComponent>(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<KnockedDownComponent>(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<StandingStateComponent>(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
}