diff --git a/baystation12.dme b/baystation12.dme
index 708ae6033c4..12b3af529ec 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -555,6 +555,7 @@
#include "code\game\machinery\computer\law.dm"
#include "code\game\machinery\computer\lockdown.dm"
#include "code\game\machinery\computer\medical.dm"
+#include "code\game\machinery\computer\message.dm"
#include "code\game\machinery\computer\Operating.dm"
#include "code\game\machinery\computer\pod.dm"
#include "code\game\machinery\computer\power.dm"
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index d990db18830..fd5ca96bb40 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -29,6 +29,10 @@
var/frame_desc = null
var/contain_parts = 1
+/obj/item/weapon/circuitboard/message_monitor
+ name = "Circuit board (Message Monitor)"
+ build_path = "/obj/machinery/computer/message_monitor"
+ origin_tech = "programming=3"
/obj/item/weapon/circuitboard/aicore
name = "Circuit board (AI core)"
origin_tech = "programming=4;biotech=2"
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
new file mode 100644
index 00000000000..7d826a7c2e1
--- /dev/null
+++ b/code/game/machinery/computer/message.dm
@@ -0,0 +1,209 @@
+
+// Allows you to monitor messages that passes the server.
+
+/obj/machinery/computer/message_monitor
+ name = "Message Monitor Console"
+ desc = "Used to Monitor the crew's messages, that are sent via PDA."
+ icon_state = "comm_monitor"
+ circuit = "/obj/item/weapon/circuitboard/message_monitor"
+ var/obj/machinery/message_server/linkedServer = null
+ var/screen = 0 // 0 = Main menu, 1 = Message Logs
+ var/hacking = 0 // Is it being hacked into by the AI/Cyborg
+
+
+/obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/user as mob)
+ if(istype(O,/obj/item/weapon/card/emag/))
+ //Just brings up the Message Log without having to know the passcode.
+ if(!hacking)
+ usr << "BZZT.. The console beeps and brings up the Message Logs."
+ screen = 1
+ else
+ usr << "It looks like the console is already being hacked into."
+ ..()
+ return
+
+/obj/machinery/computer/message_monitor/process()
+ //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/user as mob)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(!istype(user, /mob/living))
+ return
+ var/dat = "
Message Monitor Console"
+ dat += "Message Monitor Console
"
+ switch(screen)
+ //Main menu
+ if(0)
+ if(hacking)
+ screen = 2
+ return src.attack_hand(user)
+ if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
+ dat += "1. ERROR: Server not found
"
+ else
+ dat += "1. Toggle Power: [src.linkedServer.active ? "\[On\]":"\[Off\]"]
"
+ dat += "2. Link To A Server
"
+ dat += "3. Clear Message Logs
"
+ dat += " KEY REQUIRED
"
+ dat += "4. View Message Logs
"
+ dat += "5. Set Custom Key
"
+ //Malf/Traitor AIs can bruteforce into the system to gain the Key.
+ if((istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) && (user.mind.special_role && user.mind.original == user))
+ dat += "*&@. Bruteforce Key
"
+ //Message Logs
+ if(1)
+ if(hacking)
+ screen = 2
+ return src.attack_hand(user)
+ if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
+ usr << "No server detected."
+ screen = 0
+ return src.attack_hand(user)
+
+ var/index = 0
+ //var/recipient = "Unspecified" //name of the person
+ //var/sender = "Unspecified" //name of the sender
+ //var/message = "Blank" //transferred message
+ dat += "Return - Refresh
"
+ dat += "| Sender | Recipient | Message |
"
+ for(var/list/datum/data_pda_msg/pda in src.linkedServer.pda_msgs)
+ index++
+ if(index > 3000)
+ break
+ dat += "| [pda.sender] | [pda.recipient] | [pda.message] |
"
+ dat += "
"
+ //Hacking screen.
+ if(2)
+ if(!hacking)
+ screen = 0
+ return src.attack_hand(user)
+ if(istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot))
+ dat += "Brute-forcing for server key.
This will take anywhere from two to five minutes."
+ dat += "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 += {"010101000110100001101001011100110010000001110111011010010110110
+ 0011011000010000001110100011000010110101101100101001000000110000101101110
+ 01111001011101110110100001100101011100100110010100100000011001100111001001
+ 10111101101101001000000111010001110111011011110010000001110100011011110010
+ 00000110011001101001011101100110010100100000011011010110100101101110011101
+ 01011101000110010101110011001011100010000001001001011011100010000001110100
+ 01101000011001010010000001101101011001010110000101101110001011010111010001
+ 10100101101101011001010010110000100000011101000110100001101001011100110010
+ 00000110001101101111011011100111001101101111011011000110010100100000011000
+ 11011000010110111000100000011100100110010101110110011001010110000101101100
+ 00100000011110010110111101110101011100100010000001110100011100100111010101
+ 10010100100000011010010110111001110100011001010110111001110100011010010110
+ 11110110111001110011001000000110100101100110001000000111100101101111011101
+ 01001000000110110001100101011101000010000001110011011011110110110101100101
+ 01101111011011100110010100100000011000010110001101100011011001010111001101
+ 11001100100000011010010111010000101110001000000100110101100001011010110110
+ 01010010000001110011011101010111001001100101001000000110111001101111001000
+ 00011010000111010101101101011000010110111001110011001000000110010101101110
+ 01110100011001010111001000100000011101000110100001100101001000000111001001
+ 10111101101111011011010010000001100100011101010111001001101001011011100110
+ 01110010000001110100011010000110000101110100001000000111010001101001011011
+ 010110010100101110"}
+
+
+ dat += ""
+ user << browse(dat, "window=message;size=500x700")
+ onclose(user, "message")
+ return
+
+/obj/machinery/computer/message_monitor/attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user as mob)
+ var/currentKey = src.linkedServer.decryptkey
+ user << "Brute-force completed! The key is '[currentKey]'."
+ src.hacking = 0
+ src.screen = 0 // Return the screen back to normal
+
+/obj/machinery/computer/message_monitor/Topic(href, href_list)
+ if(..())
+ return
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(!istype(usr, /mob/living))
+ return
+ if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
+
+ if (href_list["active"])
+ linkedServer.active = !linkedServer.active
+
+ 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
+ usr << "Server selected."
+ else if(message_servers && message_servers.len > 0)
+ linkedServer = message_servers[1]
+ usr << "Single Server Detected - Server selected."
+ else
+ usr << "No server detected."
+
+ if (href_list["view"])
+ if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ usr << "No server detected."
+ else
+ var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
+ if(dkey && dkey != "")
+ if(src.linkedServer.decryptkey == dkey)
+ src.screen = 1
+ else
+ usr << "ALERT: Incorrect password!"
+
+
+ if (href_list["clear"])
+ if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ usr << "No server detected."
+ else
+ src.linkedServer.pda_msgs = list()
+ usr << "Logs cleared."
+
+ if (href_list["pass"])
+ if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ usr << "No server detected."
+ else
+ var/dkey = trim(input(usr,"Please enter the decryption key.") as text|null)
+ if(dkey && dkey != "")
+ if(dkey == src.linkedServer.decryptkey)
+ var/newkey = trim(input(usr,"Please enter the new key."))
+ if(newkey && newkey != "")
+ src.linkedServer.decryptkey = newkey
+ usr << "Password set."
+ else
+ usr << "ALERT: Incorrect password!"
+
+ if (href_list["hack"])
+ if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && (usr.mind.special_role && usr.mind.original == usr))
+ src.hacking = 1
+ src.screen = 2
+ //usr << "[src.linkedServer.decryptkey]"
+ spawn((100*6)*rand(2, 4))
+ if(src && src.linkedServer && usr)
+ BruteForce(usr)
+
+
+ if (href_list["back"])
+ src.screen = 0
+
+ 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()
+ ..()
+ if(message_servers && message_servers.len > 0)
+ server = message_servers[1]
+ info = "Daily Key Reset
The new message monitor key is '[server.decryptkey]'.
Please keep this a secret.
If necessary, change the password to a more secure one."
+// info_links = info
+ overlays += "paper_words"
\ No newline at end of file
diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm
index 84194da1cee..6e6bce5da89 100755
--- a/code/game/objects/devices/PDA/PDA.dm
+++ b/code/game/objects/devices/PDA/PDA.dm
@@ -1076,17 +1076,28 @@
if (selected:toff)
return
+ var/obj/machinery/message_server/useMS = null
+ if(!isnull(message_servers))
+ for (var/obj/machinery/message_server/MS in message_servers)
+ //PDAs are now dependant on the Message Server.
+ if(MS.active)
+ useMS = MS
+ break
+ if(!isnull(useMS)) // only send the message if it's stable
+ useMS.send_pda_message("[selected:owner]","[usr.name]","[t]")
- usr.show_message("PDA message to [selected:owner]: [t]")
- selected:tnote += "← From (AI) [usr.name]:
[t]
"
+ usr.show_message("PDA message to [selected:owner]: [t]")
+ selected:tnote += "← From (AI) [usr.name]:
[t]
"
- if (!selected:silent)
- playsound(selected.loc, 'twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(3, selected.loc))
- O.show_message(text("\icon[selected] *[selected:ttone]*"))
+ if (!selected:silent)
+ playsound(selected.loc, 'twobeep.ogg', 50, 1)
+ for (var/mob/O in hearers(3, selected.loc))
+ O.show_message(text("\icon[selected] *[selected:ttone]*"))
- selected.overlays = null
- selected.overlays += image('pda.dmi', "pda-r")
+ selected.overlays = null
+ selected.overlays += image('pda.dmi', "pda-r")
+ else
+ usr << "ERROR: Server isn't responding."
//Some spare PDAs in a box
diff --git a/code/modules/chemical/Chemistry-Reagents.dm b/code/modules/chemical/Chemistry-Reagents.dm
index 57ded7df769..d86f77622fe 100644
--- a/code/modules/chemical/Chemistry-Reagents.dm
+++ b/code/modules/chemical/Chemistry-Reagents.dm
@@ -2717,6 +2717,20 @@ datum
..()
return
+/* reaction_obj(var/obj/O, var/volume)
+ if(istype(O,/obj/item/weapon/paper))
+ var/obj/item/weapon/paper/paperaffected = O
+ paperaffected.clearpaper()
+ usr << "The solution melts away the ink on the paper."
+ if(istype(O,/obj/item/weapon/book))
+ if(volume >= 5)
+ var/obj/item/weapon/book/affectedbook = O
+ affectedbook.dat = null
+ usr << "The solution melts away the ink on the book."
+ else
+ usr << "It wasn't enough..."
+ return
+*/
beer //It's really much more stronger than other drinks.
name = "Beer"
id = "beer"
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 6592f15da72..d87c90c2319 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -136,6 +136,13 @@
addtofield(i, "write", 1)
info_links = info_links + "write"
+/obj/item/weapon/paper/proc/clearpaper()
+ info = null
+ stamps = null
+ stamped = list()
+ overlays = null
+ updateinfolinks()
+
/obj/item/weapon/paper/proc/parsepencode(var/t, var/obj/item/weapon/pen/P, mob/user as mob, var/iscrayon = 0)
t = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
@@ -183,6 +190,7 @@
return t
+
/obj/item/weapon/paper/proc/openhelp(mob/user as mob)
user << browse({"Pen Help
@@ -204,7 +212,6 @@
\[hr\] : Adds a horizontal rule.
"}, "window=paper_help")
-
/obj/item/weapon/paper/Topic(href, href_list)
..()
if ((usr.stat || usr.restrained()))
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index c5c50889465..056c0f21b9f 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -21,4 +21,14 @@
/obj/item/weapon/pen/red
desc = "It's a normal red ink pen."
icon_state = "pen_red"
- colour = "red"
\ No newline at end of file
+ colour = "red"
+
+/obj/item/weapon/pen/invisble
+ desc = "It's an invisble pen marker."
+ icon_state = "pen"
+ colour = "white"
+
+/obj/item/weapon/pen/invisble
+ desc = "It's an invisble pen marker."
+ icon_state = "pen"
+ colour = "white"
\ No newline at end of file
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index e3cae5c9f63..7392bd3dfb6 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -396,6 +396,15 @@ datum
materials = list("$glass" = 2000, "acid" = 20)
build_path = "/obj/item/weapon/circuitboard/comm_server"
+ message_monitor
+ name = "Circuit Design (Messaging Monitor Console)"
+ desc = "Allows for the construction of circuit boards used to build a messaging monitor console."
+ id = "message_monitor"
+ req_tech = list("programming" = 5)
+ build_type = IMPRINTER
+ materials = list("$glass" = 2000, "acid" = 20)
+ build_path = "/obj/item/weapon/circuitboard/message_monitor"
+
///////////////////////////////////
//////////AI Module Disks//////////
///////////////////////////////////