diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index e168b89261d3a1..adad9e1fc23c3d 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -76,33 +76,24 @@ #define DNA_MUTATION_BLOCKS 8 #define DNA_UNIQUE_ENZYMES_LEN 32 -//species traits for mutantraces +// species_traits list on /datum/species, please avoid adding more and use inherent_traits instead where possible #define MUTCOLORS 1 -#define HAIR 2 -#define FACEHAIR 3 -#define EYECOLOR 4 -#define LIPS 5 -#define NOTRANSSTING 7 -#define NOZOMBIE 8 -#define NO_UNDERWEAR 9 -#define NO_DNA_COPY 10 -#define DRINKSBLOOD 11 - +#define NOTRANSSTING 2 +#define NOZOMBIE 3 +#define NO_UNDERWEAR 4 +#define NO_DNA_COPY 5 +#define DRINKSBLOOD 6 /// Use this if you want to change the race's color without the player being able to pick their own color. AKA special color shifting -#define DYNCOLORS 12 -#define AGENDER 13 -/// Do not draw eyes or eyeless overlay -#define NOEYESPRITES 14 +#define DYNCOLORS 7 +#define AGENDER 8 ///If we have a limb-specific overlay sprite -#define HAS_MARKINGS 15 +#define HAS_MARKINGS 9 /// Do not draw blood overlay -#define NOBLOODOVERLAY 16 +#define NOBLOODOVERLAY 10 ///No augments, for monkeys in specific because they will turn into fucking freakazoids https://cdn.discordapp.com/attachments/326831214667235328/791313258912153640/102707682-fa7cad80-4294-11eb-8f13-8c689468aeb0.png -#define NOAUGMENTS 17 +#define NOAUGMENTS 11 ///will be assigned a universal vampire themed last name shared by their department. this is preferenced! -#define BLOOD_CLANS 18 -/// Similar to NOEYESPRITES but only excludes the eyeless overlay -#define NOEYEHOLES 19 +#define BLOOD_CLANS 12 //organ slots #define ORGAN_SLOT_ADAMANTINE_RESONATOR "adamantine_resonator" diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 58b48ec92a4fc7..0ba55307f78e28 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -55,6 +55,7 @@ #define COLOR_ASSISTANT_OLIVE "#828163" #define COLOR_VIBRANT_LIME "#00FF00" #define COLOR_SERVICE_LIME "#58C800" +#define COLOR_JADE "#5EFB6E" #define COLOR_LIME "#32CD32" #define COLOR_DARK_LIME "#00aa00" #define COLOR_VERY_PALE_LIME_GREEN "#DDFFD3" diff --git a/code/__DEFINES/sprite_accessories.dm b/code/__DEFINES/sprite_accessories.dm new file mode 100644 index 00000000000000..9c9471130e6fda --- /dev/null +++ b/code/__DEFINES/sprite_accessories.dm @@ -0,0 +1,9 @@ +// ~color source defines for sprite accessories +/// Color of the sprite accessory will match the owner's mutant color, which is granted by certain species +#define MUTANT_COLOR "mutant_color" +/// Color of the sprite accessory will match the owner's hair color +#define HAIR_COLOR "hair_color" +/// Color of the sprite accessory will match the owner's facial hair color +#define FACIAL_HAIR_COLOR "facial_hair_color" +/// Color of the sprite accessory will match the owner's (left) eye color +#define EYE_COLOR "eye_color" diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm index 8cfb61fe63b4cb..427e06124477f8 100644 --- a/code/__DEFINES/surgery.dm +++ b/code/__DEFINES/surgery.dm @@ -32,6 +32,24 @@ ///Bodypart does not get replaced during set_species() #define BP_BLOCK_CHANGE_SPECIES (1<<0) +// Flags for the head_flags var on /obj/item/bodypart/head +/// Head can have hair +#define HEAD_HAIR (1<<0) +/// Head can have facial hair +#define HEAD_FACIAL_HAIR (1<<1) +/// Head can have lips +#define HEAD_LIPS (1<<2) +/// Head can have eye sprites +#define HEAD_EYESPRITES (1<<3) +/// Head will have colored eye sprites +#define HEAD_EYECOLOR (1<<4) +/// Head can have eyeholes when missing eyes +#define HEAD_EYEHOLES (1<<5) +/// Head can have debrain overlay +#define HEAD_DEBRAIN (1<<6) +/// All head flags, default for most heads +#define HEAD_ALL_FEATURES (HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN) + /// When the surgery step fails :( #define SURGERY_STEP_FAIL -1 diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 7b3878da782e63..b6c5d2c9298f63 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -400,6 +400,16 @@ DEFINE_BITFIELD(change_exempt_flags, list( "BP_BLOCK_CHANGE_SPECIES" = BP_BLOCK_CHANGE_SPECIES, )) +DEFINE_BITFIELD(head_flags, list( + "HEAD_HAIR" = HEAD_HAIR, + "HEAD_FACIAL_HAIR" = HEAD_FACIAL_HAIR, + "HEAD_LIPS" = HEAD_LIPS, + "HEAD_EYESPRITES" = HEAD_EYESPRITES, + "HEAD_EYECOLOR" = HEAD_EYECOLOR, + "HEAD_EYEHOLES" = HEAD_EYEHOLES, + "HEAD_DEBRAIN" = HEAD_DEBRAIN, +)) + DEFINE_BITFIELD(supports_variations_flags, list( "CLOTHING_NO_VARIATION" = CLOTHING_NO_VARIATION, "CLOTHING_DIGITIGRADE_VARIATION" = CLOTHING_DIGITIGRADE_VARIATION, diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index c00df24a164c83..2cf0f4b90f589a 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -521,6 +521,7 @@ . = ..() if(.)//cant add return TRUE + var/obj/item/organ/internal/brain/brain = owner.get_organ_slot(ORGAN_SLOT_BRAIN) if(brain) brain.zone = BODY_ZONE_CHEST @@ -529,11 +530,10 @@ if(head) owner.visible_message(span_warning("[owner]'s head splatters with a sickening crunch!"), ignored_mobs = list(owner)) new /obj/effect/gibspawner/generic(get_turf(owner), owner) - head.dismember(BRUTE) + head.dismember(dam_type = BRUTE, silent = TRUE) head.drop_organs() qdel(head) - owner.regenerate_icons() - RegisterSignal(owner, COMSIG_ATTEMPT_CARBON_ATTACH_LIMB, PROC_REF(abortattachment)) + RegisterSignal(owner, COMSIG_ATTEMPT_CARBON_ATTACH_LIMB, PROC_REF(abort_attachment)) /datum/mutation/human/headless/on_losing() . = ..() @@ -541,7 +541,7 @@ return TRUE var/obj/item/organ/internal/brain/brain = owner.get_organ_slot(ORGAN_SLOT_BRAIN) if(brain) //so this doesn't instantly kill you. we could delete the brain, but it lets people cure brain issues they /really/ shouldn't be - brain.zone = BODY_ZONE_HEAD + brain.zone = initial(brain.zone) UnregisterSignal(owner, COMSIG_ATTEMPT_CARBON_ATTACH_LIMB) var/successful = owner.regenerate_limb(BODY_ZONE_HEAD) if(!successful) @@ -552,8 +552,7 @@ owner.visible_message(span_warning("[owner]'s head returns with a sickening crunch!"), span_warning("Your head regrows with a sickening crack! Ouch.")) new /obj/effect/gibspawner/generic(get_turf(owner), owner) - -/datum/mutation/human/headless/proc/abortattachment(datum/source, obj/item/bodypart/new_limb, special) //you aren't getting your head back +/datum/mutation/human/headless/proc/abort_attachment(datum/source, obj/item/bodypart/new_limb, special) //you aren't getting your head back SIGNAL_HANDLER if(istype(new_limb, /obj/item/bodypart/head)) diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 2acdb70bee4d50..18a0f947dc6d6f 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -140,9 +140,7 @@ set_limb(L) LAZYADD(victim.all_wounds, src) LAZYADD(limb.wounds, src) - //it's ok to not typecheck, humans are the only ones that deal with wounds - var/mob/living/carbon/human/human_victim = victim - no_bleeding = HAS_TRAIT(human_victim, TRAIT_NOBLOOD) + no_bleeding = HAS_TRAIT(victim, TRAIT_NOBLOOD) update_descriptions() limb.update_wounds() if(status_effect_type) diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 8a76da47d0eee4..9e24154112042a 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -6,8 +6,9 @@ icon_state = "lipstick" inhand_icon_state = "lipstick" w_class = WEIGHT_CLASS_TINY - var/colour = "red" var/open = FALSE + /// Actual color of the lipstick, also gets applied to the human + var/lipstick_color = COLOR_RED /// A trait that's applied while someone has this lipstick applied, and is removed when the lipstick is removed var/lipstick_trait @@ -31,33 +32,32 @@ if(!open) return var/mutable_appearance/colored_overlay = mutable_appearance(icon, "lipstick_uncap_color") - colored_overlay.color = colour + colored_overlay.color = lipstick_color . += colored_overlay /obj/item/lipstick/purple name = "purple lipstick" - colour = "purple" + lipstick_color = COLOR_PURPLE /obj/item/lipstick/jade - //It's still called Jade, but theres no HTML color for jade, so we use lime. name = "jade lipstick" - colour = "lime" + lipstick_color = COLOR_JADE /obj/item/lipstick/blue name = "blue lipstick" - colour = "blue" + lipstick_color = COLOR_BLUE /obj/item/lipstick/green name = "green lipstick" - colour = "green" + lipstick_color = COLOR_GREEN /obj/item/lipstick/white name = "white lipstick" - colour = "white" + lipstick_color = COLOR_WHITE /obj/item/lipstick/black name = "black lipstick" - colour = "black" + lipstick_color = COLOR_BLACK /obj/item/lipstick/black/death name = "\improper Kiss of Death" @@ -71,8 +71,16 @@ /obj/item/lipstick/random/Initialize(mapload) . = ..() icon_state = "lipstick" - colour = pick("red","purple","lime","black","green","blue","white") - name = "[colour] lipstick" + var/static/list/possible_colors + if(!possible_colors) + possible_colors = list() + for(var/obj/item/lipstick/lipstick_path as anything in (typesof(/obj/item/lipstick) - src.type)) + if(!initial(lipstick_path.lipstick_color)) + continue + possible_colors[initial(lipstick_path.lipstick_color)] = initial(lipstick_path.name) + lipstick_color = pick(possible_colors) + name = possible_colors[lipstick_color] + update_appearance() /obj/item/lipstick/attack_self(mob/user) to_chat(user, span_notice("You twist [src] [open ? "closed" : "open"].")) @@ -98,7 +106,7 @@ if(target == user) user.visible_message(span_notice("[user] does [user.p_their()] lips with \the [src]."), \ span_notice("You take a moment to apply \the [src]. Perfect!")) - target.update_lips("lipstick", colour, lipstick_trait) + target.update_lips("lipstick", lipstick_color, lipstick_trait) return user.visible_message(span_warning("[user] begins to do [target]'s lips with \the [src]."), \ @@ -107,8 +115,7 @@ return user.visible_message(span_notice("[user] does [target]'s lips with \the [src]."), \ span_notice("You apply \the [src] on [target]'s lips.")) - target.update_lips("lipstick", colour, lipstick_trait) - + target.update_lips("lipstick", lipstick_color, lipstick_trait) //you can wipe off lipstick with paper! /obj/item/paper/attack(mob/M, mob/user) @@ -145,126 +152,131 @@ shave(user, BODY_ZONE_HEAD)//doesnt need to be BODY_ZONE_HEAD specifically, but whatever return BRUTELOSS -/obj/item/razor/proc/shave(mob/living/carbon/human/H, location = BODY_ZONE_PRECISE_MOUTH) +/obj/item/razor/proc/shave(mob/living/carbon/human/skinhead, location = BODY_ZONE_PRECISE_MOUTH) if(location == BODY_ZONE_PRECISE_MOUTH) - H.facial_hairstyle = "Shaved" + skinhead.facial_hairstyle = "Shaved" else - H.hairstyle = "Skinhead" + skinhead.hairstyle = "Skinhead" - H.update_body_parts() + skinhead.update_body_parts() playsound(loc, 'sound/items/welder2.ogg', 20, TRUE) -/obj/item/razor/attack(mob/M, mob/living/user) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/location = user.zone_selected - if((location in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)) && !H.get_bodypart(BODY_ZONE_HEAD)) - to_chat(user, span_warning("[H] doesn't have a head!")) - return - if(location == BODY_ZONE_PRECISE_MOUTH) - if(!user.combat_mode) - if(H.gender == MALE) - if (H == user) - to_chat(user, span_warning("You need a mirror to properly style your own facial hair!")) - return - if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return - var/new_style = tgui_input_list(user, "Select a facial hairstyle", "Grooming", GLOB.facial_hairstyles_list) - if(isnull(new_style)) - return - if(!get_location_accessible(H, location)) - to_chat(user, span_warning("The mask is in the way!")) - return - if(HAS_TRAIT(H, TRAIT_SHAVED)) - to_chat(user, span_warning("[H] is just way too shaved. Like, really really shaved.")) - return - user.visible_message(span_notice("[user] tries to change [H]'s facial hairstyle using [src]."), span_notice("You try to change [H]'s facial hairstyle using [src].")) - if(new_style && do_after(user, 60, target = H)) - user.visible_message(span_notice("[user] successfully changes [H]'s facial hairstyle using [src]."), span_notice("You successfully change [H]'s facial hairstyle using [src].")) - H.facial_hairstyle = new_style - H.update_body_parts() - return - else - return - - else - if(!(FACEHAIR in H.dna.species.species_traits)) - to_chat(user, span_warning("There is no facial hair to shave!")) - return - if(!get_location_accessible(H, location)) - to_chat(user, span_warning("The mask is in the way!")) - return - if(H.facial_hairstyle == "Shaved") - to_chat(user, span_warning("Already clean-shaven!")) - return - - if(H == user) //shaving yourself - user.visible_message(span_notice("[user] starts to shave [user.p_their()] facial hair with [src]."), \ - span_notice("You take a moment to shave your facial hair with [src]...")) - if(do_after(user, 50, target = H)) - user.visible_message(span_notice("[user] shaves [user.p_their()] facial hair clean with [src]."), \ - span_notice("You finish shaving with [src]. Fast and clean!")) - shave(H, location) - else - user.visible_message(span_warning("[user] tries to shave [H]'s facial hair with [src]."), \ - span_notice("You start shaving [H]'s facial hair...")) - if(do_after(user, 50, target = H)) - user.visible_message(span_warning("[user] shaves off [H]'s facial hair with [src]."), \ - span_notice("You shave [H]'s facial hair clean off.")) - shave(H, location) - - else if(location == BODY_ZONE_HEAD) - if(!user.combat_mode) - if (H == user) - to_chat(user, span_warning("You need a mirror to properly style your own hair!")) +/obj/item/razor/attack(mob/target_mob, mob/living/user, params) + if(!ishuman(target_mob)) + return ..() + var/mob/living/carbon/human/human_target = target_mob + var/obj/item/bodypart/head/noggin = human_target.get_bodypart(BODY_ZONE_HEAD) + var/location = user.zone_selected + var/static/list/head_zones = list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD) + if(!noggin && (location in head_zones)) + to_chat(user, span_warning("[human_target] doesn't have a head!")) + return + if(location == BODY_ZONE_PRECISE_MOUTH) + if(!user.combat_mode) + if(human_target.gender == MALE) + if(human_target == user) + to_chat(user, span_warning("You need a mirror to properly style your own facial hair!")) return if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return - var/new_style = tgui_input_list(user, "Select a hairstyle", "Grooming", GLOB.hairstyles_list) + var/new_style = tgui_input_list(user, "Select a facial hairstyle", "Grooming", GLOB.facial_hairstyles_list) if(isnull(new_style)) return - if(!get_location_accessible(H, location)) + if(!get_location_accessible(human_target, location)) to_chat(user, span_warning("The headgear is in the way!")) return - if(HAS_TRAIT(H, TRAIT_BALD)) - to_chat(user, span_warning("[H] is just way too bald. Like, really really bald.")) + if(!(noggin.head_flags & HEAD_FACIAL_HAIR)) + to_chat(user, span_warning("There is no facial hair to style!")) return - user.visible_message(span_notice("[user] tries to change [H]'s hairstyle using [src]."), span_notice("You try to change [H]'s hairstyle using [src].")) - if(new_style && do_after(user, 60, target = H)) - user.visible_message(span_notice("[user] successfully changes [H]'s hairstyle using [src]."), span_notice("You successfully change [H]'s hairstyle using [src].")) - H.hairstyle = new_style - H.update_body_parts() + if(HAS_TRAIT(human_target, TRAIT_SHAVED)) + to_chat(user, span_warning("[human_target] is just way too shaved. Like, really really shaved.")) return - - else - if(!(HAIR in H.dna.species.species_traits)) - to_chat(user, span_warning("There is no hair to shave!")) - return - if(!get_location_accessible(H, location)) - to_chat(user, span_warning("The headgear is in the way!")) - return - if(H.hairstyle == "Bald" || H.hairstyle == "Balding Hair" || H.hairstyle == "Skinhead") - to_chat(user, span_warning("There is not enough hair left to shave!")) + user.visible_message(span_notice("[user] tries to change [human_target]'s facial hairstyle using [src]."), span_notice("You try to change [human_target]'s facial hairstyle using [src].")) + if(new_style && do_after(user, 6 SECONDS, target = human_target)) + user.visible_message(span_notice("[user] successfully changes [human_target]'s facial hairstyle using [src]."), span_notice("You successfully change [human_target]'s facial hairstyle using [src].")) + human_target.facial_hairstyle = new_style + human_target.update_body_parts(update_limb_data = TRUE) return - - if(H == user) //shaving yourself - user.visible_message(span_notice("[user] starts to shave [user.p_their()] head with [src]."), \ - span_notice("You start to shave your head with [src]...")) - if(do_after(user, 5, target = H)) - user.visible_message(span_notice("[user] shaves [user.p_their()] head with [src]."), \ - span_notice("You finish shaving with [src].")) - shave(H, location) - else - var/turf/H_loc = H.loc - user.visible_message(span_warning("[user] tries to shave [H]'s head with [src]!"), \ - span_notice("You start shaving [H]'s head...")) - if(do_after(user, 50, target = H)) - if(H_loc == H.loc) - user.visible_message(span_warning("[user] shaves [H]'s head bald with [src]!"), \ - span_notice("You shave [H]'s head bald.")) - shave(H, location) + else + return else - ..() - else - ..() + if(!get_location_accessible(human_target, location)) + to_chat(user, span_warning("The mask is in the way!")) + return + if(!(noggin.head_flags & HEAD_FACIAL_HAIR)) + to_chat(user, span_warning("There is no facial hair to shave!")) + return + if(human_target.facial_hairstyle == "Shaved") + to_chat(user, span_warning("Already clean-shaven!")) + return + + if(human_target == user) //shaving yourself + user.visible_message(span_notice("[user] starts to shave [user.p_their()] facial hair with [src]."), \ + span_notice("You take a moment to shave your facial hair with [src]...")) + if(do_after(user, 5 SECONDS, target = user)) + user.visible_message(span_notice("[user] shaves [user.p_their()] facial hair clean with [src]."), \ + span_notice("You finish shaving with [src]. Fast and clean!")) + shave(user, location) + return + else + user.visible_message(span_warning("[user] tries to shave [human_target]'s facial hair with [src]."), \ + span_notice("You start shaving [human_target]'s facial hair...")) + if(do_after(user, 5 SECONDS, target = human_target)) + user.visible_message(span_warning("[user] shaves off [human_target]'s facial hair with [src]."), \ + span_notice("You shave [human_target]'s facial hair clean off.")) + shave(human_target, location) + return + else if(location == BODY_ZONE_HEAD) + if(!user.combat_mode) + if(human_target == user) + to_chat(user, span_warning("You need a mirror to properly style your own hair!")) + return + if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + return + var/new_style = tgui_input_list(user, "Select a hairstyle", "Grooming", GLOB.hairstyles_list) + if(isnull(new_style)) + return + if(!get_location_accessible(human_target, location)) + to_chat(user, span_warning("The headgear is in the way!")) + return + if(!(noggin.head_flags & HEAD_HAIR)) + to_chat(user, span_warning("There is no hair to style!")) + return + if(HAS_TRAIT(human_target, TRAIT_BALD)) + to_chat(user, span_warning("[human_target] is just way too bald. Like, really really bald.")) + return + user.visible_message(span_notice("[user] tries to change [human_target]'s hairstyle using [src]."), span_notice("You try to change [human_target]'s hairstyle using [src].")) + if(new_style && do_after(user, 6 SECONDS, target = human_target)) + user.visible_message(span_notice("[user] successfully changes [human_target]'s hairstyle using [src]."), span_notice("You successfully change [human_target]'s hairstyle using [src].")) + human_target.hairstyle = new_style + human_target.update_body_parts(update_limb_data = TRUE) + return + else + if(!get_location_accessible(human_target, location)) + to_chat(user, span_warning("The headgear is in the way!")) + return + if(!(noggin.head_flags & HEAD_HAIR)) + to_chat(user, span_warning("There is no hair to shave!")) + return + if(human_target.hairstyle == "Bald" || human_target.hairstyle == "Balding Hair" || human_target.hairstyle == "Skinhead") + to_chat(user, span_warning("There is not enough hair left to shave!")) + return + + if(human_target == user) //shaving yourself + user.visible_message(span_notice("[user] starts to shave [user.p_their()] head with [src]."), \ + span_notice("You start to shave your head with [src]...")) + if(do_after(user, 5 SECONDS, target = user)) + user.visible_message(span_notice("[user] shaves [user.p_their()] head with [src]."), \ + span_notice("You finish shaving with [src].")) + shave(user, location) + return + else + user.visible_message(span_warning("[user] tries to shave [human_target]'s head with [src]!"), \ + span_notice("You start shaving [human_target]'s head...")) + if(do_after(user, 5 SECONDS, target = human_target)) + user.visible_message(span_warning("[user] shaves [human_target]'s head bald with [src]!"), \ + span_notice("You shave [human_target]'s head bald.")) + shave(human_target, location) + return + return ..() */ diff --git a/code/modules/antagonists/nightmare/nightmare_species.dm b/code/modules/antagonists/nightmare/nightmare_species.dm index fa8c0da16e6061..32d12cffc33f2e 100644 --- a/code/modules/antagonists/nightmare/nightmare_species.dm +++ b/code/modules/antagonists/nightmare/nightmare_species.dm @@ -7,7 +7,11 @@ examine_limb_id = SPECIES_SHADOW changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE no_equip_flags = ITEM_SLOT_MASK | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_ICLOTHING | ITEM_SLOT_SUITSTORE - species_traits = list(NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES) + species_traits = list( + NO_UNDERWEAR, + NO_DNA_COPY, + NOTRANSSTING, + ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index d5cd1d6b45b46b..83b1cd2f123814 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -109,6 +109,10 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /// will show the feature as selectable. var/relevant_external_organ = null + /// If the selected species has this head_flag by default, + /// will show the feature as selectable. + var/relevant_head_flag = null + /// Called on the saved input when retrieving. /// Also called by the value sent from the user through UI. Do not trust it. /// Input is the value inside the savefile, output is to tell other code diff --git a/code/modules/client/preferences/species_features/basic.dm b/code/modules/client/preferences/species_features/basic.dm index 257269070bcb9c..1af8211208d6c7 100644 --- a/code/modules/client/preferences/species_features/basic.dm +++ b/code/modules/client/preferences/species_features/basic.dm @@ -26,7 +26,7 @@ savefile_key = "eye_color" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - relevant_species_trait = EYECOLOR + relevant_head_flag = HEAD_EYECOLOR /datum/preference/color/eye_color/apply_to_human(mob/living/carbon/human/target, value) var/hetero = target.eye_color_heterochromatic @@ -59,7 +59,7 @@ category = PREFERENCE_CATEGORY_FEATURES main_feature_name = "Facial hair" should_generate_icons = TRUE - relevant_species_trait = FACEHAIR + relevant_head_flag = HEAD_FACIAL_HAIR /datum/preference/choiced/facial_hairstyle/init_possible_values() return generate_possible_values_for_sprite_accessories_on_head(GLOB.facial_hairstyles_list) @@ -79,7 +79,7 @@ savefile_key = "facial_hair_color" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES - relevant_species_trait = FACEHAIR + relevant_head_flag = HEAD_FACIAL_HAIR /datum/preference/color/facial_hair_color/apply_to_human(mob/living/carbon/human/target, value) target.facial_hair_color = value @@ -89,7 +89,7 @@ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_identifier = PREFERENCE_CHARACTER savefile_key = "facial_hair_gradient" - relevant_species_trait = FACEHAIR + relevant_head_flag = HEAD_FACIAL_HAIR /datum/preference/choiced/facial_hair_gradient/init_possible_values() return assoc_to_keys_features(GLOB.facial_hair_gradients_list) @@ -106,7 +106,7 @@ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_identifier = PREFERENCE_CHARACTER savefile_key = "facial_hair_gradient_color" - relevant_species_trait = FACEHAIR + relevant_head_flag = HEAD_FACIAL_HAIR /datum/preference/color/facial_hair_gradient/apply_to_human(mob/living/carbon/human/target, value) LAZYSETLEN(target.grad_color, GRADIENTS_LEN) @@ -122,7 +122,7 @@ savefile_key = "hair_color" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES - relevant_species_trait = HAIR + relevant_head_flag = HEAD_HAIR /datum/preference/color/hair_color/apply_to_human(mob/living/carbon/human/target, value) target.hair_color = value @@ -133,7 +133,7 @@ category = PREFERENCE_CATEGORY_FEATURES main_feature_name = "Hairstyle" should_generate_icons = TRUE - relevant_species_trait = HAIR + relevant_head_flag = HEAD_HAIR /datum/preference/choiced/hairstyle/init_possible_values() return generate_possible_values_for_sprite_accessories_on_head(GLOB.hairstyles_list) @@ -152,7 +152,7 @@ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_identifier = PREFERENCE_CHARACTER savefile_key = "hair_gradient" - relevant_species_trait = HAIR + relevant_head_flag = HEAD_HAIR /datum/preference/choiced/hair_gradient/init_possible_values() return assoc_to_keys_features(GLOB.hair_gradients_list) @@ -169,7 +169,7 @@ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_identifier = PREFERENCE_CHARACTER savefile_key = "hair_gradient_color" - relevant_species_trait = HAIR + relevant_head_flag = HEAD_HAIR /datum/preference/color/hair_gradient/apply_to_human(mob/living/carbon/human/target, value) LAZYSETLEN(target.grad_color, GRADIENTS_LEN) diff --git a/code/modules/clothing/head/wig.dm b/code/modules/clothing/head/wig.dm index 62c8f803a7a9a3..c71e5672c700b3 100644 --- a/code/modules/clothing/head/wig.dm +++ b/code/modules/clothing/head/wig.dm @@ -70,6 +70,10 @@ if((head.flags_inv & HIDEHAIR) && !istype(head, /obj/item/clothing/head/wig)) to_chat(user, span_warning("You can't get a good look at [target.p_their()] hair!")) return + var/obj/item/bodypart/head/noggin = target.get_bodypart(BODY_ZONE_HEAD) + if(!noggin) + to_chat(user, span_warning("[target.p_they(TRUE)] have no head!")) + return var/selected_hairstyle = null var/selected_hairstyle_color = null @@ -77,7 +81,7 @@ var/obj/item/clothing/head/wig/wig = target.head selected_hairstyle = wig.hairstyle selected_hairstyle_color = wig.color - else if((HAIR in target.dna.species.species_traits) && target.hairstyle != "Bald") + else if((noggin.head_flags & HEAD_HAIR) && target.hairstyle != "Bald") selected_hairstyle = target.hairstyle selected_hairstyle_color = "[target.hair_color]" diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 5169080146b0ae..9dd5ba707455b3 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -66,7 +66,7 @@ inhand_icon_state = "tapehat" dog_fashion = null worn_y_offset = 6 - body_parts_covered = HEAD|HAIR + body_parts_covered = HEAD //this used to also cover HAIR, but that was never valid code as HAIR is not actually a body_part define! flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR /obj/item/clothing/head/wizard/magus diff --git a/code/modules/explorer_drone/exploration_events/resource.dm b/code/modules/explorer_drone/exploration_events/resource.dm index d95981c6667f0c..3ed4ecc9b3cbe4 100644 --- a/code/modules/explorer_drone/exploration_events/resource.dm +++ b/code/modules/explorer_drone/exploration_events/resource.dm @@ -242,8 +242,8 @@ var/mob/living/carbon/human/head_species_source = new head_species_source.set_species(/datum/species/skeleton) head_species_source.real_name = "spaced locker victim" - var/obj/item/bodypart/head/skeleton_head = new - skeleton_head.update_limb(FALSE,head_species_source) + var/obj/item/bodypart/head/skeleton_head = head_species_source.get_bodypart(BODY_ZONE_HEAD) + skeleton_head.drop_limb(FALSE) qdel(head_species_source) drone.try_transfer(skeleton_head) diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index 7074ab474f38db..31ad5684de85bc 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -62,7 +62,7 @@ * Currently only used by mutantparts so don't worry about hair and stuff. * This is the source that this accessory will get its color from. Default is MUTCOLOR, but can also be HAIR, FACEHAIR, EYECOLOR and 0 if none. */ - var/color_src = MUTCOLORS + var/color_src = MUTANT_COLOR /// Decides if this sprite has an "inner" part, such as the fleshy parts on ears. var/hasinner = FALSE /// Is this part locked from roundstart selection? Used for parts that apply effects. @@ -1767,7 +1767,7 @@ name = "Cat" icon = 'icons/mob/species/human/cat_features.dmi' icon_state = "default" - color_src = HAIR + color_src = HAIR_COLOR /datum/sprite_accessory/tails/monkey name = "Monkey" @@ -1891,14 +1891,14 @@ name = "Cat" icon_state = "cat" hasinner = TRUE - color_src = HAIR + color_src = HAIR_COLOR /datum/sprite_accessory/ears/fox icon = 'icons/mob/species/human/fox_features.dmi' name = "Fox" icon_state = "fox" hasinner = TRUE - color_src = HAIR + color_src = HAIR_COLOR locked = TRUE /datum/sprite_accessory/wings/none @@ -2117,7 +2117,7 @@ /datum/sprite_accessory/caps icon = 'icons/mob/species/mush_cap.dmi' - color_src = HAIR + color_src = HAIR_COLOR em_block = TRUE /datum/sprite_accessory/caps/none diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a7a9789e7ac657..fd1c6321bae716 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -106,10 +106,11 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) if(ishuman(body)) var/mob/living/carbon/human/body_human = body - if(HAIR in body_human.dna.species.species_traits) + var/datum/species/human_species = body_human.dna.species + if(human_species.check_head_flags(HEAD_HAIR)) hairstyle = body_human.hairstyle hair_color = brighten_color(body_human.hair_color) - if(FACEHAIR in body_human.dna.species.species_traits) + if(human_species.check_head_flags(HEAD_FACIAL_HAIR)) facial_hairstyle = body_human.facial_hairstyle facial_hair_color = brighten_color(body_human.facial_hair_color) @@ -841,12 +842,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/species_type = client.prefs.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type - - if(HAIR in species.species_traits) + if(species.check_head_flags(HEAD_HAIR)) hairstyle = client.prefs.read_preference(/datum/preference/choiced/hairstyle) hair_color = brighten_color(client.prefs.read_preference(/datum/preference/color/hair_color)) - if(FACEHAIR in species.species_traits) + if(species.check_head_flags(HEAD_FACIAL_HAIR)) facial_hairstyle = client.prefs.read_preference(/datum/preference/choiced/facial_hairstyle) facial_hair_color = brighten_color(client.prefs.read_preference(/datum/preference/color/facial_hair_color)) diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 94ea1c9377a6a0..c0ebbe666849bb 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -614,27 +614,44 @@ /obj/item/bodypart/head/generate_icon_key() . = ..() - . += "-[facial_hairstyle]" - . += "-[facial_hair_color]" - if(facial_hair_gradient_style) - . += "-[facial_hair_gradient_style]" - if(hair_gradient_color) - . += "-[facial_hair_gradient_color]" + if(lip_style) + . += "-[lip_style]" + . += "-[lip_color]" + if(facial_hair_hidden) . += "-FACIAL_HAIR_HIDDEN" + else + . += "-[facial_hairstyle]" + . += "-[override_hair_color || fixed_hair_color || facial_hair_color]" + . += "-[facial_hair_alpha]" + if(facial_hair_gradient_style) + . += "-[facial_hair_gradient_style]" + . += "-[facial_hair_gradient_color]" + + if(show_missing_eyes) + . += "-SHOW_MISSING_EYES" if(show_debrained) . += "-SHOW_DEBRAINED" return . - . += "-[hair_style]" - . += "-[fixed_hair_color || override_hair_color || hair_color]" - if(hair_gradient_style) - . += "-[hair_gradient_style]" - if(hair_gradient_color) - . += "-[hair_gradient_color]" if(hair_hidden) . += "-HAIR_HIDDEN" + else + . += "-[hair_style]" + . += "-[override_hair_color || fixed_hair_color || hair_color]" + . += "-[hair_alpha]" + if(hair_gradient_style) + . += "-[hair_gradient_style]" + . += "-[hair_gradient_color]" + + return . +/obj/item/bodypart/head/generate_husk_key() + . = ..() + if(show_missing_eyes) + . += "-SHOW_MISSING_EYES" + if(show_debrained) + . += "-SHOW_DEBRAINED" return . GLOBAL_LIST_EMPTY(masked_leg_icons_cache) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/_species.dm similarity index 97% rename from code/modules/mob/living/carbon/human/species.dm rename to code/modules/mob/living/carbon/human/_species.dm index 65aaf6d25e26e3..824f463d265c47 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -32,6 +32,8 @@ GLOBAL_LIST_EMPTY(features_by_species) var/hair_color ///The alpha used by the hair. 255 is completely solid, 0 is invisible. var/hair_alpha = 255 + ///The alpha used by the facial hair. 255 is completely solid, 0 is invisible. + var/facial_hair_alpha = 255 ///This is used for children, it will determine their default limb ID for use of examine. See [/mob/living/carbon/human/proc/examine]. var/examine_limb_id @@ -185,9 +187,6 @@ GLOBAL_LIST_EMPTY(features_by_species) ///List of results you get from knife-butchering. null means you cant butcher it. Associated by resulting type - value of amount var/list/knife_butcher_results - ///List of visual overlays created by handle_body() - var/list/body_vis_overlays = list() - /// Should we preload this species's organs? var/preload = TRUE @@ -618,53 +617,25 @@ GLOBAL_LIST_EMPTY(features_by_species) return handle_mutant_bodyparts(species_human) var/list/standing = list() - var/obj/item/bodypart/head/noggin = species_human.get_bodypart(BODY_ZONE_HEAD) - - if(noggin && !(HAS_TRAIT(species_human, TRAIT_HUSK))) - // lipstick - if(species_human.lip_style && (LIPS in species_traits)) - var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[species_human.lip_style]", -BODY_LAYER) - lip_overlay.color = species_human.lip_color - noggin.worn_face_offset?.apply_offset(lip_overlay) - lip_overlay.pixel_y += height_offset - standing += lip_overlay - - // eyes - if(!(NOEYESPRITES in species_traits)) + if(!HAS_TRAIT(species_human, TRAIT_HUSK)) + var/obj/item/bodypart/head/noggin = species_human.get_bodypart(BODY_ZONE_HEAD) + if(noggin?.head_flags & HEAD_EYESPRITES) + // eyes (missing eye sprites get handled by the head itself, but sadly we have to do this stupid shit here, for now) var/obj/item/organ/internal/eyes/eye_organ = species_human.get_organ_slot(ORGAN_SLOT_EYES) - var/mutable_appearance/no_eyeslay - var/add_pixel_x = 0 - var/add_pixel_y = 0 - //cut any possible vis overlays - if(body_vis_overlays.len) - SSvis_overlays.remove_vis_overlay(species_human, body_vis_overlays) - var/list/feature_offset = noggin.worn_face_offset?.get_offset() - if(feature_offset) - add_pixel_x = feature_offset["x"] - add_pixel_y = feature_offset["y"] - add_pixel_y += height_offset - if(eye_organ) eye_organ.refresh(call_update = FALSE) for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human)) eye_overlay.pixel_y += height_offset standing += eye_overlay - else if (!(NOEYEHOLES in species_traits)) - no_eyeslay = mutable_appearance('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER) - no_eyeslay.pixel_x += add_pixel_x - no_eyeslay.pixel_y += add_pixel_y - standing += no_eyeslay - - // organic body markings - if(HAS_MARKINGS in species_traits) - var/obj/item/bodypart/chest/chest = species_human.get_bodypart(BODY_ZONE_CHEST) - var/obj/item/bodypart/arm/right/right_arm = species_human.get_bodypart(BODY_ZONE_R_ARM) - var/obj/item/bodypart/arm/left/left_arm = species_human.get_bodypart(BODY_ZONE_L_ARM) - var/obj/item/bodypart/leg/right/right_leg = species_human.get_bodypart(BODY_ZONE_R_LEG) - var/obj/item/bodypart/leg/left/left_leg = species_human.get_bodypart(BODY_ZONE_L_LEG) - var/datum/sprite_accessory/markings = GLOB.moth_markings_list[species_human.dna.features["moth_markings"]] - - if(!HAS_TRAIT(species_human, TRAIT_HUSK)) + + // organic body markings (oh my god this is terrible please rework this to be done on the limbs themselves i beg you) + if(HAS_MARKINGS in species_traits) + var/obj/item/bodypart/chest/chest = species_human.get_bodypart(BODY_ZONE_CHEST) + var/obj/item/bodypart/arm/right/right_arm = species_human.get_bodypart(BODY_ZONE_R_ARM) + var/obj/item/bodypart/arm/left/left_arm = species_human.get_bodypart(BODY_ZONE_L_ARM) + var/obj/item/bodypart/leg/right/right_leg = species_human.get_bodypart(BODY_ZONE_R_LEG) + var/obj/item/bodypart/leg/left/left_leg = species_human.get_bodypart(BODY_ZONE_L_LEG) + var/datum/sprite_accessory/markings = GLOB.moth_markings_list[species_human.dna.features["moth_markings"]] if(noggin && (IS_ORGANIC_LIMB(noggin))) var/mutable_appearance/markings_head_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_head", -BODY_LAYER) markings_head_overlay.pixel_y += height_offset @@ -809,21 +780,21 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!(HAS_TRAIT(source, TRAIT_HUSK))) if(!forced_colour) switch(accessory.color_src) - if(MUTCOLORS) + if(MUTANT_COLOR) if(fixed_mut_color) accessory_overlay.color = fixed_mut_color else accessory_overlay.color = source.dna.features["mcolor"] - if(HAIR) + if(HAIR_COLOR) if(hair_color == "mutcolor") accessory_overlay.color = source.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") accessory_overlay.color = fixed_mut_color else accessory_overlay.color = source.hair_color - if(FACEHAIR) + if(FACIAL_HAIR_COLOR) accessory_overlay.color = source.facial_hair_color - if(EYECOLOR) + if(EYE_COLOR) accessory_overlay.color = source.eye_color_left else accessory_overlay.color = forced_colour @@ -1125,7 +1096,8 @@ GLOBAL_LIST_EMPTY(features_by_species) source.domutcheck() if(time_since_irradiated > RAD_MOB_HAIRLOSS && SPT_PROB(RAD_MOB_HAIRLOSS_PROB, seconds_per_tick)) - if(!(source.hairstyle == "Bald") && (HAIR in species_traits)) + var/obj/item/bodypart/head/head = source.get_bodypart(BODY_ZONE_HEAD) + if(!(source.hairstyle == "Bald") && (head?.head_flags & HEAD_HAIR|HEAD_FACIAL_HAIR)) to_chat(source, span_danger("Your hair starts to fall out in clumps...")) addtimer(CALLBACK(src, PROC_REF(go_bald), source), 5 SECONDS) @@ -1856,7 +1828,8 @@ GLOBAL_LIST_EMPTY(features_by_species) if ( \ (preference.relevant_mutant_bodypart in mutant_bodyparts) \ || (preference.relevant_species_trait in species_traits) \ - || (preference.relevant_external_organ in external_organs) + || (preference.relevant_external_organ in external_organs) \ + || (preference.relevant_head_flag && check_head_flags(preference.relevant_head_flag)) \ ) features += preference.savefile_key @@ -2400,3 +2373,13 @@ GLOBAL_LIST_EMPTY(features_by_species) /// Creates body parts for the target completely from scratch based on the species /datum/species/proc/create_fresh_body(mob/living/carbon/target) target.create_bodyparts(bodypart_overrides) + +/** + * Checks if the species has a head with these head flags, by default. + * Admittedly, this is a very weird and seemingly redundant proc, but it + * gets used by some preferences (such as hair style) to determine whether + * or not they are accessible. + **/ +/datum/species/proc/check_head_flags(check_flags = NONE) + var/obj/item/bodypart/head/fake_head = bodypart_overrides[BODY_ZONE_HEAD] + return (initial(fake_head.head_flags) & check_flags) diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 33a17389903a8f..46b27e02f1ce42 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -930,40 +930,12 @@ mutant_styles: The mutant style - taur bodytype, STYLE_TESHARI, etc. // SKYRAT E var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) - if (!istype(my_head)) + if(!istype(my_head)) return my_head.update_limb(is_creating = update_limb_data) add_overlay(my_head.get_limb_icon()) - update_damage_overlays() - - if(my_head && !(HAS_TRAIT(src, TRAIT_HUSK))) - // lipstick - if(lip_style && (LIPS in dna.species.species_traits)) - var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[lip_style]", -BODY_LAYER) - lip_overlay.color = lip_color - my_head.worn_face_offset?.apply_offset(lip_overlay) - add_overlay(lip_overlay) - - // eyes - if(!(NOEYESPRITES in dna.species.species_traits)) - var/obj/item/organ/internal/eyes/parent_eyes = get_organ_slot(ORGAN_SLOT_EYES) - if(parent_eyes) - add_overlay(parent_eyes.generate_body_overlay(src)) - else - var/mutable_appearance/missing_eyes = mutable_appearance('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER) - my_head.worn_face_offset?.apply_offset(missing_eyes) - add_overlay(missing_eyes) - - //SKYRAT EDIT ADDITION - if (parent_eyes && parent_eyes.is_emissive) - var/mutable_appearance/emissive_appearance = emissive_appearance('icons/mob/species/human/human_face.dmi', parent_eyes ? parent_eyes.eye_icon_state : "eyes_missing", -BODY_LAYER) - emissive_appearance.appearance_flags &= ~RESET_TRANSFORM - my_head.worn_face_offset?.apply_offset(emissive_appearance) - add_overlay(emissive_appearance) - //SKYRAT EDIT END - update_worn_head() update_worn_mask() diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 8aa309a84ccf21..8796bc414936a6 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -3,7 +3,6 @@ id = SPECIES_ABDUCTOR sexes = FALSE species_traits = list( - NOEYESPRITES, NO_UNDERWEAR, ) inherent_traits = list( @@ -11,7 +10,6 @@ TRAIT_NOHUNGER, TRAIT_VIRUSIMMUNE, TRAIT_NOBLOOD, - TRAIT_NO_DEBRAIN_OVERLAY, TRAIT_CHUNKYFINGERS_IGNORE_BATON, ) mutanttongue = /obj/item/organ/internal/tongue/abductor diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 41828bdf1b4478..152d5609b45e83 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -23,7 +23,6 @@ TRAIT_RESISTHIGHPRESSURE, TRAIT_TOXIMMUNE, TRAIT_NOBLOOD, - TRAIT_NO_DEBRAIN_OVERLAY, ) inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID 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 dc628dfb08632e..68ef75a97dd90d 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -1,12 +1,7 @@ /datum/species/dullahan name = "Dullahan" id = SPECIES_DULLAHAN - species_traits = list( - EYECOLOR, - HAIR, - FACEHAIR, - LIPS, - ) + species_traits = list() inherent_traits = list( TRAIT_NOBREATH, TRAIT_NOHUNGER, diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 61883cb0f62fb9..3fe8f4965d8a4b 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -10,21 +10,10 @@ exotic_bloodtype = "LE" siemens_coeff = 0.5 //They thrive on energy payday_modifier = 0.75 - /* SKYRAT EDIT - ORIGINAL species_traits = list( DYNCOLORS, AGENDER, - NO_UNDERWEAR, - HAIR, - FACEHAIR, - ) - */ - // SKYRAT EDIT - LET THEM WEAR PANTIES - species_traits = list( - DYNCOLORS, - AGENDER, - HAIR, - FACEHAIR, + // NO_UNDERWEAR, // SKYRAT EDIT - LET THEM WEAR PANTIES ) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_cookie = /obj/item/food/energybar @@ -38,6 +27,7 @@ bodytemp_cold_damage_limit = (T20C - 10) // about 10c hair_color = "fixedmutcolor" hair_alpha = 140 + facial_hair_alpha = 140 bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/ethereal, diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index d1ee2f73152912..e19b9aeccc0771 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -2,11 +2,6 @@ name = "Flyperson" plural_form = "Flypeople" id = SPECIES_FLYPERSON - //SKYRAT EDIT - Flypeople deserve fancy hair - species_traits = list( - HAIR, - FACEHAIR - ) inherent_traits = list( TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_TACKLING_FRAIL_ATTACKER, diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 429c4430690ac1..f6c1c575b1c080 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -6,7 +6,6 @@ NO_DNA_COPY, NOTRANSSTING, NO_UNDERWEAR, - NOEYEHOLES, NOAUGMENTS, ) inherent_traits = list( diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 1cb700ed7d9ff2..33d845ce04c59f 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -1,12 +1,7 @@ /datum/species/human name = "\improper Human" id = SPECIES_HUMAN - species_traits = list( - EYECOLOR, - HAIR, - FACEHAIR, - LIPS, - ) + species_traits = list() inherent_traits = list( TRAIT_CAN_USE_FLIGHT_POTION, ) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index dc738dd888358e..1ef8b0267c08f3 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -12,7 +12,6 @@ id = SPECIES_JELLYPERSON species_traits = list( MUTCOLORS, - EYECOLOR, ) inherent_traits = list( TRAIT_TOXINLOVER, @@ -185,9 +184,12 @@ name = "\improper Slimeperson" plural_form = "Slimepeople" id = SPECIES_SLIMEPERSON - species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR) + species_traits = list( + MUTCOLORS, + ) hair_color = "mutcolor" hair_alpha = 150 + facial_hair_alpha = 150 changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT mutanteyes = /obj/item/organ/internal/eyes var/datum/action/innate/split_body/slime_split diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 84774d9a1def6f..1898edc6ab008c 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -5,8 +5,6 @@ id = SPECIES_LIZARD species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, ) inherent_traits = list( TRAIT_CAN_USE_FLIGHT_POTION, @@ -145,8 +143,6 @@ Lizard subspecies: ASHWALKERS mutantbrain = /obj/item/organ/internal/brain/primitive species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, ) inherent_traits = list( //TRAIT_LITERATE, diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 4ad0895d6c3446..f3080d4274ae85 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -14,15 +14,12 @@ knife_butcher_results = list(/obj/item/food/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1) species_traits = list( NO_UNDERWEAR, - LIPS, - NOEYESPRITES, NOBLOODOVERLAY, NOTRANSSTING, NOAUGMENTS, ) inherent_traits = list( TRAIT_GUN_NATURAL, - //TRAIT_LITERATE, TRAIT_VENTCRAWLER_NUDE, TRAIT_WEAK_SOUL, ) diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index f9ab8f29217afe..81780443870226 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -3,7 +3,6 @@ plural_form = "Mothmen" id = SPECIES_MOTH species_traits = list( - LIPS, HAS_MARKINGS, ) inherent_traits = list( diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 75fbbf8add2a54..455cecab0ac80b 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -10,7 +10,6 @@ species_traits = list( MUTCOLORS, - NOEYESPRITES, NO_UNDERWEAR, ) inherent_traits = list( @@ -28,7 +27,6 @@ mutanteyes = /obj/item/organ/internal/eyes/night_vision/mushroom mutantlungs = null use_skintones = FALSE - var/datum/martial_art/mushpunch/mush species_language_holder = /datum/language_holder/mushroom bodypart_overrides = list( @@ -39,6 +37,7 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/mushroom, BODY_ZONE_CHEST = /obj/item/bodypart/chest/mushroom, ) + var/datum/martial_art/mushpunch/mush /datum/species/mush/check_roundstart_eligible() return FALSE //hard locked out of roundstart on the order of design lead kor, this can be removed in the future when planetstation is here OR SOMETHING but right now we have a problem with races. diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 6d6cb9f985c6ab..6a82ef96a4095c 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -14,7 +14,6 @@ TRAIT_RADIMMUNE, TRAIT_RESISTCOLD, TRAIT_NOBLOOD, - TRAIT_NO_DEBRAIN_OVERLAY, ) inherent_biotypes = MOB_HUMANOID|MOB_MINERAL diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 53f483bc8ad6b7..bc66e53dc8705a 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -5,7 +5,6 @@ id = SPECIES_PODPERSON species_traits = list( MUTCOLORS, - EYECOLOR, ) inherent_traits = list( TRAIT_PLANT_SAFE, diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 07cb138d87268e..dc960f66aa25e5 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -5,9 +5,7 @@ id = SPECIES_SHADOW sexes = 0 meat = /obj/item/food/meat/slab/human/mutant/shadow - species_traits = list( - NOEYESPRITES, - ) + species_traits = list() inherent_traits = list( TRAIT_NOBREATH, TRAIT_RADIMMUNE, diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index 73a41863145540..7e63318de3bb7c 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -6,7 +6,6 @@ meat = /obj/item/food/meat/slab/human/mutant/skeleton species_traits = list( NOTRANSSTING, - NOEYESPRITES, NO_DNA_COPY, NO_UNDERWEAR, ) @@ -28,7 +27,6 @@ TRAIT_TOXIMMUNE, TRAIT_XENO_IMMUNE, TRAIT_NOBLOOD, - TRAIT_NO_DEBRAIN_OVERLAY, ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/internal/tongue/bone diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index 35b24d42b97640..d1ce5557d29976 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -1,18 +1,9 @@ /datum/species/snail name = "Snailperson" id = SPECIES_SNAIL - /*SKYRAT EDIT - ORIGINAL species_traits = list( MUTCOLORS, - NO_UNDERWEAR, - ) - */ - //SKYRAT EDIT - Snails deserve hair, and get to wear underwear, and have eye colour - species_traits = list( - MUTCOLORS, - EYECOLOR, - HAIR, - FACEHAIR + // NO_UNDERWEAR, //SKYRAT EDIT - Snails deserve to wear underwear ) inherent_traits = list( TRAIT_NO_SLIP_ALL, diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 6dd778affc76cb..34c1ddd41ad135 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -8,10 +8,6 @@ name = "Vampire" id = SPECIES_VAMPIRE species_traits = list( - EYECOLOR, - HAIR, - FACEHAIR, - LIPS, DRINKSBLOOD, BLOOD_CLANS, ) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index dd213a89ed542a..90c08cd3b7a437 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -568,8 +568,9 @@ affected_human.facial_hairstyle = "Shaved" affected_human.facial_hair_color = "#000000" affected_human.hair_color = "#000000" - if(!(HAIR in affected_human.dna.species.species_traits)) //No hair? No problem! - affected_human.dna.species.species_traits += HAIR + var/obj/item/bodypart/head/head = affected_human.get_bodypart(BODY_ZONE_HEAD) + if(head) + head.head_flags |= HEAD_HAIR //No hair? No problem! if(affected_human.dna.species.use_skintones) affected_human.skin_tone = "orange" else if(MUTCOLORS in affected_human.dna.species.species_traits) //Aliens with custom colors simply get turned orange @@ -2135,12 +2136,10 @@ var/mob/living/carbon/human/human_mob = affected_mob if(creation_purity == 1 && human_mob.has_quirk(/datum/quirk/item_quirk/bald)) human_mob.remove_quirk(/datum/quirk/item_quirk/bald) - var/datum/species/species_datum = human_mob.dna?.species - if(!species_datum) + var/obj/item/bodypart/head/head = human_mob.get_bodypart(BODY_ZONE_HEAD) + if(!head || (head.head_flags & HEAD_HAIR)) return - if(species_datum.species_traits.Find(HAIR)) - return - species_datum.species_traits |= HAIR + head.head_flags |= HEAD_HAIR var/message if(HAS_TRAIT(affected_mob, TRAIT_BALD)) message = span_warning("You feel your scalp mutate, but you are still hopelessly bald.") diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index 537d163161d077..474634bb71bee9 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -36,28 +36,16 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE bodypart_traits = list(TRAIT_DISFIGURED, TRAIT_BALD, TRAIT_SHAVED) + head_flags = HEAD_LIPS|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/head/psyker/try_attach_limb(mob/living/carbon/new_head_owner, special, abort) . = ..() if(!.) return new_head_owner.become_blind(limb_id) - if(!new_head_owner.dna?.species) - return - - new_head_owner.dna.species.species_traits |= NOEYESPRITES //MAKE VISUALS TIED TO BODYPARTS ARGHH - new_head_owner.update_body() /obj/item/bodypart/head/psyker/drop_limb(special, dismembered) owner.cure_blind(limb_id) - if(!owner.dna?.species) - return ..() - - if(initial(owner.dna.species.species_traits) & NOEYESPRITES) - return ..() - - owner.dna.species.species_traits &= ~NOEYESPRITES - owner.update_body() return ..() /// flavorful variant of psykerizing that deals damage and sends messages before calling psykerize() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index faf6ed60945389..fb35379efee1f3 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -111,6 +111,10 @@ var/px_x = 0 var/px_y = 0 + /** + * A copy of the original owner's species datum species_traits list (very hacky) + * It sucks that we have to do this, but due to MUTCOLORS and others, we have to. For now. + */ var/species_flags_list = list() ///the type of damage overlay (if any) to use when this bodypart is bruised/burned. var/dmg_overlay_type = "human" @@ -843,7 +847,7 @@ // No, xenos don't actually use bodyparts. Don't ask. var/mob/living/carbon/human/human_owner = owner var/datum/species/owner_species = human_owner.dna.species - species_flags_list = owner_species.species_traits + species_flags_list = owner_species.species_traits.Copy() limb_gender = (human_owner.physique == MALE) ? "m" : "f" if(owner_species.use_skintones) @@ -974,8 +978,9 @@ . += aux_em_block //EMISSIVE CODE END - //Ok so legs are a bit goofy in regards to layering, and we will need two images instead of one to fix that - if((body_zone == BODY_ZONE_R_LEG) || (body_zone == BODY_ZONE_L_LEG)) + //No need to handle leg layering if dropped, we only face south anyways + if(!dropped && ((body_zone == BODY_ZONE_R_LEG) || (body_zone == BODY_ZONE_L_LEG))) + //Legs are a bit goofy in regards to layering, and we will need two images instead of one to fix that var/obj/item/bodypart/leg/leg_source = src for(var/image/limb_image in .) //remove the old, unmasked image diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index a648d686ebcd3a..d01143615955d3 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -91,7 +91,7 @@ SEND_SIGNAL(owner, COMSIG_CARBON_REMOVE_LIMB, src, dismembered) SEND_SIGNAL(src, COMSIG_BODYPART_REMOVED, owner, dismembered) - update_limb(TRUE) + update_limb(dropping_limb = TRUE) //limb is out and about, it can't really be considered an implant bodypart_flags &= ~BODYPART_IMPLANTED owner.remove_bodypart(src) @@ -372,7 +372,7 @@ SEND_SIGNAL(new_limb_owner, COMSIG_CARBON_POST_ATTACH_LIMB, src, special) return TRUE -/obj/item/bodypart/head/try_attach_limb(mob/living/carbon/new_head_owner, special = FALSE, abort = FALSE) +/obj/item/bodypart/head/try_attach_limb(mob/living/carbon/new_head_owner, special = FALSE) // These are stored before calling super. This is so that if the head is from a different body, it persists its appearance. var/real_name = src.real_name @@ -415,6 +415,8 @@ sexy_chad.grad_color[GRADIENT_HAIR_KEY] = hair_gradient_color sexy_chad.grad_style[GRADIENT_FACIAL_HAIR_KEY] = facial_hair_gradient_style sexy_chad.grad_color[GRADIENT_FACIAL_HAIR_KEY] = facial_hair_gradient_color + sexy_chad.lip_style = lip_style + sexy_chad.lip_color = lip_color new_head_owner.updatehealth() new_head_owner.update_body() diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 77e81cfda81804..501a31abf160ea 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -36,36 +36,55 @@ var/show_organs_on_examine = TRUE //Limb appearance info: - var/real_name = "" //Replacement name - ///Hair color source - var/hair_color_source = null - ///Hair colour and style - var/hair_color = "#000000" - ///An override color that can be cleared later. - var/override_hair_color = null - ///An override that cannot be cleared under any circumstances - var/fixed_hair_color = null + /// Replacement name + var/real_name = "" + /// Flags related to appearance, such as hair, lips, etc + var/head_flags = HEAD_ALL_FEATURES + /// Hair style var/hair_style = "Bald" + /// Hair color source + var/hair_color_source = null + /// Hair colour and style + var/hair_color = "#000000" + /// Hair alpha var/hair_alpha = 255 + /// Hair gradient style, if any var/hair_gradient_style = null + /// Hair gradient color, if any var/hair_gradient_color = null - //Facial hair colour and style - var/facial_hair_color = "#000000" + /// Is the hair currently hidden by something? + var/hair_hidden = FALSE + + ///Facial hair style var/facial_hairstyle = "Shaved" + ///Facial hair color + var/facial_hair_color = "#000000" + ///Facial hair alpha + var/facial_hair_alpha = 255 + ///Facial hair gradient style, if any var/facial_hair_gradient_style = null + ///Facial hair gradient color, if any var/facial_hair_gradient_color = null - ///Is the hair currently hidden by something? - var/hair_hidden ///Is the facial hair currently hidden by something? - var/facial_hair_hidden - ///Draw this head as "debrained" - VAR_PROTECTED/show_debrained = FALSE - + var/facial_hair_hidden = FALSE + /// An override color that can be cleared later, affects both hair and facial hair + var/override_hair_color = null + /// An override that cannot be cleared under any circumstances, affects both hair and facial hair + var/fixed_hair_color = null + ///Type of lipstick being used, basically var/lip_style + ///Lipstick color var/lip_color = "white" + ///Current lipstick trait, if any (such as TRAIT_KISS_OF_DEATH) + var/stored_lipstick_trait + + ///Draw this head as "debrained" + VAR_PROTECTED/show_debrained = FALSE + ///Draw this head as missing eyes + VAR_PROTECTED/show_missing_eyes = FALSE /// Offset to apply to equipment worn on the ears var/datum/worn_feature_offset/worn_ears_offset @@ -78,7 +97,8 @@ /// Offset to apply to overlays placed on the face var/datum/worn_feature_offset/worn_face_offset - var/stored_lipstick_trait + ///The image for lipstick + var/mutable_appearance/lip_overlay ///The image for hair var/mutable_appearance/hair_overlay ///The image for hair gradient @@ -196,82 +216,111 @@ facial_hairstyle = "Shaved" lip_style = null stored_lipstick_trait = null - update_hair_and_lips() + update_hair_and_lips(dropping_limb, is_creating) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /obj/item/bodypart/head/get_limb_icon(dropped, draw_external_organs) - cut_overlays() . = ..() - if(dropped) //certain overlays only appear when the limb is being detached from its owner. - - if(IS_ORGANIC_LIMB(src)) //having a robotic head hides certain features. - //facial hair - if(facial_hairstyle && (FACEHAIR in species_flags_list)) - var/datum/sprite_accessory/sprite = GLOB.facial_hairstyles_list[facial_hairstyle] - if(sprite) - var/image/facial_overlay = image(sprite.icon, "[sprite.icon_state]", -HAIR_LAYER, SOUTH) - facial_overlay.color = facial_hair_color - facial_overlay.alpha = hair_alpha - . += facial_overlay - - if(!eyes && !(NOEYEHOLES in species_flags_list) && !(NOEYESPRITES in species_flags_list)) - var/image/no_eyes = image('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER, SOUTH) - worn_glasses_offset?.apply_offset(no_eyes) - . += no_eyes - - //Applies the debrained overlay if there is no brain - if(!brain) - . += get_debrain_overlay(can_rotate = FALSE) - else - var/datum/sprite_accessory/sprite2 = GLOB.hairstyles_list[hair_style] - if(sprite2 && (HAIR in species_flags_list)) - var/image/hair_overlay = image(sprite2.icon, "[sprite2.icon_state]", -HAIR_LAYER, SOUTH) - hair_overlay.color = hair_color - hair_overlay.alpha = hair_alpha - // SKYRAT ADD - Hair offset - if(LAZYFIND(owner?.dna?.species?.offset_features, OFFSET_HAIR)) - hair_overlay.pixel_x = owner.dna.species.offset_features[OFFSET_HAIR][INDEX_X] - hair_overlay.pixel_y = owner.dna.species.offset_features[OFFSET_HAIR][INDEX_Y] - // SKYRAT ADD END - . += hair_overlay - + // logic for the overlays changes when dropped (ugh, rework this later if possible) + if(dropped) + //BAHHHH don't do any of this if we are husked + if(is_husked) + return . // lipstick - if(lip_style) + if(lip_style && (head_flags & HEAD_LIPS)) var/image/lips_overlay = image('icons/mob/species/human/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH) lips_overlay.color = lip_color + worn_face_offset?.apply_offset(lips_overlay) . += lips_overlay + //facial hair + if(facial_hairstyle && (head_flags & HEAD_FACIAL_HAIR)) + var/datum/sprite_accessory/facial_hair_sprite = GLOB.facial_hairstyles_list[facial_hairstyle] + if(facial_hair_sprite) + var/image/facial_overlay = image(facial_hair_sprite.icon, "[facial_hair_sprite.icon_state]", -HAIR_LAYER, SOUTH) + facial_overlay.color = facial_hair_color + facial_overlay.alpha = hair_alpha + . += facial_overlay + + //Applies the debrained overlay if there is no brain + if(!brain && (head_flags & HEAD_DEBRAIN)) + . += get_debrain_overlay(can_rotate = FALSE) + //Otherwise, applies hair + else if(hair_style && (head_flags & HEAD_HAIR)) + var/datum/sprite_accessory/hair_sprite = GLOB.hairstyles_list[hair_style] + if(hair_sprite && (head_flags & HEAD_HAIR)) + var/image/hair_overlay = image(hair_sprite.icon, "[hair_sprite.icon_state]", -HAIR_LAYER, SOUTH) + hair_overlay.color = hair_color + hair_overlay.alpha = hair_alpha + // SKYRAT ADD - Hair offset + if(LAZYFIND(owner?.dna?.species?.offset_features, OFFSET_HAIR)) + hair_overlay.pixel_x = owner.dna.species.offset_features[OFFSET_HAIR][INDEX_X] + hair_overlay.pixel_y = owner.dna.species.offset_features[OFFSET_HAIR][INDEX_Y] + // SKYRAT ADD END + . += hair_overlay + // eyes - if(eyes && eyes.eye_icon_state && !(NOEYESPRITES in species_flags_list)) // This is a bit of copy/paste code from eyes.dm:generate_body_overlay + // This is a bit of copy/paste code from eyes.dm:generate_body_overlay + if(eyes?.eye_icon_state && (head_flags & HEAD_EYESPRITES)) var/image/eye_left = image('icons/mob/species/human/human_face.dmi', "[eyes.eye_icon_state]_l", -BODY_LAYER, SOUTH) var/image/eye_right = image('icons/mob/species/human/human_face.dmi', "[eyes.eye_icon_state]_r", -BODY_LAYER, SOUTH) - if(eyes.eye_color_left) - eye_left.color = eyes.eye_color_left - if(eyes.eye_color_right) - eye_right.color = eyes.eye_color_right - - // SKYRAT EDIT START - Customization (darn synths I swear) + if(head_flags & HEAD_EYECOLOR) + if(eyes.eye_color_left) + eye_left.color = eyes.eye_color_left + if(eyes.eye_color_right) + eye_right.color = eyes.eye_color_right + if(eyes.overlay_ignore_lighting) + eye_left.overlays += emissive_appearance(eye_left.icon, eye_left.icon_state, src, alpha = eye_left.alpha) + eye_right.overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, src, alpha = eye_right.alpha) + if(worn_face_offset) + worn_face_offset.apply_offset(eye_left) + worn_face_offset.apply_offset(eye_right) + + // SKYRAT EDIT ADDITION START - Customization (Emissives and synths) if(eyes.eye_icon_state == "None") eye_left.alpha = 0 eye_right.alpha = 0 + + if (eyes.is_emissive) // Because it was done all weird up there. + var/mutable_appearance/emissive_left = emissive_appearance(eye_left.icon, eye_left.icon_state, src, -BODY_LAYER, eye_left.alpha) + var/mutable_appearance/emissive_right = emissive_appearance(eye_right.icon, eye_right.icon_state, src, -BODY_LAYER, eye_right.alpha) + + emissive_left.appearance_flags &= ~RESET_TRANSFORM + emissive_right.appearance_flags &= ~RESET_TRANSFORM + + if(worn_face_offset) + worn_face_offset.apply_offset(emissive_right) + worn_face_offset.apply_offset(emissive_left) + + eye_left.overlays += emissive_left + eye_right.overlays += emissive_right + // SKYRAT EDIT END . += eye_left . += eye_right + else if(!eyes && (head_flags & HEAD_EYEHOLES)) + var/image/no_eyes = image('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER, SOUTH) + worn_face_offset?.apply_offset(no_eyes) + . += no_eyes else - if(!facial_hair_hidden && facial_overlay && (FACEHAIR in species_flags_list)) + if(lip_overlay && (head_flags & HEAD_LIPS)) + worn_face_offset?.apply_offset(lip_overlay) + . += lip_overlay + + if(!facial_hair_hidden && facial_overlay && (head_flags & HEAD_FACIAL_HAIR)) facial_overlay.alpha = hair_alpha . += facial_overlay if(facial_gradient_overlay) . += facial_gradient_overlay - if(show_debrained) + if(show_debrained && (head_flags & HEAD_DEBRAIN)) . += get_debrain_overlay(can_rotate = TRUE) - else if(!hair_hidden && hair_overlay && (HAIR in species_flags_list)) + else if(!hair_hidden && hair_overlay && (head_flags & HEAD_HAIR)) hair_overlay.alpha = hair_alpha // SKYRAT ADD - Hair offset if(LAZYFIND(owner?.dna?.species?.offset_features, OFFSET_HAIR)) @@ -287,6 +336,13 @@ // SKYRAT ADD END . += hair_gradient_overlay + if(show_missing_eyes && (head_flags && HEAD_EYEHOLES)) + var/mutable_appearance/no_eyes = mutable_appearance('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER) + worn_face_offset?.apply_offset(no_eyes) + . += no_eyes + + return + /// Returns an appropriate debrained icon state /obj/item/bodypart/head/proc/get_debrain_overlay(can_rotate = TRUE) var/debrain_icon = 'icons/mob/species/human/human_face.dmi' @@ -300,11 +356,9 @@ else if(bodytype & BODYTYPE_GOLEM) debrain_icon = 'icons/mob/species/golems.dmi' debrain_icon_state = "debrained" - else if((TRAIT_NOBLOOD in species_flags_list)) - return null var/image/debrain_overlay - if (can_rotate) + if(can_rotate) debrain_overlay = mutable_appearance(debrain_icon, debrain_icon_state, HAIR_LAYER) else debrain_overlay = image(debrain_icon, debrain_icon_state, -HAIR_LAYER, SOUTH) @@ -358,6 +412,7 @@ should_draw_greyscale = FALSE dmg_overlay_type = SPECIES_MONKEY is_dimorphic = FALSE + head_flags = HEAD_LIPS|HEAD_DEBRAIN /obj/item/bodypart/head/alien icon = 'icons/mob/species/alien/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/hair.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm similarity index 69% rename from code/modules/surgery/bodyparts/hair.dm rename to code/modules/surgery/bodyparts/head_hair_and_lips.dm index 8b76bc2e12ba2e..760c7102ba8774 100644 --- a/code/modules/surgery/bodyparts/hair.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -1,66 +1,63 @@ -#define SET_OVERLAY_VALUE(X,Y,Z) if(X) X.Y = Z +#define SET_OVERLAY_VALUE(overlay,variable,value) if(overlay) overlay.variable = value -///Part of `update_limb()`, this proc does what the name implies. -/obj/item/bodypart/head/proc/update_hair_and_lips() +/// Part of `update_limb()`, this proc does what the name implies. +/obj/item/bodypart/head/proc/update_hair_and_lips(dropping_limb, is_creating) + // THIS PROC DOES NOT WORK FOR DROPPED HEADS. YET. + if(!owner) + return var/mob/living/carbon/human/human_head_owner = owner var/datum/species/owner_species = human_head_owner.dna.species - if(human_head_owner.lip_style && (LIPS in owner_species.species_traits)) - lip_style = human_head_owner.lip_style - lip_color = human_head_owner.lip_color - else - lip_style = null - lip_color = "white" - - ///FACIAL HAIR CHECKS START - //we check if our hat or helmet hides our facial hair. + //HIDDEN CHECKS START + hair_hidden = FALSE facial_hair_hidden = FALSE if(human_head_owner.head) var/obj/item/hat = human_head_owner.head + if(hat.flags_inv & HIDEHAIR) + hair_hidden = TRUE if(hat.flags_inv & HIDEFACIALHAIR) facial_hair_hidden = TRUE if(human_head_owner.wear_mask) var/obj/item/mask = human_head_owner.wear_mask + if(mask.flags_inv & HIDEHAIR) + hair_hidden = TRUE if(mask.flags_inv & HIDEFACIALHAIR) facial_hair_hidden = TRUE - ///FACIAL HAIR CHECKS END - - ///HAIR CHECKS START - hair_hidden = FALSE - if(human_head_owner.head) - var/obj/item/hat = human_head_owner.head - if(hat.flags_inv & HIDEHAIR) - hair_hidden = TRUE if(human_head_owner.w_uniform) var/obj/item/item_uniform = human_head_owner.w_uniform if(item_uniform.flags_inv & HIDEHAIR) hair_hidden = TRUE - - if(human_head_owner.wear_mask) - var/obj/item/mask = human_head_owner.wear_mask - if(mask.flags_inv & HIDEHAIR) - hair_hidden = TRUE - ///HAIR CHECKS END - //invisibility stuff - if(HAS_TRAIT(human_head_owner, TRAIT_INVISIBLE_MAN)) + if(item_uniform.flags_inv & HIDEFACIALHAIR) + facial_hair_hidden = TRUE + //invisibility and husk stuff + if(HAS_TRAIT(human_head_owner, TRAIT_INVISIBLE_MAN) || HAS_TRAIT(human_head_owner, TRAIT_HUSK)) hair_hidden = TRUE facial_hair_hidden = TRUE + //HIDDEN CHECKS END - if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) + if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && (head_flags & HEAD_DEBRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) show_debrained = TRUE else show_debrained = FALSE + if(!owner.get_organ_slot(ORGAN_SLOT_EYES) && (head_flags & HEAD_EYEHOLES)) + show_missing_eyes = TRUE + else + show_missing_eyes = FALSE + var/datum/sprite_accessory/sprite_accessory + lip_overlay = null facial_overlay = null facial_gradient_overlay = null hair_overlay = null hair_gradient_overlay = null - hair_alpha = human_head_owner.hair_alpha ? human_head_owner.hair_alpha : owner_species.hair_alpha // SKYRAT EDIT - Customization - Hair alpha //hair_alpha = owner_species.hair_alpha // ORIGINAL + lip_style = human_head_owner.lip_style + lip_color = human_head_owner.lip_color + hair_alpha = human_head_owner.hair_alpha ? human_head_owner.hair_alpha : owner_species.hair_alpha // SKYRAT EDIT - Customization - Hair alpha - ORIGINAL: hair_alpha = owner_species.hair_alpha hair_color = human_head_owner.hair_color facial_hair_color = human_head_owner.facial_hair_color fixed_hair_color = owner_species.fixed_mut_color //Can be null @@ -69,31 +66,38 @@ var/atom/location = loc || owner || src - if(facial_hairstyle && !facial_hair_hidden && (FACEHAIR in species_flags_list)) + if(!facial_hair_hidden && lip_style && (head_flags & HEAD_LIPS)) + lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[lip_style]", -BODY_LAYER) + lip_overlay.color = lip_color + + if(!facial_hair_hidden && facial_hairstyle && (head_flags & HEAD_FACIAL_HAIR)) sprite_accessory = GLOB.facial_hairstyles_list[facial_hairstyle] if(sprite_accessory) - //Create the overlay + //Overlay facial_overlay = mutable_appearance(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER) - facial_overlay.overlays += emissive_blocker(facial_overlay.icon, facial_overlay.icon_state, location, alpha = hair_alpha) + facial_overlay.alpha = facial_hair_alpha //Gradients facial_hair_gradient_style = LAZYACCESS(human_head_owner.grad_style, GRADIENT_FACIAL_HAIR_KEY) if(facial_hair_gradient_style) facial_hair_gradient_color = LAZYACCESS(human_head_owner.grad_color, GRADIENT_FACIAL_HAIR_KEY) facial_gradient_overlay = make_gradient_overlay(sprite_accessory.icon, sprite_accessory.icon_state, HAIR_LAYER, GLOB.facial_hair_gradients_list[facial_hair_gradient_style], facial_hair_gradient_color) + //Emissive + facial_overlay.overlays += emissive_blocker(facial_overlay.icon, facial_overlay.icon_state, location, alpha = facial_hair_alpha) - facial_overlay.overlays += emissive_blocker(sprite_accessory.icon, sprite_accessory.icon_state, location, alpha = hair_alpha) - - if(!hair_hidden && !show_debrained && (HAIR in species_flags_list)) + if(!show_debrained && !hair_hidden && hair_style && (head_flags & HEAD_HAIR)) sprite_accessory = GLOB.hairstyles_list[hair_style] if(sprite_accessory) + //Overlay hair_overlay = mutable_appearance(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER) - hair_overlay.overlays += emissive_blocker(hair_overlay.icon, hair_overlay.icon_state, location, alpha = hair_alpha) + hair_overlay.alpha = hair_alpha + //Gradients hair_gradient_style = LAZYACCESS(human_head_owner.grad_style, GRADIENT_HAIR_KEY) if(hair_gradient_style) hair_gradient_color = LAZYACCESS(human_head_owner.grad_color, GRADIENT_HAIR_KEY) hair_gradient_overlay = make_gradient_overlay(sprite_accessory.icon, sprite_accessory.icon_state, HAIR_LAYER, GLOB.hair_gradients_list[hair_gradient_style], hair_gradient_color) + //Emissive + hair_overlay.overlays += emissive_blocker(hair_overlay.icon, hair_overlay.icon_state, location, alpha = hair_alpha) - //CREATION-ONLY END //HAIR COLOR START if(!override_hair_color) if(hair_color_source) diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 18ebc4a96e364f..96a67e848d4cc1 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -166,7 +166,7 @@ if(BODY_ZONE_CHEST) new_bodypart = new /obj/item/bodypart/chest/alien() if(new_bodypart) - new_bodypart.update_limb(src) + new_bodypart.update_limb(is_creating = TRUE) diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm index 7e52016748af11..7328b3b85b8f54 100644 --- a/code/modules/surgery/bodyparts/robot_bodyparts.dm +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -301,6 +301,8 @@ damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) + head_flags = HEAD_EYESPRITES + var/obj/item/assembly/flash/handheld/flash1 = null var/obj/item/assembly/flash/handheld/flash2 = null diff --git a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm index 076d4f684a1aee..a41f06a0e171ec 100644 --- a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm @@ -7,6 +7,7 @@ unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' brute_modifier = 1.25 //ethereal are weak to brute damage + head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/head/ethereal/update_limb(dropping_limb, is_creating) . = ..() diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index e6af6b5e4b3e01..5138b19aec44a1 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -2,6 +2,7 @@ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' limb_id = SPECIES_LIZARD is_dimorphic = FALSE + head_flags = HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/chest/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index baad134f6c89d7..d58b29fd6a8539 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -4,6 +4,7 @@ limb_id = SPECIES_SNAIL is_dimorphic = FALSE burn_modifier = 2 + head_flags = HEAD_EYESPRITES|HEAD_DEBRAIN /obj/item/bodypart/chest/snail biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! @@ -49,6 +50,7 @@ limb_id = SPECIES_ABDUCTOR is_dimorphic = FALSE should_draw_greyscale = FALSE + head_flags = NONE /obj/item/bodypart/chest/abductor biological_state = BIO_INORGANIC @@ -85,6 +87,7 @@ is_dimorphic = TRUE dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage + head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/jelly biological_state = BIO_INORGANIC @@ -122,6 +125,7 @@ biological_state = BIO_INORGANIC limb_id = SPECIES_SLIMEPERSON is_dimorphic = FALSE + head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/slime biological_state = BIO_INORGANIC @@ -149,6 +153,7 @@ biological_state = BIO_INORGANIC limb_id = SPECIES_LUMINESCENT is_dimorphic = TRUE + head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/luminescent biological_state = BIO_INORGANIC @@ -176,6 +181,7 @@ limb_id = SPECIES_ZOMBIE is_dimorphic = FALSE should_draw_greyscale = FALSE + head_flags = HEAD_EYESPRITES|HEAD_DEBRAIN /obj/item/bodypart/chest/zombie limb_id = SPECIES_ZOMBIE @@ -203,6 +209,7 @@ limb_id = SPECIES_PODPERSON is_dimorphic = TRUE burn_modifier = 1.25 + head_flags = HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/chest/pod limb_id = SPECIES_PODPERSON @@ -238,6 +245,7 @@ limb_id = SPECIES_FLYPERSON is_dimorphic = FALSE should_draw_greyscale = FALSE + head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN // SKYRAT EDIT - Flies deserve hair - ORIGINAL: head_flags = HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/chest/fly limb_id = SPECIES_FLYPERSON @@ -267,6 +275,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE burn_modifier = 1.5 + head_flags = NONE /obj/item/bodypart/chest/shadow biological_state = BIO_INORGANIC @@ -312,6 +321,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE dmg_overlay_type = null + head_flags = NONE /obj/item/bodypart/chest/skeleton biological_state = BIO_BONE @@ -349,6 +359,7 @@ limb_id = SPECIES_MUSHROOM is_dimorphic = TRUE burn_modifier = 1.25 + head_flags = NONE /obj/item/bodypart/chest/mushroom limb_id = SPECIES_MUSHROOM @@ -395,6 +406,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE dmg_overlay_type = null + head_flags = NONE /obj/item/bodypart/head/golem/Initialize(mapload) worn_ears_offset = new( diff --git a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm index 00bd790bcca6c1..007e0ca66d4a13 100644 --- a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm @@ -6,6 +6,7 @@ limb_id = SPECIES_MOTH is_dimorphic = FALSE should_draw_greyscale = FALSE + head_flags = HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN //what the fuck, moths have lips? /obj/item/bodypart/chest/moth icon = 'icons/mob/species/moth/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm index b77c89da323f7f..d9bbee1ea03e66 100644 --- a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm @@ -9,6 +9,7 @@ dmg_overlay_type = null brute_modifier = 1.5 //Plasmemes are weak burn_modifier = 1.5 //Plasmemes are weak + head_flags = HEAD_EYESPRITES /obj/item/bodypart/chest/plasmaman icon = 'icons/mob/species/plasmaman/bodyparts.dmi' diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 261aaf6751d2f2..03473c48553c64 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -56,7 +56,7 @@ return eye_recipient.cure_blind(NO_EYES) apply_damaged_eye_effects() - refresh(eye_recipient, inserting = TRUE) + refresh(eye_recipient, inserting = TRUE, call_update = TRUE) /// Refreshes the visuals of the eyes /// If call_update is TRUE, we also will call update_body @@ -90,7 +90,7 @@ // SKYRAT EDIT END if(call_update) - affected_human.dna?.species?.handle_body(affected_human) //updates eye icon + affected_human.update_body() /obj/item/organ/internal/eyes/Remove(mob/living/carbon/eye_owner, special = FALSE) . = ..() @@ -100,9 +100,9 @@ human_owner.eye_color_left = old_eye_color_left if(initial(eye_color_right)) human_owner.eye_color_right = old_eye_color_right - human_owner.update_body() if(native_fov) eye_owner.remove_fov_trait(type) + human_owner.update_body() // Cure blindness from eye damage eye_owner.cure_blind(EYE_DAMAGE) @@ -128,15 +128,11 @@ if(isnull(eye_icon_state)) return list() + var/eye_icon = parent.dna?.species.eyes_icon || 'icons/mob/species/human/human_face.dmi' // SKYRAT EDIT ADDITION var/mutable_appearance/eye_left = mutable_appearance(eye_icon, "[eye_icon_state]_l", -eyes_layer) // SKYRAT EDIT CHANGE - Customization - ORIGINAL: var/mutable_appearance/eye_left = mutable_appearance('icons/mob/human_face.dmi', "[eye_icon_state]_l", -BODY_LAYER) var/mutable_appearance/eye_right = mutable_appearance(eye_icon, "[eye_icon_state]_r", -eyes_layer) // SKYRAT EDIT CHANGE - Customization - ORIGINAL: var/mutable_appearance/eye_right = mutable_appearance('icons/mob/human_face.dmi', "[eye_icon_state]_r", -BODY_LAYER) - var/list/overlays = list(eye_left, eye_right) - - if(EYECOLOR in parent.dna?.species.species_traits) - eye_right.color = eye_color_right - eye_left.color = eye_color_left var/obscured = parent.check_obscured_slots(TRUE) if(overlay_ignore_lighting && !(obscured & ITEM_SLOT_EYES)) @@ -144,17 +140,36 @@ eye_right.overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, parent, alpha = eye_right.alpha) var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD) - if(my_head?.worn_face_offset) - for(var/mutable_appearance/overlay in overlays) - my_head.worn_face_offset.apply_offset(overlay) - - // SKYRAT EDIT START - Customization (darn synths I swear) + if(my_head) + if(my_head.head_flags & HEAD_EYECOLOR) + eye_right.color = eye_color_right + eye_left.color = eye_color_left + if(my_head.worn_face_offset) + my_head.worn_face_offset.apply_offset(eye_left) + my_head.worn_face_offset.apply_offset(eye_right) + + // SKYRAT EDIT START - Customization (Synths + Emissives) if(eye_icon_state == "None") eye_left.alpha = 0 eye_right.alpha = 0 + + if (is_emissive) // Because it was done all weird up there. + var/mutable_appearance/emissive_left = emissive_appearance(eye_left.icon, eye_left.icon_state, parent, -BODY_LAYER, eye_left.alpha) + var/mutable_appearance/emissive_right = emissive_appearance(eye_right.icon, eye_right.icon_state, parent, -BODY_LAYER, eye_right.alpha) + + emissive_left.appearance_flags &= ~RESET_TRANSFORM + emissive_right.appearance_flags &= ~RESET_TRANSFORM + + if(my_head.worn_face_offset) + my_head.worn_face_offset.apply_offset(emissive_right) + my_head.worn_face_offset.apply_offset(emissive_left) + + eye_left.overlays += emissive_left + eye_right.overlays += emissive_right + // SKYRAT EDIT END - return overlays + return list(eye_left, eye_right) #undef OFFSET_X #undef OFFSET_Y diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem.png index b6ceaeaec20ca4..32b4590ff5c4f5 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_krokodil_addict.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_krokodil_addict.png index f0a3e25deabd56..e9251e73cc5494 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_krokodil_addict.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_krokodil_addict.png differ diff --git a/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm b/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm index 04b766e945559b..a8c862309bd1b6 100644 --- a/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm +++ b/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm @@ -44,7 +44,7 @@ savefile_key = "eye_emissives" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - relevant_species_trait = EYECOLOR + relevant_head_flag = HEAD_EYECOLOR /datum/preference/toggle/eye_emissives/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) value = value && preferences && is_allowed(preferences) diff --git a/modular_skyrat/master_files/code/modules/mob/living/human/species.dm b/modular_skyrat/master_files/code/modules/mob/living/human/species.dm index 5fed66f947a939..051f52a9a1d877 100644 --- a/modular_skyrat/master_files/code/modules/mob/living/human/species.dm +++ b/modular_skyrat/master_files/code/modules/mob/living/human/species.dm @@ -16,6 +16,7 @@ if ( \ (preference.relevant_mutant_bodypart in default_mutant_bodyparts) \ || (preference.relevant_species_trait in species_traits) \ + || (preference.relevant_head_flag && check_head_flags(preference.relevant_head_flag)) \ ) features += preference.savefile_key diff --git a/modular_skyrat/modules/better_vox/code/vox_species.dm b/modular_skyrat/modules/better_vox/code/vox_species.dm index 6853e4652b73e7..72afc9bf742e8d 100644 --- a/modular_skyrat/modules/better_vox/code/vox_species.dm +++ b/modular_skyrat/modules/better_vox/code/vox_species.dm @@ -7,10 +7,6 @@ digitigrade_customization = DIGITIGRADE_NEVER // We have our own unique sprites! species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR, ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm index 3aefc2b2b52154..aa857535cf461a 100644 --- a/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm @@ -25,6 +25,7 @@ icon_greyscale = BODYPART_ICON_MAMMAL limb_id = SPECIES_MAMMAL bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC + head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/mutant icon_greyscale = BODYPART_ICON_MAMMAL diff --git a/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm index 0a9ea41204c058..098e4ad1064869 100644 --- a/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm @@ -8,7 +8,7 @@ limb_id = SPECIES_GHOUL brute_modifier = GHOUL_BRUTE_MODIFIER burn_modifier = GHOUL_BURN_MODIFIER - + head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_DEBRAIN /obj/item/bodypart/head/mutant/ghoul/Initialize(mapload) worn_ears_offset = new( diff --git a/modular_skyrat/modules/bodyparts/code/lizard_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/lizard_bodyparts.dm index 7f2015f97dfa95..8ec2ee74414810 100644 --- a/modular_skyrat/modules/bodyparts/code/lizard_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/lizard_bodyparts.dm @@ -1,6 +1,7 @@ /obj/item/bodypart/head/lizard icon_greyscale = BODYPART_ICON_LIZARD bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC // You're too slow Kapu, I did it myself ;) + head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/lizard icon_greyscale = BODYPART_ICON_LIZARD diff --git a/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm index 919bd914a42e20..80dadd5005a839 100644 --- a/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm @@ -4,6 +4,7 @@ icon_state = "moth_head_m" limb_id = SPECIES_MOTH is_dimorphic = TRUE + head_flags = HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN //what the fuck, moths have lips? /obj/item/bodypart/chest/moth icon = BODYPART_ICON_MOTH diff --git a/modular_skyrat/modules/bodyparts/code/podperson_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/podperson_bodyparts.dm index 6567289d75a8db..b23a28ff9dd78a 100644 --- a/modular_skyrat/modules/bodyparts/code/podperson_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/podperson_bodyparts.dm @@ -1,5 +1,6 @@ /obj/item/bodypart/head/pod icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/chest/pod icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC diff --git a/modular_skyrat/modules/bodyparts/code/skrell_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/skrell_bodyparts.dm index aa0b77c2e0e6cf..ae3a10f19170a2 100644 --- a/modular_skyrat/modules/bodyparts/code/skrell_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/skrell_bodyparts.dm @@ -7,6 +7,7 @@ limb_id = SPECIES_SKRELL brute_modifier = SKRELL_BRUTE_MODIFIER burn_modifier = SKRELL_BURN_MODIFIER + head_flags = HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/chest/mutant/skrell icon_greyscale = BODYPART_ICON_SKRELL diff --git a/modular_skyrat/modules/bodyparts/code/snail_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/snail_bodyparts.dm index 5f7bdb4bbda547..3dae7d44d8322d 100644 --- a/modular_skyrat/modules/bodyparts/code/snail_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/snail_bodyparts.dm @@ -1,5 +1,6 @@ /obj/item/bodypart/head/snail icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_DEBRAIN /obj/item/bodypart/chest/snail icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC diff --git a/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm index ff7bd99823352b..3762bf1d0a8828 100644 --- a/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm @@ -10,6 +10,7 @@ limb_id = SPECIES_TESHARI brute_modifier = TESHARI_BRUTE_MODIFIER burn_modifier = TESHARI_BURN_MODIFIER + head_flags = HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN /obj/item/bodypart/head/mutant/teshari/Initialize(mapload) worn_ears_offset = new( diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm index e6c856c5d9691b..f0f07262a69055 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -188,7 +188,7 @@ name = "Horse" icon_state = "horse" color_src = USE_ONE_COLOR - default_color = HAIR + default_color = DEFAULT_PRIMARY /datum/sprite_accessory/tails/mammal/wagging/husky name = "Husky" diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm index 676609b44d9ca0..46ad41c1ab58cf 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm @@ -110,46 +110,14 @@ GLOBAL_LIST_EMPTY(customizable_races) var/obj/item/bodypart/head/noggin = species_human.get_bodypart(BODY_ZONE_HEAD) if(noggin && !(HAS_TRAIT(species_human, TRAIT_HUSK))) - // lipstick - if(species_human.lip_style && (LIPS in species_traits)) - var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[species_human.lip_style]", -BODY_LAYER) - lip_overlay.color = species_human.lip_color - noggin.worn_face_offset?.apply_offset(lip_overlay) - lip_overlay.pixel_y += height_offset - standing += lip_overlay - - // eyes - if(!(NOEYESPRITES in species_traits)) + if(noggin.head_flags & HEAD_EYESPRITES) var/obj/item/organ/internal/eyes/eye_organ = species_human.get_organ_slot(ORGAN_SLOT_EYES) - var/mutable_appearance/no_eyeslay - var/add_pixel_x = 0 - var/add_pixel_y = 0 - //cut any possible vis overlays - if(body_vis_overlays.len) - SSvis_overlays.remove_vis_overlay(species_human, body_vis_overlays) - var/list/feature_offset = noggin.worn_face_offset?.get_offset() - if(feature_offset) - add_pixel_x = feature_offset["x"] - add_pixel_y = feature_offset["y"] - add_pixel_y += height_offset - - if(!eye_organ) - no_eyeslay = mutable_appearance('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER) - no_eyeslay.pixel_x += add_pixel_x - no_eyeslay.pixel_y += add_pixel_y - standing += no_eyeslay - else - eye_organ.refresh(call_update = FALSE) - if(!no_eyeslay) + if(eye_organ) + eye_organ.refresh(call_update = FALSE) for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human)) eye_overlay.pixel_y += height_offset standing += eye_overlay - if(eye_organ.is_emissive) - var/mutable_appearance/eye_emissive = emissive_appearance_copy(eye_overlay, species_human) - eye_emissive.pixel_x += add_pixel_x - eye_emissive.pixel_y += add_pixel_y - standing += eye_emissive //Underwear, Undershirts & Socks if(!(NO_UNDERWEAR in species_traits)) diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/akula.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/akula.dm index cc7b0fd9d9c24a..9a1b2325c1231a 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/akula.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/akula.dm @@ -20,9 +20,6 @@ mutanteyes = /obj/item/organ/internal/eyes/akula species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/aquatic.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/aquatic.dm index 775af3bfe41a06..8fdf9283730f9a 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/aquatic.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/aquatic.dm @@ -3,10 +3,6 @@ id = SPECIES_AQUATIC species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm index 4f8b8aed16dbde..e568c5ad22a28b 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm @@ -2,12 +2,6 @@ name = "Dwarf" id = SPECIES_DWARF examine_limb_id = SPECIES_HUMAN - species_traits = list( - EYECOLOR, - HAIR, - FACEHAIR, - LIPS, - ) inherent_traits = list( TRAIT_DWARF,TRAIT_SNOB, TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm index a73343dae35cd7..0ef1b7ec681e66 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm @@ -3,10 +3,7 @@ id = SPECIES_GHOUL examine_limb_id = SPECIES_GHOUL species_traits = list( - NOEYESPRITES, DYNCOLORS, - HAIR, - FACEHAIR ) can_have_genitals = FALSE //WHY WOULD YOU WANT TO FUCK ONE OF THESE THINGS? mutant_bodyparts = list("ghoulcolor" = "Tan Necrotic") diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/hemophage.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/hemophage.dm index 6858529f3bf400..6938aebd27128d 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/hemophage.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/hemophage.dm @@ -63,10 +63,6 @@ name = "Hemophage" id = SPECIES_HEMOPHAGE species_traits = list( - EYECOLOR, - HAIR, - FACEHAIR, - LIPS, DRINKSBLOOD, ) inherent_traits = list( diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/humanoid.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/humanoid.dm index 4f72bc66568df8..20776c46d8bcdf 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/humanoid.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/humanoid.dm @@ -1,11 +1,8 @@ /datum/species/humanoid name = "Humanoid" id = SPECIES_HUMANOID - species_traits = list(MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR + species_traits = list( + MUTCOLORS, ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/insect.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/insect.dm index 79421677adc022..373f45fa717e7e 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/insect.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/insect.dm @@ -3,10 +3,6 @@ id = SPECIES_INSECT species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm index b906f60d9e7dc3..0a1dd1fb9ae214 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm @@ -3,10 +3,6 @@ external_organs = list() species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR, ) default_mutant_bodyparts = list( "tail" = ACC_RANDOM, @@ -53,11 +49,7 @@ /datum/species/lizard/ashwalker species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, NO_UNDERWEAR, - HAIR, - FACEHAIR ) always_customizable = TRUE diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm index 7a21861ccd74b8..303286587bfe60 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm @@ -3,10 +3,6 @@ id = SPECIES_MAMMAL species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/moth.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/moth.dm index 97c70c7ffa577e..8bbd5fe28a7303 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/moth.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/moth.dm @@ -6,7 +6,6 @@ "moth_antennae" = ACC_RANDOM, ) species_traits = list( - LIPS, HAS_MARKINGS, TRAIT_ANTENNAE, MUTCOLORS, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm index 2d2f57bea2e682..2b9ee073c1f23b 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm @@ -18,9 +18,6 @@ examine_limb_id = SPECIES_PODPERSON species_traits = list( MUTCOLORS, - EYECOLOR, - HAIR, // Leaving this here so they can still use it if they want, even if it's kinda ugly compared to their special hair. - FACEHAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm index 17bda2f0072c72..734dadeddcf539 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm @@ -1,9 +1,6 @@ /datum/species/jelly species_traits = list( MUTCOLORS, - EYECOLOR, - HAIR, - FACEHAIR, ) default_mutant_bodyparts = list( "tail" = "None", diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/skrell.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/skrell.dm index 3d0f658a093750..4c77c47c6fc5c0 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/skrell.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/skrell.dm @@ -3,9 +3,6 @@ id = SPECIES_SKRELL species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - NO_SLIP_WHEN_WALKING ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/tajaran.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/tajaran.dm index 10a7358563b368..380fd37c028c75 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/tajaran.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/tajaran.dm @@ -3,9 +3,6 @@ id = SPECIES_TAJARAN species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm index 2ae7e8020d4930..9c8ac3f2888b07 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm @@ -3,9 +3,6 @@ id = SPECIES_UNATHI species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm index 9a90498c01dd94..63f0d8e082c9f5 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm @@ -6,10 +6,6 @@ can_augment = FALSE species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vulpkanin.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vulpkanin.dm index 908999b0f7b1ea..c93e410dac61b6 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vulpkanin.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vulpkanin.dm @@ -3,10 +3,6 @@ id = SPECIES_VULP species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR, ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm index 288920db481b16..8489e5d1b45593 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm @@ -5,10 +5,6 @@ family_heirlooms = list(/obj/item/toy/plush/rouny, /obj/item/toy/toy_xeno,) species_traits = list( MUTCOLORS, - EYECOLOR, - LIPS, - HAIR, - FACEHAIR ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, diff --git a/modular_skyrat/modules/mutants/code/mutant_species.dm b/modular_skyrat/modules/mutants/code/mutant_species.dm index c284ef9cc83c56..5dc0a050629b80 100644 --- a/modular_skyrat/modules/mutants/code/mutant_species.dm +++ b/modular_skyrat/modules/mutants/code/mutant_species.dm @@ -7,10 +7,7 @@ eyes_icon = 'modular_skyrat/modules/mutants/icons/mutant_eyes.dmi' species_traits = list( NOZOMBIE, - NOEYESPRITES, - LIPS, - HAIR - ) + ) inherent_traits = list( TRAIT_NOBLOOD, TRAIT_NODISMEMBER, diff --git a/modular_skyrat/modules/mutants/code/mutant_zombie_bodyparts.dm b/modular_skyrat/modules/mutants/code/mutant_zombie_bodyparts.dm index 12feff4057f502..e0b71d6ec1d8ac 100644 --- a/modular_skyrat/modules/mutants/code/mutant_zombie_bodyparts.dm +++ b/modular_skyrat/modules/mutants/code/mutant_zombie_bodyparts.dm @@ -7,6 +7,7 @@ is_dimorphic = FALSE limb_id = SPECIES_MUTANT species_color = "#ffffff" + head_flags = HEAD_HAIR|HEAD_LIPS|HEAD_DEBRAIN /obj/item/bodypart/chest/mutant_zombie icon_greyscale = 'modular_skyrat/modules/mutants/icons/mutant_parts_greyscale.dmi' diff --git a/modular_skyrat/modules/salon/code/misc_items.dm b/modular_skyrat/modules/salon/code/misc_items.dm index 56b035d29f019b..8eeb23ea8ba4b0 100644 --- a/modular_skyrat/modules/salon/code/misc_items.dm +++ b/modular_skyrat/modules/salon/code/misc_items.dm @@ -98,63 +98,79 @@ /obj/item/razor/attack(mob/attacked_mob, mob/living/user) - if(ishuman(attacked_mob)) - var/mob/living/carbon/human/target_human = attacked_mob - var/location = user.zone_selected - if(!(location in list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)) && !user.combat_mode) - to_chat(user, span_warning("You stop, look down at what you're currently holding and ponder to yourself, \"This is probably to be used on their hair or their facial hair.\"")) + if(!ishuman(attacked_mob)) + return ..() + + var/mob/living/carbon/human/target_human = attacked_mob + var/location = user.zone_selected + var/obj/item/bodypart/head/noggin = target_human.get_bodypart(BODY_ZONE_HEAD) + var/static/list/head_zones = list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD) + + if(!noggin && (location in head_zones)) + to_chat(user, span_warning("[target_human] doesn't have a head!")) + return + + if(!(location in head_zones) && !user.combat_mode) + to_chat(user, span_warning("You stop, look down at what you're currently holding and ponder to yourself, \"This is probably to be used on their hair or their facial hair.\"")) + return + + if(location == BODY_ZONE_PRECISE_MOUTH) + if(!(noggin.head_flags & HEAD_FACIAL_HAIR)) + to_chat(user, span_warning("There is no facial hair to shave!")) return - if((location in list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)) && !target_human.get_bodypart(BODY_ZONE_HEAD)) - to_chat(user, span_warning("[target_human] doesn't have a head!")) + + if(!get_location_accessible(target_human, location)) + to_chat(user, span_warning("The mask is in the way!")) return - if(location == BODY_ZONE_PRECISE_MOUTH) - if(!(FACEHAIR in target_human.dna.species.species_traits)) - to_chat(user, span_warning("There is no facial hair to shave!")) - return - if(!get_location_accessible(target_human, location)) - to_chat(user, span_warning("The mask is in the way!")) - return - if(HAS_TRAIT(target_human, TRAIT_SHAVED)) - to_chat(user, span_warning("[target_human] is just way too shaved. Like, really really shaved.")) - return - if(target_human.facial_hairstyle == "Shaved") - to_chat(user, span_warning("Already clean-shaven!")) - return - - var/self_shaving = target_human == user // Shaving yourself? - user.visible_message(span_notice("[user] starts to shave [self_shaving ? user.p_their() : "[target_human]'s"] hair with [src]."), \ - span_notice("You take a moment to shave [self_shaving ? "your" : "[target_human]'s" ] hair with [src]...")) - if(do_after(user, shaving_time, target = target_human)) - user.visible_message(span_notice("[user] shaves [self_shaving ? user.p_their() : "[target_human]'s"] hair clean with [src]."), \ - span_notice("You finish shaving [self_shaving ? "your" : " [target_human]'s"] hair with [src]. Fast and clean!")) - shave(target_human, location) - - else if(location == BODY_ZONE_HEAD) - if(!(HAIR in target_human.dna.species.species_traits)) - to_chat(user, span_warning("There is no hair to shave!")) - return - if(!get_location_accessible(target_human, location)) - to_chat(user, span_warning("The headgear is in the way!")) - return - if(target_human.hairstyle == "Bald" || target_human.hairstyle == "Balding Hair" || target_human.hairstyle == "Skinhead") - to_chat(user, span_warning("There is not enough hair left to shave!")) - return - if(HAS_TRAIT(target_human, TRAIT_SHAVED)) - to_chat(user, span_warning("[target_human] is just way too shaved. Like, really really shaved.")) - return - - var/self_shaving = target_human == user // Shaving yourself? - user.visible_message(span_notice("[user] starts to shave [self_shaving ? user.p_their() : "[target_human]'s"] hair with [src]."), \ - span_notice("You take a moment to shave [self_shaving ? "your" : "[target_human]'s" ] hair with [src]...")) - if(do_after(user, shaving_time, target = target_human)) - user.visible_message(span_notice("[user] shaves [self_shaving ? user.p_their() : "[target_human]'s"] hair clean with [src]."), \ - span_notice("You finish shaving [self_shaving ? "your" : " [target_human]'s"] hair with [src]. Fast and clean!")) - shave(target_human, location) - else - ..() - else - ..() + if(HAS_TRAIT(target_human, TRAIT_SHAVED)) + to_chat(user, span_warning("[target_human] is just way too shaved. Like, really really shaved.")) + return + + if(target_human.facial_hairstyle == "Shaved") + to_chat(user, span_warning("Already clean-shaven!")) + return + + var/self_shaving = target_human == user // Shaving yourself? + user.visible_message(span_notice("[user] starts to shave [self_shaving ? user.p_their() : "[target_human]'s"] hair with [src]."), \ + span_notice("You take a moment to shave [self_shaving ? "your" : "[target_human]'s" ] hair with [src]...")) + + if(do_after(user, shaving_time, target = target_human)) + user.visible_message(span_notice("[user] shaves [self_shaving ? user.p_their() : "[target_human]'s"] hair clean with [src]."), \ + span_notice("You finish shaving [self_shaving ? "your" : " [target_human]'s"] hair with [src]. Fast and clean!")) + + shave(target_human, location) + + else if(location == BODY_ZONE_HEAD) + if(!(noggin.head_flags & HEAD_HAIR)) + to_chat(user, span_warning("There is no hair to shave!")) + return + + if(!get_location_accessible(target_human, location)) + to_chat(user, span_warning("The headgear is in the way!")) + return + + if(target_human.hairstyle == "Bald" || target_human.hairstyle == "Balding Hair" || target_human.hairstyle == "Skinhead") + to_chat(user, span_warning("There is not enough hair left to shave!")) + return + + if(HAS_TRAIT(target_human, TRAIT_SHAVED)) + to_chat(user, span_warning("[target_human] is just way too shaved. Like, really really shaved.")) + return + + var/self_shaving = target_human == user // Shaving yourself? + user.visible_message(span_notice("[user] starts to shave [self_shaving ? user.p_their() : "[target_human]'s"] hair with [src]."), \ + span_notice("You take a moment to shave [self_shaving ? "your" : "[target_human]'s" ] hair with [src]...")) + + if(do_after(user, shaving_time, target = target_human)) + user.visible_message(span_notice("[user] shaves [self_shaving ? user.p_their() : "[target_human]'s"] hair clean with [src]."), \ + span_notice("You finish shaving [self_shaving ? "your" : " [target_human]'s"] hair with [src]. Fast and clean!")) + + shave(target_human, location) + + return + + return ..() /obj/structure/sign/barber name = "barbershop sign" diff --git a/modular_skyrat/modules/salon/code/straight_razor.dm b/modular_skyrat/modules/salon/code/straight_razor.dm index 4c95830c63f674..e6e85f7e160992 100644 --- a/modular_skyrat/modules/salon/code/straight_razor.dm +++ b/modular_skyrat/modules/salon/code/straight_razor.dm @@ -32,7 +32,8 @@ to_chat(user, span_warning("[target_human] doesn't have a head!")) return if(location == BODY_ZONE_PRECISE_MOUTH) - if(!(FACEHAIR in target_human.dna.species.species_traits)) + var/obj/item/bodypart/head/noggin = target_human.get_bodypart(BODY_ZONE_HEAD) + if(!(noggin.head_flags & HEAD_FACIAL_HAIR)) to_chat(user, span_warning("There is no facial hair to shave!")) return if(!get_location_accessible(target_human, location)) diff --git a/modular_skyrat/modules/synths/code/bodyparts/limbs.dm b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm index 5b44cf74084ede..8177c460e5abe2 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/limbs.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm @@ -12,6 +12,7 @@ burn_reduction = 0 brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER + head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/robot/synth icon_greyscale = BODYPART_ICON_IPC diff --git a/modular_skyrat/modules/synths/code/species/synthetic.dm b/modular_skyrat/modules/synths/code/species/synthetic.dm index 81a1f941ed56ca..61151b460a4155 100644 --- a/modular_skyrat/modules/synths/code/species/synthetic.dm +++ b/modular_skyrat/modules/synths/code/species/synthetic.dm @@ -21,10 +21,6 @@ ) species_traits = list( ROBOTIC_DNA_ORGANS, - EYECOLOR, - HAIR, - FACEHAIR, - LIPS, ROBOTIC_LIMBS, NOTRANSSTING, ) diff --git a/modular_skyrat/modules/teshari/code/_teshari.dm b/modular_skyrat/modules/teshari/code/_teshari.dm index 8fa547b778e27b..b159fc8250b18a 100644 --- a/modular_skyrat/modules/teshari/code/_teshari.dm +++ b/modular_skyrat/modules/teshari/code/_teshari.dm @@ -6,11 +6,11 @@ name = "Teshari" id = SPECIES_TESHARI eyes_icon = 'modular_skyrat/modules/organs/icons/teshari_eyes.dmi' - species_traits = list(MUTCOLORS, - EYECOLOR, + species_traits = list( + MUTCOLORS, NO_UNDERWEAR, HAS_MARKINGS, - ) + ) inherent_traits = list( TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, diff --git a/tgstation.dme b/tgstation.dme index aa26eaee005045..cae1fc43c93dbc 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -207,6 +207,7 @@ #include "code\__DEFINES\spatial_gridmap.dm" #include "code\__DEFINES\species_clothing_paths.dm" #include "code\__DEFINES\speech_channels.dm" +#include "code\__DEFINES\sprite_accessories.dm" #include "code\__DEFINES\stack_trace.dm" #include "code\__DEFINES\stat.dm" #include "code\__DEFINES\stat_tracking.dm" @@ -4193,6 +4194,7 @@ #include "code\modules\mob\living\carbon\alien\larva\powers.dm" #include "code\modules\mob\living\carbon\alien\special\alien_embryo.dm" #include "code\modules\mob\living\carbon\alien\special\facehugger.dm" +#include "code\modules\mob\living\carbon\human\_species.dm" #include "code\modules\mob\living\carbon\human\damage_procs.dm" #include "code\modules\mob\living\carbon\human\death.dm" #include "code\modules\mob\living\carbon\human\dummy.dm" @@ -4213,7 +4215,6 @@ #include "code\modules\mob\living\carbon\human\life.dm" #include "code\modules\mob\living\carbon\human\login.dm" #include "code\modules\mob\living\carbon\human\physiology.dm" -#include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\status_procs.dm" #include "code\modules\mob\living\carbon\human\suicides.dm" #include "code\modules\mob\living\carbon\human\monkey\monkey.dm" @@ -5115,8 +5116,8 @@ #include "code\modules\surgery\advanced\bioware\vein_threading.dm" #include "code\modules\surgery\bodyparts\_bodyparts.dm" #include "code\modules\surgery\bodyparts\dismemberment.dm" -#include "code\modules\surgery\bodyparts\hair.dm" #include "code\modules\surgery\bodyparts\head.dm" +#include "code\modules\surgery\bodyparts\head_hair_and_lips.dm" #include "code\modules\surgery\bodyparts\helpers.dm" #include "code\modules\surgery\bodyparts\parts.dm" #include "code\modules\surgery\bodyparts\robot_bodyparts.dm"