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 += "
"
+
+ message = defaultmsg
+
+ popup.set_content(dat)
+ popup.open()
+ return
+
+
+ proc/BruteForce(mob/usr as mob)
+ if(isnull(linkedServer))
+ usr << "Could not complete brute-force: Linked Server Disconnected!"
+ else
+ var/currentKey = src.linkedServer.decryptkey
+ usr << "Brute-force completed! The key is '[currentKey]'."
+ src.hacking = 0
+ src.active_state = normal_icon
+ src.screen = 0 // Return the screen back to normal
+
+ proc/UnmagConsole()
+ src.active_state = normal_icon
+ src.emag = 0
+
+ proc/ResetMessage()
+ customsender = "System Administrator"
+ customrecepient = null
+ custommessage = "This is a test, please ignore."
+ customjob = "Admin"
+
+ Topic(var/href, var/list/href_list)
+ if(!interactable() || ..(href,href_list))
+ return
+
+ if ("auth" in href_list)
+ 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.
+ if ("active" in href_list)
+ if(auth) linkedServer.active = !linkedServer.active
+ //Find a server
+ if ("find" in href_list)
+ 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 ("view" in href_list)
+ if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ message = noserver
+ else
+ if(auth)
+ src.screen = 1
+
+ //Clears the logs - KEY REQUIRED
+ if ("clear" in href_list)
+ if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ message = noserver
+ else
+ if(auth)
+ src.linkedServer.pda_msgs = list()
+ message = "NOTICE: Logs cleared."
+ //Clears the request console logs - KEY REQUIRED
+ if ("clearr" in href_list)
+ if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ message = noserver
+ else
+ if(auth)
+ src.linkedServer.rc_msgs = list()
+ message = "NOTICE: Logs cleared."
+ //Change the password - KEY REQUIRED
+ if ("pass" in href_list)
+ if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ message = noserver
+ else
+ if(auth)
+ var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
+ if(dkey && dkey != "")
+ if(src.linkedServer.decryptkey == dkey)
+ var/newkey = 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 ("hack" in href_list)
+ 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
+ src.active_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 ("delete" in href_list)
+ //Are they on the view logs screen?
+ if(screen == 1)
+ if(!linkedServer || (src.linkedServer.stat & (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 ("deleter" in href_list)
+ //Are they on the view logs screen?
+ if(screen == 4)
+ if(!linkedServer || (src.linkedServer.stat & (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 ("msg" in href_list)
+ if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ message = noserver
+ else
+ if(auth)
+ src.screen = 3
+ //Fake messaging selection - KEY REQUIRED
+ if ("select" in href_list)
+ if(src.linkedServer == null || (src.linkedServer.stat & (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
+
+ //Select Receiver
+ if("Recepient")
+ //Get out list of viable PDAs
+ var/list/obj/item/device/pda/sendPDAs = list()
+ for(var/obj/item/device/pda/P in PDAs)
+ if(!P.owner || P.toff || P.hidden) continue
+ sendPDAs += P
+ if(PDAs && PDAs.len > 0)
+ customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortAtom(sendPDAs)
+ else
+ customrecepient = null
+
+
+ //Enter custom job
+ if("RecJob")
+ customjob = input(usr, "Please enter the sender's job.") as text|null
+
+ //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/obj/item/device/pda/PDARec = null
+ for (var/obj/item/device/pda/P in PDAs)
+ if (!P.owner || P.toff || P.hidden) continue
+ 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]")
+ customrecepient.tnote += "← From [customsender] ([customjob]):
[custommessage]
"
+ if (!customrecepient.silent)
+ playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
+ for (var/mob/O in hearers(3, customrecepient.loc))
+ O.show_message(text("\icon[customrecepient] *[customrecepient.ttone]*"))
+ if( customrecepient.loc && ishuman(customrecepient.loc) )
+ var/mob/living/carbon/human/H = customrecepient.loc
+ H << "\icon[customrecepient] Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)"
+ log_pda("[usr] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]")
+ customrecepient.overlays.Cut()
+ 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]")
+ customrecepient.tnote += "← From [PDARec.owner] ([customjob]):
[custommessage]
"
+ if (!customrecepient.silent)
+ playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
+ for (var/mob/O in hearers(3, customrecepient.loc))
+ O.show_message(text("\icon[customrecepient] *[customrecepient.ttone]*"))
+ if( customrecepient.loc && ishuman(customrecepient.loc) )
+ var/mob/living/carbon/human/H = customrecepient.loc
+ H << "\icon[customrecepient] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)"
+ log_pda("[usr] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]")
+ customrecepient.overlays.Cut()
+ customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r")
+ //Finally..
+ ResetMessage()
+
+ //Request Console Logs - KEY REQUIRED
+ if("viewr" in href_list)
+ if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
+ message = noserver
+ else
+ if(auth)
+ src.screen = 4
+
+ //usr << href_list["select"]
+
+ if ("back" in href_list)
+ src.screen = 0
+ interact()
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/computers/pod.dm b/code/WorkInProgress/computer3/computers/pod.dm
new file mode 100644
index 0000000000..47f45b1c91
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/pod.dm
@@ -0,0 +1,218 @@
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+
+/obj/machinery/computer3/pod
+ name = "Pod Launch Control"
+ desc = "A controll for launching pods. Some people prefer firing Mechas."
+ icon_state = "computer_generic"
+ var/id = 1.0
+ var/obj/machinery/mass_driver/connected = null
+ var/timing = 0.0
+ var/time = 30.0
+ var/title = "Mass Driver Controls"
+
+
+/obj/machinery/computer3/pod/New()
+ ..()
+ spawn( 5 )
+ for(var/obj/machinery/mass_driver/M in world)
+ if(M.id == id)
+ connected = M
+ else
+ return
+ return
+
+
+/obj/machinery/computer3/pod/proc/alarm()
+ if(stat & (NOPOWER|BROKEN))
+ return
+
+ if(!( connected ))
+ viewers(null, null) << "Cannot locate mass driver connector. Cancelling firing sequence!"
+ return
+
+ for(var/obj/machinery/door/poddoor/M in world)
+ if(M.id == id)
+ M.open()
+ return
+ sleep(20)
+
+ for(var/obj/machinery/mass_driver/M in world)
+ if(M.id == id)
+ M.power = connected.power
+ M.drive()
+
+ sleep(50)
+ for(var/obj/machinery/door/poddoor/M in world)
+ if(M.id == id)
+ M.close()
+ return
+ return
+
+
+/obj/machinery/computer3/pod/attackby(I as obj, user as mob)
+ if(istype(I, /obj/item/tool/screwdriver))
+ playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ if(do_after(user, 20))
+ if(stat & BROKEN)
+ user << "\blue The broken glass falls out."
+ var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc )
+ new /obj/item/trash/shard( loc )
+
+ //generate appropriate circuitboard. Accounts for /pod/old computer types
+ var/obj/item/part/board/circuit/pod/M = null
+ if(istype(src, /obj/machinery/computer/pod/old))
+ M = new /obj/item/part/board/circuit/olddoor( A )
+ if(istype(src, /obj/machinery/computer/pod/old/syndicate))
+ M = new /obj/item/part/board/circuit/syndicatedoor( A )
+ if(istype(src, /obj/machinery/computer/pod/old/swf))
+ M = new /obj/item/part/board/circuit/swfdoor( A )
+ else //it's not an old computer. Generate standard pod circuitboard.
+ M = new /obj/item/part/board/circuit/pod( A )
+
+ for (var/obj/C in src)
+ C.loc = loc
+ M.id = id
+ A.circuit = M
+ A.state = 3
+ A.icon_state = "3"
+ A.anchored = 1
+ del(src)
+ else
+ user << "\blue You disconnect the monitor."
+ var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc )
+
+ //generate appropriate circuitboard. Accounts for /pod/old computer types
+ var/obj/item/part/board/circuit/pod/M = null
+ if(istype(src, /obj/machinery/computer/pod/old))
+ M = new /obj/item/part/board/circuit/olddoor( A )
+ if(istype(src, /obj/machinery/computer/pod/old/syndicate))
+ M = new /obj/item/part/board/circuit/syndicatedoor( A )
+ if(istype(src, /obj/machinery/computer/pod/old/swf))
+ M = new /obj/item/part/board/circuit/swfdoor( A )
+ else //it's not an old computer. Generate standard pod circuitboard.
+ M = new /obj/item/part/board/circuit/pod( A )
+
+ for (var/obj/C in src)
+ C.loc = loc
+ M.id = id
+ A.circuit = M
+ A.state = 4
+ A.icon_state = "4"
+ A.anchored = 1
+ del(src)
+ else
+ attack_hand(user)
+ return
+
+
+/obj/machinery/computer3/pod/attack_ai(var/mob/user as mob)
+ return attack_hand(user)
+
+
+/obj/machinery/computer3/pod/attack_paw(var/mob/user as mob)
+ return attack_hand(user)
+
+
+/obj/machinery/computer3/pod/attack_hand(var/mob/user as mob)
+ if(..())
+ return
+
+ var/dat = ""
+ user.set_machine(src)
+ if(connected)
+ var/d2
+ if(timing) //door controls do not need timers.
+ d2 = "Stop Time Launch"
+ else
+ d2 = "Initiate Time Launch"
+ var/second = time % 60
+ var/minute = (time - second) / 60
+ dat += "
\nTimer System: [d2]\nTime Left: [minute ? "[minute]:" : null][second] - - + +"
+ var/temp = ""
+ var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
+ for(var/t in L)
+ if(t == connected.power)
+ temp += "[t] "
+ else
+ temp += "[t] "
+ dat += "
\nPower Level: [temp]
\nFiring Sequence
\nTest Fire Driver
\nToggle Outer Door
"
+ else
+ dat += "
\nToggle Outer Door
"
+ dat += "
Close"
+ add_fingerprint(usr)
+ //user << browse(dat, "window=computer;size=400x500")
+ //onclose(user, "computer")
+ var/datum/browser/popup = new(user, "computer", title, 400, 500)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+
+/obj/machinery/computer3/pod/process()
+ if(!..())
+ return
+ if(timing)
+ if(time > 0)
+ time = round(time) - 1
+ else
+ alarm()
+ time = 0
+ timing = 0
+ updateDialog()
+ return
+
+
+/obj/machinery/computer3/pod/Topic(href, href_list)
+ if(..())
+ return
+ if((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
+ usr.set_machine(src)
+ if(href_list["power"])
+ var/t = text2num(href_list["power"])
+ t = min(max(0.25, t), 16)
+ if(connected)
+ connected.power = t
+ if(href_list["alarm"])
+ alarm()
+ if(href_list["time"])
+ timing = text2num(href_list["time"])
+ if(href_list["tp"])
+ var/tp = text2num(href_list["tp"])
+ time += tp
+ time = min(max(round(time), 0), 120)
+ if(href_list["door"])
+ for(var/obj/machinery/door/poddoor/M in world)
+ if(M.id == id)
+ if(M.density)
+ M.open()
+ else
+ M.close()
+ updateUsrDialog()
+ return
+
+
+
+/obj/machinery/computer3/pod/old
+ icon_state = "old"
+ name = "DoorMex Control Console"
+ title = "Door Controls"
+
+
+
+/obj/machinery/computer3/pod/old/syndicate
+ name = "ProComp Executive IIc"
+ desc = "The Syndicate operate on a tight budget. Operates external airlocks."
+ title = "External Airlock Controls"
+ req_access = list(access_syndicate)
+
+/obj/machinery/computer3/pod/old/syndicate/attack_hand(var/mob/user as mob)
+ if(!allowed(user))
+ user << "\red Access Denied"
+ return
+ else
+ ..()
+
+/obj/machinery/computer3/pod/old/swf
+ name = "Magix System IV"
+ desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorceror's Edition"
diff --git a/code/WorkInProgress/computer3/computers/power.dm b/code/WorkInProgress/computer3/computers/power.dm
new file mode 100644
index 0000000000..4bd838a207
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/power.dm
@@ -0,0 +1,47 @@
+/obj/machinery/computer3/powermonitor
+ default_prog = /datum/file/program/powermon
+ spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/cable)
+ icon_state = "frame-eng"
+
+/datum/file/program/powermon
+ name = "power monitoring console"
+ desc = "It monitors APC status."
+ active_state = "power"
+
+ proc/format(var/obj/machinery/power/apc/A)
+ var/static/list/S = list(" Off","AOff"," On", " AOn")
+ var/static/list/chg = list("N","C","F")
+ return "[copytext(add_tspace("\The [A.area]", 30), 1, 30)] [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]
"
+
+ interact()
+ if(!interactable())
+ return
+ if(!computer.net)
+ computer.Crash(MISSING_PERIPHERAL)
+ return
+ var/list/L = computer.net.get_machines(/obj/machinery/power/apc)
+ var/t = ""
+ t += "Refresh
"
+ if(!L || !L.len)
+ t += "\red No connection"
+ else
+ var/datum/powernet/powernet = computer.net.connect_to(/datum/powernet,null)
+ if(powernet)
+ t += "Total power: [powernet.avail] W
Total load: [num2text(powernet.viewload,10)] W
"
+ else
+ t += "Power statistics unavailable
"
+ t += ""
+
+ if(L.len > 0)
+ t += "Area Eqp./Lgt./Env. Load Cell
"
+ for(var/obj/machinery/power/apc/A in L)
+ t += src.format(A)
+ t += "
"
+
+ popup.set_content(t)
+ popup.open()
+
+ Topic(var/href, var/list/href_list)
+ if(!interactable() || ..(href,href_list))
+ return
+ interact()
diff --git a/code/WorkInProgress/computer3/computers/prisoner.dm b/code/WorkInProgress/computer3/computers/prisoner.dm
new file mode 100644
index 0000000000..d88a8bffdf
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/prisoner.dm
@@ -0,0 +1,109 @@
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+
+/obj/machinery/computer3/prisoner
+ name = "Prisoner Management Comsole"
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "explosive"
+ req_access = list(access_armory)
+ circuit = "/obj/item/part/board/circuit/prisoner"
+ var/id = 0.0
+ var/temp = null
+ var/status = 0
+ var/timeleft = 60
+ var/stop = 0.0
+ var/screen = 0 // 0 - No Access Denied, 1 - Access allowed
+
+
+ attack_ai(var/mob/user as mob)
+ return src.attack_hand(user)
+
+
+ attack_paw(var/mob/user as mob)
+ return
+
+
+ attack_hand(var/mob/user as mob)
+ if(..())
+ return
+ user.set_machine(src)
+ var/dat
+ dat += "Prisoner Implant Manager System
"
+ if(screen == 0)
+ dat += "
Unlock Console"
+ else if(screen == 1)
+ dat += "
Chemical Implants
"
+ var/turf/Tr = null
+ for(var/obj/item/weapon/implant/chem/C in world)
+ Tr = get_turf(C)
+ if((Tr) && (Tr.z != src.z)) continue//Out of range
+ if(!C.implanted) continue
+ dat += "[C.imp_in.name] | Remaining Units: [C.reagents.total_volume] | Inject: "
+ dat += "((1))"
+ dat += "((5))"
+ dat += "((10))
"
+ dat += "********************************
"
+ dat += "
Tracking Implants
"
+ for(var/obj/item/weapon/implant/tracking/T in world)
+ Tr = get_turf(T)
+ if((Tr) && (Tr.z != src.z)) continue//Out of range
+ if(!T.implanted) continue
+ var/loc_display = "Unknown"
+ var/mob/living/carbon/M = T.imp_in
+ if(M.z == 1 && !istype(M.loc, /turf/space))
+ var/turf/mob_loc = get_turf_loc(M)
+ loc_display = mob_loc.loc
+ if(T.malfunction)
+ loc_display = pick(teleportlocs)
+ dat += "ID: [T.id] | Location: [loc_display]
"
+ dat += "(Message Holder) |
"
+ dat += "********************************
"
+ dat += "
Lock Console"
+
+ user << browse(dat, "window=computer;size=400x500")
+ onclose(user, "computer")
+ return
+
+
+ process()
+ if(!..())
+ src.updateDialog()
+ return
+
+
+ Topic(href, href_list)
+ if(..())
+ return
+ if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
+ usr.set_machine(src)
+
+ if(href_list["inject1"])
+ var/obj/item/weapon/implant/I = locate(href_list["inject1"])
+ if(I) I.activate(1)
+
+ else if(href_list["inject5"])
+ var/obj/item/weapon/implant/I = locate(href_list["inject5"])
+ if(I) I.activate(5)
+
+ else if(href_list["inject10"])
+ var/obj/item/weapon/implant/I = locate(href_list["inject10"])
+ if(I) I.activate(10)
+
+ else if(href_list["lock"])
+ if(src.allowed(usr))
+ screen = !screen
+ else
+ usr << "Unauthorized Access."
+
+ else if(href_list["warn"])
+ var/warning = copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN)
+ if(!warning) return
+ var/obj/item/weapon/implant/I = locate(href_list["warn"])
+ if((I)&&(I.imp_in))
+ var/mob/living/carbon/R = I.imp_in
+ R << "\green You hear a voice in your head saying: '[warning]'"
+
+ src.add_fingerprint(usr)
+ src.updateUsrDialog()
+ return
+
+
diff --git a/code/WorkInProgress/computer3/computers/prisonshuttle.dm b/code/WorkInProgress/computer3/computers/prisonshuttle.dm
new file mode 100644
index 0000000000..f6f246e578
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/prisonshuttle.dm
@@ -0,0 +1,242 @@
+//Config stuff
+#define PRISON_MOVETIME 150 //Time to station is milliseconds.
+#define PRISON_STATION_AREATYPE "/area/shuttle/prison/station" //Type of the prison shuttle area for station
+#define PRISON_DOCK_AREATYPE "/area/shuttle/prison/prison" //Type of the prison shuttle area for dock
+
+var/prison_shuttle_moving_to_station = 0
+var/prison_shuttle_moving_to_prison = 0
+var/prison_shuttle_at_station = 0
+var/prison_shuttle_can_send = 1
+var/prison_shuttle_time = 0
+var/prison_shuttle_timeleft = 0
+
+/obj/machinery/computer3/prison_shuttle
+ name = "Prison Shuttle Console"
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "shuttle"
+ req_access = list(access_security)
+ circuit = "/obj/item/part/board/circuit/prison_shuttle"
+ var/temp = null
+ var/hacked = 0
+ var/allowedtocall = 0
+ var/prison_break = 0
+
+
+ attackby(I as obj, user as mob)
+ return src.attack_hand(user)
+
+
+ attack_ai(var/mob/user as mob)
+ return src.attack_hand(user)
+
+
+ attack_paw(var/mob/user as mob)
+ return src.attack_hand(user)
+
+
+ attackby(I as obj, user as mob)
+ if(istype(I, /obj/item/tool/screwdriver))
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ if(do_after(user, 20))
+ var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
+ var/obj/item/part/board/circuit/prison_shuttle/M = new /obj/item/part/board/circuit/prison_shuttle( A )
+ for (var/obj/C in src)
+ C.loc = src.loc
+ A.circuit = M
+ A.anchored = 1
+
+ if (src.stat & BROKEN)
+ user << "\blue The broken glass falls out."
+ new /obj/item/trash/shard( src.loc )
+ A.state = 3
+ A.icon_state = "3"
+ else
+ user << "\blue You disconnect the monitor."
+ A.state = 4
+ A.icon_state = "4"
+
+ del(src)
+ else if(istype(I,/obj/item/card/emag) && (!hacked))
+ hacked = 1
+ user << "\blue You disable the lock."
+ else
+ return src.attack_hand(user)
+
+
+ attack_hand(var/mob/user as mob)
+ if(!src.allowed(user) && (!hacked))
+ user << "\red Access Denied."
+ return
+ if(prison_break)
+ user << "\red Unable to locate shuttle."
+ return
+ if(..())
+ return
+ user.set_machine(src)
+ post_signal("prison")
+ var/dat
+ if (src.temp)
+ dat = src.temp
+ else
+ dat += {"Location: [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "Moving to station ([prison_shuttle_timeleft] Secs.)":prison_shuttle_at_station ? "Station":"Dock"]
+ [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "\n*Shuttle already called*
\n
":prison_shuttle_at_station ? "\nSend to Dock
\n
":"\nSend to Station
\n
"]
+ \nClose"}
+
+ //user << browse(dat, "window=computer;size=575x450")
+ //onclose(user, "computer")
+ var/datum/browser/popup = new(user, "computer", name, 575, 450)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+
+ Topic(href, href_list)
+ if(..())
+ return
+
+ if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
+ usr.set_machine(src)
+
+ if (href_list["sendtodock"])
+ if (!prison_can_move())
+ usr << "\red The prison shuttle is unable to leave."
+ return
+ if(!prison_shuttle_at_station|| prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
+ post_signal("prison")
+ usr << "\blue The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds."
+ src.temp += "Shuttle sent.
OK"
+ src.updateUsrDialog()
+ prison_shuttle_moving_to_prison = 1
+ prison_shuttle_time = world.timeofday + PRISON_MOVETIME
+ spawn(0)
+ prison_process()
+
+ else if (href_list["sendtostation"])
+ if (!prison_can_move())
+ usr << "\red The prison shuttle is unable to leave."
+ return
+ if(prison_shuttle_at_station || prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
+ post_signal("prison")
+ usr << "\blue The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds."
+ src.temp += "Shuttle sent.
OK"
+ src.updateUsrDialog()
+ prison_shuttle_moving_to_station = 1
+ prison_shuttle_time = world.timeofday + PRISON_MOVETIME
+ spawn(0)
+ prison_process()
+
+ else if (href_list["mainmenu"])
+ src.temp = null
+
+ src.add_fingerprint(usr)
+ src.updateUsrDialog()
+ return
+
+
+ proc/prison_can_move()
+ if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return 0
+ else return 1
+
+/*
+ proc/prison_break()
+ switch(prison_break)
+ if (0)
+ if(!prison_shuttle_at_station || prison_shuttle_moving_to_prison) return
+
+ prison_shuttle_moving_to_prison = 1
+ prison_shuttle_at_station = prison_shuttle_at_station
+
+ if (!prison_shuttle_moving_to_prison || !prison_shuttle_moving_to_station)
+ prison_shuttle_time = world.timeofday + PRISON_MOVETIME
+ spawn(0)
+ prison_process()
+ prison_break = 1
+ if(1)
+ prison_break = 0
+*/
+
+ proc/post_signal(var/command)
+ var/datum/radio_frequency/frequency = radio_controller.return_frequency(1311)
+ if(!frequency) return
+ var/datum/signal/status_signal = new
+ status_signal.source = src
+ status_signal.transmission_method = 1
+ status_signal.data["command"] = command
+ frequency.post_signal(src, status_signal)
+ return
+
+
+ proc/prison_process()
+ while(prison_shuttle_time - world.timeofday > 0)
+ var/ticksleft = prison_shuttle_time - world.timeofday
+
+ if(ticksleft > 1e5)
+ prison_shuttle_time = world.timeofday + 10 // midnight rollover
+
+ prison_shuttle_timeleft = (ticksleft / 10)
+ sleep(5)
+ prison_shuttle_moving_to_station = 0
+ prison_shuttle_moving_to_prison = 0
+
+ switch(prison_shuttle_at_station)
+
+ if(0)
+ prison_shuttle_at_station = 1
+ if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
+
+ if (!prison_can_move())
+ usr << "\red The prison shuttle is unable to leave."
+ return
+
+ var/area/start_location = locate(/area/shuttle/prison/prison)
+ var/area/end_location = locate(/area/shuttle/prison/station)
+
+ var/list/dstturfs = list()
+ var/throwy = world.maxy
+
+ for(var/turf/T in end_location)
+ dstturfs += T
+ if(T.y < throwy)
+ throwy = T.y
+ // hey you, get out of the way!
+ for(var/turf/T in dstturfs)
+ // find the turf to move things to
+ var/turf/D = locate(T.x, throwy - 1, 1)
+ //var/turf/E = get_step(D, SOUTH)
+ for(var/atom/movable/AM as mob|obj in T)
+ AM.Move(D)
+ if(istype(T, /turf/simulated))
+ del(T)
+ start_location.move_contents_to(end_location)
+
+ if(1)
+ prison_shuttle_at_station = 0
+ if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
+
+ if (!prison_can_move())
+ usr << "\red The prison shuttle is unable to leave."
+ return
+
+ var/area/start_location = locate(/area/shuttle/prison/station)
+ var/area/end_location = locate(/area/shuttle/prison/prison)
+
+ var/list/dstturfs = list()
+ var/throwy = world.maxy
+
+ for(var/turf/T in end_location)
+ dstturfs += T
+ if(T.y < throwy)
+ throwy = T.y
+
+ // hey you, get out of the way!
+ for(var/turf/T in dstturfs)
+ // find the turf to move things to
+ var/turf/D = locate(T.x, throwy - 1, 1)
+ //var/turf/E = get_step(D, SOUTH)
+ for(var/atom/movable/AM as mob|obj in T)
+ AM.Move(D)
+ if(istype(T, /turf/simulated))
+ del(T)
+ start_location.move_contents_to(end_location)
+ return
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/computers/robot.dm b/code/WorkInProgress/computer3/computers/robot.dm
new file mode 100644
index 0000000000..e3eca9ace2
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/robot.dm
@@ -0,0 +1,211 @@
+/obj/machinery/computer3/robotics
+ default_prog = /datum/file/program/borg_control
+ spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio)
+ icon_state = "frame-rnd"
+
+/datum/file/program/borg_control
+ name = "Cyborg Control"
+ desc = "Used to remotely lockdown or detonate linked Cyborgs."
+ active_state = "robot"
+ var/id = 0.0
+ var/temp = null
+ var/status = 0
+ var/timeleft = 60
+ var/stop = 0.0
+ var/screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text
+ req_access = list(access_robotics)
+
+ proc/start_sequence()
+ do
+ if(src.stop)
+ src.stop = 0
+ return
+ src.timeleft--
+ sleep(10)
+ while(src.timeleft)
+
+ for(var/mob/living/silicon/robot/R in mob_list)
+ if(!R.scrambledcodes)
+ R.self_destruct()
+ return
+
+
+ interact()
+ if(!interactable() || computer.z > 6)
+ return
+ var/dat
+ if (src.temp)
+ dat = "[src.temp]
Clear Screen"
+ else
+ if(screen == 0)
+ //dat += "Cyborg Control Console
"
+ dat += "1. Cyborg Status
"
+ dat += "2. Emergency Full Destruct
"
+ if(screen == 1)
+ for(var/mob/living/silicon/robot/R in mob_list)
+ if(istype(usr, /mob/living/silicon/ai))
+ if (R.connected_ai != usr)
+ continue
+ if(istype(usr, /mob/living/silicon/robot))
+ if (R != usr)
+ continue
+ if(R.scrambledcodes)
+ continue
+
+ dat += "[R.name] |"
+ if(R.stat)
+ dat += " Not Responding |"
+ else if (!R.canmove)
+ dat += " Locked Down |"
+ else
+ dat += " Operating Normally |"
+ if (!R.canmove)
+ else if(R.cell)
+ dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
+ else
+ dat += " No Cell Installed |"
+ if(R.module)
+ dat += " Module Installed ([R.module.name]) |"
+ else
+ dat += " No Module Installed |"
+ if(R.connected_ai)
+ dat += " Slaved to [R.connected_ai.name] |"
+ else
+ dat += " Independent from AI |"
+ if (istype(usr, /mob/living/silicon))
+ if(issilicon(usr) && is_special_character(usr) && !R.emagged)
+ dat += "(Hack) "
+ dat += "([R.canmove ? "Lockdown" : "Release"]) "
+ dat += "(Destroy)"
+ dat += "
"
+ dat += "(Return to Main Menu)
"
+ if(screen == 2)
+ if(!src.status)
+ dat += {"
Emergency Robot Self-Destruct
\nStatus: Off
+ \n
+ \nCountdown: [src.timeleft]/60 \[Reset\]
+ \n
+ \nStart Sequence
+ \n
+ \nClose"}
+ else
+ dat = {"Emergency Robot Self-Destruct
\nStatus: Activated
+ \n
+ \nCountdown: [src.timeleft]/60 \[Reset\]
+ \n
\nStop Sequence
+ \n
+ \nClose"}
+ dat += "(Return to Main Menu)
"
+
+ popup.set_content(dat)
+ popup.open()
+ return
+
+ Topic(var/href, var/list/href_list)
+ if(!interactable() || ..(href,href_list))
+ return
+
+ if ("killall" in href_list)
+ src.temp = {"Destroy Robots?
+
\[Swipe ID to initiate destruction sequence\]
+ Cancel"}
+
+ if ("do_killall" in href_list)
+ var/obj/item/weapon/card/id/I = usr.get_active_hand()
+ if (istype(I, /obj/item/device/pda))
+ var/obj/item/device/pda/pda = I
+ I = pda.id
+ if (istype(I))
+ if(src.check_access(I))
+ if (!status)
+ message_admins("\blue [key_name_admin(usr)] has initiated the global cyborg killswitch!")
+ log_game("\blue [key_name(usr)] has initiated the global cyborg killswitch!")
+ src.status = 1
+ src.start_sequence()
+ src.temp = null
+
+ else
+ usr << "\red Access Denied."
+
+ if ("stop" in href_list)
+ src.temp = {"
+ Stop Robot Destruction Sequence?
+
Yes
+ No"}
+
+ if ("stop2" in href_list)
+ src.stop = 1
+ src.temp = null
+ src.status = 0
+
+ if ("reset" in href_list)
+ src.timeleft = 60
+
+ if ("temp" in href_list)
+ src.temp = null
+ if ("screen" in href_list)
+ switch(href_list["screen"])
+ if("0")
+ screen = 0
+ if("1")
+ screen = 1
+ if("2")
+ screen = 2
+ if ("killbot" in href_list)
+ if(computer.allowed(usr))
+ var/mob/living/silicon/robot/R = locate(href_list["killbot"])
+ if(R)
+ var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
+ if(choice == "Confirm")
+ if(R && istype(R))
+ if(R.mind && R.mind.special_role && R.emagged)
+ R << "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered."
+ R.ResetSecurityCodes()
+
+ else
+ message_admins("\blue [key_name_admin(usr)] detonated [R.name]!")
+ log_game("\blue [key_name_admin(usr)] detonated [R.name]!")
+ R.self_destruct()
+ else
+ usr << "\red Access Denied."
+
+ if ("stopbot" in href_list)
+ if(computer.allowed(usr))
+ var/mob/living/silicon/robot/R = locate(href_list["stopbot"])
+ if(R && istype(R)) // Extra sancheck because of input var references
+ var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
+ if(choice == "Confirm")
+ if(R && istype(R))
+ message_admins("\blue [key_name_admin(usr)] [R.canmove ? "locked down" : "released"] [R.name]!")
+ log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!")
+ R.canmove = !R.canmove
+ if (R.lockcharge)
+ // R.cell.charge = R.lockcharge
+ R.lockcharge = !R.lockcharge
+ R << "Your lockdown has been lifted!"
+ else
+ R.lockcharge = !R.lockcharge
+ // R.cell.charge = 0
+ R << "You have been locked down!"
+
+ else
+ usr << "\red Access Denied."
+
+ if ("magbot" in href_list)
+ if(computer.allowed(usr))
+ var/mob/living/silicon/robot/R = locate(href_list["magbot"])
+ if(R)
+ var/choice = input("Are you certain you wish to hack [R.name]?") in list("Confirm", "Abort")
+ if(choice == "Confirm")
+ if(R && istype(R))
+// message_admins("\blue [key_name_admin(usr)] emagged [R.name] using robotic console!")
+ log_game("[key_name(usr)] emagged [R.name] using robotic console!")
+ R.emagged = 1
+ if(R.mind.special_role)
+ R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes
+
+ interact()
+ return
+
+
+
diff --git a/code/WorkInProgress/computer3/computers/scanconsole.dm b/code/WorkInProgress/computer3/computers/scanconsole.dm
new file mode 100644
index 0000000000..3092f51fb8
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/scanconsole.dm
@@ -0,0 +1,1274 @@
+/obj/machinery/computer3/scan_consolenew
+ default_prog = /datum/file/program/dnascanner
+ spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/storage/removable,/obj/item/part/computer/networking/prox)
+
+
+#define MAX_UIBLOCK 13
+#define MAX_SEBLOCK 14
+
+/datum/file/program/dnascanner
+ name = "DNA Scanner and Manipulator"
+ desc = "The DNA ScaM is sure to change your life forever."
+ active_state = "dna"
+ var/obj/machinery/dna_scannernew/scanner = null
+
+ var/ui_block = 1
+ var/se_block = 1
+ var/subblock = 1
+
+ var/uitarget = 1
+ var/uitargethex = "1"
+
+ var/radduration = 2
+ var/radstrength = 1
+
+ var/injectorready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
+
+ var/mode = 0
+ // These keep track of the patient status
+ var/present = 0
+ var/viable = 0
+
+ var/bufferlabel = ""
+ var/datum/dna/buffer = null
+ var/obj/item/part/computer/target_drive = null
+
+ Reset()
+ ..()
+ mode = 0
+ scanner = null
+ ui_block = 1
+ se_block = 1
+ subblock = 1
+ buffer = null
+ bufferlabel = ""
+
+
+ Topic(var/href, var/list/href_list)
+ if(!interactable() || !computer.net || ..(href,href_list))
+ return
+
+ scanner = computer.net.connect_to(/obj/machinery/dna_scannernew, scanner) // if exists, will be verified
+ if(!scanner)
+ computer.Crash(NETWORK_FAILURE)
+ return
+
+ // todo check everything goddamnit
+ present = scanner.occupant && scanner.occupant.dna
+ viable = present && !(NOCLONE in scanner.occupant.mutations)
+
+ // current screen/function
+ if("mode" in href_list)
+ mode = text2num(href_list["mode"])
+ // locks scanner door
+ if("lock" in href_list)
+ scanner.locked = !scanner.locked
+
+ // inject good-juice
+ if("rejuv" in href_list)
+ rejuv()
+
+ // expose to radiation, controlled otherwise
+ if("pulse" in href_list)
+ pulse(href_list["pulse"]) // ui, se, or nothing/null
+
+ if("duration" in href_list)
+ var/modifier = text2num(href_list["duration"])
+ radduration += modifier
+ if("strength" in href_list)
+ var/modifier = text2num(href_list["strength"])
+ radstrength += modifier
+
+ if("uiblock" in href_list)
+ ui_block = text2num(href_list["uiblock"])
+ if("seblock" in href_list)
+ se_block = text2num(href_list["seblock"])
+ if("subblock" in href_list)
+ subblock = text2num(href_list["subblock"])
+ if("uitarget" in href_list)
+ uitarget = text2num(href_list["uitarget"])
+ uitargethex = num2hex(uitarget)
+
+ // save dna to buffer - buffer=se,ui,ue,all,clear
+ if("buffer" in href_list)
+ if(!viable)
+ return
+ var/which = href_list["buffer"]
+ if(!which || which == "clear")
+ buffer = null
+ else
+ if(!buffer)
+ buffer = new
+ if( which == "all" )
+ buffer.unique_enzymes = scanner.occupant.dna.unique_enzymes
+ buffer.struc_enzymes = scanner.occupant.dna.struc_enzymes
+ buffer.uni_identity = scanner.occupant.dna.uni_identity
+ buffer.real_name = scanner.occupant.dna.real_name
+ buffer.mutantrace = scanner.occupant.dna.mutantrace
+ if( which == "se" )
+ buffer.struc_enzymes = scanner.occupant.dna.struc_enzymes
+ buffer.mutantrace = scanner.occupant.dna.mutantrace
+ if( which == "ui" )
+ buffer.uni_identity = scanner.occupant.dna.uni_identity
+ if( which == "ue" )
+ buffer.uni_identity = scanner.occupant.dna.uni_identity
+ buffer.unique_enzymes = scanner.occupant.dna.unique_enzymes
+ buffer.real_name = scanner.occupant.dna.real_name
+
+ // save buffer to file -
+ if("save" in href_list)
+ if(!viable || !buffer)
+ return
+ var/datum/file/data/genome/G = null
+ var/obj/item/part/computer/dest = device
+ if(target_drive)
+ dest = target_drive
+
+ switch(href_list["save"])
+ if("se")
+ if(buffer.struc_enzymes)
+ G = new /datum/file/data/genome/SE()
+ G.content = buffer.struc_enzymes
+ G:mutantrace = buffer.mutantrace // : not . due to inheritance
+ G.real_name = buffer.real_name
+ if("ui")
+ if(buffer.uni_identity)
+ G = new /datum/file/data/genome/UI()
+ G.content = buffer.uni_identity
+ G.real_name = buffer.real_name
+ if("ue")
+ if(buffer.uni_identity)
+ G = new /datum/file/data/genome/UI/UE()
+ G.content = buffer.uni_identity
+ G.real_name = buffer.real_name
+ if(G && dest)
+ var/label = input(usr, "Enter a filename:", "Save file", buffer.real_name) as text
+ G.name = G.name + "([label])"
+ dest:addfile(G)
+
+ // load buffer from file
+ if("load" in href_list)
+ var/datum/file/data/genome/G = locate(href_list["load"])
+ if(G)
+ if(!buffer)
+ buffer = new
+ switch(G.type)
+ if(/datum/file/data/genome/SE)
+ buffer.struc_enzymes = G.content
+ buffer.mutantrace = G:mutantrace
+ if(/datum/file/data/genome/UI/UE)
+ buffer.uni_identity = G.content
+ buffer.real_name = G.real_name
+ buffer.unique_enzymes = md5(buffer.real_name)
+ if(/datum/file/data/genome/UI)
+ buffer.uni_identity = G.content
+ if(/datum/file/data/genome/cloning)
+ var/datum/dna/record = G:record
+ buffer.unique_enzymes = record.unique_enzymes
+ buffer.struc_enzymes = record.struc_enzymes
+ buffer.uni_identity = record.uni_identity
+ buffer.real_name = record.real_name
+ buffer.mutantrace = record.mutantrace
+
+
+ // inject genetics into occupant
+ if("inject" in href_list)
+ if(!buffer || !viable)
+ return
+
+ var/which = href_list["inject"]
+ var/datum/dna/target = scanner.occupant.dna
+ switch(which)
+ if("all",null)
+ if(buffer.struc_enzymes)
+ target.struc_enzymes = buffer.struc_enzymes
+ if(buffer.uni_identity)
+ target.uni_identity = buffer.uni_identity
+ if(buffer.real_name)
+ target.real_name = buffer.real_name
+ target.unique_enzymes = md5(target.real_name)
+ updateappearance(scanner.occupant,target.uni_identity)
+ domutcheck(scanner.occupant, scanner, 1)
+
+ if(ishuman(scanner.occupant))
+ target.mutantrace = buffer.mutantrace
+ scanner.occupant:update_mutantrace()
+ if("se")
+ if(buffer.struc_enzymes)
+ target.struc_enzymes = buffer.struc_enzymes
+ domutcheck(scanner.occupant, scanner, 1)
+ if(ishuman(scanner.occupant))
+ target.mutantrace = buffer.mutantrace
+ scanner.occupant:update_mutantrace()
+ if("ui")
+ if(buffer.uni_identity)
+ target.uni_identity = buffer.uni_identity
+ updateappearance(scanner.occupant,target.uni_identity)
+ if("ue")
+ if(buffer.uni_identity)
+ target.uni_identity = buffer.uni_identity
+ if(buffer.real_name)
+ target.real_name = buffer.real_name
+ target.unique_enzymes = md5(target.real_name)
+ updateappearance(scanner.occupant,target.uni_identity)
+
+ // generate dna injector
+ if("generate" in href_list)
+ if(!buffer || !injectorready)
+ return
+ buffer.check_integrity()
+ var/which = href_list["generate"]
+ var/obj/item/weapon/dnainjector/inj
+ switch(which)
+ if("se")
+ inj = new(computer.loc)
+ inj.dnatype = "se"
+ inj.dna = buffer.struc_enzymes
+ inj.mutantrace = buffer.mutantrace
+ inj.name = "Structural Enzymes"
+ if("ui")
+ inj = new(computer.loc)
+ inj.dnatype = "ui"
+ inj.dna = buffer.uni_identity
+ inj.ue = null
+ inj.name = "Unique Identifiers"
+ if("ue")
+ inj = new(computer.loc)
+ inj.dnatype = "ui"
+ inj.dna = buffer.uni_identity
+ inj.ue = buffer.real_name
+ inj.name = "Unique Enzymes + Unique Identifiers"
+ if(inj)
+ injectorready = 0
+ spawn(300)
+ injectorready = 1
+ var/label = input(usr, "Enter a label", "Label [inj.name] Injector", buffer.real_name) as null|text
+ if(label && inj) // it's possible it was deleted before we get here, input suspends execution
+ inj.name += " ([label])"
+
+ interact()
+ return // putting this in there to visually mark the end of topic() while I do other things
+
+ proc/menu()
+ if(!present && (mode==1 || mode==2)) // require viable occupant
+ mode = 0
+ switch(mode)
+ if(0) // MAIN MENU
+ return main_menu()
+
+ if(1)
+ return ui_menu()
+ if(2)
+ return se_menu()
+
+ if(3)
+ return emitter_menu()
+
+ if(4)
+ return buffer_menu()
+
+ // unified header with health data
+ // option to show UI,UE,SE as plaintext
+ proc/status_display(var/dna_summary = 0)
+ var/mob/living/occupant = scanner.occupant
+ var/status_html
+ if(viable)
+ status_html = "Health:
[occupant.health]%
"
+ status_html += "Radiation Level:
[occupant.radiation]%
"
+ if(ishuman(occupant))
+ var/rejuvenators = round(occupant.reagents.get_reagent_amount("inaprovaline") / REJUVENATORS_MAX * 100)
+ status_html += "Rejuvenators:
[occupant.reagents.get_reagent_amount("inaprovaline")] units
"
+
+ if (dna_summary)
+ status_html += "Unique Enzymes :
[uppertext(occupant.dna.unique_enzymes)]
"
+ status_html += "Unique Identifier:
[occupant.dna.uni_identity]
"
+ status_html += "Structural Enzymes:
[occupant.dna.struc_enzymes]
"
+
+ var/occupant_status = "Scanner Unoccupied"
+ if(present)
+ if(!viable)
+ occupant_status = "Invalid DNA structure"
+ else
+ switch(occupant.stat) // obvious, see what their status is
+ if(0)
+ occupant_status = "Conscious"
+ if(1)
+ occupant_status = "Unconscious"
+ else
+ occupant_status = "DEAD"
+
+ occupant_status = "[occupant.name] => [occupant_status]
"
+ var/dat = "Scanner Status
[topic_link(src,"","Scan")][occupant_status][status_html]
"
+ if(present)
+ dat += topic_link(src,"lock",scanner.locked?"Unlock Scanner":"Lock Scanner") + " " + topic_link(src,"rejuv","Inject Rejuvenators")
+ else
+ dat += "[scanner.locked?"Unlock Scanner":"Lock Scanner"] Inject Rejuvenators"
+ return dat
+
+ proc/main_menu()
+ var/dat = status_display(dna_summary = 1)
+ dat += "
Main Menu
"
+ if(present)
+ dat += topic_link(src,"mode=1","Modify Unique Identifier") + "
" + topic_link(src,"mode=2","Modify Structural Enzymes") + "
"
+ else
+ dat += "Modify Unique Identifier
Modify Structural Enzymes
"
+ dat += topic_link(src,"mode=3","Radiation Emitter Settings") + "
" + topic_link(src,"mode=4","Transfer Buffer")
+ return dat
+
+
+ proc/block_plus_minus(var/topicstr, var/blockval,var/min,var/max)
+ var/left = blockval - 1
+ var/right = blockval + 1
+ if(left < min)
+ left = max
+ if(right > max)
+ right = min
+ return topic_link(src,"[topicstr]=[left]","<-") + " [blockval] " + topic_link(src,"[topicstr]=[right]","->")
+
+
+ proc/getblockstring(var/ui = 0)
+ var/mainblock = "seblock"
+ var/block = se_block
+ var/input = scanner.occupant.dna.struc_enzymes
+ if(ui)
+ mainblock = "uiblock"
+ block = ui_block
+ input = scanner.occupant.dna.uni_identity
+
+ var/string = ""
+ var/subpos = 1 // keeps track of the current sub block
+ var/blockpos = 1
+
+ for(var/i = 1, i <= length(input), i++) // loop through each letter
+
+ if(blockpos == block && subpos == subblock) // if the current block/subblock is selected, mark it
+ string += fake_link(copytext(input,i,i+1))
+ else
+ string += topic_link(src,"[mainblock]=[blockpos];subblock=[subpos]",copytext(input,i,i+1))
+
+ subpos++
+ if(subpos > 3) // add a line break for every block
+ string += "
"
+ subpos = 1
+ blockpos++
+
+ string += "
"
+ return string
+
+ proc/ui_menu()
+ if(!viable)
+ return "No viable occupant detected."
+ var/dat = topic_link(src,"mode=0","<< Main Menu") + "
"
+ dat += "Modify Unique Identifier
"
+ dat += "Unique Identifier:
[getblockstring(ui=1)]
"
+
+ dat += "Selected Block: " + block_plus_minus("uiblock",ui_block,1,MAX_UIBLOCK) + "
"
+ dat += "Selected Sub-Block: " + block_plus_minus("subblock",subblock,1,3) + "
"
+ dat += "Selected Target: " + block_plus_minus("uitarget",uitarget,0,15) + "
"
+ dat += "Modify Block
"
+ dat += topic_link(src,"pulse=ui","Irradiate") + "
"
+ return dat
+
+ proc/se_menu()
+ if(!viable)
+ return "No viable occupant detected."
+ var/dat = topic_link(src,"mode=0","<< Main Menu") + "
"
+ dat += "Modify Structural Enzymes
"
+ dat += "Structural Enzymes: [getblockstring(ui=0)]
"
+ dat += "Selected Block: " + block_plus_minus("seblock",se_block,1,MAX_SEBLOCK) + "
"
+ dat += "Selected Sub-Block: " + block_plus_minus("subblock",subblock,1,3) + "
"
+ dat += "Modify Block
"
+ dat += topic_link(src,"pulse=se","Irradiate") + "
"
+ return dat
+
+ proc/emitter_menu()
+ var/dat = topic_link(src,"mode=0","<< Main Menu") + "
"
+ dat += "Radiation Emitter Settings
"
+ if (viable)
+ dat += topic_link(src,"pulse","Pulse Radiation")
+ else
+ dat += fake_link("Pulse Radiation")
+ dat += "
"
+ dat += "Radiation Duration: " + block_plus_minus("duration",radduration,1,20) + "
"
+ dat += "Radiation Intensity: " + block_plus_minus("strength",radstrength,1,10) + "
"
+ return dat
+
+ proc/buffer_menu()
+
+ interact()
+ if(!interactable())
+ return
+ popup.add_stylesheet("scannernew", 'html/browser/scannernew.css')
+
+ if(!computer.net)
+ computer.Crash(MISSING_PERIPHERAL)
+ return
+
+ scanner = computer.net.connect_to(/obj/machinery/dna_scannernew, scanner) // if exists, will be verified
+ if(!scanner)
+ computer.Crash(NETWORK_FAILURE)
+ return
+
+ // todo check everything goddamnit
+
+ present = scanner.occupant && scanner.occupant.dna
+ viable = present && !(NOCLONE in scanner.occupant.mutations)
+
+ popup.set_content(menu())
+ popup.open()
+
+ proc/pulse(var/target as null|anything in list("ui","se"))
+
+ //Makes sure someone is in there (And valid) before trying anything
+ //More than anything, this just acts as a sanity check in case the option DOES appear for whatever reason
+
+ if(target != "ui" && target != "se")
+ target = null
+
+ // transforms into the fail condition instead of having it in yet another nested if block
+ else if( prob(20 - (radduration / 2)))
+ target += "-f"
+
+ if(!viable)
+ popup.set_content("No viable occupant detected.")
+ popup.open()
+ else
+ popup.set_content("Working ... Please wait ([radduration]) Seconds)")
+ popup.open()
+
+ var/lock_state = scanner.locked
+ scanner.locked = 1//lock it
+ sleep(10*radduration)
+
+ switch(target)
+ if("ui")
+ var/ui = scanner.occupant.dna.uni_identity
+ var/block = getblock(ui,ui_block,3)
+ var/result = ""
+ for(var/sb = 1; sb <=3; sb++)
+ var/temp = copytext(block,sb,sb+1)
+ if(sb == subblock)
+ temp = miniscramble("[uitargethex]",radstrength,radduration)
+ result += temp
+ scanner.occupant.dna.uni_identity = setblock(ui, ui_block, result,3)
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ scanner.occupant.radiation += (radstrength+radduration)
+ if("ui-f")
+ if (prob(20+radstrength))
+ randmutb(scanner.occupant)
+ domutcheck(scanner.occupant,scanner)
+ else
+ randmuti(scanner.occupant)
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ scanner.occupant.radiation += ((radstrength*2)+radduration)
+
+ if("se")
+ var/se = scanner.occupant.dna.struc_enzymes
+ var/targetblock = se_block
+
+ if (!(se_block in list(2,8,10,12)) && prob (20)) // shifts the target slightly
+ if (se_block <= 5)
+ targetblock++
+ else
+ targetblock--
+ var/block = getblock(scanner.occupant.dna.struc_enzymes,targetblock,3)
+
+ var/result = ""
+ for(var/sb = 1; sb <=3; sb++)
+ var/temp = copytext(block,sb,sb+1)
+ if(sb == subblock)
+ temp = miniscramble(temp,radstrength,radduration)
+ result += temp
+
+ scanner.occupant.dna.struc_enzymes = setblock(se, se_block, result,3)
+ domutcheck(scanner.occupant,scanner)
+ scanner.occupant.radiation += (radstrength+radduration)
+ if("se-f")
+ if (prob(80-radduration))
+ randmutb(scanner.occupant)
+ domutcheck(scanner.occupant,scanner)
+ else
+ randmuti(scanner.occupant)
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ scanner.occupant.radiation += ((radstrength*2)+radduration)
+
+ if(null)
+ if (prob(95))
+ if(prob(75))
+ randmutb(scanner.occupant)
+ else
+ randmuti(scanner.occupant)
+ else
+ if(prob(95))
+ randmutg(scanner.occupant)
+ else
+ randmuti(scanner.occupant)
+ scanner.occupant.radiation += ((radstrength*3)+radduration*3)
+
+
+ scanner.locked = lock_state
+ interact()
+
+ proc/rejuv()
+ if(!viable)
+ popup.set_content("No viable occupant detected.")
+ popup.open()
+ var/mob/living/carbon/human/H = scanner.occupant
+ if(istype(H))
+ var/inap = H.reagents.get_reagent_amount("inaprovaline") // oh my *god* this section was ugly before I shortened it
+
+ if (inap < (REJUVENATORS_MAX - REJUVENATORS_INJECT))
+ H.reagents.add_reagent("inaprovaline", REJUVENATORS_INJECT)
+ else
+ H.reagents.add_reagent("inaprovaline", max(REJUVENATORS_MAX - inap,0))
+
+/*
+/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
+
+ temp_html = null
+ var/temp_header_html = null
+ var/temp_footer_html = null
+
+ scanner_status_html = null // Scanner status is reset each update
+ var/mob/living/occupant = scanner.occupant
+ var/viable_occupant = (occupant && occupant.dna && !(NOCLONE in occupant.mutations))
+ var/mob/living/carbon/human/human_occupant = scanner.occupant
+
+ if (href_list["screen"]) // Passing a screen is only a request, we set current_screen here but it can be overridden below if necessary
+ current_screen = href_list["screen"]
+
+ if (!viable_occupant) // If there is no viable occupant only allow certain screens
+ var/allowed_no_occupant_screens = list("mainmenu", "radsetmenu", "buffermenu") //These are the screens which will be allowed if there's no occupant
+ if (!(current_screen in allowed_no_occupant_screens))
+ href_list = new /list(0) // clear list of options
+ current_screen = "mainmenu"
+
+
+ if (!current_screen) // If no screen is set default to mainmenu
+ current_screen = "mainmenu"
+
+
+ if (!scanner) //Is the scanner not connected?
+ scanner_status_html = "ERROR: No DNA Scanner connected."
+ current_screen = null // blank does not exist in the switch below, so no screen will be outputted
+ updateUsrDialog()
+ return
+
+ usr.set_machine(src)
+ if (href_list["locked"])
+ if (scanner.occupant)
+ scanner.locked = !( scanner.locked )
+ ////////////////////////////////////////////////////////
+ if (href_list["genpulse"])
+ if(!viable_occupant)//Makes sure someone is in there (And valid) before trying anything
+ temp_html = text("No viable occupant detected.")//More than anything, this just acts as a sanity check in case the option DOES appear for whatever reason
+ //usr << browse(temp_html, "window=scannernew;size=550x650")
+ //onclose(usr, "scannernew")
+ popup.set_content(temp_html)
+ popup.open()
+ else
+
+ temp_html = text("Working ... Please wait ([] Seconds)", radduration)
+ popup.set_content(temp_html)
+ popup.open()
+ var/lock_state = scanner.locked
+ scanner.locked = 1//lock it
+ sleep(10*radduration)
+ if (!scanner.occupant)
+ temp_html = null
+ return null
+ if (prob(95))
+ if(prob(75))
+ randmutb(scanner.occupant)
+ else
+ randmuti(scanner.occupant)
+ else
+ if(prob(95))
+ randmutg(scanner.occupant)
+ else
+ randmuti(scanner.occupant)
+ scanner.occupant.radiation += ((radstrength*3)+radduration*3)
+ scanner.locked = lock_state
+ temp_html = null
+ dopage(src,"screen=radsetmenu")
+ if (href_list["radleplus"])
+ if(!viable_occupant)
+ temp_html = text("No viable occupant detected.")
+ popup.set_content(temp_html)
+ popup.open()
+ if (radduration < 20)
+ radduration++
+ radduration++
+ dopage(src,"screen=radsetmenu")
+ if (href_list["radleminus"])
+ if(!viable_occupant)
+ temp_html = text("No viable occupant detected.")
+ popup.set_content(temp_html)
+ popup.open()
+ if (radduration > 2)
+ radduration--
+ radduration--
+ dopage(src,"screen=radsetmenu")
+ if (href_list["radinplus"])
+ if (radstrength < 10)
+ radstrength++
+ dopage(src,"screen=radsetmenu")
+ if (href_list["radinminus"])
+ if (radstrength > 1)
+ radstrength--
+ dopage(src,"screen=radsetmenu")
+ ////////////////////////////////////////////////////////
+ if (href_list["unimenuplus"])
+ if (ui_block < 13)
+ ui_block++
+ else
+ ui_block = 1
+ dopage(src,"screen=unimenu")
+ if (href_list["unimenuminus"])
+ if (ui_block > 1)
+ ui_block--
+ else
+ ui_block = 13
+ dopage(src,"screen=unimenu")
+ if (href_list["unimenusubplus"])
+ if (subblock < 3)
+ subblock++
+ else
+ subblock = 1
+ dopage(src,"screen=unimenu")
+ if (href_list["unimenusubminus"])
+ if (subblock > 1)
+ subblock--
+ else
+ subblock = 3
+ dopage(src,"screen=unimenu")
+ if (href_list["unimenutargetplus"])
+ if (unitarget < 15)
+ unitarget++
+ unitargethex = unitarget
+ switch(unitarget)
+ if(10)
+ unitargethex = "A"
+ if(11)
+ unitargethex = "B"
+ if(12)
+ unitargethex = "C"
+ if(13)
+ unitargethex = "D"
+ if(14)
+ unitargethex = "E"
+ if(15)
+ unitargethex = "F"
+ else
+ unitarget = 0
+ unitargethex = 0
+ dopage(src,"screen=unimenu")
+ if (href_list["unimenutargetminus"])
+ if (unitarget > 0)
+ unitarget--
+ unitargethex = unitarget
+ switch(unitarget)
+ if(10)
+ unitargethex = "A"
+ if(11)
+ unitargethex = "B"
+ if(12)
+ unitargethex = "C"
+ if(13)
+ unitargethex = "D"
+ if(14)
+ unitargethex = "E"
+ else
+ unitarget = 15
+ unitargethex = "F"
+ dopage(src,"screen=unimenu")
+ if (href_list["uimenuset"] && href_list["uimenusubset"]) // This chunk of code updates selected block / sub-block based on click
+ var/menuset = text2num(href_list["uimenuset"])
+ var/menusubset = text2num(href_list["uimenusubset"])
+ if ((menuset <= 13) && (menuset >= 1))
+ ui_block = menuset
+ if ((menusubset <= 3) && (menusubset >= 1))
+ subblock = menusubset
+ dopage(src, "unimenu")
+ if (href_list["unipulse"])
+ if(scanner.occupant)
+ var/block
+ var/newblock
+ var/tstructure2
+ block = getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),subblock,1)
+
+ temp_html = text("Working ... Please wait ([] Seconds)", radduration)
+ popup.set_content(temp_html)
+ popup.open()
+ var/lock_state = scanner.locked
+ scanner.locked = 1//lock it
+ sleep(10*radduration)
+ if (!scanner.occupant)
+ temp_html = null
+ return null
+ ///
+ if (prob((80 + (radduration / 2))))
+ block = miniscrambletarget(num2text(unitarget), radstrength, radduration)
+ newblock = null
+ if (subblock == 1) newblock = block + getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),2,1) + getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),3,1)
+ if (subblock == 2) newblock = getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),1,1) + block + getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),3,1)
+ if (subblock == 3) newblock = getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),1,1) + getblock(getblock(scanner.occupant.dna.uni_identity,ui_block,3),2,1) + block
+ tstructure2 = setblock(scanner.occupant.dna.uni_identity, ui_block, newblock,3)
+ scanner.occupant.dna.uni_identity = tstructure2
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ scanner.occupant.radiation += (radstrength+radduration)
+ else
+ if (prob(20+radstrength))
+ randmutb(scanner.occupant)
+ domutcheck(scanner.occupant,scanner)
+ else
+ randmuti(scanner.occupant)
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ scanner.occupant.radiation += ((radstrength*2)+radduration)
+ scanner.locked = lock_state
+ dopage(src,"screen=unimenu")
+
+ ////////////////////////////////////////////////////////
+ if (href_list["rejuv"])
+ if(!viable_occupant)
+ temp_html = text("No viable occupant detected.")
+ popup.set_content(temp_html)
+ popup.open()
+ else
+ if(human_occupant)
+ if (human_occupant.reagents.get_reagent_amount("inaprovaline") < REJUVENATORS_MAX)
+ if (human_occupant.reagents.get_reagent_amount("inaprovaline") < (REJUVENATORS_MAX - REJUVENATORS_INJECT))
+ human_occupant.reagents.add_reagent("inaprovaline", REJUVENATORS_INJECT)
+ else
+ human_occupant.reagents.add_reagent("inaprovaline", round(REJUVENATORS_MAX - human_occupant.reagents.get_reagent_amount("inaprovaline")))
+ //usr << text("Occupant now has [] units of rejuvenation in his/her bloodstream.", human_occupant.reagents.get_reagent_amount("inaprovaline"))
+
+ ////////////////////////////////////////////////////////
+ if (href_list["strucmenuplus"])
+ if (se_block < 14)
+ se_block++
+ else
+ se_block = 1
+ dopage(src,"screen=strucmenu")
+ if (href_list["strucmenuminus"])
+ if (se_block > 1)
+ se_block--
+ else
+ se_block = 14
+ dopage(src,"screen=strucmenu")
+ if (href_list["strucmenusubplus"])
+ if (subblock < 3)
+ subblock++
+ else
+ subblock = 1
+ dopage(src,"screen=strucmenu")
+ if (href_list["strucmenusubminus"])
+ if (subblock > 1)
+ subblock--
+ else
+ subblock = 3
+ dopage(src,"screen=strucmenu")
+ if (href_list["semenuset"] && href_list["semenusubset"]) // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
+ var/menuset = text2num(href_list["semenuset"])
+ var/menusubset = text2num(href_list["semenusubset"])
+ if ((menuset <= 14) && (menuset >= 1))
+ se_block = menuset
+ if ((menusubset <= 3) && (menusubset >= 1))
+ subblock = menusubset
+ dopage(src, "strucmenu")
+ if (href_list["strucpulse"])
+ var/block
+ var/newblock
+ var/tstructure2
+ var/oldblock
+ var/lock_state = scanner.locked
+ scanner.locked = 1//lock it
+ if (viable_occupant)
+ block = getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),subblock,1)
+
+ temp_html = text("Working ... Please wait ([] Seconds)", radduration)
+ popup.set_content(temp_html)
+ popup.open()
+ sleep(10*radduration)
+ else
+ temp_html = null
+ return null
+ ///
+ if(viable_occupant)
+ if (prob((80 + (radduration / 2))))
+ if ((se_block != 2 || se_block != 12 || se_block != 8 || se_block || 10) && prob (20))
+ oldblock = se_block
+ block = miniscramble(block, radstrength, radduration)
+ newblock = null
+ if (se_block > 1 && se_block < 5)
+ se_block++
+ else if (se_block > 5 && se_block < 14)
+ se_block--
+ if (subblock == 1) newblock = block + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),2,1) + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),3,1)
+ if (subblock == 2) newblock = getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),1,1) + block + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),3,1)
+ if (subblock == 3) newblock = getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),1,1) + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),2,1) + block
+ tstructure2 = setblock(scanner.occupant.dna.struc_enzymes, se_block, newblock,3)
+ scanner.occupant.dna.struc_enzymes = tstructure2
+ domutcheck(scanner.occupant,scanner)
+ scanner.occupant.radiation += (radstrength+radduration)
+ se_block = oldblock
+ else
+ //
+ block = miniscramble(block, radstrength, radduration)
+ newblock = null
+ if (subblock == 1) newblock = block + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),2,1) + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),3,1)
+ if (subblock == 2) newblock = getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),1,1) + block + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),3,1)
+ if (subblock == 3) newblock = getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),1,1) + getblock(getblock(scanner.occupant.dna.struc_enzymes,se_block,3),2,1) + block
+ tstructure2 = setblock(scanner.occupant.dna.struc_enzymes, se_block, newblock,3)
+ scanner.occupant.dna.struc_enzymes = tstructure2
+ domutcheck(scanner.occupant,scanner)
+ scanner.occupant.radiation += (radstrength+radduration)
+ else
+ if (prob(80-radduration))
+ randmutb(scanner.occupant)
+ domutcheck(scanner.occupant,scanner)
+ else
+ randmuti(scanner.occupant)
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ scanner.occupant.radiation += ((radstrength*2)+radduration)
+ scanner.locked = lock_state
+ ///
+ dopage(src,"screen=strucmenu")
+
+ ////////////////////////////////////////////////////////
+ if (href_list["b1addui"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer1iue = 0
+ buffer1 = scanner.occupant.dna.uni_identity
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer1owner = scanner.occupant.name
+ else
+ buffer1owner = scanner.occupant.real_name
+ buffer1label = "Unique Identifier"
+ buffer1type = "ui"
+ dopage(src,"screen=buffermenu")
+ if (href_list["b1adduiue"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer1 = scanner.occupant.dna.uni_identity
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer1owner = scanner.occupant.name
+ else
+ buffer1owner = scanner.occupant.real_name
+ buffer1label = "Unique Identifier & Unique Enzymes"
+ buffer1type = "ui"
+ buffer1iue = 1
+ dopage(src,"screen=buffermenu")
+ if (href_list["b2adduiue"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer2 = scanner.occupant.dna.uni_identity
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer2owner = scanner.occupant.name
+ else
+ buffer2owner = scanner.occupant.real_name
+ buffer2label = "Unique Identifier & Unique Enzymes"
+ buffer2type = "ui"
+ buffer2iue = 1
+ dopage(src,"screen=buffermenu")
+ if (href_list["b3adduiue"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer3 = scanner.occupant.dna.uni_identity
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer3owner = scanner.occupant.name
+ else
+ buffer3owner = scanner.occupant.real_name
+ buffer3label = "Unique Identifier & Unique Enzymes"
+ buffer3type = "ui"
+ buffer3iue = 1
+ dopage(src,"screen=buffermenu")
+ if (href_list["b2addui"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer2iue = 0
+ buffer2 = scanner.occupant.dna.uni_identity
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer2owner = scanner.occupant.name
+ else
+ buffer2owner = scanner.occupant.real_name
+ buffer2label = "Unique Identifier"
+ buffer2type = "ui"
+ dopage(src,"screen=buffermenu")
+ if (href_list["b3addui"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer3iue = 0
+ buffer3 = scanner.occupant.dna.uni_identity
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer3owner = scanner.occupant.name
+ else
+ buffer3owner = scanner.occupant.real_name
+ buffer3label = "Unique Identifier"
+ buffer3type = "ui"
+ dopage(src,"screen=buffermenu")
+ if (href_list["b1addse"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer1iue = 0
+ buffer1 = scanner.occupant.dna.struc_enzymes
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer1owner = scanner.occupant.name
+ else
+ buffer1owner = scanner.occupant.real_name
+ buffer1label = "Structural Enzymes"
+ buffer1type = "se"
+ dopage(src,"screen=buffermenu")
+ if (href_list["b2addse"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer2iue = 0
+ buffer2 = scanner.occupant.dna.struc_enzymes
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer2owner = scanner.occupant.name
+ else
+ buffer2owner = scanner.occupant.real_name
+ buffer2label = "Structural Enzymes"
+ buffer2type = "se"
+ dopage(src,"screen=buffermenu")
+ if (href_list["b3addse"])
+ if(scanner.occupant && scanner.occupant.dna)
+ buffer3iue = 0
+ buffer3 = scanner.occupant.dna.struc_enzymes
+ if (!istype(scanner.occupant,/mob/living/carbon/human))
+ buffer3owner = scanner.occupant.name
+ else
+ buffer3owner = scanner.occupant.real_name
+ buffer3label = "Structural Enzymes"
+ buffer3type = "se"
+ dopage(src,"screen=buffermenu")
+ if (href_list["b1clear"])
+ buffer1 = null
+ buffer1owner = null
+ buffer1label = null
+ buffer1iue = null
+ dopage(src,"screen=buffermenu")
+ if (href_list["b2clear"])
+ buffer2 = null
+ buffer2owner = null
+ buffer2label = null
+ buffer2iue = null
+ dopage(src,"screen=buffermenu")
+ if (href_list["b3clear"])
+ buffer3 = null
+ buffer3owner = null
+ buffer3label = null
+ buffer3iue = null
+ dopage(src,"screen=buffermenu")
+ if (href_list["b1label"])
+ buffer1label = sanitize(input("New Label:","Edit Label","Infos here"))
+ dopage(src,"screen=buffermenu")
+ if (href_list["b2label"])
+ buffer2label = sanitize(input("New Label:","Edit Label","Infos here"))
+ dopage(src,"screen=buffermenu")
+ if (href_list["b3label"])
+ buffer3label = sanitize(input("New Label:","Edit Label","Infos here"))
+ dopage(src,"screen=buffermenu")
+ if (href_list["b1transfer"])
+ if (!scanner.occupant || (NOCLONE in scanner.occupant.mutations) || !scanner.occupant.dna)
+ return
+ if (buffer1type == "ui")
+ if (buffer1iue)
+ scanner.occupant.real_name = buffer1owner
+ scanner.occupant.name = buffer1owner
+ scanner.occupant.dna.uni_identity = buffer1
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ else if (buffer1type == "se")
+ scanner.occupant.dna.struc_enzymes = buffer1
+ domutcheck(scanner.occupant,scanner)
+ temp_html = "Transfered."
+ scanner.occupant.radiation += rand(20,50)
+
+ if (href_list["b2transfer"])
+ if (!scanner.occupant || (NOCLONE in scanner.occupant.mutations) || !scanner.occupant.dna)
+ return
+ if (buffer2type == "ui")
+ if (buffer2iue)
+ scanner.occupant.real_name = buffer2owner
+ scanner.occupant.name = buffer2owner
+ scanner.occupant.dna.uni_identity = buffer2
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ else if (buffer2type == "se")
+ scanner.occupant.dna.struc_enzymes = buffer2
+ domutcheck(scanner.occupant,scanner)
+ temp_html = "Transfered."
+ scanner.occupant.radiation += rand(20,50)
+
+ if (href_list["b3transfer"])
+ if (!scanner.occupant || (NOCLONE in scanner.occupant.mutations) || !scanner.occupant.dna)
+ return
+ if (buffer3type == "ui")
+ if (buffer3iue)
+ scanner.occupant.real_name = buffer3owner
+ scanner.occupant.name = buffer3owner
+ scanner.occupant.dna.uni_identity = buffer3
+ updateappearance(scanner.occupant,scanner.occupant.dna.uni_identity)
+ else if (buffer3type == "se")
+ scanner.occupant.dna.struc_enzymes = buffer3
+ domutcheck(scanner.occupant,scanner)
+ temp_html = "Transfered."
+ scanner.occupant.radiation += rand(20,50)
+
+ if (href_list["b1injector"])
+ if (injectorready)
+ var/obj/item/tool/medical/dnainjector/I = new /obj/item/tool/medical/dnainjector
+ I.dna = buffer1
+ I.dnatype = buffer1type
+ I.loc = loc
+ I.name += " ([buffer1label])"
+ if (buffer1iue) I.ue = buffer1owner //lazy haw haw
+ temp_html = "Injector created."
+
+ injectorready = 0
+ spawn(300)
+ injectorready = 1
+ else
+ temp_html = "Replicator not ready yet."
+
+ if (href_list["b2injector"])
+ if (injectorready)
+ var/obj/item/tool/medical/dnainjector/I = new /obj/item/tool/medical/dnainjector
+ I.dna = buffer2
+ I.dnatype = buffer2type
+ I.loc = loc
+ I.name += " ([buffer2label])"
+ if (buffer2iue) I.ue = buffer2owner //lazy haw haw
+ temp_html = "Injector created."
+
+ injectorready = 0
+ spawn(300)
+ injectorready = 1
+ else
+ temp_html = "Replicator not ready yet."
+
+ if (href_list["b3injector"])
+ if (injectorready)
+ var/obj/item/tool/medical/dnainjector/I = new /obj/item/tool/medical/dnainjector
+ I.dna = buffer3
+ I.dnatype = buffer3type
+ I.loc = loc
+ I.name += " ([buffer3label])"
+ if (buffer3iue) I.ue = buffer3owner //lazy haw haw
+ temp_html = "Injector created."
+
+ injectorready = 0
+ spawn(300)
+ injectorready = 1
+ else
+ temp_html = "Replicator not ready yet."
+
+ ////////////////////////////////////////////////////////
+ if (href_list["load_disk"])
+ var/buffernum = text2num(href_list["load_disk"])
+ if ((buffernum > 3) || (buffernum < 1))
+ return
+ if ((isnull(diskette)) || (!diskette.data) || (diskette.data == ""))
+ return
+ switch(buffernum)
+ if(1)
+ buffer1 = diskette.data
+ buffer1type = diskette.data_type
+ buffer1iue = diskette.ue
+ buffer1owner = diskette.owner
+ if(2)
+ buffer2 = diskette.data
+ buffer2type = diskette.data_type
+ buffer2iue = diskette.ue
+ buffer2owner = diskette.owner
+ if(3)
+ buffer3 = diskette.data
+ buffer3type = diskette.data_type
+ buffer3iue = diskette.ue
+ buffer3owner = diskette.owner
+ temp_html = "Data loaded."
+
+ if (href_list["save_disk"])
+ var/buffernum = text2num(href_list["save_disk"])
+ if ((buffernum > 3) || (buffernum < 1))
+ return
+ if ((isnull(diskette)) || (diskette.read_only))
+ return
+ switch(buffernum)
+ if(1)
+ diskette.data = buffer1
+ diskette.data_type = buffer1type
+ diskette.ue = buffer1iue
+ diskette.owner = buffer1owner
+ diskette.name = "data disk - '[buffer1owner]'"
+ if(2)
+ diskette.data = buffer2
+ diskette.data_type = buffer2type
+ diskette.ue = buffer2iue
+ diskette.owner = buffer2owner
+ diskette.name = "data disk - '[buffer2owner]'"
+ if(3)
+ diskette.data = buffer3
+ diskette.data_type = buffer3type
+ diskette.ue = buffer3iue
+ diskette.owner = buffer3owner
+ diskette.name = "data disk - '[buffer3owner]'"
+ temp_html = "Data saved."
+ if (href_list["eject_disk"])
+ if (!diskette)
+ return
+ diskette.loc = get_turf(src)
+ diskette = null
+ ////////////////////////////////////////////////////////
+
+ temp_html = temp_header_html
+ switch(current_screen)
+ if ("mainmenu")
+ temp_html += "Main Menu
"
+ if (viable_occupant) //is there REALLY someone in there who can be modified?
+ temp_html += text("Modify Unique Identifier
", src)
+ temp_html += text("Modify Structural Enzymes
", src)
+ else
+ temp_html += "Modify Unique Identifier
"
+ temp_html += "Modify Structural Enzymes
"
+ temp_html += text("Radiation Emitter Settings
", src)
+ temp_html += text("Transfer Buffer
", src)
+
+ if ("unimenu")
+ if(!viable_occupant)
+ temp_html = text("No viable occupant detected.")
+ popup.set_content(temp_html)
+ popup.open()
+ else
+ temp_html = "<< Main Menu
"
+ temp_html += "Modify Unique Identifier
"
+ temp_html += "Unique Identifier:
[getblockstring(scanner.occupant.dna.uni_identity,ui_block,subblock,3, src,1)]
"
+ temp_html += "Selected Block:
<- [ui_block] ->"
+ temp_html += "Selected Sub-Block:
<- [subblock] ->"
+ temp_html += "Selected Target:
<- [unitargethex] ->"
+ temp_html += "
Modify Block"
+ temp_html += "
Irradiate "
+
+ if ("strucmenu")
+ if(!viable_occupant)
+ temp_html = text("No viable occupant detected.")
+ popup.set_content(temp_html)
+ popup.open()
+ else
+ temp_html = "<< Main Menu
"
+ temp_html += "Modify Structural Enzymes
"
+ temp_html += "Structural Enzymes: [getblockstring(scanner.occupant.dna.struc_enzymes,se_block,subblock,3,src,0)]
"
+ temp_html += "Selected Block:
<- [se_block] ->"
+ temp_html += "Selected Sub-Block:
<- [subblock] ->"
+ temp_html += "
Modify Block"
+ temp_html += "
Irradiate "
+
+ if ("radsetmenu")
+ temp_html = "<< Main Menu
"
+ temp_html += "Radiation Emitter Settings
"
+ if (viable_occupant)
+ temp_html += text("Pulse Radiation", src)
+ else
+ temp_html += "Pulse Radiation"
+ temp_html += "
Radiation Duration: - [radduration] +
"
+ temp_html += "Radiation Intensity: - [radstrength] +
"
+
+ if ("buffermenu")
+ temp_html = "<< Main Menu
"
+ temp_html += "Transfer Buffer
"
+ temp_html += "Buffer 1:
"
+ if (!(buffer1))
+ temp_html += "Buffer Empty
"
+ else
+ temp_html += text("Data: []
", buffer1)
+ temp_html += text("By: []
", buffer1owner)
+ temp_html += text("Label: []
", buffer1label)
+ if (viable_occupant) temp_html += text("Save : UI - UI+UE - SE
", src, src, src)
+ if (buffer1) temp_html += text("Transfer to: Occupant - Injector
", src, src)
+ //if (buffer1) temp_html += text("Isolate Block
", src)
+ if (buffer1) temp_html += "Disk: Save To | Load From
"
+ if (buffer1) temp_html += text("Edit Label
", src)
+ if (buffer1) temp_html += text("Clear Buffer
", src)
+ if (!buffer1) temp_html += "
"
+ temp_html += "Buffer 2:
"
+ if (!(buffer2))
+ temp_html += "Buffer Empty
"
+ else
+ temp_html += text("Data: []
", buffer2)
+ temp_html += text("By: []
", buffer2owner)
+ temp_html += text("Label: []
", buffer2label)
+ if (viable_occupant) temp_html += text("Save : UI - UI+UE - SE
", src, src, src)
+ if (buffer2) temp_html += text("Transfer to: Occupant - Injector
", src, src)
+ //if (buffer2) temp_html += text("Isolate Block
", src)
+ if (buffer2) temp_html += "Disk: Save To | Load From
"
+ if (buffer2) temp_html += text("Edit Label
", src)
+ if (buffer2) temp_html += text("Clear Buffer
", src)
+ if (!buffer2) temp_html += "
"
+ temp_html += "Buffer 3:
"
+ if (!(buffer3))
+ temp_html += "Buffer Empty
"
+ else
+ temp_html += text("Data: []
", buffer3)
+ temp_html += text("By: []
", buffer3owner)
+ temp_html += text("Label: []
", buffer3label)
+ if (viable_occupant) temp_html += text("Save : UI - UI+UE - SE
", src, src, src)
+ if (buffer3) temp_html += text("Transfer to: Occupant - Injector
", src, src)
+ //if (buffer3) temp_html += text("Isolate Block
", src)
+ if (buffer3) temp_html += "Disk: Save To | Load From
"
+ if (buffer3) temp_html += text("Edit Label
", src)
+ if (buffer3) temp_html += text("Clear Buffer
", src)
+ if (!buffer3) temp_html += "
"
+ temp_html += temp_footer_html
+
+ if(viable_occupant && !scanner_status_html && occupant) //is there REALLY someone in there?
+ scanner_status_html = "Health:
[occupant.health]%
"
+ scanner_status_html += "Radiation Level:
[occupant.radiation]%
"
+ if(human_occupant)
+ var/rejuvenators = round(human_occupant.reagents.get_reagent_amount("inaprovaline") / REJUVENATORS_MAX * 100)
+ scanner_status_html += "Rejuvenators:
[human_occupant.reagents.get_reagent_amount("inaprovaline")] units
"
+
+ if (current_screen == "mainmenu")
+ scanner_status_html += "Unique Enzymes :
[uppertext(occupant.dna.unique_enzymes)]
"
+ scanner_status_html += "Unique Identifier:
[occupant.dna.uni_identity]
"
+ scanner_status_html += "Structural Enzymes:
[occupant.dna.struc_enzymes]
"
+
+ var/dat = "Scanner Status
"
+
+ var/occupant_status = "Scanner Unoccupied"
+ if(occupant && occupant.dna) //is there REALLY someone in there?
+ if (!istype(occupant,/mob/living/carbon/human))
+ sleep(1)
+ if(NOCLONE in occupant.mutations)
+ occupant_status = "Invalid DNA structure"
+ else
+ switch(occupant.stat) // obvious, see what their status is
+ if(0)
+ occupant_status = "Conscious"
+ if(1)
+ occupant_status = "Unconscious"
+ else
+ occupant_status = "DEAD"
+
+ occupant_status = "[occupant.name] => [occupant_status]
"
+
+ dat += "[occupant_status][scanner_status_html]
"
+
+ var/scanner_access_text = "Lock Scanner"
+ if (scanner.locked)
+ scanner_access_text = "Unlock Scanner"
+
+ dat += "Scan "
+
+ if (occupant && occupant.dna)
+ dat += "[scanner_access_text] "
+ if (human_occupant)
+ dat += "Inject Rejuvenators
"
+ else
+ dat += "Inject Rejuvenators
"
+ else
+ dat += "[scanner_access_text] "
+ dat += "Inject Rejuvenators
"
+
+ if (!isnull(diskette))
+ dat += text("Eject Disk
", src)
+
+ dat += "
"
+
+ if (temp_html)
+ dat += temp_html
+
+ popup.set_content(dat)
+ popup.open()
+*/
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/computers/security.dm b/code/WorkInProgress/computer3/computers/security.dm
new file mode 100644
index 0000000000..8c6152e1c1
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/security.dm
@@ -0,0 +1,606 @@
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+/obj/machinery/computer3/secure_data
+ default_prog = /datum/file/program/secure_data
+ spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot,/obj/item/part/computer/networking/radio)
+ icon_state = "frame-sec"
+
+/obj/machinery/computer3/laptop/secure_data
+ default_prog = /datum/file/program/secure_data
+ spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/cardslot,/obj/item/part/computer/networking/radio)
+ icon_state = "laptop"
+
+
+/datum/file/program/secure_data//TODO:SANITY
+ name = "Security Records"
+ desc = "Used to view and edit personnel's security records"
+ active_state = "security"
+ image = 'icons/NTOS/records.png'
+
+ req_one_access = list(access_security, access_forensics_lockers)
+
+ var/obj/item/weapon/card/id/scan = null
+ var/authenticated = null
+ var/rank = null
+ var/screen = null
+ var/datum/data/record/active1 = null
+ var/datum/data/record/active2 = null
+ var/a_id = null
+ var/temp = null
+ var/printing = null
+ var/can_change_id = 0
+ var/list/Perp
+ var/tempname = null
+ //Sorting Variables
+ var/sortBy = "name"
+ var/order = 1 // -1 = Descending - 1 = Ascending
+
+
+
+ proc/authenticate()
+ if(access_security in scan.access || access_forensics_lockers in scan.access )
+ return 1
+ if(istype(usr,/mob/living/silicon/ai))
+ return 1
+ return 0
+
+ interact()
+ usr.set_machine(src)
+ scan = computer.cardslot.reader
+ if(!interactable())
+ return
+ if (computer.z > 6)
+ usr << "\red Unable to establish a connection: \black You're too far away from the station!"
+ return
+ var/dat
+
+ if (temp)
+ dat = text("[]
Clear Screen", temp, src)
+ else
+ dat = text("Confirm Identity: []
", src, (scan ? text("[]", scan.name) : "----------"))
+ if (authenticated)
+ switch(screen)
+ if(1.0)
+ dat += {"
+ "}
+ dat += text("Search Records
", src)
+ dat += text("New Record
", src)
+ dat += {"
+
+
+
+
+ | Name |
+ ID |
+ Rank |
+ Fingerprints |
+ Criminal Status |
+
"}
+ if(!isnull(data_core.general))
+ for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order))
+ var/crimstat = ""
+ for(var/datum/data/record/E in data_core.security)
+ if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
+ crimstat = E.fields["criminal"]
+ var/background
+ switch(crimstat)
+ if("*Arrest*")
+ background = "'background-color:#DC143C;'"
+ if("Incarcerated")
+ background = "'background-color:#CD853F;'"
+ if("Parolled")
+ background = "'background-color:#CD853F;'"
+ if("Released")
+ background = "'background-color:#3BB9FF;'"
+ if("None")
+ background = "'background-color:#00FF7F;'"
+ if("")
+ background = "'background-color:#00FF00;'"
+ crimstat = "No Record."
+ dat += text("| [] | ", background, src, R, R.fields["name"])
+ dat += text("[] | ", R.fields["id"])
+ dat += text("[] | ", R.fields["rank"])
+ dat += text("[] | ", R.fields["fingerprint"])
+ dat += text("[] |
", crimstat)
+ dat += "
"
+ dat += text("Record Maintenance
", src)
+ dat += text("{Log Out}",src)
+ if(2.0)
+ dat += "Records Maintenance
"
+ dat += "
Delete All Records
Back"
+ if(3.0)
+ dat += "Security Record
"
+ if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
+ var/icon/front = new(active1.fields["photo"], dir = SOUTH)
+ var/icon/side = new(active1.fields["photo"], dir = WEST)
+ usr << browse_rsc(front, "front.png")
+ usr << browse_rsc(side, "side.png")
+ dat += text("")
+ else
+ dat += "General Record Lost!
"
+ if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
+ dat += text("
\nSecurity Data
\nCriminal Status: []
\n
\nMinor Crimes: []
\nDetails: []
\n
\nMajor Crimes: []
\nDetails: []
\n
\nImportant Notes:
\n\t[]
\n
\nComments/Log
", src, active2.fields["criminal"], src, active2.fields["mi_crim"], src, active2.fields["mi_crim_d"], src, active2.fields["ma_crim"], src, active2.fields["ma_crim_d"], src, decode(active2.fields["notes"]))
+ var/counter = 1
+ while(active2.fields[text("com_[]", counter)])
+ dat += text("[]
Delete Entry
", active2.fields[text("com_[]", counter)], src, counter)
+ counter++
+ dat += text("Add Entry
", src)
+ dat += text("Delete Record (Security Only)
", src)
+ else
+ dat += "Security Record Lost!
"
+ dat += text("New Security Record
", src)
+ dat += text("\nDelete Record (ALL)
\nPrint Record
\nBack
", src, src, src)
+ if(4.0)
+ if(!Perp.len)
+ dat += text("ERROR. String could not be located.
Back", src)
+ else
+ dat += {"
+
+ "}
+ dat += text("| Search Results for '[]': | ", tempname)
+ dat += {"
+
+
+
+
+ | Name |
+ ID |
+ Rank |
+ Fingerprints |
+ Criminal Status |
+
"}
+ for(var/i=1, i<=Perp.len, i += 2)
+ var/crimstat = ""
+ var/datum/data/record/R = Perp[i]
+ if(istype(Perp[i+1],/datum/data/record/))
+ var/datum/data/record/E = Perp[i+1]
+ crimstat = E.fields["criminal"]
+ var/background
+ switch(crimstat)
+ if("*Arrest*")
+ background = "'background-color:#DC143C;'"
+ if("Incarcerated")
+ background = "'background-color:#CD853F;'"
+ if("Parolled")
+ background = "'background-color:#CD853F;'"
+ if("Released")
+ background = "'background-color:#3BB9FF;'"
+ if("None")
+ background = "'background-color:#00FF7F;'"
+ if("")
+ background = "'background-color:#FFFFFF;'"
+ crimstat = "No Record."
+ dat += text("| [] | ", background, src, R, R.fields["name"])
+ dat += text("[] | ", R.fields["id"])
+ dat += text("[] | ", R.fields["rank"])
+ dat += text("[] | ", R.fields["fingerprint"])
+ dat += text("[] |
", crimstat)
+ dat += "
"
+ dat += text("
Return to index.", src)
+ else
+ else
+ dat += text("{Log In}", src)
+ var/datum/browser/popup = new(usr, "secure_rec", "Security Records", 600, 400)
+ popup.set_content(dat)
+ popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
+ popup.open()
+ return
+
+/*Revised /N
+I can't be bothered to look more of the actual code outside of switch but that probably needs revising too.
+What a mess.*/
+ Topic(href, href_list)
+ if(!interactable() || !computer.cardslot || ..(href,href_list))
+ return
+ if (!( data_core.general.Find(active1) ))
+ active1 = null
+ if (!( data_core.security.Find(active2) ))
+ active2 = null
+ switch(href_list["choice"])
+// SORTING!
+ if("Sorting")
+ // Reverse the order if clicked twice
+ if(sortBy == href_list["sort"])
+ if(order == 1)
+ order = -1
+ else
+ order = 1
+ else
+ // New sorting order!
+ sortBy = href_list["sort"]
+ order = initial(order)
+//BASIC FUNCTIONS
+ if("Clear Screen")
+ temp = null
+
+ if ("Return")
+ screen = 1
+ active1 = null
+ active2 = null
+
+ if("Confirm Identity")
+ if (scan)
+ if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand())
+ computer.cardslot.remove(scan)
+ else
+ scan.loc = get_turf(src)
+ scan = null
+ else
+ var/obj/item/I = usr.get_active_hand()
+ if (istype(I, /obj/item/weapon/card/id))
+ computer.cardslot.insert(I)
+ scan = I
+
+ if("Log Out")
+ authenticated = null
+ screen = null
+ active1 = null
+ active2 = null
+
+ if("Log In")
+ if (istype(usr, /mob/living/silicon/ai))
+ src.active1 = null
+ src.active2 = null
+ src.authenticated = usr.name
+ src.rank = "AI"
+ src.screen = 1
+ else if (istype(usr, /mob/living/silicon/robot))
+ src.active1 = null
+ src.active2 = null
+ src.authenticated = usr.name
+ var/mob/living/silicon/robot/R = usr
+ src.rank = "[R.modtype] [R.braintype]"
+ src.screen = 1
+ else if (istype(scan, /obj/item/weapon/card/id))
+ active1 = null
+ active2 = null
+ if(authenticate())
+ authenticated = scan.registered_name
+ rank = scan.assignment
+ screen = 1
+//RECORD FUNCTIONS
+ if("Search Records")
+ var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text
+ world << "input [t1]"
+ if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !interactable()))
+ return
+ Perp = new/list()
+ t1 = lowertext(t1)
+ var/list/components = text2list(t1, " ")
+ if(components.len > 5)
+ return //Lets not let them search too greedily.
+ for(var/datum/data/record/R in data_core.general)
+ var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"]
+ for(var/i = 1, i<=components.len, i++)
+ if(findtext(temptext,components[i]))
+ var/prelist = new/list(2)
+ prelist[1] = R
+ Perp += prelist
+ for(var/i = 1, i<=Perp.len, i+=2)
+ for(var/datum/data/record/E in data_core.security)
+ var/datum/data/record/R = Perp[i]
+ if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
+ Perp[i+1] = E
+ tempname = t1
+ screen = 4
+
+ if("Record Maintenance")
+ screen = 2
+ active1 = null
+ active2 = null
+
+ if ("Browse Record")
+ var/datum/data/record/R = locate(href_list["d_rec"])
+ var/S = locate(href_list["d_rec"])
+ if (!( data_core.general.Find(R) ))
+ temp = "Record Not Found!"
+ else
+ for(var/datum/data/record/E in data_core.security)
+ if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
+ S = E
+ active1 = R
+ active2 = S
+ screen = 3
+
+/* if ("Search Fingerprints")
+ var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text
+ if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!interactable()) && (!istype(usr, /mob/living/silicon))))
+ return
+ active1 = null
+ active2 = null
+ t1 = lowertext(t1)
+ for(var/datum/data/record/R in data_core.general)
+ if (lowertext(R.fields["fingerprint"]) == t1)
+ active1 = R
+ if (!( active1 ))
+ temp = text("Could not locate record [].", t1)
+ else
+ for(var/datum/data/record/E in data_core.security)
+ if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"]))
+ active2 = E
+ screen = 3 */
+
+ if ("Print Record")
+ if (!( printing ))
+ printing = 1
+ var/datum/data/record/record1 = null
+ var/datum/data/record/record2 = null
+ if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
+ record1 = active1
+ if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
+ record2 = active2
+ sleep(50)
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( computer.loc )
+ P.info = "Security Record
"
+ if (record1)
+ P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"])
+ P.name = text("Security Record ([])", record1.fields["name"])
+ else
+ P.info += "General Record Lost!
"
+ P.name = "Security Record"
+ if (record2)
+ P.info += text("
\nSecurity Data
\nCriminal Status: []
\n
\nMinor Crimes: []
\nDetails: []
\n
\nMajor Crimes: []
\nDetails: []
\n
\nImportant Notes:
\n\t[]
\n
\nComments/Log
", record2.fields["criminal"], record2.fields["mi_crim"], record2.fields["mi_crim_d"], record2.fields["ma_crim"], record2.fields["ma_crim_d"], decode(record2.fields["notes"]))
+ var/counter = 1
+ while(record2.fields[text("com_[]", counter)])
+ P.info += text("[]
", record2.fields[text("com_[]", counter)])
+ counter++
+ else
+ P.info += "Security Record Lost!
"
+ P.info += ""
+ printing = null
+ computer.updateUsrDialog()
+//RECORD DELETE
+ if ("Delete All Records")
+ temp = ""
+ temp += "Are you sure you wish to delete all Security records?
"
+ temp += "Yes
"
+ temp += "No"
+
+ if ("Purge All Records")
+ for(var/datum/data/record/R in data_core.security)
+ del(R)
+ temp = "All Security records deleted."
+
+ if ("Add Entry")
+ if (!( istype(active2, /datum/data/record) ))
+ return
+ var/a2 = active2
+ var/t1 = copytext(sanitize(input("Add Comment:", "Secure. records", null, null) as message),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
+ return
+ var/counter = 1
+ while(active2.fields[text("com_[]", counter)])
+ counter++
+ active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
[t1]")
+
+ if ("Delete Record (ALL)")
+ if (active1)
+ temp = "Are you sure you wish to delete the record (ALL)?
"
+ temp += "Yes
"
+ temp += "No"
+
+ if ("Delete Record (Security)")
+ if (active2)
+ temp = "Are you sure you wish to delete the record (Security Portion Only)?
"
+ temp += "Yes
"
+ temp += "No"
+
+ if ("Delete Entry")
+ if ((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
+ active2.fields[text("com_[]", href_list["del_c"])] = "Deleted"
+//RECORD CREATE
+ if ("New Record (Security)")
+ if ((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) )))
+ var/datum/data/record/R = new /datum/data/record()
+ R.fields["name"] = active1.fields["name"]
+ R.fields["id"] = active1.fields["id"]
+ R.name = text("Security Record #[]", R.fields["id"])
+ R.fields["criminal"] = "None"
+ R.fields["mi_crim"] = "None"
+ R.fields["mi_crim_d"] = "No minor crime convictions."
+ R.fields["ma_crim"] = "None"
+ R.fields["ma_crim_d"] = "No major crime convictions."
+ R.fields["notes"] = "No notes."
+ data_core.security += R
+ active2 = R
+ screen = 3
+
+ if ("New Record (General)")
+ var/datum/data/record/G = new /datum/data/record()
+ G.fields["name"] = "New Record"
+ G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
+ G.fields["rank"] = "Unassigned"
+ G.fields["real_rank"] = "Unassigned"
+ G.fields["sex"] = "Male"
+ G.fields["age"] = "Unknown"
+ G.fields["fingerprint"] = "Unknown"
+ G.fields["p_stat"] = "Active"
+ G.fields["m_stat"] = "Stable"
+ G.fields["species"] = "Human"
+ data_core.general += G
+ active1 = G
+ active2 = null
+
+//FIELD FUNCTIONS
+ if ("Edit Field")
+ var/a1 = active1
+ var/a2 = active2
+ switch(href_list["field"])
+ if("name")
+ if (istype(active1, /datum/data/record))
+ var/t1 = input("Please input name:", "Secure. records", active1.fields["name"], null) as text
+ if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon)))) || active1 != a1)
+ return
+ active1.fields["name"] = t1
+ if("id")
+ if (istype(active2, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
+ return
+ active1.fields["id"] = t1
+ if("fingerprint")
+ if (istype(active1, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
+ return
+ active1.fields["fingerprint"] = t1
+ if("sex")
+ if (istype(active1, /datum/data/record))
+ if (active1.fields["sex"] == "Male")
+ active1.fields["sex"] = "Female"
+ else
+ active1.fields["sex"] = "Male"
+ if("age")
+ if (istype(active1, /datum/data/record))
+ var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
+ return
+ active1.fields["age"] = t1
+ if("mi_crim")
+ if (istype(active2, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
+ return
+ active2.fields["mi_crim"] = t1
+ if("mi_crim_d")
+ if (istype(active2, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
+ return
+ active2.fields["mi_crim_d"] = t1
+ if("ma_crim")
+ if (istype(active2, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
+ return
+ active2.fields["ma_crim"] = t1
+ if("ma_crim_d")
+ if (istype(active2, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
+ return
+ active2.fields["ma_crim_d"] = t1
+ if("notes")
+ if (istype(active2, /datum/data/record))
+ var/t1 = copytext(html_encode(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
+ return
+ active2.fields["notes"] = t1
+ if("criminal")
+ if (istype(active2, /datum/data/record))
+ temp = "Criminal Status:
"
+ temp += ""
+ if("rank")
+ var/list/L = list( "Head of Personnel", "Captain", "AI" )
+ //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N
+ if ((istype(active1, /datum/data/record) && L.Find(rank)))
+ temp = "Rank:
"
+ temp += ""
+ for(var/rank in joblist)
+ temp += "- [rank]
"
+ temp += "
"
+ else
+ alert(usr, "You do not have the required rank to do this!")
+ if("species")
+ if (istype(active1, /datum/data/record))
+ var/t1 = copytext(sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message),1,MAX_MESSAGE_LEN)
+ if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
+ return
+ active1.fields["species"] = t1
+
+//TEMPORARY MENU FUNCTIONS
+ else//To properly clear as per clear screen.
+ temp=null
+ switch(href_list["choice"])
+ if ("Change Rank")
+ if (active1)
+ active1.fields["rank"] = href_list["rank"]
+ if(href_list["rank"] in joblist)
+ active1.fields["real_rank"] = href_list["real_rank"]
+
+ if ("Change Criminal Status")
+ if (active2)
+ for(var/mob/living/carbon/human/H in player_list)
+ H.hud_updateflag |= 1 << WANTED_HUD
+ switch(href_list["criminal2"])
+ if("none")
+ active2.fields["criminal"] = "None"
+ if("arrest")
+ active2.fields["criminal"] = "*Arrest*"
+ if("incarcerated")
+ active2.fields["criminal"] = "Incarcerated"
+ if("parolled")
+ active2.fields["criminal"] = "Parolled"
+ if("released")
+ active2.fields["criminal"] = "Released"
+
+ if ("Delete Record (Security) Execute")
+ if (active2)
+ del(active2)
+
+ if ("Delete Record (ALL) Execute")
+ if (active1)
+ for(var/datum/data/record/R in data_core.medical)
+ if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
+ del(R)
+ else
+ del(active1)
+ if (active2)
+ del(active2)
+ else
+ temp = "This function does not appear to be working at the moment. Our apologies."
+
+ //computer.updateUsrDialog()
+ interact()
+ return
+
+/obj/machinery/computer3/secure_data/emp_act(severity)
+ if(stat & (BROKEN|NOPOWER))
+ ..(severity)
+ return
+
+ for(var/datum/data/record/R in data_core.security)
+ if(prob(10/severity))
+ switch(rand(1,6))
+ if(1)
+ R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]"
+ if(2)
+ R.fields["sex"] = pick("Male", "Female")
+ if(3)
+ R.fields["age"] = rand(5, 85)
+ if(4)
+ R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released")
+ if(5)
+ R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
+ if(6)
+ R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
+ continue
+
+ else if(prob(1))
+ del(R)
+ continue
+
+ ..(severity)
+
+/obj/machinery/computer3/secure_data/detective_computer
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "messyfiles"
diff --git a/code/WorkInProgress/computer3/computers/shuttle.dm b/code/WorkInProgress/computer3/computers/shuttle.dm
new file mode 100644
index 0000000000..5d5fab6528
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/shuttle.dm
@@ -0,0 +1,75 @@
+/*
+ This may not migrate to C3. It's basically a machine in the guise of a computer;
+ there is nothing interactive about it.
+*/
+
+/obj/machinery/computer3/shuttle
+ name = "Shuttle"
+ desc = "For shuttle control."
+ icon_state = "shuttle"
+ var/auth_need = 3.0
+ var/list/authorized = list( )
+
+
+ attackby(var/obj/item/card/W as obj, var/mob/user as mob)
+ if(stat & (BROKEN|NOPOWER)) return
+ if ((!( istype(W, /obj/item/card) ) || !( ticker ) || emergency_shuttle.location != 1 || !( user ))) return
+ if (istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda))
+ if (istype(W, /obj/item/device/pda))
+ var/obj/item/device/pda/pda = W
+ W = pda.id
+ if (!W:access) //no access
+ user << "The access level of [W:registered_name]\'s card is not high enough. "
+ return
+
+ var/list/cardaccess = W:access
+ if(!istype(cardaccess, /list) || !cardaccess.len) //no access
+ user << "The access level of [W:registered_name]\'s card is not high enough. "
+ return
+
+ if(!(access_heads in W:access)) //doesn't have this access
+ user << "The access level of [W:registered_name]\'s card is not high enough. "
+ return 0
+
+ var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort")
+ if(emergency_shuttle.location != 1 && user.get_active_hand() != W)
+ return 0
+ switch(choice)
+ if("Authorize")
+ src.authorized -= W:registered_name
+ src.authorized += W:registered_name
+ if (src.auth_need - src.authorized.len > 0)
+ message_admins("[key_name_admin(user)] has authorized early shuttle launch")
+ log_game("[user.ckey] has authorized early shuttle launch")
+ world << text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)
+ else
+ message_admins("[key_name_admin(user)] has launched the shuttle")
+ log_game("[user.ckey] has launched the shuttle early")
+ world << "\blue Alert: Shuttle launch time shortened to 10 seconds!"
+ emergency_shuttle.online = 1
+ emergency_shuttle.settimeleft(10)
+ //src.authorized = null
+ del(src.authorized)
+ src.authorized = list( )
+
+ if("Repeal")
+ src.authorized -= W:registered_name
+ world << text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)
+
+ if("Abort")
+ world << "\blue All authorizations to shorting time for shuttle launch have been revoked!"
+ src.authorized.len = 0
+ src.authorized = list( )
+
+ else if (istype(W, /obj/item/card/emag) && !emagged)
+ var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel")
+
+ if(!emagged && emergency_shuttle.location == 1 && user.get_active_hand() == W)
+ switch(choice)
+ if("Launch")
+ world << "\blue Alert: Shuttle launch time shortened to 10 seconds!"
+ emergency_shuttle.settimeleft( 10 )
+ emagged = 1
+ if("Cancel")
+ return
+ return
diff --git a/code/WorkInProgress/computer3/computers/specops_shuttle.dm b/code/WorkInProgress/computer3/computers/specops_shuttle.dm
new file mode 100644
index 0000000000..81c94614cf
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/specops_shuttle.dm
@@ -0,0 +1,246 @@
+//Config stuff
+#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves.
+#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station
+#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock
+
+var/specops_shuttle_moving_to_station = 0
+var/specops_shuttle_moving_to_centcom = 0
+var/specops_shuttle_at_station = 0
+var/specops_shuttle_can_send = 1
+var/specops_shuttle_time = 0
+var/specops_shuttle_timeleft = 0
+
+/obj/machinery/computer3/specops_shuttle
+ name = "Spec. Ops. Shuttle Console"
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "shuttle"
+ req_access = list(access_cent_specops)
+ var/temp = null
+ var/hacked = 0
+ var/allowedtocall = 0
+
+/proc/specops_process()
+ var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work.
+ var/area/centcom/specops/special_ops = locate()//Where is the specops area located?
+ var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
+
+ var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
+ var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
+ if(announcer)
+ announcer.say(message)
+ message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
+ announcer.say(message)
+
+ while(specops_shuttle_time - world.timeofday > 0)
+ var/ticksleft = specops_shuttle_time - world.timeofday
+
+ if(ticksleft > 1e5)
+ specops_shuttle_time = world.timeofday + 10 // midnight rollover
+ specops_shuttle_timeleft = (ticksleft / 10)
+
+ //All this does is announce the time before launch.
+ if(announcer)
+ var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
+ if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
+ message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
+ if(rounded_time_left==0)
+ message = "ALERT: TAKEOFF"
+ announcer.say(message)
+ message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
+ //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
+
+ sleep(5)
+
+ specops_shuttle_moving_to_station = 0
+ specops_shuttle_moving_to_centcom = 0
+
+ specops_shuttle_at_station = 1
+ if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return
+
+ if (!specops_can_move())
+ usr << "\red The Special Operations shuttle is unable to leave."
+ return
+
+ //Begin Marauder launchpad.
+ spawn(0)//So it parallel processes it.
+ for(var/obj/machinery/door/poddoor/M in special_ops)
+ switch(M.id)
+ if("ASSAULT0")
+ spawn(10)//1 second delay between each.
+ M.open()
+ if("ASSAULT1")
+ spawn(20)
+ M.open()
+ if("ASSAULT2")
+ spawn(30)
+ M.open()
+ if("ASSAULT3")
+ spawn(40)
+ M.open()
+
+ sleep(10)
+
+ var/spawn_marauder[] = new()
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == "Marauder Entry")
+ spawn_marauder.Add(L)
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == "Marauder Exit")
+ var/obj/effect/portal/P = new(L.loc)
+ P.invisibility = 101//So it is not seen by anyone.
+ P.failchance = 0//So it has no fail chance when teleporting.
+ P.target = pick(spawn_marauder)//Where the marauder will arrive.
+ spawn_marauder.Remove(P.target)
+
+ sleep(10)
+
+ for(var/obj/machinery/mass_driver/M in special_ops)
+ switch(M.id)
+ if("ASSAULT0")
+ spawn(10)
+ M.drive()
+ if("ASSAULT1")
+ spawn(20)
+ M.drive()
+ if("ASSAULT2")
+ spawn(30)
+ M.drive()
+ if("ASSAULT3")
+ spawn(40)
+ M.drive()
+
+ sleep(50)//Doors remain open for 5 seconds.
+
+ for(var/obj/machinery/door/poddoor/M in special_ops)
+ switch(M.id)//Doors close at the same time.
+ if("ASSAULT0")
+ spawn(0)
+ M.close()
+ if("ASSAULT1")
+ spawn(0)
+ M.close()
+ if("ASSAULT2")
+ spawn(0)
+ M.close()
+ if("ASSAULT3")
+ spawn(0)
+ M.close()
+ special_ops.readyreset()//Reset firealarm after the team launched.
+ //End Marauder launchpad.
+
+ var/area/start_location = locate(/area/shuttle/specops/centcom)
+ var/area/end_location = locate(/area/shuttle/specops/station)
+
+ var/list/dstturfs = list()
+ var/throwy = world.maxy
+
+ for(var/turf/T in end_location)
+ dstturfs += T
+ if(T.y < throwy)
+ throwy = T.y
+
+ // hey you, get out of the way!
+ for(var/turf/T in dstturfs)
+ // find the turf to move things to
+ var/turf/D = locate(T.x, throwy - 1, 1)
+ //var/turf/E = get_step(D, SOUTH)
+ for(var/atom/movable/AM as mob|obj in T)
+ AM.Move(D)
+ if(istype(T, /turf/simulated))
+ del(T)
+
+ start_location.move_contents_to(end_location)
+
+ for(var/turf/T in get_area_turfs(end_location) )
+ var/mob/M = locate(/mob) in T
+ M << "\red You have arrived to [station_name]. Commence operation!"
+
+/proc/specops_can_move()
+ if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0
+ else return 1
+
+/obj/machinery/computer3/specops_shuttle/attackby(I as obj, user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/specops_shuttle/attack_ai(var/mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/specops_shuttle/attack_paw(var/mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/specops_shuttle/attackby(I as obj, user as mob)
+ if(istype(I,/obj/item/card/emag))
+ user << "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals."
+ else
+ return attack_hand(user)
+
+/obj/machinery/computer3/specops_shuttle/attack_hand(var/mob/user as mob)
+ if(!allowed(user))
+ user << "\red Access Denied."
+ return
+
+ if (sent_strike_team == 0)
+ usr << "\red The strike team has not yet deployed."
+ return
+
+ if(..())
+ return
+
+ user.set_machine(src)
+ var/dat
+ if (temp)
+ dat = temp
+ else
+ dat += {"
+ Location: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
+ [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
\n
":specops_shuttle_at_station ? "\nShuttle Offline
\n
":"\nDepart to [station_name]
\n
"]
+ \nClose"}
+
+ //user << browse(dat, "window=computer;size=575x450")
+ //onclose(user, "computer")
+ var/datum/browser/popup = new(user, "computer", "Special Operations Shuttle", 575, 450)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/computer3/specops_shuttle/Topic(href, href_list)
+ if(..())
+ return
+
+ if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
+ usr.set_machine(src)
+
+ if (href_list["sendtodock"])
+ if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return
+
+ usr << "\blue Central Command will not allow the Special Operations shuttle to return."
+ return
+
+ else if (href_list["sendtostation"])
+ if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return
+
+ if (!specops_can_move())
+ usr << "\red The Special Operations shuttle is unable to leave."
+ return
+
+ usr << "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds."
+
+ temp += "Shuttle departing.
OK"
+ updateUsrDialog()
+
+ var/area/centcom/specops/special_ops = locate()
+ if(special_ops)
+ special_ops.readyalert()//Trigger alarm for the spec ops area.
+ specops_shuttle_moving_to_station = 1
+
+ specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME
+ spawn(0)
+ specops_process()
+
+ else if (href_list["mainmenu"])
+ temp = null
+
+ add_fingerprint(usr)
+ updateUsrDialog()
+ return
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/computers/station_alert.dm b/code/WorkInProgress/computer3/computers/station_alert.dm
new file mode 100644
index 0000000000..2ee767a39a
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/station_alert.dm
@@ -0,0 +1,114 @@
+
+/obj/machinery/computer3/station_alert
+ name = "Station Alert Console"
+ desc = "Used to access the station's automated alert system."
+ icon_state = "alert:0"
+ circuit = "/obj/item/part/board/circuit/stationalert"
+ var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list())
+
+
+ attack_ai(mob/user)
+ add_fingerprint(user)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ interact(user)
+ return
+
+
+ attack_hand(mob/user)
+ add_fingerprint(user)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ interact(user)
+ return
+
+
+ interact(mob/user)
+ usr.set_machine(src)
+ var/dat = ""
+ for (var/cat in src.alarms)
+ dat += text("[]
", cat)
+ var/list/L = src.alarms[cat]
+ if (L.len)
+ for (var/alarm in L)
+ var/list/alm = L[alarm]
+ var/area/A = alm[1]
+ var/list/sources = alm[3]
+ dat += ""
+ dat += "• "
+ dat += "[format_text(A.name)]"
+ if (sources.len > 1)
+ dat += text(" - [] sources", sources.len)
+ dat += "
\n"
+ else
+ dat += "-- All Systems Nominal
\n"
+ dat += "
\n"
+ //user << browse(dat, "window=alerts")
+ //onclose(user, "alerts")
+ var/datum/browser/popup = new(user, "alerts", "Current Station Alerts")
+ popup.add_head_content("")
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+
+
+ Topic(href, href_list)
+ if(..())
+ return
+ return
+
+
+ proc/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
+ if(stat & (BROKEN))
+ return
+ var/list/L = src.alarms[class]
+ for (var/I in L)
+ if (I == A.name)
+ var/list/alarm = L[I]
+ var/list/sources = alarm[3]
+ if (!(alarmsource in sources))
+ sources += alarmsource
+ return 1
+ var/obj/machinery/camera/C = null
+ var/list/CL = null
+ if (O && istype(O, /list))
+ CL = O
+ if (CL.len == 1)
+ C = CL[1]
+ else if (O && istype(O, /obj/machinery/camera))
+ C = O
+ L[A.name] = list(A, (C) ? C : O, list(alarmsource))
+ return 1
+
+
+ proc/cancelAlarm(var/class, area/A as area, obj/origin)
+ if(stat & (BROKEN))
+ return
+ var/list/L = src.alarms[class]
+ var/cleared = 0
+ for (var/I in L)
+ if (I == A.name)
+ var/list/alarm = L[I]
+ var/list/srcs = alarm[3]
+ if (origin in srcs)
+ srcs -= origin
+ if (srcs.len == 0)
+ cleared = 1
+ L -= I
+ return !cleared
+
+
+ process()
+ if(stat & (BROKEN|NOPOWER))
+ icon_state = "atmos0"
+ return
+ var/active_alarms = 0
+ for (var/cat in src.alarms)
+ var/list/L = src.alarms[cat]
+ if(L.len) active_alarms = 1
+ if(active_alarms)
+ icon_state = "alert:2"
+ else
+ icon_state = "alert:0"
+ ..()
+ return
diff --git a/code/WorkInProgress/computer3/computers/syndicate_shuttle.dm b/code/WorkInProgress/computer3/computers/syndicate_shuttle.dm
new file mode 100644
index 0000000000..ccd711788b
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/syndicate_shuttle.dm
@@ -0,0 +1,103 @@
+#define SYNDICATE_SHUTTLE_MOVE_TIME 240
+#define SYNDICATE_SHUTTLE_COOLDOWN 200
+
+/obj/machinery/computer3/syndicate_station
+ name = "syndicate shuttle terminal"
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "syndishuttle"
+ req_access = list(access_syndicate)
+ var/area/curr_location
+ var/moving = 0
+ var/lastMove = 0
+
+
+/obj/machinery/computer3/syndicate_station/New()
+ curr_location= locate(/area/syndicate_station/start)
+
+
+/obj/machinery/computer3/syndicate_station/proc/syndicate_move_to(area/destination as area)
+ if(moving) return
+ if(lastMove + SYNDICATE_SHUTTLE_COOLDOWN > world.time) return
+ var/area/dest_location = locate(destination)
+ if(curr_location == dest_location) return
+
+ moving = 1
+ lastMove = world.time
+
+ if(curr_location.z != dest_location.z)
+ var/area/transit_location = locate(/area/syndicate_station/transit)
+ curr_location.move_contents_to(transit_location)
+ curr_location = transit_location
+ sleep(SYNDICATE_SHUTTLE_MOVE_TIME)
+
+ curr_location.move_contents_to(dest_location)
+ curr_location = dest_location
+ moving = 0
+ return 1
+
+
+/obj/machinery/computer3/syndicate_station/attackby(obj/item/I as obj, mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_station/attack_ai(mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_station/attack_paw(mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_station/attack_hand(mob/user as mob)
+ if(!allowed(user))
+ user << "\red Access Denied"
+ return
+
+ user.set_machine(src)
+
+ var/dat = {"Location: [curr_location]
+ Ready to move[max(lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
+ Syndicate Space
+ North West of SS13 |
+ North of SS13 |
+ North East of SS13
+ South West of SS13 |
+ South of SS13 |
+ South East of SS13
+ North East of the Mining Asteroid
+ Close"}
+
+ user << browse(dat, "window=computer;size=575x450")
+ onclose(user, "computer")
+ return
+
+
+/obj/machinery/computer3/syndicate_station/Topic(href, href_list)
+ if(!isliving(usr)) return
+ var/mob/living/user = usr
+
+ if(in_range(src, user) || istype(user, /mob/living/silicon))
+ user.set_machine(src)
+
+ if(href_list["syndicate"])
+ syndicate_move_to(/area/syndicate_station/start)
+ else if(href_list["station_nw"])
+ syndicate_move_to(/area/syndicate_station/northwest)
+ else if(href_list["station_n"])
+ syndicate_move_to(/area/syndicate_station/north)
+ else if(href_list["station_ne"])
+ syndicate_move_to(/area/syndicate_station/northeast)
+ else if(href_list["station_sw"])
+ syndicate_move_to(/area/syndicate_station/southwest)
+ else if(href_list["station_s"])
+ syndicate_move_to(/area/syndicate_station/south)
+ else if(href_list["station_se"])
+ syndicate_move_to(/area/syndicate_station/southeast)
+// else if(href_list["commssat"])
+// syndicate_move_to(/area/syndicate_station/commssat)
+ else if(href_list["mining"])
+ syndicate_move_to(/area/syndicate_station/mining)
+
+ add_fingerprint(usr)
+ updateUsrDialog()
+ return
+
+/obj/machinery/computer3/syndicate_station/bullet_act(var/obj/item/projectile/Proj)
+ visible_message("[Proj] ricochets off [src]!") //let's not let them fuck themselves in the rear
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/computers/syndicate_specops_shuttle.dm b/code/WorkInProgress/computer3/computers/syndicate_specops_shuttle.dm
new file mode 100644
index 0000000000..61dc0ba975
--- /dev/null
+++ b/code/WorkInProgress/computer3/computers/syndicate_specops_shuttle.dm
@@ -0,0 +1,259 @@
+//Config stuff
+#define SYNDICATE_ELITE_MOVETIME 600 //Time to station is deciseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves.
+#define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station
+#define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock
+
+var/syndicate_elite_shuttle_moving_to_station = 0
+var/syndicate_elite_shuttle_moving_to_mothership = 0
+var/syndicate_elite_shuttle_at_station = 0
+var/syndicate_elite_shuttle_can_send = 1
+var/syndicate_elite_shuttle_time = 0
+var/syndicate_elite_shuttle_timeleft = 0
+
+/obj/machinery/computer3/syndicate_elite_shuttle
+ name = "Elite Syndicate Squad Shuttle Console"
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "syndishuttle"
+ req_access = list(access_cent_specops)
+ var/temp = null
+ var/hacked = 0
+ var/allowedtocall = 0
+
+/proc/syndicate_elite_process()
+ var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work.
+ var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located?
+ var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
+
+ var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
+ var/message = "THE SYNDICATE ELITE SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
+ if(announcer)
+ announcer.say(message)
+ // message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
+ // announcer.say(message)
+
+ while(syndicate_elite_shuttle_time - world.timeofday > 0)
+ var/ticksleft = syndicate_elite_shuttle_time - world.timeofday
+
+ if(ticksleft > 1e5)
+ syndicate_elite_shuttle_time = world.timeofday // midnight rollover
+ syndicate_elite_shuttle_timeleft = (ticksleft / 10)
+
+ //All this does is announce the time before launch.
+ if(announcer)
+ var/rounded_time_left = round(syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
+ if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
+ message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
+ if(rounded_time_left==0)
+ message = "ALERT: TAKEOFF"
+ announcer.say(message)
+ message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
+ //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
+
+ sleep(5)
+
+ syndicate_elite_shuttle_moving_to_station = 0
+ syndicate_elite_shuttle_moving_to_mothership = 0
+
+ syndicate_elite_shuttle_at_station = 1
+ if (syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return
+
+ if (!syndicate_elite_can_move())
+ usr << "\red The Syndicate Elite shuttle is unable to leave."
+ return
+
+ sleep(600)
+/*
+ //Begin Marauder launchpad.
+ spawn(0)//So it parallel processes it.
+ for(var/obj/machinery/door/poddoor/M in elite_squad)
+ switch(M.id)
+ if("ASSAULT0")
+ spawn(10)//1 second delay between each.
+ M.open()
+ if("ASSAULT1")
+ spawn(20)
+ M.open()
+ if("ASSAULT2")
+ spawn(30)
+ M.open()
+ if("ASSAULT3")
+ spawn(40)
+ M.open()
+
+ sleep(10)
+
+ var/spawn_marauder[] = new()
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == "Marauder Entry")
+ spawn_marauder.Add(L)
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == "Marauder Exit")
+ var/obj/effect/portal/P = new(L.loc)
+ P.invisibility = 101//So it is not seen by anyone.
+ P.failchance = 0//So it has no fail chance when teleporting.
+ P.target = pick(spawn_marauder)//Where the marauder will arrive.
+ spawn_marauder.Remove(P.target)
+
+ sleep(10)
+
+ for(var/obj/machinery/mass_driver/M in elite_squad)
+ switch(M.id)
+ if("ASSAULT0")
+ spawn(10)
+ M.drive()
+ if("ASSAULT1")
+ spawn(20)
+ M.drive()
+ if("ASSAULT2")
+ spawn(30)
+ M.drive()
+ if("ASSAULT3")
+ spawn(40)
+ M.drive()
+
+ sleep(50)//Doors remain open for 5 seconds.
+
+ for(var/obj/machinery/door/poddoor/M in elite_squad)
+ switch(M.id)//Doors close at the same time.
+ if("ASSAULT0")
+ spawn(0)
+ M.close()
+ if("ASSAULT1")
+ spawn(0)
+ M.close()
+ if("ASSAULT2")
+ spawn(0)
+ M.close()
+ if("ASSAULT3")
+ spawn(0)
+ M.close()
+ */
+ elite_squad.readyreset()//Reset firealarm after the team launched.
+ //End Marauder launchpad.
+/*
+ var/obj/explosionmarker = locate("Syndicate Breach Area")
+ if(explosionmarker)
+ var/turf/simulated/T = explosionmarker.loc
+ if(T)
+ explosion(T,4,6,8,10,0)
+
+ sleep(40)
+// proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1)
+
+*/
+ var/area/start_location = locate(/area/shuttle/syndicate_elite/mothership)
+ var/area/end_location = locate(/area/shuttle/syndicate_elite/station)
+
+ var/list/dstturfs = list()
+ var/throwy = world.maxy
+
+ for(var/turf/T in end_location)
+ dstturfs = T
+ if(T.y < throwy)
+ throwy = T.y
+
+ // hey you, get out of the way!
+ for(var/turf/T in dstturfs)
+ // find the turf to move things to
+ var/turf/D = locate(T.x, throwy - 1, 1)
+ //var/turf/E = get_step(D, SOUTH)
+ for(var/atom/movable/AM as mob|obj in T)
+ AM.Move(D)
+ if(istype(T, /turf/simulated))
+ del(T)
+
+ start_location.move_contents_to(end_location)
+
+ for(var/turf/T in get_area_turfs(end_location) )
+ var/mob/M = locate(/mob) in T
+ M << "\red You have arrived to [station_name]. Commence operation!"
+
+/proc/syndicate_elite_can_move()
+ if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return 0
+ else return 1
+
+/obj/machinery/computer3/syndicate_elite_shuttle/attackby(I as obj, user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_elite_shuttle/attack_ai(var/mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_elite_shuttle/attack_paw(var/mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_elite_shuttle/attackby(I as obj, user as mob)
+ if(istype(I,/obj/item/card/emag))
+ user << "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals."
+ else
+ return attack_hand(user)
+
+/obj/machinery/computer3/syndicate_elite_shuttle/attack_hand(var/mob/user as mob)
+ if(!allowed(user))
+ user << "\red Access Denied."
+ return
+
+// if (sent_syndicate_strike_team == 0)
+// usr << "\red The strike team has not yet deployed."
+// return
+
+ if(..())
+ return
+
+ user.set_machine(src)
+ var/dat
+ if (temp)
+ dat = temp
+ else
+ dat = {"Location: [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name] in ([syndicate_elite_shuttle_timeleft] seconds.)":syndicate_elite_shuttle_at_station ? "Station":"Dock"]
+ [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*
\n
":syndicate_elite_shuttle_at_station ? "\nShuttle Offline
\n
":"\nDepart to [station_name]
\n
"]
+ \nClose"}
+
+ //user << browse(dat, "window=computer;size=575x450")
+ //onclose(user, "computer")
+ var/datum/browser/popup = new(user, "computer", "Special Operations Shuttle", 575, 450)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/computer3/syndicate_elite_shuttle/Topic(href, href_list)
+ if(..())
+ return
+
+ if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
+ usr.set_machine(src)
+
+ if (href_list["sendtodock"])
+ if(!syndicate_elite_shuttle_at_station|| syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return
+
+ usr << "\blue The Syndicate will not allow the Elite Squad shuttle to return."
+ return
+
+ else if (href_list["sendtostation"])
+ if(syndicate_elite_shuttle_at_station || syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return
+
+ if (!specops_can_move())
+ usr << "\red The Syndicate Elite shuttle is unable to leave."
+ return
+
+ usr << "\blue The Syndicate Elite shuttle will arrive on [station_name] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds."
+
+ temp = "Shuttle departing.
OK"
+ updateUsrDialog()
+
+ var/area/syndicate_mothership/elite_squad/elite_squad = locate()
+ if(elite_squad)
+ elite_squad.readyalert()//Trigger alarm for the spec ops area.
+ syndicate_elite_shuttle_moving_to_station = 1
+
+ syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME
+ spawn(0)
+ syndicate_elite_process()
+
+
+ else if (href_list["mainmenu"])
+ temp = null
+
+ add_fingerprint(usr)
+ updateUsrDialog()
+ return
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/file.dm b/code/WorkInProgress/computer3/file.dm
new file mode 100644
index 0000000000..cd959a7ea0
--- /dev/null
+++ b/code/WorkInProgress/computer3/file.dm
@@ -0,0 +1,166 @@
+// I am deciding that for sayustation's purposes directories are right out,
+// we can't even get backpacks to work right with recursion, and that
+// actually fucking matters. Metadata too, that can be added if ever needed.
+
+/*
+ Files are datums that can be stored in digital storage devices
+*/
+
+/datum/file
+ var/name = "File"
+ var/extension = "dat"
+ var/volume = 10 // in KB
+ var/image = 'icons/NTOS/file.png' // determines the icon to use, found in icons/NTOS
+ var/obj/machinery/computer3/computer // the parent computer, if fixed
+ var/obj/item/part/computer/storage/device // the device that is containing this file
+
+ var/drm = 0 // Copy protection, called by copy() and move()
+ var/readonly = 0 // Edit protection, called by edit(), which is just a failcheck proc
+
+ proc/execute(var/datum/file/source)
+ return
+
+ //
+ // Copy file to device.
+ // If you overwrite this function, use the return value to make sure it succeeded
+ //
+ proc/copy(var/obj/item/part/computer/storage/dest)
+ if(!computer || computer.crit_fail) return null
+ if(drm)
+ if(!computer.emagged)
+ return null
+ var/datum/file/F = new type()
+ if(!dest.addfile(F))
+ return null // todo: arf here even though the player can't do a damn thing due to concurrency
+ return F
+
+ //
+ // Move file to device
+ // Returns null on failure even though the existing file doesn't go away
+ //
+ proc/move(var/obj/item/part/computer/storage/dest)
+ if(!computer || computer.crit_fail) return null
+ if(drm)
+ if(!computer.emagged)
+ return null
+ var/obj/item/part/computer/storage/current = device
+ if(!dest.addfile(src))
+ return null
+ current.removefile(src)
+ return src
+
+ //
+ // Determines if the file is editable. This does not use the DRM flag,
+ // but instead the readonly flag.
+ //
+
+ proc/edit()
+ if(!computer || computer.crit_fail)
+ return 0
+ if(readonly && !computer.emagged)
+ return 0 //
+ return 1
+
+/*
+ Centcom root authorization certificate
+
+ Non-destructive, officially sanctioned.
+ Has the same effect on computers as an emag.
+*/
+/datum/file/centcom_auth
+ name = "Centcom Root Access Token"
+ extension = "auth"
+ volume = 100
+ copy()
+ return null
+
+/*
+ A file that contains information
+*/
+
+/datum/file/data
+
+ var/content = "content goes here"
+ var/file_increment = 1
+ var/binary = 0 // determines if the file can't be opened by editor
+
+ // Set the content to a specific amount, increase filesize appropriately.
+ proc/set_content(var/text)
+ content = text
+ if(file_increment > 1)
+ volume = round(file_increment * length(text))
+
+ copy(var/obj/O)
+ var/datum/file/data/D = ..(O)
+ if(D)
+ D.content = content
+ D.readonly = readonly
+
+ New()
+ if(content)
+ if(file_increment > 1)
+ volume = round(file_increment * length(content))
+
+/*
+ A generic file that contains text
+*/
+
+/datum/file/data/text
+ name = "Text File"
+ extension = "txt"
+ image = 'icons/NTOS/file.png'
+ content = ""
+ file_increment = 0.002 // 0.002 kilobytes per character (1024 characters per KB)
+
+/datum/file/data/text/ClownProphecy
+ name = "Clown Prophecy"
+ content = "HONKhHONKeHONKlHONKpHONKHONmKHONKeHONKHONKpHONKlHONKeHONKaHONKsHONKe"
+
+
+/*
+ A file that contains research
+*/
+
+/datum/file/data/research
+ name = "Untitled Research"
+ binary = 1
+ content = "Untitled Tier X Research"
+ var/datum/tech/stored // the actual tech contents
+ volume = 1440
+
+/*
+ A file that contains genetic information
+*/
+
+/datum/file/data/genome
+ name = "Genetic Buffer"
+ binary = 1
+ var/real_name = "Poop"
+
+
+/datum/file/data/genome/SE
+ name = "Structural Enzymes"
+ var/mutantrace = null
+
+/datum/file/data/genome/UE
+ name = "Unique Enzymes"
+
+/*
+the way genome computers now work, a subtype is the wrong way to do this;
+it will no longer be picked up. You can change this later if you need to.
+for now put it on a disk
+
+/datum/file/data/genome/UE/GodEmperorOfMankind
+ name = "G.E.M.K."
+ content = "066000033000000000AF00330660FF4DB002690"
+ label = "God Emperor of Mankind"
+*/
+/datum/file/data/genome/UI
+ name = "Unique Identifier"
+
+/datum/file/data/genome/UI/UE
+ name = "Unique Identifier + Unique Enzymes"
+
+/datum/file/data/genome/cloning
+ name = "Cloning Data"
+ var/datum/data/record/record
diff --git a/code/WorkInProgress/computer3/laptop.dm b/code/WorkInProgress/computer3/laptop.dm
new file mode 100644
index 0000000000..c681ff50a7
--- /dev/null
+++ b/code/WorkInProgress/computer3/laptop.dm
@@ -0,0 +1,137 @@
+/*
+ Computer3 portable computer.
+
+ Battery powered only; it does not use the APC network at all.
+
+ When picked up, becomes an inert item. This item can be put in a recharger,
+ or set down and re-opened into the original machine. While closed, the computer
+ has the MAINT stat flag. If you want to ignore this, you will have to bitmask it out.
+
+ The unused(?) alt+click will toggle laptops open and closed. If we find a better
+ answer for this in the future, by all means use it. I just don't want it limited
+ to the verb, which is SIGNIFICANTLY less accessible than shutting a laptop.
+ Ctrl-click would work for closing the machine, since it's anchored, but not for
+ opening it back up again. And obviously, I don't want to override shift-click.
+ There's no double-click because that's used in regular click events. Alt-click is the
+ only obvious one left.
+*/
+
+
+/obj/item/device/laptop
+ name = "Laptop Computer"
+ desc = "A clamshell portable computer. It is closed."
+ icon = 'icons/obj/computer3.dmi'
+ icon_state = "laptop-closed"
+ item_state = "laptop-inhand"
+ pixel_x = 2
+ pixel_y = -3
+ w_class = 4
+
+ var/obj/machinery/computer3/laptop/stored_computer = null
+
+ verb/open_computer()
+ set name = "open laptop"
+ set category = "Object"
+ set src in view(1)
+
+ if(!istype(loc,/turf))
+ usr << "[src] is too bulky! You'll have to set it down."
+ return
+
+ if(!stored_computer)
+ if(contents.len)
+ for(var/obj/O in contents)
+ O.loc = loc
+ usr << "\The [src] crumbles to pieces."
+ spawn(5)
+ del src
+ return
+
+
+ stored_computer.loc = loc
+ stored_computer.stat &= ~MAINT
+ stored_computer.update_icon()
+ loc = null
+ usr << "You open \the [src]."
+
+ spawn(5)
+ del src
+
+ AltClick()
+ open_computer()
+
+/obj/machinery/computer3/laptop
+ name = "Laptop Computer"
+ desc = "A clamshell portable computer. It is open."
+
+ icon_state = "laptop"
+ density = 0
+ pixel_x = 2
+ pixel_y = -3
+ show_keyboard = 0
+
+ var/obj/item/device/laptop/portable = null
+
+ New(var/L, var/built = 0)
+ if(!built && !battery)
+ battery = new /obj/item/weapon/cell(src)
+ ..(L,built)
+
+ verb/close_computer()
+ set name = "close laptop"
+ set category = "Object"
+ set src in view(1)
+
+ if(istype(loc,/obj/item/device/laptop))
+ testing("Close closed computer")
+ return
+ if(!istype(loc,/turf))
+ testing("Odd computer location: [loc] - close laptop")
+ return
+
+ if(stat&BROKEN)
+ usr << "\The [src] is broken! You can't quite get it closed."
+ return
+
+ if(!portable)
+ portable=new
+ portable.stored_computer = src
+
+ portable.loc = loc
+ loc = portable
+ stat |= MAINT
+ usr << "You close \the [src]."
+
+ auto_use_power()
+ if(stat&MAINT)
+ return
+ if(use_power && istype(battery) && battery.charge > 0)
+ if(use_power == 1)
+ battery.use(idle_power_usage)
+ else
+ battery.use(active_power_usage)
+ return 1
+ return 0
+
+ use_power(var/amount, var/chan = -1)
+ if(battery && battery.charge > 0)
+ battery.use(amount)
+
+ power_change()
+ if( !battery || battery.charge <= 0 )
+ stat |= NOPOWER
+ else
+ stat &= ~NOPOWER
+
+ Del()
+ if(istype(loc,/obj/item/device/laptop))
+ var/obj/O = loc
+ spawn(5)
+ if(O)
+ del O
+ ..()
+
+
+ AltClick()
+ close_computer()
+
diff --git a/code/WorkInProgress/computer3/networking.dm b/code/WorkInProgress/computer3/networking.dm
new file mode 100644
index 0000000000..12341e2b6f
--- /dev/null
+++ b/code/WorkInProgress/computer3/networking.dm
@@ -0,0 +1,236 @@
+/obj/item/part/computer/networking
+ name = "Computer networking component"
+
+ /*
+ This is the public-facing proc used by NETUP.
+ It does additional checking before and after calling get_machines()
+
+ */
+ proc/connect_to(var/typekey,var/atom/previous)
+ if(!computer || computer.stat)
+ return null
+
+ if(istype(previous,typekey) && verify_machine(previous))
+ return previous
+
+ var/result = get_machines(typekey)
+
+ if(!result)
+ return null
+
+ if(islist(result))
+ var/list/R = result
+ if(R.len == 0)
+ return null
+ else if(R.len == 1)
+ return R[1]
+ else
+ var/list/atomlist = computer.format_atomlist(R)
+ result = input("Select:","Multiple destination machines located",atomlist[1]) as null|anything in atomlist
+ return atomlist[result]
+
+ if(isobj(result))
+ return result
+
+ return null // ?
+
+ /*
+ This one is used to determine the candidate machines.
+ It may return an object, a list of objects, or null.
+
+ Overwite this on any networking component.
+ */
+ proc/get_machines(var/typekey)
+ return list()
+
+ /*
+ This is used to verify that an existing machine is within the network.
+ Calling NETUP() with an object argument will run this check, and if
+ the object is still accessible, it will be used. Otherwise, another
+ search will be run.
+
+ Overwrite this on any networking component.
+ */
+ proc/verify_machine(var/obj/previous)
+ return 0
+
+/*
+ Provides radio/signaler functionality, and also
+ network-connects to anything on the same z-level
+ which is tuned to the same frequency.
+*/
+/obj/item/part/computer/networking/radio
+ name = "Wireless networking component"
+ desc = "Radio module for computers"
+
+ var/datum/radio_frequency/radio_connection = null
+ var/frequency = 1459
+ var/filter = null
+ var/range = null
+ var/subspace = 0
+
+ init()
+ ..()
+ spawn(5)
+ radio_connection = radio_controller.add_object(src, src.frequency, src.filter)
+
+ proc/set_frequency(new_frequency)
+ if(radio_controller)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = radio_controller.add_object(src, frequency, filter)
+ else
+ frequency = new_frequency
+ spawn(rand(5,10))
+ set_frequency(new_frequency)
+
+ receive_signal(var/datum/signal/signal)
+ if(!signal || !computer || (computer.stat&~MAINT)) // closed laptops use maint, allow it
+ return
+ if(computer.program)
+ computer.program.receive_signal(signal)
+
+ proc/post_signal(var/datum/signal/signal)
+ if(!computer || (computer.stat&~MAINT) || !computer.program) return
+ if(!radio_connection) return
+
+ radio_connection.post_signal(src,signal,filter,range)
+
+ get_machines(var/typekey)
+ if(!radio_connection || !radio_connection.frequency)
+ return list()
+ var/list/result = list()
+ var/turf/T = get_turf(loc)
+ var/z_level = T.z
+ for(var/obj/O in radio_connection.devices)
+ if(istype(O,typekey))
+ T = get_turf(O)
+ if(istype(O) && (subspace || (O.z == z_level))) // radio does not work across z-levels
+ result |= O
+ return result
+
+ verify_machine(var/obj/previous)
+ if(!previous) return 0
+ if(subspace)
+ return ( radio_connection && (previous in radio_connection.devices) )
+ else
+ var/turf/T = get_turf(loc)
+ var/turf/O = get_turf(previous)
+ if(!T || !O)
+ return 0
+ return ( radio_connection && (previous in radio_connection.devices) && (T.z == O.z))
+
+/*
+ Subspace networking: Communicates off-station. Allows centcom communications.
+*/
+/obj/item/part/computer/networking/radio/subspace
+ name = "subspace networking terminal"
+ desc = "Communicates long distances and through spatial anomalies."
+ subspace = 1
+
+/*
+ APC (/area) networking
+*/
+
+/obj/item/part/computer/networking/area
+ name = "short-wave networking terminal"
+ desc = "Connects to nearby computers through the area power network"
+
+ get_machines(var/typekey)
+ var/area/A = get_area(loc)
+ if(!istype(A) || A == /area)
+ return list()
+ if(typekey == null)
+ typekey = /obj/machinery
+ var/list/machines = list()
+ for(var/area/area in A.related)
+ for(var/obj/O in area.contents)
+ if(istype(O,typekey))
+ machines |= O
+ return machines
+ verify_machine(var/obj/previous)
+ if(!previous) return 0
+ var/area/A = get_area(src)
+ if( A && A == get_area(previous) )
+ return 1
+ return 0
+
+/*
+ Proximity networking: Connects to machines or computers adjacent to this device
+*/
+/obj/item/part/computer/networking/prox
+ name = "proximity networking terminal"
+ desc = "Connects a computer to adjacent machines"
+
+ get_machines(var/typekey)
+ var/turf/T = get_turf(loc)
+ if(!istype(T))
+ return list()
+ if(typekey == null)
+ typekey = /obj/machinery
+ var/list/machines = list()
+ for(var/d in cardinal)
+ var/turf/T2 = get_step(T,d)
+ for(var/obj/O in T2)
+ if(istype(O,typekey))
+ machines += O
+ return machines
+
+ verify_machine(var/obj/previous)
+ if(!previous)
+ return 0
+ if(get_dist(get_turf(previous),get_turf(loc)) == 1)
+ return 1
+ return 0
+/*
+ Cable networking: Not currently used
+*/
+
+/obj/item/part/computer/networking/cable
+ name = "cable networking terminal"
+ desc = "Connects to other machines on the same cable network."
+
+ get_machines(var/typekey)
+// if(istype(computer,/obj/machinery/computer/laptop)) // laptops move, this could get breaky
+// return list()
+ var/turf/T = get_turf(loc)
+ var/datum/powernet/P = null
+ for(var/obj/structure/cable/C in T)
+ if(C.d1 == 0)
+ P = C.powernet
+ break
+ if(!P)
+ return list()
+ if(!typekey)
+ typekey = /obj/machinery
+ else if(typekey == /datum/powernet)
+ return list(P)
+ var/list/candidates = list()
+ for(var/atom/A in P.nodes)
+ if(istype(A,typekey))
+ candidates += A
+ else if(istype(A,/obj/machinery/power/terminal))
+ var/obj/machinery/power/terminal/PT = A
+ if(istype(PT.master,typekey))
+ candidates += PT.master
+ return candidates
+
+ verify_machine(var/obj/previous)
+ if(!previous)
+ return 0
+ var/turf/T = get_turf(loc)
+ var/datum/powernet/P = null
+ for(var/obj/structure/cable/C in T)
+ if(C.d1 == 0)
+ P = C.powernet
+ break
+ if(istype(previous,/datum/powernet))
+ if(previous == P)
+ return 1
+ return 0
+ T = get_turf(previous.loc)
+ for(var/obj/structure/cable/C in T)
+ if(C.d1 == 0 && (C.powernet == P))
+ return 1
+ return 0
+
diff --git a/code/WorkInProgress/computer3/program.dm b/code/WorkInProgress/computer3/program.dm
new file mode 100644
index 0000000000..42794f4c2e
--- /dev/null
+++ b/code/WorkInProgress/computer3/program.dm
@@ -0,0 +1,404 @@
+
+/*
+Programs are a file that can be executed
+*/
+
+/datum/file/program
+ name = "Untitled"
+ extension = "prog"
+ image = 'icons/NTOS/program.png'
+ var/desc = "An unidentifiable program."
+
+ var/image/overlay = null // Icon to be put on top of the computer frame.
+
+ var/active_state = "generic" // the icon_state that the computer goes to when the program is active
+
+ drm = 0 // prevents a program from being copied
+ var/refresh = 0 // if true, computer does screen updates during process().
+ var/error = 0 // set by background programs so an error pops up when used
+
+ var/human_controls = 0 // if true, non-human animals cannot interact with this program (monkeys, xenos, etc)
+ var/ai_allowed = 1 // if true, silicon mobs (AI/cyborg) are allowed to use this program.
+
+ var/datum/browser/popup = null
+
+ // ID access: Note that computer3 does not normally check your ID.
+ // By default this is only really used for inserted cards.
+ var/list/req_access = list() // requires all of these UNLESS below succeeds
+ var/list/req_one_access = list() // requires one of these
+
+
+/datum/file/program/New()
+ ..()
+ if(!active_state)
+ active_state = "generic"
+ overlay = image('icons/obj/computer3.dmi',icon_state = active_state)
+
+
+/datum/file/program/proc/decode(text)
+ //adds line breaks
+ text = replacetext(text, "\n","
")
+ return text
+
+
+
+/datum/file/program/execute(var/datum/file/source)
+ if(computer && !computer.stat)
+ computer.program = src
+ computer.req_access = req_access
+ computer.req_one_access = req_one_access
+ update_icon()
+ computer.update_icon()
+ if(usr)
+ usr << browse(null, "window=\ref[computer]")
+ computer.attack_hand(usr)
+
+ ..()
+
+/*
+ Standard Topic() for links
+*/
+
+/datum/file/program/Topic(href, href_list)
+ return
+
+/*
+ The computer object will transfer all empty-hand calls to the program (this includes AIs, Cyborgs, and Monkies)
+*/
+/datum/file/program/proc/interact()
+ return
+
+/*
+ Standard receive_signal()
+*/
+
+/datum/file/program/proc/receive_signal(var/datum/signal/signal)
+ return
+/*
+ The computer object will transfer all attackby() calls to the program
+ If the item is a valid interactable object, return 1. Else, return 0.
+ This helps identify what to use to actually hit the computer with, and
+ what can be used to interact with it.
+
+ Screwdrivers will, by default, never call program/attackby(). That's used
+ for deconstruction instead.
+*/
+
+
+/datum/file/program/proc/attackby(O as obj, user as mob)
+ return
+
+/*
+ Try not to overwrite this proc, I'd prefer we stayed
+ with interact() as the main proc
+*/
+/datum/file/program/proc/attack_hand(mob/user as mob)
+ usr = user
+ interact()
+
+/*
+ Called when the computer is rebooted or the program exits/restarts.
+ Be sure not to save any work. Do NOT start the program again.
+ If it is the os, the computer will run it again automatically.
+
+ Also, we are deleting the browser window on the chance that this is happening
+ when the computer is damaged or disassembled, causing us to lose our computer.
+ The popup window's title is a reference to the computer, making it unique, so
+ it could introduce bugs in that case.
+*/
+/datum/file/program/proc/Reset()
+ error = 0
+ update_icon()
+ if(popup)
+ popup.close()
+ del popup
+ return
+
+/*
+ The computer object will transfer process() calls to the program.
+*/
+/datum/file/program/proc/process()
+ if(refresh && computer && !computer.stat)
+ computer.updateDialog()
+ update_icon()
+
+/datum/file/program/proc/update_icon()
+ return
+
+/datum/file/program/proc/check_access(obj/item/I)
+ if( (!istype(req_access) || !req_access.len) && (!istype(req_one_access) || !req_one_access.len) ) //no requirements
+ return 1
+
+ if(!I)
+ return 0
+
+ var/list/iAccess = I.GetAccess()
+ if(!iAccess || !iAccess.len)
+ return 0
+
+ var/list/temp = req_one_access & iAccess
+ if(temp.len) // a required access in item access list
+ return 1
+ temp = req_access - iAccess
+ if(temp.len) // a required access not in item access list
+ return 0
+ return 1
+
+
+/*
+ Because this does sanity checks I have added the code to make a popup here.
+ It also does sanity checks there that should prevent some edge case madness.
+*/
+/datum/file/program/proc/interactable(var/mob/user = usr)
+ if(computer && computer.interactable(user))
+ if(!popup)
+ popup = new(user, "\ref[computer]", name, nref=src)
+ popup.set_title_image(usr.browse_rsc_icon(overlay.icon, overlay.icon_state))
+ popup.set_title_buttons(topic_link(src,"quit","
"))
+ if(popup.user != user)
+ popup.user = user
+ popup.set_title_image(usr.browse_rsc_icon(overlay.icon, overlay.icon_state))
+ popup.set_title(name)
+ return 1
+ return 0
+
+
+/datum/file/program/proc/fake_link(var/text)
+ return "[text]"
+
+/*
+ Meant for text (not icons) -
+ lists all installed drives and their files
+
+ I am NOT adding a computer sanity check here,
+ because why the flying fuck would you get to this
+ proc before having run it at least once?
+ If you cause runtimes with this function
+ may the shame of all ages come upon you.
+*/
+/datum/file/program/proc/list_all_files_by_drive(var/typekey,var/linkop = "runfile")
+ var/dat = ""
+ if(!typekey) typekey = /datum/file
+ if(computer.hdd)
+ dat += "[computer.hdd]
"
+ for(var/datum/file/F in computer.hdd.files)
+ if(istype(F,typekey))
+ dat += topic_link(src,"[linkop]=\ref[F]",F.name) + "
"
+ if(computer.hdd.files.len == 0)
+ dat += "No files
"
+ dat += "
"
+
+ if(computer.floppy)
+ if(!computer.floppy.inserted)
+ dat += "[computer.floppy] - Eject
"
+ else
+ dat += "[computer.floppy] - [topic_link(src,"eject_disk","Eject")]
"
+ for(var/datum/file/F in computer.floppy.inserted.files)
+ dat += topic_link(src,"[linkop]=\ref[F]",F.name) + "
"
+ if(computer.floppy.inserted.files.len == 0)
+ dat += "No files
"
+ dat += "
"
+
+ if(computer.cardslot && istype(computer.cardslot.reader,/obj/item/weapon/card/data))
+ dat += "[computer.cardslot.reader] - [topic_link(src,"eject_card=reader","Eject")]
"
+ var/obj/item/weapon/card/data/D = computer.cardslot.reader
+ for(var/datum/file/F in D.files)
+ dat += topic_link(src,"[linkop]=\ref[F]",F.name) + "
"
+ if(D.files.len == 0)
+ dat += "No files
"
+ return dat
+
+// You don't NEED to use this version of topic() for this, you can do it yourself if you prefer
+// If you do, do the interactable() check first, please, I don't want to repeat it here. It's not hard.
+/datum/file/program/Topic(var/href,var/list/href_list)
+ if(!computer)
+ return 0
+
+ //
+ // usage: eject_disk
+ // only functions if there is a removable drive
+ //
+ if("eject_disk" in href_list)
+ if(computer.floppy)
+ computer.floppy.eject_disk()
+ return 1
+ //
+ // usage: eject_card | eject_card=reader | eject_card=writer
+ // only functions if there is a cardslot
+ //
+ if("eject_card" in href_list)
+ if(computer.cardslot)
+ if(computer.cardslot.dualslot && href_list["eject_card"] == "writer")
+ computer.cardslot.remove(computer.cardslot.writer)
+ else
+ computer.cardslot.remove(computer.cardslot.reader)
+ return 1
+ //
+ // usage: runfile=\ref[file]
+ // executes the file
+ //
+ if("runfile" in href_list)
+ var/datum/file/F = locate(href_list["runfile"])
+ if(F && F.computer == computer)
+ F.execute(src)
+ return 1
+
+ if("close" in href_list)
+ usr.unset_machine()
+ popup.close()
+ return 1
+ //
+ // usage: quit
+ // unloads the program, returning control to the OS
+ //
+ if("quit" in href_list)
+ computer.program = null
+ usr << browse(null,"window=\ref[computer]") // NTOS will need to resize the window
+ computer.update_icon()
+ computer.updateDialog()
+ return 1
+ return 0
+
+
+/datum/file/program/RD
+ name = "R&D Manager"
+ image = 'icons/NTOS/research.png'
+ desc = "A software suit for generic research and development machinery interaction. Comes pre-packaged with extensive cryptographic databanks for secure connections with external devices."
+ active_state = "rdcomp"
+ volume = 11000
+
+/datum/file/program/RDserv
+ name = "R&D Server"
+ image = 'icons/NTOS/server.png'
+ active_state = "rdcomp"
+ volume = 9000
+
+/datum/file/program/SuitSensors
+ name = "Crew Monitoring"
+ image = 'icons/NTOS/monitoring.png'
+ active_state = "crew"
+ volume = 3400
+
+/datum/file/program/Genetics
+ name = "Genetics Suite"
+ image = 'icons/NTOS/genetics.png'
+ desc = "A sophisticated software suite containing read-only genetics hardware specifications and a highly compressed genome databank."
+ active_state = "dna"
+ volume = 8000
+
+/datum/file/program/Cloning
+ name = "Cloning Platform"
+ image = 'icons/NTOS/cloning.png'
+ desc = "A software platform for accessing external cloning apparatus."
+ active_state = "dna"
+ volume = 7000
+
+/datum/file/program/TCOMmonitor
+ name = "TComm Monitor"
+ image = 'icons/NTOS/tcomms.png'
+ active_state = "comm_monitor"
+ volume = 5500
+
+/datum/file/program/TCOMlogs
+ name = "TComm Log View"
+ image = 'icons/NTOS/tcomms.png'
+ active_state = "comm_logs"
+ volume = 5230
+
+/datum/file/program/TCOMtraffic
+ name = "TComm Traffic"
+ image = 'icons/NTOS/tcomms.png'
+ active_state = "generic"
+ volume = 8080
+
+/datum/file/program/securitycam
+ name = "Sec-Cam Viewport"
+ image = 'icons/NTOS/camera.png'
+ drm = 1
+ active_state = "cameras"
+ volume = 2190
+
+/datum/file/program/securityrecords
+ name = "Security Records"
+ image = 'icons/NTOS/records.png'
+ drm = 1
+ active_state = "security"
+ volume = 2520
+
+/datum/file/program/medicalrecords
+ name = "Medical Records"
+ image = 'icons/NTOS/medical.png'
+ drm = 1
+ active_state = "medcomp"
+ volume = 5000
+
+/datum/file/program/SMSmonitor
+ name = "Messaging Monitor"
+ image = 'icons/NTOS/pda.png'
+ active_state = "comm_monitor"
+ volume = 3070
+
+/datum/file/program/OperationMonitor
+ name = "OR Monitor"
+ image = 'icons/NTOS/operating.png'
+ active_state = "operating"
+ volume = 4750
+
+/datum/file/program/PodLaunch
+ name = "Pod Launch"
+ active_state = "computer_generic"
+ volume = 520
+
+/datum/file/program/PowerMonitor
+ name = "Power Grid"
+ image = 'icons/NTOS/power.png'
+ active_state = "power"
+ volume = 7200
+
+/datum/file/program/PrisonerManagement
+ name = "Prisoner Control"
+ image = 'icons/NTOS/prison.png'
+ drm = 1
+ active_state = "power"
+ volume = 5000
+
+/datum/file/program/Roboticscontrol
+ name = "Cyborg Maint"
+ image = 'icons/NTOS/borgcontrol.png'
+ active_state = "robot"
+ volume = 9050
+
+/datum/file/program/AIupload
+ name = "AI Upload"
+ image = 'icons/NTOS/aiupload.png'
+ active_state = "command"
+ volume = 5000
+
+/datum/file/program/Cyborgupload
+ name = "Cyborg Upload"
+ image = 'icons/NTOS/borgupload.png'
+ active_state = "command"
+ volume = 5000
+
+/datum/file/program/Exosuit
+ name = "Exosuit Monitor"
+ image = 'icons/NTOS/exocontrol.png'
+ active_state = "mecha"
+ volume = 7000
+
+/datum/file/program/EmergencyShuttle
+ name = "Shuttle Console"
+ active_state = "shuttle"
+ volume = 10000
+
+/datum/file/program/Stationalert
+ name = "Alert Monitor"
+ image = 'icons/NTOS/alerts.png'
+ active_state = "computer_generic"
+ volume = 10150
+
+
+
+
+
+
diff --git a/code/WorkInProgress/computer3/program_disks.dm b/code/WorkInProgress/computer3/program_disks.dm
new file mode 100644
index 0000000000..201fff3939
--- /dev/null
+++ b/code/WorkInProgress/computer3/program_disks.dm
@@ -0,0 +1,44 @@
+
+
+/obj/item/weapon/disk/file/arcade
+ name = "Arcade game grab pack"
+ desc = "A program install disk."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "datadisk_arcade"
+ spawn_files = list(/datum/file/program/arcade,/datum/file/program/arcade,/datum/file/program/arcade,/datum/file/program/arcade)
+
+/*/obj/item/weapon/disk/file/aifixer
+ name = "AI System Integrity Restorer"
+ desc = "A program install disk."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "datadisk_arcade"
+ spawn_files = list(/datum/file/program/aifixer)*/
+
+/obj/item/weapon/disk/file/atmos_alert
+ name = "Atmospheric Alert Notifier"
+ desc = "A program install disk."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "datadisk_arcade"
+ spawn_files = list(/datum/file/program/atmos_alert)
+
+/obj/item/weapon/disk/file/cameras
+ name = "Camera Viewer"
+ desc = "A program install disk."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "datadisk_arcade"
+ spawn_files = list(/datum/file/program/security)
+
+/obj/item/weapon/disk/file/card
+ name = "ID Card Modifier"
+ desc = "A program install disk."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "datadisk_arcade"
+ spawn_files = list(/datum/file/program/card_comp)
+/*
+/obj/item/weapon/disk/file/genetics
+ name = "Genetics & Cloning"
+ desc = "A program install disk."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "datadisk_arcade"
+ spawn_files = list(/datum/file/program/cloning,/datum/file/program/dnascanner)
+*/
diff --git a/code/WorkInProgress/computer3/server.dm b/code/WorkInProgress/computer3/server.dm
new file mode 100644
index 0000000000..9e32918fea
--- /dev/null
+++ b/code/WorkInProgress/computer3/server.dm
@@ -0,0 +1,32 @@
+/*
+ Todo:
+ I can probably get away with a global list on servers that contains database sort of stuff
+ (replacing the datacore probably)
+ with the justification that they loadbalance and duplicate data across each other. As long as
+ one server-type computer exists, the station will still have access to datacore-type info.
+
+ I can doubtless use this for station alerts as well, which is good, because I was sort of
+ wondering how the hell I was going to port that.
+
+ Also todo: Server computers should maybe generate heat the way the R&D server does?
+ At least the rack computer probably should.
+*/
+
+/obj/machinery/computer3/server
+ name = "server"
+ icon = 'icons/obj/computer3.dmi'
+ icon_state = "serverframe"
+ show_keyboard = 0
+
+/obj/machinery/computer3/server/rack
+ name = "server rack"
+ icon_state = "rackframe"
+
+ spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio/subspace)
+
+ update_icon()
+ //overlays.Cut()
+ return
+
+ attack_hand() // Racks have no screen, only AI can use them
+ return
diff --git a/code/WorkInProgress/computer3/storage.dm b/code/WorkInProgress/computer3/storage.dm
new file mode 100644
index 0000000000..acf9a76288
--- /dev/null
+++ b/code/WorkInProgress/computer3/storage.dm
@@ -0,0 +1,184 @@
+/*
+ Computer devices that can store programs, files, etc.
+*/
+
+/obj/item/part/computer/storage
+ name = "Storage Device"
+ desc = "A device used for storing and retrieving digital information."
+
+ // storage capacity, kb
+ var/volume = 0
+ var/max_volume = 64 // should be enough for anyone
+
+ var/driveletter = null // drive letter according to the computer
+
+ var/list/files = list() // a list of files in the memory (ALL files)
+ var/removeable = 0 // determinse if the storage device is a removable hard drive (ie floppy)
+
+
+ var/writeprotect = 0 // determines if the drive forbids writing.
+ // note that write-protect is hardware and does not respect emagging.
+
+ var/list/spawnfiles = list()// For mappers, special drives, and data disks
+
+ New()
+ ..()
+ if(islist(spawnfiles))
+ if(removeable && spawnfiles.len)
+ var/obj/item/part/computer/storage/removable/R = src
+ R.inserted = new(src)
+ if(writeprotect)
+ R.inserted.writeprotect = 1
+ for(var/typekey in spawnfiles)
+ addfile(new typekey(),1)
+
+ // Add a file to the hard drive, returns 0 if failed
+ // forced is used when spawning files on a write-protect drive
+ proc/addfile(var/datum/file/F,var/forced = 0)
+ if(!F || crit_fail || (F in files))
+ return 1
+ if(writeprotect && !forced)
+ return 0
+ if(volume + F.volume > max_volume)
+ if(!forced)
+ return 0
+ max_volume = volume + F.volume
+
+ files.Add(F)
+ volume += F.volume
+ F.computer = computer
+ F.device = src
+ return 1
+ proc/removefile(var/datum/file/F,var/forced = 0)
+ if(!F || !(F in files))
+ return 1
+ if(writeprotect && !forced)
+ return 0
+
+ files -= F
+ volume -= F.volume
+ if(F.device == src)
+ F.device = null
+ F.computer = null
+ return 1
+
+ init(var/obj/machinery/computer/target)
+ computer = target
+ for(var/datum/file/F in files)
+ F.computer = computer
+
+/*
+ Standard hard drives for computers. Used in computer construction
+*/
+
+/obj/item/part/computer/storage/hdd
+ name = "Hard Drive"
+ max_volume = 25000
+ icon_state = "hdd1"
+
+
+/obj/item/part/computer/storage/hdd/big
+ name = "Big Hard Drive"
+ max_volume = 50000
+ icon_state = "hdd2"
+
+/obj/item/part/computer/storage/hdd/gigantic
+ name = "Gigantic Hard Drive"
+ max_volume = 75000
+ icon_state = "hdd3"
+
+/*
+ Removeable hard drives for portable storage
+*/
+
+/obj/item/part/computer/storage/removable
+ name = "Disk Drive"
+ max_volume = 3000
+ removeable = 1
+
+ attackby_types = list(/obj/item/weapon/disk/file, /obj/item/weapon/pen)
+ var/obj/item/weapon/disk/file/inserted = null
+
+ proc/eject_disk(var/forced = 0)
+ if(!forced)
+ return
+ files = list()
+ inserted.loc = computer.loc
+ if(usr)
+ if(!usr.get_active_hand())
+ usr.put_in_active_hand(inserted)
+ else if(forced && !usr.get_inactive_hand())
+ usr.put_in_inactive_hand(inserted)
+ for(var/datum/file/F in inserted.files)
+ F.computer = null
+ inserted = null
+
+
+ attackby(obj/O as obj, mob/user as mob)
+ if(inserted && istype(O,/obj/item/weapon/pen))
+ usr << "You use [O] to carefully pry [inserted] out of [src]."
+ eject_disk(forced = 1)
+ return
+
+ if(istype(O,/obj/item/weapon/disk/file))
+ if(inserted)
+ usr << "There's already a disk in [src]!"
+ return
+
+ usr << "You insert [O] into [src]."
+ usr.drop_item()
+ O.loc = src
+ inserted = O
+ writeprotect = inserted.writeprotect
+
+ files = inserted.files
+ for(var/datum/file/F in inserted.files)
+ F.computer = computer
+
+ return
+
+ ..()
+
+ addfile(var/datum/file/F)
+ if(!F || !inserted)
+ return 0
+
+ if(F in inserted.files)
+ return 1
+
+ if(inserted.volume + F.volume > inserted.max_volume)
+ return 0
+
+ inserted.files.Add(F)
+ F.computer = computer
+ F.device = inserted
+ return 1
+
+/*
+ Removable hard drive presents...
+ removeable disk!
+*/
+
+/obj/item/weapon/disk/file
+ //parent_type = /obj/item/part/computer/storage // todon't: do this
+ name = "Data Disk"
+ desc = "A device that can be inserted and removed into computers easily as a form of portable data storage. This one stores 1 Megabyte"
+ var/list/files
+ var/list/spawn_files = list()
+ var/writeprotect = 0
+ var/volume = 0
+ var/max_volume = 1028
+
+
+ New()
+ ..()
+ icon_state = "datadisk[rand(0,6)]"
+ src.pixel_x = rand(-5, 5)
+ src.pixel_y = rand(-5, 5)
+ files = list()
+ if(istype(spawn_files))
+ for(var/typekey in spawn_files)
+ var/datum/file/F = new typekey()
+ F.device = src
+ files += F
+ volume += F.volume
diff --git a/code/WorkInProgress/computer3/test_machines.dm b/code/WorkInProgress/computer3/test_machines.dm
new file mode 100644
index 0000000000..998937e634
--- /dev/null
+++ b/code/WorkInProgress/computer3/test_machines.dm
@@ -0,0 +1,86 @@
+
+/obj/machinery/computer3/testing
+ spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
+ /datum/file/program/security,/datum/file/program/card_comp,
+ /datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
+ /datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
+
+ /datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
+ /datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
+ spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
+ /obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
+ /obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
+ New(var/L,var/built=0)
+ if(!built && !battery)
+ battery = new /obj/item/weapon/cell(src)
+ ..(L,built)
+
+/obj/machinery/computer3/laptop/testing
+ spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
+ /datum/file/program/security,/datum/file/program/card_comp,
+ /datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
+ /datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
+
+ /datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
+ /datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
+ spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
+ /obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
+ /obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
+ New(var/L,var/built=0)
+ if(!built && !battery)
+ battery = new /obj/item/weapon/cell/super(src)
+ ..(L,built)
+
+/obj/machinery/computer3/wall_comp/testing
+ spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
+ /datum/file/program/security,/datum/file/program/card_comp,
+ /datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
+ /datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
+
+ /datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
+ /datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
+ spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
+ /obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
+ /obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
+ New(var/L,var/built=0)
+ if(!built && !battery)
+ battery = new /obj/item/weapon/cell(src)
+ ..(L,built)
+
+/obj/machinery/computer3/server/testing
+ spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
+ /datum/file/program/security,/datum/file/program/card_comp,
+ /datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
+ /datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
+
+ /datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
+ /datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
+ spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
+ /obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
+ /obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
+ New(var/L,var/built=0)
+ if(!built && !battery)
+ battery = new /obj/item/weapon/cell(src)
+ ..(L,built)
+
+/obj/machinery/computer3/server/rack/testing
+ spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
+ /datum/file/program/security,/datum/file/program/card_comp,
+ /datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
+ /datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
+
+ /datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
+ /datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
+ spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
+ /obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
+ /obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
+ New(var/L,var/built=0)
+ if(!built && !battery)
+ battery = new /obj/item/weapon/cell(src)
+ ..(L,built)
+
+/obj/item/weapon/storage/box/testing_disks
+ New()
+ ..()
+ for(var/typekey in typesof(/obj/item/weapon/disk/file) - /obj/item/weapon/disk/file)
+ new typekey(src)
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/upload/lawfile.dm b/code/WorkInProgress/computer3/upload/lawfile.dm
new file mode 100644
index 0000000000..e3b21f537e
--- /dev/null
+++ b/code/WorkInProgress/computer3/upload/lawfile.dm
@@ -0,0 +1,29 @@
+/*
+ Computer3 law changes:
+
+ * Laws are a file type
+ * Connecting to the AI requires a network connection
+ * Connecting to a borg requires a radio or network.
+
+*/
+
+/datum/file/ai_law
+ var/list/hacklaws = null
+ var/zerolaw = null
+ var/list/corelaws = null
+ var/list/auxlaws = null
+
+ var/configurable = 0
+
+ // override this when you need to be able to alter the parameters of the lawset
+ proc/configure()
+ return
+
+ execute(var/datum/file/program/source)
+ if(istype(usr,/mob/living/silicon))
+ return
+ if(istype(source,/datum/file/program/NTOS))
+ if(configurable)
+ configure()
+ return
+ if(istype(source,/datum/file/program/upload/ai))
\ No newline at end of file
diff --git a/code/WorkInProgress/computer3/upload/programs.dm b/code/WorkInProgress/computer3/upload/programs.dm
new file mode 100644
index 0000000000..bcf45159b6
--- /dev/null
+++ b/code/WorkInProgress/computer3/upload/programs.dm
@@ -0,0 +1,13 @@
+/*
+ Note that as with existing ai upload, this is not an interactive program.
+ That means that the work is done in execute() rather than interact()
+*/
+
+/datum/file/program/upload/ai
+ execute(var/datum/file/program/source)
+ if(!interactable() || istype(usr,/mob/living/silicon))
+ return 0
+ if(!computer.net)
+ usr << "An indecipherable set of code flicks across the screen. Nothing else happens."
+ return
+ var/list/results = computer.net.get_machines
\ No newline at end of file
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index c6c1c38a4f..8b65de1f37 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1386,3 +1386,8 @@ var/list/WALLITEMS = list(
/proc/format_text(text)
return replacetext(replacetext(text,"\proper ",""),"\improper ","")
+
+/proc/topic_link(var/datum/D, var/arglist, var/content)
+ if(istype(arglist,/list))
+ arglist = list2params(arglist)
+ return "[content]"
\ No newline at end of file
diff --git a/code/datums/browser.dm b/code/datums/browser.dm
index cee5acdd53..31124c6faf 100644
--- a/code/datums/browser.dm
+++ b/code/datums/browser.dm
@@ -13,6 +13,7 @@
var/body_elements
var/head_content = ""
var/content = ""
+ var/title_buttons = ""
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
@@ -29,9 +30,15 @@
ref = nref
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs
+/datum/browser/proc/set_title(ntitle)
+ title = format_text(ntitle)
+
/datum/browser/proc/add_head_content(nhead_content)
head_content = nhead_content
+/datum/browser/proc/set_title_buttons(ntitle_buttons)
+ title_buttons = ntitle_buttons
+
/datum/browser/proc/set_window_options(nwindow_options)
window_options = nwindow_options
diff --git a/code/setup.dm b/code/setup.dm
index 86d1aaff87..4971241ea8 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -758,3 +758,12 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse
#define COLOR_YELLOW "#FFFF00"
#define COLOR_ORANGE "#FF9900"
#define COLOR_WHITE "#FFFFFF"
+
+
+//computer3 error codes, move lower in the file when it passes dev -Sayu
+ #define PROG_CRASH 1 // Generic crash
+ #define MISSING_PERIPHERAL 2 // Missing hardware
+ #define BUSTED_ASS_COMPUTER 4 // Self-perpetuating error. BAC will continue to crash forever.
+ #define MISSING_PROGRAM 8 // Some files try to automatically launch a program. This is that failing.
+ #define FILE_DRM 16 // Some files want to not be copied/moved. This is them complaining that you tried.
+ #define NETWORK_FAILURE 32
\ No newline at end of file
diff --git a/icons/NTOS/airestore.png b/icons/NTOS/airestore.png
new file mode 100644
index 0000000000..d8e5207bfb
Binary files /dev/null and b/icons/NTOS/airestore.png differ
diff --git a/icons/NTOS/aiupload.png b/icons/NTOS/aiupload.png
new file mode 100644
index 0000000000..25a8d8694e
Binary files /dev/null and b/icons/NTOS/aiupload.png differ
diff --git a/icons/NTOS/alerts.png b/icons/NTOS/alerts.png
new file mode 100644
index 0000000000..d395428c7c
Binary files /dev/null and b/icons/NTOS/alerts.png differ
diff --git a/icons/NTOS/borgcontrol.png b/icons/NTOS/borgcontrol.png
new file mode 100644
index 0000000000..63e0815954
Binary files /dev/null and b/icons/NTOS/borgcontrol.png differ
diff --git a/icons/NTOS/borgupload.png b/icons/NTOS/borgupload.png
new file mode 100644
index 0000000000..dfb24cecfd
Binary files /dev/null and b/icons/NTOS/borgupload.png differ
diff --git a/icons/NTOS/camera.png b/icons/NTOS/camera.png
new file mode 100644
index 0000000000..a9a726b03d
Binary files /dev/null and b/icons/NTOS/camera.png differ
diff --git a/icons/NTOS/cardcomp.png b/icons/NTOS/cardcomp.png
new file mode 100644
index 0000000000..e7df0ab207
Binary files /dev/null and b/icons/NTOS/cardcomp.png differ
diff --git a/icons/NTOS/cloning.png b/icons/NTOS/cloning.png
new file mode 100644
index 0000000000..6fa2942505
Binary files /dev/null and b/icons/NTOS/cloning.png differ
diff --git a/icons/NTOS/comms.png b/icons/NTOS/comms.png
new file mode 100644
index 0000000000..e089889d93
Binary files /dev/null and b/icons/NTOS/comms.png differ
diff --git a/icons/NTOS/copyfile.png b/icons/NTOS/copyfile.png
new file mode 100644
index 0000000000..50c10b3757
Binary files /dev/null and b/icons/NTOS/copyfile.png differ
diff --git a/icons/NTOS/deletefile.png b/icons/NTOS/deletefile.png
new file mode 100644
index 0000000000..ada175fad2
Binary files /dev/null and b/icons/NTOS/deletefile.png differ
diff --git a/icons/NTOS/drive.png b/icons/NTOS/drive.png
new file mode 100644
index 0000000000..69ca021f8b
Binary files /dev/null and b/icons/NTOS/drive.png differ
diff --git a/icons/NTOS/exocontrol.png b/icons/NTOS/exocontrol.png
new file mode 100644
index 0000000000..101f32e44d
Binary files /dev/null and b/icons/NTOS/exocontrol.png differ
diff --git a/icons/NTOS/file.png b/icons/NTOS/file.png
new file mode 100644
index 0000000000..05556e01f8
Binary files /dev/null and b/icons/NTOS/file.png differ
diff --git a/icons/NTOS/folder.png b/icons/NTOS/folder.png
new file mode 100644
index 0000000000..05780bc651
Binary files /dev/null and b/icons/NTOS/folder.png differ
diff --git a/icons/NTOS/foldermeta.png b/icons/NTOS/foldermeta.png
new file mode 100644
index 0000000000..0d7a26b943
Binary files /dev/null and b/icons/NTOS/foldermeta.png differ
diff --git a/icons/NTOS/genetics.png b/icons/NTOS/genetics.png
new file mode 100644
index 0000000000..6f5b2320fc
Binary files /dev/null and b/icons/NTOS/genetics.png differ
diff --git a/icons/NTOS/medical.png b/icons/NTOS/medical.png
new file mode 100644
index 0000000000..a3b6a21b54
Binary files /dev/null and b/icons/NTOS/medical.png differ
diff --git a/icons/NTOS/monitoring.png b/icons/NTOS/monitoring.png
new file mode 100644
index 0000000000..a94910e48a
Binary files /dev/null and b/icons/NTOS/monitoring.png differ
diff --git a/icons/NTOS/movefile.png b/icons/NTOS/movefile.png
new file mode 100644
index 0000000000..5b31c6c2a8
Binary files /dev/null and b/icons/NTOS/movefile.png differ
diff --git a/icons/NTOS/ntos.png b/icons/NTOS/ntos.png
new file mode 100644
index 0000000000..8b9d735cc9
Binary files /dev/null and b/icons/NTOS/ntos.png differ
diff --git a/icons/NTOS/operating.png b/icons/NTOS/operating.png
new file mode 100644
index 0000000000..ab8f65ef7a
Binary files /dev/null and b/icons/NTOS/operating.png differ
diff --git a/icons/NTOS/pda.png b/icons/NTOS/pda.png
new file mode 100644
index 0000000000..c6b0bb00fb
Binary files /dev/null and b/icons/NTOS/pda.png differ
diff --git a/icons/NTOS/power.png b/icons/NTOS/power.png
new file mode 100644
index 0000000000..b2e4cc837f
Binary files /dev/null and b/icons/NTOS/power.png differ
diff --git a/icons/NTOS/prison.png b/icons/NTOS/prison.png
new file mode 100644
index 0000000000..a846fe0041
Binary files /dev/null and b/icons/NTOS/prison.png differ
diff --git a/icons/NTOS/program.png b/icons/NTOS/program.png
new file mode 100644
index 0000000000..ac16128763
Binary files /dev/null and b/icons/NTOS/program.png differ
diff --git a/icons/NTOS/records.png b/icons/NTOS/records.png
new file mode 100644
index 0000000000..eaaf68e50d
Binary files /dev/null and b/icons/NTOS/records.png differ
diff --git a/icons/NTOS/research.png b/icons/NTOS/research.png
new file mode 100644
index 0000000000..5ebd63aafc
Binary files /dev/null and b/icons/NTOS/research.png differ
diff --git a/icons/NTOS/server.png b/icons/NTOS/server.png
new file mode 100644
index 0000000000..6d96b11413
Binary files /dev/null and b/icons/NTOS/server.png differ
diff --git a/icons/NTOS/tb_close.png b/icons/NTOS/tb_close.png
new file mode 100644
index 0000000000..b99a6d8154
Binary files /dev/null and b/icons/NTOS/tb_close.png differ
diff --git a/icons/NTOS/tcomms.png b/icons/NTOS/tcomms.png
new file mode 100644
index 0000000000..a63b23c8df
Binary files /dev/null and b/icons/NTOS/tcomms.png differ
diff --git a/icons/obj/computer3.dmi b/icons/obj/computer3.dmi
new file mode 100644
index 0000000000..4942da6a6b
Binary files /dev/null and b/icons/obj/computer3.dmi differ