From 4500f8873756e46b6d22301130d2056709000474 Mon Sep 17 00:00:00 2001 From: Fishfish458 <47410468+Fishfish458@users.noreply.github.com> Date: Sat, 19 Mar 2022 14:00:01 -0500 Subject: [PATCH] Add door emag visuals and sound (#6971) Co-authored-by: fishfish458 --- Content.Client/Doors/AirlockVisualizer.cs | 15 ++++++++++++ Content.Server/Doors/Systems/DoorSystem.cs | 22 ++++++++++++++++-- .../Doors/Components/DoorComponent.cs | 12 +++++++++- .../Doors/Systems/SharedDoorSystem.cs | 11 ++++++++- .../Doors/Windoors/windoor.rsi/meta.json | 2 +- .../windoor.rsi/{spark.png => sparks.png} | Bin 6 files changed, 57 insertions(+), 5 deletions(-) rename Resources/Textures/Structures/Doors/Windoors/windoor.rsi/{spark.png => sparks.png} (100%) diff --git a/Content.Client/Doors/AirlockVisualizer.cs b/Content.Client/Doors/AirlockVisualizer.cs index 1afa3bd1db..b774c28cb2 100644 --- a/Content.Client/Doors/AirlockVisualizer.cs +++ b/Content.Client/Doors/AirlockVisualizer.cs @@ -26,6 +26,10 @@ namespace Content.Client.Doors [DataField("denyAnimationTime")] private float _denyDelay = 0.3f; + + [DataField("emagAnimationTime")] + private float _delayEmag = 1.5f; + /// /// Whether the maintenance panel is animated or stays static. /// False for windoors. @@ -55,6 +59,7 @@ namespace Content.Client.Doors private Animation CloseAnimation = default!; private Animation OpenAnimation = default!; private Animation DenyAnimation = default!; + private Animation EmaggingAnimation = default!; void ISerializationHooks.AfterDeserialization() { @@ -107,6 +112,13 @@ namespace Content.Client.Doors } } } + EmaggingAnimation = new Animation {Length = TimeSpan.FromSeconds(_delay)}; + { + var flickUnlit = new AnimationTrackSpriteFlick(); + EmaggingAnimation.AnimationTracks.Add(flickUnlit); + flickUnlit.LayerKey = DoorVisualLayers.BaseUnlit; + flickUnlit.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("sparks", 0f)); + } if (!_simpleVisuals) { @@ -186,6 +198,9 @@ namespace Content.Client.Doors case DoorState.Welded: weldedVisible = true; break; + case DoorState.Emagging: + animPlayer.Play(EmaggingAnimation, AnimationKey); + break; default: throw new ArgumentOutOfRangeException(); } diff --git a/Content.Server/Doors/Systems/DoorSystem.cs b/Content.Server/Doors/Systems/DoorSystem.cs index aa6c405370..4a0a1d4cb2 100644 --- a/Content.Server/Doors/Systems/DoorSystem.cs +++ b/Content.Server/Doors/Systems/DoorSystem.cs @@ -18,6 +18,7 @@ using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Physics.Dynamics; using Robust.Shared.Player; +using Content.Shared.Hands.Components; using System.Linq; namespace Content.Server.Doors.Systems; @@ -288,18 +289,35 @@ public sealed class DoorSystem : SharedDoorSystem if(!container.Insert(board)) Logger.Warning($"Couldn't insert board {ToPrettyString(board)} into door {ToPrettyString(uid)}!"); } + private void OnEmagged(EntityUid uid, DoorComponent door, GotEmaggedEvent args) { if(TryComp(uid, out var airlockComponent)) { if (door.State == DoorState.Closed) { - StartOpening(uid); - airlockComponent?.SetBoltsWithAudio(!airlockComponent.IsBolted()); + SetState(uid, DoorState.Emagging, door); + PlaySound(uid, door.SparkSound.GetSound(), AudioParams.Default.WithVolume(8), args.UserUid, false); args.Handled = true; } } } + + public override void StartOpening(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false) + { + if (!Resolve(uid, ref door)) + return; + + DoorState lastState = door.State; + + SetState(uid, DoorState.Opening, door); + + if (door.OpenSound != null) + PlaySound(uid, door.OpenSound.GetSound(), AudioParams.Default.WithVolume(-5), user, predicted); + + if(lastState == DoorState.Emagging && TryComp(door.Owner, out var airlockComponent)) + airlockComponent?.SetBoltsWithAudio(!airlockComponent.IsBolted()); + } } public sealed class PryFinishedEvent : EntityEventArgs { } diff --git a/Content.Shared/Doors/Components/DoorComponent.cs b/Content.Shared/Doors/Components/DoorComponent.cs index c44f14ce31..ad1850e5ed 100644 --- a/Content.Shared/Doors/Components/DoorComponent.cs +++ b/Content.Shared/Doors/Components/DoorComponent.cs @@ -59,6 +59,9 @@ public sealed class DoorComponent : Component, ISerializationHooks [DataField("denyDuration")] public readonly TimeSpan DenyDuration = TimeSpan.FromSeconds(0.45f); + [DataField("emagDuration")] + public readonly TimeSpan EmagDuration = TimeSpan.FromSeconds(0.8f); + /// /// When the door is active, this is the time when the state will next update. /// @@ -116,6 +119,12 @@ public sealed class DoorComponent : Component, ISerializationHooks /// [DataField("tryOpenDoorSound")] public SoundSpecifier TryOpenDoorSound = new SoundPathSpecifier("/Audio/Effects/bang.ogg"); + + /// + /// Sound to play when door has been emagged or possibly electrically tampered + /// + [DataField("sparkSound")] + public SoundSpecifier SparkSound = new SoundCollectionSpecifier("sparks"); #endregion #region Crushing @@ -164,7 +173,7 @@ public sealed class DoorComponent : Component, ISerializationHooks _secondsUntilStateChange = null; return; }; - + var curTime = IoCManager.Resolve().CurTime; _secondsUntilStateChange = (float) (NextStateChange.Value - curTime).TotalSeconds; } @@ -230,6 +239,7 @@ public enum DoorState Opening, Welded, Denying, + Emagging } [Serializable, NetSerializable] diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.cs index 3b7b850d82..b9fbca2919 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.cs @@ -135,6 +135,11 @@ public abstract class SharedDoorSystem : EntitySystem door.NextStateChange = GameTiming.CurTime + door.DenyDuration; break; + case DoorState.Emagging: + _activeDoors.Add(door); + door.NextStateChange = GameTiming.CurTime + door.EmagDuration; + break; + case DoorState.Open: case DoorState.Closed: door.Partial = false; @@ -352,7 +357,7 @@ public abstract class SharedDoorSystem : EntitySystem SetCollidable(uid, true, door, physics); door.NextStateChange = GameTiming.CurTime + door.CloseTimeTwo; _activeDoors.Add(door); - + // Crush any entities. Note that we don't check airlock safety here. This should have been checked before // the door closed. Crush(uid, door, physics); @@ -579,6 +584,10 @@ public abstract class SharedDoorSystem : EntitySystem SetState(door.Owner, DoorState.Closed, door); break; + case DoorState.Emagging: + StartOpening(door.Owner, door); + break; + case DoorState.Open: // This door is open, and queued for an auto-close. if (!TryClose(door.Owner, door, predicted: true)) diff --git a/Resources/Textures/Structures/Doors/Windoors/windoor.rsi/meta.json b/Resources/Textures/Structures/Doors/Windoors/windoor.rsi/meta.json index 129ed1367c..66954b6662 100644 --- a/Resources/Textures/Structures/Doors/Windoors/windoor.rsi/meta.json +++ b/Resources/Textures/Structures/Doors/Windoors/windoor.rsi/meta.json @@ -131,7 +131,7 @@ ] }, { - "name":"spark", + "name":"sparks", "directions":4, "delays":[ [ diff --git a/Resources/Textures/Structures/Doors/Windoors/windoor.rsi/spark.png b/Resources/Textures/Structures/Doors/Windoors/windoor.rsi/sparks.png similarity index 100% rename from Resources/Textures/Structures/Doors/Windoors/windoor.rsi/spark.png rename to Resources/Textures/Structures/Doors/Windoors/windoor.rsi/sparks.png