mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 04:57:57 +01:00
Moves hair and eyes into standing overlays (#95781)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Reference in New Issue
Block a user