// Allows you to monitor messages that passes the server.
var/list/message_monitors = list()
/obj/machinery/computer/message_monitor
name = "Message Monitor Console"
desc = "Used to Monitor the crew's messages, that are sent via PDA. Can also be used to view Request Console messages."
icon = 'icons/obj/machines/telecomms.dmi'
icon_state = "message_monitor"
var/hack_icon = "message_monitor_hacked"
var/normal_icon = "message_monitor"
circuit = "/obj/item/weapon/circuitboard/message_monitor"
//Server linked to.
var/obj/machinery/message_server/linkedServer = null
//Messages - Saves me time if I want to change something.
var/noserver = "ALERT: No server detected."
var/incorrectkey = "ALERT: Incorrect decryption key!"
var/defaultmsg = "Welcome. Please select an option."
var/rebootmsg = "%$&(�: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!"
//Computer properties
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
var/hacking = 0 // Is it being hacked into by the AI/Cyborg
var/message = "System bootup complete. Please select an option." // The message that shows on the main menu.
var/auth = 0 // Are they authenticated?
var/optioncount = 7
// Custom Message properties
var/customsender = "System Administrator"
var/obj/item/device/pda/customrecepient = null
var/customjob = "Admin"
var/custommessage = "This is a test, please ignore."
var/switchboard_columns = 5
var/switchboard_namelength = 5
var/obj/landline/linking = null
var/obj/item/telephone/switchboard/switchboard_headset = null
var/switchboard_sound = 'sound/items/cable_plug.mp3'
var/switchboard_sound2 = 'sound/items/cable_unplug.mp3'
light_color = LIGHT_COLOR_GREEN
/obj/machinery/computer/message_monitor/New()
..()
switchboard_headset = new /obj/item/telephone/switchboard (src)
message_monitors += src
/obj/machinery/computer/message_monitor/Destroy()
message_monitors -= src
if(switchboard_headset)
qdel(switchboard_headset)
..()
/obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob)
if(!istype(user))
return
if(O.is_screwdriver(user) && emagged)
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
to_chat(user, "It is too hot to mess with!")
return
..()
return
/obj/machinery/computer/message_monitor/emag_act(mob/user as mob)
// Will create sparks and print out the console's password. You will then have to wait a while for the console to be back online.
// It'll take more time if there's more characters in the password..
if(!emagged)
if(!isnull(src.linkedServer))
icon_state = hack_icon // An error screen I made in the computers.dmi
emagged = 1
screen = 2
spark(src, 5, FALSE)
var/obj/item/weapon/paper/monitorkey/MK = new/obj/item/weapon/paper/monitorkey
MK.forceMove(src.loc)
// Will help make emagging the console not so easy to get away with.
MK.info += "
�%@%(*$%&(�&?*(%&�/{}"
spawn(100*length(src.linkedServer.decryptkey)) UnmagConsole()
message = rebootmsg
else
if(user)
to_chat(user, "A 'no server' error appears on the screen.")
/obj/machinery/computer/message_monitor/update_icon()
..()
if(stat & (NOPOWER|BROKEN|FORCEDISABLE))
return
if(emagged || hacking)
icon_state = hack_icon
else
icon_state = normal_icon
/obj/machinery/computer/message_monitor/initialize()
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
if(!linkedServer)
if(message_servers && message_servers.len > 0)
linkedServer = message_servers[1]
return
/obj/machinery/computer/message_monitor/attack_hand(var/mob/living/user as mob)
if(stat & (NOPOWER|BROKEN|FORCEDISABLE))
return
if(!istype(user) && !isAdminGhost(user))
return
//If the computer is being hacked or is emagged, display the reboot message.
if(hacking || emagged)
message = rebootmsg
var/dat = "
Message Monitor Console"
dat += {"Message Monitor Console
"}
if(auth)
dat += {""}
else
dat += {" \[Unauthenticated\] /
Server Power: [src.linkedServer && src.linkedServer.is_functioning() ? "\[On\]":"\[Off\]"]"}
dat += {" Landline auto-routing: [src.linkedServer && src.linkedServer.landlines_functioning() ? "\[On\]":"\[Off\]"]
"}
if(hacking || emagged)
screen = 2
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN|FORCEDISABLE)))
message = noserver
switch(screen)
//Main menu
if(0)
// = TAB
var/i = 0
dat += " [++i]. Link To A Server"
if(auth)
if(!linkedServer || (linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
dat += " ERROR: Server not found!
"
else
dat += {" [++i]. View Message Logs
[++i]. View Request Console Logs
[++i]. Clear Message Logs
[++i]. Clear Request Console Logs
[++i]. Set Custom Key
[++i]. Send Admin Message
"}
else
for(var/n = ++i; n <= optioncount; n++)
dat += " [n]. ---------------
"
if((istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) && user.mind.special_role)
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
dat += "*&@#. Bruteforce Key
"
else
dat += "
"
dat += "
Landline Switchboard
"
//TODO add exclamation marks here if someone's calling
//Bottom message
if(!auth)
dat += "
Please authenticate with the server in order to show additional options."
else
dat += "
Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering properties."
//Message Logs
if(1)
var/index = 0
//var/recipient = "Unspecified" //name of the person
//var/sender = "Unspecified" //name of the sender
//var/message = "Blank" //transferred message
dat += {"Back - Refresh
| X | Sender | Recipient | Message | Photo |
"}
for(var/datum/data_pda_msg/pda in src.linkedServer.pda_msgs)
index++
if(index > 3000)
break
// Del - Sender - Recepient - Message - Photo
// X - Al Green - Your Mom - WHAT UP!? - [Photo]
var/imgdat = ""
if(pda.img_sent)
user << browse_rsc(pda.img_sent, "tmp_photo_[index].png")
imgdat = "
"
dat += "| X | [pda.sender] | [pda.recipient] | [pda.message] | [imgdat] |
"
dat += "
"
//Hacking screen.
if(2)
if(istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot))
dat += {"Brute-forcing for server key.
It will take 20 seconds for every character that the password has.
In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."}
else
//It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever.
dat += {"01000010011100100111010101110100011001010010110
10110011001101111011100100110001101101001011011100110011
10010000001100110011011110111001000100000011100110110010
10111001001110110011001010111001000100000011010110110010
10111100100101110001000000100100101110100001000000111011
10110100101101100011011000010000001110100011000010110101
10110010100100000001100100011000000100000011100110110010
10110001101101111011011100110010001110011001000000110011
00110111101110010001000000110010101110110011001010111001
00111100100100000011000110110100001100001011100100110000
10110001101110100011001010111001000100000011101000110100
00110000101110100001000000111010001101000011001010010000
00111000001100001011100110111001101110111011011110111001
00110010000100000011010000110000101110011001011100010000
00100100101101110001000000111010001101000011001010010000
00110110101100101011000010110111001110100011010010110110
10110010100101100001000000111010001101000011010010111001
10010000001100011011011110110111001110011011011110110110
00110010100100000011000110110000101101110001000000111001
00110010101110110011001010110000101101100001000000111100
10110111101110101011100100010000001110100011100100111010
10110010100100000011010010110111001110100011001010110111
00111010001101001011011110110111001110011001000000110100
10110011000100000011110010110111101110101001000000110110
00110010101110100001000000111001101101111011011010110010
10110111101101110011001010010000001100001011000110110001
10110010101110011011100110010000001101001011101000010111
00010000001001101011000010110101101100101001000000111001
10111010101110010011001010010000001101110011011110010000
00110100001110101011011010110000101101110011100110010000
00110010101101110011101000110010101110010001000000111010
00110100001100101001000000111001001101111011011110110110
10010000001100100011101010111001001101001011011100110011
10010000001110100011010000110000101110100001000000111010
001101001011011010110010100101110"}
//Fake messages
if(3)
dat += "Back - Reset
"
dat += {"
| Sender |
Sender's Job |
Recipient |
Message |
"}
//Sender - Sender's Job - Recepient - Message
//Al Green- Your Dad - Your Mom - WHAT UP!?
dat += {"| [customsender] |
[customjob] |
[customrecepient ? customrecepient.owner : "NONE"] |
[custommessage] |
"}
dat += "
Send"
//Request Console Logs
if(4)
var/index = 0
/* data_rc_msg
X - 5%
var/rec_dpt = "Unspecified" //name of the person - 15%
var/send_dpt = "Unspecified" //name of the sender- 15%
var/message = "Blank" //transferred message - 300px
var/stamp = "Unstamped" - 15%
var/id_auth = "Unauthenticated" - 15%
var/priority = "Normal" - 10%
*/
dat += "Back - Refresh
"
dat += {"| X | Sending Dep. | Receiving Dep. |
Message | Stamp | ID Auth. | Priority. |
"}
for(var/datum/data_rc_msg/rc in src.linkedServer.rc_msgs)
index++
if(index > 3000)
break
// Del - Sender - Recepient - Message
// X - Al Green - Your Mom - WHAT UP!?
dat += {"| X | [rc.send_dpt] |
[rc.rec_dpt] | [rc.message] | [rc.stamp] | [rc.id_auth] | [rc.priority] |
"}
dat += "
"
if(5) //manual switchboard
var/current_button_num = 1
dat += ""
dat += ""
for(var/obj/machinery/requests_console/RC in requests_consoles)
var/shortname_end = RC.department_short ? RC.department_short : RC.department
shortname_end = copytext(shortname_end,1,switchboard_namelength-1)
var/shortname = RC.master_department_short + "-" + shortname_end
var/callconnector
if(RC.landline.calling)
callconnector = "x"
else
if(linking && RC.landline != linking)
callconnector = "o"
else
callconnector = " "
var/b = RC.landline.get_status()
if(b)
shortname = "[shortname]"
dat += "| [shortname]\[[callconnector]\] | " //thanks no. 455311247
current_button_num += 1
if(current_button_num > switchboard_columns)
dat += "
"
current_button_num = 1
dat += "
"
dat += "
"
var/currentline = "null"
if(switchboard_headset && switchboard_headset.linked_landline)
var/obj/machinery/requests_console/RC = switchboard_headset.linked_landline.attached_to
if(RC)
currentline = RC.master_department_short + "-" + copytext(RC.department,1,switchboard_namelength-1)
currentline = "[currentline]"
dat += "
Currently plugged to line: [currentline]"
dat += "
Back"
dat += ""
message = defaultmsg
user << browse(HTML_SKELETON(dat), "window=message;size=700x700")
onclose(user, "message")
return
/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user as mob)
if(isnull(linkedServer))
to_chat(user, "Could not complete brute-force: Linked Server Disconnected!")
else
var/currentKey = src.linkedServer.decryptkey
to_chat(user, "Brute-force completed! The key is '[currentKey]'.")
src.hacking = 0
src.icon_state = normal_icon
src.screen = 0 // Return the screen back to normal
/obj/machinery/computer/message_monitor/proc/UnmagConsole()
src.icon_state = normal_icon
src.emagged = 0
/obj/machinery/computer/message_monitor/proc/ResetMessage()
customsender = "System Administrator"
customrecepient = null
custommessage = "This is a test, please ignore."
customjob = "Admin"
/obj/machinery/computer/message_monitor/Topic(href, href_list)
if(..())
return 1
else
//Authenticate
if (href_list["auth"])
if(auth)
auth = 0
screen = 0
else
var/dkey = sanitize(trim(input(usr, "Please enter the decryption key.") as text|null))
if(dkey && dkey != "")
if(src.linkedServer.decryptkey == dkey)
auth = 1
else
message = incorrectkey
//Turn the server on/off.
if (href_list["active"])
if(auth)
linkedServer.disabled = !linkedServer.disabled
//toggle automatic landline connections
if (href_list["toggleLandlines"])
if(auth)
linkedServer.automatic_landlines = !linkedServer.automatic_landlines
//Find a server
if (href_list["find"])
if(message_servers && message_servers.len > 1)
src.linkedServer = input(usr,"Please select a server.", "Select a server.", null) as null|anything in message_servers
message = "NOTICE: Server selected."
else if(message_servers && message_servers.len > 0)
linkedServer = message_servers[1]
message = "NOTICE: Only Single Server Detected - Server selected."
else
message = noserver
//View the logs - KEY REQUIRED
if (href_list["view"])
if(src.linkedServer == null || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else
if(auth)
src.screen = 1
//Clears the logs - KEY REQUIRED
if (href_list["clear"])
if(!linkedServer || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else
if(auth)
src.linkedServer.pda_msgs = list()
message = "NOTICE: Logs cleared."
//Clears the request console logs - KEY REQUIRED
if (href_list["clearr"])
if(!linkedServer || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else
if(auth)
src.linkedServer.rc_msgs = list()
message = "NOTICE: Logs cleared."
//Change the password - KEY REQUIRED
if (href_list["pass"])
if(!linkedServer || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else
if(auth)
var/dkey = sanitize(trim(input(usr, "Please enter the decryption key.") as text|null))
if(dkey && dkey != "")
if(src.linkedServer.decryptkey == dkey)
var/newkey = sanitize(trim(input(usr,"Please enter the new key (3 - 16 characters max):")))
if(length(newkey) <= 3)
message = "NOTICE: Decryption key too short!"
else if(length(newkey) > 16)
message = "NOTICE: Decryption key too long!"
else if(newkey && newkey != "")
src.linkedServer.decryptkey = newkey
message = "NOTICE: Decryption key set."
else
message = incorrectkey
//Hack the Console to get the password
if (href_list["hack"])
if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && usr.mind.special_role)
src.hacking = 1
src.screen = 2
src.icon_state = hack_icon
//Time it takes to bruteforce is dependant on the password length.
spawn(100*length(src.linkedServer.decryptkey))
if(src && src.linkedServer && usr)
BruteForce(usr)
//Delete the log.
if (href_list["delete"])
//Are they on the view logs screen?
if(screen == 1)
if(!linkedServer || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else //if(istype(href_list["delete"], /datum/data_pda_msg))
src.linkedServer.pda_msgs -= locate(href_list["delete"])
message = "NOTICE: Log Deleted!"
//Delete the request console log.
if (href_list["deleter"])
//Are they on the view logs screen?
if(screen == 4)
if(!linkedServer || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else //if(istype(href_list["delete"], /datum/data_pda_msg))
src.linkedServer.rc_msgs -= locate(href_list["deleter"])
message = "NOTICE: Log Deleted!"
//Create a custom message
if (href_list["msg"])
if(src.linkedServer == null || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else
if(auth)
src.screen = 3
//Fake messaging selection - KEY REQUIRED
if (href_list["select"])
if(src.linkedServer == null || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
screen = 0
else
switch(href_list["select"])
//Reset
if("Reset")
ResetMessage()
//Select Your Name
if("Sender")
customsender = input(usr, "Please enter the sender's name.") as text|null
customsender = copytext(sanitize(customsender), 1, MAX_NAME_LEN)
//Select Receiver
if("Recepient")
//Get out list of viable PDAs
var/list/obj/item/device/pda/sendPDAs = get_viewable_pdas()
if(PDAs && PDAs.len > 0)
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
else
customrecepient = null
//Enter custom job
if("RecJob")
customjob = input(usr, "Please enter the sender's job.") as text|null
customjob = copytext(sanitize(customjob), 1, MAX_NAME_LEN)
//Enter message
if("Message")
custommessage = input(usr, "Please enter your message.") as text|null
custommessage = copytext(sanitize(custommessage), 1, MAX_MESSAGE_LEN)
//Send message
if("Send")
if(isnull(customsender) || customsender == "")
customsender = "UNKNOWN"
if(isnull(customrecepient))
message = "NOTICE: No recepient selected!"
return src.attack_hand(usr)
if(isnull(custommessage) || custommessage == "")
message = "NOTICE: No message entered!"
return src.attack_hand(usr)
var/datum/pda_app/messenger/message_app = locate(/datum/pda_app/messenger) in customrecepient.applications
if(!message_app) //Shouldn't show up but just in case we need to explain it, also to prevent the below runtiming
message = "NOTICE: This PDA does not have a messenger, somehow."
return src.attack_hand(usr)
var/obj/item/device/pda/PDARec = null
for (var/obj/item/device/pda/P in get_viewable_pdas())
if(P.owner == customsender)
PDARec = P
//Sender isn't faking as someone who exists
if(isnull(PDARec))
src.linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]")
message_app.tnote += "← From [customsender] ([customjob]):
[custommessage]
"
if (!message_app.silent)
playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(3, customrecepient.loc))
O.show_message(text("[bicon(customrecepient)] *[message_app.ttone]*"))
if( customrecepient.loc && ishuman(customrecepient.loc) )
var/mob/living/carbon/human/H = customrecepient.loc
to_chat(H, "[bicon(customrecepient)] Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)")
log_pda("[key_name(usr)] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]")
customrecepient.overlays.len = 0
customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r")
//Sender is faking as someone who exists
else
src.linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]")
message_app.tnote += "← From [PDARec.owner] ([customjob]):
[custommessage]
"
if (!message_app.silent)
playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(3, customrecepient.loc))
O.show_message(text("[bicon(customrecepient)] *[message_app.ttone]*"))
if( customrecepient.loc && ishuman(customrecepient.loc) )
var/mob/living/carbon/human/H = customrecepient.loc
to_chat(H, "[bicon(customrecepient)] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)")
log_pda("[key_name(usr)] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]")
customrecepient.overlays.len = 0
customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r")
//Finally..
ResetMessage()
//Request Console Logs - KEY REQUIRED
if(href_list["viewr"])
if(src.linkedServer == null || (src.linkedServer.stat & (FORCEDISABLE|NOPOWER|BROKEN)))
message = noserver
else
if(auth)
src.screen = 4
// to_chat(usr, href_list["select"])
if (href_list["switchboard"])
src.screen = 5
if (href_list["stopCall"])
var/obj/landline/L = locate(href_list["stopCall"])
if(L)
if(L.calling)
L.calling.last_call_log += text("call disconnected by operator
")
L.calling.calling = null
if(L.calling.linked_phone)
playsound(L.calling.linked_phone, switchboard_sound2, 100, 1)
L.last_call_log += text("call disconnected by operator
")
if(L.linked_phone)
playsound(L.linked_phone, switchboard_sound2, 100, 1)
L.calling = null
updateUsrDialog()
playsound(src, switchboard_sound2, 100, 1)
if (href_list["manualCall"])
var/obj/landline/L = locate(href_list["manualCall"])
if(L && linking && (L != linking))
if(L.calling || linking.calling)
return
L.calling = linking
linking.calling = L
L.ring_loop()
linking.ring_loop()
var/obj/machinery/requests_console/L_console = L.attached_to
var/obj/machinery/requests_console/linking_console = linking.attached_to
L.last_call_log += text("connected to [linking_console.department] by operator
")
linking.last_call_log += text("connected to [L_console.department] by operator
")
if(L.calling.linked_phone)
playsound(L.calling.linked_phone, switchboard_sound, 100, 1)
if(L.linked_phone)
playsound(L.linked_phone, switchboard_sound, 100, 1)
playsound(src, switchboard_sound, 100, 1)
linking = FALSE
if (href_list["setLink"])
var/obj/landline/L = locate(href_list["setLink"])
if(!L || linking)
return
linking = L
playsound(src, switchboard_sound, 100, 1)
updateUsrDialog()
if (href_list["back"])
src.screen = 0
if (href_list["clearCurrentLine"])
if(switchboard_headset && switchboard_headset.linked_landline)
var/obj/landline/LL = switchboard_headset.linked_landline
if(LL.linked_phone)
playsound(LL.linked_phone, switchboard_sound2, 100, 1)
if(LL.calling && LL.calling.linked_phone)
playsound(LL.calling.linked_phone, switchboard_sound2, 100, 1)
LL.listening_operators -= src.switchboard_headset
switchboard_headset.linked_landline = null
playsound(src, switchboard_sound2, 100, 1)
updateUsrDialog()
if (href_list["setCurrentLine"])
var/obj/landline/L = locate(href_list["setCurrentLine"])
if(L && switchboard_headset)
L.listening_operators += switchboard_headset
switchboard_headset.linked_landline = L
playsound(src, switchboard_sound, 100, 1)
if(L.linked_phone)
playsound(L.linked_phone, switchboard_sound, 100, 1)
if(L.calling && L.calling.linked_phone)
playsound(L.calling.linked_phone, switchboard_sound, 100, 1)
updateUsrDialog()
return src.attack_hand(usr)
/obj/item/weapon/paper/monitorkey
//..()
name = "Monitor Decryption Key"
var/obj/machinery/message_server/server = null
/obj/item/weapon/paper/monitorkey/New()
..()
spawn(10)
if(message_servers)
for(var/obj/machinery/message_server/server in message_servers)
if(!isnull(server))
if(!isnull(server.decryptkey))
info = "Daily Key Reset
The new message monitor key is '[server.decryptkey]'.
Please keep this a secret and away from the clown.
If necessary, change the password to a more secure one."
info_links = info
overlays += image(icon = icon, icon_state = "paper_words")
break