Prevents limb regeneration when changing species (#19945)

* Prevents clings from quick regenerating bodyparts

* Clarify a comment

* Reworks to work with monkeys and other sources as well

* qdel organ if it doesn't get inserted

* Use initial instead of creating and qdeling

* Revert unnecessary cast
This commit is contained in:
Luc
2023-01-05 11:52:34 -06:00
committed by GitHub
parent 6491512cbd
commit 4b255c16e4
8 changed files with 61 additions and 21 deletions
+23 -4
View File
@@ -1243,7 +1243,7 @@
/mob/living/carbon/human/proc/change_dna(datum/dna/new_dna, include_species_change = FALSE, keep_flavor_text = FALSE)
if(include_species_change)
set_species(new_dna.species.type, retain_damage = TRUE, transformation = TRUE)
set_species(new_dna.species.type, retain_damage = TRUE, transformation = TRUE, keep_missing_bodyparts = TRUE)
dna = new_dna.Clone()
if (include_species_change) //We have to call this after new_dna.Clone() so that species actions don't get overwritten
dna.species.on_species_gain(src)
@@ -1258,7 +1258,19 @@
sec_hud_set_ID()
/mob/living/carbon/human/proc/set_species(datum/species/new_species, use_default_color = FALSE, delay_icon_update = FALSE, skip_same_check = FALSE, retain_damage = FALSE, transformation = FALSE)
/**
* Change a mob's species.
*
* Arguments:
* * new_species - The user's new species.
* * use_default_color - If true, use the species' default color for the new mob.
* * delay_icon_update - If true, UpdateAppearance() won't be called in this proc.
* * skip_same_check - If true, don't bail out early if we would be changing to our current species and run through everything anyway.
* * retain_damage - If true, damage on the mob will be re-applied post-transform. Otherwise, the mob will have its organs healed.
* * transformation - If true, don't apply new species traits to the mob. A false value should be used when creating a new mob instead of transforming into a new species.
* * keep_missing_bodyparts - If true, any bodyparts (legs, head, etc.) that were missing on the mob before species change will be missing post-change as well.
*/
/mob/living/carbon/human/proc/set_species(datum/species/new_species, use_default_color = FALSE, delay_icon_update = FALSE, skip_same_check = FALSE, retain_damage = FALSE, transformation = FALSE, keep_missing_bodyparts = FALSE)
if(!skip_same_check)
if(dna.species.name == initial(new_species.name))
return
@@ -1316,9 +1328,16 @@
if(!transformation) //Distinguish between creating a mob and switching species
dna.species.on_species_gain(src)
var/list/missing_bodyparts = list() // should line up here to pop out only what's missing
if(keep_missing_bodyparts)
for(var/organ_name as anything in bodyparts_by_name)
if(isnull(bodyparts_by_name[organ_name]))
missing_bodyparts |= organ_name
if(retain_damage)
//Create a list of body parts which are damaged by burn or brute and save them to apply after new organs are generated. First we just handle external organs.
var/bodypart_damages = list()
//Loop through all external organs and save the damage states for brute and burn
for(var/obj/item/organ/external/E as anything in bodyparts)
if(E.brute_dam == 0 && E.burn_dam == 0 && !(E.status & ORGAN_INT_BLEEDING)) //If there's no damage we don't bother remembering it.
@@ -1342,7 +1361,7 @@
internal_damages += list(stats)
//Create the new organs for the species change
dna.species.create_organs(src)
dna.species.create_organs(src, missing_bodyparts)
//Apply relevant damages and variables to the new organs.
for(var/obj/item/organ/external/E as anything in bodyparts)
@@ -1377,7 +1396,7 @@
qdel(part)
else
dna.species.create_organs(src)
dna.species.create_organs(src, missing_bodyparts)
for(var/obj/item/thing in kept_items)
var/equipped = equip_to_slot_if_possible(thing, kept_items[thing])
@@ -190,7 +190,15 @@
var/datum/language/species_language = GLOB.all_languages[language]
return species_language.get_random_name(gender)
/datum/species/proc/create_organs(mob/living/carbon/human/H) //Handles creation of mob organs.
/**
* Handles creation of mob organs.
*
* Arguments:
* * H: The human to create organs inside of
* * bodyparts_to_omit: Any bodyparts in this list (and organs within them) should not be added.
*/
/datum/species/proc/create_organs(mob/living/carbon/human/H, list/bodyparts_to_omit) //Handles creation of mob organs.
QDEL_LIST_CONTENTS(H.internal_organs)
QDEL_LIST_CONTENTS(H.bodyparts)
@@ -198,21 +206,29 @@
LAZYREINITLIST(H.bodyparts_by_name)
LAZYREINITLIST(H.internal_organs)
for(var/limb_type in has_limbs)
var/list/organ_data = has_limbs[limb_type]
for(var/limb_name in has_limbs)
if(bodyparts_to_omit && (limb_name in bodyparts_to_omit))
H.bodyparts_by_name[limb_name] = null // Null it out, but leave the name here so it's still "there"
continue
var/list/organ_data = has_limbs[limb_name]
var/limb_path = organ_data["path"]
var/obj/item/organ/O = new limb_path(H)
organ_data["descriptor"] = O.name
for(var/index in has_organ)
var/organ = has_organ[index]
// organ new code calls `insert` on its own
new organ(H)
var/obj/item/organ/internal/organ_path = has_organ[index]
if(initial(organ_path.parent_organ) in bodyparts_to_omit)
continue
var/obj/item/organ/internal/org = new organ_path()
org.insert(H)
create_mutant_organs(H)
for(var/name in H.bodyparts_by_name)
H.bodyparts |= H.bodyparts_by_name[name]
var/part_type = H.bodyparts_by_name[name]
if(!isnull(part_type))
H.bodyparts |= part_type // we do not want nulls here, even though it's alright to have them in bodyparts_by_name
for(var/obj/item/organ/external/E as anything in H.bodyparts)
E.owner = H
@@ -221,10 +237,15 @@
/datum/species/proc/create_mutant_organs(mob/living/carbon/human/H)
var/obj/item/organ/internal/ears/ears = H.get_int_organ(/obj/item/organ/internal/ears)
if(ears)
if(istype(ears, mutantears))
// if they're the same, just heal them and don't bother replacing them
ears.rejuvenate()
return
qdel(ears)
if(mutantears)
ears = new mutantears(H)
if(mutantears && !isnull(H.bodyparts_by_name[initial(mutantears.parent_organ)]))
var/obj/item/organ/internal/ears/new_ears = new mutantears()
new_ears.insert(H)
/datum/species/proc/breathe(mob/living/carbon/human/H)
if(HAS_TRAIT(H, TRAIT_NOBREATH))
+1 -1
View File
@@ -1,6 +1,6 @@
/mob/living/carbon/human/proc/monkeyize()
var/mob/H = src
H.dna.SetSEState(GLOB.monkeyblock,1)
H.dna.SetSEState(GLOB.monkeyblock, 1)
singlemutcheck(H, GLOB.monkeyblock, MUTCHK_FORCED)
/mob/new_player/AIize()