Add security barriers (#4458)

* Add sprites

* Lock system now raises lock toggle events

* Add prototype and barrier system

* Toggle lock on click

* Barrier blocks bullets (like a real wall)

* Barrier now destroyable

* Fancy visualzer and lighting. Also unlock by default

* Deleted comma

* Ignored components?

* Update Resources/Prototypes/Entities/Objects/Specific/Security/barrier.yml

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Objects/Specific/Security/barrier.yml

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

* Toggle Lock no longer handled

* Made it much easier to move through airlocks

Co-authored-by: Swept <sweptwastaken@protonmail.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Alex Evgrashin
2021-08-22 19:32:24 +03:00
committed by GitHub
parent 1960e86d0c
commit 8408c1128f
12 changed files with 221 additions and 0 deletions

View File

@@ -57,6 +57,7 @@ namespace Content.Client.Entry
"CablePlacer",
"Drink",
"Food",
"DeployableBarrier",
"MagicMirror",
"FloorTile",
"ShuttleController",

View File

@@ -0,0 +1,39 @@
using Content.Shared.Security;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
namespace Content.Client.Security
{
[UsedImplicitly]
public class DeployableBarrierVisualizer : AppearanceVisualizer
{
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out SpriteComponent? sprite))
return;
if (!component.TryGetData(DeployableBarrierVisuals.State, out DeployableBarrierState state))
return;
switch (state)
{
case DeployableBarrierState.Idle:
sprite.LayerSetState(0, "idle");
ToggleLight(component, false);
break;
case DeployableBarrierState.Deployed:
sprite.LayerSetState(0, "deployed");
ToggleLight(component, true);
break;
}
}
private void ToggleLight(AppearanceComponent component, bool enabled)
{
if (component.Owner.TryGetComponent(out PointLightComponent? light))
light.Enabled = enabled;
}
}
}

View File

@@ -20,6 +20,7 @@ namespace Content.Server.Storage.Components
public override string Name => "Lock";
[ViewVariables(VVAccess.ReadWrite)] [DataField("locked")] public bool Locked { get; set; } = true;
[ViewVariables(VVAccess.ReadWrite)] [DataField("lockOnClick")] public bool LockOnClick { get; set; } = false;
[ViewVariables(VVAccess.ReadWrite)] [DataField("unlockingSound")] public SoundSpecifier UnlockSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/door_lock_off.ogg");
[ViewVariables(VVAccess.ReadWrite)] [DataField("lockingSound")] public SoundSpecifier LockSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/door_lock_off.ogg");

View File

@@ -43,6 +43,11 @@ namespace Content.Server.Lock
{
DoUnlock(lockComp, args);
}
else
{
if (lockComp.LockOnClick)
DoLock(lockComp, args);
}
}
private void OnExamined(EntityUid eUI, LockComponent lockComp, ExaminedEvent args)
@@ -73,6 +78,8 @@ namespace Content.Server.Lock
appearanceComp.SetData(StorageVisuals.Locked, true);
}
RaiseLocalEvent(lockComp.Owner.Uid, new LockToggledEvent(true));
args.Handled = true;
}
@@ -95,6 +102,8 @@ namespace Content.Server.Lock
appearanceComp.SetData(StorageVisuals.Locked, false);
}
RaiseLocalEvent(lockComp.Owner.Uid, new LockToggledEvent(false));
// To stop EntityStorageComponent from opening right after the container gets unlocked
args.Handled = true;
}

View File

@@ -0,0 +1,14 @@
using Robust.Shared.GameObjects;
namespace Content.Server.Lock
{
public class LockToggledEvent : EntityEventArgs
{
public readonly bool Locked;
public LockToggledEvent(bool locked)
{
Locked = locked;
}
}
}

View File

@@ -0,0 +1,10 @@
using Robust.Shared.GameObjects;
namespace Content.Server.Security
{
[RegisterComponent]
public class DeployableBarrierComponent : Component
{
public override string Name => "DeployableBarrier";
}
}

View File

@@ -0,0 +1,43 @@
using Content.Server.Lock;
using Content.Server.Storage.Components;
using Content.Shared.Security;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using System;
namespace Content.Server.Security.Systems
{
public class DeployableBarrierSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DeployableBarrierComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<DeployableBarrierComponent, LockToggledEvent>(OnLockToggled);
}
private void OnStartup(EntityUid uid, DeployableBarrierComponent component, ComponentStartup args)
{
if (!component.Owner.TryGetComponent(out LockComponent? lockComponent))
return;
ToggleBarrierDeploy(component, lockComponent.Locked);
}
private void OnLockToggled(EntityUid uid, DeployableBarrierComponent component, LockToggledEvent args)
{
ToggleBarrierDeploy(component, args.Locked);
}
private void ToggleBarrierDeploy(DeployableBarrierComponent component, bool isDeployed)
{
component.Owner.Transform.Anchored = isDeployed;
if (!component.Owner.TryGetComponent(out AppearanceComponent? appearanceComponent))
return;
var state = isDeployed ? DeployableBarrierState.Deployed : DeployableBarrierState.Idle;
appearanceComponent.SetData(DeployableBarrierVisuals.State, state);
}
}
}

View File

@@ -0,0 +1,23 @@
using Robust.Shared.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Content.Shared.Security
{
[Serializable, NetSerializable]
public enum DeployableBarrierVisuals : byte
{
State
}
[Serializable, NetSerializable]
public enum DeployableBarrierState : byte
{
Idle,
Deployed
}
}

View File

@@ -0,0 +1,55 @@
- type: entity
name: deployable barrier
id: DeployableBarrier
description: A deployable barrier. Swipe your ID card to lock/unlock it.
parent: BaseStructure
components:
- type: Sprite
sprite: Objects/Specific/Security/barrier.rsi
netsync: false
state: idle
- type: InteractionOutline
- type: Physics
fixtures:
- shape:
!type:PhysShapeCircle
radius: 0.45
layer:
- Opaque
- Impassable
- VaultImpassable
- SmallImpassable
mask:
- Impassable
mass: 150
- type: AccessReader
access: [["Security"]]
- type: Lock
locked: false
lockOnClick: true # toggle lock just by clicking on barrier
- type: DeployableBarrier
- type: Damageable
resistances: metallicResistances
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 300
behaviors:
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel:
min: 5
max: 5
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/metalbreak.ogg
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: PointLight
enabled: false
radius: 3
color: red
- type: Appearance
visuals:
- type: DeployableBarrierVisualizer

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

View File

@@ -0,0 +1,26 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"license": "CC-BY-SA-3.0",
"copyright": "Taken from cev-eris at https://github.com/discordia-space/CEV-Eris/commit/476e374cea95ff5e8b1603c48342bf700e2cd7af",
"states": [
{
"name": "idle"
},
{
"name": "deployed",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.5
]
]
}
]
}