diff --git a/Content.Shared/Stunnable/KnockedDownComponent.cs b/Content.Shared/Stunnable/KnockedDownComponent.cs index 7b684e20e4..e4f11b8cda 100644 --- a/Content.Shared/Stunnable/KnockedDownComponent.cs +++ b/Content.Shared/Stunnable/KnockedDownComponent.cs @@ -2,33 +2,17 @@ using Robust.Shared.Audio; using Robust.Shared.GameStates; 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] - [NetworkedComponent] - [Access(typeof(SharedStunSystem))] - public sealed class KnockedDownComponent : Component - { - [DataField("helpInterval")] - public float HelpInterval { get; set; } = 1f; + [DataField("helpInterval"), AutoNetworkedField] + public float HelpInterval = 1f; - [DataField("helpAttemptSound")] - public SoundSpecifier StunAttemptSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"); + [DataField("helpAttemptSound")] + public SoundSpecifier StunAttemptSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"); - [ViewVariables] - public float HelpTimer { get; set; } = 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; - } - } + [ViewVariables, AutoNetworkedField] + public float HelpTimer = 0f; } diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 1cd2bcb557..4f1534f544 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -17,296 +17,259 @@ using Content.Shared.Movement.Systems; using Content.Shared.Standing; using Content.Shared.StatusEffect; using Content.Shared.Throwing; -using JetBrains.Annotations; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Player; -namespace Content.Shared.Stunnable +namespace Content.Shared.Stunnable; + +public abstract class SharedStunSystem : EntitySystem { - [UsedImplicitly] - public abstract class SharedStunSystem : EntitySystem + [Dependency] private readonly ActionBlockerSystem _blocker = default!; + [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!; + + /// + /// Friction modifier for knocked down players. + /// Doesn't make them faster but makes them slow down... slower. + /// + public const float KnockDownModifier = 0.4f; + + public override void Initialize() { - [Dependency] private readonly ActionBlockerSystem _blocker = default!; - [Dependency] private readonly StandingStateSystem _standingStateSystem = default!; - [Dependency] private readonly StatusEffectsSystem _statusEffectSystem = default!; - [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + SubscribeLocalEvent(OnKnockInit); + SubscribeLocalEvent(OnKnockShutdown); + SubscribeLocalEvent(OnStandAttempt); - /// - /// Friction modifier for knocked down players. - /// Doesn't make them faster but makes them slow down... slower. - /// - public const float KnockDownModifier = 0.4f; + SubscribeLocalEvent(OnSlowInit); + SubscribeLocalEvent(OnSlowRemove); - public override void Initialize() + SubscribeLocalEvent(UpdateCanMove); + SubscribeLocalEvent(UpdateCanMove); + + // helping people up if they're knocked down + SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent(OnRefreshMovespeed); + + SubscribeLocalEvent(OnKnockedTileFriction); + + // Attempt event subscriptions. + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnMoveAttempt); + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnEquipAttempt); + SubscribeLocalEvent(OnUnequipAttempt); + SubscribeLocalEvent(OnMobStateChanged); + } + + + + private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args) + { + if (!TryComp(uid, out var status)) { - SubscribeLocalEvent(OnKnockInit); - SubscribeLocalEvent(OnKnockShutdown); - SubscribeLocalEvent(OnStandAttempt); - - SubscribeLocalEvent(OnSlowInit); - SubscribeLocalEvent(OnSlowRemove); - - SubscribeLocalEvent(UpdateCanMove); - SubscribeLocalEvent(UpdateCanMove); - - SubscribeLocalEvent(OnSlowGetState); - SubscribeLocalEvent(OnSlowHandleState); - - SubscribeLocalEvent(OnKnockGetState); - SubscribeLocalEvent(OnKnockHandleState); - - // helping people up if they're knocked down - SubscribeLocalEvent(OnInteractHand); - SubscribeLocalEvent(OnRefreshMovespeed); - - SubscribeLocalEvent(OnKnockedTileFriction); - - // Attempt event subscriptions. - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnMoveAttempt); - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnAttempt); - SubscribeLocalEvent(OnEquipAttempt); - SubscribeLocalEvent(OnUnequipAttempt); - SubscribeLocalEvent(OnMobStateChanged); + return; } - - - - private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args) + switch (args.NewMobState) { - if (!TryComp(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; - } - 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...) + + /// + /// Stuns the entity, disallowing it from doing many interactions temporarily. + /// + 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(uid, "Stun", time, refresh)) + return false; + _adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} stunned for {time.Seconds} seconds"); + return true; + } + + /// + /// Knocks down the entity, making it fall to the ground. + /// + 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(uid, "KnockedDown", time, refresh); + } + + /// + /// Applies knockdown and stun to the entity temporarily. + /// + 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); + } + + /// + /// Slows down the mob's walking/running speed temporarily + /// + 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(uid, "SlowedDown", time, refresh, status)) { - _blocker.UpdateCanMove(uid); - } + var slowed = Comp(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) - { - args.State = new SlowedDownComponentState(component.SprintSpeedModifier, component.WalkSpeedModifier); - } + slowed.WalkSpeedModifier *= walkSpeedMultiplier; + slowed.SprintSpeedModifier *= runSpeedMultiplier; - private void OnSlowHandleState(EntityUid uid, SlowedDownComponent component, ref ComponentHandleState args) - { - if (args.Current is SlowedDownComponentState state) - { - component.SprintSpeedModifier = state.SprintSpeedModifier; - component.WalkSpeedModifier = state.WalkSpeedModifier; - } - } + _movementSpeedModifier.RefreshMovementSpeedModifiers(uid); - 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...) - - /// - /// Stuns the entity, disallowing it from doing many interactions temporarily. - /// - 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(uid, "Stun", time, refresh)) - return false; - _adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} stunned for {time.Seconds} seconds"); return true; } - /// - /// Knocks down the entity, making it fall to the ground. - /// - 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(uid, "KnockedDown", time, refresh); - } - - /// - /// Applies knockdown and stun to the entity temporarily. - /// - 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); - } - - /// - /// Slows down the mob's walking/running speed temporarily - /// - 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(uid, "SlowedDown", time, refresh, status)) - { - var slowed = EntityManager.GetComponent(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(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 - + 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(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 + } diff --git a/Content.Shared/Stunnable/SlowedDownComponent.cs b/Content.Shared/Stunnable/SlowedDownComponent.cs index f91b9567f6..c4822b1eae 100644 --- a/Content.Shared/Stunnable/SlowedDownComponent.cs +++ b/Content.Shared/Stunnable/SlowedDownComponent.cs @@ -1,27 +1,14 @@ -using Robust.Shared.GameStates; +using Robust.Shared.GameStates; 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] - [NetworkedComponent] - [Access(typeof(SharedStunSystem))] - public sealed class SlowedDownComponent : Component - { - public float SprintSpeedModifier { get; set; } = 0.5f; - public float WalkSpeedModifier { get; set; } = 0.5f; - } + [ViewVariables, DataField("sprintSpeedModifier"), AutoNetworkedField] + public float SprintSpeedModifier = 0.5f; - [Serializable, NetSerializable] - public sealed class SlowedDownComponentState : ComponentState - { - public float SprintSpeedModifier { get; set; } - public float WalkSpeedModifier { get; set; } - - public SlowedDownComponentState(float sprintSpeedModifier, float walkSpeedModifier) - { - SprintSpeedModifier = sprintSpeedModifier; - WalkSpeedModifier = walkSpeedModifier; - } - } + [ViewVariables, DataField("walkSpeedModifier"), AutoNetworkedField] + public float WalkSpeedModifier = 0.5f; } diff --git a/Content.Shared/Stunnable/StunnedComponent.cs b/Content.Shared/Stunnable/StunnedComponent.cs index 8b36e11f42..d083b16448 100644 --- a/Content.Shared/Stunnable/StunnedComponent.cs +++ b/Content.Shared/Stunnable/StunnedComponent.cs @@ -1,10 +1,8 @@ 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 - { - } }