/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)