Prevent non-airlock doors from closing on people. (#6882)
This commit is contained in:
@@ -130,12 +130,19 @@ public sealed class DoorComponent : Component, ISerializationHooks
|
|||||||
public DamageSpecifier? CrushDamage;
|
public DamageSpecifier? CrushDamage;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If false, this door is incapable of crushing entities. Note that this differs from the airlock's "safety"
|
/// If false, this door is incapable of crushing entities. This just determines whether it will apply damage and
|
||||||
/// feature that checks for colliding entities.
|
/// stun, not whether it can close despite entities being in the way.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("canCrush")]
|
[DataField("canCrush")]
|
||||||
public readonly bool CanCrush = true;
|
public readonly bool CanCrush = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to check for colliding entities before closing. This may be overridden by other system by subscribing to
|
||||||
|
/// <see cref="BeforeDoorClosedEvent"/>. For example, hacked airlocks will set this to false.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("performCollisionCheck")]
|
||||||
|
public readonly bool PerformCollisionCheck = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of EntityUids of entities we're currently crushing. Cleared in OnPartialOpen().
|
/// List of EntityUids of entities we're currently crushing. Cleared in OnPartialOpen().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -25,16 +25,23 @@ namespace Content.Shared.Doors
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised when the door is determining whether it is able to close.
|
/// Raised when the door is determining whether it is able to close. If the event is canceled, the door will not
|
||||||
/// Cancel to stop the door from being closed.
|
/// close. Additionally this event also has a bool that determines whether or not the door should perform a
|
||||||
|
/// safety/collision check before closing. This check has to be proactively disabled by things like hacked airlocks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This event is raised both when the door is initially closed, and when it is just about to become "partially"
|
/// This event is raised both when the door is initially closed, and when it is just about to become "partially"
|
||||||
/// closed (opaque & collidable). If canceled while partially closing, it will start opening again. Useful for
|
/// closed (opaque & collidable). If canceled while partially closing, it will start opening again. Useful in case
|
||||||
/// things like airlock anti-crush safety features.
|
/// an entity entered the door just as it was about to become "solid".
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public sealed class BeforeDoorClosedEvent : CancellableEntityEventArgs
|
public sealed class BeforeDoorClosedEvent : CancellableEntityEventArgs
|
||||||
{
|
{
|
||||||
|
public bool PerformCollisionCheck;
|
||||||
|
|
||||||
|
public BeforeDoorClosedEvent(bool performCollisionCheck)
|
||||||
|
{
|
||||||
|
PerformCollisionCheck = performCollisionCheck;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ public abstract class SharedAirlockSystem : EntitySystem
|
|||||||
|
|
||||||
protected virtual void OnBeforeDoorClosed(EntityUid uid, SharedAirlockComponent airlock, BeforeDoorClosedEvent args)
|
protected virtual void OnBeforeDoorClosed(EntityUid uid, SharedAirlockComponent airlock, BeforeDoorClosedEvent args)
|
||||||
{
|
{
|
||||||
if (airlock.Safety && DoorSystem.GetColliding(uid).Any())
|
if (!airlock.Safety)
|
||||||
args.Cancel();
|
args.PerformCollisionCheck = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -309,12 +309,15 @@ public abstract class SharedDoorSystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref door))
|
if (!Resolve(uid, ref door))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ev = new BeforeDoorClosedEvent();
|
var ev = new BeforeDoorClosedEvent(door.PerformCollisionCheck);
|
||||||
RaiseLocalEvent(uid, ev, false);
|
RaiseLocalEvent(uid, ev, false);
|
||||||
if (ev.Cancelled)
|
if (ev.Cancelled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return HasAccess(uid, user);
|
if (!HasAccess(uid, user))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !ev.PerformCollisionCheck || !GetColliding(uid).Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void StartClosing(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
public virtual void StartClosing(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||||
@@ -387,11 +390,10 @@ public abstract class SharedDoorSystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref door))
|
if (!Resolve(uid, ref door))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// is this door capable of crushing? NOT the same as an airlock safety check. The door will still close.
|
|
||||||
if (!door.CanCrush)
|
if (!door.CanCrush)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Crush
|
// Find entities and apply curshing effects
|
||||||
var stunTime = door.DoorStunTime + door.OpenTimeOne;
|
var stunTime = door.DoorStunTime + door.OpenTimeOne;
|
||||||
foreach (var entity in GetColliding(uid, physics))
|
foreach (var entity in GetColliding(uid, physics))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user