minor stun refactor (#18752)
* file scope * stun autogen state --------- Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -2,33 +2,17 @@ using Robust.Shared.Audio;
|
|||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Stunnable
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedStunSystem))]
|
||||||
|
public sealed partial class KnockedDownComponent : Component
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[DataField("helpInterval"), AutoNetworkedField]
|
||||||
[NetworkedComponent]
|
public float HelpInterval = 1f;
|
||||||
[Access(typeof(SharedStunSystem))]
|
|
||||||
public sealed class KnockedDownComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("helpInterval")]
|
|
||||||
public float HelpInterval { get; set; } = 1f;
|
|
||||||
|
|
||||||
[DataField("helpAttemptSound")]
|
[DataField("helpAttemptSound")]
|
||||||
public SoundSpecifier StunAttemptSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg");
|
public SoundSpecifier StunAttemptSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg");
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables, AutoNetworkedField]
|
||||||
public float HelpTimer { get; set; } = 0f;
|
public float HelpTimer = 0f;
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class KnockedDownComponentState : ComponentState
|
|
||||||
{
|
|
||||||
public float HelpInterval { get; set; }
|
|
||||||
public float HelpTimer { get; set; }
|
|
||||||
|
|
||||||
public KnockedDownComponentState(float helpInterval, float helpTimer)
|
|
||||||
{
|
|
||||||
HelpInterval = helpInterval;
|
|
||||||
HelpTimer = helpTimer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,296 +17,259 @@ using Content.Shared.Movement.Systems;
|
|||||||
using Content.Shared.Standing;
|
using Content.Shared.Standing;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffect;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
namespace Content.Shared.Stunnable
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
public abstract class SharedStunSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[UsedImplicitly]
|
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
||||||
public abstract class SharedStunSystem : EntitySystem
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
|
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
[Dependency] private readonly StandingStateSystem _standingState = default!;
|
||||||
|
[Dependency] private readonly StatusEffectsSystem _statusEffect = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Friction modifier for knocked down players.
|
||||||
|
/// Doesn't make them faster but makes them slow down... slower.
|
||||||
|
/// </summary>
|
||||||
|
public const float KnockDownModifier = 0.4f;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
SubscribeLocalEvent<KnockedDownComponent, ComponentInit>(OnKnockInit);
|
||||||
[Dependency] private readonly StandingStateSystem _standingStateSystem = default!;
|
SubscribeLocalEvent<KnockedDownComponent, ComponentShutdown>(OnKnockShutdown);
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffectSystem = default!;
|
SubscribeLocalEvent<KnockedDownComponent, StandAttemptEvent>(OnStandAttempt);
|
||||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
|
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
SubscribeLocalEvent<SlowedDownComponent, ComponentInit>(OnSlowInit);
|
||||||
/// Friction modifier for knocked down players.
|
SubscribeLocalEvent<SlowedDownComponent, ComponentShutdown>(OnSlowRemove);
|
||||||
/// Doesn't make them faster but makes them slow down... slower.
|
|
||||||
/// </summary>
|
|
||||||
public const float KnockDownModifier = 0.4f;
|
|
||||||
|
|
||||||
public override void Initialize()
|
SubscribeLocalEvent<StunnedComponent, ComponentStartup>(UpdateCanMove);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, ComponentShutdown>(UpdateCanMove);
|
||||||
|
|
||||||
|
// helping people up if they're knocked down
|
||||||
|
SubscribeLocalEvent<KnockedDownComponent, InteractHandEvent>(OnInteractHand);
|
||||||
|
SubscribeLocalEvent<SlowedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<KnockedDownComponent, TileFrictionEvent>(OnKnockedTileFriction);
|
||||||
|
|
||||||
|
// Attempt event subscriptions.
|
||||||
|
SubscribeLocalEvent<StunnedComponent, ChangeDirectionAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, UpdateCanMoveEvent>(OnMoveAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, InteractionAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, UseAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, ThrowAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, DropAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, AttackAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, PickupAttemptEvent>(OnAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, IsEquippingAttemptEvent>(OnEquipAttempt);
|
||||||
|
SubscribeLocalEvent<StunnedComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
||||||
|
SubscribeLocalEvent<MobStateComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp<StatusEffectsComponent>(uid, out var status))
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<KnockedDownComponent, ComponentInit>(OnKnockInit);
|
return;
|
||||||
SubscribeLocalEvent<KnockedDownComponent, ComponentShutdown>(OnKnockShutdown);
|
|
||||||
SubscribeLocalEvent<KnockedDownComponent, StandAttemptEvent>(OnStandAttempt);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, ComponentInit>(OnSlowInit);
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, ComponentShutdown>(OnSlowRemove);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<StunnedComponent, ComponentStartup>(UpdateCanMove);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, ComponentShutdown>(UpdateCanMove);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, ComponentGetState>(OnSlowGetState);
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, ComponentHandleState>(OnSlowHandleState);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<KnockedDownComponent, ComponentGetState>(OnKnockGetState);
|
|
||||||
SubscribeLocalEvent<KnockedDownComponent, ComponentHandleState>(OnKnockHandleState);
|
|
||||||
|
|
||||||
// helping people up if they're knocked down
|
|
||||||
SubscribeLocalEvent<KnockedDownComponent, InteractHandEvent>(OnInteractHand);
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<KnockedDownComponent, TileFrictionEvent>(OnKnockedTileFriction);
|
|
||||||
|
|
||||||
// Attempt event subscriptions.
|
|
||||||
SubscribeLocalEvent<StunnedComponent, ChangeDirectionAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, UpdateCanMoveEvent>(OnMoveAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, InteractionAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, UseAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, ThrowAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, DropAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, AttackAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, PickupAttemptEvent>(OnAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, IsEquippingAttemptEvent>(OnEquipAttempt);
|
|
||||||
SubscribeLocalEvent<StunnedComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
|
||||||
SubscribeLocalEvent<MobStateComponent, MobStateChangedEvent>(OnMobStateChanged);
|
|
||||||
}
|
}
|
||||||
|
switch (args.NewMobState)
|
||||||
|
|
||||||
|
|
||||||
private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args)
|
|
||||||
{
|
{
|
||||||
if (!TryComp<StatusEffectsComponent>(uid, out var status))
|
case MobState.Alive:
|
||||||
{
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MobState.Critical:
|
||||||
|
{
|
||||||
|
_statusEffect.TryRemoveStatusEffect(uid, "Stun");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MobState.Dead:
|
||||||
|
{
|
||||||
|
_statusEffect.TryRemoveStatusEffect(uid, "Stun");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MobState.Invalid:
|
||||||
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
switch (args.NewMobState)
|
|
||||||
{
|
|
||||||
case MobState.Alive:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MobState.Critical:
|
|
||||||
{
|
|
||||||
_statusEffectSystem.TryRemoveStatusEffect(uid, "Stun");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MobState.Dead:
|
|
||||||
{
|
|
||||||
_statusEffectSystem.TryRemoveStatusEffect(uid, "Stun");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MobState.Invalid:
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEventArgs args)
|
}
|
||||||
|
|
||||||
|
private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEventArgs args)
|
||||||
|
{
|
||||||
|
_blocker.UpdateCanMove(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
_standingState.Down(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
_standingState.Stand(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args)
|
||||||
|
{
|
||||||
|
if (component.LifeStage <= ComponentLifeStage.Running)
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSlowInit(EntityUid uid, SlowedDownComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSlowRemove(EntityUid uid, SlowedDownComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
component.SprintSpeedModifier = 1f;
|
||||||
|
component.WalkSpeedModifier = 1f;
|
||||||
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRefreshMovespeed(EntityUid uid, SlowedDownComponent component, RefreshMovementSpeedModifiersEvent args)
|
||||||
|
{
|
||||||
|
args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO STUN: Make events for different things. (Getting modifiers, attempt events, informative events...)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stuns the entity, disallowing it from doing many interactions temporarily.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryStun(EntityUid uid, TimeSpan time, bool refresh,
|
||||||
|
StatusEffectsComponent? status = null)
|
||||||
|
{
|
||||||
|
if (time <= TimeSpan.Zero)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Resolve(uid, ref status, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_statusEffect.TryAddStatusEffect<StunnedComponent>(uid, "Stun", time, refresh))
|
||||||
|
return false;
|
||||||
|
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} stunned for {time.Seconds} seconds");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Knocks down the entity, making it fall to the ground.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryKnockdown(EntityUid uid, TimeSpan time, bool refresh,
|
||||||
|
StatusEffectsComponent? status = null)
|
||||||
|
{
|
||||||
|
if (time <= TimeSpan.Zero)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Resolve(uid, ref status, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _statusEffect.TryAddStatusEffect<KnockedDownComponent>(uid, "KnockedDown", time, refresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies knockdown and stun to the entity temporarily.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryParalyze(EntityUid uid, TimeSpan time, bool refresh,
|
||||||
|
StatusEffectsComponent? status = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref status, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return TryKnockdown(uid, time, refresh, status) && TryStun(uid, time, refresh, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Slows down the mob's walking/running speed temporarily
|
||||||
|
/// </summary>
|
||||||
|
public bool TrySlowdown(EntityUid uid, TimeSpan time, bool refresh,
|
||||||
|
float walkSpeedMultiplier = 1f, float runSpeedMultiplier = 1f,
|
||||||
|
StatusEffectsComponent? status = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref status, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (time <= TimeSpan.Zero)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_statusEffect.TryAddStatusEffect<SlowedDownComponent>(uid, "SlowedDown", time, refresh, status))
|
||||||
{
|
{
|
||||||
_blocker.UpdateCanMove(uid);
|
var slowed = Comp<SlowedDownComponent>(uid);
|
||||||
}
|
// Doesn't make much sense to have the "TrySlowdown" method speed up entities now does it?
|
||||||
|
walkSpeedMultiplier = Math.Clamp(walkSpeedMultiplier, 0f, 1f);
|
||||||
|
runSpeedMultiplier = Math.Clamp(runSpeedMultiplier, 0f, 1f);
|
||||||
|
|
||||||
private void OnSlowGetState(EntityUid uid, SlowedDownComponent component, ref ComponentGetState args)
|
slowed.WalkSpeedModifier *= walkSpeedMultiplier;
|
||||||
{
|
slowed.SprintSpeedModifier *= runSpeedMultiplier;
|
||||||
args.State = new SlowedDownComponentState(component.SprintSpeedModifier, component.WalkSpeedModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlowHandleState(EntityUid uid, SlowedDownComponent component, ref ComponentHandleState args)
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
||||||
{
|
|
||||||
if (args.Current is SlowedDownComponentState state)
|
|
||||||
{
|
|
||||||
component.SprintSpeedModifier = state.SprintSpeedModifier;
|
|
||||||
component.WalkSpeedModifier = state.WalkSpeedModifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnKnockGetState(EntityUid uid, KnockedDownComponent component, ref ComponentGetState args)
|
|
||||||
{
|
|
||||||
args.State = new KnockedDownComponentState(component.HelpInterval, component.HelpTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnKnockHandleState(EntityUid uid, KnockedDownComponent component, ref ComponentHandleState args)
|
|
||||||
{
|
|
||||||
if (args.Current is KnockedDownComponentState state)
|
|
||||||
{
|
|
||||||
component.HelpInterval = state.HelpInterval;
|
|
||||||
component.HelpTimer = state.HelpTimer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args)
|
|
||||||
{
|
|
||||||
_standingStateSystem.Down(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args)
|
|
||||||
{
|
|
||||||
_standingStateSystem.Stand(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args)
|
|
||||||
{
|
|
||||||
if (component.LifeStage <= ComponentLifeStage.Running)
|
|
||||||
args.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlowInit(EntityUid uid, SlowedDownComponent component, ComponentInit args)
|
|
||||||
{
|
|
||||||
_movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlowRemove(EntityUid uid, SlowedDownComponent component, ComponentShutdown args)
|
|
||||||
{
|
|
||||||
component.SprintSpeedModifier = 1f;
|
|
||||||
component.WalkSpeedModifier = 1f;
|
|
||||||
_movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRefreshMovespeed(EntityUid uid, SlowedDownComponent component, RefreshMovementSpeedModifiersEvent args)
|
|
||||||
{
|
|
||||||
args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO STUN: Make events for different things. (Getting modifiers, attempt events, informative events...)
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stuns the entity, disallowing it from doing many interactions temporarily.
|
|
||||||
/// </summary>
|
|
||||||
public bool TryStun(EntityUid uid, TimeSpan time, bool refresh,
|
|
||||||
StatusEffectsComponent? status = null)
|
|
||||||
{
|
|
||||||
if (time <= TimeSpan.Zero)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!Resolve(uid, ref status, false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!_statusEffectSystem.TryAddStatusEffect<StunnedComponent>(uid, "Stun", time, refresh))
|
|
||||||
return false;
|
|
||||||
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} stunned for {time.Seconds} seconds");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
return false;
|
||||||
/// Knocks down the entity, making it fall to the ground.
|
|
||||||
/// </summary>
|
|
||||||
public bool TryKnockdown(EntityUid uid, TimeSpan time, bool refresh,
|
|
||||||
StatusEffectsComponent? status = null)
|
|
||||||
{
|
|
||||||
if (time <= TimeSpan.Zero)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!Resolve(uid, ref status, false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return _statusEffectSystem.TryAddStatusEffect<KnockedDownComponent>(uid, "KnockedDown", time, refresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applies knockdown and stun to the entity temporarily.
|
|
||||||
/// </summary>
|
|
||||||
public bool TryParalyze(EntityUid uid, TimeSpan time, bool refresh,
|
|
||||||
StatusEffectsComponent? status = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref status, false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return TryKnockdown(uid, time, refresh, status) && TryStun(uid, time, refresh, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Slows down the mob's walking/running speed temporarily
|
|
||||||
/// </summary>
|
|
||||||
public bool TrySlowdown(EntityUid uid, TimeSpan time, bool refresh,
|
|
||||||
float walkSpeedMultiplier = 1f, float runSpeedMultiplier = 1f,
|
|
||||||
StatusEffectsComponent? status = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref status, false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (time <= TimeSpan.Zero)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_statusEffectSystem.TryAddStatusEffect<SlowedDownComponent>(uid, "SlowedDown", time, refresh, status))
|
|
||||||
{
|
|
||||||
var slowed = EntityManager.GetComponent<SlowedDownComponent>(uid);
|
|
||||||
// Doesn't make much sense to have the "TrySlowdown" method speed up entities now does it?
|
|
||||||
walkSpeedMultiplier = Math.Clamp(walkSpeedMultiplier, 0f, 1f);
|
|
||||||
runSpeedMultiplier = Math.Clamp(runSpeedMultiplier, 0f, 1f);
|
|
||||||
|
|
||||||
slowed.WalkSpeedModifier *= walkSpeedMultiplier;
|
|
||||||
slowed.SprintSpeedModifier *= runSpeedMultiplier;
|
|
||||||
|
|
||||||
_movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnInteractHand(EntityUid uid, KnockedDownComponent knocked, InteractHandEvent args)
|
|
||||||
{
|
|
||||||
if (args.Handled || knocked.HelpTimer > 0f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO: This should be an event.
|
|
||||||
if (HasComp<SleepingComponent>(uid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Set it to half the help interval so helping is actually useful...
|
|
||||||
knocked.HelpTimer = knocked.HelpInterval/2f;
|
|
||||||
|
|
||||||
_statusEffectSystem.TryRemoveTime(uid, "KnockedDown", TimeSpan.FromSeconds(knocked.HelpInterval));
|
|
||||||
_audio.PlayPredicted(knocked.StunAttemptSound, uid, args.User);
|
|
||||||
Dirty(knocked);
|
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnKnockedTileFriction(EntityUid uid, KnockedDownComponent component, ref TileFrictionEvent args)
|
|
||||||
{
|
|
||||||
args.Modifier *= KnockDownModifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Attempt Event Handling
|
|
||||||
|
|
||||||
private void OnMoveAttempt(EntityUid uid, StunnedComponent stunned, UpdateCanMoveEvent args)
|
|
||||||
{
|
|
||||||
if (stunned.LifeStage > ComponentLifeStage.Running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
args.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAttempt(EntityUid uid, StunnedComponent stunned, CancellableEntityEventArgs args)
|
|
||||||
{
|
|
||||||
args.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEquipAttempt(EntityUid uid, StunnedComponent stunned, IsEquippingAttemptEvent args)
|
|
||||||
{
|
|
||||||
// is this a self-equip, or are they being stripped?
|
|
||||||
if (args.Equipee == uid)
|
|
||||||
args.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUnequipAttempt(EntityUid uid, StunnedComponent stunned, IsUnequippingAttemptEvent args)
|
|
||||||
{
|
|
||||||
// is this a self-equip, or are they being stripped?
|
|
||||||
if (args.Unequipee == uid)
|
|
||||||
args.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnInteractHand(EntityUid uid, KnockedDownComponent knocked, InteractHandEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled || knocked.HelpTimer > 0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: This should be an event.
|
||||||
|
if (HasComp<SleepingComponent>(uid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set it to half the help interval so helping is actually useful...
|
||||||
|
knocked.HelpTimer = knocked.HelpInterval/2f;
|
||||||
|
|
||||||
|
_statusEffect.TryRemoveTime(uid, "KnockedDown", TimeSpan.FromSeconds(knocked.HelpInterval));
|
||||||
|
_audio.PlayPredicted(knocked.StunAttemptSound, uid, args.User);
|
||||||
|
Dirty(knocked);
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKnockedTileFriction(EntityUid uid, KnockedDownComponent component, ref TileFrictionEvent args)
|
||||||
|
{
|
||||||
|
args.Modifier *= KnockDownModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Attempt Event Handling
|
||||||
|
|
||||||
|
private void OnMoveAttempt(EntityUid uid, StunnedComponent stunned, UpdateCanMoveEvent args)
|
||||||
|
{
|
||||||
|
if (stunned.LifeStage > ComponentLifeStage.Running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAttempt(EntityUid uid, StunnedComponent stunned, CancellableEntityEventArgs args)
|
||||||
|
{
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEquipAttempt(EntityUid uid, StunnedComponent stunned, IsEquippingAttemptEvent args)
|
||||||
|
{
|
||||||
|
// is this a self-equip, or are they being stripped?
|
||||||
|
if (args.Equipee == uid)
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnequipAttempt(EntityUid uid, StunnedComponent stunned, IsUnequippingAttemptEvent args)
|
||||||
|
{
|
||||||
|
// is this a self-equip, or are they being stripped?
|
||||||
|
if (args.Unequipee == uid)
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,14 @@
|
|||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Stunnable
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedStunSystem))]
|
||||||
|
public sealed partial class SlowedDownComponent : Component
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[ViewVariables, DataField("sprintSpeedModifier"), AutoNetworkedField]
|
||||||
[NetworkedComponent]
|
public float SprintSpeedModifier = 0.5f;
|
||||||
[Access(typeof(SharedStunSystem))]
|
|
||||||
public sealed class SlowedDownComponent : Component
|
|
||||||
{
|
|
||||||
public float SprintSpeedModifier { get; set; } = 0.5f;
|
|
||||||
public float WalkSpeedModifier { get; set; } = 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[ViewVariables, DataField("walkSpeedModifier"), AutoNetworkedField]
|
||||||
public sealed class SlowedDownComponentState : ComponentState
|
public float WalkSpeedModifier = 0.5f;
|
||||||
{
|
|
||||||
public float SprintSpeedModifier { get; set; }
|
|
||||||
public float WalkSpeedModifier { get; set; }
|
|
||||||
|
|
||||||
public SlowedDownComponentState(float sprintSpeedModifier, float walkSpeedModifier)
|
|
||||||
{
|
|
||||||
SprintSpeedModifier = sprintSpeedModifier;
|
|
||||||
WalkSpeedModifier = walkSpeedModifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Shared.Stunnable
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedStunSystem))]
|
||||||
|
public sealed class StunnedComponent : Component
|
||||||
{
|
{
|
||||||
[Access(typeof(SharedStunSystem))]
|
|
||||||
[RegisterComponent, NetworkedComponent]
|
|
||||||
public sealed class StunnedComponent : Component
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user