mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
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:
@@ -54,8 +54,6 @@
|
||||
#define LIMB_COLOR_FISH_INFUSION 15
|
||||
/// Carp infusion color priority
|
||||
#define LIMB_COLOR_CARP_INFUSION 20
|
||||
/// Untextured fish suicide color priority
|
||||
#define LIMB_COLOR_CS_SOURCE_SUICIDE 30
|
||||
/// Base priority for atom colors, gets atom priorities added to it
|
||||
#define LIMB_COLOR_ATOM_COLOR 40
|
||||
/// Voidwalker effect color priority
|
||||
|
||||
+22
-43
@@ -734,6 +734,16 @@
|
||||
#define GRADIENT_APPLIES_TO_HAIR (1<<0)
|
||||
#define GRADIENT_APPLIES_TO_FACIAL_HAIR (1<<1)
|
||||
|
||||
// Used in applying height
|
||||
/// Used for overlays centered around the upper half of the human sprite
|
||||
#define UPPER_BODY "upper body"
|
||||
/// Used for overlays centered around the lower half of the human sprite
|
||||
#define LOWER_BODY "lower body"
|
||||
/// Used for overlays that should not offset at all
|
||||
#define NO_MODIFY "do not modify"
|
||||
/// Used for overlays that stretch the full body and thus need a filter
|
||||
#define ENTIRE_BODY "full body"
|
||||
|
||||
// Height defines
|
||||
// - They are numbers so you can compare height values (x height < y height)
|
||||
// - They do not start at 0 for futureproofing
|
||||
@@ -749,20 +759,19 @@
|
||||
#define HUMAN_HEIGHT_TALL 14
|
||||
#define HUMAN_HEIGHT_TALLER 16
|
||||
#define HUMAN_HEIGHT_TALLEST 18
|
||||
// If you add a height here update human_heights_to_offsets as well!
|
||||
|
||||
/// Assoc list of all heights, cast to strings, to """"tuples"""""
|
||||
/// The first """tuple""" index is the upper body offset
|
||||
/// The second """tuple""" index is the lower body offset
|
||||
GLOBAL_LIST_INIT(human_heights_to_offsets, list(
|
||||
"[MONKEY_HEIGHT_DWARF]" = list(-9, -3),
|
||||
"[MONKEY_HEIGHT_MEDIUM]" = list(-7, -4),
|
||||
"[HUMAN_HEIGHT_DWARF]" = list(-5, -4),
|
||||
"[HUMAN_HEIGHT_SHORTEST]" = list(-2, -1),
|
||||
"[HUMAN_HEIGHT_SHORT]" = list(-1, -1),
|
||||
"[HUMAN_HEIGHT_MEDIUM]" = list(0, 0),
|
||||
"[HUMAN_HEIGHT_TALL]" = list(1, 1),
|
||||
"[HUMAN_HEIGHT_TALLER]" = list(2, 1),
|
||||
"[HUMAN_HEIGHT_TALLEST]" = list(3, 2),
|
||||
/// Assoc list of all heights, to offset values
|
||||
GLOBAL_ALIST_INIT(human_heights_to_offsets, alist(
|
||||
MONKEY_HEIGHT_DWARF = list("[UPPER_BODY]" = -9, "[LOWER_BODY]" = -3),
|
||||
MONKEY_HEIGHT_MEDIUM = list("[UPPER_BODY]" = -7, "[LOWER_BODY]" = -4),
|
||||
HUMAN_HEIGHT_DWARF = list("[UPPER_BODY]" = -5, "[LOWER_BODY]" = -4),
|
||||
HUMAN_HEIGHT_SHORTEST = list("[UPPER_BODY]" = -2, "[LOWER_BODY]" = -1),
|
||||
HUMAN_HEIGHT_SHORT = list("[UPPER_BODY]" = -1, "[LOWER_BODY]" = -1),
|
||||
HUMAN_HEIGHT_MEDIUM = list("[UPPER_BODY]" = 0, "[LOWER_BODY]" = 0),
|
||||
HUMAN_HEIGHT_TALL = list("[UPPER_BODY]" = 1, "[LOWER_BODY]" = 1),
|
||||
HUMAN_HEIGHT_TALLER = list("[UPPER_BODY]" = 2, "[LOWER_BODY]" = 1),
|
||||
HUMAN_HEIGHT_TALLEST = list("[UPPER_BODY]" = 3, "[LOWER_BODY]" = 2),
|
||||
))
|
||||
|
||||
/*
|
||||
@@ -869,34 +878,6 @@ GLOBAL_LIST_INIT(human_heights_to_offsets, list(
|
||||
/// (You ONLY need to update this if you add a standing overlay, adding an integer.)
|
||||
#define TOTAL_LAYERS 23
|
||||
|
||||
#define UPPER_BODY "upper body"
|
||||
#define LOWER_BODY "lower body"
|
||||
#define NO_MODIFY "do not modify"
|
||||
|
||||
/// Used for human height overlay adjustments
|
||||
/// Certain standing overlay layers shouldn't have a filter applied and should instead just offset by a pixel y
|
||||
/// This list contains all the layers that must offset, with its value being whether it's a part of the upper half of the body (TRUE) or not (FALSE)
|
||||
GLOBAL_LIST_INIT(layers_to_offset, list(
|
||||
// Weapons commonly cross the middle of the sprite so they get cut in half by the filter
|
||||
"[HANDS_LAYER]" = LOWER_BODY,
|
||||
// Very tall hats will get cut off by filter
|
||||
"[HEAD_LAYER]" = UPPER_BODY,
|
||||
// Hair will get cut off by filter
|
||||
"[HAIR_LAYER]" = UPPER_BODY,
|
||||
// Doesn't do much
|
||||
"[EYES_LAYER]" = UPPER_BODY,
|
||||
// Long belts (sabre sheathe) will get cut off by filter
|
||||
"[BELT_LAYER]" = LOWER_BODY,
|
||||
// Everything below looks fine with or without a filter, so we can skip it and just offset
|
||||
// (In practice they'd be fine if they got a filter but we can optimize a bit by not.)
|
||||
"[NECK_LAYER]" = UPPER_BODY,
|
||||
"[GLASSES_LAYER]" = UPPER_BODY,
|
||||
"[GLOVES_LAYER]" = LOWER_BODY,
|
||||
"[HANDCUFF_LAYER]" = LOWER_BODY,
|
||||
"[ID_LAYER]" = UPPER_BODY,
|
||||
"[FACEMASK_LAYER]" = UPPER_BODY,
|
||||
))
|
||||
|
||||
//Bitflags for the layers a bodypart overlay can draw on (can be drawn on multiple layers)
|
||||
/// Draws overlay on the BODY_FRONT_LAYER
|
||||
#define EXTERNAL_FRONT (1 << 0)
|
||||
@@ -904,8 +885,6 @@ GLOBAL_LIST_INIT(layers_to_offset, list(
|
||||
#define EXTERNAL_ADJACENT (1 << 1)
|
||||
/// Draws overlay on the BODY_BEHIND_LAYER
|
||||
#define EXTERNAL_BEHIND (1 << 2)
|
||||
/// Draws organ on all EXTERNAL layers
|
||||
#define ALL_EXTERNAL_OVERLAYS EXTERNAL_FRONT | EXTERNAL_ADJACENT | EXTERNAL_BEHIND
|
||||
|
||||
// Bitflags for external organs restylability
|
||||
#define EXTERNAL_RESTYLE_ALL ALL
|
||||
|
||||
@@ -3,34 +3,36 @@
|
||||
/datum/bodypart_overlay
|
||||
/// Sometimes we need multiple layers, for like the back, middle and front of the person (EXTERNAL_FRONT, EXTERNAL_ADJACENT, EXTERNAL_BEHIND)
|
||||
var/layers
|
||||
/// List of all possible layers. Used for looping through in drawing
|
||||
var/static/list/all_layers = list(EXTERNAL_FRONT, EXTERNAL_ADJACENT, EXTERNAL_BEHIND)
|
||||
/// List of all possible layers to their real layer. Used for looping through in drawing
|
||||
var/static/alist/all_layers = alist(
|
||||
EXTERNAL_FRONT = -BODY_FRONT_LAYER,
|
||||
EXTERNAL_ADJACENT = -BODY_ADJ_LAYER,
|
||||
EXTERNAL_BEHIND = -BODY_BEHIND_LAYER,
|
||||
)
|
||||
/// Key of the icon states of all the sprite_datums for easy caching
|
||||
var/cache_key = ""
|
||||
/// Whether the overlay blocks emissive light
|
||||
var/blocks_emissive = EMISSIVE_BLOCK_UNIQUE
|
||||
/// Can this overlay be drawn on husked mobs?
|
||||
var/draw_on_husks = HUSK_OVERLAY_NONE
|
||||
/// Determines body area of the overlay for height offsets
|
||||
var/offset_location = NO_MODIFY
|
||||
|
||||
///Wrapper for getting the proper image, colored and everything
|
||||
/datum/bodypart_overlay/proc/get_overlay(layer, obj/item/bodypart/limb, is_husked = FALSE)
|
||||
layer = bitflag_to_layer(layer)
|
||||
/datum/bodypart_overlay/proc/get_overlay(layer, obj/item/bodypart/limb)
|
||||
var/image/main_image = get_image(layer, limb)
|
||||
|
||||
if (is_husked && draw_on_husks != HUSK_OVERLAY_NORMAL)
|
||||
if (limb?.is_husked && draw_on_husks != HUSK_OVERLAY_NORMAL)
|
||||
main_image = huskify_image(main_image)
|
||||
main_image.color = limb.husk_color
|
||||
else
|
||||
color_image(main_image, layer, limb)
|
||||
|
||||
if(blocks_emissive == EMISSIVE_BLOCK_NONE || !limb)
|
||||
return main_image
|
||||
var/list/created_overlays = list(main_image)
|
||||
if(blocks_emissive != EMISSIVE_BLOCK_NONE && !isnull(limb))
|
||||
created_overlays += emissive_blocker(main_image.icon, main_image.icon_state, limb, layer = main_image.layer, alpha = main_image.alpha)
|
||||
|
||||
var/list/all_images = list(
|
||||
main_image,
|
||||
emissive_blocker(main_image.icon, main_image.icon_state, limb, layer = main_image.layer, alpha = main_image.alpha)
|
||||
)
|
||||
return all_images
|
||||
return created_overlays
|
||||
|
||||
/datum/bodypart_overlay/proc/huskify_image(image/main_image)
|
||||
var/icon/husk_icon = new(main_image.icon)
|
||||
@@ -70,29 +72,15 @@
|
||||
if(-BODY_FRONT_LAYER)
|
||||
return "FRONT"
|
||||
|
||||
///Converts a bitflag to the right layer. I'd love to make this a static index list, but byond made an attempt on my life when i did
|
||||
/datum/bodypart_overlay/proc/bitflag_to_layer(layer)
|
||||
switch(layer)
|
||||
if(EXTERNAL_BEHIND)
|
||||
return -BODY_BEHIND_LAYER
|
||||
if(EXTERNAL_ADJACENT)
|
||||
return -BODY_ADJ_LAYER
|
||||
if(EXTERNAL_FRONT)
|
||||
return -BODY_FRONT_LAYER
|
||||
|
||||
///Check whether we can draw the overlays. You generally don't want lizard snouts to draw over an EVA suit
|
||||
/datum/bodypart_overlay/proc/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
|
||||
/datum/bodypart_overlay/proc/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return !is_husked || draw_on_husks
|
||||
return !bodypart_owner.is_husked || draw_on_husks
|
||||
|
||||
///Colorizes the limb it's inserted to, if required.
|
||||
/datum/bodypart_overlay/proc/override_color(obj/item/bodypart/bodypart_owner)
|
||||
CRASH("External organ color set to override with no override proc.")
|
||||
|
||||
///Generate a unique identifier to cache with. If you change something about the image, but the icon cache stays the same, it'll simply pull the unchanged image out of the cache
|
||||
/datum/bodypart_overlay/proc/generate_icon_cache(obj/item/bodypart/limb)
|
||||
/datum/bodypart_overlay/proc/icon_render_key(obj/item/bodypart/limb)
|
||||
return list()
|
||||
|
||||
/// Additionally color or texture the limb
|
||||
/datum/bodypart_overlay/proc/modify_bodypart_appearance(datum/appearance)
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
///Variant of bodypart_overlay for displaying emote overlays. See [/datum/emote/living/blush/run_emote] for an example on how to use one of these.
|
||||
/datum/bodypart_overlay/simple/emote
|
||||
icon = 'icons/mob/human/emote_visuals.dmi'
|
||||
offset_location = UPPER_BODY
|
||||
///The body zone to attach the overlay to, overlay won't be added if no bodypart can be found with this
|
||||
var/attached_body_zone = BODY_ZONE_CHEST
|
||||
///The feature key used to figure out what specific bodily feature we offset this to follow
|
||||
@@ -25,10 +26,8 @@
|
||||
|
||||
///Removes the overlay from the attached bodypart and updates the necessary sprites
|
||||
/datum/bodypart_overlay/simple/emote/Destroy()
|
||||
var/obj/item/bodypart/referenced_bodypart = attached_bodypart.resolve()
|
||||
if(!referenced_bodypart)
|
||||
return ..()
|
||||
referenced_bodypart.remove_bodypart_overlay(src)
|
||||
var/obj/item/bodypart/referenced_bodypart = attached_bodypart?.resolve()
|
||||
referenced_bodypart?.remove_bodypart_overlay(src)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
@@ -41,13 +40,7 @@
|
||||
*/
|
||||
/mob/living/carbon/human/proc/give_emote_overlay(datum/bodypart_overlay/simple/emote/overlay_typepath)
|
||||
var/obj/item/bodypart/bodypart = get_bodypart(overlay_typepath::attached_body_zone)
|
||||
if(!bodypart)
|
||||
return null
|
||||
if(locate(overlay_typepath) in bodypart.bodypart_overlays)
|
||||
return null
|
||||
var/datum/bodypart_overlay/simple/emote/overlay = new overlay_typepath()
|
||||
bodypart.add_bodypart_overlay(overlay)
|
||||
return overlay
|
||||
return bodypart?.add_bodypart_overlay(overlay_typepath)
|
||||
|
||||
/datum/bodypart_overlay/simple/emote/tongue
|
||||
icon_state = "tongue"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/// For body markings applied on the species, which need some extra code
|
||||
/datum/bodypart_overlay/simple/body_marking
|
||||
layers = EXTERNAL_ADJACENT
|
||||
offset_location = ENTIRE_BODY
|
||||
/// Listen to the gendercode, if the limb is bimorphic
|
||||
var/use_gender = FALSE
|
||||
/// Which dna feature key to draw from
|
||||
@@ -29,12 +30,12 @@
|
||||
use_gender = accessory.gender_specific
|
||||
draw_color = accessory.color_src ? set_color : null
|
||||
|
||||
/datum/bodypart_overlay/simple/body_marking/generate_icon_cache(obj/item/bodypart/limb)
|
||||
/datum/bodypart_overlay/simple/body_marking/icon_render_key(obj/item/bodypart/limb)
|
||||
. = ..()
|
||||
. += use_gender
|
||||
. += draw_color
|
||||
|
||||
/datum/bodypart_overlay/simple/body_marking/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
|
||||
/datum/bodypart_overlay/simple/body_marking/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
|
||||
return ..() && icon_state != SPRITE_ACCESSORY_NONE
|
||||
|
||||
/datum/bodypart_overlay/simple/body_marking/get_image(layer, obj/item/bodypart/limb)
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
sprite_datum = fetch_sprite_datum_from_name(accessory_name)
|
||||
|
||||
///Generate a unique key based on our sprites. So that if we've aleady drawn these sprites, they can be found in the cache and wont have to be drawn again (blessing and curse, but mostly curse)
|
||||
/datum/bodypart_overlay/mutant/generate_icon_cache(obj/item/bodypart/limb)
|
||||
/datum/bodypart_overlay/mutant/icon_render_key(obj/item/bodypart/limb)
|
||||
. = list()
|
||||
. += "[get_base_icon_state()]"
|
||||
. += "[feature_key]"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
overlay.color = draw_color
|
||||
|
||||
/datum/bodypart_overlay/simple/generate_icon_cache(obj/item/bodypart/limb)
|
||||
/datum/bodypart_overlay/simple/icon_render_key(obj/item/bodypart/limb)
|
||||
. = ..()
|
||||
. += icon_state
|
||||
|
||||
@@ -24,14 +24,17 @@
|
||||
icon_state = "sixpack"
|
||||
layers = EXTERNAL_ADJACENT
|
||||
draw_on_husks = HUSK_OVERLAY_GRAYSCALE
|
||||
offset_location = ENTIRE_BODY
|
||||
|
||||
///bags drawn beneath the eyes
|
||||
/datum/bodypart_overlay/simple/bags
|
||||
icon_state = "bags"
|
||||
draw_color = COLOR_WEBSAFE_DARK_GRAY
|
||||
layers = EXTERNAL_ADJACENT
|
||||
offset_location = UPPER_BODY
|
||||
|
||||
///PENDING eyes drawn on the face
|
||||
/datum/bodypart_overlay/simple/soul_pending_eyes
|
||||
icon_state = "soul_pending_eyes"
|
||||
layers = EXTERNAL_FRONT
|
||||
offset_location = UPPER_BODY
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/// Bodypart overlays focused on texturing limbs
|
||||
/datum/bodypart_overlay/texture
|
||||
/datum/bodypart_texture
|
||||
/// icon file for the texture
|
||||
var/texture_icon
|
||||
/// icon state for the texture
|
||||
@@ -9,42 +9,42 @@
|
||||
/// Priority of this texture - all textures with a lower priority will not be rendered
|
||||
var/overlay_priority = 0
|
||||
|
||||
/datum/bodypart_overlay/texture/New()
|
||||
/datum/bodypart_texture/New()
|
||||
. = ..()
|
||||
cached_texture_icon = icon(texture_icon, texture_icon_state)
|
||||
|
||||
/datum/bodypart_overlay/texture/modify_bodypart_appearance(datum/appearance)
|
||||
/datum/bodypart_texture/proc/modify_bodypart_appearance(image/appearance)
|
||||
appearance.add_filter("bodypart_texture_[texture_icon_state]", 1, layering_filter(icon = cached_texture_icon, blend_mode = BLEND_INSET_OVERLAY))
|
||||
|
||||
/datum/bodypart_overlay/texture/generate_icon_cache(obj/item/bodypart/limb)
|
||||
. = ..()
|
||||
. += type
|
||||
/datum/bodypart_texture/proc/icon_render_key()
|
||||
return type
|
||||
|
||||
/datum/bodypart_overlay/texture/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
|
||||
if (!..())
|
||||
return FALSE
|
||||
for (var/datum/bodypart_overlay/texture/other_texture in bodypart_owner.bodypart_overlays)
|
||||
/datum/bodypart_texture/proc/can_texture_bodypart(obj/item/bodypart/bodypart_owner)
|
||||
for (var/datum/bodypart_texture/other_texture as anything in bodypart_owner.bodypart_textures)
|
||||
if (other_texture.overlay_priority > overlay_priority)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/bodypart_overlay/texture/spacey
|
||||
blocks_emissive = EMISSIVE_BLOCK_NONE
|
||||
/datum/bodypart_texture/spacey
|
||||
texture_icon_state = "spacey"
|
||||
texture_icon = 'icons/mob/human/textures.dmi'
|
||||
overlay_priority = BODYPART_OVERLAY_VOIDWALKER_CURSE
|
||||
|
||||
/datum/bodypart_overlay/texture/carpskin
|
||||
/datum/bodypart_texture/carpskin
|
||||
texture_icon_state = "carpskin"
|
||||
texture_icon = 'icons/mob/human/textures.dmi'
|
||||
overlay_priority = BODYPART_OVERLAY_CARP_INFUSION
|
||||
|
||||
/datum/bodypart_overlay/texture/checkered
|
||||
/datum/bodypart_texture/checkered
|
||||
texture_icon_state = "checkered"
|
||||
texture_icon = 'icons/mob/human/textures.dmi'
|
||||
overlay_priority = BODYPART_OVERLAY_CSS_SUICIDE
|
||||
|
||||
/datum/bodypart_overlay/texture/fishscale
|
||||
/datum/bodypart_texture/checkered/modify_bodypart_appearance(image/appearance)
|
||||
. = ..()
|
||||
appearance.color = COLOR_WHITE
|
||||
|
||||
/datum/bodypart_texture/fishscale
|
||||
texture_icon_state = "fishscale"
|
||||
texture_icon = 'icons/mob/human/textures.dmi'
|
||||
overlay_priority = BODYPART_OVERLAY_FISH_INFUSION
|
||||
|
||||
@@ -77,10 +77,7 @@
|
||||
|
||||
// we might have some lingering blinking eyes
|
||||
var/obj/item/bodypart/head/head = source.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(head)
|
||||
var/soul_eyes = locate(/datum/bodypart_overlay/simple/soul_pending_eyes) in head.bodypart_overlays
|
||||
if(soul_eyes)
|
||||
head.remove_bodypart_overlay(soul_eyes)
|
||||
head?.remove_bodypart_overlay(/datum/bodypart_overlay/simple/soul_pending_eyes)
|
||||
|
||||
prepare_brain(removed_brain)
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
var/bonus_biotype
|
||||
/// If the biotype was added - used to check if we should remove the biotype or not, on organ set loss.
|
||||
var/biotype_added = FALSE
|
||||
/// Limb overlay to apply upon activation
|
||||
var/limb_overlay
|
||||
/// Color priority for limb overlay
|
||||
/// Limb texture to apply upon activation
|
||||
var/limb_texture
|
||||
/// Color priority for limb limb_texture
|
||||
var/color_overlay_priority
|
||||
|
||||
/datum/status_effect/organ_set_bonus/proc/set_organs(new_value, obj/item/organ/organ)
|
||||
@@ -97,22 +97,21 @@
|
||||
if(bonus_activate_text)
|
||||
to_chat(owner, bonus_activate_text)
|
||||
|
||||
// Add limb overlay
|
||||
if(!iscarbon(owner) || !limb_overlay)
|
||||
// Add limb texture
|
||||
if(!limb_texture)
|
||||
return TRUE
|
||||
|
||||
var/mob/living/carbon/carbon_owner = owner
|
||||
RegisterSignal(carbon_owner, COMSIG_CARBON_ATTACH_LIMB, PROC_REF(texture_limb))
|
||||
RegisterSignal(carbon_owner, COMSIG_CARBON_REMOVE_LIMB, PROC_REF(untexture_limb))
|
||||
RegisterSignal(owner, COMSIG_CARBON_ATTACH_LIMB, PROC_REF(texture_limb))
|
||||
RegisterSignal(owner, COMSIG_CARBON_REMOVE_LIMB, PROC_REF(untexture_limb))
|
||||
|
||||
for(var/obj/item/bodypart/limb as anything in carbon_owner.get_bodyparts())
|
||||
for(var/obj/item/bodypart/limb as anything in owner.get_bodyparts())
|
||||
if (!(limb.bodytype & BODYTYPE_ORGANIC))
|
||||
continue
|
||||
limb.add_bodypart_overlay(new limb_overlay(), update = FALSE)
|
||||
limb.add_bodypart_texture(limb_texture, update = FALSE)
|
||||
if (color_overlay_priority)
|
||||
limb.add_color_override(COLOR_WHITE, color_overlay_priority)
|
||||
|
||||
carbon_owner.update_body()
|
||||
owner.update_body()
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/organ_set_bonus/proc/disable_bonus(obj/item/organ/removed_organ)
|
||||
@@ -130,24 +129,20 @@
|
||||
to_chat(owner, bonus_deactivate_text)
|
||||
|
||||
// Remove limb overlay
|
||||
if(!iscarbon(owner) || !limb_overlay)
|
||||
if(!limb_texture)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/carbon_owner = owner
|
||||
UnregisterSignal(carbon_owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))
|
||||
UnregisterSignal(owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))
|
||||
|
||||
if(QDELETED(carbon_owner))
|
||||
if(QDELETED(owner))
|
||||
return
|
||||
|
||||
for(var/obj/item/bodypart/limb as anything in carbon_owner.get_bodyparts())
|
||||
var/overlay = locate(limb_overlay) in limb.bodypart_overlays
|
||||
if(!overlay)
|
||||
continue
|
||||
limb.remove_bodypart_overlay(overlay, update = FALSE)
|
||||
for(var/obj/item/bodypart/limb as anything in owner.get_bodyparts())
|
||||
limb.remove_bodypart_texture(limb_texture, update = FALSE)
|
||||
if (color_overlay_priority)
|
||||
limb.remove_color_override(color_overlay_priority)
|
||||
|
||||
carbon_owner.update_body()
|
||||
owner.update_body()
|
||||
|
||||
/datum/status_effect/organ_set_bonus/proc/texture_limb(atom/source, obj/item/bodypart/limb)
|
||||
SIGNAL_HANDLER
|
||||
@@ -156,16 +151,13 @@
|
||||
return
|
||||
|
||||
// Not updating because enable/disable_bonus(obj/item/organ/removed_organ) call it down the line, and calls coming from comsigs update the owner's body themselves
|
||||
limb.add_bodypart_overlay(new limb_overlay(), update = FALSE)
|
||||
limb.add_bodypart_texture(limb_texture, update = FALSE)
|
||||
if(color_overlay_priority)
|
||||
limb.add_color_override(COLOR_WHITE, color_overlay_priority)
|
||||
|
||||
/datum/status_effect/organ_set_bonus/proc/untexture_limb(atom/source, obj/item/bodypart/limb)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/overlay = locate(limb_overlay) in limb.bodypart_overlays
|
||||
if(!overlay)
|
||||
return
|
||||
limb.remove_bodypart_overlay(overlay, update = FALSE)
|
||||
limb.remove_bodypart_texture(limb_texture, update = FALSE)
|
||||
if(color_overlay_priority)
|
||||
limb.remove_color_override(color_overlay_priority)
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mutable_appearance/mutation_appearance = mutable_appearance(mutation_icon, mutation_icon_state, -layer_used)
|
||||
owner.apply_height_offsets(mutation_appearance, offset_location)
|
||||
owner.apply_height(mutation_appearance, offset_location)
|
||||
|
||||
overlay_list += mutation_appearance
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
locked = TRUE // fake parent
|
||||
conflicts = list(/datum/mutation/adaptation)
|
||||
mutation_traits = list(TRAIT_WADDLING)
|
||||
mutation_icon = 'icons/mob/effects/genetics.dmi'
|
||||
offset_location = FULL_BODY
|
||||
|
||||
/datum/mutation/adaptation/New(datum/mutation/copymut)
|
||||
. = ..()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
difficulty = 8
|
||||
power_coeff = 1
|
||||
mutation_icon_state = "radiation"
|
||||
offset_location = FULL_BODY
|
||||
/// Weakref to our radiation emitter component
|
||||
var/datum/weakref/radioactivity_source_ref
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ GLOBAL_LIST_EMPTY(heretic_arenas)
|
||||
crown_overlay.pixel_z = 24
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/human_parent = owner
|
||||
human_parent.apply_height_offsets(crown_overlay, UPPER_BODY)
|
||||
human_parent.apply_height(crown_overlay, UPPER_BODY)
|
||||
var/obj/item/bodypart/head/human_head = human_parent.get_bodypart(BODY_ZONE_HEAD)
|
||||
human_head?.worn_head_offset?.apply_offset(crown_overlay)
|
||||
owner.add_overlay(crown_overlay)
|
||||
@@ -210,7 +210,7 @@ GLOBAL_LIST_EMPTY(heretic_arenas)
|
||||
crown_overlay.pixel_z = 24
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/human_parent = owner
|
||||
human_parent.apply_height_offsets(crown_overlay, UPPER_BODY)
|
||||
human_parent.apply_height(crown_overlay, UPPER_BODY)
|
||||
var/obj/item/bodypart/head/human_head = human_parent.get_bodypart(BODY_ZONE_HEAD)
|
||||
human_head?.worn_head_offset?.apply_offset(crown_overlay)
|
||||
owner.add_overlay(crown_overlay)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
halo_overlay.pixel_w = 0
|
||||
if (ishuman(owner))
|
||||
var/mob/living/carbon/human/human_parent = owner
|
||||
human_parent.apply_height_offsets(halo_overlay, UPPER_BODY)
|
||||
human_parent.apply_height(halo_overlay, UPPER_BODY)
|
||||
|
||||
var/obj/item/bodypart/head/human_head = human_parent.get_bodypart(BODY_ZONE_HEAD)
|
||||
human_head?.worn_head_offset?.apply_offset(halo_overlay)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
bonus_deactivate_text = span_notice("Your DNA is once again mostly yours, and so fades your ability to space-swim...")
|
||||
bonus_traits = list(TRAIT_SPACEWALK)
|
||||
bonus_biotype = MOB_AQUATIC
|
||||
limb_overlay = /datum/bodypart_overlay/texture/carpskin
|
||||
limb_texture = /datum/bodypart_texture/carpskin
|
||||
color_overlay_priority = LIMB_COLOR_CARP_INFUSION
|
||||
|
||||
///Carp lungs! You can breathe in space! Oh... you can't breathe on the station, you need low oxygen environments.
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
TRAIT_WATER_ADAPTATION,
|
||||
)
|
||||
bonus_biotype = MOB_AQUATIC
|
||||
limb_overlay = /datum/bodypart_overlay/texture/fishscale
|
||||
limb_texture = /datum/bodypart_texture/fishscale
|
||||
/// Are we at all five organs?
|
||||
var/color_active = FALSE
|
||||
|
||||
@@ -301,15 +301,6 @@
|
||||
else //otherwise get one from a set of faded out blue and some greys colors.
|
||||
return pick("#B4B8DD", "#85C7D0", "#67BBEE", "#2F4450", "#55CCBB", "#999FD0", "#345066", "#585B69", "#7381A0", "#B6DDE5", "#4E4E50")
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/fish/get_image(image_layer, obj/item/bodypart/limb)
|
||||
var/mutable_appearance/appearance = ..()
|
||||
// We add all appearances the parent bodypart has to the tail to inherit scales and fancy effects
|
||||
// but most other organs don't want to inherit those so we do it here and not on parent
|
||||
for (var/datum/bodypart_overlay/texture/texture in limb.bodypart_overlays)
|
||||
if(texture.can_draw_on_bodypart(limb, limb.owner, limb.is_husked))
|
||||
texture.modify_bodypart_appearance(appearance)
|
||||
return appearance
|
||||
|
||||
///Lungs that replace the need of oxygen with water vapor or being wet
|
||||
/obj/item/organ/lungs/fish
|
||||
name = "mutated gills"
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
icon_state = "roach_shell"
|
||||
layers = EXTERNAL_FRONT|EXTERNAL_BEHIND
|
||||
draw_on_husks = HUSK_OVERLAY_GRAYSCALE
|
||||
offset_location = ENTIRE_BODY
|
||||
|
||||
/datum/bodypart_overlay/simple/roach_shell/get_image(image_layer, obj/item/bodypart/limb)
|
||||
return image(
|
||||
|
||||
@@ -123,7 +123,8 @@
|
||||
/// Body part overlays applied by golem status effects
|
||||
/datum/bodypart_overlay/simple/golem_overlay
|
||||
icon = 'icons/mob/human/species/golems.dmi'
|
||||
layers = ALL_EXTERNAL_OVERLAYS
|
||||
layers = EXTERNAL_FRONT | EXTERNAL_ADJACENT | EXTERNAL_BEHIND
|
||||
offset_location = ENTIRE_BODY
|
||||
///The bodypart that the overlay is currently applied to
|
||||
var/datum/weakref/attached_bodypart
|
||||
|
||||
@@ -134,9 +135,7 @@
|
||||
|
||||
/datum/bodypart_overlay/simple/golem_overlay/Destroy(force)
|
||||
var/obj/item/bodypart/referenced_bodypart = attached_bodypart.resolve()
|
||||
if(!referenced_bodypart)
|
||||
return ..()
|
||||
referenced_bodypart.remove_bodypart_overlay(src)
|
||||
referenced_bodypart?.remove_bodypart_overlay(src)
|
||||
return ..()
|
||||
|
||||
/// Freezes hunger for the duration
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
random_gain = FALSE
|
||||
known_trauma = FALSE
|
||||
/// Type for the bodypart texture we add
|
||||
var/bodypart_overlay_type = /datum/bodypart_overlay/texture/spacey
|
||||
var/bodypart_texture_type = /datum/bodypart_texture/spacey
|
||||
/// Color in which we paint the space texture
|
||||
var/space_color = COLOR_WHITE
|
||||
///traits we give on gain
|
||||
@@ -90,7 +90,7 @@
|
||||
SIGNAL_HANDLER
|
||||
|
||||
// Not updating because on_gain/on_lose() call it down the line, and calls coming from comsigs update the owner's body themselves
|
||||
limb.add_bodypart_overlay(new bodypart_overlay_type(), update = FALSE)
|
||||
limb.add_bodypart_texture(bodypart_texture_type, update = FALSE)
|
||||
limb.add_color_override(space_color, LIMB_COLOR_VOIDWALKER_CURSE)
|
||||
if(istype(limb, /obj/item/bodypart/head))
|
||||
var/obj/item/bodypart/head/head = limb
|
||||
@@ -99,10 +99,9 @@
|
||||
/datum/brain_trauma/voided/proc/untexture_limb(atom/source, obj/item/bodypart/limb)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/overlay = locate(bodypart_overlay_type) in limb.bodypart_overlays
|
||||
if(overlay)
|
||||
limb.remove_bodypart_overlay(overlay, update = FALSE)
|
||||
limb.remove_color_override(LIMB_COLOR_VOIDWALKER_CURSE)
|
||||
|
||||
limb.remove_bodypart_texture(bodypart_texture_type, update = FALSE)
|
||||
limb.remove_color_override(LIMB_COLOR_VOIDWALKER_CURSE)
|
||||
|
||||
if(istype(limb, /obj/item/bodypart/head))
|
||||
var/obj/item/bodypart/head/head = limb
|
||||
|
||||
@@ -116,8 +116,7 @@
|
||||
return ..()
|
||||
|
||||
for(var/obj/item/bodypart/limb in user.get_bodyparts())
|
||||
limb.add_color_override(COLOR_WHITE, LIMB_COLOR_CS_SOURCE_SUICIDE)
|
||||
limb.add_bodypart_overlay(new /datum/bodypart_overlay/texture/checkered(), update = FALSE)
|
||||
limb.add_bodypart_overlay(/datum/bodypart_texture/checkered, update = FALSE)
|
||||
|
||||
var/obj/item/bodypart/head/head = user.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(!isnull(head))
|
||||
|
||||
@@ -722,8 +722,9 @@
|
||||
/datum/bodypart_overlay/simple/babbearfish
|
||||
icon_state = "babbearfish"
|
||||
draw_on_husks = HUSK_OVERLAY_NORMAL
|
||||
offset_location = UPPER_BODY
|
||||
|
||||
/datum/bodypart_overlay/simple/babbearfish/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
|
||||
/datum/bodypart_overlay/simple/babbearfish/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
|
||||
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEEARS)
|
||||
|
||||
/obj/item/organ/ears/babbelfish/Initialize(mapload)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
electrocution_skeleton_anim.appearance_flags |= RESET_COLOR|KEEP_APART
|
||||
if(ishuman(hallucinator))
|
||||
var/mob/living/carbon/human/human_hallucinator = hallucinator
|
||||
human_hallucinator.apply_height_filters(electrocution_skeleton_anim)
|
||||
human_hallucinator.apply_height(electrocution_skeleton_anim, ENTIRE_BODY)
|
||||
|
||||
SET_PLANE_EXPLICIT(shock_image, ABOVE_GAME_PLANE, hallucinator)
|
||||
SET_PLANE_EXPLICIT(electrocution_skeleton_anim, ABOVE_GAME_PLANE, hallucinator)
|
||||
|
||||
@@ -271,7 +271,8 @@ GLOBAL_LIST_INIT(raptor_colors, init_raptor_colors())
|
||||
// Raptors won't have the best of times keeping up tall humans or fatties up in the air
|
||||
var/struggling = HAS_TRAIT(user, TRAIT_FAT) || user.mob_height > HUMAN_HEIGHT_SHORTEST
|
||||
if (wings_open)
|
||||
wings_underlay = user.apply_height_offsets(mutable_appearance(worn_icon, "raptor_purple_wings", -BODY_BEHIND_LAYER, user), UPPER_BODY)
|
||||
wings_underlay = mutable_appearance(worn_icon, "raptor_purple_wings", -BODY_BEHIND_LAYER, user)
|
||||
user.apply_height(wings_underlay, UPPER_BODY)
|
||||
user.add_overlay(wings_underlay)
|
||||
user.physiology.stun_mod *= 2
|
||||
user.add_traits(list(TRAIT_MOVE_FLOATING, TRAIT_IGNORING_GRAVITY, TRAIT_NOGRAV_ALWAYS_DRIFT), REF(src))
|
||||
|
||||
@@ -302,6 +302,7 @@
|
||||
if(isnull(damage_overlay))
|
||||
return
|
||||
|
||||
apply_height(damage_overlay, ENTIRE_BODY)
|
||||
overlays_standing[DAMAGE_LAYER] = damage_overlay
|
||||
apply_overlay(DAMAGE_LAYER)
|
||||
|
||||
@@ -324,6 +325,7 @@
|
||||
if(isnull(wound_overlay))
|
||||
return
|
||||
|
||||
apply_height(wound_overlay, ENTIRE_BODY)
|
||||
overlays_standing[WOUND_LAYER] = wound_overlay
|
||||
apply_overlay(WOUND_LAYER)
|
||||
|
||||
@@ -387,7 +389,7 @@
|
||||
var/mutable_appearance/handcuff_overlay = mutable_appearance('icons/mob/simple/mob.dmi', "handcuff1", -HANDCUFF_LAYER)
|
||||
if(handcuffed.blocks_emissive != EMISSIVE_BLOCK_NONE)
|
||||
handcuff_overlay.overlays += emissive_blocker(handcuff_overlay.icon, handcuff_overlay.icon_state, src, alpha = handcuff_overlay.alpha)
|
||||
|
||||
apply_height(handcuff_overlay, LOWER_BODY) // low hanging
|
||||
overlays_standing[HANDCUFF_LAYER] = handcuff_overlay
|
||||
apply_overlay(HANDCUFF_LAYER)
|
||||
|
||||
@@ -498,9 +500,11 @@
|
||||
if(is_invisible)
|
||||
. += "invisible"
|
||||
for(var/datum/bodypart_overlay/overlay as anything in bodypart_overlays)
|
||||
if(!overlay.can_draw_on_bodypart(src, owner, is_husked))
|
||||
continue
|
||||
. += overlay.generate_icon_cache(src)
|
||||
if(overlay.can_draw_on_bodypart(src, owner))
|
||||
. += overlay.icon_render_key(src)
|
||||
for(var/datum/bodypart_texture/texture as anything in bodypart_textures)
|
||||
if(texture.can_texture_bodypart(src))
|
||||
. += texture.icon_render_key()
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/human_owner = owner
|
||||
. += "[human_owner.mob_height]"
|
||||
@@ -525,11 +529,10 @@
|
||||
. += body_zone
|
||||
if(is_invisible)
|
||||
. += "invisible"
|
||||
. += "[LAZYLEN(blood_dna_info) ? get_color_from_blood_list(blood_dna_info) : BLOOD_COLOR_RED]"
|
||||
for(var/datum/bodypart_overlay/overlay as anything in bodypart_overlays)
|
||||
if(!overlay.can_draw_on_bodypart(src, owner, TRUE))
|
||||
continue
|
||||
. += overlay.generate_icon_cache(src)
|
||||
if(overlay.can_draw_on_bodypart(src, owner))
|
||||
. += overlay.icon_render_key(src)
|
||||
. += "[LAZYLEN(blood_dna_info) ? get_color_from_blood_list(blood_dna_info) : BLOOD_COLOR_RED]"
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/human_owner = owner
|
||||
. += "[human_owner.mob_height]"
|
||||
|
||||
@@ -2047,9 +2047,14 @@ GLOBAL_LIST_EMPTY(features_by_species)
|
||||
|
||||
/// Remove body markings
|
||||
/datum/species/proc/remove_body_markings(mob/living/carbon/human/hooman)
|
||||
var/needs_update = FALSE
|
||||
for(var/obj/item/bodypart/part as anything in hooman.get_bodyparts())
|
||||
for(var/datum/bodypart_overlay/simple/body_marking/marking in part.bodypart_overlays)
|
||||
part.remove_bodypart_overlay(marking)
|
||||
part.remove_bodypart_overlay(marking, update = FALSE)
|
||||
needs_update = TRUE
|
||||
|
||||
if(needs_update && !(hooman.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
|
||||
hooman.update_body_parts()
|
||||
|
||||
/**
|
||||
* Calculates the expected height values for this species
|
||||
|
||||
@@ -95,19 +95,17 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
|
||||
/mob/living/carbon/human/dummy/log_mob_tag(text)
|
||||
return
|
||||
|
||||
// To speed up the preference menu, we apply 1 filter to the entire mob
|
||||
// To speed up the preference menu, we apply one height filter to the entire mob,
|
||||
// rather than independently applying offsets and filters to each individual overlay
|
||||
// This looks good enough to pass the sniff test and saves a lot of time
|
||||
/mob/living/carbon/human/dummy/regenerate_icons()
|
||||
. = ..()
|
||||
apply_height_filters(src, TRUE)
|
||||
apply_height(src, ENTIRE_BODY)
|
||||
|
||||
/mob/living/carbon/human/dummy/apply_height_filters(image/appearance, only_apply_in_prefs = FALSE)
|
||||
if(only_apply_in_prefs)
|
||||
/mob/living/carbon/human/dummy/apply_height(image/appearance, upper_torso)
|
||||
if(appearance == src)
|
||||
return ..()
|
||||
|
||||
// Not necessary with above
|
||||
/mob/living/carbon/human/dummy/apply_height_offsets(image/appearance, upper_torso)
|
||||
return
|
||||
|
||||
/// Takes in an accessory list and returns the first entry from that list, ensuring that we dont return SPRITE_ACCESSORY_NONE in the process.
|
||||
/proc/get_consistent_feature_entry(list/accessory_feature_list)
|
||||
var/consistent_entry = (accessory_feature_list- SPRITE_ACCESSORY_NONE)[1]
|
||||
|
||||
@@ -637,7 +637,7 @@
|
||||
if(dna?.species)
|
||||
add_atom_colour(COLOR_BLACK, TEMPORARY_COLOUR_PRIORITY)
|
||||
var/mutable_appearance/shock_animation_dna = mutable_appearance(icon, "electrocuted_base", appearance_flags = RESET_COLOR|KEEP_APART)
|
||||
apply_height_filters(shock_animation_dna)
|
||||
apply_height(shock_animation_dna, ENTIRE_BODY)
|
||||
zap_appearance = shock_animation_dna
|
||||
|
||||
// Otherwise do a generic animation
|
||||
|
||||
@@ -85,7 +85,7 @@ There are several things that need to be remembered:
|
||||
if(uniform.adjusted == ALT_STYLE)
|
||||
target_overlay = "[target_overlay]_d"
|
||||
|
||||
var/mutable_appearance/uniform_overlay
|
||||
|
||||
//This is how non-humanoid clothing works. You check if the mob has the right bodyflag, and the clothing has the corresponding clothing flag.
|
||||
//handled_by_bodyshape is used to track whether or not we successfully used an alternate sprite. It's set to TRUE to ease up on copy-paste.
|
||||
//icon_file MUST be set to null by default, or it causes issues.
|
||||
@@ -107,7 +107,7 @@ There are several things that need to be remembered:
|
||||
handled_by_bodyshape = FALSE
|
||||
|
||||
//END SPECIES HANDLING
|
||||
uniform_overlay = uniform.build_worn_icon(
|
||||
var/mutable_appearance/uniform_overlay = uniform.build_worn_icon(
|
||||
default_layer = UNIFORM_LAYER,
|
||||
default_icon_file = icon_file,
|
||||
isinhands = FALSE,
|
||||
@@ -117,6 +117,7 @@ There are several things that need to be remembered:
|
||||
bodyshape = bodyshape,
|
||||
)
|
||||
|
||||
apply_height(uniform_overlay, ENTIRE_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_uniform_offset?.apply_offset(uniform_overlay)
|
||||
overlays_standing[UNIFORM_LAYER] = uniform_overlay
|
||||
@@ -127,8 +128,6 @@ There are several things that need to be remembered:
|
||||
remove_overlay(ID_LAYER)
|
||||
hud_used?.update_inventory_slot(ITEM_SLOT_ID)
|
||||
|
||||
var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
|
||||
|
||||
if(wear_id)
|
||||
var/obj/item/worn_item = wear_id
|
||||
|
||||
@@ -136,12 +135,9 @@ There are several things that need to be remembered:
|
||||
return
|
||||
|
||||
var/icon_file = 'icons/mob/clothing/id.dmi'
|
||||
var/mutable_appearance/id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
|
||||
id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
|
||||
if(!id_overlay)
|
||||
return
|
||||
|
||||
apply_height(id_overlay, UPPER_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_id_offset?.apply_offset(id_overlay)
|
||||
overlays_standing[ID_LAYER] = id_overlay
|
||||
@@ -167,6 +163,8 @@ There are several things that need to be remembered:
|
||||
var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands_right")
|
||||
blood_overlay.color = get_blood_dna_color()
|
||||
hands_combined.overlays += blood_overlay
|
||||
|
||||
apply_height(hands_combined, LOWER_BODY)
|
||||
overlays_standing[GLOVES_LAYER] = hands_combined
|
||||
apply_overlay(GLOVES_LAYER)
|
||||
return
|
||||
@@ -183,11 +181,10 @@ There are several things that need to be remembered:
|
||||
var/feature_y_offset = 0
|
||||
//needs to be typed, hand_bodyparts can have nulls
|
||||
for (var/obj/item/bodypart/arm/my_hand in hand_bodyparts)
|
||||
var/list/glove_offset = my_hand.worn_glove_offset?.get_offset()
|
||||
if (glove_offset && (!feature_y_offset || glove_offset["y"] > feature_y_offset))
|
||||
feature_y_offset = glove_offset["y"]
|
||||
feature_y_offset = max(my_hand.worn_glove_offset?.get_offset()["y"], feature_y_offset)
|
||||
|
||||
gloves_overlay.pixel_z += feature_y_offset
|
||||
apply_height(gloves_overlay, LOWER_BODY)
|
||||
|
||||
// We dont have any >2 hands human species (and likely wont ever), so theres no point in splitting this because:
|
||||
// It will only run if the left hand OR the right hand is missing, and it wont run if both are missing because you cant wear gloves with no arms
|
||||
@@ -221,6 +218,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = 'icons/mob/clothing/eyes.dmi'
|
||||
|
||||
var/mutable_appearance/glasses_overlay = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(glasses_overlay, UPPER_BODY)
|
||||
my_head.worn_glasses_offset?.apply_offset(glasses_overlay)
|
||||
overlays_standing[GLASSES_LAYER] = glasses_overlay
|
||||
apply_overlay(GLASSES_LAYER)
|
||||
@@ -242,6 +240,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = 'icons/mob/clothing/ears.dmi'
|
||||
|
||||
var/mutable_appearance/ears_overlay = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(ears_overlay, UPPER_BODY)
|
||||
my_head.worn_ears_offset?.apply_offset(ears_overlay)
|
||||
overlays_standing[EARS_LAYER] = ears_overlay
|
||||
apply_overlay(EARS_LAYER)
|
||||
@@ -259,6 +258,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = 'icons/mob/clothing/neck.dmi'
|
||||
|
||||
var/mutable_appearance/neck_overlay = worn_item.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(neck_overlay, ENTIRE_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_neck_offset?.apply_offset(neck_overlay)
|
||||
overlays_standing[NECK_LAYER] = neck_overlay
|
||||
@@ -281,19 +281,13 @@ There are several things that need to be remembered:
|
||||
var/icon_file = DEFAULT_SHOES_FILE
|
||||
|
||||
var/mutable_appearance/shoes_overlay = shoes.build_worn_icon(default_layer = SHOES_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
if(!shoes_overlay)
|
||||
return
|
||||
|
||||
var/feature_y_offset = 0
|
||||
for (var/body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
for (var/body_zone in GLOB.leg_zones)
|
||||
var/obj/item/bodypart/leg/my_leg = get_bodypart(body_zone)
|
||||
if(isnull(my_leg))
|
||||
continue
|
||||
var/list/foot_offset = my_leg.worn_foot_offset?.get_offset()
|
||||
if (foot_offset && foot_offset["y"] > feature_y_offset)
|
||||
feature_y_offset = foot_offset["y"]
|
||||
feature_y_offset = max(my_leg?.worn_foot_offset?.get_offset()["y"], feature_y_offset)
|
||||
|
||||
shoes_overlay.pixel_z += feature_y_offset
|
||||
// apply_height(shoes_overlay, NO_MODIFY) // Shoes are rooted
|
||||
overlays_standing[SHOES_LAYER] = shoes_overlay
|
||||
|
||||
apply_overlay(SHOES_LAYER)
|
||||
@@ -308,6 +302,7 @@ There are several things that need to be remembered:
|
||||
return
|
||||
|
||||
var/mutable_appearance/s_store_overlay = worn_item.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/belt_mirror.dmi')
|
||||
apply_height(s_store_overlay, ENTIRE_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_suit_storage_offset?.apply_offset(s_store_overlay)
|
||||
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
|
||||
@@ -325,6 +320,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = 'icons/mob/clothing/head/default.dmi'
|
||||
|
||||
var/mutable_appearance/head_overlay = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(head_overlay, UPPER_BODY)
|
||||
var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD)
|
||||
my_head?.worn_head_offset?.apply_offset(head_overlay)
|
||||
overlays_standing[HEAD_LAYER] = head_overlay
|
||||
@@ -343,6 +339,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = 'icons/mob/clothing/belt.dmi'
|
||||
|
||||
var/mutable_appearance/belt_overlay = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(belt_overlay, ENTIRE_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_belt_offset?.apply_offset(belt_overlay)
|
||||
overlays_standing[BELT_LAYER] = belt_overlay
|
||||
@@ -362,6 +359,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = DEFAULT_SUIT_FILE
|
||||
|
||||
var/mutable_appearance/suit_overlay = wear_suit.build_worn_icon(default_layer = SUIT_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(suit_overlay, ENTIRE_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_suit_offset?.apply_offset(suit_overlay)
|
||||
overlays_standing[SUIT_LAYER] = suit_overlay
|
||||
@@ -389,6 +387,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file = 'icons/mob/clothing/mask.dmi'
|
||||
|
||||
var/mutable_appearance/mask_overlay = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(mask_overlay, LOWER_BODY)
|
||||
my_head.worn_mask_offset?.apply_offset(mask_overlay)
|
||||
overlays_standing[FACEMASK_LAYER] = mask_overlay
|
||||
|
||||
@@ -399,18 +398,13 @@ There are several things that need to be remembered:
|
||||
hud_used?.update_inventory_slot(ITEM_SLOT_BACK)
|
||||
|
||||
if(back)
|
||||
var/obj/item/worn_item = back
|
||||
var/mutable_appearance/back_overlay
|
||||
|
||||
if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON))
|
||||
if(HAS_TRAIT(back, TRAIT_NO_WORN_ICON))
|
||||
return
|
||||
|
||||
var/icon_file = 'icons/mob/clothing/back.dmi'
|
||||
|
||||
back_overlay = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
|
||||
if(!back_overlay)
|
||||
return
|
||||
var/mutable_appearance/back_overlay = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = icon_file, bodyshape = bodyshape)
|
||||
apply_height(back_overlay, ENTIRE_BODY)
|
||||
var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST)
|
||||
my_chest?.worn_back_offset?.apply_offset(back_overlay)
|
||||
overlays_standing[BACK_LAYER] = back_overlay
|
||||
@@ -425,9 +419,10 @@ There are several things that need to be remembered:
|
||||
if(!t_state)
|
||||
t_state = worn_item.icon_state
|
||||
|
||||
var/mutable_appearance/hand_overlay
|
||||
|
||||
var/icon_file = IS_RIGHT_INDEX(held_index) ? worn_item.righthand_file : worn_item.lefthand_file
|
||||
hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE, bodyshape = bodyshape)
|
||||
var/mutable_appearance/hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE, bodyshape = bodyshape)
|
||||
apply_height(hand_overlay, LOWER_BODY)
|
||||
var/obj/item/bodypart/arm/held_in_hand = hand_bodyparts[held_index]
|
||||
held_in_hand?.held_hand_offset?.apply_offset(hand_overlay)
|
||||
|
||||
@@ -667,14 +662,12 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
|
||||
/mob/living/carbon/human/update_body(is_creating = FALSE)
|
||||
remove_overlay(BODY_LAYER)
|
||||
|
||||
var/list/body_overlays = list()
|
||||
body_overlays += get_underwear_overlays()
|
||||
|
||||
if(length(body_overlays))
|
||||
overlays_standing[BODY_LAYER] = body_overlays
|
||||
var/list/clothing_overlays = get_underwear_overlays()
|
||||
if(length(clothing_overlays))
|
||||
for(var/image/overlay as anything in clothing_overlays)
|
||||
apply_height(overlay, ENTIRE_BODY)
|
||||
overlays_standing[BODY_LAYER] = clothing_overlays
|
||||
apply_overlay(BODY_LAYER)
|
||||
|
||||
// parent call will update the actual bodyparts
|
||||
return ..()
|
||||
|
||||
@@ -722,6 +715,8 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
|
||||
var/list/eye_overlays = noggin.get_eye_overlays()
|
||||
if(length(eye_overlays))
|
||||
for(var/image/overlay as anything in eye_overlays)
|
||||
apply_height(overlay, UPPER_BODY)
|
||||
overlays_standing[EYES_LAYER] = eye_overlays
|
||||
apply_overlay(EYES_LAYER)
|
||||
|
||||
@@ -735,6 +730,8 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
var/obj/item/bodypart/head/head = get_bodypart(BODY_ZONE_HEAD)
|
||||
var/list/head_overlays = head?.get_hair_overlays()
|
||||
if(length(head_overlays))
|
||||
for(var/image/overlay as anything in head_overlays)
|
||||
apply_height(overlay, UPPER_BODY)
|
||||
overlays_standing[HAIR_LAYER] = head_overlays
|
||||
apply_overlay(HAIR_LAYER)
|
||||
|
||||
@@ -751,6 +748,7 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
for (var/mutable_appearance/overlay as anything in eye_overlays)
|
||||
overlay.pixel_w = 0
|
||||
overlay.pixel_z = 0
|
||||
apply_height(overlay, UPPER_BODY)
|
||||
noggin.worn_face_offset.apply_offset(overlay)
|
||||
|
||||
overlays_standing[EYES_LAYER] = eye_overlays
|
||||
@@ -775,56 +773,37 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
update_eyes()
|
||||
update_hair()
|
||||
|
||||
// Hooks into human apply overlay so that we can modify all overlays applied through standing overlays to our height system.
|
||||
// Some of our overlays will be passed through a displacement filter to make our mob look taller or shorter.
|
||||
// Some overlays can't be displaced as they're too close to the edge of the sprite or cross the middle point in a weird way.
|
||||
// So instead we have to pass them through an offset, which is close enough to look good.
|
||||
/mob/living/carbon/human/apply_overlay(cache_index)
|
||||
if(mob_height == HUMAN_HEIGHT_MEDIUM)
|
||||
return ..()
|
||||
|
||||
var/raw_applied = overlays_standing[cache_index]
|
||||
var/string_form_index = num2text(cache_index)
|
||||
var/offset_type = GLOB.layers_to_offset[string_form_index]
|
||||
if(isnull(offset_type))
|
||||
if(islist(raw_applied))
|
||||
for(var/image/applied_appearance in raw_applied)
|
||||
apply_height_filters(applied_appearance)
|
||||
else if(isimage(raw_applied))
|
||||
apply_height_filters(raw_applied)
|
||||
else
|
||||
if(islist(raw_applied))
|
||||
for(var/image/applied_appearance in raw_applied)
|
||||
apply_height_offsets(applied_appearance, offset_type)
|
||||
else if(isimage(raw_applied))
|
||||
apply_height_offsets(raw_applied, offset_type)
|
||||
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Used in some circumstances where appearances can get cut off from the mob sprite from being too tall
|
||||
* Applies an offset or a filter to an appearance accordance to the height of our mob
|
||||
*
|
||||
* upper_torso is to specify whether the appearance is locate in the upper half of the mob rather than the lower half,
|
||||
* higher up things (hats for example) need to be offset more due to the location of the filter displacement
|
||||
* * appearance - The appearance to apply the height changes to
|
||||
* * body_area - The body area this appearance is on, used to determine what offsets/filters to apply
|
||||
*/
|
||||
/mob/living/carbon/human/proc/apply_height_offsets(image/appearance, upper_torso)
|
||||
var/height_to_use = num2text(mob_height)
|
||||
var/final_offset = 0
|
||||
switch(upper_torso)
|
||||
if(UPPER_BODY)
|
||||
final_offset = GLOB.human_heights_to_offsets[height_to_use][1]
|
||||
if(LOWER_BODY)
|
||||
final_offset = GLOB.human_heights_to_offsets[height_to_use][2]
|
||||
else
|
||||
/mob/living/carbon/proc/apply_height(image/appearance, body_area)
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/apply_height(image/appearance, body_area)
|
||||
if(mob_height == HUMAN_HEIGHT_MEDIUM)
|
||||
return // default, no handling needed
|
||||
|
||||
switch(body_area)
|
||||
if(LOWER_BODY, UPPER_BODY)
|
||||
appearance.pixel_z += GLOB.human_heights_to_offsets[mob_height][body_area]
|
||||
return
|
||||
if(ENTIRE_BODY)
|
||||
apply_height_filter(appearance)
|
||||
return
|
||||
if(NO_MODIFY)
|
||||
return
|
||||
|
||||
appearance.pixel_z += final_offset
|
||||
return appearance
|
||||
stack_trace("Invalid height body_area specified ([body_area || "null"])")
|
||||
|
||||
/**
|
||||
* Applies a filter to an appearance according to mob height
|
||||
*/
|
||||
/mob/living/carbon/human/proc/apply_height_filters(image/appearance)
|
||||
/mob/living/carbon/human/proc/apply_height_filter(image/appearance)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
var/static/icon/cut_torso_mask = icon('icons/effects/cut.dmi', "Cut1")
|
||||
var/static/icon/cut_legs_mask = icon('icons/effects/cut.dmi', "Cut2")
|
||||
var/static/icon/lenghten_torso_mask = icon('icons/effects/cut.dmi', "Cut3")
|
||||
@@ -953,8 +932,8 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
// Kinda gross but because many humans overlays do not use KEEP_TOGETHER we need to manually propogate the filter
|
||||
// Otherwise overlays, such as worn overlays on icons, won't have the filter "applied", and the effect kinda breaks
|
||||
if(!(appearance.appearance_flags & KEEP_TOGETHER))
|
||||
for(var/image/overlay in list() + appearance.underlays + appearance.overlays)
|
||||
apply_height_filters(overlay)
|
||||
for(var/mutable_appearance/child_overlay as anything in appearance.underlays + appearance.overlays)
|
||||
apply_height_filter(child_overlay)
|
||||
|
||||
return appearance
|
||||
|
||||
|
||||
@@ -105,8 +105,9 @@
|
||||
layers = EXTERNAL_ADJACENT
|
||||
feature_key = FEATURE_MUSH_CAP
|
||||
dyable = TRUE
|
||||
offset_location = UPPER_BODY
|
||||
|
||||
/datum/bodypart_overlay/mutant/mushroom_cap/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE)
|
||||
/datum/bodypart_overlay/mutant/mushroom_cap/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner)
|
||||
return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
|
||||
|
||||
/datum/bodypart_overlay/mutant/mushroom_cap/override_color(obj/item/bodypart/bodypart_owner)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user