fish-station/Content.Shared/Standing/StandingStateSystem.cs
2024-10-30 10:39:38 +03:00

160 lines
5.9 KiB
C#

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.Systems;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;
namespace Content.Shared.Standing
{
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!;
[Dependency] private readonly SharedBuckleSystem _buckle = default!;
private const int StandingCollisionLayer = (int) CollisionGroup.MidImpassable;
public bool IsDown(EntityUid uid, StandingStateComponent? standingState = null)
{
if (!Resolve(uid, ref standingState, false))
return false;
return standingState.CurrentState is StandingState.Lying or StandingState.GettingUp;
}
public bool Down(EntityUid uid,
bool playSound = true,
bool dropHeldItems = true,
bool force = false,
StandingStateComponent? standingState = null,
AppearanceComponent? appearance = null,
HandsComponent? hands = null,
LayingDownComponent? layingDown = null)
{
if (!Resolve(uid, ref standingState, false))
return false;
// Optional components
Resolve(uid, ref appearance, ref hands, ref layingDown, false);
if (standingState.CurrentState is StandingState.Lying)
return true;
// Even if we're getting up, we want to reset to lying down
if (standingState.CurrentState is StandingState.GettingUp)
{
standingState.CurrentState = StandingState.Lying;
Dirty(uid, standingState);
return true;
}
if (dropHeldItems && hands != null)
RaiseLocalEvent(uid, new DropHandItemsEvent(), false);
// Only check buckle if we're not forcing
if (!force)
{
if (TryComp(uid, out BuckleComponent? buckle) &&
buckle.Buckled &&
!_buckle.TryUnbuckle(uid, uid, buckleComp: buckle))
return false;
var msg = new DownAttemptEvent();
RaiseLocalEvent(uid, msg, false);
if (msg.Cancelled)
return false;
}
standingState.CurrentState = StandingState.Lying;
Dirty(uid, standingState);
RaiseLocalEvent(uid, new DownedEvent(), false);
_appearance.SetData(uid, RotationVisuals.RotationState, RotationState.Horizontal, appearance);
if (TryComp(uid, out FixturesComponent? fixtureComponent))
{
foreach (var (key, fixture) in fixtureComponent.Fixtures)
{
if ((fixture.CollisionMask & StandingCollisionLayer) == 0)
continue;
standingState.ChangedFixtures.Add(key);
_physics.SetCollisionMask(uid, key, fixture, fixture.CollisionMask & ~StandingCollisionLayer, manager: fixtureComponent);
}
}
if (standingState.LifeStage > ComponentLifeStage.Starting && playSound)
_audio.PlayPredicted(standingState.DownSound, uid, null);
_movement.RefreshMovementSpeedModifiers(uid);
return true;
}
public bool Stand(EntityUid uid,
StandingStateComponent? standingState = null,
AppearanceComponent? appearance = null,
LayingDownComponent? layingDown = null,
bool force = false)
{
if (!Resolve(uid, ref standingState, false))
return false;
Resolve(uid, ref appearance, ref layingDown, false);
// Already standing
if (standingState.CurrentState is StandingState.Standing)
return true;
if (!force && TryComp(uid, out BuckleComponent? buckle))
{
if (buckle.Buckled)
{
if (!_buckle.TryUnbuckle(uid, uid, buckleComp: buckle))
return false;
}
}
if (!force)
{
var msg = new StandAttemptEvent();
RaiseLocalEvent(uid, msg, false);
if (msg.Cancelled)
return false;
}
standingState.CurrentState = StandingState.Standing;
Dirty(uid, standingState);
RaiseLocalEvent(uid, new StoodEvent(), false);
_appearance.SetData(uid, RotationVisuals.RotationState, RotationState.Vertical, appearance);
if (TryComp(uid, out FixturesComponent? fixtureComponent))
{
foreach (var key in standingState.ChangedFixtures)
{
if (fixtureComponent.Fixtures.TryGetValue(key, out var fixture))
_physics.SetCollisionMask(uid, key, fixture, fixture.CollisionMask | StandingCollisionLayer, fixtureComponent);
}
}
standingState.ChangedFixtures.Clear();
_movement.RefreshMovementSpeedModifiers(uid);
return true;
}
}
public sealed class DropHandItemsEvent : EventArgs { }
public sealed class DownAttemptEvent : CancellableEntityEventArgs { }
public sealed class StandAttemptEvent : CancellableEntityEventArgs { }
public sealed class StoodEvent : EntityEventArgs { }
public sealed class DownedEvent : EntityEventArgs { }
}