Allows clings to regenerate without a brain. (#19856)

* Move brain organ code where it belongs

* Rename too

* WIP, but hey, it kinda works now.

* Account for a few missing heads

* Remove vital check, killing the user on death

* Let defibs and scanners better deal with these

* Remove debug brains

* Clean up some more contingencies

* More head checks

* Update code/modules/antagonists/changeling/datum_changeling.dm

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

* Fixes up signal business

* some stuff from sean's review

* Add some type safety checks for heads

* oops

* Update code/game/objects/items/weapons/cosmetics.dm

get this in there too

Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com>

* Remove decap sword

* Quick suggestions

Co-authored-by: Ryan <80364400+Sirryan2002@users.noreply.github.com>

* Addresses shedding problems

* Add new defib changes

* this is why we have CI

Co-authored-by: Farie82 <farie82@users.noreply.github.com>
Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com>
Co-authored-by: Ryan <80364400+Sirryan2002@users.noreply.github.com>
This commit is contained in:
Luc
2023-01-20 19:25:51 -05:00
committed by GitHub
co-authored by Farie82 S34N Ryan
parent b90bb7bcb8
commit b940c1eb21
27 changed files with 208 additions and 133 deletions
@@ -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, "<span class='notice'>The brain is a useless organ to us, we are able to regenerate!</span>")
else
to_chat(L, "<span class='notice'>While our current form may be lifeless, this is not the end for us as we can still regenerate!</span>")
/proc/ischangeling(mob/M)
return M.mind?.has_antag_datum(/datum/antagonist/changeling)
@@ -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, "<span class='warning'>This person doesn't have a head!</span>")
return 0
C.visible_message("<span class='danger'>[user] dunks [C]'s face into [src]!</span>", \
@@ -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, "<span class='warning'>This person doesn't have a head!</span>")
return 0
C.visible_message("<span class='danger'>[user] bashes [C]'s head in [src]'s door!</span>", \
@@ -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()
@@ -361,10 +361,9 @@
msg += "<span class = 'deptradio'>Medical records:</span> <a href='?src=[UID()];medrecord=`'>\[View\]</a> <a href='?src=[UID()];medrecordadd=`'>\[Add comment\]</a>\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 += "*---------*</span>"
if(pose)
+28 -25
View File
@@ -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)
@@ -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
@@ -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, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
@@ -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
@@ -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"
@@ -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")
@@ -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
@@ -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"]
@@ -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)
@@ -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)
@@ -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"