diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index df9b7cc2296..7c082f0b228 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -647,6 +647,9 @@ #define GRADIENT_APPLIES_TO_HAIR (1<<0) #define GRADIENT_APPLIES_TO_FACIAL_HAIR (1<<1) +// Hair masks +#define HAIR_MASK_HIDE_ABOVE_45_DEG_MEDIUM "hide_above_45deg" + // Height defines // - They are numbers so you can compare height values (x height < y height) // - They do not start at 0 for futureproofing diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 58b1b1ae346..fe3441dd02b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -130,6 +130,9 @@ var/flags_inv ///you can see someone's mask through their transparent visor, but you can't reach it var/transparent_protection = NONE + ///Name of a mask in icons\mob\human\hair_masks.dmi to apply to hair when this item is worn + ///Used by certain hats to give the appearance of squishing down tall hairstyles without hiding the hair completely + var/hair_mask = "" ///flags for what should be done when you click on the item, default is picking it up var/interaction_flags_item = INTERACT_ITEM_ATTACK_HAND_PICKUP diff --git a/code/modules/clothing/chameleon/_chameleon_action.dm b/code/modules/clothing/chameleon/_chameleon_action.dm index b9a1697976b..fbbe480e59a 100644 --- a/code/modules/clothing/chameleon/_chameleon_action.dm +++ b/code/modules/clothing/chameleon/_chameleon_action.dm @@ -156,6 +156,7 @@ ) item_target.flags_inv = initial(picked_item.flags_inv) + item_target.hair_mask = initial(picked_item.hair_mask) item_target.transparent_protection = initial(picked_item.transparent_protection) if(isclothing(item_target) && ispath(picked_item, /obj/item/clothing)) var/obj/item/clothing/clothing_target = item_target diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 6cd88c1746c..56a8661a412 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -9,6 +9,7 @@ inhand_icon_state = null armor_type = /datum/armor/utility_hardhat flags_inv = 0 + hair_mask = HAIR_MASK_HIDE_ABOVE_45_DEG_MEDIUM actions_types = list(/datum/action/item_action/toggle_helmet_light) clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT resistance_flags = FIRE_PROOF @@ -211,6 +212,7 @@ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF visor_flags_cover = NONE flags_inv = HIDEEARS|HIDEHAIR|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT + hair_mask = "" transparent_protection = HIDEMASK|HIDEEYES visor_flags_inv = NONE visor_state = "weldvisor_atmos" @@ -230,6 +232,8 @@ hat_type = "pumpkin" clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT + hair_mask = "" + armor_type = /datum/armor/none light_range = 2 //luminosity when on flags_cover = HEADCOVERSEYES @@ -296,6 +300,7 @@ inhand_icon_state = null hat_type = "reindeer" flags_inv = 0 + hair_mask = "" armor_type = /datum/armor/none light_range = 1 //luminosity when on clothing_traits = list() diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 8863dedd43e..aebba0ae2a9 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -580,6 +580,8 @@ if(gradient_styles?[GRADIENT_HAIR_KEY]) . += "-[gradient_styles[GRADIENT_HAIR_KEY]]" . += "-[gradient_colors[GRADIENT_HAIR_KEY]]" + if(LAZYLEN(hair_masks)) + . += "-[jointext(hair_masks, "-")]" return . diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index cce8935f803..30c841147a7 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -43,6 +43,8 @@ var/hair_alpha = 255 /// Is the hair currently hidden by something? var/hair_hidden = FALSE + /// Lazy initialized hashset of all hair masks that should be applied + var/list/hair_masks ///Facial hair style var/facial_hairstyle = "Shaved" diff --git a/code/modules/surgery/bodyparts/head_hair_and_lips.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm index 7f81a615f35..861076e184b 100644 --- a/code/modules/surgery/bodyparts/head_hair_and_lips.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -8,12 +8,15 @@ //HIDDEN CHECKS START hair_hidden = FALSE facial_hair_hidden = FALSE + LAZYNULL(hair_masks) if(human_head_owner) for(var/obj/item/worn_item in human_head_owner.get_equipped_items()) if(worn_item.flags_inv & HIDEHAIR) hair_hidden = TRUE if(worn_item.flags_inv & HIDEFACIALHAIR) facial_hair_hidden = TRUE + if(worn_item.hair_mask) + LAZYSET(hair_masks, worn_item.hair_mask, TRUE) //invisibility and husk stuff if(HAS_TRAIT(human_head_owner, TRAIT_INVISIBLE_MAN) || HAS_TRAIT(human_head_owner, TRAIT_HUSK)) hair_hidden = TRUE @@ -99,15 +102,24 @@ var/facial_hair_gradient_style = gradient_styles[GRADIENT_FACIAL_HAIR_KEY] if(facial_hair_gradient_style != "None") var/facial_hair_gradient_color = gradient_colors[GRADIENT_FACIAL_HAIR_KEY] - var/image/facial_hair_gradient_overlay = get_gradient_overlay(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER, SSaccessories.facial_hair_gradients_list[facial_hair_gradient_style], facial_hair_gradient_color, image_dir) + var/image/facial_hair_gradient_overlay = get_gradient_overlay(icon(sprite_accessory.icon, sprite_accessory.icon_state), -HAIR_LAYER, SSaccessories.facial_hair_gradients_list[facial_hair_gradient_style], facial_hair_gradient_color, image_dir) . += facial_hair_gradient_overlay var/image/hair_overlay if(!(show_debrained && (head_flags & HEAD_DEBRAIN)) && !hair_hidden && hairstyle && (head_flags & HEAD_HAIR)) var/datum/sprite_accessory/hair/hair_sprite_accessory = SSaccessories.hairstyles_list[hairstyle] if(hair_sprite_accessory) + var/icon/base_icon + if(LAZYLEN(hair_masks)) + base_icon = icon(hair_sprite_accessory.icon, hair_sprite_accessory.icon_state) + for(var/mask in hair_masks) + var/icon/blend_with = icon('icons/mob/human/hair_masks.dmi', mask) + blend_with.Shift(SOUTH, hair_sprite_accessory.y_offset) + base_icon.Blend(blend_with, ICON_ADD) + else + base_icon = icon(hair_sprite_accessory.icon, hair_sprite_accessory.icon_state) //Overlay - hair_overlay = image(hair_sprite_accessory.icon, hair_sprite_accessory.icon_state, -HAIR_LAYER, image_dir) + hair_overlay = image(base_icon, layer=-HAIR_LAYER, dir=image_dir) hair_overlay.alpha = hair_alpha hair_overlay.pixel_y = hair_sprite_accessory.y_offset //Emissive blocker @@ -120,7 +132,7 @@ var/hair_gradient_style = gradient_styles[GRADIENT_HAIR_KEY] if(hair_gradient_style != "None") var/hair_gradient_color = gradient_colors[GRADIENT_HAIR_KEY] - var/image/hair_gradient_overlay = get_gradient_overlay(hair_sprite_accessory.icon, hair_sprite_accessory.icon_state, -HAIR_LAYER, SSaccessories.hair_gradients_list[hair_gradient_style], hair_gradient_color, image_dir) + var/image/hair_gradient_overlay = get_gradient_overlay(base_icon, -HAIR_LAYER, SSaccessories.hair_gradients_list[hair_gradient_style], hair_gradient_color, image_dir) hair_gradient_overlay.pixel_y = hair_sprite_accessory.y_offset . += hair_gradient_overlay @@ -184,12 +196,12 @@ return eyeless_overlay /// Returns an appropriate hair/facial hair gradient overlay -/obj/item/bodypart/head/proc/get_gradient_overlay(file, icon, layer, datum/sprite_accessory/gradient, grad_color, image_dir) +/obj/item/bodypart/head/proc/get_gradient_overlay(icon/base_icon, layer, datum/sprite_accessory/gradient, grad_color, image_dir) RETURN_TYPE(/mutable_appearance) var/mutable_appearance/gradient_overlay = mutable_appearance(layer = layer) var/icon/temp = icon(gradient.icon, gradient.icon_state, image_dir) - var/icon/temp_hair = icon(file, icon, image_dir) + var/icon/temp_hair = icon(base_icon, dir=image_dir) temp.Blend(temp_hair, ICON_ADD) gradient_overlay.icon = temp gradient_overlay.color = grad_color diff --git a/icons/mob/human/hair_masks.dmi b/icons/mob/human/hair_masks.dmi new file mode 100644 index 00000000000..45ecb761d9a Binary files /dev/null and b/icons/mob/human/hair_masks.dmi differ