diff --git a/code/datums/components/defibrillator.dm b/code/datums/components/defibrillator.dm index 32144f9279e..b2b244e98ac 100644 --- a/code/datums/components/defibrillator.dm +++ b/code/datums/components/defibrillator.dm @@ -242,7 +242,7 @@ busy = FALSE return - if(target.stat != DEAD) + if(target.stat != DEAD && !HAS_TRAIT(target, TRAIT_FAKEDEATH)) user.visible_message("[defib_ref] buzzes: Patient is not in a valid state. Operation aborted.") playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0) SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm) @@ -262,6 +262,8 @@ // run through some quick failure states after shocking. + var/obj/item/organ/internal/brain/brain_org = target.get_organ_slot("brain") + if(tplus > tlimit || (!target.get_int_organ(/obj/item/organ/internal/heart || !target.get_int_organ(/obj/item/organ/internal/brain/slime)))) user.visible_message("[defib_ref] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.") defib_success = FALSE @@ -274,13 +276,16 @@ else if (target.blood_volume < BLOOD_VOLUME_SURVIVE) user.visible_message("[defib_ref] buzzes: Resuscitation failed - Patient blood volume critically low.") defib_success = FALSE + else if(!istype(brain_org)) // so things like headless clings don't get outed + user.visible_message("[defib_ref] buzzes: Resuscitation failed - No brain detected within patient.") + defib_success = FALSE else if(ghost) if(!ghost.can_reenter_corpse) // DNR or AntagHUD user.visible_message("[defib_ref] buzzes: Resuscitation failed - No electrical brain activity detected.") else user.visible_message("[defib_ref] buzzes: Resuscitation failed - Patient's brain is unresponsive. Further attempts may succeed.") defib_success = FALSE - else if(HAS_TRAIT(target, TRAIT_BADDNA) || (signal_result & COMPONENT_BLOCK_DEFIB)) // these are a bit more arbitrary + else if((signal_result & COMPONENT_BLOCK_DEFIB) || HAS_TRAIT(target, TRAIT_FAKEDEATH) || HAS_TRAIT(target, TRAIT_BADDNA)) // these are a bit more arbitrary user.visible_message("[defib_ref] buzzes: Resuscitation failed.") defib_success = FALSE diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm index d2c9819e098..b3eaaba83cc 100644 --- a/code/datums/diseases/advance/symptoms/beard.dm +++ b/code/datums/diseases/advance/symptoms/beard.dm @@ -31,6 +31,8 @@ BONUS if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!istype(head_organ)) + return switch(A.stage) if(1, 2) to_chat(H, "Your chin itches.") diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm index 2a6b0ba5bac..917ccbf14f6 100644 --- a/code/datums/diseases/advance/symptoms/shedding.dm +++ b/code/datums/diseases/advance/symptoms/shedding.dm @@ -26,23 +26,26 @@ BONUS /datum/symptom/shedding/Activate(datum/disease/advance/A) ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - to_chat(M, "[pick("Your scalp itches.", "Your skin feels flakey.")]") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(NO_HAIR in H.dna.species.species_traits) - return // Hair can't fall out if you don't have any - var/obj/item/organ/external/head/head_organ = H.get_organ("head") - switch(A.stage) - if(3, 4) - if(!(head_organ.h_style == "Bald") && !(head_organ.h_style == "Balding Hair")) - to_chat(H, "Your hair starts to fall out in clumps...") - addtimer(CALLBACK(src, PROC_REF(change_hair), H, head_organ, null, "Balding Hair"), 5 SECONDS) - if(5) - if(!(head_organ.f_style == "Shaved") || !(head_organ.h_style == "Bald")) - to_chat(H, "Your hair starts to fall out in clumps...") - addtimer(CALLBACK(src, PROC_REF(change_hair), H, head_organ, "Shaved", "Bald"), 5 SECONDS) + if(!prob(SYMPTOM_ACTIVATION_PROB)) + return + if(!ishuman(A.affected_mob)) + return + var/mob/living/carbon/human/H = A.affected_mob + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!istype(head_organ)) + return + to_chat(H, "[pick("Your scalp itches.", "Your skin feels flakey.")]") + if(NO_HAIR in H.dna.species.species_traits) + return // Hair can't fall out if you don't have any + switch(A.stage) + if(3, 4) + if(head_organ.h_style != "Bald" && head_organ.h_style != "Balding Hair") + to_chat(H, "Your hair starts to fall out in clumps...") + addtimer(CALLBACK(src, PROC_REF(change_hair), H, head_organ, null, "Balding Hair"), 5 SECONDS) + if(5) + if((head_organ.f_style != "Shaved") || (head_organ.h_style != "Bald")) + to_chat(H, "Your hair starts to fall out in clumps...") + addtimer(CALLBACK(src, PROC_REF(change_hair), H, head_organ, "Shaved", "Bald"), 5 SECONDS) /datum/symptom/shedding/proc/change_hair(mob/living/carbon/human/H, obj/item/organ/external/head/head_organ, f_style, h_style) if(!H || !head_organ) diff --git a/code/game/dna/mutations/powers.dm b/code/game/dna/mutations/powers.dm index b23c12d8874..b1860da7d95 100644 --- a/code/game/dna/mutations/powers.dm +++ b/code/game/dna/mutations/powers.dm @@ -766,58 +766,60 @@ if(new_eyes) M.change_eye_color(new_eyes) - //Alt heads. - if(head_organ.dna.species.bodyflags & HAS_ALT_HEADS) - var/list/valid_alt_heads = M.generate_valid_alt_heads() - var/new_alt_head = input("Please select alternate head", "Character Generation", head_organ.alt_head) as null|anything in valid_alt_heads - if(new_alt_head) - M.change_alt_head(new_alt_head) + if(istype(head_organ)) + //Alt heads. + if(head_organ.dna.species.bodyflags & HAS_ALT_HEADS) + var/list/valid_alt_heads = M.generate_valid_alt_heads() + var/new_alt_head = input("Please select alternate head", "Character Generation", head_organ.alt_head) as null|anything in valid_alt_heads + if(new_alt_head) + M.change_alt_head(new_alt_head) - // hair - var/list/valid_hairstyles = M.generate_valid_hairstyles() - var/new_style = input("Please select hair style", "Character Generation", head_organ.h_style) as null|anything in valid_hairstyles + // hair + var/list/valid_hairstyles = M.generate_valid_hairstyles() + var/new_style = input("Please select hair style", "Character Generation", head_organ.h_style) as null|anything in valid_hairstyles - // if new style selected (not cancel) - if(new_style) - M.change_hair(new_style) + // if new style selected (not cancel) + if(new_style) + M.change_hair(new_style) - var/new_hair = input("Please select hair color.", "Character Generation", head_organ.hair_colour) as null|color - if(new_hair) - M.change_hair_color(new_hair) - - var/datum/sprite_accessory/hair_style = GLOB.hair_styles_public_list[head_organ.h_style] - if(hair_style.secondary_theme && !hair_style.no_sec_colour) - new_hair = input("Please select secondary hair color.", "Character Generation", head_organ.sec_hair_colour) as null|color + var/new_hair = input("Please select hair color.", "Character Generation", head_organ.hair_colour) as null|color if(new_hair) - M.change_hair_color(new_hair, 1) + M.change_hair_color(new_hair) - // facial hair - var/list/valid_facial_hairstyles = M.generate_valid_facial_hairstyles() - new_style = input("Please select facial style", "Character Generation", head_organ.f_style) as null|anything in valid_facial_hairstyles + var/datum/sprite_accessory/hair_style = GLOB.hair_styles_public_list[head_organ.h_style] + if(hair_style.secondary_theme && !hair_style.no_sec_colour) + new_hair = input("Please select secondary hair color.", "Character Generation", head_organ.sec_hair_colour) as null|color + if(new_hair) + M.change_hair_color(new_hair, TRUE) - if(new_style) - M.change_facial_hair(new_style) + // facial hair + var/list/valid_facial_hairstyles = M.generate_valid_facial_hairstyles() + new_style = input("Please select facial style", "Character Generation", head_organ.f_style) as null|anything in valid_facial_hairstyles - var/new_facial = input("Please select facial hair color.", "Character Generation", head_organ.facial_colour) as null|color - if(new_facial) - M.change_facial_hair_color(new_facial) + if(new_style) + M.change_facial_hair(new_style) - var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[head_organ.f_style] - if(facial_hair_style.secondary_theme && !facial_hair_style.no_sec_colour) - new_facial = input("Please select secondary facial hair color.", "Character Generation", head_organ.sec_facial_colour) as null|color + var/new_facial = input("Please select facial hair color.", "Character Generation", head_organ.facial_colour) as null|color if(new_facial) - M.change_facial_hair_color(new_facial, 1) + M.change_facial_hair_color(new_facial) - //Head accessory. - if(head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) - var/list/valid_head_accessories = M.generate_valid_head_accessories() - var/new_head_accessory = input("Please select head accessory style", "Character Generation", head_organ.ha_style) as null|anything in valid_head_accessories - if(new_head_accessory) - M.change_head_accessory(new_head_accessory) + var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[head_organ.f_style] + if(facial_hair_style.secondary_theme && !facial_hair_style.no_sec_colour) + new_facial = input("Please select secondary facial hair color.", "Character Generation", head_organ.sec_facial_colour) as null|color + if(new_facial) + M.change_facial_hair_color(new_facial, TRUE) + + //Head accessory. + if(head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) + var/list/valid_head_accessories = M.generate_valid_head_accessories() + var/new_head_accessory = input("Please select head accessory style", "Character Generation", head_organ.ha_style) as null|anything in valid_head_accessories + if(new_head_accessory) + M.change_head_accessory(new_head_accessory) + + var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", head_organ.headacc_colour) as null|color + if(new_head_accessory_colour) + M.change_head_accessory_color(new_head_accessory_colour) - var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", head_organ.headacc_colour) as null|color - if(new_head_accessory_colour) - M.change_head_accessory_color(new_head_accessory_colour) //Body accessory. if((M.dna.species.tail && M.dna.species.bodyflags & (HAS_TAIL)) || (M.dna.species.wing && M.dna.species.bodyflags & (HAS_WING))) @@ -827,16 +829,18 @@ if(new_body_accessory) M.change_body_accessory(new_body_accessory) - //Head markings. - if(M.dna.species.bodyflags & HAS_HEAD_MARKINGS) - var/list/valid_head_markings = M.generate_valid_markings("head") - var/new_marking = input("Please select head marking style", "Character Generation", M.m_styles["head"]) as null|anything in valid_head_markings - if(new_marking) - M.change_markings(new_marking, "head") + if(istype(head_organ)) + //Head markings. + if(M.dna.species.bodyflags & HAS_HEAD_MARKINGS) + var/list/valid_head_markings = M.generate_valid_markings("head") + var/new_marking = input("Please select head marking style", "Character Generation", M.m_styles["head"]) as null|anything in valid_head_markings + if(new_marking) + M.change_markings(new_marking, "head") + + var/new_marking_colour = input("Please select head marking colour.", "Character Generation", M.m_colours["head"]) as null|color + if(new_marking_colour) + M.change_marking_color(new_marking_colour, "head") - var/new_marking_colour = input("Please select head marking colour.", "Character Generation", M.m_colours["head"]) as null|color - if(new_marking_colour) - M.change_marking_color(new_marking_colour, "head") //Body markings. if(M.dna.species.bodyflags & HAS_BODY_MARKINGS) var/list/valid_body_markings = M.generate_valid_markings("body") diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 86497f5eefa..81d9c394637 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -229,7 +229,7 @@ var/occupantData[0] if(occupant) occupantData["name"] = occupant.name - occupantData["stat"] = occupant.stat + occupantData["stat"] = HAS_TRAIT(occupant, TRAIT_FAKEDEATH) ? DEAD : occupant.stat occupantData["health"] = occupant.health occupantData["maxHealth"] = occupant.maxHealth diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index eed6f6627ba..8e6268ed726 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -786,7 +786,7 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays) visible_message("[user] headbutts the airlock.") var/obj/item/organ/external/affecting = H.get_organ("head") H.Weaken(10 SECONDS) - if(affecting.receive_damage(10, 0)) + if(istype(affecting) && affecting.receive_damage(10, 0)) H.UpdateDamageIcon() else visible_message("[user] headbutts the airlock. Good thing [user.p_theyre()] wearing a helmet.") diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index d9530d82408..d746c74242f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -597,7 +597,8 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) if(!eyes) // should still get stabbed in the head var/obj/item/organ/external/head/head = H.bodyparts_by_name["head"] - head.receive_damage(rand(10,14), 1) + if(head) + head.receive_damage(rand(10, 14), 1) return eyes.receive_damage(rand(3,4), 1) if(eyes.damage >= eyes.min_bruised_damage) @@ -615,7 +616,7 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons if(M.stat != 2) to_chat(M, "You go blind!") var/obj/item/organ/external/affecting = H.get_organ("head") - if(affecting.receive_damage(7)) + if(istype(affecting) && affecting.receive_damage(7)) H.UpdateDamageIcon() else M.take_organ_damage(7) diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 7fb532cb501..90dd8b77f83 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -111,6 +111,9 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/C = H.get_organ("head") + if(!istype(C)) + to_chat(user, "There's nothing to cut, [M] [M.p_are()] missing [M.p_their()] head!") + return ..() var/datum/robolimb/robohead = GLOB.all_robolimbs[C.model] if(user.zone_selected == "mouth") if(!get_location_accessible(H, "mouth")) diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index 7cf73d16f01..afc917a9667 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -28,6 +28,9 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/C = H.get_organ("head") + if(!C) + to_chat(user, "[M] doesn't have a head!") + return //facial hair var/f_new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in H.generate_valid_facial_hairstyles() //handle normal hair diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 3cded3b9768..5569410cf9e 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -122,7 +122,7 @@ if(!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000) var/obj/item/organ/external/head/head = H.get_organ("head") - head.disfigure() + head?.disfigure() H.inflate_gib() return OBLITERATION diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index 9540ab7932a..676c3f7786f 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -108,7 +108,7 @@ var/obj/item/organ/external/head/head = H.get_organ("head") - if(QDELETED(head)) + if(QDELETED(head) || !istype(head)) blade_status = GUILLOTINE_BLADE_DROPPED icon_state = "guillotine" return diff --git a/code/modules/antagonists/changeling/datum_changeling.dm b/code/modules/antagonists/changeling/datum_changeling.dm index a86d183dbf5..6c1fd388bb4 100644 --- a/code/modules/antagonists/changeling/datum_changeling.dm +++ b/code/modules/antagonists/changeling/datum_changeling.dm @@ -111,6 +111,17 @@ for(var/power_type in innate_powers) give_power(new power_type, L) + RegisterSignal(L, COMSIG_MOB_DEATH, PROC_REF(on_death)) + + var/mob/living/carbon/C = L + + if(!istype(C)) + return + + // Brains are optional for changelings. + var/obj/item/organ/internal/brain/ling_brain = C.get_organ_slot("brain") + ling_brain?.decoy_brain = TRUE + /datum/antagonist/changeling/remove_innate_effects(mob/living/mob_override) var/mob/living/L = ..() if(!ishuman(L)) @@ -120,6 +131,7 @@ L.hud_used.lingchemdisplay.invisibility = 101 L.remove_language("Changeling") remove_unnatural_languages(L) + UnregisterSignal(L, COMSIG_MOB_DEATH) // If there's a mob_override, this is a body transfer, and therefore we should only remove their powers from the old body. if(mob_override) for(var/datum/action/changeling/power in acquired_powers) @@ -128,6 +140,16 @@ else respec(FALSE) + var/mob/living/carbon/C = L + + if(!istype(C)) + return + + // If they get de-clinged, make sure they can't just chop their own head off for the hell of it + var/obj/item/organ/internal/brain/former_ling_brain = C.get_organ_slot("brain") + if(former_ling_brain && former_ling_brain.decoy_brain != initial(former_ling_brain.decoy_brain)) + former_ling_brain.decoy_brain = FALSE + /* * Always absorb X amount of genomes, plus random traitor objectives. * If they have two objectives as well as absorb, they must survive rather than escape. @@ -400,5 +422,18 @@ return FALSE return TRUE +/datum/antagonist/changeling/proc/on_death(mob/living/L, gibbed) + SIGNAL_HANDLER + if(QDELETED(L) || gibbed) // they were probably incinerated or gibbed, no coming back from that. + return + var/mob/living/carbon/human/H = L + if(!istype(H)) + return + + if(!H.get_organ_slot("brain")) + to_chat(L, "The brain is a useless organ to us, we are able to regenerate!") + else + to_chat(L, "While our current form may be lifeless, this is not the end for us as we can still regenerate!") + /proc/ischangeling(mob/M) return M.mind?.has_antag_datum(/datum/antagonist/changeling) diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index e95dbe17534..361051f3e8d 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -91,7 +91,7 @@ return 0 var/mob/living/carbon/human/C = G.affecting var/obj/item/organ/external/head/head = C.get_organ("head") - if(!head) + if(!istype(head)) to_chat(user, "This person doesn't have a head!") return 0 C.visible_message("[user] dunks [C]'s face into [src]!", \ diff --git a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm index 82ae915fa04..ecf8850c546 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm @@ -51,7 +51,7 @@ return 0 var/mob/living/carbon/human/C = G.affecting var/obj/item/organ/external/head/head = C.get_organ("head") - if(!head) + if(!istype(head)) to_chat(user, "This person doesn't have a head!") return 0 C.visible_message("[user] bashes [C]'s head in [src]'s door!", \ diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 793440bb760..5e57fda2546 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -10,13 +10,14 @@ gender = new_gender - var/datum/sprite_accessory/hair/current_hair = GLOB.hair_styles_full_list[H.h_style] - if(current_hair.gender != NEUTER && current_hair.gender != gender) - reset_head_hair() + if(istype(H)) + var/datum/sprite_accessory/hair/current_hair = GLOB.hair_styles_full_list[H.h_style] + if(current_hair.gender != NEUTER && current_hair.gender != gender) + reset_head_hair() - var/datum/sprite_accessory/hair/current_fhair = GLOB.facial_hair_styles_list[H.f_style] - if(current_fhair.gender != NEUTER && current_fhair.gender != gender) - reset_facial_hair() + var/datum/sprite_accessory/hair/current_fhair = GLOB.facial_hair_styles_list[H.f_style] + if(current_fhair.gender != NEUTER && current_fhair.gender != gender) + reset_facial_hair() if(update_dna) update_dna() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 662d842bcf6..8358d5fc245 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -361,10 +361,9 @@ msg += "Medical records: \[View\] \[Add comment\]\n" if(print_flavor_text() && !skipface) - if(get_organ("head")) - var/obj/item/organ/external/head/H = get_organ("head") - if(!(H.status & ORGAN_DISFIGURED)) - msg += "[print_flavor_text()]\n" + var/obj/item/organ/external/head/H = get_organ("head") + if(H && !(H.status & ORGAN_DISFIGURED)) + msg += "[print_flavor_text()]\n" msg += "*---------*" if(pose) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 2928f79caa2..2d1bc194aec 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1393,32 +1393,33 @@ //Handle default hair/head accessories for created mobs. var/obj/item/organ/external/head/H = get_organ("head") - if(dna.species.default_hair) - H.h_style = dna.species.default_hair - else - H.h_style = "Bald" - if(dna.species.default_fhair) - H.f_style = dna.species.default_fhair - else - H.f_style = "Shaved" - if(dna.species.default_headacc) - H.ha_style = dna.species.default_headacc - else - H.ha_style = "None" + if(istype(H)) + if(dna.species.default_hair) + H.h_style = dna.species.default_hair + else + H.h_style = "Bald" + if(dna.species.default_fhair) + H.f_style = dna.species.default_fhair + else + H.f_style = "Shaved" + if(dna.species.default_headacc) + H.ha_style = dna.species.default_headacc + else + H.ha_style = "None" - if(dna.species.default_hair_colour) - //Apply colour. - H.hair_colour = dna.species.default_hair_colour - else - H.hair_colour = "#000000" - if(dna.species.default_fhair_colour) - H.facial_colour = dna.species.default_fhair_colour - else - H.facial_colour = "#000000" - if(dna.species.default_headacc_colour) - H.headacc_colour = dna.species.default_headacc_colour - else - H.headacc_colour = "#000000" + if(dna.species.default_hair_colour) + //Apply colour. + H.hair_colour = dna.species.default_hair_colour + else + H.hair_colour = "#000000" + if(dna.species.default_fhair_colour) + H.facial_colour = dna.species.default_fhair_colour + else + H.facial_colour = "#000000" + if(dna.species.default_headacc_colour) + H.headacc_colour = dna.species.default_headacc_colour + else + H.headacc_colour = "#000000" m_styles = DEFAULT_MARKING_STYLES //Wipes out markings, setting them all to "None". m_colours = DEFAULT_MARKING_COLOURS //Defaults colour to #00000 for all markings. @@ -1525,6 +1526,8 @@ /mob/living/carbon/human/proc/get_eye_shine() //Referenced cult constructs for shining in the dark. Needs to be above lighting effects such as shading. var/obj/item/organ/external/head/head_organ = get_organ("head") + if(!istype(head_organ)) + return var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style] var/icon/hair = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") var/mutable_appearance/MA = mutable_appearance(get_icon_difference(get_eyecon(), hair), layer = ABOVE_LIGHTING_LAYER) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 5d45ce51925..d569186ca97 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -64,6 +64,10 @@ if(sponge) return min(sponge.damage,maxHealth*2) else + if(ischangeling(src)) + // if a changeling has no brain, they have no brain damage. + return 0 + return 200 else return 0 diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 5808f42bfca..26a61e7cfa9 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -847,7 +847,7 @@ if(radiation > RAD_MOB_HAIRLOSS) var/obj/item/organ/external/head/head_organ = H.get_organ("head") - if(!head_organ || (NO_HAIR in species_traits)) + if(!istype(head_organ) || (NO_HAIR in species_traits)) return if(prob(15) && head_organ.h_style != "Bald") to_chat(H, "Your hair starts to fall out in clumps...") @@ -1019,4 +1019,4 @@ It'll return null if the organ doesn't correspond, so include null checks when u return H.skin_colour else var/obj/item/organ/external/head/HD = H.get_organ("head") - return HD.hair_colour + return HD?.hair_colour diff --git a/code/modules/mob/living/carbon/human/species/machine.dm b/code/modules/mob/living/carbon/human/species/machine.dm index 4a4143c7fbb..49fba255d19 100644 --- a/code/modules/mob/living/carbon/human/species/machine.dm +++ b/code/modules/mob/living/carbon/human/species/machine.dm @@ -103,7 +103,7 @@ /datum/species/machine/handle_death(gibbed, mob/living/carbon/human/H) var/obj/item/organ/external/head/head_organ = H.get_organ("head") - if(!head_organ) + if(!istype(head_organ)) return head_organ.h_style = "Bald" head_organ.f_style = "Shaved" diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 2c557e34b9f..96612c49dc1 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -306,7 +306,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) markings_standing.Blend(b_marking_s, ICON_OVERLAY) //Head markings. var/obj/item/organ/external/head/head_organ = get_organ("head") - if(head_organ && m_styles["head"]) //If the head is destroyed, forget the head markings. This prevents floating optical markings on decapitated IPCs, for example. + if(istype(head_organ) && m_styles["head"]) //If the head is destroyed, forget the head markings. This prevents floating optical markings on decapitated IPCs, for example. var/head_marking = m_styles["head"] var/datum/sprite_accessory/head_marking_style = GLOB.marking_styles_list[head_marking] if(head_marking_style && head_marking_style.species_allowed && (head_organ.dna.species.name in head_marking_style.species_allowed)) @@ -325,7 +325,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) remove_overlay(HEAD_ACC_OVER_LAYER) var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ) + if(!istype(head_organ)) return //masks and helmets can obscure our head accessory @@ -360,7 +360,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) remove_overlay(HAIR_LAYER) var/obj/item/organ/external/head/O = get_organ("head") - if(!O) + if(!istype(O)) return if((head?.flags & BLOCKHAIR) || (wear_mask?.flags & BLOCKHAIR)) @@ -445,7 +445,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) remove_overlay(FHAIR_OVER_LAYER) var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ) + if(!istype(head_organ)) return //masks and helmets can obscure our facial hair, unless we're a synthetic @@ -987,7 +987,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(wear_mask && (istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory))) if(!(slot_wear_mask in check_obscured_slots())) var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ) + if(!istype(head_organ)) return // Nothing to update here var/datum/sprite_accessory/alt_heads/alternate_head if(head_organ.alt_head && head_organ.alt_head != "None") diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm index 5db4febebd9..65ef17b0997 100644 --- a/code/modules/mob/living/carbon/superheroes.dm +++ b/code/modules/mob/living/carbon/superheroes.dm @@ -220,7 +220,7 @@ SSticker.mode.greyshirts += target.mind target.set_species(/datum/species/human) var/obj/item/organ/external/head/head_organ = target.get_organ("head") - if(head_organ) + if(istype(head_organ)) head_organ.h_style = "Bald" head_organ.f_style = "Shaved" target.s_tone = 35 diff --git a/code/modules/reagents/chemistry/reagents/misc.dm b/code/modules/reagents/chemistry/reagents/misc.dm index dfc1723315f..e112fce4017 100644 --- a/code/modules/reagents/chemistry/reagents/misc.dm +++ b/code/modules/reagents/chemistry/reagents/misc.dm @@ -355,6 +355,8 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!istype(head_organ)) + return ..() head_organ.facial_colour = rand_hex_color() head_organ.sec_facial_colour = rand_hex_color() head_organ.hair_colour = rand_hex_color() @@ -376,6 +378,8 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!istype(head_organ)) + return ..() head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.name) H.update_hair() @@ -395,6 +399,8 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!istype(head_organ)) + return ..() var/datum/sprite_accessory/tmp_hair_style = GLOB.hair_styles_full_list["Very Long Hair"] var/datum/sprite_accessory/tmp_facial_hair_style = GLOB.facial_hair_styles_list["Very Long Beard"] diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index c39d7912c05..40c6eb97134 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -297,7 +297,7 @@ H.take_organ_damage(5, 10) H.emote("scream") var/obj/item/organ/external/affecting = H.get_organ("head") - if(affecting) + if(istype(affecting)) affecting.disfigure() else H.take_organ_damage(5, 10) @@ -340,7 +340,7 @@ if(volume > 9) if(!H.wear_mask && !H.head) var/obj/item/organ/external/affecting = H.get_organ("head") - if(affecting) + if(istype(affecting)) affecting.disfigure() H.adjustFireLoss(min(max(8, (volume - 5) * 3), 75)) H.emote("scream") @@ -380,7 +380,7 @@ return if(volume >= 50 && prob(75)) var/obj/item/organ/external/affecting = H.get_organ("head") - if(affecting) + if(istype(affecting)) affecting.disfigure() H.adjustBruteLoss(5) H.adjustFireLoss(15) diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/surgery/organs/brain.dm similarity index 88% rename from code/modules/mob/living/carbon/brain/brain_item.dm rename to code/modules/surgery/organs/brain.dm index c2d1235ba6b..7b8720eab14 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/surgery/organs/brain.dm @@ -18,6 +18,9 @@ var/mmi_icon = 'icons/obj/assemblies.dmi' var/mmi_icon_state = "mmi_full" + /// If it's a fake brain without a mob assigned that should still be treated like a real brain. + var/decoy_brain = FALSE + /obj/item/organ/internal/brain/xeno name = "xenomorph brain" desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" @@ -48,12 +51,12 @@ /obj/item/organ/internal/brain/examine(mob/user) // -- TLE . = ..() - if(brainmob && brainmob.client)//if thar be a brain inside... the brain. + if(brainmob && brainmob.client) //if thar be a brain inside... the brain . += "You can feel the small spark of life still left in this one." else . += "This one seems particularly lifeless. Perhaps it will regain some of its luster later.." -/obj/item/organ/internal/brain/remove(mob/living/user,special = 0) +/obj/item/organ/internal/brain/remove(mob/living/user, special = 0) if(dna) name = "[dna.real_name]'s [initial(name)]" @@ -61,27 +64,30 @@ var/obj/item/organ/internal/brain/B = src if(!special) - if(owner.mind && !non_primary)//don't transfer if the owner does not have a mind. + if(owner.mind && !non_primary && !decoy_brain)//don't transfer if the owner does not have a mind. B.transfer_identity(user) if(ishuman(owner)) var/mob/living/carbon/human/H = owner H.update_hair() - + owner.thought_bubble_image = initial(owner.thought_bubble_image) . = ..() -/obj/item/organ/internal/brain/insert(mob/living/target,special = 0) +/obj/item/organ/internal/brain/insert(mob/living/target, special = 0) name = "[initial(name)]" - var/brain_already_exists = 0 + var/brain_already_exists = FALSE if(ishuman(target)) // No more IPC multibrain shenanigans if(target.get_int_organ(/obj/item/organ/internal/brain)) - brain_already_exists = 1 + brain_already_exists = TRUE var/mob/living/carbon/human/H = target H.update_hair() + if(ischangeling(target)) + decoy_brain = TRUE + if(!brain_already_exists) if(brainmob) if(target.key) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index a3d0c884a8d..6fa711e6180 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -301,7 +301,7 @@ if(ishuman(owner)) var/mob/living/carbon/human/H = owner - var/obj/item/organ/external/head/head_organ = H.get_organ("head") + var/obj/item/organ/external/head/head_organ = H.get_organ("head") // damn well better have a head if you have a beard if(!(head_organ.h_style == "Very Long Hair" || head_organ.h_style == "Mohawk")) if(prob(10)) head_organ.h_style = "Mohawk" diff --git a/paradise.dme b/paradise.dme index 4f8735b57fc..fe21625f385 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1959,7 +1959,6 @@ #include "code\modules\mob\living\carbon\alien\special\facehugger.dm" #include "code\modules\mob\living\carbon\brain\brain.dm" #include "code\modules\mob\living\carbon\brain\brain_emote.dm" -#include "code\modules\mob\living\carbon\brain\brain_item.dm" #include "code\modules\mob\living\carbon\brain\death.dm" #include "code\modules\mob\living\carbon\brain\life.dm" #include "code\modules\mob\living\carbon\brain\login.dm" @@ -2538,6 +2537,7 @@ #include "code\modules\surgery\organs\autosurgeon.dm" #include "code\modules\surgery\organs\blood.dm" #include "code\modules\surgery\organs\body_egg.dm" +#include "code\modules\surgery\organs\brain.dm" #include "code\modules\surgery\organs\ears.dm" #include "code\modules\surgery\organs\eyes.dm" #include "code\modules\surgery\organs\heart.dm"