Airlock Hacking: AutoClose & Safety (#1395)

This commit is contained in:
Exp
2020-07-17 10:51:43 +02:00
committed by GitHub
parent 607ca2d824
commit 90ca60c56a
3 changed files with 133 additions and 22 deletions

View File

@@ -62,7 +62,6 @@ namespace Content.Server.GameObjects.Components.Doors
set set
{ {
_boltsDown = value; _boltsDown = value;
UpdateWiresStatus();
UpdateBoltLightStatus(); UpdateBoltLightStatus();
} }
} }
@@ -75,11 +74,18 @@ namespace Content.Server.GameObjects.Components.Doors
set set
{ {
_boltLightsWirePulsed = value; _boltLightsWirePulsed = value;
UpdateWiresStatus();
UpdateBoltLightStatus(); UpdateBoltLightStatus();
} }
} }
private const float AutoCloseDelayFast = 1;
// True => AutoCloseDelay; False => AutoCloseDelayFast
private bool NormalCloseSpeed
{
get => CloseSpeed == AutoCloseDelay;
set => CloseSpeed = value ? AutoCloseDelay : AutoCloseDelayFast;
}
private void UpdateWiresStatus() private void UpdateWiresStatus()
{ {
var powerLight = new StatusLightData(Color.Yellow, StatusLightState.On, "POWR"); 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, var boltLightsStatus = new StatusLightData(Color.Lime,
_boltLightsWirePulsed ? StatusLightState.On : StatusLightState.Off, "BLTL"); _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.PowerIndicator, powerLight);
_wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus); _wires.SetStatus(AirlockWireStatus.BoltIndicator, boltStatus);
_wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus); _wires.SetStatus(AirlockWireStatus.BoltLightIndicator, boltLightsStatus);
_wires.SetStatus(3, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT")); _wires.SetStatus(AirlockWireStatus.AIControlIndicator, new StatusLightData(Color.Purple, StatusLightState.BlinkingSlow, "AICT"));
_wires.SetStatus(4, new StatusLightData(Color.Orange, StatusLightState.Off, "TIME")); _wires.SetStatus(AirlockWireStatus.TimingIndicator, timingStatus);
_wires.SetStatus(5, new StatusLightData(Color.Red, StatusLightState.Off, "SAFE")); _wires.SetStatus(AirlockWireStatus.SafetyIndicator, safetyStatus);
/* /*
_wires.SetStatus(6, powerLight); _wires.SetStatus(6, powerLight);
_wires.SetStatus(7, powerLight); _wires.SetStatus(7, powerLight);
@@ -210,6 +225,23 @@ namespace Content.Server.GameObjects.Components.Doors
/// Mending causes them to go on again /// Mending causes them to go on again
/// </summary> /// </summary>
BoltLight, 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) public void RegisterWires(WiresComponent.WiresBuilder builder)
@@ -218,8 +250,8 @@ namespace Content.Server.GameObjects.Components.Doors
builder.CreateWire(Wires.BackupPower); builder.CreateWire(Wires.BackupPower);
builder.CreateWire(Wires.Bolts); builder.CreateWire(Wires.Bolts);
builder.CreateWire(Wires.BoltLight); builder.CreateWire(Wires.BoltLight);
builder.CreateWire(4); builder.CreateWire(Wires.Timing);
builder.CreateWire(5); builder.CreateWire(Wires.Safety);
/* /*
builder.CreateWire(6); builder.CreateWire(6);
builder.CreateWire(7); 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 // we need to change the property here to set the appearance again
BoltLightsVisible = !_boltLightsWirePulsed; BoltLightsVisible = !_boltLightsWirePulsed;
break; 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: case Wires.BoltLight:
BoltLightsVisible = true; BoltLightsVisible = true;
break; 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: case Wires.BoltLight:
BoltLightsVisible = false; BoltLightsVisible = false;
break; break;
case Wires.Timing:
AutoClose = false;
break;
case Wires.Safety:
Safety = false;
break;
} }
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Linq;
using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Access;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces.GameObjects.Components.Interaction; using Content.Server.Interfaces.GameObjects.Components.Interaction;
using Content.Server.Utility; using Content.Server.Utility;
@@ -31,17 +33,25 @@ namespace Content.Server.GameObjects
set => _state = value; 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 CollidableComponent collidableComponent;
private AppearanceComponent _appearance; private AppearanceComponent _appearance;
private CancellationTokenSource _cancellationTokenSource; 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 OpenTimeOne = TimeSpan.FromSeconds(0.3f);
private static readonly TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.9f); private static readonly TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.9f);
private static readonly TimeSpan DenyTime = TimeSpan.FromSeconds(0.45f); private static readonly TimeSpan DenyTime = TimeSpan.FromSeconds(0.45f);
private const int DoorCrushDamage = 15;
private const float DoorStunTime = 5f;
protected bool Safety = true;
[ViewVariables] [ViewVariables]
private bool _occludes; private bool _occludes;
@@ -192,27 +202,72 @@ namespace Content.Server.GameObjects
Close(); 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() public bool Close()
{ {
bool shouldCheckCrush = false;
if (collidableComponent.IsColliding(Vector2.Zero, false)) if (collidableComponent.IsColliding(Vector2.Zero, false))
{ {
// Do nothing, somebody's in the door. if (Safety)
return false; return false;
// check if we crush someone while closing
shouldCheckCrush = true;
} }
State = DoorState.Closing; State = DoorState.Closing;
collidableComponent.Hard = true;
OpenTimeCounter = 0; OpenTimeCounter = 0;
SetAppearance(DoorVisualState.Closing); SetAppearance(DoorVisualState.Closing);
Timer.Spawn(CloseTime, () =>
{
State = DoorState.Closed;
SetAppearance(DoorVisualState.Closed);
if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder)) if (_occludes && Owner.TryGetComponent(out OccluderComponent occluder))
{ {
occluder.Enabled = true; 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);
}, _cancellationTokenSource.Token); }, _cancellationTokenSource.Token);
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, true)); Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, true));
return true; return true;
@@ -232,7 +287,6 @@ namespace Content.Server.GameObjects
}, _cancellationTokenSource.Token); }, _cancellationTokenSource.Token);
} }
private const float AUTO_CLOSE_DELAY = 5;
public virtual void OnUpdate(float frameTime) public virtual void OnUpdate(float frameTime)
{ {
if (State != DoorState.Open) if (State != DoorState.Open)
@@ -240,8 +294,12 @@ namespace Content.Server.GameObjects
return; return;
} }
if (AutoClose)
{
OpenTimeCounter += frameTime; OpenTimeCounter += frameTime;
if (OpenTimeCounter > AUTO_CLOSE_DELAY) }
if (OpenTimeCounter > CloseSpeed)
{ {
if (!CanClose() || !Close()) if (!CanClose() || !Close())
{ {

View File

@@ -9,5 +9,8 @@ namespace Content.Shared.GameObjects.Components.Doors
PowerIndicator, PowerIndicator,
BoltIndicator, BoltIndicator,
BoltLightIndicator, BoltLightIndicator,
AIControlIndicator,
TimingIndicator,
SafetyIndicator,
} }
} }