Airlock Hacking: AutoClose & Safety (#1395)
This commit is contained in:
@@ -62,7 +62,6 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
set
|
||||
{
|
||||
_boltsDown = value;
|
||||
UpdateWiresStatus();
|
||||
UpdateBoltLightStatus();
|
||||
}
|
||||
}
|
||||
@@ -75,11 +74,18 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
set
|
||||
{
|
||||
_boltLightsWirePulsed = value;
|
||||
UpdateWiresStatus();
|
||||
UpdateBoltLightStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private const float AutoCloseDelayFast = 1;
|
||||
// True => AutoCloseDelay; False => AutoCloseDelayFast
|
||||
private bool NormalCloseSpeed
|
||||
{
|
||||
get => CloseSpeed == AutoCloseDelay;
|
||||
set => CloseSpeed = value ? AutoCloseDelay : AutoCloseDelayFast;
|
||||
}
|
||||
|
||||
private void UpdateWiresStatus()
|
||||
{
|
||||
var powerLight = new StatusLightData(Color.Yellow, StatusLightState.On, "POWR");
|
||||
@@ -98,12 +104,21 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
var boltLightsStatus = new StatusLightData(Color.Lime,
|
||||
_boltLightsWirePulsed ? StatusLightState.On : StatusLightState.Off, "BLTL");
|
||||
|
||||
var timingStatus =
|
||||
new StatusLightData(Color.Orange, !AutoClose ? StatusLightState.Off :
|
||||
!NormalCloseSpeed ? StatusLightState.BlinkingSlow :
|
||||
StatusLightState.On,
|
||||
"TIME");
|
||||
|
||||
var safetyStatus =
|
||||
new StatusLightData(Color.Red, Safety ? StatusLightState.On : StatusLightState.Off, "SAFE");
|
||||
|
||||
_wires.SetStatus(AirlockWireStatus.PowerIndicator, powerLight);
|
||||
_wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus);
|
||||
_wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus);
|
||||
_wires.SetStatus(3, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
|
||||
_wires.SetStatus(4, new StatusLightData(Color.Orange, StatusLightState.Off, "TIME"));
|
||||
_wires.SetStatus(5, new StatusLightData(Color.Red, StatusLightState.Off, "SAFE"));
|
||||
_wires.SetStatus(AirlockWireStatus.AIControlIndicator, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
|
||||
_wires.SetStatus(AirlockWireStatus.TimingIndicator, timingStatus);
|
||||
_wires.SetStatus(AirlockWireStatus.SafetyIndicator, safetyStatus);
|
||||
/*
|
||||
_wires.SetStatus(6, powerLight);
|
||||
_wires.SetStatus(7, powerLight);
|
||||
@@ -210,6 +225,23 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
/// Mending causes them to go on again
|
||||
/// </summary>
|
||||
BoltLight,
|
||||
|
||||
// Placeholder for when AI is implemented
|
||||
AIControl,
|
||||
|
||||
/// <summary>
|
||||
/// Pulsing causes door to close faster
|
||||
/// Cutting disables door timer, causing door to stop closing automatically
|
||||
/// Mending restores door timer
|
||||
/// </summary>
|
||||
Timing,
|
||||
|
||||
/// <summary>
|
||||
/// Pulsing toggles safety
|
||||
/// Cutting disables safety
|
||||
/// Mending enables safety
|
||||
/// </summary>
|
||||
Safety,
|
||||
}
|
||||
|
||||
public void RegisterWires(WiresComponent.WiresBuilder builder)
|
||||
@@ -218,8 +250,8 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
builder.CreateWire(Wires.BackupPower);
|
||||
builder.CreateWire(Wires.Bolts);
|
||||
builder.CreateWire(Wires.BoltLight);
|
||||
builder.CreateWire(4);
|
||||
builder.CreateWire(5);
|
||||
builder.CreateWire(Wires.Timing);
|
||||
builder.CreateWire(Wires.Safety);
|
||||
/*
|
||||
builder.CreateWire(6);
|
||||
builder.CreateWire(7);
|
||||
@@ -263,6 +295,12 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
// we need to change the property here to set the appearance again
|
||||
BoltLightsVisible = !_boltLightsWirePulsed;
|
||||
break;
|
||||
case Wires.Timing:
|
||||
NormalCloseSpeed = !NormalCloseSpeed;
|
||||
break;
|
||||
case Wires.Safety:
|
||||
Safety = !Safety;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +317,12 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
case Wires.BoltLight:
|
||||
BoltLightsVisible = true;
|
||||
break;
|
||||
case Wires.Timing:
|
||||
AutoClose = true;
|
||||
break;
|
||||
case Wires.Safety:
|
||||
Safety = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,6 +336,12 @@ namespace Content.Server.GameObjects.Components.Doors
|
||||
case Wires.BoltLight:
|
||||
BoltLightsVisible = false;
|
||||
break;
|
||||
case Wires.Timing:
|
||||
AutoClose = false;
|
||||
break;
|
||||
case Wires.Safety:
|
||||
Safety = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Access;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Server.Interfaces.GameObjects.Components.Interaction;
|
||||
using Content.Server.Utility;
|
||||
@@ -31,17 +33,25 @@ namespace Content.Server.GameObjects
|
||||
set => _state = value;
|
||||
}
|
||||
|
||||
private float OpenTimeCounter;
|
||||
protected float OpenTimeCounter;
|
||||
protected bool AutoClose = true;
|
||||
protected const float AutoCloseDelay = 5;
|
||||
protected float CloseSpeed = AutoCloseDelay;
|
||||
|
||||
private CollidableComponent collidableComponent;
|
||||
private AppearanceComponent _appearance;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
|
||||
private static readonly TimeSpan CloseTime = TimeSpan.FromSeconds(1.2f);
|
||||
private static readonly TimeSpan CloseTimeOne = TimeSpan.FromSeconds(0.3f);
|
||||
private static readonly TimeSpan CloseTimeTwo = TimeSpan.FromSeconds(0.9f);
|
||||
private static readonly TimeSpan OpenTimeOne = TimeSpan.FromSeconds(0.3f);
|
||||
private static readonly TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.9f);
|
||||
private static readonly TimeSpan DenyTime = TimeSpan.FromSeconds(0.45f);
|
||||
|
||||
private const int DoorCrushDamage = 15;
|
||||
private const float DoorStunTime = 5f;
|
||||
protected bool Safety = true;
|
||||
|
||||
[ViewVariables]
|
||||
private bool _occludes;
|
||||
|
||||
@@ -192,27 +202,72 @@ namespace Content.Server.GameObjects
|
||||
Close();
|
||||
}
|
||||
|
||||
private void CheckCrush()
|
||||
{
|
||||
// Check if collides with something
|
||||
var collidesWith = collidableComponent.GetCollidingEntities(Vector2.Zero, false);
|
||||
if (collidesWith.Count() != 0)
|
||||
{
|
||||
// Crush
|
||||
bool hitSomeone = false;
|
||||
foreach (var e in collidesWith)
|
||||
{
|
||||
if (!e.TryGetComponent(out StunnableComponent stun)
|
||||
|| !e.TryGetComponent(out DamageableComponent damage)
|
||||
|| !e.TryGetComponent(out ICollidableComponent otherBody)
|
||||
|| !Owner.TryGetComponent(out ICollidableComponent body))
|
||||
continue;
|
||||
|
||||
var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);
|
||||
|
||||
if (percentage < 0.1f)
|
||||
continue;
|
||||
|
||||
damage.TakeDamage(Shared.GameObjects.DamageType.Brute, DoorCrushDamage);
|
||||
stun.Paralyze(DoorStunTime);
|
||||
hitSomeone = true;
|
||||
}
|
||||
// If we hit someone, open up after stun (opens right when stun ends)
|
||||
if (hitSomeone)
|
||||
{
|
||||
Timer.Spawn(TimeSpan.FromSeconds(DoorStunTime) - OpenTimeOne - OpenTimeTwo, () => Open());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Close()
|
||||
{
|
||||
bool shouldCheckCrush = false;
|
||||
if (collidableComponent.IsColliding(Vector2.Zero, false))
|
||||
{
|
||||
// Do nothing, somebody's in the door.
|
||||
return false;
|
||||
if (Safety)
|
||||
return false;
|
||||
|
||||
// check if we crush someone while closing
|
||||
shouldCheckCrush = true;
|
||||
}
|
||||
|
||||
State = DoorState.Closing;
|
||||
collidableComponent.Hard = true;
|
||||
OpenTimeCounter = 0;
|
||||
SetAppearance(DoorVisualState.Closing);
|
||||
|
||||
Timer.Spawn(CloseTime, () =>
|
||||
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
|
||||
{
|
||||
occluder.Enabled = true;
|
||||
}
|
||||
|
||||
Timer.Spawn(CloseTimeOne, async () =>
|
||||
{
|
||||
if (shouldCheckCrush)
|
||||
{
|
||||
CheckCrush();
|
||||
}
|
||||
|
||||
collidableComponent.Hard = true;
|
||||
|
||||
await Timer.Delay(CloseTimeTwo, _cancellationTokenSource.Token);
|
||||
|
||||
State = DoorState.Closed;
|
||||
SetAppearance(DoorVisualState.Closed);
|
||||
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
|
||||
{
|
||||
occluder.Enabled = true;
|
||||
}
|
||||
}, _cancellationTokenSource.Token);
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, true));
|
||||
return true;
|
||||
@@ -232,7 +287,6 @@ namespace Content.Server.GameObjects
|
||||
}, _cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
private const float AUTO_CLOSE_DELAY = 5;
|
||||
public virtual void OnUpdate(float frameTime)
|
||||
{
|
||||
if (State != DoorState.Open)
|
||||
@@ -240,8 +294,12 @@ namespace Content.Server.GameObjects
|
||||
return;
|
||||
}
|
||||
|
||||
OpenTimeCounter += frameTime;
|
||||
if (OpenTimeCounter > AUTO_CLOSE_DELAY)
|
||||
if (AutoClose)
|
||||
{
|
||||
OpenTimeCounter += frameTime;
|
||||
}
|
||||
|
||||
if (OpenTimeCounter > CloseSpeed)
|
||||
{
|
||||
if (!CanClose() || !Close())
|
||||
{
|
||||
|
||||
@@ -9,5 +9,8 @@ namespace Content.Shared.GameObjects.Components.Doors
|
||||
PowerIndicator,
|
||||
BoltIndicator,
|
||||
BoltLightIndicator,
|
||||
AIControlIndicator,
|
||||
TimingIndicator,
|
||||
SafetyIndicator,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user