Dna, Bodyrecord, Xenochi Revive Refactor (#17732)

* changeling fix

* Move body spawning into BR

* small fix, organization

* replace xeno regen

* Body descriptor system removed

* Revert "Body descriptor system removed"

This reverts commit 04a0aa3ac8.

* massive bodyrecord copy refactor

* this too

* dna copying is now sane

* make a merge easier

* better file for this

* may we ensure peace everlasting

* linter

* oops, missed the test

* fixed up

* furthering the test

* different way to check

* looking promising

* required exclusions

* more test

* another tweak

* setup better

* globin

* test name change

* really mess up that monkey

* gradient style to UI entry

* scramble ignore

* illegal species

* scramble fix

* grad fix, more test fixes

* doing that right

* need these too

* missed defferal

* missed pathing

* documentation wall

* blood color needs a safety

* promethean prep

* this early set isn't needed

* some protections

* fixed waddler nulltest

* failure test

* intensify scan

* second fail test

* noticing

* dna test case

* other dna test case

* Test is bunk

* huge dna cleanup, better signal

* don't edit these

* documentation

* Do not use loc = src.loc

* oops

* Use weakrefs in pods

* remaining weakrefs

* reduce changes in pr

* cloning computer does not rotate itself when used

* moved body design to new BR code, and fixed screen size

* badlinting

* updated

* No instakilling teshari

* jiggles you

* TGUI

* move along

* m ove it

* Update AppearanceChangerMisc.tsx

* this too

* gender is race whoops

* Allow old clonepods too

* xc

* further encapsulation and some fixes

* oops

* misc not race

* separated that

* custom footsteps exchanged

* Custom speech bubble and xenochi stuff

* Update xenochimera.dm

* remove digileg snowflake

* try this

* Update xenochimera.dm

* proper close

* Always update our DNA

* awa

* extremely laggy check removed, actually useless

* explaining

* lower delay time

* slower jigglin

* Revert "slower jigglin"

This reverts commit c801f7d7f5.

* disable appearance editor due to various issues

* Promie love

* xenochi vanity test

* lmao

* earwings

* wording and slot revival

* mobvar?

* Phasing out specific shapeshifter appearances

If you have access to changing your icon, you can change whatever you want.

* saveslot loading

* more

* synth

* Shoot out limbs

* almost ready

* nullcheck

* xenochi revive handles size and weight correctly

* weaver cocoon updated xenochi internal record after tf

* cannot remove from lost limbs

* limbs properly respawn on slot revive

---------

Co-authored-by: C.L. <killer65311@gmail.com>
This commit is contained in:
Will
2025-06-09 08:20:42 -07:00
committed by GitHub
co-authored by C.L.
parent ebca26a85c
commit cbd3f1ea2b
42 changed files with 1079 additions and 901 deletions
+2
View File
@@ -187,6 +187,8 @@
if(def_lang)
new_character.default_language = def_lang
SEND_SIGNAL(new_character, COMSIG_HUMAN_DNA_FINALIZED)
//If desired, apply equipment.
if(equip_body)
if(charjob)
+12 -11
View File
@@ -148,16 +148,17 @@
var/list/clonepods = list()
for(var/obj/machinery/clonepod/transhuman/pod in pods)
var/status = "idle"
var/mob/living/occupant = pod.get_occupant()
if(pod.mess)
status = "mess"
else if(pod.occupant && !(pod.stat & NOPOWER))
else if(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
"progress" = (occupant && occupant.stat != DEAD) ? pod.get_completion() : 0
))
data["pods"] = clonepods
@@ -177,8 +178,8 @@
resleevers += list(list(
"sleever" = REF(resleever),
"name" = sanitize(capitalize(resleever.name)),
"occupied" = !!resleever.occupant,
"occupant" = resleever.occupant ? resleever.occupant.real_name : "None"
"occupied" = !!resleever.get_occupant(),
"occupant" = resleever.get_occupant() ? resleever.get_occupant().real_name : "None"
))
data["sleevers"] = resleevers
@@ -322,7 +323,7 @@
return
//Already doing someone.
if(pod.occupant)
if(pod.get_occupant())
set_temp("Error: Growpod is currently occupied.", "danger")
active_br = null
return
@@ -375,26 +376,26 @@
switch(mode)
if(1) //Body resleeving
//No body to sleeve into.
if(!sleever.occupant)
if(!sleever.get_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)
if(sleever.get_occupant().resleeve_lock && active_mr.ckey != sleever.get_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)
for(var/mob/living/carbon/human/H in sleever.get_occupant())
if(H.resleeve_lock && active_mr.ckey != H.resleeve_lock)
continue
subtargets += H
if(subtargets.len)
var/oc_sanity = sleever.occupant
var/oc_sanity = sleever.get_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))
if(!override || oc_sanity != sleever.get_occupant() || !(override in sleever.get_occupant()))
set_temp("Error: Target selection aborted.", "danger")
active_mr = null
return
@@ -558,7 +559,7 @@
if(!selected_sleever)
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to no selected sleever.", "danger")
if(selected_sleever && !selected_sleever.occupant)
if(selected_sleever && !selected_sleever.get_occupant())
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to lack of sleever occupant.", "danger")
else
+1
View File
@@ -59,6 +59,7 @@
if(!designer_gui)
designer_gui = new(src, null)
designer_gui.linked_body_design_console = WEAKREF(src)
CallAsync(designer_gui, TYPE_PROC_REF(/datum/tgui_module/appearance_changer,jiggle_map))
if(!designer_gui.owner)
designer_gui.make_fake_owner()
selected_record = FALSE
+197 -26
View File
@@ -134,6 +134,11 @@
speciesname = M.custom_species ? M.custom_species : null
bodygender = M.gender
body_oocnotes = M.ooc_notes
body_ooclikes = M.ooc_notes_likes
body_oocdislikes = M.ooc_notes_dislikes
body_oocfavs = M.ooc_notes_favs
body_oocmaybes = M.ooc_notes_maybes
body_oocstyle = M.ooc_notes_style
sizemult = M.size_multiplier
weight = M.weight
aflags = M.appearance_flags
@@ -204,7 +209,6 @@
if(add_to_db)
SStranscore.add_body(src, database_key = database_key)
/**
* Make a deep copy of this record so it can be saved on a disk without modifications
* to the original affecting the copy.
@@ -214,28 +218,195 @@
/datum/transhuman/body_record/proc/init_from_br(var/datum/transhuman/body_record/orig)
ASSERT(!QDELETED(orig))
ASSERT(istype(orig))
src.mydna = new ()
qdel_swap(src.mydna.dna, orig.mydna.dna.Clone())
src.mydna.ckey = orig.mydna.ckey
src.mydna.id = orig.mydna.id
src.mydna.name = orig.mydna.name
src.mydna.types = orig.mydna.types
src.mydna.flavor = orig.mydna.flavor.Copy()
src.ckey = orig.ckey
src.locked = orig.locked
src.client_ref = orig.client_ref
src.mind_ref = orig.mind_ref
src.synthetic = orig.synthetic
src.speciesname = orig.speciesname
src.bodygender = orig.bodygender
src.body_oocnotes = orig.body_oocnotes
src.body_ooclikes = orig.body_ooclikes
src.body_oocdislikes = orig.body_oocdislikes
src.limb_data = orig.limb_data.Copy()
src.organ_data = orig.organ_data.Copy()
src.genetic_modifiers = orig.genetic_modifiers.Copy()
src.toocomplex = orig.toocomplex
src.sizemult = orig.sizemult
src.aflags = orig.aflags
src.breath_type = orig.breath_type
src.weight = orig.weight
for(var/A in vars)
switch(A)
if(BLACKLISTED_COPY_VARS)
continue
if("mydna")
mydna = orig.mydna.copy()
continue
if(islist(vars[A]))
var/list/L = orig.vars[A]
vars[A] = L.Copy()
continue
vars[A] = orig.vars[A]
/**
* Spawning a body was once left entirely up to the machine doing it, but bodies are massivley complex
* objects, and doing it this way lead to huge amounts of copypasted code to do the same thing.
* If you want to spawn a body from a BR, please use these...
*/
/// The core of resleeving, creates a mob based on the current record
/datum/transhuman/body_record/proc/produce_human_mob(var/location, var/is_synthfab, var/force_unlock, var/backup_name)
// These are broken up into steps, otherwise the proc gets massive and hard to read.
var/mob/living/carbon/human/H = internal_producebody(location,backup_name)
internal_producebody_handlesleevelock(H,force_unlock)
internal_producebody_updatelimbandorgans(H)
internal_producebody_updatednastate(H,is_synthfab)
internal_producebody_virgoOOC(H)
internal_producebody_misc(H)
return H
/// Creates a human mob with the correct species, name, and a stable state.
/datum/transhuman/body_record/proc/internal_producebody(var/location,var/backup_name)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
var/mob/living/carbon/human/H = new /mob/living/carbon/human(location, mydna.dna.species)
if(!mydna.dna.real_name)
mydna.dna.real_name = backup_name
H.real_name = mydna.dna.real_name
H.name = H.real_name
for(var/datum/language/L in mydna.languages)
H.add_language(L.name)
H.suiciding = 0
H.losebreath = 0
H.mind = null
return H
/// Sets the new body's sleevelock status, to prevent impersonation by transfering an incorrect mind.
/datum/transhuman/body_record/proc/internal_producebody_handlesleevelock(var/mob/living/carbon/human/H,var/force_unlock)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
if(locked && !force_unlock)
if(ckey)
H.resleeve_lock = ckey
else
// Ensure even body scans without an attached ckey respect locking
H.resleeve_lock = "@badckey"
/// Either converts limbs to robotics or prosthetic states, or removes them entirely based off record.
/datum/transhuman/body_record/proc/internal_producebody_updatelimbandorgans(var/mob/living/carbon/human/H,var/is_synthfab)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
//Fix the external organs
for(var/part in limb_data)
var/status = limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = H.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
if(!is_synthfab)
O.remove_rejuv() //Don't robotize them, leave them removed so robotics can attach a part.
else
O.robotize(status)
//Then the internal organs
for(var/part in organ_data)
var/status = organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = H.internal_organs_by_name[part]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
/// Transfers dna data to mob, and reinits traits and appearance from it
/datum/transhuman/body_record/proc/internal_producebody_updatednastate(var/mob/living/carbon/human/H,var/is_synthfab)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
//Apply DNA from record
if(!mydna.dna) // This case should never happen, but copied from clone pod... Who knows with this codebase.
mydna.dna = new /datum/dna()
qdel_swap(H.dna, mydna.dna.Clone())
H.original_player = ckey
//Apply genetic modifiers, synths don't use these
if(!is_synthfab)
for(var/modifier_type in mydna.genetic_modifiers)
H.add_modifier(modifier_type)
//Update appearance, remake icons
H.UpdateAppearance()
H.sync_dna_traits(FALSE) // Traitgenes Sync traits to genetics if needed
H.sync_organ_dna()
H.regenerate_icons()
H.initialize_vessel()
/// Transfers VORE related information cached in the mob
/datum/transhuman/body_record/proc/internal_producebody_virgoOOC(var/mob/living/carbon/human/H)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
H.ooc_notes = body_oocnotes
H.ooc_notes_likes = body_ooclikes
H.ooc_notes_dislikes = body_oocdislikes
H.ooc_notes_favs = body_oocfavs
H.ooc_notes_maybes = body_oocmaybes
H.ooc_notes_style = body_oocstyle
/datum/transhuman/body_record/proc/internal_producebody_misc(var/mob/living/carbon/human/H)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
H.flavor_texts = mydna.flavor.Copy()
H.resize(sizemult, FALSE)
H.appearance_flags = aflags
H.weight = weight
if(speciesname)
H.custom_species = speciesname
/**
* Specialty revival procs. Uses the BR for data, but needs to handle some weird logic for xenochi/slimes
*/
/datum/transhuman/body_record/proc/revive_xenochimera(var/mob/living/carbon/human/H,var/heal_robot_limbs,var/from_save_slot)
// Boy this one is complex, but what do we expect when trying to heal damage and organ loss in this game!
if(!H || QDELETED(H)) // Someone, somewhere, will call this without any safety. I feel it in my bones cappin'
return
// Don't unlock unwilling xenochi!
internal_producebody_handlesleevelock(H,FALSE)
// Reset our organs/limbs.
H.species.create_organs(H)
internal_producebody_updatelimbandorgans(H, heal_robot_limbs)
//Don't boot out anyone already in the mob.
if(!H.client || !H.key)
for (var/obj/item/organ/internal/brain/CH in GLOB.all_brain_organs)
if(CH.brainmob)
if(CH.brainmob.real_name == H.real_name)
if(CH.brainmob.mind)
CH.brainmob.mind.transfer_to(H)
qdel(CH)
// Traitgenes Disable all traits currently active, before species.produceCopy() applies them during updatednastate(). Relevant here as genetraits may not match prior dna!
for(var/datum/gene/trait/gene in GLOB.dna_genes)
if(gene.name in H.active_genes)
gene.deactivate(H)
H.active_genes -= gene.name
internal_producebody_updatednastate(H,FALSE)
internal_producebody_virgoOOC(H) // Is this needed?
internal_producebody_misc(H)
// Begin actual REVIVIAL. Do NOT use revive(). That uses client prefs and allows save hacking.
H.revival_healing_action()
// Update record from vanity copy of slot if needed
if(from_save_slot)
H.client.prefs.vanity_copy_to(H,FALSE,TRUE,TRUE,FALSE)
for(var/category in H.all_underwear) // No undies
H.hide_underwear[category] = TRUE
H.update_underwear()
return H
/datum/transhuman/body_record/proc/revive_promethean(var/mob/living/carbon/human/H)
// TODO - See note in code\modules\organs\internal\brain.dm for slime brains
return
+46 -196
View File
@@ -29,83 +29,9 @@
remove_biomass(CLONE_BIOMASS)
//Get the DNA and generate a new mob
var/datum/dna2/record/R = current_project.mydna
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
if(current_project.locked)
if(current_project.ckey)
H.resleeve_lock = current_project.ckey
else
// Ensure even body scans without an attached ckey respect locking
H.resleeve_lock = "@badckey"
var/mob/living/carbon/human/H = current_project.produce_human_mob(src,FALSE,FALSE,"clone ([rand(0,999)])")
SEND_SIGNAL(H, COMSIG_HUMAN_DNA_FINALIZED)
//Fix the external organs
for(var/part in current_project.limb_data)
var/status = current_project.limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = H.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
O.remove_rejuv() //Don't robotize them, leave them removed so robotics can attach a part.
//Look, this machine can do this because [reasons] okay?!
for(var/part in current_project.organ_data)
var/status = current_project.organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = H.internal_organs_by_name[part]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
occupant = H
//Set the name or generate one
if(!R.dna.real_name)
R.dna.real_name = "clone ([rand(0,999)])"
H.real_name = R.dna.real_name
//Apply DNA
qdel_swap(H.dna, R.dna.Clone())
H.original_player = current_project.ckey
//Apply genetic modifiers
for(var/modifier_type in R.genetic_modifiers)
H.add_modifier(modifier_type)
//Apply legs
H.digitigrade = R.dna.digitigrade // ensure clone mob has digitigrade var set appropriately
if(H.dna.digitigrade <> R.dna.digitigrade)
H.dna.digitigrade = R.dna.digitigrade // ensure cloned DNA is set appropriately from record??? for some reason it doesn't get set right despite the override to datum/dna/Clone()
//Apply damage
H.adjustCloneLoss((H.getMaxHealth() - (H.getMaxHealth()))*-0.75)
H.Paralyse(4)
H.updatehealth()
//Update appearance, remake icons
H.UpdateAppearance()
H.sync_dna_traits(FALSE) // Traitgenes Sync traits to genetics if needed
H.sync_organ_dna()
H.regenerate_icons()
H.initialize_vessel()
// Traitgenes Moved breathing equipment to AFTER the genes set it
//Give breathing equipment if needed
if(current_project.breath_type != null && current_project.breath_type != GAS_O2)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), slot_wear_mask)
@@ -121,25 +47,11 @@
if(istype(H.internal,/obj/item/tank) && H.internals)
H.internals.icon_state = "internal1"
//Basically all the VORE stuff
H.ooc_notes = current_project.body_oocnotes
H.ooc_notes_likes = current_project.body_ooclikes
H.ooc_notes_dislikes = current_project.body_oocdislikes
H.ooc_notes_favs = current_project.body_oocfavs
H.ooc_notes_maybes = current_project.body_oocmaybes
H.ooc_notes_style = current_project.body_oocstyle
H.flavor_texts = current_project.mydna.flavor.Copy()
H.resize(current_project.sizemult, FALSE)
H.appearance_flags = current_project.aflags
H.weight = current_project.weight
if(current_project.speciesname)
H.custom_species = current_project.speciesname
//Suiciding var
H.suiciding = 0
//Making double-sure this is not set
H.mind = null
//Apply damage
set_occupant(H)
H.adjustCloneLoss((H.getMaxHealth() - (H.getMaxHealth()))*-0.75)
H.Paralyse(4)
H.updatehealth()
//Machine specific stuff at the end
update_icon()
@@ -147,6 +59,7 @@
return 1
/obj/machinery/clonepod/transhuman/process()
var/mob/living/occupant = get_occupant()
if(stat & NOPOWER)
if(occupant)
locked = 0
@@ -187,7 +100,7 @@
return
else if((!occupant) || (occupant.loc != src))
occupant = null
set_occupant(null)
if(locked)
locked = 0
update_icon()
@@ -196,13 +109,14 @@
return
/obj/machinery/clonepod/transhuman/get_completion()
var/mob/living/occupant = get_occupant()
if(occupant)
return 100 * ((occupant.health + (occupant.getMaxHealth()))) / (occupant.getMaxHealth() + abs(occupant.getMaxHealth()))
return 0
/obj/machinery/clonepod/transhuman/examine(mob/user, infix, suffix)
. = ..()
if(occupant)
if(get_occupant())
var/completion = get_completion()
. += "Progress: [round(completion)]% [chat_progress_bar(round(completion), TRUE)]"
@@ -295,95 +209,16 @@
return
//Get the DNA and generate a new mob
var/datum/dna2/record/R = current_project.mydna
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
if(current_project.locked)
if(current_project.ckey)
H.resleeve_lock = current_project.ckey
else
// Ensure even body scans without an attached ckey respect locking
H.resleeve_lock = "@badckey"
//Fix the external organs
for(var/part in current_project.limb_data)
var/status = current_project.limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = H.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
O.robotize(status)
//Then the internal organs
for(var/part in current_project.organ_data)
var/status = current_project.organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = H.internal_organs_by_name[part]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
//Set the name or generate one
if(!R.dna.real_name)
R.dna.real_name = "synth ([rand(0,999)])"
H.real_name = R.dna.real_name
//Apply DNA
qdel_swap(H.dna, R.dna.Clone())
H.original_player = current_project.ckey
//Apply legs
H.digitigrade = R.dna.digitigrade // ensure clone mob has digitigrade var set appropriately
if(H.dna.digitigrade <> R.dna.digitigrade)
H.dna.digitigrade = R.dna.digitigrade // ensure cloned DNA is set appropriately from record??? for some reason it doesn't get set right despite the override to datum/dna/Clone()
var/mob/living/carbon/human/H = current_project.produce_human_mob(src,TRUE,FALSE,"synth ([rand(0,999)])")
SEND_SIGNAL(H, COMSIG_HUMAN_DNA_FINALIZED)
//Apply damage
H.adjustBruteLoss(brute_value)
H.adjustFireLoss(burn_value)
H.updatehealth()
//Update appearance, remake icons
H.UpdateAppearance()
H.sync_dna_traits(FALSE) // Traitgenes Sync traits to genetics if needed
H.sync_organ_dna()
H.regenerate_icons()
H.initialize_vessel()
//Basically all the VORE stuff
H.ooc_notes = current_project.body_oocnotes
H.ooc_notes_likes = current_project.body_ooclikes
H.ooc_notes_dislikes = current_project.body_oocdislikes
H.flavor_texts = current_project.mydna.flavor.Copy()
H.resize(current_project.sizemult)
H.appearance_flags = current_project.aflags
H.weight = current_project.weight
if(current_project.speciesname)
H.custom_species = current_project.speciesname
//Suiciding var
H.suiciding = 0
//Making double-sure this is not set
H.mind = null
//Plonk them here.
H.regenerate_icons()
H.loc = get_turf(src)
H.forceMove(get_turf(src))
//Machine specific stuff at the end
stored_material[MAT_STEEL] -= body_cost
@@ -459,7 +294,7 @@
var/blur_amount
var/confuse_amount
var/mob/living/carbon/human/occupant = null
VAR_PRIVATE/datum/weakref/weakref_occupant = null
var/connected = null
var/sleevecards = 2
@@ -476,6 +311,18 @@
RefreshParts()
update_icon()
/obj/machinery/transhuman/resleever/proc/set_occupant(var/mob/living/carbon/human/H)
SHOULD_NOT_OVERRIDE(TRUE)
if(!H)
weakref_occupant = null
return
weakref_occupant = WEAKREF(H)
/obj/machinery/transhuman/resleever/proc/get_occupant()
RETURN_TYPE(/mob/living/carbon/human)
SHOULD_NOT_OVERRIDE(TRUE)
return weakref_occupant?.resolve()
/obj/machinery/transhuman/resleever/RefreshParts()
var/scan_rating = 0
for(var/obj/item/stock_parts/scanning_module/SM in component_parts)
@@ -502,14 +349,15 @@
/obj/machinery/transhuman/resleever/tgui_data(mob/user)
var/list/data = list()
data["occupied"] = !!occupant
if(occupant)
data["name"] = occupant.name
data["health"] = occupant.health
data["maxHealth"] = occupant.getMaxHealth()
data["stat"] = occupant.stat
data["mindStatus"] = !!occupant.mind
data["mindName"] = occupant.mind?.name
var/mob/living/carbon/human/H = get_occupant()
data["occupied"] = !!H
if(H)
data["name"] = H.name
data["health"] = H.health
data["maxHealth"] = H.getMaxHealth()
data["stat"] = H.stat
data["mindStatus"] = !!H.mind
data["mindName"] = H.mind?.name
return data
/obj/machinery/transhuman/resleever/attackby(obj/item/W, mob/user)
@@ -572,6 +420,7 @@
add_fingerprint(user)
/obj/machinery/transhuman/resleever/proc/putmind(var/datum/transhuman/mind_record/MR, mode = 1, var/mob/living/carbon/human/override = null, var/db_key)
var/mob/living/carbon/human/occupant = get_occupant()
if((!occupant || !istype(occupant) || occupant.stat >= DEAD) && mode == 1)
return 0
@@ -654,13 +503,14 @@
return 1
/obj/machinery/transhuman/resleever/proc/go_out(var/mob/M)
if(!( src.occupant ))
var/mob/living/carbon/human/occupant = get_occupant()
if(!occupant)
return
if (src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
src.occupant.loc = src.loc
src.occupant = null
if (occupant.client)
occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE
occupant.forceMove(get_turf(src))
set_occupant(null)
icon_state = "implantchair"
return
@@ -668,7 +518,7 @@
if(!ishuman(M))
to_chat(usr, span_warning("\The [src] cannot hold this!"))
return
if(src.occupant)
if(get_occupant())
to_chat(usr, span_warning("\The [src] is already occupied!"))
return
if(M.client)
@@ -676,7 +526,7 @@
M.client.eye = src
M.stop_pulling()
M.loc = src
src.occupant = M
set_occupant(M)
src.add_fingerprint(usr)
icon_state = "implantchair_on"
return 1