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