item cabinet rework + stuff (#26779)
This commit is contained in:
@@ -1,27 +0,0 @@
|
|||||||
using Content.Shared.Cabinet;
|
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Client.Cabinet;
|
|
||||||
|
|
||||||
public sealed class ItemCabinetSystem : SharedItemCabinetSystem
|
|
||||||
{
|
|
||||||
protected override void UpdateAppearance(EntityUid uid, ItemCabinetComponent? cabinet = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref cabinet))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var state = cabinet.Opened ? cabinet.OpenState : cabinet.ClosedState;
|
|
||||||
if (state != null)
|
|
||||||
sprite.LayerSetState(ItemCabinetVisualLayers.Door, state);
|
|
||||||
sprite.LayerSetVisible(ItemCabinetVisualLayers.ContainsItem, cabinet.CabinetSlot.HasItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ItemCabinetVisualLayers
|
|
||||||
{
|
|
||||||
Door,
|
|
||||||
ContainsItem
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using Content.Shared.Cabinet;
|
|
||||||
|
|
||||||
namespace Content.Server.Cabinet;
|
|
||||||
|
|
||||||
public sealed class ItemCabinetSystem : SharedItemCabinetSystem
|
|
||||||
{
|
|
||||||
// shitposting on main???
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,43 +1,25 @@
|
|||||||
using Content.Shared.Containers.ItemSlots;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Cabinet;
|
namespace Content.Shared.Cabinet;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for entities that can be opened, closed, and can hold one item. E.g., fire extinguisher cabinets.
|
/// Used for entities that can be opened, closed, and can hold one item. E.g., fire extinguisher cabinets.
|
||||||
|
/// Requires <c>OpenableComponent</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
[RegisterComponent, NetworkedComponent, Access(typeof(ItemCabinetSystem))]
|
||||||
public sealed partial class ItemCabinetComponent : Component
|
public sealed partial class ItemCabinetComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sound to be played when the cabinet door is opened.
|
/// Name of the <see cref="ItemSlot"/> that stores the actual item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
[DataField]
|
||||||
public SoundSpecifier? DoorSound;
|
public string Slot = "ItemCabinet";
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="ItemSlot"/> that stores the actual item. The entity whitelist, sounds, and other
|
[Serializable, NetSerializable]
|
||||||
/// behaviours are specified by this <see cref="ItemSlot"/> definition.
|
public enum ItemCabinetVisuals : byte
|
||||||
/// </summary>
|
{
|
||||||
[DataField, ViewVariables]
|
ContainsItem,
|
||||||
public ItemSlot CabinetSlot = new();
|
Layer
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the cabinet is currently open or not.
|
|
||||||
/// </summary>
|
|
||||||
[DataField, AutoNetworkedField]
|
|
||||||
public bool Opened;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The state for when the cabinet is open
|
|
||||||
/// </summary>
|
|
||||||
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public string? OpenState;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The state for when the cabinet is closed
|
|
||||||
/// </summary>
|
|
||||||
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public string? ClosedState;
|
|
||||||
}
|
}
|
||||||
|
|||||||
95
Content.Shared/Cabinet/ItemCabinetSystem.cs
Normal file
95
Content.Shared/Cabinet/ItemCabinetSystem.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using Content.Shared.Containers.ItemSlots;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Nutrition.Components;
|
||||||
|
using Content.Shared.Nutrition.EntitySystems;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Content.Shared.Cabinet;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls ItemCabinet slot locking and visuals.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ItemCabinetSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly ItemSlotsSystem _slots = default!;
|
||||||
|
[Dependency] private readonly OpenableSystem _openable = default!;
|
||||||
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ItemCabinetComponent, ComponentStartup>(OnStartup);
|
||||||
|
SubscribeLocalEvent<ItemCabinetComponent, MapInitEvent>(OnMapInit);
|
||||||
|
SubscribeLocalEvent<ItemCabinetComponent, EntInsertedIntoContainerMessage>(OnContainerModified);
|
||||||
|
SubscribeLocalEvent<ItemCabinetComponent, EntRemovedFromContainerMessage>(OnContainerModified);
|
||||||
|
SubscribeLocalEvent<ItemCabinetComponent, OpenableOpenedEvent>(OnOpened);
|
||||||
|
SubscribeLocalEvent<ItemCabinetComponent, OpenableClosedEvent>(OnClosed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStartup(Entity<ItemCabinetComponent> ent, ref ComponentStartup args)
|
||||||
|
{
|
||||||
|
UpdateAppearance(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMapInit(Entity<ItemCabinetComponent> ent, ref MapInitEvent args)
|
||||||
|
{
|
||||||
|
// update at mapinit to avoid copy pasting locked: true and locked: false for each closed/open prototype
|
||||||
|
SetSlotLock(ent, !_openable.IsOpen(ent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAppearance(Entity<ItemCabinetComponent> ent)
|
||||||
|
{
|
||||||
|
_appearance.SetData(ent, ItemCabinetVisuals.ContainsItem, HasItem(ent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnContainerModified(EntityUid uid, ItemCabinetComponent component, ContainerModifiedMessage args)
|
||||||
|
{
|
||||||
|
if (args.Container.ID == component.Slot)
|
||||||
|
UpdateAppearance((uid, component));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOpened(Entity<ItemCabinetComponent> ent, ref OpenableOpenedEvent args)
|
||||||
|
{
|
||||||
|
SetSlotLock(ent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClosed(Entity<ItemCabinetComponent> ent, ref OpenableClosedEvent args)
|
||||||
|
{
|
||||||
|
SetSlotLock(ent, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to get the cabinet's item slot.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetSlot(Entity<ItemCabinetComponent> ent, [NotNullWhen(true)] out ItemSlot? slot)
|
||||||
|
{
|
||||||
|
slot = null;
|
||||||
|
if (!TryComp<ItemSlotsComponent>(ent, out var slots))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _slots.TryGetSlot(ent, ent.Comp.Slot, out slot, slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the cabinet contains an item.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasItem(Entity<ItemCabinetComponent> ent)
|
||||||
|
{
|
||||||
|
return TryGetSlot(ent, out var slot) && slot.HasItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock or unlock the underlying item slot.
|
||||||
|
/// </summary>
|
||||||
|
public void SetSlotLock(Entity<ItemCabinetComponent> ent, bool closed)
|
||||||
|
{
|
||||||
|
if (!TryComp<ItemSlotsComponent>(ent, out var slots))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_slots.TryGetSlot(ent, ent.Comp.Slot, out var slot, slots))
|
||||||
|
_slots.SetLock(ent, slot, closed, slots);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
using Content.Shared.Containers.ItemSlots;
|
|
||||||
using Content.Shared.Interaction;
|
|
||||||
using Content.Shared.Lock;
|
|
||||||
using Content.Shared.Verbs;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Audio.Systems;
|
|
||||||
using Robust.Shared.Containers;
|
|
||||||
using Robust.Shared.Timing;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Shared.Cabinet;
|
|
||||||
|
|
||||||
public abstract class SharedItemCabinetSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
|
||||||
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
|
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, ComponentInit>(OnComponentInit);
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, ComponentRemove>(OnComponentRemove);
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, ComponentStartup>(OnComponentStartup);
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, AfterAutoHandleStateEvent>(OnComponentHandleState);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, ActivateInWorldEvent>(OnActivateInWorld);
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, GetVerbsEvent<AlternativeVerb>>(AddToggleOpenVerb);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, EntInsertedIntoContainerMessage>(OnContainerModified);
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, EntRemovedFromContainerMessage>(OnContainerModified);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<ItemCabinetComponent, LockToggleAttemptEvent>(OnLockToggleAttempt);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnComponentInit(EntityUid uid, ItemCabinetComponent cabinet, ComponentInit args)
|
|
||||||
{
|
|
||||||
_itemSlots.AddItemSlot(uid, "ItemCabinet", cabinet.CabinetSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnComponentRemove(EntityUid uid, ItemCabinetComponent cabinet, ComponentRemove args)
|
|
||||||
{
|
|
||||||
_itemSlots.RemoveItemSlot(uid, cabinet.CabinetSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnComponentStartup(EntityUid uid, ItemCabinetComponent cabinet, ComponentStartup args)
|
|
||||||
{
|
|
||||||
UpdateAppearance(uid, cabinet);
|
|
||||||
_itemSlots.SetLock(uid, cabinet.CabinetSlot, !cabinet.Opened);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnComponentHandleState(Entity<ItemCabinetComponent> ent, ref AfterAutoHandleStateEvent args)
|
|
||||||
{
|
|
||||||
UpdateAppearance(ent, ent);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void UpdateAppearance(EntityUid uid, ItemCabinetComponent? cabinet = null)
|
|
||||||
{
|
|
||||||
// we don't fuck with appearance data, and instead just manually update the sprite on the client
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnContainerModified(EntityUid uid, ItemCabinetComponent cabinet, ContainerModifiedMessage args)
|
|
||||||
{
|
|
||||||
if (!cabinet.Initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (args.Container.ID == cabinet.CabinetSlot.ID)
|
|
||||||
UpdateAppearance(uid, cabinet);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnLockToggleAttempt(EntityUid uid, ItemCabinetComponent cabinet, ref LockToggleAttemptEvent args)
|
|
||||||
{
|
|
||||||
// Cannot lock or unlock while open.
|
|
||||||
if (cabinet.Opened)
|
|
||||||
args.Cancelled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddToggleOpenVerb(EntityUid uid, ItemCabinetComponent cabinet, GetVerbsEvent<AlternativeVerb> args)
|
|
||||||
{
|
|
||||||
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (TryComp<LockComponent>(uid, out var lockComponent) && lockComponent.Locked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Toggle open verb
|
|
||||||
AlternativeVerb toggleVerb = new()
|
|
||||||
{
|
|
||||||
Act = () => ToggleItemCabinet(uid, args.User, cabinet)
|
|
||||||
};
|
|
||||||
if (cabinet.Opened)
|
|
||||||
{
|
|
||||||
toggleVerb.Text = Loc.GetString("verb-common-close");
|
|
||||||
toggleVerb.Icon =
|
|
||||||
new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/close.svg.192dpi.png"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toggleVerb.Text = Loc.GetString("verb-common-open");
|
|
||||||
toggleVerb.Icon =
|
|
||||||
new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/open.svg.192dpi.png"));
|
|
||||||
}
|
|
||||||
args.Verbs.Add(toggleVerb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnActivateInWorld(EntityUid uid, ItemCabinetComponent comp, ActivateInWorldEvent args)
|
|
||||||
{
|
|
||||||
if (args.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
ToggleItemCabinet(uid, args.User, comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Toggles the ItemCabinet's state.
|
|
||||||
/// </summary>
|
|
||||||
public void ToggleItemCabinet(EntityUid uid, EntityUid? user = null, ItemCabinetComponent? cabinet = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref cabinet))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (TryComp<LockComponent>(uid, out var lockComponent) && lockComponent.Locked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cabinet.Opened = !cabinet.Opened;
|
|
||||||
Dirty(uid, cabinet);
|
|
||||||
_itemSlots.SetLock(uid, cabinet.CabinetSlot, !cabinet.Opened);
|
|
||||||
|
|
||||||
if (_timing.IsFirstTimePredicted)
|
|
||||||
{
|
|
||||||
UpdateAppearance(uid, cabinet);
|
|
||||||
_audio.PlayPredicted(cabinet.DoorSound, uid, user, AudioParams.Default.WithVariation(0.15f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -235,6 +235,7 @@ public sealed class LockSystem : EntitySystem
|
|||||||
return !ev.Cancelled;
|
return !ev.Cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this should be a helper on AccessReaderSystem since so many systems copy paste it
|
||||||
private bool HasUserAccess(EntityUid uid, EntityUid user, AccessReaderComponent? reader = null, bool quiet = true)
|
private bool HasUserAccess(EntityUid uid, EntityUid user, AccessReaderComponent? reader = null, bool quiet = true)
|
||||||
{
|
{
|
||||||
// Not having an AccessComponent means you get free access. woo!
|
// Not having an AccessComponent means you get free access. woo!
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ public sealed partial class OpenableComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool OpenableByHand = true;
|
public bool OpenableByHand = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, tries to open when activated in world.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool OpenOnActivate;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Text shown when examining and its open.
|
/// Text shown when examining and its open.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -58,7 +64,7 @@ public sealed partial class OpenableComponent : Component
|
|||||||
/// Sound played when opening.
|
/// Sound played when opening.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public SoundSpecifier Sound = new SoundCollectionSpecifier("canOpenSounds");
|
public SoundSpecifier? Sound = new SoundCollectionSpecifier("canOpenSounds");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Can this item be closed again after opening?
|
/// Can this item be closed again after opening?
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.Chemistry.EntitySystems;
|
using Content.Shared.Chemistry.EntitySystems;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Lock;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Nutrition.Components;
|
using Content.Shared.Nutrition.Components;
|
||||||
@@ -16,6 +17,7 @@ namespace Content.Shared.Nutrition.EntitySystems;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class OpenableSystem : EntitySystem
|
public sealed partial class OpenableSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly LockSystem _lock = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
@@ -26,26 +28,49 @@ public sealed partial class OpenableSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<OpenableComponent, ComponentInit>(OnInit);
|
SubscribeLocalEvent<OpenableComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<OpenableComponent, UseInHandEvent>(OnUse);
|
SubscribeLocalEvent<OpenableComponent, UseInHandEvent>(OnUse);
|
||||||
|
// always try to unlock first before opening
|
||||||
|
SubscribeLocalEvent<OpenableComponent, ActivateInWorldEvent>(OnActivated, after: new[] { typeof(LockSystem) });
|
||||||
SubscribeLocalEvent<OpenableComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<OpenableComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<OpenableComponent, MeleeHitEvent>(HandleIfClosed);
|
SubscribeLocalEvent<OpenableComponent, MeleeHitEvent>(HandleIfClosed);
|
||||||
SubscribeLocalEvent<OpenableComponent, AfterInteractEvent>(HandleIfClosed);
|
SubscribeLocalEvent<OpenableComponent, AfterInteractEvent>(HandleIfClosed);
|
||||||
SubscribeLocalEvent<OpenableComponent, GetVerbsEvent<Verb>>(AddOpenCloseVerbs);
|
SubscribeLocalEvent<OpenableComponent, GetVerbsEvent<AlternativeVerb>>(OnGetVerbs);
|
||||||
SubscribeLocalEvent<OpenableComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
|
SubscribeLocalEvent<OpenableComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
|
||||||
SubscribeLocalEvent<OpenableComponent, AttemptShakeEvent>(OnAttemptShake);
|
SubscribeLocalEvent<OpenableComponent, AttemptShakeEvent>(OnAttemptShake);
|
||||||
SubscribeLocalEvent<OpenableComponent, AttemptAddFizzinessEvent>(OnAttemptAddFizziness);
|
SubscribeLocalEvent<OpenableComponent, AttemptAddFizzinessEvent>(OnAttemptAddFizziness);
|
||||||
|
SubscribeLocalEvent<OpenableComponent, LockToggleAttemptEvent>(OnLockToggleAttempt);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
SubscribeLocalEvent<OpenableComponent, MapInitEvent>(OnMapInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, OpenableComponent comp, ComponentInit args)
|
private void OnMapInit(Entity<OpenableComponent> ent, ref MapInitEvent args)
|
||||||
{
|
{
|
||||||
UpdateAppearance(uid, comp);
|
if (ent.Comp.Opened && _lock.IsLocked(ent.Owner))
|
||||||
|
Log.Error($"Entity {ent} spawned locked open, this is a prototype mistake.");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private void OnInit(Entity<OpenableComponent> ent, ref ComponentInit args)
|
||||||
|
{
|
||||||
|
UpdateAppearance(ent, ent.Comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUse(EntityUid uid, OpenableComponent comp, UseInHandEvent args)
|
private void OnUse(Entity<OpenableComponent> ent, ref UseInHandEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || !comp.OpenableByHand)
|
if (args.Handled || !ent.Comp.OpenableByHand)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Handled = TryOpen(uid, comp, args.User);
|
args.Handled = TryToggle(ent, args.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnActivated(Entity<OpenableComponent> ent, ref ActivateInWorldEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled || !ent.Comp.OpenOnActivate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Handled = TryToggle(ent, args.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExamined(EntityUid uid, OpenableComponent comp, ExaminedEvent args)
|
private void OnExamined(EntityUid uid, OpenableComponent comp, ExaminedEvent args)
|
||||||
@@ -63,12 +88,12 @@ public sealed partial class OpenableSystem : EntitySystem
|
|||||||
args.Handled = !comp.Opened;
|
args.Handled = !comp.Opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddOpenCloseVerbs(EntityUid uid, OpenableComponent comp, GetVerbsEvent<Verb> args)
|
private void OnGetVerbs(EntityUid uid, OpenableComponent comp, GetVerbsEvent<AlternativeVerb> args)
|
||||||
{
|
{
|
||||||
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
|
if (args.Hands == null || !args.CanAccess || !args.CanInteract || _lock.IsLocked(uid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Verb verb;
|
AlternativeVerb verb;
|
||||||
if (comp.Opened)
|
if (comp.Opened)
|
||||||
{
|
{
|
||||||
if (!comp.Closeable)
|
if (!comp.Closeable)
|
||||||
@@ -78,7 +103,8 @@ public sealed partial class OpenableSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
Text = Loc.GetString(comp.CloseVerbText),
|
Text = Loc.GetString(comp.CloseVerbText),
|
||||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/close.svg.192dpi.png")),
|
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/close.svg.192dpi.png")),
|
||||||
Act = () => TryClose(args.Target, comp, args.User)
|
Act = () => TryClose(args.Target, comp, args.User),
|
||||||
|
// this verb is lower priority than drink verb (2) so it doesn't conflict
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -116,6 +142,13 @@ public sealed partial class OpenableSystem : EntitySystem
|
|||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnLockToggleAttempt(Entity<OpenableComponent> ent, ref LockToggleAttemptEvent args)
|
||||||
|
{
|
||||||
|
// can't lock something while it's open
|
||||||
|
if (ent.Comp.Opened)
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if the entity either does not have OpenableComponent or it is opened.
|
/// Returns true if the entity either does not have OpenableComponent or it is opened.
|
||||||
/// Drinks that don't have OpenableComponent are automatically open, so it returns true.
|
/// Drinks that don't have OpenableComponent are automatically open, so it returns true.
|
||||||
@@ -189,7 +222,12 @@ public sealed partial class OpenableSystem : EntitySystem
|
|||||||
/// <returns>Whether it got opened</returns>
|
/// <returns>Whether it got opened</returns>
|
||||||
public bool TryOpen(EntityUid uid, OpenableComponent? comp = null, EntityUid? user = null)
|
public bool TryOpen(EntityUid uid, OpenableComponent? comp = null, EntityUid? user = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref comp, false) || comp.Opened)
|
if (!Resolve(uid, ref comp, false) || comp.Opened || _lock.IsLocked(uid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var ev = new OpenableOpenAttemptEvent(user);
|
||||||
|
RaiseLocalEvent(uid, ref ev);
|
||||||
|
if (ev.Cancelled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SetOpen(uid, true, comp, user);
|
SetOpen(uid, true, comp, user);
|
||||||
@@ -211,6 +249,18 @@ public sealed partial class OpenableSystem : EntitySystem
|
|||||||
_audio.PlayPredicted(comp.CloseSound, uid, user);
|
_audio.PlayPredicted(comp.CloseSound, uid, user);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If opened, tries closing it if it's closeable.
|
||||||
|
/// If closed, tries opening it.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryToggle(Entity<OpenableComponent> ent, EntityUid? user)
|
||||||
|
{
|
||||||
|
if (ent.Comp.Opened && ent.Comp.Closeable)
|
||||||
|
return TryClose(ent, ent.Comp, user);
|
||||||
|
|
||||||
|
return TryOpen(ent, ent.Comp, user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -224,3 +274,9 @@ public record struct OpenableOpenedEvent(EntityUid? User = null);
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct OpenableClosedEvent(EntityUid? User = null);
|
public record struct OpenableClosedEvent(EntityUid? User = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised before trying to open an Openable.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct OpenableOpenAttemptEvent(EntityUid? User, bool Cancelled = false);
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
- type: entity
|
||||||
|
abstract: true
|
||||||
|
id: BaseItemCabinet
|
||||||
|
components:
|
||||||
|
- type: Openable
|
||||||
|
openOnActivate: true
|
||||||
|
closeable: true
|
||||||
|
sound:
|
||||||
|
path: /Audio/Machines/machine_switch.ogg
|
||||||
|
closeSound:
|
||||||
|
path: /Audio/Machines/machine_switch.ogg
|
||||||
|
- type: ItemCabinet
|
||||||
|
- type: ItemSlots
|
||||||
|
- type: ContainerContainer
|
||||||
|
containers:
|
||||||
|
ItemCabinet: !type:ContainerSlot
|
||||||
|
- type: Appearance
|
||||||
|
# perfect for most things but you can always replace it
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.ItemCabinetVisuals.ContainsItem:
|
||||||
|
enum.ItemCabinetVisuals.Layer:
|
||||||
|
True: { visible: true }
|
||||||
|
False: { visible: false }
|
||||||
|
enum.OpenableVisuals.Opened:
|
||||||
|
enum.OpenableVisuals.Layer:
|
||||||
|
True: { state: open }
|
||||||
|
False: { state: closed }
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
abstract: true
|
||||||
|
parent: BaseItemCabinet
|
||||||
|
id: BaseItemCabinetGlass
|
||||||
|
components:
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.ItemCabinetVisuals.ContainsItem:
|
||||||
|
enum.ItemCabinetVisuals.Layer:
|
||||||
|
True: { visible: true }
|
||||||
|
False: { visible: false }
|
||||||
|
enum.OpenableVisuals.Opened:
|
||||||
|
enum.OpenableVisuals.Layer:
|
||||||
|
True: { state: glass-up }
|
||||||
|
False: { state: glass }
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
|
parent: [BaseStructureDynamic, BaseItemCabinetGlass]
|
||||||
id: BaseGlassBox
|
id: BaseGlassBox
|
||||||
parent: BaseStructureDynamic
|
|
||||||
abstract: true
|
abstract: true
|
||||||
placement:
|
|
||||||
mode: SnapgridCenter
|
|
||||||
components:
|
components:
|
||||||
- type: Transform
|
- type: Transform
|
||||||
anchored: true
|
anchored: true
|
||||||
- type: Physics
|
- type: Physics
|
||||||
bodyType: Static
|
bodyType: Static
|
||||||
- type: Clickable
|
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
fixtures:
|
fixtures:
|
||||||
@@ -23,13 +20,8 @@
|
|||||||
layer:
|
layer:
|
||||||
- MidImpassable
|
- MidImpassable
|
||||||
- LowImpassable
|
- LowImpassable
|
||||||
- type: ItemSlots
|
|
||||||
- type: ContainerContainer
|
|
||||||
containers:
|
|
||||||
ItemCabinet: !type:ContainerSlot
|
|
||||||
- type: Anchorable
|
- type: Anchorable
|
||||||
delay: 4
|
delay: 4
|
||||||
- type: Appearance
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: GlassBox
|
id: GlassBox
|
||||||
@@ -44,10 +36,10 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: base
|
- state: base
|
||||||
- state: caplaser # TODO: Remove it after item scaling in cabinets is implemented.
|
- state: caplaser # TODO: Remove it after item scaling in cabinets is implemented.
|
||||||
map: ["enum.ItemCabinetVisualLayers.ContainsItem"]
|
map: ["enum.ItemCabinetVisuals.Layer"]
|
||||||
visible: true
|
visible: true
|
||||||
- state: glass
|
- state: glass
|
||||||
map: ["enum.ItemCabinetVisualLayers.Door"]
|
map: ["enum.OpenableVisuals.Layer"]
|
||||||
- state: locked
|
- state: locked
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
map: ["enum.LockVisualLayers.Lock"]
|
map: ["enum.LockVisualLayers.Lock"]
|
||||||
@@ -118,49 +110,39 @@
|
|||||||
- type: Construction
|
- type: Construction
|
||||||
graph: GlassBox
|
graph: GlassBox
|
||||||
node: glassBox
|
node: glassBox
|
||||||
- type: ItemCabinet
|
- type: ItemSlots
|
||||||
cabinetSlot:
|
slots:
|
||||||
ejectOnInteract: true
|
ItemCabinet:
|
||||||
whitelist:
|
ejectOnInteract: true
|
||||||
tags:
|
whitelist:
|
||||||
- WeaponAntiqueLaser
|
tags:
|
||||||
doorSound:
|
- WeaponAntiqueLaser
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
ejectSound: /Audio/Machines/machine_switch.ogg
|
||||||
openState: glass-up
|
|
||||||
closedState: glass
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: GlassBoxLaserOpen
|
id: GlassBoxLaserOpen
|
||||||
parent: GlassBoxLaser
|
parent: GlassBoxLaser
|
||||||
suffix: AntiqueLaser, Open
|
suffix: AntiqueLaser, Open
|
||||||
components:
|
components:
|
||||||
|
- type: Openable
|
||||||
|
opened: true
|
||||||
- type: Lock
|
- type: Lock
|
||||||
locked: false
|
locked: false
|
||||||
- type: ItemCabinet
|
|
||||||
opened: true
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: GlassBoxLaserFilled
|
id: GlassBoxLaserFilled
|
||||||
parent: GlassBoxLaser
|
parent: GlassBoxLaser
|
||||||
suffix: AntiqueLaser, Filled
|
suffix: AntiqueLaser, Filled
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: ContainerFill
|
||||||
cabinetSlot:
|
containers:
|
||||||
startingItem: WeaponAntiqueLaser
|
ItemCabinet:
|
||||||
ejectOnInteract: true
|
- WeaponAntiqueLaser
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- WeaponAntiqueLaser
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: [GlassBoxLaserFilled, GlassBoxLaserOpen]
|
||||||
id: GlassBoxLaserFilledOpen
|
id: GlassBoxLaserFilledOpen
|
||||||
parent: GlassBoxLaserFilled
|
|
||||||
suffix: AntiqueLaser, Filled, Open
|
suffix: AntiqueLaser, Filled, Open
|
||||||
components:
|
|
||||||
- type: Lock
|
|
||||||
locked: false
|
|
||||||
- type: ItemCabinet
|
|
||||||
opened: true
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: GlassBoxFrame
|
id: GlassBoxFrame
|
||||||
|
|||||||
@@ -1,100 +1,74 @@
|
|||||||
- type: entity
|
# TODO: same as other wallmount cabinets they should use a base structure prototype
|
||||||
|
- type: entity
|
||||||
|
parent: BaseItemCabinet
|
||||||
id: DefibrillatorCabinet
|
id: DefibrillatorCabinet
|
||||||
name: defibrillator cabinet
|
name: defibrillator cabinet
|
||||||
description: A small wall mounted cabinet designed to hold a defibrillator.
|
description: A small wall mounted cabinet designed to hold a defibrillator.
|
||||||
|
placement:
|
||||||
|
mode: SnapgridCenter
|
||||||
components:
|
components:
|
||||||
- type: WallMount
|
- type: WallMount
|
||||||
arc: 175
|
arc: 175
|
||||||
- type: Transform
|
- type: Transform
|
||||||
anchored: true
|
anchored: true
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Wallmounts/defib_cabinet.rsi
|
sprite: Structures/Wallmounts/defib_cabinet.rsi
|
||||||
noRot: false
|
noRot: false
|
||||||
layers:
|
layers:
|
||||||
- state: frame
|
- state: frame
|
||||||
- state: fill
|
- state: fill
|
||||||
map: ["enum.ItemCabinetVisualLayers.ContainsItem"]
|
map: ["enum.ItemCabinetVisuals.Layer"]
|
||||||
visible: true
|
visible: true
|
||||||
- state: closed
|
- state: closed
|
||||||
map: ["enum.ItemCabinetVisualLayers.Door"]
|
map: ["enum.OpenableVisuals.Layer"]
|
||||||
- type: ItemCabinet
|
- type: ItemSlots
|
||||||
cabinetSlot:
|
slots:
|
||||||
|
ItemCabinet:
|
||||||
ejectOnInteract: true
|
ejectOnInteract: true
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- Defibrillator
|
- Defibrillator
|
||||||
doorSound:
|
- type: Damageable
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
damageContainer: Inorganic
|
||||||
openState: open
|
damageModifierSet: Metallic
|
||||||
closedState: closed
|
- type: Destructible
|
||||||
- type: Appearance
|
thresholds:
|
||||||
- type: ItemSlots
|
- trigger: !type:DamageTrigger
|
||||||
- type: ContainerContainer
|
damage: 80
|
||||||
containers:
|
behaviors:
|
||||||
ItemCabinet: !type:ContainerSlot
|
- !type:DoActsBehavior
|
||||||
- type: Damageable
|
acts: [ "Destruction" ]
|
||||||
damageContainer: Inorganic
|
- trigger: !type:DamageTrigger
|
||||||
damageModifierSet: Metallic
|
damage: 40
|
||||||
- type: Destructible
|
behaviors:
|
||||||
thresholds:
|
- !type:EmptyAllContainersBehaviour
|
||||||
- trigger:
|
- !type:DoActsBehavior
|
||||||
!type:DamageTrigger
|
acts: [ "Destruction" ]
|
||||||
damage: 80
|
- !type:PlaySoundBehavior
|
||||||
behaviors:
|
sound:
|
||||||
- !type:DoActsBehavior
|
collection: MetalGlassBreak
|
||||||
acts: [ "Destruction" ]
|
|
||||||
- trigger:
|
|
||||||
!type:DamageTrigger
|
|
||||||
damage: 40
|
|
||||||
behaviors:
|
|
||||||
- !type:EmptyAllContainersBehaviour
|
|
||||||
- !type:DoActsBehavior
|
|
||||||
acts: [ "Destruction" ]
|
|
||||||
- !type:PlaySoundBehavior
|
|
||||||
sound:
|
|
||||||
collection: MetalGlassBreak
|
|
||||||
placement:
|
|
||||||
mode: SnapgridCenter
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: DefibrillatorCabinetOpen
|
|
||||||
parent: DefibrillatorCabinet
|
parent: DefibrillatorCabinet
|
||||||
|
id: DefibrillatorCabinetOpen
|
||||||
suffix: Open
|
suffix: Open
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: Openable
|
||||||
opened: true
|
opened: true
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: DefibrillatorCabinetFilled
|
|
||||||
parent: DefibrillatorCabinet
|
parent: DefibrillatorCabinet
|
||||||
|
id: DefibrillatorCabinetFilled
|
||||||
suffix: Filled
|
suffix: Filled
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: ContainerFill
|
||||||
cabinetSlot:
|
containers:
|
||||||
ejectOnInteract: true
|
ItemCabinet:
|
||||||
startingItem: Defibrillator
|
- Defibrillator
|
||||||
whitelist:
|
|
||||||
components:
|
|
||||||
- Defibrillator
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: [DefibrillatorCabinetFilled, DefibrillatorCabinetOpen]
|
||||||
id: DefibrillatorCabinetFilledOpen
|
id: DefibrillatorCabinetFilledOpen
|
||||||
parent: DefibrillatorCabinetFilled
|
|
||||||
suffix: Filled, Open
|
suffix: Filled, Open
|
||||||
components:
|
|
||||||
- type: ItemCabinet
|
|
||||||
opened: true
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
- type: entity
|
# TODO: this could probably use some kind of base structure prototype
|
||||||
|
# every wallmount cabinet copypastes placement and like 8 components
|
||||||
|
- type: entity
|
||||||
|
parent: BaseItemCabinet
|
||||||
id: ExtinguisherCabinet
|
id: ExtinguisherCabinet
|
||||||
name: extinguisher cabinet
|
name: extinguisher cabinet
|
||||||
description: A small wall mounted cabinet designed to hold a fire extinguisher.
|
description: A small wall mounted cabinet designed to hold a fire extinguisher.
|
||||||
|
placement:
|
||||||
|
mode: SnapgridCenter
|
||||||
components:
|
components:
|
||||||
- type: WallMount
|
- type: WallMount
|
||||||
arc: 360
|
arc: 360
|
||||||
@@ -15,25 +20,17 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: frame
|
- state: frame
|
||||||
- state: extinguisher
|
- state: extinguisher
|
||||||
map: ["enum.ItemCabinetVisualLayers.ContainsItem"]
|
map: ["enum.ItemCabinetVisuals.Layer"]
|
||||||
visible: true
|
visible: true
|
||||||
- state: closed
|
- state: closed
|
||||||
map: ["enum.ItemCabinetVisualLayers.Door"]
|
map: ["enum.OpenableVisuals.Layer"]
|
||||||
- type: ItemCabinet
|
|
||||||
cabinetSlot:
|
|
||||||
ejectOnInteract: true
|
|
||||||
whitelist:
|
|
||||||
components:
|
|
||||||
- FireExtinguisher
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
- type: Appearance
|
|
||||||
- type: ItemSlots
|
- type: ItemSlots
|
||||||
- type: ContainerContainer
|
slots:
|
||||||
containers:
|
ItemCabinet:
|
||||||
ItemCabinet: !type:ContainerSlot
|
ejectOnInteract: true
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- FireExtinguisher
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: Metallic
|
damageModifierSet: Metallic
|
||||||
@@ -57,46 +54,26 @@
|
|||||||
collection: MetalGlassBreak
|
collection: MetalGlassBreak
|
||||||
params:
|
params:
|
||||||
volume: -4
|
volume: -4
|
||||||
placement:
|
|
||||||
mode: SnapgridCenter
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ExtinguisherCabinetOpen
|
|
||||||
parent: ExtinguisherCabinet
|
parent: ExtinguisherCabinet
|
||||||
|
id: ExtinguisherCabinetOpen
|
||||||
suffix: Open
|
suffix: Open
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: Openable
|
||||||
opened: true
|
opened: true
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ExtinguisherCabinetFilled
|
|
||||||
parent: ExtinguisherCabinet
|
parent: ExtinguisherCabinet
|
||||||
|
id: ExtinguisherCabinetFilled
|
||||||
suffix: Filled
|
suffix: Filled
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: ContainerFill
|
||||||
cabinetSlot:
|
containers:
|
||||||
ejectOnInteract: true
|
ItemCabinet:
|
||||||
startingItem: FireExtinguisher
|
- FireExtinguisher
|
||||||
whitelist:
|
|
||||||
components:
|
|
||||||
- FireExtinguisher
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: [ExtinguisherCabinetFilled, ExtinguisherCabinetOpen]
|
||||||
id: ExtinguisherCabinetFilledOpen
|
id: ExtinguisherCabinetFilledOpen
|
||||||
parent: ExtinguisherCabinetFilled
|
|
||||||
suffix: Filled, Open
|
suffix: Filled, Open
|
||||||
components:
|
|
||||||
- type: ItemCabinet
|
|
||||||
opened: true
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: open
|
|
||||||
closedState: closed
|
|
||||||
|
|||||||
@@ -1,29 +1,33 @@
|
|||||||
|
# TODO: same as fire extinguisher make it use a base structure theres lots of copy paste
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: BaseItemCabinetGlass
|
||||||
id: FireAxeCabinet
|
id: FireAxeCabinet
|
||||||
name: fire axe cabinet
|
name: fire axe cabinet
|
||||||
description: There is a small label that reads "For Emergency use only" along with details for safe use of the axe. As if.
|
description: There is a small label that reads "For Emergency use only" along with details for safe use of the axe. As if.
|
||||||
|
placement:
|
||||||
|
mode: SnapgridCenter
|
||||||
components:
|
components:
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: Glass
|
damageModifierSet: Glass
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
thresholds:
|
thresholds:
|
||||||
- trigger:
|
- trigger:
|
||||||
!type:DamageTrigger
|
!type:DamageTrigger
|
||||||
damage: 300
|
damage: 300
|
||||||
behaviors:
|
behaviors:
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: [ "Destruction" ]
|
acts: [ "Destruction" ]
|
||||||
- trigger:
|
- trigger:
|
||||||
!type:DamageTrigger
|
!type:DamageTrigger
|
||||||
damage: 200 #20ish crowbar hits
|
damage: 200 #20ish crowbar hits
|
||||||
behaviors:
|
behaviors:
|
||||||
- !type:EmptyAllContainersBehaviour
|
- !type:EmptyAllContainersBehaviour
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: [ "Destruction" ]
|
acts: [ "Destruction" ]
|
||||||
- !type:PlaySoundBehavior
|
- !type:PlaySoundBehavior
|
||||||
sound:
|
sound:
|
||||||
collection: MetalGlassBreak
|
collection: MetalGlassBreak
|
||||||
- type: MeleeSound
|
- type: MeleeSound
|
||||||
soundGroups:
|
soundGroups:
|
||||||
Brute:
|
Brute:
|
||||||
@@ -36,68 +40,42 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: cabinet
|
- state: cabinet
|
||||||
- state: fireaxe
|
- state: fireaxe
|
||||||
map: ["enum.ItemCabinetVisualLayers.ContainsItem"]
|
map: ["enum.ItemCabinetVisuals.Layer"]
|
||||||
visible: true
|
visible: true
|
||||||
- state: glass
|
- state: glass
|
||||||
map: ["enum.ItemCabinetVisualLayers.Door"]
|
map: ["enum.OpenableVisuals.Layer"]
|
||||||
- type: ItemCabinet
|
- type: ItemSlots
|
||||||
cabinetSlot:
|
slots:
|
||||||
ejectOnInteract: true
|
ItemCabinet:
|
||||||
whitelist:
|
ejectOnInteract: true
|
||||||
tags:
|
whitelist:
|
||||||
- FireAxe
|
tags:
|
||||||
doorSound:
|
- FireAxe
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: glass-up
|
|
||||||
closedState: glass
|
|
||||||
- type: Appearance
|
|
||||||
- type: Lock
|
- type: Lock
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
access: [["Atmospherics"], ["Command"]]
|
access: [["Atmospherics"], ["Command"]]
|
||||||
- type: ItemSlots
|
|
||||||
- type: ContainerContainer
|
|
||||||
containers:
|
|
||||||
ItemCabinet: !type:ContainerSlot
|
|
||||||
placement:
|
|
||||||
mode: SnapgridCenter
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: FireAxeCabinetOpen
|
|
||||||
parent: FireAxeCabinet
|
parent: FireAxeCabinet
|
||||||
|
id: FireAxeCabinetOpen
|
||||||
suffix: Open
|
suffix: Open
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: Openable
|
||||||
opened: true
|
opened: true
|
||||||
doorSound:
|
- type: Lock
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
locked: false
|
||||||
openState: glass-up
|
|
||||||
closedState: glass
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: FireAxeCabinetFilled
|
|
||||||
parent: FireAxeCabinet
|
parent: FireAxeCabinet
|
||||||
|
id: FireAxeCabinetFilled
|
||||||
suffix: Filled
|
suffix: Filled
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: ContainerFill
|
||||||
cabinetSlot:
|
containers:
|
||||||
startingItem: FireAxe
|
ItemCabinet:
|
||||||
ejectOnInteract: true
|
- FireAxe
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- FireAxe
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: glass-up
|
|
||||||
closedState: glass
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: [FireAxeCabinetFilled, FireAxeCabinetOpen]
|
||||||
id: FireAxeCabinetFilledOpen
|
id: FireAxeCabinetFilledOpen
|
||||||
parent: FireAxeCabinetFilled
|
|
||||||
suffix: Filled, Open
|
suffix: Filled, Open
|
||||||
components:
|
|
||||||
- type: ItemCabinet
|
|
||||||
opened: true
|
|
||||||
doorSound:
|
|
||||||
path: /Audio/Machines/machine_switch.ogg
|
|
||||||
openState: glass-up
|
|
||||||
closedState: glass
|
|
||||||
|
|||||||
@@ -9,39 +9,41 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: cabinet
|
- state: cabinet
|
||||||
- state: shotgun
|
- state: shotgun
|
||||||
map: ["enum.ItemCabinetVisualLayers.ContainsItem"]
|
map: ["enum.ItemCabinetVisuals.Layer"]
|
||||||
visible: true
|
visible: true
|
||||||
- state: glass
|
- state: glass
|
||||||
map: ["enum.ItemCabinetVisualLayers.Door"]
|
map: ["enum.OpenableVisuals.Layer"]
|
||||||
- type: ItemCabinet
|
- type: ItemSlots
|
||||||
cabinetSlot:
|
slots:
|
||||||
ejectOnInteract: true
|
ItemCabinet:
|
||||||
whitelist:
|
ejectOnInteract: true
|
||||||
tags:
|
whitelist:
|
||||||
- WeaponShotgunKammerer
|
tags:
|
||||||
|
- WeaponShotgunKammerer
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
access: [["Security"], ["Command"]]
|
access: [["Security"], ["Command"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: ShotGunCabinet
|
||||||
id: ShotGunCabinetOpen
|
id: ShotGunCabinetOpen
|
||||||
parent: [ShotGunCabinet, FireAxeCabinetOpen]
|
|
||||||
suffix: Open
|
suffix: Open
|
||||||
|
components:
|
||||||
|
- type: Openable
|
||||||
|
opened: true
|
||||||
|
- type: Lock
|
||||||
|
locked: false
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: ShotGunCabinet
|
||||||
id: ShotGunCabinetFilled
|
id: ShotGunCabinetFilled
|
||||||
parent: [ShotGunCabinet,FireAxeCabinetFilled]
|
|
||||||
suffix: Filled
|
suffix: Filled
|
||||||
components:
|
components:
|
||||||
- type: ItemCabinet
|
- type: ContainerFill
|
||||||
cabinetSlot:
|
containers:
|
||||||
startingItem: WeaponShotgunKammerer
|
ItemCabinet:
|
||||||
ejectOnInteract: true
|
- WeaponShotgunKammerer
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- WeaponShotgunKammerer
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
parent: [ShotGunCabinetFilled, ShotGunCabinetOpen]
|
||||||
id: ShotGunCabinetFilledOpen
|
id: ShotGunCabinetFilledOpen
|
||||||
parent: [ShotGunCabinetFilled,FireAxeCabinetFilledOpen]
|
|
||||||
suffix: Filled, Open
|
suffix: Filled, Open
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user