Height and minor bodypart overlay refactor (#96570)

## About The Pull Request

### Main changes

Height is no longer applied in `apply_overlay`

There is now a proc titled `apply_height()` which is passed an
appearance and a body area, and handles either applying a filter or
adjusting the offset of the appearance up or down

`apply_height` is now called directly when applying item appearances
(ie, `update_worn_x`)
`apply_height` is also called directly in `get_limb_icon` (as height is
included in limb render keys).

### Other changes

Bodypart overlays were cleaned up a bit. You can now apply and remove
bodypart overlays directly with just the typepath, which is a bit more
convenient.

Bodypart textures were split into a separate type. Previously, textures
relied on insertion order to be "correctly" added (any bodypart overlays
added later would not be modified by the bodypart texture). Now

Fixed a bug with cybernetics while I was there. They reskin by changing
DMI so they needed to have their DMI included in their render keys.

## Why It's Good For The Game

This allows us to be more specific and less wasteful about applying
height filters and whatnot - We can now specify whether certain overlays
are offset or given a filter.

For example: In the past, horns and frills were filtered solely because
they were attached to the head and the head was filtered.
We couldn't independently say "Offsets the horns and frills, they don't
need filters".
But now, not only are we able to say "rather than filter the head, just
apply an offset", we can also say "horns and frills should be offset
rather than filtered".

TL;DR fixes the issue where horns or cat ears are cut off by height
filters, yippee.

## Changelog

🆑 Melbert
fix: Cybernetic reskinning should break less. 
fix: Horns and cat ears should be cut off less by height.
fix: Bodypart textures should apply more consistently. 
refactor: Mutant parts like moth wings, lizard tails, cat eats, etc.
have been refactored a tiny bit, report any oddities.
refactor: Bodypart textures were refactored a tiny bit, report any
oddities.
refactor: Refactored the way height works, report anything weird looking
things involving that.
/🆑
This commit is contained in:
MrMelbert
2026-06-27 10:28:43 +02:00
committed by GitHub
parent a05270b364
commit 21ea64aec5
40 changed files with 371 additions and 309 deletions
+113 -22
View File
@@ -160,7 +160,9 @@
var/list/applied_items
///A list of all bodypart overlays to draw
var/list/bodypart_overlays = list()
var/list/bodypart_overlays
///A list of all bodypart textures to apply
var/list/bodypart_textures
/// Type of an attack from this limb does. Arms will do punches, Legs for kicks, and head for bites. (TO ADD: tactical chestbumps)
var/attack_type = BRUTE
@@ -215,7 +217,7 @@
/// get_damage() / total_damage must surpass this to allow our limb to be disabled, even temporarily, by an EMP.
var/robotic_emp_paralyze_damage_percent_threshold = 0.3
/// A potential texturing overlay to put on the limb
var/datum/bodypart_overlay/texture/texture_bodypart_overlay
var/datum/bodypart_texture/texture_bodypart_overlay
/// Lazylist of /datum/status_effect/grouped/bodypart_effect types. Instances of this are applied to the carbon when added the limb is attached, and merged with similair limbs
var/list/bodypart_effects
/// The cached info about the blood this organ belongs to, set during on_removal()
@@ -301,6 +303,14 @@
QDEL_LIST_ASSOC_VAL(applied_items)
QDEL_LAZYLIST(scars)
// Overlays and textures may be owned by something else like a status effect,
// so we'll just remove them all rather than delete them
// Worst case scenario they'll just get swept up by GC and which is fine
for(var/datum/bodypart_overlay/remaining_overlay in bodypart_overlays)
remove_bodypart_overlay(remaining_overlay, update = FALSE)
for(var/datum/bodypart_texture/remaining_texture in bodypart_textures)
remove_bodypart_texture(remaining_texture, update = FALSE)
for(var/atom/movable/movable in contents)
qdel(movable)
@@ -1369,30 +1379,43 @@
// Add two masked images based on the old one
. += leg_source.generate_masked_leg(limb_image)
// Apply height to the overlays we generated so far
// This is done before collecting bodypart overlays so we don't apply height twice to the same overlays
if(!dropped && !isnull(owner))
for(var/image/generated_overlay as anything in .)
// While you may think that heads could be applied with UPPER_BODY instead of ENTIRE_BODY to save us one filter,
// it's more important to keep it consistent for things like getflaticon
owner.apply_height(generated_overlay, ENTIRE_BODY)
// Draw external organs like horns and frills
// Height is applied again in here so we can specify where the overlay is set (ie offset_location)
for(var/datum/bodypart_overlay/overlay as anything in bodypart_overlays)
if(!overlay.can_draw_on_bodypart(src, owner, is_husked))
if(!overlay.can_draw_on_bodypart(src, owner))
continue
// Some externals have multiple layers for background, foreground and between
for(var/external_layer in overlay.all_layers)
for(var/external_layer, actual_layer in overlay.all_layers)
if(!(overlay.layers & external_layer))
continue
var/external_overlay = overlay.get_overlay(external_layer, src, is_husked)
if (!dropped)
. += external_overlay
for (var/mutable_appearance/actual_overlay as anything in overlay.get_overlay(actual_layer, src))
if(dropped || isnull(owner))
. += image(actual_overlay, dir = SOUTH)
continue
owner.apply_height(actual_overlay, overlay.offset_location)
. += actual_overlay
// Then texture everything at once, including bodypart overlays
for(var/datum/bodypart_texture/texture as anything in bodypart_textures)
if(!texture.can_texture_bodypart(src))
continue
for(var/image/generated_overlay as anything in .)
var/appearance_plane = PLANE_TO_TRUE(generated_overlay.plane)
if(appearance_plane != FLOAT_PLANE && appearance_plane != GAME_PLANE)
continue
if (!islist(external_overlay))
. += image(external_overlay, dir = SOUTH)
continue
for (var/mutable_appearance/actual_overlay as anything in external_overlay)
. += image(actual_overlay, dir = SOUTH)
for(var/datum/layer in .)
overlay.modify_bodypart_appearance(layer)
texture.modify_bodypart_appearance(generated_overlay)
SEND_SIGNAL(src, COMSIG_BODYPART_GET_LIMB_ICON, ., dropped)
return .
@@ -1409,24 +1432,92 @@
husk_blood.color = LAZYLEN(blood_dna_info) ? get_color_from_blood_list(blood_dna_info) : BLOOD_COLOR_RED
return husk_blood
///Add a bodypart overlay and call the appropriate update procs
/**
* Adds a bodypart overlay to the limb
*
* * overlay: The overlay to add. Either an instance of a bodypart overlay or a typepath of a bodypart overlay.
* If you pass a typepath, the proc will avoid creating duplicates.
* * update: Whether to call update procs after adding the overlay.
* Set this to FALSE if you are adding multiple overlays at once.
*/
/obj/item/bodypart/proc/add_bodypart_overlay(datum/bodypart_overlay/overlay, update = TRUE)
bodypart_overlays += overlay
if(ispath(overlay, /datum/bodypart_overlay))
if(locate(overlay) in bodypart_overlays)
return
overlay = new overlay()
LAZYADD(bodypart_overlays, overlay)
overlay.added_to_limb(src)
if(!update)
return
if(!owner)
if(isnull(owner))
update_icon_dropped()
else if(!(owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
owner.update_body_parts()
///Remove a bodypart overlay and call the appropriate update procs
/**
* Removes a bodypart overlay from the limb
*
* * overlay: The overlay to remove. Either an instance of a bodypart overlay or a typepath of a bodypart overlay.
* If you pass a typepath, the first overlay of that typepath found will be removed.
* * update: Whether to call update procs after removing the overlay.
* Set this to FALSE if you are removing multiple overlays at once.
*/
/obj/item/bodypart/proc/remove_bodypart_overlay(datum/bodypart_overlay/overlay, update = TRUE)
bodypart_overlays -= overlay
if(ispath(overlay, /datum/bodypart_overlay))
overlay = locate(overlay) in bodypart_overlays
if(isnull(overlay))
return
LAZYREMOVE(bodypart_overlays, overlay)
overlay.removed_from_limb(src)
if(!update)
return
if(!owner)
if(isnull(owner))
update_icon_dropped()
else if(!(owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
owner.update_body_parts()
/**
* Adds a bodypart texture to the limb
*
* * texture: The texture to add. Either an instance of a bodypart texture or a typepath of a bodypart texture.
* If you pass a typepath, the proc will avoid creating duplicates.
* * update: Whether to call update procs after adding the texture.
* Set this to FALSE if you are adding multiple textures at once.
*/
/obj/item/bodypart/proc/add_bodypart_texture(datum/bodypart_texture/texture, update = TRUE)
if(ispath(texture, /datum/bodypart_texture))
if(locate(texture) in bodypart_textures)
return
texture = new texture()
LAZYADD(bodypart_textures, texture)
if(!update)
return
if(isnull(owner))
update_icon_dropped()
else if(!(owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
owner.update_body_parts()
/**
* Removes a bodypart texture from the limb
*
* * texture: The texture to remove. Either an instance of a bodypart texture or a typepath of a bodypart texture.
* If you pass a typepath, the first texture of that typepath found will be removed.
* * update: Whether to call update procs after removing the texture.
* Set this to FALSE if you are removing multiple textures at once.
*/
/obj/item/bodypart/proc/remove_bodypart_texture(datum/bodypart_texture/texture, update = TRUE)
if(ispath(texture, /datum/bodypart_texture))
texture = locate(texture) in bodypart_textures
if(isnull(texture))
return
LAZYREMOVE(bodypart_textures, texture)
if(!update)
return
if(isnull(owner))
update_icon_dropped()
else if(!(owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
owner.update_body_parts()
@@ -46,6 +46,11 @@
bodypart_flags = BODYPART_UNHUSKABLE
butcher_replacement = null
/obj/item/bodypart/arm/left/robot/generate_icon_key()
. = ..()
if(limb_id == BODYPART_ID_ROBOTIC)
. += should_draw_greyscale ? icon_greyscale : icon_static
/obj/item/bodypart/arm/right/robot
name = "cyborg right arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
@@ -82,6 +87,11 @@
bodypart_flags = BODYPART_UNHUSKABLE
butcher_replacement = null
/obj/item/bodypart/arm/right/robot/generate_icon_key()
. = ..()
if(limb_id == BODYPART_ID_ROBOTIC)
. += should_draw_greyscale ? icon_greyscale : icon_static
/obj/item/bodypart/leg/left/robot
name = "cyborg left leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
@@ -118,6 +128,11 @@
bodypart_flags = BODYPART_UNHUSKABLE
butcher_replacement = null
/obj/item/bodypart/leg/left/robot/generate_icon_key()
. = ..()
if(limb_id == BODYPART_ID_ROBOTIC)
. += should_draw_greyscale ? icon_greyscale : icon_static
/obj/item/bodypart/leg/left/robot/emp_effect(severity, protection)
. = ..()
if(!. || isnull(owner))
@@ -168,6 +183,11 @@
bodypart_flags = BODYPART_UNHUSKABLE
butcher_replacement = null
/obj/item/bodypart/leg/right/robot/generate_icon_key()
. = ..()
if(limb_id == BODYPART_ID_ROBOTIC)
. += should_draw_greyscale ? icon_greyscale : icon_static
/obj/item/bodypart/leg/right/robot/emp_effect(severity, protection)
. = ..()
if(!. || isnull(owner))
@@ -222,6 +242,13 @@
var/wired = FALSE
var/obj/item/stock_parts/power_store/cell = null
/obj/item/bodypart/chest/robot/generate_icon_key()
. = ..()
// When we reskin cybernetic limbs, we solely change their icon, nothing else
// So we need to include the relevant icon in the cache key
if(limb_id == BODYPART_ID_ROBOTIC)
. += should_draw_greyscale ? icon_greyscale : icon_static
/obj/item/bodypart/chest/robot/emp_effect(severity, protection)
. = ..()
if(!. || isnull(owner))
@@ -398,6 +425,11 @@
var/obj/item/assembly/flash/handheld/flash1 = null
var/obj/item/assembly/flash/handheld/flash2 = null
/obj/item/bodypart/head/robot/generate_icon_key()
. = ..()
if(limb_id == BODYPART_ID_ROBOTIC)
. += should_draw_greyscale ? icon_greyscale : icon_static
#define EMP_GLITCH "EMP_GLITCH"
/obj/item/bodypart/head/robot/emp_effect(severity, protection)
@@ -37,7 +37,7 @@
return ..()
/// Returns the current offset which should be used for this feature
/datum/worn_feature_offset/proc/get_offset()
/datum/worn_feature_offset/proc/get_offset() as /list
var/current_dir = owner ? owner.dir : SOUTH
if(ISDIAGONALDIR(current_dir))
current_dir = current_dir & (EAST|WEST)
+14 -9
View File
@@ -94,9 +94,9 @@ Unlike normal organs, we're actually inside a persons limbs at all times
return
//Build the mob sprite and use it as our overlay
for(var/external_layer in bodypart_overlay.all_layers)
for(var/external_layer, actual_layer in bodypart_overlay.all_layers)
if(bodypart_overlay.layers & external_layer)
. += bodypart_overlay.get_overlay(external_layer, bodypart_owner, bodypart_owner?.is_husked)
. += bodypart_overlay.get_overlay(actual_layer, bodypart_owner)
///The horns of a lizard!
/obj/item/organ/horns
@@ -119,8 +119,9 @@ Unlike normal organs, we're actually inside a persons limbs at all times
feature_key = FEATURE_HORNS
dyable = TRUE
draw_on_husks = HUSK_OVERLAY_NORMAL
offset_location = UPPER_BODY
/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
///The frills of a lizard (like weird fin ears)
@@ -142,11 +143,12 @@ Unlike normal organs, we're actually inside a persons limbs at all times
/datum/bodypart_overlay/mutant/frills
layers = EXTERNAL_ADJACENT
feature_key = FEATURE_FRILLS
offset_location = UPPER_BODY
/datum/bodypart_overlay/mutant/frills/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/frills/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
/datum/bodypart_overlay/mutant/frills/generate_icon_cache(obj/item/bodypart/limb)
/datum/bodypart_overlay/mutant/frills/icon_render_key(obj/item/bodypart/limb)
. = ..()
if(LAZYLEN(limb?.owner?.hair_masks))
. += jointext(limb.owner.hair_masks, ",")
@@ -211,8 +213,9 @@ Unlike normal organs, we're actually inside a persons limbs at all times
layers = EXTERNAL_ADJACENT
feature_key = FEATURE_SNOUT
draw_on_husks = HUSK_OVERLAY_GRAYSCALE
offset_location = UPPER_BODY
/datum/bodypart_overlay/mutant/snout/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/snout/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDESNOUT)
///A moth's antennae
@@ -280,6 +283,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times
layers = EXTERNAL_FRONT | EXTERNAL_BEHIND
feature_key = FEATURE_MOTH_ANTENNAE
dyable = TRUE
offset_location = UPPER_BODY
///Accessory datum of the burn sprite
var/datum/sprite_accessory/burn_datum = /datum/sprite_accessory/moth_antennae/burnt_off
///Are we burned? If so we draw differently
@@ -293,7 +297,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times
/datum/bodypart_overlay/mutant/antennae/get_base_icon_state()
return burnt ? burn_datum.icon_state : sprite_datum.icon_state
/datum/bodypart_overlay/mutant/antennae/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/antennae/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEANTENNAE)
///The leafy hair of a podperson
@@ -318,6 +322,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times
layers = EXTERNAL_FRONT|EXTERNAL_ADJACENT
feature_key = FEATURE_POD_HAIR
dyable = TRUE
offset_location = UPPER_BODY
///This layer will be colored differently than the rest of the organ. So we can get differently colored flowers or something
var/color_swapped_layer = EXTERNAL_FRONT
@@ -325,7 +330,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times
var/color_inverse_base = 255
/datum/bodypart_overlay/mutant/pod_hair/color_image(image/overlay, draw_layer, obj/item/bodypart/limb)
if(draw_layer != bitflag_to_layer(color_swapped_layer))
if(draw_layer != all_layers[color_swapped_layer])
return ..()
var/color_to_use = dye_color || draw_color
@@ -335,5 +340,5 @@ Unlike normal organs, we're actually inside a persons limbs at all times
else
overlay.color = null
/datum/bodypart_overlay/mutant/pod_hair/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/pod_hair/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
+2 -1
View File
@@ -32,8 +32,9 @@
feature_key = FEATURE_SPINES
dyable = TRUE
draw_on_husks = HUSK_OVERLAY_GRAYSCALE
offset_location = ENTIRE_BODY
/datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEJUMPSUIT)
/datum/bodypart_overlay/mutant/spines/set_dye_color(new_color, obj/item/organ/tail/organ)
+4 -2
View File
@@ -142,12 +142,13 @@
/datum/bodypart_overlay/mutant/tail
layers = EXTERNAL_FRONT|EXTERNAL_BEHIND
dyable = TRUE
offset_location = ENTIRE_BODY
var/wagging = FALSE
/datum/bodypart_overlay/mutant/tail/get_base_icon_state()
return "[wagging ? "wagging_" : ""][sprite_datum.icon_state]" //add the wagging tag if we be wagging
/datum/bodypart_overlay/mutant/tail/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/tail/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEJUMPSUIT)
/obj/item/organ/tail/cat
@@ -254,6 +255,7 @@
layers = EXTERNAL_ADJACENT|EXTERNAL_BEHIND
feature_key = FEATURE_TAILSPINES
draw_on_husks = HUSK_OVERLAY_GRAYSCALE
offset_location = ENTIRE_BODY
///Spines wag when the tail does
var/wagging = FALSE
/// Key for tail spine states, depends on the shape of the tail. Defined in the tail sprite datum.
@@ -262,7 +264,7 @@
/datum/bodypart_overlay/mutant/tail_spines/get_base_icon_state()
return (!isnull(tail_spine_key) ? "[tail_spine_key]_" : "") + (wagging ? "wagging_" : "") + sprite_datum.icon_state // Select the wagging state if appropriate
/datum/bodypart_overlay/mutant/tail_spines/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/tail_spines/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEJUMPSUIT)
/datum/bodypart_overlay/mutant/tail_spines/set_dye_color(new_color, obj/item/organ/organ)
@@ -183,7 +183,7 @@
feature_key = initial(feature_key)
set_appearance_from_name(sprite_datum.name)
/datum/bodypart_overlay/mutant/wings/functional/generate_icon_cache(obj/item/bodypart/limb)
/datum/bodypart_overlay/mutant/wings/functional/icon_render_key(obj/item/bodypart/limb)
. = ..()
. += wings_open ? "open" : "closed"
+3 -2
View File
@@ -22,10 +22,11 @@
///Bodypart overlay of default wings. Does not have any wing functionality
/datum/bodypart_overlay/mutant/wings
layers = ALL_EXTERNAL_OVERLAYS
layers = EXTERNAL_FRONT | EXTERNAL_ADJACENT | EXTERNAL_BEHIND
feature_key = FEATURE_WINGS
offset_location = ENTIRE_BODY
/// Slot we check against
var/slot_blocker = HIDEJUMPSUIT
/datum/bodypart_overlay/mutant/wings/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/wings/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & slot_blocker)
@@ -47,6 +47,7 @@
/datum/bodypart_overlay/augment
layers = EXTERNAL_ADJACENT
draw_on_husks = HUSK_OVERLAY_NORMAL
offset_location = ENTIRE_BODY
/// Implant that owns this overlay
var/obj/item/organ/cyberimp/implant
@@ -58,12 +59,11 @@
implant = null
return ..()
/datum/bodypart_overlay/augment/generate_icon_cache(obj/item/bodypart/limb)
/datum/bodypart_overlay/augment/icon_render_key(obj/item/bodypart/limb)
. = ..()
. += implant.get_overlay_state()
/datum/bodypart_overlay/augment/get_overlay(layer, obj/item/bodypart/limb)
layer = bitflag_to_layer(layer)
var/list/imageset = implant.get_overlay(layer, limb)
if(blocks_emissive == EMISSIVE_BLOCK_NONE || !limb)
return imageset
@@ -162,11 +162,12 @@
color_source = ORGAN_COLOR_HAIR
feature_key = FEATURE_EARS
dyable = TRUE
offset_location = UPPER_BODY
/// Layer upon which we add the inner ears overlay
var/inner_layer = EXTERNAL_FRONT
/datum/bodypart_overlay/mutant/cat_ears/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
/datum/bodypart_overlay/mutant/cat_ears/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
/datum/bodypart_overlay/mutant/cat_ears/get_image(image_layer, obj/item/bodypart/limb)
@@ -174,7 +175,7 @@
base_ears.color = (dye_color || draw_color)
// Only add inner ears on the inner layer
if(image_layer != bitflag_to_layer(inner_layer))
if(image_layer != all_layers[inner_layer])
return base_ears
// Construct image of inner ears, apply to base ears as an overlay
@@ -237,7 +238,7 @@
var/inner_color = "#F0004A"
/datum/bodypart_overlay/mutant/cat_ears/cybernetic/get_image(image_layer, obj/item/bodypart/limb)
if (image_layer != bitflag_to_layer(inner_layer))
if (image_layer != all_layers[inner_layer])
return ..()
var/mutable_appearance/ear_holder = ..()
var/mutable_appearance/inner = ear_holder.overlays[2]
@@ -245,7 +246,7 @@
return ear_holder
/datum/bodypart_overlay/mutant/cat_ears/cybernetic/get_overlay(layer, obj/item/bodypart/limb)
if (layer != inner_layer)
if (layer != all_layers[inner_layer])
return ..()
var/list/all_images = ..()
var/mutable_appearance/ear_holder = all_images[1]