using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
using Content.Shared.StatusEffectNew;
using Robust.Shared.Prototypes;
namespace Content.Shared.Movement.Systems;
///
/// This handles the application of movement and friction modifiers to an entity as status effects.
///
public sealed class MovementModStatusSystem : EntitySystem
{
public static readonly EntProtoId StatusEffectFriction = "StatusEffectFriction";
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
[Dependency] private readonly StatusEffectsSystem _status = default!;
///
public override void Initialize()
{
SubscribeLocalEvent(OnFrictionStatusEffectRemoved);
SubscribeLocalEvent>(OnRefreshFrictionStatus);
SubscribeLocalEvent>(OnRefreshTileFrictionStatus);
}
private void OnRefreshFrictionStatus(Entity ent, ref StatusEffectRelayedEvent args)
{
var ev = args.Args;
ev.ModifyFriction(ent.Comp.FrictionModifier);
ev.ModifyAcceleration(ent.Comp.AccelerationModifier);
args.Args = ev;
}
private void OnRefreshTileFrictionStatus(Entity ent, ref StatusEffectRelayedEvent args)
{
var ev = args.Args;
ev.Modifier *= ent.Comp.FrictionModifier;
args.Args = ev;
}
///
/// Applies a friction de-buff to the player.
///
public bool TryFriction(EntityUid uid,
TimeSpan time,
bool refresh,
float friction,
float acceleration)
{
if (time <= TimeSpan.Zero)
return false;
if (refresh)
{
return _status.TryUpdateStatusEffectDuration(uid, StatusEffectFriction, out var status, time)
&& TrySetFrictionStatus(status.Value, friction, acceleration, uid);
}
else
{
return _status.TryAddStatusEffectDuration(uid, StatusEffectFriction, out var status, time)
&& TrySetFrictionStatus(status.Value, friction, acceleration, uid);
}
}
///
/// Sets the friction status modifiers for a status effect.
///
/// The status effect entity we're modifying.
/// The friction modifier we're applying.
/// The entity the status effect is attached to that we need to refresh.
private bool TrySetFrictionStatus(Entity status, float friction, EntityUid entity)
{
return TrySetFrictionStatus(status, friction, friction, entity);
}
///
/// Sets the friction status modifiers for a status effect.
///
/// The status effect entity we're modifying.
/// The friction modifier we're applying.
/// The acceleration modifier we're applying
/// The entity the status effect is attached to that we need to refresh.
private bool TrySetFrictionStatus(Entity status, float friction, float acceleration, EntityUid entity)
{
if (!Resolve(status, ref status.Comp, false))
return false;
status.Comp.FrictionModifier = friction;
status.Comp.AccelerationModifier = acceleration;
Dirty(status);
_movementSpeedModifier.RefreshFrictionModifiers(entity);
return true;
}
private void OnFrictionStatusEffectRemoved(Entity entity, ref StatusEffectRemovedEvent args)
{
TrySetFrictionStatus(entity!, 1f, args.Target);
}
}