-PDA is now sorted.

-Improved the Message Monitor UI to make it easier to use.
-Added a Message Monitor in Tech Storage, hopefully so it will be used more. You will still need the key to use it.
-You need the key to turn servers on/off remotely via the Message Monitor.

git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4099 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
giacomand@gmail.com
2012-07-17 21:30:31 +00:00
parent 2a06209972
commit e4c971e3e4
5 changed files with 126 additions and 104 deletions

View File

@@ -246,6 +246,31 @@
/proc/capitalize(var/t as text) /proc/capitalize(var/t as text)
return uppertext(copytext(t, 1, 2)) + copytext(t, 2) return uppertext(copytext(t, 1, 2)) + copytext(t, 2)
//Sorts Atoms by their name property.
//Sorry for the copy+pasta, I doubt quick sorting will change anytime soon though.
// Order 1 = Ascending / Order -1 = Descending
/proc/sortAtom(var/list/atom/L, var/order = 1)
if(isnull(L) || L.len < 2)
return L
var/middle = L.len / 2 + 1
return mergeAtoms(sortAtom(L.Copy(0,middle)), sortAtom(L.Copy(middle)), order)
/proc/mergeAtoms(var/list/atom/L, var/list/atom/R, var/order = 1)
var/Li=1
var/Ri=1
var/list/result = new()
while(Li <= L.len && Ri <= R.len)
var/atom/rL = L[Li]
var/atom/rR = R[Ri]
if(sorttext(rL.name, rR.name) == order)
result += L[Li++]
else
result += R[Ri++]
if(Li <= L.len)
return (result + L.Copy(Li, 0))
return (result + R.Copy(Ri, 0))
/proc/sortRecord(var/list/datum/data/record/L, var/field = "name", var/order = 1) /proc/sortRecord(var/list/datum/data/record/L, var/field = "name", var/order = 1)
if(isnull(L) || L.len < 2) if(isnull(L) || L.len < 2)
return L return L

View File

@@ -25,6 +25,8 @@
var/hacking = 0 // Is it being hacked into by the AI/Cyborg var/hacking = 0 // Is it being hacked into by the AI/Cyborg
var/emag = 0 // When it is emagged. var/emag = 0 // When it is emagged.
var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu. var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu.
var/auth = 0 // Are they authenticated?
var/optioncount = 7
// Custom Message Properties // Custom Message Properties
var/customsender = "System Administrator" var/customsender = "System Administrator"
var/obj/item/device/pda/customrecepient = null var/obj/item/device/pda/customrecepient = null
@@ -32,26 +34,29 @@
var/custommessage = "This is a test, please ignore." var/custommessage = "This is a test, please ignore."
/obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/user as mob) /obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob)
if(stat & (NOPOWER|BROKEN)) if(stat & (NOPOWER|BROKEN))
return return
if(!istype(user, /mob/living)) if(!istype(user))
return return
if(istype(O,/obj/item/weapon/card/emag/)) if(istype(O,/obj/item/weapon/card/emag/))
// 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. // 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.. // It'll take more time if there's more characters in the password..
if(!emag) if(!emag)
icon_state = hack_icon // An error screen I made in the computers.dmi if(!isnull(src.linkedServer))
emag = 1 icon_state = hack_icon // An error screen I made in the computers.dmi
screen = 2 emag = 1
spark_system.set_up(5, 0, src) screen = 2
src.spark_system.start() spark_system.set_up(5, 0, src)
var/obj/item/weapon/paper/monitorkey/MK = new/obj/item/weapon/paper/monitorkey src.spark_system.start()
MK.loc = src.loc var/obj/item/weapon/paper/monitorkey/MK = new/obj/item/weapon/paper/monitorkey
// Will help make emagging the console not so easy to get away with. MK.loc = src.loc
MK.info += "<br><br><font color='red'><3E>%@%(*$%&(<28>&?*(%&<26>/{}</font>" // Will help make emagging the console not so easy to get away with.
spawn(100*length(src.linkedServer.decryptkey)) UnmagConsole() MK.info += "<br><br><font color='red'><3E>%@%(*$%&(<28>&?*(%&<26>/{}</font>"
message = rebootmsg spawn(100*length(src.linkedServer.decryptkey)) UnmagConsole()
message = rebootmsg
else
user << "<span class='notice'>A no server error appears on the screen.</span>"
if(isscrewdriver(O) && emag) if(isscrewdriver(O) && emag)
//Stops people from just unscrewing the monitor and putting it back to get the console working again. //Stops people from just unscrewing the monitor and putting it back to get the console working again.
user << "<span class='warning'>It is too hot to mess with!</span>" user << "<span class='warning'>It is too hot to mess with!</span>"
@@ -76,10 +81,10 @@
linkedServer = message_servers[1] linkedServer = message_servers[1]
return return
/obj/machinery/computer/message_monitor/attack_hand(var/mob/user as mob) /obj/machinery/computer/message_monitor/attack_hand(var/mob/living/user as mob)
if(stat & (NOPOWER|BROKEN)) if(stat & (NOPOWER|BROKEN))
return return
if(!istype(user, /mob/living)) if(!istype(user))
return return
//If the computer is being hacked or is emagged, display the reboot message. //If the computer is being hacked or is emagged, display the reboot message.
if(hacking || emag) if(hacking || emag)
@@ -87,39 +92,53 @@
var/dat = "<head><title>Message Monitor Console</title></head><body>" var/dat = "<head><title>Message Monitor Console</title></head><body>"
dat += "<center><h2>Message Monitor Console</h2></center><hr>" dat += "<center><h2>Message Monitor Console</h2></center><hr>"
dat += "<center><h4><font color='blue'[message]</h5></center>" dat += "<center><h4><font color='blue'[message]</h5></center>"
if(auth)
dat += "<h4><dd><A href='?src=\ref[src];auth=1'>&#09;<font color='green'>\[Authenticated\]</font></a>&#09;/"
dat += " Server Power: <A href='?src=\ref[src];active=1'>[src.linkedServer && src.linkedServer.active ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a></h4>"
else
dat += "<h4><dd><A href='?src=\ref[src];auth=1'>&#09;<font color='red'>\[Unauthenticated\]</font></a>&#09;/"
dat += " Server Power: <u>[src.linkedServer && src.linkedServer.active ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</u></h4>"
if(hacking || emag)
screen = 2
else if(!auth || !linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) message = noserver
screen = 0
switch(screen) switch(screen)
//Main menu //Main menu
if(0) if(0)
if(hacking || emag)
screen = 2
return src.attack_hand(user)
//&#09; = TAB //&#09; = TAB
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) var/i = 0
dat += "<dd><A>&#09;ERROR: Server not found</A><br></dd>" dat += "<dd><A href='?src=\ref[src];find=1'>&#09;[++i]. Link To A Server</a></dd>"
if(auth)
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
dat += "<dd><A>&#09;ERROR: Server not found!</A><br></dd>"
else
dat += "<dd><A href='?src=\ref[src];view=1'>&#09;[++i]. View Message Logs </a><br></dd>"
dat += "<dd><A href='?src=\ref[src];viewr=1'>&#09;[++i]. View Request Console Logs </a></br></dd>"
dat += "<dd><A href='?src=\ref[src];clear=1'>&#09;[++i]. Clear Message Logs</a><br></dd>"
dat += "<dd><A href='?src=\ref[src];clearr=1'>&#09;[++i]. Clear Request Console Logs</a><br></dd>"
dat += "<dd><A href='?src=\ref[src];pass=1'>&#09;[++i]. Set Custom Key</a><br></dd>"
dat += "<dd><A href='?src=\ref[src];msg=1'>&#09;[++i]. Send Admin Message</a><br></dd>"
else else
dat += "<dd><A href='?src=\ref[src];active=1'>&#09;1. Toggle Power: [src.linkedServer.active ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a><br></dd>" for(var/n = ++i; n <= optioncount; n++)
dat += "<dd><A href='?src=\ref[src];find=1'>&#09;2. Link To A Server</a><hr></dd>" dat += "<dd><font color='blue'>&#09;[n]. ---------------</font><br></dd>"
dat += "<dd><font color='red'> KEY REQUIRED</font></dd><hr>"
dat += "<dd><A href='?src=\ref[src];view=1'>&#09;3. View Message Logs </a><br></dd>"
dat += "<dd><A href='?src=\ref[src];viewr=1'>&#09;4. View Request Console Logs </a></br></dd>"
dat += "<dd><A href='?src=\ref[src];clear=1'>&#09;5. Clear Message Logs</a><br></dd>"
dat += "<dd><A href='?src=\ref[src];clearr=1'>&#09;6. Clear Request Console Logs</a><br></dd>"
dat += "<dd><A href='?src=\ref[src];pass=1'>&#09;7. Set Custom Key</a><br></dd>"
dat += "<dd><A href='?src=\ref[src];msg=1'>&#09;8. Send Admin Message</a><hr><br></dd>"
//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)) if((istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) && (user.mind.special_role && user.mind.original == user))
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
dat += "<dd><A href='?src=\ref[src];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>" dat += "<dd><A href='?src=\ref[src];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>"
else
dat += "<br>"
//Bottom message
if(!auth)
dat += "<br><hr><dd><span class='notice'>Please authenticate with the server in order to show additional options.</span>"
else
dat += "<br><hr><dd><span class='warning'>Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties.</span>"
//Message Logs //Message Logs
if(1) if(1)
if(hacking || emag)
screen = 2
return src.attack_hand(user)
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver
screen = 0
return src.attack_hand(user)
var/index = 0 var/index = 0
//var/recipient = "Unspecified" //name of the person //var/recipient = "Unspecified" //name of the person
//var/sender = "Unspecified" //name of the sender //var/sender = "Unspecified" //name of the sender
@@ -136,9 +155,6 @@
dat += "</table>" dat += "</table>"
//Hacking screen. //Hacking screen.
if(2) if(2)
if(!hacking && !emag)
screen = 0
return src.attack_hand(user)
if(istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) if(istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot))
dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has." dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has."
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." 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."
@@ -182,9 +198,6 @@
//Fake messages //Fake messages
if(3) if(3)
if(hacking || emag)
screen = 2
return src.attack_hand(user)
dat += "<center><A href='?src=\ref[src];back=1'>Back</a> - <A href='?src=\ref[src];Reset=1'>Reset</a></center><hr>" dat += "<center><A href='?src=\ref[src];back=1'>Back</a> - <A href='?src=\ref[src];Reset=1'>Reset</a></center><hr>"
dat += {"<table border='1' width='100%'> dat += {"<table border='1' width='100%'>
@@ -203,13 +216,6 @@
//Request Console Logs //Request Console Logs
if(4) if(4)
if(hacking || emag)
screen = 2
return src.attack_hand(user)
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver
screen = 0
return src.attack_hand(user)
var/index = 0 var/index = 0
/* data_rc_msg /* data_rc_msg
@@ -245,8 +251,11 @@
return src.attack_hand(user) return src.attack_hand(user)
/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user as mob) /obj/machinery/computer/message_monitor/proc/BruteForce(mob/user as mob)
var/currentKey = src.linkedServer.decryptkey if(isnull(linkedServer))
user << "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>" user << "<span class='warning'>Could not complete brute-force: Linked Server Disconnected!</span>"
else
var/currentKey = src.linkedServer.decryptkey
user << "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>"
src.hacking = 0 src.hacking = 0
src.icon_state = normal_icon src.icon_state = normal_icon
src.screen = 0 // Return the screen back to normal src.screen = 0 // Return the screen back to normal
@@ -269,9 +278,22 @@
if(!istype(usr, /mob/living)) if(!istype(usr, /mob/living))
return return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
//Authenticate
if (href_list["auth"])
if(auth)
auth = 0
screen = 0
else
var/dkey = 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. //Turn the server on/off.
if (href_list["active"]) if (href_list["active"])
linkedServer.active = !linkedServer.active if(auth) linkedServer.active = !linkedServer.active
//Find a server //Find a server
if (href_list["find"]) if (href_list["find"])
if(message_servers && message_servers.len > 1) if(message_servers && message_servers.len > 1)
@@ -288,56 +310,39 @@
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver message = noserver
else else
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) if(auth)
if(dkey && dkey != "") src.screen = 1
if(src.linkedServer.decryptkey == dkey)
src.screen = 1
else
message = incorrectkey
//Clears the logs - KEY REQUIRED //Clears the logs - KEY REQUIRED
if (href_list["clear"]) if (href_list["clear"])
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver message = noserver
else else
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) if(auth)
if(dkey && dkey != "") src.linkedServer.pda_msgs = list()
if(src.linkedServer.decryptkey == dkey) message = "<span class='notice'>NOTICE: Logs cleared.</span>"
src.linkedServer.pda_msgs = list()
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
else
message = incorrectkey
//Clears the request console logs - KEY REQUIRED //Clears the request console logs - KEY REQUIRED
if (href_list["clearr"]) if (href_list["clearr"])
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver message = noserver
else else
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) if(auth)
if(dkey && dkey != "") src.linkedServer.rc_msgs = list()
if(src.linkedServer.decryptkey == dkey) message = "<span class='notice'>NOTICE: Logs cleared.</span>"
src.linkedServer.rc_msgs = list()
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
else
message = incorrectkey
//Change the password - KEY REQUIRED //Change the password - KEY REQUIRED
if (href_list["pass"]) if (href_list["pass"])
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver message = noserver
else else
var/dkey = trim(input(usr,"Please enter the decryption key:") as text|null) if(auth)
if(dkey && dkey != "") var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
if(dkey == src.linkedServer.decryptkey) if(length(newkey) <= 3)
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):")) message = "<span class='notice'>NOTICE: Decryption key too short!</span>"
if(length(newkey) <= 3) else if(length(newkey) > 16)
message = "<span class='notice'>NOTICE: Decryption key too short!</span>" message = "<span class='notice'>NOTICE: Decryption key too long!</span>"
else if(length(newkey) > 16) else if(newkey && newkey != "")
message = "<span class='notice'>NOTICE: Decryption key too long!</span>" src.linkedServer.decryptkey = newkey
else if(newkey && newkey != "") message = "<span class='notice'>NOTICE: Decryption key set.</span>"
src.linkedServer.decryptkey = newkey
message = "<span class='notice'>NOTICE: Decryption key set.</span>"
else
message = incorrectkey
//Hack the Console to get the password //Hack the Console to get the password
if (href_list["hack"]) 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)) if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && (usr.mind.special_role && usr.mind.original == usr))
@@ -371,12 +376,8 @@
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver message = noserver
else else
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) if(auth)
if(dkey && dkey != "") src.screen = 3
if(src.linkedServer.decryptkey == dkey)
src.screen = 3
else
message = incorrectkey
//Fake messaging selection - KEY REQUIRED //Fake messaging selection - KEY REQUIRED
if (href_list["select"]) if (href_list["select"])
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
@@ -401,7 +402,7 @@
if(!P.owner || P.toff) continue if(!P.owner || P.toff) continue
sendPDAs += P sendPDAs += P
if(PDAs && PDAs.len > 0) if(PDAs && PDAs.len > 0)
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortList(sendPDAs) customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
else else
customrecepient = null customrecepient = null
@@ -469,12 +470,8 @@
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
message = noserver message = noserver
else else
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) if(auth)
if(dkey && dkey != "") src.screen = 4
if(src.linkedServer.decryptkey == dkey)
src.screen = 4
else
message = incorrectkey
//usr << href_list["select"] //usr << href_list["select"]

View File

@@ -356,7 +356,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/count = 0 var/count = 0
if (!toff) if (!toff)
for (var/obj/item/device/pda/P in sortList(PDAs)) for (var/obj/item/device/pda/P in sortAtom(PDAs))
if (!P.owner||P.toff||P == src) continue if (!P.owner||P.toff||P == src) continue
dat += "<li><a href='byond://?src=\ref[src];choice=Message;target=\ref[P]'>[P]</a>" dat += "<li><a href='byond://?src=\ref[src];choice=Message;target=\ref[P]'>[P]</a>"
if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate) if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate)

View File

@@ -638,7 +638,7 @@
[(pda.silent) ? "<font color='red'> \[Off\]</font>" : "<font color='green'> \[On\]</font>"]</a><br><br>"} [(pda.silent) ? "<font color='red'> \[Off\]</font>" : "<font color='green'> \[On\]</font>"]</a><br><br>"}
dat += "<ul>" dat += "<ul>"
if(!pda.toff) if(!pda.toff)
for (var/obj/item/device/pda/P in sortList(PDAs)) for (var/obj/item/device/pda/P in sortAtom(PDAs))
if (!P.owner||P.toff||P == src.pda) continue if (!P.owner||P.toff||P == src.pda) continue
dat += "<li><a href='byond://?src=\ref[src];software=pdamessage;target=\ref[P]'>[P]</a>" dat += "<li><a href='byond://?src=\ref[src];software=pdamessage;target=\ref[P]'>[P]</a>"
dat += "</li>" dat += "</li>"

View File

@@ -1381,7 +1381,7 @@
"aAC" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/requests_console{department = "Tech storage"; pixel_x = -30},/turf/simulated/floor/plating,/area/storage/tech) "aAC" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/requests_console{department = "Tech storage"; pixel_x = -30},/turf/simulated/floor/plating,/area/storage/tech)
"aAD" = (/obj/machinery/light,/obj/machinery/light_switch{pixel_y = -23},/turf/simulated/floor/plating,/area/storage/tech) "aAD" = (/obj/machinery/light,/obj/machinery/light_switch{pixel_y = -23},/turf/simulated/floor/plating,/area/storage/tech)
"aAE" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = "90Curve"},/turf/simulated/floor/plating,/area/storage/tech) "aAE" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = "90Curve"},/turf/simulated/floor/plating,/area/storage/tech)
"aAF" = (/obj/machinery/light,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0; tag = "Streight"},/turf/simulated/floor/plating,/area/storage/tech) "aAF" = (/obj/machinery/light,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0; tag = "Streight"},/obj/item/weapon/circuitboard/message_monitor{step_x = 3; step_y = 29},/turf/simulated/floor/plating,/area/storage/tech)
"aAG" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = "90Curve"},/turf/simulated/floor/plating,/area/storage/tech) "aAG" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = "90Curve"},/turf/simulated/floor/plating,/area/storage/tech)
"aAH" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/obj/machinery/camera{c_tag = "Tech Storage South"; dir = 1; network = "SS13"},/turf/simulated/floor/plating,/area/storage/tech) "aAH" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/obj/machinery/camera{c_tag = "Tech Storage South"; dir = 1; network = "SS13"},/turf/simulated/floor/plating,/area/storage/tech)
"aAI" = (/obj/machinery/camera{c_tag = "Secure Construction Area"; dir = 4; network = "SS13"},/obj/item/weapon/crowbar,/obj/item/weapon/extinguisher,/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/structure/table/reinforced,/turf/simulated/floor/plating,/area/teleporter/gateway) "aAI" = (/obj/machinery/camera{c_tag = "Secure Construction Area"; dir = 4; network = "SS13"},/obj/item/weapon/crowbar,/obj/item/weapon/extinguisher,/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/structure/table/reinforced,/turf/simulated/floor/plating,/area/teleporter/gateway)