From 780f30bd4de15bc5465cedd4db93fac659c37719 Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Sat, 4 Jul 2020 21:01:44 +0200
Subject: [PATCH 1/4] Fixing cloning
---
code/game/machinery/cloning.dm | 4 ++--
code/game/machinery/computer/cloning.dm | 4 ++--
code/game/machinery/exp_cloner.dm | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 9afe4808fd..5e5854e935 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -134,7 +134,7 @@
return examine(user)
//Start growing a human clone in the pod!
-/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
+/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -170,7 +170,7 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
- H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features)
+ H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 7834d6f2a2..70c13bd1d1 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -73,7 +73,7 @@
if(pod.occupant)
continue //how though?
- if(pod.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"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
+ if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
temp = "[R.fields["name"]] => Cloning cycle in progress..."
records -= R
@@ -415,7 +415,7 @@
else if(pod.occupant)
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(pod.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"], C.fields["quirks"], C.fields["bank_account"]))
+ else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], R.fields["traumas"]))
temp = "[C.fields["name"]] => Cloning cycle in progress..."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm
index 2c669aac80..75a915af3d 100644
--- a/code/game/machinery/exp_cloner.dm
+++ b/code/game/machinery/exp_cloner.dm
@@ -9,7 +9,7 @@
internal_radio = FALSE
//Start growing a human clone in the pod!
-/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
+/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -292,7 +292,7 @@
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
- pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
+ pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => Cloning data sent to pod."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
From 562b57095da3e36e24bc768d3cc1b83c5d1e964d Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Sun, 5 Jul 2020 03:04:53 +0200
Subject: [PATCH 2/4] mowing down the experimental cloner copypasta.
---
.../SpaceRuins/cloning_facility.dmm | 2 +-
code/__DEFINES/machines.dm | 4 +
code/game/machinery/cloning.dm | 68 ++--
code/game/machinery/computer/cloning.dm | 253 ++++++++++-----
code/game/machinery/exp_cloner.dm | 298 ------------------
.../circuitboards/computer_circuitboards.dm | 4 +-
.../reagents/chemistry/reagents/SDGF.dm | 2 +-
tgstation.dme | 1 -
8 files changed, 218 insertions(+), 414 deletions(-)
delete mode 100644 code/game/machinery/exp_cloner.dm
diff --git a/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm b/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm
index 1fb4e60aff..d440e2d15b 100644
--- a/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm
+++ b/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm
@@ -69,7 +69,7 @@
/turf/open/floor/plasteel/white,
/area/ruin/space/has_grav/powered/ancient_shuttle)
"j" = (
-/obj/machinery/computer/prototype_cloning,
+/obj/machinery/computer/cloning/prototype,
/obj/machinery/light{
dir = 1
},
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 5a26feb624..0e8e34d20e 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -115,3 +115,7 @@
//these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified.
#define PLANT_GENE_REMOVABLE (1<<0)
#define PLANT_GENE_EXTRACTABLE (1<<1)
+
+#define CLONEPOD_GET_MIND 1
+#define CLONEPOD_POLL_MIND 2
+#define CLONEPOD_NO_MIND 3
\ No newline at end of file
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 5e5854e935..6f798a41ef 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -26,6 +26,7 @@
var/efficiency
var/datum/mind/clonemind
+ var/get_clone_mind = CLONEPOD_GET_MIND
var/grab_ghost_when = CLONER_MATURE_CLONE
var/internal_radio = TRUE
@@ -139,31 +140,32 @@
return FALSE
if(mess || attempting)
return FALSE
- clonemind = locate(mindref) in SSticker.minds
- if(!istype(clonemind)) //not a mind
- return FALSE
- if(!QDELETED(clonemind.current))
- if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
+ if(get_clone_mind == CLONEPOD_GET_MIND)
+ clonemind = locate(mindref) in SSticker.minds
+ if(!istype(clonemind)) //not a mind
return FALSE
- if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
+ if(!QDELETED(clonemind.current))
+ if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
+ return FALSE
+ if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
+ return FALSE
+ if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
+ return FALSE
+ if(clonemind.active) //somebody is using that mind
+ if( ckey(clonemind.key)!=ckey )
+ return FALSE
+ else
+ // get_ghost() will fail if they're unable to reenter their body
+ var/mob/dead/observer/G = clonemind.get_ghost()
+ if(!G)
+ return FALSE
+ if(G.suiciding) // The ghost came from a body that is suiciding.
+ return FALSE
+ if(clonemind.damnation_type) //Can't clone the damned.
+ INVOKE_ASYNC(src, .proc/horrifyingsound)
+ mess = TRUE
+ update_icon()
return FALSE
- if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
- return FALSE
- if(clonemind.active) //somebody is using that mind
- if( ckey(clonemind.key)!=ckey )
- return FALSE
- else
- // get_ghost() will fail if they're unable to reenter their body
- var/mob/dead/observer/G = clonemind.get_ghost()
- if(!G)
- return FALSE
- if(G.suiciding) // The ghost came from a body that is suiciding.
- return FALSE
- if(clonemind.damnation_type) //Can't clone the damned.
- INVOKE_ASYNC(src, .proc/horrifyingsound)
- mess = TRUE
- update_icon()
- return FALSE
current_insurance = insurance
attempting = TRUE //One at a time!!
countdown.start()
@@ -192,7 +194,14 @@
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
H.Unconscious(80)
- clonemind.transfer_to(H)
+ if(clonemind)
+ clonemind.transfer_to(H)
+
+ else if(get_clone_mind == CLONEPOD_POLL_MIND)
+ var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", null, null, null, 100, H, POLL_IGNORE_CLONE)
+ if(LAZYLEN(candidates))
+ var/mob/C = pick(candidates)
+ H.key = C.key
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
@@ -549,6 +558,17 @@
. += "cover-on"
. += "panel"
+//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
+/obj/machinery/clonepod/experimental
+ name = "experimental cloning pod"
+ desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
+ icon = 'icons/obj/machines/cloning.dmi'
+ icon_state = "pod_0"
+ req_access = null
+ circuit = /obj/item/circuitboard/machine/clonepod/experimental
+ internal_radio = FALSE
+ get_clone_mind = CLONEPOD_POLL_MIND
+
/*
* Manual -- A big ol' manual.
*/
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 70c13bd1d1..8f70661cc9 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -8,6 +8,7 @@
circuit = /obj/item/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/clonepod_type = /obj/machinery/clonepod
var/list/pods //Linked cloning pods
var/temp = "Inactive"
var/scantemp_ckey
@@ -17,6 +18,7 @@
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
var/loading = 0 // Nice loading text
var/autoprocess = 0
+ var/use_records = TRUE // Old experimental cloner.
var/list/records = list()
light_color = LIGHT_COLOR_BLUE
@@ -36,29 +38,32 @@
return ..()
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/pod = P
- if(pod.occupant && pod.clonemind == mind)
- return null
- if(pod.is_operational() && !(pod.occupant || pod.mess))
- return pod
+ if(!pods)
+ return
+ for(var/P in pods)
+ var/obj/machinery/clonepod/pod = P
+ if(pod.occupant && pod.get_clone_mind == CLONEPOD_GET_MIND && pod.clonemind == mind)
+ return null
+ if(pod.is_operational() && !(pod.occupant || pod.mess))
+ return pod
/obj/machinery/computer/cloning/proc/HasEfficientPod()
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/pod = P
- if(pod.is_operational() && pod.efficiency > 5)
- return TRUE
+ if(!pods)
+ return
+ for(var/P in pods)
+ var/obj/machinery/clonepod/pod = P
+ if(pod.is_operational() && pod.efficiency > 5)
+ return TRUE
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/pod = P
- if(pod.occupant && pod.clonemind == mind)
- return pod
- else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
- . = pod
+ if(!pods)
+ return
+ for(var/P in pods)
+ var/obj/machinery/clonepod/pod = P
+ if(pod.occupant && pod.clonemind == mind)
+ return pod
+ else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
+ . = pod
/obj/machinery/computer/cloning/process()
if(!(scanner && LAZYLEN(pods) && autoprocess))
@@ -103,12 +108,10 @@
return null
/obj/machinery/computer/cloning/proc/findcloner()
- var/obj/machinery/clonepod/podf = null
-
+ var/obj/machinery/clonepod/podf
for(var/direction in GLOB.cardinals)
-
- podf = locate(/obj/machinery/clonepod, get_step(src, direction))
- if (!isnull(podf) && podf.is_operational())
+ podf = locate(clonepod_type, get_step(src, direction))
+ if(podf?.is_operational())
AttachCloner(podf)
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
@@ -132,7 +135,7 @@
else if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
- if(istype(P.buffer, /obj/machinery/clonepod))
+ if(istype(P.buffer, clonepod_type))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-")
P.buffer = null
@@ -157,13 +160,14 @@
var/dat = ""
dat += "Refresh"
- if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
- if(!autoprocess)
- dat += "Autoclone"
+ if(use_records)
+ if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
+ if(!autoprocess)
+ dat += "Autoclone"
+ else
+ dat += "Stop autoclone"
else
- dat += "Stop autoclone"
- else
- dat += "Autoclone"
+ dat += "Autoclone"
dat += "
Cloning Pod Status
"
dat += "[temp]
"
@@ -190,26 +194,29 @@
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
- if(scanner_occupant.ckey != scantemp_ckey)
- scantemp = "Ready to Scan"
- scantemp_ckey = scanner_occupant.ckey
+ if(use_records)
+ if(scanner_occupant.ckey != scantemp_ckey)
+ scantemp = "Ready to Scan"
+ scantemp_ckey = scanner_occupant.ckey
+ else
+ scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += ""
if(scanner_occupant)
- dat += "Start Scan"
- dat += "
[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]"
+ dat += "[use_records ? "Start Scan" : "Clone"]"
+ dat += "
[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
"
+ dat += "[use_records ? "Start Scan" : "Clone"]"
+ if(use_records)
+ // 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
"
@@ -290,24 +297,19 @@
autoprocess = FALSE
STOP_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ . = TRUE
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
- loading = 1
+ loading = TRUE
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
- spawn(20)
- src.scan_occupant(scanner.occupant)
-
- loading = 0
- src.updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
- scanner.locked = prev_locked
-
+ addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
+ . = TRUE
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
@@ -317,8 +319,17 @@
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ . = TRUE
- else if(href_list["view_rec"])
+
+ else if (href_list["refresh"])
+ src.updateUsrDialog()
+ playsound(src, "terminal_type", 25, 0)
+ . = TRUE
+
+ if(. || !use_records)
+ return
+ if(href_list["view_rec"])
playsound(src, "terminal_type", 25, 0)
src.active_record = find_record("id", href_list["view_rec"], records)
if(active_record)
@@ -330,6 +341,7 @@
src.menu = 3
else
src.temp = "Record missing."
+ . = TRUE
else if (href_list["del_rec"])
if ((!src.active_record) || (src.menu < 3))
@@ -353,8 +365,9 @@
else
src.temp = "Access Denied."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ . = TRUE
- else if (href_list["disk"]) //Load or eject.
+ else if (href_list["disk"] && use_records) //Load or eject.
switch(href_list["disk"])
if("load")
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
@@ -392,10 +405,7 @@
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
src.temp = "Save successful."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
- else if (href_list["refresh"])
- src.updateUsrDialog()
- playsound(src, "terminal_type", 25, 0)
+ . = TRUE
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
@@ -415,7 +425,7 @@
else if(pod.occupant)
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], R.fields["traumas"]))
+ else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
temp = "[C.fields["name"]] => Cloning cycle in progress..."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
@@ -429,15 +439,30 @@
else
temp = "Data corruption."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ . = TRUE
- else if (href_list["menu"])
- src.menu = text2num(href_list["menu"])
+ else if (href_list["menu"] && use_records)
+ menu = text2num(href_list["menu"])
playsound(src, "terminal_type", 25, 0)
+ . = TRUE
+/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
+ if(!scanner)
+ return
src.add_fingerprint(usr)
src.updateUsrDialog()
return
+ if(use_records)
+ scan_occupant(L)
+ else
+ clone_occupant(L)
+
+ loading = FALSE
+ src.updateUsrDialog()
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ scanner.locked = prev_locked
+
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
@@ -455,30 +480,9 @@
if(isbrain(mob_occupant))
dna = B.stored_dna
- if(!istype(dna))
- scantemp = "Unable to locate valid genetic data."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if(mob_occupant.suiciding || mob_occupant.hellbound)
- scantemp = "Subject's brain is not responding to scanning stimuli."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if((HAS_TRAIT(mob_occupant, TRAIT_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_alert.ogg', 50, 0)
- return
- if ((!mob_occupant.ckey) || (!mob_occupant.client))
- scantemp = "Mental interface failure."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if (find_record("ckey", mob_occupant.ckey, records))
- scantemp = "Subject already in database."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if(SSeconomy.full_ancap && !has_bank_account)
- scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ if(!can_scan(dna, mob_occupant, FALSE, has_bank_account))
return
+
var/datum/data/record/R = new()
if(dna.species)
// We store the instance rather than the path, because some
@@ -529,3 +533,78 @@
board.records = records
scantemp = "Subject successfully scanned."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+
+//Used by the experimental cloning computer.
+/obj/machinery/computer/cloning/proc/clone_occupant(occupant)
+ var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
+ var/datum/dna/dna
+ if(ishuman(mob_occupant))
+ var/mob/living/carbon/C = mob_occupant
+ dna = C.has_dna()
+ if(isbrain(mob_occupant))
+ var/mob/living/brain/B = mob_occupant
+ dna = B.stored_dna
+
+ if(!can_scan(dna, mob_occupant, TRUE))
+ return
+
+ var/clone_species
+ if(dna.species)
+ clone_species = dna.species
+ else
+ var/datum/species/rando_race = pick(GLOB.roundstart_races)
+ clone_species = rando_race.type
+
+ var/obj/machinery/clonepod/pod = GetAvailablePod()
+ //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
+ if(!LAZYLEN(pods))
+ temp = "No Clonepods detected."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else if(!pod)
+ temp = "No Clonepods available."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else if(pod.occupant)
+ temp = "Cloning cycle already in progress."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else
+ pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
+ temp = "[mob_occupant.real_name] => Cloning data sent to pod."
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+
+/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account)
+ if(!istype(dna))
+ scantemp = "Unable to locate valid genetic data."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if(!experimental)
+ if(mob_occupant.suiciding || mob_occupant.hellbound)
+ scantemp = "Subject's brain is not responding to scanning stimuli."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if((HAS_TRAIT(mob_occupant, TRAIT_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_alert.ogg', 50, 0)
+ return
+ if (!experimental)
+ if(!mob_occupant.ckey || !mob_occupant.client)
+ scantemp = "Mental interface failure."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if (find_record("ckey", mob_occupant.ckey, records))
+ scantemp = "Subject already in database."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if(SSeconomy.full_ancap && !account)
+ scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ return TRUE
+
+//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
+/obj/machinery/computer/cloning/prototype
+ name = "prototype cloning console"
+ desc = "Used to operate an experimental cloner."
+ icon_screen = "dna"
+ icon_keyboard = "med_key"
+ circuit = /obj/item/circuitboard/computer/cloning/prototype
+ clonepod_type = /obj/machinery/clonepod/experimental
diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm
deleted file mode 100644
index 75a915af3d..0000000000
--- a/code/game/machinery/exp_cloner.dm
+++ /dev/null
@@ -1,298 +0,0 @@
-//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
-/obj/machinery/clonepod/experimental
- name = "experimental cloning pod"
- desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
- icon = 'icons/obj/machines/cloning.dmi'
- icon_state = "pod_0"
- req_access = null
- circuit = /obj/item/circuitboard/machine/clonepod/experimental
- internal_radio = FALSE
-
-//Start growing a human clone in the pod!
-/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
- if(panel_open)
- return FALSE
- if(mess || attempting)
- return FALSE
-
- attempting = TRUE //One at a time!!
- countdown.start()
-
- var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
-
- H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
-
- if(efficiency > 2)
- var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
- H.dna.remove_mutation_group(unclean_mutations)
- if(efficiency > 5 && prob(20))
- H.easy_randmut(POSITIVE)
- if(efficiency < 3 && prob(50))
- var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
- if(ismob(M))
- H = M
-
- H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
- occupant = H
-
- if(!clonename) //to prevent null names
- clonename = "clone ([rand(1,999)])"
- H.real_name = clonename
-
- icon_state = "pod_1"
- //Get the clone body ready
- maim_clone(H)
- ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
- ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
- ADD_TRAIT(H, TRAIT_MUTE, "cloning")
- ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
- ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
- H.Unconscious(80)
-
- var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
- if(LAZYLEN(candidates))
- var/mob/C = pick(candidates)
- H.key = C.key
-
- if(grab_ghost_when == CLONER_FRESH_CLONE)
- H.grab_ghost()
- to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
So this is what cloning feels like?")
-
- if(grab_ghost_when == CLONER_MATURE_CLONE)
- H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
- to_chat(H.get_ghost(TRUE), "Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.")
-
- if(H)
- H.faction |= factions
-
- H.set_cloned_appearance()
-
- H.suiciding = FALSE
- attempting = FALSE
- return TRUE
-
-
-//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
-/obj/machinery/computer/prototype_cloning
- name = "prototype cloning console"
- desc = "Used to operate an experimental cloner."
- icon_screen = "dna"
- icon_keyboard = "med_key"
- circuit = /obj/item/circuitboard/computer/prototype_cloning
- var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
- var/list/pods //Linked experimental cloning pods
- var/temp = "Inactive"
- var/scantemp = "Ready to Scan"
- var/loading = FALSE // Nice loading text
-
- light_color = LIGHT_COLOR_BLUE
-
-/obj/machinery/computer/prototype_cloning/Initialize()
- . = ..()
- updatemodules(TRUE)
-
-/obj/machinery/computer/prototype_cloning/Destroy()
- if(pods)
- for(var/P in pods)
- DetachCloner(P)
- pods = null
- return ..()
-
-/obj/machinery/computer/prototype_cloning/proc/GetAvailablePod(mind = null)
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/experimental/pod = P
- if(pod.is_operational() && !(pod.occupant || pod.mess))
- return pod
-
-/obj/machinery/computer/prototype_cloning/proc/updatemodules(findfirstcloner)
- scanner = findscanner()
- if(findfirstcloner && !LAZYLEN(pods))
- findcloner()
-
-/obj/machinery/computer/prototype_cloning/proc/findscanner()
- var/obj/machinery/dna_scannernew/scannerf = null
-
- // Loop through every direction
- for(var/direction in GLOB.cardinals)
- // Try to find a scanner in that direction
- scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
- // 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/prototype_cloning/proc/findcloner()
- var/obj/machinery/clonepod/experimental/podf = null
- for(var/direction in GLOB.cardinals)
- podf = locate(/obj/machinery/clonepod/experimental, get_step(src, direction))
- if (!isnull(podf) && podf.is_operational())
- AttachCloner(podf)
-
-/obj/machinery/computer/prototype_cloning/proc/AttachCloner(obj/machinery/clonepod/experimental/pod)
- if(!pod.connected)
- pod.connected = src
- LAZYADD(pods, pod)
-
-/obj/machinery/computer/prototype_cloning/proc/DetachCloner(obj/machinery/clonepod/experimental/pod)
- pod.connected = null
- LAZYREMOVE(pods, pod)
-
-/obj/machinery/computer/prototype_cloning/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/multitool))
- var/obj/item/multitool/P = W
-
- if(istype(P.buffer, /obj/machinery/clonepod/experimental))
- if(get_area(P.buffer) != get_area(src))
- to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-")
- P.buffer = null
- return
- to_chat(user, "-% Successfully linked [P.buffer] with [src] %-")
- var/obj/machinery/clonepod/experimental/pod = P.buffer
- if(pod.connected)
- pod.connected.DetachCloner(pod)
- AttachCloner(pod)
- else
- P.buffer = src
- to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-")
- return
- else
- return ..()
-
-/obj/machinery/computer/prototype_cloning/attack_hand(mob/user)
- if(..())
- return
- interact(user)
-
-/obj/machinery/computer/prototype_cloning/interact(mob/user)
- user.set_machine(src)
- add_fingerprint(user)
-
- if(..())
- return
-
- updatemodules(TRUE)
-
- var/dat = ""
- dat += "Refresh"
-
- dat += "Cloning Pod Status
"
- dat += "[temp]
"
-
- if (isnull(src.scanner) || !LAZYLEN(pods))
- dat += "Modules
"
- //dat += "Reload Modules"
- if (isnull(src.scanner))
- dat += "ERROR: No Scanner detected!
"
- if (!LAZYLEN(pods))
- dat += "ERROR: No Pod detected
"
-
- // Scan-n-Clone
- if (!isnull(src.scanner))
- var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
-
- dat += "Cloning
"
-
- dat += ""
- if(!scanner_occupant)
- dat += "Scanner Unoccupied"
- else if(loading)
- dat += "[scanner_occupant] => Scanning..."
- else
- scantemp = "Ready to Clone"
- dat += "[scanner_occupant] => [scantemp]"
- dat += "
"
-
- if(scanner_occupant)
- dat += "Clone"
- dat += "
[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]"
- else
- dat += "Clone"
-
- var/datum/browser/popup = new(user, "cloning", "Prototype 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/prototype_cloning/Topic(href, href_list)
- if(..())
- return
-
- if(loading)
- return
-
- else if ((href_list["clone"]) && !isnull(scanner) && scanner.is_operational())
- scantemp = ""
-
- loading = TRUE
- updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
- say("Initiating scan...")
-
- spawn(20)
- clone_occupant(scanner.occupant)
- loading = FALSE
- updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
- //No locking an open scanner.
- else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
- if ((!scanner.locked) && (scanner.occupant))
- scanner.locked = TRUE
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else
- scanner.locked = FALSE
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
- else if (href_list["refresh"])
- updateUsrDialog()
- playsound(src, "terminal_type", 25, 0)
-
- add_fingerprint(usr)
- updateUsrDialog()
- return
-
-/obj/machinery/computer/prototype_cloning/proc/clone_occupant(occupant)
- var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
- var/datum/dna/dna
- if(ishuman(mob_occupant))
- var/mob/living/carbon/C = mob_occupant
- dna = C.has_dna()
- if(isbrain(mob_occupant))
- var/mob/living/brain/B = mob_occupant
- dna = B.stored_dna
-
- if(!istype(dna))
- scantemp = "Unable to locate valid genetic data."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if((HAS_TRAIT(mob_occupant, TRAIT_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_alert.ogg', 50, 0)
- return
-
- var/clone_species
- if(dna.species)
- clone_species = dna.species
- else
- var/datum/species/rando_race = pick(GLOB.roundstart_races)
- clone_species = rando_race.type
-
- var/obj/machinery/clonepod/pod = GetAvailablePod()
- //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
- if(!LAZYLEN(pods))
- temp = "No Clonepods detected."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(!pod)
- temp = "No Clonepods available."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(pod.occupant)
- temp = "Cloning cycle already in progress."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else
- pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
- temp = "[mob_occupant.real_name] => Cloning data sent to pod."
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index f94c8f3513..2fa48582f7 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -116,9 +116,9 @@
build_path = /obj/machinery/computer/cloning
var/list/records = list()
-/obj/item/circuitboard/computer/prototype_cloning
+/obj/item/circuitboard/computer/cloning/prototype
name = "Prototype Cloning (Computer Board)"
- build_path = /obj/machinery/computer/prototype_cloning
+ build_path = /obj/machinery/computer/cloning/prototype
/obj/item/circuitboard/computer/arcade/battle
name = "Arcade Battle (Computer Board)"
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
index 37ec1ee69f..dfbe103b43 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
@@ -63,7 +63,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
startHunger = M.nutrition
if(pollStarted == FALSE)
pollStarted = TRUE
- candies = pollGhostCandidates("Do you want and agree to play as a clone of [M], respect their character and not engage in ERP without permission from the original?", ignore_category = POLL_IGNORE_CLONE)
+ candies = pollGhostCandidates("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", ignore_category = POLL_IGNORE_CLONE)
log_reagent("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.")
if(20 to INFINITY)
if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there!
diff --git a/tgstation.dme b/tgstation.dme
index 3f9c5ff81b..ccc21a1c38 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -743,7 +743,6 @@
#include "code\game\machinery\dna_scanner.dm"
#include "code\game\machinery\doppler_array.dm"
#include "code\game\machinery\droneDispenser.dm"
-#include "code\game\machinery\exp_cloner.dm"
#include "code\game\machinery\firealarm.dm"
#include "code\game\machinery\flasher.dm"
#include "code\game\machinery\gulag_item_reclaimer.dm"
From e12c3382dee2c150372e2bf3b08b3990d612cbfc Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Sun, 5 Jul 2020 03:48:41 +0200
Subject: [PATCH 3/4] undefined variable.
---
.../code/modules/reagents/chemistry/reagents/SDGF.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
index dfbe103b43..8ef302e904 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
@@ -63,7 +63,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
startHunger = M.nutrition
if(pollStarted == FALSE)
pollStarted = TRUE
- candies = pollGhostCandidates("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", ignore_category = POLL_IGNORE_CLONE)
+ candies = pollGhostCandidates("Do you want to play as [M]'s defective clone? (Don't ERP without permission from the original)", ignore_category = POLL_IGNORE_CLONE)
log_reagent("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.")
if(20 to INFINITY)
if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there!
From afb5b5237ce99e052f026ff612fd5b117fef711c Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Mon, 6 Jul 2020 22:42:32 +0200
Subject: [PATCH 4/4] linter & stuff.
---
code/game/machinery/computer/cloning.dm | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 8f70661cc9..400ce041c7 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -447,11 +447,10 @@
. = TRUE
/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
- if(!scanner)
+ if(!scanner || !L)
return
src.add_fingerprint(usr)
src.updateUsrDialog()
- return
if(use_records)
scan_occupant(L)