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 sprite.LayerSetState(StorageVisualLayers.Door, open
? _stateOpen ?? $"{_stateBase}_open" ? _stateOpen ?? $"{_stateBase}_open"
: _stateClosed ?? $"{_stateBase}_door"); : _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 public enum StorageVisualLayers
{ {
Door Door,
Welded,
Lock
} }
} }

View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -2,4 +2,19 @@
id: LockerSecureBase id: LockerSecureBase
parent: LockerGeneric parent: LockerGeneric
abstract: true 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
- state: generic_door - state: generic_door
map: ["enum.StorageVisualLayers.Door"] map: ["enum.StorageVisualLayers.Door"]
- state: welded
visible: false
map: ["enum.StorageVisualLayers.Welded"]
- type: Icon - type: Icon
sprite: Buildings/closet.rsi sprite: Buildings/closet.rsi
state: generic_door state: generic_door

View File

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