diff --git a/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs
new file mode 100644
index 0000000000..29d6c635eb
--- /dev/null
+++ b/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs
@@ -0,0 +1,23 @@
+using Content.Client.Radio.Ui;
+using Content.Shared.Radio;
+using Content.Shared.Radio.Components;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.Radio.EntitySystems;
+
+public sealed class RadioDeviceSystem : EntitySystem
+{
+ [Dependency] private readonly UserInterfaceSystem _ui = default!;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnAfterHandleState);
+ }
+
+ private void OnAfterHandleState(Entity ent, ref AfterAutoHandleStateEvent args)
+ {
+ if (_ui.TryGetOpenUi(ent.Owner, IntercomUiKey.Key, out var bui))
+ bui.Update(ent);
+ }
+}
diff --git a/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs b/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs
index abbb1d58ec..7b3e39aa08 100644
--- a/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs
+++ b/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs
@@ -1,6 +1,6 @@
using Content.Shared.Radio;
+using Content.Shared.Radio.Components;
using JetBrains.Annotations;
-using Robust.Client.GameObjects;
namespace Content.Client.Radio.Ui;
@@ -19,7 +19,9 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface
{
base.Open();
- _menu = new();
+ var comp = EntMan.GetComponent(Owner);
+
+ _menu = new((Owner, comp));
_menu.OnMicPressed += enabled =>
{
@@ -46,13 +48,8 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface
_menu?.Close();
}
- protected override void UpdateState(BoundUserInterfaceState state)
+ public void Update(Entity ent)
{
- base.UpdateState(state);
-
- if (state is not IntercomBoundUIState msg)
- return;
-
- _menu?.Update(msg);
+ _menu?.Update(ent);
}
}
diff --git a/Content.Client/Radio/Ui/IntercomMenu.xaml.cs b/Content.Client/Radio/Ui/IntercomMenu.xaml.cs
index 8b4b38753c..2e08913051 100644
--- a/Content.Client/Radio/Ui/IntercomMenu.xaml.cs
+++ b/Content.Client/Radio/Ui/IntercomMenu.xaml.cs
@@ -1,8 +1,9 @@
using Content.Client.UserInterface.Controls;
-using Content.Shared.Radio;
+using Content.Shared.Radio.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
namespace Content.Client.Radio.Ui;
@@ -17,38 +18,54 @@ public sealed partial class IntercomMenu : FancyWindow
private readonly List _channels = new();
- public IntercomMenu()
+ public IntercomMenu(Entity entity)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
MicButton.OnPressed += args => OnMicPressed?.Invoke(args.Button.Pressed);
SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed);
+
+ Update(entity);
}
- public void Update(IntercomBoundUIState state)
+ public void Update(Entity entity)
{
- MicButton.Pressed = state.MicEnabled;
- SpeakerButton.Pressed = state.SpeakerEnabled;
+ MicButton.Pressed = entity.Comp.MicrophoneEnabled;
+ SpeakerButton.Pressed = entity.Comp.SpeakerEnabled;
+
+ MicButton.Disabled = entity.Comp.SupportedChannels.Count == 0;
+ SpeakerButton.Disabled = entity.Comp.SupportedChannels.Count == 0;
+ ChannelOptions.Disabled = entity.Comp.SupportedChannels.Count == 0;
ChannelOptions.Clear();
_channels.Clear();
- for (var i = 0; i < state.AvailableChannels.Count; i++)
+ for (var i = 0; i < entity.Comp.SupportedChannels.Count; i++)
{
- var channel = state.AvailableChannels[i];
- if (!_prototype.TryIndex(channel, out var prototype))
+ var channel = entity.Comp.SupportedChannels[i];
+ if (!_prototype.TryIndex(channel, out var prototype))
continue;
_channels.Add(channel);
ChannelOptions.AddItem(Loc.GetString(prototype.Name), i);
- if (channel == state.SelectedChannel)
+ if (channel == entity.Comp.CurrentChannel)
ChannelOptions.Select(i);
}
+
+ if (entity.Comp.SupportedChannels.Count == 0)
+ {
+ ChannelOptions.AddItem(Loc.GetString("intercom-options-none"), 0);
+ ChannelOptions.Select(0);
+ }
+
ChannelOptions.OnItemSelected += args =>
{
+ if (!_channels.TryGetValue(args.Id, out var proto))
+ return;
+
ChannelOptions.SelectId(args.Id);
- OnChannelSelected?.Invoke(_channels[args.Id]);
+ OnChannelSelected?.Invoke(proto);
};
}
}
diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs
index 8484fb2336..1258e0b8c7 100644
--- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs
+++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs
@@ -1,3 +1,4 @@
+using System.Linq;
using Content.Server.Chat.Systems;
using Content.Server.Interaction;
using Content.Server.Popups;
@@ -6,13 +7,10 @@ using Content.Server.Power.EntitySystems;
using Content.Server.Radio.Components;
using Content.Server.Speech;
using Content.Server.Speech.Components;
-using Content.Shared.UserInterface;
-using Content.Shared.Chat;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Radio;
using Content.Shared.Radio.Components;
-using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.Server.Radio.EntitySystems;
@@ -28,7 +26,6 @@ public sealed class RadioDeviceSystem : EntitySystem
[Dependency] private readonly RadioSystem _radio = default!;
[Dependency] private readonly InteractionSystem _interaction = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
- [Dependency] private readonly UserInterfaceSystem _ui = default!;
// Used to prevent a shitter from using a bunch of radios to spam chat.
private HashSet<(string, EntityUid)> _recentlySent = new();
@@ -47,7 +44,7 @@ public sealed class RadioDeviceSystem : EntitySystem
SubscribeLocalEvent(OnActivateSpeaker);
SubscribeLocalEvent(OnReceiveRadio);
- SubscribeLocalEvent(OnBeforeIntercomUiOpen);
+ SubscribeLocalEvent(OnIntercomEncryptionChannelsChanged);
SubscribeLocalEvent(OnToggleIntercomMic);
SubscribeLocalEvent(OnToggleIntercomSpeaker);
SubscribeLocalEvent(OnSelectIntercomChannel);
@@ -150,18 +147,18 @@ public sealed class RadioDeviceSystem : EntitySystem
SetSpeakerEnabled(uid, user, !component.Enabled, quiet, component);
}
- public void SetSpeakerEnabled(EntityUid uid, EntityUid user, bool enabled, bool quiet = false, RadioSpeakerComponent? component = null)
+ public void SetSpeakerEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioSpeakerComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
component.Enabled = enabled;
- if (!quiet)
+ if (!quiet && user != null)
{
var state = Loc.GetString(component.Enabled ? "handheld-radio-component-on-state" : "handheld-radio-component-off-state");
var message = Loc.GetString("handheld-radio-component-on-use", ("radioState", state));
- _popup.PopupEntity(message, user, user);
+ _popup.PopupEntity(message, user.Value, user.Value);
}
_appearance.SetData(uid, RadioDeviceVisuals.Speaker, component.Enabled);
@@ -213,61 +210,74 @@ public sealed class RadioDeviceSystem : EntitySystem
var nameEv = new TransformSpeakerNameEvent(args.MessageSource, Name(args.MessageSource));
RaiseLocalEvent(args.MessageSource, nameEv);
- var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)),
+ var name = Loc.GetString("speech-name-relay",
+ ("speaker", Name(uid)),
("originalName", nameEv.Name));
// log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios
_chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false);
}
- private void OnBeforeIntercomUiOpen(EntityUid uid, IntercomComponent component, BeforeActivatableUIOpenEvent args)
+ private void OnIntercomEncryptionChannelsChanged(Entity ent, ref EncryptionChannelsChangedEvent args)
{
- UpdateIntercomUi(uid, component);
+ ent.Comp.SupportedChannels = args.Component.Channels.Select(p => new ProtoId(p)).ToList();
+
+ var channel = args.Component.DefaultChannel;
+ if (ent.Comp.CurrentChannel != null && ent.Comp.SupportedChannels.Contains(ent.Comp.CurrentChannel.Value))
+ channel = ent.Comp.CurrentChannel;
+
+ SetIntercomChannel(ent, channel);
}
- private void OnToggleIntercomMic(EntityUid uid, IntercomComponent component, ToggleIntercomMicMessage args)
+ private void OnToggleIntercomMic(Entity ent, ref ToggleIntercomMicMessage args)
{
- if (component.RequiresPower && !this.IsPowered(uid, EntityManager))
+ if (ent.Comp.RequiresPower && !this.IsPowered(ent, EntityManager))
return;
- SetMicrophoneEnabled(uid, args.Actor, args.Enabled, true);
- UpdateIntercomUi(uid, component);
+ SetMicrophoneEnabled(ent, args.Actor, args.Enabled, true);
+ ent.Comp.MicrophoneEnabled = args.Enabled;
+ Dirty(ent);
}
- private void OnToggleIntercomSpeaker(EntityUid uid, IntercomComponent component, ToggleIntercomSpeakerMessage args)
+ private void OnToggleIntercomSpeaker(Entity ent, ref ToggleIntercomSpeakerMessage args)
{
- if (component.RequiresPower && !this.IsPowered(uid, EntityManager))
+ if (ent.Comp.RequiresPower && !this.IsPowered(ent, EntityManager))
return;
- SetSpeakerEnabled(uid, args.Actor, args.Enabled, true);
- UpdateIntercomUi(uid, component);
+ SetSpeakerEnabled(ent, args.Actor, args.Enabled, true);
+ ent.Comp.SpeakerEnabled = args.Enabled;
+ Dirty(ent);
}
- private void OnSelectIntercomChannel(EntityUid uid, IntercomComponent component, SelectIntercomChannelMessage args)
+ private void OnSelectIntercomChannel(Entity ent, ref SelectIntercomChannelMessage args)
{
- if (component.RequiresPower && !this.IsPowered(uid, EntityManager))
+ if (ent.Comp.RequiresPower && !this.IsPowered(ent, EntityManager))
return;
- if (!_protoMan.TryIndex(args.Channel, out _) || !component.SupportedChannels.Contains(args.Channel))
+ if (!_protoMan.HasIndex(args.Channel) || !ent.Comp.SupportedChannels.Contains(args.Channel))
return;
- if (TryComp(uid, out var mic))
- mic.BroadcastChannel = args.Channel;
- if (TryComp(uid, out var speaker))
- speaker.Channels = new(){ args.Channel };
- UpdateIntercomUi(uid, component);
+ SetIntercomChannel(ent, args.Channel);
}
- private void UpdateIntercomUi(EntityUid uid, IntercomComponent component)
+ private void SetIntercomChannel(Entity ent, ProtoId? channel)
{
- var micComp = CompOrNull(uid);
- var speakerComp = CompOrNull(uid);
+ ent.Comp.CurrentChannel = channel;
- var micEnabled = micComp?.Enabled ?? false;
- var speakerEnabled = speakerComp?.Enabled ?? false;
- var availableChannels = component.SupportedChannels;
- var selectedChannel = micComp?.BroadcastChannel ?? SharedChatSystem.CommonChannel;
- var state = new IntercomBoundUIState(micEnabled, speakerEnabled, availableChannels, selectedChannel);
- _ui.SetUiState(uid, IntercomUiKey.Key, state);
+ if (channel == null)
+ {
+ SetSpeakerEnabled(ent, null, false);
+ SetMicrophoneEnabled(ent, null, false);
+ ent.Comp.MicrophoneEnabled = false;
+ ent.Comp.SpeakerEnabled = false;
+ Dirty(ent);
+ return;
+ }
+
+ if (TryComp(ent, out var mic))
+ mic.BroadcastChannel = channel;
+ if (TryComp(ent, out var speaker))
+ speaker.Channels = new(){ channel };
+ Dirty(ent);
}
}
diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs
index 4341746aaf..3ad101e62d 100644
--- a/Content.Server/Radio/EntitySystems/RadioSystem.cs
+++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs
@@ -33,11 +33,15 @@ public sealed class RadioSystem : EntitySystem
// set used to prevent radio feedback loops.
private readonly HashSet _messages = new();
+ private EntityQuery _exemptQuery;
+
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnIntrinsicReceive);
SubscribeLocalEvent(OnIntrinsicSpeak);
+
+ _exemptQuery = GetEntityQuery();
}
private void OnIntrinsicSpeak(EntityUid uid, IntrinsicRadioTransmitterComponent component, EntitySpokeEvent args)
@@ -121,9 +125,8 @@ public sealed class RadioSystem : EntitySystem
var sourceMapId = Transform(radioSource).MapID;
var hasActiveServer = HasActiveServer(sourceMapId, channel.ID);
- var hasMicro = HasComp(radioSource);
+ var sourceServerExempt = _exemptQuery.HasComp(radioSource);
- var speakerQuery = GetEntityQuery();
var radioQuery = EntityQueryEnumerator();
while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform))
{
@@ -138,7 +141,7 @@ public sealed class RadioSystem : EntitySystem
continue;
// don't need telecom server for long range channels or handheld radios and intercoms
- var needServer = !channel.LongRange && (!hasMicro || !speakerQuery.HasComponent(receiver));
+ var needServer = !channel.LongRange && !sourceServerExempt;
if (needServer && !hasActiveServer)
continue;
diff --git a/Content.Shared/Radio/Components/IntercomComponent.cs b/Content.Shared/Radio/Components/IntercomComponent.cs
index be2734ff16..8d7b87597b 100644
--- a/Content.Shared/Radio/Components/IntercomComponent.cs
+++ b/Content.Shared/Radio/Components/IntercomComponent.cs
@@ -1,23 +1,32 @@
using Robust.Shared.GameStates;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
+using Robust.Shared.Prototypes;
namespace Content.Shared.Radio.Components;
///
/// Handles intercom ui and is authoritative on the channels an intercom can access.
///
-[RegisterComponent, NetworkedComponent]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
public sealed partial class IntercomComponent : Component
{
///
- /// Does this intercom require popwer to function
+ /// Does this intercom require power to function
///
- [DataField("requiresPower"), ViewVariables(VVAccess.ReadWrite)]
+ [DataField]
public bool RequiresPower = true;
+ [DataField, AutoNetworkedField]
+ public bool SpeakerEnabled;
+
+ [DataField, AutoNetworkedField]
+ public bool MicrophoneEnabled;
+
+ [DataField, AutoNetworkedField]
+ public ProtoId? CurrentChannel;
+
///
/// The list of radio channel prototypes this intercom can choose between.
///
- [DataField("supportedChannels", customTypeSerializer: typeof(PrototypeIdListSerializer))]
- public List SupportedChannels = new();
+ [DataField, AutoNetworkedField]
+ public List> SupportedChannels = new();
}
diff --git a/Content.Shared/Radio/Components/TelecomExemptComponent.cs b/Content.Shared/Radio/Components/TelecomExemptComponent.cs
new file mode 100644
index 0000000000..7af5c1c78c
--- /dev/null
+++ b/Content.Shared/Radio/Components/TelecomExemptComponent.cs
@@ -0,0 +1,9 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Radio.Components;
+
+///
+/// This is used for a radio that doesn't need a telecom server in order to broadcast.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class TelecomExemptComponent : Component;
diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs
index ea07b5f8a5..cfa553661a 100644
--- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs
+++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs
@@ -31,6 +31,7 @@ public sealed partial class EncryptionKeySystem : EntitySystem
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
+ [Dependency] private readonly SharedWiresSystem _wires = default!;
public override void Initialize()
{
@@ -150,7 +151,7 @@ public sealed partial class EncryptionKeySystem : EntitySystem
return;
}
- if (TryComp(uid, out var panel) && !panel.Open)
+ if (!_wires.IsPanelOpen(uid))
{
_popup.PopupClient(Loc.GetString("encryption-keys-panel-locked"), uid, args.User);
return;
@@ -184,8 +185,15 @@ public sealed partial class EncryptionKeySystem : EntitySystem
if (component.Channels.Count > 0)
{
- args.PushMarkup(Loc.GetString("examine-encryption-channels-prefix"));
- AddChannelsExamine(component.Channels, component.DefaultChannel, args, _protoManager, "examine-encryption-channel");
+ using (args.PushGroup(nameof(EncryptionKeyComponent)))
+ {
+ args.PushMarkup(Loc.GetString("examine-encryption-channels-prefix"));
+ AddChannelsExamine(component.Channels,
+ component.DefaultChannel,
+ args,
+ _protoManager,
+ "examine-encryption-channel");
+ }
}
}
diff --git a/Content.Shared/Radio/SharedIntercom.cs b/Content.Shared/Radio/SharedIntercom.cs
index 410843312f..f697add8b9 100644
--- a/Content.Shared/Radio/SharedIntercom.cs
+++ b/Content.Shared/Radio/SharedIntercom.cs
@@ -1,4 +1,5 @@
-using Robust.Shared.Serialization;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
namespace Content.Shared.Radio;
@@ -8,23 +9,6 @@ public enum IntercomUiKey
Key,
}
-[Serializable, NetSerializable]
-public sealed class IntercomBoundUIState : BoundUserInterfaceState
-{
- public bool MicEnabled;
- public bool SpeakerEnabled;
- public List AvailableChannels;
- public string SelectedChannel;
-
- public IntercomBoundUIState(bool micEnabled, bool speakerEnabled, List availableChannels, string selectedChannel)
- {
- MicEnabled = micEnabled;
- SpeakerEnabled = speakerEnabled;
- AvailableChannels = availableChannels;
- SelectedChannel = selectedChannel;
- }
-}
-
[Serializable, NetSerializable]
public sealed class ToggleIntercomMicMessage : BoundUserInterfaceMessage
{
diff --git a/Content.Shared/Wires/SharedWiresSystem.cs b/Content.Shared/Wires/SharedWiresSystem.cs
index d84766a5fc..7032293eaf 100644
--- a/Content.Shared/Wires/SharedWiresSystem.cs
+++ b/Content.Shared/Wires/SharedWiresSystem.cs
@@ -20,6 +20,7 @@ public abstract class SharedWiresSystem : EntitySystem
{
base.Initialize();
+ SubscribeLocalEvent(OnStartup);
SubscribeLocalEvent(OnPanelDoAfter);
SubscribeLocalEvent(OnInteractUsing);
SubscribeLocalEvent(OnExamine);
@@ -28,6 +29,11 @@ public abstract class SharedWiresSystem : EntitySystem
SubscribeLocalEvent(OnActivatableUIPanelChanged);
}
+ private void OnStartup(Entity ent, ref ComponentStartup args)
+ {
+ UpdateAppearance(ent, ent);
+ }
+
private void OnPanelDoAfter(EntityUid uid, WiresPanelComponent panel, WirePanelDoAfterEvent args)
{
if (args.Cancelled)
diff --git a/Resources/Locale/en-US/radio/components/intercom.ftl b/Resources/Locale/en-US/radio/components/intercom.ftl
index e56e3cd0f7..63303999c2 100644
--- a/Resources/Locale/en-US/radio/components/intercom.ftl
+++ b/Resources/Locale/en-US/radio/components/intercom.ftl
@@ -1,5 +1,6 @@
intercom-menu-title = Intercom
intercom-channel-label = Channel:
intercom-button-text-mic = Mic.
-intercom-button-text-speaker = Speak
+intercom-button-text-speaker = Spkr.
+intercom-options-none = No channels
intercom-flavor-text-left = Keep lines free of chatter
diff --git a/Resources/Prototypes/Entities/Objects/Devices/radio.yml b/Resources/Prototypes/Entities/Objects/Devices/radio.yml
index 43f84fe404..77b6cac2d3 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/radio.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/radio.yml
@@ -4,6 +4,7 @@
parent: BaseItem
id: RadioHandheld
components:
+ - type: TelecomExempt
- type: RadioMicrophone
broadcastChannel: Handheld
- type: RadioSpeaker
@@ -39,4 +40,4 @@
sprite: Objects/Devices/securityhandy.rsi
- type: Item
sprite: Objects/Devices/securityhandy.rsi
- heldPrefix: walkietalkie
\ No newline at end of file
+ heldPrefix: walkietalkie
diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/intercom.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/intercom.yml
index 2cf77d843c..ca1b1b6c40 100644
--- a/Resources/Prototypes/Entities/Structures/Wallmounts/intercom.yml
+++ b/Resources/Prototypes/Entities/Structures/Wallmounts/intercom.yml
@@ -1,5 +1,5 @@
- type: entity
- id: Intercom
+ id: BaseIntercom
name: intercom
description: An intercom. For when the station just needs to know something.
abstract: true
@@ -9,6 +9,10 @@
- type: Electrified
enabled: false
usesApcPower: true
+ - type: TelecomExempt
+ - type: EncryptionKeyHolder
+ keySlots: 3
+ keysExtractionMethod: Prying
- type: RadioMicrophone
powerRequired: true
unobstructedRequired: true
@@ -24,12 +28,14 @@
- type: InteractionOutline
- type: Appearance
- type: WiresVisuals
+ - type: WiresPanelSecurity
- type: ContainerFill
containers:
board: [ IntercomElectronics ]
- type: ContainerContainer
containers:
board: !type:Container
+ key_slots: !type:Container
- type: Sprite
noRot: false
drawdepth: SmallObjects
@@ -49,7 +55,6 @@
visible: false
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- shader: unshaded
visible: false
- type: Transform
noRot: false
@@ -61,6 +66,7 @@
- type: ActivatableUIRequiresPower
- type: ActivatableUI
key: enum.IntercomUiKey.Key
+ singleUser: true
- type: UserInterface
interfaces:
enum.IntercomUiKey.Key:
@@ -116,7 +122,7 @@
- Wallmount
- type: entity
- id: IntercomAssesmbly
+ id: IntercomAssembly
name: intercom assembly
description: An intercom. It doesn't seem very helpful right now.
components:
@@ -126,7 +132,18 @@
- type: Sprite
drawdepth: SmallObjects
sprite: Structures/Wallmounts/intercom.rsi
- state: build
+ layers:
+ - state: build
+ - state: panel
+ visible: false
+ map: [ "wires" ]
+ - type: Appearance
+ - type: GenericVisualizer
+ visuals:
+ enum.ConstructionVisuals.Layer:
+ wires:
+ 0: { visible: false }
+ 1: { visible: true }
- type: Construction
graph: Intercom
node: assembly
@@ -137,97 +154,176 @@
snap:
- Wallmount
+# this weird inheritance BS exists for construction shitcode
+- type: entity
+ id: IntercomConstructed
+ parent: BaseIntercom
+ suffix: Empty, Panel Open
+ components:
+ - type: Sprite
+ layers:
+ - state: base
+ - state: unshaded
+ map: ["enum.PowerDeviceVisualLayers.Powered"]
+ shader: unshaded
+ - state: broadcasting
+ map: ["enum.RadioDeviceVisualLayers.Broadcasting"]
+ shader: unshaded
+ visible: false
+ - state: speaker
+ map: ["enum.RadioDeviceVisualLayers.Speaker"]
+ shader: unshaded
+ visible: false
+ - state: panel
+ map: ["enum.WiresVisualLayers.MaintenancePanel"]
+ visible: true
+ - type: WiresPanel
+ open: true
+
+- type: entity
+ id: Intercom
+ parent: IntercomConstructed
+ suffix: ""
+ components:
+ - type: Sprite
+ layers:
+ - state: base
+ - state: unshaded
+ map: ["enum.PowerDeviceVisualLayers.Powered"]
+ shader: unshaded
+ - state: broadcasting
+ map: ["enum.RadioDeviceVisualLayers.Broadcasting"]
+ shader: unshaded
+ visible: false
+ - state: speaker
+ map: ["enum.RadioDeviceVisualLayers.Speaker"]
+ shader: unshaded
+ visible: false
+ - state: panel
+ map: ["enum.WiresVisualLayers.MaintenancePanel"]
+ - type: WiresPanel
+ open: false
+
- type: entity
id: IntercomCommon
parent: Intercom
suffix: Common
components:
- - type: Intercom
- supportedChannels:
- - Common
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
- type: entity
id: IntercomCommand
parent: Intercom
suffix: Command
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Command
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyCommand
- type: entity
id: IntercomEngineering
parent: Intercom
suffix: Engineering
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Engineering
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyEngineering
- type: entity
id: IntercomMedical
parent: Intercom
suffix: Medical
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Medical
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyMedical
- type: entity
id: IntercomScience
parent: Intercom
suffix: Science
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Science
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyScience
- type: entity
id: IntercomSecurity
parent: Intercom
suffix: Security
+ description: An intercom. It's been reinforced with metal from security helmets, making it a bitch-and-a-half to open.
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Security
+ - type: WiresPanel
+ openDelay: 5
+ - type: WiresPanelSecurity
+ examine: wires-panel-component-on-examine-security-level2
+ wiresAccessible: false
+ - type: Construction
+ node: intercomReinforced
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeySecurity
- type: entity
id: IntercomService
parent: Intercom
suffix: Service
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Service
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyService
- type: entity
id: IntercomSupply
parent: Intercom
suffix: Supply
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Supply
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyCargo
- type: entity
id: IntercomAll
parent: Intercom
suffix: All
components:
- - type: Intercom
- supportedChannels:
- - Common
- - Command
- - Engineering
- - Medical
- - Science
- - Security
- - Service
- - Supply
+ - type: ContainerFill
+ containers:
+ board:
+ - IntercomElectronics
+ key_slots:
+ - EncryptionKeyCommon
+ - EncryptionKeyStationMaster
diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/intercom.yml b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/intercom.yml
index 2247860f89..ba29d72539 100644
--- a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/intercom.yml
+++ b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/intercom.yml
@@ -11,13 +11,17 @@
doAfter: 2.0
- node: assembly
- entity: IntercomAssesmbly
+ entity: IntercomAssembly
edges:
- to: wired
steps:
- material: Cable
amount: 2
doAfter: 1
+ completed:
+ - !type:VisualizerDataInt
+ key: "enum.ConstructionVisuals.Layer"
+ data: 1
- to: start
completed:
- !type:GivePrototype
@@ -29,7 +33,7 @@
doAfter: 2
- node: wired
- entity: IntercomAssesmbly
+ entity: IntercomAssembly
edges:
- to: electronics
steps:
@@ -45,6 +49,9 @@
- !type:GivePrototype
prototype: CableApcStack1
amount: 2
+ - !type:VisualizerDataInt
+ key: "enum.ConstructionVisuals.Layer"
+ data: 0
steps:
- tool: Cutting
doAfter: 1
@@ -57,7 +64,11 @@
doAfter: 2
- node: intercom
- entity: IntercomCommon #TODO: make this work with encryption keys
+ entity: IntercomConstructed
+ doNotReplaceInheritingEntities: true
+ actions:
+ - !type:SetWiresPanelSecurity
+ wiresAccessible: true
edges:
- to: wired
conditions:
@@ -72,3 +83,27 @@
steps:
- tool: Prying
doAfter: 1
+ - to: intercomReinforced
+ conditions:
+ - !type:WirePanel
+ steps:
+ - material: Steel
+ amount: 1
+ - tool: Welding
+ doAfter: 1
+
+ - node: intercomReinforced
+ actions:
+ - !type:SetWiresPanelSecurity
+ examine: wires-panel-component-on-examine-security-level2
+ wiresAccessible: false
+ edges:
+ - to: intercom
+ conditions:
+ - !type:WirePanel
+ completed:
+ - !type:GivePrototype
+ prototype: SheetSteel1
+ steps:
+ - tool: Welding
+ doAfter: 5
diff --git a/Resources/Prototypes/Recipes/Construction/utilities.yml b/Resources/Prototypes/Recipes/Construction/utilities.yml
index 19f2fee183..82c16de7b6 100644
--- a/Resources/Prototypes/Recipes/Construction/utilities.yml
+++ b/Resources/Prototypes/Recipes/Construction/utilities.yml
@@ -790,7 +790,7 @@
# INTERCOM
- type: construction
name: intercom
- id: IntercomAssesmbly
+ id: IntercomAssembly
graph: Intercom
startNode: start
targetNode: intercom
diff --git a/Resources/Textures/Structures/Wallmounts/intercom.rsi/base.png b/Resources/Textures/Structures/Wallmounts/intercom.rsi/base.png
index 787af3f538..a85cbfbecc 100644
Binary files a/Resources/Textures/Structures/Wallmounts/intercom.rsi/base.png and b/Resources/Textures/Structures/Wallmounts/intercom.rsi/base.png differ
diff --git a/Resources/Textures/Structures/Wallmounts/intercom.rsi/broadcasting.png b/Resources/Textures/Structures/Wallmounts/intercom.rsi/broadcasting.png
index 0566c70e35..962417ccb4 100644
Binary files a/Resources/Textures/Structures/Wallmounts/intercom.rsi/broadcasting.png and b/Resources/Textures/Structures/Wallmounts/intercom.rsi/broadcasting.png differ
diff --git a/Resources/Textures/Structures/Wallmounts/intercom.rsi/build.png b/Resources/Textures/Structures/Wallmounts/intercom.rsi/build.png
index cfd5d5fffa..e8edab0fa0 100644
Binary files a/Resources/Textures/Structures/Wallmounts/intercom.rsi/build.png and b/Resources/Textures/Structures/Wallmounts/intercom.rsi/build.png differ
diff --git a/Resources/Textures/Structures/Wallmounts/intercom.rsi/panel.png b/Resources/Textures/Structures/Wallmounts/intercom.rsi/panel.png
index 3bfeb8df58..68f4cd1240 100644
Binary files a/Resources/Textures/Structures/Wallmounts/intercom.rsi/panel.png and b/Resources/Textures/Structures/Wallmounts/intercom.rsi/panel.png differ
diff --git a/Resources/Textures/Structures/Wallmounts/intercom.rsi/speaker.png b/Resources/Textures/Structures/Wallmounts/intercom.rsi/speaker.png
index eb09c52fc3..4bcd29d7f4 100644
Binary files a/Resources/Textures/Structures/Wallmounts/intercom.rsi/speaker.png and b/Resources/Textures/Structures/Wallmounts/intercom.rsi/speaker.png differ
diff --git a/Resources/Textures/Structures/Wallmounts/intercom.rsi/unshaded.png b/Resources/Textures/Structures/Wallmounts/intercom.rsi/unshaded.png
index 7b0bb63072..a8fda54fc9 100644
Binary files a/Resources/Textures/Structures/Wallmounts/intercom.rsi/unshaded.png and b/Resources/Textures/Structures/Wallmounts/intercom.rsi/unshaded.png differ
diff --git a/Resources/migration.yml b/Resources/migration.yml
index ef0a5f46b7..bd42de8f2c 100644
--- a/Resources/migration.yml
+++ b/Resources/migration.yml
@@ -358,3 +358,6 @@ FloorTileItemReinforced: PartRodMetal1
#2024-06-25
BookChefGaming: BookHowToCookForFortySpaceman
+
+#2024-06-29
+IntercomAssesmbly: IntercomAssembly