mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-24 04:28:12 +01:00
Whitespace Standardization [MDB IGNORE] (#15748)
* Update settings * Whitespace changes * Comment out merger hooks in gitattributes Corrupt maps would have to be resolved in repo before hooks could be updated * Revert "Whitespace changes" This reverts commitafbdd1d844. * Whitespace again minus example * Gitignore example changelog * Restore changelog merge setting * Keep older dmi hook attribute until hooks can be updated * update vscode settings too * Renormalize remaining * Revert "Gitignore example changelog" This reverts commitde22ad375d. * Attempt to normalize example.yml (and another file I guess) * Try again
This commit is contained in:
@@ -1,97 +1,97 @@
|
||||
/obj/item/device/communicator/proc/analyze_air()
|
||||
var/list/results = list()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(!isnull(T))
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles
|
||||
if (total_moles)
|
||||
var/o2_level = environment.gas["oxygen"]/total_moles
|
||||
var/n2_level = environment.gas["nitrogen"]/total_moles
|
||||
var/co2_level = environment.gas["carbon_dioxide"]/total_moles
|
||||
var/phoron_level = environment.gas["phoron"]/total_moles
|
||||
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
|
||||
|
||||
// Label is what the entry is describing
|
||||
// Type identifies which unit or other special characters to use
|
||||
// Val is the information reported
|
||||
// Bad_high/_low are the values outside of which the entry reports as dangerous
|
||||
// Poor_high/_low are the values outside of which the entry reports as unideal
|
||||
// Values were extracted from the template itself
|
||||
results = list(
|
||||
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
|
||||
list("entry" = "Temperature", "units" = "\u00B0" + "C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
|
||||
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
|
||||
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
|
||||
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0)
|
||||
)
|
||||
|
||||
if(isnull(results))
|
||||
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
|
||||
return results
|
||||
|
||||
|
||||
// Proc - compile_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the list of newsfeeds, compiled for template processing
|
||||
/obj/item/device/communicator/proc/compile_news()
|
||||
var/list/feeds = list()
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
var/list/messages = list()
|
||||
if(!channel.censored && channel.channel_name != "Vir News Network") //Do not load the 'IC news' channel as it is simply too long.
|
||||
var/index = 0
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
index++
|
||||
var/list/msgdata = list(
|
||||
"author" = FM.author,
|
||||
"body" = FM.body,
|
||||
"img" = null,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"caption" = FM.caption,
|
||||
"index" = index
|
||||
)
|
||||
if(FM.img)
|
||||
msgdata["img"] = icon2base64(FM.img)
|
||||
messages[++messages.len] = msgdata
|
||||
|
||||
feeds[++feeds.len] = list(
|
||||
"name" = channel.channel_name,
|
||||
"censored" = channel.censored,
|
||||
"author" = channel.author,
|
||||
"messages" = messages,
|
||||
"index" = feeds.len + 1 // actually align them, since I guess the population of the list doesn't occur until after the evaluation of the new entry's contents
|
||||
)
|
||||
return feeds
|
||||
|
||||
// Proc - get_recent_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the latest three newscasts, compiled for template processing
|
||||
/obj/item/device/communicator/proc/get_recent_news()
|
||||
var/list/news = list()
|
||||
|
||||
// Compile all the newscasts
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
if(!channel.censored)
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
var/body = replacetext(FM.body, "\n", "<br>")
|
||||
news[++news.len] = list(
|
||||
"channel" = channel.channel_name,
|
||||
"author" = FM.author,
|
||||
"body" = body,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"has_image" = (FM.img != null),
|
||||
"caption" = FM.caption,
|
||||
"time" = FM.post_time
|
||||
)
|
||||
|
||||
// Cut out all but the youngest three
|
||||
if(news.len > 3)
|
||||
sortByKey(news, "time")
|
||||
news.Cut(1, news.len - 2) // Last three have largest timestamps, youngest posts
|
||||
news.Swap(1, 3) // List is sorted in ascending order of timestamp, we want descending
|
||||
|
||||
return news
|
||||
/obj/item/device/communicator/proc/analyze_air()
|
||||
var/list/results = list()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(!isnull(T))
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles
|
||||
if (total_moles)
|
||||
var/o2_level = environment.gas["oxygen"]/total_moles
|
||||
var/n2_level = environment.gas["nitrogen"]/total_moles
|
||||
var/co2_level = environment.gas["carbon_dioxide"]/total_moles
|
||||
var/phoron_level = environment.gas["phoron"]/total_moles
|
||||
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
|
||||
|
||||
// Label is what the entry is describing
|
||||
// Type identifies which unit or other special characters to use
|
||||
// Val is the information reported
|
||||
// Bad_high/_low are the values outside of which the entry reports as dangerous
|
||||
// Poor_high/_low are the values outside of which the entry reports as unideal
|
||||
// Values were extracted from the template itself
|
||||
results = list(
|
||||
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
|
||||
list("entry" = "Temperature", "units" = "\u00B0" + "C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
|
||||
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
|
||||
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
|
||||
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0)
|
||||
)
|
||||
|
||||
if(isnull(results))
|
||||
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
|
||||
return results
|
||||
|
||||
|
||||
// Proc - compile_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the list of newsfeeds, compiled for template processing
|
||||
/obj/item/device/communicator/proc/compile_news()
|
||||
var/list/feeds = list()
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
var/list/messages = list()
|
||||
if(!channel.censored && channel.channel_name != "Vir News Network") //Do not load the 'IC news' channel as it is simply too long.
|
||||
var/index = 0
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
index++
|
||||
var/list/msgdata = list(
|
||||
"author" = FM.author,
|
||||
"body" = FM.body,
|
||||
"img" = null,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"caption" = FM.caption,
|
||||
"index" = index
|
||||
)
|
||||
if(FM.img)
|
||||
msgdata["img"] = icon2base64(FM.img)
|
||||
messages[++messages.len] = msgdata
|
||||
|
||||
feeds[++feeds.len] = list(
|
||||
"name" = channel.channel_name,
|
||||
"censored" = channel.censored,
|
||||
"author" = channel.author,
|
||||
"messages" = messages,
|
||||
"index" = feeds.len + 1 // actually align them, since I guess the population of the list doesn't occur until after the evaluation of the new entry's contents
|
||||
)
|
||||
return feeds
|
||||
|
||||
// Proc - get_recent_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the latest three newscasts, compiled for template processing
|
||||
/obj/item/device/communicator/proc/get_recent_news()
|
||||
var/list/news = list()
|
||||
|
||||
// Compile all the newscasts
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
if(!channel.censored)
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
var/body = replacetext(FM.body, "\n", "<br>")
|
||||
news[++news.len] = list(
|
||||
"channel" = channel.channel_name,
|
||||
"author" = FM.author,
|
||||
"body" = body,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"has_image" = (FM.img != null),
|
||||
"caption" = FM.caption,
|
||||
"time" = FM.post_time
|
||||
)
|
||||
|
||||
// Cut out all but the youngest three
|
||||
if(news.len > 3)
|
||||
sortByKey(news, "time")
|
||||
news.Cut(1, news.len - 2) // Last three have largest timestamps, youngest posts
|
||||
news.Swap(1, 3) // List is sorted in ascending order of timestamp, we want descending
|
||||
|
||||
return news
|
||||
|
||||
@@ -1,185 +1,185 @@
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 4 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received,
|
||||
// text - message text to send if message is of type "text")
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response and IM function.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
|
||||
if(origin_atom in voice_invites)
|
||||
var/user = null
|
||||
if(ismob(origin_atom.loc))
|
||||
user = origin_atom.loc
|
||||
open_connection(user, origin_atom)
|
||||
return
|
||||
else if(origin_atom in voice_requests)
|
||||
return //Spam prevention
|
||||
else
|
||||
request(origin_atom)
|
||||
if(message == "ping")
|
||||
if(network_visibility)
|
||||
var/random = rand(200,350)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
request_im(origin_atom, origin_address, text)
|
||||
return
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/mob/observer/dead/receive_exonet_message(origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(istype(origin_atom, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = origin_atom
|
||||
if(src in comm.voice_invites)
|
||||
comm.open_connection(src)
|
||||
return
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
verb, and select that name to answer the call.</span>")
|
||||
src << 'sound/machines/defib_SafetyOn.ogg'
|
||||
comm.voice_invites |= src
|
||||
if(message == "ping")
|
||||
if(client && client.prefs.communicator_visibility)
|
||||
var/random = rand(450,700)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Received text message from [origin_atom]: <b>\"[text]\"</b></span>")
|
||||
src << 'sound/machines/defib_safetyOff.ogg'
|
||||
exonet_messages.Add("<b>From [origin_atom]:</b><br>[text]")
|
||||
return
|
||||
|
||||
// Proc: request_im()
|
||||
// Parameters: 3 (candidate - the communicator wanting to message the device, origin_address - the address of the sender, text - the message)
|
||||
// Description: Response to a communicator trying to message the device.
|
||||
// Adds them to the list of people that have messaged this device and adds the message to the message list.
|
||||
/obj/item/device/communicator/proc/request_im(var/atom/candidate, var/origin_address, var/text)
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
var/mob/observer/dead/ghost = candidate
|
||||
who = ghost.name
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.im_contacts |= src
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/CIRC = candidate
|
||||
who = CIRC
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else return
|
||||
|
||||
im_contacts |= candidate
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
if(ringer)
|
||||
var/S
|
||||
if(ttone in ttone_sound)
|
||||
S = ttone_sound[ttone]
|
||||
else
|
||||
S = 'sound/machines/twobeep.ogg'
|
||||
|
||||
playsound(src, S, 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *[ttone]*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Message from [who]: <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[candidate]'>Reply</a>)</span>")
|
||||
|
||||
// This is the only Topic the communicators really uses
|
||||
/obj/item/device/communicator/Topic(href, href_list)
|
||||
switch(href_list["action"])
|
||||
if("Reply")
|
||||
var/obj/item/device/communicator/comm = locate(href_list["target"])
|
||||
var/message = tgui_input_text(usr, "Enter your message below.", "Reply")
|
||||
|
||||
if(message)
|
||||
exonet.send_message(comm.exonet.address, "text", message)
|
||||
im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message))
|
||||
log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
|
||||
// Verb: text_communicator()
|
||||
// Parameters: None
|
||||
// Description: Allows a ghost to send a text message to a communicator.
|
||||
/mob/observer/dead/verb/text_communicator()
|
||||
set category = "Ghost"
|
||||
set name = "Text Communicator"
|
||||
set desc = "If there is a communicator available, send a text message to it."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src, "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a text message to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
var/text_message = sanitize(tgui_input_text(src, "What do you want the message to say?", multiline = TRUE))
|
||||
if(text_message && O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "text", text_message)
|
||||
|
||||
to_chat(src, "<span class='notice'>You have sent '[text_message]' to [chosen_communicator].</span>")
|
||||
exonet_messages.Add("<b>To [chosen_communicator]:</b><br>[text_message]")
|
||||
log_pda("(DCOMM: [src]) sent \"[text_message]\" to [chosen_communicator]", src)
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
|
||||
continue
|
||||
if(M == src)
|
||||
continue
|
||||
M.show_message("Comm IM - [src] -> [chosen_communicator]: [text_message]")
|
||||
|
||||
|
||||
|
||||
// Verb: show_text_messages()
|
||||
// Parameters: None
|
||||
// Description: Lets ghosts review messages they've sent or received.
|
||||
/mob/observer/dead/verb/show_text_messages()
|
||||
set category = "Ghost"
|
||||
set name = "Show Text Messages"
|
||||
set desc = "Allows you to see exonet text messages you've sent and received."
|
||||
|
||||
var/HTML = "<html><head><title>Exonet Message Log</title></head><body>"
|
||||
for(var/line in exonet_messages)
|
||||
HTML += line + "<br>"
|
||||
HTML +="</body></html>"
|
||||
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 4 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received,
|
||||
// text - message text to send if message is of type "text")
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response and IM function.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
|
||||
if(origin_atom in voice_invites)
|
||||
var/user = null
|
||||
if(ismob(origin_atom.loc))
|
||||
user = origin_atom.loc
|
||||
open_connection(user, origin_atom)
|
||||
return
|
||||
else if(origin_atom in voice_requests)
|
||||
return //Spam prevention
|
||||
else
|
||||
request(origin_atom)
|
||||
if(message == "ping")
|
||||
if(network_visibility)
|
||||
var/random = rand(200,350)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
request_im(origin_atom, origin_address, text)
|
||||
return
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/mob/observer/dead/receive_exonet_message(origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(istype(origin_atom, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = origin_atom
|
||||
if(src in comm.voice_invites)
|
||||
comm.open_connection(src)
|
||||
return
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
verb, and select that name to answer the call.</span>")
|
||||
src << 'sound/machines/defib_SafetyOn.ogg'
|
||||
comm.voice_invites |= src
|
||||
if(message == "ping")
|
||||
if(client && client.prefs.communicator_visibility)
|
||||
var/random = rand(450,700)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Received text message from [origin_atom]: <b>\"[text]\"</b></span>")
|
||||
src << 'sound/machines/defib_safetyOff.ogg'
|
||||
exonet_messages.Add("<b>From [origin_atom]:</b><br>[text]")
|
||||
return
|
||||
|
||||
// Proc: request_im()
|
||||
// Parameters: 3 (candidate - the communicator wanting to message the device, origin_address - the address of the sender, text - the message)
|
||||
// Description: Response to a communicator trying to message the device.
|
||||
// Adds them to the list of people that have messaged this device and adds the message to the message list.
|
||||
/obj/item/device/communicator/proc/request_im(var/atom/candidate, var/origin_address, var/text)
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
var/mob/observer/dead/ghost = candidate
|
||||
who = ghost.name
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.im_contacts |= src
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/CIRC = candidate
|
||||
who = CIRC
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else return
|
||||
|
||||
im_contacts |= candidate
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
if(ringer)
|
||||
var/S
|
||||
if(ttone in ttone_sound)
|
||||
S = ttone_sound[ttone]
|
||||
else
|
||||
S = 'sound/machines/twobeep.ogg'
|
||||
|
||||
playsound(src, S, 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *[ttone]*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Message from [who]: <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[candidate]'>Reply</a>)</span>")
|
||||
|
||||
// This is the only Topic the communicators really uses
|
||||
/obj/item/device/communicator/Topic(href, href_list)
|
||||
switch(href_list["action"])
|
||||
if("Reply")
|
||||
var/obj/item/device/communicator/comm = locate(href_list["target"])
|
||||
var/message = tgui_input_text(usr, "Enter your message below.", "Reply")
|
||||
|
||||
if(message)
|
||||
exonet.send_message(comm.exonet.address, "text", message)
|
||||
im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message))
|
||||
log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
|
||||
// Verb: text_communicator()
|
||||
// Parameters: None
|
||||
// Description: Allows a ghost to send a text message to a communicator.
|
||||
/mob/observer/dead/verb/text_communicator()
|
||||
set category = "Ghost"
|
||||
set name = "Text Communicator"
|
||||
set desc = "If there is a communicator available, send a text message to it."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src, "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a text message to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
var/text_message = sanitize(tgui_input_text(src, "What do you want the message to say?", multiline = TRUE))
|
||||
if(text_message && O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "text", text_message)
|
||||
|
||||
to_chat(src, "<span class='notice'>You have sent '[text_message]' to [chosen_communicator].</span>")
|
||||
exonet_messages.Add("<b>To [chosen_communicator]:</b><br>[text_message]")
|
||||
log_pda("(DCOMM: [src]) sent \"[text_message]\" to [chosen_communicator]", src)
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
|
||||
continue
|
||||
if(M == src)
|
||||
continue
|
||||
M.show_message("Comm IM - [src] -> [chosen_communicator]: [text_message]")
|
||||
|
||||
|
||||
|
||||
// Verb: show_text_messages()
|
||||
// Parameters: None
|
||||
// Description: Lets ghosts review messages they've sent or received.
|
||||
/mob/observer/dead/verb/show_text_messages()
|
||||
set category = "Ghost"
|
||||
set name = "Show Text Messages"
|
||||
set desc = "Allows you to see exonet text messages you've sent and received."
|
||||
|
||||
var/HTML = "<html><head><title>Exonet Message Log</title></head><body>"
|
||||
for(var/line in exonet_messages)
|
||||
HTML += line + "<br>"
|
||||
HTML +="</body></html>"
|
||||
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
|
||||
|
||||
@@ -1,366 +1,366 @@
|
||||
// Proc: add_communicating()
|
||||
// Parameters: 1 (comm - the communicator to add to communicating)
|
||||
// Description: Used when this communicator gets a new communicator to relay say/me messages to
|
||||
/obj/item/device/communicator/proc/add_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating |= comm
|
||||
listening_objects |= src
|
||||
update_icon()
|
||||
|
||||
// Proc: del_communicating()
|
||||
// Parameters: 1 (comm - the communicator to remove from communicating)
|
||||
// Description: Used when this communicator is being asked to stop relaying say/me messages to another
|
||||
/obj/item/device/communicator/proc/del_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating.Remove(comm)
|
||||
update_icon()
|
||||
|
||||
// Proc: open_connection()
|
||||
// Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device)
|
||||
// Description: Typechecks the candidate, then calls the correct proc for further connecting.
|
||||
/obj/item/device/communicator/proc/open_connection(mob/user, var/atom/candidate)
|
||||
if(isobserver(candidate))
|
||||
voice_invites.Remove(candidate)
|
||||
open_connection_to_ghost(user, candidate)
|
||||
else
|
||||
if(istype(candidate, /obj/item/device/communicator))
|
||||
open_connection_to_communicator(user, candidate)
|
||||
|
||||
// Proc: open_connection_to_communicator()
|
||||
// Parameters: 2 (user - the person who initiated this and will be receiving feedback information, candidate - someone else's communicator)
|
||||
// Description: Adds the candidate and src to each other's communicating lists, allowing messages seen by the devices to be relayed.
|
||||
/obj/item/device/communicator/proc/open_connection_to_communicator(mob/user, var/atom/candidate)
|
||||
if(!istype(candidate, /obj/item/device/communicator))
|
||||
return
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
voice_invites.Remove(candidate)
|
||||
comm.voice_requests.Remove(src)
|
||||
|
||||
if(user)
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connecting to [src].</span>")
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [comm].</span>")
|
||||
sleep(10)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Dialing internally from [station_name()], [system_name()].</span>")
|
||||
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection re-routed to [comm] at [comm.exonet.address].</span>")
|
||||
sleep(40)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection to [comm] at [comm.exonet.address] established.</span>")
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connection to [src] at [exonet.address] established.</span>")
|
||||
sleep(20)
|
||||
|
||||
src.add_communicating(comm)
|
||||
comm.add_communicating(src)
|
||||
|
||||
// Proc: open_connection_to_ghost()
|
||||
// Parameters: 2 (user - the person who initiated this, candidate - the ghost that will be turned into a voice mob)
|
||||
// Description: Pulls the candidate ghost from deadchat, makes a new voice mob, transfers their identity, then their client.
|
||||
/obj/item/device/communicator/proc/open_connection_to_ghost(mob/user, var/mob/candidate)
|
||||
if(!isobserver(candidate))
|
||||
return
|
||||
//Handle moving the ghost into the new shell.
|
||||
announce_ghost_joinleave(candidate, 0, "They are occupying a personal communications device now.")
|
||||
voice_requests.Remove(candidate)
|
||||
voice_invites.Remove(candidate)
|
||||
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
|
||||
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
|
||||
//Do some simple logging since this is a tad risky as a concept.
|
||||
var/msg = "[candidate && candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
|
||||
[user && user.client ? "[user.client.key]" : "*no key*"] ([user ? "[user]" : "*null*"]) at [x],[y],[z]. They have joined as [new_voice.name]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
new_voice.mind = candidate.mind //Transfer the mind, if any.
|
||||
new_voice.ckey = candidate.ckey //Finally, bring the client over.
|
||||
voice_mobs.Add(new_voice)
|
||||
listening_objects |= src
|
||||
|
||||
var/obj/screen/blackness = new() //Makes a black screen, so the candidate can't see what's going on before actually 'connecting' to the communicator.
|
||||
blackness.screen_loc = ui_entire_screen
|
||||
blackness.icon = 'icons/effects/effects.dmi'
|
||||
blackness.icon_state = "1"
|
||||
blackness.mouse_opacity = 2 //Can't see anything!
|
||||
new_voice.client.screen.Add(blackness)
|
||||
|
||||
update_icon()
|
||||
|
||||
//Now for some connection fluff.
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connecting to [candidate].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [src].</span>")
|
||||
sleep(10)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>")
|
||||
sleep(20)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connecting to [station_name()] telecommunications array.</span>")
|
||||
sleep(40)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>")
|
||||
sleep(20)
|
||||
|
||||
//We're connected, no need to hide everything.
|
||||
new_voice.client.screen.Remove(blackness)
|
||||
qdel(blackness)
|
||||
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [src] established.</span>")
|
||||
to_chat(new_voice, "<b>To talk to the person on the other end of the call, just talk normally.</b>")
|
||||
to_chat(new_voice, "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>")
|
||||
to_chat(new_voice, "<b>Remember, your character does not know anything you've learned from observing!</b>")
|
||||
if(new_voice.mind)
|
||||
new_voice.mind.assigned_role = "Disembodied Voice"
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Your communicator is now connected to [candidate]'s communicator.</span>")
|
||||
|
||||
// Proc: close_connection()
|
||||
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
|
||||
// Description: Deletes specific voice_mobs or disconnects communicators, and shows a message to everyone when doing so. If target is null, all communicators
|
||||
// and voice mobs are removed.
|
||||
/obj/item/device/communicator/proc/close_connection(mob/user, var/atom/target, var/reason)
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
return
|
||||
|
||||
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
|
||||
if(target && voice != target) //If no target is inputted, it deletes all of them.
|
||||
continue
|
||||
to_chat(voice, "<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
voice_mobs.Remove(voice)
|
||||
qdel(voice)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators.
|
||||
if(target && comm != target)
|
||||
continue
|
||||
src.del_communicating(comm)
|
||||
comm.del_communicating(src)
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
if(comm.camera && video_source == comm.camera) //We hung up on the person on video
|
||||
end_video()
|
||||
if(camera && comm.video_source == camera) //We hung up on them while they were watching us
|
||||
comm.end_video()
|
||||
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
listening_objects.Remove(src)
|
||||
|
||||
// Proc: request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator wanting to call the device)
|
||||
// Description: Response to a communicator or observer trying to call the device. Adds them to the list of requesters
|
||||
/obj/item/device/communicator/proc/request(var/atom/candidate)
|
||||
if(candidate in voice_requests)
|
||||
return
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
who = candidate.name
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.voice_invites |= src
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
voice_requests |= candidate
|
||||
|
||||
if(ringer)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Communications request from [who].</span>")
|
||||
|
||||
// Proc: del_request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator to be declined)
|
||||
// Description: Declines a request and cleans up both ends
|
||||
/obj/item/device/communicator/proc/del_request(var/atom/candidate)
|
||||
if(!(candidate in voice_requests))
|
||||
return
|
||||
|
||||
if(isobserver(candidate))
|
||||
to_chat(candidate, "<span class='warning'>Your communicator call request was declined.</span>")
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
comm.voice_invites -= src
|
||||
|
||||
voice_requests -= candidate
|
||||
|
||||
//Search for holder of our device.
|
||||
var/mob/living/us = null
|
||||
if(loc && isliving(loc))
|
||||
us = loc
|
||||
|
||||
if(us)
|
||||
to_chat(us, "<span class='notice'>\icon[src][bicon(src)] Declined request.</span>")
|
||||
|
||||
// Proc: see_emote()
|
||||
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
|
||||
// Description: Relays the emote to all linked communicators.
|
||||
/obj/item/device/communicator/see_emote(mob/living/M, text)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[text]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
|
||||
var/dst = get_dist(get_turf(mob),get_turf(comm))
|
||||
if(dst <= video_range)
|
||||
mob.show_message(rendered)
|
||||
else
|
||||
to_chat(mob, "You can barely see some movement on \the [src]'s display.")
|
||||
|
||||
..()
|
||||
|
||||
// Proc: hear_talk()
|
||||
// Parameters: 3 (M - the mob the speech originated from,
|
||||
// list/message_pieces - what is being said w/ baked languages,
|
||||
// verb - the word used to describe how text is being said)
|
||||
// Description: Relays the speech to all linked communicators.
|
||||
/obj/item/device/communicator/hear_talk(mob/M, list/message_pieces, verb)
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
var/list/combined = mob.combine_message(message_pieces, verb, M)
|
||||
var/message = combined["formatted"]
|
||||
var/name_used = M.GetVoice()
|
||||
var/rendered = null
|
||||
rendered = "<span class='game say'>\icon[src][bicon(src)] <span class='name'>[name_used]</span> [message]</span>"
|
||||
mob.show_message(rendered, 2)
|
||||
|
||||
// Proc: show_message()
|
||||
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
|
||||
// Description: Relays the message to all linked communicators.
|
||||
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[msg]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0)
|
||||
var/list/mobs_to_relay = in_range["mobs"]
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
mob.show_message(rendered)
|
||||
..()
|
||||
|
||||
// Verb: join_as_voice()
|
||||
// Parameters: None
|
||||
// Description: Allows ghosts to call communicators, if they meet all the requirements.
|
||||
/mob/observer/dead/verb/join_as_voice()
|
||||
set category = "Ghost"
|
||||
set name = "Call Communicator"
|
||||
set desc = "If there is a communicator available, send a request to speak through it. This will reset your respawn timer, if someone picks up."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
var/confirm = tgui_alert(src, "Would you like to talk as [src.client.prefs.real_name], over a communicator? This will reset your respawn timer, if someone answers.", "Join as Voice?", list("Yes","No"))
|
||||
if(confirm == "No")
|
||||
return
|
||||
|
||||
if(config.antag_hud_restricted && has_enabled_antagHUD == 1)
|
||||
to_chat(src, "<span class='danger'>You have used the antagHUD and cannot respawn or use communicators!</span>")
|
||||
return
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src , "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a voice request to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
if(O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "voice")
|
||||
|
||||
to_chat(src, "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers.")
|
||||
|
||||
// Proc: connect_video()
|
||||
// Parameters: user - the mob doing the viewing of video, comm - the communicator at the far end
|
||||
// Description: Sets up a videocall and puts the first view into it using watch_video, and updates the icon
|
||||
/obj/item/device/communicator/proc/connect_video(mob/user,obj/item/device/communicator/comm)
|
||||
if((!user) || (!comm) || user.stat) return //KO or dead, or already in a video
|
||||
|
||||
if(video_source) //Already in a video
|
||||
to_chat(user, "<span class='danger'>You are already connected to a video call!</span>")
|
||||
return
|
||||
|
||||
if(user.blinded) //User is blinded
|
||||
to_chat(user, "<span class='danger'>You cannot see well enough to do that!</span>")
|
||||
return
|
||||
|
||||
if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something
|
||||
to_chat(user, "<span class='danger'>\icon[src][bicon(src)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to start video over existing call.</span>")
|
||||
sleep(30)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Please wait...</span>")
|
||||
|
||||
video_source = comm.camera
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] New video connection from [comm].</span>")
|
||||
update_active_camera_screen()
|
||||
GLOB.moved_event.register(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
update_icon()
|
||||
|
||||
// Proc: end_video()
|
||||
// Parameters: reason - the text reason to print for why it ended
|
||||
// Description: Ends the video call by clearing video_source
|
||||
/obj/item/device/communicator/proc/end_video(var/reason)
|
||||
GLOB.moved_event.unregister(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
show_static()
|
||||
video_source = null
|
||||
|
||||
. = "<span class='danger'>\icon[src][bicon(src)] [reason ? reason : "Video session ended"].</span>"
|
||||
|
||||
visible_message(.)
|
||||
update_icon()
|
||||
// Proc: add_communicating()
|
||||
// Parameters: 1 (comm - the communicator to add to communicating)
|
||||
// Description: Used when this communicator gets a new communicator to relay say/me messages to
|
||||
/obj/item/device/communicator/proc/add_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating |= comm
|
||||
listening_objects |= src
|
||||
update_icon()
|
||||
|
||||
// Proc: del_communicating()
|
||||
// Parameters: 1 (comm - the communicator to remove from communicating)
|
||||
// Description: Used when this communicator is being asked to stop relaying say/me messages to another
|
||||
/obj/item/device/communicator/proc/del_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating.Remove(comm)
|
||||
update_icon()
|
||||
|
||||
// Proc: open_connection()
|
||||
// Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device)
|
||||
// Description: Typechecks the candidate, then calls the correct proc for further connecting.
|
||||
/obj/item/device/communicator/proc/open_connection(mob/user, var/atom/candidate)
|
||||
if(isobserver(candidate))
|
||||
voice_invites.Remove(candidate)
|
||||
open_connection_to_ghost(user, candidate)
|
||||
else
|
||||
if(istype(candidate, /obj/item/device/communicator))
|
||||
open_connection_to_communicator(user, candidate)
|
||||
|
||||
// Proc: open_connection_to_communicator()
|
||||
// Parameters: 2 (user - the person who initiated this and will be receiving feedback information, candidate - someone else's communicator)
|
||||
// Description: Adds the candidate and src to each other's communicating lists, allowing messages seen by the devices to be relayed.
|
||||
/obj/item/device/communicator/proc/open_connection_to_communicator(mob/user, var/atom/candidate)
|
||||
if(!istype(candidate, /obj/item/device/communicator))
|
||||
return
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
voice_invites.Remove(candidate)
|
||||
comm.voice_requests.Remove(src)
|
||||
|
||||
if(user)
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connecting to [src].</span>")
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [comm].</span>")
|
||||
sleep(10)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Dialing internally from [station_name()], [system_name()].</span>")
|
||||
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection re-routed to [comm] at [comm.exonet.address].</span>")
|
||||
sleep(40)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection to [comm] at [comm.exonet.address] established.</span>")
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connection to [src] at [exonet.address] established.</span>")
|
||||
sleep(20)
|
||||
|
||||
src.add_communicating(comm)
|
||||
comm.add_communicating(src)
|
||||
|
||||
// Proc: open_connection_to_ghost()
|
||||
// Parameters: 2 (user - the person who initiated this, candidate - the ghost that will be turned into a voice mob)
|
||||
// Description: Pulls the candidate ghost from deadchat, makes a new voice mob, transfers their identity, then their client.
|
||||
/obj/item/device/communicator/proc/open_connection_to_ghost(mob/user, var/mob/candidate)
|
||||
if(!isobserver(candidate))
|
||||
return
|
||||
//Handle moving the ghost into the new shell.
|
||||
announce_ghost_joinleave(candidate, 0, "They are occupying a personal communications device now.")
|
||||
voice_requests.Remove(candidate)
|
||||
voice_invites.Remove(candidate)
|
||||
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
|
||||
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
|
||||
//Do some simple logging since this is a tad risky as a concept.
|
||||
var/msg = "[candidate && candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
|
||||
[user && user.client ? "[user.client.key]" : "*no key*"] ([user ? "[user]" : "*null*"]) at [x],[y],[z]. They have joined as [new_voice.name]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
new_voice.mind = candidate.mind //Transfer the mind, if any.
|
||||
new_voice.ckey = candidate.ckey //Finally, bring the client over.
|
||||
voice_mobs.Add(new_voice)
|
||||
listening_objects |= src
|
||||
|
||||
var/obj/screen/blackness = new() //Makes a black screen, so the candidate can't see what's going on before actually 'connecting' to the communicator.
|
||||
blackness.screen_loc = ui_entire_screen
|
||||
blackness.icon = 'icons/effects/effects.dmi'
|
||||
blackness.icon_state = "1"
|
||||
blackness.mouse_opacity = 2 //Can't see anything!
|
||||
new_voice.client.screen.Add(blackness)
|
||||
|
||||
update_icon()
|
||||
|
||||
//Now for some connection fluff.
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connecting to [candidate].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [src].</span>")
|
||||
sleep(10)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>")
|
||||
sleep(20)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connecting to [station_name()] telecommunications array.</span>")
|
||||
sleep(40)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>")
|
||||
sleep(20)
|
||||
|
||||
//We're connected, no need to hide everything.
|
||||
new_voice.client.screen.Remove(blackness)
|
||||
qdel(blackness)
|
||||
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [src] established.</span>")
|
||||
to_chat(new_voice, "<b>To talk to the person on the other end of the call, just talk normally.</b>")
|
||||
to_chat(new_voice, "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>")
|
||||
to_chat(new_voice, "<b>Remember, your character does not know anything you've learned from observing!</b>")
|
||||
if(new_voice.mind)
|
||||
new_voice.mind.assigned_role = "Disembodied Voice"
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Your communicator is now connected to [candidate]'s communicator.</span>")
|
||||
|
||||
// Proc: close_connection()
|
||||
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
|
||||
// Description: Deletes specific voice_mobs or disconnects communicators, and shows a message to everyone when doing so. If target is null, all communicators
|
||||
// and voice mobs are removed.
|
||||
/obj/item/device/communicator/proc/close_connection(mob/user, var/atom/target, var/reason)
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
return
|
||||
|
||||
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
|
||||
if(target && voice != target) //If no target is inputted, it deletes all of them.
|
||||
continue
|
||||
to_chat(voice, "<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
voice_mobs.Remove(voice)
|
||||
qdel(voice)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators.
|
||||
if(target && comm != target)
|
||||
continue
|
||||
src.del_communicating(comm)
|
||||
comm.del_communicating(src)
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
if(comm.camera && video_source == comm.camera) //We hung up on the person on video
|
||||
end_video()
|
||||
if(camera && comm.video_source == camera) //We hung up on them while they were watching us
|
||||
comm.end_video()
|
||||
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
listening_objects.Remove(src)
|
||||
|
||||
// Proc: request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator wanting to call the device)
|
||||
// Description: Response to a communicator or observer trying to call the device. Adds them to the list of requesters
|
||||
/obj/item/device/communicator/proc/request(var/atom/candidate)
|
||||
if(candidate in voice_requests)
|
||||
return
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
who = candidate.name
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.voice_invites |= src
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
voice_requests |= candidate
|
||||
|
||||
if(ringer)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Communications request from [who].</span>")
|
||||
|
||||
// Proc: del_request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator to be declined)
|
||||
// Description: Declines a request and cleans up both ends
|
||||
/obj/item/device/communicator/proc/del_request(var/atom/candidate)
|
||||
if(!(candidate in voice_requests))
|
||||
return
|
||||
|
||||
if(isobserver(candidate))
|
||||
to_chat(candidate, "<span class='warning'>Your communicator call request was declined.</span>")
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
comm.voice_invites -= src
|
||||
|
||||
voice_requests -= candidate
|
||||
|
||||
//Search for holder of our device.
|
||||
var/mob/living/us = null
|
||||
if(loc && isliving(loc))
|
||||
us = loc
|
||||
|
||||
if(us)
|
||||
to_chat(us, "<span class='notice'>\icon[src][bicon(src)] Declined request.</span>")
|
||||
|
||||
// Proc: see_emote()
|
||||
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
|
||||
// Description: Relays the emote to all linked communicators.
|
||||
/obj/item/device/communicator/see_emote(mob/living/M, text)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[text]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
|
||||
var/dst = get_dist(get_turf(mob),get_turf(comm))
|
||||
if(dst <= video_range)
|
||||
mob.show_message(rendered)
|
||||
else
|
||||
to_chat(mob, "You can barely see some movement on \the [src]'s display.")
|
||||
|
||||
..()
|
||||
|
||||
// Proc: hear_talk()
|
||||
// Parameters: 3 (M - the mob the speech originated from,
|
||||
// list/message_pieces - what is being said w/ baked languages,
|
||||
// verb - the word used to describe how text is being said)
|
||||
// Description: Relays the speech to all linked communicators.
|
||||
/obj/item/device/communicator/hear_talk(mob/M, list/message_pieces, verb)
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
var/list/combined = mob.combine_message(message_pieces, verb, M)
|
||||
var/message = combined["formatted"]
|
||||
var/name_used = M.GetVoice()
|
||||
var/rendered = null
|
||||
rendered = "<span class='game say'>\icon[src][bicon(src)] <span class='name'>[name_used]</span> [message]</span>"
|
||||
mob.show_message(rendered, 2)
|
||||
|
||||
// Proc: show_message()
|
||||
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
|
||||
// Description: Relays the message to all linked communicators.
|
||||
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[msg]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0)
|
||||
var/list/mobs_to_relay = in_range["mobs"]
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
mob.show_message(rendered)
|
||||
..()
|
||||
|
||||
// Verb: join_as_voice()
|
||||
// Parameters: None
|
||||
// Description: Allows ghosts to call communicators, if they meet all the requirements.
|
||||
/mob/observer/dead/verb/join_as_voice()
|
||||
set category = "Ghost"
|
||||
set name = "Call Communicator"
|
||||
set desc = "If there is a communicator available, send a request to speak through it. This will reset your respawn timer, if someone picks up."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
var/confirm = tgui_alert(src, "Would you like to talk as [src.client.prefs.real_name], over a communicator? This will reset your respawn timer, if someone answers.", "Join as Voice?", list("Yes","No"))
|
||||
if(confirm == "No")
|
||||
return
|
||||
|
||||
if(config.antag_hud_restricted && has_enabled_antagHUD == 1)
|
||||
to_chat(src, "<span class='danger'>You have used the antagHUD and cannot respawn or use communicators!</span>")
|
||||
return
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src , "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a voice request to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
if(O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "voice")
|
||||
|
||||
to_chat(src, "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers.")
|
||||
|
||||
// Proc: connect_video()
|
||||
// Parameters: user - the mob doing the viewing of video, comm - the communicator at the far end
|
||||
// Description: Sets up a videocall and puts the first view into it using watch_video, and updates the icon
|
||||
/obj/item/device/communicator/proc/connect_video(mob/user,obj/item/device/communicator/comm)
|
||||
if((!user) || (!comm) || user.stat) return //KO or dead, or already in a video
|
||||
|
||||
if(video_source) //Already in a video
|
||||
to_chat(user, "<span class='danger'>You are already connected to a video call!</span>")
|
||||
return
|
||||
|
||||
if(user.blinded) //User is blinded
|
||||
to_chat(user, "<span class='danger'>You cannot see well enough to do that!</span>")
|
||||
return
|
||||
|
||||
if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something
|
||||
to_chat(user, "<span class='danger'>\icon[src][bicon(src)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to start video over existing call.</span>")
|
||||
sleep(30)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Please wait...</span>")
|
||||
|
||||
video_source = comm.camera
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] New video connection from [comm].</span>")
|
||||
update_active_camera_screen()
|
||||
GLOB.moved_event.register(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
update_icon()
|
||||
|
||||
// Proc: end_video()
|
||||
// Parameters: reason - the text reason to print for why it ended
|
||||
// Description: Ends the video call by clearing video_source
|
||||
/obj/item/device/communicator/proc/end_video(var/reason)
|
||||
GLOB.moved_event.unregister(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
show_static()
|
||||
video_source = null
|
||||
|
||||
. = "<span class='danger'>\icon[src][bicon(src)] [reason ? reason : "Video session ended"].</span>"
|
||||
|
||||
visible_message(.)
|
||||
update_icon()
|
||||
|
||||
Reference in New Issue
Block a user