From c16501aef0edb2a90aa0eb815b64ac3829a80df7 Mon Sep 17 00:00:00 2001 From: Flleeppyy Date: Sun, 24 May 2026 04:51:22 -0700 Subject: [PATCH 1/4] holy fuck our radio system is so ASSSSS --- cev_eris.dme | 1 + code/__DEFINES/radio.dm | 135 ++++++++ code/__HELPERS/unsorted.dm | 2 +- code/controllers/communications.dm | 298 +++++++----------- code/controllers/subsystems/blackbox.dm | 30 +- code/datums/uplink/uplink_sources.dm | 6 +- code/datums/weakref.dm | 33 +- code/defines/procs/radio.dm | 4 +- code/game/antagonist/antagonist_equip.dm | 4 +- code/game/machinery/bots/mulebot.dm | 2 +- code/game/machinery/door_control.dm | 4 +- code/game/machinery/doors/blast_door.dm | 6 +- code/game/machinery/telecomms/broadcaster.dm | 92 ++++-- code/game/machinery/telecomms/presets.dm | 44 +-- .../objects/items/devices/radio/headset.dm | 4 +- .../objects/items/devices/radio/intercom.dm | 16 +- .../game/objects/items/devices/radio/radio.dm | 58 ++-- code/modules/admin/verbs/diagnostics.dm | 18 +- code/modules/assembly/signaler.dm | 14 +- code/modules/mob/living/bot/secbot.dm | 2 +- code/modules/mob/living/silicon/pai/pai.dm | 2 - .../mob/living/simple_animal/parrot.dm | 2 +- .../file_system/programs/generic/signaller.dm | 4 +- .../hardware/network_card.dm | 2 +- tgui/packages/tgui-say/TguiSay.tsx | 4 +- tgui/packages/tgui-say/constants.ts | 11 +- tgui/packages/tgui-say/helpers.ts | 7 +- tgui/packages/tgui-say/styles/colors.scss | 7 +- 28 files changed, 473 insertions(+), 339 deletions(-) create mode 100644 code/__DEFINES/radio.dm diff --git a/cev_eris.dme b/cev_eris.dme index 4de71c54ac1..cb4c48971e5 100644 --- a/cev_eris.dme +++ b/cev_eris.dme @@ -89,6 +89,7 @@ #include "code\__DEFINES\projectile_defines.dm" #include "code\__DEFINES\protect.dm" #include "code\__DEFINES\qdel.dm" +#include "code\__DEFINES\radio.dm" #include "code\__DEFINES\reagents.dm" #include "code\__DEFINES\research.dm" #include "code\__DEFINES\rust_g.dm" diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm new file mode 100644 index 00000000000..692b633d8b4 --- /dev/null +++ b/code/__DEFINES/radio.dm @@ -0,0 +1,135 @@ +/* +Frequency range: 1200 to 1600 +Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking) + +Radio: +1459 - standard radio chat +1364 - NT department +1351 - Science +1353 - Command +1355 - Medical +1357 - Engineering +1359 - Security +1341 - deathsquad +1443 - Confession Intercom +1347 - Cargo techs +1349 - Service people + +Devices: +1451 - tracking implant +1457 - RSD default +1201 - Player-build blast doors and shutters. + +On the map: +1311 for prison shuttle console (in fact, it is not used) +1435 for status displays +1437 for atmospherics/fire alerts +1438 for engine components +1439 for air pumps, air scrubbers, atmo control +1441 for atmospherics - supply tanks +1443 for atmospherics - distribution loop/mixed air tank +1445 for bot nav beacons +1447 for mulebot, secbot and ed209 control +1449 for airlock controls, electropack, magnets +1451 for toxin lab access +1453 for engineering access +1455 for AI access +1461 for circuits +*/ + +#define RADIO_CHANNEL_COMMON "Common" +#define RADIO_KEY_COMMON "h" + +#define RADIO_CHANNEL_SCIENCE "Science" +#define RADIO_KEY_SCIENCE "n" + +#define RADIO_CHANNEL_COMMAND "Command" +#define RADIO_KEY_COMMAND "c" + +#define RADIO_CHANNEL_MEDICAL "Medical" +#define RADIO_KEY_MEDICAL "m" + +#define RADIO_CHANNEL_ENGINEERING "Engineering" +#define RADIO_KEY_ENGINEERING "e" + +#define RADIO_CHANNEL_SECURITY "Security" +#define RADIO_KEY_SECURITY "s" + +#define RADIO_CHANNEL_SPEC_OPS "Special Ops" +#define RADIO_KEY_SPEC_OPS "o" // Verify key + +#define RADIO_CHANNEL_MERCENARY "Mercenary" +#define RADIO_KEY_MERCENARY "y" + +#define RADIO_CHANNEL_PIRATE "Pirate" +#define RADIO_KEY_PIRATE "x" + +#define RADIO_CHANNEL_SUPPLY "Supply" +#define RADIO_KEY_SUPPLY "u" + +#define RADIO_CHANNEL_NT_VOICE "NT Voice" +#define RADIO_KEY_NT_VOICE "t" + +#define RADIO_CHANNEL_SERVICE "Service" +#define RADIO_KEY_SERVICE "v" + +#define RADIO_CHANNEL_AI_PRIVATE "AI Private" +#define RADIO_KEY_AI_PRIVATE "p" + +#define RADIO_CHANNEL_MEDICAL_I "Medical(I)" +#define RADIO_KEY_MEDICAL_I "mi" // Verify key + +#define RADIO_CHANNEL_SECURITY_I "Security(I)" +#define RADIO_KEY_SECURITY_I "si" // Verify key + +#define MIN_FREQ 1441 +#define MAX_FREQ 1489 +#define FREQ_RADIO_LOW 1200 +#define FREQ_RADIO_HIGH 1600 + +#define FREQ_BOT 1447 +#define FREQ_COMM 1353 +#define FREQ_AI 1343 +#define FREQ_DTH 1341 +#define FREQ_SYND 1213 + +// For player built blast doors. +#define FREQ_BLAST_DOOR 1201 +#define FREQ_YARR 1220 + +// department channels +#define FREQ_COMMON 1459 +#define FREQ_NT 1364 +#define FREQ_SEC 1359 +#define FREQ_ENG 1357 +#define FREQ_MED 1355 +#define FREQ_SCI 1351 +#define FREQ_SRV 1349 +#define FREQ_SUP 1347 + +// internal department channels +#define FREQ_MED_I 1485 +#define FREQ_SEC_I 1475 + + +#define TRANSMISSION_WIRE 0 +#define TRANSMISSION_RADIO 1 + +/* filters */ +//When devices register with the radio controller, they might register under a certain filter. +//Other devices can then choose to send signals to only those devices that belong to a particular filter. +//This is done for performance, so we don't send signals to lots of machines unnecessarily. + +//This filter is special because devices belonging to default also recieve signals sent to any other filter. +#define RADIO_DEFAULT "radio_default" + +#define RADIO_TO_AIRALARM "radio_airalarm" //air alarms +#define RADIO_FROM_AIRALARM "radio_airalarm_rcvr" //devices interested in recieving signals from air alarms +#define RADIO_CHAT "radio_telecoms" +#define RADIO_ATMOSIA "radio_atmos" +#define RADIO_NAVBEACONS "radio_navbeacon" +#define RADIO_AIRLOCK "radio_airlock" +#define RADIO_SECBOT "radio_secbot" +#define RADIO_MULEBOT "radio_mulebot" +#define RADIO_MAGNETS "radio_magnet" +#define RADIO_BLASTDOORS "radio_blastdoors" diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index a0de6126b4f..3aecf68e67f 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -252,7 +252,7 @@ Turf and target are seperate in case you want to teleport some distance from a t return TRUE //Ensure the frequency is within bounds of what it should be sending/recieving at -/proc/sanitize_frequency(f, low = PUBLIC_LOW_FREQ, high = PUBLIC_HIGH_FREQ) +/proc/sanitize_frequency(f, low = MIN_FREQ, high = MAX_FREQ) f = round(f) f = max(low, f) f = min(high, f) diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm index 4f6d51ea2b5..6639f20fa14 100644 --- a/code/controllers/communications.dm +++ b/code/controllers/communications.dm @@ -61,218 +61,152 @@ */ -/* -Frequency range: 1200 to 1600 -Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking) - -Radio: -1459 - standard radio chat -1364 - NT department -1351 - Science -1353 - Command -1355 - Medical -1357 - Engineering -1359 - Security -1341 - deathsquad -1443 - Confession Intercom -1347 - Cargo techs -1349 - Service people - -Devices: -1451 - tracking implant -1457 - RSD default -1201 - Player-build blast doors and shutters. - -On the map: -1311 for prison shuttle console (in fact, it is not used) -1435 for status displays -1437 for atmospherics/fire alerts -1438 for engine components -1439 for air pumps, air scrubbers, atmo control -1441 for atmospherics - supply tanks -1443 for atmospherics - distribution loop/mixed air tank -1445 for bot nav beacons -1447 for mulebot, secbot and ed209 control -1449 for airlock controls, electropack, magnets -1451 for toxin lab access -1453 for engineering access -1455 for AI access -1461 for circuits -*/ - -var/const/RADIO_LOW_FREQ = 1200 -var/const/PUBLIC_LOW_FREQ = 1441 -var/const/PUBLIC_HIGH_FREQ = 1489 -var/const/RADIO_HIGH_FREQ = 1600 - -var/const/BOT_FREQ = 1447 -var/const/COMM_FREQ = 1353 -var/const/AI_FREQ = 1343 -var/const/DTH_FREQ = 1341 -var/const/SYND_FREQ = 1213 - -// For player built blast doors. -var/const/BLAST_DOOR_FREQ = 1201 -var/const/YARR_FREQ = 1220 - -// department channels -var/const/PUB_FREQ = 1459 -var/const/NT_FREQ = 1364 -var/const/SEC_FREQ = 1359 -var/const/ENG_FREQ = 1357 -var/const/MED_FREQ = 1355 -var/const/SCI_FREQ = 1351 -var/const/SRV_FREQ = 1349 -var/const/SUP_FREQ = 1347 - - -// internal department channels -var/const/MED_I_FREQ = 1485 -var/const/SEC_I_FREQ = 1475 - -var/list/radiochannels = list( - "Common" = PUB_FREQ, - "Science" = SCI_FREQ, - "Command" = COMM_FREQ, - "Medical" = MED_FREQ, - "Engineering" = ENG_FREQ, - "Security" = SEC_FREQ, - "Special Ops" = DTH_FREQ, - "Mercenary" = SYND_FREQ, - "Pirate" = YARR_FREQ, - "Supply" = SUP_FREQ, - "NT Voice" = NT_FREQ, - "Service" = SRV_FREQ, - "AI Private" = AI_FREQ, - "Medical(I)" = MED_I_FREQ, - "Security(I)" = SEC_I_FREQ -) +// For information on what objects or departments use what frequencies, +// see __DEFINES/radio.dm. Mappers may also select additional frequencies for +// use in maps, such as in intercoms. + +GLOBAL_LIST_INIT(radiochannels, list( + "[RADIO_CHANNEL_COMMON]" = FREQ_COMMON, + "[RADIO_CHANNEL_SCIENCE]" = FREQ_SCI, + "[RADIO_CHANNEL_COMMAND]" = FREQ_COMM, + "[RADIO_CHANNEL_MEDICAL]" = FREQ_MED, + "[RADIO_CHANNEL_ENGINEERING]" = FREQ_ENG, + "[RADIO_CHANNEL_SECURITY]" = FREQ_SEC, + "[RADIO_CHANNEL_SPEC_OPS]" = FREQ_DTH, + "[RADIO_CHANNEL_MERCENARY]" = FREQ_SYND, + "[RADIO_CHANNEL_PIRATE]" = FREQ_YARR, + "[RADIO_CHANNEL_SUPPLY]" = FREQ_SUP, + "[RADIO_CHANNEL_NT_VOICE]" = FREQ_NT, + "[RADIO_CHANNEL_SERVICE]" = FREQ_SRV, + "[RADIO_CHANNEL_AI_PRIVATE]" = FREQ_AI, + "[RADIO_CHANNEL_MEDICAL_I]" = FREQ_MED_I, + "[RADIO_CHANNEL_SECURITY_I]" = FREQ_SEC_I +)) // central command channels, i.e deathsquid -var/list/CENT_FREQS = list(DTH_FREQ) +#define CEFREQ_NTS list(FREQ_DTH) // Antag channels, i.e. Syndicate -var/list/ANTAG_FREQS = list(SYND_FREQ, YARR_FREQ) +#define ANTAG_FREQS list(FREQ_SYND, FREQ_YARR) //Department channels, arranged lexically -var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, NT_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ) - -#define TRANSMISSION_WIRE 0 -#define TRANSMISSION_RADIO 1 - -/proc/frequency_span_class(frequency) - // Antags! - if (frequency in ANTAG_FREQS) +#define DEPT_FREQS list(FREQ_AI, FREQ_COMM, FREQ_ENG, FREQ_MED, FREQ_NT, FREQ_SEC, FREQ_SCI, FREQ_SRV, FREQ_SUP) + +GLOBAL_LIST_INIT(freqtospan, list( + "[FREQ_COMM]" = "comradio", + "[FREQ_AI]" = "airadio", + "[FREQ_SEC]" = "secradio", + "[FREQ_ENG]" = "engradio", + "[FREQ_SCI]" = "sciradio", + "[FREQ_MED]" = "medradio", + "[FREQ_SUP]" = "supradio", + "[FREQ_SRV]" = "srvradio", + "[FREQ_NT]" = "ntradio" +)) + +/proc/get_radio_span(freq) + var/returntext = GLOB.freqtospan["[freq]"] + + if(freq in ANTAG_FREQS) return "syndradio" - // centcom channels - if(frequency in CENT_FREQS) + if(freq in CEFREQ_NTS) return "centradio" - // command channel - if(frequency == COMM_FREQ) - return "comradio" - // AI private channel - if(frequency == AI_FREQ) - return "airadio" - // department radio formatting (poorly optimized, ugh) - if(frequency == SEC_FREQ) - return "secradio" - if (frequency == ENG_FREQ) - return "engradio" - if(frequency == SCI_FREQ) - return "sciradio" - if(frequency == MED_FREQ) - return "medradio" - if(frequency == SUP_FREQ) // cargo - return "supradio" - if(frequency == SRV_FREQ) // service - return "srvradio" - if(frequency == NT_FREQ) - return "ntradio" - if(frequency in DEPT_FREQS) + if(freq in DEPT_FREQS) return "deptradio" + if(returntext) + return returntext return "radio" -/* filters */ -//When devices register with the radio controller, they might register under a certain filter. -//Other devices can then choose to send signals to only those devices that belong to a particular filter. -//This is done for performance, so we don't send signals to lots of machines unnecessarily. - -//This filter is special because devices belonging to default also recieve signals sent to any other filter. -var/const/RADIO_DEFAULT = "radio_default" - -var/const/RADIO_TO_AIRALARM = "radio_airalarm" //air alarms -var/const/RADIO_FROM_AIRALARM = "radio_airalarm_rcvr" //devices interested in recieving signals from air alarms -var/const/RADIO_CHAT = "radio_telecoms" -var/const/RADIO_ATMOSIA = "radio_atmos" -var/const/RADIO_NAVBEACONS = "radio_navbeacon" -var/const/RADIO_AIRLOCK = "radio_airlock" -var/const/RADIO_SECBOT = "radio_secbot" -var/const/RADIO_MULEBOT = "radio_mulebot" -var/const/RADIO_MAGNETS = "radio_magnet" -var/const/RADIO_BLASTDOORS = "radio_blastdoors" - //callback used by objects to react to incoming radio signals /obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) return null +// TODO: Make devices weakrefs /datum/radio_frequency - var/frequency as num - var/list/list/obj/devices = list() + var/frequency + /// List of filters -> list of devices + var/list/list/datum/weakref/devices = list() +/datum/radio_frequency/New(freq) + frequency = freq + +//If range > 0, only post to devices on the same z_level and within range +//Use range = -1, to restrain to the same z_level without limiting range /datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null) + // Ensure the signal's data is fully filled + signal.source = source + signal.frequency = frequency + + //Apply filter to the signal. If none supply, broadcast to every devices + //_default channel is always checked + var/list/filter_list + + if(filter) + filter_list = list(filter,"_default") + else + filter_list = devices + + //If checking range, find the source turf var/turf/start_point if(range) start_point = get_turf(source) if(!start_point) - qdel(signal) - return 0 - if (filter) - send_to_filter(source, signal, filter, start_point, range) - send_to_filter(source, signal, RADIO_DEFAULT, start_point, range) - else - //Broadcast the signal to everyone! - for (var/next_filter in devices) - send_to_filter(source, signal, next_filter, start_point, range) - -//Sends a signal to all machines belonging to a given filter. Should be called by post_signal() -/datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, filter, turf/start_point = null, range = null) - if (range && !start_point) - return - for(var/obj/device in devices[filter]) - if(device == source) - continue - if(range) - var/turf/end_point = get_turf(device) - if(!end_point) + return + + //Send the data + for(var/current_filter in filter_list) + for(var/datum/weakref/device_ref as anything in devices[current_filter]) + var/obj/device = device_ref.resolve() + if(!device) + devices[current_filter] -= device_ref continue - if(start_point.z != end_point.z || get_dist(start_point, end_point) > range) + if(device == source) continue - device.receive_signal(signal, TRANSMISSION_RADIO, frequency) - -/datum/radio_frequency/proc/add_listener(obj/device as obj, filter as text|null) + if(range) + var/turf/end_point = get_turf(device) + if(!end_point) + continue + if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range)) + continue + device.receive_signal(signal, TRANSMISSION_RADIO, frequency) + CHECK_TICK + + +// /datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, filter, turf/start_point = null, range = null) +// if (range && !start_point) +// return +// for(var/obj/device in devices[filter]) +// if(device == source) +// continue +// if(range) +// var/turf/end_point = get_turf(device) +// if(!end_point) +// continue +// if(start_point.z != end_point.z || get_dist(start_point, end_point) > range) +// continue +// device.receive_signal(signal, TRANSMISSION_RADIO, frequency) + +/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null) if (!filter) - filter = RADIO_DEFAULT - //log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]") - var/list/obj/devices_line = devices[filter] - if (!devices_line) - devices_line = new - devices[filter] = devices_line - devices_line+=device -// var/list/obj/devices_line___ = devices[filter_str] -// var/l = devices_line___.len - //log_admin("DEBUG: devices_line.len=[devices_line.len]") - //log_admin("DEBUG: devices(filter_str).len=[l]") + filter = "_default" + + var/datum/weakref/new_listener = WEAKREF(device) + if(isnull(new_listener)) + return stack_trace("null, non-datum, or qdeleted device") + var/list/devices_line = devices[filter] + if(!devices_line) + devices[filter] = devices_line = list() + devices_line += new_listener /datum/radio_frequency/proc/remove_listener(obj/device) - for (var/devices_filter in devices) + for(var/devices_filter in devices) var/list/devices_line = devices[devices_filter] - devices_line -= device - while (null in devices_line) - devices_line -= null - if (devices_line.len==0) + if(!devices_line) + devices -= devices_filter + devices_line -= WEAKREF(device) + if(!devices_line.len) devices -= devices_filter - del(devices_line) /datum/signal var/obj/source diff --git a/code/controllers/subsystems/blackbox.dm b/code/controllers/subsystems/blackbox.dm index 894a1536dd0..5d9e74c25f1 100644 --- a/code/controllers/subsystems/blackbox.dm +++ b/code/controllers/subsystems/blackbox.dm @@ -135,35 +135,35 @@ SUBSYSTEM_DEF(blackbox) if(sealed) return switch(freq) - if(COMM_FREQ) + if(FREQ_COMM) record_feedback("tally", "radio_usage", 1, "common") - if(SCI_FREQ) + if(FREQ_SCI) record_feedback("tally", "radio_usage", 1, "science") - if(COMM_FREQ) + if(FREQ_COMM) record_feedback("tally", "radio_usage", 1, "command") - if(MED_FREQ) + if(FREQ_MED) record_feedback("tally", "radio_usage", 1, "medical") - if(ENG_FREQ) + if(FREQ_ENG) record_feedback("tally", "radio_usage", 1, "engineering") - if(SEC_FREQ) + if(FREQ_SEC) record_feedback("tally", "radio_usage", 1, "security") - if(DTH_FREQ) + if(FREQ_DTH) record_feedback("tally", "radio_usage", 1, "specialops") - if(SYND_FREQ) + if(FREQ_SYND) record_feedback("tally", "radio_usage", 1, "mercenary") - if(YARR_FREQ) + if(FREQ_YARR) record_feedback("tally", "radio_usage", 1, "pirate") - if(SUP_FREQ) + if(FREQ_SUP) record_feedback("tally", "radio_usage", 1, "supply") - if(NT_FREQ) + if(FREQ_NT) record_feedback("tally", "radio_usage", 1, "ntvoice") - if(SRV_FREQ) + if(FREQ_SRV) record_feedback("tally", "radio_usage", 1, "service") - if(AI_FREQ) + if(FREQ_AI) record_feedback("tally", "radio_usage", 1, "ai private") - if(MED_I_FREQ) + if(FREQ_MED_I) record_feedback("tally", "radio_usage", 1, "medicali") - if(SEC_I_FREQ) + if(FREQ_SEC_I) record_feedback("tally", "radio_usage", 1, "securityi") else record_feedback("tally", "radio_usage", 1, "other") diff --git a/code/datums/uplink/uplink_sources.dm b/code/datums/uplink/uplink_sources.dm index 541b390304c..5dbebabe8f1 100644 --- a/code/datums/uplink/uplink_sources.dm +++ b/code/datums/uplink/uplink_sources.dm @@ -45,10 +45,10 @@ GLOBAL_LIST_INIT(default_uplink_source_priority, list( if(!R) return SETUP_FAILED - var/freq = PUBLIC_LOW_FREQ + var/freq = MIN_FREQ var/list/freqlist = list() - while (freq <= PUBLIC_HIGH_FREQ) - if (freq < 1451 || freq > PUB_FREQ) + while (freq <= MAX_FREQ) + if (freq < 1451 || freq > FREQ_COMMON) freqlist += freq freq += 2 if ((freq % 2) == 0) diff --git a/code/datums/weakref.dm b/code/datums/weakref.dm index 2b878f0943c..dedc0d8eff9 100644 --- a/code/datums/weakref.dm +++ b/code/datums/weakref.dm @@ -37,7 +37,7 @@ * * A common use case for weak references is holding onto what created itself. * For example, if a machine wanted to know what its last user was, it might - * create a `var/mob/living/last_user`. However, this is a storng reference to + * create a `var/mob/living/last_user`. However, this is a strong reference to * the mob, and thus will force a hard deletion when that mob is deleted. * It is often better in this case to instead create a weakref to the user, * meaning this type definition becomes `var/datum/weakref/last_user`. @@ -75,3 +75,34 @@ /datum/weakref/proc/resolve() var/datum/D = locate(reference) return (!QDELETED(D) && D.weak_reference == src) ? D : null + +/** + * SERIOUSLY READ THE AUTODOC COMMENT FOR THIS PROC BEFORE EVEN THINKING ABOUT USING IT + * + * Like resolve, but doesn't care if the datum is being qdeleted but hasn't been deleted yet. + * + * The return value of this proc leaves hanging references if the datum is being qdeleted but hasn't been deleted yet. + * + * Do not do anything that would create a lasting reference to the return value, such as giving it a tag, putting it on the map, + * adding it to an atom's contents or vis_contents, giving it a key (if it's a mob), attaching it to an atom (if it's an image), + * or assigning it to a datum or list referenced somewhere other than a temporary value. + * + * Unless you're resolving a weakref to a datum in a COMSIG_QDELETING signal handler registered on that very same datum, + * just use resolve instead. + */ +/datum/weakref/proc/hard_resolve() + var/datum/D = locate(reference) + return (D?.weak_reference == src) ? D : null + +/datum/weakref/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION(VV_HK_WEAKREF_RESOLVE, "Go to reference") + +/datum/weakref/vv_do_topic(list/href_list) + . = ..() + if(href_list[VV_HK_WEAKREF_RESOLVE]) + if(!check_rights(NONE)) + return + var/datum/R = resolve() + if(R) + usr.client.debug_variables(R) diff --git a/code/defines/procs/radio.dm b/code/defines/procs/radio.dm index a05234dfe02..2af1ff9c53f 100644 --- a/code/defines/procs/radio.dm +++ b/code/defines/procs/radio.dm @@ -19,8 +19,8 @@ if(display_freq in ANTAG_FREQS) freq_text = "#unkn" else - for(var/channel in radiochannels) - if(radiochannels[channel] == display_freq) + for(var/channel in GLOB.radiochannels) + if(GLOB.radiochannels[channel] == display_freq) freq_text = channel break diff --git a/code/game/antagonist/antagonist_equip.dm b/code/game/antagonist/antagonist_equip.dm index 341a74c6d46..9bcdefa28d5 100644 --- a/code/game/antagonist/antagonist_equip.dm +++ b/code/game/antagonist/antagonist_equip.dm @@ -63,9 +63,9 @@ var/obj/item/device/radio/R - if(freq == SYND_FREQ) + if(freq == FREQ_SYND) R = new/obj/item/device/radio/headset/syndicate(H) - else if(freq == YARR_FREQ) + else if(freq == FREQ_YARR) R = new/obj/item/device/radio/headset/pirates(H) else R = new/obj/item/device/radio/headset(H) diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 6e82c39455a..71c70bfdd71 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -19,7 +19,7 @@ brute_dam_coeff = 0.5 var/atom/movable/load = null // the loaded crate (usually) var/beacon_freq = 1400 - var/control_freq = BOT_FREQ + var/control_freq = FREQ_BOT suffix = "" diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index b039f128986..0cfd7564516 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -136,7 +136,7 @@ /obj/machinery/button/remote/blast_door/Initialize() . = ..() - radio_conn = SSradio.add_object(src, BLAST_DOOR_FREQ, RADIO_BLASTDOORS) + radio_conn = SSradio.add_object(src, FREQ_BLAST_DOOR, RADIO_BLASTDOORS) AddComponent(/datum/component/overlay_manager) /// Update status at initialization! @@ -151,7 +151,7 @@ /obj/machinery/button/remote/blast_door/Destroy() - SSradio.remove_object(src, BLAST_DOOR_FREQ) + SSradio.remove_object(src, FREQ_BLAST_DOOR) radio_conn = null . = ..() diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index c17ff50502f..09549b30ee9 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -50,7 +50,7 @@ /obj/machinery/door/blast/Initialize() . = ..() - radio_connection = SSradio.add_object(src , BLAST_DOOR_FREQ, RADIO_BLASTDOORS) + radio_connection = SSradio.add_object(src , FREQ_BLAST_DOOR, RADIO_BLASTDOORS) if(!electronics) electronics = new(src) if(_wifi_id) @@ -66,13 +66,13 @@ */ /obj/machinery/door/blast/Destroy() - SSradio.remove_object(src, BLAST_DOOR_FREQ) + SSradio.remove_object(src, FREQ_BLAST_DOOR) radio_connection = null return ..() /obj/machinery/door/blast/proc/broadcast_status() var/datum/signal/data_packet = new() - data_packet.frequency = BLAST_DOOR_FREQ + data_packet.frequency = FREQ_BLAST_DOOR data_packet.encryption = electronics.wifi_id data_packet.data = list() data_packet.data["message"] = density ? "DATA_DOOR_CLOSED" : "DATA_DOOR_OPENED" diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 1fa938d45ba..cd9f2d15bfb 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -231,7 +231,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(data == 1) - for(var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/intercom/R = device_ref.resolve() + if(!R) + continue if(R.receive_range(display_freq, level) > -1) radios += R @@ -239,7 +242,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else if(data == 2) - for(var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/R = device_ref.resolve() + if(!R) + continue if(istype(R, /obj/item/device/radio/headset)) continue @@ -252,7 +258,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else if(data == 3) for(var/antag_freq in ANTAG_FREQS) var/datum/radio_frequency/antag_connection = SSradio.return_frequency(antag_freq) - for(var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in antag_connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/R = device_ref.resolve() + if(!R) + continue if(R.receive_range(antag_freq, level) > -1) radios += R @@ -260,7 +269,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else - for(var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/R = device_ref.resolve() + if(!R) + continue if(R.receive_range(display_freq, level) > -1) radios += R @@ -357,7 +369,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept var/part_b_extra = "" if(data == 3) // intercepted radio message part_b_extra = " (Intercepted)" - var/part_a = "\[[freq_text]\][part_b_extra] " // goes in the actual output + var/part_a = "\[[freq_text]\][part_b_extra] " // goes in the actual output // --- Some more pre-message formatting --- var/part_b = " " // Tweaked for security headsets -- TLE @@ -380,27 +392,27 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(istype(blackbox)) switch(display_freq) - if(PUB_FREQ) + if(FREQ_COMMON) blackbox.msg_common += blackbox_msg - if(SCI_FREQ) + if(FREQ_SCI) blackbox.msg_science += blackbox_msg - if(COMM_FREQ) + if(FREQ_COMM) blackbox.msg_command += blackbox_msg - if(MED_FREQ) + if(FREQ_MED) blackbox.msg_medical += blackbox_msg - if(ENG_FREQ) + if(FREQ_ENG) blackbox.msg_engineering += blackbox_msg - if(SEC_FREQ) + if(FREQ_SEC) blackbox.msg_security += blackbox_msg - if(DTH_FREQ) + if(FREQ_DTH) blackbox.msg_deathsquad += blackbox_msg - if(SYND_FREQ) + if(FREQ_SYND) blackbox.msg_syndicate += blackbox_msg - if(SUP_FREQ) + if(FREQ_SUP) blackbox.msg_cargo += blackbox_msg - if(SRV_FREQ) + if(FREQ_SRV) blackbox.msg_service += blackbox_msg - if(NT_FREQ) + if(FREQ_NT) blackbox.msg_nt += blackbox_msg else blackbox.messages += blackbox_msg @@ -472,7 +484,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // --- Broadcast only to intercom devices --- if(data == 1) - for(var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/intercom/R = device_ref.resolve() + if(!R) + continue var/turf/position = get_turf(R) if(position && (position.z in levels)) receive |= R.send_hear(display_freq, position.z) @@ -481,7 +496,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // --- Broadcast only to intercoms and station-bounced radios --- else if(data == 2) - for(var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/R = device_ref.resolve() + if(!R) + continue if(istype(R, /obj/item/device/radio/headset)) continue @@ -495,7 +513,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else if(data == 3) for(var/freq in ANTAG_FREQS) var/datum/radio_frequency/antag_connection = SSradio.return_frequency(freq) - for(var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in antag_connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/R = device_ref.resolve() + if(!R) + continue var/turf/position = get_turf(R) if(position && (position.z in levels)) receive |= R.send_hear(freq) @@ -504,7 +525,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // --- Broadcast to ALL radio devices --- else - for(var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) + for(var/datum/weakref/device_ref in connection.devices["[RADIO_CHAT]"]) + var/obj/item/device/radio/R = device_ref.resolve() + if(!R) + continue var/turf/position = get_turf(R) if(position && (position.z in levels)) receive |= R.send_hear(display_freq) @@ -546,7 +570,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(length(heard_normal) || length(heard_garbled) || length(heard_gibberish)) /* --- Some miscellaneous variables to format the string output --- */ - var/part_a = "" // goes in the actual output + var/part_a = "" // goes in the actual output var/freq_text = get_frequency_name(display_freq) // --- Some more pre-message formatting --- @@ -564,29 +588,29 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(istype(blackbox)) switch(display_freq) - if(PUB_FREQ) + if(FREQ_COMMON) blackbox.msg_common += blackbox_msg - if(SCI_FREQ) + if(FREQ_SCI) blackbox.msg_science += blackbox_msg - if(COMM_FREQ) + if(FREQ_COMM) blackbox.msg_command += blackbox_msg - if(MED_FREQ) + if(FREQ_MED) blackbox.msg_medical += blackbox_msg - if(ENG_FREQ) + if(FREQ_ENG) blackbox.msg_engineering += blackbox_msg - if(SEC_FREQ) + if(FREQ_SEC) blackbox.msg_security += blackbox_msg - if(DTH_FREQ) + if(FREQ_DTH) blackbox.msg_deathsquad += blackbox_msg - if(SYND_FREQ) + if(FREQ_SYND) blackbox.msg_syndicate += blackbox_msg - if(YARR_FREQ) + if(FREQ_YARR) blackbox.msg_pirate += blackbox_msg - if(SUP_FREQ) + if(FREQ_SUP) blackbox.msg_cargo += blackbox_msg - if(SRV_FREQ) + if(FREQ_SRV) blackbox.msg_service += blackbox_msg - if(NT_FREQ) + if(FREQ_NT) blackbox.msg_nt += blackbox_msg else blackbox.messages += blackbox_msg @@ -648,7 +672,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept "done" = 0, "level" = pos.z // The level it is being broadcasted at. ) - signal.frequency = PUB_FREQ// Common channel + signal.frequency = FREQ_COMMON// Common channel //#### Sending the signal to all subspace receivers ####// for(var/obj/machinery/telecomms/receiver/R in telecomms_list) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index aedee3f8cff..ab9344f3882 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -64,11 +64,11 @@ id = "Receiver A" network = "eris" autolinkers = list("receiverA") // link to relay - freq_listening = list(AI_FREQ, SCI_FREQ, MED_FREQ, NT_FREQ, SUP_FREQ, SRV_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ) + freq_listening = list(FREQ_AI, FREQ_SCI, FREQ_MED, FREQ_NT, FREQ_SUP, FREQ_SRV, FREQ_COMM, FREQ_ENG, FREQ_SEC) //Common and other radio frequencies for people to freely use /obj/machinery/telecomms/receiver/preset_right/New() - for(var/i = PUBLIC_LOW_FREQ; i < PUBLIC_HIGH_FREQ; i += 2) + for(var/i = MIN_FREQ; i < MAX_FREQ; i += 2) freq_listening |= i ..() @@ -77,7 +77,7 @@ network = "eris" produces_heat = 0 autolinkers = list("receiverCent") - freq_listening = list(DTH_FREQ) + freq_listening = list(FREQ_DTH) //Buses @@ -85,18 +85,18 @@ /obj/machinery/telecomms/bus/preset_one id = "Bus 1" network = "eris" - freq_listening = list(SCI_FREQ, MED_FREQ) + freq_listening = list(FREQ_SCI, FREQ_MED) autolinkers = list("processor1", "science", "medical") /obj/machinery/telecomms/bus/preset_two id = "Bus 2" network = "eris" - freq_listening = list(SUP_FREQ, SRV_FREQ, NT_FREQ) + freq_listening = list(FREQ_SUP, FREQ_SRV, FREQ_NT) autolinkers = list("processor2", "supply", "service", "nt", "unused") /obj/machinery/telecomms/bus/preset_two/New() - for(var/i = PUBLIC_LOW_FREQ; i < PUBLIC_HIGH_FREQ; i += 2) - if(i == PUB_FREQ) + for(var/i = MIN_FREQ; i < MAX_FREQ; i += 2) + if(i == FREQ_COMMON) continue freq_listening |= i ..() @@ -104,19 +104,19 @@ /obj/machinery/telecomms/bus/preset_three id = "Bus 3" network = "eris" - freq_listening = list(SEC_FREQ, COMM_FREQ) + freq_listening = list(FREQ_SEC, FREQ_COMM) autolinkers = list("processor3", "security", "command") /obj/machinery/telecomms/bus/preset_four id = "Bus 4" network = "eris" - freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ) + freq_listening = list(FREQ_ENG, FREQ_AI, FREQ_COMMON) autolinkers = list("processor4", "engineering", "common") /obj/machinery/telecomms/bus/preset_cent id = "CentCom Bus" network = "eris" - freq_listening = list(DTH_FREQ) + freq_listening = list(FREQ_DTH) produces_heat = 0 autolinkers = list("processorCent", "centcom") @@ -156,27 +156,27 @@ /obj/machinery/telecomms/server/presets/science id = "Science Server" - freq_listening = list(SCI_FREQ) + freq_listening = list(FREQ_SCI) autolinkers = list("science") /obj/machinery/telecomms/server/presets/medical id = "Medical Server" - freq_listening = list(MED_FREQ) + freq_listening = list(FREQ_MED) autolinkers = list("medical") /obj/machinery/telecomms/server/presets/supply id = "Supply Server" - freq_listening = list(SUP_FREQ) + freq_listening = list(FREQ_SUP) autolinkers = list("supply") /obj/machinery/telecomms/server/presets/service id = "Service Server" - freq_listening = list(SRV_FREQ) + freq_listening = list(FREQ_SRV) autolinkers = list("service") /obj/machinery/telecomms/server/presets/common id = "Common Server" - freq_listening = list(PUB_FREQ, AI_FREQ) // AI Private and Common + freq_listening = list(FREQ_COMMON, FREQ_AI) // AI Private and Common autolinkers = list("common") // "Unused" channels, AKA all others. @@ -186,36 +186,36 @@ autolinkers = list("unused") /obj/machinery/telecomms/server/presets/unused/New() - for(var/i = PUBLIC_LOW_FREQ; i < PUBLIC_HIGH_FREQ; i += 2) - if(i == AI_FREQ || i == PUB_FREQ) + for(var/i = MIN_FREQ; i < MAX_FREQ; i += 2) + if(i == FREQ_AI || i == FREQ_COMMON) continue freq_listening |= i ..() /obj/machinery/telecomms/server/presets/command id = "Command Server" - freq_listening = list(COMM_FREQ) + freq_listening = list(FREQ_COMM) autolinkers = list("command") /obj/machinery/telecomms/server/presets/engineering id = "Engineering Server" - freq_listening = list(ENG_FREQ) + freq_listening = list(FREQ_ENG) autolinkers = list("engineering") /obj/machinery/telecomms/server/presets/security id = "Security Server" - freq_listening = list(SEC_FREQ) + freq_listening = list(FREQ_SEC) autolinkers = list("security") /obj/machinery/telecomms/server/presets/centcom id = "CentCom Server" - freq_listening = list(DTH_FREQ) + freq_listening = list(FREQ_DTH) produces_heat = 0 autolinkers = list("centcom") /obj/machinery/telecomms/server/presets/nt id = "NT Voice Server" - freq_listening = list(NT_FREQ) + freq_listening = list(FREQ_NT) autolinkers = list("nt") diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 78b775b23e9..7e86f457420 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -233,7 +233,7 @@ if(QUALITY_SCREW_DRIVING in I.tool_qualities) if(keyslot1 || keyslot2) for(var/ch_name in channels) - SSradio.remove_object(src, radiochannels[ch_name]) + SSradio.remove_object(src, GLOB.radiochannels[ch_name]) secure_radio_connections[ch_name] = null var/turf/T = get_turf(user) @@ -324,7 +324,7 @@ for (var/ch_name in channels) - secure_radio_connections[ch_name] = SSradio.add_object(src, radiochannels[ch_name], RADIO_CHAT) + secure_radio_connections[ch_name] = SSradio.add_object(src, GLOB.radiochannels[ch_name], RADIO_CHAT) if(setDescription) setupRadioDescription() diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 64699aac419..10d5798064d 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -22,7 +22,7 @@ /obj/item/device/radio/intercom/private name = "ship intercom (Private)" - frequency = AI_FREQ + frequency = FREQ_AI /obj/item/device/radio/intercom/department canhear_range = 5 @@ -31,11 +31,11 @@ /obj/item/device/radio/intercom/department/medbay name = "ship intercom (Medbay)" - frequency = MED_I_FREQ + frequency = FREQ_MED_I /obj/item/device/radio/intercom/department/security name = "ship intercom (Security)" - frequency = SEC_I_FREQ + frequency = FREQ_SEC_I /obj/item/device/radio/intercom/New() ..() @@ -48,21 +48,21 @@ /obj/item/device/radio/intercom/department/security/New() ..() internal_channels = list( - num2text(PUB_FREQ) = list(), - num2text(SEC_I_FREQ) = list(access_security) + num2text(FREQ_COMMON) = list(), + num2text(FREQ_SEC_I) = list(access_security) ) /obj/item/device/radio/intercom/syndicate name = "illicit intercom" desc = "Talk through this. Evilly" - frequency = SYND_FREQ + frequency = FREQ_SYND subspace_transmission = 1 syndie = 1 /obj/item/device/radio/intercom/syndicate/New() ..() - internal_channels[num2text(SYND_FREQ)] = list(access_syndicate) + internal_channels[num2text(FREQ_SYND)] = list(access_syndicate) /obj/item/device/radio/intercom/attack_ai(mob/user as mob) src.add_fingerprint(user) @@ -127,7 +127,7 @@ /obj/item/device/radio/intercom/locked/ai_private name = "\improper AI intercom" - frequency = AI_FREQ + frequency = FREQ_AI broadcasting = 1 listening = 1 diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 70fc6ea2fe0..9c22d26158d 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -1,27 +1,27 @@ // Access check is of the type requires one. These have been carefully selected to avoid allowing the janitor to see channels he shouldn't var/global/list/default_internal_channels = list( - num2text(PUB_FREQ) = list(), - num2text(AI_FREQ) = list(access_synth), - num2text(COMM_FREQ)= list(access_heads), - num2text(ENG_FREQ) = list(access_engine_equip, access_atmospherics), - num2text(MED_FREQ) = list(access_medical_equip), - num2text(NT_FREQ) = list(access_nt_disciple), - num2text(MED_I_FREQ)=list(access_medical_equip), - num2text(SEC_FREQ) = list(access_security), - num2text(SEC_I_FREQ)=list(access_security), - num2text(SCI_FREQ) = list(access_tox,access_robotics,access_xenobiology), - num2text(SUP_FREQ) = list(access_cargo), - num2text(SRV_FREQ) = list(access_janitor, access_hydroponics) + num2text(FREQ_COMMON) = list(), + num2text(FREQ_AI) = list(access_synth), + num2text(FREQ_COMM)= list(access_heads), + num2text(FREQ_ENG) = list(access_engine_equip, access_atmospherics), + num2text(FREQ_MED) = list(access_medical_equip), + num2text(FREQ_NT) = list(access_nt_disciple), + num2text(FREQ_MED_I)=list(access_medical_equip), + num2text(FREQ_SEC) = list(access_security), + num2text(FREQ_SEC_I)=list(access_security), + num2text(FREQ_SCI) = list(access_tox,access_robotics,access_xenobiology), + num2text(FREQ_SUP) = list(access_cargo), + num2text(FREQ_SRV) = list(access_janitor, access_hydroponics) ) var/global/list/unique_internal_channels = list( - num2text(DTH_FREQ) = list(access_cent_specops) + num2text(FREQ_DTH) = list(access_cent_specops) ) var/global/list/default_medbay_channels = list( - num2text(PUB_FREQ) = list(), - num2text(MED_FREQ) = list(access_medical_equip), - num2text(MED_I_FREQ) = list(access_medical_equip) + num2text(FREQ_COMMON) = list(), + num2text(FREQ_MED) = list(access_medical_equip), + num2text(FREQ_MED_I) = list(access_medical_equip) ) /obj/item/device/radio @@ -44,7 +44,7 @@ var/global/list/default_medbay_channels = list( var/on = TRUE // 0 for off var/last_transmission - var/frequency = PUB_FREQ //common chat + var/frequency = FREQ_COMMON //common chat var/contractor_frequency = 0 //tune to frequency to unlock contractor supplies var/canhear_range = 3 // the range which mobs can hear this radio from var/datum/wires/radio/wires @@ -81,7 +81,7 @@ var/global/list/default_medbay_channels = list( QDEL_NULL(wires) SSradio.remove_object(src, frequency) for (var/ch_name in channels) - SSradio.remove_object(src, radiochannels[ch_name]) + SSradio.remove_object(src, GLOB.radiochannels[ch_name]) return ..() @@ -91,12 +91,12 @@ var/global/list/default_medbay_channels = list( /obj/item/device/radio/Initialize() . = ..() - if(frequency < RADIO_LOW_FREQ || frequency > RADIO_HIGH_FREQ) - frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + if(frequency < FREQ_RADIO_LOW || frequency > FREQ_RADIO_HIGH) + frequency = sanitize_frequency(frequency, FREQ_RADIO_LOW, FREQ_RADIO_HIGH) set_frequency(frequency) for (var/ch_name in channels) - secure_radio_connections[ch_name] = SSradio.add_object(src, radiochannels[ch_name], RADIO_CHAT) + secure_radio_connections[ch_name] = SSradio.add_object(src, GLOB.radiochannels[ch_name], RADIO_CHAT) return INITIALIZE_HINT_LATELOAD @@ -149,7 +149,7 @@ var/global/list/default_medbay_channels = list( var/chan_stat = channels[ch_name] var/listening = !!(chan_stat & FREQ_LISTENING) != 0 - dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = frequency_span_class(radiochannels[ch_name])))) + dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = get_radio_span(GLOB.radiochannels[ch_name])))) return dat @@ -157,7 +157,7 @@ var/global/list/default_medbay_channels = list( var/dat[0] for(var/internal_chan in internal_channels) if(has_channel_access(user, internal_chan)) - dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan))))) + dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = get_radio_span(text2num(internal_chan))))) return dat @@ -215,7 +215,7 @@ var/global/list/default_medbay_channels = list( else if (href_list["freq"]) var/new_frequency = (frequency + text2num(href_list["freq"])) - if ((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)) + if ((new_frequency < MIN_FREQ || new_frequency > MAX_FREQ)) new_frequency = sanitize_frequency(new_frequency) set_frequency(new_frequency) if(hidden_uplink) @@ -614,7 +614,7 @@ var/global/list/default_medbay_channels = list( for(var/ch_name in channels) - SSradio.remove_object(src, radiochannels[ch_name]) + SSradio.remove_object(src, GLOB.radiochannels[ch_name]) secure_radio_connections[ch_name] = null @@ -666,7 +666,7 @@ var/global/list/default_medbay_channels = list( src.syndie = TRUE for (var/ch_name in src.channels) - secure_radio_connections[ch_name] = SSradio.add_object(src, radiochannels[ch_name], RADIO_CHAT) + secure_radio_connections[ch_name] = SSradio.add_object(src, GLOB.radiochannels[ch_name], RADIO_CHAT) return @@ -737,11 +737,11 @@ var/global/list/default_medbay_channels = list( /obj/item/device/radio/proc/config(op) for (var/ch_name in channels) - SSradio.remove_object(src, radiochannels[ch_name]) + SSradio.remove_object(src, GLOB.radiochannels[ch_name]) secure_radio_connections = new channels = op for (var/ch_name in op) - secure_radio_connections[ch_name] = SSradio.add_object(src, radiochannels[ch_name], RADIO_CHAT) + secure_radio_connections[ch_name] = SSradio.add_object(src, GLOB.radiochannels[ch_name], RADIO_CHAT) return /obj/item/device/radio/off @@ -755,7 +755,7 @@ var/global/list/default_medbay_channels = list( name = "phone" /obj/item/device/radio/phone/medbay - frequency = MED_I_FREQ + frequency = FREQ_MED_I /obj/item/device/radio/phone/medbay/New() ..() diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 3cdda3c9547..3c6fd1a676f 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -41,18 +41,24 @@ output += "  ERROR
" continue for (var/filter in fqs.devices) - var/list/f = fqs.devices[filter] - if (!f) + var/list/filtered = fqs.devices[filter] + if (!filtered) output += "  [filter]: ERROR
" continue - output += "  [filter]: [f.len]
" - for (var/device in f) - if (isobj(device)) - output += "    [device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])
" + output += "  [filter]: [filtered.len]
" + for(var/datum/weakref/device_ref as anything in filtered) + var/atom/device = device_ref.resolve() + if(!device) + filtered -= device_ref + continue + if (istype(device, /atom)) + var/atom/A = device + output += "    [device] ([AREACOORD(A)])
" else output += "    [device]
" usr << browse(HTML_SKELETON_TITLE("Radio Report", output),"window=radioreport") + BLACKBOX_LOG_ADMIN_VERB("Show Radio Report") /client/proc/reload_admins() set name = "Reload Admins" diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index f9a187e25c1..98b32eed5f3 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -62,7 +62,7 @@ /obj/item/device/assembly/signaler/proc/set_freq(new_freq) - set_frequency(sanitize_frequency(round(new_freq), RADIO_LOW_FREQ, RADIO_HIGH_FREQ)) + set_frequency(sanitize_frequency(round(new_freq), FREQ_RADIO_LOW, FREQ_RADIO_HIGH)) /obj/item/device/assembly/signaler/ui_status(mob/user) @@ -81,8 +81,8 @@ /obj/item/device/assembly/signaler/ui_data(mob/user) var/list/data = list( - "maxFrequency" = RADIO_HIGH_FREQ, - "minFrequency" = RADIO_LOW_FREQ, + "maxFrequency" = FREQ_RADIO_HIGH, + "minFrequency" = FREQ_RADIO_LOW, "frequency" = frequency, "code" = code ) @@ -201,16 +201,16 @@ secured = TRUE code = 0 - frequency = BLAST_DOOR_FREQ + frequency = FREQ_BLAST_DOOR delay = 1 var/last_message = 0 var/command = "CMD_DOOR_TOGGLE" /obj/item/device/assembly/signaler/door_controller/set_frequency(new_frequency) - SSradio.remove_object(src, BLAST_DOOR_FREQ) - frequency = BLAST_DOOR_FREQ - radio_connection = SSradio.add_object(src, BLAST_DOOR_FREQ, RADIO_BLASTDOORS) + SSradio.remove_object(src, FREQ_BLAST_DOOR) + frequency = FREQ_BLAST_DOOR + radio_connection = SSradio.add_object(src, FREQ_BLAST_DOOR, RADIO_BLASTDOORS) // No nanoUI for u /obj/item/device/assembly/signaler/door_controller/nano_ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nano_topic_state/state) diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index 6717dbfb68f..b0188be9c93 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -30,7 +30,7 @@ var/obj/secbot_listener/listener = null var/beacon_freq = 1445 // Navigation beacon frequency - var/control_freq = BOT_FREQ // Bot control frequency + var/control_freq = FREQ_BOT // Bot control frequency var/list/path = list() var/frustration = 0 var/turf/patrol_target = null // This is where we are headed diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 50c307c0653..c345a50ad63 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -69,8 +69,6 @@ var/hackprogress = 0 // Possible values: 0 - 1000, >= 1000 means the hack is complete and will be reset upon next check var/hack_aborted = 0 - var/obj/item/radio/integrated/signal/sradio // AI's signaller - var/translator_on = 0 // keeps track of the translator module /mob/living/silicon/pai/New(obj/item/device/paicard) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index e21530d671e..0d60c352e6d 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -722,7 +722,7 @@ message = capitalize(trim_left(message)) if(message_mode) - if(message_mode in radiochannels) + if(message_mode in GLOB.radiochannels) if(ears && istype(ears,/obj/item/device/radio)) ears.talk_into(src,sanitize(message), message_mode, verb, null, getSpeechVolume()) diff --git a/code/modules/modular_computers/file_system/programs/generic/signaller.dm b/code/modules/modular_computers/file_system/programs/generic/signaller.dm index bec5f499afc..6b387597611 100644 --- a/code/modules/modular_computers/file_system/programs/generic/signaller.dm +++ b/code/modules/modular_computers/file_system/programs/generic/signaller.dm @@ -80,9 +80,9 @@ return 1 if(href_list["edit_freq"]) - var/input_freq = input("Enter signal frequency ([RADIO_LOW_FREQ]-[RADIO_HIGH_FREQ]):", "Signal parameters", computer.network_card.frequency) as num|null + var/input_freq = input("Enter signal frequency ([FREQ_RADIO_LOW]-[FREQ_RADIO_HIGH]):", "Signal parameters", computer.network_card.frequency) as num|null if(input_freq && CanUseTopic(usr) && computer && computer.network_card) - if(input_freq < RADIO_LOW_FREQ) // A decimal input maybe? + if(input_freq < FREQ_RADIO_LOW) // A decimal input maybe? input_freq *= 10 computer.network_card.set_frequency(round(input_freq)) diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm index 6ca4d79f9d0..5623d54a388 100644 --- a/code/modules/modular_computers/hardware/network_card.dm +++ b/code/modules/modular_computers/hardware/network_card.dm @@ -46,7 +46,7 @@ var/global/ntnet_card_uid = 1 return SSradio.remove_object(src, frequency) - frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + frequency = sanitize_frequency(new_frequency, FREQ_RADIO_LOW, FREQ_RADIO_HIGH) radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT) /obj/item/computer_hardware/network_card/proc/signal(new_frequency, code) diff --git a/tgui/packages/tgui-say/TguiSay.tsx b/tgui/packages/tgui-say/TguiSay.tsx index b4a2724d78f..19ae360d5ed 100644 --- a/tgui/packages/tgui-say/TguiSay.tsx +++ b/tgui/packages/tgui-say/TguiSay.tsx @@ -21,6 +21,8 @@ type ByondProps = { scale: BooleanLike; }; +const cssSafeRegex = /[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g; + export function TguiSay() { const innerRef = useRef(null); const channelIterator = useRef(new ChannelIterator()); @@ -268,7 +270,7 @@ export function TguiSay() { const theme = (lightMode && 'lightMode') || - (currentPrefix && RADIO_PREFIXES[currentPrefix]) || + (currentPrefix && RADIO_PREFIXES[currentPrefix].replaceAll(cssSafeRegex, '')) || channelIterator.current.current(); return ( diff --git a/tgui/packages/tgui-say/constants.ts b/tgui/packages/tgui-say/constants.ts index 3f451f63ee1..17c2eca4e7a 100644 --- a/tgui/packages/tgui-say/constants.ts +++ b/tgui/packages/tgui-say/constants.ts @@ -18,18 +18,19 @@ export enum LineLength { * Displays the name in the left button, tags a css class. */ export const RADIO_PREFIXES = { - ':a ': 'Hive', ':b ': 'io', ':c ': 'Cmd', ':e ': 'Engi', - ':g ': 'Cling', ':m ': 'Med', + ':mi ': 'Med(I)', ':n ': 'Sci', - ':o ': 'AI', - ':p ': 'Ent', + ':o ': 'Spec', + ':p ': 'AI', ':s ': 'Sec', - ':y ': 'Merc', + ':si ': 'Sec(I)', ':t ': 'NT', ':u ': 'Supp', ':v ': 'Svc', + ':x ': 'Pirate', + ':y ': 'Merc', } as const; diff --git a/tgui/packages/tgui-say/helpers.ts b/tgui/packages/tgui-say/helpers.ts index 2cbb0d12b9d..884a95adbff 100644 --- a/tgui/packages/tgui-say/helpers.ts +++ b/tgui/packages/tgui-say/helpers.ts @@ -49,7 +49,7 @@ function setWindowVisibility(visible: boolean, scale: boolean): void { }); } -const CHANNEL_REGEX = /^[:.]\w\s/; +const CHANNEL_REGEX = /^[:.]\w{1,3}\s/; /** Tests for a channel prefix, returning it or none */ export function getPrefix( @@ -60,9 +60,10 @@ export function getPrefix( } let adjusted = value - .slice(0, 3) + .slice(0, 4) + ?.trim() ?.toLowerCase() - ?.replace('.', ':') as keyof typeof RADIO_PREFIXES; + ?.replace('.', ':') + " " as keyof typeof RADIO_PREFIXES; if (!RADIO_PREFIXES[adjusted]) { return; diff --git a/tgui/packages/tgui-say/styles/colors.scss b/tgui/packages/tgui-say/styles/colors.scss index 9ee5624648a..1c72badaee4 100644 --- a/tgui/packages/tgui-say/styles/colors.scss +++ b/tgui/packages/tgui-say/styles/colors.scss @@ -11,24 +11,25 @@ $_channel_map: ( 'Admin': hsl(300, 100%, 86.7%), 'AI': hsl(332.2, 59.6%, 60.2%), 'CCom': hsl(197, 62.6%, 39.8%), - 'Cling': hsl(86.7, 56.6%, 28%), 'Cmd': hsl(202, 98%, 50%), 'NT': hsl(46, 65%, 52%), 'Engi': hsl(17, 87.8%, 61.4%), - 'Hive': hsl(300, 17.7%, 44.3%), 'io': hsl(209.6, 100%, 55.9%), 'Me': hsl(227, 63.5%, 60.2%), 'Med': hsl(202, 83.6%, 64.1%), + 'MedI': hsl(202, 83.6%, 54.1%), // Med(I) 'OOC': hsl(47.9, 100%, 40%), 'LOOC': #fafa3b, 'Mentor': #ff00ff, - 'Ent': hsl(176.1, 20%, 45.1%), 'Radio': hsl(132.8, 74.4%, 45.9%), 'Say': hsl(213.6, 37.9%, 74.1%), 'Sci': hsl(271.6, 91.7%, 76.5%), 'Sec': hsl(0, 71.2%, 53.7%), + 'SecI': hsl(0, 71.2%, 43.7%), // Sec(I) + 'Spec': hsl(180, 20%, 55%), 'Supp': hsl(33.7, 44.9%, 49.8%), 'Svc': hsl(88.1, 60.6%, 40.8%), + 'Pirate': hsl(10, 80%, 50%), 'Merc': hsl(359.1, 31.8%, 42.5%), ); From f6df3474f27ffaf8f57e6622d91076538047fe7c Mon Sep 17 00:00:00 2001 From: Flleeppyy Date: Sun, 24 May 2026 04:51:36 -0700 Subject: [PATCH 2/4] hehe scope creep --- code/game/objects/items/weapons/traps.dm | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 9445ed85470..8c17fb5b012 100755 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -236,22 +236,20 @@ Freeing yourself is much harder than freeing someone else. Calling for help is a //If an attempt to release the mob fails, it digs in and deals more damage /obj/item/beartrap/proc/fail_attempt(user, difficulty) - if (!buckled_mob) + if (QDELETED(buckled_mob)) return - var/mob/living/L = buckled_mob //armour - - if( L.damage_through_armor(fail_damage, BRUTE, target_zone, ARMOR_MELEE, used_weapon = src) ) + if( buckled_mob.damage_through_armor(fail_damage, BRUTE, target_zone, ARMOR_MELEE, used_weapon = src) ) //No damage - no stun - L.Stun(4) //A short stun prevents spamming failure attempts + buckled_mob.Stun(4) //A short stun prevents spamming failure attempts shake_camera(user, 2, 1) if (ishuman(L)) - var/mob/living/carbon/human/H = L - visible_message(span_danger("\The [src] snaps back, digging deeper into [buckled_mob.name]'s [H.get_organ(target_zone).name]")) + var/mob/living/carbon/human/H = buckled_mob + visible_message(span_danger("\The [src] snaps back, digging deeper into [buckled_mob]'s [H.get_organ(target_zone)]")) else - visible_message(span_danger("\The [src] snaps back, digging deeper into [buckled_mob.name]")) + visible_message(span_danger("\The [src] snaps back, digging deeper into [buckled_mob]")) playsound(src, 'sound/effects/impacts/beartrap_shut.ogg', 10, 1,-2,-2)//Fairly quiet snapping sound From 6c88ada565421f58a2fb82bc24923fa39220ac03 Mon Sep 17 00:00:00 2001 From: Flleeppyy Date: Sun, 24 May 2026 07:55:44 -0700 Subject: [PATCH 3/4] aeugheghd --- code/game/objects/items/weapons/traps.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 8c17fb5b012..66e9a87fa57 100755 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -245,7 +245,7 @@ Freeing yourself is much harder than freeing someone else. Calling for help is a buckled_mob.Stun(4) //A short stun prevents spamming failure attempts shake_camera(user, 2, 1) - if (ishuman(L)) + if (ishuman(buckled_mob)) var/mob/living/carbon/human/H = buckled_mob visible_message(span_danger("\The [src] snaps back, digging deeper into [buckled_mob]'s [H.get_organ(target_zone)]")) else From c6d3e9b5f4f6a2b29e5a29f8e04968c5683360b5 Mon Sep 17 00:00:00 2001 From: Flleeppyy Date: Sun, 24 May 2026 08:06:37 -0700 Subject: [PATCH 4/4] fixies :3 --- tgui/packages/tgui-say/TguiSay.tsx | 3 ++- tgui/packages/tgui-say/helpers.ts | 7 ++----- tgui/packages/tgui-say/styles/colors.scss | 6 ++++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tgui/packages/tgui-say/TguiSay.tsx b/tgui/packages/tgui-say/TguiSay.tsx index 19ae360d5ed..18d3e0d1fee 100644 --- a/tgui/packages/tgui-say/TguiSay.tsx +++ b/tgui/packages/tgui-say/TguiSay.tsx @@ -270,7 +270,8 @@ export function TguiSay() { const theme = (lightMode && 'lightMode') || - (currentPrefix && RADIO_PREFIXES[currentPrefix].replaceAll(cssSafeRegex, '')) || + (currentPrefix && + RADIO_PREFIXES[currentPrefix].replaceAll(cssSafeRegex, '')) || channelIterator.current.current(); return ( diff --git a/tgui/packages/tgui-say/helpers.ts b/tgui/packages/tgui-say/helpers.ts index 884a95adbff..fbe571739c7 100644 --- a/tgui/packages/tgui-say/helpers.ts +++ b/tgui/packages/tgui-say/helpers.ts @@ -59,11 +59,8 @@ export function getPrefix( return; } - let adjusted = value - .slice(0, 4) - ?.trim() - ?.toLowerCase() - ?.replace('.', ':') + " " as keyof typeof RADIO_PREFIXES; + let adjusted = (value.slice(0, 4)?.trim()?.toLowerCase()?.replace('.', ':') + + ' ') as keyof typeof RADIO_PREFIXES; if (!RADIO_PREFIXES[adjusted]) { return; diff --git a/tgui/packages/tgui-say/styles/colors.scss b/tgui/packages/tgui-say/styles/colors.scss index 1c72badaee4..7826eda6e66 100644 --- a/tgui/packages/tgui-say/styles/colors.scss +++ b/tgui/packages/tgui-say/styles/colors.scss @@ -17,7 +17,8 @@ $_channel_map: ( 'io': hsl(209.6, 100%, 55.9%), 'Me': hsl(227, 63.5%, 60.2%), 'Med': hsl(202, 83.6%, 64.1%), - 'MedI': hsl(202, 83.6%, 54.1%), // Med(I) + // Med(I) + 'MedI': hsl(202, 83.6%, 54.1%), 'OOC': hsl(47.9, 100%, 40%), 'LOOC': #fafa3b, 'Mentor': #ff00ff, @@ -25,7 +26,8 @@ $_channel_map: ( 'Say': hsl(213.6, 37.9%, 74.1%), 'Sci': hsl(271.6, 91.7%, 76.5%), 'Sec': hsl(0, 71.2%, 53.7%), - 'SecI': hsl(0, 71.2%, 43.7%), // Sec(I) + // Sec(I) + 'SecI': hsl(0, 71.2%, 43.7%), 'Spec': hsl(180, 20%, 55%), 'Supp': hsl(33.7, 44.9%, 49.8%), 'Svc': hsl(88.1, 60.6%, 40.8%),