From c8b89c70081750b62fdbc41c7228178393feaf55 Mon Sep 17 00:00:00 2001
From: AlexMorgan3817 <46600554+AlexMorgan3817@users.noreply.github.com>
Date: Sun, 29 Jan 2023 00:53:08 +0000
Subject: [PATCH] Encryption Keys for headsets (#12615)
---
.../Chat/Systems/ChatSystem.Radio.cs | 4 +-
.../Radio/Components/HeadsetComponent.cs | 52 +++-
.../Radio/EntitySystems/HeadsetSystem.cs | 156 +++++++++-
.../Radio/EncryptionKeyComponent.cs | 23 ++
Content.Shared/Radio/EncryptionKeySystem.cs | 55 ++++
.../en-US/headset/headset-component.ftl | 18 +-
.../Locale/en-US/store/uplink-catalog.ftl | 5 +-
.../Prototypes/Catalog/uplink_catalog.yml | 16 +-
.../Entities/Clothing/Ears/headsets.yml | 251 +++++++--------
.../Entities/Clothing/Ears/headsets_alt.yml | 154 ++++------
.../Objects/Devices/encryption_keys.yml | 287 ++++++++++++++++++
.../encryption_keys.rsi/bin_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/cap_cypherkey.png | Bin 0 -> 143 bytes
.../encryption_keys.rsi/cargo_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/ce_cypherkey.png | Bin 0 -> 143 bytes
.../encryption_keys.rsi/cmo_cypherkey.png | Bin 0 -> 143 bytes
.../encryption_keys.rsi/com_cypherkey.png | Bin 0 -> 154 bytes
.../Devices/encryption_keys.rsi/cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/eng_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/hop_cypherkey.png | Bin 0 -> 143 bytes
.../encryption_keys.rsi/hos_cypherkey.png | Bin 0 -> 143 bytes
.../encryption_keys.rsi/med_cypherkey.png | Bin 0 -> 158 bytes
.../encryption_keys.rsi/medsci_cypherkey.png | Bin 0 -> 157 bytes
.../Devices/encryption_keys.rsi/meta.json | 32 ++
.../encryption_keys.rsi/mine_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/nt_cypherkey.png | Bin 0 -> 157 bytes
.../encryption_keys.rsi/qm_cypherkey.png | Bin 0 -> 157 bytes
.../encryption_keys.rsi/rd_cypherkey.png | Bin 0 -> 143 bytes
.../encryption_keys.rsi/rob_cypherkey.png | Bin 0 -> 157 bytes
.../encryption_keys.rsi/sci_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/sec_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/srv_cypherkey.png | Bin 0 -> 154 bytes
.../encryption_keys.rsi/syn_cypherkey.png | Bin 0 -> 154 bytes
33 files changed, 783 insertions(+), 270 deletions(-)
create mode 100644 Content.Shared/Radio/EncryptionKeyComponent.cs
create mode 100644 Content.Shared/Radio/EncryptionKeySystem.cs
create mode 100644 Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/bin_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/cap_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/cargo_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/ce_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/cmo_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/com_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/eng_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/hop_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/hos_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/med_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/medsci_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/meta.json
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/mine_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/nt_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/qm_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/rd_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/rob_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/sci_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/sec_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/srv_cypherkey.png
create mode 100644 Resources/Textures/Objects/Devices/encryption_keys.rsi/syn_cypherkey.png
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 0000000000000000000000000000000000000000..3b8647c6104e1cccfb67dab9021b5472baa62ebf
GIT binary patch
literal 154
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4*8>L*oB@KF3~6aI8U8cW
z`lZhWN->rM`2{mLJiCzwHN#*PIm4GbN{7c_B|WE;w~z5B9|fuV(wtM6gI{yd-|44$rjF6*2UngAV`FjoKo
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..830d7b2bb57f5ccacb143f2e37582049200b1202
GIT binary patch
literal 143
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*8>L*{6AxSW+nrJ@qeYm
zwmX30j3q&S!3+-1ZlnP@hMq2tAre!Q6BbBxv^hvR>1Oa8yAZ(6k$hE4Bl*9*M)G%k
niDYq3rGmEw%!y$aI2agu=88_^WO{K4sF}gj)z4*}Q$iB}PBbYu
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..9e4f74a0ec13502f46868aa8abc0463d7c85bdfb
GIT binary patch
literal 154
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4*8>L*oB@KF3~6aIotzxw
z9?U-glwvFi@(X5gcy=QV$g%WvaSYLzn4BQtaX>>uqe1Jyl7@JO70jXhiwy-9aLm}T
y!(uVlj2#PB8W=i?FKFT_$u^W}d-r7_149cVSKq^a{dqt`7(8A5T-G@yGywoqVle9f
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..da72b41527546582a2e4f84e25c06cd1d467b1a9
GIT binary patch
literal 143
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*8>L*oB@KF4FAtCEdRc?
z7bwnH666=m;PC858jxe?>Eak7F*P}1fka1}gQSyg2G6kz0qh*fSG6>f|J!RMf7h2t
m7Uxtdcw4}n7L*oB@KF438c?`o<-G
z4Jgi7666=m;PC858jxe?>Eak7F*P}1fka1}gQSyg2G6kz0qh*fSG6>f|J!RMf7h2t
m7Uxtdcw4}n7L*oB@KF3~6aI8I1p%
zGYf#!GL{7S1v5B2yO9RuSbDlRhGzopr0KCdCR{#J2
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..093a913b3d2cd830d05ce4bae12000f0df2d755f
GIT binary patch
literal 154
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4*8>L*oB@KF3~6aI|1&TI
zd|Jl@lwvFi@(X5gcy=QV$g%WvaSYLzn4BQtaX>>uqe1Jyl7@JO70jXhiwy-9aLm}T
y!(uVlj2#PB8W=i?FKFT_$u^W}d-r7_149cVSKq^a{dqt`7(8A5T-G@yGywoCoG^L-
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..580f7776ebef3082b0d2839e76aea37e752d3db4
GIT binary patch
literal 154
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4*8>L*oB@KF3~6aI|DRzn
z-)rUolwvFi@(X5gcy=QV$g%WvaSYLzn4BQtaX>>uqe1Jyl7@JO70jXhiwy-9aLm}T
y!(uVlj2#PB8W=i?FKFT_$u^W}d-r7_149cVSKq^a{dqt`7(8A5T-G@yGywoer!c+%
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..ee5b4ef5e8144c80ccc2a9f107d3b5614c18cd2f
GIT binary patch
literal 143
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*8>L*oB@KF3=GEqmwR^4
z2Z}S61o;IsI6S+N2ILrex;TbNOifN$Akoq0AnBx=!E@|F06RzWRV|I=|MnWm-}NPu
l#W|G<-WD(?hF#!bVCb1EI*pU*#U-F-22WQ%mvv4FO#q7>Dct}7
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..f7b96b0f47d81b484b81583fb32176f5a6d57ca7
GIT binary patch
literal 143
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*8>L*oB@KF3^N%RdLA{!
z0>v3ig8YIR9G=}s19A*KT^vIsrY0vWkmzW0kaW_`;5l|7fSn`xs+LCbe|wGO@A?wS
k;+#qaZwr_c!!B?DO_?h?jg#rcC7@;oPgg&ebxsLQ0B7bYcK`qY
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..8ccf581185fe9f3a924e50cf214f9d963ce0d814
GIT binary patch
literal 158
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*oB@KF3~6aIA3b{X
z^y$-}84T(`S;mqezhDN3XE)M-94k*3#}JK)$q5o32Q)M^8ng~9X^3Z7!5qrJ*ic{r
z$BZ32SQc~5*s)-xfuW=Lf+j9;@$^4@&gH)X7#LL*oB@KF3~6aIA3b`M
zW_(7)I-VOS%UBZR7tG-B>_!@pW9jMQ7@{#TIYGkXfQE)fgVup14e<;sm_zv&8wxDo
zn6aaUZ86u3mPIQK3|+++G;x(=8_Kl3`?8RMf#nQ0+ua{O7XuAp@O1TaS?83{1OO7Y
BGQL*oB@KF3~6aIr|B_f
ze@PbyN->rM`2{mLJiCzwHN#*PIm4GbN{7c_B|WE;w~z5B9|fuV(wtM6gI{yd-|44$rjF6*2Ung9*WFe?B6
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..a29ae041aee25fe1e9ff5a4edc3a710ce6da98b9
GIT binary patch
literal 157
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*oB@KF3~6aIA3b^`
zpY6wY-m(QK%UBZR7tG-B>_!@pW9jMQ7@{#TIYGkXfQE)fgVup14e<;sm_zv&8wxDo
zn6aaUZ86u3mPIQK3|+++G;x(=8_Kl3`?8RMf#nQ0+ua{O7XuAp@O1TaS?83{1OO^1
BGY9|x
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..24d667b545c3db4028fdf24afd90d353314700df
GIT binary patch
literal 157
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*oB@KF3~6aIotzw}
z=`rqId@K?u%UBZR7tG-B>_!@pW9jMQ7@{#TIYGkXfQE)fgVup14e<;sm_zv&8wxDo
zn6aaUZ86u3mPIQK3|+++G;x(=8_Kl3`?8RMf#nQ0+ua{O7XuAp@O1TaS?83{1OT}x
BG5G)h
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..17e96526fe9f475ad2bae40c94c55ebd84284c9b
GIT binary patch
literal 143
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*8>L*oB@KF4D#82b>`Mn
zfZ~iLL4Lsu4$p3+0Xc@AE{-7*QHaS5oI!PC{xWt~$(696}?DD40M
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..d4a818480e76cda8f9e736fd470087c7e64b4753
GIT binary patch
literal 157
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*oB@KF3~6aI|DRz<
zGd?r(OV|vcEMrNKUoeBivm0qZj-{uIV~EDYL*oB@KF3~6aI(~Qp?
z={$A~D8*P3SMuXOYB@OWmE0{z17aIyJ;Fz&v
yhs9#989NrNG%$1&U(m!=l5Hr{_U_9<28I?!uD*x;`tyK>FnGH9xvXL*oB@KF3~6aIXEHFz
ztdN`llwvFi@(X5gcy=QV$g%WvaSYLzn4BQtaX>>uqe1Jyl7@JO70jXhiwy-9aLm}T
y!(uVlj2#PB8W=i?FKFT_$u^W}d-r7_149cVSKq^a{dqt`7(8A5T-G@yGywq7FE5V(
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..bafc6c04e3d156e7805a50f19a92c3f6149ec622
GIT binary patch
literal 154
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4*8>L*oB@KF3~6aIHEJ20
zmUi&~r5HSR1#>9>Vncxi95Z(8
xuvpABW5L*czSxCnaLn7EC_V36BFB8X65+2bMI%Gpt|^gTe~DWM4f9Yihn
literal 0
HcmV?d00001