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