mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-17 17:16:50 +01:00
659 lines
22 KiB
Plaintext
659 lines
22 KiB
Plaintext
//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_BIOMASS 150
|
|
|
|
#define BIOMASS_BASE_AMOUNT 50 // How much biomass a BIOMASSABLE item gives the cloning pod
|
|
|
|
// Not a comprehensive list: Further PRs should add appropriate items here.
|
|
// Meat as usual, monstermeat covers goliath, xeno, spider, bear meat
|
|
GLOBAL_LIST_INIT(cloner_biomass_items, list(\
|
|
/obj/item/reagent_containers/food/snacks/meat,\
|
|
/obj/item/reagent_containers/food/snacks/monstermeat,
|
|
/obj/item/reagent_containers/food/snacks/carpmeat,
|
|
/obj/item/reagent_containers/food/snacks/salmonmeat,
|
|
/obj/item/reagent_containers/food/snacks/catfishmeat,
|
|
/obj/item/reagent_containers/food/snacks/tofurkey))
|
|
|
|
#define MINIMUM_HEAL_LEVEL 40
|
|
#define CLONE_INITIAL_DAMAGE 190
|
|
#define BRAIN_INITIAL_DAMAGE 90 // our minds are too feeble for 190
|
|
|
|
/obj/machinery/clonepod
|
|
anchored = TRUE
|
|
name = "cloning pod"
|
|
desc = "An electronically-lockable pod for growing organic tissue."
|
|
density = TRUE
|
|
icon = 'icons/obj/cloning.dmi'
|
|
icon_state = "pod_idle"
|
|
req_access = list(ACCESS_MEDICAL) //For premature unlocking.
|
|
|
|
var/mob/living/carbon/human/occupant
|
|
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/biomass = 0
|
|
var/speed_coeff
|
|
var/efficiency
|
|
|
|
var/datum/mind/clonemind
|
|
var/grab_ghost_when = CLONER_MATURE_CLONE
|
|
|
|
var/obj/item/radio/Radio
|
|
var/radio_announce = TRUE
|
|
|
|
var/obj/effect/countdown/clonepod/countdown
|
|
|
|
var/list/brine_types = list("corazone", "perfluorodecalin", "epinephrine", "salglu_solution") //stops heart attacks, heart failure, shock, and keeps their O2 levels normal
|
|
var/list/missing_organs = list()
|
|
var/organs_number = 0
|
|
|
|
light_color = LIGHT_COLOR_PURE_GREEN
|
|
|
|
/obj/machinery/clonepod/power_change()
|
|
..() //we don't check return here because we also care about the BROKEN flag
|
|
if(!(stat & (BROKEN|NOPOWER)))
|
|
set_light(2)
|
|
else
|
|
set_light(0)
|
|
|
|
/obj/machinery/clonepod/biomass
|
|
biomass = CLONE_BIOMASS
|
|
|
|
/obj/machinery/clonepod/Initialize(mapload)
|
|
. = ..()
|
|
countdown = new(src)
|
|
|
|
Radio = new /obj/item/radio(src)
|
|
Radio.listening = FALSE
|
|
Radio.config(list("Medical" = 0))
|
|
Radio.follow_target = src
|
|
|
|
component_parts = list()
|
|
component_parts += new /obj/item/circuitboard/clonepod(null)
|
|
component_parts += new /obj/item/stock_parts/scanning_module(null)
|
|
component_parts += new /obj/item/stock_parts/scanning_module(null)
|
|
component_parts += new /obj/item/stock_parts/manipulator(null)
|
|
component_parts += new /obj/item/stock_parts/manipulator(null)
|
|
component_parts += new /obj/item/stack/sheet/glass(null)
|
|
component_parts += new /obj/item/stack/cable_coil(null, 1)
|
|
component_parts += new /obj/item/stack/cable_coil(null, 1)
|
|
RefreshParts()
|
|
update_icon()
|
|
|
|
/obj/machinery/clonepod/upgraded/Initialize(mapload)
|
|
. = ..()
|
|
component_parts = list()
|
|
component_parts += new /obj/item/circuitboard/clonepod(null)
|
|
component_parts += new /obj/item/stock_parts/scanning_module/phasic(null)
|
|
component_parts += new /obj/item/stock_parts/scanning_module/phasic(null)
|
|
component_parts += new /obj/item/stock_parts/manipulator/pico(null)
|
|
component_parts += new /obj/item/stock_parts/manipulator/pico(null)
|
|
component_parts += new /obj/item/stack/sheet/glass(null)
|
|
component_parts += new /obj/item/stack/cable_coil(null, 1)
|
|
component_parts += new /obj/item/stack/cable_coil(null, 1)
|
|
biomass = CLONE_BIOMASS
|
|
RefreshParts()
|
|
|
|
/obj/machinery/clonepod/Destroy()
|
|
if(connected)
|
|
connected.pods -= src
|
|
connected = null
|
|
if(clonemind)
|
|
UnregisterSignal(clonemind.current, COMSIG_LIVING_REVIVE)
|
|
UnregisterSignal(clonemind, COMSIG_MIND_TRANSER_TO)
|
|
QDEL_NULL(Radio)
|
|
QDEL_NULL(countdown)
|
|
QDEL_LIST_CONTENTS(missing_organs)
|
|
return ..()
|
|
|
|
/obj/machinery/clonepod/RefreshParts()
|
|
speed_coeff = 0
|
|
efficiency = 0
|
|
for(var/obj/item/stock_parts/scanning_module/S in component_parts)
|
|
efficiency += S.rating
|
|
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
|
speed_coeff += P.rating
|
|
heal_level = max(min((efficiency * 15) + 10, 100), MINIMUM_HEAL_LEVEL)
|
|
|
|
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
|
|
//TO-DO: Make the genetics machine accept them.
|
|
/obj/item/disk/data
|
|
name = "Genetics Data Disk"
|
|
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
|
|
var/datum/dna2/record/buf = null
|
|
var/read_only = FALSE //Well,it's still a floppy disk
|
|
|
|
/obj/item/disk/data/proc/initialize()
|
|
buf = new
|
|
buf.dna=new
|
|
|
|
/obj/item/disk/data/Destroy()
|
|
QDEL_NULL(buf)
|
|
return ..()
|
|
|
|
/obj/item/disk/data/demo
|
|
name = "data disk - 'God Emperor of Mankind'"
|
|
read_only = TRUE
|
|
|
|
/obj/item/disk/data/demo/New()
|
|
..()
|
|
initialize()
|
|
buf.types=DNA2_BUF_UE|DNA2_BUF_UI
|
|
//data = "066000033000000000AF00330660FF4DB002690"
|
|
//data = "0C80C80C80C80C80C8000000000000161FBDDEF" - Farmer Jeff
|
|
buf.dna.real_name="God Emperor of Mankind"
|
|
buf.dna.unique_enzymes = md5(buf.dna.real_name)
|
|
buf.dna.UI=list(0x066,0x000,0x033,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0xAF0,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x033,0x066,0x0FF,0x4DB,0x002,0x690,0x000,0x000,0x000,0x328,0x045,0x5FC,0x053,0x035,0x035,0x035)
|
|
//buf.dna.UI=list(0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x000,0x000,0x000,0x000,0x161,0xFBD,0xDEF) // Farmer Jeff
|
|
if(buf.dna.UI.len != DNA_UI_LENGTH) //If there's a disparity b/w the dna UI string lengths, 0-fill the extra blocks in this UI.
|
|
for(var/i in buf.dna.UI.len to DNA_UI_LENGTH)
|
|
buf.dna.UI += 0x000
|
|
buf.dna.ResetSE()
|
|
buf.dna.UpdateUI()
|
|
|
|
/obj/item/disk/data/monkey
|
|
name = "data disk - 'Mr. Muggles'"
|
|
read_only = 1
|
|
|
|
/obj/item/disk/data/monkey/New()
|
|
..()
|
|
initialize()
|
|
buf.types=DNA2_BUF_SE
|
|
var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
|
|
for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++)
|
|
new_SE += rand(1,1024)
|
|
buf.dna.SE=new_SE
|
|
buf.dna.SetSEValueRange(GLOB.monkeyblock,0xDAC, 0xFFF)
|
|
|
|
//Disk stuff.
|
|
/obj/item/disk/data/New()
|
|
..()
|
|
var/diskcolor = pick(0,1,2)
|
|
icon_state = "datadisk[diskcolor]"
|
|
|
|
/obj/item/disk/data/attack_self(mob/user as mob)
|
|
read_only = !read_only
|
|
to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].")
|
|
|
|
/obj/item/disk/data/examine(mob/user)
|
|
. = ..()
|
|
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
|
|
|
|
//Clonepod
|
|
|
|
/obj/machinery/clonepod/examine(mob/user)
|
|
. = ..()
|
|
if(mess)
|
|
. += "It's filled with blood and viscera. You swear you can see it moving..."
|
|
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
|
. += "<span class='warning'>Yellow ooze is dripping out of the synthmeat storage chamber...</span>"
|
|
if(!occupant || stat & (NOPOWER|BROKEN))
|
|
return
|
|
if(occupant && occupant.stat != DEAD)
|
|
. += "Current clone cycle is [round(get_completion())]% complete."
|
|
|
|
/obj/machinery/clonepod/return_air() //non-reactive air
|
|
RETURN_TYPE(/datum/gas_mixture)
|
|
var/datum/gas_mixture/GM = new
|
|
GM.nitrogen = MOLES_O2STANDARD + MOLES_N2STANDARD
|
|
GM.temperature = T20C
|
|
return GM
|
|
|
|
/obj/machinery/clonepod/proc/get_completion()
|
|
. = (100 * ((occupant.health + 100) / (heal_level + 100)))
|
|
|
|
/obj/machinery/clonepod/attack_ai(mob/user)
|
|
return examine(user)
|
|
|
|
//Radio Announcement
|
|
|
|
/obj/machinery/clonepod/proc/announce_radio_message(message)
|
|
if(radio_announce)
|
|
Radio.autosay(message, name, "Medical", list(z))
|
|
|
|
//Start growing a human clone in the pod!
|
|
/obj/machinery/clonepod/proc/growclone(datum/dna2/record/R)
|
|
if(mess || attempting || panel_open || stat & (NOPOWER|BROKEN))
|
|
return 0
|
|
clonemind = locate(R.mind)
|
|
if(!istype(clonemind)) //not a mind
|
|
return 0
|
|
if(clonemind.current && clonemind.current.stat != DEAD) //mind is associated with a non-dead body
|
|
return 0
|
|
if(clonemind.active) //somebody is using that mind
|
|
if(ckey(clonemind.key) != R.ckey )
|
|
return 0
|
|
if(clonemind.suicided) // and stay out!
|
|
malfunction(go_easy = 0)
|
|
return -1 // Flush the record
|
|
else
|
|
// get_ghost() will fail if they're unable to reenter their body
|
|
var/mob/dead/observer/G = clonemind.get_ghost()
|
|
if(!G)
|
|
return 0
|
|
|
|
if(biomass >= CLONE_BIOMASS)
|
|
biomass -= CLONE_BIOMASS
|
|
else
|
|
return 0
|
|
|
|
attempting = TRUE //One at a time!!
|
|
countdown.start()
|
|
|
|
if(!R.dna)
|
|
R.dna = new /datum/dna()
|
|
|
|
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
|
|
H.set_species(R.dna.species.type)
|
|
occupant = H
|
|
|
|
if(!R.dna.real_name) //to prevent null names
|
|
R.dna.real_name = H.real_name
|
|
else
|
|
H.real_name = R.dna.real_name
|
|
|
|
H.dna = R.dna.Clone()
|
|
|
|
for(var/datum/language/L in R.languages)
|
|
H.add_language(L.name)
|
|
|
|
domutcheck(H, MUTCHK_FORCED) //Ensures species that get powers by the species proc handle_dna keep them
|
|
|
|
if(efficiency > 2 && efficiency < 5 && prob(25))
|
|
randmutb(H)
|
|
if(efficiency > 5 && prob(20))
|
|
randmutg(H)
|
|
if(efficiency < 3 && prob(50))
|
|
randmutb(H)
|
|
|
|
H.dna.UpdateSE()
|
|
H.dna.UpdateUI()
|
|
|
|
H.sync_organ_dna(1) // It's literally a fresh body as you can get, so all organs properly belong to it
|
|
H.UpdateAppearance()
|
|
|
|
check_brine()
|
|
//Get the clone body ready
|
|
maim_clone(H)
|
|
H.Paralyse(8 SECONDS)
|
|
|
|
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
|
clonemind.transfer_to(H)
|
|
H.ckey = R.ckey
|
|
update_clone_antag(H) //Since the body's got the mind, update their antag stuff right now. Otherwise, wait until they get kicked out (as per the CLONER_MATURE_CLONE business) to do it.
|
|
var/message
|
|
message += "<b>Consciousness slowly creeps over you as your body regenerates.</b><br>"
|
|
message += "<i>So this is what cloning feels like?</i>"
|
|
to_chat(H, "<span class='notice'>[message]</span>")
|
|
else if(grab_ghost_when == CLONER_MATURE_CLONE)
|
|
to_chat(clonemind.current, "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
|
|
// Set up a soul link with the dead body to catch a revival
|
|
RegisterSignal(clonemind.current, COMSIG_LIVING_REVIVE, PROC_REF(occupant_got_revived))
|
|
RegisterSignal(clonemind, COMSIG_MIND_TRANSER_TO, PROC_REF(occupant_got_revived))
|
|
|
|
SSblackbox.record_feedback("tally", "players_revived", 1, "cloned")
|
|
update_icon()
|
|
|
|
H.suiciding = FALSE
|
|
attempting = FALSE
|
|
return 1
|
|
|
|
//Grow clones to maturity then kick them out. FREELOADERS
|
|
/obj/machinery/clonepod/process()
|
|
var/show_message = FALSE
|
|
for(var/obj/item/item in range(1, src))
|
|
if(is_type_in_list(item, GLOB.cloner_biomass_items))
|
|
qdel(item)
|
|
biomass += BIOMASS_BASE_AMOUNT
|
|
show_message = TRUE
|
|
if(show_message)
|
|
visible_message("[src] sucks in and processes the nearby biomass.")
|
|
|
|
if(stat & NOPOWER) //Autoeject if power is lost
|
|
if(occupant)
|
|
go_out()
|
|
connected_message("Clone Ejected: Loss of power.")
|
|
|
|
else if((occupant) && (occupant.loc == src))
|
|
if((occupant.stat == DEAD) || (occupant.suiciding)) //Autoeject corpses and suiciding dudes.
|
|
announce_radio_message("The cloning of <b>[occupant]</b> has been aborted due to unrecoverable tissue failure.")
|
|
go_out()
|
|
connected_message("Clone Rejected: Deceased.")
|
|
|
|
else if(occupant.cloneloss > (100 - heal_level))
|
|
occupant.Paralyse(8 SECONDS)
|
|
|
|
//Slowly get that clone healed and finished.
|
|
occupant.adjustCloneLoss(-((speed_coeff/2)))
|
|
|
|
// For human species that lack non-vital parts for some weird reason
|
|
if(organs_number)
|
|
var/progress = CLONE_INITIAL_DAMAGE - occupant.getCloneLoss()
|
|
progress += (100 - MINIMUM_HEAL_LEVEL)
|
|
var/milestone = CLONE_INITIAL_DAMAGE / organs_number
|
|
// Doing this as a #define so that the value can change when evaluated multiple times
|
|
#define INSTALLED (organs_number - length(missing_organs))
|
|
|
|
while((progress / milestone) > INSTALLED && length(missing_organs))
|
|
var/obj/item/organ/I = pick_n_take(missing_organs)
|
|
I.safe_replace(occupant)
|
|
|
|
#undef INSTALLED
|
|
|
|
//Premature clones may have brain damage.
|
|
occupant.adjustBrainLoss(-((speed_coeff/20)*efficiency))
|
|
|
|
check_brine()
|
|
|
|
//Also heal some oxyloss ourselves just in case!!
|
|
occupant.adjustOxyLoss(-10)
|
|
|
|
use_power(7500) //This might need tweaking.
|
|
|
|
else if((occupant.cloneloss <= (100 - heal_level)))
|
|
connected_message("Cloning Process Complete.")
|
|
announce_radio_message("The cloning cycle of <b>[occupant]</b> is complete.")
|
|
go_out()
|
|
|
|
else if((!occupant) || (occupant.loc != src))
|
|
occupant = null
|
|
update_icon()
|
|
use_power(200)
|
|
|
|
//Let's unlock this early I guess. Might be too early, needs tweaking.
|
|
/obj/machinery/clonepod/attackby(obj/item/I, mob/user, params)
|
|
if(exchange_parts(user, I))
|
|
return
|
|
|
|
if(I.GetID())
|
|
if(!check_access(I))
|
|
to_chat(user, "<span class='danger'>Access Denied.</span>")
|
|
return
|
|
if(!(occupant || mess))
|
|
to_chat(user, "<span class='danger'>Error: Pod has no occupant.</span>")
|
|
return
|
|
else
|
|
connected_message("Authorized Ejection")
|
|
announce_radio_message("An authorized ejection of [(occupant) ? occupant.real_name : "the malfunctioning pod"] has occurred")
|
|
to_chat(user, "<span class='notice'>You force an emergency ejection.</span>")
|
|
go_out()
|
|
|
|
// A user can feed in biomass sources manually.
|
|
else if(is_type_in_list(I, GLOB.cloner_biomass_items))
|
|
if(user.drop_item())
|
|
to_chat(user, "<span class='notice'>[src] processes [I].</span>")
|
|
biomass += BIOMASS_BASE_AMOUNT
|
|
qdel(I)
|
|
else
|
|
return ..()
|
|
|
|
/obj/machinery/clonepod/crowbar_act(mob/user, obj/item/I)
|
|
. = TRUE
|
|
default_deconstruction_crowbar(user, I)
|
|
|
|
/obj/machinery/clonepod/multitool_act(mob/user, obj/item/I)
|
|
. = TRUE
|
|
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
|
return
|
|
if(!I.multitool_check_buffer(user))
|
|
return
|
|
var/obj/item/multitool/M = I
|
|
M.set_multitool_buffer(user, src)
|
|
|
|
/obj/machinery/clonepod/screwdriver_act(mob/user, obj/item/I)
|
|
. = TRUE
|
|
// These icon states don't really matter since we need to call update_icon() to handle panel open/closed overlays anyway.
|
|
default_deconstruction_screwdriver(user, null, null, I)
|
|
update_icon()
|
|
|
|
/obj/machinery/clonepod/wrench_act(mob/user, obj/item/I)
|
|
. = TRUE
|
|
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
|
return
|
|
if(occupant)
|
|
to_chat(user, "<span class='warning'>Can not do that while [src] is in use.</span>")
|
|
return
|
|
if(anchored)
|
|
WRENCH_UNANCHOR_MESSAGE
|
|
anchored = FALSE
|
|
connected.pods -= src
|
|
connected = null
|
|
else
|
|
WRENCH_ANCHOR_MESSAGE
|
|
anchored = TRUE
|
|
|
|
/obj/machinery/clonepod/emag_act(user)
|
|
malfunction()
|
|
|
|
/obj/machinery/clonepod/cmag_act(mob/user)
|
|
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
|
return
|
|
playsound(src, "sparks", 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
|
to_chat(user, "<span class='warning'>A droplet of bananium ooze seeps into the synthmeat storage chamber...</span>")
|
|
ADD_TRAIT(src, TRAIT_CMAGGED, CLOWN_EMAG)
|
|
|
|
/obj/machinery/clonepod/proc/update_clone_antag(mob/living/carbon/human/H)
|
|
// Check to see if the clone's mind is an antagonist of any kind and handle them accordingly to make sure they get their spells, HUD/whatever else back.
|
|
if(H.mind in SSticker.mode.syndicates)
|
|
SSticker.mode.update_synd_icons_added()
|
|
if(H.mind in SSticker.mode.cult)
|
|
SSticker.mode.update_cult_icons_added(H.mind) // Adds the cult antag hud
|
|
SSticker.mode.add_cult_actions(H.mind) // And all the actions
|
|
if(SSticker.mode.cult_risen)
|
|
SSticker.mode.rise(H)
|
|
if(SSticker.mode.cult_ascendant)
|
|
SSticker.mode.ascend(H)
|
|
|
|
//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 = "[name] : [message]"
|
|
connected.updateUsrDialog()
|
|
return TRUE
|
|
|
|
/obj/machinery/clonepod/proc/go_out()
|
|
countdown.stop()
|
|
var/turf/T = get_turf(src)
|
|
if(mess) //Clean that mess and dump those gibs!
|
|
for(var/i in missing_organs)
|
|
var/obj/I = i
|
|
I.forceMove(T)
|
|
missing_organs.Cut()
|
|
mess = FALSE
|
|
new /obj/effect/gibspawner/generic(get_turf(src), occupant)
|
|
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
|
|
update_icon()
|
|
return
|
|
|
|
if(!occupant)
|
|
return
|
|
|
|
if(grab_ghost_when == CLONER_MATURE_CLONE)
|
|
UnregisterSignal(clonemind.current, COMSIG_LIVING_REVIVE)
|
|
UnregisterSignal(clonemind, COMSIG_MIND_TRANSER_TO)
|
|
clonemind.transfer_to(occupant)
|
|
occupant.grab_ghost()
|
|
update_clone_antag(occupant)
|
|
to_chat(occupant, "<span class='userdanger'>You remember nothing from the time that you were dead!</span>")
|
|
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br>\
|
|
<i>You feel like a new being.</i></span>")
|
|
if(HAS_TRAIT(src, TRAIT_CMAGGED))
|
|
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1)
|
|
occupant.dna.SetSEState(GLOB.clumsyblock, TRUE, FALSE)
|
|
occupant.dna.SetSEState(GLOB.comicblock, TRUE, FALSE)
|
|
singlemutcheck(occupant, GLOB.clumsyblock, MUTCHK_FORCED)
|
|
singlemutcheck(occupant, GLOB.comicblock, MUTCHK_FORCED)
|
|
occupant.dna.default_blocks.Add(GLOB.clumsyblock) //Until Genetics fixes you, this is your life now
|
|
occupant.dna.default_blocks.Add(GLOB.comicblock)
|
|
occupant.flash_eyes(visual = 1)
|
|
clonemind = null
|
|
|
|
|
|
QDEL_LIST_CONTENTS(missing_organs)
|
|
occupant.SetLoseBreath(0) // Stop friggin' dying, gosh damn
|
|
occupant.setOxyLoss(0)
|
|
for(var/datum/disease/critical/crit in occupant.viruses)
|
|
crit.cure()
|
|
occupant.forceMove(T)
|
|
occupant.update_body()
|
|
domutcheck(occupant) //Waiting until they're out before possible notransform.
|
|
occupant.special_post_clone_handling()
|
|
occupant = null
|
|
update_icon()
|
|
|
|
/obj/machinery/clonepod/proc/malfunction(go_easy = FALSE)
|
|
if(occupant)
|
|
connected_message("Critical Error!")
|
|
announce_radio_message("Critical error! Please contact a Thinktronic Systems technician, as your warranty may be affected.")
|
|
UnregisterSignal(clonemind.current, COMSIG_LIVING_REVIVE)
|
|
UnregisterSignal(clonemind, COMSIG_MIND_TRANSER_TO)
|
|
if(!go_easy)
|
|
if(occupant.mind != clonemind)
|
|
clonemind.transfer_to(occupant)
|
|
occupant.grab_ghost() // We really just want to make you suffer.
|
|
var/message
|
|
message += "<b>Agony blazes across your consciousness as your body is torn apart.</b><br>"
|
|
message += "<i>Is this what dying is like? Yes it is.</i>"
|
|
to_chat(occupant, "<span class='warning'>[message]</span>")
|
|
SEND_SOUND(occupant, sound('sound/hallucinations/veryfar_noise.ogg', 0, 1, 50))
|
|
QDEL_LIST_CONTENTS(missing_organs)
|
|
clonemind = null
|
|
spawn(40)
|
|
qdel(occupant)
|
|
|
|
|
|
playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
|
|
mess = TRUE
|
|
update_icon()
|
|
|
|
/obj/machinery/clonepod/update_icon_state()
|
|
if(occupant && !(stat & NOPOWER))
|
|
icon_state = "pod_cloning"
|
|
else if(mess)
|
|
icon_state = "pod_mess"
|
|
else
|
|
icon_state = "pod_idle"
|
|
|
|
/obj/machinery/clonepod/update_overlays()
|
|
. = ..()
|
|
if(panel_open)
|
|
. += "panel_open"
|
|
|
|
/obj/machinery/clonepod/relaymove(mob/user)
|
|
if(user.stat == CONSCIOUS)
|
|
go_out()
|
|
|
|
/obj/machinery/clonepod/emp_act(severity)
|
|
if(prob(100/(severity*efficiency))) malfunction()
|
|
..()
|
|
|
|
/obj/machinery/clonepod/ex_act(severity)
|
|
..()
|
|
if(!QDELETED(src) && occupant)
|
|
go_out()
|
|
|
|
/obj/machinery/clonepod/handle_atom_del(atom/A)
|
|
if(A == occupant)
|
|
occupant = null
|
|
countdown.stop()
|
|
|
|
/obj/machinery/clonepod/deconstruct(disassembled = TRUE)
|
|
if(occupant)
|
|
go_out()
|
|
..()
|
|
|
|
/obj/machinery/clonepod/proc/occupant_got_revived()
|
|
// The old body's back in shape, time to ditch the cloning one
|
|
malfunction(go_easy = TRUE)
|
|
|
|
/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H)
|
|
QDEL_LIST_CONTENTS(missing_organs)
|
|
|
|
H.setCloneLoss(CLONE_INITIAL_DAMAGE, FALSE)
|
|
H.setBrainLoss(BRAIN_INITIAL_DAMAGE)
|
|
|
|
for(var/o in H.internal_organs)
|
|
var/obj/item/organ/O = o
|
|
if(!istype(O) || O.vital)
|
|
continue
|
|
|
|
// Let's non-specially remove all non-vital organs
|
|
// What could possibly go wrong
|
|
var/obj/item/I = O.remove(H)
|
|
// Make this support stuff that turns into items when removed
|
|
I.forceMove(src)
|
|
missing_organs += I
|
|
|
|
var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
|
|
for(var/zone in zones)
|
|
var/obj/item/organ/external/E = H.get_organ(zone)
|
|
var/obj/item/I = E.remove(H)
|
|
I.forceMove(src)
|
|
missing_organs += I
|
|
|
|
organs_number = length(missing_organs)
|
|
H.updatehealth()
|
|
|
|
/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)
|
|
|
|
/*
|
|
* Genetics Diskette Box
|
|
*/
|
|
|
|
/obj/item/storage/box/disks
|
|
name = "Genetics Diskette Box"
|
|
icon_state = "disk_kit"
|
|
|
|
/obj/item/storage/box/disks/populate_contents()
|
|
for(var/i in 1 to 7)
|
|
new /obj/item/disk/data(src)
|
|
|
|
/*
|
|
* Manual -- A big ol' manual.
|
|
*/
|
|
|
|
/obj/item/paper/Cloning
|
|
name = "paper - 'H-87 Cloning Apparatus Manual"
|
|
info = {"<h4>Getting Started</h4>
|
|
Congratulations, your station has purchased the H-87 industrial cloning device!<br>
|
|
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!<br>
|
|
<b>That's all there is to it!</b><br>
|
|
<i>Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.</i><br>
|
|
<p>Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR BIO-CHIP into the subject, which may be viewed from each profile.
|
|
Profile Deletion has been restricted to \[Station Head\] level access.</p>
|
|
<h4>Cloning from a profile</h4>
|
|
Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.<br>
|
|
Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.<br>
|
|
<br>
|
|
<p>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.</p><br>
|
|
<i>Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.</i><br>
|
|
<h4>Profile Management</h4>
|
|
<p>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.</p><br>
|
|
<i>A good diskette is a great way to counter aforementioned genetic drift!</i><br>
|
|
<br>
|
|
<font size=1>This technology produced under license from Thinktronic Systems, LTD.</font>"}
|
|
|
|
//SOME SCRAPS I GUESS
|
|
/* EMP grenade/spell effect
|
|
if(istype(A, /obj/machinery/clonepod))
|
|
A:malfunction()
|
|
*/
|
|
|
|
#undef MINIMUM_HEAL_LEVEL
|