diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index d0fcb3bcbe..f35a6eaa15 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1399,3 +1399,20 @@ GLOBAL_PROTECT(valid_HTTPSGet)
/proc/pass()
return
+
+/proc/get_mob_or_brainmob(occupant)
+ var/mob/living/mob_occupant
+
+ if(isliving(occupant))
+ mob_occupant = occupant
+
+ else if(isbodypart(occupant))
+ var/obj/item/bodypart/head/head = occupant
+
+ mob_occupant = head.brainmob
+
+ else if(isorgan(occupant))
+ var/obj/item/organ/brain/brain = occupant
+ mob_occupant = brain.brainmob
+
+ return mob_occupant
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index b95dbff56d..ec87cf6ba9 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -1,499 +1,504 @@
-//Cloning revival method.
-//The pod handles the actual cloning while the computer manages the clone profiles
-
-//Potential replacement for genetics revives or something I dunno (?)
-
-#define CLONE_INITIAL_DAMAGE 190 //Clones in clonepods start with 190 cloneloss damage and 190 brainloss damage, thats just logical
-#define MINIMUM_HEAL_LEVEL 40
-
-#define SPEAK(message) radio.talk_into(src, message, radio_channel, get_spans(), get_default_language())
-
-/obj/machinery/clonepod
- anchored = 1
- name = "cloning pod"
- desc = "An electronically-lockable pod for growing organic tissue."
- density = 1
- icon = 'icons/obj/cloning.dmi'
- icon_state = "pod_0"
- req_access = list(GLOB.access_cloning) //For premature unlocking.
- verb_say = "states"
- var/heal_level //The clone is released once its health reaches this level.
- var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
- var/mess = FALSE //Need to clean out it if it's full of exploded clone.
- var/attempting = FALSE //One clone attempt at a time thanks
- var/speed_coeff
- var/efficiency
-
- var/datum/mind/clonemind
- var/grab_ghost_when = CLONER_MATURE_CLONE
-
- var/obj/item/device/radio/radio
- var/radio_key = /obj/item/device/encryptionkey/headset_med
- var/radio_channel = "Medical"
-
- var/obj/effect/countdown/clonepod/countdown
-
- var/list/unattached_flesh
- var/flesh_number = 0
-
- // The "brine" is the reagents that are automatically added in small
- // amounts to the occupant.
- var/static/list/brine_types = list(
- "salbutamol", // anti-oxyloss
- "bicaridine", // NOBREATHE species take brute in crit
- "corazone", // prevents cardiac arrest damage
- "mimesbane") // stops them gasping from lack of air.
-
-/obj/machinery/clonepod/New()
- ..()
- var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
- B.apply_default_parts(src)
-
- countdown = new(src)
-
- radio = new(src)
- radio.keyslot = new radio_key
- radio.subspace_transmission = 1
- radio.canhear_range = 0
- radio.recalculateChannels()
-
-/obj/machinery/clonepod/Destroy()
- go_out()
- qdel(radio)
- radio = null
- qdel(countdown)
- countdown = null
- if(connected)
- connected.DetachCloner(src)
- for(var/i in unattached_flesh)
- qdel(i)
- LAZYCLEARLIST(unattached_flesh)
- unattached_flesh = null
- . = ..()
-
-/obj/machinery/clonepod/RefreshParts()
- speed_coeff = 0
- efficiency = 0
- for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts)
- efficiency += S.rating
- for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
- speed_coeff += P.rating
- heal_level = (efficiency * 15) + 10
- if(heal_level < MINIMUM_HEAL_LEVEL)
- heal_level = MINIMUM_HEAL_LEVEL
- if(heal_level > 100)
- heal_level = 100
-
-/obj/item/weapon/circuitboard/machine/clonepod
- name = "Clone Pod (Machine Board)"
- build_path = /obj/machinery/clonepod
- origin_tech = "programming=2;biotech=2"
- req_components = list(
- /obj/item/stack/cable_coil = 2,
- /obj/item/weapon/stock_parts/scanning_module = 2,
- /obj/item/weapon/stock_parts/manipulator = 2,
- /obj/item/stack/sheet/glass = 1)
-
-//The return of data disks?? Just for transferring between genetics machine/cloning machine.
-//TO-DO: Make the genetics machine accept them.
-/obj/item/weapon/disk/data
- name = "cloning data disk"
- icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
- var/list/fields = list()
- var/read_only = 0 //Well,it's still a floppy disk
-
-//Disk stuff.
-/obj/item/weapon/disk/data/New()
- ..()
- icon_state = "datadisk[rand(0,6)]"
- add_overlay("datadisk_gene")
-
-/obj/item/weapon/disk/data/attack_self(mob/user)
- read_only = !read_only
- to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].")
-
-/obj/item/weapon/disk/data/examine(mob/user)
- ..()
- to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
-
-
-//Clonepod
-
-/obj/machinery/clonepod/examine(mob/user)
- ..()
- var/mob/living/mob_occupant = occupant
- if(mess)
- to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
- if(is_operational() && mob_occupant)
- if(mob_occupant.stat != DEAD)
- to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
-
-/obj/machinery/clonepod/return_air()
- // We want to simulate the clone not being in contact with
- // the atmosphere, so we'll put them in a constant pressure
- // nitrogen. They'll breathe through the chemicals we pump into them.
- var/static/datum/gas_mixture/immutable/cloner/GM //global so that there's only one instance made for all cloning pods
- if(!GM)
- GM = new
- return GM
-
-/obj/machinery/clonepod/proc/get_completion()
- . = FALSE
- var/mob/living/mob_occupant = occupant
- if(mob_occupant)
- . = (100 * ((mob_occupant.health + 100) / (heal_level + 100)))
-
-/obj/machinery/clonepod/attack_ai(mob/user)
- return examine(user)
-
-//Start growing a human clone in the pod!
-/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions)
- if(panel_open)
- return FALSE
- if(mess || attempting)
- return FALSE
- clonemind = locate(mindref)
- if(!istype(clonemind)) //not a mind
- return FALSE
- if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body
- 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(clonemind.damnation_type) //Can't clone the damned.
- INVOKE_ASYNC(src, .proc/horrifyingsound)
- mess = TRUE
- icon_state = "pod_g"
- update_icon()
- return FALSE
-
- attempting = TRUE //One at a time!!
- countdown.start()
-
- var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
-
- if(clonemind.changeling)
- var/obj/item/organ/brain/B = H.getorganslot("brain")
- B.vital = FALSE
- B.decoy_override = TRUE
-
- H.hardset_dna(ui, se, H.real_name, null, 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.randmutvg()
- if(efficiency < 3 && prob(50))
- var/mob/M = H.randmutb()
- 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(0,999)])"
- H.real_name = clonename
-
- icon_state = "pod_1"
- //Get the clone body ready
- maim_clone(H)
- check_brine() // put in chemicals NOW to stop death via cardiac arrest
- H.Paralyse(4)
-
- clonemind.transfer_to(H)
-
- 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
-
-//Grow clones to maturity then kick them out. FREELOADERS
-/obj/machinery/clonepod/process()
- var/mob/living/mob_occupant = occupant
-
- if(!is_operational()) //Autoeject if power is lost
- if(mob_occupant)
- go_out()
- connected_message("Clone Ejected: Loss of power.")
-
- else if(mob_occupant && (mob_occupant.loc == src))
- if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
- connected_message("Clone Rejected: Deceased.")
- SPEAK("The cloning of [mob_occupant.real_name] has been \
- aborted due to unrecoverable tissue failure.")
- go_out()
-
- else if(mob_occupant.cloneloss > (100 - heal_level))
- mob_occupant.Paralyse(4)
-
- //Slowly get that clone healed and finished.
- mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
- var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
- // To avoid the default cloner making incomplete clones
- progress += (100 - MINIMUM_HEAL_LEVEL)
- var/milestone = CLONE_INITIAL_DAMAGE / flesh_number
- var/installed = flesh_number - unattached_flesh.len
-
- if((progress / milestone) >= installed)
- // attach some flesh
- var/obj/item/I = pick_n_take(unattached_flesh)
- if(isorgan(I))
- var/obj/item/organ/O = I
- O.Insert(mob_occupant)
- else if(isbodypart(I))
- var/obj/item/bodypart/BP = I
- BP.attach_limb(mob_occupant)
-
- //Premature clones may have brain damage.
- mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
-
- check_brine()
-
- use_power(7500) //This might need tweaking.
-
- else if((mob_occupant.cloneloss <= (100 - heal_level)))
- connected_message("Cloning Process Complete.")
- SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.")
- go_out()
-
- else if (!mob_occupant || mob_occupant.loc != src)
- occupant = null
- if (!mess && !panel_open)
- icon_state = "pod_0"
- use_power(200)
-
-//Let's unlock this early I guess. Might be too early, needs tweaking.
-/obj/machinery/clonepod/attackby(obj/item/weapon/W, mob/user, params)
- if(!(occupant || mess))
- if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W))
- return
-
- if(exchange_parts(user, W))
- return
-
- if(default_deconstruction_crowbar(W))
- return
-
- if(istype(W,/obj/item/device/multitool))
- var/obj/item/device/multitool/P = W
-
- if(istype(P.buffer, /obj/machinery/computer/cloning))
- 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/computer/cloning/comp = P.buffer
- if(connected)
- connected.DetachCloner(src)
- comp.AttachCloner(src)
- else
- P.buffer = src
- to_chat(user, "-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-")
- return
-
- var/mob/living/mob_occupant = occupant
- if(W.GetID())
- if(!check_access(W))
- to_chat(user, "Access Denied.")
- return
- if(!(mob_occupant || mess))
- to_chat(user, "Error: Pod has no occupant.")
- return
- else
- connected_message("Authorized Ejection")
-
- SPEAK("An authorized ejection of [clonemind.name] has occurred.")
-
- to_chat(user, "You force an emergency ejection. ")
- go_out()
- else
- return ..()
-
-/obj/machinery/clonepod/emag_act(mob/user)
- if(!occupant)
- return
- to_chat(user, "You corrupt the genetic compiler.")
- malfunction()
-
-//Put messages in the connected computer's temp var for display.
-/obj/machinery/clonepod/proc/connected_message(message)
- if ((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning)))
- return FALSE
- if (!message)
- return FALSE
-
- connected.temp = message
- connected.updateUsrDialog()
- return TRUE
-
-/obj/machinery/clonepod/proc/go_out()
- countdown.stop()
- var/mob/living/mob_occupant = occupant
-
- if(mess) //Clean that mess and dump those gibs!
- mess = FALSE
- new /obj/effect/gibspawner/generic(loc)
- audible_message("You hear a splat.")
- icon_state = "pod_0"
- return
-
- if(!mob_occupant)
- return
-
-
- if(grab_ghost_when == CLONER_MATURE_CLONE)
- mob_occupant.grab_ghost()
- to_chat(occupant, "There is a bright flash!
You feel like a new being.")
- mob_occupant.flash_act()
-
- var/turf/T = get_turf(src)
- occupant.forceMove(T)
- icon_state = "pod_0"
- mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
-
- occupant = null
-
-/obj/machinery/clonepod/proc/malfunction()
- var/mob/living/mob_occupant = occupant
- if(mob_occupant)
- connected_message("Critical Error!")
- SPEAK("Critical error! Please contact a Thinktronic Systems \
- technician, as your warranty may be affected.")
- mess = TRUE
-
- for(var/obj/item/O in unattached_flesh)
- qdel(O)
-
- icon_state = "pod_g"
- if(mob_occupant.mind != clonemind)
- clonemind.transfer_to(mob_occupant)
- mob_occupant.grab_ghost() // We really just want to make you suffer.
- flash_color(mob_occupant, flash_color="#960000", flash_time=100)
- to_chat(mob_occupant, "Agony blazes across your consciousness as your body is torn apart.
Is this what dying is like? Yes it is.")
- playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
- mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
- QDEL_IN(mob_occupant, 40)
-
-/obj/machinery/clonepod/relaymove(mob/user)
- if(user.stat == CONSCIOUS)
- go_out()
-
-/obj/machinery/clonepod/emp_act(severity)
-
- var/mob/living/mob_occupant = occupant
- if(mob_occupant && prob(100/(severity*efficiency)))
- connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
- SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
-
- go_out()
- ..()
-
-/obj/machinery/clonepod/ex_act(severity, target)
- ..()
- if(!QDELETED(src))
- go_out()
-
-/obj/machinery/clonepod/handle_atom_del(atom/A)
- if(A == occupant)
- occupant = null
- countdown.stop()
-
-/obj/machinery/clonepod/proc/horrifyingsound()
- for(var/i in 1 to 5)
- playsound(loc,pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 100, rand(0.95,1.05))
- sleep(1)
- sleep(10)
- playsound(loc,'sound/hallucinations/wail.ogg',100,1)
-
-/obj/machinery/clonepod/deconstruct(disassembled = TRUE)
- if(occupant)
- go_out()
- ..()
-
-/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H)
- if(!unattached_flesh)
- unattached_flesh = list()
- else
- for(var/fl in unattached_flesh)
- qdel(fl)
- unattached_flesh.Cut()
-
- H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
- H.setBrainLoss(CLONE_INITIAL_DAMAGE)
- // In addition to being cellularly damaged and having barely any
- // brain function, they also have no limbs or internal organs.
- var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
- for(var/zone in zones)
- var/obj/item/bodypart/BP = H.get_bodypart(zone)
- BP.drop_limb()
- BP.forceMove(src)
- unattached_flesh += BP
-
- for(var/o in H.internal_organs)
- var/obj/item/organ/organ = o
- if(!istype(organ) || organ.vital)
- continue
- organ.Remove(H, special=TRUE)
- organ.forceMove(src)
- unattached_flesh += organ
-
- flesh_number = unattached_flesh.len
-
-/obj/machinery/clonepod/proc/check_brine()
- // Clones are in a pickled bath of mild chemicals, keeping
- // them alive, despite their lack of internal organs
- for(var/bt in brine_types)
- if(occupant.reagents.get_reagent_amount(bt) < 1)
- occupant.reagents.add_reagent(bt, 1)
-
-/*
- * Manual -- A big ol' manual.
- */
-
-/obj/item/weapon/paper/Cloning
- name = "paper - 'H-87 Cloning Apparatus Manual"
- info = {"
Getting Started
- Congratulations, your station has purchased the H-87 industrial cloning device!
- Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
- That's all there is to it!
- Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.
- Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile.
- Profile Deletion has been restricted to \[Station Head\] level access.
- Cloning from a profile
- Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.
- Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.
-
- The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds.
- The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.
- Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.
- Profile Management
- The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES.
- These diskettes are used to transfer genetic information between machines and profiles.
- A load/save dialog will become available in each profile if a disk is inserted.
- A good diskette is a great way to counter aforementioned genetic drift!
-
- This technology produced under license from Thinktronic Systems, LTD."}
-
-#undef CLONE_INITIAL_DAMAGE
-#undef SPEAK
-#undef MINIMUM_HEAL_LEVEL
+//Cloning revival method.
+//The pod handles the actual cloning while the computer manages the clone profiles
+
+//Potential replacement for genetics revives or something I dunno (?)
+
+#define CLONE_INITIAL_DAMAGE 190 //Clones in clonepods start with 190 cloneloss damage and 190 brainloss damage, thats just logical
+#define MINIMUM_HEAL_LEVEL 40
+
+#define SPEAK(message) radio.talk_into(src, message, radio_channel, get_spans(), get_default_language())
+
+/obj/machinery/clonepod
+ anchored = 1
+ name = "cloning pod"
+ desc = "An electronically-lockable pod for growing organic tissue."
+ density = 1
+ icon = 'icons/obj/cloning.dmi'
+ icon_state = "pod_0"
+ req_access = list(GLOB.access_cloning) //For premature unlocking.
+ verb_say = "states"
+ var/heal_level //The clone is released once its health reaches this level.
+ var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
+ var/mess = FALSE //Need to clean out it if it's full of exploded clone.
+ var/attempting = FALSE //One clone attempt at a time thanks
+ var/speed_coeff
+ var/efficiency
+
+ var/datum/mind/clonemind
+ var/grab_ghost_when = CLONER_MATURE_CLONE
+
+ var/obj/item/device/radio/radio
+ var/radio_key = /obj/item/device/encryptionkey/headset_med
+ var/radio_channel = "Medical"
+
+ var/obj/effect/countdown/clonepod/countdown
+
+ var/list/unattached_flesh
+ var/flesh_number = 0
+
+ // The "brine" is the reagents that are automatically added in small
+ // amounts to the occupant.
+ var/static/list/brine_types = list(
+ "salbutamol", // anti-oxyloss
+ "bicaridine", // NOBREATHE species take brute in crit
+ "corazone", // prevents cardiac arrest damage
+ "mimesbane") // stops them gasping from lack of air.
+
+/obj/machinery/clonepod/New()
+ ..()
+ var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
+ B.apply_default_parts(src)
+
+ countdown = new(src)
+
+ radio = new(src)
+ radio.keyslot = new radio_key
+ radio.subspace_transmission = 1
+ radio.canhear_range = 0
+ radio.recalculateChannels()
+
+/obj/machinery/clonepod/Destroy()
+ go_out()
+ qdel(radio)
+ radio = null
+ qdel(countdown)
+ countdown = null
+ if(connected)
+ connected.DetachCloner(src)
+ for(var/i in unattached_flesh)
+ qdel(i)
+ LAZYCLEARLIST(unattached_flesh)
+ unattached_flesh = null
+ . = ..()
+
+/obj/machinery/clonepod/RefreshParts()
+ speed_coeff = 0
+ efficiency = 0
+ for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts)
+ efficiency += S.rating
+ for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
+ speed_coeff += P.rating
+ heal_level = (efficiency * 15) + 10
+ if(heal_level < MINIMUM_HEAL_LEVEL)
+ heal_level = MINIMUM_HEAL_LEVEL
+ if(heal_level > 100)
+ heal_level = 100
+
+/obj/item/weapon/circuitboard/machine/clonepod
+ name = "Clone Pod (Machine Board)"
+ build_path = /obj/machinery/clonepod
+ origin_tech = "programming=2;biotech=2"
+ req_components = list(
+ /obj/item/stack/cable_coil = 2,
+ /obj/item/weapon/stock_parts/scanning_module = 2,
+ /obj/item/weapon/stock_parts/manipulator = 2,
+ /obj/item/stack/sheet/glass = 1)
+
+//The return of data disks?? Just for transferring between genetics machine/cloning machine.
+//TO-DO: Make the genetics machine accept them.
+/obj/item/weapon/disk/data
+ name = "cloning data disk"
+ icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
+ var/list/fields = list()
+ var/read_only = 0 //Well,it's still a floppy disk
+
+//Disk stuff.
+/obj/item/weapon/disk/data/New()
+ ..()
+ icon_state = "datadisk[rand(0,6)]"
+ add_overlay("datadisk_gene")
+
+/obj/item/weapon/disk/data/attack_self(mob/user)
+ read_only = !read_only
+ to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].")
+
+/obj/item/weapon/disk/data/examine(mob/user)
+ ..()
+ to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
+
+
+//Clonepod
+
+/obj/machinery/clonepod/examine(mob/user)
+ ..()
+ var/mob/living/mob_occupant = occupant
+ if(mess)
+ to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
+ if(is_operational() && mob_occupant)
+ if(mob_occupant.stat != DEAD)
+ to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
+
+/obj/machinery/clonepod/return_air()
+ // We want to simulate the clone not being in contact with
+ // the atmosphere, so we'll put them in a constant pressure
+ // nitrogen. They'll breathe through the chemicals we pump into them.
+ var/static/datum/gas_mixture/immutable/cloner/GM //global so that there's only one instance made for all cloning pods
+ if(!GM)
+ GM = new
+ return GM
+
+/obj/machinery/clonepod/proc/get_completion()
+ . = FALSE
+ var/mob/living/mob_occupant = occupant
+ if(mob_occupant)
+ . = (100 * ((mob_occupant.health + 100) / (heal_level + 100)))
+
+/obj/machinery/clonepod/attack_ai(mob/user)
+ return examine(user)
+
+//Start growing a human clone in the pod!
+/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions)
+ if(panel_open)
+ return FALSE
+ if(mess || attempting)
+ return FALSE
+ clonemind = locate(mindref)
+ if(!istype(clonemind)) //not a mind
+ return FALSE
+ if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body
+ 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(clonemind.damnation_type) //Can't clone the damned.
+ INVOKE_ASYNC(src, .proc/horrifyingsound)
+ mess = TRUE
+ icon_state = "pod_g"
+ update_icon()
+ return FALSE
+
+ attempting = TRUE //One at a time!!
+ countdown.start()
+
+ var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
+
+ if(clonemind.changeling)
+ var/obj/item/organ/brain/B = H.getorganslot("brain")
+ B.vital = FALSE
+ B.decoy_override = TRUE
+
+ H.hardset_dna(ui, se, H.real_name, null, 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.randmutvg()
+ if(efficiency < 3 && prob(50))
+ var/mob/M = H.randmutb()
+ 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(0,999)])"
+ H.real_name = clonename
+
+ icon_state = "pod_1"
+ //Get the clone body ready
+ maim_clone(H)
+ check_brine() // put in chemicals NOW to stop death via cardiac arrest
+ H.Paralyse(4)
+
+ clonemind.transfer_to(H)
+
+ 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
+
+//Grow clones to maturity then kick them out. FREELOADERS
+/obj/machinery/clonepod/process()
+ var/mob/living/mob_occupant = occupant
+
+ if(!is_operational()) //Autoeject if power is lost
+ if(mob_occupant)
+ go_out()
+ connected_message("Clone Ejected: Loss of power.")
+
+ else if(mob_occupant && (mob_occupant.loc == src))
+ if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
+ connected_message("Clone Rejected: Deceased.")
+ SPEAK("The cloning of [mob_occupant.real_name] has been \
+ aborted due to unrecoverable tissue failure.")
+ go_out()
+
+ else if(mob_occupant.cloneloss > (100 - heal_level))
+ mob_occupant.Paralyse(4)
+
+ //Slowly get that clone healed and finished.
+ mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
+ var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
+ // To avoid the default cloner making incomplete clones
+ progress += (100 - MINIMUM_HEAL_LEVEL)
+ var/milestone = CLONE_INITIAL_DAMAGE / flesh_number
+ var/installed = flesh_number - unattached_flesh.len
+
+ if((progress / milestone) >= installed)
+ // attach some flesh
+ var/obj/item/I = pick_n_take(unattached_flesh)
+ if(isorgan(I))
+ var/obj/item/organ/O = I
+ O.Insert(mob_occupant)
+ else if(isbodypart(I))
+ var/obj/item/bodypart/BP = I
+ BP.attach_limb(mob_occupant)
+
+ //Premature clones may have brain damage.
+ mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
+
+ check_brine()
+
+ use_power(7500) //This might need tweaking.
+
+ else if((mob_occupant.cloneloss <= (100 - heal_level)))
+ connected_message("Cloning Process Complete.")
+ SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.")
+
+ // If the cloner is upgraded to debugging high levels, sometimes
+ // organs and limbs can be missing.
+ for(var/i in unattached_flesh)
+ if(isorgan(i))
+ var/obj/item/organ/O = i
+ O.Insert(mob_occupant)
+ else if(isbodypart(i))
+ var/obj/item/bodypart/BP = i
+ BP.attach_limb(mob_occupant)
+
+ go_out()
+
+ else if (!mob_occupant || mob_occupant.loc != src)
+ occupant = null
+ if (!mess && !panel_open)
+ icon_state = "pod_0"
+ use_power(200)
+
+//Let's unlock this early I guess. Might be too early, needs tweaking.
+/obj/machinery/clonepod/attackby(obj/item/weapon/W, mob/user, params)
+ if(!(occupant || mess))
+ if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W))
+ return
+
+ if(exchange_parts(user, W))
+ return
+
+ if(default_deconstruction_crowbar(W))
+ return
+
+ if(istype(W,/obj/item/device/multitool))
+ var/obj/item/device/multitool/P = W
+
+ if(istype(P.buffer, /obj/machinery/computer/cloning))
+ 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/computer/cloning/comp = P.buffer
+ if(connected)
+ connected.DetachCloner(src)
+ comp.AttachCloner(src)
+ else
+ P.buffer = src
+ to_chat(user, "-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-")
+ return
+
+ var/mob/living/mob_occupant = occupant
+ if(W.GetID())
+ if(!check_access(W))
+ to_chat(user, "Access Denied.")
+ return
+ if(!(mob_occupant || mess))
+ to_chat(user, "Error: Pod has no occupant.")
+ return
+ else
+ connected_message("Authorized Ejection")
+ SPEAK("An authorized ejection of [clonemind.name] has occurred.")
+ to_chat(user, "You force an emergency ejection. ")
+ go_out()
+ else
+ return ..()
+
+/obj/machinery/clonepod/emag_act(mob/user)
+ if(!occupant)
+ return
+ to_chat(user, "You corrupt the genetic compiler.")
+ malfunction()
+
+//Put messages in the connected computer's temp var for display.
+/obj/machinery/clonepod/proc/connected_message(message)
+ if ((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning)))
+ return FALSE
+ if (!message)
+ return FALSE
+
+ connected.temp = message
+ connected.updateUsrDialog()
+ return TRUE
+
+/obj/machinery/clonepod/proc/go_out()
+ countdown.stop()
+ var/mob/living/mob_occupant = occupant
+
+ if(mess) //Clean that mess and dump those gibs!
+ mess = FALSE
+ new /obj/effect/gibspawner/generic(loc)
+ audible_message("You hear a splat.")
+ icon_state = "pod_0"
+ return
+
+ if(!mob_occupant)
+ return
+
+
+ if(grab_ghost_when == CLONER_MATURE_CLONE)
+ mob_occupant.grab_ghost()
+ to_chat(occupant, "There is a bright flash!
You feel like a new being.")
+ mob_occupant.flash_act()
+
+ var/turf/T = get_turf(src)
+ occupant.forceMove(T)
+ icon_state = "pod_0"
+ mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
+
+ occupant = null
+
+/obj/machinery/clonepod/proc/malfunction()
+ var/mob/living/mob_occupant = occupant
+ if(mob_occupant)
+ connected_message("Critical Error!")
+ SPEAK("Critical error! Please contact a Thinktronic Systems \
+ technician, as your warranty may be affected.")
+ mess = TRUE
+ for(var/obj/item/O in unattached_flesh)
+ qdel(O)
+ icon_state = "pod_g"
+ if(mob_occupant.mind != clonemind)
+ clonemind.transfer_to(mob_occupant)
+ mob_occupant.grab_ghost() // We really just want to make you suffer.
+ flash_color(mob_occupant, flash_color="#960000", flash_time=100)
+ to_chat(mob_occupant, "Agony blazes across your consciousness as your body is torn apart.
Is this what dying is like? Yes it is.")
+ playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
+ mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
+ QDEL_IN(mob_occupant, 40)
+
+/obj/machinery/clonepod/relaymove(mob/user)
+ if(user.stat == CONSCIOUS)
+ go_out()
+
+/obj/machinery/clonepod/emp_act(severity)
+ var/mob/living/mob_occupant = occupant
+ if(mob_occupant && prob(100/(severity*efficiency)))
+ connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
+ SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
+ go_out()
+ ..()
+
+/obj/machinery/clonepod/ex_act(severity, target)
+ ..()
+ if(!QDELETED(src))
+ go_out()
+
+/obj/machinery/clonepod/handle_atom_del(atom/A)
+ if(A == occupant)
+ occupant = null
+ countdown.stop()
+
+/obj/machinery/clonepod/proc/horrifyingsound()
+ for(var/i in 1 to 5)
+ playsound(loc,pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 100, rand(0.95,1.05))
+ sleep(1)
+ sleep(10)
+ playsound(loc,'sound/hallucinations/wail.ogg',100,1)
+
+/obj/machinery/clonepod/deconstruct(disassembled = TRUE)
+ if(occupant)
+ go_out()
+ ..()
+
+/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H)
+ if(!unattached_flesh)
+ unattached_flesh = list()
+ else
+ for(var/fl in unattached_flesh)
+ qdel(fl)
+ unattached_flesh.Cut()
+
+ H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
+ H.setBrainLoss(CLONE_INITIAL_DAMAGE)
+ // In addition to being cellularly damaged and having barely any
+ // brain function, they also have no limbs or internal organs.
+ var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
+ for(var/zone in zones)
+ var/obj/item/bodypart/BP = H.get_bodypart(zone)
+ BP.drop_limb()
+ BP.forceMove(src)
+ unattached_flesh += BP
+
+ for(var/o in H.internal_organs)
+ var/obj/item/organ/organ = o
+ if(!istype(organ) || organ.vital)
+ continue
+ organ.Remove(H, special=TRUE)
+ organ.forceMove(src)
+ unattached_flesh += organ
+
+ flesh_number = unattached_flesh.len
+
+/obj/machinery/clonepod/proc/check_brine()
+ // Clones are in a pickled bath of mild chemicals, keeping
+ // them alive, despite their lack of internal organs
+ for(var/bt in brine_types)
+ if(occupant.reagents.get_reagent_amount(bt) < 1)
+ occupant.reagents.add_reagent(bt, 1)
+
+/*
+ * Manual -- A big ol' manual.
+ */
+
+/obj/item/weapon/paper/Cloning
+ name = "paper - 'H-87 Cloning Apparatus Manual"
+ info = {"Getting Started
+ Congratulations, your station has purchased the H-87 industrial cloning device!
+ Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
+ That's all there is to it!
+ Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.
+ Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile.
+ Profile Deletion has been restricted to \[Station Head\] level access.
+ Cloning from a profile
+ Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.
+ Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.
+
+ The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds.
+ The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.
+ Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.
+ Profile Management
+ The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES.
+ These diskettes are used to transfer genetic information between machines and profiles.
+ A load/save dialog will become available in each profile if a disk is inserted.
+ A good diskette is a great way to counter aforementioned genetic drift!
+
+ This technology produced under license from Thinktronic Systems, LTD."}
+
+#undef CLONE_INITIAL_DAMAGE
+#undef SPEAK
+#undef MINIMUM_HEAL_LEVEL
\ No newline at end of file
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index f20e92b721..9e367d43b1 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -1,4 +1,3 @@
-
/obj/machinery/computer/cloning
name = "cloning console"
desc = "Used to clone people and manage DNA."
@@ -61,7 +60,7 @@
return
if(scanner.occupant && scanner.scan_level > 2)
- scan_mob(scanner.occupant)
+ scan_occupant(scanner.occupant)
for(var/datum/data/record/R in records)
var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields["mind"])
@@ -185,8 +184,7 @@
// Scanner
if (!isnull(src.scanner))
-
- var/mob/living/scanner_occupant = scanner.occupant
+ var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
dat += "Scanner Functions
"
@@ -303,7 +301,7 @@
say("Initiating scan...")
spawn(20)
- src.scan_mob(scanner.occupant)
+ src.scan_occupant(scanner.occupant)
loading = 0
src.updateUsrDialog()
@@ -435,64 +433,70 @@
src.updateUsrDialog()
return
-/obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject)
- if (!istype(subject))
+/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
+ var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
+ var/datum/dna/dna
+ if(iscarbon(mob_occupant))
+ var/mob/living/carbon/C = mob_occupant
+ dna = C.has_dna()
+ if(istype(mob_occupant, /mob/living/brain))
+ 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 (!subject.getorgan(/obj/item/organ/brain))
- scantemp = "No signs of intelligence detected."
- playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
- return
- if (subject.suiciding == 1 || subject.hellbound)
+ 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 ((subject.disabilities & NOCLONE) && (src.scanner.scan_level < 2))
+ if((mob_occupant.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_alert.ogg', 50, 0)
return
- if ((!subject.ckey) || (!subject.client))
+ 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", subject.ckey, records))
+ if (find_record("ckey", mob_occupant.ckey, records))
scantemp = "Subject already in database."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
var/datum/data/record/R = new()
- if(subject.dna.species)
+ if(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
+ R.fields["mrace"] = 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
+ R.fields["ckey"] = mob_occupant.ckey
+ R.fields["name"] = mob_occupant.real_name
+ R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6)
+ R.fields["UE"] = dna.unique_enzymes
+ R.fields["UI"] = dna.uni_identity
+ R.fields["SE"] = dna.struc_enzymes
+ R.fields["blood_type"] = dna.blood_type
+ R.fields["features"] = dna.features
+ R.fields["factions"] = mob_occupant.faction
+
+ if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
+ R.fields["mind"] = "\ref[mob_occupant.mind]"
+
+ //Add an implant if needed
var/obj/item/weapon/implant/health/imp
- for(var/obj/item/weapon/implant/health/HI in subject.implants)
+ for(var/obj/item/weapon/implant/health/HI in mob_occupant.implants)
imp = HI
break
if(!imp)
- imp = new /obj/item/weapon/implant/health(subject)
- imp.implant(subject)
+ imp = new /obj/item/weapon/implant/health(mob_occupant)
+ imp.implant(mob_occupant)
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_prompt_confirm.ogg', 50, 0)
diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm
index d572b3e9dc..e5785e0dab 100644
--- a/code/game/machinery/dna_scanner.dm
+++ b/code/game/machinery/dna_scanner.dm
@@ -9,6 +9,7 @@
use_power = 1
idle_power_usage = 50
active_power_usage = 300
+ occupant_typecache = list(/mob/living, /obj/item/bodypart/head, /obj/item/organ/brain)
var/damage_coeff
var/scan_level
var/precision_coeff
@@ -98,6 +99,13 @@
open_machine()
+/obj/machinery/dna_scannernew/proc/locate_computer(type_)
+ for(dir in list(NORTH,EAST,SOUTH,WEST))
+ var/C = locate(type_, get_step(src, dir))
+ if(C)
+ return C
+ return null
+
/obj/machinery/dna_scannernew/close_machine()
if(!state_open)
return 0
@@ -105,22 +113,19 @@
..()
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
- var/mob/living/mob_occupant = occupant
- if(mob_occupant)
- if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
- || locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \
- || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \
- || locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
+ var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
+ if(istype(mob_occupant))
+ if(locate_computer(/obj/machinery/computer/cloning))
if(!mob_occupant.suiciding && !(mob_occupant.disabilities & NOCLONE) && !mob_occupant.hellbound)
mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
- var/obj/machinery/computer/scan_consolenew/console
- for(dir in list(NORTH,EAST,SOUTH,WEST))
- console = locate(/obj/machinery/computer/scan_consolenew, get_step(src, dir))
- if(console)
- console.on_scanner_close()
- break
- return 1
+ // DNA manipulators cannot operate on severed heads or brains
+ if(isliving(occupant))
+ var/obj/machinery/computer/scan_consolenew/console = locate_computer(/obj/machinery/computer/scan_consolenew)
+ if(console)
+ console.on_scanner_close()
+
+ return TRUE
/obj/machinery/dna_scannernew/open_machine()
if(state_open)
@@ -158,4 +163,4 @@
if(..(user,1,0)) //don't set the machine, since there's no dialog
return
- toggle_open(user)
+ toggle_open(user)
\ No newline at end of file
diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm
index 1f74ed1917..11700b7638 100644
--- a/code/modules/mob/living/brain/brain.dm
+++ b/code/modules/mob/living/brain/brain.dm
@@ -1,5 +1,3 @@
-
-
/mob/living/brain
var/obj/item/device/mmi/container = null
var/timeofhostdeath = 0