diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 2c746200f72..eedad7977d6 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -500,6 +500,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /////////////////////////// DNA MOB-PROCS ////////////////////// /mob/proc/set_species(datum/species/mrace, icon_update = 1) + SHOULD_NOT_SLEEP(TRUE) return /mob/living/brain/set_species(datum/species/mrace, icon_update = 1) @@ -524,7 +525,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) else return death_sound = new_race.death_sound - dna.species.on_species_loss(src, new_race, pref_load) + + if (dna.species.properly_gained) + dna.species.on_species_loss(src, new_race, pref_load) + var/datum/species/old_species = dna.species dna.species = new_race dna.species.on_species_gain(src, old_species, pref_load) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 0bc30aa64b3..1c6ecf7ba9c 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -168,7 +168,10 @@ Medical HUD! Basic mode needs suit sensors on. //called when a living mob changes health /mob/living/proc/med_hud_set_health() - var/image/holder = hud_list[HEALTH_HUD] + var/image/holder = hud_list?[HEALTH_HUD] + if (isnull(holder)) + return + holder.icon_state = "hud[RoundHealth(src)]" var/icon/I = icon(icon, icon_state, dir) holder.pixel_y = I.Height() - world.icon_size @@ -179,7 +182,10 @@ Medical HUD! Basic mode needs suit sensors on. //called when a carbon changes stat, virus or XENO_HOST /mob/living/proc/med_hud_set_status() - var/image/holder = hud_list[STATUS_HUD] + var/image/holder = hud_list?[STATUS_HUD] + if (isnull(holder)) + return + var/icon/I = icon(icon, icon_state, dir) holder.pixel_y = I.Height() - world.icon_size if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH))) @@ -188,7 +194,10 @@ Medical HUD! Basic mode needs suit sensors on. holder.icon_state = "hudhealthy" /mob/living/carbon/med_hud_set_status() - var/image/holder = hud_list[STATUS_HUD] + var/image/holder = hud_list?[STATUS_HUD] + if (isnull(holder)) + return + var/icon/I = icon(icon, icon_state, dir) var/virus_threat = check_virus() holder.pixel_y = I.Height() - world.icon_size diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index f8ae0688f35..efb0961dca8 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -35,7 +35,7 @@ human.dna.blood_type = random_blood_type() human.dna.features["mcolor"] = "#[random_color()]" - human.dna.species.randomize_active_underwear(human) + human.dna.species.randomize_active_underwear_only(human) for(var/datum/species/species_path as anything in subtypesof(/datum/species)) var/datum/species/new_species = new species_path diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e6c7957095b..33ea238bfb7 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1,6 +1,6 @@ /mob/living/carbon/Initialize(mapload) . = ..() - create_reagents(1000, REAGENT_HOLDER_ALIVE) + create_carbon_reagents() update_body_parts() //to update the carbon's new bodyparts appearance register_context() @@ -217,6 +217,12 @@ /mob/living/carbon/proc/canBeHandcuffed() return FALSE +/mob/living/carbon/proc/create_carbon_reagents() + if (!isnull(reagents)) + return + + create_reagents(1000, REAGENT_HOLDER_ALIVE) + /mob/living/carbon/Topic(href, href_list) ..() if(href_list["embedded_object"] && usr.canUseTopic(src, be_close = TRUE, no_dexterity = TRUE)) @@ -986,11 +992,14 @@ to_chat(user, span_notice("You retrieve some of [src]\'s internal organs!")) remove_all_embedded_objects() -/mob/living/carbon/proc/create_bodyparts() +/// Creates body parts for this carbon completely from scratch. +/// Optionally takes a map of body zones to what type to instantiate instead of them. +/mob/living/carbon/proc/create_bodyparts(list/overrides) var/l_arm_index_next = -1 var/r_arm_index_next = 0 - for(var/bodypart_path in bodyparts) - var/obj/item/bodypart/bodypart_instance = new bodypart_path() + for(var/obj/item/bodypart/bodypart_path as anything in bodyparts) + var/real_body_part_path = overrides?[initial(bodypart_path.body_zone)] || bodypart_path + var/obj/item/bodypart/bodypart_instance = new real_body_part_path() bodypart_instance.set_owner(src) bodyparts.Remove(bodypart_path) add_bodypart(bodypart_instance) diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index e0f3c7ebbc5..86b5cde7c29 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -69,7 +69,9 @@ /// Total level of visualy impairing items var/tinttotal = 0 - ///Gets filled up in [create_bodyparts()][/mob/living/carbon/proc/create_bodyparts] + /// Gets filled up in [/datum/species/proc/replace_body]. + /// Will either contain a list of typepaths if nothing has been created yet, + /// or a list of the body part objects. var/list/bodyparts = list( /obj/item/bodypart/chest, /obj/item/bodypart/head, diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 7679432e9cd..3c9714d4965 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -83,7 +83,6 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) return /proc/create_consistent_human_dna(mob/living/carbon/human/target) - target.create_dna() target.dna.initialize_dna(skip_index = TRUE) target.dna.features["body_markings"] = "None" target.dna.features["ears"] = "None" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 98756edd90d..2c457a08bfe 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -4,16 +4,16 @@ icon_state = "" //Remove the inherent human icon that is visible on the map editor. We're rendering ourselves limb by limb, having it still be there results in a bug where the basic human icon appears below as south in all directions and generally looks nasty. - //initialize limbs first - create_bodyparts() - setup_mood() + create_dna() + dna.species.create_fresh_body(src) setup_human_dna() - prepare_huds() //Prevents a nasty runtime on human init - if(dna.species) - INVOKE_ASYNC(src, PROC_REF(set_species), dna.species.type) + create_carbon_reagents() + set_species(dna.species.type) + + prepare_huds() //Prevents a nasty runtime on human init //initialise organs create_internal_organs() //most of it is done in set_species now, this is only for parent call @@ -43,7 +43,6 @@ /mob/living/carbon/human/proc/setup_human_dna() //initialize dna. for spawned humans; overwritten by other code - create_dna(src) randomize_human(src) dna.initialize_dna() @@ -1067,9 +1066,10 @@ var/race = null var/use_random_name = TRUE -/mob/living/carbon/human/species/Initialize(mapload) - . = ..() - INVOKE_ASYNC(src, PROC_REF(set_species), race) +/mob/living/carbon/human/species/create_dna() + dna = new /datum/dna(src) + if (!isnull(race)) + dna.species = new race /mob/living/carbon/human/species/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE, list/override_features, list/override_mutantparts, list/override_markings, retain_features = FALSE, retain_mutantparts = FALSE) // SKYRAT EDIT - Customization . = ..() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 6c5609ca062..feb3ef779d4 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -223,6 +223,10 @@ GLOBAL_LIST_EMPTY(features_by_species) /// This supresses the "dosen't appear to be himself" examine text for if the mob is run by an AI controller. Should be used on any NPC human subtypes. Monkeys are the prime example. var/ai_controlled_species = FALSE + /// Was on_species_gain ever actually called? + /// Species code is really odd... + var/properly_gained = FALSE + /////////// // PROCS // /////////// @@ -448,7 +452,9 @@ GLOBAL_LIST_EMPTY(features_by_species) C.mob_biotypes = inherent_biotypes - replace_body(C, src) + if (old_species.type != type) + replace_body(C, src) + regenerate_organs(C, old_species, visual_only = C.visual_only_organs) INVOKE_ASYNC(src, PROC_REF(worn_items_fit_body_check), C, TRUE) @@ -510,6 +516,8 @@ GLOBAL_LIST_EMPTY(features_by_species) SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) + properly_gained = TRUE + /** * Proc called when a carbon is no longer this species. * @@ -809,11 +817,16 @@ GLOBAL_LIST_EMPTY(features_by_species) return "FRONT_OVER" //SKYRAT EDIT ADDITION END -///Proc that will randomise the underwear (i.e. top, pants and socks) of a species' associated mob -/datum/species/proc/randomize_active_underwear(mob/living/carbon/human/human_mob) +///Proc that will randomise the underwear (i.e. top, pants and socks) of a species' associated mob, +/// but will not update the body right away. +/datum/species/proc/randomize_active_underwear_only(mob/living/carbon/human/human_mob) human_mob.undershirt = random_undershirt(human_mob.gender) human_mob.underwear = random_underwear(human_mob.gender) human_mob.socks = random_socks(human_mob.gender) + +///Proc that will randomise the underwear (i.e. top, pants and socks) of a species' associated mob +/datum/species/proc/randomize_active_underwear(mob/living/carbon/human/human_mob) + randomize_active_underwear_only(human_mob) human_mob.update_body() ///Proc that will randomize all the external organs (i.e. horns, frills, tails etc.) of a species' associated mob @@ -2247,3 +2260,7 @@ GLOBAL_LIST_EMPTY(features_by_species) new_part.replace_limb(target, TRUE) new_part.update_limb(is_creating = TRUE) qdel(old_part) + +/// Creates body parts for the target completely from scratch based on the species +/datum/species/proc/create_fresh_body(mob/living/carbon/target) + target.create_bodyparts(bodypart_overrides) diff --git a/modular_skyrat/modules/customization/datums/dna.dm b/modular_skyrat/modules/customization/datums/dna.dm index d585b0b98a2..0a517782bb1 100644 --- a/modular_skyrat/modules/customization/datums/dna.dm +++ b/modular_skyrat/modules/customization/datums/dna.dm @@ -199,7 +199,8 @@ GLOBAL_LIST_EMPTY(total_uf_len_by_block) else return death_sound = new_race.death_sound - dna.species.on_species_loss(src, new_race, pref_load) + if (dna.species.properly_gained) + dna.species.on_species_loss(src, new_race, pref_load) var/datum/species/old_species = dna.species dna.species = new_race