diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 6e72897d12c..ea1d94ce790 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -13,6 +13,10 @@ ///Take on the dna/preference from whoever we're gonna be inserted in var/imprint_on_next_insertion = TRUE +/datum/bodypart_overlay/mutant/get_overlay(layer, obj/item/bodypart/limb) + inherit_color(limb) // If draw_color is not set yet, go ahead and do that + return ..() + ///Completely random image and color generation (obeys what a player can choose from) /datum/bodypart_overlay/mutant/proc/randomize_appearance() randomize_sprite() @@ -90,8 +94,13 @@ ///Give the organ its color. Force will override the existing one. /datum/bodypart_overlay/mutant/proc/inherit_color(obj/item/bodypart/ownerlimb, force) + if(isnull(ownerlimb)) + draw_color = null + return TRUE + if(draw_color && !force) - return + return FALSE + switch(color_source) if(ORGAN_COLOR_OVERRIDE) draw_color = override_color(ownerlimb.draw_color) @@ -102,6 +111,7 @@ return var/mob/living/carbon/human/human_owner = ownerlimb.owner draw_color = human_owner.hair_color + return TRUE ///Sprite accessories are singletons, stored list("Big Snout" = instance of /datum/sprite_accessory/snout/big), so here we get that singleton diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 3eb448aa90c..7e2938df5da 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -167,9 +167,9 @@ GLOBAL_LIST_EMPTY(features_by_species) ///What anim to use for gibbing var/gib_anim = "gibbed-h" - - //Do NOT remove by setting to null. use OR make an ASSOCIATED TRAIT. - //why does it work this way? because traits also disable the downsides of not having an organ, removing organs but not having the trait will make your species die + // Prefer anything other than setting these to null, such as TRAITS + // why? + // because traits also disable the downsides of not having an organ, removing organs but not having the trait or logic will make your species die ///Replaces default brain with a different organ var/obj/item/organ/internal/brain/mutantbrain = /obj/item/organ/internal/brain @@ -345,6 +345,9 @@ GLOBAL_LIST_EMPTY(features_by_species) var/obj/item/organ/oldorgan = C.getorganslot(slot) //used in removing var/obj/item/organ/neworgan = slot_mutantorgans[slot] //used in adding if(!neworgan) //these can be null, if so we shouldn't regenerate + if(oldorgan) // although we also need to remove the old organ if it exists + oldorgan.Remove(C, special=TRUE) + qdel(oldorgan) continue if(visual_only && !initial(neworgan.visual)) diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm index b1c97ae3587..94e4722e663 100644 --- a/code/modules/surgery/organs/external/_external_organs.dm +++ b/code/modules/surgery/organs/external/_external_organs.dm @@ -158,7 +158,7 @@ //Build the mob sprite and use it as our overlay for(var/external_layer in bodypart_overlay.all_layers) if(bodypart_overlay.layers & external_layer) - . += bodypart_overlay.get_overlay(external_layer, limb = null) + . += bodypart_overlay.get_overlay(external_layer, ownerlimb) ///The horns of a lizard! /obj/item/organ/external/horns @@ -356,8 +356,11 @@ if(draw_layer != bitflag_to_layer(color_swapped_layer)) return ..() - var/list/rgb_list = rgb2num(draw_color) - overlay.color = rgb(color_inverse_base - rgb_list[1], color_inverse_base - rgb_list[2], color_inverse_base - rgb_list[3]) //inversa da color + if(draw_color) // can someone explain to me why draw_color is allowed to EVER BE AN EMPTY STRING + var/list/rgb_list = rgb2num(draw_color) + overlay.color = rgb(color_inverse_base - rgb_list[1], color_inverse_base - rgb_list[2], color_inverse_base - rgb_list[3]) //inversa da color + else + overlay.color = null /datum/bodypart_overlay/mutant/pod_hair/can_draw_on_bodypart(mob/living/carbon/human/human) if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR)) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 3648417e05c..7be24238634 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -152,6 +152,7 @@ #include "monkey_business.dm" #include "mouse_bite_cable.dm" #include "mutant_hands_consistency.dm" +#include "mutant_organs.dm" #include "novaflower_burn.dm" #include "ntnetwork_tests.dm" #include "nuke_cinematic.dm" diff --git a/code/modules/unit_tests/mutant_organs.dm b/code/modules/unit_tests/mutant_organs.dm new file mode 100644 index 00000000000..b61dacdb477 --- /dev/null +++ b/code/modules/unit_tests/mutant_organs.dm @@ -0,0 +1,65 @@ +/** + * Iterates over all species to ensure that organs are valid after being set to a mutant species + */ +/datum/unit_test/mutant_organs + +/datum/unit_test/mutant_organs/Run() + var/mob/living/carbon/human/consistent/dummy = allocate(/mob/living/carbon/human/consistent) + var/list/ignore = list( + /datum/species/dullahan, + ) + var/list/species = subtypesof(/datum/species) - ignore + var/static/list/organs_we_care_about = list( + ORGAN_SLOT_BRAIN, + ORGAN_SLOT_HEART, + ORGAN_SLOT_LUNGS, + ORGAN_SLOT_EYES, + ORGAN_SLOT_EARS, + ORGAN_SLOT_TONGUE, + ORGAN_SLOT_LIVER, + ORGAN_SLOT_STOMACH, + ORGAN_SLOT_APPENDIX, + ) + + for(var/datum/species/species_type as anything in species) + // change them to the species + dummy.set_species(species_type) + + // check all their organs + for(var/organ_slot in organs_we_care_about) + var/expected_type = slot_to_species_organ_type(organ_slot, species_type) + var/obj/item/organ/actual_organ = dummy.getorganslot(organ_slot) + if(isnull(actual_organ)) + if(!isnull(expected_type)) + TEST_FAIL("[species_type] did not update their [organ_slot] organ to [expected_type], no organ was found") + continue + else + if(isnull(expected_type)) + TEST_FAIL("[species_type] did not remove their [organ_slot] organ") + continue + + if(actual_organ.type != expected_type) + TEST_FAIL("[species_type] did not update their [organ_slot] organ to [expected_type], instead it was [actual_organ.type]") + continue + +/datum/unit_test/mutant_organs/proc/slot_to_species_organ_type(slot, datum/species/species) + switch(slot) + if(ORGAN_SLOT_BRAIN) + return initial(species.mutantbrain) + if(ORGAN_SLOT_HEART) + return initial(species.mutantheart) + if(ORGAN_SLOT_LUNGS) + return initial(species.mutantlungs) + if(ORGAN_SLOT_EYES) + return initial(species.mutanteyes) + if(ORGAN_SLOT_EARS) + return initial(species.mutantears) + if(ORGAN_SLOT_TONGUE) + return initial(species.mutanttongue) + if(ORGAN_SLOT_LIVER) + return initial(species.mutantliver) + if(ORGAN_SLOT_STOMACH) + return initial(species.mutantstomach) + if(ORGAN_SLOT_APPENDIX) + return initial(species.mutantappendix) + CRASH("Invalid organ slot [slot]") // just incase someone adds an organ we care about and forgets to add it here