Encryption Keys for headsets (#12615)

This commit is contained in:
AlexMorgan3817
2023-01-29 00:53:08 +00:00
committed by GitHub
parent 14ba167201
commit c8b89c7008
33 changed files with 783 additions and 270 deletions

View File

@@ -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 // Redirect to defaultChannel of headsetComp if it goes to "h" channel code after making sure defaultChannel exists
if (message[1] == 'h' if (message[1] == 'h'
&& _headsetComponent != null && _headsetComponent != null
&& _headsetComponent.defaultChannel != null && _headsetComponent.DefaultChannel != null
&& _prototypeManager.TryIndex(_headsetComponent.defaultChannel, out RadioChannelPrototype? protoDefaultChannel)) && _prototypeManager.TryIndex(_headsetComponent.DefaultChannel, out RadioChannelPrototype? protoDefaultChannel))
{ {
// Set Channel to headset defaultChannel // Set Channel to headset defaultChannel
channel = protoDefaultChannel; channel = protoDefaultChannel;

View File

@@ -1,11 +1,12 @@
using Content.Server.Radio.EntitySystems; using Content.Server.Radio.EntitySystems;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Radio; 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; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Radio.Components; namespace Content.Server.Radio.Components;
/// <summary> /// <summary>
/// This component relays radio messages to the parent entity's chat when equipped. /// This component relays radio messages to the parent entity's chat when equipped.
/// </summary> /// </summary>
@@ -13,17 +14,52 @@ namespace Content.Server.Radio.Components;
[Access(typeof(HeadsetSystem))] [Access(typeof(HeadsetSystem))]
public sealed class HeadsetComponent : Component public sealed class HeadsetComponent : Component
{ {
[DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))] /// <summary>
public readonly HashSet<string> 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.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("isKeysUnlocked")]
public bool IsKeysUnlocked = true;
/// <summary>
/// Shows which tool a person should use to extract the encryption keys from the headset.
/// default "Screwing"
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("keysExtractionMethod", customTypeSerializer: typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
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<string> Channels = new();
// Maybe make the defaultChannel an actual channel type some day, and use that for parsing messages // Maybe make the defaultChannel an actual channel type some day, and use that for parsing messages
// [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))] // [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))]
// public readonly HashSet<string> defaultChannel = new(); // public readonly HashSet<string> defaultChannel = new();
/// <summary>
/// This variable defines what channel will be used with using ":h" (department channel prefix).
[DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdSerializer<RadioChannelPrototype>))] /// Headset read DefaultChannel of first encryption key installed.
public readonly string? defaultChannel; /// Do not change this variable from headset or VV, better change encryption keys and UpdateDefaultChannel.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
public string? DefaultChannel;
[DataField("enabled")] [DataField("enabled")]
public bool Enabled = true; public bool Enabled = true;

View File

@@ -1,11 +1,18 @@
using Content.Server.Chat.Systems; 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.Examine;
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Content.Shared.Radio; using Content.Shared.Radio;
using Content.Server.Radio.Components;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Containers;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using System.Linq;
using Robust.Shared.Profiling;
namespace Content.Server.Radio.EntitySystems; namespace Content.Server.Radio.EntitySystems;
@@ -14,6 +21,10 @@ public sealed class HeadsetSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _protoManager = default!; [Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly INetManager _netMan = default!;
[Dependency] private readonly RadioSystem _radio = 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() public override void Initialize()
{ {
@@ -23,6 +34,10 @@ public sealed class HeadsetSystem : EntitySystem
SubscribeLocalEvent<HeadsetComponent, GotEquippedEvent>(OnGotEquipped); SubscribeLocalEvent<HeadsetComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<HeadsetComponent, GotUnequippedEvent>(OnGotUnequipped); SubscribeLocalEvent<HeadsetComponent, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<WearingHeadsetComponent, EntitySpokeEvent>(OnSpeak); SubscribeLocalEvent<WearingHeadsetComponent, EntitySpokeEvent>(OnSpeak);
SubscribeLocalEvent<HeadsetComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<HeadsetComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<HeadsetComponent, EntInsertedIntoContainerMessage>(OnContainerInserted);
} }
private void OnSpeak(EntityUid uid, WearingHeadsetComponent component, EntitySpokeEvent args) private void OnSpeak(EntityUid uid, WearingHeadsetComponent component, EntitySpokeEvent args)
@@ -43,10 +58,15 @@ public sealed class HeadsetSystem : EntitySystem
if (component.IsEquipped && component.Enabled) if (component.IsEquipped && component.Enabled)
{ {
EnsureComp<WearingHeadsetComponent>(args.Equipee).Headset = uid; EnsureComp<WearingHeadsetComponent>(args.Equipee).Headset = uid;
EnsureComp<ActiveRadioComponent>(uid).Channels.UnionWith(component.Channels); PushRadioChannelsToOwner(uid, component, EnsureComp<ActiveRadioComponent>(uid));
} }
} }
private void PushRadioChannelsToOwner(EntityUid uid, HeadsetComponent component, ActiveRadioComponent activeRadio)
{
activeRadio.Channels.UnionWith(component.Channels);
}
private void OnGotUnequipped(EntityUid uid, HeadsetComponent component, GotUnequippedEvent args) private void OnGotUnequipped(EntityUid uid, HeadsetComponent component, GotUnequippedEvent args)
{ {
component.IsEquipped = false; component.IsEquipped = false;
@@ -86,21 +106,127 @@ public sealed class HeadsetSystem : EntitySystem
{ {
if (!args.IsInDetailsRange) if (!args.IsInDetailsRange)
return; return;
if (component.KeyContainer.ContainedEntities.Count == 0)
args.PushMarkup(Loc.GetString("examine-headset"));
foreach (var id in component.Channels)
{ {
if (id == "Common") continue; args.PushMarkup(Loc.GetString("examine-headset-no-keys"));
return;
var proto = _protoManager.Index<RadioChannelPrototype>(id);
args.PushMarkup(Loc.GetString("examine-headset-channel",
("color", proto.Color),
("key", proto.KeyCode),
("id", proto.LocalizedName),
("freq", proto.Frequency)));
} }
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<RadioChannelPrototype>(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<Container>(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<EncryptionKeyComponent>(i, out var key))
{
UploadChannelsFromKey(component, key);
}
}
}
private void OnInteractUsing(EntityUid uid, HeadsetComponent component, InteractUsingEvent args)
{
if (!TryComp<ContainerManagerComponent>(uid, out var storage))
return;
if(!component.IsKeysUnlocked)
{
_popupSystem.PopupEntity(Loc.GetString("headset-encryption-keys-are-locked"), uid, args.User);
return;
}
if (TryComp<EncryptionKeyComponent>(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<ToolComponent>(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<EntityUid>();
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<EncryptionKeyComponent>(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<EncryptionKeyComponent>(args.Entity, out var added))
{
UpdateDefaultChannel(component);
UploadChannelsFromKey(component, added);
PushRadioChannelsToOwner(uid, component, EnsureComp<ActiveRadioComponent>(uid));
}
return;
} }
} }

View File

@@ -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;
/// <summary>
/// This component is currently used for providing access to channels for "HeadsetComponent"s.
/// It should be used for intercoms and other radios in future.
/// </summary>
[RegisterComponent]
public sealed class EncryptionKeyComponent : Component
{
[DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))]
public HashSet<string> Channels = new();
/// <summary>
/// This variable defines what channel will be used with using ":h" (department channel prefix).
/// Headset read DefaultChannel of first encryption key installed.
/// </summary>
[DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdSerializer<RadioChannelPrototype>))]
public readonly string? DefaultChannel;
}

View File

@@ -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<EncryptionKeyComponent, ExaminedEvent>(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<RadioChannelPrototype>(component.DefaultChannel);
args.PushMarkup(Loc.GetString("examine-encryption-key-default-channel", ("channel", component.DefaultChannel), ("color", proto.Color)));
}
}
}
/// <summary>
/// A static method for formating list of radio channels for examine events.
/// </summary>
/// <param name="channels">HashSet of channels in headset, encryptionkey or etc.</param>
/// <param name="protoManager">IPrototypeManager for getting prototypes of channels with their variables.</param>
/// <param name="channelFTLPattern">String that provide id of pattern in .ftl files to format channel with variables of it.</param>
public static void GetChannelsExamine(HashSet<string> channels, ExaminedEvent examineEvent, IPrototypeManager protoManager, string channelFTLPattern)
{
foreach (var id in channels)
{
var proto = protoManager.Index<RadioChannelPrototype>(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)));
}
}
}

View File

@@ -1,12 +1,22 @@
# Chat window radio wrap (prefix and postfix) # Chat window radio wrap (prefix and postfix)
chat-radio-message-wrap = [color={$color}]{$channel} {$name} says: "{$message}"[/color] 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-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-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-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 {$prefix} for the currently tuned frequency. 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-common = Common
chat-radio-centcom = CentCom chat-radio-centcom = CentCom

View File

@@ -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-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-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-name = Hypopen
uplink-hypopen-desc = A chemical hypospray disguised as a pen, capable of instantly injecting up to 15u of reagents. Starts empty. uplink-hypopen-desc = A chemical hypospray disguised as a pen, capable of instantly injecting up to 15u of reagents. Starts empty.

View File

@@ -268,16 +268,26 @@
categories: categories:
- UplinkUtility - 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 - type: listing
id: UplinkHeadset id: UplinkHeadset
name: uplink-headset-name name: uplink-headset-name
description: uplink-headset-desc description: uplink-headset-desc
productEntity: ClothingHeadsetAltSyndicate productEntity: ClothingHeadsetAltSyndicate
cost: cost:
Telecrystal: 2 # next step is adding encryption keys Telecrystal: 4
categories: 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 - type: listing
id: UplinkHypopen id: UplinkHypopen

View File

@@ -5,7 +5,15 @@
name: headset name: headset
description: An updated, modular intercom that fits over the head. Takes encryption keys. description: An updated, modular intercom that fits over the head. Takes encryption keys.
components: components:
- type: ContainerContainer
containers:
key_slots: !type:Container
- type: ContainerFill
containers:
key_slots:
- EncryptionKeyCommon
- type: Headset - type: Headset
keysExtractionMethod: Screwing
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
@@ -13,38 +21,50 @@
- ears - ears
sprite: Clothing/Ears/Headsets/base.rsi 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 - type: entity
parent: ClothingHeadset parent: ClothingHeadset
id: ClothingHeadsetCargo id: ClothingHeadsetCargo
name: cargo headset name: cargo headset
description: A headset used by supply employees. description: A headset used by supply employees.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Supply - EncryptionKeyCargo
defaultChannel: Supply
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/cargo.rsi sprite: Clothing/Ears/Headsets/cargo.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/cargo.rsi sprite: Clothing/Ears/Headsets/cargo.rsi
- type: entity - 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 id: ClothingHeadsetQM
name: qm headset name: qm headset
description: A headset used by the quartermaster. description: A headset used by the quartermaster.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Command key_slots:
- Common - EncryptionKeyQM
- Supply
defaultChannel: Supply
- type: Sprite
sprite: Clothing/Ears/Headsets/cargo.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/cargo.rsi
- type: entity - type: entity
parent: ClothingHeadset parent: ClothingHeadset
@@ -52,18 +72,10 @@
name: CentCom headset name: CentCom headset
description: A headset used by the upper echelons of Nanotrasen. description: A headset used by the upper echelons of Nanotrasen.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Command - EncryptionKeyCentCom
- CentCom
- Engineering
- Medical
- Science
- Security
- Service
- Supply
defaultChannel: CentCom
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/centcom.rsi sprite: Clothing/Ears/Headsets/centcom.rsi
- type: Clothing - type: Clothing
@@ -75,17 +87,10 @@
name: command headset name: command headset
description: A headset with a commanding channel. description: A headset with a commanding channel.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Command - EncryptionKeyCommand
- Engineering
- Medical
- Science
- Security
- Service
- Supply
defaultChannel: Command
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/command.rsi sprite: Clothing/Ears/Headsets/command.rsi
- type: Clothing - type: Clothing
@@ -97,32 +102,25 @@
name: engineering headset name: engineering headset
description: A headset for engineers to chat while the station burns around them. description: A headset for engineers to chat while the station burns around them.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Engineering - EncryptionKeyEngineering
defaultChannel: Engineering
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/engineering.rsi sprite: Clothing/Ears/Headsets/engineering.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/engineering.rsi sprite: Clothing/Ears/Headsets/engineering.rsi
- type: entity - type: entity
parent: ClothingHeadset parent: ClothingHeadsetEngineering
id: ClothingHeadsetCE id: ClothingHeadsetCE
name: ce headset name: ce headset
description: A headset for the chief engineer to ignore all emergency calls on. description: A headset for the chief engineer to ignore all emergency calls on.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Command key_slots:
- Common - EncryptionKeyCE
- Engineering
defaultChannel: Engineering
- type: Sprite
sprite: Clothing/Ears/Headsets/engineering.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/engineering.rsi
- type: entity - type: entity
parent: ClothingHeadset parent: ClothingHeadset
@@ -130,97 +128,70 @@
name: medical headset name: medical headset
description: A headset for the trained staff of the medbay. description: A headset for the trained staff of the medbay.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Medical - EncryptionKeyMedical
defaultChannel: Medical
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/medical.rsi sprite: Clothing/Ears/Headsets/medical.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/medical.rsi 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 - type: entity
parent: ClothingHeadset parent: ClothingHeadset
id: ClothingHeadsetScience id: ClothingHeadsetScience
name: science headset name: science headset
description: A sciency headset. Like usual. description: A sciency headset. Like usual.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Science - EncryptionKeyScience
defaultChannel: Science
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/science.rsi sprite: Clothing/Ears/Headsets/science.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/science.rsi sprite: Clothing/Ears/Headsets/science.rsi
- type: entity - 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 id: ClothingHeadsetRD
name: rd headset name: rd headset
description: Lamarr used to love chewing on this... description: Lamarr used to love chewing on this...
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Command key_slots:
- Common - EncryptionKeyRD
- Science
defaultChannel: Science
- type: Sprite
sprite: Clothing/Ears/Headsets/science.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/science.rsi
- type: entity - type: entity
parent: ClothingHeadset parent: ClothingHeadset
@@ -228,11 +199,10 @@
name: security headset name: security headset
description: This is used by your elite security force. description: This is used by your elite security force.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Security - EncryptionKeySecurity
defaultChannel: Security
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/security.rsi sprite: Clothing/Ears/Headsets/security.rsi
- type: Clothing - type: Clothing
@@ -244,25 +214,12 @@
name: service headset name: service headset
description: Headset used by the service staff, tasked with keeping the station full, happy and clean. description: Headset used by the service staff, tasked with keeping the station full, happy and clean.
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Service - EncryptionKeyService
defaultChannel: Service
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/service.rsi sprite: Clothing/Ears/Headsets/service.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/service.rsi 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

View File

@@ -1,56 +1,52 @@
- type: entity - type: entity
abstract: true abstract: true
parent: Clothing parent: ClothingHeadset
id: ClothingHeadsetAlt id: ClothingHeadsetAlt
name: headset name: headset
description: An updated, modular intercom that fits over the head. Takes encryption keys. description: An updated, modular intercom that fits over the head. Takes encryption keys.
components: components:
- type: Headset
- type: Sprite - type: Sprite
state: icon_alt state: icon_alt
- type: Clothing - type: Clothing
equippedPrefix: alt 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 - type: entity
parent: ClothingHeadsetAlt parent: ClothingHeadsetAlt
id: ClothingHeadsetAltCentCom id: ClothingHeadsetAltCentCom
name: CentCom over-ear headset name: CentCom over-ear headset
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Command - EncryptionKeyCentCom
- CentCom - type: Sprite
- Engineering sprite: Clothing/Ears/Headsets/centcom.rsi
- Medical - type: Clothing
- Science sprite: Clothing/Ears/Headsets/centcom.rsi
- Security
- Service
- Supply
defaultChannel: CentCom
- type: Sprite
sprite: Clothing/Ears/Headsets/centcom.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/centcom.rsi
- type: entity - type: entity
parent: ClothingHeadsetAlt parent: ClothingHeadsetAlt
id: ClothingHeadsetAltCommand id: ClothingHeadsetAltCommand
name: command over-ear headset name: command over-ear headset
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Common key_slots:
- Command - EncryptionKeyCommand
- Engineering
- Medical
- Science
- Security
- Service
- Supply
defaultChannel: Command
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/command.rsi sprite: Clothing/Ears/Headsets/command.rsi
- type: Clothing - type: Clothing
@@ -58,15 +54,27 @@
- type: entity - type: entity
parent: ClothingHeadsetAlt parent: ClothingHeadsetAlt
id: ClothingHeadsetAltMedical id: ClothingHeadsetAltEngineering
name: medical over-ear headset name: chief engineer's over-ear headset
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Command key_slots:
- Common - EncryptionKeyCE
- Medical - type: Sprite
defaultChannel: Medical 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 - type: Sprite
sprite: Clothing/Ears/Headsets/medical.rsi sprite: Clothing/Ears/Headsets/medical.rsi
- type: Clothing - type: Clothing
@@ -75,77 +83,43 @@
- type: entity - type: entity
parent: ClothingHeadsetAlt parent: ClothingHeadsetAlt
id: ClothingHeadsetAltSecurity id: ClothingHeadsetAltSecurity
name: security over-ear headset name: head of security's over-ear headset
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Command key_slots:
- Common - EncryptionKeyHOS
- Security
defaultChannel: Security
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/security.rsi sprite: Clothing/Ears/Headsets/security.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/security.rsi 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 - type: entity
parent: ClothingHeadsetAlt parent: ClothingHeadsetAlt
id: ClothingHeadsetAltScience id: ClothingHeadsetAltScience
name: science over-ear headset name: research director's over-ear headset
components: components:
- type: Headset - type: ContainerFill
channels: containers:
- Command key_slots:
- Common - EncryptionKeyRD
- Science
defaultChannel: Science
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/science.rsi sprite: Clothing/Ears/Headsets/science.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Ears/Headsets/science.rsi 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 - type: entity
parent: ClothingHeadsetAlt parent: ClothingHeadsetAlt
id: ClothingHeadsetAltSyndicate id: ClothingHeadsetAltSyndicate
name: syndicate over-ear headset name: blood-red over-ear headset
description: An updated, modular syndicate intercom that fits over the head and takes encryption keys. Protects ears from flashbangs. description: An updated, modular syndicate intercom that fits over the head and takes encryption keys (there are 4 slots for them).
components: components:
- type: Headset - type: Headset
channels: keySlots: 4
- Syndicate - type: ContainerFill
defaultChannel: Syndicate containers:
key_slots:
- EncryptionKeySyndie
- type: Sprite - type: Sprite
sprite: Clothing/Ears/Headsets/syndicate.rsi sprite: Clothing/Ears/Headsets/syndicate.rsi
- type: Clothing - type: Clothing

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

View File

@@ -0,0 +1,32 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from infinity baystation 12, https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi",
"size": {
"x": 32,
"y": 32
},
"states": [
{"name": "cypherkey"},
{"name": "bin_cypherkey"},
{"name": "cap_cypherkey"},
{"name": "cargo_cypherkey"},
{"name": "ce_cypherkey"},
{"name": "cmo_cypherkey"},
{"name": "com_cypherkey"},
{"name": "eng_cypherkey"},
{"name": "hop_cypherkey"},
{"name": "hos_cypherkey"},
{"name": "medsci_cypherkey"},
{"name": "med_cypherkey"},
{"name": "mine_cypherkey"},
{"name": "nt_cypherkey"},
{"name": "qm_cypherkey"},
{"name": "rd_cypherkey"},
{"name": "rob_cypherkey"},
{"name": "sci_cypherkey"},
{"name": "sec_cypherkey"},
{"name": "srv_cypherkey"},
{"name": "syn_cypherkey"}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B