diff --git a/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs b/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs index 7d1b1a38ee..57221a127f 100644 --- a/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs +++ b/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs @@ -1,26 +1,16 @@ using System; -using Content.Server.Stunnable.Components; -using Content.Shared.Audio; using Content.Shared.Damage; -using Content.Shared.Damage.Components; -using Robust.Shared.Audio; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Physics.Collision; -using Robust.Shared.Physics.Dynamics; -using Robust.Shared.Player; -using Robust.Shared.Random; using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.Timing; namespace Content.Server.Damage.Components { + /// + /// Should the entity take damage / be stunned if colliding at a speed above MinimumSpeed? + /// [RegisterComponent] - public class DamageOnHighSpeedImpactComponent : Component, IStartCollide + internal sealed class DamageOnHighSpeedImpactComponent : Component { - [Dependency] private readonly IRobustRandom _robustRandom = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; - public override string Name => "DamageOnHighSpeedImpact"; [DataField("damage")] @@ -41,30 +31,7 @@ namespace Content.Server.Damage.Components public float StunSeconds { get; set; } = 1f; [DataField("damageCooldown")] public float DamageCooldown { get; set; } = 2f; - private TimeSpan _lastHit = TimeSpan.Zero; - void IStartCollide.CollideWith(Fixture ourFixture, Fixture otherFixture, in Manifold manifold) - { - if (!Owner.TryGetComponent(out IDamageableComponent? damageable)) return; - - var speed = ourFixture.Body.LinearVelocity.Length; - - if (speed < MinimumSpeed) return; - - if (!string.IsNullOrEmpty(SoundHit)) - SoundSystem.Play(Filter.Pvs(otherFixture.Body.Owner), SoundHit, otherFixture.Body.Owner, AudioHelpers.WithVariation(0.125f).WithVolume(-0.125f)); - - if ((_gameTiming.CurTime - _lastHit).TotalSeconds < DamageCooldown) - return; - - _lastHit = _gameTiming.CurTime; - - var damage = (int) (BaseDamage * (speed / MinimumSpeed) * Factor); - - if (Owner.TryGetComponent(out StunnableComponent? stun) && _robustRandom.Prob(StunChance)) - stun.Stun(StunSeconds); - - damageable.ChangeDamage(Damage, damage, false, otherFixture.Body.Owner); - } + internal TimeSpan LastHit = TimeSpan.Zero; } } diff --git a/Content.Server/Damage/DamageOnHighSpeedImpactSystem.cs b/Content.Server/Damage/DamageOnHighSpeedImpactSystem.cs new file mode 100644 index 0000000000..38f32586e6 --- /dev/null +++ b/Content.Server/Damage/DamageOnHighSpeedImpactSystem.cs @@ -0,0 +1,53 @@ +using Content.Server.Damage.Components; +using Content.Server.Stunnable.Components; +using Content.Shared.Audio; +using Content.Shared.Damage.Components; +using JetBrains.Annotations; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Player; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server.Damage +{ + [UsedImplicitly] + internal sealed class DamageOnHighSpeedImpactSystem: EntitySystem + { + [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(HandleCollide); + } + + private void HandleCollide(EntityUid uid, DamageOnHighSpeedImpactComponent component, StartCollideEvent args) + { + if (!ComponentManager.TryGetComponent(uid, out IDamageableComponent? damageable)) return; + + var otherBody = args.OtherFixture.Body.Owner; + var speed = args.OurFixture.Body.LinearVelocity.Length; + + if (speed < component.MinimumSpeed) return; + + if (!string.IsNullOrEmpty(component.SoundHit)) + SoundSystem.Play(Filter.Pvs(otherBody), component.SoundHit, otherBody, AudioHelpers.WithVariation(0.125f).WithVolume(-0.125f)); + + if ((_gameTiming.CurTime - component.LastHit).TotalSeconds < component.DamageCooldown) + return; + + component.LastHit = _gameTiming.CurTime; + + var damage = (int) (component.BaseDamage * (speed / component.MinimumSpeed) * component.Factor); + + if (ComponentManager.TryGetComponent(uid, out StunnableComponent? stun) && _robustRandom.Prob(component.StunChance)) + stun.Stun(component.StunSeconds); + + damageable.ChangeDamage(component.Damage, damage, false, args.OtherFixture.Body.Owner); + } + } +}