diff --git a/Content.Server/Chat/Systems/ChatSystem.Radio.cs b/Content.Server/Chat/Systems/ChatSystem.Radio.cs
index 172ac780fd..1a18ac4bb5 100644
--- a/Content.Server/Chat/Systems/ChatSystem.Radio.cs
+++ b/Content.Server/Chat/Systems/ChatSystem.Radio.cs
@@ -67,8 +67,8 @@ public sealed partial class ChatSystem
// Redirect to defaultChannel of headsetComp if it goes to "h" channel code after making sure defaultChannel exists
if (message[1] == 'h'
&& _headsetComponent != null
- && _headsetComponent.defaultChannel != null
- && _prototypeManager.TryIndex(_headsetComponent.defaultChannel, out RadioChannelPrototype? protoDefaultChannel))
+ && _headsetComponent.DefaultChannel != null
+ && _prototypeManager.TryIndex(_headsetComponent.DefaultChannel, out RadioChannelPrototype? protoDefaultChannel))
{
// Set Channel to headset defaultChannel
channel = protoDefaultChannel;
diff --git a/Content.Server/Radio/Components/HeadsetComponent.cs b/Content.Server/Radio/Components/HeadsetComponent.cs
index caf09fe875..fb9ee9a247 100644
--- a/Content.Server/Radio/Components/HeadsetComponent.cs
+++ b/Content.Server/Radio/Components/HeadsetComponent.cs
@@ -1,11 +1,12 @@
using Content.Server.Radio.EntitySystems;
using Content.Shared.Inventory;
using Content.Shared.Radio;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+using Content.Shared.Tools;
+using Robust.Shared.Audio;
+using Robust.Shared.Containers;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Radio.Components;
-
///
/// This component relays radio messages to the parent entity's chat when equipped.
///
@@ -13,17 +14,52 @@ namespace Content.Server.Radio.Components;
[Access(typeof(HeadsetSystem))]
public sealed class HeadsetComponent : Component
{
- [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))]
- public readonly HashSet Channels = new() { "Common" };
+ ///
+ /// This variable indicates locked state of encryption keys, allowing or prohibiting inserting and removing of encryption keys from headset.
+ /// true => User are able to remove encryption keys with tool mentioned in KeysExtractionMethod, and put encryption keys in headset.
+ /// false => encryption keys are locked in headset, they can't be properly removed or added.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("isKeysUnlocked")]
+ public bool IsKeysUnlocked = true;
+ ///
+ /// Shows which tool a person should use to extract the encryption keys from the headset.
+ /// default "Screwing"
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("keysExtractionMethod", customTypeSerializer: typeof(PrototypeIdSerializer))]
+ public string KeysExtractionMethod = "Screwing";
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("keySlots")]
+ public int KeySlots = 2;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("keyExtractionSound")]
+ public SoundSpecifier KeyExtractionSound = new SoundPathSpecifier("/Audio/Items/pistol_magout.ogg");
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("keyInsertionSound")]
+ public SoundSpecifier KeyInsertionSound = new SoundPathSpecifier("/Audio/Items/pistol_magin.ogg");
+
+ [ViewVariables]
+ public Container KeyContainer = default!;
+ public const string KeyContainerName = "key_slots";
+
+ [ViewVariables]
+ public HashSet Channels = new();
// Maybe make the defaultChannel an actual channel type some day, and use that for parsing messages
// [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))]
// public readonly HashSet defaultChannel = new();
-
-
- [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdSerializer))]
- public readonly string? defaultChannel;
+ ///
+ /// This variable defines what channel will be used with using ":h" (department channel prefix).
+ /// Headset read DefaultChannel of first encryption key installed.
+ /// Do not change this variable from headset or VV, better change encryption keys and UpdateDefaultChannel.
+ ///
+ [ViewVariables(VVAccess.ReadOnly)]
+ public string? DefaultChannel;
[DataField("enabled")]
public bool Enabled = true;
diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs
index f8ae3503e2..f4b0585a30 100644
--- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs
+++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs
@@ -1,11 +1,18 @@
using Content.Server.Chat.Systems;
-using Content.Server.Radio.Components;
+using Content.Server.Popups;
+using Content.Server.Tools;
+using Content.Shared.Tools.Components;
using Content.Shared.Examine;
+using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Radio;
+using Content.Server.Radio.Components;
using Robust.Server.GameObjects;
+using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
+using System.Linq;
+using Robust.Shared.Profiling;
namespace Content.Server.Radio.EntitySystems;
@@ -14,6 +21,10 @@ public sealed class HeadsetSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly INetManager _netMan = default!;
[Dependency] private readonly RadioSystem _radio = default!;
+ [Dependency] private readonly ToolSystem _toolSystem = default!;
+ [Dependency] private readonly PopupSystem _popupSystem = default!;
+ [Dependency] private readonly SharedContainerSystem _container = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
public override void Initialize()
{
@@ -23,6 +34,10 @@ public sealed class HeadsetSystem : EntitySystem
SubscribeLocalEvent(OnGotEquipped);
SubscribeLocalEvent(OnGotUnequipped);
SubscribeLocalEvent(OnSpeak);
+
+ SubscribeLocalEvent(OnStartup);
+ SubscribeLocalEvent(OnInteractUsing);
+ SubscribeLocalEvent(OnContainerInserted);
}
private void OnSpeak(EntityUid uid, WearingHeadsetComponent component, EntitySpokeEvent args)
@@ -43,10 +58,15 @@ public sealed class HeadsetSystem : EntitySystem
if (component.IsEquipped && component.Enabled)
{
EnsureComp(args.Equipee).Headset = uid;
- EnsureComp(uid).Channels.UnionWith(component.Channels);
+ PushRadioChannelsToOwner(uid, component, EnsureComp(uid));
}
}
+ private void PushRadioChannelsToOwner(EntityUid uid, HeadsetComponent component, ActiveRadioComponent activeRadio)
+ {
+ activeRadio.Channels.UnionWith(component.Channels);
+ }
+
private void OnGotUnequipped(EntityUid uid, HeadsetComponent component, GotUnequippedEvent args)
{
component.IsEquipped = false;
@@ -86,21 +106,127 @@ public sealed class HeadsetSystem : EntitySystem
{
if (!args.IsInDetailsRange)
return;
-
- args.PushMarkup(Loc.GetString("examine-headset"));
-
- foreach (var id in component.Channels)
+ if (component.KeyContainer.ContainedEntities.Count == 0)
{
- if (id == "Common") continue;
-
- var proto = _protoManager.Index(id);
- args.PushMarkup(Loc.GetString("examine-headset-channel",
- ("color", proto.Color),
- ("key", proto.KeyCode),
- ("id", proto.LocalizedName),
- ("freq", proto.Frequency)));
+ args.PushMarkup(Loc.GetString("examine-headset-no-keys"));
+ return;
}
+ else if (component.Channels.Count > 0)
+ {
+ args.PushMarkup(Loc.GetString("examine-headset-channels-prefix"));
+ EncryptionKeySystem.GetChannelsExamine(component.Channels, args, _protoManager, "examine-headset-channel");
+ args.PushMarkup(Loc.GetString("examine-headset-chat-prefix", ("prefix", ":h")));
+ if (component.DefaultChannel != null)
+ {
+ var proto = _protoManager.Index(component.DefaultChannel);
+ args.PushMarkup(Loc.GetString("examine-headset-default-channel", ("channel", component.DefaultChannel), ("color", proto.Color)));
+ }
+ }
+ }
- args.PushMarkup(Loc.GetString("examine-headset-chat-prefix", ("prefix", ";")));
+ private void OnStartup(EntityUid uid, HeadsetComponent component, ComponentStartup args)
+ {
+ component.KeyContainer = _container.EnsureContainer(uid, HeadsetComponent.KeyContainerName);
+ }
+
+ private bool InstallKey(HeadsetComponent component, EntityUid key, EncryptionKeyComponent keyComponent)
+ {
+ if (component.KeyContainer.Insert(key))
+ {
+ UploadChannelsFromKey(component, keyComponent);
+ return true;
+ }
+ return false;
+ }
+
+ private void UploadChannelsFromKey(HeadsetComponent component, EncryptionKeyComponent key)
+ {
+ foreach (var j in key.Channels)
+ component.Channels.Add(j);
+ }
+
+ public void RecalculateChannels(HeadsetComponent component)
+ {
+ component.Channels.Clear();
+ foreach (EntityUid i in component.KeyContainer.ContainedEntities)
+ {
+ if (TryComp(i, out var key))
+ {
+ UploadChannelsFromKey(component, key);
+ }
+ }
+ }
+
+ private void OnInteractUsing(EntityUid uid, HeadsetComponent component, InteractUsingEvent args)
+ {
+ if (!TryComp(uid, out var storage))
+ return;
+ if(!component.IsKeysUnlocked)
+ {
+ _popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-are-locked"), uid, args.User);
+ return;
+ }
+ if (TryComp(args.Used, out var key))
+ {
+ if (component.KeySlots > component.KeyContainer.ContainedEntities.Count)
+ {
+ if (InstallKey(component, args.Used, key))
+ {
+ _popupSystem.PopupEntity(Loc.GetString("headset-encryption-key-successfully-installed"), uid, args.User);
+ _audio.PlayPvs(component.KeyInsertionSound, args.Target);
+ }
+ }
+ else
+ {
+ _popupSystem.PopupEntity(Loc.GetString("headset-encryption-key-slots-already-full"), uid, args.User);
+ }
+ }
+ if (TryComp(args.Used, out var tool))
+ {
+ if (component.KeyContainer.ContainedEntities.Count > 0)
+ {
+ if (_toolSystem.UseTool(
+ args.Used, args.User, uid,
+ 0f, 0f, new String[] { component.KeysExtractionMethod },
+ doAfterCompleteEvent: null, toolComponent: tool)
+ )
+ {
+ var contained = component.KeyContainer.ContainedEntities.ToArray();
+ foreach (var i in contained)
+ component.KeyContainer.Remove(i);
+ component.Channels.Clear();
+ UpdateDefaultChannel(component);
+ _popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-all-extracted"), uid, args.User);
+ _audio.PlayPvs(component.KeyExtractionSound, args.Target);
+ }
+ }
+ else
+ {
+ _popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-no-keys"), uid, args.User);
+ }
+ }
+ }
+
+ private void UpdateDefaultChannel(HeadsetComponent component)
+ {
+ if (component.KeyContainer.ContainedEntities.Count >= 1)
+ component.DefaultChannel = EnsureComp(component.KeyContainer.ContainedEntities[0])?.DefaultChannel;
+ else
+ component.DefaultChannel = null;
+ }
+
+ private void OnContainerInserted(EntityUid uid, HeadsetComponent component, EntInsertedIntoContainerMessage args)
+ {
+ if (args.Container.ID != HeadsetComponent.KeyContainerName)
+ {
+ return;
+ }
+ if (TryComp(args.Entity, out var added))
+ {
+ UpdateDefaultChannel(component);
+ UploadChannelsFromKey(component, added);
+ PushRadioChannelsToOwner(uid, component, EnsureComp(uid));
+ }
+ return;
}
}
diff --git a/Content.Shared/Radio/EncryptionKeyComponent.cs b/Content.Shared/Radio/EncryptionKeyComponent.cs
new file mode 100644
index 0000000000..9fcd649a40
--- /dev/null
+++ b/Content.Shared/Radio/EncryptionKeyComponent.cs
@@ -0,0 +1,23 @@
+using Content.Shared.Radio;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+
+namespace Content.Server.Radio.Components;
+///
+/// This component is currently used for providing access to channels for "HeadsetComponent"s.
+/// It should be used for intercoms and other radios in future.
+///
+[RegisterComponent]
+public sealed class EncryptionKeyComponent : Component
+{
+ [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))]
+ public HashSet Channels = new();
+
+
+ ///
+ /// This variable defines what channel will be used with using ":h" (department channel prefix).
+ /// Headset read DefaultChannel of first encryption key installed.
+ ///
+ [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdSerializer))]
+ public readonly string? DefaultChannel;
+}
diff --git a/Content.Shared/Radio/EncryptionKeySystem.cs b/Content.Shared/Radio/EncryptionKeySystem.cs
new file mode 100644
index 0000000000..37bd5c7670
--- /dev/null
+++ b/Content.Shared/Radio/EncryptionKeySystem.cs
@@ -0,0 +1,55 @@
+using Content.Server.Radio.Components;
+using Content.Shared.Examine;
+using Content.Shared.Radio;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Radio.EntitySystems;
+
+public sealed class EncryptionKeySystem : EntitySystem
+{
+ [Dependency] private readonly IPrototypeManager _protoManager = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent(OnExamined);
+ }
+
+ private void OnExamined(EntityUid uid, EncryptionKeyComponent component, ExaminedEvent args)
+ {
+ if (!args.IsInDetailsRange)
+ return;
+ if(component.Channels.Count > 0)
+ {
+ args.PushMarkup(Loc.GetString("examine-encryption-key-channels-prefix"));
+ EncryptionKeySystem.GetChannelsExamine(component.Channels, args, _protoManager, "examine-headset-channel");
+ if (component.DefaultChannel != null)
+ {
+ var proto = _protoManager.Index(component.DefaultChannel);
+ args.PushMarkup(Loc.GetString("examine-encryption-key-default-channel", ("channel", component.DefaultChannel), ("color", proto.Color)));
+ }
+ }
+ }
+
+ ///
+ /// A static method for formating list of radio channels for examine events.
+ ///
+ /// HashSet of channels in headset, encryptionkey or etc.
+ /// IPrototypeManager for getting prototypes of channels with their variables.
+ /// String that provide id of pattern in .ftl files to format channel with variables of it.
+ public static void GetChannelsExamine(HashSet channels, ExaminedEvent examineEvent, IPrototypeManager protoManager, string channelFTLPattern)
+ {
+ foreach (var id in channels)
+ {
+ var proto = protoManager.Index(id);
+ string keyCode = "" + proto.KeyCode;
+ if (id != "Common")
+ keyCode = ":" + keyCode;
+ examineEvent.PushMarkup(Loc.GetString(channelFTLPattern,
+ ("color", proto.Color),
+ ("key", keyCode),
+ ("id", proto.LocalizedName),
+ ("freq", proto.Frequency)));
+ }
+ }
+}
diff --git a/Resources/Locale/en-US/headset/headset-component.ftl b/Resources/Locale/en-US/headset/headset-component.ftl
index 44795011ef..bf68eb4260 100644
--- a/Resources/Locale/en-US/headset/headset-component.ftl
+++ b/Resources/Locale/en-US/headset/headset-component.ftl
@@ -1,12 +1,22 @@
# Chat window radio wrap (prefix and postfix)
chat-radio-message-wrap = [color={$color}]{$channel} {$name} says: "{$message}"[/color]
+headset-encryption-key-successfully-installed = You put the key into the headset.
+headset-encryption-key-slots-already-full = There is no place for another key.
+headset-encryption-keys-all-extracted = You pop out the encryption keys from the headset!
+headset-encryption-keys-no-keys = This headset has no encryption keys!
+headset-encryption-keys-are-locked = The headset's key slots are locked, you cannot add or remove any keys.
+
+examine-encryption-key-channels-prefix = It is providing these frequencies to the headset:
+
examine-radio-frequency = It's set to broadcast over the {$frequency} frequency.
-examine-headset = A small screen on the headset displays the following available frequencies:
-examine-headset-channel = [color={$color}]:{$key} for {$id} ({$freq})[/color]
-
-examine-headset-chat-prefix = Use {$prefix} for the currently tuned frequency.
+examine-headset-channels-prefix = A small screen on the headset displays the following available frequencies:
+examine-headset-channel = [color={$color}]{$key} for {$id} ({$freq})[/color]
+examine-headset-no-keys = It seems broken. There are no encryption keys in it.
+examine-headset-chat-prefix = Use this {$prefix} for your department's frequency.
+examine-headset-default-channel = It's indicates that default channel of this headset is [color={$color}]{$channel}[/color].
+examine-encryption-key-default-channel = It's seems like [color={$color}]{$channel}[/color] is a default channel.
chat-radio-common = Common
chat-radio-centcom = CentCom
diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl
index 1e14c889a6..28fa900bc8 100644
--- a/Resources/Locale/en-US/store/uplink-catalog.ftl
+++ b/Resources/Locale/en-US/store/uplink-catalog.ftl
@@ -76,7 +76,10 @@ uplink-stealth-box-name = Stealth Box
uplink-stealth-box-desc = A box outfitted with stealth technology, sneak around with this and don't move too fast now!
uplink-headset-name = Syndicate Over-ear Headset
-uplink-headset-desc = A headset that allows you to listen in on departmental channels, or contact other traitors.
+uplink-headset-desc = A headset that allows you to communicate with other syndicate operatives. Has 4 slots for encryption keys.
+
+uplink-encryption-key-name = Syndicate Encryption Key
+uplink-encryption-key-desc = An encryption key for access to the secret frequency of our special agents. No one will know about your special channel with friends... or rivals.
uplink-hypopen-name = Hypopen
uplink-hypopen-desc = A chemical hypospray disguised as a pen, capable of instantly injecting up to 15u of reagents. Starts empty.
diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml
index 811e76d66e..5aae9b79ba 100644
--- a/Resources/Prototypes/Catalog/uplink_catalog.yml
+++ b/Resources/Prototypes/Catalog/uplink_catalog.yml
@@ -268,16 +268,26 @@
categories:
- UplinkUtility
-#TODO: Increase the price of this to 4-5/remove it when we get encrpytion keys
+#TODO: Increase the price to 4 when flashbang prof.
- type: listing
id: UplinkHeadset
name: uplink-headset-name
description: uplink-headset-desc
productEntity: ClothingHeadsetAltSyndicate
cost:
- Telecrystal: 2 # next step is adding encryption keys
+ Telecrystal: 4
categories:
- - UplinkUtility
+ - UplinkUtility
+
+- type: listing
+ id: UplinkHeadsetEncryptionKey
+ name: uplink-encryption-key-name
+ description: uplink-encryption-key-desc
+ productEntity: EncryptionKeySyndie
+ cost:
+ Telecrystal: 2
+ categories:
+ - UplinkUtility
- type: listing
id: UplinkHypopen
diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml
index 44448d298f..8dc10add35 100644
--- a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml
+++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml
@@ -5,7 +5,15 @@
name: headset
description: An updated, modular intercom that fits over the head. Takes encryption keys.
components:
+ - type: ContainerContainer
+ containers:
+ key_slots: !type:Container
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCommon
- type: Headset
+ keysExtractionMethod: Screwing
- type: Sprite
state: icon
- type: Clothing
@@ -13,38 +21,50 @@
- ears
sprite: Clothing/Ears/Headsets/base.rsi
+- type: entity
+ parent: ClothingHeadset
+ id: ClothingHeadsetGrey
+ name: passenger headset
+ components:
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/base.rsi
+
- type: entity
parent: ClothingHeadset
id: ClothingHeadsetCargo
name: cargo headset
description: A headset used by supply employees.
components:
- - type: Headset
- channels:
- - Common
- - Supply
- defaultChannel: Supply
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCargo
- type: Sprite
sprite: Clothing/Ears/Headsets/cargo.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/cargo.rsi
- type: entity
- parent: ClothingHeadset
+ parent: ClothingHeadsetCargo
+ id: ClothingHeadsetMining
+ name: mining headset
+ description: Headset used by shaft miners.
+ components:
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/mining.rsi
+ - type: Clothing
+ sprite: Clothing/Ears/Headsets/mining.rsi
+
+- type: entity
+ parent: ClothingHeadsetCargo
id: ClothingHeadsetQM
name: qm headset
description: A headset used by the quartermaster.
components:
- - type: Headset
- channels:
- - Command
- - Common
- - Supply
- defaultChannel: Supply
- - type: Sprite
- sprite: Clothing/Ears/Headsets/cargo.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/cargo.rsi
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyQM
- type: entity
parent: ClothingHeadset
@@ -52,18 +72,10 @@
name: CentCom headset
description: A headset used by the upper echelons of Nanotrasen.
components:
- - type: Headset
- channels:
- - Common
- - Command
- - CentCom
- - Engineering
- - Medical
- - Science
- - Security
- - Service
- - Supply
- defaultChannel: CentCom
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCentCom
- type: Sprite
sprite: Clothing/Ears/Headsets/centcom.rsi
- type: Clothing
@@ -75,17 +87,10 @@
name: command headset
description: A headset with a commanding channel.
components:
- - type: Headset
- channels:
- - Common
- - Command
- - Engineering
- - Medical
- - Science
- - Security
- - Service
- - Supply
- defaultChannel: Command
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCommand
- type: Sprite
sprite: Clothing/Ears/Headsets/command.rsi
- type: Clothing
@@ -97,32 +102,25 @@
name: engineering headset
description: A headset for engineers to chat while the station burns around them.
components:
- - type: Headset
- channels:
- - Common
- - Engineering
- defaultChannel: Engineering
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyEngineering
- type: Sprite
sprite: Clothing/Ears/Headsets/engineering.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/engineering.rsi
- type: entity
- parent: ClothingHeadset
+ parent: ClothingHeadsetEngineering
id: ClothingHeadsetCE
name: ce headset
description: A headset for the chief engineer to ignore all emergency calls on.
components:
- - type: Headset
- channels:
- - Command
- - Common
- - Engineering
- defaultChannel: Engineering
- - type: Sprite
- sprite: Clothing/Ears/Headsets/engineering.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/engineering.rsi
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCE
- type: entity
parent: ClothingHeadset
@@ -130,97 +128,70 @@
name: medical headset
description: A headset for the trained staff of the medbay.
components:
- - type: Headset
- channels:
- - Common
- - Medical
- defaultChannel: Medical
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyMedical
- type: Sprite
sprite: Clothing/Ears/Headsets/medical.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/medical.rsi
-- type: entity
- parent: ClothingHeadset
- id: ClothingHeadsetMedicalScience
- name: medical research headset
- description: A headset that is a result of the mating between medical and science.
- components:
- - type: Headset
- channels:
- - Common
- - Medical
- - Science
- defaultChannel: Science
- - type: Sprite
- sprite: Clothing/Ears/Headsets/medicalscience.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/medicalscience.rsi
-
-- type: entity
- parent: ClothingHeadset
- id: ClothingHeadsetMining
- name: mining headset
- description: Headset used by shaft miners.
- components:
- - type: Headset
- channels:
- - Common
- - Supply
- defaultChannel: Supply
- - type: Sprite
- sprite: Clothing/Ears/Headsets/mining.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/mining.rsi
-
-- type: entity
- parent: ClothingHeadset
- id: ClothingHeadsetRobotics
- name: robotics headset
- description: Made specifically for the roboticists, who cannot decide between departments.
- components:
- - type: Headset
- channels:
- - Common
- - Science
- defaultChannel: Science
- - type: Sprite
- sprite: Clothing/Ears/Headsets/robotics.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/robotics.rsi
-
- type: entity
parent: ClothingHeadset
id: ClothingHeadsetScience
name: science headset
description: A sciency headset. Like usual.
components:
- - type: Headset
- channels:
- - Common
- - Science
- defaultChannel: Science
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyScience
- type: Sprite
sprite: Clothing/Ears/Headsets/science.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/science.rsi
- type: entity
- parent: ClothingHeadset
+ parent: ClothingHeadsetScience
+ id: ClothingHeadsetMedicalScience
+ name: medical research headset
+ description: A headset that is a result of the mating between medical and science.
+ components:
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyMedicalScience
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/medicalscience.rsi
+ - type: Clothing
+ sprite: Clothing/Ears/Headsets/medicalscience.rsi
+
+- type: entity
+ parent: ClothingHeadsetScience
+ id: ClothingHeadsetRobotics
+ name: robotics headset
+ description: Made specifically for the roboticists, who cannot decide between departments.
+ components:
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyRobo
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/robotics.rsi
+ - type: Clothing
+ sprite: Clothing/Ears/Headsets/robotics.rsi
+
+- type: entity
+ parent: ClothingHeadsetScience
id: ClothingHeadsetRD
name: rd headset
description: Lamarr used to love chewing on this...
components:
- - type: Headset
- channels:
- - Command
- - Common
- - Science
- defaultChannel: Science
- - type: Sprite
- sprite: Clothing/Ears/Headsets/science.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/science.rsi
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyRD
- type: entity
parent: ClothingHeadset
@@ -228,11 +199,10 @@
name: security headset
description: This is used by your elite security force.
components:
- - type: Headset
- channels:
- - Common
- - Security
- defaultChannel: Security
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeySecurity
- type: Sprite
sprite: Clothing/Ears/Headsets/security.rsi
- type: Clothing
@@ -244,25 +214,12 @@
name: service headset
description: Headset used by the service staff, tasked with keeping the station full, happy and clean.
components:
- - type: Headset
- channels:
- - Common
- - Service
- defaultChannel: Service
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyService
- type: Sprite
sprite: Clothing/Ears/Headsets/service.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/service.rsi
-- type: entity
- parent: ClothingHeadset
- id: ClothingHeadsetGrey
- name: passenger headset
- description: An updated, modular intercom that fits over the head. Takes encryption keys.
- components:
- - type: Headset
- channels:
- - Common
- defaultChannel: Common
- - type: Sprite
- sprite: Clothing/Ears/Headsets/base.rsi
diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml
index d4f603941e..85770cab21 100644
--- a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml
+++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml
@@ -1,56 +1,52 @@
- type: entity
abstract: true
- parent: Clothing
+ parent: ClothingHeadset
id: ClothingHeadsetAlt
name: headset
description: An updated, modular intercom that fits over the head. Takes encryption keys.
components:
- - type: Headset
- type: Sprite
state: icon_alt
- type: Clothing
equippedPrefix: alt
- slots:
- - ears
+
+- type: entity
+ parent: ClothingHeadsetAlt
+ id: ClothingHeadsetAltCargo
+ name: quartermaster's over-ear headset
+ components:
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyQM
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/cargo.rsi
+ - type: Clothing
+ sprite: Clothing/Ears/Headsets/cargo.rsi
- type: entity
parent: ClothingHeadsetAlt
id: ClothingHeadsetAltCentCom
name: CentCom over-ear headset
components:
- - type: Headset
- channels:
- - Common
- - Command
- - CentCom
- - Engineering
- - Medical
- - Science
- - Security
- - Service
- - Supply
- defaultChannel: CentCom
- - type: Sprite
- sprite: Clothing/Ears/Headsets/centcom.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/centcom.rsi
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCentCom
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/centcom.rsi
+ - type: Clothing
+ sprite: Clothing/Ears/Headsets/centcom.rsi
- type: entity
parent: ClothingHeadsetAlt
id: ClothingHeadsetAltCommand
name: command over-ear headset
components:
- - type: Headset
- channels:
- - Common
- - Command
- - Engineering
- - Medical
- - Science
- - Security
- - Service
- - Supply
- defaultChannel: Command
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCommand
- type: Sprite
sprite: Clothing/Ears/Headsets/command.rsi
- type: Clothing
@@ -58,15 +54,27 @@
- type: entity
parent: ClothingHeadsetAlt
- id: ClothingHeadsetAltMedical
- name: medical over-ear headset
+ id: ClothingHeadsetAltEngineering
+ name: chief engineer's over-ear headset
components:
- - type: Headset
- channels:
- - Command
- - Common
- - Medical
- defaultChannel: Medical
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCE
+ - type: Sprite
+ sprite: Clothing/Ears/Headsets/engineering.rsi
+ - type: Clothing
+ sprite: Clothing/Ears/Headsets/engineering.rsi
+
+- type: entity
+ parent: ClothingHeadsetAlt
+ id: ClothingHeadsetAltMedical
+ name: chief medical officer's over-ear headset
+ components:
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyCMO
- type: Sprite
sprite: Clothing/Ears/Headsets/medical.rsi
- type: Clothing
@@ -75,77 +83,43 @@
- type: entity
parent: ClothingHeadsetAlt
id: ClothingHeadsetAltSecurity
- name: security over-ear headset
+ name: head of security's over-ear headset
components:
- - type: Headset
- channels:
- - Command
- - Common
- - Security
- defaultChannel: Security
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyHOS
- type: Sprite
sprite: Clothing/Ears/Headsets/security.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/security.rsi
-- type: entity
- parent: ClothingHeadsetAlt
- id: ClothingHeadsetAltEngineering
- name: engineering over-ear headset
- components:
- - type: Headset
- channels:
- - Command
- - Common
- - Engineering
- defaultChannel: Engineering
- - type: Sprite
- sprite: Clothing/Ears/Headsets/engineering.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/engineering.rsi
-
- type: entity
parent: ClothingHeadsetAlt
id: ClothingHeadsetAltScience
- name: science over-ear headset
+ name: research director's over-ear headset
components:
- - type: Headset
- channels:
- - Command
- - Common
- - Science
- defaultChannel: Science
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeyRD
- type: Sprite
sprite: Clothing/Ears/Headsets/science.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/science.rsi
-- type: entity
- parent: ClothingHeadsetAlt
- id: ClothingHeadsetAltCargo
- name: cargo over-ear headset
- components:
- - type: Headset
- channels:
- - Command
- - Common
- - Supply
- defaultChannel: Supply
- - type: Sprite
- sprite: Clothing/Ears/Headsets/cargo.rsi
- - type: Clothing
- sprite: Clothing/Ears/Headsets/cargo.rsi
-
- type: entity
parent: ClothingHeadsetAlt
id: ClothingHeadsetAltSyndicate
- name: syndicate over-ear headset
- description: An updated, modular syndicate intercom that fits over the head and takes encryption keys. Protects ears from flashbangs.
+ name: blood-red over-ear headset
+ description: An updated, modular syndicate intercom that fits over the head and takes encryption keys (there are 4 slots for them).
components:
- type: Headset
- channels:
- - Syndicate
- defaultChannel: Syndicate
+ keySlots: 4
+ - type: ContainerFill
+ containers:
+ key_slots:
+ - EncryptionKeySyndie
- type: Sprite
sprite: Clothing/Ears/Headsets/syndicate.rsi
- type: Clothing
diff --git a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml
new file mode 100644
index 0000000000..e2aa9833f1
--- /dev/null
+++ b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml
@@ -0,0 +1,287 @@
+- type: entity
+ abstract: true
+ parent: BaseItem
+ id: EncryptionKey
+ name: encryption key
+ description: A small cypher chip for headsets.
+ components:
+ - type: EncryptionKey
+ - type: Item
+ sprite: Objects/Devices/encryption_keys.rsi
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: cypherkey
+ netsync: false
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyCommon
+ name: passenger encryption key
+ description: An encryption key used by anyone.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ defaultChannel: Common
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyCargo
+ name: cargo encryption key
+ description: An encryption key used by supply employees.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Supply
+ defaultChannel: Supply
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: cargo_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyQM
+ name: quartermaster's encryption key
+ description: An encryption key used by the boss of cargo.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - Supply
+ defaultChannel: Supply
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: qm_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyCentCom
+ name: central command encryption key
+ description: An encryption key used by captain's bosses.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - CentCom
+ - Engineering
+ - Medical
+ - Science
+ - Security
+ - Service
+ - Supply
+ defaultChannel: CentCom
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: bin_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyCommand
+ name: command encryption key
+ description: An encryption key used by crew's bosses.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - Engineering
+ - Medical
+ - Science
+ - Security
+ - Service
+ - Supply
+ defaultChannel: Command
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: com_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyEngineering
+ name: engineering encryption key
+ description: An encryption key used by the engineers.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Engineering
+ defaultChannel: Engineering
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: eng_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyCE
+ name: chief engineer's encryption key
+ description: An encryption key used by the boss of the real men.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - Engineering
+ defaultChannel: Engineering
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: ce_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyMedical
+ name: medical encryption key
+ description: An encryption key used by those who save lives.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Medical
+ defaultChannel: Medical
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: med_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyCMO
+ name: chief medical officer encryption key
+ description: An encryption key used by the head of the medical department.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - Medical
+ defaultChannel: Medical
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: cmo_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyMedicalScience
+ name: med-sci encryption key
+ description: An encryption key used by someone who hasn't decided which side to take.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Medical
+ - Science
+ defaultChannel: Science
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: medsci_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyScience
+ name: science encryption key
+ description: An encryption key used by scientists. Maybe it is plasmaproof?
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Science
+ defaultChannel: Science
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: sci_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyRobo
+ name: robotech encryption key
+ description: An encryption key used by robototech engineers. Maybe it has a LAH-6000 on it?
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Science
+ defaultChannel: Science
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: rob_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyRD
+ name: research director's encryption key
+ description: An encryption key used by the head of the science department. Looks like it's been chewed on.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - Science
+ defaultChannel: Science
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: rd_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeySecurity
+ name: security encryption key
+ description: An encryption key used by security.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Security
+ defaultChannel: Security
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: sec_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyHOS
+ name: head of security encryption key
+ description: An encryption key used by the boss of security.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Command
+ - Security
+ defaultChannel: Security
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: hos_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeyService
+ name: service encryption key
+ description: An encryption key used by the service staff, tasked with keeping the station full, happy and clean.
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Service
+ defaultChannel: Service
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: srv_cypherkey
+
+- type: entity
+ parent: EncryptionKey
+ id: EncryptionKeySyndie
+ name: blood-red encryption key
+ description: An encryption key used by... wait... Who is owner of this chip?
+ components:
+ - type: EncryptionKey
+ channels:
+ - Common
+ - Syndicate
+ defaultChannel: Syndicate
+ - type: Sprite
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: syn_cypherkey
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/bin_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/bin_cypherkey.png
new file mode 100644
index 0000000000..3b8647c610
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/bin_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/cap_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cap_cypherkey.png
new file mode 100644
index 0000000000..830d7b2bb5
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cap_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/cargo_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cargo_cypherkey.png
new file mode 100644
index 0000000000..9e4f74a0ec
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cargo_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/ce_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/ce_cypherkey.png
new file mode 100644
index 0000000000..da72b41527
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/ce_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/cmo_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cmo_cypherkey.png
new file mode 100644
index 0000000000..6ff0d4563f
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cmo_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/com_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/com_cypherkey.png
new file mode 100644
index 0000000000..32d6779174
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/com_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cypherkey.png
new file mode 100644
index 0000000000..093a913b3d
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/eng_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/eng_cypherkey.png
new file mode 100644
index 0000000000..580f7776eb
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/eng_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/hop_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/hop_cypherkey.png
new file mode 100644
index 0000000000..ee5b4ef5e8
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/hop_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/hos_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/hos_cypherkey.png
new file mode 100644
index 0000000000..f7b96b0f47
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/hos_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/med_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/med_cypherkey.png
new file mode 100644
index 0000000000..8ccf581185
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/med_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/medsci_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/medsci_cypherkey.png
new file mode 100644
index 0000000000..3efc63976a
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/medsci_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/meta.json b/Resources/Textures/Objects/Devices/encryption_keys.rsi/meta.json
new file mode 100644
index 0000000000..04c8803e66
--- /dev/null
+++ b/Resources/Textures/Objects/Devices/encryption_keys.rsi/meta.json
@@ -0,0 +1,32 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from infinity baystation 12, https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {"name": "cypherkey"},
+ {"name": "bin_cypherkey"},
+ {"name": "cap_cypherkey"},
+ {"name": "cargo_cypherkey"},
+ {"name": "ce_cypherkey"},
+ {"name": "cmo_cypherkey"},
+ {"name": "com_cypherkey"},
+ {"name": "eng_cypherkey"},
+ {"name": "hop_cypherkey"},
+ {"name": "hos_cypherkey"},
+ {"name": "medsci_cypherkey"},
+ {"name": "med_cypherkey"},
+ {"name": "mine_cypherkey"},
+ {"name": "nt_cypherkey"},
+ {"name": "qm_cypherkey"},
+ {"name": "rd_cypherkey"},
+ {"name": "rob_cypherkey"},
+ {"name": "sci_cypherkey"},
+ {"name": "sec_cypherkey"},
+ {"name": "srv_cypherkey"},
+ {"name": "syn_cypherkey"}
+ ]
+}
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/mine_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/mine_cypherkey.png
new file mode 100644
index 0000000000..4705ce55e6
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/mine_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/nt_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/nt_cypherkey.png
new file mode 100644
index 0000000000..a29ae041ae
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/nt_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/qm_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/qm_cypherkey.png
new file mode 100644
index 0000000000..24d667b545
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/qm_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/rd_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/rd_cypherkey.png
new file mode 100644
index 0000000000..17e96526fe
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/rd_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/rob_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/rob_cypherkey.png
new file mode 100644
index 0000000000..d4a818480e
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/rob_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/sci_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/sci_cypherkey.png
new file mode 100644
index 0000000000..b5b79f7fcf
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/sci_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/sec_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/sec_cypherkey.png
new file mode 100644
index 0000000000..860127b346
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/sec_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/srv_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/srv_cypherkey.png
new file mode 100644
index 0000000000..bafc6c04e3
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/srv_cypherkey.png differ
diff --git a/Resources/Textures/Objects/Devices/encryption_keys.rsi/syn_cypherkey.png b/Resources/Textures/Objects/Devices/encryption_keys.rsi/syn_cypherkey.png
new file mode 100644
index 0000000000..f02db61884
Binary files /dev/null and b/Resources/Textures/Objects/Devices/encryption_keys.rsi/syn_cypherkey.png differ