diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 8bf1b6e330..a765115910 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -151,6 +151,7 @@ "Flippable", "Airtight", "MovedByPressure", + "DamageOnHighSpeedImpact", }; } } diff --git a/Content.Server/Atmos/Reactions/PhoronFireReaction.cs b/Content.Server/Atmos/Reactions/PhoronFireReaction.cs index 0d7fa36083..acef249b02 100644 --- a/Content.Server/Atmos/Reactions/PhoronFireReaction.cs +++ b/Content.Server/Atmos/Reactions/PhoronFireReaction.cs @@ -49,10 +49,7 @@ namespace Content.Server.Atmos.Reactions mixture.SetMoles(Gas.Phoron, mixture.GetMoles(Gas.Phoron) - phoronBurnRate); mixture.SetMoles(Gas.Oxygen, mixture.GetMoles(Gas.Oxygen) - (phoronBurnRate * oxygenBurnRate)); - if(superSaturation) - mixture.AdjustMoles(Gas.Tritium, phoronBurnRate); - else - mixture.AdjustMoles(Gas.CarbonDioxide, phoronBurnRate); + mixture.AdjustMoles(superSaturation ? Gas.Tritium : Gas.CarbonDioxide, phoronBurnRate); energyReleased += Atmospherics.FirePhoronEnergyReleased * (phoronBurnRate); diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 86c0ee5c95..b39440c520 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -13,6 +13,7 @@ using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; +using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Serialization; @@ -323,8 +324,8 @@ namespace Content.Server.GameObjects.Components.Atmos switch (_state) { case ProcessState.TileEqualize: - if(ProcessTileEqualize()) - _state = ProcessState.ActiveTiles; + ProcessTileEqualize(); + _state = ProcessState.ActiveTiles; return; case ProcessState.ActiveTiles: if(ProcessActiveTiles()) @@ -335,8 +336,8 @@ namespace Content.Server.GameObjects.Components.Atmos _state = ProcessState.HighPressureDelta; return; case ProcessState.HighPressureDelta: - if(ProcessHighPressureDelta()) - _state = ProcessState.Hotspots; + ProcessHighPressureDelta(); + _state = ProcessState.Hotspots; break; case ProcessState.Hotspots: if(ProcessHotspots()) @@ -347,7 +348,7 @@ namespace Content.Server.GameObjects.Components.Atmos UpdateCounter++; } - public bool ProcessTileEqualize() + public void ProcessTileEqualize() { _stopwatch.Restart(); @@ -360,10 +361,10 @@ namespace Content.Server.GameObjects.Components.Atmos number = 0; // Process the rest next time. if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds) - return false; + return; } - return true; + return; } public bool ProcessActiveTiles() @@ -411,7 +412,7 @@ namespace Content.Server.GameObjects.Components.Atmos return true; } - public bool ProcessHighPressureDelta() + public void ProcessHighPressureDelta() { _stopwatch.Restart(); @@ -427,10 +428,10 @@ namespace Content.Server.GameObjects.Components.Atmos number = 0; // Process the rest next time. if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds) - return false; + return; } - return true; + return; } private bool ProcessHotspots() diff --git a/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs b/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs new file mode 100644 index 0000000000..2d5fc7cfdc --- /dev/null +++ b/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs @@ -0,0 +1,67 @@ +using Content.Server.GameObjects.Components.Mobs; +using Content.Server.Interfaces.GameObjects; +using Content.Shared.Audio; +using Content.Shared.GameObjects; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.IoC; +using Robust.Shared.Random; +using Robust.Shared.Serialization; + +namespace Content.Server.GameObjects.Components.Damage +{ + [RegisterComponent] + public class DamageOnHighSpeedImpactComponent : Component, ICollideBehavior + { + [Dependency] private IRobustRandom _robustRandom = default!; + + public override string Name => "DamageOnHighSpeedImpact"; + + public DamageType Damage { get; set; } = DamageType.Brute; + public float MinimumSpeed { get; set; } = 20f; + public int BaseDamage { get; set; } = 5; + public float Factor { get; set; } = 0.75f; + public string SoundHit { get; set; } = ""; + public float StunChance { get; set; } = 0.25f; + public int StunMinimumDamage { get; set; } = 10; + public float StunSeconds { get; set; } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(this, x => Damage, "damage", DamageType.Brute); + serializer.DataField(this, x => MinimumSpeed, "minimumSpeed", 20f); + serializer.DataField(this, x => BaseDamage, "baseDamage", 5); + serializer.DataField(this, x => Factor, "factor", 1f); + serializer.DataField(this, x => SoundHit, "soundHit", ""); + serializer.DataField(this, x => StunChance, "stunChance", 0.25f); + serializer.DataField(this, x => StunSeconds, "stunSeconds", 1f); + serializer.DataField(this, x => StunMinimumDamage, "stunMinimumDamage", 10); + } + + public void CollideWith(IEntity collidedWith) + { + if (!Owner.TryGetComponent(out ICollidableComponent collidable) || !Owner.TryGetComponent(out DamageableComponent damageable)) return; + + var speed = collidable.LinearVelocity.Length; + + if (speed < MinimumSpeed) return; + + var damage = (int) (BaseDamage * (speed / MinimumSpeed) * Factor); + + if(!string.IsNullOrEmpty(SoundHit)) + EntitySystem.Get().PlayFromEntity(SoundHit, collidedWith, AudioHelpers.WithVariation(0.125f).WithVolume(-0.125f)); + + if (Owner.TryGetComponent(out StunnableComponent stun) && _robustRandom.Prob(StunChance)) + stun.Stun(StunSeconds); + + damageable.TakeDamage(Damage, damage, collidedWith, Owner); + } + } +} diff --git a/Resources/Audio/effects/bang.ogg b/Resources/Audio/Effects/bang.ogg similarity index 100% rename from Resources/Audio/effects/bang.ogg rename to Resources/Audio/Effects/bang.ogg diff --git a/Resources/Audio/Effects/hit_kick.ogg b/Resources/Audio/Effects/hit_kick.ogg new file mode 100644 index 0000000000..5638e5d2d6 Binary files /dev/null and b/Resources/Audio/Effects/hit_kick.ogg differ diff --git a/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml b/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml index 45ae98fcca..19d0a25958 100644 --- a/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml +++ b/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml @@ -18,6 +18,8 @@ state: generic_door - type: Clickable - type: MovedByPressure + - type: DamageOnHighSpeedImpact + soundHit: /Audio/Effects/bang.ogg - type: InteractionOutline - type: Collidable shapes: diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index eab5362bdd..4c65dc043d 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -12,6 +12,8 @@ - type: Hands - type: MovementSpeedModifier - type: MovedByPressure + - type: DamageOnHighSpeedImpact + soundHit: /Audio/Effects/hit_kick.ogg - type: Hunger - type: Thirst # Organs diff --git a/Resources/Prototypes/Entities/item_base.yml b/Resources/Prototypes/Entities/item_base.yml index 160dfad548..33fb7b38d1 100644 --- a/Resources/Prototypes/Entities/item_base.yml +++ b/Resources/Prototypes/Entities/item_base.yml @@ -8,6 +8,7 @@ - type: Clickable - type: InteractionOutline - type: MovedByPressure + - type: DamageOnHighSpeedImpact - type: Collidable shapes: - !type:PhysShapeAabb