Documents a lot of undocumented telecommunications code (#78934)

## About The Pull Request
Telecommunications code is very old, I'm sure that isn't a shock to
anyone. One of the issues it had was that it was poorly documented, so
I've spent a few hours today making sure that at least one person could
understand what was going on in there, and actually left some traces of
what I understood from it all.

Now, it's a bit cleaner, and hopefully a lot easier to understand
because the stuff's actually explained, and the explanations are up to
date. Because there was still code from over eight years ago that
straight-up just didn't match the contents of the file at all.

I tried to not change any of the logic, I did one minor adjustment just
to improve the coherency of a variable that's not actually used
anywhere, but I kept it in case it becomes useful in the future, since I
wanted to keep feature parity here.

This should open up the way to actually making some changes to
telecommunications in the future, which I'm looking forward to, too.

## Why It's Good For The Game
Less undocumented nightmarish code from ages ago, now it's at least
documented, so it'll be easier to tweak moving forward.

## Changelog

🆑 GoldenAlpharex
code: Documented a huge part of telecommunications machinery and signal
code, and did some minor code improvements to said code.
/🆑
This commit is contained in:
GoldenAlpharex
2023-10-16 14:20:23 +02:00
committed by GitHub
parent 5f8dc9e6d4
commit afb5b61b2a
16 changed files with 429 additions and 302 deletions
+15
View File
@@ -130,6 +130,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list(
))
/datum/radio_frequency
/// The frequency of this radio frequency. Of course.
var/frequency
/// List of filters -> list of devices
var/list/list/datum/weakref/devices = list()
@@ -178,6 +179,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list(
device.receive_signal(signal)
CHECK_TICK
/// Handles adding a listener to the radio frequency.
/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null)
if (!filter)
filter = "_default"
@@ -190,6 +192,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list(
devices[filter] = devices_line = list()
devices_line += new_listener
/// Handles removing a listener from this radio frequency.
/datum/radio_frequency/proc/remove_listener(obj/device)
for(var/devices_filter in devices)
var/list/devices_line = devices[devices_filter]
@@ -199,15 +202,27 @@ GLOBAL_LIST_INIT(reverseradiochannels, list(
if(!devices_line.len)
devices -= devices_filter
/**
* Proc for reacting to a received `/datum/signal`. To be implemented as needed,
* does nothing by default.
*/
/obj/proc/receive_signal(datum/signal/signal)
set waitfor = FALSE
return
/datum/signal
/// The source of this signal.
var/obj/source
/// The frequency on which this signal was emitted.
var/frequency = 0
/// The method through which this signal was transmitted.
/// See all of the `TRANSMISSION_X` in `code/__DEFINES/radio.dm` for
/// all of the possible options.
var/transmission_method
/// The data carried through this signal. Defaults to `null`, otherwise it's
/// an associative list of (string, any).
var/list/data
/// Logging data, used for logging purposes. Makes sense, right?
var/logging_data
/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO, logging_data = null)
+44 -63
View File
@@ -1,67 +1,26 @@
/*
Here is the big, bad function that broadcasts a message given the appropriate
parameters.
@param M:
Reference to the mob/speaker, stored in signal.data["mob"]
@param vmask:
Boolean value if the mob is "hiding" its identity via voice mask, stored in
signal.data["vmask"]
@param vmessage:
If specified, will display this as the message; such as "chimpering"
for monkeys if the mob is not understood. Stored in signal.data["vmessage"].
@param radio:
Reference to the radio broadcasting the message, stored in signal.data["radio"]
@param message:
The actual string message to display to mobs who understood mob M. Stored in
signal.data["message"]
@param name:
The name to display when a mob receives the message. signal.data["name"]
@param job:
The name job to display for the AI when it receives the message. signal.data["job"]
@param realname:
The "real" name associated with the mob. signal.data["realname"]
@param vname:
If specified, will use this name when mob M is not understood. signal.data["vname"]
@param data:
If specified:
1 -- Will only broadcast to intercoms
2 -- Will only broadcast to intercoms and station-bounced radios
3 -- Broadcast to syndicate frequency
4 -- AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob
@param compression:
If 0, the signal is audible
If nonzero, the signal may be partially inaudible or just complete gibberish.
@param level:
The list of Z levels that the sending radio is broadcasting to. Having 0 in the list broadcasts on all levels
@param freq
The frequency of the signal
**/
// Subtype of /datum/signal with additional processing information.
/datum/signal/subspace
transmission_method = TRANSMISSION_SUBSPACE
/// The type of server this signal is meant to be relayed to.
/// Not exclusive, the bus will usually try to send it through
/// more signals, but for that look for
/// `/obj/machinery/telecomms/bus/receive_information()`
var/server_type = /obj/machinery/telecomms/server
/// The signal that was the origin of this one, in case it was a copy.
var/datum/signal/subspace/original
/// The levels on which this signal can be received. Generally set by
/// a broadcaster, a relay or a message server.
/// If this list contains `0`, then it will be receivable on every single
/// z-level.
var/list/levels
/datum/signal/subspace/New(data)
src.data = data || list()
/**
* Handles creating a new subspace signal that's a hard copy of this one, linked
* to this current signal via the `original` value, so that it can be traced back.
*/
/datum/signal/subspace/proc/copy()
var/datum/signal/subspace/copy = new
copy.original = src
@@ -73,18 +32,26 @@
copy.data = data.Copy()
return copy
/**
* Handles marking the current signal, as well as its original signal,
* and their original signals (recursively) as done, in their `data["done"]`.
*/
/datum/signal/subspace/proc/mark_done()
var/datum/signal/subspace/current = src
while (current)
current.data["done"] = TRUE
current = current.original
/**
* Handles sending this signal to every available receiver and mainframe.
*/
/datum/signal/subspace/proc/send_to_receivers()
for(var/obj/machinery/telecomms/receiver/R in GLOB.telecomms_list)
R.receive_signal(src)
for(var/obj/machinery/telecomms/allinone/R in GLOB.telecomms_list)
R.receive_signal(src)
for(var/obj/machinery/telecomms/receiver/receiver in GLOB.telecomms_list)
receiver.receive_signal(src)
for(var/obj/machinery/telecomms/allinone/all_in_one_receiver in GLOB.telecomms_list)
all_in_one_receiver.receive_signal(src)
/// Handles broadcasting this signal out, to be implemented by subtypes.
/datum/signal/subspace/proc/broadcast()
set waitfor = FALSE
@@ -92,9 +59,14 @@
// Despite "subspace" in the name, these transmissions can also be RADIO
// (intercoms and SBRs) or SUPERSPACE (CentCom).
/datum/signal/subspace/vocal
/// The virtualspeaker associated with this vocal transmission.
var/atom/movable/virtualspeaker/virt
/// The language this vocal transmission was sent in.
var/datum/language/language
#define COMPRESSION_VOCAL_SIGNAL_MIN 35
#define COMPRESSION_VOCAL_SIGNAL_MAX 65
/datum/signal/subspace/vocal/New(
obj/source, // the originating radio
frequency, // the frequency the signal is taking place on
@@ -113,13 +85,16 @@
"name" = speaker.name,
"job" = speaker.job,
"message" = message,
"compression" = rand(35, 65),
"compression" = rand(COMPRESSION_VOCAL_SIGNAL_MIN, COMPRESSION_VOCAL_SIGNAL_MAX),
"language" = lang_instance.name,
"spans" = spans,
"mods" = message_mods
)
levels = SSmapping.get_connected_levels(get_turf(source))
#undef COMPRESSION_VOCAL_SIGNAL_MIN
#undef COMPRESSION_VOCAL_SIGNAL_MAX
/datum/signal/subspace/vocal/copy()
var/datum/signal/subspace/vocal/copy = new(source, frequency, virt, language)
copy.original = src
@@ -127,6 +102,10 @@
copy.levels = levels
return copy
/// Past this amount of compression, the resulting gibberish will actually
/// replace characters, making it even harder to understand.
#define COMPRESSION_REPLACE_CHARACTER_THRESHOLD 30
/// This is the meat function for making radios hear vocal transmissions.
/datum/signal/subspace/vocal/broadcast()
set waitfor = FALSE
@@ -137,7 +116,7 @@
return
var/compression = data["compression"]
if(compression > 0)
message = Gibberish(message, compression >= 30)
message = Gibberish(message, compression >= COMPRESSION_REPLACE_CHARACTER_THRESHOLD)
var/list/signal_reaches_every_z_level = levels
@@ -206,8 +185,8 @@
var/spans_part = ""
if(length(spans))
spans_part = "(spans:"
for(var/S in spans)
spans_part = "[spans_part] [S]"
for(var/span in spans)
spans_part = "[spans_part] [span]"
spans_part = "[spans_part] ) "
var/lang_name = data["language"]
@@ -220,4 +199,6 @@
else
log_telecomms("[virt.source] [log_text] [loc_name(get_turf(virt.source))]")
QDEL_IN(virt, 50) // Make extra sure the virtualspeaker gets qdeleted
QDEL_IN(virt, 5 SECONDS) // Make extra sure the virtualspeaker gets qdeleted
#undef COMPRESSION_REPLACE_CHARACTER_THRESHOLD
@@ -41,7 +41,7 @@
// Send selected server data
var/list/server_out = list()
server_out["name"] = SelectedServer.name
server_out["traffic"] = SelectedServer.totaltraffic
server_out["traffic"] = SelectedServer.total_traffic
// Get the messages on this server
var/list/packets = list()
for(var/datum/comm_log_entry/packet in SelectedServer.log_entries)
@@ -20,13 +20,16 @@
var/obj/machinery/telecomms/message_server/linkedServer = null
/// Sparks effect - For emag
var/datum/effect_system/spark_spread/spark_system
/// Computer properties
var/screen = MSG_MON_SCREEN_MAIN // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
var/message = "System bootup complete. Please select an option." // The message that shows on the main menu.
var/auth = FALSE // Are they authenticated?
/// Error, Success & Notice messages
/// Computer properties.
/// 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
var/screen = MSG_MON_SCREEN_MAIN
/// The message that shows on the main menu.
var/message = "System bootup complete. Please select an option."
/// Error message to display in the interface.
var/error_message = ""
/// Notice message to display in the interface.
var/notice_message = ""
/// Success message to display in the interface.
var/success_message = ""
/// Decrypt password
var/password = ""
@@ -89,7 +92,7 @@
"error_message" = error_message,
"notice_message" = notice_message,
"success_message" = success_message,
"auth" = auth,
"auth" = authenticated,
"server_status" = !LINKED_SERVER_NONRESPONSIVE,
)
@@ -109,7 +112,7 @@
if(MSG_MON_SCREEN_REQUEST_LOGS)
var/list/request_list = list()
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
request_list += list(list("ref" = REF(rc), "message" = rc.message, "stamp" = rc.stamp, "id_auth" = rc.id_auth, "departament" = rc.send_dpt))
request_list += list(list("ref" = REF(rc), "message" = rc.message, "stamp" = rc.stamp, "id_auth" = rc.id_auth, "departament" = rc.sender_department))
data["requests"] = request_list
return data
@@ -126,15 +129,15 @@
if("auth")
var/authPass = params["auth_password"]
if(auth)
auth = FALSE
if(authenticated)
authenticated = FALSE
return TRUE
if(linkedServer.decryptkey != authPass)
error_message = "ALERT: Incorrect decryption key!"
return TRUE
auth = TRUE
authenticated = TRUE
success_message = "YOU SUCCESFULLY LOGGED IN!"
return TRUE
@@ -246,14 +249,14 @@
linkedServer.receive_information(signal, null)
usr.log_message("(Tablet: [name] | [usr.real_name]) sent \"[message]\" to [signal.format_target()]", LOG_PDA)
return TRUE
// Malfunction AI and cyborgs can hack console. This will auth console, but you need to wait password selection
// Malfunction AI and cyborgs can hack console. This will authenticate the console, but you need to wait password selection
if("hack")
var/time = 10 SECONDS * length(linkedServer.decryptkey)
addtimer(CALLBACK(src, PROC_REF(unemag_console)), time)
screen = MSG_MON_SCREEN_HACKED
error_message = "%$&(£: Critical %$$@ Error // !RestArting! <lOadiNg backUp iNput ouTput> - ?pLeaSe wAit!"
linkedServer.toggled = FALSE
auth = TRUE
authenticated = TRUE
return TRUE
return TRUE
@@ -284,6 +287,9 @@
else
return INITIALIZE_HINT_LATELOAD
/**
* Handles printing the monitor key for a given server onto this piece of paper.
*/
/obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server)
add_raw_text("<center><h2>Daily Key Reset</h2></center><br>The new message monitor key is <b>[server.decryptkey]</b>.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one.")
add_overlay("paper_words")
@@ -1,15 +1,13 @@
/*
All telecommunications interactions:
*/
// This file is separate from telecommunications.dm to isolate the implementation
// of basic interactions with the machines.
/obj/machinery/telecomms
var/temp = "" // output message
/// The current temporary frequency used to add new filtered frequencies
/// options.
var/tempfreq = FREQ_COMMON
/// The current mob operating the machine.
var/mob/living/operator
///Illegal frequencies that can't be listened to by telecommunication servers.
/// Illegal frequencies that can't be listened to by telecommunication servers.
var/list/banned_frequencies = list(
FREQ_SYNDICATE,
FREQ_CENTCOM,
@@ -19,7 +17,7 @@
FREQ_CTF_BLUE,
)
/obj/machinery/telecomms/attackby(obj/item/P, mob/user, params)
/obj/machinery/telecomms/attackby(obj/item/attacking_item, mob/user, params)
var/icon_closed = initial(icon_state)
var/icon_open = "[initial(icon_state)]_o"
@@ -27,13 +25,13 @@
icon_closed = "[initial(icon_state)]_off"
icon_open = "[initial(icon_state)]_o_off"
if(default_deconstruction_screwdriver(user, icon_open, icon_closed, P))
if(default_deconstruction_screwdriver(user, icon_open, icon_closed, attacking_item))
return
// Using a multitool lets you access the receiver's interface
else if(P.tool_behaviour == TOOL_MULTITOOL)
else if(attacking_item.tool_behaviour == TOOL_MULTITOOL)
attack_hand(user)
else if(default_deconstruction_crowbar(P))
else if(default_deconstruction_crowbar(attacking_item))
return
else
return ..()
@@ -122,8 +120,8 @@
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
return
else
for(var/obj/machinery/telecomms/T in links)
remove_link(T)
for(var/obj/machinery/telecomms/linked_machine in links)
remove_link(linked_machine)
network = params["value"]
links = list()
operator.log_message("has changed the network for [src] to [network].", LOG_GAME)
@@ -145,13 +143,13 @@
operator.log_message("removed frequency [params["value"]] for [src].", LOG_GAME)
. = TRUE
if("unlink")
var/obj/machinery/telecomms/T = links[text2num(params["value"])]
if(T)
. = remove_link(T, operator)
var/obj/machinery/telecomms/machine_to_unlink = links[text2num(params["value"])]
if(machine_to_unlink)
. = remove_link(machine_to_unlink, operator)
if("link")
if(heldmultitool)
var/obj/machinery/telecomms/T = heldmultitool.buffer
. = add_new_link(T, operator)
var/obj/machinery/telecomms/machine_to_link = heldmultitool.buffer
. = add_new_link(machine_to_link, operator)
if("buffer")
heldmultitool.set_buffer(src)
. = TRUE
@@ -162,7 +160,7 @@
add_act(action, params)
. = TRUE
///adds new_connection to src's links list AND vice versa. also updates links_by_telecomms_type
/// Adds new_connection to src's links list AND vice versa. Also updates `links_by_telecomms_type`.
/obj/machinery/telecomms/proc/add_new_link(obj/machinery/telecomms/new_connection, mob/user)
if(!istype(new_connection) || new_connection == src)
return FALSE
@@ -180,7 +178,7 @@
user.log_message("linked [src] for [new_connection].", LOG_GAME)
return TRUE
///removes old_connection from src's links list AND vice versa. also updates links_by_telecomms_type
/// Removes old_connection from src's links list AND vice versa. Also updates `links_by_telecomms_type`.
/obj/machinery/telecomms/proc/remove_link(obj/machinery/telecomms/old_connection, mob/user)
if(!istype(old_connection) || old_connection == src)
return FALSE
@@ -198,6 +196,11 @@
return TRUE
/**
* Wrapper for adding additional options to a machine's interface.
*
* Returns a list, or `null` if it wasn't implemented by the machine.
*/
/obj/machinery/telecomms/proc/add_option()
return
@@ -214,7 +217,14 @@
data["receiving"] = receiving
return data
/**
* Wrapper for adding another time of action for `ui_act()`, rather than
* having you override `ui_act` yourself.
*
* Returns `TRUE` if the action was handled, nothing if not.
*/
/obj/machinery/telecomms/proc/add_act(action, params)
return
/obj/machinery/telecomms/relay/add_act(action, params)
switch(action)
@@ -236,20 +246,19 @@
else
change_frequency = 0
// Returns a multitool from a user depending on their mobtype.
/// Returns a multitool from a user depending on their mobtype.
/obj/machinery/telecomms/proc/get_multitool(mob/user)
var/obj/item/multitool/P = null
var/obj/item/multitool/multitool = null
// Let's double check
if(!issilicon(user) && istype(user.get_active_held_item(), /obj/item/multitool))
P = user.get_active_held_item()
multitool = user.get_active_held_item()
else if(isAI(user))
var/mob/living/silicon/ai/U = user
P = U.aiMulti
multitool = U.aiMulti
else if(iscyborg(user) && in_range(user, src))
if(istype(user.get_active_held_item(), /obj/item/multitool))
P = user.get_active_held_item()
return P
multitool = user.get_active_held_item()
return multitool
/obj/machinery/telecomms/proc/canAccess(mob/user)
if(issilicon(user) || in_range(user, src))
@@ -1,8 +1,7 @@
/*
Basically just an empty shell for receiving and broadcasting radio messages. Not
very flexible, but it gets the job done.
*/
/**
* Basically just an empty shell for receiving and broadcasting radio messages. Not
* very flexible, but it gets the job done.
*/
/obj/machinery/telecomms/allinone
name = "telecommunications mainframe"
icon_state = "comm_server"
@@ -41,6 +40,6 @@
sleep(signal.data["slow"]) // simulate the network lag if necessary
signal.broadcast()
/obj/machinery/telecomms/allinone/attackby(obj/item/P, mob/user, params)
if(P.tool_behaviour == TOOL_MULTITOOL)
/obj/machinery/telecomms/allinone/attackby(obj/item/attacking_item, mob/user, params)
if(attacking_item.tool_behaviour == TOOL_MULTITOOL)
return attack_hand(user)
@@ -1,13 +1,14 @@
/*
The broadcaster sends processed messages to all radio devices in the game. They
do not have to be headsets; intercoms and station-bounced radios suffice.
They receive their message from a server after the message has been logged.
*/
GLOBAL_LIST_EMPTY(recentmessages) // global list of recent messages broadcasted : used to circumvent massive radio spam
GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages list is kept in sync
/// Global list of recent messages broadcasted : used to circumvent massive radio spam
GLOBAL_LIST_EMPTY(recent_messages)
/// Used to make sure restarting the recent_messages list is kept in sync.
GLOBAL_VAR_INIT(message_delay, FALSE)
/**
* The broadcaster sends processed messages to all radio devices in the game. They
* do not have to be headsets; intercoms and station-bounced radios suffice.
*
* They receive their message from a server after the message has been logged.
*/
/obj/machinery/telecomms/broadcaster
name = "subspace broadcaster"
icon_state = "broadcaster"
@@ -18,15 +19,17 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages
circuit = /obj/item/circuitboard/machine/telecomms/broadcaster
/obj/machinery/telecomms/broadcaster/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
// Don't broadcast rejected signals
if(!istype(signal))
return
// Don't broadcast rejected signals
if(signal.data["reject"])
return
if(!signal.data["message"])
return
var/signal_message = "[signal.frequency]:[signal.data["message"]]:[signal.data["name"]]"
if(signal_message in GLOB.recentmessages)
if(signal_message in GLOB.recent_messages)
return
// Prevents massive radio spam
@@ -35,11 +38,11 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages
if(original && ("compression" in signal.data))
original.data["compression"] = signal.data["compression"]
var/turf/T = get_turf(src)
if (T)
signal.levels |= SSmapping.get_connected_levels(T)
var/turf/current_turf = get_turf(src)
if (current_turf)
signal.levels |= SSmapping.get_connected_levels(current_turf)
GLOB.recentmessages.Add(signal_message)
GLOB.recent_messages.Add(signal_message)
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
@@ -55,29 +58,31 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages
use_power(idle_power_usage)
/**
* Simply resets the message delay and the recent messages list, to ensure that
* recent messages can be sent again. Is called on a one second timer after a
* delay is set, from `/obj/machinery/telecomms/broadcaster/receive_information()`
*/
/proc/end_message_delay()
GLOB.message_delay = FALSE
GLOB.recentmessages = list()
GLOB.recent_messages = list()
/obj/machinery/telecomms/broadcaster/Destroy()
// In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore.
if(GLOB.message_delay)
GLOB.message_delay = 0
GLOB.message_delay = FALSE
return ..()
//Preset Broadcasters
// Preset Broadcasters
//--PRESET LEFT--//
/obj/machinery/telecomms/broadcaster/preset_left
id = "Broadcaster A"
network = "tcommsat"
autolinkers = list("broadcasterA")
//--PRESET RIGHT--//
/obj/machinery/telecomms/broadcaster/preset_right
id = "Broadcaster B"
network = "tcommsat"
+16 -12
View File
@@ -1,13 +1,13 @@
/*
The bus mainframe idles and waits for hubs to relay them signals. They act
as junctions for the network.
They transfer uncompressed subspace packets to processor units, and then take
the processed packet to a server for logging.
Link to a subspace hub if it can't send to a server.
*/
/**
* The bus mainframe idles and waits for hubs to relay them signals. They act
* as junctions for the network.
*
* They transfer uncompressed subspace packets to processor units, and then take
* the processed packet to a server for logging.
*
* Can be linked to a telecommunications hub or a broadcaster in the absence
* of a server, at the cost of some added latency.
*/
/obj/machinery/telecomms/bus
name = "bus mainframe"
icon_state = "bus"
@@ -17,7 +17,9 @@
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01
netspeed = 40
circuit = /obj/item/circuitboard/machine/telecomms/bus
var/change_frequency = 0
/// The frequency this bus will use to override the received signal's frequency,
/// if not `NONE`.
var/change_frequency = NONE
/obj/machinery/telecomms/bus/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
if(!istype(signal) || !is_freq_listening(signal))
@@ -47,7 +49,7 @@
use_power(idle_power_usage)
//Preset Buses
// Preset Buses
/obj/machinery/telecomms/bus/preset_one
id = "Bus 1"
@@ -75,6 +77,8 @@
/obj/machinery/telecomms/bus/preset_four/Initialize(mapload)
. = ..()
// We want to include every freely-available frequency on this one, so they
// get processed quickly when used on-station.
for(var/i = MIN_FREQ, i <= MAX_FREQ, i += 2)
freq_listening |= i
+32 -14
View File
@@ -1,13 +1,12 @@
/*
The HUB idles until it receives information. It then passes on that information
depending on where it came from.
This is the heart of the Telecommunications Network, sending information where it
is needed. It mainly receives information from long-distance Relays and then sends
that information to be processed. Afterwards it gets the uncompressed information
from Servers/Buses and sends that back to the relay, to then be broadcasted.
*/
/**
* The HUB idles until it receives information. It then passes on that information
* depending on where it came from.
*
* This is the heart of the Telecommunications Network, sending information where it
* is needed. It mainly receives information from long-distance Relays and then sends
* that information to be processed. Afterwards it gets the uncompressed information
* from Servers/Buses and sends that back to the relay, to then be broadcasted.
*/
/obj/machinery/telecomms/hub
name = "telecommunication hub"
icon_state = "hub"
@@ -53,12 +52,31 @@
QDEL_NULL(soundloop)
return ..()
//Preset HUB
// Preset HUB
/obj/machinery/telecomms/hub/preset
id = "Hub"
network = "tcommsat"
autolinkers = list("hub", "relay", "s_relay", "m_relay", "r_relay", "h_relay", "science", "medical",
"supply", "service", "common", "command", "engineering", "security",
"receiverA", "receiverB", "broadcasterA", "broadcasterB", "autorelay", "messaging")
autolinkers = list(
"hub",
"relay",
"s_relay",
"m_relay",
"r_relay",
"h_relay",
"science",
"medical",
"supply",
"service",
"common",
"command",
"engineering",
"security",
"receiverA",
"receiverB",
"broadcasterA",
"broadcasterB",
"autorelay",
"messaging",
)
@@ -1,17 +1,12 @@
/*
The equivalent of the server, for PDA and request console messages.
Without it, PDA and request console messages cannot be transmitted.
PDAs require the rest of the telecomms setup, but request consoles only
require the message server.
*/
// A decorational representation of SSblackbox, usually placed alongside the message server. Also contains a traitor theft item.
/obj/machinery/blackbox_recorder
name = "Blackbox Recorder"
icon = 'icons/obj/machines/telecomms.dmi'
icon_state = "blackbox"
name = "Blackbox Recorder"
density = TRUE
armor_type = /datum/armor/machinery_blackbox_recorder
/// The object that's stored in the machine, which is to say, the blackbox itself.
/// When it hasn't already been stolen, of course.
var/obj/item/stored
/datum/armor/machinery_blackbox_recorder
@@ -39,15 +34,15 @@
to_chat(user, span_warning("It seems that the blackbox is missing..."))
return
/obj/machinery/blackbox_recorder/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/blackbox))
if(HAS_TRAIT(I, TRAIT_NODROP) || !user.transferItemToLoc(I, src))
to_chat(user, span_warning("[I] is stuck to your hand!"))
/obj/machinery/blackbox_recorder/attackby(obj/item/attacking_item, mob/living/user, params)
if(istype(attacking_item, /obj/item/blackbox))
if(HAS_TRAIT(attacking_item, TRAIT_NODROP) || !user.transferItemToLoc(attacking_item, src))
to_chat(user, span_warning("[attacking_item] is stuck to your hand!"))
return
user.visible_message(span_notice("[user] clicks [I] into [src]!"), \
user.visible_message(span_notice("[user] clicks [attacking_item] into [src]!"), \
span_notice("You press the device into [src], and it clicks into place. The tapes begin spinning again."))
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
stored = I
stored = attacking_item
update_appearance()
return
return ..()
@@ -73,26 +68,41 @@
w_class = WEIGHT_CLASS_BULKY
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
#define MESSAGE_SERVER_FUNCTIONING_MESSAGE "This is an automated message. The messaging system is functioning correctly."
// The message server itself.
/**
* The equivalent of the server, for PDA and request console messages.
* Without it, PDA and request console messages cannot be transmitted.
* PDAs require the rest of the telecomms setup, but request consoles only
* require the message server.
*/
/obj/machinery/telecomms/message_server
icon_state = "message_server"
name = "Messaging Server"
desc = "A machine that processes and routes PDA and request console messages."
icon_state = "message_server"
telecomms_type = /obj/machinery/telecomms/message_server
density = TRUE
circuit = /obj/item/circuitboard/machine/telecomms/message_server
/// A list of all the PDA messages that were intercepted and processed by
/// this messaging server.
var/list/datum/data_tablet_msg/pda_msgs = list()
/// A list of all the Request Console messages that were intercepted and
/// processed by this messaging server.
var/list/datum/data_rc_msg/rc_msgs = list()
/// The password of this messaging server.
var/decryptkey = "password"
var/calibrating = 15 MINUTES //Init reads this and adds world.time, then becomes 0 when that time has passed and the machine works
/// Init reads this and adds world.time, then becomes 0 when that time has
/// passed and the machine works.
/// Basically, if it's not 0, it's calibrating and therefore non-functional.
var/calibrating = 15 MINUTES
#define MESSAGE_SERVER_FUNCTIONING_MESSAGE "This is an automated message. The messaging system is functioning correctly."
/obj/machinery/telecomms/message_server/Initialize(mapload)
. = ..()
if (!decryptkey)
decryptkey = GenerateKey()
decryptkey = generate_key()
if (calibrating)
calibrating += world.time
@@ -112,12 +122,16 @@
if(calibrating)
. += span_warning("It's still calibrating.")
/obj/machinery/telecomms/message_server/proc/GenerateKey()
var/newKey
newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le")
newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai")
newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
return newKey
/**
* Handles generating a key for the message server, returning it. Doesn't assign
* it in this proc, you have to do so yourself.
*/
/obj/machinery/telecomms/message_server/proc/generate_key()
var/generated_key
generated_key += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le")
generated_key += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai")
generated_key += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
return generated_key
/obj/machinery/telecomms/message_server/process()
. = ..()
@@ -125,6 +139,8 @@
calibrating = 0
pda_msgs += new /datum/data_tablet_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE)
#undef MESSAGE_SERVER_FUNCTIONING_MESSAGE
/obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/messaging/signal, obj/machinery/telecomms/machine_from)
// can't log non-message signals
if(!istype(signal) || !signal.data["message"] || !on || calibrating)
@@ -136,8 +152,8 @@
var/datum/data_tablet_msg/log_message = new(PDAsignal.format_target(), PDAsignal.format_sender(), PDAsignal.format_message(), PDAsignal.format_photo_path())
pda_msgs += log_message
else if(istype(signal, /datum/signal/subspace/messaging/rc))
var/datum/data_rc_msg/msg = new(signal.data["rec_dpt"], signal.data["send_dpt"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"])
if(signal.data["send_dpt"]) // don't log messages not from a department but allow them to work
var/datum/data_rc_msg/msg = new(signal.data["receiving_department"], signal.data["sender_department"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"])
if(signal.data["sender_department"]) // don't log messages not from a department but allow them to work
rc_msgs += msg
signal.data["reject"] = FALSE
@@ -151,6 +167,14 @@
if(calibrating)
. += "message_server_calibrate"
// Preset messaging server
/obj/machinery/telecomms/message_server/preset
id = "Messaging Server"
network = "tcommsat"
autolinkers = list("messaging")
decryptkey = null //random
calibrating = 0
// Root messaging signal datum
/datum/signal/subspace/messaging
@@ -160,8 +184,8 @@
/datum/signal/subspace/messaging/New(init_source, init_data)
source = init_source
data = init_data
var/turf/T = get_turf(source)
levels = SSmapping.get_connected_levels(T)
var/turf/origin_turf = get_turf(source)
levels = SSmapping.get_connected_levels(origin_turf)
if(!("reject" in data))
data["reject"] = TRUE
@@ -172,20 +196,26 @@
return copy
// Tablet message signal datum
/// Returns a string representing the target of this message, formatted properly.
/datum/signal/subspace/messaging/tablet_message/proc/format_target()
if (data["everyone"])
return "Everyone"
var/datum/computer_file/program/messenger/target_app = data["targets"][1]
var/obj/item/modular_computer/target = target_app.computer
return "[target.saved_identification] ([target.saved_job])"
return STRINGIFY_PDA_TARGET(target.saved_identification, target.saved_job)
/// Returns a string representing the sender of this message, formatted properly.
/datum/signal/subspace/messaging/tablet_message/proc/format_sender()
var/display_name = get_messenger_name(locate(data["ref"]))
return display_name ? display_name : STRINGIFY_PDA_TARGET(data["fakename"], data["fakejob"])
/// Returns the formatted message contained in this message. Use this to apply
/// any processing to it if it needs to be formatted in a specific way.
/datum/signal/subspace/messaging/tablet_message/proc/format_message()
return data["message"]
/// Returns the formatted photo path contained in this message, if there's one.
/datum/signal/subspace/messaging/tablet_message/proc/format_photo_path()
return data["photo"]
@@ -201,13 +231,19 @@
if(ckey(console.department) == recipient_department || (data["ore_update"] && console.receive_ore_updates))
console.create_message(data)
// Log datums stored by the message server.
/// Log datums stored by the message server.
/datum/data_tablet_msg
/// Who sent the message.
var/sender = "Unspecified"
/// Who was targeted by the message.
var/recipient = "Unspecified"
var/message = "Blank" // transferred message
var/picture_asset_key // attached photo path
var/automated = FALSE // automated message
/// The transfered message.
var/message = "Blank"
/// The attached photo path, if any.
var/picture_asset_key
/// Whether or not it's an automated message. Defaults to `FALSE`.
var/automated = FALSE
/datum/data_tablet_msg/New(param_rec, param_sender, param_message, param_photo)
if(param_rec)
@@ -219,19 +255,32 @@
if(param_photo)
picture_asset_key = param_photo
#define REQUEST_PRIORITY_NORMAL "Normal"
#define REQUEST_PRIORITY_HIGH "High"
#define REQUEST_PRIORITY_EXTREME "Extreme"
#define REQUEST_PRIORITY_UNDETERMINED "Undetermined"
/datum/data_rc_msg
var/rec_dpt = "Unspecified" // receiving department
var/send_dpt = "Unspecified" // sending department
/// The department that sent the request.
var/sender_department = "Unspecified"
/// The department that was targeted by the request.
var/receiving_department = "Unspecified"
/// The message of the request.
var/message = "Blank"
/// The stamp that authenticated this message, if any.
var/stamp = "Unstamped"
/// The ID that authenticated this message, if any.
var/id_auth = "Unauthenticated"
var/priority = "Normal"
/// The priority of this request.
var/priority = REQUEST_PRIORITY_NORMAL
/datum/data_rc_msg/New(param_rec, param_sender, param_message, param_stamp, param_id_auth, param_priority)
if(param_rec)
rec_dpt = param_rec
receiving_department = param_rec
if(param_sender)
send_dpt = param_sender
sender_department = param_sender
if(param_message)
message = param_message
if(param_stamp)
@@ -241,19 +290,15 @@
if(param_priority)
switch(param_priority)
if(REQ_NORMAL_MESSAGE_PRIORITY)
priority = "Normal"
priority = REQUEST_PRIORITY_NORMAL
if(REQ_HIGH_MESSAGE_PRIORITY)
priority = "High"
priority = REQUEST_PRIORITY_HIGH
if(REQ_EXTREME_MESSAGE_PRIORITY)
priority = "Extreme"
priority = REQUEST_PRIORITY_EXTREME
else
priority = "Undetermined"
priority = REQUEST_PRIORITY_UNDETERMINED
#undef MESSAGE_SERVER_FUNCTIONING_MESSAGE
/obj/machinery/telecomms/message_server/preset
id = "Messaging Server"
network = "tcommsat"
autolinkers = list("messaging")
decryptkey = null //random
calibrating = 0
#undef REQUEST_PRIORITY_NORMAL
#undef REQUEST_PRIORITY_HIGH
#undef REQUEST_PRIORITY_EXTREME
#undef REQUEST_PRIORITY_UNDETERMINED
@@ -1,11 +1,10 @@
/*
The processor is a very simple machine that decompresses subspace signals and
transfers them back to the original bus. It is essential in producing audible
data.
Link to servers if bus is not present
*/
/**
* The processor is a very simple machine that decompresses subspace signals and
* transfers them back to the original bus. It is essential in producing audible
* data.
*
* They'll link to servers if bus is not present, with some delay added to it.
*/
/obj/machinery/telecomms/processor
name = "processor unit"
icon_state = "processor"
@@ -14,16 +13,22 @@
density = TRUE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01
circuit = /obj/item/circuitboard/machine/telecomms/processor
var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals
/// Whether this processor is currently compressing the data,
/// or actually decompressing it. Defaults to `FALSE`.
var/compressing = FALSE
#define COMPRESSION_AMOUNT_COMPRESSING 100
#define COMPRESSION_AMOUNT_DECOMPRESSING 0
/obj/machinery/telecomms/processor/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
if(!is_freq_listening(signal))
return
if (!process_mode)
signal.data["compression"] = 100 // even more compressed signal
else if (signal.data["compression"])
signal.data["compression"] = 0 // uncompress subspace signal
if(compressing)
signal.data["compression"] = COMPRESSION_AMOUNT_COMPRESSING // We compress the signal even further.
// Otherwise we just fully decompress it if it was compressed to begin with.
else if(signal.data["compression"])
signal.data["compression"] = COMPRESSION_AMOUNT_DECOMPRESSING
if(istype(machine_from, /obj/machinery/telecomms/bus))
relay_direct_information(signal, machine_from) // send the signal back to the machine
@@ -31,7 +36,10 @@
signal.data["slow"] += rand(5, 10) // slow the signal down
relay_information(signal, signal.server_type)
//Preset Processors
#undef COMPRESSION_AMOUNT_COMPRESSING
#undef COMPRESSION_AMOUNT_DECOMPRESSING
// Preset Processors
/obj/machinery/telecomms/processor/preset_one
id = "Processor 1"
@@ -1,11 +1,10 @@
/*
The receiver idles and receives messages from subspace-compatible radio equipment;
primarily headsets. Then they just relay this information to all linked devices,
which would probably be network hubs.
Link to Processor Units in case receiver can't send to bus units.
*/
/**
* The receiver idles and receives messages from subspace-compatible radio equipment,
* primarily headsets. Then they just relay this information to all linked devices,
* which would usually be through the telecommunications hub.
*
* Link to Processor Units in case receiver can't send to a telecommunication hub.
*/
/obj/machinery/telecomms/receiver
name = "subspace receiver"
icon_state = "broadcast receiver"
@@ -27,21 +26,27 @@
use_power(idle_power_usage)
/**
* Checks whether the signal can be received by this receiver or not, based on
* if it's in the signal's `levels`, or if there's a liked hub with a linked
* relay that can receive the signal for it.
*
* Returns `TRUE` if it can receive the signal, `FALSE` if not.
*/
/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/subspace/signal)
if (z in signal.levels)
return TRUE
for(var/obj/machinery/telecomms/hub/H in links)
for(var/obj/machinery/telecomms/relay/R in H.links)
if(R.can_receive(signal) && (R.z in signal.levels))
for(var/obj/machinery/telecomms/hub/linked_hub in links)
for(var/obj/machinery/telecomms/relay/linked_relay in linked_hub.links)
if(linked_relay.can_receive(signal) && (linked_relay.z in signal.levels))
return TRUE
return FALSE
//Preset Receivers
// Preset Receivers
//--PRESET LEFT--//
/obj/machinery/telecomms/receiver/preset_left
id = "Receiver A"
network = "tcommsat"
@@ -50,16 +55,16 @@
//--PRESET RIGHT--//
/obj/machinery/telecomms/receiver/preset_right
id = "Receiver B"
network = "tcommsat"
autolinkers = list("receiverB") // link to relay
freq_listening = list(FREQ_COMMAND, FREQ_ENGINEERING, FREQ_SECURITY)
//Common and other radio frequencies for people to freely use
/obj/machinery/telecomms/receiver/preset_right/Initialize(mapload)
. = ..()
// Also add common and other freely-available radio frequencies for people
// to have access to.
for(var/i = MIN_FREQ, i <= MAX_FREQ, i += 2)
freq_listening |= i
+38 -20
View File
@@ -1,11 +1,11 @@
/*
The relay idles until it receives information. It then passes on that information
depending on where it came from.
The relay is needed in order to send information pass Z levels. It must be linked
with a HUB, the only other machine that can send/receive pass Z levels.
*/
/**
* The relay idles until it receives information. It then passes on that information
* depending on where it came from.
*
* The relay is needed in order to send information to different Z levels. It
* must be linked with a hub, the only other machine that can send to/receive
* from other Z levels.
*/
/obj/machinery/telecomms/relay
name = "telecommunication relay"
icon_state = "relay"
@@ -14,10 +14,12 @@
density = TRUE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01
netspeed = 5
long_range_link = 1
long_range_link = TRUE
circuit = /obj/item/circuitboard/machine/telecomms/relay
var/broadcasting = 1
var/receiving = 1
/// Can this relay broadcast signals to other Z levels?
var/broadcasting = TRUE
/// Can this relay receive signals from other Z levels?
var/receiving = TRUE
/obj/machinery/telecomms/relay/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
// Add our level and send it back
@@ -25,33 +27,49 @@
if(can_send(signal) && relay_turf)
// Relays send signals to all ZTRAIT_STATION z-levels
if(SSmapping.level_trait(relay_turf.z, ZTRAIT_STATION))
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
signal.levels |= SSmapping.get_connected_levels(z)
for(var/z_level in SSmapping.levels_by_trait(ZTRAIT_STATION))
signal.levels |= SSmapping.get_connected_levels(z_level)
else
signal.levels |= SSmapping.get_connected_levels(relay_turf)
use_power(idle_power_usage)
/// Checks to see if it can send/receive.
/obj/machinery/telecomms/relay/proc/can(datum/signal/signal)
/**
* Checks to see if the relay can send/receive the signal, by checking if it's
* on, and if it's listening to the frequency of the signal.
*
* Returns `TRUE` if it can listen to the signal, `FALSE` if not.
*/
/obj/machinery/telecomms/relay/proc/can_listen_to_signal(datum/signal/signal)
if(!on)
return FALSE
if(!is_freq_listening(signal))
return FALSE
return TRUE
/**
* Checks to see if the relay can send this signal, which requires it to have
* `broadcasting` set to `TRUE`.
*
* Returns `TRUE` if it can send the signal, `FALSE` if not.
*/
/obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal)
if(!can(signal))
if(!can_listen_to_signal(signal))
return FALSE
return broadcasting
/**
* Checks to see if the relay can receive this signal, which requires it to have
* `receiving` set to `TRUE`.
*
* Returns `TRUE` if it can receive the signal, `FALSE` if not.
*/
/obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal)
if(!can(signal))
if(!can_listen_to_signal(signal))
return FALSE
return receiving
//Preset Relay
// Preset Relays
/obj/machinery/telecomms/relay/preset
network = "tcommsat"
@@ -78,7 +96,7 @@
toggled = FALSE
autolinkers = list("r_relay")
//Generic preset relay
// Generic preset relay
/obj/machinery/telecomms/relay/preset/auto
hide = TRUE
autolinkers = list("autorelay")
@@ -1,10 +1,11 @@
/*
The server logs all traffic and signal data. Once it records the signal, it sends
it to the subspace broadcaster.
Store a maximum of 100 logs and then deletes them.
*/
#define MAX_LOG_ENTRIES 400
/**
* The server logs all traffic and signal data. Once it records the signal, it
* sends it to the subspace broadcaster.
*
* Store a maximum of `MAX_LOG_ENTRIES` (400) log entries and then deletes them.
*/
/obj/machinery/telecomms/server
name = "telecommunication server"
icon_state = "comm_server"
@@ -13,8 +14,13 @@
density = TRUE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01
circuit = /obj/item/circuitboard/machine/telecomms/server
/// A list of previous entries on the network. It will not exceed
/// `MAX_LOG_ENTRIES` entries in length, flushing the oldest entries
/// automatically.
var/list/log_entries = list()
var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes)
/// Total trafic, which is increased every time a signal is increased and
/// the current traffic is higher than 0. See `traffic` for more info.
var/total_traffic = 0
/obj/machinery/telecomms/server/receive_information(datum/signal/subspace/vocal/signal, obj/machinery/telecomms/machine_from)
// can't log non-vocal signals
@@ -22,10 +28,10 @@
return
if(traffic > 0)
totaltraffic += traffic // add current traffic to total traffic
total_traffic += traffic // add current traffic to total traffic
// Delete particularly old logs
if (log_entries.len >= 400)
if (log_entries.len >= MAX_LOG_ENTRIES)
log_entries.Cut(1, 2)
// Don't create a log if the frequency is banned from being logged
@@ -39,7 +45,7 @@
// If the signal is still compressed, make the log entry gibberish
var/compression = signal.data["compression"]
if(compression > 0)
if(compression > NONE)
log.input_type = "Corrupt File"
var/replace_characters = compression >= 20 ? TRUE : FALSE
log.parameters["name"] = Gibberish(signal.data["name"], replace_characters)
@@ -47,7 +53,7 @@
log.parameters["message"] = Gibberish(signal.data["message"], replace_characters)
// Give the log a name and store it
var/identifier = num2text( rand(-1000,1000) + world.time )
var/identifier = num2text(rand(-1000, 1000) + world.time)
log.name = "data packet ([md5(identifier)])"
log_entries.Add(log)
@@ -57,11 +63,16 @@
use_power(idle_power_usage)
// Simple log entry datum
#undef MAX_LOG_ENTRIES
/// Simple log entry datum for the telecommunication server
/datum/comm_log_entry
/// Type of entry.
var/input_type = "Speech File"
/// Name of the entry.
var/name = "data packet (#)"
var/parameters = list() // copied from signal.data above
/// Parameters extracted from the signal.
var/parameters = list()
// Preset Servers
@@ -98,9 +109,9 @@
freq_listening = list()
autolinkers = list("common")
//Common and other radio frequencies for people to freely use
/obj/machinery/telecomms/server/presets/common/Initialize(mapload)
. = ..()
// Common and other radio frequencies for people to freely use
for(var/i = MIN_FREQ, i <= MAX_FREQ, i += 2)
freq_listening |= i
@@ -1,19 +1,11 @@
/*
Hello, friends, this is Doohl from sexylands. You may be wondering what this
monstrous code file is. Sit down, boys and girls, while I tell you the tale.
The telecom machines were designed to be compatible with any radio
signals, provided they use subspace transmission. Currently they are only used for
headsets, but they can eventually be outfitted for real COMPUTER networks. This
is just a skeleton, ladies and gentlemen.
Look at radio.dm for the prequel to this code.
*/
/// A list of all of the `/obj/machinery/telecomms` (and subtypes) machines
/// that exist in the world currently.
GLOBAL_LIST_EMPTY(telecomms_list)
/**
* The basic telecomms machinery type, implementing all of the logic that's
* shared between all of the telecomms machinery.
*/
/obj/machinery/telecomms
icon = 'icons/obj/machines/telecomms.dmi'
critical_machine = TRUE
@@ -40,15 +32,16 @@ GLOBAL_LIST_EMPTY(telecomms_list)
// list of frequencies to tune into: if none, will listen to all
var/list/freq_listening = list()
/// Is it actually active or not?
var/on = TRUE
/// Is it toggled on
/// Is it toggled on, so is it /meant/ to be active?
var/toggled = TRUE
/// Can you link it across Z levels or on the otherside of the map? (Relay & Hub)
var/long_range_link = FALSE
/// Is it a hidden machine?
var/hide = FALSE
///Looping sounds for any servers
/// Looping sounds for any servers
var/datum/looping_sound/server/soundloop
/// relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending
@@ -90,16 +83,20 @@ GLOBAL_LIST_EMPTY(telecomms_list)
return send_count
/// Sends a signal directly to a machine.
/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine)
// send signal directly to a machine
machine.receive_information(signal, src)
///receive information from linked machinery
/// Receive information from linked machinery
/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
return
/**
* Checks whether the machinery is listening to that signal.
*
* Returns `TRUE` if found, `FALSE` if not.
*/
/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal)
// return TRUE if found, FALSE if not found
return signal && (!length(freq_listening) || (signal.frequency in freq_listening))
/obj/machinery/telecomms/Initialize(mapload)
@@ -122,17 +119,17 @@ GLOBAL_LIST_EMPTY(telecomms_list)
links = list()
return ..()
/// Used in auto linking
/obj/machinery/telecomms/proc/add_automatic_link(obj/machinery/telecomms/T)
/// Handles the automatic linking of another machine to this one.
/obj/machinery/telecomms/proc/add_automatic_link(obj/machinery/telecomms/machine_to_link)
var/turf/position = get_turf(src)
var/turf/T_position = get_turf(T)
if((position.z != T_position.z) && !(long_range_link && T.long_range_link))
var/turf/T_position = get_turf(machine_to_link)
if((position.z != T_position.z) && !(long_range_link && machine_to_link.long_range_link))
return
if(src == T)
if(src == machine_to_link)
return
for(var/autolinker_id in autolinkers)
if(autolinker_id in T.autolinkers)
add_new_link(T)
if(autolinker_id in machine_to_link.autolinkers)
add_new_link(machine_to_link)
return
/obj/machinery/telecomms/update_icon_state()
@@ -143,6 +140,11 @@ GLOBAL_LIST_EMPTY(telecomms_list)
update_appearance()
return ..()
/**
* Handles updating the power state of the machine, modifying its `on`
* variable based on if it's `toggled` and if it's either broken, has no power
* or it's EMP'd. Handles updating appearance based on that power change.
*/
/obj/machinery/telecomms/proc/update_power()
var/old_on = on
if(toggled)
@@ -167,8 +169,9 @@ GLOBAL_LIST_EMPTY(telecomms_list)
return
if(prob(100/severity) && !(machine_stat & EMPED))
set_machine_stat(machine_stat | EMPED)
var/duration = (300 * 10)/severity
addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 20, duration + 20))
var/duration = (300 SECONDS)/severity
addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 2 SECONDS, duration + 2 SECONDS))
/// Handles the machine stopping being affected by an EMP.
/obj/machinery/telecomms/proc/de_emp()
set_machine_stat(machine_stat & ~EMPED)
@@ -28,7 +28,7 @@ type Request = {
ref: string;
message: string;
stamp: string;
send_dpt: string;
sender_department: string;
id_auth: string;
};
@@ -75,7 +75,7 @@ const RequestLogsScreen = (props, context) => {
</Table.Cell>
<Table.Cell>{request.message}</Table.Cell>
<Table.Cell>{request.stamp}</Table.Cell>
<Table.Cell>{request.send_dpt}</Table.Cell>
<Table.Cell>{request.sender_department}</Table.Cell>
<Table.Cell>{request.id_auth}</Table.Cell>
</Table.Row>
))}