Secure lockers & locker welding.
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,9 @@ namespace Content.Shared.GameObjects.Components.Storage
|
||||
[Serializable]
|
||||
public enum StorageVisuals
|
||||
{
|
||||
Open
|
||||
Open,
|
||||
CanLock,
|
||||
Welded,
|
||||
Locked
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Resources/Audio/machines/door_lock_off.ogg
Normal file
BIN
Resources/Audio/machines/door_lock_off.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/machines/door_lock_on.ogg
Normal file
BIN
Resources/Audio/machines/door_lock_on.ogg
Normal file
Binary file not shown.
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
Anchored: false
|
||||
- type: EntityStorage
|
||||
Capacity: 60
|
||||
CanWeldShut: false
|
||||
- type: PlaceableSurface
|
||||
- type: Damageable
|
||||
- type: Destructible
|
||||
|
||||
Reference in New Issue
Block a user