diff --git a/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs b/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs index 3a0ddeccca..b1824396f0 100644 --- a/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs +++ b/Content.Server/Damage/Components/DamageOnHighSpeedImpactComponent.cs @@ -1,33 +1,40 @@ +using Content.Server.Damage.Systems; using Content.Shared.Damage; using Robust.Shared.Audio; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; -namespace Content.Server.Damage.Components +namespace Content.Server.Damage.Components; + +/// +/// Should the entity take damage / be stunned if colliding at a speed above MinimumSpeed? +/// +[RegisterComponent, Access(typeof(DamageOnHighSpeedImpactSystem))] +public sealed class DamageOnHighSpeedImpactComponent : Component { - /// - /// Should the entity take damage / be stunned if colliding at a speed above MinimumSpeed? - /// - [RegisterComponent] - internal sealed class DamageOnHighSpeedImpactComponent : Component - { - [DataField("minimumSpeed")] - public float MinimumSpeed { get; set; } = 20f; - [DataField("factor")] - public float Factor { get; set; } = 0.5f; - [DataField("soundHit", required: true)] - public SoundSpecifier SoundHit { get; set; } = default!; - [DataField("stunChance")] - public float StunChance { get; set; } = 0.25f; - [DataField("stunMinimumDamage")] - public int StunMinimumDamage { get; set; } = 10; - [DataField("stunSeconds")] - public float StunSeconds { get; set; } = 1f; - [DataField("damageCooldown")] - public float DamageCooldown { get; set; } = 2f; + [DataField("minimumSpeed"), ViewVariables(VVAccess.ReadWrite)] + public float MinimumSpeed = 20f; - internal TimeSpan LastHit = TimeSpan.Zero; + [DataField("speedDamageFactor"), ViewVariables(VVAccess.ReadWrite)] + public float SpeedDamageFactor = 0.5f; - [DataField("damage", required: true)] - [ViewVariables(VVAccess.ReadWrite)] - public DamageSpecifier Damage = default!; - } + [DataField("soundHit", required: true), ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier SoundHit = default!; + + [DataField("stunChance"), ViewVariables(VVAccess.ReadWrite)] + public float StunChance = 0.25f; + + [DataField("stunMinimumDamage"), ViewVariables(VVAccess.ReadWrite)] + public int StunMinimumDamage = 10; + + [DataField("stunSeconds"), ViewVariables(VVAccess.ReadWrite)] + public float StunSeconds = 1f; + + [DataField("damageCooldown"), ViewVariables(VVAccess.ReadWrite)] + public float DamageCooldown = 2f; + + [DataField("lastHit", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan LastHit = TimeSpan.Zero; + + [DataField("damage", required: true), ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier Damage = default!; } diff --git a/Content.Server/Damage/Systems/DamageOnHighSpeedImpactSystem.cs b/Content.Server/Damage/Systems/DamageOnHighSpeedImpactSystem.cs index 99ef99e04c..47797582e4 100644 --- a/Content.Server/Damage/Systems/DamageOnHighSpeedImpactSystem.cs +++ b/Content.Server/Damage/Systems/DamageOnHighSpeedImpactSystem.cs @@ -1,55 +1,55 @@ using Content.Server.Damage.Components; using Content.Server.Stunnable; -using Content.Shared.Audio; using Content.Shared.Damage; -using JetBrains.Annotations; +using Content.Shared.Effects; using Robust.Shared.Audio; -using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Events; using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Timing; -namespace Content.Server.Damage.Systems +namespace Content.Server.Damage.Systems; + +public sealed class DamageOnHighSpeedImpactSystem : EntitySystem { - [UsedImplicitly] - internal sealed class DamageOnHighSpeedImpactSystem: EntitySystem + [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly StunSystem _stun = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + public override void Initialize() { - [Dependency] private readonly IRobustRandom _robustRandom = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly StunSystem _stunSystem = default!; + base.Initialize(); + SubscribeLocalEvent(HandleCollide); + } - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(HandleCollide); - } + private void HandleCollide(EntityUid uid, DamageOnHighSpeedImpactComponent component, ref StartCollideEvent args) + { + if (!args.OurFixture.Hard || !args.OtherFixture.Hard) + return; - private void HandleCollide(EntityUid uid, DamageOnHighSpeedImpactComponent component, ref StartCollideEvent args) - { - if (!EntityManager.HasComponent(uid)) - return; + if (!EntityManager.HasComponent(uid)) + return; - var otherBody = args.OtherEntity; - var speed = args.OurBody.LinearVelocity.Length(); + var speed = args.OurBody.LinearVelocity.Length(); - if (speed < component.MinimumSpeed) - return; + if (speed < component.MinimumSpeed) + return; - SoundSystem.Play(component.SoundHit.GetSound(), Filter.Pvs(otherBody), otherBody, AudioHelpers.WithVariation(0.125f).WithVolume(-0.125f)); + if ((_gameTiming.CurTime - component.LastHit).TotalSeconds < component.DamageCooldown) + return; - if ((_gameTiming.CurTime - component.LastHit).TotalSeconds < component.DamageCooldown) - return; + component.LastHit = _gameTiming.CurTime; - component.LastHit = _gameTiming.CurTime; + if (_robustRandom.Prob(component.StunChance)) + _stun.TryStun(uid, TimeSpan.FromSeconds(component.StunSeconds), true); - if (_robustRandom.Prob(component.StunChance)) - _stunSystem.TryStun(uid, TimeSpan.FromSeconds(component.StunSeconds), true); + var damageScale = component.SpeedDamageFactor * speed / component.MinimumSpeed; - var damageScale = (speed / component.MinimumSpeed) * component.Factor; + _damageable.TryChangeDamage(uid, component.Damage * damageScale); - _damageableSystem.TryChangeDamage(uid, component.Damage * damageScale); - } + _audio.PlayPvs(component.SoundHit, uid, AudioParams.Default.WithVariation(0.125f).WithVolume(-0.125f)); + RaiseNetworkEvent(new ColorFlashEffectEvent(Color.Red, new List { uid }), Filter.Pvs(uid, entityManager: EntityManager)); } }