replace xeno regen

This commit is contained in:
Willburd
2025-05-18 18:51:59 -04:00
parent ea0296d74a
commit c1000da8c6
8 changed files with 132 additions and 96 deletions
+2
View File
@@ -593,6 +593,8 @@
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit"
///Whenever EquipRanked is called, called after job is set
#define COMSIG_JOB_RECEIVED "job_received"
///When the initial spawn's records are saved. Regardless of pref for it.
#define COMSIG_INITIAL_RECORDS "initial_record_save"
// /datum/species signals
+11 -2
View File
@@ -11,20 +11,29 @@
'sound/effects/mob_effects/xenochimera/regen_3.ogg',
'sound/effects/mob_effects/xenochimera/regen_5.ogg'
)
var/datum/transhuman/body_record/revival_record
/datum/component/xenochimera/Initialize()
if(!ishuman(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_XENOCHIMERA_COMPONENT, PROC_REF(handle_comp))
RegisterSignal(owner, COMSIG_INITIAL_RECORDS, PROC_REF(handle_record))
add_verb(owner, /mob/living/carbon/human/proc/reconstitute_form)
/datum/component/xenochimera/Destroy(force)
UnregisterSignal(owner, COMSIG_XENOCHIMERA_COMPONENT)
UnregisterSignal(owner, COMSIG_INITIAL_RECORDS)
remove_verb(owner, /mob/living/carbon/human/proc/reconstitute_form)
qdel_null(revival_record)
owner = null
. = ..()
/datum/component/xenochimera/proc/handle_record()
if(QDELETED(owner))
return
revival_record = new(owner)
/datum/component/xenochimera/proc/handle_comp()
if(QDELETED(owner))
return
@@ -397,8 +406,8 @@
var/old_nutrition = nutrition
var/braindamage = min(5, max(0, (brainloss-1) * 0.5)) //brainloss is tricky to heal and might take a couple of goes to get rid of completely.
var/uninjured=quickcheckuninjured()
//I did have special snowflake code, but this is easier. //It's also EXTREMELY BAD AND LETS THEM SAVEFILE HACK.
revive()
xc.revival_record.rebuild_human_mob(src,FALSE)
mutations.Remove(HUSK)
setBrainLoss(braindamage)
species.update_vore_belly_def_variant()
+15 -43
View File
@@ -68,27 +68,27 @@
return
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R)
/obj/machinery/clonepod/proc/growclone(var/datum/transhuman/body_record/BR)
if(mess || attempting)
return 0
var/datum/mind/clonemind = locate(R.mind)
var/datum/mind/clonemind = locate(BR.mydna.mind)
if(!istype(clonemind, /datum/mind)) //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)
if(ckey(clonemind.key) != BR.ckey)
return 0
else
for(var/mob/observer/dead/G in player_list)
if(G.ckey == R.ckey)
if(G.ckey == BR.ckey)
if(G.can_reenter_corpse)
break
else
return 0
for(var/modifier_type in R.genetic_modifiers) //Can't be cloned, even if they had a previous scan
for(var/modifier_type in BR.genetic_modifiers) //Can't be cloned, even if they had a previous scan
if(istype(modifier_type, /datum/modifier/no_clone))
return 0
@@ -102,24 +102,16 @@
spawn(30)
eject_wait = 0
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
occupant = H
if(!R.dna.real_name) //to prevent null names
R.dna.real_name = "clone ([rand(0,999)])"
H.real_name = R.dna.real_name
H.gender = R.gender
H.descriptors = R.body_descriptors
//Get the clone body ready
//Get the clone body ready, let's calculate their health so the pod doesn't immediately eject them!!!
var/mob/living/carbon/human/H = BR.produce_human_mob(src,FALSE, FALSE, "clone ([rand(0,999)])")
H.adjustCloneLoss(150) // New damage var so you can't eject a clone early then stab them to abuse the current damage system --NeoFite
H.Paralyse(4)
//Here let's calculate their health so the pod doesn't immediately eject them!!!
H.updatehealth()
H.set_cloned_appearance()
// Move mind to body along with key
clonemind.transfer_to(H)
H.ckey = R.ckey
H.ckey = BR.ckey
to_chat(H, span_warning(span_bold("Consciousness slowly creeps over you as your body regenerates.") + "<br>" + span_bold(span_large("Your recent memories are fuzzy, and it's hard to remember anything from today...")) + \
"<br>" + span_notice(span_italics("So this is what cloning feels like?"))))
@@ -128,44 +120,24 @@
update_antag_icons(H.mind)
// -- End mode specific stuff
if(!R.dna)
H.dna = new /datum/dna()
qdel_swap(H.dna, new /datum/dna())
else
qdel_swap(H.dna, R.dna)
H.UpdateAppearance()
H.sync_dna_traits(FALSE) // Traitgenes Sync traits to genetics if needed
H.sync_organ_dna()
H.initialize_vessel()
H.set_cloned_appearance()
update_icon()
// A modifier is added which makes the new clone be unrobust.
// Upgraded cloners can reduce the time of the modifier, up to 80%
var/modifier_lower_bound = 25 MINUTES
var/modifier_upper_bound = 40 MINUTES
// Upgraded cloners can reduce the time of the modifier, up to 80%
var/clone_sickness_length = abs(((heal_level - 20) / 100 ) - 1)
clone_sickness_length = between(0.2, clone_sickness_length, 1.0) // Caps it off just incase.
modifier_lower_bound = round(modifier_lower_bound * clone_sickness_length, 1)
modifier_upper_bound = round(modifier_upper_bound * clone_sickness_length, 1)
H.add_modifier(H.species.cloning_modifier, rand(modifier_lower_bound, modifier_upper_bound))
// Modifier that doesn't do anything.
H.add_modifier(/datum/modifier/cloned)
// This is really stupid.
for(var/modifier_type in R.genetic_modifiers)
H.add_modifier(modifier_type)
for(var/datum/language/L in R.languages)
H.add_language(L.name)
H.flavor_texts = R.flavor.Copy()
H.suiciding = 0
// Finished!
update_icon()
occupant = H
attempting = 0
return 1
//Grow clones to maturity then kick them out. FREELOADERS
+21 -22
View File
@@ -14,7 +14,7 @@
var/list/scantemp = null
var/menu = MENU_MAIN //Which menu screen to display
var/list/records = null
var/datum/dna2/record/active_record = null
var/datum/transhuman/body_record/active_BR = null
var/obj/item/disk/body_record/diskette = null // Traitgenes - Storing the entire body record
var/loading = 0 // Nice loading text
var/autoprocess = 0
@@ -206,15 +206,14 @@
. = TRUE
switch(tgui_modal_act(src, action, params))
if(TGUI_MODAL_ANSWER)
if(params["id"] == "del_rec" && active_record)
if(params["id"] == "del_rec" && active_BR)
var/obj/item/card/id/C = ui.user.get_active_hand()
if(!istype(C) && !istype(C, /obj/item/pda))
set_temp("ID not in hand.", "danger")
return
if(check_access(C))
records.Remove(active_record)
qdel(active_record.dna)
qdel(active_record)
records.Remove(active_BR)
qdel(active_BR) // Already deletes dna in destroy()
set_temp("Record deleted.", "success")
menu = MENU_RECORDS
else
@@ -245,28 +244,28 @@
var/ref = params["ref"]
if(!length(ref))
return
active_record = locate(ref)
if(istype(active_record))
if(isnull(active_record.ckey))
qdel(active_record)
active_BR = locate(ref)
if(istype(active_BR))
if(isnull(active_BR.ckey))
qdel(active_BR)
set_temp("Error: Record corrupt.", "danger")
else
var/obj/item/implant/health/H = null
if(active_record.implant)
H = locate(active_record.implant)
if(active_BR.mydna.implant)
H = locate(active_BR.mydna.implant)
var/list/payload = list(
activerecord = "\ref[active_record]",
activerecord = "\ref[active_BR]",
health = (H && istype(H)) ? H.sensehealth() : "",
realname = sanitize(active_record.dna.real_name),
unidentity = active_record.dna.uni_identity,
strucenzymes = active_record.dna.struc_enzymes,
realname = sanitize(active_BR.mydna.dna.real_name),
unidentity = active_BR.mydna.dna.uni_identity,
strucenzymes = active_BR.mydna.dna.struc_enzymes,
)
tgui_modal_message(src, action, "", null, payload)
else
active_record = null
active_BR = null
set_temp("Error: Record missing.", "danger")
if("del_rec")
if(!active_record)
if(!active_BR)
return
tgui_modal_boolean(src, action, "Please confirm that you want to delete the record by holding your ID and pressing Delete:", yes_text = "Delete", no_text = "Cancel")
if("disk") // Disk management.
@@ -277,20 +276,20 @@
if(isnull(diskette) || isnull(diskette.stored)) // Traitgenes Storing the entire body record
set_temp("Error: The disk's data could not be read.", "danger")
return
else if(isnull(active_record))
else if(isnull(active_BR))
set_temp("Error: No active record was found.", "danger")
menu = MENU_MAIN
return
active_record = diskette.stored.mydna // Traitgenes Storing the entire body record
active_BR = new(diskette.stored) // Traitgenes Storing the entire body record
set_temp("Successfully loaded from disk.", "success")
if("save")
if(isnull(diskette) || isnull(active_record)) // Traitgenes Removed readonly
if(isnull(diskette) || isnull(active_BR)) // Traitgenes Removed readonly
set_temp("Error: The data could not be saved.", "danger")
return
diskette.stored.mydna = active_record // Traitgenes Storing the entire body record
diskette.name = "data disk - '[active_record.dna.real_name]'"
diskette.stored = new(active_BR) // Traitgenes Storing the entire body record
diskette.name = "data disk - '[active_BR.mydna.dna.real_name]'"
set_temp("Successfully saved to disk.", "success")
if("eject")
if(!isnull(diskette))
@@ -26,20 +26,23 @@
/datum/category_item/player_setup_item/vore/resleeve/copy_to_mob(var/mob/living/carbon/human/character)
if(character && !istype(character,/mob/living/carbon/human/dummy))
spawn(50)
if(QDELETED(character) || QDELETED(pref))
return // They might have been deleted during the wait
if(!character.virtual_reality_mob && !(/mob/living/carbon/human/proc/perform_exit_vr in character.verbs)) //Janky fix to prevent resleeving VR avatars but beats refactoring transcore
if(pref.resleeve_scan)
var/datum/transhuman/body_record/BR = new()
BR.init_from_mob(character, pref.resleeve_scan, pref.resleeve_lock)
if(pref.mind_scan)
var/datum/transcore_db/our_db = SStranscore.db_by_key(null)
if(our_db)
our_db.m_backup(character.mind,character.nif,one_time = TRUE)
if(pref.resleeve_lock)
character.resleeve_lock = character.ckey
character.original_player = character.ckey
addtimer(CALLBACK(character, TYPE_PROC_REF(/mob/living/carbon/human,initial_record_sync), pref), 5 SECONDS, TIMER_DELETE_ME)
/mob/living/carbon/human/proc/initial_record_sync(var/datum/preferences/pref)
if(QDELETED(src) || QDELETED(pref))
return // They might have been deleted during the wait
if(!virtual_reality_mob && !(/mob/living/carbon/human/proc/perform_exit_vr in verbs)) //Janky fix to prevent resleeving VR avatars but beats refactoring transcore
if(pref.resleeve_scan)
var/datum/transhuman/body_record/BR = new()
BR.init_from_mob(src, pref.resleeve_scan, pref.resleeve_lock)
if(pref.mind_scan)
var/datum/transcore_db/our_db = SStranscore.db_by_key(null)
if(our_db)
our_db.m_backup(mind,nif,one_time = TRUE)
if(pref.resleeve_lock)
resleeve_lock = ckey
original_player = ckey
SEND_SIGNAL(src, COMSIG_INITIAL_RECORDS)
/datum/category_item/player_setup_item/vore/resleeve/content(var/mob/user)
. += "<br>"
+5
View File
@@ -679,7 +679,12 @@
return 1
return 0
/// Revives a body using the client's preferences if human
/mob/living/proc/revive()
revival_healing_action()
/// Performs the actual healing of Aheal, seperate from revive() because it does not use client prefs. Will not heal everything, and expects to be called through revive() or with a bodyrecord doing a respawn/revive.
/mob/living/proc/revival_healing_action()
rejuvenate()
if(buckled)
buckled.unbuckle_mob()
+59 -13
View File
@@ -246,24 +246,35 @@
*/
/// The core of resleeving, creates a mob based on the current record
/datum/transhuman/body_record/proc/produce_human_mob(var/is_synthfab, var/force_unlock, var/backup_name)
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, mydna.dna.species)
if(!mydna.dna.real_name)
mydna.dna.real_name = backup_name
H.real_name = mydna.dna.real_name
// Setup body
/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_virgocharacterdata(H)
// Finish off
H.suiciding = 0
H.mind = null
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.gender = mydna.gender
H.descriptors = mydna.body_descriptors
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)
@@ -274,6 +285,7 @@
// 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)
@@ -313,11 +325,14 @@
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
@@ -338,10 +353,10 @@
H.regenerate_icons()
H.initialize_vessel()
/// Transfers VORE related information cached in the mob
/datum/transhuman/body_record/proc/internal_producebody_virgocharacterdata(var/mob/living/carbon/human/H)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
//Basically all the VORE stuff
H.ooc_notes = body_oocnotes
H.ooc_notes_likes = body_ooclikes
H.ooc_notes_dislikes = body_oocdislikes
@@ -354,3 +369,34 @@
H.weight = weight
if(speciesname)
H.custom_species = speciesname
/// Rebuild a body from a record, like aheal, but without save files. Primarily used for anything that heals like xenochimera.
/datum/transhuman/body_record/proc/rebuild_human_mob(var/mob/living/carbon/human/H,var/heal_robot_limbs)
// 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
// Reset our organs/limbs.
H.species.create_organs(H)
internal_producebody_updatelimbandorgans(H)
//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 prefs.copy_to() is applied, as it refreshes the traits list!
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,heal_robot_limbs)
// Begin actual REVIVIAL. Do NOT use revive(). That uses client prefs and allows save hacking.
H.revival_healing_action()
return H
+2 -2
View File
@@ -29,7 +29,7 @@
remove_biomass(CLONE_BIOMASS)
//Get the DNA and generate a new mob
var/mob/living/carbon/human/H = current_project.produce_human_mob(FALSE,FALSE,"clone ([rand(0,999)])")
var/mob/living/carbon/human/H = current_project.produce_human_mob(src,FALSE,FALSE,"clone ([rand(0,999)])")
//Give breathing equipment if needed
if(current_project.breath_type != null && current_project.breath_type != GAS_O2)
@@ -206,7 +206,7 @@
return
//Get the DNA and generate a new mob
var/mob/living/carbon/human/H = current_project.produce_human_mob(TRUE,FALSE,"synth ([rand(0,999)])")
var/mob/living/carbon/human/H = current_project.produce_human_mob(src,TRUE,FALSE,"synth ([rand(0,999)])")
//Apply damage
H.adjustBruteLoss(brute_value)