Refactor telecomms to send messages to logically adjacent zlevels

This commit is contained in:
Aronai Sieyes
2020-04-10 20:24:19 -04:00
parent 942ed8d806
commit e2d2964546
14 changed files with 577 additions and 204 deletions

View File

@@ -246,7 +246,7 @@
var/turf/speaker = get_turf(R) var/turf/speaker = get_turf(R)
if(speaker) if(speaker)
for(var/turf/T in hear(R.canhear_range,speaker)) for(var/turf/T in hear(R.canhear_range,speaker))
speaker_coverage[T] = T speaker_coverage[T] = R
// Try to find all the players who can hear the message // Try to find all the players who can hear the message

View File

@@ -219,6 +219,7 @@
var/on_enter_occupant_message = "You feel cool air surround you. You go numb as your senses turn inward." var/on_enter_occupant_message = "You feel cool air surround you. You go numb as your senses turn inward."
var/on_store_visible_message_1 = "hums and hisses as it moves" //We need two variables because byond doesn't let us have variables inside strings at compile-time. var/on_store_visible_message_1 = "hums and hisses as it moves" //We need two variables because byond doesn't let us have variables inside strings at compile-time.
var/on_store_visible_message_2 = "into storage." var/on_store_visible_message_2 = "into storage."
var/announce_channel = "Common"
var/allow_occupant_types = list(/mob/living/carbon/human) var/allow_occupant_types = list(/mob/living/carbon/human)
var/disallow_occupant_types = list() var/disallow_occupant_types = list()
@@ -519,7 +520,7 @@
control_computer._admin_logs += "[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) at [stationtime2text()]" control_computer._admin_logs += "[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) at [stationtime2text()]"
log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.") log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]") announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE))
//visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.</span>", 3) //visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.</span>", 3)
visible_message("<span class='notice'>\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2].</span>", 3) visible_message("<span class='notice'>\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2].</span>", 3)

View File

@@ -23,6 +23,12 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
produces_heat = 0 produces_heat = 0
delay = 7 delay = 7
circuit = /obj/item/weapon/circuitboard/telecomms/broadcaster circuit = /obj/item/weapon/circuitboard/telecomms/broadcaster
//Vars only used if you're using the overmap
var/overmap_range = 0
var/overmap_range_min = 0
var/overmap_range_max = 5
//Linked bluespace radios
var/list/linked_radios_weakrefs = list()
/obj/machinery/telecomms/processor/Initialize() /obj/machinery/telecomms/processor/Initialize()
. = ..() . = ..()
@@ -34,6 +40,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
component_parts += new /obj/item/weapon/stock_parts/micro_laser/high(src) component_parts += new /obj/item/weapon/stock_parts/micro_laser/high(src)
component_parts += new /obj/item/stack/cable_coil(src, 1) component_parts += new /obj/item/stack/cable_coil(src, 1)
/obj/machinery/telecomms/broadcaster/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
return
linked_radios_weakrefs |= weakref(R)
/obj/machinery/telecomms/broadcaster/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) /obj/machinery/telecomms/broadcaster/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
// Don't broadcast rejected signals // Don't broadcast rejected signals
if(signal.data["reject"]) if(signal.data["reject"])
@@ -58,46 +69,51 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(signal.data["slow"] > 0) if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary sleep(signal.data["slow"]) // simulate the network lag if necessary
signal.data["level"] |= listening_level signal.data["level"] |= using_map.get_map_levels(listening_level, TRUE, overmap_range)
var/list/forced_radios
for(var/weakref/wr in linked_radios_weakrefs)
var/obj/item/device/radio/R = wr.resolve()
if(istype(R))
LAZYDISTINCTADD(forced_radios, R)
/** #### - Normal Broadcast - #### **/ /** #### - Normal Broadcast - #### **/
if(signal.data["type"] == SIGNAL_NORMAL)
if(signal.data["type"] == 0)
/* ###### Broadcast a message using signal.data ###### */ /* ###### Broadcast a message using signal.data ###### */
Broadcast_Message(signal.data["connection"], signal.data["mob"], Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"], signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],, signal.data["realname"], signal.data["vname"], DATA_NORMAL,
signal.data["compression"], signal.data["level"], signal.frequency, signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"], signal.data["language"] ) signal.data["verb"], signal.data["language"], forced_radios)
/** #### - Simple Broadcast - #### **/ /** #### - Simple Broadcast - #### **/
if(signal.data["type"] == 1) if(signal.data["type"] == SIGNAL_SIMPLE)
/* ###### Broadcast a message using signal.data ###### */ /* ###### Broadcast a message using signal.data ###### */
Broadcast_SimpleMessage(signal.data["name"], signal.frequency, Broadcast_SimpleMessage(signal.data["name"], signal.frequency,
signal.data["message"],null, null, signal.data["message"], DATA_NORMAL, null,
signal.data["compression"], listening_level) signal.data["compression"], listening_level, forced_radios)
/** #### - Artificial Broadcast - #### **/ /** #### - Artificial Broadcast - #### **/
// (Imitates a mob) // (Imitates a mob)
if(signal.data["type"] == 2) if(signal.data["type"] == SIGNAL_FAKE)
/* ###### Broadcast a message using signal.data ###### */ /* ###### Broadcast a message using signal.data ###### */
// Parameter "data" as 4: AI can't track this person/mob // Parameter "data" as DATA_FAKE: AI can't track this person/mob
Broadcast_Message(signal.data["connection"], signal.data["mob"], Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"], signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency, signal.data["realname"], signal.data["vname"], DATA_FAKE,
signal.data["verb"], signal.data["language"]) signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"], signal.data["language"], forced_radios)
if(!message_delay) if(!message_delay)
message_delay = 1 message_delay = 1
@@ -118,6 +134,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* /*
Basically just an empty shell for receiving and broadcasting radio messages. Not Basically just an empty shell for receiving and broadcasting radio messages. Not
very flexible, but it gets the job done. very flexible, but it gets the job done.
NOTE: This AIO device listens on *every* zlevel (it does not even check)
*/ */
/obj/machinery/telecomms/allinone /obj/machinery/telecomms/allinone
@@ -126,15 +143,98 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
icon_state = "comm_server" icon_state = "comm_server"
desc = "A compact machine used for portable subspace telecommuniations processing." desc = "A compact machine used for portable subspace telecommuniations processing."
density = 1 density = 1
use_power = USE_POWER_IDLE
idle_power_usage = 20
anchored = 1 anchored = 1
use_power = USE_POWER_OFF
idle_power_usage = 0
machinetype = 6 machinetype = 6
produces_heat = 0 produces_heat = 0
var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel
var/overmap_range = 0 //Same turf
var/list/linked_radios_weakrefs = list()
/obj/machinery/telecomms/allinone/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
return
linked_radios_weakrefs |= weakref(R)
/obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal) /obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal)
// Has to be on to receive messages
if(!on)
return
// Why did you use this subtype?
if(!using_map.use_overmap)
return
// Someone else handling it?
if(signal.data["done"])
return
// Where are we able to hear from (and talk to, since we're AIO) anyway?
var/map_levels = using_map.get_map_levels(z, TRUE, overmap_range)
//Bluespace can skip this check
if(signal.transmission_method != TRANSMISSION_BLUESPACE)
var/list/signal_levels = list()
signal_levels += signal.data["level"] //If it's text/number, it'll be the only entry, if it's a list, it'll get combined
var/list/overlap = map_levels & signal_levels //Returns a list of similar levels
if(!overlap.len)
return
if(is_freq_listening(signal)) // detect subspace signals
signal.data["done"] = 1 // mark the signal as being broadcasted since we're a broadcaster
signal.data["compression"] = 0 // decompress since we're a processor
// Search for the original signal and mark it as done as well
var/datum/signal/original = signal.data["original"]
if(original)
original.data["done"] = 1
// For some reason level is both used as a list and not a list, and now it needs to be a list.
signal.data["level"] = map_levels
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
/* ###### Broadcast a message using signal.data ###### */
var/datum/radio_frequency/connection = signal.data["connection"]
var/list/forced_radios
for(var/weakref/wr in linked_radios_weakrefs)
var/obj/item/device/radio/R = wr.resolve()
if(istype(R))
LAZYDISTINCTADD(forced_radios, R)
Broadcast_Message(
signal.data["connection"],
signal.data["mob"],
signal.data["vmask"],
signal.data["vmessage"],
signal.data["radio"],
signal.data["message"],
signal.data["name"],
signal.data["job"],
signal.data["realname"],
signal.data["vname"],
DATA_NORMAL,
signal.data["compression"],
signal.data["level"],
connection.frequency,
signal.data["verb"],
signal.data["language"],
forced_radios
)
//Antag version with unlimited range (doesn't even check) and uses no power, to enable antag comms to work anywhere.
/obj/machinery/telecomms/allinone/antag
use_power = USE_POWER_OFF
idle_power_usage = 0
/obj/machinery/telecomms/allinone/antag/receive_signal(datum/signal/signal)
if(!on) // has to be on to receive messages if(!on) // has to be on to receive messages
return return
@@ -159,23 +259,29 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/datum/radio_frequency/connection = signal.data["connection"] var/datum/radio_frequency/connection = signal.data["connection"]
var/list/forced_radios
for(var/weakref/wr in linked_radios_weakrefs)
var/obj/item/device/radio/R = wr.resolve()
if(istype(R))
LAZYDISTINCTADD(forced_radios, R)
if(connection.frequency in ANTAG_FREQS) // if antag broadcast, just if(connection.frequency in ANTAG_FREQS) // if antag broadcast, just
Broadcast_Message(signal.data["connection"], signal.data["mob"], Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"], signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency, signal.data["realname"], signal.data["vname"], DATA_NORMAL,
signal.data["verb"], signal.data["language"]) signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], signal.data["language"], forced_radios)
else else
if(intercept) if(intercept)
Broadcast_Message(signal.data["connection"], signal.data["mob"], Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"], signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"], signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"], signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, signal.data["realname"], signal.data["vname"], DATA_ANTAG,
signal.data["verb"], signal.data["language"]) signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], signal.data["language"], forced_radios)
/** /**
@@ -237,7 +343,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M, /proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
var/vmask, var/vmessage, var/obj/item/device/radio/radio, var/vmask, var/vmessage, var/obj/item/device/radio/radio,
var/message, var/name, var/job, var/realname, var/vname, var/message, var/name, var/job, var/realname, var/vname,
var/data, var/compression, var/list/level, var/freq, var/verbage = "says", var/datum/language/speaking = null) var/data, var/compression, var/list/level, var/freq, var/verbage = "says",
var/datum/language/speaking = null, var/list/forced_radios)
/* ###### Prepare the radio connection ###### */ /* ###### Prepare the radio connection ###### */
@@ -246,17 +353,22 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/list/obj/item/device/radio/radios = list() var/list/obj/item/device/radio/radios = list()
for(var/obj/item/device/radio/R in forced_radios)
//Cursory check to ensure they are 'on' and stuff
if(R.receive_range(display_freq, list(0)))
radios |= R
// --- Broadcast only to intercom devices --- // --- Broadcast only to intercom devices ---
if(data == 1) if(data == DATA_INTERCOM)
for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
if(R.receive_range(display_freq, level) > -1) if(R.receive_range(display_freq, level) > -1)
radios += R radios |= R
// --- Broadcast only to intercoms and station-bounced radios --- // --- Broadcast only to intercoms and station-bounced radios ---
else if(data == 2) else if(data == DATA_LOCAL)
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
@@ -264,16 +376,16 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
continue continue
if(R.receive_range(display_freq, level) > -1) if(R.receive_range(display_freq, level) > -1)
radios += R radios |= R
// --- Broadcast to antag radios! --- // --- Broadcast to antag radios! ---
else if(data == 3) else if(data == DATA_ANTAG)
for(var/antag_freq in ANTAG_FREQS) for(var/antag_freq in ANTAG_FREQS)
var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(antag_freq) var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(antag_freq)
for (var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"])
if(R.receive_range(antag_freq, level) > -1) if(R.receive_range(antag_freq, level) > -1)
radios += R radios |= R
// --- Broadcast to ALL radio devices --- // --- Broadcast to ALL radio devices ---
@@ -281,7 +393,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
if(R.receive_range(display_freq, level) > -1) if(R.receive_range(display_freq, level) > -1)
radios += R radios |= R
// Get a list of mobs who can hear from the radios we collected. // Get a list of mobs who can hear from the radios we collected.
var/list/receive = get_mobs_in_radio_ranges(radios) var/list/receive = get_mobs_in_radio_ranges(radios)
@@ -307,7 +419,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
continue continue
// Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates // Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates
if(data == 3 && istype(R, /mob/observer/dead) && R.is_preference_enabled(/datum/client_preference/ghost_radio)) if(data == DATA_ANTAG && istype(R, /mob/observer/dead) && R.is_preference_enabled(/datum/client_preference/ghost_radio))
continue continue
// --- Check for compression --- // --- Check for compression ---
@@ -346,7 +458,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/freq_text = get_frequency_name(display_freq) var/freq_text = get_frequency_name(display_freq)
var/part_b_extra = "" var/part_b_extra = ""
if(data == 3) // intercepted radio message if(data == DATA_ANTAG) // intercepted radio message
part_b_extra = " <i>(Intercepted)</i>" part_b_extra = " <i>(Intercepted)</i>"
var/part_a = "<span class='[frequency_span_class(display_freq)]'>[bicon(radio)]<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output var/part_a = "<span class='[frequency_span_class(display_freq)]'>[bicon(radio)]<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output
@@ -438,7 +550,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
return 1 return 1
/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level) /proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level, var/list/forced_radios)
/* ###### Prepare the radio connection ###### */ /* ###### Prepare the radio connection ###### */
@@ -452,10 +564,12 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/list/receive = list() var/list/receive = list()
for(var/obj/item/device/radio/R in forced_radios)
receive |= R.send_hear(display_freq)
// --- Broadcast only to intercom devices --- // --- Broadcast only to intercom devices ---
if(data == 1) if(data == DATA_INTERCOM)
for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
var/turf/position = get_turf(R) var/turf/position = get_turf(R)
if(position && position.z == level) if(position && position.z == level)
@@ -464,7 +578,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Broadcast only to intercoms and station-bounced radios --- // --- Broadcast only to intercoms and station-bounced radios ---
else if(data == 2) else if(data == DATA_LOCAL)
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
if(istype(R, /obj/item/device/radio/headset)) if(istype(R, /obj/item/device/radio/headset))
@@ -476,7 +590,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Broadcast to antag radios! --- // --- Broadcast to antag radios! ---
else if(data == 3) else if(data == DATA_ANTAG)
for(var/freq in ANTAG_FREQS) for(var/freq in ANTAG_FREQS)
var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(freq) var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(freq)
for (var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"]) for (var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"])
@@ -541,7 +655,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Some more pre-message formatting --- // --- Some more pre-message formatting ---
var/part_b_extra = "" var/part_b_extra = ""
if(data == 3) // intercepted radio message if(data == DATA_ANTAG) // intercepted radio message
part_b_extra = " <i>(Intercepted)</i>" part_b_extra = " <i>(Intercepted)</i>"
// Create a radio headset for the sole purpose of using its icon // Create a radio headset for the sole purpose of using its icon
@@ -617,15 +731,15 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/atom/proc/test_telecomms() /atom/proc/test_telecomms()
var/datum/signal/signal = src.telecomms_process() var/datum/signal/signal = src.telecomms_process()
var/turf/position = get_turf(src) var/pos_z = get_z(src)
return (position.z in signal.data["level"] && signal.data["done"]) return (pos_z in signal.data["level"] && signal.data["done"])
/atom/proc/telecomms_process(var/do_sleep = 1) /atom/proc/telecomms_process(var/do_sleep = 1)
// First, we want to generate a new radio signal // First, we want to generate a new radio signal
var/datum/signal/signal = new var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission. signal.transmission_method = TRANSMISSION_SUBSPACE
var/turf/pos = get_turf(src) var/pos_z = get_z(src)
// --- Finally, tag the actual signal with the appropriate values --- // --- Finally, tag the actual signal with the appropriate values ---
signal.data = list( signal.data = list(
@@ -633,10 +747,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
"message" = "TEST", "message" = "TEST",
"compression" = rand(45, 50), // If the signal is compressed, compress our message too. "compression" = rand(45, 50), // If the signal is compressed, compress our message too.
"traffic" = 0, // dictates the total traffic sum that the signal went through "traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 4, // determines what type of radio input it is: test broadcast "type" = SIGNAL_TEST, // determines what type of radio input it is: test broadcast
"reject" = 0, "reject" = 0,
"done" = 0, "done" = 0,
"level" = pos.z // The level it is being broadcasted at. "level" = pos_z // The level it is being broadcasted at.
) )
signal.frequency = PUB_FREQ// Common channel signal.frequency = PUB_FREQ// Common channel

View File

@@ -219,6 +219,38 @@
temp = "<font color = #666633>-% Frequency changing deactivated %-</font>" temp = "<font color = #666633>-% Frequency changing deactivated %-</font>"
// BROADCASTER
/obj/machinery/telecomms/broadcaster/Options_Menu()
// Note the machine 'displays' 1 higher than overmap_range to save users from the abstraction that range '0' is valid and everything on the same turf.
var/dat = "<br>Broadcast Range (affects power usage)<br><a href='?src=\ref[src];range_down=1'>-</a> [overmap_range+1] gigameter\s <a href='?src=\ref[src];range_up=1'>+</a>"
return dat
/obj/machinery/telecomms/broadcaster/Options_Topic(href, href_list)
if(href_list["range_down"])
if(overmap_range > overmap_range_min)
overmap_range--
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
if(href_list["range_up"])
if(overmap_range < overmap_range_max)
overmap_range++
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
// RECEIVER
/obj/machinery/telecomms/receiver/Options_Menu()
// Note the machine 'displays' 1 higher than overmap_range to save users from the abstraction that range '0' is valid and everything on the same turf.
var/dat = "<br>Receive Range (affects power usage)<br><a href='?src=\ref[src];range_down=1'>-</a> [overmap_range+1] gigameter\s <a href='?src=\ref[src];range_up=1'>+</a>"
return dat
/obj/machinery/telecomms/receiver/Options_Topic(href, href_list)
if(href_list["range_down"])
if(overmap_range > overmap_range_min)
overmap_range--
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
if(href_list["range_up"])
if(overmap_range < overmap_range_max)
overmap_range++
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
/obj/machinery/telecomms/Topic(href, href_list) /obj/machinery/telecomms/Topic(href, href_list)
if(!issilicon(usr)) if(!issilicon(usr))

View File

@@ -68,7 +68,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
var/datum/signal/copy var/datum/signal/copy
if(copysig) if(copysig)
copy = new copy = new
copy.transmission_method = 2 copy.transmission_method = TRANSMISSION_SUBSPACE
copy.frequency = signal.frequency copy.frequency = signal.frequency
copy.data = signal.data.Copy() copy.data = signal.data.Copy()
@@ -141,9 +141,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// Used in auto linking // Used in auto linking
/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) /obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T)
var/turf/position = get_turf(src) var/pos_z = get_z(src)
var/turf/T_position = get_turf(T) var/tpos_z = get_z(T)
if((position.z == T_position.z) || (src.long_range_link && T.long_range_link)) if((pos_z == tpos_z) || (src.long_range_link && T.long_range_link))
for(var/x in autolinkers) for(var/x in autolinkers)
if(T.autolinkers.Find(x)) if(T.autolinkers.Find(x))
if(src != T) if(src != T)
@@ -256,6 +256,12 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
machinetype = 1 machinetype = 1
produces_heat = 0 produces_heat = 0
circuit = /obj/item/weapon/circuitboard/telecomms/receiver circuit = /obj/item/weapon/circuitboard/telecomms/receiver
//Vars only used if you're using the overmap
var/overmap_range = 0
var/overmap_range_min = 0
var/overmap_range_max = 5
var/list/linked_radios_weakrefs = list()
/obj/machinery/telecomms/receiver/Initialize() /obj/machinery/telecomms/receiver/Initialize()
. = ..() . = ..()
@@ -267,8 +273,12 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
RefreshParts() RefreshParts()
/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal) /obj/machinery/telecomms/receiver/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
return
linked_radios_weakrefs |= weakref(R)
/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal)
if(!on) // has to be on to receive messages if(!on) // has to be on to receive messages
return return
if(!signal) if(!signal)
@@ -276,7 +286,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
if(!check_receive_level(signal)) if(!check_receive_level(signal))
return return
if(signal.transmission_method == 2) if(signal.transmission_method == TRANSMISSION_SUBSPACE)
if(is_freq_listening(signal)) // detect subspace signals if(is_freq_listening(signal)) // detect subspace signals
@@ -288,14 +298,31 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
relay_information(signal, "/obj/machinery/telecomms/bus") // Send it to a bus instead, if it's linked to one relay_information(signal, "/obj/machinery/telecomms/bus") // Send it to a bus instead, if it's linked to one
/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal) /obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal)
// If it's a direct message from a bluespace radio, we eat it and convert it into a subspace signal locally
if(signal.transmission_method == TRANSMISSION_BLUESPACE)
var/obj/item/device/radio/R = signal.data["radio"]
if(signal.data["level"] != listening_level) //Who're you?
if(!(weakref(R) in linked_radios_weakrefs))
signal.data["reject"] = 1
return 0
//We'll resend this for you
signal.data["level"] = z
signal.transmission_method = TRANSMISSION_SUBSPACE
return 1
//Where can we hear?
var/list/listening_levels = using_map.get_map_levels(listening_level, TRUE, overmap_range)
// We couldn't 'hear' it, maybe a relay linked to our hub can 'hear' it
if(!(signal.data["level"] in listening_levels))
for(var/obj/machinery/telecomms/hub/H in links) for(var/obj/machinery/telecomms/hub/H in links)
var/list/connected_levels = list() var/list/relayed_levels = list()
for(var/obj/machinery/telecomms/relay/R in H.links) for(var/obj/machinery/telecomms/relay/R in H.links)
if(R.can_receive(signal)) if(R.can_receive(signal))
connected_levels |= R.listening_level relayed_levels |= R.listening_level
if(signal.data["level"] in connected_levels) if(signal.data["level"] in relayed_levels)
return 1 return 1
return 0 return 0
return 1 return 1
@@ -405,7 +432,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// Add our level and send it back // Add our level and send it back
if(can_send(signal)) if(can_send(signal))
signal.data["level"] |= listening_level signal.data["level"] |= using_map.get_map_levels(listening_level)
// Checks to see if it can send/receive. // Checks to see if it can send/receive.
@@ -602,7 +629,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
totaltraffic += traffic // add current traffic to total traffic totaltraffic += traffic // add current traffic to total traffic
//Is this a test signal? Bypass logging //Is this a test signal? Bypass logging
if(signal.data["type"] != 4) if(signal.data["type"] != SIGNAL_TEST)
// If signal has a message and appropriate frequency // If signal has a message and appropriate frequency

View File

@@ -52,6 +52,13 @@ var/global/list/default_medbay_channels = list(
w_class = ITEMSIZE_SMALL w_class = ITEMSIZE_SMALL
show_messages = 1 show_messages = 1
// Bluespace radios talk directly to telecomms equipment
var/bluespace_radio = FALSE
var/weakref/bs_tx_weakref //Maybe misleading, this is the device to TRANSMIT TO
// For mappers or subtypes, to start them prelinked to these devices
var/bs_tx_preload_id
var/bs_rx_preload_id
matter = list("glass" = 25,DEFAULT_WALL_MATERIAL = 75) matter = list("glass" = 25,DEFAULT_WALL_MATERIAL = 75)
var/const/FREQ_LISTENING = 1 var/const/FREQ_LISTENING = 1
var/list/internal_channels var/list/internal_channels
@@ -90,6 +97,43 @@ var/global/list/default_medbay_channels = list(
for (var/ch_name in channels) for (var/ch_name in channels)
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
if(bluespace_radio)
if(bs_tx_preload_id)
//Try to find a receiver
for(var/obj/machinery/telecomms/receiver/RX in telecomms_list)
if(RX.id == bs_tx_preload_id) //Again, bs_tx is the thing to TRANSMIT TO, so a receiver.
bs_tx_weakref = weakref(RX)
RX.link_radio(src)
break
//Hmm, howabout an AIO machine
if(!bs_tx_weakref)
for(var/obj/machinery/telecomms/allinone/AIO in telecomms_list)
if(AIO.id == bs_tx_preload_id)
bs_tx_weakref = weakref(AIO)
AIO.link_radio(src)
break
if(!bs_tx_weakref)
testing("A radio [src] at [x],[y],[z] specified bluespace prelink IDs, but the machines with corresponding IDs ([bs_tx_preload_id], [bs_rx_preload_id]) couldn't be found.")
if(bs_rx_preload_id)
var/found = 0
//Try to find a transmitter
for(var/obj/machinery/telecomms/broadcaster/TX in telecomms_list)
if(TX.id == bs_rx_preload_id) //Again, bs_rx is the thing to RECEIVE FROM, so a transmitter.
TX.link_radio(src)
found = 1
break
//Hmm, howabout an AIO machine
if(!found)
for(var/obj/machinery/telecomms/allinone/AIO in telecomms_list)
if(AIO.id == bs_rx_preload_id)
AIO.link_radio(src)
found = 1
break
if(!found)
testing("A radio [src] at [x],[y],[z] specified bluespace prelink IDs, but the machines with corresponding IDs ([bs_tx_preload_id], [bs_rx_preload_id]) couldn't be found.")
/obj/item/device/radio/attack_self(mob/user as mob) /obj/item/device/radio/attack_self(mob/user as mob)
user.set_machine(src) user.set_machine(src)
interact(user) interact(user)
@@ -240,11 +284,10 @@ var/global/list/default_medbay_channels = list(
if(.) if(.)
SSnanoui.update_uis(src) SSnanoui.update_uis(src)
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT /obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/list/zlevels) //BS12 EDIT
var/datum/radio_frequency/connection = null var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0) if(channel && channels && channels.len > 0)
if (channel == "department") if (channel == "department")
//to_world("DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"")
channel = channels[1] channel = channels[1]
connection = secure_radio_connections[channel] connection = secure_radio_connections[channel]
else else
@@ -253,12 +296,15 @@ var/global/list/default_medbay_channels = list(
if (!istype(connection)) if (!istype(connection))
return return
if(!LAZYLEN(zlevels))
zlevels = list(0)
var/static/mob/living/silicon/ai/announcer/A = new /mob/living/silicon/ai/announcer(src, null, null, 1) var/static/mob/living/silicon/ai/announcer/A = new /mob/living/silicon/ai/announcer(src, null, null, 1)
A.SetName(from) A.SetName(from)
Broadcast_Message(connection, A, Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src, 0, "*garbled automated announcement*", src,
message, from, "Automated Announcement", from, "synthesized voice", message, from, "Automated Announcement", from, "synthesized voice",
4, 0, list(0), connection.frequency, "states") 4, 0, zlevels, connection.frequency, "states")
// Interprets the message mode when talking into a radio, possibly returning a connection datum // Interprets the message mode when talking into a radio, possibly returning a connection datum
/obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, message, message_mode) /obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, message, message_mode)
@@ -310,7 +356,7 @@ var/global/list/default_medbay_channels = list(
if (!istype(connection)) if (!istype(connection))
return FALSE return FALSE
var/turf/position = get_turf(src) var/pos_z = get_z(src)
//#### Tagging the signal with all appropriate identity values ####// //#### Tagging the signal with all appropriate identity values ####//
@@ -359,20 +405,8 @@ var/global/list/default_medbay_channels = list(
jobname = "Unknown" jobname = "Unknown"
voicemask = 1 voicemask = 1
/* ###### Radio headsets can only broadcast through subspace ###### */
if(subspace_transmission)
var/list/jamming = is_jammed(src)
if(jamming)
var/distance = jamming["distance"]
to_chat(M, "<span class='danger'>[bicon(src)] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.</span>")
return FALSE
// First, we want to generate a new radio signal // First, we want to generate a new radio signal
var/datum/signal/signal = new var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission.
// transmission_method could probably be enumerated through #define. Would be neater.
// --- Finally, tag the actual signal with the appropriate values --- // --- Finally, tag the actual signal with the appropriate values ---
signal.data = list( signal.data = list(
@@ -397,15 +431,46 @@ var/global/list/default_medbay_channels = list(
"radio" = src, // stores the radio used for transmission "radio" = src, // stores the radio used for transmission
"slow" = 0, // how much to sleep() before broadcasting - simulates net lag "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
"traffic" = 0, // dictates the total traffic sum that the signal went through "traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 0, // determines what type of radio input it is: normal broadcast "type" = SIGNAL_NORMAL, // determines what type of radio input it is: normal broadcast
"server" = null, // the last server to log this signal "server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = position.z, // The source's z level "level" = pos_z, // The source's z level
"language" = speaking, "language" = speaking,
"verb" = verb "verb" = verb
) )
signal.frequency = connection.frequency // Quick frequency set signal.frequency = connection.frequency // Quick frequency set
var/filter_type = DATA_LOCAL //If we end up having to send it the old fashioned way, it's with this data var.
/* ###### Bluespace radios talk directly to receivers (and only directly to receivers) ###### */
if(bluespace_radio)
//Nothing to transmit to
if(!bs_tx_weakref)
to_chat(loc, "<span class='warning'>\The [src] buzzes to inform you of the lack of a functioning connection.</span>")
return FALSE
var/obj/machinery/telecomms/tx_to = bs_tx_weakref.resolve()
//Was linked, now destroyed or something
if(!tx_to)
bs_tx_weakref = null
to_chat(loc, "<span class='warning'>\The [src] buzzes to inform you of the lack of a functioning connection.</span>")
return FALSE
//Transmitted in the blind. If we get a message back, cool. If not, oh well.
signal.transmission_method = TRANSMISSION_BLUESPACE
return tx_to.receive_signal(signal)
/* ###### Radios with subspace_transmission can only broadcast through subspace (unless they have adhoc_fallback) ###### */
else if(subspace_transmission)
var/list/jamming = is_jammed(src)
if(jamming)
var/distance = jamming["distance"]
to_chat(M, "<span class='danger'>[bicon(src)] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.</span>")
return FALSE
// First, we want to generate a new radio signal
signal.transmission_method = TRANSMISSION_SUBSPACE
//#### Sending the signal to all subspace receivers ####// //#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in telecomms_list) for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
@@ -416,84 +481,47 @@ var/global/list/default_medbay_channels = list(
R.receive_signal(signal) R.receive_signal(signal)
// Receiving code can be located in Telecommunications.dm // Receiving code can be located in Telecommunications.dm
if(signal.data["done"] && position.z in signal.data["level"]) if(signal.data["done"] && (pos_z in signal.data["level"]))
return TRUE //Huzzah, sent via subspace return TRUE //Huzzah, sent via subspace
else if(adhoc_fallback) //Less huzzah, we have to fallback else if(adhoc_fallback) //Less huzzah, we have to fallback
to_chat(loc, "<span class='warning'>\The [src] pings as it falls back to local radio transmission.</span>") to_chat(loc, "<span class='warning'>\The [src] pings as it falls back to local radio transmission.</span>")
subspace_transmission = FALSE subspace_transmission = FALSE
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message, displayname, jobname, real_name, M.voice_name, else //Oh well
signal.transmission_method, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb,speaking) return FALSE
/* ###### Intercoms and station-bounced radios ###### */ /* ###### Intercoms and station-bounced radios ###### */
else
var/filter_type = 2
/* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */ /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
if(istype(src, /obj/item/device/radio/intercom)) if(istype(src, /obj/item/device/radio/intercom))
filter_type = 1 filter_type = DATA_INTERCOM
var/datum/signal/signal = new
signal.transmission_method = 2
/* --- Try to send a normal subspace broadcast first */ /* --- Try to send a normal subspace broadcast first */
signal.transmission_method = TRANSMISSION_SUBSPACE
signal.data = list( signal.data["compression"] = 0
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = displayname, // the mob's display name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
"vname" = M.voice_name, // the name to display if the voice wasn't understood
"vmask" = voicemask, // 1 if the mob is using a voice gas mas
"compression" = 0, // uncompressed radio signal
"message" = message, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
"slow" = 0,
"traffic" = 0,
"type" = 0,
"server" = null,
"reject" = 0,
"level" = position.z,
"language" = speaking,
"verb" = verb
)
signal.frequency = connection.frequency // Quick frequency set
for(var/obj/machinery/telecomms/receiver/R in telecomms_list) for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal) R.receive_signal(signal)
if(signal.data["done"] && position.z in signal.data["level"]) // Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
if(signal.data["done"] && pos_z in signal.data["level"])
if(adhoc_fallback) if(adhoc_fallback)
to_chat(loc, "<span class='notice'>\The [src] pings as it reestablishes subspace communications.</span>") to_chat(loc, "<span class='notice'>\The [src] pings as it reestablishes subspace communications.</span>")
subspace_transmission = TRUE subspace_transmission = TRUE
// we're done here. // we're done here.
return TRUE return TRUE
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level. //Nothing handled any sort of remote radio-ing and returned before now, just squawk on this zlevel.
// Send a mundane broadcast with limited targets:
//THIS IS TEMPORARY. YEAH RIGHT
if(!connection) return FALSE //~Carn
//VOREStation Add Start
if(bluespace_radio)
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message, displayname, jobname, real_name, M.voice_name, src, message, displayname, jobname, real_name, M.voice_name,
0, signal.data["compression"], list(0), connection.frequency,verb,speaking) filter_type, signal.data["compression"], using_map.get_map_levels(pos_z), connection.frequency, verb, speaking)
//VOREStation Add End
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb,speaking)
/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null) /obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null)
@@ -502,24 +530,11 @@ var/global/list/default_medbay_channels = list(
talk_into(M, msg,null,verb,speaking) talk_into(M, msg,null,verb,speaking)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
if ((R.frequency == frequency && message))
return TRUE
else if
else
return null
return
*/
/obj/item/device/radio/proc/receive_range(freq, level) /obj/item/device/radio/proc/receive_range(freq, level)
// check if this radio can receive on the given frequency, and if so, // check if this radio can receive on the given frequency, and if so,
// what the range is in which mobs will hear the radio // what the range is in which mobs will hear the radio
// returns: -1 if can't receive, range otherwise // returns: -1 if can't receive, range otherwise
if(wires.IsIndexCut(WIRE_RECEIVE)) if(wires.IsIndexCut(WIRE_RECEIVE))
return -1 return -1
if(!listening) if(!listening)
@@ -527,8 +542,8 @@ var/global/list/default_medbay_channels = list(
if(is_jammed(src)) if(is_jammed(src))
return -1 return -1
if(!(0 in level)) if(!(0 in level))
var/turf/position = get_turf(src) var/pos_z = get_z(src)
if((!position || !(position.z in level)) && !bluespace_radio) //VOREStation Edit if(!(pos_z in level))
return -1 return -1
if(freq in ANTAG_FREQS) if(freq in ANTAG_FREQS)
if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys

View File

@@ -0,0 +1,153 @@
/obj/item/device/bluespaceradio
name = "bluespace radio"
desc = "A powerful radio that uses a tiny bluespace wormhole to send signals directly to subspace receivers and transmitters, bypassing the limitations of subspace."
icon = 'icons/obj/radio.dmi'
icon_state = "radiopack"
item_state = "radiopack"
slot_flags = SLOT_BACK
force = 5
throwforce = 6
preserve_item = 1
w_class = ITEMSIZE_LARGE
action_button_name = "Remove/Replace Handset"
var/obj/item/device/radio/bluespacehandset/linked/handset = /obj/item/device/radio/bluespacehandset/linked
/obj/item/device/bluespaceradio/Initialize()
. = ..()
if(ispath(handset))
handset = new handset(src, src)
/obj/item/device/bluespaceradio/Destroy()
. = ..()
QDEL_NULL(handset)
/obj/item/device/bluespaceradio/ui_action_click()
toggle_handset()
/obj/item/device/bluespaceradio/attack_hand(var/mob/user)
if(loc == user)
toggle_handset()
else
..()
/obj/item/device/bluespaceradio/MouseDrop()
if(ismob(loc))
if(!CanMouseDrop(src))
return
var/mob/M = loc
if(!M.unEquip(src))
return
add_fingerprint(usr)
M.put_in_any_hand_if_possible(src)
/obj/item/device/bluespaceradio/attackby(var/obj/item/weapon/W, var/mob/user, var/params)
if(W == handset)
reattach_handset(user)
else
return ..()
/obj/item/device/bluespaceradio/verb/toggle_handset()
set name = "Toggle Handset"
set category = "Object"
var/mob/living/carbon/human/user = usr
if(!handset)
to_chat(user, "<span class='warning'>The handset is missing!</span>")
return
if(handset.loc != src)
reattach_handset(user) //Remove from their hands and back onto the defib unit
return
if(!slot_check())
to_chat(user, "<span class='warning'>You need to equip [src] before taking out [handset].</span>")
else
if(!usr.put_in_hands(handset)) //Detach the handset into the user's hands
to_chat(user, "<span class='warning'>You need a free hand to hold the handset!</span>")
update_icon() //success
//checks that the base unit is in the correct slot to be used
/obj/item/device/bluespaceradio/proc/slot_check()
var/mob/M = loc
if(!istype(M))
return 0 //not equipped
if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_back) == src)
return 1
if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_s_store) == src)
return 1
return 0
/obj/item/device/bluespaceradio/dropped(var/mob/user)
..()
reattach_handset(user) //handset attached to a base unit should never exist outside of their base unit or the mob equipping the base unit
/obj/item/device/bluespaceradio/proc/reattach_handset(var/mob/user)
if(!handset) return
if(ismob(handset.loc))
var/mob/M = handset.loc
if(M.drop_from_inventory(handset, src))
to_chat(user, "<span class='notice'>\The [handset] snaps back into the main unit.</span>")
else
handset.forceMove(src)
//Subspace Radio Handset
/obj/item/device/radio/bluespacehandset
name = "bluespace radio handset"
desc = "A large walkie talkie attached to the bluespace radio by a retractable cord. It sits comfortably on a slot in the radio when not in use."
bluespace_radio = TRUE
icon_state = "signaller"
slot_flags = null
w_class = ITEMSIZE_LARGE
canhear_range = 1
/obj/item/device/radio/bluespacehandset/linked
var/obj/item/device/bluespaceradio/base_unit
/obj/item/device/radio/bluespacehandset/linked/Initialize(mapload, var/obj/item/device/bluespaceradio/radio)
base_unit = radio
. = ..()
/obj/item/device/radio/bluespacehandset/linked/Destroy()
if(base_unit)
//ensure the base unit's icon updates
if(base_unit.handset == src)
base_unit.handset = null
base_unit = null
return ..()
/obj/item/device/radio/bluespacehandset/linked/dropped(var/mob/user)
..() //update twohanding
if(base_unit)
base_unit.reattach_handset(user) //handset attached to a base unit should never exist outside of their base unit or the mob equipping the base unit
/obj/item/device/radio/bluespacehandset/linked/receive_range(var/freq, var/list/level)
//Only care about megabroadcasts or things that are targeted at us
if(!(0 in level))
return -1
if(wires.IsIndexCut(WIRE_RECEIVE))
return -1
if(!listening)
return -1
if(is_jammed(src))
return -1
if (!on)
return -1
if (!freq) //recieved on main frequency
if (!listening)
return -1
else
var/accept = (freq==frequency && listening)
if (!accept)
for (var/ch_name in channels)
var/datum/radio_frequency/RF = secure_radio_connections[ch_name]
if (RF && RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
accept = 1
break
if (!accept)
return -1
return canhear_range

View File

@@ -525,7 +525,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
//If we're announcing their arrival //If we're announcing their arrival
if(announce) if(announce)
AnnounceArrival(new_character, new_character.mind.assigned_role) AnnounceArrival(new_character, new_character.mind.assigned_role, "Common", new_character.z)
log_admin("[admin] has spawned [player_key]'s character [new_character.real_name].") log_admin("[admin] has spawned [player_key]'s character [new_character.real_name].")
message_admins("[admin] has spawned [player_key]'s character [new_character.real_name].", 1) message_admins("[admin] has spawned [player_key]'s character [new_character.real_name].", 1)

View File

@@ -419,18 +419,19 @@
//Grab some data from the character prefs for use in random news procs. //Grab some data from the character prefs for use in random news procs.
AnnounceArrival(character, rank, join_message) AnnounceArrival(character, rank, join_message, announce_channel, character.z)
else else
AnnounceCyborg(character, rank, join_message) AnnounceCyborg(character, rank, join_message, announce_channel, character.z)
qdel(src) qdel(src)
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message) /mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message, var/channel, var/zlevel)
if (ticker.current_state == GAME_STATE_PLAYING) if (ticker.current_state == GAME_STATE_PLAYING)
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE) : null
if(character.mind.role_alt_title) if(character.mind.role_alt_title)
rank = character.mind.role_alt_title rank = character.mind.role_alt_title
// can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc. // can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc.
global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer", channel, zlevels)
/mob/new_player/proc/LateChoices() /mob/new_player/proc/LateChoices()
var/name = client.prefs.be_random_name ? "friend" : client.prefs.real_name var/name = client.prefs.be_random_name ? "friend" : client.prefs.real_name

View File

@@ -79,20 +79,25 @@ var/global/ntnet_card_uid = 1
return 0 return 0
if(holder2) if(holder2)
var/turf/T = get_turf(holder2) var/holderz = get_z(holder2)
if(!istype(T)) //no reception in nullspace if(!holderz) //no reception in nullspace
return 0 return 0
if(T.z in using_map.station_levels) var/list/zlevels_in_range = using_map.get_map_levels(holderz, long_range)
// Computer is on station. Low/High signal depending on what type of network card you have var/best = 0
if(long_range) for(var/relay in ntnet_global.relays)
return 2 var/obj/machinery/ntnet_relay/R = relay
else //Relay is down
return 1 if(!R.operable())
if(T.z in using_map.contact_levels) //not on station, but close enough for radio signal to travel continue
if(long_range) // Computer is not on station, but it has upgraded network card. Low signal. //We're on the same z
return 1 if(R.z == holderz)
best = 2
return 0 // Computer is not on station and does not have upgraded network card. No signal. break // No point in going further
//Not on the same z but within range anyway
if(R.z in zlevels_in_range)
best = 1
return best
return 0 // No computer!
/obj/item/weapon/computer_hardware/network_card/Destroy() /obj/item/weapon/computer_hardware/network_card/Destroy()
if(holder2 && (holder2.network_card == src)) if(holder2 && (holder2.network_card == src))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -159,20 +159,44 @@ var/list/all_maps = list()
empty_levels = list(world.maxz) empty_levels = list(world.maxz)
return pick(empty_levels) return pick(empty_levels)
// Get the list of zlevels that a computer on srcz can see maps of (for power/crew monitor, cameras, etc) // Get a list of 'nearby' or 'connected' zlevels.
// The long_range parameter expands the coverage. Default is to return map_levels for long range otherwise just srcz. // You should at least return a list with the given z if nothing else.
// zLevels outside station_levels will return an empty list. /datum/map/proc/get_map_levels(var/srcz, var/long_range = FALSE, var/om_range = -1)
/datum/map/proc/get_map_levels(var/srcz, var/long_range = TRUE) //Overmap behavior
if (long_range && (srcz in map_levels)) if(use_overmap)
return map_levels //Get what sector we're in
else if (srcz in station_levels) var/obj/effect/overmap/visitable/O = get_overmap_sector(srcz)
if(!istype(O))
//Not in a sector, just the passed zlevel
return list(srcz) return list(srcz)
//Just the sector we're in
if(om_range == -1)
return O.map_z.Copy()
//Otherwise every sector we're on top of
var/list/connections = list()
var/turf/T = get_turf(O)
var/turfrange = long_range ? max(0, om_range) : om_range
for(var/obj/effect/overmap/visitable/V in range(turfrange, T))
connections += V.map_z // Adding list to list adds contents
return connections
//Traditional behavior
else else
return list() //If long range, and they're at least in contact levels, return contact levels.
if (long_range && (srcz in contact_levels))
return contact_levels.Copy()
//If in station levels, return station levels
else if (srcz in station_levels)
return station_levels.Copy()
//Just give them back their zlevel
else
return list(srcz)
/datum/map/proc/get_zlevel_name(var/index) /datum/map/proc/get_zlevel_name(var/index)
var/datum/map_z_level/Z = zlevels["[index]"] var/datum/map_z_level/Z = zlevels["[index]"]
return Z.name return Z?.name
// Access check is of the type requires one. These have been carefully selected to avoid allowing the janitor to see channels he shouldn't // Access check is of the type requires one. These have been carefully selected to avoid allowing the janitor to see channels he shouldn't
// This list needs to be purged but people insist on adding more cruft to the radio. // This list needs to be purged but people insist on adding more cruft to the radio.

View File

@@ -1128,6 +1128,7 @@
#include "code\game\objects\items\devices\radio\jammer_vr.dm" #include "code\game\objects\items\devices\radio\jammer_vr.dm"
#include "code\game\objects\items\devices\radio\radio.dm" #include "code\game\objects\items\devices\radio\radio.dm"
#include "code\game\objects\items\devices\radio\radio_vr.dm" #include "code\game\objects\items\devices\radio\radio_vr.dm"
#include "code\game\objects\items\devices\radio\radiopack.dm"
#include "code\game\objects\items\robot\robot_items.dm" #include "code\game\objects\items\robot\robot_items.dm"
#include "code\game\objects\items\robot\robot_parts.dm" #include "code\game\objects\items\robot\robot_parts.dm"
#include "code\game\objects\items\robot\robot_upgrades.dm" #include "code\game\objects\items\robot\robot_upgrades.dm"