Files
Paradise/code/game/objects/radio/radio.dm
T
Erthilo 8954b5aa2b TG: Doohl: Readme please:
This 'fixes' a runtime that occurs when intercomms are tuned to frequencies they
probably shouldn't be able to. I'm guessing there's no connection datum defined
for those frequencies. Although, I'm clueless at telecomms stuff and I don't
want to break anything.

runtime error: Cannot read null.frequency
proc name: Broadcast Message (/proc/Broadcast_Message)
usr: null
src: null
call stack:
 Broadcast Message(null, S.I.G.M.A. (/mob/living/silicon/ai), 0, null, General
Listening Channel (/obj/item/device/radio/intercom), "J.R. Bob Dobbs has signed
up a...", "S.I.G.M.A.", "AI", "S.I.G.M.A.", "synthesized voice", 1, 0)
 General Listening Channel (/obj/item/device/radio/intercom): talk
into(S.I.G.M.A. (/mob/living/silicon/ai), "J.R. Bob Dobbs has signed up a...",
null)
 General Listening Channel (/obj/item/device/radio/intercom): hear
talk(S.I.G.M.A. (/mob/living/silicon/ai), "J.R. Bob Dobbs has signed up a...")
 General Listening Channel (/obj/item/device/radio/intercom): hear
talk(S.I.G.M.A. (/mob/living/silicon/ai), "J.R. Bob Dobbs has signed up a...")
 S.I.G.M.A. (/mob/living/silicon/ai): say("J.R. Bob Dobbs has signed up a...")

I reproduced the problem on the centre private-intercomm in the AI upload by
tuning it down to about 121.7 or something.
Revision: r3474
Author: 	 elly1...@rocketmail.com

P.S. Sorry for the nag but Agouri would down-vote all the things if I hadn't
tagged your name up there. :3

Also, removed some misplaced areas from the centcomm z-level (Quartermaster's
storage and a teleport one)
2012-05-05 22:05:50 +01:00

739 lines
24 KiB
Plaintext

var/GLOBAL_RADIO_TYPE = 1 // radio type to use
// 0 = old radios
// 1 = new radios (subspace technology)
/obj/item/device/radio
icon = 'radio.dmi'
name = "station bounced radio"
suffix = "\[3\]"
icon_state = "walkietalkie"
item_state = "walkietalkie"
var
on = 1 // 0 for off
last_transmission
frequency = 1459 //common chat
traitor_frequency = 0 //tune to frequency to unlock traitor supplies
canhear_range = 3 // the range which mobs can hear this radio from
obj/item/device/radio/patch_link = null
obj/item/device/uplink/radio/traitorradio = null
wires = WIRE_SIGNAL | WIRE_RECEIVE | WIRE_TRANSMIT
b_stat = 0
broadcasting = 0
listening = 1
freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
subspace_transmission = 0
// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
flags = 450 // hello i'm a fucking idiot why is this 450?? CODE GODS PLEASE EXPLAIN~
throw_speed = 2
throw_range = 9
w_class = 2
g_amt = 25
m_amt = 75
var/const
WIRE_SIGNAL = 1 //sends a signal, like to set off a bomb or electrocute someone
WIRE_RECEIVE = 2
WIRE_TRANSMIT = 4
TRANSMISSION_DELAY = 5 // only 2/second/radio
FREQ_LISTENING = 1
//FREQ_BROADCASTING = 2
/obj/item/device/radio
var
datum/radio_frequency/radio_connection
list/datum/radio_frequency/secure_radio_connections = new
proc
set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
/obj/item/device/radio/New()
..()
if(radio_controller)
initialize()
// If intercom: do a local power check loop
if(istype(src, /obj/item/device/radio/intercom))
spawn(5)
checkpower()
/obj/item/device/radio/initialize()
if(freerange)
if(frequency < 1200 || frequency > 1600)
frequency = sanitize_frequency(frequency)
else if (frequency < 1441 || frequency > 1489)
world.log << "[src] ([type]) has a frequency of [frequency], sanitizing."
frequency = sanitize_frequency(frequency)
set_frequency(frequency)
for (var/ch_name in channels)
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
/obj/item/device/radio/attack_self(mob/user as mob)
user.machine = src
interact(user)
/obj/item/device/radio/proc/interact(mob/user as mob)
if(!on)
return
var/dat = {"
<html><head><title>[src]</title></head><body><TT>
Microphone: [broadcasting ? "<A href='byond://?src=\ref[src];talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];talk=1'>Disengaged</A>"]<BR>
Speaker: [listening ? "<A href='byond://?src=\ref[src];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];listen=1'>Disengaged</A>"]<BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A>
[format_frequency(frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
"}
for (var/ch_name in channels)
dat+=text_sec_channel(ch_name, channels[ch_name])
dat+={"[text_wires()]</TT></body></html>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
/obj/item/device/radio/proc/text_wires()
if (!b_stat)
return ""
return {"
<hr>
Green Wire: <A href='byond://?src=\ref[src];wires=4'>[(wires & 4) ? "Cut" : "Mend"] Wire</A><BR>
Red Wire: <A href='byond://?src=\ref[src];wires=2'>[(wires & 2) ? "Cut" : "Mend"] Wire</A><BR>
Blue Wire: <A href='byond://?src=\ref[src];wires=1'>[(wires & 1) ? "Cut" : "Mend"] Wire</A><BR>
"}
/obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat)
var/list = !!(chan_stat&FREQ_LISTENING)!=0
return {"
<B>[chan_name]</B><br>
Speaker: <A href='byond://?src=\ref[src];ch_name=[chan_name];listen=[!list]'>[list ? "Engaged" : "Disengaged"]</A><BR>
"}
/obj/item/device/radio/proc/checkpower()
// Simple loop, checks for power. Strictly for intercoms
while(src)
if(!src.loc)
on = 0
else
var/area/A = src.loc.loc
if(!A || !isarea(A) || !A.master)
on = 0
else
on = A.master.powered(EQUIP) // set "on" to the power status
if(!on)
icon_state = "intercom-p"
else
icon_state = "intercom"
sleep(30)
/obj/item/device/radio/Topic(href, href_list)
//..()
if (usr.stat || !on)
return
if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) ))))
usr << browse(null, "window=radio")
return
usr.machine = src
if (href_list["track"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
if(A && target)
A.ai_actual_track(target)
return
else if (href_list["faketrack"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
if(A && target)
A:cameraFollow = target
A << text("Now tracking [] on camera.", target.name)
if (usr.machine == null)
usr.machine = usr
while (usr:cameraFollow == target)
usr << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
sleep(40)
continue
return
else if (href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
if (!freerange || (frequency < 1200 || frequency > 1600))
new_frequency = sanitize_frequency(new_frequency)
set_frequency(new_frequency)
if (traitor_frequency && frequency == traitor_frequency)
usr.machine = null
usr << browse(null, "window=radio")
// now transform the regular radio, into a (disguised)syndicate uplink!
var/obj/item/device/uplink/radio/T = traitorradio
var/obj/item/device/radio/R = src
R.loc = T
T.loc = usr
T.layer = R.layer
R.layer = 0
if (usr.client)
usr.client.screen -= R
if (usr.r_hand == R)
usr.u_equip(R)
usr.r_hand = T
else
usr.u_equip(R)
usr.l_hand = T
R.loc = T
T.attack_self(usr)
return
else if (href_list["talk"])
broadcasting = text2num(href_list["talk"])
else if (href_list["listen"])
var/chan_name = href_list["ch_name"]
if (!chan_name)
listening = text2num(href_list["listen"])
else
if (channels[chan_name] & FREQ_LISTENING)
channels[chan_name] &= ~FREQ_LISTENING
else
channels[chan_name] |= FREQ_LISTENING
else if (href_list["wires"])
var/t1 = text2num(href_list["wires"])
if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) ))
return
if (wires & t1)
wires &= ~t1
else
wires |= t1
if (!( master ))
if (istype(loc, /mob))
interact(loc)
else
updateDialog()
else
if (istype(master.loc, /mob))
interact(master.loc)
else
updateDialog()
add_fingerprint(usr)
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel)
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if (channel == "department")
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
channel = channels[1]
connection = secure_radio_connections[channel]
else
connection = radio_connection
channel = null
if (!istype(connection))
return
if (!connection)
return
Broadcast_Message(connection, new /mob/living/silicon/ai(src), 0, "*garbled automated announcement*",
src, message, from, "Automated Announcement", from, "synthesized voice", 4, 0)
return
/obj/item/device/radio/talk_into(mob/M as mob, message, channel)
if(!on) return // the device has to be on
/* Fix for permacell radios, but kinda eh about actually fixing them.
if(!(src.wires & WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
return
*/
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
/* Quick introduction:
This new radio system uses a very robust FTL signaling technology unoriginally
dubbed "subspace" which is somewhat similar to 'blue-space' but can't
actually transmit large mass. Headsets are the only radio devices capable
of sending subspace transmissions to the Communications Satellite.
A headset sends a signal to a subspace listener/reciever elsewhere in space,
the signal gets processed and logged, and an audible transmission gets sent
to each individual headset.
*/
//#### Grab the connection datum ####//
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if (channel == "department")
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
channel = channels[1]
connection = secure_radio_connections[channel]
else
connection = radio_connection
channel = null
if (!istype(connection))
return
if (!connection)
return
//#### Tagging the signal with all appropriate identity values ####//
// ||-- The mob's name identity --||
var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
var/real_name = M.real_name // mob's real name
var/mobkey = "none" // player key associated with mob
var/voicemask = 0 // the speaker is wearing a voice mask
if(M.client)
mobkey = M.key // assign the mob's key
var/jobname // the mob's "job"
// --- Human: use their actual job ---
if (ishuman(M))
jobname = M:get_assignment()
// --- Carbon Nonhuman ---
else if (iscarbon(M)) // Nonhuman carbon mob
jobname = "No id"
// --- AI ---
else if (isAI(M))
jobname = "AI"
// --- Cyborg ---
else if (isrobot(M))
jobname = "Cyborg"
// --- Personal AI (pAI) ---
else if (istype(M, /mob/living/silicon/pai))
jobname = "Personal AI"
// --- Unidentifiable mob ---
else
jobname = "Unknown"
// --- Modifications to the mob's identity ---
// The mob is disguising their identity:
if (istype(M.wear_mask, /obj/item/clothing/mask/gas/voice))
if(M.wear_mask:vchange)
displayname = M.wear_mask:voice
jobname = "Unknown"
voicemask = 1
/* ###### Radio headsets can only broadcast through subspace ###### */
if(subspace_transmission)
// First, we want to generate a new radio signal
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 ---
signal.data = list(
// Identity-associated tags:
"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" = M.voice_message, // 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 mask
// We store things that would otherwise be kept in the actual mob
// so that they can be logged even AFTER the mob is deleted or something
// Other tags:
"compression" = rand(45,50), // compressed 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, // how much to sleep() before broadcasting - simulates net lag
"traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 0, // determines what type of radio input it is: normal broadcast
"server" = null, // the last server to log this signal
"reject" = 0 // if nonzero, the signal will not be accepted by any broadcasting machinery
)
signal.frequency = connection.frequency // Quick frequency set
//#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in world)
R.receive_signal(signal)
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in world)
R.receive_signal(signal)
// Receiving code can be located in Telecommunications.dm
return
/* ###### Intercoms and station-bounced radios ###### */
var/filter_type = 2
/* --- 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))
filter_type = 1
var/datum/signal/signal = new
signal.transmission_method = 2
/* --- Try to send a normal subspace broadcast first */
signal.data = list(
"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" = M.voice_message, // 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
)
signal.frequency = connection.frequency // Quick frequency set
for(var/obj/machinery/telecomms/receiver/R in world)
R.receive_signal(signal)
sleep(rand(10,25)) // wait a little...
if(signal.data["done"])
// we're done here.
return
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet.
// Send a mundane broadcast with limited targets:
//THIS IS TEMPORARY.
if(!connection) return //~Carn
Broadcast_Message(connection, M, voicemask, M.voice_message,
src, message, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"])
else // OLD RADIO SYSTEMS: By Goons?
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if (channel == "department")
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
channel = channels[1]
connection = secure_radio_connections[channel]
else
connection = radio_connection
channel = null
if (!istype(connection))
return
if (!connection)
return
var/display_freq = connection.frequency
//world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]"
var/eqjobname
if (ishuman(M))
eqjobname = M:get_assignment()
else if (iscarbon(M))
eqjobname = "No id" //only humans can wear ID
else if (isAI(M))
eqjobname = "AI"
else if (isrobot(M))
eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion.
else if (istype(M, /mob/living/silicon/pai))
eqjobname = "Personal AI"
else
eqjobname = "Unknown"
if (!(wires & WIRE_TRANSMIT))
return
var/list/receive = list()
//for (var/obj/item/device/radio/R in radio_connection.devices)
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) // Modified for security headset code -- TLE
//if(R.accept_rad(src, message))
receive |= R.send_hear(display_freq)
//world << "DEBUG: receive.len=[receive.len]"
var/list/heard_masked = list() // masked name or no real name
var/list/heard_normal = list() // normal message
var/list/heard_voice = list() // voice message
var/list/heard_garbled = list() // garbled message
for (var/mob/R in receive)
if (R.client && R.client.STFU_radio) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
continue
if (R.say_understands(M))
if (!ishuman(M) || istype(M.wear_mask, /obj/item/clothing/mask/gas/voice))
heard_masked += R
else
heard_normal += R
else
if (M.voice_message)
heard_voice += R
else
heard_garbled += R
if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled))
var/part_a = "<span class='radio'><span class='name'>"
//var/part_b = "</span><b> \icon[src]\[[format_frequency(frequency)]\]</b> <span class='message'>"
var/freq_text
switch(display_freq)
if(SYND_FREQ)
freq_text = "#unkn"
if(COMM_FREQ)
freq_text = "Command"
if(1351)
freq_text = "Science"
if(1355)
freq_text = "Medical"
if(1357)
freq_text = "Engineering"
if(1359)
freq_text = "Security"
if(1349)
freq_text = "Mining"
if(1347)
freq_text = "Cargo"
//There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
if(!freq_text)
freq_text = format_frequency(display_freq)
var/part_b = "</span><b> \icon[src]\[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
var/part_c = "</span></span>"
if (display_freq==SYND_FREQ)
part_a = "<span class='syndradio'><span class='name'>"
else if (display_freq==COMM_FREQ)
part_a = "<span class='comradio'><span class='name'>"
else if (display_freq in DEPT_FREQS)
part_a = "<span class='deptradio'><span class='name'>"
var/quotedmsg = M.say_quote(message)
//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][M.name][part_blackbox_b][quotedmsg][part_c]"
//var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
for (var/obj/machinery/blackbox_recorder/BR in world)
//BR.messages_admin += blackbox_admin_msg
switch(display_freq)
if(1459)
BR.msg_common += blackbox_msg
if(1351)
BR.msg_science += blackbox_msg
if(1353)
BR.msg_command += blackbox_msg
if(1355)
BR.msg_medical += blackbox_msg
if(1357)
BR.msg_engineering += blackbox_msg
if(1359)
BR.msg_security += blackbox_msg
if(1441)
BR.msg_deathsquad += blackbox_msg
if(1213)
BR.msg_syndicate += blackbox_msg
if(1349)
BR.msg_mining += blackbox_msg
if(1347)
BR.msg_cargo += blackbox_msg
else
BR.messages += blackbox_msg
//End of research and feedback code.
if (length(heard_masked))
var/N = M.name
var/J = eqjobname
if (istype(M.wear_mask, /obj/item/clothing/mask/gas/voice)&&M.wear_mask:vchange)
//To properly have the ninja show up on radio. Could also be useful for similar items.
//Would not be necessary but the mob could be wearing a mask that is not a voice changer.
N = M.wear_mask:voice
J = "Unknown"
var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_masked)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[N] ([J]) </a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
if (length(heard_normal))
var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_normal)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.real_name] ([eqjobname]) </a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
if (length(heard_voice))
var/rendered = "[part_a][M.voice_name][part_b][M.voice_message][part_c]"
for (var/mob/R in heard_voice)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name] ([eqjobname]) </a>[part_b][M.voice_message][part_c]", 2)
else
R.show_message(rendered, 2)
if (length(heard_garbled))
quotedmsg = M.say_quote(stars(message))
var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_voice)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name]</a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
/obj/item/device/radio/hear_talk(mob/M as mob, msg)
if (broadcasting)
talk_into(M, msg)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
if ((R.frequency == frequency && message))
return 1
else if
else
return null
return
*/
/obj/item/device/radio/proc/send_hear(freq)
/*
I'm removing this because this is apparently a REALLY REALLY bad thing and causes
people's transmissions to get cut off. This also means radios have no delay. A
fair price to pay for reliable radios. -- Doohl
if(last_transmission && world.time < (last_transmission + TRANSMISSION_DELAY))
return
last_transmission = world.time
*/
if (!(wires & WIRE_RECEIVE))
return
if (!on)
return
if (!freq) //recieved on main frequency
if (!listening)
return
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.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
accept = 1
break
if (!accept)
return
/* // UURAAAGH ALL THE CPUS, WASTED. ALL OF THEM. NO. -- Doohl
var/turf/T = get_turf(src)
var/list/hear = hearers(1, T)
var/list/V
//find mobs in lockers, cryo and intellicards, brains, MMIs, and so on.
for (var/mob/M in world)
if (isturf(M.loc))
continue //if M can hear us it is already was found by hearers()
if (!M.client)
continue //skip monkeys and leavers
if (!V) //lasy initialisation
V = view(1, T)
if (get_turf(M) in V) //this slow, but I don't think we'd have a lot of wardrobewhores every round --rastaf0
hear+=M
*/
/* Instead, let's individually search potential containers for mobs! More verbose but a LOT more efficient and less laggy */
// Check gamehelpers.dm for the proc definition:
return get_mobs_in_view(canhear_range, src)
/obj/item/device/radio/examine()
set src in view()
..()
if ((in_range(src, usr) || loc == usr))
if (b_stat)
usr.show_message("\blue \the [src] can be attached and modified!")
else
usr.show_message("\blue \the [src] can not be modified or attached!")
return
/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
user.machine = src
if (!( istype(W, /obj/item/weapon/screwdriver) ))
return
b_stat = !( b_stat )
if(!istype(src, /obj/item/device/radio/beacon))
if (b_stat)
user.show_message("\blue The radio can now be attached and modified!")
else
user.show_message("\blue The radio can no longer be modified or attached!")
updateDialog()
//Foreach goto(83)
add_fingerprint(user)
return
else return
/obj/item/device/radio/emp_act(severity)
broadcasting = 0
listening = 0
for (var/ch_name in channels)
channels[ch_name] = 0
..()
/obj/item/device/radio/proc/config(op)
for (var/ch_name in channels)
radio_controller.remove_object(src, radiochannels[ch_name])
secure_radio_connections = new
channels = op
for (var/ch_name in op)
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
return