From 7ed2ee82bf13e8e4d97298391c099a7b8050128f Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Thu, 4 Aug 2022 14:11:42 +0100 Subject: [PATCH 01/24] core changes --- code/datums/components/dullahan.dm | 81 +++++++++++++++++++ code/datums/mutable_appearance.dm | 3 + .../sprite_accessories/_sprite_accessories.dm | 2 + .../new_player/sprite_accessories/ears.dm | 1 + .../sprite_accessories/hair_face.dm | 1 + .../sprite_accessories/hair_head.dm | 1 + .../new_player/sprite_accessories/horns.dm | 1 + .../sprite_accessories/ipc_synths.dm | 1 + .../new_player/sprite_accessories/snouts.dm | 1 + .../new_player/sprite_accessories/synthliz.dm | 1 + .../mob/living/carbon/human/species.dm | 14 +++- .../mob/living/carbon/human/update_icons.dm | 5 +- code/modules/surgery/bodyparts/head.dm | 16 ++-- tgstation.dme | 1 + 14 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 code/datums/components/dullahan.dm diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm new file mode 100644 index 0000000000..ee6d5beef0 --- /dev/null +++ b/code/datums/components/dullahan.dm @@ -0,0 +1,81 @@ +/datum/component/dullahan + var/obj/item/dullahan_head/dullahan_head + + +/datum/component/dullahan/Initialize() + var/mob/living/carbon/human/H = parent + if(!H) + return + + dullahan_head = new(get_turf(H)) + + dullahan_head.name = "[H.name]'s head" + dullahan_head.desc = "the decapitated head of [H.name]" + dullahan_head.owner = H + + // make sure the brain can't decay or fall out + var/obj/item/organ/brain/B = H.getorganslot(ORGAN_SLOT_BRAIN) + B.zone = "abstract" // it exists in the ethereal plain + B.organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT | ORGAN_VITAL + + // moving the brain's zone means we don't need the head to survive + var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD) + head.drop_limb() + qdel(head) + + dullahan_head.update_appearance() + +/obj/item/dullahan_head + name = "coders lament" + desc = "you shouldn't be reading this" + flags_1 = HEAR_1 + var/mob/living/carbon/human/owner + // this is for keeping track of the overlays because you can't read the actual overlays list as it's a special byond var + var/list/overlays_standing + +// allow the 'fake' head to relay speech back to the mob +/obj/item/dullahan_head/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) + if(owner) + var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]" + var/hrefpart = "" + var/treated_message = lang_treat(speaker, message_language, raw_message, spans, message_mode) + var/rendered = "[hrefpart][namepart] [treated_message]" + + if (owner.client?.prefs.chat_on_map && (owner.client.prefs.see_chat_non_mob || ismob(speaker))) + owner.create_chat_message(speaker, message_language, raw_message, spans, message_mode) + owner.show_message(rendered, MSG_AUDIBLE) + +// update head sprite +/obj/item/dullahan_head/proc/remove_head_overlays() + overlays_standing = list() + cut_overlays() + +/obj/item/dullahan_head/proc/add_head_overlay(var/overlay) + overlays_standing += overlay + add_overlay(overlay) + +/obj/item/dullahan_head/update_appearance() + remove_head_overlays() + // to do this without duplicating large amounts of code + // it's best to regenerate the head, then remove it once we have the overlays we want + owner.regenerate_limb(BODY_ZONE_HEAD, TRUE) // don't heal them + owner.regenerate_icons() // yes i know it's expensive but do you want me to rewrite our entire overlay system + var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD) + add_overlay(head.get_limb_icon(FALSE, TRUE, TRUE)) + for(var/overlay in owner.overlays_standing) + if(istype(overlay, /mutable_appearance)) + var/mutable_appearance/mutable = overlay + message_admins("category is [mutable.category] and icon is [mutable.icon_state]") + if(mutable.category == "HEAD") + add_head_overlay(mutable) + else + if(islist(overlay)) + var/list/list_appearances = overlay + for(var/overlay2 in list_appearances) + if(istype(overlay2, /mutable_appearance)) + var/mutable_appearance/mutable = overlay2 + message_admins("category is [mutable.category] and icon is [mutable.icon_state]") + if(mutable.category == "HEAD") + add_head_overlay(mutable) + //head.drop_limb() + //qdel(head) \ No newline at end of file diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm index b04f55ef0e..104147ebeb 100644 --- a/code/datums/mutable_appearance.dm +++ b/code/datums/mutable_appearance.dm @@ -4,6 +4,9 @@ // Mutable appearances are children of images, just so you know. +/mutable_appearance + var/category // listen i want to store some meta information on mutable appearances don't judge me + /mutable_appearance/New() ..() plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm index 08ae75d728..964a171e59 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm @@ -77,6 +77,8 @@ //For soft-restricting markings to species IDs var/list/recommended_species + var/mutable_category // simply do not worry about this value + /datum/sprite_accessory/proc/is_not_visible(var/mob/living/carbon/human/H, var/tauric) //return if the accessory shouldn't be shown return FALSE diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm index 628a5e53ac..294c3b78f2 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm @@ -2,6 +2,7 @@ icon = 'icons/mob/mutant_bodyparts.dmi' mutant_part_string = "ears" relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) + mutable_category = "HEAD" /datum/sprite_accessory/ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm index f3e179e802..06d4c34f72 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm @@ -4,6 +4,7 @@ /datum/sprite_accessory/facial_hair icon = 'icons/mob/hair.dmi' gender = MALE // barf (unless you're a dorf, dorfs dig chix w/ beards :P) + mutable_category = "HEAD" // please make sure they're sorted alphabetically and categorized /datum/sprite_accessory/facial_hair/shaved //this is exempt from the alphabetical sort diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm index e002fa369d..9e868d69c6 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm @@ -3,6 +3,7 @@ ////////////////////// /datum/sprite_accessory/hair icon = 'icons/mob/hair.dmi' // default icon for all hairs + mutable_category = "HEAD" // please make sure they're sorted alphabetically and, where needed, categorized // try to capitalize the names please~ diff --git a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm index 0d097b24f0..14e340fc2e 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm @@ -2,6 +2,7 @@ icon = 'icons/mob/mutant_bodyparts.dmi' color_src = HORNCOLOR relevant_layers = list(HORNS_LAYER) + mutable_category = "HEAD" /datum/sprite_accessory/horns/is_not_visible(var/mob/living/carbon/human/H, var/tauric) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm index 8bda196faa..f73a4a35a1 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm @@ -6,6 +6,7 @@ icon = 'modular_citadel/icons/mob/ipc_screens.dmi' color_src = null relevant_layers = list(BODY_ADJ_LAYER) + mutable_category = "HEAD" /datum/sprite_accessory/screen/blank name = "Blank" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm index 75b62e8c0f..aa9ec41dcc 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm @@ -2,6 +2,7 @@ icon = 'icons/mob/mutant_bodyparts.dmi' mutant_part_string = "snout" relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + mutable_category = "HEAD" /datum/sprite_accessory/snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm index 08897ade34..870f4f5ba4 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm @@ -5,6 +5,7 @@ color_src = MUTCOLORS name = "Synthetic Lizard - Snout" icon_state = "synthliz_basic" + mutable_category = "HEAD" /datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_under icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi' diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index ddbb23741b..c8cc58c916 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -697,6 +697,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) fhair_file = 'icons/mob/facialhair_extensions.dmi' var/mutable_appearance/facial_overlay = mutable_appearance(fhair_file, fhair_state, -HAIR_LAYER) + facial_overlay.category = "HEAD" if(!forced_colour) if(hair_color) @@ -734,8 +735,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!hair_hidden || dynamic_hair_suffix) var/mutable_appearance/hair_overlay = mutable_appearance(layer = -HAIR_LAYER) + hair_overlay.category = "HEAD" var/mutable_appearance/gradient_overlay = mutable_appearance(layer = -HAIR_LAYER) - if(!hair_hidden && !H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain + gradient_overlay.category = "HEAD" + if(!hair_hidden && !H.getorgan(/obj/item/organ/brain) && !H.GetComponent(/datum/component/dullahan)) //Applies the debrained overlay if there is no brain (ignore if they are dullahan) if(!(NOBLOOD in species_traits)) hair_overlay.icon = 'icons/mob/human_parts.dmi' hair_overlay.icon_state = "debrained" @@ -811,6 +814,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // lipstick if(H.lip_style && (LIPS in species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/lips.dmi', "lips_[H.lip_style]", -BODY_LAYER) + lip_overlay.category = "HEAD" lip_overlay.color = H.lip_color if(OFFSET_LIPS in H.dna.species.offset_features) @@ -822,8 +826,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // eyes if(!(NOEYES in species_traits)) var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES) - if(!has_eyes) + if(!has_eyes && !H.GetComponent(/datum/component/dullahan)) standing += mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER) + message_admins("EYES MISSING APPLIED 2") else var/left_state = DEFAULT_LEFT_EYE_STATE var/right_state = DEFAULT_RIGHT_EYE_STATE @@ -832,6 +837,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) right_state = eye_type + "_right_eye" var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER) var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER) + left_eye.category = "HEAD" + right_eye.category = "HEAD" if((EYECOLOR in species_traits) && has_eyes) left_eye.color = "#" + H.left_eye_color right_eye.color = "#" + H.right_eye_color @@ -1009,6 +1016,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) for(var/bodypart in relevant_layers[layer]) var/datum/sprite_accessory/S = bodypart var/mutable_appearance/accessory_overlay = mutable_appearance(S.icon, layer = -layernum) + accessory_overlay.category = S.mutable_category bodypart = S.mutant_part_string || dna_feature_as_text_string[S] if(S.gender_specific) @@ -1113,6 +1121,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(S.extra) //apply the extra overlay, if there is one var/mutable_appearance/extra_accessory_overlay = mutable_appearance(S.icon, layer = -layernum) + extra_accessory_overlay.category = S.mutable_category if(S.gender_specific) extra_accessory_overlay.icon_state = "[g]_[bodypart]_extra_[S.icon_state]_[layertext]" else @@ -1159,6 +1168,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(S.extra2) //apply the extra overlay, if there is one var/mutable_appearance/extra2_accessory_overlay = mutable_appearance(S.icon, layer = -layernum) + extra2_accessory_overlay.category = S.mutable_category if(S.gender_specific) extra2_accessory_overlay.icon_state = "[g]_[bodypart]_extra2_[S.icon_state]_[layertext]" else diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a0620c8990..f225afdd79 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -791,8 +791,9 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if // eyes if(!(NOEYES in dna.species.species_traits)) var/has_eyes = getorganslot(ORGAN_SLOT_EYES) - if(!has_eyes) + if(!has_eyes && !GetComponent(/datum/component/dullahan)) add_overlay(mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER)) + message_admins("EYES MISSING APPLIED") else var/left_state = DEFAULT_LEFT_EYE_STATE var/right_state = DEFAULT_RIGHT_EYE_STATE @@ -803,6 +804,8 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if right_state = eye_type + "_right_eye" var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER) var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER) + left_eye.category = "HEAD" + right_eye.category = "HEAD" if((EYECOLOR in dna.species.species_traits) && has_eyes) left_eye.color = "#" + left_eye_color right_eye.color = "#" + right_eye_color diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 8c283f5ebc..7278dc6888 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -134,7 +134,7 @@ I.pixel_y = px_y add_overlay(standing) -/obj/item/bodypart/head/get_limb_icon(dropped) +/obj/item/bodypart/head/get_limb_icon(dropped, ignore_brain = FALSE, ignore_eyes = FALSE) if(custom_head) return cut_overlays() @@ -152,7 +152,7 @@ . += facial_overlay //Applies the debrained overlay if there is no brain - if(!brain) + if(!brain && !ignore_brain) var/image/debrain_overlay = image(layer = -HAIR_LAYER, dir = SOUTH) if(animal_origin == ALIEN_BODYPART) debrain_overlay.icon = 'icons/mob/animal_parts.dmi' @@ -175,12 +175,13 @@ // lipstick if(lip_style) - var/image/lips_overlay = image('icons/mob/lips.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH) + var/mutable_appearance/lips_overlay = mutable_appearance('icons/mob/lips.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH) + lips_overlay.category = "HEAD" lips_overlay.color = lip_color . += lips_overlay // eyes - if(eyes) + if(eyes || ignore_eyes) var/left_state = DEFAULT_LEFT_EYE_STATE var/right_state = DEFAULT_RIGHT_EYE_STATE if(owner && owner.dna.species) @@ -189,17 +190,20 @@ left_state = eye_type + "_left_eye" right_state = eye_type + "_right_eye" if(left_state != DEFAULT_NO_EYE_STATE) - var/image/left_eye = image('icons/mob/hair.dmi', left_state, -BODY_LAYER, SOUTH) + var/mutable_appearance/left_eye = mutable_appearance('icons/mob/hair.dmi', left_state, -BODY_LAYER, SOUTH) + left_eye.category = "HEAD" if(eyes.left_eye_color) left_eye.color = "#" + eyes.left_eye_color . += left_eye if(right_state != DEFAULT_NO_EYE_STATE) - var/image/right_eye = image('icons/mob/hair.dmi', right_state, -BODY_LAYER, SOUTH) + var/mutable_appearance/right_eye = mutable_appearance('icons/mob/hair.dmi', right_state, -BODY_LAYER, SOUTH) + right_eye.category = "HEAD" if(eyes.right_eye_color) right_eye.color = "#" + eyes.right_eye_color . += right_eye else var/eyes_overlay = image('icons/mob/hair.dmi', "eyes_missing", -BODY_LAYER, SOUTH) + message_admins("EYES MISSING ALSO IGNORE EYES IS [ignore_eyes]") . += eyes_overlay /obj/item/bodypart/head/monkey diff --git a/tgstation.dme b/tgstation.dme index 4fb3920c45..9fd6194e67 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -521,6 +521,7 @@ #include "code\datums\components\combat_mode.dm" #include "code\datums\components\construction.dm" #include "code\datums\components\dejavu.dm" +#include "code\datums\components\dullahan.dm" #include "code\datums\components\earprotection.dm" #include "code\datums\components\edible.dm" #include "code\datums\components\edit_complainer.dm" From 818e564c9262d9c6331f997c90d671ba43ccd39a Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 15:44:40 +0100 Subject: [PATCH 02/24] stable --- code/__DEFINES/traits.dm | 2 + code/datums/accents.dm | 9 +- code/datums/components/dullahan.dm | 92 +++++++++++++++++-- code/game/objects/structures/mirror.dm | 2 +- .../mob/living/carbon/human/species.dm | 18 ++-- .../carbon/human/species_types/dullahan.dm | 29 ------ .../mob/living/carbon/human/update_icons.dm | 39 ++++---- .../surgery/bodyparts/dismemberment.dm | 4 +- code/modules/surgery/bodyparts/head.dm | 5 +- 9 files changed, 125 insertions(+), 75 deletions(-) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 94ace816ac..d562755083 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -235,6 +235,8 @@ #define TRAIT_BEING_CARRIED "being_carried" #define TRAIT_GLASS_BONES "glass_bones" #define TRAIT_PAPER_SKIN "paper_skin" +//used because it's more reliable than checking for the component +#define TRAIT_DULLAHAN "dullahan" // mobility flag traits // IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it) diff --git a/code/datums/accents.dm b/code/datums/accents.dm index d9e073b729..cfd6e873fa 100644 --- a/code/datums/accents.dm +++ b/code/datums/accents.dm @@ -94,10 +94,9 @@ /datum/accent/dullahan/modify_speech(list/speech_args, datum/source, mob/living/carbon/owner) if(owner) - if(isdullahan(owner)) - var/datum/species/dullahan/D = owner.dna.species - if(isobj(D.myhead.loc)) - var/obj/O = D.myhead.loc - O.say(speech_args[SPEECH_MESSAGE]) + var/datum/component/dullahan/dullahan = owner.GetComponent(/datum/component/dullahan) + if(dullahan) + if(dullahan.dullahan_head) + dullahan.dullahan_head.say(speech_args[SPEECH_MESSAGE]) speech_args[SPEECH_MESSAGE] = "" return speech_args diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index ee6d5beef0..a3e1335e6b 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -1,30 +1,69 @@ /datum/component/dullahan var/obj/item/dullahan_head/dullahan_head - /datum/component/dullahan/Initialize() + . = ..() + var/mob/living/carbon/human/H = parent if(!H) - return + return . + + ADD_TRAIT(H, TRAIT_DULLAHAN, "dullahan_component") dullahan_head = new(get_turf(H)) dullahan_head.name = "[H.name]'s head" dullahan_head.desc = "the decapitated head of [H.name]" dullahan_head.owner = H + RegisterSignal(H, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head) // make sure the brain can't decay or fall out var/obj/item/organ/brain/B = H.getorganslot(ORGAN_SLOT_BRAIN) B.zone = "abstract" // it exists in the ethereal plain B.organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT | ORGAN_VITAL + dullahan_head.B = B + + // the eyes get similar treatment + var/obj/item/organ/eyes/dullahan/new_eyes = new() + var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES) + new_eyes.left_eye_color = E.left_eye_color + new_eyes.right_eye_color = E.right_eye_color + E.Remove() + qdel(E) + new_eyes.Insert(H) + + // make sure you handle the tongue correctly, too! + var/obj/item/organ/tongue/T = H.getorganslot(ORGAN_SLOT_TONGUE) + T.Remove() + qdel(T) + + var/obj/item/organ/tongue/dullahan/new_tongue = new() + new_tongue.Insert(H) // moving the brain's zone means we don't need the head to survive var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD) head.drop_limb() qdel(head) + H.flags_1 &= ~(HEAR_1) + dullahan_head.update_appearance() +/datum/component/dullahan/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs) + excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs. + +/obj/item/organ/tongue/dullahan + zone = "abstract" + initial_accents = list(/datum/accent/dullahan) + organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT + +/obj/item/organ/eyes/dullahan + name = "head vision" + desc = "An abstraction." + actions_types = list(/datum/action/item_action/organ_action/dullahan) + zone = "abstract" + tint = INFINITY // used to switch the vision perspective to the head on species_gain(). + /obj/item/dullahan_head name = "coders lament" desc = "you shouldn't be reading this" @@ -32,6 +71,12 @@ var/mob/living/carbon/human/owner // this is for keeping track of the overlays because you can't read the actual overlays list as it's a special byond var var/list/overlays_standing + var/obj/item/organ/brain/B + +/obj/item/dullahan_head/Destroy() + B.Remove() + B.forceMove(get_turf(src)) + . = ..() // allow the 'fake' head to relay speech back to the mob /obj/item/dullahan_head/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) @@ -43,7 +88,7 @@ if (owner.client?.prefs.chat_on_map && (owner.client.prefs.see_chat_non_mob || ismob(speaker))) owner.create_chat_message(speaker, message_language, raw_message, spans, message_mode) - owner.show_message(rendered, MSG_AUDIBLE) + owner.show_message(rendered, "") // update head sprite /obj/item/dullahan_head/proc/remove_head_overlays() @@ -59,13 +104,12 @@ // to do this without duplicating large amounts of code // it's best to regenerate the head, then remove it once we have the overlays we want owner.regenerate_limb(BODY_ZONE_HEAD, TRUE) // don't heal them - owner.regenerate_icons() // yes i know it's expensive but do you want me to rewrite our entire overlay system + owner.regenerate_icons(TRUE) // yes i know it's expensive but do you want me to rewrite our entire overlay system, also block recursive calls here by passing in TRUE (it wont go back to call update_appearance this way) var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD) add_overlay(head.get_limb_icon(FALSE, TRUE, TRUE)) for(var/overlay in owner.overlays_standing) if(istype(overlay, /mutable_appearance)) var/mutable_appearance/mutable = overlay - message_admins("category is [mutable.category] and icon is [mutable.icon_state]") if(mutable.category == "HEAD") add_head_overlay(mutable) else @@ -74,8 +118,40 @@ for(var/overlay2 in list_appearances) if(istype(overlay2, /mutable_appearance)) var/mutable_appearance/mutable = overlay2 - message_admins("category is [mutable.category] and icon is [mutable.icon_state]") if(mutable.category == "HEAD") add_head_overlay(mutable) - //head.drop_limb() - //qdel(head) \ No newline at end of file + head.drop_limb() + qdel(head) + +/obj/item/dullahan_head/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs) + excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs. + +/datum/action/item_action/organ_action/dullahan + name = "Toggle Perspective" + desc = "Switch between seeing normally from your head, or blindly from your body." + +/datum/action/item_action/organ_action/dullahan/Trigger() + . = ..() + var/mob/living/carbon/human/H = owner + var/obj/item/organ/eyes/E = owner.getorganslot(ORGAN_SLOT_EYES) + if(E) + if(E.tint) + E.tint = 0 + else + E.tint = INFINITY + + var/datum/component/dullahan/D = H.GetComponent(/datum/component/dullahan) + if(D) + D.update_vision_perspective() + +/datum/component/dullahan/proc/update_vision_perspective() + var/mob/living/carbon/human/H = parent + if(!H) + return . + var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) + if(eyes) + H.update_tint() + if(eyes.tint) + H.reset_perspective(H) + else + H.reset_perspective(dullahan_head) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index a70d9d4678..9ff41c4404 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -41,7 +41,7 @@ if(new_style) H.hair_style = new_style - H.update_hair() + H.update_mutant_bodyparts() /obj/structure/mirror/examine_status(mob/user) if(broken) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index c8cc58c916..b73f1da93a 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -345,7 +345,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/obj/item/organ/stomach/stomach = C.getorganslot(ORGAN_SLOT_STOMACH) var/obj/item/organ/tail/tail = C.getorganslot(ORGAN_SLOT_TAIL) - var/should_have_brain = TRUE + var/should_have_brain = !(HAS_TRAIT(C, TRAIT_DULLAHAN)) var/should_have_heart = !(NOBLOOD in species_traits) var/should_have_lungs = ((TRAIT_AUXILIARY_LUNGS in inherent_traits) || !(TRAIT_NOBREATH in inherent_traits)) var/should_have_appendix = !(TRAIT_NOHUNGER in inherent_traits) @@ -803,7 +803,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.apply_overlay(HAIR_LAYER) -/datum/species/proc/handle_body(mob/living/carbon/human/H) +/datum/species/proc/handle_body(mob/living/carbon/human/H, block_recursive_calls = FALSE) H.remove_overlay(BODY_LAYER) var/list/standing = list() @@ -825,10 +825,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // eyes if(!(NOEYES in species_traits)) - var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES) - if(!has_eyes && !H.GetComponent(/datum/component/dullahan)) + var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES) || HAS_TRAIT(H, TRAIT_DULLAHAN) // if they are a dullahan just assume eyes exist + if(!has_eyes) standing += mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER) - message_admins("EYES MISSING APPLIED 2") else var/left_state = DEFAULT_LEFT_EYE_STATE var/right_state = DEFAULT_RIGHT_EYE_STATE @@ -899,9 +898,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.overlays_standing[BODY_LAYER] = standing H.apply_overlay(BODY_LAYER) - handle_mutant_bodyparts(H) + handle_mutant_bodyparts(H, null, block_recursive_calls) -/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) +/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour, block_recursive_calls = FALSE) var/list/bodyparts_to_add = mutant_bodyparts.Copy() H.remove_overlay(BODY_BEHIND_LAYER) @@ -1216,6 +1215,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.apply_overlay(BODY_FRONT_LAYER) H.apply_overlay(HORNS_LAYER) + if(!block_recursive_calls) + var/datum/component/dullahan/D = H.GetComponent(/datum/component/dullahan) + if(D && D.dullahan_head) + D.dullahan_head.update_appearance() + /* * Equip the outfit required for life. Replaces items currently worn. */ diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index facc3dfd8d..ed06d2be5a 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -82,38 +82,9 @@ decoy_override = TRUE organ_flags = ORGAN_NO_SPOIL//Do not decay -/obj/item/organ/tongue/dullahan - zone = "abstract" - accents = list(/datum/accent/dullahan) - /obj/item/organ/ears/dullahan zone = "abstract" -/obj/item/organ/eyes/dullahan - name = "head vision" - desc = "An abstraction." - actions_types = list(/datum/action/item_action/organ_action/dullahan) - zone = "abstract" - tint = INFINITY // used to switch the vision perspective to the head on species_gain(). - -/datum/action/item_action/organ_action/dullahan - name = "Toggle Perspective" - desc = "Switch between seeing normally from your head, or blindly from your body." - -/datum/action/item_action/organ_action/dullahan/Trigger() - . = ..() - var/obj/item/organ/eyes/dullahan/DE = target - if(DE.tint) - DE.tint = 0 - else - DE.tint = INFINITY - - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - if(isdullahan(H)) - var/datum/species/dullahan/D = H.dna.species - D.update_vision_perspective(H) - /obj/item/dullahan_relay name = "dullahan relay" var/mob/living/owner diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index f225afdd79..db0b4ddfac 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -58,14 +58,14 @@ There are several things that need to be remembered: dna.species.handle_hair(src) //used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body. -/mob/living/carbon/human/proc/update_mutant_bodyparts() +/mob/living/carbon/human/proc/update_mutant_bodyparts(block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) - dna.species.handle_mutant_bodyparts(src) + dna.species.handle_mutant_bodyparts(src, null, block_recursive_calls) -/mob/living/carbon/human/update_body(update_genitals = FALSE) +/mob/living/carbon/human/update_body(update_genitals = FALSE, block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) remove_overlay(BODY_LAYER) - dna.species.handle_body(src) + dna.species.handle_body(src, block_recursive_calls) ..() if(update_genitals) update_genitals() @@ -75,24 +75,24 @@ There are several things that need to be remembered: /* --------------------------------------- */ //For legacy support. -/mob/living/carbon/human/regenerate_icons() +/mob/living/carbon/human/regenerate_icons(block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) if(!..()) icon_render_key = null //invalidate bodyparts cache - update_body(TRUE) + update_body(TRUE, block_recursive_calls) update_hair() - update_inv_w_uniform() + update_inv_w_uniform(block_recursive_calls) update_inv_wear_id() update_inv_gloves() update_inv_glasses() update_inv_ears() update_inv_shoes() update_inv_s_store() - update_inv_wear_mask() - update_inv_head() + update_inv_wear_mask(block_recursive_calls) + update_inv_head(block_recursive_calls) update_inv_belt() update_inv_back() - update_inv_wear_suit() + update_inv_wear_suit(block_recursive_calls) update_inv_pockets() update_inv_neck() update_transform() @@ -123,7 +123,7 @@ There are several things that need to be remembered: apply_overlay(ANTAG_LAYER) -/mob/living/carbon/human/update_inv_w_uniform() +/mob/living/carbon/human/update_inv_w_uniform(block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) remove_overlay(UNIFORM_LAYER) @@ -173,7 +173,7 @@ There are several things that need to be remembered: overlays_standing[UNIFORM_LAYER] = uniform_overlay apply_overlay(UNIFORM_LAYER) - update_mutant_bodyparts() + update_mutant_bodyparts(block_recursive_calls) /mob/living/carbon/human/update_inv_wear_id() if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) @@ -349,7 +349,7 @@ There are several things that need to be remembered: overlays_standing[SUIT_STORE_LAYER] = s_store_overlay apply_overlay(SUIT_STORE_LAYER) -/mob/living/carbon/human/update_inv_head() +/mob/living/carbon/human/update_inv_head(block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) remove_overlay(HEAD_LAYER) @@ -387,7 +387,7 @@ There are several things that need to be remembered: head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2] overlays_standing[HEAD_LAYER] = head_overlay apply_overlay(HEAD_LAYER) - update_mutant_bodyparts() + update_mutant_bodyparts(block_recursive_calls) /mob/living/carbon/human/update_inv_belt() if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) @@ -411,7 +411,7 @@ There are several things that need to be remembered: overlays_standing[BELT_LAYER] = belt_overlay apply_overlay(BELT_LAYER) -/mob/living/carbon/human/update_inv_wear_suit() +/mob/living/carbon/human/update_inv_wear_suit(block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) remove_overlay(SUIT_LAYER) @@ -471,7 +471,7 @@ There are several things that need to be remembered: suit_overlay = center_image(suit_overlay, dimension_x, dimension_y) overlays_standing[SUIT_LAYER] = suit_overlay update_hair() - update_mutant_bodyparts() + update_mutant_bodyparts(block_recursive_calls) apply_overlay(SUIT_LAYER) @@ -498,7 +498,7 @@ There are several things that need to be remembered: update_observer_view(r_store) -/mob/living/carbon/human/update_inv_wear_mask() +/mob/living/carbon/human/update_inv_wear_mask(block_recursive_calls = FALSE) if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) remove_overlay(FACEMASK_LAYER) @@ -537,7 +537,7 @@ There are several things that need to be remembered: mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2] overlays_standing[FACEMASK_LAYER] = mask_overlay apply_overlay(FACEMASK_LAYER) - update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout + update_mutant_bodyparts(block_recursive_calls) //e.g. upgate needed because mask now hides lizard snout /mob/living/carbon/human/update_inv_back() if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER)) @@ -791,9 +791,8 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if // eyes if(!(NOEYES in dna.species.species_traits)) var/has_eyes = getorganslot(ORGAN_SLOT_EYES) - if(!has_eyes && !GetComponent(/datum/component/dullahan)) + if(!has_eyes && !HAS_TRAIT(src, TRAIT_DULLAHAN)) add_overlay(mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER)) - message_admins("EYES MISSING APPLIED") else var/left_state = DEFAULT_LEFT_EYE_STATE var/right_state = DEFAULT_RIGHT_EYE_STATE diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 6b5b4a14aa..96b9290239 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -142,7 +142,7 @@ update_icon_dropped() C.update_health_hud() //update the healthdoll - C.update_body() + C.update_body(FALSE, TRUE) // block recursive calls because we dont want to crash, i.e. don't tell a dullahan to update when dropping its limb C.update_hair() C.update_mobility() @@ -370,7 +370,7 @@ update_disabled() C.updatehealth() - C.update_body() + C.update_body(FALSE, TRUE) // again block recursive calls because dullahans will try update their icons by regenerating their head C.update_hair() C.update_damage_overlays() C.update_mobility() diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 7278dc6888..ea43740093 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -134,7 +134,7 @@ I.pixel_y = px_y add_overlay(standing) -/obj/item/bodypart/head/get_limb_icon(dropped, ignore_brain = FALSE, ignore_eyes = FALSE) +/obj/item/bodypart/head/get_limb_icon(dropped, ignore_brain = FALSE) if(custom_head) return cut_overlays() @@ -181,7 +181,7 @@ . += lips_overlay // eyes - if(eyes || ignore_eyes) + if(eyes || ignore_brain) var/left_state = DEFAULT_LEFT_EYE_STATE var/right_state = DEFAULT_RIGHT_EYE_STATE if(owner && owner.dna.species) @@ -203,7 +203,6 @@ . += right_eye else var/eyes_overlay = image('icons/mob/hair.dmi', "eyes_missing", -BODY_LAYER, SOUTH) - message_admins("EYES MISSING ALSO IGNORE EYES IS [ignore_eyes]") . += eyes_overlay /obj/item/bodypart/head/monkey From b05f6e221d9893d6383bc2caeb64c322cf6c406c Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:06:49 +0100 Subject: [PATCH 03/24] MIGRATIONS DELETIONS AND QUIRKS OH MY --- code/__DEFINES/is_helpers.dm | 1 - code/datums/components/dullahan.dm | 6 + code/datums/traits/neutral.dm | 9 ++ code/modules/client/preferences_savefile.dm | 14 +- .../carbon/human/species_types/dullahan.dm | 136 ------------------ 5 files changed, 28 insertions(+), 138 deletions(-) delete mode 100644 code/modules/mob/living/carbon/human/species_types/dullahan.dm diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index cfd2cebbd0..640079e9b8 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -74,7 +74,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid)) #define isethereal(A) (is_species(A, /datum/species/ethereal)) #define isvampire(A) (is_species(A,/datum/species/vampire)) -#define isdullahan(A) (is_species(A, /datum/species/dullahan)) #define ismush(A) (is_species(A, /datum/species/mush)) #define isshadow(A) (is_species(A, /datum/species/shadow)) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index a3e1335e6b..5e0658be39 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -47,8 +47,14 @@ H.flags_1 &= ~(HEAR_1) + RegisterSignal(dullahan_head, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner) + dullahan_head.update_appearance() +/datum/component/dullahan/proc/include_owner(datum/source, list/processing_list, list/hearers) + if(!QDELETED(parent)) + hearers += parent + /datum/component/dullahan/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs) excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs. diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index aebe6ec7fa..8f7043c715 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -186,3 +186,12 @@ value = 0 medical_record_text = "Patient should not come into contact with sodium." mob_trait = TRAIT_SALT_SENSITIVE + +/datum/quirk/dullahan + name = "Dullahan" + desc = "Your head is detached from your body." + value = 0 + medical_record_text = "Patient seems to have some kind of spatial link with their decapitated head." + +/datum/quirk/dullahan/post_add() + quirk_holder.AddComponent(/datum/component/dullahan) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 249dbba45f..b4a8952675 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -5,7 +5,7 @@ // You do not need to raise this if you are adding new values that have sane defaults. // Only raise this value when changing the meaning/format/name/layout of an existing value // where you would want the updater procs below to run -#define SAVEFILE_VERSION_MAX 55 +#define SAVEFILE_VERSION_MAX 56 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -358,6 +358,18 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(length(old_flavor_text) && !length(features["feature_flavor_text"])) features["feature_flavor_text"] = old_flavor_text + // hey what happened to 55 + + // dullahans as a species cease to exist + if(current_version < 56) + var/species_id = S["species"] + if(species_id = SPECIES_DULLAHAN) + S["species"] = SPECIES_HUMAN + if(islist(S["all_quirks"]) + S["all_quirks"] += "Dullahan" + else + S["all_quirks"] = list("Dullahan") + /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) return diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm deleted file mode 100644 index ed06d2be5a..0000000000 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ /dev/null @@ -1,136 +0,0 @@ -/datum/species/dullahan - name = "Dullahan" - id = SPECIES_DULLAHAN - default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) - inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) - mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None") - use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM - mutant_brain = /obj/item/organ/brain/dullahan - mutanteyes = /obj/item/organ/eyes/dullahan - mutanttongue = /obj/item/organ/tongue/dullahan - mutantears = /obj/item/organ/ears/dullahan - blacklisted = TRUE - limbs_id = SPECIES_HUMAN - skinned_type = /obj/item/stack/sheet/animalhide/human - has_field_of_vision = FALSE //Too much of a trouble, their vision is already bound to their severed head. - species_category = SPECIES_CATEGORY_UNDEAD - var/pumpkin = FALSE - wings_icons = SPECIES_WINGS_SKELETAL //seems suitable for an undead. - - var/obj/item/dullahan_relay/myhead - -/datum/species/dullahan/pumpkin - name = "Pumpkin Head Dullahan" - id = "pumpkindullahan" - pumpkin = TRUE - -/datum/species/dullahan/check_roundstart_eligible() - if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) - return TRUE - return ..() - -/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - . = ..() - H.flags_1 &= ~(HEAR_1) - var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD) - if(head) - if(pumpkin)//Pumpkinhead! - head.animal_origin = 100 - head.icon = 'icons/obj/clothing/hats.dmi' - head.icon_state = "hardhat1_pumpkin_j" - head.custom_head = TRUE - head.drop_limb() - if(!QDELETED(head)) //drop_limb() deletes the limb if it's no drop location and dummy humans used for rendering icons are located in nullspace. Do the math. - head.throwforce = 25 - myhead = new /obj/item/dullahan_relay (head, H) - H.put_in_hands(head) - var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES) - for(var/datum/action/item_action/organ_action/OA in E.actions) - OA.Trigger() - -/datum/species/dullahan/on_species_loss(mob/living/carbon/human/H) - H.flags_1 |= HEAR_1 - H.reset_perspective(H) - if(myhead) - var/obj/item/dullahan_relay/DR = myhead - myhead = null - DR.owner = null - qdel(DR) - H.regenerate_limb(BODY_ZONE_HEAD,FALSE) - ..() - -/datum/species/dullahan/spec_life(mob/living/carbon/human/H) - if(QDELETED(myhead)) - myhead = null - H.gib() - var/obj/item/bodypart/head/head2 = H.get_bodypart(BODY_ZONE_HEAD) - if(head2) - myhead = null - H.gib() - -/datum/species/dullahan/proc/update_vision_perspective(mob/living/carbon/human/H) - var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) - if(eyes) - H.update_tint() - if(eyes.tint) - H.reset_perspective(H) - else - H.reset_perspective(myhead) - -/obj/item/organ/brain/dullahan - decoy_override = TRUE - organ_flags = ORGAN_NO_SPOIL//Do not decay - -/obj/item/organ/ears/dullahan - zone = "abstract" - -/obj/item/dullahan_relay - name = "dullahan relay" - var/mob/living/owner - flags_1 = HEAR_1 - -/obj/item/dullahan_relay/Initialize(mapload, mob/living/carbon/human/new_owner) - . = ..() - if(!new_owner) - return INITIALIZE_HINT_QDEL - owner = new_owner - START_PROCESSING(SSobj, src) - RegisterSignal(owner, COMSIG_MOB_CLICKED_SHIFT_ON, .proc/examinate_check) - RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner) - RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head) - RegisterSignal(owner, COMSIG_LIVING_REVIVE, .proc/retrieve_head) - -/obj/item/dullahan_relay/proc/examinate_check(mob/source, atom/target) - if(source.client.eye == src) - return COMPONENT_ALLOW_EXAMINATE - -/obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers) - if(!QDELETED(owner)) - hearers += owner - -/obj/item/dullahan_relay/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs) - excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs. - -//Retrieving the owner's head for better ahealing. -/obj/item/dullahan_relay/proc/retrieve_head(datum/source, full_heal, admin_revive) - if(admin_revive) - var/obj/item/bodypart/head/H = loc - var/turf/T = get_turf(owner) - if(H && istype(H) && T && !(H in owner.GetAllContents())) - H.forceMove(T) - -/obj/item/dullahan_relay/process() - if(!istype(loc, /obj/item/bodypart/head) || QDELETED(owner)) - . = PROCESS_KILL - qdel(src) - -/obj/item/dullahan_relay/Destroy() - if(!QDELETED(owner)) - var/mob/living/carbon/human/H = owner - if(isdullahan(H)) - var/datum/species/dullahan/D = H.dna.species - D.myhead = null - owner.gib() - owner = null - ..() From b4330b2f3d2e5f35cd2c72a3525f07c945c6b32f Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:19:22 +0100 Subject: [PATCH 04/24] GOODBYE SPECIES, HELLO COMPONENT --- code/datums/components/dullahan.dm | 22 +++++++++++++++++++ code/datums/dna.dm | 15 +++++-------- code/datums/wounds/slash.dm | 2 +- code/game/machinery/recycler.dm | 2 +- code/modules/client/preferences_savefile.dm | 4 ++-- code/modules/holiday/halloween/jacqueen.dm | 20 +---------------- code/modules/mob/living/carbon/human/human.dm | 3 --- .../mob/living/carbon/human/species.dm | 4 ++-- code/modules/projectiles/projectile/magic.dm | 2 +- tgstation.dme | 1 - 10 files changed, 36 insertions(+), 39 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 5e0658be39..b39726082a 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -161,3 +161,25 @@ H.reset_perspective(H) else H.reset_perspective(dullahan_head) + +/datum/component/dullahan/Destroy() + UnregisterSignal(parent, COMSIG_LIVING_REGENERATE_LIMBS) + qdel(dullahan_head) + REMOVE_TRAIT(parent, TRAIT_DULLAHAN, "dullahan_component") + + // work out what organs to give them based on their species + if(ishuman(parent)) + var/mob/living/carbon/human/H = parent + var/obj/item/organ/eyes/new_eyes = new H.dna.species.mutant_eyes() + var/obj/item/organ/brain/new_brain = new H.dna.species.mutant_brain() + var/obj/item/organ/eyes/old_eyes = H.getorganslot(ORGAN_SLOT_EYES) + var/obj/item/organ/brain/old_brain = H.getorganslot(ORGAN_SLOT_BRAIN) + + old_brain.Remove(TRUE,TRUE) + QDEL_NULL(old_brain) + new_brain.Insert(C, TRUE, TRUE) + + old_eyes.Remove(TRUE,TRUE) + QDEL_NULL(old_eyes) + new_eyes.Insert(C, TRUE, TRUE) + . = ..() diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 5619a09f05..bb2dab8033 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -717,16 +717,13 @@ death() petrify(INFINITY) if(3) - if(prob(90)) - var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD)) - if(BP) - BP.dismember() - else - unequip_everything() - drop_all_held_items() - gib() + var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD)) + if(BP) + BP.dismember() else - set_species(/datum/species/dullahan) + unequip_everything() + drop_all_held_items() + gib() /datum/dna/proc/update_body_size(old_size) if(!holder || features["body_size"] == old_size) diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 6a631ab8f4..68740e78ab 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -177,7 +177,7 @@ if(isinsect(victim) || iscatperson(victim) || ismammal(victim) || isdwarf(victim) || ismonkey(victim)) // Yep you can lick monkeys. user.reagents.add_reagent(/datum/reagent/hairball, 2) - else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || isdullahan(victim)) + else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || HAS_TRAIT(victim, TRAIT_DULLAHAN)) user.reagents.add_reagent(/datum/reagent/hairball, 1) if(blood_flow > minimum_flow) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index c1dac389bf..c561170af4 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -119,7 +119,7 @@ if(istype(AM, /obj/item)) var/obj/item/bodypart/head/as_head = AM var/obj/item/mmi/as_mmi = AM - if(istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_relay)) + if(istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_head)) living_detected = living_detected ? living_detected : AM nom += AM else if(isliving(AM)) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index b4a8952675..3a7e52e706 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -363,9 +363,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car // dullahans as a species cease to exist if(current_version < 56) var/species_id = S["species"] - if(species_id = SPECIES_DULLAHAN) + if(species_id == SPECIES_DULLAHAN) S["species"] = SPECIES_HUMAN - if(islist(S["all_quirks"]) + if(islist(S["all_quirks"])) S["all_quirks"] += "Dullahan" else S["all_quirks"] = list("Dullahan") diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 77187532f9..66ae3dce4b 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -219,23 +219,11 @@ /mob/living/simple_animal/jacq/proc/treat(mob/living/carbon/C, gender) visible_message("[src] gives off a glowing smile, \"What ken Ah offer ye? I can magic up an object, a potion or a plushie fer ye.\"") jacqrunes("What ken Ah offer ye? I can magic up an object, a potion or a plushie fer ye.", C) - var/choices_reward = list("Object - 3 candies", "Potion - 2 candies", "Jacqueline Tracker - 2 candies", "Plushie - 1 candy", "Can I get to know you instead?", "Become a pumpkinhead dullahan (perma) - 4 candies") + var/choices_reward = list("Object - 3 candies", "Potion - 2 candies", "Jacqueline Tracker - 2 candies", "Plushie - 1 candy", "Can I get to know you instead?") var/choice_reward = input(usr, "Trick or Treat?", "Trick or Treat?") in choices_reward //rewards switch(choice_reward) - if("Become a pumpkinhead dullahan (perma) - 4 candies") - if(!take_candies(C, 4)) - visible_message("[src] raises an eyebrown, \"It's 4 candies for that [gender]! Thems the rules!\"") - jacqrunes("It's 4 candies for that [gender]! Thems the rules!", C) - return - visible_message("[src] waves their arms around, \"Off comes your head, a pumpkin taking it's stead!\"") - jacqrunes("Off comes your head, a pumpkin taking it's stead!", C) - C.reagents.add_reagent(/datum/reagent/mutationtoxin/pumpkinhead, 5) - sleep(20) - poof() - return - if("Object - 3 candies") if(!take_candies(C, 3)) visible_message("[src] raises an eyebrown, \"It's 3 candies per trinket [gender]! Thems the rules!\"") @@ -688,12 +676,6 @@ else ..() -/datum/reagent/mutationtoxin/pumpkinhead - name = "Pumpkin head mutation toxin" - race = /datum/species/dullahan/pumpkin - mutationtext = "The pain subsides. You feel your head roll off your shoulders... and you smell pumpkin." - //I couldn't get the replace head sprite with a pumpkin to work so, it is what it is. - /mob/living/simple_animal/jacq/proc/check_candies(mob/living/carbon/C) var/invs = C.get_contents() var/candy_count = 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c60e4c6cb2..b81863e932 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -954,9 +954,6 @@ /mob/living/carbon/human/species/corporate race = /datum/species/corporate -/mob/living/carbon/human/species/dullahan - race = /datum/species/dullahan - /mob/living/carbon/human/species/felinid race = /datum/species/human/felinid diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b73f1da93a..77ad6c7d5a 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -345,11 +345,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/obj/item/organ/stomach/stomach = C.getorganslot(ORGAN_SLOT_STOMACH) var/obj/item/organ/tail/tail = C.getorganslot(ORGAN_SLOT_TAIL) - var/should_have_brain = !(HAS_TRAIT(C, TRAIT_DULLAHAN)) + var/should_have_brain = !(HAS_TRAIT(C, TRAIT_DULLAHAN)) // do not mess with a dullahans brain var/should_have_heart = !(NOBLOOD in species_traits) var/should_have_lungs = ((TRAIT_AUXILIARY_LUNGS in inherent_traits) || !(TRAIT_NOBREATH in inherent_traits)) var/should_have_appendix = !(TRAIT_NOHUNGER in inherent_traits) - var/should_have_eyes = TRUE + var/should_have_eyes = !(HAS_TRAIT(C, TRAIT_DULLAHAN)) // .. or their eyes var/should_have_ears = TRUE var/should_have_tongue = TRUE var/should_have_liver = !(NOLIVER in species_traits) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 9761881067..2959666a4c 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -37,7 +37,7 @@ return BULLET_ACT_BLOCK if(iscarbon(target)) var/mob/living/carbon/C = target - if(!is_species(C, /datum/species/dullahan)) //No accidental instagibbing dullahans please + if(HAS_TRAIT(C, TRAIT_DULLAHAN)) //No accidental instagibbing dullahans please C.regenerate_limbs() C.regenerate_organs() if(target.revive(full_heal = 1)) diff --git a/tgstation.dme b/tgstation.dme index 9fd6194e67..ca7d9ebda1 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2696,7 +2696,6 @@ #include "code\modules\mob\living\carbon\human\species_types\arachnid.dm" #include "code\modules\mob\living\carbon\human\species_types\bugmen.dm" #include "code\modules\mob\living\carbon\human\species_types\corporate.dm" -#include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\dwarves.dm" #include "code\modules\mob\living\carbon\human\species_types\ethereal.dm" #include "code\modules\mob\living\carbon\human\species_types\felinid.dm" From a397402a2e6b8de9466c7f1c3e0913d24b91895a Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:19:43 +0100 Subject: [PATCH 05/24] local man can't spell --- code/datums/components/dullahan.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index b39726082a..2c34c3d1d1 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -177,9 +177,9 @@ old_brain.Remove(TRUE,TRUE) QDEL_NULL(old_brain) - new_brain.Insert(C, TRUE, TRUE) + new_brain.Insert(H, TRUE, TRUE) old_eyes.Remove(TRUE,TRUE) QDEL_NULL(old_eyes) - new_eyes.Insert(C, TRUE, TRUE) + new_eyes.Insert(H, TRUE, TRUE) . = ..() From 6410c942445eef8096c08cc75e303764dcac5b62 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 20:58:27 +0100 Subject: [PATCH 06/24] Update dullahan.dm --- code/datums/components/dullahan.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 2c34c3d1d1..d362af99e4 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -170,7 +170,7 @@ // work out what organs to give them based on their species if(ishuman(parent)) var/mob/living/carbon/human/H = parent - var/obj/item/organ/eyes/new_eyes = new H.dna.species.mutant_eyes() + var/obj/item/organ/eyes/new_eyes = new H.dna.species.mutanteyes() var/obj/item/organ/brain/new_brain = new H.dna.species.mutant_brain() var/obj/item/organ/eyes/old_eyes = H.getorganslot(ORGAN_SLOT_EYES) var/obj/item/organ/brain/old_brain = H.getorganslot(ORGAN_SLOT_BRAIN) From fdd66a2b104883f5e92461d0e3328a4a45a2895e Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 21:48:55 +0100 Subject: [PATCH 07/24] gib people after their head is destroyed --- code/datums/components/dullahan.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index d362af99e4..c340b1ed0a 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -82,6 +82,8 @@ /obj/item/dullahan_head/Destroy() B.Remove() B.forceMove(get_turf(src)) + var/mob/living/human/H = parent + H.gib() . = ..() // allow the 'fake' head to relay speech back to the mob From d49b6d0779c531577be60bf87e72e0bc541b2d32 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 5 Aug 2022 22:22:29 +0100 Subject: [PATCH 08/24] ae --- code/datums/components/dullahan.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index c340b1ed0a..ce6c1e7eb7 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -82,8 +82,7 @@ /obj/item/dullahan_head/Destroy() B.Remove() B.forceMove(get_turf(src)) - var/mob/living/human/H = parent - H.gib() + owner.gib() . = ..() // allow the 'fake' head to relay speech back to the mob From 276143f5132524c6eda5f4e5e5faa6d6eab4933e Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 7 Aug 2022 23:17:49 +0100 Subject: [PATCH 09/24] Update dullahan.dm --- code/datums/components/dullahan.dm | 38 +++++++++++++----------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index ce6c1e7eb7..9401d3d3d0 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -19,17 +19,19 @@ // make sure the brain can't decay or fall out var/obj/item/organ/brain/B = H.getorganslot(ORGAN_SLOT_BRAIN) - B.zone = "abstract" // it exists in the ethereal plain - B.organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT | ORGAN_VITAL - dullahan_head.B = B + if(B) + B.zone = "abstract" // it exists in the ethereal plain + B.organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT | ORGAN_VITAL + dullahan_head.B = B // the eyes get similar treatment var/obj/item/organ/eyes/dullahan/new_eyes = new() var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES) - new_eyes.left_eye_color = E.left_eye_color - new_eyes.right_eye_color = E.right_eye_color - E.Remove() - qdel(E) + if(E) + new_eyes.left_eye_color = E.left_eye_color + new_eyes.right_eye_color = E.right_eye_color + E.Remove() + qdel(E) new_eyes.Insert(H) // make sure you handle the tongue correctly, too! @@ -40,10 +42,16 @@ var/obj/item/organ/tongue/dullahan/new_tongue = new() new_tongue.Insert(H) + // uh, eyes! + var/obj/item/organ/ears/dullahan_ears = H.getorganslot(ORGAN_SLOT_EARS) + if(dullahan_ears) + dullahan_ears.zone = "abstract" + // moving the brain's zone means we don't need the head to survive var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD) - head.drop_limb() - qdel(head) + if(head) + head.drop_limb() + qdel(head) H.flags_1 &= ~(HEAR_1) @@ -85,18 +93,6 @@ owner.gib() . = ..() -// allow the 'fake' head to relay speech back to the mob -/obj/item/dullahan_head/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) - if(owner) - var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]" - var/hrefpart = "" - var/treated_message = lang_treat(speaker, message_language, raw_message, spans, message_mode) - var/rendered = "[hrefpart][namepart] [treated_message]" - - if (owner.client?.prefs.chat_on_map && (owner.client.prefs.see_chat_non_mob || ismob(speaker))) - owner.create_chat_message(speaker, message_language, raw_message, spans, message_mode) - owner.show_message(rendered, "") - // update head sprite /obj/item/dullahan_head/proc/remove_head_overlays() overlays_standing = list() From 783d22b2d2f964904464fa3f7564fd8840df3639 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 7 Aug 2022 23:38:38 +0100 Subject: [PATCH 10/24] some more additions --- .../mob/dead/new_player/sprite_accessories/alienpeople.dm | 1 + code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm | 1 + code/modules/mob/dead/new_player/sprite_accessories/caps.dm | 1 + .../modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm | 1 + 4 files changed, 4 insertions(+) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm index 3972bdc2c3..9a7108af4c 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm @@ -48,6 +48,7 @@ icon = 'modular_citadel/icons/mob/xeno_parts_greyscale.dmi' mutant_part_string = "xhead" relevant_layers = list(BODY_ADJ_LAYER) + category = "HEAD" /datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm b/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm index 460b41f0d9..f16e751cc6 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm @@ -49,6 +49,7 @@ relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) mutant_part_string = "mandibles" color_src = 0 + category = "HEAD" /datum/sprite_accessory/arachnid_mandibles/none name = "None" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/caps.dm b/code/modules/mob/dead/new_player/sprite_accessories/caps.dm index d974672490..2e8416fbb5 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/caps.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/caps.dm @@ -2,6 +2,7 @@ icon = 'icons/mob/mutant_bodyparts.dmi' color_src = HAIR relevant_layers = list(BODY_ADJ_LAYER) + category = "HEAD" /datum/sprite_accessory/caps/round name = "Round" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm index f73a4a35a1..8a50091e73 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm @@ -134,6 +134,7 @@ relevant_layers = list(BODY_ADJ_LAYER) recommended_species = list("ipc") mutant_part_string = "ipc_antenna" + category = "HEAD" /datum/sprite_accessory/antenna/none name = "None" From 7df374a1f5cc539e336059b322fe672266bcfe0d Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 7 Aug 2022 23:51:02 +0100 Subject: [PATCH 11/24] IPC PLEASE --- .../mob/dead/new_player/sprite_accessories/ipc_synths.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm index 8a50091e73..ee6d8b3ceb 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm @@ -8,6 +8,10 @@ relevant_layers = list(BODY_ADJ_LAYER) mutable_category = "HEAD" +/datum/sprite_accessory/screen/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return (HD == null) // it's not visible if head is null + /datum/sprite_accessory/screen/blank name = "Blank" icon_state = "blank" From 671e5dd8726d34ae7210fc524f7a01b2084e4751 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 7 Aug 2022 23:53:08 +0100 Subject: [PATCH 12/24] oh shit oh fuck --- .../mob/dead/new_player/sprite_accessories/alienpeople.dm | 2 +- code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm | 2 +- code/modules/mob/dead/new_player/sprite_accessories/caps.dm | 2 +- .../mob/dead/new_player/sprite_accessories/ipc_synths.dm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm index 9a7108af4c..ba334d2934 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm @@ -48,7 +48,7 @@ icon = 'modular_citadel/icons/mob/xeno_parts_greyscale.dmi' mutant_part_string = "xhead" relevant_layers = list(BODY_ADJ_LAYER) - category = "HEAD" + mutable_category = "HEAD" /datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm b/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm index f16e751cc6..cd032b6a2a 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm @@ -49,7 +49,7 @@ relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) mutant_part_string = "mandibles" color_src = 0 - category = "HEAD" + mutable_category = "HEAD" /datum/sprite_accessory/arachnid_mandibles/none name = "None" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/caps.dm b/code/modules/mob/dead/new_player/sprite_accessories/caps.dm index 2e8416fbb5..5b30591d07 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/caps.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/caps.dm @@ -2,7 +2,7 @@ icon = 'icons/mob/mutant_bodyparts.dmi' color_src = HAIR relevant_layers = list(BODY_ADJ_LAYER) - category = "HEAD" + mutable_category = "HEAD" /datum/sprite_accessory/caps/round name = "Round" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm index ee6d8b3ceb..ec5c6ea792 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm @@ -138,7 +138,7 @@ relevant_layers = list(BODY_ADJ_LAYER) recommended_species = list("ipc") mutant_part_string = "ipc_antenna" - category = "HEAD" + mutable_category = "HEAD" /datum/sprite_accessory/antenna/none name = "None" From b5e70ba0080f35c104570b0fcb67a4aaf98408a1 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Mon, 8 Aug 2022 00:08:13 +0100 Subject: [PATCH 13/24] we do a little fix --- code/modules/client/preferences.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 8a9f122f43..409916da30 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -3357,6 +3357,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking wheels.setDir(spawn_chair.dir) wheels.buckle_mob(character) + var/datum/component/dullahan/dullahan = character.GetComponent(/datum/component/dullahan) + // if you ready up, quirks are assigned first, very stupid + if(dullahan && dullahan.dullahan_head) + dullahan.dullahan_head.name = "[character.name]'s head" + dullahan.dullahan_head.desc = "the decapitated head of [character.name]" /datum/preferences/proc/get_default_name(name_id) switch(name_id) From 9a8c356f2436a8a2424cf57b894c971f37841f96 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Mon, 8 Aug 2022 00:17:56 +0100 Subject: [PATCH 14/24] slightly better --- code/datums/components/dullahan.dm | 5 +++-- code/modules/client/preferences.dm | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 9401d3d3d0..09c65600f1 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -12,8 +12,9 @@ dullahan_head = new(get_turf(H)) - dullahan_head.name = "[H.name]'s head" - dullahan_head.desc = "the decapitated head of [H.name]" + if(length(H.name)) + dullahan_head.name = "[H.name]'s head" + dullahan_head.desc = "the decapitated head of [H.name]" dullahan_head.owner = H RegisterSignal(H, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 409916da30..3d08998a82 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -3359,7 +3359,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) wheels.buckle_mob(character) var/datum/component/dullahan/dullahan = character.GetComponent(/datum/component/dullahan) // if you ready up, quirks are assigned first, very stupid - if(dullahan && dullahan.dullahan_head) + if(dullahan && dullahan.dullahan_head && length(dullahan_head.name)) dullahan.dullahan_head.name = "[character.name]'s head" dullahan.dullahan_head.desc = "the decapitated head of [character.name]" From a2f4ea39af4bb41cd2d622c1d575d66f0f37e8e4 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Mon, 8 Aug 2022 00:29:20 +0100 Subject: [PATCH 15/24] attempted fix at the ready-up issue --- code/modules/client/preferences.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 3d08998a82..1e3c1defd4 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -3359,7 +3359,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) wheels.buckle_mob(character) var/datum/component/dullahan/dullahan = character.GetComponent(/datum/component/dullahan) // if you ready up, quirks are assigned first, very stupid - if(dullahan && dullahan.dullahan_head && length(dullahan_head.name)) + if(dullahan && dullahan.dullahan_head && length(dullahan.dullahan_head.name)) dullahan.dullahan_head.name = "[character.name]'s head" dullahan.dullahan_head.desc = "the decapitated head of [character.name]" From 529ada40efe7b981354fa799c9005a12fa491641 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Mon, 8 Aug 2022 16:36:15 +0100 Subject: [PATCH 16/24] auto retry --- code/datums/components/dullahan.dm | 15 ++++++++++++--- code/modules/client/preferences.dm | 5 ----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 09c65600f1..b3b2c44a63 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -12,9 +12,8 @@ dullahan_head = new(get_turf(H)) - if(length(H.name)) - dullahan_head.name = "[H.name]'s head" - dullahan_head.desc = "the decapitated head of [H.name]" + update_name() + dullahan_head.owner = H RegisterSignal(H, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head) @@ -60,6 +59,16 @@ dullahan_head.update_appearance() +/datum/component/dullahan/proc/update_name(retries = 0) + if(retries > 3) + return FALSE + var/mob/living/carbon/human/H = parent + if(length(H.name)) + dullahan_head.name = "[H.name]'s head" + dullahan_head.desc = "the decapitated head of [H.name]" + return TRUE + addtimer(CALLBACK(src, .proc/update_name, retries + 1), 2 SECONDS) + /datum/component/dullahan/proc/include_owner(datum/source, list/processing_list, list/hearers) if(!QDELETED(parent)) hearers += parent diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 1e3c1defd4..8a9f122f43 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -3357,11 +3357,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking wheels.setDir(spawn_chair.dir) wheels.buckle_mob(character) - var/datum/component/dullahan/dullahan = character.GetComponent(/datum/component/dullahan) - // if you ready up, quirks are assigned first, very stupid - if(dullahan && dullahan.dullahan_head && length(dullahan.dullahan_head.name)) - dullahan.dullahan_head.name = "[character.name]'s head" - dullahan.dullahan_head.desc = "the decapitated head of [character.name]" /datum/preferences/proc/get_default_name(name_id) switch(name_id) From a9f77d9344e1443753835119f716d34a315507bd Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Mon, 8 Aug 2022 16:38:02 +0100 Subject: [PATCH 17/24] let it retry for up to a minute --- code/datums/components/dullahan.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index b3b2c44a63..053fe2ff11 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -60,7 +60,7 @@ dullahan_head.update_appearance() /datum/component/dullahan/proc/update_name(retries = 0) - if(retries > 3) + if(retries > 30) return FALSE var/mob/living/carbon/human/H = parent if(length(H.name)) From 8ee01d0bc4eeabd8d45c9ce25a83fdb6010a452b Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Tue, 9 Aug 2022 11:08:52 +0100 Subject: [PATCH 18/24] Update dullahan.dm --- code/datums/components/dullahan.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 053fe2ff11..7d35b2d874 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -96,6 +96,7 @@ // this is for keeping track of the overlays because you can't read the actual overlays list as it's a special byond var var/list/overlays_standing var/obj/item/organ/brain/B + w_class = WEIGHT_CLASS_BULKY /obj/item/dullahan_head/Destroy() B.Remove() From e71686d8acdf53f1c4d37970c188604935b48099 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Tue, 9 Aug 2022 11:59:10 +0100 Subject: [PATCH 19/24] fixes --- code/__DEFINES/_flags/item_flags.dm | 2 +- code/datums/components/dullahan.dm | 7 +++++++ code/modules/surgery/organs/organ_internal.dm | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/code/__DEFINES/_flags/item_flags.dm b/code/__DEFINES/_flags/item_flags.dm index 529499127d..d28cb80bab 100644 --- a/code/__DEFINES/_flags/item_flags.dm +++ b/code/__DEFINES/_flags/item_flags.dm @@ -51,4 +51,4 @@ #define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances #define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment. #define ORGAN_EDIBLE (1<<7) //is a snack? :D -#define ORGAN_SYNTHETIC_EMP (1<<6) //Synthetic organ affected by an EMP. Deteriorates over time. +#define ORGAN_SYNTHETIC_EMP (1<<8) //Synthetic organ affected by an EMP. Deteriorates over time. diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 7d35b2d874..944f99c028 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -87,6 +87,7 @@ actions_types = list(/datum/action/item_action/organ_action/dullahan) zone = "abstract" tint = INFINITY // used to switch the vision perspective to the head on species_gain(). + organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT /obj/item/dullahan_head name = "coders lament" @@ -180,8 +181,10 @@ var/mob/living/carbon/human/H = parent var/obj/item/organ/eyes/new_eyes = new H.dna.species.mutanteyes() var/obj/item/organ/brain/new_brain = new H.dna.species.mutant_brain() + var/obj/item/organ/tongue/new_tongue = new H.dna.species.mutanttongue() var/obj/item/organ/eyes/old_eyes = H.getorganslot(ORGAN_SLOT_EYES) var/obj/item/organ/brain/old_brain = H.getorganslot(ORGAN_SLOT_BRAIN) + var/obj/item/organ/tongue/old_tongue = H.getorganslot(ORGAN_SLOT_TONGUE) old_brain.Remove(TRUE,TRUE) QDEL_NULL(old_brain) @@ -190,4 +193,8 @@ old_eyes.Remove(TRUE,TRUE) QDEL_NULL(old_eyes) new_eyes.Insert(H, TRUE, TRUE) + + old_tongue.Remove(TRUE,TRUE) + QDEL_NULL(old_tongue) + new_tongue.Insert(H, TRUE, TRUE) . = ..() diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index d4a2663374..2c9b9b99d4 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -103,6 +103,7 @@ is_cold() if(organ_flags & ORGAN_FROZEN) return + message_admins("fuck you we're killing [owner]") applyOrganDamage(maxHealth * decay_factor * (seconds * 0.5)) /obj/item/organ/proc/can_decay() @@ -155,6 +156,7 @@ if(organ_flags & ORGAN_FAILING || !owner) return FALSE if(organ_flags & ORGAN_SYNTHETIC_EMP) //Synthetic organ has been emped, is now failing. + message_admins("emp go brrr") applyOrganDamage(maxHealth * decay_factor) return FALSE if(organ_flags & ORGAN_SYNTHETIC) @@ -165,6 +167,7 @@ ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's satiety healing_amount -= owner.satiety > 0 ? 4 * (maxHealth * healing_factor) * (owner.satiety / MAX_SATIETY) : 0 if(healing_amount) + message_admins("we um are healing") applyOrganDamage(healing_amount) //to FERMI_TWEAK return TRUE From 835323bdbcb9aa3c8ce0eeb137857799c125b19a Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Tue, 9 Aug 2022 12:07:09 +0100 Subject: [PATCH 20/24] neurine fixes your traumas, yo! --- .../reagents/chemistry/reagents/medicine_reagents.dm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 0a78af67b2..a5fbead7cb 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1081,6 +1081,13 @@ else B.gain_trauma_type(BRAIN_TRAUMA_SPECIAL) +/datum/reagent/medicine/neurine/reaction_obj(obj/O, reac_volume) + if(istype(O, /obj/item/dullahan_head)) + var/obj/item/dullahan_head/head = O + if(head.B) + head.B.applyOrganDamage(-20) + if(head.owner) + head.owner.cure_trauma_type(resilience = TRAUMA_RESILIENCE_SURGERY) /datum/reagent/medicine/neurine/on_mob_life(mob/living/carbon/C) if(holder.has_reagent(/datum/reagent/consumable/ethanol/neurotoxin)) From 5d925412b1134dc5ef78babfed23a24be072fa70 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Tue, 9 Aug 2022 16:37:39 +0100 Subject: [PATCH 21/24] Update organ_internal.dm --- code/modules/surgery/organs/organ_internal.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 2c9b9b99d4..d4a2663374 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -103,7 +103,6 @@ is_cold() if(organ_flags & ORGAN_FROZEN) return - message_admins("fuck you we're killing [owner]") applyOrganDamage(maxHealth * decay_factor * (seconds * 0.5)) /obj/item/organ/proc/can_decay() @@ -156,7 +155,6 @@ if(organ_flags & ORGAN_FAILING || !owner) return FALSE if(organ_flags & ORGAN_SYNTHETIC_EMP) //Synthetic organ has been emped, is now failing. - message_admins("emp go brrr") applyOrganDamage(maxHealth * decay_factor) return FALSE if(organ_flags & ORGAN_SYNTHETIC) @@ -167,7 +165,6 @@ ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's satiety healing_amount -= owner.satiety > 0 ? 4 * (maxHealth * healing_factor) * (owner.satiety / MAX_SATIETY) : 0 if(healing_amount) - message_admins("we um are healing") applyOrganDamage(healing_amount) //to FERMI_TWEAK return TRUE From b260794e54db91f11ce3380e52711db25ec56268 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Wed, 10 Aug 2022 16:37:21 +0100 Subject: [PATCH 22/24] Update dullahan.dm --- code/datums/components/dullahan.dm | 58 +++++++++++++++++------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 944f99c028..6b18f7f6c1 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -100,9 +100,10 @@ w_class = WEIGHT_CLASS_BULKY /obj/item/dullahan_head/Destroy() - B.Remove() - B.forceMove(get_turf(src)) - owner.gib() + if(owner) + B.Remove() + B.forceMove(get_turf(src)) + owner.gib() . = ..() // update head sprite @@ -115,28 +116,31 @@ add_overlay(overlay) /obj/item/dullahan_head/update_appearance() - remove_head_overlays() - // to do this without duplicating large amounts of code - // it's best to regenerate the head, then remove it once we have the overlays we want - owner.regenerate_limb(BODY_ZONE_HEAD, TRUE) // don't heal them - owner.regenerate_icons(TRUE) // yes i know it's expensive but do you want me to rewrite our entire overlay system, also block recursive calls here by passing in TRUE (it wont go back to call update_appearance this way) - var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD) - add_overlay(head.get_limb_icon(FALSE, TRUE, TRUE)) - for(var/overlay in owner.overlays_standing) - if(istype(overlay, /mutable_appearance)) - var/mutable_appearance/mutable = overlay - if(mutable.category == "HEAD") - add_head_overlay(mutable) - else - if(islist(overlay)) - var/list/list_appearances = overlay - for(var/overlay2 in list_appearances) - if(istype(overlay2, /mutable_appearance)) - var/mutable_appearance/mutable = overlay2 - if(mutable.category == "HEAD") - add_head_overlay(mutable) - head.drop_limb() - qdel(head) + if(owner && !HAS_TRAIT(owner, TRAIT_HUMAN_NO_RENDER)) + remove_head_overlays() + // to do this without duplicating large amounts of code + // it's best to regenerate the head, then remove it once we have the overlays we want + owner.regenerate_limb(BODY_ZONE_HEAD, TRUE) // don't heal them + owner.cut_overlays() + owner.regenerate_icons(TRUE) // yes i know it's expensive but do you want me to rewrite our entire overlay system, also block recursive calls here by passing in TRUE (it wont go back to call update_appearance this way) + var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD) + if(head) + add_overlay(head.get_limb_icon(FALSE, TRUE, TRUE)) + for(var/overlay in owner.overlays_standing) + if(istype(overlay, /mutable_appearance)) + var/mutable_appearance/mutable = overlay + if(mutable.category == "HEAD") + add_head_overlay(mutable) + else + if(islist(overlay)) + var/list/list_appearances = overlay + for(var/overlay2 in list_appearances) + if(istype(overlay2, /mutable_appearance)) + var/mutable_appearance/mutable = overlay2 + if(mutable.category == "HEAD") + add_head_overlay(mutable) + head.drop_limb() + qdel(head) /obj/item/dullahan_head/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs) excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs. @@ -173,6 +177,7 @@ /datum/component/dullahan/Destroy() UnregisterSignal(parent, COMSIG_LIVING_REGENERATE_LIMBS) + dullahan_head.owner = null qdel(dullahan_head) REMOVE_TRAIT(parent, TRAIT_DULLAHAN, "dullahan_component") @@ -186,6 +191,9 @@ var/obj/item/organ/brain/old_brain = H.getorganslot(ORGAN_SLOT_BRAIN) var/obj/item/organ/tongue/old_tongue = H.getorganslot(ORGAN_SLOT_TONGUE) + H.regenerate_limb(BODY_ZONE_HEAD, TRUE) + H.reset_perspective(H) + old_brain.Remove(TRUE,TRUE) QDEL_NULL(old_brain) new_brain.Insert(H, TRUE, TRUE) From 325d467ac580f9bba7741eebf333314469bf821a Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 13 Aug 2022 18:45:25 +0100 Subject: [PATCH 23/24] Update mirror.dm --- code/game/objects/structures/mirror.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 9ff41c4404..ffb48ce633 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -42,6 +42,7 @@ H.hair_style = new_style H.update_mutant_bodyparts() + H.update_hair() /obj/structure/mirror/examine_status(mob/user) if(broken) From b7673e234fc001ee47f8e35c267ab6ae12c879a8 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 9 Dec 2022 13:30:10 +0000 Subject: [PATCH 24/24] add no hunger no breath --- code/datums/components/dullahan.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 6b18f7f6c1..973f06a61e 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -9,6 +9,8 @@ return . ADD_TRAIT(H, TRAIT_DULLAHAN, "dullahan_component") + ADD_TRAIT(H, TRAIT_NOHUNGER, "dullahan_component_no_hunger") + ADD_TRAIT(H, TRAIT_NOBREATH, "dullahan_component_no_breath") dullahan_head = new(get_turf(H))