/** 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 var/server_type = /obj/machinery/telecomms/server var/datum/signal/subspace/original var/list/levels /datum/signal/subspace/New(data) src.data = data || list() /datum/signal/subspace/proc/copy() var/datum/signal/subspace/copy = new copy.original = src copy.source = source copy.levels = levels copy.frequency = frequency copy.server_type = server_type copy.transmission_method = transmission_method 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() 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) /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/atom/movable/virtualspeaker/virt var/datum/language/language /datum/signal/subspace/vocal/New( obj/source, // the originating radio frequency, // the frequency the signal is taking place on atom/movable/virtualspeaker/speaker, // representation of the method's speaker datum/language/language, // the langauge of the message message, // the text content of the message spans // the list of spans applied to the message ) src.source = source src.frequency = frequency src.language = language virt = speaker var/datum/language/lang_instance = GLOB.language_datum_instances[language] data = list( "name" = speaker.name, "job" = speaker.job, "message" = message, "compression" = rand(35, 65), "language" = lang_instance.name, "spans" = spans ) var/turf/T = get_turf(source) levels = list(T.z) /datum/signal/subspace/vocal/copy() var/datum/signal/subspace/vocal/copy = new(source, frequency, virt, language) copy.original = src copy.data = data.Copy() copy.levels = levels return copy // This is the meat function for making radios hear vocal transmissions. /datum/signal/subspace/vocal/broadcast() set waitfor = FALSE // Perform final composition steps on the message. var/message = copytext(data["message"], 1, MAX_BROADCAST_LEN) if(!message) return var/compression = data["compression"] if(compression > 0) message = Gibberish(message, compression + 40) // Assemble the list of radios var/list/radios = list() switch (transmission_method) if (TRANSMISSION_SUBSPACE) // Reaches any radios on the levels for(var/obj/item/radio/R in GLOB.all_radios["[frequency]"]) if(R.can_receive(frequency, levels)) radios += R // Syndicate radios can hear all well-known radio channels if (num2text(frequency) in GLOB.reverseradiochannels) for(var/obj/item/radio/R in GLOB.all_radios["[FREQ_SYNDICATE]"]) if(R.can_receive(FREQ_SYNDICATE, list(R.z))) radios |= R if (TRANSMISSION_RADIO) // Only radios not currently in subspace mode for(var/obj/item/radio/R in GLOB.all_radios["[frequency]"]) if(!R.subspace_transmission && R.can_receive(frequency, levels)) radios += R if (TRANSMISSION_SUPERSPACE) // Only radios which are independent for(var/obj/item/radio/R in GLOB.all_radios["[frequency]"]) if(R.independent && R.can_receive(frequency, levels)) radios += R // From the list of radios, find all mobs who can hear those. var/list/receive = get_mobs_in_radio_ranges(radios) // Cut out mobs with clients who are admins and have radio chatter disabled. for(var/mob/R in receive) if (R.client && R.client.holder && !(R.client.prefs.chat_toggles & CHAT_RADIO)) receive -= R // Add observers who have ghost radio enabled. for(var/mob/dead/observer/M in GLOB.player_list) if(M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTRADIO)) receive |= M // Render the message and have everybody hear it. // Always call this on the virtualspeaker to avoid issues. var/spans = data["spans"] var/rendered = virt.compose_message(virt, language, message, frequency, spans) for(var/atom/movable/hearer in receive) hearer.Hear(rendered, virt, language, message, frequency, spans) // This following recording is intended for research and feedback in the use of department radio channels if(length(receive)) SSblackbox.LogBroadcast(frequency) QDEL_IN(virt, 50) // Make extra sure the virtualspeaker gets qdeleted