Intercom buffs and fixes (#29580)

* Intercom buffs and fixes

* remove unused bui state

* mild sec intercom buff

* reinforce sec intercoms
This commit is contained in:
Nemanja
2024-07-07 10:19:10 -04:00
committed by GitHub
parent 063c5de985
commit 0e9ed36b85
22 changed files with 338 additions and 136 deletions

View File

@@ -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!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<IntercomComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
}
private void OnAfterHandleState(Entity<IntercomComponent> ent, ref AfterAutoHandleStateEvent args)
{
if (_ui.TryGetOpenUi<IntercomBoundUserInterface>(ent.Owner, IntercomUiKey.Key, out var bui))
bui.Update(ent);
}
}

View File

@@ -1,6 +1,6 @@
using Content.Shared.Radio; using Content.Shared.Radio;
using Content.Shared.Radio.Components;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects;
namespace Content.Client.Radio.Ui; namespace Content.Client.Radio.Ui;
@@ -19,7 +19,9 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface
{ {
base.Open(); base.Open();
_menu = new(); var comp = EntMan.GetComponent<IntercomComponent>(Owner);
_menu = new((Owner, comp));
_menu.OnMicPressed += enabled => _menu.OnMicPressed += enabled =>
{ {
@@ -46,13 +48,8 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface
_menu?.Close(); _menu?.Close();
} }
protected override void UpdateState(BoundUserInterfaceState state) public void Update(Entity<IntercomComponent> ent)
{ {
base.UpdateState(state); _menu?.Update(ent);
if (state is not IntercomBoundUIState msg)
return;
_menu?.Update(msg);
} }
} }

View File

@@ -1,8 +1,9 @@
using Content.Client.UserInterface.Controls; using Content.Client.UserInterface.Controls;
using Content.Shared.Radio; using Content.Shared.Radio.Components;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client.Radio.Ui; namespace Content.Client.Radio.Ui;
@@ -17,38 +18,54 @@ public sealed partial class IntercomMenu : FancyWindow
private readonly List<string> _channels = new(); private readonly List<string> _channels = new();
public IntercomMenu() public IntercomMenu(Entity<IntercomComponent> entity)
{ {
RobustXamlLoader.Load(this); RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
MicButton.OnPressed += args => OnMicPressed?.Invoke(args.Button.Pressed); MicButton.OnPressed += args => OnMicPressed?.Invoke(args.Button.Pressed);
SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed); SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed);
Update(entity);
} }
public void Update(IntercomBoundUIState state) public void Update(Entity<IntercomComponent> entity)
{ {
MicButton.Pressed = state.MicEnabled; MicButton.Pressed = entity.Comp.MicrophoneEnabled;
SpeakerButton.Pressed = state.SpeakerEnabled; 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(); ChannelOptions.Clear();
_channels.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]; var channel = entity.Comp.SupportedChannels[i];
if (!_prototype.TryIndex<RadioChannelPrototype>(channel, out var prototype)) if (!_prototype.TryIndex(channel, out var prototype))
continue; continue;
_channels.Add(channel); _channels.Add(channel);
ChannelOptions.AddItem(Loc.GetString(prototype.Name), i); ChannelOptions.AddItem(Loc.GetString(prototype.Name), i);
if (channel == state.SelectedChannel) if (channel == entity.Comp.CurrentChannel)
ChannelOptions.Select(i); ChannelOptions.Select(i);
} }
if (entity.Comp.SupportedChannels.Count == 0)
{
ChannelOptions.AddItem(Loc.GetString("intercom-options-none"), 0);
ChannelOptions.Select(0);
}
ChannelOptions.OnItemSelected += args => ChannelOptions.OnItemSelected += args =>
{ {
if (!_channels.TryGetValue(args.Id, out var proto))
return;
ChannelOptions.SelectId(args.Id); ChannelOptions.SelectId(args.Id);
OnChannelSelected?.Invoke(_channels[args.Id]); OnChannelSelected?.Invoke(proto);
}; };
} }
} }

View File

@@ -1,3 +1,4 @@
using System.Linq;
using Content.Server.Chat.Systems; using Content.Server.Chat.Systems;
using Content.Server.Interaction; using Content.Server.Interaction;
using Content.Server.Popups; using Content.Server.Popups;
@@ -6,13 +7,10 @@ using Content.Server.Power.EntitySystems;
using Content.Server.Radio.Components; using Content.Server.Radio.Components;
using Content.Server.Speech; using Content.Server.Speech;
using Content.Server.Speech.Components; using Content.Server.Speech.Components;
using Content.Shared.UserInterface;
using Content.Shared.Chat;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Radio; using Content.Shared.Radio;
using Content.Shared.Radio.Components; using Content.Shared.Radio.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Server.Radio.EntitySystems; namespace Content.Server.Radio.EntitySystems;
@@ -28,7 +26,6 @@ public sealed class RadioDeviceSystem : EntitySystem
[Dependency] private readonly RadioSystem _radio = default!; [Dependency] private readonly RadioSystem _radio = default!;
[Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly InteractionSystem _interaction = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = 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. // Used to prevent a shitter from using a bunch of radios to spam chat.
private HashSet<(string, EntityUid)> _recentlySent = new(); private HashSet<(string, EntityUid)> _recentlySent = new();
@@ -47,7 +44,7 @@ public sealed class RadioDeviceSystem : EntitySystem
SubscribeLocalEvent<RadioSpeakerComponent, ActivateInWorldEvent>(OnActivateSpeaker); SubscribeLocalEvent<RadioSpeakerComponent, ActivateInWorldEvent>(OnActivateSpeaker);
SubscribeLocalEvent<RadioSpeakerComponent, RadioReceiveEvent>(OnReceiveRadio); SubscribeLocalEvent<RadioSpeakerComponent, RadioReceiveEvent>(OnReceiveRadio);
SubscribeLocalEvent<IntercomComponent, BeforeActivatableUIOpenEvent>(OnBeforeIntercomUiOpen); SubscribeLocalEvent<IntercomComponent, EncryptionChannelsChangedEvent>(OnIntercomEncryptionChannelsChanged);
SubscribeLocalEvent<IntercomComponent, ToggleIntercomMicMessage>(OnToggleIntercomMic); SubscribeLocalEvent<IntercomComponent, ToggleIntercomMicMessage>(OnToggleIntercomMic);
SubscribeLocalEvent<IntercomComponent, ToggleIntercomSpeakerMessage>(OnToggleIntercomSpeaker); SubscribeLocalEvent<IntercomComponent, ToggleIntercomSpeakerMessage>(OnToggleIntercomSpeaker);
SubscribeLocalEvent<IntercomComponent, SelectIntercomChannelMessage>(OnSelectIntercomChannel); SubscribeLocalEvent<IntercomComponent, SelectIntercomChannelMessage>(OnSelectIntercomChannel);
@@ -150,18 +147,18 @@ public sealed class RadioDeviceSystem : EntitySystem
SetSpeakerEnabled(uid, user, !component.Enabled, quiet, component); 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)) if (!Resolve(uid, ref component))
return; return;
component.Enabled = enabled; 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 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)); 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); _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)); var nameEv = new TransformSpeakerNameEvent(args.MessageSource, Name(args.MessageSource));
RaiseLocalEvent(args.MessageSource, nameEv); 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)); ("originalName", nameEv.Name));
// log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios // 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); _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<IntercomComponent> ent, ref EncryptionChannelsChangedEvent args)
{ {
UpdateIntercomUi(uid, component); ent.Comp.SupportedChannels = args.Component.Channels.Select(p => new ProtoId<RadioChannelPrototype>(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<IntercomComponent> ent, ref ToggleIntercomMicMessage args)
{ {
if (component.RequiresPower && !this.IsPowered(uid, EntityManager)) if (ent.Comp.RequiresPower && !this.IsPowered(ent, EntityManager))
return; return;
SetMicrophoneEnabled(uid, args.Actor, args.Enabled, true); SetMicrophoneEnabled(ent, args.Actor, args.Enabled, true);
UpdateIntercomUi(uid, component); ent.Comp.MicrophoneEnabled = args.Enabled;
Dirty(ent);
} }
private void OnToggleIntercomSpeaker(EntityUid uid, IntercomComponent component, ToggleIntercomSpeakerMessage args) private void OnToggleIntercomSpeaker(Entity<IntercomComponent> ent, ref ToggleIntercomSpeakerMessage args)
{ {
if (component.RequiresPower && !this.IsPowered(uid, EntityManager)) if (ent.Comp.RequiresPower && !this.IsPowered(ent, EntityManager))
return; return;
SetSpeakerEnabled(uid, args.Actor, args.Enabled, true); SetSpeakerEnabled(ent, args.Actor, args.Enabled, true);
UpdateIntercomUi(uid, component); ent.Comp.SpeakerEnabled = args.Enabled;
Dirty(ent);
} }
private void OnSelectIntercomChannel(EntityUid uid, IntercomComponent component, SelectIntercomChannelMessage args) private void OnSelectIntercomChannel(Entity<IntercomComponent> ent, ref SelectIntercomChannelMessage args)
{ {
if (component.RequiresPower && !this.IsPowered(uid, EntityManager)) if (ent.Comp.RequiresPower && !this.IsPowered(ent, EntityManager))
return; return;
if (!_protoMan.TryIndex<RadioChannelPrototype>(args.Channel, out _) || !component.SupportedChannels.Contains(args.Channel)) if (!_protoMan.HasIndex<RadioChannelPrototype>(args.Channel) || !ent.Comp.SupportedChannels.Contains(args.Channel))
return; return;
if (TryComp<RadioMicrophoneComponent>(uid, out var mic)) SetIntercomChannel(ent, args.Channel);
mic.BroadcastChannel = args.Channel;
if (TryComp<RadioSpeakerComponent>(uid, out var speaker))
speaker.Channels = new(){ args.Channel };
UpdateIntercomUi(uid, component);
} }
private void UpdateIntercomUi(EntityUid uid, IntercomComponent component) private void SetIntercomChannel(Entity<IntercomComponent> ent, ProtoId<RadioChannelPrototype>? channel)
{ {
var micComp = CompOrNull<RadioMicrophoneComponent>(uid); ent.Comp.CurrentChannel = channel;
var speakerComp = CompOrNull<RadioSpeakerComponent>(uid);
var micEnabled = micComp?.Enabled ?? false; if (channel == null)
var speakerEnabled = speakerComp?.Enabled ?? false; {
var availableChannels = component.SupportedChannels; SetSpeakerEnabled(ent, null, false);
var selectedChannel = micComp?.BroadcastChannel ?? SharedChatSystem.CommonChannel; SetMicrophoneEnabled(ent, null, false);
var state = new IntercomBoundUIState(micEnabled, speakerEnabled, availableChannels, selectedChannel); ent.Comp.MicrophoneEnabled = false;
_ui.SetUiState(uid, IntercomUiKey.Key, state); ent.Comp.SpeakerEnabled = false;
Dirty(ent);
return;
}
if (TryComp<RadioMicrophoneComponent>(ent, out var mic))
mic.BroadcastChannel = channel;
if (TryComp<RadioSpeakerComponent>(ent, out var speaker))
speaker.Channels = new(){ channel };
Dirty(ent);
} }
} }

View File

@@ -33,11 +33,15 @@ public sealed class RadioSystem : EntitySystem
// set used to prevent radio feedback loops. // set used to prevent radio feedback loops.
private readonly HashSet<string> _messages = new(); private readonly HashSet<string> _messages = new();
private EntityQuery<TelecomExemptComponent> _exemptQuery;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<IntrinsicRadioReceiverComponent, RadioReceiveEvent>(OnIntrinsicReceive); SubscribeLocalEvent<IntrinsicRadioReceiverComponent, RadioReceiveEvent>(OnIntrinsicReceive);
SubscribeLocalEvent<IntrinsicRadioTransmitterComponent, EntitySpokeEvent>(OnIntrinsicSpeak); SubscribeLocalEvent<IntrinsicRadioTransmitterComponent, EntitySpokeEvent>(OnIntrinsicSpeak);
_exemptQuery = GetEntityQuery<TelecomExemptComponent>();
} }
private void OnIntrinsicSpeak(EntityUid uid, IntrinsicRadioTransmitterComponent component, EntitySpokeEvent args) private void OnIntrinsicSpeak(EntityUid uid, IntrinsicRadioTransmitterComponent component, EntitySpokeEvent args)
@@ -121,9 +125,8 @@ public sealed class RadioSystem : EntitySystem
var sourceMapId = Transform(radioSource).MapID; var sourceMapId = Transform(radioSource).MapID;
var hasActiveServer = HasActiveServer(sourceMapId, channel.ID); var hasActiveServer = HasActiveServer(sourceMapId, channel.ID);
var hasMicro = HasComp<RadioMicrophoneComponent>(radioSource); var sourceServerExempt = _exemptQuery.HasComp(radioSource);
var speakerQuery = GetEntityQuery<RadioSpeakerComponent>();
var radioQuery = EntityQueryEnumerator<ActiveRadioComponent, TransformComponent>(); var radioQuery = EntityQueryEnumerator<ActiveRadioComponent, TransformComponent>();
while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform)) while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform))
{ {
@@ -138,7 +141,7 @@ public sealed class RadioSystem : EntitySystem
continue; continue;
// don't need telecom server for long range channels or handheld radios and intercoms // 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) if (needServer && !hasActiveServer)
continue; continue;

View File

@@ -1,23 +1,32 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Prototypes;
namespace Content.Shared.Radio.Components; namespace Content.Shared.Radio.Components;
/// <summary> /// <summary>
/// Handles intercom ui and is authoritative on the channels an intercom can access. /// Handles intercom ui and is authoritative on the channels an intercom can access.
/// </summary> /// </summary>
[RegisterComponent, NetworkedComponent] [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
public sealed partial class IntercomComponent : Component public sealed partial class IntercomComponent : Component
{ {
/// <summary> /// <summary>
/// Does this intercom require popwer to function /// Does this intercom require power to function
/// </summary> /// </summary>
[DataField("requiresPower"), ViewVariables(VVAccess.ReadWrite)] [DataField]
public bool RequiresPower = true; public bool RequiresPower = true;
[DataField, AutoNetworkedField]
public bool SpeakerEnabled;
[DataField, AutoNetworkedField]
public bool MicrophoneEnabled;
[DataField, AutoNetworkedField]
public ProtoId<RadioChannelPrototype>? CurrentChannel;
/// <summary> /// <summary>
/// The list of radio channel prototypes this intercom can choose between. /// The list of radio channel prototypes this intercom can choose between.
/// </summary> /// </summary>
[DataField("supportedChannels", customTypeSerializer: typeof(PrototypeIdListSerializer<RadioChannelPrototype>))] [DataField, AutoNetworkedField]
public List<string> SupportedChannels = new(); public List<ProtoId<RadioChannelPrototype>> SupportedChannels = new();
} }

View File

@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Radio.Components;
/// <summary>
/// This is used for a radio that doesn't need a telecom server in order to broadcast.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class TelecomExemptComponent : Component;

View File

@@ -31,6 +31,7 @@ public sealed partial class EncryptionKeySystem : EntitySystem
[Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedWiresSystem _wires = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -150,7 +151,7 @@ public sealed partial class EncryptionKeySystem : EntitySystem
return; return;
} }
if (TryComp<WiresPanelComponent>(uid, out var panel) && !panel.Open) if (!_wires.IsPanelOpen(uid))
{ {
_popup.PopupClient(Loc.GetString("encryption-keys-panel-locked"), uid, args.User); _popup.PopupClient(Loc.GetString("encryption-keys-panel-locked"), uid, args.User);
return; return;
@@ -184,8 +185,15 @@ public sealed partial class EncryptionKeySystem : EntitySystem
if (component.Channels.Count > 0) if (component.Channels.Count > 0)
{ {
args.PushMarkup(Loc.GetString("examine-encryption-channels-prefix")); using (args.PushGroup(nameof(EncryptionKeyComponent)))
AddChannelsExamine(component.Channels, component.DefaultChannel, args, _protoManager, "examine-encryption-channel"); {
args.PushMarkup(Loc.GetString("examine-encryption-channels-prefix"));
AddChannelsExamine(component.Channels,
component.DefaultChannel,
args,
_protoManager,
"examine-encryption-channel");
}
} }
} }

View File

@@ -1,4 +1,5 @@
using Robust.Shared.Serialization; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Radio; namespace Content.Shared.Radio;
@@ -8,23 +9,6 @@ public enum IntercomUiKey
Key, Key,
} }
[Serializable, NetSerializable]
public sealed class IntercomBoundUIState : BoundUserInterfaceState
{
public bool MicEnabled;
public bool SpeakerEnabled;
public List<string> AvailableChannels;
public string SelectedChannel;
public IntercomBoundUIState(bool micEnabled, bool speakerEnabled, List<string> availableChannels, string selectedChannel)
{
MicEnabled = micEnabled;
SpeakerEnabled = speakerEnabled;
AvailableChannels = availableChannels;
SelectedChannel = selectedChannel;
}
}
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class ToggleIntercomMicMessage : BoundUserInterfaceMessage public sealed class ToggleIntercomMicMessage : BoundUserInterfaceMessage
{ {

View File

@@ -20,6 +20,7 @@ public abstract class SharedWiresSystem : EntitySystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<WiresPanelComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<WiresPanelComponent, WirePanelDoAfterEvent>(OnPanelDoAfter); SubscribeLocalEvent<WiresPanelComponent, WirePanelDoAfterEvent>(OnPanelDoAfter);
SubscribeLocalEvent<WiresPanelComponent, InteractUsingEvent>(OnInteractUsing); SubscribeLocalEvent<WiresPanelComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<WiresPanelComponent, ExaminedEvent>(OnExamine); SubscribeLocalEvent<WiresPanelComponent, ExaminedEvent>(OnExamine);
@@ -28,6 +29,11 @@ public abstract class SharedWiresSystem : EntitySystem
SubscribeLocalEvent<ActivatableUIRequiresPanelComponent, PanelChangedEvent>(OnActivatableUIPanelChanged); SubscribeLocalEvent<ActivatableUIRequiresPanelComponent, PanelChangedEvent>(OnActivatableUIPanelChanged);
} }
private void OnStartup(Entity<WiresPanelComponent> ent, ref ComponentStartup args)
{
UpdateAppearance(ent, ent);
}
private void OnPanelDoAfter(EntityUid uid, WiresPanelComponent panel, WirePanelDoAfterEvent args) private void OnPanelDoAfter(EntityUid uid, WiresPanelComponent panel, WirePanelDoAfterEvent args)
{ {
if (args.Cancelled) if (args.Cancelled)

View File

@@ -1,5 +1,6 @@
intercom-menu-title = Intercom intercom-menu-title = Intercom
intercom-channel-label = Channel: intercom-channel-label = Channel:
intercom-button-text-mic = Mic. 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 intercom-flavor-text-left = Keep lines free of chatter

View File

@@ -4,6 +4,7 @@
parent: BaseItem parent: BaseItem
id: RadioHandheld id: RadioHandheld
components: components:
- type: TelecomExempt
- type: RadioMicrophone - type: RadioMicrophone
broadcastChannel: Handheld broadcastChannel: Handheld
- type: RadioSpeaker - type: RadioSpeaker
@@ -39,4 +40,4 @@
sprite: Objects/Devices/securityhandy.rsi sprite: Objects/Devices/securityhandy.rsi
- type: Item - type: Item
sprite: Objects/Devices/securityhandy.rsi sprite: Objects/Devices/securityhandy.rsi
heldPrefix: walkietalkie heldPrefix: walkietalkie

View File

@@ -1,5 +1,5 @@
- type: entity - type: entity
id: Intercom id: BaseIntercom
name: intercom name: intercom
description: An intercom. For when the station just needs to know something. description: An intercom. For when the station just needs to know something.
abstract: true abstract: true
@@ -9,6 +9,10 @@
- type: Electrified - type: Electrified
enabled: false enabled: false
usesApcPower: true usesApcPower: true
- type: TelecomExempt
- type: EncryptionKeyHolder
keySlots: 3
keysExtractionMethod: Prying
- type: RadioMicrophone - type: RadioMicrophone
powerRequired: true powerRequired: true
unobstructedRequired: true unobstructedRequired: true
@@ -24,12 +28,14 @@
- type: InteractionOutline - type: InteractionOutline
- type: Appearance - type: Appearance
- type: WiresVisuals - type: WiresVisuals
- type: WiresPanelSecurity
- type: ContainerFill - type: ContainerFill
containers: containers:
board: [ IntercomElectronics ] board: [ IntercomElectronics ]
- type: ContainerContainer - type: ContainerContainer
containers: containers:
board: !type:Container board: !type:Container
key_slots: !type:Container
- type: Sprite - type: Sprite
noRot: false noRot: false
drawdepth: SmallObjects drawdepth: SmallObjects
@@ -49,7 +55,6 @@
visible: false visible: false
- state: panel - state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"] map: ["enum.WiresVisualLayers.MaintenancePanel"]
shader: unshaded
visible: false visible: false
- type: Transform - type: Transform
noRot: false noRot: false
@@ -61,6 +66,7 @@
- type: ActivatableUIRequiresPower - type: ActivatableUIRequiresPower
- type: ActivatableUI - type: ActivatableUI
key: enum.IntercomUiKey.Key key: enum.IntercomUiKey.Key
singleUser: true
- type: UserInterface - type: UserInterface
interfaces: interfaces:
enum.IntercomUiKey.Key: enum.IntercomUiKey.Key:
@@ -116,7 +122,7 @@
- Wallmount - Wallmount
- type: entity - type: entity
id: IntercomAssesmbly id: IntercomAssembly
name: intercom assembly name: intercom assembly
description: An intercom. It doesn't seem very helpful right now. description: An intercom. It doesn't seem very helpful right now.
components: components:
@@ -126,7 +132,18 @@
- type: Sprite - type: Sprite
drawdepth: SmallObjects drawdepth: SmallObjects
sprite: Structures/Wallmounts/intercom.rsi 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 - type: Construction
graph: Intercom graph: Intercom
node: assembly node: assembly
@@ -137,97 +154,176 @@
snap: snap:
- Wallmount - 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 - type: entity
id: IntercomCommon id: IntercomCommon
parent: Intercom parent: Intercom
suffix: Common suffix: Common
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- IntercomElectronics
key_slots:
- EncryptionKeyCommon
- type: entity - type: entity
id: IntercomCommand id: IntercomCommand
parent: Intercom parent: Intercom
suffix: Command suffix: Command
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Command - IntercomElectronics
key_slots:
- EncryptionKeyCommon
- EncryptionKeyCommand
- type: entity - type: entity
id: IntercomEngineering id: IntercomEngineering
parent: Intercom parent: Intercom
suffix: Engineering suffix: Engineering
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Engineering - IntercomElectronics
key_slots:
- EncryptionKeyCommon
- EncryptionKeyEngineering
- type: entity - type: entity
id: IntercomMedical id: IntercomMedical
parent: Intercom parent: Intercom
suffix: Medical suffix: Medical
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Medical - IntercomElectronics
key_slots:
- EncryptionKeyCommon
- EncryptionKeyMedical
- type: entity - type: entity
id: IntercomScience id: IntercomScience
parent: Intercom parent: Intercom
suffix: Science suffix: Science
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Science - IntercomElectronics
key_slots:
- EncryptionKeyCommon
- EncryptionKeyScience
- type: entity - type: entity
id: IntercomSecurity id: IntercomSecurity
parent: Intercom parent: Intercom
suffix: Security suffix: Security
description: An intercom. It's been reinforced with metal from security helmets, making it a bitch-and-a-half to open.
components: components:
- type: Intercom - type: WiresPanel
supportedChannels: openDelay: 5
- Common - type: WiresPanelSecurity
- Security 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 - type: entity
id: IntercomService id: IntercomService
parent: Intercom parent: Intercom
suffix: Service suffix: Service
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Service - IntercomElectronics
key_slots:
- EncryptionKeyCommon
- EncryptionKeyService
- type: entity - type: entity
id: IntercomSupply id: IntercomSupply
parent: Intercom parent: Intercom
suffix: Supply suffix: Supply
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Supply - IntercomElectronics
key_slots:
- EncryptionKeyCommon
- EncryptionKeyCargo
- type: entity - type: entity
id: IntercomAll id: IntercomAll
parent: Intercom parent: Intercom
suffix: All suffix: All
components: components:
- type: Intercom - type: ContainerFill
supportedChannels: containers:
- Common board:
- Command - IntercomElectronics
- Engineering key_slots:
- Medical - EncryptionKeyCommon
- Science - EncryptionKeyStationMaster
- Security
- Service
- Supply

View File

@@ -11,13 +11,17 @@
doAfter: 2.0 doAfter: 2.0
- node: assembly - node: assembly
entity: IntercomAssesmbly entity: IntercomAssembly
edges: edges:
- to: wired - to: wired
steps: steps:
- material: Cable - material: Cable
amount: 2 amount: 2
doAfter: 1 doAfter: 1
completed:
- !type:VisualizerDataInt
key: "enum.ConstructionVisuals.Layer"
data: 1
- to: start - to: start
completed: completed:
- !type:GivePrototype - !type:GivePrototype
@@ -29,7 +33,7 @@
doAfter: 2 doAfter: 2
- node: wired - node: wired
entity: IntercomAssesmbly entity: IntercomAssembly
edges: edges:
- to: electronics - to: electronics
steps: steps:
@@ -45,6 +49,9 @@
- !type:GivePrototype - !type:GivePrototype
prototype: CableApcStack1 prototype: CableApcStack1
amount: 2 amount: 2
- !type:VisualizerDataInt
key: "enum.ConstructionVisuals.Layer"
data: 0
steps: steps:
- tool: Cutting - tool: Cutting
doAfter: 1 doAfter: 1
@@ -57,7 +64,11 @@
doAfter: 2 doAfter: 2
- node: intercom - node: intercom
entity: IntercomCommon #TODO: make this work with encryption keys entity: IntercomConstructed
doNotReplaceInheritingEntities: true
actions:
- !type:SetWiresPanelSecurity
wiresAccessible: true
edges: edges:
- to: wired - to: wired
conditions: conditions:
@@ -72,3 +83,27 @@
steps: steps:
- tool: Prying - tool: Prying
doAfter: 1 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

View File

@@ -790,7 +790,7 @@
# INTERCOM # INTERCOM
- type: construction - type: construction
name: intercom name: intercom
id: IntercomAssesmbly id: IntercomAssembly
graph: Intercom graph: Intercom
startNode: start startNode: start
targetNode: intercom targetNode: intercom

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 B

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 217 B

View File

@@ -358,3 +358,6 @@ FloorTileItemReinforced: PartRodMetal1
#2024-06-25 #2024-06-25
BookChefGaming: BookHowToCookForFortySpaceman BookChefGaming: BookHowToCookForFortySpaceman
#2024-06-29
IntercomAssesmbly: IntercomAssembly