/obj/machinery/computer/cloning name = "cloning console" desc = "Used to clone people and manage DNA." icon_screen = "dna" icon_keyboard = "med_key" circuit = /obj/item/weapon/circuitboard/computer/cloning req_access = list(access_heads) //Only used for record deletion right now. var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning. var/obj/machinery/clonepod/pod1 = null //Linked cloning pod. var/temp = "Inactive" var/scantemp_ckey var/scantemp = "Ready to Scan" var/menu = 1 //Which menu screen to display var/list/records = list() var/datum/data/record/active_record = null var/obj/item/weapon/disk/data/diskette = null //Mostly so the geneticist can steal everything. var/loading = 0 // Nice loading text var/autoprocess = 0 light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/cloning/New() ..() spawn(5) updatemodules() /obj/machinery/computer/cloning/process() if(!(scanner && pod1 && autoprocess)) return if(!pod1.is_operational()) return if(scanner.occupant && (scanner.scan_level > 2)) scan_mob(scanner.occupant) if(!(pod1.occupant || pod1.mess) && (pod1.efficiency > 5)) for(var/datum/data/record/R in records) if(!(pod1.occupant || pod1.mess)) if(pod1.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"])) records -= R /obj/machinery/computer/cloning/proc/updatemodules() src.scanner = findscanner() src.pod1 = findcloner() if (!isnull(src.pod1)) src.pod1.connected = src // Some variable the pod needs /obj/machinery/computer/cloning/proc/findscanner() var/obj/machinery/dna_scannernew/scannerf = null // Loop through every direction for(dir in list(NORTH,EAST,SOUTH,WEST)) // Try to find a scanner in that direction scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, dir)) // If found and operational, return the scanner if (!isnull(scannerf) && scannerf.is_operational()) return scannerf // If no scanner was found, it will return null return null /obj/machinery/computer/cloning/proc/findcloner() var/obj/machinery/clonepod/podf = null for(dir in list(NORTH,EAST,SOUTH,WEST)) podf = locate(/obj/machinery/clonepod, get_step(src, dir)) if (!isnull(podf) && podf.is_operational()) return podf /obj/machinery/computer/cloning/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES if (!src.diskette) if(!user.drop_item()) return W.loc = src src.diskette = W user << "You insert [W]." playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) src.updateUsrDialog() else return ..() /obj/machinery/computer/cloning/attack_hand(mob/user) if(..()) return interact(user) /obj/machinery/computer/cloning/interact(mob/user) user.set_machine(src) add_fingerprint(user) if(..()) return updatemodules() var/dat = "" dat += "Refresh" if(scanner && pod1 && ((scanner.scan_level > 2) || (pod1.efficiency > 5))) if(!autoprocess) dat += "Autoprocess" else dat += "Stop autoprocess" else dat += "Autoprocess" dat += "

Cloning Pod Status

" dat += "
[temp] 
" switch(src.menu) if(1) // Modules if (isnull(src.scanner) || isnull(src.pod1)) dat += "

Modules

" //dat += "Reload Modules" if (isnull(src.scanner)) dat += "ERROR: No Scanner detected!
" if (isnull(src.pod1)) dat += "ERROR: No Pod detected
" // Scanner if (!isnull(src.scanner)) dat += "

Scanner Functions

" dat += "
" if (!src.scanner.occupant) dat += "Scanner Unoccupied" else if(loading) dat += "[src.scanner.occupant] => Scanning..." else if (src.scanner.occupant.ckey != scantemp_ckey) scantemp = "Ready to Scan" scantemp_ckey = src.scanner.occupant.ckey dat += "[src.scanner.occupant] => [scantemp]" dat += "
" if (src.scanner.occupant) dat += "Start Scan" dat += "
[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]" else dat += "Start Scan" // Database dat += "

Database Functions

" if (src.records.len && src.records.len > 0) dat += "View Records ([src.records.len])
" else dat += "View Records (0)
" if (src.diskette) dat += "Eject Disk
" if(2) dat += "

Current records

" dat += "<< Back

" for(var/datum/data/record/R in records) dat += "

[R.fields["name"]]

Scan ID [R.fields["id"]] View Record" if(3) dat += "

Selected Record

" dat += "<< Back
" if (!src.active_record) dat += "Record not found." else dat += "

[src.active_record.fields["name"]]

" dat += "Scan ID [src.active_record.fields["id"]] Clone
" var/obj/item/weapon/implant/health/H = locate(src.active_record.fields["imp"]) if ((H) && (istype(H))) dat += "Health Implant Data:
[H.sensehealth()]

" else dat += "Unable to locate Health Implant.

" dat += "Unique Identifier:
[src.active_record.fields["UI"]]
" dat += "Structural Enzymes:
[src.active_record.fields["SE"]]
" if(diskette && diskette.fields) dat += "
" dat += "

Inserted Disk

" dat += "Contents: " var/list/L = list() if(diskette.fields["UI"]) L += "Unique Identifier" if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"]) L += "Unique Enzymes" if(diskette.fields["SE"]) L += "Structural Enzymes" dat += english_list(L, "Empty", " + ", " + ") dat += "
Load from Disk" dat += "
Save to Disk" dat += "
" dat += "Delete Record" if(4) if (!src.active_record) src.menu = 2 dat = "[src.temp]
" dat += "

Confirm Record Deletion

" dat += "Scan card to confirm.
" dat += "Cancel" //user << browse(dat, "window=cloning") //onclose(user, "cloning") var/datum/browser/popup = new(user, "cloning", "Cloning System Control") popup.set_content(dat) popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/cloning/Topic(href, href_list) if(..()) return if(loading) return if(href_list["task"]) switch(href_list["task"]) if("autoprocess") autoprocess = 1 playsound(src, 'sound/machines/terminal_select.ogg', 50, 0) if("stopautoprocess") autoprocess = 0 playsound(src, 'sound/machines/terminal_select.ogg', 50, 0) else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational()) scantemp = "" loading = 1 src.updateUsrDialog() playsound(src, 'sound/machines/terminal_processing.ogg', 50, 0) say("Initiating scan...") spawn(20) src.scan_mob(scanner.occupant) loading = 0 src.updateUsrDialog() //No locking an open scanner. else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational()) if ((!scanner.locked) && (scanner.occupant)) scanner.locked = 1 playsound(src, 'sound/machines/DoorClick.ogg', 50, 0) else scanner.locked = 0 playsound(src, 'sound/machines/DoorClick.ogg', 50, 0) else if(href_list["view_rec"]) playsound(src, 'sound/machines/terminal_select.ogg', 50, 0) src.active_record = find_record("id", href_list["view_rec"], records) if(active_record) if(!active_record.fields["ckey"]) records -= active_record active_record = null src.temp = "Record Corrupt" else src.menu = 3 else src.temp = "Record missing." else if (href_list["del_rec"]) if ((!src.active_record) || (src.menu < 3)) return if (src.menu == 3) //If we are viewing a record, confirm deletion src.temp = "Delete record?" src.menu = 4 playsound(src, 'sound/machines/terminal_displaying.ogg', 50, 0) else if (src.menu == 4) var/obj/item/weapon/card/id/C = usr.get_active_hand() if (istype(C)||istype(C, /obj/item/device/pda)) if(src.check_access(C)) src.temp = "[src.active_record.fields["name"]] => Record deleted." src.records.Remove(active_record) active_record = null playsound(src, 'sound/machines/terminal_success.ogg', 50, 0) src.menu = 2 else src.temp = "Access Denied." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else if (href_list["disk"]) //Load or eject. switch(href_list["disk"]) if("load") if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields) src.temp = "Load error." src.updateUsrDialog() playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return if (!src.active_record) src.temp = "Record error." src.menu = 1 src.updateUsrDialog() playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return for(var/key in diskette.fields) src.active_record.fields[key] = diskette.fields[key] src.temp = "Load successful." playsound(src, 'sound/machines/terminal_success.ogg', 50, 0) if("eject") if(src.diskette) src.diskette.loc = src.loc src.diskette = null playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) if("save") if(!diskette || diskette.read_only || !active_record || !active_record.fields) src.temp = "Save error." src.updateUsrDialog() playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return diskette.fields = active_record.fields.Copy() diskette.name = "data disk - '[src.diskette.fields["name"]]'" src.temp = "Save successful." playsound(src, 'sound/machines/terminal_success.ogg', 50, 0) else if (href_list["refresh"]) src.updateUsrDialog() else if (href_list["clone"]) var/datum/data/record/C = find_record("id", href_list["clone"], records) //Look for that player! They better be dead! if(C) //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. if(!pod1) temp = "No Clonepod detected." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else if(pod1.occupant) temp = "Clonepod is currently occupied." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else if(pod1.mess) temp = "Clonepod malfunction." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else if(!config.revival_cloning) temp = "Unable to initiate cloning cycle." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else if(pod1.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"])) temp = "[C.fields["name"]] => Cloning cycle in progress..." playsound(src, 'sound/machines/terminal_processing.ogg', 50, 0) records.Remove(C) if(active_record == C) active_record = null menu = 1 else temp = "[C.fields["name"]] => Initialisation failure." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else temp = "Data corruption." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) else if (href_list["menu"]) src.menu = text2num(href_list["menu"]) playsound(src, 'sound/machines/terminal_select.ogg', 50, 0) src.add_fingerprint(usr) src.updateUsrDialog() return /obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject) if (!istype(subject)) scantemp = "Unable to locate valid genetic data." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return if (!subject.getorgan(/obj/item/organ/brain)) scantemp = "No signs of intelligence detected." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return if (subject.suiciding == 1 || subject.hellbound) scantemp = "Subject's brain is not responding to scanning stimuli." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return if ((subject.disabilities & NOCLONE) && (src.scanner.scan_level < 2)) scantemp = "Subject no longer contains the fundamental materials required to create a living clone." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return if ((!subject.ckey) || (!subject.client)) scantemp = "Mental interface failure." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return if (find_record("ckey", subject.ckey, records)) scantemp = "Subject already in database." playsound(src, 'sound/machines/terminal_error.ogg', 50, 0) return var/datum/data/record/R = new() if(subject.dna.species) // We store the instance rather than the path, because some // species (abductors, slimepeople) store state in their // species datums R.fields["mrace"] = subject.dna.species else var/datum/species/rando_race = pick(config.roundstart_races) R.fields["mrace"] = rando_race.type R.fields["ckey"] = subject.ckey R.fields["name"] = subject.real_name R.fields["id"] = copytext(md5(subject.real_name), 2, 6) R.fields["UE"] = subject.dna.unique_enzymes R.fields["UI"] = subject.dna.uni_identity R.fields["SE"] = subject.dna.struc_enzymes R.fields["blood_type"] = subject.dna.blood_type R.fields["features"] = subject.dna.features R.fields["factions"] = subject.faction //Add an implant if needed var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject) if(!imp) imp = new /obj/item/weapon/implant/health(subject) imp.implanted = subject R.fields["imp"] = "\ref[imp]" //Update it if needed else R.fields["imp"] = "\ref[imp]" if (!isnull(subject.mind)) //Save that mind so traitors can continue traitoring after cloning. R.fields["mind"] = "\ref[subject.mind]" src.records += R scantemp = "Subject successfully scanned." playsound(src, 'sound/machines/terminal_success.ogg', 50, 0)