diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm index 5312cba6e14..1b85e76c772 100644 --- a/code/__DEFINES/mob.dm +++ b/code/__DEFINES/mob.dm @@ -120,6 +120,7 @@ #define TINT_IMPAIR 2 //Threshold of tint level to apply weld mask overlay #define TINT_BLIND 3 //Threshold of tint level to obscure vision fully +#define EYE_SHINE_THRESHOLD 6 //dark_view threshold past which a humanoid's eyes will 'shine' in the dark. #define isliving(A) (istype((A), /mob/living)) #define iscarbon(A) (istype((A), /mob/living/carbon)) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index ac17d0591c5..96109186359 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -897,3 +897,12 @@ proc/rand_hex_color() for(var/i=0;i<6;i++) color = color+pick(colors) return "#[color]" + +//Imagine removing pixels from the main icon that are covered by pixels from the mask icon. +proc/get_icon_difference(var/icon/main, var/icon/mask) + if(istype(main) && istype(mask)) + mask.Blend(rgb(255,255,255), ICON_SUBTRACT) //Make all pixels on the mask as black as possible. + mask.Opaque(rgb(255,255,255)) //Make the transparent pixels (background) white. + mask.BecomeAlphaMask() //Make all the black pixels vanish (fully transparent), leaving only the white pixels. + main.AddAlphaMask(mask) //Make the pixels in the main icon that are in the transparent zone of the mask icon also vanish (fully transparent). + return main diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index f106d579e94..8be1eaa478b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1337,7 +1337,7 @@ Standard way to write links -Sayu if(covered_locations & HEAD) return 0 if("eyes") - if(covered_locations & HEAD || face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES) + if(face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES || eyesmouth_covered & HEADCOVERSEYES) return 0 if("mouth") if(covered_locations & HEAD || face_covered & HIDEFACE || eyesmouth_covered & MASKCOVERSMOUTH) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 57d7cac79b5..030a022476d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1668,12 +1668,18 @@ G.icon_state = "grabbed1" G.synch() -/mob/living/carbon/human/proc/eyes_shine() /*Used to check if eyes should shine in the dark. Returns the image of the eyes on the layer where they will appear to shine. - Eyes need to have significantly high darksight to shine unless the mob has the XRAY vision mutation. Eyes will not shine if they are covered in any way.*/ +/*Used to check if eyes should shine in the dark. Returns the image of the eyes on the layer where they will appear to shine. +Eyes need to have significantly high darksight to shine unless the mob has the XRAY vision mutation. Eyes will not shine if they are covered in any way.*/ +/mob/living/carbon/human/proc/eyes_shine() var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) - var/const/shine_threshold = 6 - if(istype(eyes) && ((eyes.get_dark_view() > shine_threshold) || (XRAY in mutations)) && get_location_accessible(src, "eyes")) - return(image(eyes.generate_icon(), layer = LIGHTING_LAYER + 1)) //Referenced cult constructs for shining in the dark. Needs to be above lighting effects such as shading. + if(!istype(eyes)) + return FALSE + if(!(eyes.get_dark_view() > EYE_SHINE_THRESHOLD) && !(XRAY in mutations)) + return FALSE + if(!get_location_accessible(src, "eyes")) + return FALSE + + return TRUE /mob/living/carbon/human/proc/gut() set category = "Abilities" diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 77074bee3f6..26805d4e791 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -105,6 +105,7 @@ Please contact me on #coderbus IRC. ~Carn x /mob/living/carbon/human var/list/overlays_standing[TOTAL_LAYERS] + var/list/misc_effect_overlays = list() //Overlays that are applied at a custom layer (defined in each image's .layer property) outside of standard overlay application. Updated in update_misc_effects() var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed var/icon/skeleton var/list/cached_standing_overlays = list() // List of everything currently in a human's actual overlays @@ -154,13 +155,16 @@ Please contact me on #coderbus IRC. ~Carn x I.layer = (-2 - (TOTAL_LAYERS - i)) // Highest layer gets -2, each prior layer is 1 lower new_overlays += I + update_misc_effects() + if(misc_effect_overlays) + new_overlays += misc_effect_overlays + if(frozen) // Admin freeze overlay new_overlays += frozen overlays += (new_overlays - old_overlays) overlays -= (old_overlays - new_overlays) cached_standing_overlays = new_overlays - overlays |= eyes_shine() //Only applies eyeshine if the eyes are uncovered and have significantly high darksight or XRAY vision. update_transform() @@ -1325,6 +1329,14 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() +/mob/living/carbon/human/proc/update_misc_effects() + misc_effect_overlays.Cut() + + //Begin appending miscellaneous effects. + if(eyes_shine()) + var/obj/item/organ/internal/eyes/E = get_int_organ(/obj/item/organ/internal/eyes) + misc_effect_overlays += E.get_eye_shine() //Image layer is specified in get_eye_shine() proc as LIGHTING_LAYER + 1. + /mob/living/carbon/human/proc/force_update_limbs() for(var/obj/item/organ/external/O in bodyparts) O.sync_colour_to_human(src) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 6114ae57ed1..b1adcce9ae8 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -305,12 +305,23 @@ /obj/item/organ/internal/eyes/proc/update_colour() dna.write_eyes_attributes(src) -/obj/item/organ/internal/eyes/proc/generate_icon(var/mob/living/carbon/human/H) - var/mob/living/carbon/human/G = H ? H : owner - if(istype(G)) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', G.species.eyes) - eyes_icon.Blend(eye_colour, ICON_ADD) - return(eyes_icon) +/obj/item/organ/internal/eyes/proc/generate_icon(var/mob/living/carbon/human/HA) + var/mob/living/carbon/human/H = HA + if(!istype(H)) + H = owner + var/icon/eyes_icon = new /icon('icons/mob/human_face.dmi', H.species.eyes) + eyes_icon.Blend(eye_colour, ICON_ADD) + return eyes_icon + +/obj/item/organ/internal/eyes/proc/get_eye_shine(var/mob/living/carbon/human/HA) //Referenced cult constructs for shining in the dark. Needs to be above lighting effects such as shading. + var/mob/living/carbon/human/H = HA + if(!istype(H)) + H = owner + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + var/datum/sprite_accessory/hair/hair_style = hair_styles_full_list[head_organ.h_style] + var/icon/hair = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + + return image(get_icon_difference(generate_icon(H), hair), layer = LIGHTING_LAYER + 1) //Cut the hair's pixels from the eyes icon so eyes covered by bangs stay hidden even while on a higher layer. /obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a special colour matrix if the eyes are organic and the mob is colourblind, otherwise it uses the current one. if(!robotic && owner.disabilities & COLOURBLIND)