Files
mineymonkeyandGitHub 1a30a33b7c Another circuit fix (#22977)
Reduces max phoron and steel storage potential of the IC Circuit
Printer. Particularly steel is reduced when the cloning disk is
installed and phoron is set to one bar instead of two.

Also put in some safety measures for importing being lost due to server
latency.

Oh and well the radio command receiver is built in now.
2026-08-04 10:54:29 +00:00

287 lines
9.1 KiB
Plaintext

// Subtype of /datum/signal with additional processing information.
/datum/signal/subspace
transmission_method = TRANSMISSION_SUBSPACE
var/server_type = /obj/structure/machinery/telecomms/server
var/datum/signal/subspace/original
var/origin_level
var/list/levels
var/obj/effect/overmap/visitable/sector
/datum/signal/subspace/New(obj/source, frequency, message = "", data = null)
src.source = source
src.frequency = frequency
var/turf/T = get_turf(source)
if(isturf(T))
origin_level = T.z
if(data)
src.data = data
else
src.data = list(
"compression" = rand(35, 65),
"message" = message
)
if(SSatlas.current_map.use_overmap && istype(source))
sector = GLOB.map_sectors["[source.z]"]
/datum/signal/subspace/proc/copy()
var/datum/signal/subspace/copy = new
copy.original = src
copy.source = source
copy.levels = levels
copy.origin_level = origin_level
copy.frequency = frequency
copy.server_type = server_type
copy.transmission_method = transmission_method
copy.sector = sector
copy.data = data.Copy()
return copy
/datum/signal/subspace/proc/mark_done()
var/datum/signal/subspace/current = src
while (current)
current.data["done"] = TRUE
current = current.original
/datum/signal/subspace/proc/send_to_receivers()
if(!source.loc)
// It's an announcer message, just send it to the horizon's receiver
for(var/obj/structure/machinery/telecomms/receiver/R in SSmachinery.all_receivers)
if(is_station_level(R.z))
R.receive_signal(src)
return TRUE
var/closest_range = 999999
var/list/candidates = list()
var/obj/structure/machinery/telecomms/selected_receiver
var/t_range = -1
for(var/obj/structure/machinery/telecomms/R in SSmachinery.all_receivers)
t_range = R.receive_range(src)
if(t_range <= -1)
continue
if(t_range < closest_range)
candidates = list(R)
closest_range = t_range
else if(t_range == closest_range)
candidates |= R
if(!length(candidates))
return
if(length(candidates) > 1)
// Unlikely we ever have two receivers at the same distance listening to one frequency, but still
closest_range = 128 // get_dist returns 127 max
t_range = -1
for(var/obj/structure/machinery/telecomms/R in candidates)
t_range = get_dist(R, source)
if(t_range < closest_range)
selected_receiver = R
closest_range = t_range
continue
else
selected_receiver = candidates[1]
selected_receiver.receive_signal(src)
return TRUE
/datum/signal/subspace/proc/broadcast()
set waitfor = FALSE
// Vocal transmissions (i.e. using saycode).
// Despite "subspace" in the name, these transmissions can also be RADIO
// (intercoms and SBRs) or SUPERSPACE (CentCom).
/datum/signal/subspace/vocal
var/datum/weakref/speaker
var/datum/language/language
/// The speaker's say_message, if any. Null for the announcer, etc.
var/datum/say_message/say_message
/datum/signal/subspace/vocal/New(obj/source, frequency, datum/weakref/speaker, datum/language/language, message, say_verb, datum/say_message/say_message)
src.source = source
src.frequency = frequency
src.language = language
src.speaker = speaker
src.say_message = say_message
var/turf/T = get_turf(source)
if(isturf(T))
origin_level = T.z
levels = list(T.z)
if(SSatlas.current_map.use_overmap)
sector = GLOB.map_sectors["[T.z]"]
else // if the source is in nullspace, it's probably an autosay
levels = SSmapping.levels_by_trait(ZTRAIT_STATION)
origin_level = levels[1]
sector = GLOB.map_sectors["[levels[1]]"]
var/mob/M = speaker.resolve()
data = list(
"name" = M.GetVoice(),
"job" = M.job,
"message" = message,
"compression" = rand(35, 65),
"language" = language,
"say_verb" = say_verb
)
/datum/signal/subspace/vocal/copy()
var/datum/signal/subspace/vocal/copy = new(source, frequency, speaker, language, say_message = say_message)
copy.original = src
copy.data = data.Copy()
copy.levels = levels
return copy
// THE MEAT for making radios hear vocal transmissions.
/datum/signal/subspace/vocal/broadcast()
set waitfor = FALSE
var/message = copytext(data["message"], 1, MAX_MESSAGE_LEN)
if(!message || message == "")
return
var/list/signal_reaches_every_z_level = levels
if(0 in levels)
signal_reaches_every_z_level = RADIO_NO_Z_LEVEL_RESTRICTION
var/list/radios = list()
switch (transmission_method)
if (TRANSMISSION_SUBSPACE)
// Reach any radios on the levels
var/list/all_radios_of_our_frequency = SSradio.get_devices(frequency, RADIO_CHAT)
for (var/obj/item/radio/subspace_radio in all_radios_of_our_frequency)
if(subspace_radio.can_receive(frequency, signal_reaches_every_z_level))
radios += subspace_radio
// Cool antag radios can hear all Horizon comms
for (var/antag_freq in list(SYND_FREQ, RAID_FREQ, NINJ_FREQ))
for (var/obj/item/radio/syndicate_radios in SSradio.get_devices(antag_freq, RADIO_CHAT))
if(syndicate_radios.can_receive(antag_freq, signal_reaches_every_z_level))
radios |= syndicate_radios
if (TRANSMISSION_RADIO)
// Only radios not in subspace mode
for (var/obj/item/radio/non_subspace_radio in SSradio.get_devices(frequency, RADIO_CHAT))
if(!non_subspace_radio.subspace_transmission && non_subspace_radio.can_receive(frequency, levels))
radios += non_subspace_radio
if (TRANSMISSION_SUPERSPACE)
// Independent radios
for (var/obj/item/radio/indie_radio in SSradio.get_devices(frequency, RADIO_CHAT))
if(indie_radio.independent && indie_radio.can_receive(frequency, levels))
radios += indie_radio
var/list/receive = get_hearers_in_radio_ranges(radios)
// Electronic radio headsets expose received traffic to their built-in
// command receiver independently of whether a mob can hear the message.
for(var/obj/item/radio/headset/circuitry/circuit_headset in radios)
circuit_headset.receive_circuit_radio_command(data["name"], message, get_frequency_name(frequency))
// Cut out admins which have radio chatter disabled
for (var/mob/R in receive)
if(R.client && R.client.holder && !(R.client.prefs.toggles & CHAT_RADIO))
receive -= R
// Add observers who have ghost radio enabled
for (var/mob/abstract/ghost/observer/M in GLOB.player_list)
if(M.client && (M.client.prefs?.toggles & CHAT_GHOSTRADIO))
receive |= M
// a lot more efficient than checking big lists again
if(length(SSodyssey.storytellers))
for(var/mob/abstract/ghost/storyteller/storyteller in SSodyssey.storytellers)
receive |= storyteller
/* --- Some miscellaneous variables to format the string output --- */
var/freq_text = get_frequency_name(frequency)
var/part_b_extra = ""
if(data == 3) // intercepted radio message
part_b_extra = " <i>(Intercepted)</i>"
var/part_a = "<span class='[frequency_span_class(frequency)]'>%ACCENT%<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output
// --- Some more pre-message formatting ---
var/part_b = "</span> <span class='message'></span>" // Tweaked for security headsets -- TLE
var/part_c = "</span>"
// --- Filter the message; place it in quotes apply a verb ---
var/mob/M = speaker.resolve()
var/quotedmsg = null
if(M)
quotedmsg = M.say_quote(message)
else
quotedmsg = "says, \"[message]\""
var/compression = data["compression"]
// Carry the original message if untouched in transit, else build one from the flat text.
var/datum/say_message/radio_msg
if(say_message && say_message.to_string() == data["message"])
radio_msg = say_message.copy()
else
radio_msg = new
radio_msg.speaker = M
radio_msg.verb = data["say_verb"]
radio_msg.collapse_to(language, message)
radio_msg.say_mode = SAYMODE_RADIO
radio_msg.base_clarity = compression ? CLARITY_FAINT : CLARITY_CLEAR
radio_msg.radio_parts = list(part_a, part_b, part_c)
for (var/mob/hearer in receive)
if(!hearer)
crash_with("null found in the hearers list returned by the spatial grid")
continue
hearer.hear_message(radio_msg)
// --- This following recording is intended for research and feedback in the use of department radio channels ---
var/part_blackbox_b = "</span><b> \[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
var/blackbox_msg = "[part_a][data["name"]][part_blackbox_b][quotedmsg][part_c]"
if(istype(SSstatistics))
switch(frequency)
if(PUB_FREQ)
SSstatistics.msg_common += blackbox_msg
if(SCI_FREQ)
SSstatistics.msg_science += blackbox_msg
if(COMM_FREQ)
SSstatistics.msg_command += blackbox_msg
if(MED_FREQ)
SSstatistics.msg_medical += blackbox_msg
if(ENG_FREQ)
SSstatistics.msg_engineering += blackbox_msg
if(SEC_FREQ)
SSstatistics.msg_security += blackbox_msg
if(DTH_FREQ)
SSstatistics.msg_deathsquad += blackbox_msg
if(SYND_FREQ)
SSstatistics.msg_syndicate += blackbox_msg
if(COAL_FREQ)
SSstatistics.msg_coalition += blackbox_msg
if(RAID_FREQ)
SSstatistics.msg_raider += blackbox_msg
if(NINJ_FREQ)
SSstatistics.msg_ninja += blackbox_msg
if(BLSP_FREQ)
SSstatistics.msg_bluespace += blackbox_msg
if(BURG_FREQ)
SSstatistics.msg_burglar += blackbox_msg
if(SUP_FREQ)
SSstatistics.msg_cargo += blackbox_msg
if(SRV_FREQ)
SSstatistics.msg_service += blackbox_msg
else
if(frequency in AWAY_FREQS_ASSIGNED)
SSstatistics.msg_ship += blackbox_msg
else
SSstatistics.messages += blackbox_msg