From 35494b93bbd7d262faa6b836ea9d65ed56c93db4 Mon Sep 17 00:00:00 2001
From: FeudeyTF <72273449+FeudeyTF@users.noreply.github.com>
Date: Fri, 27 Jun 2025 18:19:18 +0300
Subject: [PATCH] Telecomms Update: Ability to change existing radio channels
and create new ones (#91647)
## About The Pull Request
I have added the ability to create and edit station radio channels
through the existing telecommunications system.
You can change the name of the radio channel and its color.
The channel settings are changed and created through the servers
(Frequencies Settings)

Here i created my own channel:
1) Add frequency at Receiver (you will not see channel name):

2) Add frequency at Bus (you will not see channel name):

3) Add frequency at Server
4) Add settings for your frequency

5) See the result:

Important Notes:
1) Headsets, radios, and intercoms will not see a change in
telecommunications, but will use standard names (Common, Security etc.).
2) There are still reserved names that cannot be used: CentComm,
Syndicate, Uplink, CTFs channels
3) Servers must filter frequency for applying settings on them
## Why It's Good For The Game
Now telecommunication channels names and colors depends on the settings
of the network servers, which makes it more flexible and logical. It is
also useful for foreign language servers, as you can translate channel
names.
## Changelog
:cl:
add: Added ability to change existing radio channels and create new
qol: Added color for some buttons in Telecomms UI
/:cl:
---
.../signals_atom/signals_atom_movable.dm | 8 +-
code/__DEFINES/radio.dm | 17 +++
code/__HELPERS/radio.dm | 2 +-
code/datums/brain_damage/imaginary_friend.dm | 8 +-
code/game/communications.dm | 27 +----
code/game/machinery/doors/passworddoor.dm | 2 +-
code/game/machinery/hologram.dm | 4 +-
code/game/machinery/telecomms/broadcasting.dm | 13 ++-
.../telecomms/machine_interactions.dm | 109 +++++++++++++++++-
.../machinery/telecomms/machines/server.dm | 73 +++++++++++-
.../objects/items/devices/radio/headset.dm | 6 +-
.../objects/items/devices/radio/intercom.dm | 2 +-
.../game/objects/items/devices/radio/radio.dm | 12 +-
.../objects/items/devices/taperecorder.dm | 2 +-
code/game/say.dm | 31 +++--
code/modules/admin/verbs/borgpanel.dm | 2 +-
code/modules/assembly/voice.dm | 2 +-
code/modules/clothing/head/jobs.dm | 2 +-
code/modules/hallucination/fake_chat.dm | 2 +-
code/modules/hallucination/mother.dm | 2 +-
.../mining_loot/megafauna/colossus.dm | 2 +-
.../mining_loot/megafauna/the_thing.dm | 2 +-
.../modules/mob/dead/observer/observer_say.dm | 4 +-
code/modules/mob/living/basic/bots/_bots.dm | 2 +-
.../mob/living/basic/pets/parrot/_parrot.dm | 2 +-
.../mob/living/carbon/human/human_say.dm | 2 +-
.../carbon/human/species_types/dullahan.dm | 4 +-
code/modules/mob/living/living_say.dm | 10 +-
code/modules/mob/living/silicon/ai/ai_say.dm | 2 +-
.../mob/living/silicon/ai/freelook/eye.dm | 2 +-
.../modules/mob/living/silicon/robot/robot.dm | 2 +-
.../modules/mob/living/silicon/silicon_say.dm | 2 +-
.../mob/living/simple_animal/bot/bot.dm | 2 +-
.../simple_animal/bot/bot_announcement.dm | 2 +-
code/modules/mob/say_readme.md | 2 +-
code/modules/mod/mod_link.dm | 4 +-
code/modules/wiremod/components/atom/hear.dm | 2 +-
interface/stylesheet.dm | 9 --
.../tgui-panel/styles/tgchat/chat-dark.scss | 37 ------
.../tgui-panel/styles/tgchat/chat-light.scss | 36 ------
tgui/packages/tgui/interfaces/Telecomms.jsx | 98 ++++++++++++----
41 files changed, 360 insertions(+), 194 deletions(-)
diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm
index 2d257b6ffda..1df2f39cc1b 100644
--- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm
@@ -70,9 +70,11 @@
#define HEARING_LANGUAGE 3
#define HEARING_RAW_MESSAGE 4
#define HEARING_RADIO_FREQ 5
- #define HEARING_SPANS 6
- #define HEARING_MESSAGE_MODE 7
- #define HEARING_RANGE 8
+ #define HEARING_RADIO_FREQ_NAME 6
+ #define HEARING_RADIO_FREQ_COLOR 7
+ #define HEARING_SPANS 8
+ #define HEARING_MESSAGE_MODE 9
+ #define HEARING_RANGE 10
///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
#define COMSIG_MOVABLE_DISPOSING "movable_disposing"
diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm
index 03dd4cc0e2f..582e0d9a4a4 100644
--- a/code/__DEFINES/radio.dm
+++ b/code/__DEFINES/radio.dm
@@ -4,61 +4,78 @@
#define RADIO_CHANNEL_COMMON "Common"
#define RADIO_KEY_COMMON ";"
+#define RADIO_COLOR_COMMON "#1ecc43"
#define RADIO_CHANNEL_SECURITY "Security"
#define RADIO_KEY_SECURITY "s"
#define RADIO_TOKEN_SECURITY ":s"
+#define RADIO_COLOR_SECURITY "#dd3535"
#define RADIO_CHANNEL_ENGINEERING "Engineering"
#define RADIO_KEY_ENGINEERING "e"
#define RADIO_TOKEN_ENGINEERING ":e"
+#define RADIO_COLOR_ENGINEERING "#f37746"
#define RADIO_CHANNEL_COMMAND "Command"
#define RADIO_KEY_COMMAND "c"
#define RADIO_TOKEN_COMMAND ":c"
+#define RADIO_COLOR_COMMAND "#fcdf03"
#define RADIO_CHANNEL_SCIENCE "Science"
#define RADIO_KEY_SCIENCE "n"
#define RADIO_TOKEN_SCIENCE ":n"
+#define RADIO_COLOR_SCIENCE "#c68cfa"
#define RADIO_CHANNEL_MEDICAL "Medical"
#define RADIO_KEY_MEDICAL "m"
#define RADIO_TOKEN_MEDICAL ":m"
+#define RADIO_COLOR_MEDICAL "#57b8f0"
#define RADIO_CHANNEL_SUPPLY "Supply"
#define RADIO_KEY_SUPPLY "u"
#define RADIO_TOKEN_SUPPLY ":u"
+#define RADIO_COLOR_SUPPLY "#b88646"
#define RADIO_CHANNEL_SERVICE "Service"
#define RADIO_KEY_SERVICE "v"
#define RADIO_TOKEN_SERVICE ":v"
+#define RADIO_COLOR_SERVICE "#6ca729"
#define RADIO_CHANNEL_AI_PRIVATE "AI Private"
#define RADIO_KEY_AI_PRIVATE "o"
#define RADIO_TOKEN_AI_PRIVATE ":o"
+#define RADIO_COLOR_AI_PRIVATE "#d65d95"
#define RADIO_CHANNEL_ENTERTAINMENT "Entertainment"
#define RADIO_KEY_ENTERTAINMENT "p"
#define RADIO_TOKEN_ENTERTAINMENT ":p"
+#define RADIO_COLOR_ENTERTAIMENT "#79c5a8"
#define STATUS_DISPLAY_RELAY "Captain-Cast"
#define RADIO_CHANNEL_SYNDICATE "Syndicate"
#define RADIO_KEY_SYNDICATE "t"
#define RADIO_TOKEN_SYNDICATE ":t"
+#define RADIO_COLOR_SYNDICATE "#8f4a4b"
#define RADIO_CHANNEL_CENTCOM "CentCom"
#define RADIO_KEY_CENTCOM "y"
#define RADIO_TOKEN_CENTCOM ":y"
+#define RADIO_COLOR_CENTCOM "#2681a5"
#define RADIO_CHANNEL_UPLINK "Uplink"
#define RADIO_KEY_UPLINK "z"
#define RADIO_TOKEN_UPLINK ":z"
+#define RADIO_COLOR_UPLINK "#8f4a4b"
#define RADIO_CHANNEL_CTF_RED "Red Team"
+#define RADIO_COLOR_CTF_RED "#ff0000"
#define RADIO_CHANNEL_CTF_BLUE "Blue Team"
+#define RADIO_COLOR_CTF_BLUE "#0000ff"
#define RADIO_CHANNEL_CTF_GREEN "Green Team"
+#define RADIO_COLOR_GREEN "#00ff00"
#define RADIO_CHANNEL_CTF_YELLOW "Yellow Team"
+#define RADIO_COLOR_YELLOW "#d1ba22"
#define MIN_FREE_FREQ 1201 // -------------------------------------------------
diff --git a/code/__HELPERS/radio.dm b/code/__HELPERS/radio.dm
index 64d70181d9b..9f25af914dd 100644
--- a/code/__HELPERS/radio.dm
+++ b/code/__HELPERS/radio.dm
@@ -30,6 +30,6 @@
freq_to_check = rand(start, end)
if(!(freq_to_check % 2)) // Ensure the last digit is an odd number
freq_to_check++
- while((freq_to_check == 0) || ("[freq_to_check]" in GLOB.reverseradiochannels))
+ while((freq_to_check == 0) || ("[freq_to_check]" in GLOB.reserved_radio_frequencies))
return freq_to_check
diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm
index bb1e149ffe6..449b0ec0657 100644
--- a/code/datums/brain_damage/imaginary_friend.dm
+++ b/code/datums/brain_damage/imaginary_friend.dm
@@ -216,10 +216,10 @@
owner.imaginary_group -= src
return ..()
-/mob/eye/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
+/mob/eye/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, freq_name, freq_color, list/spans, list/message_mods = list(), message_range)
if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
create_chat_message(speaker, message_language, raw_message, spans)
- to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods))
+ to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, freq_name, freq_color, spans, message_mods))
/mob/eye/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null)
message = get_message_mods(message, message_mods)
@@ -263,10 +263,10 @@
var/dead_rendered = "[span_name("[name] (Imaginary friend of [owner])")] [quoted_message]"
var/language = message_language || owner.get_selected_language()
- Hear(rendered, src, language, message, null, spans, message_mods) // We always hear what we say
+ Hear(rendered, src, language, message, null, null, null, spans, message_mods) // We always hear what we say
var/group = owner.imaginary_group - src // The people in our group don't, so we have to exclude ourselves not to hear twice
for(var/mob/person in group)
- person.Hear(null, src, language, message, null, spans, message_mods, range)
+ person.Hear(null, src, language, message, null, null, null, spans, message_mods, range)
// Speech bubble, but only for those who have runechat off
var/list/speech_bubble_recipients = list()
diff --git a/code/game/communications.dm b/code/game/communications.dm
index 1eff3571f57..9e40080a49d 100644
--- a/code/game/communications.dm
+++ b/code/game/communications.dm
@@ -91,7 +91,7 @@ GLOBAL_LIST_EMPTY(all_radios)
// see __DEFINES/radio.dm. Mappers may also select additional frequencies for
// use in maps, such as in intercoms.
-GLOBAL_LIST_INIT(radiochannels, list(
+GLOBAL_LIST_INIT(default_radio_channels, list(
RADIO_CHANNEL_COMMON = FREQ_COMMON,
RADIO_CHANNEL_SCIENCE = FREQ_SCIENCE,
RADIO_CHANNEL_COMMAND = FREQ_COMMAND,
@@ -112,20 +112,10 @@ GLOBAL_LIST_INIT(radiochannels, list(
STATUS_DISPLAY_RELAY = FREQ_STATUS_DISPLAYS,
))
-GLOBAL_LIST_INIT(reverseradiochannels, list(
- "[FREQ_COMMON]" = RADIO_CHANNEL_COMMON,
- "[FREQ_SCIENCE]" = RADIO_CHANNEL_SCIENCE,
- "[FREQ_COMMAND]" = RADIO_CHANNEL_COMMAND,
- "[FREQ_MEDICAL]" = RADIO_CHANNEL_MEDICAL,
- "[FREQ_ENGINEERING]" = RADIO_CHANNEL_ENGINEERING,
- "[FREQ_SECURITY]" = RADIO_CHANNEL_SECURITY,
+GLOBAL_LIST_INIT(reserved_radio_frequencies, list(
"[FREQ_CENTCOM]" = RADIO_CHANNEL_CENTCOM,
"[FREQ_SYNDICATE]" = RADIO_CHANNEL_SYNDICATE,
"[FREQ_UPLINK]" = RADIO_CHANNEL_UPLINK,
- "[FREQ_SUPPLY]" = RADIO_CHANNEL_SUPPLY,
- "[FREQ_SERVICE]" = RADIO_CHANNEL_SERVICE,
- "[FREQ_AI_PRIVATE]" = RADIO_CHANNEL_AI_PRIVATE,
- "[FREQ_ENTERTAINMENT]" = RADIO_CHANNEL_ENTERTAINMENT,
"[FREQ_CTF_RED]" = RADIO_CHANNEL_CTF_RED,
"[FREQ_CTF_BLUE]" = RADIO_CHANNEL_CTF_BLUE,
"[FREQ_CTF_GREEN]" = RADIO_CHANNEL_CTF_GREEN,
@@ -133,19 +123,10 @@ GLOBAL_LIST_INIT(reverseradiochannels, list(
"[FREQ_STATUS_DISPLAYS]" = STATUS_DISPLAY_RELAY,
))
-GLOBAL_LIST_INIT(radiocolors, list(
- RADIO_CHANNEL_COMMON = "#008000",
- RADIO_CHANNEL_SCIENCE = "#993399",
- RADIO_CHANNEL_COMMAND = "#948f02",
- RADIO_CHANNEL_MEDICAL = "#337296",
- RADIO_CHANNEL_ENGINEERING = "#fb5613",
- RADIO_CHANNEL_SECURITY = "#a30000",
+GLOBAL_LIST_INIT(reserved_radio_colors, list(
RADIO_CHANNEL_CENTCOM = "#686868",
RADIO_CHANNEL_SYNDICATE = "#6d3f40",
- RADIO_CHANNEL_SUPPLY = "#a8732b",
- RADIO_CHANNEL_SERVICE = "#6eaa2c",
- RADIO_CHANNEL_AI_PRIVATE = "#ff00ff",
- RADIO_CHANNEL_ENTERTAINMENT = "#00ff99",
+ RADIO_CHANNEL_UPLINK = "#6d3f40",
RADIO_CHANNEL_CTF_RED = "#ff0000",
RADIO_CHANNEL_CTF_BLUE = "#0000ff",
RADIO_CHANNEL_CTF_GREEN = "#00ff00",
diff --git a/code/game/machinery/doors/passworddoor.dm b/code/game/machinery/doors/passworddoor.dm
index 8d35f44b0d8..cb20b6a44f0 100644
--- a/code/game/machinery/doors/passworddoor.dm
+++ b/code/game/machinery/doors/passworddoor.dm
@@ -44,7 +44,7 @@
/obj/machinery/door/password/get_save_vars()
return ..() + NAMEOF(src, password)
-/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
+/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
. = ..()
if(!density || !voice_activated || radio_freq)
return
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 0e027bfe357..d53667e61b8 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -575,7 +575,7 @@ Possible to do for anyone motivated enough:
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
-/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
+/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
. = ..()
if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
for(var/mob/living/silicon/ai/master in masters)
@@ -587,7 +587,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(speaker == holocall_to_update.hologram && holocall_to_update.user.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
holocall_to_update.user.create_chat_message(speaker, message_language, raw_message, spans)
else
- holocall_to_update.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods, message_range = INFINITY)
+ holocall_to_update.user.Hear(message, speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, spans, message_mods, message_range = INFINITY)
if(outgoing_call?.hologram && speaker == outgoing_call.user)
outgoing_call.hologram.say(raw_message, sanitize = FALSE)
diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm
index a65b31223b9..289ac960f8f 100644
--- a/code/game/machinery/telecomms/broadcasting.dm
+++ b/code/game/machinery/telecomms/broadcasting.dm
@@ -141,10 +141,11 @@
radios -= subspace_radio
// Syndicate radios can hear all well-known radio channels
- if (num2text(frequency) in GLOB.reverseradiochannels)
- for(var/obj/item/radio/syndicate_radios in GLOB.all_radios["[FREQ_SYNDICATE]"])
- if(syndicate_radios.can_receive(FREQ_SYNDICATE, RADIO_NO_Z_LEVEL_RESTRICTION))
- radios |= syndicate_radios
+ for(var/channel in GLOB.default_radio_channels)
+ if (GLOB.default_radio_channels[channel] == frequency)
+ for(var/obj/item/radio/syndicate_radios in GLOB.all_radios["[FREQ_SYNDICATE]"])
+ if(syndicate_radios.can_receive(FREQ_SYNDICATE, RADIO_NO_Z_LEVEL_RESTRICTION))
+ radios |= syndicate_radios
if (TRANSMISSION_RADIO)
// Only radios not currently in subspace mode
@@ -173,14 +174,14 @@
// Always call this on the virtualspeaker to avoid issues.
var/spans = data["spans"]
var/list/message_mods = data["mods"]
- var/rendered = virt.compose_message(virt, language, message, frequency, spans)
+ var/rendered = virt.compose_message(virt, language, message, frequency, data["frequency_name"], data["frequency_color"], spans)
for(var/atom/movable/hearer as anything in receive)
if(!hearer)
stack_trace("null found in the hearers list returned by the spatial grid. this is bad")
continue
spans -= blacklisted_spans
- hearer.Hear(rendered, virt, language, message, frequency, spans, message_mods, message_range = INFINITY)
+ hearer.Hear(rendered, virt, language, message, frequency, data["frequency_name"], data["frequency_color"], spans, message_mods, message_range = INFINITY)
// This following recording is intended for research and feedback in the use of department radio channels
if(length(receive))
diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm
index f61349208a3..054edc51763 100644
--- a/code/game/machinery/telecomms/machine_interactions.dm
+++ b/code/game/machinery/telecomms/machine_interactions.dm
@@ -45,6 +45,7 @@
data += add_option()
+ data["channels"] = get_channels()
data["minfreq"] = MIN_FREE_FREQ
data["maxfreq"] = MAX_FREE_FREQ
data["frequency"] = tempfreq
@@ -79,7 +80,6 @@
for(var/x in freq_listening)
frequencies += list(x)
data["frequencies"] = frequencies
-
return data
/obj/machinery/telecomms/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
@@ -194,6 +194,52 @@
return TRUE
+/**
+ *
+ * Returns information (name and color) about all channels in machine's network
+ */
+/obj/machinery/telecomms/proc/get_channels()
+ var/list/channels = list()
+ for(var/channel_freq in GLOB.reserved_radio_frequencies)
+ var/channel_name = GLOB.reserved_radio_frequencies[channel_freq]
+ channels += list(list(
+ "freq" = text2num(channel_freq),
+ "name" = channel_name,
+ "color" = GLOB.reserved_radio_colors[channel_name]
+ ))
+
+ var/obj/machinery/telecomms/hub/hub
+ if(istype(src, /obj/machinery/telecomms/hub))
+ hub = src
+ else
+ for(var/obj/machinery/telecomms/link in links)
+ if(istype(link, /obj/machinery/telecomms/hub))
+ hub = link
+ break
+
+ if(hub)
+ for(var/obj/machinery/telecomms/link in hub.links)
+ if(istype(link, /obj/machinery/telecomms/server))
+ var/obj/machinery/telecomms/server/server = link
+ for(var/freq_info_freq in server.frequency_infos)
+ var/list/freq_info = server.frequency_infos[freq_info_freq]
+ channels += list(list(
+ "freq" = text2num(freq_info_freq),
+ "name" = freq_info["name"],
+ "color" = freq_info["color"]
+ ))
+ else if(istype(src, /obj/machinery/telecomms/server))
+ var/obj/machinery/telecomms/server/server = src
+ for(var/freq_info_freq in server.frequency_infos)
+ var/list/freq_info = server.frequency_infos[freq_info_freq]
+ channels += list(list(
+ "freq" = text2num(freq_info_freq),
+ "name" = freq_info["name"],
+ "color" = freq_info["color"]
+ ))
+
+ return channels
+
/**
* Wrapper for adding additional options to a machine's interface.
*
@@ -215,6 +261,21 @@
data["receiving"] = receiving
return data
+/obj/machinery/telecomms/server/add_option()
+ var/list/data = list()
+ data["type"] = "server"
+ var/list/infos = list()
+ for(var/freq_info_freq in frequency_infos)
+ var/list/freq_info = frequency_infos[freq_info_freq]
+ infos += list(list(
+ "frequency" = freq_info_freq,
+ "name" = freq_info["name"],
+ "color" = freq_info["color"]
+ ))
+
+ data["frequencyinfos"] = infos
+ return data
+
/**
* Wrapper for adding another time of action for `ui_act()`, rather than
* having you override `ui_act` yourself.
@@ -244,6 +305,52 @@
else
change_frequency = 0
+/obj/machinery/telecomms/server/add_act(action, params)
+ switch(action)
+ if("delete")
+ frequency_infos.Remove(num2text(params["value"]))
+ . = TRUE
+ if("modify_freq_info")
+ var/freq = params["freq"]
+ var/info = frequency_infos[freq]
+ if(info)
+ var/new_name = tgui_input_text(usr, "Please enter new frequency name", "Modifying Frequency Information", info["name"], MAX_NAME_LEN)
+ if(new_name)
+ for(var/list/channel in get_channels())
+ if(num2text(channel["freq"]) != freq && channel["name"] == new_name)
+ return
+ info["name"] = new_name
+ var/new_color = input(usr, "Choose color for frequency", "Modifying Frequency Information", info["color"]) as color|null
+ if(new_color)
+ info["color"] = new_color
+ frequency_infos[params["freq"]] = info
+ . = TRUE
+ if("add_freq_info")
+ var/freq = tgui_input_number(usr, "Please enter frequency", "Adding Frequency Information", 145.9, 160, 120, round_value = FALSE)
+ if(!freq)
+ return
+ freq = round(freq*10)
+ if(!(freq in freq_listening))
+ return
+ var/name = tgui_input_text(usr, "Please enter frequency name", "Adding Frequency Information", max_length = MAX_NAME_LEN)
+ if(!name)
+ return
+
+ for(var/list/channel in get_channels())
+ if(channel["freq"] == freq || channel["name"] == name)
+ return
+ var/color = input(usr, "Choose color for frequency", "Adding Frequency Information") as color|null
+ if(!color)
+ return
+ frequency_infos[num2text(freq)] = list(
+ "name" = name,
+ "color" = color
+ )
+ . = TRUE
+ if("delete_freq_info")
+ frequency_infos.Remove(params["freq"])
+ . = TRUE
+
/// Returns a multitool from a user depending on their mobtype.
/obj/machinery/telecomms/proc/get_multitool(mob/user)
. = null
diff --git a/code/game/machinery/telecomms/machines/server.dm b/code/game/machinery/telecomms/machines/server.dm
index 1c7557b79de..943bffe82c2 100644
--- a/code/game/machinery/telecomms/machines/server.dm
+++ b/code/game/machinery/telecomms/machines/server.dm
@@ -14,6 +14,8 @@
density = TRUE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01
circuit = /obj/item/circuitboard/machine/telecomms/server
+ /// List of frequency info: the name and color of each frequency that the server processes
+ var/list/frequency_infos = list()
/// A list of previous entries on the network. It will not exceed
/// `MAX_LOG_ENTRIES` entries in length, flushing the oldest entries
/// automatically.
@@ -30,6 +32,11 @@
if(traffic > 0)
total_traffic += traffic // add current traffic to total traffic
+ var/freq_info = frequency_infos["[signal.frequency]"]
+ if(freq_info)
+ signal.data["frequency_name"] = freq_info["name"]
+ signal.data["frequency_color"] = freq_info["color"]
+
// Delete particularly old logs
if (log_entries.len >= MAX_LOG_ENTRIES)
log_entries.Cut(1, 2)
@@ -89,26 +96,69 @@
freq_listening = list(FREQ_SCIENCE)
autolinkers = list("science")
+/obj/machinery/telecomms/server/presets/science/New()
+ . = ..()
+ frequency_infos["[FREQ_SCIENCE]"] = list(
+ "name" = RADIO_CHANNEL_SCIENCE,
+ "color" = RADIO_COLOR_SCIENCE
+ )
+
/obj/machinery/telecomms/server/presets/medical
id = "Medical Server"
freq_listening = list(FREQ_MEDICAL)
autolinkers = list("medical")
+/obj/machinery/telecomms/server/presets/medical/New()
+ . = ..()
+ frequency_infos["[FREQ_MEDICAL]"] = list(
+ "name" = RADIO_CHANNEL_MEDICAL,
+ "color" = RADIO_COLOR_MEDICAL
+ )
+
/obj/machinery/telecomms/server/presets/supply
id = "Supply Server"
freq_listening = list(FREQ_SUPPLY)
autolinkers = list("supply")
+/obj/machinery/telecomms/server/presets/supply/New()
+ . = ..()
+ frequency_infos["[FREQ_SUPPLY]"] = list(
+ "name" = RADIO_CHANNEL_SUPPLY,
+ "color" = RADIO_COLOR_SUPPLY
+ )
+
/obj/machinery/telecomms/server/presets/service
id = "Service & Entertainment Server"
freq_listening = list(FREQ_SERVICE, FREQ_ENTERTAINMENT)
autolinkers = list("service", "entertainment")
+/obj/machinery/telecomms/server/presets/service/New()
+ . = ..()
+ frequency_infos["[FREQ_SERVICE]"] = list(
+ "name" = RADIO_CHANNEL_SERVICE,
+ "color" = RADIO_COLOR_SERVICE
+ )
+ frequency_infos["[FREQ_ENTERTAINMENT]"] = list(
+ "name" = RADIO_CHANNEL_ENTERTAINMENT,
+ "color" = RADIO_COLOR_ENTERTAIMENT
+ )
+
/obj/machinery/telecomms/server/presets/common
- id = "Common Server"
+ id = "Common & AI Server"
freq_listening = list()
autolinkers = list("common")
+/obj/machinery/telecomms/server/presets/common/New()
+ . = ..()
+ frequency_infos["[FREQ_COMMON]"] = list(
+ "name" = RADIO_CHANNEL_COMMON,
+ "color" = RADIO_COLOR_COMMON
+ )
+ frequency_infos["[FREQ_AI_PRIVATE]"] = list(
+ "name" = RADIO_CHANNEL_AI_PRIVATE,
+ "color" = RADIO_COLOR_AI_PRIVATE
+ )
+
/obj/machinery/telecomms/server/presets/common/Initialize(mapload)
. = ..()
// Common and other radio frequencies for people to freely use
@@ -120,16 +170,37 @@
freq_listening = list(FREQ_COMMAND)
autolinkers = list("command")
+/obj/machinery/telecomms/server/presets/command/New()
+ . = ..()
+ frequency_infos["[FREQ_COMMAND]"] = list(
+ "name" = RADIO_CHANNEL_COMMAND,
+ "color" = RADIO_COLOR_COMMAND
+ )
+
/obj/machinery/telecomms/server/presets/engineering
id = "Engineering Server"
freq_listening = list(FREQ_ENGINEERING)
autolinkers = list("engineering")
+/obj/machinery/telecomms/server/presets/engineering/New()
+ . = ..()
+ frequency_infos["[FREQ_ENGINEERING]"] = list(
+ "name" = RADIO_CHANNEL_ENGINEERING,
+ "color" = RADIO_COLOR_ENGINEERING
+ )
+
/obj/machinery/telecomms/server/presets/security
id = "Security Server"
freq_listening = list(FREQ_SECURITY)
autolinkers = list("security")
+/obj/machinery/telecomms/server/presets/security/New()
+ . = ..()
+ frequency_infos["[FREQ_SECURITY]"] = list(
+ "name" = RADIO_CHANNEL_SECURITY,
+ "color" = RADIO_COLOR_SECURITY
+ )
+
/obj/machinery/telecomms/server/presets/common/birdstation/Initialize(mapload)
. = ..()
freq_listening = list()
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 620c12d6041..beaab018372 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -62,7 +62,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
for(var/i in 1 to length(channels))
var/channel_name = channels[i]
var/channel_token = GLOB.channel_tokens[channel_name]
- var/channel_span_class = get_radio_span(GLOB.radiochannels[channel_name])
+ var/channel_span_class = get_radio_span(GLOB.default_radio_channels[channel_name])
if(i == 1)
available_channels += "
[span_class(channel_span_class, MODE_TOKEN_DEPARTMENT)] or [span_class(channel_span_class, channel_token)] for [span_class(channel_span_class, channel_name)]