Files
CHOMPStation2/code/modules/resleeving/computers.dm
CHOMPStation2StaffMirrorBot ce2446922e [MIRROR] Initialize fixing (#10335)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-03-08 22:22:04 +01:00

571 lines
19 KiB
Plaintext

#define MENU_MAIN 1
#define MENU_BODY 2
#define MENU_MIND 3
/obj/machinery/computer/transhuman/resleeving
name = "resleeving control console"
catalogue_data = list(/datum/category_item/catalogue/technology/resleeving)
icon_keyboard = "med_key"
icon_screen = "dna"
light_color = "#315ab4"
bubble_icon = "medical"
circuit = /obj/item/circuitboard/resleeving_control
req_access = list(access_heads) //Only used for record deletion right now.
var/list/pods = null //Linked grower pods.
var/list/spods = null
var/list/sleevers = null //Linked resleeving booths.
var/list/temp = null
var/menu = MENU_MAIN //Which menu screen to display
var/datum/transhuman/body_record/active_br = null
var/can_grow_active = FALSE
var/datum/transhuman/mind_record/active_mr = null
var/can_sleeve_active = FALSE
var/organic_capable = 1
var/synthetic_capable = 1
var/obj/item/disk/transcore/disk
var/obj/machinery/clonepod/transhuman/selected_pod
var/obj/machinery/transhuman/synthprinter/selected_printer
var/obj/machinery/transhuman/resleever/selected_sleever
// Resleeving database this machine interacts with. Blank for default database
// Needs a matching /datum/transcore_db with key defined in code
var/db_key
var/datum/transcore_db/our_db // These persist all round and are never destroyed, just keep a hard ref
var/gene_sequencing = FALSE // Traitgenes edit - create a dna injector for fixing dna, but don't let it be abusable
/obj/machinery/computer/transhuman/resleeving/Initialize(mapload)
. = ..()
pods = list()
spods = list()
sleevers = list()
our_db = SStranscore.db_by_key(db_key)
updatemodules()
/obj/machinery/computer/transhuman/resleeving/Destroy()
releasepods()
return ..()
/obj/machinery/computer/transhuman/resleeving/proc/updatemodules()
releasepods()
findpods()
/obj/machinery/computer/transhuman/resleeving/proc/releasepods()
for(var/obj/machinery/clonepod/transhuman/P in pods)
P.connected = null
P.name = initial(P.name)
pods.Cut()
for(var/obj/machinery/transhuman/synthprinter/P in spods)
P.connected = null
P.name = initial(P.name)
spods.Cut()
for(var/obj/machinery/transhuman/resleever/P in sleevers)
P.connected = null
P.name = initial(P.name)
sleevers.Cut()
/obj/machinery/computer/transhuman/resleeving/proc/findpods()
var/num = 1
var/area/A = get_area(src)
for(var/obj/machinery/clonepod/transhuman/P in A.get_contents())
if(!P.connected)
pods += P
P.connected = src
P.name = "[initial(P.name)] #[num++]"
for(var/obj/machinery/transhuman/synthprinter/P in A.get_contents())
if(!P.connected)
spods += P
P.connected = src
P.name = "[initial(P.name)] #[num++]"
for(var/obj/machinery/transhuman/resleever/P in A.get_contents())
if(!P.connected)
sleevers += P
P.connected = src
P.name = "[initial(P.name)] #[num++]"
/obj/machinery/computer/transhuman/resleeving/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/multitool))
var/obj/item/multitool/M = W
var/obj/machinery/clonepod/transhuman/P = M.connecting
if(istype(P) && !(P in pods))
pods += P
P.connected = src
P.name = "[initial(P.name)] #[pods.len]"
to_chat(user, span_notice("You connect [P] to [src]."))
else if(istype(W, /obj/item/disk/transcore) && !our_db.core_dumped)
user.unEquip(W)
disk = W
disk.forceMove(src)
to_chat(user, span_notice("You insert \the [W] into \the [src]."))
if(istype(W, /obj/item/disk/body_record))
var/obj/item/disk/body_record/brDisk = W
if(!brDisk.stored)
to_chat(user, span_warning("\The [W] does not contain a stored body record."))
return
user.unEquip(W)
W.forceMove(get_turf(src)) // Drop on top of us
active_br = new /datum/transhuman/body_record(brDisk.stored) // Loads a COPY!
to_chat(user, span_notice("\The [src] loads the body record from \the [W] before ejecting it."))
attack_hand(user)
view_b_rec(REF(active_br))
else
..()
return
/obj/machinery/computer/transhuman/resleeving/attack_ai(mob/user as mob)
return attack_hand(user)
/obj/machinery/computer/transhuman/resleeving/attack_hand(mob/user as mob)
user.set_machine(src)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
updatemodules()
tgui_interact(user)
/obj/machinery/computer/transhuman/resleeving/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/simple/cloning),
get_asset_datum(/datum/asset/simple/cloning/resleeving),
)
/obj/machinery/computer/transhuman/resleeving/tgui_interact(mob/user, datum/tgui/ui = null)
if(stat & (NOPOWER|BROKEN))
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ResleevingConsole", "Resleeving Console")
ui.open()
/obj/machinery/computer/transhuman/resleeving/tgui_data(mob/user)
var/data[0]
data["menu"] = menu
var/list/clonepods = list()
for(var/obj/machinery/clonepod/transhuman/pod in pods)
var/status = "idle"
if(pod.mess)
status = "mess"
else if(pod.occupant && !(pod.stat & NOPOWER))
status = "cloning"
clonepods += list(list(
"pod" = REF(pod),
"name" = sanitize(capitalize(pod.name)),
"biomass" = pod.get_biomass(),
"status" = status,
"progress" = (pod.occupant && pod.occupant.stat != DEAD) ? pod.get_completion() : 0
))
data["pods"] = clonepods
var/list/synthpods = list()
for(var/obj/machinery/transhuman/synthprinter/spod in spods)
synthpods += list(list(
"spod" = REF(spod),
"name" = sanitize(capitalize(spod.name)),
"busy" = spod.busy,
"steel" = spod.stored_material[MAT_STEEL],
"glass" = spod.stored_material[MAT_GLASS]
))
data["spods"] = synthpods
var/list/resleevers = list()
for(var/obj/machinery/transhuman/resleever/resleever in sleevers)
resleevers += list(list(
"sleever" = REF(resleever),
"name" = sanitize(capitalize(resleever.name)),
"occupied" = !!resleever.occupant,
"occupant" = resleever.occupant ? resleever.occupant.real_name : "None"
))
data["sleevers"] = resleevers
data["coredumped"] = our_db.core_dumped
data["emergency"] = disk
data["temp"] = temp
data["selected_pod"] = REF(selected_pod)
data["selected_printer"] = REF(selected_printer)
data["selected_sleever"] = REF(selected_sleever)
var/list/bodyrecords_list_ui = list()
for(var/N in our_db.body_scans)
var/datum/transhuman/body_record/BR = our_db.body_scans[N]
bodyrecords_list_ui += list(list(
"name" = N,
"recref" = REF(BR)
))
data["bodyrecords"] = bodyrecords_list_ui
var/list/mindrecords_list_ui = list()
for(var/N in our_db.backed_up)
var/datum/transhuman/mind_record/MR = our_db.backed_up[N]
mindrecords_list_ui += list(list(
"name" = N,
"recref" = REF(MR)
))
data["mindrecords"] = mindrecords_list_ui
data["active_b_rec"] = null
if(active_br)
data["active_b_rec"] = list(
activerecord = REF(active_br),
realname = sanitize(active_br.mydna.name),
species = active_br.speciesname ? active_br.speciesname : active_br.mydna.dna.species,
sex = active_br.bodygender,
mind_compat = active_br.locked ? "Low" : "High",
synthetic = active_br.synthetic,
oocnotes = active_br.body_oocnotes ? active_br.body_oocnotes : "None",
can_grow_active = can_grow_active,
)
data["active_m_rec"] = null
if(active_mr)
data["active_m_rec"] = list(
activerecord = REF(active_mr),
realname = sanitize(active_mr.mindname),
obviously_dead = active_mr.dead_state == MR_DEAD ? "Past-due" : "Current",
oocnotes = active_mr.mind_oocnotes ? active_mr.mind_oocnotes : "None.",
can_sleeve_active = can_sleeve_active,
)
return data
/obj/machinery/computer/transhuman/resleeving/tgui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
switch(action)
if("view_b_rec")
view_b_rec(params["ref"])
. = TRUE
if("clear_b_rec")
active_br = null
. = TRUE
if("view_m_rec")
view_m_rec(params["ref"])
. = TRUE
if("clear_m_rec")
active_mr = null
. = TRUE
if("coredump")
if(disk)
our_db.core_dump(disk)
sleep(5)
visible_message(span_warning("\The [src] spits out \the [disk]."))
disk.forceMove(get_turf(src))
disk = null
. = TRUE
if("ejectdisk")
disk.forceMove(get_turf(src))
disk = null
. = TRUE
if("create")
. = TRUE
if(istype(active_br))
//Tried to grow a synth but no synth pods.
if(active_br.synthetic && !spods.len)
set_temp("Error: No SynthFabs detected.", "danger")
//Tried to grow an organic but no growpods.
else if(!active_br.synthetic && !pods.len)
set_temp("Error: No growpods detected.", "danger")
//We have the machines. We can rebuild them. Probably.
else
//We're cloning a synth.
if(active_br.synthetic)
var/obj/machinery/transhuman/synthprinter/spod = selected_printer
if(!istype(spod))
set_temp("Error: No SynthFab selected.", "danger")
active_br = null
return
//Already doing someone.
if(spod.busy)
set_temp("Error: SynthFab is currently busy.", "danger")
active_br = null
return
//Not enough steel or glass
else if(spod.stored_material[MAT_STEEL] < spod.body_cost)
set_temp("Error: Not enough [MAT_STEEL] in SynthFab.", "danger")
active_br = null
return
else if(spod.stored_material[MAT_GLASS] < spod.body_cost)
set_temp("Error: Not enough glass in SynthFab.", "danger")
active_br = null
return
//Gross pod (broke mid-cloning or something).
else if(spod.broken)
set_temp("Error: SynthFab malfunction.", "danger")
active_br = null
return
//Do the cloning!
else if(spod.print(active_br))
set_temp("Initiating printing cycle...", "success")
active_br = null
menu = 1
else
set_temp("Initiating printing cycle... Error: Post-initialisation failed. Printing cycle aborted.", "danger")
active_br = null
return
//We're cloning an organic.
else
var/obj/machinery/clonepod/transhuman/pod = selected_pod
if(!istype(pod))
set_temp("Error: No clonepod selected.", "danger")
active_br = null
return
//Already doing someone.
if(pod.occupant)
set_temp("Error: Growpod is currently occupied.", "danger")
active_br = null
return
//Not enough materials.
else if(pod.get_biomass() < CLONE_BIOMASS)
set_temp("Error: Not enough biomass.", "danger")
active_br = null
return
//Gross pod (broke mid-cloning or something).
else if(pod.mess)
set_temp("Error: Growpod malfunction.", "danger")
active_br = null
return
//Disabled in config.
else if(!CONFIG_GET(flag/revival_cloning))
set_temp("Error: Unable to initiate growing cycle.", "danger")
active_br = null
return
//Do the cloning!
else if(pod.growclone(active_br))
set_temp("Initiating growing cycle...", "success")
active_br = null
else
set_temp("Initiating growing cycle... Error: Post-initialisation failed. Growing cycle aborted.", "danger")
active_br = null
return
//The body record is broken somehow.
else
set_temp("Error: Data corruption.", "danger")
active_br = null
if("sleeve")
if(istype(active_mr))
. = TRUE
if(!sleevers.len)
set_temp("Error: No sleevers detected.", "danger")
active_mr = null
else
var/mode = text2num(params["mode"])
var/override
var/obj/machinery/transhuman/resleever/sleever = selected_sleever
if(!istype(sleever))
set_temp("Error: No resleeving pod selected.", "danger")
active_mr = null
return
switch(mode)
if(1) //Body resleeving
//No body to sleeve into.
if(!sleever.occupant)
set_temp("Error: Resleeving pod is not occupied.", "danger")
active_mr = null
return
//OOC body lock thing.
if(sleever.occupant.resleeve_lock && active_mr.ckey != sleever.occupant.resleeve_lock)
set_temp("Error: Mind incompatible with body.", "danger")
active_mr = null
return
var/list/subtargets = list()
for(var/mob/living/carbon/human/H in sleever.occupant)
if(H.resleeve_lock && active_mr.ckey != H.resleeve_lock)
continue
subtargets += H
if(subtargets.len)
var/oc_sanity = sleever.occupant
override = tgui_input_list(ui.user,"Multiple bodies detected. Select target for resleeving of [active_mr.mindname] manually. Sleeving of primary body is unsafe with sub-contents, and is not listed.", "Resleeving Target", subtargets)
if(!override || oc_sanity != sleever.occupant || !(override in sleever.occupant))
set_temp("Error: Target selection aborted.", "danger")
active_mr = null
return
if(2) //Card resleeving
if(sleever.sleevecards <= 0)
set_temp("Error: No available cards in resleever.", "danger")
active_mr = null
return
//Body to sleeve into, but mind is in another living body.
if(active_mr.mind_ref.current && active_mr.mind_ref.current.stat < DEAD) //Mind is in a body already that's alive
var/answer = tgui_alert(active_mr.mind_ref.current,"Someone is attempting to restore a backup of your mind. Do you want to abandon this body, and move there? You MAY suffer memory loss! (Same rules as CMD apply)","Resleeving",list("No","Yes"))
//They declined to be moved.
if(answer != "Yes")
set_temp("Initiating resleeving... Error: Post-initialisation failed. Resleeving cycle aborted.", "danger")
active_mr = null
return TRUE
//They were dead, or otherwise available.
sleever.putmind(active_mr,mode,override,db_key = db_key)
set_temp("Initiating resleeving...")
active_mr = null
if("selectpod")
var/ref = params["ref"]
if(!length(ref))
return
var/obj/machinery/clonepod/selected = locate(ref)
if(istype(selected) && (selected in pods))
selected_pod = selected
. = TRUE
if("selectprinter")
var/ref = params["ref"]
if(!length(ref))
return
var/obj/machinery/transhuman/synthprinter/selected = locate(ref)
if(istype(selected) && (selected in spods))
selected_printer = selected
. = TRUE
if("selectsleever")
var/ref = params["ref"]
if(!length(ref))
return
var/obj/machinery/transhuman/resleever/selected = locate(ref)
if(istype(selected) && (selected in sleevers))
selected_sleever = selected
. = TRUE
if("menu")
menu = clamp(text2num(params["num"]), MENU_MAIN, MENU_MIND)
. = TRUE
// Traitgenes edit begin - create a dna injector based off the BR currently selected, to allow normal doctors to reset someone's SEs
if("genereset")
if(gene_sequencing)
set_temp("Sequencing Record... Please wait.")
tgui_modal_clear(src)
else if(istype(active_br))
set_temp("Sequencing Record...")
tgui_modal_clear(src)
gene_sequencing = TRUE
// Make the injector here, so no desync
var/obj/item/dnainjector/I = new(src)
I.name += " ([active_br.mydna.name] - Resequencer)"
I.desc = "Resequences structural enzymes to match the body record this was created from."
I.buf = active_br.mydna.copy()
I.buf.types = DNA2_BUF_SE
atom_say("Beginning injector synthesis.")
addtimer(CALLBACK(src, PROC_REF(dispense_injector), I), 10 SECONDS, TIMER_DELETE_ME)
. = TRUE
if("cleartemp")
temp = null
. = TRUE
/obj/machinery/computer/transhuman/resleeving/proc/dispense_injector(var/obj/item/dnainjector/I)
I.forceMove(loc)
gene_sequencing = FALSE
set_temp("Injector dispensed...")
visible_message(span_notice("\The [src] ejects \the [I]."))
playsound(src, 'sound/machines/ding.ogg', 50, 1)
// In here because only relevant to computer
/obj/item/cmo_disk_holder
name = "cmo emergency packet"
desc = "A small paper packet with printing on one side. \"Tear open in case of Code Delta or Emergency Evacuation ONLY. Use in any other case is UNLAWFUL.\""
catalogue_data = list(/datum/category_item/catalogue/technology/resleeving)
icon = 'icons/vore/custom_items_vr.dmi'
icon_state = "cmoemergency"
item_state = "card-id"
/obj/item/cmo_disk_holder/attack_self(var/mob/attacker)
playsound(src, 'sound/items/poster_ripped.ogg', 50)
to_chat(attacker, span_warning("You tear open \the [name]."))
attacker.unEquip(src)
var/obj/item/disk/transcore/newdisk = new(get_turf(src))
attacker.put_in_any_hand_if_possible(newdisk)
qdel(src)
/obj/item/disk/transcore
name = "TransCore Dump Disk"
desc = "It has a small label. \n\
\"1.INSERT DISK INTO RESLEEVING CONSOLE\n\
2. BEGIN CORE DUMP PROCEDURE\n\
3. ENSURE DISK SAFETY WHEN EJECTED\""
catalogue_data = list(/datum/category_item/catalogue/technology/resleeving)
icon = 'icons/obj/cloning.dmi'
icon_state = "harddisk"
item_state = "card-id"
w_class = ITEMSIZE_SMALL
var/list/datum/transhuman/mind_record/stored = list()
/**
* Sets a temporary message to display to the user
*
* Arguments:
* * text - Text to display, null/empty to clear the message from the UI
* * style - The style of the message: (color name), info, success, warning, danger
*/
/obj/machinery/computer/transhuman/resleeving/proc/set_temp(text = "", style = "info", update_now = FALSE)
temp = list(text = text, style = style)
if(update_now)
SStgui.update_uis(src)
/obj/machinery/computer/transhuman/resleeving/proc/view_b_rec(ref)
if(!length(ref))
return
active_br = locate(ref)
if(istype(active_br))
can_grow_active = TRUE
if(!synthetic_capable && active_br.synthetic) //Disqualified due to being synthetic in an organic only.
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to lack of synthfabs.", "danger")
else if(!organic_capable && !active_br.synthetic) //Disqualified for the opposite.
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to lack of cloners.", "danger")
else if(!synthetic_capable && !organic_capable) //What have you done??
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to lack of synthfabs and cloners.", "danger")
else if(active_br.toocomplex)
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to species complexity.", "danger")
else
active_br = null
set_temp("Error: Record missing.", "danger")
/obj/machinery/computer/transhuman/resleeving/proc/view_m_rec(ref)
if(!length(ref))
return
active_mr = locate(ref)
if(istype(active_mr))
if(isnull(active_mr.ckey))
qdel(active_mr)
set_temp("Error: Record corrupt.", "danger")
else
can_sleeve_active = TRUE
if(!LAZYLEN(sleevers))
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to no sleevers.", "danger")
if(!selected_sleever)
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to no selected sleever.", "danger")
if(selected_sleever && !selected_sleever.occupant)
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to lack of sleever occupant.", "danger")
else
active_mr = null
set_temp("Error: Record missing.", "danger")
#undef MENU_MAIN
#undef MENU_BODY
#undef MENU_MIND