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); } }