//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() . = "
Configuration Switches:
" for (var/i = 8, i >= 1, i >>= 1) var/styleColor = (net_number & i) ? "#60B54A" : "#CD1818" . += "" . += "
##
" 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 = "Databank - \[[bank_id]]" dat += "[capitalize(src.setup_tape_tag)]: [src.tape ? "Eject" : "--------"]
" 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 += "
[readout]

" dat += "Reset Connection
" dat += "
Read Only: " if(!src.read_only) dat += "YES NO
" else dat += "YES NO
" 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, "The cover is screwed shut.") 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, "You cannot press the ejection button.") 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, "There is already a [src.setup_tape_tag] in the drive.") return if (src.locked) boutput(user, "The cover is screwed shut.") 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 = "SimUnit - \[[bank_id]]" dat += "Tank One: [src.tank1 ? "Eject" : "None"]
" dat += "Tank Two: [src.tank2 ? "Eject" : "None"]
" dat += "Simulation: [vrbomb ? "IN PROGRESS" : "BEGIN"]
" 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 += "
[readout]

" dat += "Reset Connection
" 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, "You cannot press the ejection button.") 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, "Both tanks are required!") return if(last_sim && (last_sim + sim_delay > world.time)) boutput(usr, "Simulator not ready, please try again later.") return if(vrbomb) boutput(usr, "Simulation already in progress!") 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 = "Nuclear Charge" dat += "
[src.timing ? "SYSTEM ACTIVE" : "System Idle"]
Time: [src.time]
" 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 += "
[readout]

" dat += "Reset Connection
" 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, "[src.time] seconds until nuclear charge detonation.") 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 += " ([T.x],[T.y],[T.z])" message_admins(admessage) //World announcement. boutput(world, "Alert: Self-Destruct Sequence has been engaged.") boutput(world, "Detonation in T-[src.time] seconds!") 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, "Alert: Self-Destruct Sequence has been disengaged!") 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 = "Network Radio" dat += "Active Frequencies:
" if (frequencies.len) var/linebreakCounter = 2 for (var/theFreq in frequencies) dat += "[copytext(theFreq, 1, 4)].[copytext(theFreq, 4)] MHz   " if (linebreakCounter-- < 1) linebreakCounter = 2 dat += "
" else dat += "
None
" 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 += "
[readout]

" dat += "Reset Connection
" 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, "The tray is full!") return if(W:info) boutput(user, "That paper has already been used!") 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, "The tray is full!") 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 = "Printer - \[[print_id]]" dat += "
[temp_msg]
" if(jam) dat += "Printing: JAMMED
" else dat += "Printing: [printing ? "YES" : "NO"]
" 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 += "
[readout]

" dat += "Reset Connection
" 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, "You clear the jam.") 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, "
") 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("[src] bursts into flames!") 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("[src] pings!") 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 = "Scanner - \[[copytext(bank_id,4)]]" dat += "Document: [src.scanned_thing ? src.scanned_thing.name : "-----"]
" 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 += "
[readout]

" dat += "Reset Connection
" 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, "There is already something in the scanner!") 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, "There is no electronic control over the actual document.") 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, "
", 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 = "IR Detector - \[[detector_id]]" dat += "Status: " switch (state) if (0) dat += "INACTIVE" if (1) dat += "IDLE" if (2) dat += "ON GUARD" if (3) dat += "ALERTED" else dat += "ERROR" 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 += "
[readout]

" dat += "Reset Connection
" 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 = "HEPT Emitter
Emission Crystals
" if (!telecrystals) telecrystals = new/list(5) if (beam) dat += "Panel is locked while active
" else dat += "
" for (var/i = 1, i <= telecrystals.len, i++) if (src.beam) if (isnull(telecrystals[i])) dat += "" else dat += "" else if (isnull(telecrystals[i])) dat += "" else dat += "" 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 += "
-----+++++-----EJECT


Host Connection: " dat += "
[readout]

" dat += "Reset Connection
" 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, "The panel is locked.") 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, "You insert [I] into the slot.") src.updateUsrDialog() return else if (href_list["eject"]) if (src.beam) boutput(usr, "The panel is locked.") 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, "You remove [toEject] from the slot.") 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, "You seem to have left something...behind.") 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 = "[setup_device_name]" dat += "
[return_html_interface()]
" 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 += "
[readout]

" dat += "Reset Connection
" 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, "[src.name] is already loaded!") return src.visible_message("[user.name] 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, "You can't unload it while it's active!") return for (var/obj/O in src.contents) O.set_loc(over_object) src.visible_message("[M.name] 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 "Pitching: [src.active ? "YES" : "NO"]

Strength: [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("[src.name] 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("[src.name] pings.") src.active = 0 playsound(src, "sound/machines/buzz-two.ogg", 50, 1) src.update_icon() return src.visible_message("[src.name] 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("[user] 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 "Detecting: [src.active ? "YES" : "NO"]

Stand Extended: [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("[src.name] 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("[src.name] clanks and clatters noisily!") playsound(src.loc, "sound/effects/clang.ogg", 50, 1) message_host("command=ack") else if (standval == 0 && src.density == 1) src.visible_message("[src.name] 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, "There's already something on the stand!") 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("[src.name] 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("[src.name] 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 "Loaded: [src.contents.len ? "YES" : "NO"]
Active: [src.active ? "YES" : "NO"]

Wattage: [src.wattage]W
Voltage: [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("[src.name] 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("[src.name] 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("[user] 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 "Loaded: [src.contents.len ? "YES" : "NO"]
Active: [src.active ? "YES" : "NO"]

Radiation Strength: [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("[user] 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("[src.name] 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("[src.name] 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 "Active: [src.active ? "YES" : "NO"]

Target Temperature: [src.temptarget]K
Current Temperature: [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("[src.name] 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 "Active: [src.active ? "YES" : "NO"]

Laser Strength: [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 "Active: [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() . = {"INPUT STATUS "} for (var/bit = 7, bit >= 0, bit--) . += "" . += "
[bit]
" 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