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
{
_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;
}
}

View File

@@ -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.
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, () =>
{
State = DoorState.Closed;
SetAppearance(DoorVisualState.Closed);
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);
}, _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;
}
if (AutoClose)
{
OpenTimeCounter += frameTime;
if (OpenTimeCounter > AUTO_CLOSE_DELAY)
}
if (OpenTimeCounter > CloseSpeed)
{
if (!CanClose() || !Close())
{

View File

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