Secure lockers & locker welding.

This commit is contained in:
Pieter-Jan Briers
2020-05-25 13:58:56 +02:00
parent cb9ec58c15
commit 8794381697
9 changed files with 305 additions and 19 deletions

View File

@@ -59,11 +59,32 @@ namespace Content.Client.GameObjects.Components.Storage
sprite.LayerSetState(StorageVisualLayers.Door, open
? _stateOpen ?? $"{_stateBase}_open"
: _stateClosed ?? $"{_stateBase}_door");
if (component.TryGetData(StorageVisuals.CanLock, out bool canLock) && canLock)
{
if (!component.TryGetData(StorageVisuals.Locked, out bool locked))
{
locked = true;
}
sprite.LayerSetVisible(StorageVisualLayers.Lock, !open);
if (!open)
{
sprite.LayerSetState(StorageVisualLayers.Lock, locked ? "locked" : "unlocked");
}
}
if (component.TryGetData(StorageVisuals.Welded, out bool weldedVal))
{
sprite.LayerSetVisible(StorageVisualLayers.Welded, weldedVal);
}
}
}
public enum StorageVisualLayers
{
Door
Door,
Welded,
Lock
}
}

View File

@@ -1,18 +1,22 @@
using System;
using System.Linq;
using Content.Server.GameObjects.Components.Interactable;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Sound;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Utility;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.Interfaces;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -22,18 +26,26 @@ namespace Content.Server.GameObjects.Components
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IStorageComponent))]
public class EntityStorageComponent : Component, IActivate, IStorageComponent
public class EntityStorageComponent : Component, IActivate, IStorageComponent, IInteractUsing
{
public override string Name => "EntityStorage";
private const float MaxSize = 1.0f; // maximum width or height of an entity allowed inside the storage.
private static readonly TimeSpan InternalOpenAttemptDelay = TimeSpan.FromSeconds(0.5);
private TimeSpan _lastInternalOpenAttempt;
[ViewVariables]
private int StorageCapacityMax;
[ViewVariables]
private bool IsCollidableWhenOpen;
[ViewVariables]
private Container Contents;
[ViewVariables]
private IEntityQuery entityQuery;
private bool _showContents;
private bool _open;
private bool _isWeldedShut;
/// <summary>
/// Determines if the container contents should be drawn when the container is closed.
@@ -49,6 +61,31 @@ namespace Content.Server.GameObjects.Components
}
}
[ViewVariables(VVAccess.ReadWrite)]
public bool Open
{
get => _open;
private set => _open = value;
}
[ViewVariables(VVAccess.ReadWrite)]
public bool IsWeldedShut
{
get => _isWeldedShut;
set
{
_isWeldedShut = value;
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(StorageVisuals.Welded, value);
}
}
}
[ViewVariables(VVAccess.ReadWrite)]
public bool CanWeldShut { get; set; }
/// <inheritdoc />
public override void Initialize()
{
@@ -73,29 +110,30 @@ namespace Content.Server.GameObjects.Components
serializer.DataField(ref IsCollidableWhenOpen, "IsCollidableWhenOpen", false);
serializer.DataField(ref _showContents, "showContents", false);
serializer.DataField(ref _open, "open", false);
}
[ViewVariables(VVAccess.ReadWrite)]
public bool Open
{
get => _open;
private set => _open = value;
serializer.DataField(this, a => a.IsWeldedShut, "IsWeldedShut", false);
serializer.DataField(this, a => a.CanWeldShut, "CanWeldShut", true);
}
public virtual void Activate(ActivateEventArgs eventArgs)
{
ToggleOpen();
ToggleOpen(eventArgs.User);
}
private void ToggleOpen()
protected virtual void ToggleOpen(IEntity user)
{
if (IsWeldedShut)
{
Owner.PopupMessage(user, Loc.GetString("It's welded completely shut!"));
return;
}
if (Open)
{
CloseStorage();
}
else
{
OpenStorage();
TryOpenStorage(user);
}
}
@@ -130,6 +168,7 @@ namespace Content.Server.GameObjects.Components
{
soundComponent.Play("/Audio/machines/closetclose.ogg");
}
_lastInternalOpenAttempt = default;
}
private void OpenStorage()
@@ -238,12 +277,30 @@ namespace Content.Server.GameObjects.Components
case RelayMovementEntityMessage msg:
if (msg.Entity.HasComponent<HandsComponent>())
{
OpenStorage();
var timing = IoCManager.Resolve<IGameTiming>();
if (timing.CurTime <
_lastInternalOpenAttempt + InternalOpenAttemptDelay)
{
break;
}
_lastInternalOpenAttempt = timing.CurTime;
TryOpenStorage(msg.Entity);
}
break;
}
}
protected virtual void TryOpenStorage(IEntity user)
{
if (IsWeldedShut)
{
Owner.PopupMessage(user, Loc.GetString("It's welded completely shut!"));
return;
}
OpenStorage();
}
/// <inheritdoc />
public bool Remove(IEntity entity)
{
@@ -284,14 +341,43 @@ namespace Content.Server.GameObjects.Components
{
protected override void GetData(IEntity user, EntityStorageComponent component, VerbData data)
{
data.Text = component.Open ? "Close" : "Open";
component.OpenVerbGetData(user, component, data);
}
/// <inheritdoc />
protected override void Activate(IEntity user, EntityStorageComponent component)
{
component.ToggleOpen();
}
component.ToggleOpen(user);
}
}
protected virtual void OpenVerbGetData(IEntity user, EntityStorageComponent component, VerbData data)
{
if (IsWeldedShut)
{
data.Visibility = VerbVisibility.Disabled;
var verb = Loc.GetString(component.Open ? "Close" : "Open");
data.Text = Loc.GetString("{0} (welded shut)", verb);
return;
}
data.Text = component.Open ? "Close" : "Open";
}
public bool InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!CanWeldShut)
return false;
if (!eventArgs.Using.TryGetComponent(out WelderComponent tool))
return false;
if (!tool.UseTool(eventArgs.User, Owner, ToolQuality.Welding, 1f))
return false;
IsWeldedShut ^= true;
return true;
}
}
}

View File

@@ -0,0 +1,157 @@
using Content.Server.GameObjects.Components.Access;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.Interfaces;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Items.Storage
{
[RegisterComponent]
[ComponentReference(typeof(EntityStorageComponent))]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IStorageComponent))]
public class SecureEntityStorageComponent : EntityStorageComponent
{
public override string Name => "SecureEntityStorage";
private bool _locked;
[ViewVariables(VVAccess.ReadWrite)]
public bool Locked
{
get => _locked;
set
{
_locked = value;
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(StorageVisuals.Locked, _locked);
}
}
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _locked, "locked", true);
}
protected override void Startup()
{
base.Startup();
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(StorageVisuals.CanLock, true);
}
}
public override void Activate(ActivateEventArgs eventArgs)
{
if (Locked)
{
DoToggleLock(eventArgs.User);
return;
}
base.Activate(eventArgs);
}
protected override void TryOpenStorage(IEntity user)
{
if (Locked)
{
Owner.PopupMessage(user, "It's locked!");
return;
}
base.TryOpenStorage(user);
}
protected override void OpenVerbGetData(IEntity user, EntityStorageComponent component, VerbData data)
{
if (Locked)
{
data.Visibility = VerbVisibility.Invisible;
return;
}
base.OpenVerbGetData(user, component, data);
}
private void DoToggleLock(IEntity user)
{
if (Locked)
{
DoUnlock(user);
}
else
{
DoLock(user);
}
}
private void DoUnlock(IEntity user)
{
if (CheckAccess(user)) return;
Locked = false;
EntitySystem.Get<AudioSystem>().Play("/Audio/machines/door_lock_off.ogg", Owner, AudioParams.Default.WithVolume(-5));
}
private void DoLock(IEntity user)
{
if (CheckAccess(user)) return;
Locked = true;
EntitySystem.Get<AudioSystem>().Play("/Audio/machines/door_lock_on.ogg", Owner, AudioParams.Default.WithVolume(-5));
}
private bool CheckAccess(IEntity user)
{
if (Owner.TryGetComponent(out AccessReader reader))
{
if (!reader.IsAllowed(user))
{
IoCManager.Resolve<IServerNotifyManager>()
.PopupMessage(Owner, user, Loc.GetString("Access denied"));
return true;
}
}
return false;
}
[Verb]
private sealed class ToggleLockVerb : Verb<SecureEntityStorageComponent>
{
protected override void GetData(IEntity user, SecureEntityStorageComponent component, VerbData data)
{
if (component.Open)
{
data.Visibility = VerbVisibility.Invisible;
return;
}
data.Text = component.Locked ? Loc.GetString("Unlock") : Loc.GetString("Lock");
}
protected override void Activate(IEntity user, SecureEntityStorageComponent component)
{
component.DoToggleLock(user);
}
}
}
}

View File

@@ -86,6 +86,9 @@ namespace Content.Shared.GameObjects.Components.Storage
[Serializable]
public enum StorageVisuals
{
Open
Open,
CanLock,
Welded,
Locked
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -2,4 +2,19 @@
id: LockerSecureBase
parent: LockerGeneric
abstract: true
# TODO: Access components and such.
components:
- type: AccessReader
- type: SecureEntityStorage
- type: Sprite
netsync: false
sprite: Buildings/closet.rsi
layers:
- state: generic
- state: generic_door
map: ["enum.StorageVisualLayers.Door"]
- state: locked
map: ["enum.StorageVisualLayers.Lock"]
shader: unshaded
- state: welded
visible: false
map: ["enum.StorageVisualLayers.Welded"]

View File

@@ -10,6 +10,9 @@
- state: generic
- state: generic_door
map: ["enum.StorageVisualLayers.Door"]
- state: welded
visible: false
map: ["enum.StorageVisualLayers.Welded"]
- type: Icon
sprite: Buildings/closet.rsi
state: generic_door

View File

@@ -27,6 +27,7 @@
Anchored: false
- type: EntityStorage
Capacity: 60
CanWeldShut: false
- type: PlaceableSurface
- type: Damageable
- type: Destructible