using Content.Shared.ActionBlocker;
using Content.Shared.Movement.Events;
using Content.Shared.StepTrigger.Systems;
using Robust.Shared.Network;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;
namespace Content.Shared.Chasm;
///
/// Handles making entities fall into chasms when stepped on.
///
public sealed class ChasmSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnStepTriggered);
SubscribeLocalEvent(OnStepTriggerAttempt);
SubscribeLocalEvent(OnUnpaused);
SubscribeLocalEvent(OnUpdateCanMove);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
// don't predict queuedels on client
if (_net.IsClient)
return;
var query = EntityQueryEnumerator();
while (query.MoveNext(out var uid, out var chasm))
{
if (_timing.CurTime < chasm.NextDeletionTime)
continue;
QueueDel(uid);
}
}
private void OnStepTriggered(EntityUid uid, ChasmComponent component, ref StepTriggeredEvent args)
{
// already doomed
if (HasComp(args.Tripper))
return;
var falling = AddComp(args.Tripper);
falling.NextDeletionTime = _timing.CurTime + falling.DeletionTime;
_blocker.UpdateCanMove(args.Tripper);
_audio.PlayPredicted(component.FallingSound, uid, args.Tripper);
}
private void OnStepTriggerAttempt(EntityUid uid, ChasmComponent component, ref StepTriggerAttemptEvent args)
{
if (TryComp(args.Tripper, out var physics) && physics.BodyStatus == BodyStatus.InAir)
return;
args.Continue = true;
}
private void OnUnpaused(EntityUid uid, ChasmFallingComponent component, ref EntityUnpausedEvent args)
{
component.NextDeletionTime += args.PausedTime;
}
private void OnUpdateCanMove(EntityUid uid, ChasmFallingComponent component, UpdateCanMoveEvent args)
{
args.Cancel();
}
}