Files
drsingh dc4217b498 modified process scheduler, 510 compatibility, explosions moved to process
this is all very alpha please don't hate me too much if i fucked it up
2016-03-12 16:36:00 -08:00

4895 lines
136 KiB
Plaintext

//Miscellaneous Terminal Devices
//CONTENTS:
// Basic pnet machine
// HIGH-TECH tape storage
// A bomb simulator. Test bombs in VR!
// Outpost self-destruct !nuke!
// A wirenet -> wireless link thing.
// A printer! All the fun of printing, now in SS13!
// Pathogen manipulator TO-DO
// Security system monitor
// A dangerous teleportation-oriented testing apparatus.
// Generic testing appartus
/obj/machinery/networked
anchored = 1
density = 1
icon = 'icons/obj/networked.dmi'
var/net_id = null
var/host_id = null //Who are we connected to? (If we have a single host)
var/old_host_id = null //Were we previously connected to someone? Do we care?
var/obj/machinery/power/data_terminal/link = null
var/device_tag = "PNET_GENERICDV"
var/timeout = 40 //The time until we auto disconnect (if we don't get a refresh ping)
var/timeout_alert = 0 //Have we sent a timeout refresh alert?
var/last_reset = 0 //Last world.time we were manually reset.
var/net_number = 0 //A cute little bitfield (0-3 exposed) to allow multiple networks on one wirenet. Differentiate between intended hosts, if they care.
var/panel_open = 0
proc/post_status(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3, var/key4, var/value4)
if(!src.link || !target_id)
return
var/datum/signal/signal = get_free_signal()
signal.source = src
signal.transmission_method = TRANSMISSION_WIRE
signal.data[key] = value
if(key2)
signal.data[key2] = value2
if(key3)
signal.data[key3] = value3
if(key4)
signal.data[key4] = value4
signal.data["address_1"] = target_id
signal.data["sender"] = src.net_id
src.link.post_signal(src, signal)
proc/post_file(var/target_id, var/key, var/value, var/file)
if(!src.link || !target_id)
return
var/datum/signal/signal = get_free_signal()
signal.source = src
signal.transmission_method = TRANSMISSION_WIRE
signal.data[key] = value
if(file)
var/datum/computer/file/F = file
signal.data_file = F.copy_file()
signal.data["address_1"] = target_id
signal.data["command"] = "term_file"
signal.data["sender"] = src.net_id
src.link.post_signal(src, signal)
proc/net_switch_html()
. = "<br>Configuration Switches:<br><table border='1' style='background-color:#7A7A7A'><tr>"
for (var/i = 8, i >= 1, i >>= 1)
var/styleColor = (net_number & i) ? "#60B54A" : "#CD1818"
. += "<td style='background-color:[styleColor]'><a href='?src=\ref[src];dipsw=[i]' style='color:[styleColor]'>##</a></td>"
. += "</tr></table>"
Topic(href, href_list)
if (..())
return 1
if (href_list["dipsw"] && src.panel_open && get_dist(usr, src) < 2)
var/switchNum = text2num(href_list["dipsw"])
if (switchNum < 1 || switchNum > 8)
return 1
switchNum = round(switchNum)
if (net_number & switchNum)
net_number &= ~switchNum
else
net_number |= switchNum
src.updateUsrDialog()
return 1
return 0
disposing()
if (src.link)
src.link.master = null
src.link = null
..()
/obj/machinery/networked/storage
name = "Databank"
desc = "A networked data storage device."
anchored = 1
density = 1
icon_state = "tapedrive0"
device_tag = "PNET_DATA_BANK"
mats = 12
var/base_icon_state = "tapedrive"
var/bank_id = null //Unique Identifier for this databank.
var/locked = 1
var/read_only = 0 //Read only, even if the disk isn't!
var/obj/item/disk/data/tape = null
var/setup_drive_size = 128
var/setup_tape_tag = "tape"
var/setup_tape_type = /obj/item/disk/data/tape //Parent type that can be used as disk.
var/setup_drive_type = /obj/item/disk/data/tape //Use this path for the tape
var/setup_spawn_with_tape = 1 //Spawn with tape in the drive.
var/setup_access_click = 0 //Play tape drive noise when accessed.
var/setup_allow_boot = 0 //We respond to bootreq requests.
var/setup_accept_tapes = 1
power_usage = 200
tape_drive
name = "Databank"
desc = "A networked tape drive."
icon_state = "tapedrive0"
base_icon_state = "tapedrive"
setup_access_click = 1
setup_tape_tag = "tape"
setup_tape_type = /obj/item/disk/data/tape
setup_allow_boot = 1
clone()
var/obj/machinery/networked/storage/clonestore = ..()
if (!clonestore)
return
clonestore.locked = src.locked
clonestore.base_icon_state = src.base_icon_state
clonestore.device_tag = src.device_tag
clonestore.read_only = src.read_only
clonestore.setup_access_click = src.setup_access_click
clonestore.setup_allow_boot = src.setup_allow_boot
clonestore.setup_tape_type = src.setup_tape_type
clonestore.setup_drive_type = src.setup_drive_type
clonestore.bank_id = src.bank_id
if (src.tape)
clonestore.tape = src.tape.clone()
return clonestore
New()
..()
if(!bank_id)
bank_id = "GENERIC"
src.net_id = generate_net_id(src)
spawn(5)
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
if(!tape && (setup_drive_size > 0) && setup_spawn_with_tape)
if(src.setup_drive_type)
if (istext(src.setup_drive_type))
src.setup_drive_type = text2path(src.setup_drive_type)
src.tape = new src.setup_drive_type (src)
src.tape.set_loc(src)
src.tape.file_amount = max(src.setup_drive_size, src.tape.file_amount)
src.power_change() //Update the icon
disposing()
if (src.tape)
src.tape.dispose()
src.tape = null
..()
process()
if(stat & BROKEN)
return
..()
if(stat & NOPOWER)
return
use_power(200)
if(!host_id || !link)
return
if(src.timeout == 0)
src.post_status(host_id, "command","term_disconnect","data","timeout")
src.host_id = null
src.updateUsrDialog()
src.timeout = initial(src.timeout)
src.timeout_alert = 0
else
src.timeout--
if(src.timeout <= 5 && !src.timeout_alert)
src.timeout_alert = 1
src.post_status(src.host_id, "command","term_ping","data","reply")
return
attack_hand(mob/user as mob)
if(..() && !(stat & NOPOWER)) //Allow them to remove tapes even if the power's out.
return
user.machine = src
var/dat = "<html><head><title>Databank - \[[bank_id]]</title></head><body>"
dat += "<b>[capitalize(src.setup_tape_tag)]:</b> <a href='?src=\ref[src];tape=1'>[src.tape ? "Eject" : "--------"]</a><hr>"
if (stat & NOPOWER)
user << browse(dat,"window=databank;size=245x302")
onclose(user,"databank")
return
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
dat += "<br>Read Only: "
if(!src.read_only)
dat += "<a href='?src=\ref[src];read=1'>YES</a> <b>NO</b><br>"
else
dat += "<b>YES</b> <a href='?src=\ref[src];read=1'>NO</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=databank;size=245x302")
onclose(user,"databank")
return
Topic(href, href_list)
if(..() && !(href_list["tape"] && (stat&NOPOWER)))
return
usr.machine = src
if(href_list["tape"])
if(src.locked)
boutput(usr, "<span style=\"color:red\">The cover is screwed shut.</span>")
return
//Ai/cyborgs cannot physically remove a tape from a room away.
if(istype(usr,/mob/living/silicon) && get_dist(src, usr) > 1)
boutput(usr, "<span style=\"color:red\">You cannot press the ejection button.</span>")
return
if(src.tape)
src.tape.set_loc(src.loc)
src.tape = null
boutput(usr, "You remove the [src.setup_tape_tag] from the drive.")
src.power_change()
if (src.host_id && !(stat & (NOPOWER|BROKEN)))
src.post_status(src.host_id,"command","term_message","data","command=status&status=notape")
else
var/obj/item/I = usr.equipped()
if (istype(I, src.setup_tape_type))
usr.drop_item()
I.set_loc(src)
src.tape = I
boutput(usr, "You insert [I].")
src.sync(src.host_id)
src.power_change()
src.updateUsrDialog()
return
else if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id && !old_host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
else if (href_list["read"])
src.read_only = !src.read_only
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, src.setup_tape_type) && setup_accept_tapes) //INSERT SOME TAPES
if (src.tape)
boutput(user, "<span style=\"color:red\">There is already a [src.setup_tape_tag] in the drive.</span>")
return
if (src.locked)
boutput(user, "<span style=\"color:red\">The cover is screwed shut.</span>")
return
user.drop_item()
W.set_loc(src)
src.tape = W
boutput(user, "You insert [W].")
src.power_change()
src.updateUsrDialog()
src.sync(src.host_id)
return
else if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
src.locked = !src.locked
src.panel_open = !src.locked
boutput(user, "You [src.locked ? "secure" : "unscrew"] the cover.")
src.updateUsrDialog()
return
else
..()
return
receive_signal(datum/signal/signal)
if(stat & (NOPOWER) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
if(signal.transmission_method != TRANSMISSION_WIRE) //This is a wired device only.
return
var/target = signal.data["sender"]
//They don't need to target us specifically to ping us.
//Otherwise, if they aren't addressing us, ignore them
if(signal.data["address_1"] != src.net_id)
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
spawn(5) //Send a reply for those curious jerks
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[src.net_number]")
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !signal.data["sender"])
return
switch(sigcommand)
if("term_connect") //Terminal interface stuff.
if(target == src.host_id)
//WHAT IS THIS, HOW COULD THIS HAPPEN??
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(2) //Sign up with the driver (if a mainframe contacted us)
src.post_status(target,"command","term_message","data","command=register&data=[src.bank_id]")
return
if("term_message","term_file")
if(target != src.host_id) //Huh, who is this?
return
var/list/data = params2list(signal.data["data"])
if(!data)
return
var/sessionid = data["session"]
if (!sessionid)
sessionid = 0
if (setup_access_click)
playsound(src.loc, "sound/machines/driveclick.ogg", 25, 0, -2)
switch(data["command"])
if("sync")
if (!src.tape)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
src.sync(target)
return
if("catalog") //List file directory/tape information
if(!src.tape)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
var/datum/computer/file/record/catrec = new
catrec.fields["/header"] = "name=[tape.title]&used=[tape.file_used]&size=[tape.file_amount]"
if(!tape.root.contents.len)
catrec.fields["NOFILE"] = "NOFILES"
else
for(var/datum/computer/file/F in tape.root.contents)
catrec.fields[F.name] = "[F.extension] - [F.size]"
spawn(2)
src.post_file(target, "data","command=catalog",catrec)
//qdel(catrec) //A copy is sent, the original is no longer needed.
if (catrec)
catrec.dispose()
return
if("filereq") //Send a file from tape if available.
if(!src.tape)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
if(isnull(data["fname"]))
src.post_status(target,"command","term_message","data","command=status&status=noparam&session=[sessionid]")
return
var/checkname = data["fname"]
var/datum/computer/file/sought = get_file_name(checkname, src.tape.root)
if(istype(sought))
src.post_file(target, "data","command=file",sought)
else
src.post_status(target,"command","term_message","data","command=status&status=nofile&session=[sessionid]")
return
if("filestore") //Store a file on tape.
if(!src.tape)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
if(src.tape.read_only || src.read_only)
src.post_status(target,"command","term_message","data","command=status&status=readonly&session=[sessionid]")
return
var/datum/computer/file/newfile = signal.data_file
if(!istype(newfile))
src.post_status(target,"command","term_message","data","command=status&status=badfile&session=[sessionid]")
return
if(findtext(newfile.name, "/"))
src.post_status(target,"command","term_message","data","command=status&status=badname&session=[sessionid]")
return
var/datum/computer/taken = get_file_name(newfile.name, src.tape.root)
if(taken)
if (istype(taken, newfile.type))
taken.dispose()
taken = null
else
src.post_status(target,"command","term_message","data","command=status&status=takenfile&session=[sessionid]")
return
var/datum/computer/file/F2 = newfile.copy_file()
if(tape.root.add_file(F2) != 1)
//qdel(F2)
F2.dispose()
F2 = null
src.post_status(target,"command","term_message","data","command=status&status=noroom&session=[sessionid]")
return
src.post_status(target,"command","term_message","data","command=status&status=success&session=[sessionid]")
return
if("delfile")
if(!src.tape)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
if(src.tape.read_only || src.read_only)
src.post_status(target,"command","term_message","data","command=status&status=readonly&session=[sessionid]")
return
if(isnull(data["fname"]))
src.post_status(target,"command","term_message","data","command=status&status=noparam&session=[sessionid]")
return
var/checkname = data["fname"]
var/datum/computer/file/sought = get_file_name(checkname, src.tape.root)
if(istype(sought))
//qdel(sought)
sought.dispose()
src.post_status(target,"command","term_message","data","command=status&status=success&session=[sessionid]")
return
src.post_status(target,"command","term_message","data","command=status&status=nofile&session=[sessionid]")
return
if("modfile")
if(!src.tape)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
if(src.tape.read_only || src.read_only)
src.post_status(target,"command","term_message","data","command=status&status=readonly&session=[sessionid]")
return
if(isnull(data["fname"]) || isnull(data["field"]))
src.post_status(target,"command","term_message","data","command=status&status=noparam&session=[sessionid]")
return
var/checkname = data["fname"]
var/datum/computer/file/sought = get_file_name(checkname, src.tape.root)
if(istype(sought))
var/newval = data["val"]
if (isnum(text2num(newval)))
newval = text2num(newval)
sought.metadata[data["field"]] = newval
src.post_status(target,"command","term_message","data","command=status&status=success&session=[sessionid]")
return
src.post_status(target,"command","term_message","data","command=status&status=nofile&session=[sessionid]")
return
if("bootreq") //Special request for a mainframe OS file + any drivers on tape.
if(!src.tape || !setup_allow_boot)
src.post_status(target,"command","term_message","data","command=status&status=notape&session=[sessionid]")
return
var/datum/computer/file/mainframe_program/os/foundos = locate() in src.tape.root.contents
if(!istype(foundos))
src.post_status(target,"command","term_message","data","command=status&status=nofile&session=[sessionid]")
return
//Stuff it in a file archive.
var/datum/computer/file/archive/archive = new
archive.max_contained_size = src.tape.file_amount
var/datum/computer/file/foundos_copy = foundos.copy_file()
archive.add_file(foundos_copy)
//Might as well stuff any other executable files hanging around too.
for(var/datum/computer/file/mainframe_program/MP in src.tape.root.contents)
if(MP == foundos)
continue
var/datum/computer/file/MP_copy = MP.copy_file()
var/success = archive.add_file(MP_copy)
if(!success)
//qdel(MP_copy)
MP_copy.dispose()
break
src.post_file(target, "data","command=file&session=[sessionid]",archive)
return
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0 //no really please stay zero
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0 //no really please stay zero
src.updateUsrDialog()
return
return
power_change()
if(!src.tape)
icon_state = "[base_icon_state]0"
return
else if(powered())
icon_state = "[base_icon_state]1"
stat &= ~NOPOWER
else
spawn(rand(0, 15))
icon_state = "[base_icon_state]-p"
stat |= NOPOWER
proc //Computer3/Mainframe loan procs are the best procs!!
is_name_invalid(string) //Check if a filename is invalid somehow
if(!string)
return 1
if(ckey(string) != replacetext(lowertext(string), " ", null))
return 1
if(findtext(string, "/"))
return 1
return 0
//Find a file with a given name
get_file_name(string, var/datum/computer/folder/check_folder)
if(!string || (!check_folder || !istype(check_folder)))
return null
var/datum/computer/taken = null
for(var/datum/computer/file/F in check_folder.contents)
var/string2 = ckey(F.name)
if(cmptext(string,string2))
taken = F
break
return taken
sync(var/target)
if (!src.tape || !target || src.stat & (NOPOWER|BROKEN))
return
var/datum/computer/file/archive/archive = new
archive.max_contained_size = src.tape.file_amount
for(var/datum/computer/file/F in src.tape.root.contents)
var/datum/computer/file/F_copy = F.copy_file()
var/success = archive.add_file(F_copy)
if(!success)
//qdel(F_copy)
F_copy.dispose()
break
src.post_file(target, "data","command=sync",archive)
return
/obj/machinery/networked/storage/bomb_tester
name = "Explosive Simulator"
desc = "A networked device designed to simulate and analyze explosions. Takes two tanks."
anchored = 1
density = 1
icon_state = "bomb_scanner0"
base_icon_state = "bomb_scanner"
setup_access_click = 0
read_only = 1
setup_drive_size = 4
setup_drive_type = /obj/item/disk/data/bomb_tester
setup_accept_tapes = 0
var/obj/item/tank/tank1 = null
var/obj/item/tank/tank2 = null
var/datum/computer/file/record/results = null
var/setup_result_name = "Bomblog"
var/obj/item/device/transfer_valve/vr/vrbomb = null
var/last_sim = 0 //Last world.time we tested a bomb.
var/sim_delay = 300 //Time until next simulation.
power_usage = 200
var/vr_landmark = "bombtest-bomb" //Landmark where the ~vr bomb~ spawns.
power_change()
if(powered())
stat &= ~NOPOWER
update_icon()
else
spawn(rand(0, 15))
stat |= NOPOWER
update_icon()
if(vrbomb)
qdel(vrbomb)
return
process()
if(stat & BROKEN)
return
..()
if(stat & NOPOWER)
return
use_power(200)
if(!host_id || !link)
return
if(src.timeout == 0)
src.post_status(host_id, "command","term_disconnect","data","timeout")
src.host_id = null
src.updateUsrDialog()
src.timeout = initial(src.timeout)
src.timeout_alert = 0
else
src.timeout--
if(src.timeout <= 5 && !src.timeout_alert)
src.timeout_alert = 1
src.post_status(src.host_id, "command","term_ping","data","reply")
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/tank))
return attack_hand(user)
else if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
boutput(user, "You [src.locked ? "secure" : "unscrew"] the maintenance panel.")
src.panel_open = !src.panel_open
src.updateUsrDialog()
return
else
..()
return
attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
if(user.lying || user.stat)
return 1
if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon))
return 1
user.machine = src
var/dat = "<html><head><title>SimUnit - \[[bank_id]]</title></head><body>"
dat += "<b>Tank One:</b> <a href='?src=\ref[src];tank=1'>[src.tank1 ? "Eject" : "None"]</a><br>"
dat += "<b>Tank Two:</b> <a href='?src=\ref[src];tank=2'>[src.tank2 ? "Eject" : "None"]</a><hr>"
dat += "<b>Simulation:</b> [vrbomb ? "IN PROGRESS" : "<a href='?src=\ref[src];simulate=1'>BEGIN</a>"]<br>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=bombtester;size=245x302")
onclose(user,"bombtester")
return
Topic(href, href_list)
if(..())
return
usr.machine = src
if (href_list["tank"])
//Ai/cyborgs cannot physically remove a tape from a room away.
if(istype(usr,/mob/living/silicon) && get_dist(src, usr) > 1)
boutput(usr, "<span style=\"color:red\">You cannot press the ejection button.</span>")
return
switch(href_list["tank"])
if("1")
if(src.tank1)
src.tank1.set_loc(src.loc)
src.tank1 = null
boutput(usr, "You remove the tank.")
if(vrbomb)
qdel(vrbomb)
else
var/obj/item/I = usr.equipped()
if (istype(I, /obj/item/tank))
usr.drop_item()
I.set_loc(src)
src.tank1 = I
boutput(usr, "You insert [I].")
src.update_icon()
if("2")
if(src.tank2)
src.tank2.set_loc(src.loc)
src.tank2 = null
boutput(usr, "You remove the tank.")
if(vrbomb)
qdel(vrbomb)
else
var/obj/item/I = usr.equipped()
if (istype(I, /obj/item/tank))
usr.drop_item()
I.set_loc(src)
src.tank2 = I
boutput(usr, "You insert [I].")
src.update_icon()
src.updateUsrDialog()
else if(href_list["simulate"])
if(!tank1 || !tank2)
boutput(usr, "<span style=\"color:red\">Both tanks are required!</span>")
return
if(last_sim && (last_sim + sim_delay > world.time))
boutput(usr, "<span style=\"color:red\">Simulator not ready, please try again later.</span>")
return
if(vrbomb)
boutput(usr, "<span style=\"color:red\">Simulation already in progress!</span>")
return
src.generate_vrbomb()
src.updateUsrDialog()
else if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
proc
generate_vrbomb()
if(!tank1 || !tank2)
return
if(vrbomb)
qdel(vrbomb)
var/obj/landmark/B = locate("landmark*[vr_landmark]")
if(!B)
playsound(src.loc, "sound/machines/buzz-sigh.ogg", 50, 1)
src.visible_message("[src] emits a somber ping.")
return
vrbomb = new
vrbomb.set_loc(B.loc)
vrbomb.anchored = 1
vrbomb.tester = src
var/obj/item/device/timer/T = new
vrbomb.attached_device = T
T.master = vrbomb
T.time = 6
var/obj/item/tank/vrtank1 = new tank1.type
var/obj/item/tank/vrtank2 = new tank2.type
vrtank1.air_contents.copy_from(tank1.air_contents)
vrtank2.air_contents.copy_from(tank2.air_contents)
vrbomb.tank_one = vrtank1
vrbomb.tank_two = vrtank2
vrtank1.master = vrbomb
vrtank1.set_loc(vrbomb)
vrtank2.master = vrbomb
vrtank2.set_loc(vrbomb)
vrbomb.update_icon()
T.timing = 1
T.c_state(1)
if (!(T in processing_items))
processing_items.Add(T)
src.last_sim = world.time
var/area/to_reset = get_area(vrbomb) //Reset the magic vr turf.
if(to_reset && to_reset.name != "Space")
for(var/turf/unsimulated/bombvr/VT in to_reset)
VT.icon_state = initial(VT.icon_state)
for(var/turf/unsimulated/wall/bombvr/VT in to_reset)
VT.icon_state = initial(VT.icon_state)
VT.opacity = 1
VT.density = 1
if(results)
//qdel(results)
results.dispose()
src.new_bomb_log()
return
new_bomb_log()
if(!tape)
return
if(results)
//qdel(results)
results.dispose()
results = new
results.name = setup_result_name
results.fields += "Test [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], 2053"
results.fields += "Atmospheric Tank #1:"
if(tank1)
var/datum/gas_mixture/environment = tank1.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
results.fields += "Tank Pressure: [round(pressure,0.1)] kPa"
if(total_moles)
var/o2_level = environment.oxygen/total_moles
var/n2_level = environment.nitrogen/total_moles
var/co2_level = environment.carbon_dioxide/total_moles
var/plasma_level = environment.toxins/total_moles
var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
results.fields += "Nitrogen: [round(n2_level*100)]%"
results.fields += "Oxygen: [round(o2_level*100)]%"
results.fields += "Carbon Dioxide: [round(co2_level*100)]%"
results.fields += "FAAE-1 (\"Plasma\"): [round(plasma_level*100)]%"
if(unknown_level > 0.01)
results.fields += "Unknown: [round(unknown_level)]%"
results.fields += "|n"
else
results.fields += "Tank Empty"
else
results.fields += "None. (Sensor Error?)"
results.fields += "Atmospheric Tank #2:"
if(tank2)
var/datum/gas_mixture/environment = tank2.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
results.fields += "Tank Pressure: [round(pressure,0.1)] kPa"
if(total_moles)
var/o2_level = environment.oxygen/total_moles
var/n2_level = environment.nitrogen/total_moles
var/co2_level = environment.carbon_dioxide/total_moles
var/plasma_level = environment.toxins/total_moles
var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
results.fields += "Nitrogen: [round(n2_level*100)]%"
results.fields += "Oxygen: [round(o2_level*100)]%"
results.fields += "Carbon Dioxide: [round(co2_level*100)]%"
results.fields += "FAAE-1 (\"Plasma\"): [round(plasma_level*100)]%"
if(unknown_level > 0.01)
results.fields += "Unknown: [round(unknown_level)]%"
results.fields += "|n"
else
results.fields += "Tank Empty"
else
results.fields += "None. (Sensor Error?)"
results.fields += "VR Bomb Monitor log:|nWaiting for monitor..."
src.tape.root.add_file( src.results )
src.sync(src.host_id)
return
//Called by our vrbomb as it heats up (Or doesn't.)
update_bomb_log(var/newdata, var/sync_log = 0)
if(!results || !newdata || !tape)
return
results.fields += newdata
if (sync_log)
src.sync(src.host_id)
return
update_icon()
src.overlays = null
if(tank1) //Update tank overlays.
src.overlays += image(src.icon,"bscanner-tank1")
if(tank2)
src.overlays += image(src.icon,"bscanner-tank2")
if(stat & BROKEN)
icon_state = "bomb_scannerb"
return
if(stat & NOPOWER)
icon_state = "bomb_scanner-p"
return
if(src.tank1 && src.tank2)
icon_state = "bomb_scanner1"
else
icon_state = "bomb_scanner0"
return
//Generic disk to hold VR bomb log
/obj/item/disk/data/bomb_tester
desc = "You shouldn't be seeing this!"
title = "TEMPBUFFER"
file_amount = 4
/obj/machinery/networked/nuclear_charge
name = "Nuclear Charge"
anchored = 1
density = 1
icon_state = "net_nuke0"
desc = "A nuclear charge used as a self-destruct device. Uh oh!"
device_tag = "PNET_NUCCHARGE"
var/timing = 0
var/time = 60
power_usage = 120
var/status_display_freq = "1435"
#define DISARM_CUTOFF 10 //Can't disarm past this point! OH NO!
mats = 80 //haha this is a bad idea
is_syndicate = 1 //^ Agreed
New()
..()
spawn(5)
src.net_id = generate_net_id(src)
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
attack_hand(mob/user as mob)
if(..() || stat & NOPOWER)
return
user.machine = src
var/dat = "<html><head><title>Nuclear Charge</title></head><body>"
dat += "<hr>[src.timing ? "SYSTEM ACTIVE" : "System Idle"]<br>Time: [src.time]<hr>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=pnetnuke;size=245x302")
onclose(user,"pnetnuke")
return
Topic(href, href_list)
if(..())
return
usr.machine = src
if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
process()
..()
if(stat & NOPOWER)
return
use_power(120)
if(!host_id || !link)
return
if(src.timeout == 0)
src.post_status(host_id, "command","term_disconnect","data","timeout")
src.host_id = null
src.updateUsrDialog()
src.timeout = initial(src.timeout)
src.timeout_alert = 0
else
src.timeout--
if(src.timeout <= 5 && !src.timeout_alert)
src.timeout_alert = 1
src.post_status(src.host_id, "command","term_ping","data","reply")
if(src.timing)
src.time--
post_display_status(src.time)
if(src.time <= 0)
outpost_destroyed = 1
src.detonate()
return
if(src.time == DISARM_CUTOFF)
world << sound('sound/misc/airraid_loop.ogg')
if(src.time <= DISARM_CUTOFF)
src.icon_state = "net_nuke2"
boutput(world, "<span style=\"color:red\"><b>[src.time] seconds until nuclear charge detonation.</b></span>")
else
src.time -= 2
src.icon_state = "net_nuke1"
src.updateUsrDialog()
else
src.icon_state = "net_nuke0"
return
power_change()
if(powered())
stat &= ~NOPOWER
if(src.timing)
if(src.time <= DISARM_CUTOFF)
src.icon_state = "net_nuke2"
else
src.icon_state = "net_nuke1"
else
src.icon_state = "net_nuke0"
else
spawn(rand(0, 15))
icon_state = "net_nuke-p"
stat |= NOPOWER
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
boutput(user, "You [src.panel_open ? "secure" : "unscrew"] the maintenance panel.")
src.panel_open = !src.panel_open
src.updateUsrDialog()
return
else
..()
receive_signal(datum/signal/signal)
if(stat & (NOPOWER) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
if(signal.transmission_method != TRANSMISSION_WIRE)
return
var/target = signal.data["sender"]
//They don't need to target us specifically to ping us.
//Otherwise, if they aren't addressing us, ignore them
if(signal.data["address_1"] != src.net_id)
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
spawn(5) //Send a reply for those curious jerks
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[src.net_number]")
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !signal.data["sender"])
return
switch(sigcommand)
if("term_connect") //Terminal interface stuff.
if(target == src.host_id)
//WHAT IS THIS, HOW COULD THIS HAPPEN??
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(2) //Sign up with the driver (if a mainframe contacted us)
src.post_status(target,"command","term_message","data","command=register&data=nucharge")
return
if("term_message","term_file")
if(target != src.host_id) //Huh, who is this?
return
var/list/data = params2list(signal.data["data"])
if(!data)
return
var/sessionid = data["session"]
if (!sessionid)
sessionid = 0
switch(data["command"])
if("status")
var/status_string = "command=n_status"
status_string += "&active=[src.timing]&timeleft=[src.time]&session=[sessionid]"
spawn(0)
src.post_status(target,"command","term_message","data",status_string)
return
if("settime")
if(src.timing) //No changing the time when we're already timing!
src.post_status(target,"command","term_message","data","command=status&status=failure&session=[sessionid]")
return
var/thetime = text2num(data["time"])
if(isnull(thetime))
src.post_status(target,"command","term_message","data","command=status&status=noparam&session=[sessionid]")
return
thetime = max( min(thetime,440), 30)
src.time = thetime
src.post_status(target,"command","term_message","data","command=status&status=success&session=[sessionid]")
return
if("act")
if(src.timing)
src.post_status(target,"command","term_message","data","command=status&status=failure&session=[sessionid]")
return
if(data["auth"] != netpass_heads)
src.post_status(target,"command","term_message","data","command=status&status=badauth&session=[sessionid]")
return
src.timing = 1
src.post_status(target,"command","term_message","data","command=status&status=success&session=[sessionid]")
var/admessage = "NUKE: Network Nuclear Charge armed for [time] seconds."
var/turf/T = get_turf(src)
if(T)
admessage += "<b> ([T.x],[T.y],[T.z])</b>"
message_admins(admessage)
//World announcement.
boutput(world, "<span style=\"color:red\"><b>Alert: Self-Destruct Sequence has been engaged.</b></span>")
boutput(world, "<span style=\"color:red\"><b>Detonation in T-[src.time] seconds!</b></span>")
return
if("deact")
if(data["auth"] != netpass_heads)
src.post_status(target,"command","term_message","data","command=status&status=badauth&session=[sessionid]")
return
if(!src.timing || src.time <= DISARM_CUTOFF)
src.post_status(target,"command","term_message","data","command=status&status=failure&session=[sessionid]")
return
src.timing = 0
src.time = max(src.time,30) //so we don't have some jerk letting it tick down to 11 and then saving it for later.
src.icon_state = "net_nuke0"
src.post_status(target,"command","term_message","data","command=status&status=success&session=[sessionid]")
//World announcement.
boutput(world, "<span style=\"color:red\"><B>Alert: Self-Destruct Sequence has been disengaged!</B></span>")
post_display_status(-1)
return
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0 //no really please stay zero
src.updateUsrDialog()
return
return
proc/detonate()
world << sound('sound/effects/kaboom.ogg')
//explosion(src, src.loc, 10, 20, 30, 35)
explosion_new(src, get_turf(src), 10000)
//dispose()
src.dispose()
return
proc/post_display_status(var/timeleft)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(status_display_freq)
if(!frequency) return
var/datum/signal/status_signal = get_free_signal()
status_signal.source = src
status_signal.transmission_method = 1
if(timeleft < 0)
status_signal.data["command"] = "blank"
else
status_signal.data["command"] = "destruct"
status_signal.data["time"] = "[timeleft]"
frequency.post_signal(src, status_signal)
#undef DISARM_CUTOFF
/obj/machinery/networked/radio
name = "Network Radio"
desc = "A networked radio interface."
anchored = 1
density = 1
icon_state = "net_radio"
device_tag = "PNET_PR6_RADIO"
//var/freq = 1219
mats = 8
var/list/frequencies = list()
var/datum/radio_frequency/radio_connection
var/transmission_range = 100 //How far does our signal reach?
var/take_radio_input = 1 //Do we echo radio signals addresed to us back to our host?
var/can_be_host = 0
power_usage = 100
var/last_ping = 0
New()
..()
src.net_id = generate_net_id(src)
spawn(5)
if (radio_controller)
frequencies["1411"] = radio_controller.add_object(src, "1411")
frequencies["1419"] = radio_controller.add_object(src, "1419")
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
attack_hand(mob/user as mob)
if(..() || (stat & (NOPOWER|BROKEN)))
return
user.machine = src
var/dat = "<html><head><title>Network Radio</title></head><body>"
dat += "Active Frequencies:<hr>"
if (frequencies.len)
var/linebreakCounter = 2
for (var/theFreq in frequencies)
dat += "[copytext(theFreq, 1, 4)].[copytext(theFreq, 4)] MHz&nbsp;&nbsp;&nbsp;"
if (linebreakCounter-- < 1)
linebreakCounter = 2
dat += "<br>"
else
dat += "<center>None</center>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "<hr>Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=net_radio;size=245x302")
onclose(user,"net_radio")
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
boutput(user, "You [src.panel_open ? "secure" : "unscrew"] the maintenance panel.")
src.panel_open = !src.panel_open
src.updateUsrDialog()
return
else
..()
Topic(href, href_list)
if(..())
return
usr.machine = src
if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
power_change()
if(powered())
icon_state = "net_radio"
stat &= ~NOPOWER
else
spawn(rand(0, 15))
icon_state = "net_radio0"
stat |= NOPOWER
process()
..()
if(stat & NOPOWER)
return
use_power(100)
if(!host_id || !link)
return
if(src.timeout == 0)
src.post_status(host_id, "command","term_disconnect","data","timeout")
src.host_id = null
src.updateUsrDialog()
src.timeout = initial(src.timeout)
src.timeout_alert = 0
else
src.timeout--
if(src.timeout <= 5 && !src.timeout_alert)
src.timeout_alert = 1
src.post_status(src.host_id, "command","term_ping","data","reply")
return
receive_signal(datum/signal/signal, transmission_type, theFreq)
if(stat & (NOPOWER) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
var/target = signal.data["sender"] ? signal.data["sender"] : signal.data["netid"]
if(!target)
return
//We care very deeply about address_1.
if(!cmptext(signal.data["address_1"], src.net_id))
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")))
spawn(5) //Send a reply for those curious jerks
if (signal.transmission_method == TRANSMISSION_RADIO)
var/datum/radio_frequency/transmit_connection = radio_controller.return_frequency("[theFreq]")
if(!transmit_connection)
return
var/datum/signal/rsignal = get_free_signal()
rsignal.source = src
rsignal.transmission_method = TRANSMISSION_RADIO
rsignal.data = list("address_1"=target, "command"="ping_reply", "device"=src.device_tag, "netid"=src.net_id, "net"="[net_number]", "sender" = src.net_id)
transmit_connection.post_signal(src, rsignal, transmission_range)
else
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[net_number]")
return
if (signal.transmission_method == TRANSMISSION_WIRE)
return
// if (!signal.data["target_device"])
// return
if(signal.transmission_method == TRANSMISSION_RADIO && src.take_radio_input)
if(!host_id)
if (can_be_host && signal.data["address_2"])
var/datum/signal/redirected_signal = get_free_signal()
redirected_signal.source = src
redirected_signal.transmission_method = TRANSMISSION_WIRE
redirected_signal.data = signal.data:Copy()
redirected_signal.data["address_1"] = redirected_signal.data["address_2"]
redirected_signal.data["sender1"] = redirected_signal.data["sender"]
redirected_signal.data["sender"] = src.net_id
src.link.post_signal(src, redirected_signal)
return
//var/list/working = signal.data:Copy()
var/datum/computer/working_file = null
if(signal.data_file)
working_file = signal.data_file.copy_file()
var/workparams = list2params(signal.data)
if(!workparams)
//qdel(working)
// if (working)
// working.len = 0
// working = null
//qdel(working_file)
if (working_file)
working_file.dispose()
return
if (theFreq)
workparams += "&_freq=[theFreq]"
spawn(2)
if(working_file)
src.post_file(src.host_id,"data",workparams,working_file)
else
src.post_status(src.host_id,"command","term_message","data",workparams)
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !target)
return
switch(sigcommand)
if("term_connect") //Terminal interface stuff.
if(target == src.host_id)
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(5) //Sign up with the driver (if a mainframe contacted us)
src.post_status(target,"command","term_message","data","command=register[(frequencies && frequencies.len) ? "&freqs=[jointext(frequencies,",")]" : ""]")
return
if("term_message","term_file")
if(target != src.host_id) //Huh, who is this?
return
var/list/data = params2list(signal.data["data"])
if(!data || !data["_freq"])// || (!data["_command"] && !data["address_1"] && data["acc_code"] != netpass_heads) ) //Either address a specific bot or have the code for all of them, buddy
src.post_status(target,"command","term_message","data","command=status&status=failure")
return
if (data["_command"])
switch (lowertext(data["_command"]))
if ("add")
var/newFreq = "[round(max(1000, min(text2num(data["_freq"]), 1500)))]"
if (newFreq && !(newFreq in frequencies))
frequencies[newFreq] = radio_controller.add_object(src, newFreq)
if ("remove")
var/newFreq = "[round(max(1000, min(text2num(data["_freq"]), 1500)))]"
if (newFreq && (newFreq in frequencies))
radio_controller.remove_object(src, newFreq)
frequencies -= newFreq
if ("clear")
for (var/x in frequencies)
radio_controller.remove_object(src, x)
frequencies.len = 0
else
src.post_status(target,"command","term_message","data","command=status&status=failure")
return
var/newFreq = round(max(1000, min(text2num(data["_freq"]), 1500)))
data -= "_freq"
if (!newFreq || !radio_controller || !data.len)
src.post_status(target,"command","term_message","data","command=status&status=failure")
return
var/datum/radio_frequency/transmit_connection = radio_controller.return_frequency("[newFreq]")
if(!transmit_connection)
src.post_status(target,"command","term_message","data","command=status&status=failure")
return
var/datum/signal/rsignal = get_free_signal()
rsignal.source = src
rsignal.transmission_method = TRANSMISSION_RADIO
rsignal.data = data.Copy()
rsignal.data["sender"] = src.net_id
spawn(0)
transmit_connection.post_signal(src, rsignal, transmission_range)
flick("net_radio-blink", src)
src.post_status(target,"command","term_message","data","command=status&status=success")
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0 //No need to be alerted about this anymore.
src.updateUsrDialog()
return
return
/obj/machinery/networked/printer
name = "Printer"
desc = "A networked printer. It's designed to print."
anchored = 1
density = 1
icon_state = "printer0"
device_tag = "PNET_PRINTDEVC"
mats = 6
var/print_id = null //Just like databanks.
var/temp_msg = "PRINTER OK" //Appears in the interface window.
var/printing = 0 //Are we printing RIGHT NOW?
var/list/print_buffer = list() //Are we waiting to print anything?
var/jam = 0 //Oh no! A jam! I hope somebody unjams us right quick!
var/blinking = 0 //Is our indicator light blinking?
var/sheets_remaining = 15 //How many blank sheets of paper do we have left?
power_usage = 200
#define MAX_SHEETS 20
#define SETUP_JAM_IGNITION 6 //How jammed do we have to be before we break down?
#define MAX_PRINTBUFFER_SIZE 10
New()
..()
if(!print_id)
src.print_id = "GENERIC"
spawn(5)
src.net_id = generate_net_id(src)
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
src.update_icon() //Update the icon
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/paper)) //Load up the printer!
if (sheets_remaining >= MAX_SHEETS)
boutput(user, "<span style=\"color:red\">The tray is full!</span>")
return
if(W:info)
boutput(user, "<span style=\"color:red\">That paper has already been used!</span>")
return
user.drop_item()
qdel(W)
boutput(user, "You load the paper into [src].")
if(!src.sheets_remaining && !src.jam)
src.clear_alert()
src.sheets_remaining++
src.updateUsrDialog()
return
else if (istype(W, /obj/item/paper_bin)) //Load up the printer!
if (sheets_remaining >= MAX_SHEETS)
boutput(user, "<span style=\"color:red\">The tray is full!</span>")
return
var/to_remove = MAX_SHEETS - sheets_remaining
if(W:amount > to_remove)
W:amount -= to_remove
boutput(user, "You load [to_remove] sheets into the tray.")
src.sheets_remaining += to_remove
else
boutput(user, "You load [W:amount] sheets into the tray.")
src.sheets_remaining += W:amount
user.drop_item()
qdel(W)
if(!src.jam)
src.clear_alert()
if(src.temp_msg == "PC LOAD LETTER")
src.temp_msg = "PRINTER OK"
src.updateUsrDialog()
return
else if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
boutput(user, "You [src.panel_open ? "secure" : "unscrew"] the maintenance panel.")
src.panel_open = !src.panel_open
src.updateUsrDialog()
return
else
return attack_hand(user)
return
attack_hand(mob/user as mob)
if(..() || (stat & (NOPOWER|BROKEN)))
return
user.machine = src
var/dat = "<html><head><title>Printer - \[[print_id]]</title></head><body>"
dat += "<hr><tt>[temp_msg]</tt><hr>"
if(jam)
dat += "<b>Printing:</b> <a href='?src=\ref[src];unjam=1'>JAMMED</a><br>"
else
dat += "<b>Printing:</b> [printing ? "YES" : "NO"]<br>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=printer;size=245x302")
onclose(user,"printer")
return
Topic(href, href_list)
if(..())
return
usr.machine = src
if (href_list["unjam"])
if(src.jam)
if(get_dist(src,usr) > 1)
boutput(usr, "You are too far away to unjam it.")
return
src.jam = 0
src.blinking = 0
src.update_icon()
src.temp_msg = "PRINTER OK"
src.updateUsrDialog()
boutput(usr, "<span style=\"color:blue\">You clear the jam.</span>")
else
boutput(usr, "There is no jam to clear.")
else if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.print_buffer.len = 0
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
process()
if(stat & BROKEN)
printing = 0
return
..()
if(stat & NOPOWER)
printing = 0
return
use_power(200)
if(!host_id || !link)
return
if(src.timeout == 0)
src.post_status(host_id, "command","term_disconnect","data","timeout")
src.host_id = null
src.updateUsrDialog()
src.timeout = initial(src.timeout)
src.timeout_alert = 0
else
src.timeout--
if(src.timeout <= 5 && !src.timeout_alert)
src.timeout_alert = 1
src.post_status(src.host_id, "command","term_ping","data","reply")
if(!printing && print_buffer.len)
src.print()
return
receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
if(signal.transmission_method != TRANSMISSION_WIRE) //No radio for us thanks
return
var/target = signal.data["sender"]
if(signal.data["address_1"] != src.net_id)
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
spawn(5)
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[net_number]")
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !signal.data["sender"])
return
switch(sigcommand)
if("term_connect") //Terminal interface stuff.
if(target == src.host_id)
//WHAT IS THIS, HOW COULD THIS HAPPEN??
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(2) //Sign up with the driver (if a mainframe contacted us)
src.post_status(target,"command","term_message","data","command=register&data=[src.print_id]")
return
if("term_message","term_file")
if(target != src.host_id) //Huh, who is this?
return
var/list/data = params2list(signal.data["data"])
if(!data)
return
switch(data["command"])
if("print")
if(!signal.data_file || (!istype(signal.data_file, /datum/computer/file/text) && !istype(signal.data_file, /datum/computer/file/record)))
src.post_status(target,"command","term_message","data","command=status&status=badfile")
return
if(print_buffer.len+1 > MAX_PRINTBUFFER_SIZE)
src.post_status(target,"command","term_message","data","command=status&status=bufferfull")
return
var/buffer_add = null
if(istype(signal.data_file, /datum/computer/file/record))
var/datum/computer/file/record/rec = signal.data_file
if (rec.fields)
buffer_add = jointext(rec.fields, "<br>")
else
buffer_add = signal.data_file:data
if(!buffer_add)
src.post_status(target,"command","term_message","data","command=status&status=badfile")
return
var/title = copytext(data["title"], 1, 64)
if (!title)
title = "printout"
buffer_add = "[title]&title;[buffer_add]"
src.print_buffer += buffer_add
return
if("clearbuffer")
src.print_buffer.len = 0
src.post_status(target,"command","term_message","data","command=status&status=success")
return
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.updateUsrDialog()
return
return
proc
print()
if(stat & (NOPOWER|BROKEN))
return 0
if(!src.host_id)
return 0
if(src.printing || !print_buffer.len)
return 0
var/print_text = print_buffer[1]
print_buffer.Cut(1,2) //Remove the first stage.
// if(!userid)
// src.post_status(src.host_id,"command","term_message","data","command=status&status=nouser")
// return 0
if(!sheets_remaining)
src.post_status(src.host_id,"command","term_message","data","command=status&status=nopaper")
return 0
if(prob(1) || src.jam)
if(jam())
return 1
src.post_status(src.host_id,"command","term_message","data","command=status&status=jam")
src.print_alert()
return 1
src.printing = 1
if(!print_text)
src.printing = 0
return 0
sheets_remaining--
flick("printer-printing",src)
playsound(src.loc, "sound/machines/printer_dotmatrix.ogg", 50, 1)
spawn(32)
var/obj/item/paper/P = new /obj/item/paper( src.loc )
var/titlepoint = findtext(print_text, "&title;",1 , 72)
if (titlepoint)
P.name = "paper- '[copytext(print_text,1,titlepoint)]'"
print_text = copytext(print_text, titlepoint+7)
else
P.name = "paper- 'Printout'"
P.info = print_text
var/formStartPoint = 1
var/formEndPoint = 0
if (!P.form_startpoints)
P.form_startpoints = list()
P.form_endpoints = list()
. = 0
while (formStartPoint)
formStartPoint = findtext(P.info, "__", formStartPoint)
if (formStartPoint)
formEndPoint = formStartPoint + 1
while (copytext(P.info, formEndPoint, formEndPoint+1) == "_")
formEndPoint++
P.form_startpoints["[.]"] = formStartPoint
P.form_endpoints["[.++]"] = formEndPoint
formStartPoint = formEndPoint+1
src.printing = 0
if(sheets_remaining <= 0)
temp_msg = "PC LOAD LETTER"
src.print_alert()
src.post_status(src.host_id,"command","term_message","data","command=status&status=lowpaper")
else
src.post_status(src.host_id,"command","term_message","data","command=status&status=success")
src.updateUsrDialog()
return 1
jam()
jam++
if(jam >= SETUP_JAM_IGNITION && !(stat & BROKEN))
stat |= BROKEN
src.visible_message("<span style=\"color:red\"><b>[src]</b> bursts into flames!</span>")
src.printing = 0
src.print_buffer.len = 0
src.update_icon()
var/datum/effects/system/spark_spread/s = unpool(/datum/effects/system/spark_spread)
s.set_up(3, 1, src)
s.start()
if(src.host_id) //welp, we're broken.
src.post_status(src.host_id,"command","term_message","data","command=status&status=thermalert")
return 1
src.printing = 0
src.print_buffer.len = 0
return 0
print_alert()
blinking = 1
src.update_icon()
playsound(src.loc, "sound/machines/buzz-sigh.ogg", 50, 1)
src.visible_message("<span style=\"color:red\">[src] pings!</span>")
return
clear_alert()
blinking = 0
src.update_icon()
return
update_icon()
src.overlays = null
if(src.jam) //Update jam overlay.
src.overlays += image(src.icon,"printer-jamoverlay")
if(stat & BROKEN)
icon_state = "printerb"
return
if(stat & NOPOWER)
icon_state = "printer-p"
return
if(src.blinking)
icon_state = "printer-blink"
else
icon_state = "printer0"
return
#undef MAX_SHEETS
#undef SETUP_JAM_IGNITION
#undef MAX_PRINTBUFFER_SIZE
/obj/machinery/networked/storage/scanner
name = "Scanner"
desc = "A networked drum scanner. It's designed to...scan documents."
anchored = 1
density = 1
icon_state = "scanner0"
//device_tag = "PNET_SCANDEVC"
var/scanning = 0 //Are we scanning RIGHT NOW?
var/obj/item/scanned_thing //Ideally, this would be a paper or photo.
var/datum/computer/file/scan_buffer
setup_access_click = 0
read_only = 1
setup_drive_size = 16
setup_drive_type = /obj/item/disk/data/bomb_tester
setup_accept_tapes = 0
power_usage = 200
New()
..()
if (!dd_hasprefix(uppertext(src.bank_id),"SC-"))
src.bank_id = "SC-[bank_id]"
attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
if(user.lying || user.stat)
return 1
if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon))
return 1
user.machine = src
var/dat = "<html><head><title>Scanner - \[[copytext(bank_id,4)]]</title></head><body>"
dat += "<b>Document:</b> <a href='?src=\ref[src];document=1'>[src.scanned_thing ? src.scanned_thing.name : "-----"]</a><br>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=scanner;size=245x302")
onclose(user,"scanner")
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/paper) || istype(W, /obj/item/photo))
if (scanned_thing)
boutput(user, "<span style=\"color:red\">There is already something in the scanner!</span>")
return
usr.drop_item()
W.set_loc(src)
scanned_thing = W
power_change()
spawn(0)
scan_document()
src.updateUsrDialog()
else
return ..()
Topic(href, href_list)
if(..())
return
usr.machine = src
if (href_list["document"])
if(istype(usr,/mob/living/silicon) && get_dist(src, usr) > 1)
boutput(usr, "<span style=\"color:red\">There is no electronic control over the actual document.</span>")
return
if (scanned_thing)
scanned_thing.set_loc(src.loc)
scanned_thing = null
else
var/obj/item/I = usr.equipped()
if (istype(I, /obj/item/paper) || istype(I, /obj/item/photo))
usr.drop_item()
I.set_loc(src)
src.scanned_thing = I
boutput(usr, "You insert [I].")
src.power_change()
src.updateUsrDialog()
src.add_fingerprint(usr)
return
power_change()
if(powered())
stat &= ~NOPOWER
src.icon_state = "scanner[!isnull(scanned_thing)]"
else
spawn(rand(0, 15))
stat |= NOPOWER
src.icon_state = "scanner[!isnull(scanned_thing)]-p"
return
process()
if(stat & BROKEN)
return
..()
if(stat & NOPOWER)
return
use_power(200)
if(!host_id || !link)
return
if(src.timeout == 0)
src.post_status(host_id, "command","term_disconnect","data","timeout")
src.host_id = null
src.updateUsrDialog()
src.timeout = initial(src.timeout)
src.timeout_alert = 0
else
src.timeout--
if(src.timeout <= 5 && !src.timeout_alert)
src.timeout_alert = 1
src.post_status(src.host_id, "command","term_ping","data","reply")
return
proc/scan_document()
if ((stat & (NOPOWER|BROKEN)) || !src.host_id || src.scanning)
return 1
if (!scanned_thing)
return 1
scanning = 1
flick("scanner-scanning",src)
sleep(20)
if (scan_buffer)
scan_buffer.dispose()
scan_buffer = null
if (istype(scanned_thing, /obj/item/paper))
var/obj/item/paper/paper_thing = scanned_thing
var/datum/computer/file/record/scanned = new
scanned.fields = process_paper_info( paper_thing.info )
scanned.name = "document"
if (src.tape.root.add_file( scanned ))
scan_buffer = scanned
src.sync(src.host_id)
playsound(src.loc, "sound/machines/ping.ogg", 50, 0)
else
scanned.dispose()
scanning = 0
return 0
else if (istype(scanned_thing, /obj/item/photo))
var/obj/item/photo/photo_thing = scanned_thing
var/datum/computer/file/image/scanned = new
scanned.ourImage = photo_thing.fullImage
scanned.name = "document"
if (src.tape.root.add_file( scanned ))
scan_buffer = scanned
src.sync(src.host_id)
playsound(src.loc, "sound/machines/ping.ogg", 50, 0)
else
scanned.dispose()
scanning = 0
return 0
scanning = 0
return 1
proc/process_paper_info(var/info)
if (!istext(info))
return null
var/list/output = list()
var/infoLength = length(info)
var/searchPosition = 1
var/findPosition = 1
while (1)
findPosition = findtext(info, "<br>", searchPosition, 0)
. = copytext(info, searchPosition, findPosition)
var/innerOpen = 1
var/innerClose = 1
while (1)
innerOpen = findtext(., "<", 1, 0)
innerClose = findtext(., ">", innerOpen, 0)
if (!innerOpen || !innerClose)
break
. = copytext(., 1, innerOpen) + copytext(., innerClose + 1)
output += .
if (!findPosition)
break
searchPosition = findPosition + 4
if (searchPosition > infoLength)
break
return output
//IR tripwire/threat analyzer.
/obj/machinery/networked/secdetector
name = "IR Detector"
desc = "An infrared tripwire and video camera coupled with a sophisticated threat-analysis system."
icon_state = "secdetector0"
device_tag = "PNET_IR_DETECT"
var/detector_id = null
var/obj/beam/ir_beam/scan_beam = null
var/online = 1 //Are we looking for anything or just sitting there?
var/state = 1 //1 idle, 2 active, 3 triggered.
var/active_time = 0 //Set >0 when active, decrement every tick, return to idle state when zero.
var/active_brightness = 0.7 //Luminosity when seeking (State == 2)
var/alert_brightness = 0.4
var/setup_beam_length = 24 //Max length of scan_beam.
var/setup_active_time = 20 //Length of time active after beam is crossed.
var/setup_alerted_time = 60 //Length of time alerted after seeing a threat.
var/area_access = access_heads //ID access required to not be considered a threat.
var/datum/light/light
New()
..() //Set detector ID if not already set, generate net ID, then update icon.
if(!detector_id)
src.detector_id = "GENERIC"
light = new /datum/light/point
light.set_color(0.20, 0.65, 0.20)
light.attach(src)
spawn(5)
src.net_id = generate_net_id(src)
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
src.update_icon()
return
/*
Del()
if (src.scan_beam)
qdel(src.scan_beam)
..()
*/
disposing()
if (src.scan_beam)
src.scan_beam.dispose()
src.scan_beam = null
if (src.link)
src.link.master = null
src.link = null
..()
attack_hand(mob/user as mob)
if(..() || (stat & (NOPOWER|BROKEN)))
return
user.machine = src
var/dat = "<html><head><title>IR Detector - \[[detector_id]]</title></head><body>"
dat += "Status: "
switch (state)
if (0)
dat += "<b>INACTIVE</b>"
if (1)
dat += "<b>IDLE</b>"
if (2)
dat += "<b>ON GUARD</b>"
if (3)
dat += "<b>ALERTED</b>"
else
dat += "<b>ERROR</b>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "<br>Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=secdetector;size=245x302")
onclose(user,"secdetector")
return
Topic(href, href_list)
if(..())
return
usr.machine = src
if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
process()
if (stat & BROKEN)
return
power_usage = max(20, 20*src.state)
..()
if (stat & NOPOWER)
return
use_power(power_usage)
if (active_time > 0)
active_time--
if (!active_time)
//src.state = src.online
src.update_icon(src.online)
switch (src.state)
if (0)
if (src.scan_beam)
//qdel(src.scan_beam)
src.scan_beam.dispose()
if (1)
if (!src.scan_beam)
var/turf/beamTurf = get_step(src, src.dir)
if (!istype(beamTurf) || beamTurf.density)
return
src.scan_beam = new /obj/beam/ir_beam(beamTurf, setup_beam_length)
src.scan_beam.master = src
src.scan_beam.dir = src.dir
return
if (2)
for (var/mob/living/C in view(7,src))
if (C.stat)
continue
if (assess_threat(C))
src.state = 3
src.active_time = src.setup_alerted_time
if (src.host_id)
src.post_status(src.host_id,"command","term_message","data","command=statechange&state=alert")
src.update_icon(3)
playsound(src.loc, "sound/machines/whistlealert.ogg", 50, 1)
return
return
return
receive_signal(datum/signal/signal)
if((stat & (NOPOWER|BROKEN)) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
if(signal.transmission_method != TRANSMISSION_WIRE) //Wired comms only.
return
var/target = signal.data["sender"]
if(signal.data["address_1"] != src.net_id)
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
spawn(5)
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[src.net_number]")
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !signal.data["sender"])
return
switch(sigcommand)
if("term_connect") //Terminal interface stuff.
if(target == src.host_id)
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(2) //Sign up with the driver (if a mainframe contacted us)
src.post_status(target,"command","term_message","data","command=register&data=[src.detector_id]")
return
if("term_message","term_file")
if(target != src.host_id) //Huh, who is this?
return
var/list/data = params2list(signal.data["data"])
if(!data)
return
switch(lowertext(data["command"]))
if("activate")
src.online = 1
src.update_icon(max(1, src.state))
if("deactivate")
src.online = 0
src.active_time = 0
src.update_icon(0)
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.updateUsrDialog()
return
return
ex_act(severity)
switch(severity)
if(1.0)
qdel(src)
return
if(2.0)
if (prob(50))
src.stat |= BROKEN
src.update_icon(0)
if(3.0)
if (prob(25))
src.stat |= BROKEN
src.update_icon(0)
else
return
power_change()
if(powered(ENVIRON))
stat &= ~NOPOWER
else
stat |= NOPOWER
src.update_icon(src.state)
proc
update_icon(var/newState = 1)
if (stat & (NOPOWER|BROKEN))
light.disable()
icon_state = "secdetector-p"
if (src.scan_beam)
//qdel(src.scan_beam)
src.scan_beam.dispose()
src.state = src.online
return
var/change = (src.state != newState)
src.state = newState
icon_state = "secdetector[src.state]"
switch (src.state)
if (2 to 3)
light.set_brightness(src.state == 2 ? src.active_brightness : src.alert_brightness)
light.enable()
if (1)
light.disable()
if (src.host_id && change)
src.post_status(src.host_id,"command","term_message","data","command=statechange&state=idle")
if (0)
light.disable()
if (src.host_id && change)
src.post_status(src.host_id,"command","term_message","data","command=statechange&state=inactive")
return
beam_crossed() //Called when anything solid crosses the beam, places us into the alert state.
if (src.state != 1)
return
//qdel(src.scan_beam)
if (src.scan_beam)
src.scan_beam.dispose()
src.active_time = src.setup_active_time
update_icon(2)
if (src.host_id)
src.post_status(src.host_id,"command","term_message","data","command=statechange&state=onguard")
playsound(src.loc, "sound/machines/whistlebeep.ogg", 50, 1)
return
assess_threat(mob/living/threat as mob) //Default scanners just check for humans without proper access and aliens.
if (issilicon(threat))
return 0
if (ismonkey(threat))
return 0
if (!ishuman(threat))
return 1
var/mob/living/carbon/human/humanThreat = threat
if (humanThreat.wear_id)
if(area_access in humanThreat.wear_id:access)
return 0
return 1
/obj/beam
var/obj/beam/next
var/limit = 48
dir = 2
layer = NOLIGHT_EFFECTS_LAYER_BASE
anchored = 1.0
flags = TABLEPASS
disposing()
if (src.next)
src.next.dispose()
src.next = null
Bumped()
src.hit()
return
HasEntered(atom/movable/AM as mob|obj)
if (istype(AM, /obj/beam) || istype(AM, /obj/critter/aberration))
return
spawn( 0 )
src.hit(AM)
return
return
proc
hit(atom/movable/AM as mob|obj)
generate_next()
if (src.limit < 1)
return
var/turf/nextTurf = get_step(src, src.dir)
if (istype(nextTurf))
if (nextTurf.density)
return
src.next = new src.type(nextTurf, src.limit-1)
//next.master = src.master
next.dir = src.dir
for (var/atom/movable/hitAtom in nextTurf)
if (hitAtom.density && !hitAtom.anchored)
src.hit(hitAtom)
continue
return
//Infrared beam for secdetector
/obj/beam/ir_beam
name = "infrared beam"
desc = "A beam of infrared light."
icon = 'icons/obj/projectiles.dmi'
icon_state = "ibeam"
invisibility = 2
dir = 2
//var/obj/beam/ir_beam/next = null
var/obj/machinery/networked/secdetector/master = null
//var/limit = 24
anchored = 1.0
flags = TABLEPASS
New(location, newLimit)
..()
if (newLimit != null)
src.limit = newLimit
spawn(3)
generate_next()
return
/*
Del()
if (src.next)
qdel(src.next)
..()
*/
disposing()
src.master = null
..()
HasEntered(atom/movable/AM as mob|obj)
if(isobserver(AM) || isintangible(AM)) return
if (istype(AM, /obj/beam))
return
spawn( 0 )
src.hit()
return
return
hit()
if (istype(src.master))
src.master.beam_crossed()
//dispose()
src.dispose()
return
generate_next()
if (src.limit < 1)
return
var/turf/nextTurf = get_step(src, src.dir)
if (istype(nextTurf))
if (nextTurf.density)
return
src.next = new /obj/beam/ir_beam(nextTurf, src.limit-1)
next:master = src.master
next.dir = src.dir
return
//Rather fancy science emitter gizmo
/obj/machinery/networked/h7_emitter
name = "HEPT emitter"
desc = "An incredibly complex and dangerous analysis tool that generates a particle-transposition beam via applied use of telecrystal properties."
icon_state = "heptemitter0"
device_tag = "PNET_HEPT_EMIT"
dir = NORTH
var/obj/beam/h7_beam/beam = null
var/list/telecrystals[5]
var/crystalCount = 0
power_usage = 0
var/setup_beam_length = 48
New()
..()
spawn(5)
src.net_id = generate_net_id(src)
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
src.update_icon()
return
/*
Del()
if (src.beam)
qdel(src.beam)
..()
*/
disposing()
if (src.beam)
src.beam.dispose()
src.beam = null
if (src.link)
src.link.master = null
src.link = null
for (var/obj/item/I in src.telecrystals)
I.set_loc(src.loc)
src.telecrystals.len = 0
..()
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/raw_material/telecrystal))
return attack_hand(user)
else if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
boutput(user, "You [src.panel_open ? "secure" : "unscrew"] the maintenance panel.")
src.panel_open = !src.panel_open
src.updateUsrDialog()
return
else
..()
return
attack_hand(mob/user as mob)
if(..() || (stat & (NOPOWER|BROKEN)))
return
user.machine = src
var/dat = "<html><head><title>HEPT Emitter</title></head><body><hr><center>Emission Crystals<br>"
if (!telecrystals)
telecrystals = new/list(5)
if (beam)
dat += "<i>Panel is locked while active</i><br><table border='1'><tr>"
else
dat += "<table border='1'><tr>"
for (var/i = 1, i <= telecrystals.len, i++)
if (src.beam)
if (isnull(telecrystals[i]))
dat += "<td style='background-color:#F80000'><font color=white>-----<font></td>"
else
dat += "<td style='background-color:#33FF00'><font color=white>+++++<font></td>"
else
if (isnull(telecrystals[i]))
dat += "<td style='background-color:#F80000'><font color=white><a href='?src=\ref[src];insert=[i]'>-----</a><font></td>"
else
dat += "<td style='background-color:#33FF00'><font color=white><a href='?src=\ref[src];eject=[i]'>EJECT</a><font></td>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "</tr></table></center><hr><br>Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=h7emitter;size=285x302")
onclose(user,"h7emitter")
return
Topic(href, href_list)
if(..())
return
usr.machine = src
src.add_fingerprint(usr)
if (href_list["insert"])
if (src.beam)
boutput(usr, "<span style=\"color:red\">The panel is locked.</span>")
return
var/targetSlot = round(text2num(href_list["insert"]))
if (!targetSlot || (targetSlot < 1) || (targetSlot > telecrystals.len))
return
if (telecrystals[targetSlot] != null)
return
var/obj/item/I = usr.equipped()
if (istype(I, /obj/item/raw_material/telecrystal))
usr.drop_item()
I.set_loc(src)
telecrystals[targetSlot] = I
crystalCount = min(crystalCount + 1, telecrystals.len)
boutput(usr, "<span style=\"color:blue\">You insert [I] into the slot.</span>")
src.updateUsrDialog()
return
else if (href_list["eject"])
if (src.beam)
boutput(usr, "<span style=\"color:red\">The panel is locked.</span>")
return
var/targetCrystal = round(text2num(href_list["eject"]))
if (!targetCrystal || (targetCrystal < 1) || (targetCrystal > telecrystals.len))
return
var/obj/item/toEject = telecrystals[targetCrystal]
if (toEject)
telecrystals[targetCrystal] = null
crystalCount = max(crystalCount - 1, 0)
toEject.set_loc(get_turf(src))
boutput(usr, "<span style=\"color:blue\">You remove [toEject] from the slot.</span>")
src.updateUsrDialog()
return
else if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
process()
if (stat & BROKEN)
return
power_usage = 200 * crystalCount
..()
if (stat & NOPOWER)
return
use_power(power_usage)
return
receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
if(signal.transmission_method != TRANSMISSION_WIRE)
return
var/target = signal.data["sender"]
if(signal.data["address_1"] != src.net_id)
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
spawn(5)
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[src.net_number]")
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !signal.data["sender"])
return
switch(sigcommand)
if("term_connect")
if(target == src.host_id)
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(2) //Sign up with the driver (if a mainframe contacted us)
src.post_status(target,"command","term_message","data","command=register&data=[isnull(src.beam) ? "0" : "1"]")
return
if("term_message","term_file")
if(target != src.host_id)
return
var/list/data = params2list(signal.data["data"])
if(!data)
return
switch(lowertext(data["command"]))
if("activate")
if (!src.beam && src.generate_beam())
src.post_status(target,"command","term_message","data","command=ack")
else
src.post_status(target,"command","term_message","data","command=nack")
if("deactivate")
if (src.beam)
//qdel(src.beam)
src.beam.dispose()
src.post_status(target,"command","term_message","data","command=ack")
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.updateUsrDialog()
return
return
power_change()
if(powered())
stat &= ~NOPOWER
src.update_icon()
else
spawn(rand(0, 15))
stat |= NOPOWER
src.update_icon()
ex_act(severity)
switch(severity)
if(1.0)
//dispose()
src.dispose()
return
if(2.0)
if (prob(50))
src.stat |= BROKEN
src.update_icon()
if(3.0)
if (prob(25))
src.stat |= BROKEN
src.update_icon()
else
return
proc
update_icon()
if (stat & (NOPOWER|BROKEN))
src.icon_state = "heptemitter-p"
if (src.beam)
//qdel(src.beam)
src.beam.dispose()
else
src.icon_state = "heptemitter[src.beam ? "1" : "0"]"
return
generate_beam()
if ((stat & (NOPOWER|BROKEN)) || !crystalCount)
return 0
if (!beam)
var/turf/beamTurf = get_step(src, src.dir)
if (!istype(beamTurf) || beamTurf.density)
return 0
src.beam = new /obj/beam/h7_beam(beamTurf, setup_beam_length, crystalCount)
src.beam.master = src
src.beam.dir = src.dir
for (var/atom/movable/hitAtom in beamTurf)
if (hitAtom.density && !hitAtom.anchored)
src.beam.hit(hitAtom)
continue
else
src.beam.update_power(src.crystalCount)
update_icon()
src.updateUsrDialog()
return 1
//Deathbeam for preceding death emitter
/obj/beam/h7_beam
name = "energy beam"
desc = "A rather threatening beam of photons!"
icon = 'icons/obj/projectiles.dmi'
icon_state = "h7beam1"
dir = 2
layer = NOLIGHT_EFFECTS_LAYER_BASE
var/power = 1 //How dangerous is this beam, anyhow? 1-5. 1-3 cause minor teleport hops and radiation damage, 4 tends to deposit people in a place separate from their stuff (or organs), and 5 tears their molecules apart
//var/obj/beam/h7_beam/next = null
var/obj/machinery/networked/h7_emitter/master = null
limit = 48
anchored = 1.0
flags = TABLEPASS
var/datum/light/light
New(location, newLimit, newPower)
..()
light = new /datum/light/point
light.attach(src)
light.set_color(0.28, 0.07, 0.58)
light.set_brightness(min(src.power, 3) / 5)
light.set_height(0.5)
light.enable()
if (newLimit != null)
src.limit = newLimit
if (newPower != null)
src.power = newPower
src.icon_state = "h7beam[min(src.power, 5)]"
spawn(2)
generate_next()
return
disposing()
if (src.master)
if (src.master.beam == src)
src.master.beam = null
src.master = null
..()
/*
Del()
if (src.next)
qdel(src.next)
..()
disposing()
if (src.next)
src.next.dispose()
src.next = null
if (src.master)
if (src.master.beam == src)
src.master.beam = null
src.master = null
..()
Bumped()
src.hit()
return
HasEntered(atom/movable/AM as mob|obj)
if (istype(AM, /obj/beam) || istype(AM, /obj/critter/aberration))
return
spawn( 0 )
src.hit(AM)
return
return
*/
proc
update_power(var/newPower)
if (!newPower)
return
src.power = max(1, newPower)
if (src.next)
src.next:update_power(newPower)
return
telehop(atom/movable/hopAtom as mob|obj, hopOffset=1, varyZ=0)
var/targetZLevel = hopAtom.z
if (varyZ)
targetZLevel = pick(1,3,4,5)
hopOffset *= 3
var/turf/lowerLeft = locate( max(hopAtom.x - hopOffset, 1), max(1, hopAtom.y - hopOffset), targetZLevel)
var/turf/upperRight = locate( min( world.maxx, hopAtom.x + hopOffset), min(world.maxy, hopAtom.y + hopOffset), targetZLevel)
if (!lowerLeft || !upperRight)
return
var/list/hopTurfs = block(lowerLeft, upperRight)
if (!hopTurfs.len)
return
playsound(hopAtom.loc, "warp", 50, 1)
do_teleport(hopAtom, pick(hopTurfs), 0)
return
hit(atom/movable/AM as mob|obj)
if (istype(AM, /mob/living))
var/mob/living/hitMob = AM
switch (src.power)
if (1 to 3)
//telehop + radiation
if (iscarbon(hitMob))
hitMob.irradiate(100)
hitMob.weakened = max(hitMob.weakened, 2)
telehop(hitMob, src.power, src.power > 2)
return
if (4)
//big telehop + might leave parts behind.
if (iscarbon(hitMob))
hitMob.irradiate(100)
random_brute_damage(hitMob, 25)
hitMob.weakened = max(hitMob.weakened, 2)
if (ishuman(hitMob) && prob(25))
var/mob/living/carbon/human/hitHuman = hitMob
if (hitHuman.organHolder && hitHuman.organHolder.brain)
var/obj/item/organ/brain/B = hitHuman.organHolder.drop_organ("Brain", hitHuman.loc)
telehop(B, 2, 0)
boutput(hitHuman, "<span style=\"color:red\"><b>You seem to have left something...behind.</b></span>")
telehop(hitMob, src.power, 1)
return
else
//Are they a human wearing the obsidian crown?
if (ishuman(hitMob) && istype(hitMob:head, /obj/item/clothing/head/void_crown))
var/obj/source = locate(/obj/dfissure_from)
if (!source)
telehop(AM, 5, 1)
return
var/area/sourceArea = get_area(source)
sourceArea.Entered(AM, AM.loc)
AM.set_loc(get_turf(source))
return
//death!!
hitMob.vaporize()
return
else if (istype(AM, /obj) && !istype(AM, /obj/effects))
telehop(AM, src.power, src.power > 2)
return
return
generate_next()
if (src.limit < 1)
return
var/turf/nextTurf = get_step(src, src.dir)
if (istype(nextTurf))
if (nextTurf.density)
return
src.next = new /obj/beam/h7_beam(nextTurf, src.limit-1, src.power)
next:master = src.master
next.dir = src.dir
for (var/atom/movable/hitAtom in nextTurf)
if (hitAtom.density && !hitAtom.anchored)
src.hit(hitAtom)
continue
return
//Generic test apparatus
/obj/machinery/networked/test_apparatus
name = "Generic Testing Apparatus"
desc = "A large device designed to facilitate...some manner... of analysis."
icon_state = "pathmanip0"
var/active = 0 //If this device is currently activated in some manner. The device will assume the icon state of setup_base_icon_state + active (1 : 0) when the icon is updated.
var/session = null
var/setup_base_icon_state = "pathmanip"
var/setup_test_id = "GENERIC" //Simple test identifier, sent upon mainframe connection.
var/setup_device_name = "Testing Apparatus" //Device name to appear in html interface
var/setup_capability_value = "E" //E for Enactor (provides a stimulus), S for Sensor (Records stimulus), or B for both.
//Don't forget to give devices unique device_tag values of the form "PNET_XXXXXXXXX"
device_tag = "PNET_TEST_APPT" //This is the device tag used to interface with the mainframe GTPIO driver.
power_usage = 200
var/dragload = 0 // can we click-drag a machinery-type artifact into this machine?
New()
..()
spawn(5)
src.net_id = generate_net_id(src)
if(!src.link)
var/turf/T = get_turf(src)
var/obj/machinery/power/data_terminal/test_link = locate() in T
if(test_link && !test_link.is_valid_master(test_link.master))
src.link = test_link
src.link.master = src
src.update_icon()
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/raw_material/telecrystal))
return attack_hand(user)
else if (istype(W, /obj/item/screwdriver))
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
boutput(user, "You [src.panel_open ? "secure" : "unscrew"] the maintenance panel.")
src.panel_open = !src.panel_open
src.updateUsrDialog()
return
else
..()
return
attack_hand(mob/user as mob)
if(..() || (stat & (NOPOWER|BROKEN)))
return
user.machine = src
var/dat = "<html><head><title>[setup_device_name]</title></head><body>"
dat += "<hr>[return_html_interface()]<hr>"
var/readout_color = "#000000"
var/readout = "ERROR"
if(src.host_id)
readout_color = "#33FF00"
readout = "OK CONNECTION"
else
readout_color = "#F80000"
readout = "NO CONNECTION"
dat += "<br>Host Connection: "
dat += "<table border='1' style='background-color:[readout_color]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
if (src.panel_open)
dat += net_switch_html()
user << browse(dat,"window=testap\ref[src];size=285x302")
onclose(user,"testap\ref[src]")
return
MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if (!istype(O,/obj/) || O.anchored) return
if (get_dist(src,O) > 1 || !isturf(O.loc)) return
if (src.dragload)
if (src.contents.len)
boutput(user, "<span style=\"color:red\">[src.name] is already loaded!</span>")
return
src.visible_message("<b>[user.name]</b> loads [O] into [src.name]!")
O.set_loc(src)
src.update_icon()
else return
MouseDrop(obj/over_object as obj, src_location, over_location)
var/mob/M = usr
if (!istype(over_object, /turf/)) return
if (!src.dragload) return
if (get_dist(src,over_object) > 1) return
if ((get_dist(src, M) > 1) || M.stat) return
if (src.active)
boutput(usr, "<span style=\"color:red\">You can't unload it while it's active!</span>")
return
for (var/obj/O in src.contents) O.set_loc(over_object)
src.visible_message("<b>[M.name]</b> unloads [src.name]!")
src.update_icon()
Topic(href, href_list)
if(..())
return
usr.machine = src
src.add_fingerprint(usr)
interface_topic(href_list)
if (href_list["reset"])
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
return
if(!host_id)
return
src.last_reset = world.time
var/rem_host = src.host_id ? src.host_id : src.old_host_id
src.host_id = null
src.old_host_id = null
src.post_status(rem_host, "command","term_disconnect")
spawn(5)
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
src.updateUsrDialog()
return
src.add_fingerprint(usr)
return
process()
if (stat & BROKEN)
return 1
..()
if (stat & NOPOWER)
return 1
use_power(200)
return 0
receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN) || !src.link)
return
if(!signal || !src.net_id || signal.encryption)
return
if(signal.transmission_method != TRANSMISSION_WIRE)
return
var/target = signal.data["sender"]
if(signal.data["address_1"] != src.net_id)
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
spawn(5)
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[src.net_number]")
return
var/sigcommand = lowertext(signal.data["command"])
if(!sigcommand || !signal.data["sender"])
return
switch(sigcommand)
if("term_connect")
if(target == src.host_id)
src.host_id = null
src.updateUsrDialog()
spawn(3)
src.post_status(target, "command","term_disconnect")
return
if(src.host_id)
return
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.host_id = target
src.old_host_id = target
if(signal.data["data"] != "noreply")
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
src.updateUsrDialog()
spawn(2) //Sign up with the driver (if a mainframe contacted us)
src.message_host("command=register&id=[src.setup_test_id]&data=[isnull(src.active) ? "0" : "1"]&capability=[setup_capability_value]")
return
if("term_message","term_file")
if(target != src.host_id)
return
var/list/data = params2list(signal.data["data"])
if(!data)
return
if (data["session"])
src.session = data["session"]
else
src.session = null
src.message_interface(data)
return
if("term_ping")
if(target != src.host_id)
return
if(signal.data["data"] == "reply")
src.post_status(target, "command","term_ping")
src.timeout = initial(src.timeout)
src.timeout_alert = 0
return
if("term_disconnect")
if(target == src.host_id)
src.host_id = null
src.timeout = initial(src.timeout)
src.timeout_alert = 0
src.updateUsrDialog()
return
return
power_change()
if(powered())
stat &= ~NOPOWER
src.update_icon()
else
spawn(rand(0, 15))
stat |= NOPOWER
src.update_icon()
ex_act(severity)
switch(severity)
if(1.0)
//dispose()
src.dispose()
return
if(2.0)
if (prob(50))
src.stat |= BROKEN
src.update_icon()
if(3.0)
if (prob(25))
src.stat |= BROKEN
src.update_icon()
else
return
proc
update_icon()
if (stat & (NOPOWER|BROKEN))
src.icon_state = "[setup_base_icon_state]-p"
else
src.icon_state = "[setup_base_icon_state][src.active ? "1" : "0"]"
return
//Generate html interface to appear in interaction window above the host connection controls
return_html_interface()
return
//The accompanying Topic to go with the html interface. Mob proximity and the reset input are already handled outside of this.
interface_topic(list/href_list)
return
//Mainframe terminal message interface. Typically, a command is contained within the "command" key in the list, all values as strings.
//Though this will generally be used by an appropriate mainframe driver, it IS possible for players to connect directly and issue their own commands
//over the terminal interface.
//Example response to "read" command:
// message_host("command=read&data=hello&format=sread")
//Example response to "info" command:
// message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Power-Charge")
message_interface(var/list/packetData)
return
//Send a terminal message to our host device
message_host(var/message, var/datum/computer/file/file)
if (!src.host_id || !message)
return
if (file)
if (src.session)
message += "&session=[src.session]"
src.post_file(src.host_id,"data",message, file)
else
if (src.session)
message += "&session=[src.session]"
src.post_status(src.host_id,"command","term_message","data",message)
return
//A test enactor that fires small objects at things. Things like artifacts.
/obj/machinery/networked/test_apparatus/pitching_machine
name = "Automatic Pitching Machine"
desc = "A large computer-controlled pitching machine."
icon_state = "pitching0"
setup_base_icon_state = "pitching"
setup_test_id = "PITCHER"
setup_device_name = "Pitching Machine"
setup_capability_value = "E"
var/throw_strength = 50
var/setup_max_objects = 10
return_html_interface()
return "<b>Pitching:</b> [src.active ? "YES" : "NO"]<br><br><b>Strength:</b> [src.throw_strength]%"
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Power")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
if (lowertext(packetData["field"]) != "power")
message_host("command=nack")
return
var/newPower = text2num(packetData["value"])
if (!isnum(newPower) || (newPower < 1) || (newPower > 100))
message_host("command=nack")
return
throw_strength = round(newPower)
message_host("command=ack")
if ("peek")
if (lowertext(packetData["field"]) != "power")
message_host("command=nack")
return
message_host("command=peeked&field=power&value=[throw_strength]")
if ("activate")
if (src.contents.len)
active = src.contents.len
message_host("command=ack")
src.update_icon()
else
message_host("command=nack")
if ("pulse")
var/duration = text2num(packetData["duration"])
if (isnum(duration))
duration = round(max(1, min(duration, 255)))
else
src.active = 0
message_host("command=nack")
return
src.active = duration
message_host("command=ack")
src.update_icon()
if ("deactivate")
active = 0
message_host("command=ack")
src.update_icon()
return
process()
if (..())
return
if (src.active)
if (src.contents.len)
src.active--
var/atom/movable/to_toss = pick(src.contents)
if (istype(to_toss))
to_toss.set_loc(src.loc)
src.visible_message("<b>[src.name]</b> launches [to_toss]!")
playsound(src.loc, "sound/effects/syringeproj.ogg", 50, 1)
to_toss.throw_at(get_edge_target_turf(src, src.dir), throw_strength, (throw_strength/50))
if (!src.active)
src.visible_message("<b>[src.name]</b> pings.")
src.active = 0
playsound(src, "sound/machines/buzz-two.ogg", 50, 1)
src.update_icon()
return
src.visible_message("<b>[src.name]</b> pings.")
src.active = 0
playsound(src, "sound/machines/chime.ogg", 50, 1)
src.update_icon()
return
attackby(var/obj/item/I, mob/user)
if (src.stat & (NOPOWER|BROKEN))
return
if (istype(I, /obj/item/grab))
return
if (I.w_class < 4)
if (src.contents.len < src.setup_max_objects)
user.drop_item()
I.set_loc(src)
user.visible_message("<b>[user]</b> loads [I] into [src.name]!")
return
else
boutput(user, "There is no room left for that!")
return
else
boutput(user, "That is far too big to fit!")
return
return ..()
/obj/machinery/networked/test_apparatus/impact_pad
name = "Impact Sensor Pad"
desc = "A floor pad that detects the physical reactions of objects placed on it."
icon_state = "impactpad0"
density = 0
setup_base_icon_state = "impactpad"
setup_test_id = "IMPACTPAD"
setup_device_name = "Impact Pad"
setup_capability_value = "S"
var/list/sensed = list("0","0")
return_html_interface()
return "<b>Detecting:</b> [src.active ? "YES" : "NO"]<br><br><b>Stand Extended:</b> [src.density ? "YES" : "NO"]"
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Stand&readinglist=Vibration Amplitude-VF,Vibration Frequency-VPS")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
if (lowertext(packetData["field"]) != "stand")
message_host("command=nack")
return
var/standval = text2num(packetData["value"])
if (standval < 0 || standval > 1)
message_host("command=nack")
return
if (standval == 1 && src.density == 0)
if (!locate(/obj/item/) in src.loc.contents)
src.visible_message("<b>[src.name]</b> extends its stand.")
src.density = 1
src.setup_base_icon_state = "impactstand"
flick("impactpad-extend",src)
src.update_icon()
playsound(src.loc, "sound/effects/pump.ogg", 50, 1)
else
src.visible_message("<span style=\"color:red\"><b>[src.name]</b> clanks and clatters noisily!</span>")
playsound(src.loc, "sound/effects/clang.ogg", 50, 1)
message_host("command=ack")
else if (standval == 0 && src.density == 1)
src.visible_message("<b>[src.name]</b> retracts its stand.")
src.density = 0
src.setup_base_icon_state = "impactpad"
flick("impactstand-retract",src)
src.update_icon()
playsound(src.loc, "sound/effects/pump.ogg", 50, 1)
message_host("command=ack")
else
message_host("command=ack")
return
if ("peek")
if (lowertext(packetData["field"]) != "stand")
message_host("command=nack")
return
message_host("command=peeked&field=stand&value=[density]")
if ("read")
if(src.sensed[1] == null || src.sensed[2] == null)
message_host("command=nack")
else
message_host("command=read&data=[src.sensed[1]],[src.sensed[2]]")
message_host("command=ack")
return
attackby(var/obj/item/I, mob/user)
if (istype(I, /obj/item/grab))
return
if (src.density)
if (locate(/obj/item/) in src.loc.contents)
boutput(user, "<span style=\"color:red\">There's already something on the stand!</span>")
return
else
user.drop_item()
I.set_loc(src.loc)
else
user.drop_item()
I.set_loc(src.loc)
return
Bumped(M as mob|obj)
if (src.density)
for (var/obj/item/I in src.loc.contents)
I.Bumped(M)
if (istype(I.artifact,/datum/artifact/) && istype(M,/obj/item/))
var/obj/item/ITM = M
var/obj/ART = I
src.impactpad_senseforce(ART, ITM)
return
bullet_act(var/obj/projectile/P)
if (src.density)
for (var/obj/item/I in src.loc.contents)
I.bullet_act(P)
switch (P.proj_data.damage_type)
if(D_KINETIC,D_PIERCING,D_SLASHING)
src.impactpad_senseforce_shot(I, P)
return
proc/impactpad_senseforce(var/obj/I, var/obj/item/M)
if (istype(I.artifact,/datum/artifact/))
var/datum/artifact/ARTDATA = I.artifact
var/stimforce = M.throwforce
src.sensed[1] = stimforce * ARTDATA.react_mpct[1]
src.sensed[2] = stimforce * ARTDATA.react_mpct[2]
if (src.sensed[2] != 0 && ARTDATA.faults.len)
src.sensed[2] += rand(ARTDATA.faults.len / 2,ARTDATA.faults.len * 2)
var/datum/artifact_trigger/AT = ARTDATA.get_trigger_by_string("force")
if (AT)
src.sensed[1] *= 5
src.sensed[2] *= 5
else
src.sensed[1] = "???"
src.sensed[2] = "0"
src.visible_message("<b>[src.name]</b> registers an impact and chimes.")
playsound(src.loc, "sound/machines/chime.ogg", 50, 1)
proc/impactpad_senseforce_shot(var/obj/I, var/datum/projectile/P)
if (istype(I.artifact,/datum/artifact/))
var/datum/artifact/ARTDATA = I.artifact
var/stimforce = P.power
src.sensed[1] = stimforce * ARTDATA.react_mpct[1]
src.sensed[2] = stimforce * ARTDATA.react_mpct[2]
if (src.sensed[2] != 0 && ARTDATA.faults.len)
src.sensed[2] += rand(ARTDATA.faults.len / 2,ARTDATA.faults.len * 2)
var/datum/artifact_trigger/AT = ARTDATA.get_trigger_by_string("force")
if (AT)
src.sensed[1] *= 5
src.sensed[2] *= 5
else
src.sensed[1] = "???"
src.sensed[2] = "0"
src.visible_message("<b>[src.name]</b> registers an impact and chimes.")
playsound(src, "sound/machines/chime.ogg", 50, 1)
/obj/machinery/networked/test_apparatus/electrobox
name = "Electrical Testing Apparatus"
desc = "A contained unit for exposing machinery to electrical currents."
icon_state = "elecbox0"
density = 1
dragload = 1
setup_base_icon_state = "elecbox"
setup_test_id = "ELEC_BOX"
setup_device_name = "Electrical Testing Apparatus"
setup_capability_value = "B"
var/voltage = 10 // runs from 1 to 100
var/wattage = 1 // runs from 1 to 50
var/timer = 0
var/list/sensed = list("???","???","100")
return_html_interface()
return "<b>Loaded:</b> [src.contents.len ? "YES" : "NO"]<br><b>Active:</b> [src.active ? "YES" : "NO"]<br><br><b>Wattage:</b> [src.wattage]W<br><b>Voltage:</b> [src.voltage]V"
update_icon()
src.overlays = null
if (src.contents.len)
src.overlays += image('icons/obj/networked.dmi', "elecbox-doors")
..()
process()
if (src.active && src.contents.len && !(stat & BROKEN))
power_usage = src.wattage * src.voltage + 220
else
power_usage = 220
if (..())
if (src.active && (stat & NOPOWER))
src.active = 0
return
if (!src.contents.len && src.active)
src.active = 0
src.visible_message("<b>[src.name]</b> buzzes angrily and stops operating!")
playsound(src.loc, "sound/machines/buzz-two.ogg", 50, 1)
src.update_icon()
return
if (src.active)
use_power(src.wattage * src.voltage) // ???????? (voltwatts????)
if (src.timer > 0)
src.timer--
if (src.timer == 0)
src.active = 0
src.timer = -1
src.visible_message("<b>[src.name]</b> emits a buzz and shuts down.")
playsound(src.loc, "sound/machines/buzz-sigh.ogg", 50, 1)
src.update_icon()
return
var/current = src.wattage * src.voltage
if (locate(/mob/living/) in src.contents)
for (var/mob/living/carbon/OUCH in src.contents)
OUCH.TakeDamage("All",0,current / 500)
else
var/obj/M = pick(src.contents)
if (istype(M.artifact,/datum/artifact/))
M.ArtifactStimulus("elec", current)
else use_power(20)
return
attackby(var/obj/item/I, mob/user)
if (src.stat & (NOPOWER|BROKEN))
return
if (istype(I, /obj/item/grab))
return // do this later when everything else is ironed out
if (!src.contents.len)
user.drop_item()
I.set_loc(src)
user.visible_message("<b>[user]</b> loads [I] into [src.name]!")
src.update_icon()
return
else
boutput(user, "There is no room left for that!")
return
return ..()
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Voltage,Wattage&readinglist=Test Amps-A,Load Impedance-Ohm,Circuit Capacity-J,Interference-%")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
if (lowertext(packetData["field"]) != "voltage" && lowertext(packetData["field"]) != "wattage")
message_host("command=nack")
return
var/pokeval = text2num(packetData["value"])
if (lowertext(packetData["field"]) == "voltage")
if (pokeval < 1 || pokeval > 100)
message_host("command=nack")
return
src.voltage = pokeval
if (lowertext(packetData["field"]) == "wattage")
if (pokeval < 1 || pokeval > 50)
message_host("command=nack")
return
src.wattage = pokeval
message_host("command=ack")
return
if ("peek")
if (lowertext(packetData["field"]) != "voltage" && lowertext(packetData["field"]) != "wattage")
message_host("command=nack")
return
if (lowertext(packetData["field"]) == "voltage")
message_host("command=peeked&field=voltage&value=[voltage]")
else if (lowertext(packetData["field"]) == "wattage")
message_host("command=peeked&field=wattage&value=[wattage]")
if ("read")
if(src.sensed[1] == null || src.sensed[2] == null || src.sensed[3] == null || !src.active)
message_host("command=nack")
else
// Electrobox - returns Returned Current, Circuit Capacity, Circuit Interference
var/current = "ERROR"
if (src.wattage > 0 && src.voltage > 0)
current = src.wattage / src.voltage
message_host("command=read&data=[current],[src.sensed[1]],[src.sensed[2]],[src.sensed[3]]")
message_host("command=ack")
if ("sense")
if (src.contents.len && src.active)
var/obj/M = pick(src.contents)
if (istype(M.artifact,/datum/artifact/))
var/datum/artifact/A = M.artifact
var/current = src.wattage / src.voltage
if (A.react_elec[1] == "equal")
src.sensed[1] = src.voltage / current
else
src.sensed[1] = src.voltage / (current * A.react_elec[1])
src.sensed[2] = A.react_elec[2]
src.sensed[3] = A.react_elec[3]
if (A.artitype == "eldritch")
src.sensed[3] += rand(-7,7)
for(var/datum/artifact_fault in A.faults)
if (prob(50))
src.sensed[1] *= rand(1.5,4.0)
else
src.sensed[1] /= rand(1.5,4.0)
src.sensed[3] += rand(-4,4)
var/datum/artifact_trigger/AT = A.get_trigger_by_string("elec")
if (AT)
src.sensed[3] *= 3
else
src.sensed[1] = "???"
src.sensed[2] = "???"
src.sensed[3] = "100"
else message_host("command=nack")
// Electrobox - returns Returned Current, Circuit Capacity, Circuit Interference
if ("activate")
if (src.contents.len && !src.active)
active = 1
src.timer = -1
message_host("command=ack")
src.update_icon()
else
message_host("command=nack")
if ("pulse")
var/duration = text2num(packetData["duration"])
if (isnum(duration) && !src.active)
duration = round(max(1, min(duration, 255)))
else
src.active = 0
message_host("command=nack")
return
src.active = 1
src.timer = duration
message_host("command=ack")
src.update_icon()
if ("deactivate")
src.active = 0
src.timer = -1
message_host("command=ack")
src.update_icon()
return
/obj/machinery/networked/test_apparatus/xraymachine
name = "X-Ray Scanner"
desc = "Performs radiography on objects to determine their structure."
icon_state = "xray0"
density = 1
dragload = 1
setup_base_icon_state = "xray"
setup_test_id = "X_RAY"
setup_device_name = "X-Ray Scanner"
setup_capability_value = "B"
var/radstrength = 1 // 1 to 10
var/list/sensed = list("???","???","???","NO","NONE")
// X-ray - returns Density, Structural Consistency, Structural Integrity
return_html_interface()
return "<b>Loaded:</b> [src.contents.len ? "YES" : "NO"]<br><b>Active:</b> [src.active ? "YES" : "NO"]<br><br>Radiation Strength:</b> [src.radstrength * 10]%"
update_icon()
src.overlays = null
if (src.contents.len) src.overlays += image('icons/obj/networked.dmi', "xray-lid")
..()
attackby(var/obj/item/I, mob/user)
if (src.stat & (NOPOWER|BROKEN))
return
if (istype(I, /obj/item/grab))
return
if (!src.contents.len)
user.drop_item()
I.set_loc(src)
user.visible_message("<b>[user]</b> loads [I] into [src.name]!")
src.update_icon()
return
else
boutput(user, "There is no room left for that!")
return
return ..()
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Radstrength&readinglist=Radiation Strength-%,Object Density-p,Structural Consistency-%,Structural Integrity-%,Radiation Response,Special Features of Object")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
var/pokeval = text2num(packetData["value"])
if (lowertext(packetData["field"]) == "radstrength")
if (pokeval < 1 || pokeval > 10)
message_host("command=nack")
return
src.radstrength = round(pokeval)
message_host("command=ack")
return
message_host("command=nack")
return
if ("peek")
if (lowertext(packetData["field"]) != "radstrength")
message_host("command=nack")
return
message_host("command=peeked&field=radstrength&value=[radstrength]")
if ("read")
if(src.sensed[1] == null || src.sensed[2] == null || src.sensed[3] == null || src.sensed[4] == null || src.sensed[5] == null || src.active)
message_host("command=nack")
else
// X-ray - returns Density, Structural Consistency, Structural Integrity, Response
message_host("command=read&data=[src.radstrength * 10],[src.sensed[1]],[src.sensed[2]],[src.sensed[3]],[src.sensed[4]],[src.sensed[5]]")
message_host("command=ack")
if ("sense","deactivate")
message_host("command=nack")
if ("activate", "pulse")
if (src.contents.len && !src.active)
message_host("command=ack")
active = 1
src.update_icon()
src.visible_message("<b>[src.name]</b> begins to operate.")
if (narrator_mode)
playsound(src.loc, 'sound/vox/genetics.ogg', 50, 1)
else if (prob(1))
playsound(src.loc, 'sound/vox/genetics.ogg', 50, 1)
else
playsound(src.loc, 'sound/machines/genetics.ogg', 50, 1)
if (src.contents.len)
var/obj/M = pick(src.contents)
if (istype(M.artifact,/datum/artifact/))
var/datum/artifact/A = M.artifact
// Density
var/density = A.react_xray[1]
if (A.artitype == "eldritch" && prob(33))
var/randval = rand(-2,6)
if (prob(50))
density *= rand(-2,6)
else
density /= (randval == 0 ? 1 : randval)
if (A.artitype == "eldritch" && prob(6))
density = 666
src.sensed[1] = density
// Structural Consistency
var/consistency = A.react_xray[2]
if (consistency > 85 && A.artitype == "martian")
consistency = 85
if (A.artitype == "eldritch" && prob(20))
consistency *= rand(2,6)
src.sensed[2] = consistency
// Structural Integrity
var/integrity = A.react_xray[3]
for (var/datum/artifact_fault in A.faults)
integrity -= 7
if (A.artitype == "eldritch" && prob(33))
if (prob(50)) integrity *= rand(2,4)
else integrity /= rand(2,4)
if (integrity > 80 && A.artitype == "martian")
integrity = 80
if (integrity < 0) src.sensed[3] = "< 1"
else src.sensed[3] = integrity
// Radiation Response
var/responsive = A.react_xray[4]
if (A.artitype == "martian")
responsive -= 3
if (A.artitype == "eldritch" && prob(33))
responsive += rand(-2,2)
if (responsive <= src.radstrength)
src.sensed[4] = "WEAK RESPONSE"
else
src.sensed[4] = "NO RESPONSE"
var/datum/artifact_trigger/AT = A.get_trigger_by_string("radiate")
if (AT)
if (src.sensed[4] == "WEAK RESPONSE")
src.sensed[4] = "POWERFUL RESPONSE"
else
src.sensed[4] = "STRONG RESPONSE"
// Special Features
src.sensed[5] = A.react_xray[5]
if (A.artitype == "martian")
src.sensed[5] += ",ORGANIC"
if (M.contents.len)
src.sensed[5] += ",CONTAINS OTHER OBJECT"
if (A.artitype == "eldritch" && prob(6))
src.sensed[5] = "ERROR"
M.ArtifactStimulus("radiate", src.radstrength)
else
src.sensed[1] = "???"
src.sensed[2] = "???"
src.sensed[3] = "???"
src.sensed[4] = "NO"
src.sensed[5] = "NONE"
spawn(50)
src.visible_message("<b>[src.name]</b> finishes working and shuts down.")
playsound(src, "sound/machines/chime.ogg", 50, 1)
active = 0
src.update_icon()
else
message_host("command=nack")
return
/obj/machinery/networked/test_apparatus/heater
name = "Heater Plate"
desc = "Exposes artifacts to heat and measures their reaction."
icon_state = "heater0"
density = 0
var/image/heat_overlay = null
setup_base_icon_state = "heater"
setup_test_id = "HEATER"
setup_device_name = "Heater Plate"
setup_capability_value = "B"
var/temptarget = 310 // 200 to 400
var/temperature = 310 // the plate's actual current temperature
var/stopattarget = 0 // pulse mode - do we automatically stop when we hit the target temp?
var/list/sensed = list("UNKNOWN","UNKNOWN","UNKNOWN")
// Heat Plate - returns Artifact Temp, Heat Response, Cold Response
power_usage = 200
New()
..()
heat_overlay = image('icons/obj/networked.dmi', "")
return_html_interface()
return "<b>Active:</b> [src.active ? "YES" : "NO"]<br><br>Target Temperature:</b> [src.temptarget]K<br>Current Temperature:</b> [src.temperature]K"
update_icon()
src.overlays = null
switch(src.temperature)
if (371 to INFINITY)
heat_overlay.icon_state = "heat+3"
if (351 to 370)
heat_overlay.icon_state = "heat+2"
if (331 to 350)
heat_overlay.icon_state = "heat+1"
if (270 to 289)
heat_overlay.icon_state = "heat-1"
if (250 to 269)
heat_overlay.icon_state = "heat-2"
if (230 to -99)
heat_overlay.icon_state = "heat-3"
else
heat_overlay.icon_state = ""
src.overlays += heat_overlay
..()
attackby(var/obj/item/I, mob/user)
if (istype(I, /obj/item/grab))
return
if (locate(/obj/) in src.loc.contents)
..()
else
user.drop_item()
I.set_loc(src.loc)
return
process()
if (src.active)
power_usage = 280
else
power_usage = 200
if (..())
return
if (src.active)
use_power(80)
if (src.temperature < src.temptarget)
src.temperature += 5
else if (src.temperature > src.temptarget)
src.temperature -= 5
if (src.temperature != 310)
for (var/obj/M in src.loc.contents)
if (istype(M.artifact,/datum/artifact/))
M.ArtifactStimulus("heat", temperature)
if (src.stopattarget && src.temperature == src.temptarget)
src.active = 0
src.visible_message("<b>[src.name]</b> reaches its target temperature and shuts down.")
playsound(src.loc, "sound/machines/chime.ogg", 50, 1)
else
use_power(20)
if (src.temperature > 310)
src.temperature--
else if (src.temperature < 310)
src.temperature++
src.update_icon()
return
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Temptarget,Temperature&readinglist=Target Temperature-K,Current Temperature-K,Artifact Temperature-K,Object Responds to Temperature,Details")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
if (lowertext(packetData["field"]) != "temptarget")
message_host("command=nack")
return
var/pokeval = text2num(packetData["value"])
if (pokeval < 200 || pokeval > 400)
message_host("command=nack")
return
src.temptarget = pokeval
message_host("command=ack")
return
if ("peek")
if (lowertext(packetData["field"]) == "temperature")
message_host("command=peeked&field=temperature&value=[temperature]")
else if (lowertext(packetData["field"]) == "temptarget")
message_host("command=peeked&field=temptarget&value=[temptarget]")
else
message_host("command=nack")
if ("read")
if(src.sensed[1] == null || src.sensed[2] == null || src.sensed[3] == null)
message_host("command=nack")
else
// Heat Plate - returns Artifact Temp, Heat Response, Cold Response
message_host("command=read&data=[src.temptarget],[src.temperature],[src.sensed[1]],[src.sensed[2]],[src.sensed[3]]")
message_host("command=ack")
if ("sense")
// Heat Plate - returns Artifact Temp, Heat Response, Cold Response
var/obj/M = null
for(var/obj/M2 in src.loc.contents)
if (M2 == src)
continue
if (M2.artifact)
M = M2
break
if (!M)
src.sensed[1] = "ERROR"
src.sensed[2] = "ERROR"
src.sensed[3] = "ERROR"
else
if (istype(M.artifact,/datum/artifact/))
var/datum/artifact/A = M.artifact
// Artifact Temperature
var/tempdiff = (src.temperature - 310) * A.react_heat[1]
src.sensed[1] = "[310 + tempdiff]"
// Response
var/datum/artifact_trigger/AT_H = A.get_trigger_by_path(/datum/artifact_trigger/heat)
var/datum/artifact_trigger/AT_C = A.get_trigger_by_path(/datum/artifact_trigger/cold)
if ((istype(AT_H) && src.temperature > 310) || (istype(AT_C) && src.temperature < 310))
src.sensed[2] = "YES"
else
src.sensed[2] = "NO"
src.sensed[3] = A.react_heat[2]
else
src.sensed[1] = "???"
src.sensed[2] = "NO"
src.sensed[3] = "NONE"
message_host("command=ack")
if ("activate")
src.active = 1
src.stopattarget = 0
message_host("command=ack")
src.update_icon()
if ("pulse")
var/duration = text2num(packetData["duration"])
if (isnum(duration))
temptarget = duration
else
message_host("command=nack")
return
src.stopattarget = 1
src.active = 1
message_host("command=ack")
src.update_icon()
if ("deactivate")
src.active = 0
message_host("command=ack")
src.update_icon()
return
/* Finish this later when I can think of how exactly to implement it
/obj/machinery/networked/test_apparatus/laserE
name = "Laser Emitter"
desc = "Emits a laser beam for artifact testing purposes."
icon_state = "laserE0"
density = 1
setup_base_icon_state = "laserE"
setup_test_id = "LASER_E"
setup_device_name = "Laser Emitter"
setup_capability_value = "E"
var/strength = 1 // 1 to 5?
var/duration = -1 // seconds
power_usage = 200
return_html_interface()
return "<b>Active:</b> [src.active ? "YES" : "NO"]<br><br>Laser Strength:</b> [src.strength]"
process()
if (active)
power_usage = 200 + src.strength * 500
else
power_usage = 200
if (..())
return
if (src.active)
use_power(src.strength * 500)
src.duration--
if (src.duration == 0)
src.active = 0
else
use_power(20)
return
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=Strength,Duration")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
if (lowertext(packetData["field"]) != "strength")
message_host("command=nack")
return
var/pokeval = text2num(packetData["value"])
if (pokeval < 1 || pokeval > 5)
message_host("command=nack")
return
src.strength = pokeval
message_host("command=ack")
return
if ("peek")
if (lowertext(packetData["field"]) != "strength")
message_host("command=nack")
return
if (lowertext(packetData["field"]) == "strength") message_host("command=peeked&value=[src.strength]")
if ("activate")
if (!src.active)
src.active = 1
src.duration = -1
message_host("command=ack")
src.update_icon()
else message_host("command=nack")
if ("pulse")
var/timer = text2num(packetData["duration"])
if (!src.active)
if (isnum(duration)) src.duration = timer
else message_host("command=nack")
else message_host("command=nack")
src.active = 1
message_host("command=ack")
src.update_icon()
if ("deactivate")
src.active = 0
src.duration = -1
message_host("command=ack")
src.update_icon()
return
/obj/machinery/networked/test_apparatus/laserR
name = "Laser Reciever"
desc = "Catches a laser beam and analyses how it was changed since emission."
icon_state = "laserR0"
density = 1
setup_base_icon_state = "laserR"
setup_test_id = "LASER_R"
setup_device_name = "Laser Reciever"
setup_capability_value = "S"
var/list/sensed = list(null,null)*/
/obj/machinery/networked/test_apparatus/gas_sensor
icon_state = "gsensor1"
name = "Gas Sensor"
desc = "A device that detects the composition of the air nearby."
density = 0
dragload = 0
setup_base_icon_state = "gsensor"
setup_test_id = "GAS_0"
setup_device_name = "Gas Sensor"
setup_capability_value = "S"
active = 1
var/setup_tag = null
//Pressure, Temperature, O2, N2, CO2, Plasma, Misc
var/list/sensed = list(null, null, null, null, null, null, null)
New()
..()
if (src.setup_tag)
setup_test_id = "GAS_[uppertext( copytext(src.setup_tag,1,9) )]"
return_html_interface()
return "<b>Active:</b> [src.active ? "YES" : "NO"]"
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=None&readinglist=Pressure-kPa,Temperature-K,Oxygen-%,Nitrogen-%,CO2-%,FAAE_1-%,Misc-%")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke","peek")
message_host("command=nack")
if ("sense")
var/datum/gas_mixture/air_sample = return_air()
var/total_moles = max(air_sample.total_moles(), 1)
if (air_sample)
sensed[1] = round(air_sample.return_pressure(), 0.1)
sensed[2] = round(air_sample.temperature, 0.1)
sensed[3] = round(100*air_sample.oxygen/total_moles, 0.1)
sensed[4] = round(100*air_sample.nitrogen/total_moles, 0.1)
sensed[5] = round(100*air_sample.carbon_dioxide/total_moles, 0.1)
sensed[6] = round(100*air_sample.toxins/total_moles, 0.1)
var/tgmoles = 0
if(air_sample.trace_gases && air_sample.trace_gases.len)
for(var/datum/gas/trace_gas in air_sample.trace_gases)
tgmoles += trace_gas.moles
sensed[7] = round(100*tgmoles/total_moles, 0.1)
else
for (var/i = 1, i <= sensed.len, i++)
sensed[i] = "???"
message_host("command=ack")
if ("read")
if (!sensed || sensed.len < 7)
message_host("command=nack")
return
for (var/i=1,i<=sensed.len,i++)
if (sensed[i] == null)
message_host("command=nack")
return
message_host("command=read&data=[sensed[1]],[sensed[2]],[sensed[3]],[sensed[4]],[sensed[5]],[sensed[6]],[sensed[7]]")
message_host("command=ack")
return
/obj/machinery/networked/test_apparatus/mechanics
name = "IO Block"
desc = "An 8 input, 8 output interface for mechanics components."
icon_state = "generic0"
density = 1
dragload = 0
setup_base_icon_state = "generic"
setup_test_id = "PIO"
setup_device_name = "IO Block"
setup_capability_value = "B"
var/output_word = 0
var/input_word = 0
var/buffered_input_word = 0
var/pulses = 0 //If nonzero, we will pulse this many times and then deactivate
var/tmp/datum/mechanicsMessage/lastSignal = null
power_usage = 200
New()
..()
mechanics = new(src)
mechanics.master = src
mechanics.addInput("input 0", "fire0")
mechanics.addInput("input 1", "fire1")
mechanics.addInput("input 2", "fire2")
mechanics.addInput("input 3", "fire3")
mechanics.addInput("input 4", "fire4")
mechanics.addInput("input 5", "fire5")
mechanics.addInput("input 6", "fire6")
mechanics.addInput("input 7", "fire7")
return_html_interface()
. = {"<b>INPUT STATUS</b>
<table border='1' style='color:#FFFFFF'>
<tr>"}
for (var/bit = 7, bit >= 0, bit--)
. += "<td id='bit[bit]'> <div align=left style='background-color=[input_word & (1<<bit) ? "#33FF00" : "#F80000"]'>[bit]</div></td>"
. += "</tr></table>"
message_interface(var/list/packetData)
switch (lowertext(packetData["command"]))
if ("info")
message_host("command=info&id=[src.setup_test_id]&capability=[setup_capability_value]&status=[src.active ? "1" : "0"]&valuelist=OutputWord&readinglist=Input Line")
if ("status")
message_host("command=status&data=[src.active ? "1" : "0"]")
if ("poke")
. = lowertext(packetData["field"])
if (. == "outputword")
var/pokeval = text2num(packetData["value"])
if (pokeval < 0 || pokeval > 255)
message_host("command=nack")
return
src.output_word = pokeval
message_host("command=ack")
else if (copytext(.,1,7) == "output")
. = round( text2num(copytext(.,7)) )
if (!isnum(.) || . < 0 || . > 7)
message_host("command=nack")
return
if (packetData["value"] == "1")
output_word |= 1<<.
else if (packetData["value"] == "0")
output_word &= ~(1<<.)
else
message_host("command=nack")
return
message_host("command=ack")
else
message_host("command=nack")
return
return
if ("peek")
if (lowertext(packetData["field"]) == "outputword")
message_host("command=peeked&field=outputword&value=[output_word]")
message_host("command=nack")
if ("read")
message_host("command=read&data=[buffered_input_word ? "TRUE" : "FALSE"]")
message_host("command=ack")
if ("sense")
buffered_input_word = input_word
message_host("command=ack")
if ("activate")
src.pulses = 0
src.active = 1
message_host("command=ack")
src.update_icon()
if ("pulse")
var/duration = text2num(packetData["duration"])
if (isnum(duration))
src.pulses = max(0, min(round(duration), 255))
else
message_host("command=nack")
return
src.active = 1
message_host("command=ack")
src.update_icon()
if ("deactivate")
src.active = 0
src.pulses = 0
message_host("command=ack")
src.update_icon()
return
process()
if (active)
power_usage = 300
else
power_usage = 200
if (..())
return
if (src.active)
use_power(100)
if (lastSignal)
lastSignal.signal = "[output_word]"
mechanics.fireOutgoing(lastSignal)
lastSignal = null
else
mechanics.fireOutgoing(mechanics.newSignal("[output_word]"))
if (pulses)
pulses--
if (pulses < 1)
active = 0
else
use_power(20)
return
proc
fire0(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 1
else
input_word &= ~1
lastSignal = anInput
fire1(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 2
else
input_word &= ~2
lastSignal = anInput
fire2(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 4
else
input_word &= ~4
lastSignal = anInput
fire3(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 8
else
input_word &= ~8
lastSignal = anInput
fire4(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 16
else
input_word &= ~16
lastSignal = anInput
fire5(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 32
else
input_word &= ~32
fire6(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 64
else
input_word &= ~64
lastSignal = anInput
fire7(var/datum/mechanicsMessage/anInput)
if (anInput && anInput.isTrue())
input_word |= 128
else
input_word &= ~128
lastSignal = anInput