From 700611a6bee2716b665fc5d48906875ad2ac7735 Mon Sep 17 00:00:00 2001
From: username <32684670+Snorkcom@users.noreply.github.com>
Date: Sun, 16 Aug 2026 04:58:54 +0600
Subject: [PATCH 1/2] Add a guidebook page for communication channels
Adds a localized guidebook page under New Player > Controls that lists available radio and collective-mind channels with their chat keys and descriptions. The table is generated from game prototypes, supports filtering, highlights key prefixes, and allows copying non-empty keys by clicking them.
---
.../GuideCommunicationChannelsTable.cs | 380 ++++++++++++++++++
.../guidebook/communication-channels.ftl | 50 +++
.../guidebook/communication-channels.ftl | 50 +++
Resources/Prototypes/Guidebook/newplayer.yml | 1 +
.../Guidebook/communication_channels.yml | 7 +
.../Controls/CommunicationChannels.xml | 7 +
6 files changed, 495 insertions(+)
create mode 100644 Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs
create mode 100644 Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl
create mode 100644 Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl
create mode 100644 Resources/Prototypes/_CorvaxGoob/Guidebook/communication_channels.yml
create mode 100644 Resources/ServerInfo/_CorvaxGoob/Guidebook/NewPlayer/Controls/CommunicationChannels.xml
diff --git a/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs b/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs
new file mode 100644
index 000000000000..f64c37e391a0
--- /dev/null
+++ b/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs
@@ -0,0 +1,380 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Content.Client.Guidebook.Controls;
+using Content.Client.Guidebook.Richtext;
+using Content.Client.Message;
+using Content.Client.UserInterface.ControlExtensions;
+using Content.Shared._Starlight.CollectiveMind;
+using Content.Shared.Chat;
+using Content.Shared.Radio;
+using JetBrains.Annotations;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+
+namespace Content.Client._CorvaxGoob.Guidebook.Controls;
+
+///
+/// Builds the localized communication-channel reference table used by the guidebook.
+/// Radio and collective-mind prototypes are read at runtime, so newly added channels
+/// appear here without maintaining a second hard-coded list.
+///
+[UsedImplicitly]
+public sealed class GuideCommunicationChannelsTable : BoxContainer, IDocumentTag
+{
+ [Dependency] private IPrototypeManager _prototype = default!;
+ [Dependency] private IClipboardManager _clipboard = default!;
+
+ private const int NameWidth = 190;
+ private const int KeyWidth = 80;
+ private const string LatinKeyColor = "#8fcfff";
+ private const string GuideHintColor = "#c8a16c";
+
+ // Rows are retained so the local search field can hide them without rebuilding the table.
+ private readonly List _rows = [];
+
+ public GuideCommunicationChannelsTable()
+ {
+ IoCManager.InjectDependencies(this);
+
+ Orientation = LayoutOrientation.Vertical;
+ HorizontalExpand = true;
+ MouseFilter = MouseFilterMode.Stop;
+ }
+
+ public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control)
+ {
+ GenerateTable();
+ control = this;
+ return true;
+ }
+
+ private void GenerateTable()
+ {
+ RemoveAllChildren();
+ _rows.Clear();
+
+ // Page copy is built here instead of being hard-coded in the XML document,
+ // allowing the same guide entry to work with every available locale.
+ AddChild(BuildPageTitle());
+ AddChild(BuildIntroduction());
+ AddChild(BuildCopyHint());
+ AddChild(BuildSearchBar());
+ AddChild(BuildHeaderRow());
+
+ var rows = _prototype.EnumeratePrototypes()
+ .Select(BuildRadioRow)
+ .Concat(_prototype.EnumeratePrototypes().Select(BuildCollectiveMindRow))
+ // Sort by the already localized channel name. Keep this simple because
+ // client content is sandbox-checked and some runtime comparer types are blocked.
+ .OrderBy(row => row.Name)
+ .ToList();
+
+ foreach (var row in rows)
+ {
+ var control = new CommunicationChannelGuideRow(row, _clipboard);
+ _rows.Add(control);
+ AddChild(control);
+ }
+ }
+
+ private static Label BuildPageTitle()
+ {
+ return new Label
+ {
+ Text = Loc.GetString("guide-communication-channels-page-title"),
+ StyleClasses = { "LabelHeadingBigger" }
+ };
+ }
+
+ private static RichTextLabel BuildIntroduction()
+ {
+ var introduction = new RichTextLabel
+ {
+ HorizontalExpand = true,
+ Margin = new Thickness(0, 2, 0, 2)
+ };
+
+ introduction.SetMarkup(Loc.GetString(
+ "guide-communication-channels-page-introduction",
+ ("keyColor", GuideHintColor)));
+ return introduction;
+ }
+
+ private static RichTextLabel BuildCopyHint()
+ {
+ var hint = new RichTextLabel
+ {
+ HorizontalExpand = true
+ };
+
+ hint.SetMarkup(Loc.GetString(
+ "guide-communication-channels-page-copy-hint",
+ ("keyColor", GuideHintColor)));
+ return hint;
+ }
+
+ private LineEdit BuildSearchBar()
+ {
+ var search = new LineEdit
+ {
+ PlaceHolder = Loc.GetString("guide-communication-channels-search-placeholder"),
+ HorizontalExpand = true,
+ Margin = new Thickness(0, 4, 0, 4)
+ };
+
+ search.OnTextChanged += _ => ApplyFilter(search.Text);
+ return search;
+ }
+
+ private void ApplyFilter(string query)
+ {
+ foreach (var row in _rows)
+ {
+ row.SetHiddenState(true, query);
+ }
+ }
+
+ private static CommunicationChannelGuideData BuildRadioRow(RadioChannelPrototype channel)
+ {
+ // Common radio uses ';'. Channels without a key (such as Handheld) intentionally
+ // leave the table cell empty because there is no prefix the player can type.
+ var prefix = channel.ID == SharedChatSystem.CommonChannel
+ ? SharedChatSystem.RadioCommonPrefix.ToString()
+ : channel.KeyCode == '\0'
+ ? string.Empty
+ : $"{SharedChatSystem.RadioChannelPrefix}{char.ToLowerInvariant(channel.KeyCode)}";
+
+ return new CommunicationChannelGuideData(
+ channel.LocalizedName,
+ prefix,
+ GetDescription("radio", channel.ID, channel.LocalizedName),
+ channel.Color);
+ }
+
+ private static CommunicationChannelGuideData BuildCollectiveMindRow(CollectiveMindPrototype mind)
+ {
+ var prefix = mind.KeyCode == '\0'
+ ? string.Empty
+ : $"{SharedChatSystem.CollectiveMindPrefix}{char.ToLowerInvariant(mind.KeyCode)}";
+
+ return new CommunicationChannelGuideData(
+ mind.LocalizedName,
+ prefix,
+ GetDescription("collective-mind", mind.ID, mind.LocalizedName),
+ mind.Color);
+ }
+
+ private static string GetDescription(string kind, string id, string name)
+ {
+ // A channel-specific description is preferred, while the generic text keeps
+ // mod-added prototypes useful even before a dedicated localization is written.
+ var specificKey = $"guide-communication-channels-description-{kind}-{id.ToLowerInvariant()}";
+ if (Loc.TryGetString(specificKey, out var description))
+ return description;
+
+ return Loc.GetString($"guide-communication-channels-description-{kind}-generic", ("channel", name));
+ }
+
+ private static Control BuildHeaderRow()
+ {
+ var panel = new PanelContainer
+ {
+ HorizontalExpand = true,
+ Margin = new Thickness(0, 2, 0, 2),
+ PanelOverride = new StyleBoxFlat
+ {
+ BackgroundColor = Color.FromHex("#252735"),
+ BorderColor = Color.FromHex("#4c5066"),
+ BorderThickness = new Thickness(1)
+ }
+ };
+
+ var row = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ HorizontalExpand = true,
+ Margin = new Thickness(6, 4)
+ };
+
+ row.AddChild(BuildHeaderLabel("guide-communication-channels-header-name", NameWidth));
+ row.AddChild(BuildCenteredHeaderLabel("guide-communication-channels-header-key"));
+ row.AddChild(BuildHeaderLabel("guide-communication-channels-header-description", 0, true));
+
+ panel.AddChild(row);
+ return panel;
+ }
+
+ private static RichTextLabel BuildHeaderLabel(string locKey, int width, bool expand = false)
+ {
+ var label = new RichTextLabel
+ {
+ HorizontalExpand = expand
+ };
+
+ if (!expand)
+ label.SetWidth = width;
+
+ label.SetMarkup($"[bold]{FormattedMessage.EscapeText(Loc.GetString(locKey))}[/bold]");
+ return label;
+ }
+
+ private static Control BuildCenteredHeaderLabel(string locKey)
+ {
+ var text = FormattedMessage.EscapeText(Loc.GetString(locKey));
+ return BuildKeyCell($"[bold]{text}[/bold]");
+ }
+
+ ///
+ /// Creates the fixed-width key cell. Centering a RichTextLabel itself does not
+ /// center its markup, so a centered child is placed inside this container.
+ ///
+ private static BoxContainer BuildKeyCell(string? markup = null, string? copyText = null, IClipboardManager? clipboard = null)
+ {
+ var cell = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ Align = BoxContainer.AlignMode.Center,
+ SetWidth = KeyWidth
+ };
+
+ if (markup == null)
+ return cell;
+
+ var label = new RichTextLabel
+ {
+ HorizontalAlignment = HAlignment.Center
+ };
+
+ label.SetMarkup(markup);
+
+ if (copyText != null && clipboard != null)
+ {
+ var button = new ContainerButton
+ {
+ HorizontalAlignment = HAlignment.Center
+ };
+
+ button.OnPressed += _ => clipboard.SetText(copyText);
+ button.AddChild(label);
+ cell.AddChild(button);
+ return cell;
+ }
+
+ cell.AddChild(label);
+ return cell;
+ }
+
+ private sealed class CommunicationChannelGuideRow : PanelContainer, ISearchableControl
+ {
+ private readonly IClipboardManager _clipboard;
+ private readonly string _searchText;
+
+ public CommunicationChannelGuideRow(CommunicationChannelGuideData data, IClipboardManager clipboard)
+ {
+ _clipboard = clipboard;
+ HorizontalExpand = true;
+ Margin = new Thickness(0, 0, 0, 2);
+ PanelOverride = new StyleBoxFlat
+ {
+ BackgroundColor = Color.FromHex("#1d1f2a"),
+ BorderColor = Color.FromHex("#393c4d"),
+ BorderThickness = new Thickness(1)
+ };
+
+ var row = new BoxContainer
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ HorizontalExpand = true,
+ Margin = new Thickness(6, 4)
+ };
+
+ row.AddChild(BuildChannelName(data.Name, data.Color));
+ row.AddChild(BuildKey(data.Prefix));
+ row.AddChild(BuildDescription(data.Description));
+
+ AddChild(row);
+
+ _searchText = $"{data.Prefix} {data.Name} {data.Description}";
+ }
+
+ public bool CheckMatchesSearch(string query)
+ {
+ return string.IsNullOrWhiteSpace(query)
+ || _searchText.Contains(query.Trim(), StringComparison.OrdinalIgnoreCase)
+ || this.ChildrenContainText(query);
+ }
+
+ public void SetHiddenState(bool state, string query)
+ {
+ Visible = CheckMatchesSearch(query) ? state : !state;
+ }
+
+ private static RichTextLabel BuildDescription(string text)
+ {
+ var label = new RichTextLabel
+ {
+ HorizontalExpand = true
+ };
+
+ label.SetMarkup(FormattedMessage.EscapeText(text));
+ return label;
+ }
+
+ private Control BuildKey(string prefix)
+ {
+ if (string.IsNullOrEmpty(prefix))
+ return BuildKeyCell();
+
+ var escapedPrefix = FormattedMessage.EscapeText(prefix);
+ string markup;
+
+ // Highlight only Latin key letters, leaving ':' or '+' and every
+ // non-Latin character in the normal text color.
+ var hasSelectableKey = prefix.Length > 1 &&
+ (prefix[0] == SharedChatSystem.RadioChannelPrefix ||
+ prefix[0] == SharedChatSystem.CollectiveMindPrefix);
+
+ if (hasSelectableKey && IsLatinLetter(prefix[^1]))
+ {
+ var marker = FormattedMessage.EscapeText(prefix[..^1]);
+ var key = FormattedMessage.EscapeText(prefix[^1].ToString());
+ markup = $"[bold]{marker}[color={LatinKeyColor}]{key}[/color][/bold]";
+ }
+ else
+ {
+ markup = $"[bold]{escapedPrefix}[/bold]";
+ }
+
+ return BuildKeyCell(markup, prefix, _clipboard);
+ }
+
+ private static bool IsLatinLetter(char value)
+ {
+ return value is >= 'A' and <= 'Z' or >= 'a' and <= 'z';
+ }
+
+ private static RichTextLabel BuildChannelName(string name, Color color)
+ {
+ var label = new RichTextLabel
+ {
+ // A fixed width keeps all columns aligned and lets long localized
+ // names such as «Центральное Командование» wrap onto two lines.
+ SetWidth = NameWidth
+ };
+
+ label.SetMarkup($"[color={color.ToHex()}][bold]{FormattedMessage.EscapeText(name)}[/bold][/color]");
+ return label;
+ }
+ }
+
+ private sealed record CommunicationChannelGuideData(
+ string Name,
+ string Prefix,
+ string Description,
+ Color Color);
+}
diff --git a/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl b/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl
new file mode 100644
index 000000000000..274e31e17339
--- /dev/null
+++ b/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+guide-entry-communication-channels = Communication channels
+
+guide-communication-channels-page-title = Communication channels
+guide-communication-channels-page-introduction = The table lists channels that can be selected with a prefix at the start of a message. Radio channels require access through a suitable device, while mind channels require the corresponding mental link. ([color={ $keyColor }];[/color]) sends to the common channel, ([color={ $keyColor }]:[/color]) selects a radio channel by its key, and ([color={ $keyColor }]+[/color]) selects a collective-mind channel.
+guide-communication-channels-page-copy-hint = [color={ $keyColor }]Click a key to copy it.[/color]
+
+guide-communication-channels-search-placeholder = Filter channels
+guide-communication-channels-header-key = Key
+guide-communication-channels-header-name = Channel
+guide-communication-channels-header-description = Description
+
+guide-communication-channels-description-radio-generic = The “{ $channel }” radio channel. Sending requires access through equipment or an intrinsic transmitter.
+guide-communication-channels-description-collective-mind-generic = The “{ $channel }” channel for entities connected to the matching collective mind.
+
+guide-communication-channels-description-radio-common = The station-wide common channel. Most headsets can use it, and it is sent with a semicolon.
+guide-communication-channels-description-radio-centcom = Channel for Central Command representatives and special response teams.
+guide-communication-channels-description-radio-command = Command channel for the captain, department heads, and other command roles.
+guide-communication-channels-description-radio-engineering = Engineering channel for repairs, construction, atmospherics, and power supply.
+guide-communication-channels-description-radio-medical = Medical channel for doctors, chemists, paramedics, and sharing medical information.
+guide-communication-channels-description-radio-science = Science channel for scientists, researchers, roboticists, anomalists, and experiment coordination.
+guide-communication-channels-description-radio-security = Security channel for patrols, call response, and department coordination.
+guide-communication-channels-description-radio-service = Service channel for the bar, kitchen, botany, janitorial work, chapel, theater, and other service tasks.
+guide-communication-channels-description-radio-supply = Supply channel for cargo technicians, miners, salvage specialists, and station orders.
+guide-communication-channels-description-radio-syndicate = Hidden Syndicate channel. Access comes from matching devices and encryption keys.
+guide-communication-channels-description-radio-handheld = Local handheld-radio channel. Communication requires a handheld radio tuned to the same frequency.
+guide-communication-channels-description-radio-freelance = Freelance channel for independent groups when their equipment grants access.
+guide-communication-channels-description-radio-xenoborg = Xenoborg channel for xenoborgs and related systems.
+guide-communication-channels-description-radio-mothership = Mothership core channel for communicating with xenoborgs. Xenoborgs can hear it, but transmit on the Xenoborg channel.
+guide-communication-channels-description-radio-legal = Legal channel for the magistrate, lawyers, and related legal roles.
+guide-communication-channels-description-radio-future = Special long-range future radio channel.
+guide-communication-channels-description-radio-radioshow = Broadcasting channel for the radio host and station radio.
+guide-communication-channels-description-radio-cosmicradio = Cosmic cult channel for cultists and related entities.
+
+guide-communication-channels-description-collective-mind-dragonmind = Dragon mind channel for carp, sharks, and related entities.
+guide-communication-channels-description-collective-mind-lingmind = Changeling hivemind channel.
+guide-communication-channels-description-collective-mind-tidemind = Tidemind channel for greytide-related events.
+guide-communication-channels-description-collective-mind-blobmind = Blob mind channel for the core, factories, and other blob organisms.
+guide-communication-channels-description-collective-mind-mansuslink = Mansus Link for heretics and their summoned creatures.
+guide-communication-channels-description-collective-mind-abductormind = Mind channel for greys and their team.
+guide-communication-channels-description-collective-mind-binary = Binary channel for synthetics and related devices.
+guide-communication-channels-description-collective-mind-dronemind = Drone mind channel.
+guide-communication-channels-description-collective-mind-mousemind = Mouse mind channel.
+guide-communication-channels-description-collective-mind-empathy = Empathic link for entities that have access to this mind.
+guide-communication-channels-description-collective-mind-binglemind = Bingle link.
+guide-communication-channels-description-collective-mind-shadowmind = Shadow mind channel.
+guide-communication-channels-description-collective-mind-xenomorphivemind = Xenomorph hivemind channel.
+guide-communication-channels-description-collective-mind-abductormindantag = Antagonist abductor mind channel.
+guide-communication-channels-description-collective-mind-wraithmind = Wraith mind channel.
diff --git a/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl b/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl
new file mode 100644
index 000000000000..f2c6446a87b0
--- /dev/null
+++ b/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+guide-entry-communication-channels = Каналы связи
+
+guide-communication-channels-page-title = Каналы связи
+guide-communication-channels-page-introduction = В таблице перечислены каналы, которые можно выбрать префиксом в начале сообщения. Для радиоканала нужен доступ через подходящее устройство, а для канала разума — соответствующая связь. ([color={ $keyColor }];[/color]) отправляет в общий канал, ([color={ $keyColor }]:[/color]) выбирает радиоканал по букве, а ([color={ $keyColor }]+[/color]) выбирает канал коллективного разума.
+guide-communication-channels-page-copy-hint = [color={ $keyColor }]Нажмите на ключ, чтобы скопировать его.[/color]
+
+guide-communication-channels-search-placeholder = Фильтр каналов
+guide-communication-channels-header-key = Ключ
+guide-communication-channels-header-name = Канал
+guide-communication-channels-header-description = Описание
+
+guide-communication-channels-description-radio-generic = Радиоканал «{ $channel }». Для отправки нужен доступ к этому каналу через экипировку или встроенный передатчик.
+guide-communication-channels-description-collective-mind-generic = Канал «{ $channel }» для существ, подключённых к соответствующему коллективному разуму.
+
+guide-communication-channels-description-radio-common = Общий канал станции. Обычно доступен большинству гарнитур и отправляется через точку с запятой.
+guide-communication-channels-description-radio-centcom = Канал для связи с представителями Центрального Командования и специальными группами.
+guide-communication-channels-description-radio-command = Командный канал капитана, глав отделов и других должностей командования.
+guide-communication-channels-description-radio-engineering = Канал инженерного отдела для ремонта, строительства, атмосферики и электроснабжения.
+guide-communication-channels-description-radio-medical = Канал медицинского отдела для врачей, химиков, парамедиков и обмена медицинской информацией.
+guide-communication-channels-description-radio-science = Канал научного отдела для учёных, исследователей, робототехников, аномалистов и координации экспериментов.
+guide-communication-channels-description-radio-security = Канал службы безопасности для патрулей, реагирования на вызовы и координации отдела.
+guide-communication-channels-description-radio-service = Канал сервисного отдела: бар, кухня, ботаника, уборка, церковь, театр и прочие сервисные задачи.
+guide-communication-channels-description-radio-supply = Канал отдела снабжения для грузчиков, шахтёров, утилизаторов и заказов.
+guide-communication-channels-description-radio-syndicate = Скрытый канал Синдиката. Доступен через соответствующие устройства и ключи.
+guide-communication-channels-description-radio-handheld = Локальный канал портативных раций. Для связи требуется портативная рация, настроенная на ту же частоту.
+guide-communication-channels-description-radio-freelance = Канал фрилансеров и независимых групп, если экипировка даёт к нему доступ.
+guide-communication-channels-description-radio-xenoborg = Канал ксеноборгов и связанных с ними систем.
+guide-communication-channels-description-radio-mothership = Канал ядра материнского шаттла для связи с ксеноборгами. Ксеноборги слышат его, но сами передают по каналу «Ксеноборги».
+guide-communication-channels-description-radio-legal = Юридический канал для магистрата, юристов и связанных правовых ролей.
+guide-communication-channels-description-radio-future = Специальный дальний радиоканал будущего.
+guide-communication-channels-description-radio-radioshow = Канал радиовещания для ведущего и станционной радиостанции.
+guide-communication-channels-description-radio-cosmicradio = Канал космического культа и связанных с ним существ.
+
+guide-communication-channels-description-collective-mind-dragonmind = Канал разума дракона для карпов, акул и связанных с ним существ.
+guide-communication-channels-description-collective-mind-lingmind = Канал коллективного разума генокрадов.
+guide-communication-channels-description-collective-mind-tidemind = Канал грейтайдов и связанных с ними событий.
+guide-communication-channels-description-collective-mind-blobmind = Канал блоба для ядра, фабрик и других частей организма.
+guide-communication-channels-description-collective-mind-mansuslink = Связь Мансуса для еретиков и их призванных существ.
+guide-communication-channels-description-collective-mind-abductormind = Канал серых и их команды.
+guide-communication-channels-description-collective-mind-binary = Двоичный канал синтетиков и связанных устройств.
+guide-communication-channels-description-collective-mind-dronemind = Канал дронов.
+guide-communication-channels-description-collective-mind-mousemind = Канал мышей.
+guide-communication-channels-description-collective-mind-empathy = Эмпатическая связь существ, которым доступен этот разум.
+guide-communication-channels-description-collective-mind-binglemind = Связь бинглов.
+guide-communication-channels-description-collective-mind-shadowmind = Разум теней.
+guide-communication-channels-description-collective-mind-xenomorphivemind = Разум улья ксеноморфов.
+guide-communication-channels-description-collective-mind-abductormindantag = Канал антагонистов-абдукторов.
+guide-communication-channels-description-collective-mind-wraithmind = Разум фантомов.
diff --git a/Resources/Prototypes/Guidebook/newplayer.yml b/Resources/Prototypes/Guidebook/newplayer.yml
index b268ab895d87..a2559d00f016 100644
--- a/Resources/Prototypes/Guidebook/newplayer.yml
+++ b/Resources/Prototypes/Guidebook/newplayer.yml
@@ -14,6 +14,7 @@
text: "/ServerInfo/Guidebook/NewPlayer/Controls/Controls.xml"
children:
- Radio
+ - CommunicationChannels # CorvaxGoob - available-radio-channels-guide
- type: guideEntry
id: Radio
diff --git a/Resources/Prototypes/_CorvaxGoob/Guidebook/communication_channels.yml b/Resources/Prototypes/_CorvaxGoob/Guidebook/communication_channels.yml
new file mode 100644
index 000000000000..c1f34b2647c6
--- /dev/null
+++ b/Resources/Prototypes/_CorvaxGoob/Guidebook/communication_channels.yml
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+- type: guideEntry
+ id: CommunicationChannels
+ name: guide-entry-communication-channels
+ text: "/ServerInfo/_CorvaxGoob/Guidebook/NewPlayer/Controls/CommunicationChannels.xml"
+ priority: 1
diff --git a/Resources/ServerInfo/_CorvaxGoob/Guidebook/NewPlayer/Controls/CommunicationChannels.xml b/Resources/ServerInfo/_CorvaxGoob/Guidebook/NewPlayer/Controls/CommunicationChannels.xml
new file mode 100644
index 000000000000..1f97e73405de
--- /dev/null
+++ b/Resources/ServerInfo/_CorvaxGoob/Guidebook/NewPlayer/Controls/CommunicationChannels.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
From 2b4f2a5d60d93418ceb2ef7a43c5dfabdf4350a3 Mon Sep 17 00:00:00 2001
From: username <32684670+Snorkcom@users.noreply.github.com>
Date: Sun, 16 Aug 2026 17:52:36 +0600
Subject: [PATCH 2/2] refactor + fixes+ comments
---
.../GuideCommunicationChannelsTable.cs | 153 +++++++++---------
.../guidebook/communication-channels.ftl | 28 ++--
.../guidebook/communication-channels.ftl | 28 ++--
3 files changed, 111 insertions(+), 98 deletions(-)
diff --git a/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs b/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs
index f64c37e391a0..d36bf950e5c1 100644
--- a/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs
+++ b/Content.Client/_CorvaxGoob/Guidebook/Controls/GuideCommunicationChannelsTable.cs
@@ -5,7 +5,6 @@
using Content.Client.Guidebook.Controls;
using Content.Client.Guidebook.Richtext;
using Content.Client.Message;
-using Content.Client.UserInterface.ControlExtensions;
using Content.Shared._Starlight.CollectiveMind;
using Content.Shared.Chat;
using Content.Shared.Radio;
@@ -31,9 +30,22 @@ public sealed class GuideCommunicationChannelsTable : BoxContainer, IDocumentTag
private const int NameWidth = 190;
private const int KeyWidth = 80;
- private const string LatinKeyColor = "#8fcfff";
private const string GuideHintColor = "#c8a16c";
+ private static readonly StyleBoxFlat HeaderPanelStyle = new()
+ {
+ BackgroundColor = Color.FromHex("#252735"),
+ BorderColor = Color.FromHex("#4c5066"),
+ BorderThickness = new Thickness(1)
+ };
+
+ private static readonly StyleBoxFlat RowPanelStyle = new()
+ {
+ BackgroundColor = Color.FromHex("#1d1f2a"),
+ BorderColor = Color.FromHex("#393c4d"),
+ BorderThickness = new Thickness(1)
+ };
+
// Rows are retained so the local search field can hide them without rebuilding the table.
private readonly List _rows = [];
@@ -58,21 +70,18 @@ private void GenerateTable()
RemoveAllChildren();
_rows.Clear();
- // Page copy is built here instead of being hard-coded in the XML document,
- // allowing the same guide entry to work with every available locale.
+ // Page layout: title, introduction, copy hint, filter, header, then generated rows.
AddChild(BuildPageTitle());
AddChild(BuildIntroduction());
AddChild(BuildCopyHint());
AddChild(BuildSearchBar());
AddChild(BuildHeaderRow());
+ // Sort by the already localized channel name.
var rows = _prototype.EnumeratePrototypes()
.Select(BuildRadioRow)
.Concat(_prototype.EnumeratePrototypes().Select(BuildCollectiveMindRow))
- // Sort by the already localized channel name. Keep this simple because
- // client content is sandbox-checked and some runtime comparer types are blocked.
- .OrderBy(row => row.Name)
- .ToList();
+ .OrderBy(static row => row.Name);
foreach (var row in rows)
{
@@ -86,36 +95,34 @@ private static Label BuildPageTitle()
{
return new Label
{
- Text = Loc.GetString("guide-communication-channels-page-title"),
+ Text = Loc.GetString("guide-entry-communication-channels"),
StyleClasses = { "LabelHeadingBigger" }
};
}
private static RichTextLabel BuildIntroduction()
{
- var introduction = new RichTextLabel
- {
- HorizontalExpand = true,
- Margin = new Thickness(0, 2, 0, 2)
- };
-
- introduction.SetMarkup(Loc.GetString(
+ return BuildPageText(
"guide-communication-channels-page-introduction",
- ("keyColor", GuideHintColor)));
- return introduction;
+ new Thickness(0, 2, 0, 2));
}
private static RichTextLabel BuildCopyHint()
{
- var hint = new RichTextLabel
+ return BuildPageText("guide-communication-channels-page-copy-hint");
+ }
+
+ // Creates localized rich-text blocks shown above the channel table.
+ private static RichTextLabel BuildPageText(string locKey, Thickness margin = default)
+ {
+ var label = new RichTextLabel
{
- HorizontalExpand = true
+ HorizontalExpand = true,
+ Margin = margin
};
- hint.SetMarkup(Loc.GetString(
- "guide-communication-channels-page-copy-hint",
- ("keyColor", GuideHintColor)));
- return hint;
+ label.SetMarkup(Loc.GetString(locKey, ("keyColor", GuideHintColor)));
+ return label;
}
private LineEdit BuildSearchBar()
@@ -127,7 +134,7 @@ private LineEdit BuildSearchBar()
Margin = new Thickness(0, 4, 0, 4)
};
- search.OnTextChanged += _ => ApplyFilter(search.Text);
+ search.OnTextChanged += args => ApplyFilter(args.Text);
return search;
}
@@ -139,40 +146,49 @@ private void ApplyFilter(string query)
}
}
+ // Builds a row from the localized name, keycode, and color of a radioChannel prototype.
private static CommunicationChannelGuideData BuildRadioRow(RadioChannelPrototype channel)
{
- // Common radio uses ';'. Channels without a key (such as Handheld) intentionally
- // leave the table cell empty because there is no prefix the player can type.
+ // Common uses the chat-wide ';' prefix. Other channels combine the ':' prefix
+ // with RadioChannelPrototype.KeyCode, which is loaded from the prototype's keycode field.
+ var name = channel.LocalizedName;
var prefix = channel.ID == SharedChatSystem.CommonChannel
? SharedChatSystem.RadioCommonPrefix.ToString()
- : channel.KeyCode == '\0'
- ? string.Empty
- : $"{SharedChatSystem.RadioChannelPrefix}{char.ToLowerInvariant(channel.KeyCode)}";
+ : BuildPrefix(SharedChatSystem.RadioChannelPrefix, channel.KeyCode);
return new CommunicationChannelGuideData(
- channel.LocalizedName,
+ name,
prefix,
- GetDescription("radio", channel.ID, channel.LocalizedName),
+ GetDescription("radio", channel.ID, name),
channel.Color);
}
+ // Builds a row from the localized name, keycode, and color of a collectiveMind prototype.
private static CommunicationChannelGuideData BuildCollectiveMindRow(CollectiveMindPrototype mind)
{
- var prefix = mind.KeyCode == '\0'
- ? string.Empty
- : $"{SharedChatSystem.CollectiveMindPrefix}{char.ToLowerInvariant(mind.KeyCode)}";
+ // The '+' prefix comes from the chat system, while CollectiveMindPrototype.KeyCode
+ // is loaded from the prototype's keycode field.
+ var name = mind.LocalizedName;
+ var prefix = BuildPrefix(SharedChatSystem.CollectiveMindPrefix, mind.KeyCode);
return new CommunicationChannelGuideData(
- mind.LocalizedName,
+ name,
prefix,
- GetDescription("collective-mind", mind.ID, mind.LocalizedName),
+ GetDescription("collective-mind", mind.ID, name),
mind.Color);
}
+ // Returns the exact prefix players type in chat, or no key for keyless prototypes.
+ private static string BuildPrefix(char prefix, char keyCode)
+ {
+ return keyCode == '\0'
+ ? string.Empty
+ : $"{prefix}{char.ToLowerInvariant(keyCode)}";
+ }
+
+ // Uses a specific description when present, otherwise falls back to generic text.
private static string GetDescription(string kind, string id, string name)
{
- // A channel-specific description is preferred, while the generic text keeps
- // mod-added prototypes useful even before a dedicated localization is written.
var specificKey = $"guide-communication-channels-description-{kind}-{id.ToLowerInvariant()}";
if (Loc.TryGetString(specificKey, out var description))
return description;
@@ -180,18 +196,13 @@ private static string GetDescription(string kind, string id, string name)
return Loc.GetString($"guide-communication-channels-description-{kind}-generic", ("channel", name));
}
- private static Control BuildHeaderRow()
+ private static PanelContainer BuildHeaderRow()
{
var panel = new PanelContainer
{
HorizontalExpand = true,
Margin = new Thickness(0, 2, 0, 2),
- PanelOverride = new StyleBoxFlat
- {
- BackgroundColor = Color.FromHex("#252735"),
- BorderColor = Color.FromHex("#4c5066"),
- BorderThickness = new Thickness(1)
- }
+ PanelOverride = HeaderPanelStyle
};
var row = new BoxContainer
@@ -203,27 +214,27 @@ private static Control BuildHeaderRow()
row.AddChild(BuildHeaderLabel("guide-communication-channels-header-name", NameWidth));
row.AddChild(BuildCenteredHeaderLabel("guide-communication-channels-header-key"));
- row.AddChild(BuildHeaderLabel("guide-communication-channels-header-description", 0, true));
+ row.AddChild(BuildHeaderLabel("guide-communication-channels-header-description"));
panel.AddChild(row);
return panel;
}
- private static RichTextLabel BuildHeaderLabel(string locKey, int width, bool expand = false)
+ private static RichTextLabel BuildHeaderLabel(string locKey, int? width = null)
{
var label = new RichTextLabel
{
- HorizontalExpand = expand
+ HorizontalExpand = width == null
};
- if (!expand)
- label.SetWidth = width;
+ if (width != null)
+ label.SetWidth = width.Value;
label.SetMarkup($"[bold]{FormattedMessage.EscapeText(Loc.GetString(locKey))}[/bold]");
return label;
}
- private static Control BuildCenteredHeaderLabel(string locKey)
+ private static BoxContainer BuildCenteredHeaderLabel(string locKey)
{
var text = FormattedMessage.EscapeText(Loc.GetString(locKey));
return BuildKeyCell($"[bold]{text}[/bold]");
@@ -233,7 +244,10 @@ private static Control BuildCenteredHeaderLabel(string locKey)
/// Creates the fixed-width key cell. Centering a RichTextLabel itself does not
/// center its markup, so a centered child is placed inside this container.
///
- private static BoxContainer BuildKeyCell(string? markup = null, string? copyText = null, IClipboardManager? clipboard = null)
+ private static BoxContainer BuildKeyCell(
+ string? markup = null,
+ string? copyText = null,
+ IClipboardManager? clipboard = null)
{
var cell = new BoxContainer
{
@@ -269,22 +283,17 @@ private static BoxContainer BuildKeyCell(string? markup = null, string? copyText
return cell;
}
+ // Renders one channel row, stores searchable text for the filter,
+ // and lets players copy a non-empty chat key by clicking it.
private sealed class CommunicationChannelGuideRow : PanelContainer, ISearchableControl
{
- private readonly IClipboardManager _clipboard;
private readonly string _searchText;
public CommunicationChannelGuideRow(CommunicationChannelGuideData data, IClipboardManager clipboard)
{
- _clipboard = clipboard;
HorizontalExpand = true;
Margin = new Thickness(0, 0, 0, 2);
- PanelOverride = new StyleBoxFlat
- {
- BackgroundColor = Color.FromHex("#1d1f2a"),
- BorderColor = Color.FromHex("#393c4d"),
- BorderThickness = new Thickness(1)
- };
+ PanelOverride = RowPanelStyle;
var row = new BoxContainer
{
@@ -294,7 +303,7 @@ public CommunicationChannelGuideRow(CommunicationChannelGuideData data, IClipboa
};
row.AddChild(BuildChannelName(data.Name, data.Color));
- row.AddChild(BuildKey(data.Prefix));
+ row.AddChild(BuildKey(data.Prefix, clipboard));
row.AddChild(BuildDescription(data.Description));
AddChild(row);
@@ -304,9 +313,9 @@ public CommunicationChannelGuideRow(CommunicationChannelGuideData data, IClipboa
public bool CheckMatchesSearch(string query)
{
- return string.IsNullOrWhiteSpace(query)
- || _searchText.Contains(query.Trim(), StringComparison.OrdinalIgnoreCase)
- || this.ChildrenContainText(query);
+ var search = query.Trim();
+ return search.Length == 0
+ || _searchText.Contains(search, StringComparison.OrdinalIgnoreCase);
}
public void SetHiddenState(bool state, string query)
@@ -325,12 +334,12 @@ private static RichTextLabel BuildDescription(string text)
return label;
}
- private Control BuildKey(string prefix)
+ // Builds the key cell, adds color highlighting, and wires click-to-copy.
+ private static BoxContainer BuildKey(string prefix, IClipboardManager clipboard)
{
if (string.IsNullOrEmpty(prefix))
return BuildKeyCell();
- var escapedPrefix = FormattedMessage.EscapeText(prefix);
string markup;
// Highlight only Latin key letters, leaving ':' or '+' and every
@@ -343,14 +352,14 @@ private Control BuildKey(string prefix)
{
var marker = FormattedMessage.EscapeText(prefix[..^1]);
var key = FormattedMessage.EscapeText(prefix[^1].ToString());
- markup = $"[bold]{marker}[color={LatinKeyColor}]{key}[/color][/bold]";
+ markup = $"[bold]{marker}[color={GuideHintColor}]{key}[/color][/bold]";
}
else
{
- markup = $"[bold]{escapedPrefix}[/bold]";
+ markup = $"[bold]{FormattedMessage.EscapeText(prefix)}[/bold]";
}
- return BuildKeyCell(markup, prefix, _clipboard);
+ return BuildKeyCell(markup, prefix, clipboard);
}
private static bool IsLatinLetter(char value)
@@ -362,8 +371,7 @@ private static RichTextLabel BuildChannelName(string name, Color color)
{
var label = new RichTextLabel
{
- // A fixed width keeps all columns aligned and lets long localized
- // names such as «Центральное Командование» wrap onto two lines.
+ // A fixed width keeps columns aligned and lets long names wrap.
SetWidth = NameWidth
};
@@ -372,6 +380,7 @@ private static RichTextLabel BuildChannelName(string name, Color color)
}
}
+ // Prepared data used to render one channel table row.
private sealed record CommunicationChannelGuideData(
string Name,
string Prefix,
diff --git a/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl b/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl
index 274e31e17339..e5c88ef42cd1 100644
--- a/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl
+++ b/Resources/Locale/en-US/_CorvaxGoob/guidebook/communication-channels.ftl
@@ -2,11 +2,13 @@
guide-entry-communication-channels = Communication channels
-guide-communication-channels-page-title = Communication channels
-guide-communication-channels-page-introduction = The table lists channels that can be selected with a prefix at the start of a message. Radio channels require access through a suitable device, while mind channels require the corresponding mental link. ([color={ $keyColor }];[/color]) sends to the common channel, ([color={ $keyColor }]:[/color]) selects a radio channel by its key, and ([color={ $keyColor }]+[/color]) selects a collective-mind channel.
-guide-communication-channels-page-copy-hint = [color={ $keyColor }]Click a key to copy it.[/color]
+guide-communication-channels-page-introduction =
+ The table lists channels that can be selected with a prefix at the start of a message.
+ Radio channels require access through a suitable device, while mind channels require the corresponding link.
+ ([color={ $keyColor }];[/color]) sends to the common channel, ([color={ $keyColor }]:[/color]) selects a radio channel by its key, and ([color={ $keyColor }]+[/color]) selects a collective-mind channel.
+guide-communication-channels-page-copy-hint = [color={ $keyColor }]Click a key in the table to copy it.[/color]
-guide-communication-channels-search-placeholder = Filter channels
+guide-communication-channels-search-placeholder = Filter
guide-communication-channels-header-key = Key
guide-communication-channels-header-name = Channel
guide-communication-channels-header-description = Description
@@ -17,29 +19,29 @@ guide-communication-channels-description-collective-mind-generic = The “{ $cha
guide-communication-channels-description-radio-common = The station-wide common channel. Most headsets can use it, and it is sent with a semicolon.
guide-communication-channels-description-radio-centcom = Channel for Central Command representatives and special response teams.
guide-communication-channels-description-radio-command = Command channel for the captain, department heads, and other command roles.
-guide-communication-channels-description-radio-engineering = Engineering channel for repairs, construction, atmospherics, and power supply.
+guide-communication-channels-description-radio-engineering = Engineering channel for repairs, construction, power supply, and atmospherics.
guide-communication-channels-description-radio-medical = Medical channel for doctors, chemists, paramedics, and sharing medical information.
-guide-communication-channels-description-radio-science = Science channel for scientists, researchers, roboticists, anomalists, and experiment coordination.
+guide-communication-channels-description-radio-science = Science channel for scientists, roboticists, anomalists, and experiment coordination.
guide-communication-channels-description-radio-security = Security channel for patrols, call response, and department coordination.
-guide-communication-channels-description-radio-service = Service channel for the bar, kitchen, botany, janitorial work, chapel, theater, and other service tasks.
+guide-communication-channels-description-radio-service = Service channel for the bar, kitchen, botany, janitorial work, theater, chapel, and other service tasks.
guide-communication-channels-description-radio-supply = Supply channel for cargo technicians, miners, salvage specialists, and station orders.
-guide-communication-channels-description-radio-syndicate = Hidden Syndicate channel. Access comes from matching devices and encryption keys.
+guide-communication-channels-description-radio-syndicate = Hidden Syndicate channel. Access comes from matching devices and encryption keys; transmissions are encrypted, hiding speaker names.
guide-communication-channels-description-radio-handheld = Local handheld-radio channel. Communication requires a handheld radio tuned to the same frequency.
guide-communication-channels-description-radio-freelance = Freelance channel for independent groups when their equipment grants access.
guide-communication-channels-description-radio-xenoborg = Xenoborg channel for xenoborgs and related systems.
guide-communication-channels-description-radio-mothership = Mothership core channel for communicating with xenoborgs. Xenoborgs can hear it, but transmit on the Xenoborg channel.
guide-communication-channels-description-radio-legal = Legal channel for the magistrate, lawyers, and related legal roles.
-guide-communication-channels-description-radio-future = Special long-range future radio channel.
+guide-communication-channels-description-radio-future = Special long-range future radio channel. Will be available in the future…
guide-communication-channels-description-radio-radioshow = Broadcasting channel for the radio host and station radio.
guide-communication-channels-description-radio-cosmicradio = Cosmic cult channel for cultists and related entities.
-guide-communication-channels-description-collective-mind-dragonmind = Dragon mind channel for carp, sharks, and related entities.
+guide-communication-channels-description-collective-mind-dragonmind = Collective mind channel for the dragon, carp, and sharks.
guide-communication-channels-description-collective-mind-lingmind = Changeling hivemind channel.
guide-communication-channels-description-collective-mind-tidemind = Tidemind channel for greytide-related events.
-guide-communication-channels-description-collective-mind-blobmind = Blob mind channel for the core, factories, and other blob organisms.
+guide-communication-channels-description-collective-mind-blobmind = Blob channel linking the core, minions, and other parts of the organism.
guide-communication-channels-description-collective-mind-mansuslink = Mansus Link for heretics and their summoned creatures.
-guide-communication-channels-description-collective-mind-abductormind = Mind channel for greys and their team.
-guide-communication-channels-description-collective-mind-binary = Binary channel for synthetics and related devices.
+guide-communication-channels-description-collective-mind-abductormind = Communication channel for greys and their team.
+guide-communication-channels-description-collective-mind-binary = Binary channel for synthetics, cyborgs, borgs, artificial intelligence, and related devices.
guide-communication-channels-description-collective-mind-dronemind = Drone mind channel.
guide-communication-channels-description-collective-mind-mousemind = Mouse mind channel.
guide-communication-channels-description-collective-mind-empathy = Empathic link for entities that have access to this mind.
diff --git a/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl b/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl
index f2c6446a87b0..10bbe84c4d71 100644
--- a/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl
+++ b/Resources/Locale/ru-RU/_CorvaxGoob/guidebook/communication-channels.ftl
@@ -2,11 +2,13 @@
guide-entry-communication-channels = Каналы связи
-guide-communication-channels-page-title = Каналы связи
-guide-communication-channels-page-introduction = В таблице перечислены каналы, которые можно выбрать префиксом в начале сообщения. Для радиоканала нужен доступ через подходящее устройство, а для канала разума — соответствующая связь. ([color={ $keyColor }];[/color]) отправляет в общий канал, ([color={ $keyColor }]:[/color]) выбирает радиоканал по букве, а ([color={ $keyColor }]+[/color]) выбирает канал коллективного разума.
-guide-communication-channels-page-copy-hint = [color={ $keyColor }]Нажмите на ключ, чтобы скопировать его.[/color]
+guide-communication-channels-page-introduction =
+ В таблице перечислены каналы, которые можно выбрать префиксом в начале сообщения.
+ Для радиоканала нужен доступ через подходящее устройство, а для канала разума — соответствующая связь.
+ ([color={ $keyColor }];[/color]) отправляет в общий канал, ([color={ $keyColor }]:[/color]) выбирает радиоканал по букве, а ([color={ $keyColor }]+[/color]) выбирает канал коллективного разума.
+guide-communication-channels-page-copy-hint = [color={ $keyColor }]Нажмите на ключ в таблице, чтобы скопировать его.[/color]
-guide-communication-channels-search-placeholder = Фильтр каналов
+guide-communication-channels-search-placeholder = Фильтр
guide-communication-channels-header-key = Ключ
guide-communication-channels-header-name = Канал
guide-communication-channels-header-description = Описание
@@ -17,29 +19,29 @@ guide-communication-channels-description-collective-mind-generic = Канал «
guide-communication-channels-description-radio-common = Общий канал станции. Обычно доступен большинству гарнитур и отправляется через точку с запятой.
guide-communication-channels-description-radio-centcom = Канал для связи с представителями Центрального Командования и специальными группами.
guide-communication-channels-description-radio-command = Командный канал капитана, глав отделов и других должностей командования.
-guide-communication-channels-description-radio-engineering = Канал инженерного отдела для ремонта, строительства, атмосферики и электроснабжения.
+guide-communication-channels-description-radio-engineering = Канал инженерного отдела для ремонта, строительства, электроснабжения и атмосферики.
guide-communication-channels-description-radio-medical = Канал медицинского отдела для врачей, химиков, парамедиков и обмена медицинской информацией.
-guide-communication-channels-description-radio-science = Канал научного отдела для учёных, исследователей, робототехников, аномалистов и координации экспериментов.
+guide-communication-channels-description-radio-science = Канал научного отдела для учёных, робототехников, аномалистов и координации экспериментов.
guide-communication-channels-description-radio-security = Канал службы безопасности для патрулей, реагирования на вызовы и координации отдела.
-guide-communication-channels-description-radio-service = Канал сервисного отдела: бар, кухня, ботаника, уборка, церковь, театр и прочие сервисные задачи.
+guide-communication-channels-description-radio-service = Канал сервисного отдела: бар, кухня, ботаника, уборка, театр, церковь и прочие сервисные задачи.
guide-communication-channels-description-radio-supply = Канал отдела снабжения для грузчиков, шахтёров, утилизаторов и заказов.
-guide-communication-channels-description-radio-syndicate = Скрытый канал Синдиката. Доступен через соответствующие устройства и ключи.
+guide-communication-channels-description-radio-syndicate = Скрытый канал Синдиката. Доступен через соответствующие устройства и ключи; шифрует передачу, скрывая имена говорящих.
guide-communication-channels-description-radio-handheld = Локальный канал портативных раций. Для связи требуется портативная рация, настроенная на ту же частоту.
guide-communication-channels-description-radio-freelance = Канал фрилансеров и независимых групп, если экипировка даёт к нему доступ.
guide-communication-channels-description-radio-xenoborg = Канал ксеноборгов и связанных с ними систем.
guide-communication-channels-description-radio-mothership = Канал ядра материнского шаттла для связи с ксеноборгами. Ксеноборги слышат его, но сами передают по каналу «Ксеноборги».
guide-communication-channels-description-radio-legal = Юридический канал для магистрата, юристов и связанных правовых ролей.
-guide-communication-channels-description-radio-future = Специальный дальний радиоканал будущего.
+guide-communication-channels-description-radio-future = Специальный дальний радиоканал будущего. Будет доступен в будущем…
guide-communication-channels-description-radio-radioshow = Канал радиовещания для ведущего и станционной радиостанции.
guide-communication-channels-description-radio-cosmicradio = Канал космического культа и связанных с ним существ.
-guide-communication-channels-description-collective-mind-dragonmind = Канал разума дракона для карпов, акул и связанных с ним существ.
+guide-communication-channels-description-collective-mind-dragonmind = Канал коллективного разума дракона, карпов и акул.
guide-communication-channels-description-collective-mind-lingmind = Канал коллективного разума генокрадов.
guide-communication-channels-description-collective-mind-tidemind = Канал грейтайдов и связанных с ними событий.
-guide-communication-channels-description-collective-mind-blobmind = Канал блоба для ядра, фабрик и других частей организма.
+guide-communication-channels-description-collective-mind-blobmind = Канал блоба, объединяющий ядро, приспешников и другие части организма.
guide-communication-channels-description-collective-mind-mansuslink = Связь Мансуса для еретиков и их призванных существ.
-guide-communication-channels-description-collective-mind-abductormind = Канал серых и их команды.
-guide-communication-channels-description-collective-mind-binary = Двоичный канал синтетиков и связанных устройств.
+guide-communication-channels-description-collective-mind-abductormind = Канал связи серых и их команды.
+guide-communication-channels-description-collective-mind-binary = Двоичный канал для синтетиков, киборгов, боргов, искусственного интеллекта и связанных устройств.
guide-communication-channels-description-collective-mind-dronemind = Канал дронов.
guide-communication-channels-description-collective-mind-mousemind = Канал мышей.
guide-communication-channels-description-collective-mind-empathy = Эмпатическая связь существ, которым доступен этот разум.