Moves hair and eyes into standing overlays (#95781)

This commit is contained in:
MrMelbert
2026-05-04 15:50:36 -05:00
committed by GitHub
parent 505afdcf3d
commit cee225fecb
39 changed files with 414 additions and 393 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
/datum/outfit/cultist/post_equip(mob/living/carbon/human/equipped, visuals_only)
equipped.set_eye_color(BLOODCULT_EYE)
equipped.update_body()
equipped.update_eyes()
///Returns whether the given mob is convertable to the blood cult
/proc/is_convertable_to_cult(mob/living/target, datum/team/cult/specific_cult)
+1
View File
@@ -196,6 +196,7 @@
var/mob/living/carbon/human/dummy/consistent/dummy = new()
dummy.set_haircolor(COLOR_SILVER, update = FALSE)
dummy.set_hairstyle("CIA", update = FALSE)
dummy.update_hair()
var/datum/universal_icon/dummy_icon = render_preview_outfit(preview_outfit, dummy)
qdel(dummy)
return finish_preview_icon(dummy_icon)
+6 -8
View File
@@ -221,18 +221,16 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
if(ghost_accs == GHOST_ACCS_FULL && (icon_state in GLOB.ghost_forms_with_accessories_list)) //check if this form supports accessories and if the client wants to show them
if(facial_hairstyle)
var/datum/sprite_accessory/S = SSaccessories.facial_hairstyles_list[facial_hairstyle]
if(S)
facial_hair_overlay = mutable_appearance(S.icon, "[S.icon_state]", -HAIR_LAYER)
if(facial_hair_color)
facial_hair_overlay.color = facial_hair_color
if(S && S.icon_state != SPRITE_ACCESSORY_NONE)
facial_hair_overlay = mutable_appearance(S.icon, S.icon_state, -HAIR_LAYER)
facial_hair_overlay.color = facial_hair_color
facial_hair_overlay.alpha = 200
add_overlay(facial_hair_overlay)
if(hairstyle)
var/datum/sprite_accessory/hair/S = SSaccessories.hairstyles_list[hairstyle]
if(S)
hair_overlay = mutable_appearance(S.icon, "[S.icon_state]", -HAIR_LAYER)
if(hair_color)
hair_overlay.color = hair_color
if(S && S.icon_state != SPRITE_ACCESSORY_NONE)
hair_overlay = mutable_appearance(S.icon, S.icon_state, -HAIR_LAYER)
hair_overlay.color = hair_color
hair_overlay.alpha = 200
hair_overlay.pixel_z = S.y_offset
add_overlay(hair_overlay)
+13 -3
View File
@@ -130,8 +130,6 @@
if((!QDELETED(src) || !QDELETED(owner)) && !(movement_flags & NO_ID_TRANSFER))
transfer_identity(organ_owner)
if(!special)
if(!(organ_owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
organ_owner.update_body_parts()
organ_owner.clear_mood_event("brain_damage")
organ_owner.med_hud_set_status()
@@ -348,9 +346,21 @@
owner.investigate_log("has been killed by brain damage.", INVESTIGATE_DEATHS)
owner.death()
/obj/item/organ/brain/on_bodypart_insert(obj/item/bodypart/limb)
. = ..()
if(ishuman(limb.owner))
limb.owner.update_hair()
else
limb.update_icon_dropped()
/obj/item/organ/brain/on_bodypart_remove(obj/item/bodypart/limb, movement_flags)
. = ..()
update_brain_color(animate = FALSE) // once it's out in the world we need to make sure it's the right color
if(ishuman(limb.owner))
limb.owner.update_hair()
else
limb.update_icon_dropped()
// once it's out in the world we need to make sure it's the right color
update_brain_color(animate = FALSE)
/obj/item/organ/brain/apply_organ_damage(damage_amount, maximum = maxHealth, required_organ_flag = NONE)
. = ..()
@@ -131,3 +131,6 @@
var/obscured_slots = NONE
/// Covered hide flags (hideflags that can be seen, BUT can't be interacted with)
var/covered_slots = NONE
/// Lazylist of all hair masks applied to this mob's hairstyles
var/list/hair_masks
@@ -464,10 +464,13 @@
update_damage_overlays()
update_wound_overlays()
var/limb_count_update = 0
var/head_update = FALSE
var/list/new_limbs = list()
for(var/body_zone, limb_untyped in get_bodyparts_by_zones())
var/obj/item/bodypart/limb = limb_untyped
if(isnull(limb) || IS_STUMP(limb))
if(body_zone == BODY_ZONE_HEAD)
head_update = TRUE
if(icon_render_keys[body_zone])
icon_render_keys -= body_zone
limb_count_update += 1
@@ -483,6 +486,8 @@
new_limbs += limb_icon_cache[new_key]
else
if(body_zone == BODY_ZONE_HEAD)
head_update = TRUE
limb_icon_cache[new_key] ||= limb.get_limb_icon(dropped = FALSE)
new_limbs += limb_icon_cache[new_key]
icon_render_keys[limb.body_zone] = new_key
@@ -498,6 +503,10 @@
overlays_standing[BODYPARTS_LAYER] = new_limbs
apply_overlay(BODYPARTS_LAYER)
// for legacy support, head changes triggers an eye/hair update
if(head_update)
update_eyes()
update_hair()
/mob/living/carbon/proc/update_face_offset()
return
@@ -543,6 +552,12 @@
SEND_SIGNAL(src, COMSIG_BODYPART_GENERATE_ICON_KEY, .)
return .
/obj/item/bodypart/head/generate_icon_key()
. = ..()
if(lip_style)
. += lip_color
. += lip_style
///Generates a cache key specifically for husks
/obj/item/bodypart/proc/generate_husk_key()
RETURN_TYPE(/list)
@@ -565,44 +580,6 @@
. += "[human_owner.mob_height]"
return .
/obj/item/bodypart/head/generate_icon_key()
. = ..()
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]"
var/facial_hair_gradient_style = get_hair_gradient_style(GRADIENT_FACIAL_HAIR_KEY)
if(facial_hair_gradient_style)
. += "-[facial_hair_gradient_style]"
. += "-[get_hair_gradient_color(GRADIENT_FACIAL_HAIR_KEY)]"
if(show_eyeless)
. += "-SHOW_EYELESS"
if(show_debrained)
. += "-SHOW_DEBRAINED"
return .
if(hair_hidden)
. += "-HAIR_HIDDEN"
else
. += "-[hairstyle]"
. += "-[override_hair_color || fixed_hair_color || hair_color]"
. += "-[hair_alpha]"
var/hair_gradient_style = get_hair_gradient_style(GRADIENT_HAIR_KEY)
if(hair_gradient_style)
. += "-[hair_gradient_style]"
. += "-[get_hair_gradient_color(GRADIENT_HAIR_KEY)]"
if(LAZYLEN(hair_masks))
. += "-[jointext(hair_masks, "-")]"
return .
GLOBAL_LIST_EMPTY(masked_leg_icons_cache)
/**
@@ -76,8 +76,12 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
item.item_flags |= IN_INVENTORY
if(!item.visual_equipped(src, slot, initial))
return FALSE
if(!(slot & item.slot_flags)) // Things below only update if slotted in (ie: not held)
return TRUE
add_item_coverage(item)
if(item.hair_mask)
LAZYADD(hair_masks, item.hair_mask)
update_hair()
return TRUE
/mob/living/carbon/human/dummy/proc/wipe_state()
+11 -5
View File
@@ -980,12 +980,12 @@
/mob/living/carbon/human/proc/add_eye_color_left(color, color_priority, update_body = TRUE)
LAZYSET(eye_color_left_overrides, "[color_priority]", color)
if (update_body)
update_body()
update_eyes()
/mob/living/carbon/human/proc/add_eye_color_right(color, color_priority, update_body = TRUE)
LAZYSET(eye_color_right_overrides, "[color_priority]", color)
if (update_body)
update_body()
update_eyes()
/mob/living/carbon/human/proc/add_eye_color(color, color_priority, update_body = TRUE)
add_eye_color_left(color, color_priority, update_body = FALSE)
@@ -995,9 +995,12 @@
LAZYREMOVE(eye_color_left_overrides, "[color_priority]")
LAZYREMOVE(eye_color_right_overrides, "[color_priority]")
if (update_body)
update_body()
update_eyes()
/mob/living/carbon/human/proc/get_right_eye_color()
/mob/living/carbon/proc/get_right_eye_color()
return
/mob/living/carbon/human/get_right_eye_color()
if (!LAZYLEN(eye_color_right_overrides))
return eye_color_right
@@ -1010,7 +1013,10 @@
eye_color = eye_color_right_overrides[override_priority]
return eye_color
/mob/living/carbon/human/proc/get_left_eye_color()
/mob/living/carbon/proc/get_left_eye_color()
return
/mob/living/carbon/human/get_left_eye_color()
if (!LAZYLEN(eye_color_left_overrides))
return eye_color_left
@@ -48,27 +48,27 @@ There are several things that need to be remembered:
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
if(!..())
update_worn_undersuit()
update_worn_id()
update_worn_glasses()
update_worn_gloves()
update_worn_ears()
update_worn_shoes()
update_suit_storage()
update_worn_mask()
update_worn_head()
update_worn_belt()
update_worn_back()
update_worn_oversuit()
update_pockets()
update_worn_neck()
update_transform()
//mutations
update_mutations_overlay()
//damage overlays
update_damage_overlays()
. = ..()
update_worn_undersuit()
update_worn_id()
update_worn_glasses()
update_worn_gloves()
update_worn_ears()
update_worn_shoes()
update_suit_storage()
update_worn_mask()
update_worn_head()
update_worn_belt()
update_worn_back()
update_worn_oversuit()
update_pockets()
update_worn_neck()
update_transform()
update_mutations_overlay()
update_damage_overlays()
// These are done via parent call update_body(), keeping them here for clarity
// update_hair()
// update_eyes()
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
@@ -860,57 +860,78 @@ generate/load female uniform sprites matching all previously decided variables
break
/mob/living/carbon/human/update_body(is_creating = FALSE)
update_eyes()
update_underwear()
remove_overlay(BODY_LAYER)
var/list/body_overlays = list()
body_overlays += get_underwear_overlays()
if(length(body_overlays))
overlays_standing[BODY_LAYER] = body_overlays
apply_overlay(BODY_LAYER)
// parent call will update the actual bodyparts
return ..()
/mob/living/carbon/human/proc/update_underwear()
remove_overlay(BODY_LAYER)
/// Returns a list of all underclothing overlays to be applied to the mob
/mob/living/carbon/human/proc/get_underwear_overlays()
. = list()
if(HAS_TRAIT(src, TRAIT_HUSK) || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN) || HAS_TRAIT(src, TRAIT_NO_UNDERWEAR))
return
return .
// Underwear, Undershirts & Socks
var/list/standing = list()
var/active_bodyshapes = get_active_bodyshapes()
if(underwear)
var/datum/sprite_accessory/clothing/underwear/undie_accessory = SSaccessories.underwear_list[underwear]
var/mutable_appearance/underwear_overlay = undie_accessory?.make_appearance(underwear_color, physique, active_bodyshapes)
if(underwear_overlay)
standing += underwear_overlay
. += underwear_overlay
if(undershirt)
var/datum/sprite_accessory/clothing/undershirt/shirt_accessory = SSaccessories.undershirt_list[undershirt]
var/mutable_appearance/shirt_overlay = shirt_accessory?.make_appearance(null, physique, active_bodyshapes)
if(shirt_overlay)
standing += shirt_overlay
. += shirt_overlay
if(socks && num_legs >= 2 && !(bodyshape & BODYSHAPE_DIGITIGRADE))
var/datum/sprite_accessory/clothing/socks/sock_accessory = SSaccessories.socks_list[socks]
var/mutable_appearance/socks_overlay = sock_accessory?.make_appearance(null, physique, active_bodyshapes)
if(socks_overlay)
standing += socks_overlay
. += socks_overlay
if(standing.len)
overlays_standing[BODY_LAYER] = standing
return .
apply_overlay(BODY_LAYER)
/// Updates eye sprites if relevant
/mob/living/proc/update_eyes(refresh = TRUE)
return
/mob/living/carbon/human/proc/update_eyes()
/mob/living/carbon/human/update_eyes(refresh = TRUE)
remove_overlay(EYES_LAYER)
if(HAS_TRAIT(src, TRAIT_HUSK) || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN))
var/obj/item/bodypart/head/noggin = get_bodypart(BODY_ZONE_HEAD)
if(isnull(noggin) || noggin.is_husked || noggin.is_invisible)
return
// 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/eyes/eye_organ = get_organ_slot(ORGAN_SLOT_EYES)
if (!eye_organ)
return
if(refresh)
var/obj/item/organ/eyes/eyes = locate() in noggin
eyes?.refresh(src, call_update = FALSE)
var/obj/item/bodypart/head/noggin = get_bodypart(deprecise_zone(eye_organ.zone)) // Futureproofing for HARS/weird species
if(istype(noggin) && !(noggin?.head_flags & HEAD_EYESPRITES))
return
var/list/eye_overlays = noggin.get_eye_overlays()
if(length(eye_overlays))
overlays_standing[EYES_LAYER] = eye_overlays
apply_overlay(EYES_LAYER)
eye_organ.refresh(call_update = FALSE)
overlays_standing[EYES_LAYER] = eye_organ.generate_body_overlay(src, noggin)
apply_overlay(EYES_LAYER)
/// Updates hair sprites if relevant
/mob/living/proc/update_hair()
return
/mob/living/carbon/human/update_hair()
remove_overlay(HAIR_LAYER)
var/obj/item/bodypart/head/head = get_bodypart(BODY_ZONE_HEAD)
var/list/head_overlays = head?.get_hair_overlays()
if(length(head_overlays))
overlays_standing[HAIR_LAYER] = head_overlays
apply_overlay(HAIR_LAYER)
/// Updates face (as of now, only eye) offsets
/mob/living/carbon/human/update_face_offset()
@@ -931,8 +952,8 @@ generate/load female uniform sprites matching all previously decided variables
apply_overlay(EYES_LAYER)
// Only renders the head of the human
/mob/living/carbon/human/proc/update_body_parts_head_only(update_limb_data)
/// Makes all aspects of the mob invisibile but the head and its associated sprites
/mob/living/carbon/human/proc/render_only_head()
if(!dna?.species)
return
@@ -941,11 +962,13 @@ generate/load female uniform sprites matching all previously decided variables
if(!istype(my_head))
return
my_head.update_limb(is_creating = update_limb_data)
add_overlay(my_head.get_limb_icon(dropped = FALSE, update_on = src))
cut_overlays()
my_head.update_limb()
add_overlay(my_head.get_limb_icon())
update_worn_head()
update_worn_mask()
update_eyes()
update_hair()
/**
* Used to perform regular updates to the limbs of humans with special bodyshapes
@@ -12,8 +12,9 @@
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(clean_face))
RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_HUSK), SIGNAL_REMOVETRAIT(TRAIT_HUSK)), PROC_REF(refresh_obscured))
RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_HUSK), SIGNAL_REMOVETRAIT(TRAIT_HUSK)), PROC_REF(husk_trait_toggle))
RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_INVISIBLE_MAN), SIGNAL_REMOVETRAIT(TRAIT_INVISIBLE_MAN)), PROC_REF(invisible_man_toggle))
RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_NO_UNDERWEAR), SIGNAL_REMOVETRAIT(TRAIT_NO_UNDERWEAR)), PROC_REF(no_underwear_toggle))
/// Gaining or losing [TRAIT_DWARF] updates our height and grants passtable
/mob/living/carbon/human/proc/on_dwarf_trait(datum/source)
@@ -67,8 +68,19 @@
)
playsound(src, SFX_RUSTLE, 50, TRUE, -5, frequency = 0.8)
/mob/living/carbon/human/proc/husk_trait_toggle(datum/source)
SIGNAL_HANDLER
refresh_obscured()
update_body()
/// When [TRAIT_INVISIBLE_MAN] is added or removed we need to update a few things
/mob/living/carbon/human/proc/invisible_man_toggle(datum/source)
SIGNAL_HANDLER
refresh_obscured()
update_visible_name()
update_body()
/// When [TRAIT_NO_UNDERWEAR] is added or removed we need to update our body to hide or show underwear sprites
/mob/living/carbon/human/proc/no_underwear_toggle(datum/source)
SIGNAL_HANDLER
update_body()
@@ -60,7 +60,6 @@
eyes.eye_color_left = human.eye_color_left
eyes.eye_color_right = human.eye_color_right
eyes.bodypart_insert(head)
human.update_body()
head.update_limb()
head.update_icon_dropped()
RegisterSignal(head, COMSIG_QDELETING, PROC_REF(on_head_destroyed))
@@ -112,16 +112,16 @@
currently_flickered = FALSE
ethereal_light.set_light_on(TRUE)
fixed_mut_color = current_color
ethereal.update_body()
ethereal.set_facial_haircolor(current_color, override = TRUE, update = FALSE)
ethereal.set_haircolor(current_color, override = TRUE, update = TRUE)
ethereal.set_haircolor(current_color, override = TRUE, update = FALSE)
ethereal.update_body()
else
ethereal_light.set_light_on(FALSE)
var/dead_color = rgb(128,128,128)
fixed_mut_color = dead_color
ethereal.update_body()
ethereal.set_facial_haircolor(dead_color, override = TRUE, update = FALSE)
ethereal.set_haircolor(dead_color, override = TRUE, update = TRUE)
ethereal.set_haircolor(dead_color, override = TRUE, update = FALSE)
ethereal.update_body()
/datum/species/ethereal/proc/on_emp_act(mob/living/carbon/human/source, severity, protection)
SIGNAL_HANDLER
@@ -128,7 +128,7 @@
var/obj/item/organ/ears/cat/cat_ears = human_for_preview.get_organ_by_type(/obj/item/organ/ears/cat)
if (cat_ears)
cat_ears.color = human_for_preview.hair_color
human_for_preview.update_body()
human_for_preview.update_hair()
/datum/species/human/felinid/get_physical_attributes()
return "Felinids are very similar to humans in almost all respects, with their biggest differences being the ability to lick their wounds, \
@@ -31,7 +31,6 @@
. = ..()
to_chat(new_vampire, "[info_text]")
new_vampire.skin_tone = "albino"
new_vampire.update_body(0)
RegisterSignal(new_vampire, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby))
RegisterSignal(new_vampire, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
if(new_vampire.hud_used)
+4 -2
View File
@@ -172,7 +172,8 @@
if(!(slot & item.slot_flags)) // Things below only update if slotted in (ie: not held)
return
if(item.hair_mask)
update_body()
LAZYADD(hair_masks, item.hair_mask)
update_hair()
add_item_coverage(item)
/mob/living/carbon/has_unequipped(obj/item/item)
@@ -182,7 +183,8 @@
hud_used?.update_locked_slots()
if(item.hair_mask)
update_body()
LAZYREMOVE(hair_masks, item.hair_mask)
update_hair()
remove_item_coverage(item)
/mob/living/carbon/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE)
+1 -1
View File
@@ -2413,7 +2413,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
return
if(. <= UNCONSCIOUS || new_stat >= UNCONSCIOUS)
update_body() // to update eyes
update_eyes()
switch(.) //Previous stat.
if(CONSCIOUS)
+4 -6
View File
@@ -513,19 +513,17 @@
REMOVE_TRAIT(src, TRAIT_HUSK, source)
if(HAS_TRAIT(src, TRAIT_HUSK))
return FALSE
update_body()
UnregisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_UNHUSKABLE))
return TRUE
/mob/living/proc/become_husk(source)
if(HAS_TRAIT(src, TRAIT_UNHUSKABLE))
return
return FALSE
var/was_husk = HAS_TRAIT(src, TRAIT_HUSK)
ADD_TRAIT(src, TRAIT_HUSK, source)
if (was_husk)
return
update_body()
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_UNHUSKABLE), PROC_REF(became_unhuskable))
if (!was_husk)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_UNHUSKABLE), PROC_REF(became_unhuskable))
return TRUE
/// Called when we become unhuskable while already husked
/mob/living/proc/became_unhuskable()
-3
View File
@@ -95,9 +95,6 @@
/mob/proc/update_body()
return
/mob/proc/update_hair()
return
///Updates the glasses overlay & HUD element.
/mob/proc/update_worn_glasses()
return
@@ -769,7 +769,6 @@
invisible_man.add_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS, TRAIT_NO_BLOOD_OVERLAY), type)
invisible_man.update_body()
invisible_man.remove_from_all_data_huds()
invisible_man.sound_environment_override = SOUND_ENVIROMENT_PHASED
@@ -781,7 +780,6 @@
to_chat(invisible_man, span_notice("As you sober up, opacity once again returns to your body meats."))
invisible_man.update_body()
invisible_man.sound_environment_override = NONE
if(!invisible_man.hud_used)
@@ -3501,7 +3501,7 @@
if (eyes && !IS_ROBOTIC_ORGAN(eyes))
eyes.eye_color_left = color
eyes.eye_color_right = color
affected_human.update_body()
affected_human.update_eyes()
/datum/reagent/luminescent_fluid/red
name = "Red Luminiscent Fluid"
+2 -1
View File
@@ -281,6 +281,7 @@
if (length(drop_results))
butcher_drops = string_list(drop_results)
butcher_drop_cache[type] = butcher_drops
update_limb(TRUE)
update_icon_dropped()
refresh_bleed_rate()
@@ -1168,7 +1169,7 @@
update_draw_color()
if(!is_creating || !owner)
return
return FALSE
// There should technically to be an ishuman(owner) check here, but it is absent because no basetype carbons use bodyparts
// No, xenos don't actually use bodyparts. Don't ask.
@@ -328,7 +328,7 @@
// behavior within said bodyparts list. We sort it here, as it's the only place we make changes to bodyparts.
new_limb_owner.bodyparts = sort_list(new_limb_owner.bodyparts, GLOBAL_PROC_REF(cmp_bodypart_by_body_part_asc))
new_limb_owner.updatehealth()
new_limb_owner.update_body()
new_limb_owner.update_body() // updates lips + hair + eyes
new_limb_owner.update_damage_overlays()
if(!special)
new_limb_owner.hud_used?.update_locked_slots()
@@ -372,7 +372,7 @@
sexy_chad.lip_color = lip_color
new_head_owner.updatehealth()
new_head_owner.update_body()
new_head_owner.update_body() // updates lips + hair + eyes
new_head_owner.update_damage_overlays()
/obj/item/bodypart/arm/try_attach_limb(mob/living/carbon/new_arm_owner, special, lazy)
+15 -53
View File
@@ -44,10 +44,6 @@
var/hair_color = COLOR_BLACK
/// Hair alpha
var/hair_alpha = 255
/// Is the hair currently hidden by something?
var/hair_hidden = FALSE
/// Lazy initialized hashset of all hair mask types that should be applied
var/list/hair_masks
///Facial hair style
var/facial_hairstyle = "Shaved"
@@ -55,8 +51,6 @@
var/facial_hair_color = COLOR_BLACK
///Facial hair alpha
var/facial_hair_alpha = 255
///Is the facial hair currently hidden by something?
var/facial_hair_hidden = FALSE
/// Gradient styles, if any
var/list/gradient_styles
@@ -89,15 +83,8 @@
/// Offset to apply to overlays placed on the face
var/datum/worn_feature_offset/worn_face_offset
VAR_PROTECTED
/// Draw this head as "debrained"
show_debrained = FALSE
/// Draw this head as missing eyes
show_eyeless = FALSE
/// Can this head be dismembered normally?
can_dismember = FALSE
/// Can this head be dismembered normally?
VAR_PROTECTED/can_dismember = FALSE
/obj/item/bodypart/head/Initialize(mapload)
. = ..()
@@ -188,50 +175,25 @@
/obj/item/bodypart/head/update_limb(dropping_limb, is_creating)
. = ..()
if(!isnull(owner))
if(isnull(owner))
return
if(is_husked)
ADD_TRAIT(src, TRAIT_DISFIGURED, HUSK_TRAIT)
else
REMOVE_TRAIT(src, TRAIT_DISFIGURED, HUSK_TRAIT)
if(is_creating)
real_name = owner.real_name
if(is_husked)
ADD_TRAIT(src, TRAIT_DISFIGURED, HUSK_TRAIT)
else
REMOVE_TRAIT(src, TRAIT_DISFIGURED, HUSK_TRAIT)
update_hair_and_lips(dropping_limb, is_creating)
// Ensures putting organs in and removing organs from our head always updates the limb
/obj/item/bodypart/head/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
if(isorgan(arrived) && !ismob(loc))
addtimer(CALLBACK(src, PROC_REF(update_head_on_organ_movement)), 1, TIMER_UNIQUE|TIMER_DELETE_ME)
/obj/item/bodypart/head/Exited(atom/movable/gone, direction)
. = ..()
if(isorgan(gone) && !ismob(loc))
addtimer(CALLBACK(src, PROC_REF(update_head_on_organ_movement)), 1, TIMER_UNIQUE|TIMER_DELETE_ME)
/obj/item/bodypart/head/proc/update_head_on_organ_movement()
update_limb()
update_icon_dropped()
copy_appearance_from(owner)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/obj/item/bodypart/head/get_limb_icon(dropped, mob/living/carbon/update_on)
/obj/item/bodypart/head/get_limb_icon(dropped)
. = ..()
. += get_hair_and_lips_icon(dropped)
// We need to get the eyes if we are dropped (ugh)
if(!dropped)
return
if(dropped) // These overlays are applied as standing overlays so we only need them if dropped
. += get_hair_overlays(dropped)
. += get_eye_overlays(dropped)
var/obj/item/organ/eyes/eyes = locate(/obj/item/organ/eyes) in src
if(!eyes)
if (!(head_flags & HEAD_EYEHOLES))
return
var/image/no_eyes = image('icons/mob/human/human_eyes.dmi', "eyes_missing", -EYES_LAYER, SOUTH)
worn_face_offset?.apply_offset(no_eyes)
. += no_eyes
return
if(head_flags & HEAD_EYESPRITES)
for (var/mutable_appearance/overlay as anything in eyes.generate_body_overlay(null, src))
. += image(overlay, dir = SOUTH)
. += get_lips_overlays(dropped)
/obj/item/bodypart/head/get_voice(add_id_name)
return "The head of [get_face_name()]"
@@ -1,49 +1,3 @@
#define SET_OVERLAY_VALUE(overlay,variable,value) if(overlay) overlay.variable = value
/// Part of `update_limb()`, basically does all the head specific icon stuff.
/obj/item/bodypart/head/proc/update_hair_and_lips(dropping_limb, is_creating)
var/mob/living/carbon/human/human_head_owner = owner
//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(INCLUDE_ABSTRACT))
if(worn_item.hair_mask)
LAZYSET(hair_masks, worn_item.hair_mask, TRUE)
hair_hidden = !!(human_head_owner.obscured_slots & HIDEHAIR)
facial_hair_hidden = !!(human_head_owner.obscured_slots & HIDEFACIALHAIR)
if(is_husked)
hair_hidden = TRUE
facial_hair_hidden = TRUE
//HIDDEN CHECKS END
if(owner)
if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY))
show_debrained = TRUE
else
show_debrained = FALSE
if(!owner.get_organ_slot(ORGAN_SLOT_EYES))
show_eyeless = TRUE
else
show_eyeless = FALSE
else
if(!hair_hidden && !(locate(/obj/item/organ/brain) in src))
show_debrained = TRUE
else
show_debrained = FALSE
if(!(locate(/obj/item/organ/eyes) in src))
show_eyeless = TRUE
else
show_eyeless = FALSE
if(!is_creating || !owner)
return
copy_appearance_from(human_head_owner)
/obj/item/bodypart/head/proc/copy_appearance_from(mob/living/carbon/human/target, overwrite_eyes = FALSE)
var/datum/species/target_species = target.dna.species
@@ -77,110 +31,145 @@
skin_tone = ""
species_color = ""
/obj/item/bodypart/head/proc/get_hair_and_lips_icon(dropped)
SHOULD_CALL_PARENT(TRUE)
RETURN_TYPE(/list)
/// Returns a list of all overlays associated with the lips
/obj/item/bodypart/head/proc/get_lips_overlays(dropped)
. = list()
if(!lip_style || is_husked || is_invisible || (owner?.obscured_slots & HIDEFACIALHAIR) || !(head_flags & HEAD_LIPS))
return .
var/atom/location = loc || owner || src
var/image_dir = null
if (dropped)
image_dir = SOUTH
var/image/lip_overlay = image('icons/mob/human/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, dir = (dropped ? SOUTH : null))
lip_overlay.color = lip_color
worn_face_offset?.apply_offset(lip_overlay)
. += lip_overlay
return .
var/datum/sprite_accessory/sprite_accessory
if(!facial_hair_hidden && lip_style && (head_flags & HEAD_LIPS))
//not a sprite accessory, don't ask
//Overlay
var/image/lip_overlay = image('icons/mob/human/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, dir = image_dir)
lip_overlay.color = lip_color
//Offsets
worn_face_offset?.apply_offset(lip_overlay)
. += lip_overlay
/// Returns a list of all hair/facial hair related overlays, or alternatively the debrained overlay if applicable
/obj/item/bodypart/head/proc/get_hair_overlays(dropped)
. = list()
var/hair_hidden = is_husked || is_invisible || (owner?.obscured_slots & HIDEHAIR)
var/facial_hair_hidden = is_husked || is_invisible || (owner?.obscured_slots & HIDEFACIALHAIR)
var/image/facial_hair_overlay
if(!facial_hair_hidden && facial_hairstyle && (head_flags & HEAD_FACIAL_HAIR))
sprite_accessory = SSaccessories.facial_hairstyles_list[facial_hairstyle]
if(sprite_accessory)
//Overlay
facial_hair_overlay = image(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER, dir = image_dir)
facial_hair_overlay.alpha = facial_hair_alpha
//Emissive blocker
if(blocks_emissive != EMISSIVE_BLOCK_NONE)
var/mutable_appearance/em_block = emissive_blocker(facial_hair_overlay.icon, facial_hair_overlay.icon_state, location, alpha = facial_hair_alpha)
if (dropped)
em_block = image(em_block, dir = SOUTH)
facial_hair_overlay.overlays += em_block
//Offsets
worn_face_offset?.apply_offset(facial_hair_overlay)
. += facial_hair_overlay
//Gradients
var/facial_hair_gradient_style = get_hair_gradient_style(GRADIENT_FACIAL_HAIR_KEY)
if(facial_hair_gradient_style != "None")
var/facial_hair_gradient_color = get_hair_gradient_color(GRADIENT_FACIAL_HAIR_KEY)
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, dropped)
. += facial_hair_gradient_overlay
if(!facial_hair_hidden && (head_flags & HEAD_FACIAL_HAIR))
. += get_base_facial_hair_overlays(dropped)
var/list/all_hair_overlays = list()
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)
//Hair masks
var/icon/base_icon = icon(hair_sprite_accessory.getCachedIcon(hair_masks))
//Overlay
all_hair_overlays += image(base_icon, layer=-HAIR_LAYER, dir = image_dir)
//If we have any hair appendages (ponytails, etc.) sticking out on a particular side, we need to add an additional hair layer to go above hats/helmets for the sides they stick out on
if(LAZYLEN(hair_sprite_accessory.hair_appendages_outer))
var/strictly_masked_zones = NONE
for(var/datum/hair_mask/mask as anything in hair_masks)
strictly_masked_zones |= mask.strict_coverage_zones
for(var/appendage_icon_state in hair_sprite_accessory.hair_appendages_outer)
var/appendage_zone = hair_sprite_accessory.hair_appendages_outer[appendage_icon_state]
if(!(appendage_zone & strictly_masked_zones)) // if there are no strict masks in this zone
all_hair_overlays += image(hair_sprite_accessory.icon, icon_state=appendage_icon_state, layer=-OUTER_HAIR_LAYER, dir = image_dir)
for(var/image/hair_overlay as anything in all_hair_overlays)
hair_overlay.alpha = hair_alpha
hair_overlay.pixel_z = hair_sprite_accessory.y_offset
//Emissive blocker
if(blocks_emissive != EMISSIVE_BLOCK_NONE)
var/mutable_appearance/em_block = emissive_blocker(hair_overlay.icon, hair_overlay.icon_state, location, alpha = hair_alpha)
if (dropped)
em_block = image(em_block, dir = SOUTH)
hair_overlay.overlays += em_block
//Offsets
worn_face_offset?.apply_offset(hair_overlay)
. += hair_overlay
//Gradients
var/hair_gradient_style = get_hair_gradient_style(GRADIENT_HAIR_KEY)
if(hair_gradient_style != "None")
var/hair_gradient_color = get_hair_gradient_color(GRADIENT_HAIR_KEY)
var/image/hair_gradient_overlay = get_gradient_overlay(base_icon, hair_overlay.layer, SSaccessories.hair_gradients_list[hair_gradient_style], hair_gradient_color, dropped)
hair_gradient_overlay.pixel_z = hair_sprite_accessory.y_offset
. += hair_gradient_overlay
if(show_debrained && (head_flags & HEAD_DEBRAIN))
. += get_debrain_overlay(dropped)
if(show_eyeless && (head_flags & HEAD_EYEHOLES))
. += get_eyeless_overlay(dropped)
//HAIR COLOR START
if(override_hair_color)
SET_OVERLAY_VALUE(facial_hair_overlay, color, override_hair_color)
for(var/image/hair_overlay as anything in all_hair_overlays)
SET_OVERLAY_VALUE(hair_overlay, color, override_hair_color)
else if(fixed_hair_color)
SET_OVERLAY_VALUE(facial_hair_overlay, color, fixed_hair_color)
for(var/image/hair_overlay as anything in all_hair_overlays)
SET_OVERLAY_VALUE(hair_overlay, color, fixed_hair_color)
else
SET_OVERLAY_VALUE(facial_hair_overlay, color, facial_hair_color)
for(var/image/hair_overlay as anything in all_hair_overlays)
SET_OVERLAY_VALUE(hair_overlay, color, hair_color)
//HAIR COLOR END
if(!hair_hidden)
var/obj/item/organ/brain/brain = locate() in src
if(QDELETED(brain) && (head_flags & HEAD_DEBRAIN))
. += get_debrain_overlay(dropped)
else if(head_flags & HEAD_HAIR)
. += get_base_hair_overlays(dropped)
return .
#undef SET_OVERLAY_VALUE
/// Used in constructing the hair overlays - handles just facial hair
/obj/item/bodypart/head/proc/get_base_facial_hair_overlays(dropped)
PRIVATE_PROC(TRUE)
. = list()
var/datum/sprite_accessory/facial_hair/sprite_accessory = SSaccessories.facial_hairstyles_list[facial_hairstyle]
if(!sprite_accessory || sprite_accessory.icon_state == SPRITE_ACCESSORY_NONE)
return .
var/atom/location = loc || owner || src
var/image_dir = dropped ? SOUTH : null
// Overlay
var/image/facial_hair_overlay = image(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER, dir = image_dir)
facial_hair_overlay.alpha = facial_hair_alpha
set_overlay_hair_color(facial_hair_overlay)
// Emissive blocker
if(blocks_emissive != EMISSIVE_BLOCK_NONE)
var/mutable_appearance/em_block = emissive_blocker(facial_hair_overlay.icon, facial_hair_overlay.icon_state, location, alpha = facial_hair_alpha)
if (dropped)
em_block = image(em_block, dir = SOUTH)
facial_hair_overlay.overlays += em_block
//Offsets
worn_face_offset?.apply_offset(facial_hair_overlay)
. += facial_hair_overlay
//Gradients
var/facial_hair_gradient_style = get_hair_gradient_style(GRADIENT_FACIAL_HAIR_KEY)
if(facial_hair_gradient_style != SPRITE_ACCESSORY_NONE)
var/facial_hair_gradient_color = get_hair_gradient_color(GRADIENT_FACIAL_HAIR_KEY)
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, dropped)
. += facial_hair_gradient_overlay
return .
/// Used in constructing the hair overlays - handles just the hair on top of the head
/obj/item/bodypart/head/proc/get_base_hair_overlays(dropped)
PRIVATE_PROC(TRUE)
. = list()
var/datum/sprite_accessory/hair/hair_sprite_accessory = SSaccessories.hairstyles_list[hairstyle]
if(!hair_sprite_accessory || hair_sprite_accessory.icon_state == SPRITE_ACCESSORY_NONE)
return .
var/atom/location = loc || owner || src
var/image_dir = dropped ? SOUTH : null
var/list/all_hair_overlays = list()
// Hair masks
var/icon/base_icon = icon(hair_sprite_accessory.getCachedIcon(owner?.hair_masks))
// Overlay
all_hair_overlays += image(base_icon, layer = -HAIR_LAYER, dir = image_dir)
// If we have any hair appendages (ponytails, etc.) sticking out on a particular side,
// we need to add an additional hair layer to go above hats/helmets for the sides they stick out on
if(LAZYLEN(hair_sprite_accessory.hair_appendages_outer))
var/strictly_masked_zones = NONE
for(var/datum/hair_mask/mask as anything in owner?.hair_masks)
strictly_masked_zones |= mask.strict_coverage_zones
for(var/appendage_icon_state in hair_sprite_accessory.hair_appendages_outer)
var/appendage_zone = hair_sprite_accessory.hair_appendages_outer[appendage_icon_state]
if(!(appendage_zone & strictly_masked_zones)) // if there are no strict masks in this zone
all_hair_overlays += image(hair_sprite_accessory.icon, icon_state = appendage_icon_state, layer = -OUTER_HAIR_LAYER, dir = image_dir)
for(var/image/hair_overlay as anything in all_hair_overlays)
set_overlay_hair_color(hair_overlay)
hair_overlay.alpha = hair_alpha
hair_overlay.pixel_z = hair_sprite_accessory.y_offset
// Emissive blocker
if(blocks_emissive != EMISSIVE_BLOCK_NONE)
var/mutable_appearance/em_block = emissive_blocker(hair_overlay.icon, hair_overlay.icon_state, location, alpha = hair_alpha)
if (dropped)
em_block = image(em_block, dir = SOUTH)
hair_overlay.overlays += em_block
// Offsets
worn_face_offset?.apply_offset(hair_overlay)
. += hair_overlay
// Gradients
var/hair_gradient_style = get_hair_gradient_style(GRADIENT_HAIR_KEY)
if(hair_gradient_style != SPRITE_ACCESSORY_NONE)
var/hair_gradient_color = get_hair_gradient_color(GRADIENT_HAIR_KEY)
var/image/hair_gradient_overlay = get_gradient_overlay(base_icon, hair_overlay.layer, SSaccessories.hair_gradients_list[hair_gradient_style], hair_gradient_color, dropped)
hair_gradient_overlay.pixel_z = hair_sprite_accessory.y_offset
. += hair_gradient_overlay
return .
/// Helper for setting hair color of an overlay appropriately
/obj/item/bodypart/head/proc/set_overlay_hair_color(image/hair_overlay)
PRIVATE_PROC(TRUE)
if(override_hair_color)
hair_overlay.color = override_hair_color
else if(fixed_hair_color)
hair_overlay.color = fixed_hair_color
else
hair_overlay.color = hair_color
/// Returns a list of all eye related overlays, or an eyeless overlay if applicable
/obj/item/bodypart/head/proc/get_eye_overlays(dropped)
. = list()
var/obj/item/organ/eyes/eyes = locate() in src
if(QDELETED(eyes))
if(head_flags & HEAD_EYEHOLES)
. += get_eyeless_overlay(dropped)
return .
if(head_flags & HEAD_EYESPRITES)
. += eyes.generate_body_overlay(src)
return .
/// Returns an appropriate debrained overlay
/obj/item/bodypart/head/proc/get_debrain_overlay(dropped)
@@ -251,7 +240,7 @@
hopefully_a_head?.stored_lipstick_trait = apply_trait
if(update)
update_body_parts()
update_body() // lips is done as a body layer
/**
* A wrapper for [mob/living/carbon/human/proc/update_lips] that sets the lip style and color to null.
@@ -279,7 +268,7 @@
my_head?.hairstyle = new_style
if(update)
update_body_parts()
update_hair()
/**
* Set the hair color of a human.
@@ -300,7 +289,7 @@
my_head?.hair_color = hex_string
if(update)
update_body_parts()
update_hair()
/**
* Get the hair gradient style of a human.
@@ -352,7 +341,7 @@
LAZYSET(my_head.gradient_styles, GRADIENT_HAIR_KEY, new_style)
if(update)
update_body_parts()
update_hair()
/**
* Get the hair gradient color of a human.
@@ -406,7 +395,7 @@
LAZYSET(my_head.gradient_colors, GRADIENT_HAIR_KEY, new_color)
if(update)
update_body_parts()
update_hair()
/**
* Set the facial hair style of a human.
@@ -422,7 +411,7 @@
my_head?.facial_hairstyle = new_style
if(update)
update_body_parts()
update_hair()
/**
* Set the facial hair color of a human.
@@ -443,7 +432,7 @@
my_head?.facial_hair_color = hex_string
if(update)
update_body_parts()
update_hair()
/**
* Set the facial hair gradient style of a human.
@@ -462,7 +451,7 @@
LAZYSET(my_head.gradient_styles, GRADIENT_FACIAL_HAIR_KEY, new_style)
if(update)
update_body_parts()
update_hair()
/**
* Set the facial hair gradient color of a human.
@@ -481,4 +470,4 @@
LAZYSET(my_head.gradient_colors, GRADIENT_FACIAL_HAIR_KEY, new_color)
if(update)
update_body_parts()
update_hair()
@@ -112,8 +112,11 @@
/// Refreshes the visuals of the eyes
/// If call_update is TRUE, we also will call update_body
/obj/item/organ/eyes/proc/refresh(mob/living/carbon/eye_owner = owner, call_update = TRUE)
owner.update_sight()
owner.update_tint()
if(isnull(eye_owner))
return
eye_owner.update_sight()
eye_owner.update_tint()
if(!ishuman(eye_owner))
return
@@ -131,7 +134,7 @@
affected_human.add_fov_trait(type, native_fov)
if(call_update)
affected_human.update_body()
affected_human.update_eyes()
/obj/item/organ/eyes/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
@@ -144,7 +147,7 @@
if(native_fov)
organ_owner.remove_fov_trait(type)
if(!special)
human_owner.update_body()
human_owner.update_eyes(refresh = FALSE)
// become blind (if not special)
if(!special)
@@ -173,6 +176,20 @@
SIGNAL_REMOVETRAIT(TRAIT_REFLECTIVE_EYES),
))
/obj/item/organ/eyes/on_bodypart_insert(obj/item/bodypart/limb)
. = ..()
if(ishuman(limb.owner))
limb.owner.update_eyes(refresh = FALSE)
else
limb.update_icon_dropped()
/obj/item/organ/eyes/on_bodypart_remove(obj/item/bodypart/limb, movement_flags)
. = ..()
if(ishuman(limb.owner))
limb.owner.update_eyes(refresh = FALSE)
else
limb.update_icon_dropped()
///Called whenever the luminescent and/or reflective eyes traits are added or removed
/obj/item/organ/eyes/proc/on_shiny_eyes_trait_update(mob/living/carbon/human/source)
SIGNAL_HANDLER
@@ -182,7 +199,7 @@
. = ..()
if (ishuman(owner))
refresh_atom_color_overrides()
owner.update_body()
owner.update_eyes()
/// Adds eye color overrides to our owner from our atom color
/obj/item/organ/eyes/proc/refresh_atom_color_overrides()
@@ -285,47 +302,42 @@
// Always show if we have an appendix
return ..() || (owner.stat != DEAD && !HAS_TRAIT(owner, TRAIT_KNOCKEDOUT) && (owner.is_blind() || owner.is_nearsighted()))
/// This proc generates a list of overlays that the eye should be displayed using for the given parent
/obj/item/organ/eyes/proc/generate_body_overlay(mob/living/carbon/human/parent, obj/item/bodypart/limb)
if(isnull(eye_icon_state))
/// This proc generates a list of overlays that the eye displays on the given head
/obj/item/organ/eyes/proc/generate_body_overlay(obj/item/bodypart/head/my_head)
if(!eye_icon_state || isnull(my_head))
return list()
var/mutable_appearance/eye_left = mutable_appearance(eye_icon, "[eye_icon_state]_l", -EYES_LAYER, parent || limb)
var/mutable_appearance/eye_right = mutable_appearance(eye_icon, "[eye_icon_state]_r", -EYES_LAYER, parent || limb)
var/eye_dir = my_head.owner ? null : SOUTH
var/mutable_appearance/eye_left = mutable_appearance(eye_icon, "[eye_icon_state]_l", -EYES_LAYER)
var/mutable_appearance/eye_right = mutable_appearance(eye_icon, "[eye_icon_state]_r", -EYES_LAYER)
eye_left.dir = eye_dir
eye_right.dir = eye_dir
var/list/overlays = list(eye_left, eye_right)
if(!(parent?.obscured_slots & HIDEEYES))
overlays += get_emissive_overlays(eye_left, eye_right, parent || limb)
if(my_head.owner && !(my_head.owner.obscured_slots & HIDEEYES))
overlays += get_emissive_overlays(eye_left, eye_right, my_head)
if(!limb)
return overlays
// Futureproofing for HARS/weird species
var/obj/item/bodypart/head/head = astype(limb, /obj/item/bodypart/head)
if(head?.head_flags & HEAD_EYECOLOR)
if (parent)
eye_right.color = parent.get_right_eye_color()
eye_left.color = parent.get_left_eye_color()
var/list/eyelids = setup_eyelids(eye_left, eye_right, parent)
if (LAZYLEN(eyelids))
overlays += eyelids
else
eye_right.color = eye_color_right
eye_left.color = eye_color_left
if(my_head.head_flags & HEAD_EYECOLOR)
eye_right.color = eye_color_right || my_head.owner?.get_right_eye_color()
eye_left.color = eye_color_left || my_head.owner?.get_left_eye_color()
var/list/eyelids = get_eyelid_overlays(eye_left, eye_right, my_head)
if (LAZYLEN(eyelids))
overlays += eyelids
if (scarring & RIGHT_EYE_SCAR)
var/mutable_appearance/right_scar = mutable_appearance('icons/mob/human/human_eyes.dmi', "eye_scar_right", -EYES_LAYER, parent || limb)
right_scar.color = limb.draw_color
var/mutable_appearance/right_scar = mutable_appearance('icons/mob/human/human_eyes.dmi', "eye_scar_right", -EYES_LAYER)
right_scar.color = my_head.draw_color
overlays += right_scar
if (scarring & LEFT_EYE_SCAR)
var/mutable_appearance/left_scar = mutable_appearance('icons/mob/human/human_eyes.dmi', "eye_scar_left", -EYES_LAYER, parent || limb)
left_scar.color = limb.draw_color
var/mutable_appearance/left_scar = mutable_appearance('icons/mob/human/human_eyes.dmi', "eye_scar_left", -EYES_LAYER)
left_scar.color = my_head.draw_color
overlays += left_scar
if(head?.worn_face_offset)
if(my_head.worn_face_offset)
for (var/mutable_appearance/overlay as anything in overlays)
head.worn_face_offset.apply_offset(overlay)
my_head.worn_face_offset.apply_offset(overlay)
return overlays
@@ -392,7 +404,7 @@
owner.assign_nearsightedness(TRAIT_LEFT_EYE_SCAR, 1, FALSE)
if((scarring & RIGHT_EYE_SCAR) && (scarring & LEFT_EYE_SCAR))
owner.become_blind(EYE_SCARRING_TRAIT)
owner.update_body()
owner.update_eyes()
/obj/item/organ/eyes/proc/fix_scar(side)
if (!(scarring & side))
@@ -404,7 +416,7 @@
return
owner.cure_nearsighted(side == RIGHT_EYE_SCAR ? TRAIT_RIGHT_EYE_SCAR : TRAIT_LEFT_EYE_SCAR)
owner.cure_blind(EYE_SCARRING_TRAIT)
owner.update_body()
owner.update_eyes()
#undef OFFSET_X
#undef OFFSET_Y
@@ -448,10 +460,10 @@
#define BLINK_LOOPS 5
/// Modifies eye overlays to also act as eyelids, both for blinking and for when you're knocked out cold
/obj/item/organ/eyes/proc/setup_eyelids(mutable_appearance/eye_left, mutable_appearance/eye_right, mob/living/carbon/human/parent)
var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD)
/obj/item/organ/eyes/proc/get_eyelid_overlays(mutable_appearance/eye_left, mutable_appearance/eye_right, obj/item/bodypart/head/my_head)
var/mob/living/carbon/human/parent = my_head.owner
// Robotic eyes or colorless heads don't get the privelege of having eyelids
if (IS_ROBOTIC_ORGAN(src) || !my_head.draw_color || HAS_TRAIT(parent, TRAIT_NO_EYELIDS))
if (isnull(parent) || IS_ROBOTIC_ORGAN(src) || !my_head.draw_color || HAS_TRAIT(parent, TRAIT_NO_EYELIDS))
return
var/list/base_color = rgb2num(my_head.draw_color, COLORSPACE_HSL)
@@ -558,12 +558,12 @@
"Security Status" = JUDGE_RECORDCHECK,
)
/obj/item/organ/eyes/robotic/tacvisor/generate_body_overlay(mob/living/carbon/human/parent, obj/item/bodypart/limb)
var/mutable_appearance/visor_overlay = mutable_appearance(eye_icon, eye_icon_state, -EYES_LAYER, parent || limb)
/obj/item/organ/eyes/robotic/tacvisor/generate_body_overlay(obj/item/bodypart/limb)
var/mutable_appearance/visor_overlay = mutable_appearance(eye_icon, eye_icon_state, -EYES_LAYER)
var/list/eye_overlays = list(visor_overlay)
var/mob/living/carbon/human/parent = limb.owner
if (parent && parent.appears_alive() && !HAS_TRAIT(parent, TRAIT_KNOCKEDOUT))
var/mutable_appearance/display_overlay = mutable_appearance(eye_icon, "[eye_icon_state]_[LOWER_TEXT(visor_display)]", -EYES_LAYER, parent)
var/mutable_appearance/display_overlay = mutable_appearance(eye_icon, "[eye_icon_state]_[LOWER_TEXT(visor_display)]", -EYES_LAYER)
eye_overlays += display_overlay
if(!(parent.obscured_slots & HIDEEYES))
eye_overlays += emissive_appearance(eye_icon, "[eye_icon_state]_[LOWER_TEXT(visor_display)]", parent, -EYES_LAYER)
+1
View File
@@ -287,6 +287,7 @@
#include "screenshot_airlocks.dm"
#include "screenshot_antag_icons.dm"
#include "screenshot_basic.dm"
#include "screenshot_debrain.dm"
#include "screenshot_digi.dm"
#include "screenshot_dynamic_human_icons.dm"
#include "screenshot_high_luminosity_eyes.dm"
@@ -0,0 +1,32 @@
/// Tests debrained overlay. And also eyeless since we're here
/datum/unit_test/screenshot_debrain
var/last_frame = 1
/datum/unit_test/screenshot_debrain/Run()
var/mob/living/carbon/human/human = allocate(/mob/living/carbon/human/dummy/consistent)
var/obj/item/organ/brain/their_brain = human.get_organ_by_type(__IMPLIED_TYPE__)
var/obj/item/organ/eyes/their_eyes = human.get_organ_by_type(__IMPLIED_TYPE__)
human.set_hairstyle(/datum/sprite_accessory/hair/bedheadv4::name)
human.set_facial_hairstyle(/datum/sprite_accessory/facial_hair/vlongbeard::name)
human.set_haircolor(COLOR_BLACK)
human.set_facial_haircolor(COLOR_BLACK)
var/icon/final_icon = icon('icons/effects/effects.dmi', "nothing")
// record pre-test appearance
final_icon.Insert(getFlatIcon(human, no_anim = TRUE), dir = SOUTH, frame = 1)
// remove brain, record appearance
their_brain.Remove(human)
final_icon.Insert(getFlatIcon(human, no_anim = TRUE), dir = NORTH, frame = 1)
// remove eyes, record appearance
their_eyes.Remove(human)
final_icon.Insert(getFlatIcon(human, no_anim = TRUE), dir = EAST, frame = 1)
// re-add organs, record appearance
their_brain.Insert(human)
their_eyes.Insert(human)
final_icon.Insert(getFlatIcon(human, no_anim = TRUE), dir = WEST, frame = 1)
// test the final screenshot
test_screenshot("head_organs", final_icon)
Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB