Cleans up duplicate calls in bodypart overlays, implements a texture priority system (#89783)

## About The Pull Request

Implemented a bodypart texture overlay priority system - ensures that
derez suicide always goes ontop of carp infusions, and voidwalker curse
goes ontop of both - currently the last one applied is the one that
sticks with you. Also cleaned up duplicate update_body calls, either
removing them or adding ``update = FALSE`` to overlay code.

## Why It's Good For The Game

Having whichever overlay was applied the latest be displayed is just too
inconsistent. And duplicate calls eat perf, bad.
This commit is contained in:
SmArtKar
2025-03-11 19:28:34 +01:00
committed by GitHub
parent 6f22e7fb1f
commit fc71aa3977
18 changed files with 134 additions and 49 deletions

View File

@@ -47,7 +47,13 @@
// Color priorities for bodyparts
#define LIMB_COLOR_HULK 10
#define LIMB_COLOR_CARP_INFUSION 20
#define LIMB_COLOR_CS_SOURCE_SUICIDE 30
/// Base priority for atom colors, gets atom priorities added to it
#define LIMB_COLOR_ATOM_COLOR 30
#define LIMB_COLOR_ATOM_COLOR 40
/// Voidwalker effect color priority
#define LIMB_COLOR_VOIDWALKER_CURSE 40
#define LIMB_COLOR_VOIDWALKER_CURSE 50
// Overlay priorities
#define BODYPART_OVERLAY_CARP_INFUSION 1
#define BODYPART_OVERLAY_CSS_SUICIDE 2
#define BODYPART_OVERLAY_VOIDWALKER_CURSE 3

View File

@@ -69,7 +69,7 @@
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(mob/living/carbon/human/human)
/datum/bodypart_overlay/proc/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
return TRUE
///Colorizes the limb it's inserted to, if required.

View File

@@ -35,7 +35,7 @@
. += use_gender
. += draw_color
/datum/bodypart_overlay/simple/body_marking/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/simple/body_marking/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
return icon_state != SPRITE_ACCESSORY_NONE
/datum/bodypart_overlay/simple/body_marking/get_image(layer, obj/item/bodypart/limb)

View File

@@ -6,27 +6,37 @@
var/texture_icon_state
/// Cache the icon so we dont have to make a new one each time
var/cached_texture_icon
/// Priority of this texture - all textures with a lower priority will not be rendered
var/overlay_priority = 0
/datum/bodypart_overlay/texture/New()
. = ..()
cached_texture_icon = icon(texture_icon, texture_icon_state)
/datum/bodypart_overlay/texture/modify_bodypart_appearance(datum/appearance)
appearance.add_filter("bodypart_texture_[texture_icon_state]", 1, layering_filter(icon = cached_texture_icon,blend_mode = BLEND_INSET_OVERLAY))
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()
return "[type]"
/datum/bodypart_overlay/texture/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
for (var/datum/bodypart_overlay/texture/other_texture in bodypart_owner.bodypart_overlays)
if (other_texture.overlay_priority > overlay_priority)
return FALSE
return TRUE
/datum/bodypart_overlay/texture/spacey
blocks_emissive = EMISSIVE_BLOCK_NONE
texture_icon_state = "spacey"
texture_icon = 'icons/mob/human/textures.dmi'
overlay_priority = BODYPART_OVERLAY_VOIDWALKER_CURSE
/datum/bodypart_overlay/texture/carpskin
texture_icon_state = "carpskin"
texture_icon = 'icons/mob/human/textures.dmi'
overlay_priority = BODYPART_OVERLAY_CARP_INFUSION
/datum/bodypart_overlay/texture/checkered
texture_icon_state = "checkered"
texture_icon = 'icons/mob/human/textures.dmi'
overlay_priority = BODYPART_OVERLAY_CSS_SUICIDE

View File

@@ -78,9 +78,8 @@
hewmon = aliver
head = hewmon.get_bodypart(BODY_ZONE_HEAD)
if(head)
soul_eyes = new /datum/bodypart_overlay/simple/soul_pending_eyes ()
soul_eyes = new /datum/bodypart_overlay/simple/soul_pending_eyes()
head.add_bodypart_overlay(soul_eyes)
hewmon.update_body_parts()
var/mob/dead/observer/chosen_one = SSpolling.poll_ghosts_for_target(
question = "Would you like to play as a recovered crewmember?",
@@ -94,7 +93,6 @@
)
if(head)
head.remove_bodypart_overlay(soul_eyes)
hewmon?.update_body_parts()
if(!isobserver(chosen_one))
if(refuse_revival_if_failed)

View File

@@ -100,10 +100,16 @@
// Add limb overlay
if(!iscarbon(owner) || !limb_overlay)
return TRUE
var/mob/living/carbon/carbon_owner = owner
for(var/obj/item/bodypart/limb in carbon_owner.bodyparts)
limb.add_bodypart_overlay(new limb_overlay())
limb.add_color_override(COLOR_WHITE, color_overlay_priority)
RegisterSignal(carbon_owner, COMSIG_CARBON_ATTACH_LIMB, PROC_REF(texture_limb))
RegisterSignal(carbon_owner, COMSIG_CARBON_REMOVE_LIMB, PROC_REF(untexture_limb))
for(var/obj/item/bodypart/limb as anything in carbon_owner.bodyparts)
limb.add_bodypart_overlay(new limb_overlay(), update = FALSE)
if (color_overlay_priority)
limb.add_color_override(COLOR_WHITE, color_overlay_priority)
carbon_owner.update_body()
return TRUE
@@ -122,12 +128,39 @@
to_chat(owner, bonus_deactivate_text)
// Remove limb overlay
if(!iscarbon(owner) || QDELETED(owner) || !limb_overlay)
if(!iscarbon(owner) || !limb_overlay)
return
var/mob/living/carbon/carbon_owner = owner
for(var/obj/item/bodypart/limb in carbon_owner.bodyparts)
UnregisterSignal(carbon_owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))
if(QDELETED(carbon_owner))
return
for(var/obj/item/bodypart/limb as anything in carbon_owner.bodyparts)
var/overlay = locate(limb_overlay) in limb.bodypart_overlays
if(overlay)
limb.remove_bodypart_overlay(overlay)
if(!overlay)
continue
limb.remove_bodypart_overlay(overlay, update = FALSE)
if (color_overlay_priority)
limb.remove_color_override(color_overlay_priority)
carbon_owner.update_body()
/datum/status_effect/organ_set_bonus/proc/texture_limb(atom/source, obj/item/bodypart/limb)
SIGNAL_HANDLER
// Not updating because enable/disable_bonus() 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)
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)
if(color_overlay_priority)
limb.remove_color_override(color_overlay_priority)

View File

@@ -51,12 +51,14 @@
for(var/obj/item/bodypart/bodypart as anything in owner.bodyparts)
untexture_limb(owner, bodypart)
owner.update_body()
/// Apply the space texture
/datum/brain_trauma/voided/proc/texture_limb(atom/source, obj/item/bodypart/limb)
SIGNAL_HANDLER
limb.add_bodypart_overlay(new bodypart_overlay_type)
// 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_color_override(space_color, LIMB_COLOR_VOIDWALKER_CURSE)
if(istype(limb, /obj/item/bodypart/head))
var/obj/item/bodypart/head/head = limb
@@ -67,7 +69,7 @@
var/overlay = locate(bodypart_overlay_type) in limb.bodypart_overlays
if(overlay)
limb.remove_bodypart_overlay(overlay)
limb.remove_bodypart_overlay(overlay, update = FALSE)
limb.remove_color_override(LIMB_COLOR_VOIDWALKER_CURSE)
if(istype(limb, /obj/item/bodypart/head))

View File

@@ -112,17 +112,17 @@
beauty = FISH_BEAUTY_NULL
/obj/item/fish/holo/checkered/suicide_act(mob/living/carbon/user)
if(!iscarbon(user))
return ..()
for(var/obj/item/bodypart/limb in user.bodyparts)
limb.add_bodypart_overlay(new /datum/bodypart_overlay/texture/checkered)
limb.add_color_override(COLOR_WHITE, LIMB_COLOR_CS_SOURCE_SUICIDE)
limb.add_bodypart_overlay(new /datum/bodypart_overlay/texture/checkered(), update = FALSE)
var/obj/item/bodypart/head/head = user.get_bodypart(BODY_ZONE_HEAD)
if(!isnull(head))
head.head_flags &= ~HEAD_EYESPRITES
user.update_body()
return ..()
/obj/item/fish/holo/halffish

View File

@@ -716,7 +716,10 @@
/datum/bodypart_overlay/simple/babbearfish
icon_state = "babbearfish"
/datum/bodypart_overlay/simple/babbearfish/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/simple/babbearfish/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if((human.head?.flags_inv & HIDEEARS) || (human.wear_mask?.flags_inv & HIDEEARS))
return FALSE
return TRUE

View File

@@ -528,7 +528,7 @@
if(is_invisible)
. += "-invisible"
for(var/datum/bodypart_overlay/overlay as anything in bodypart_overlays)
if(!overlay.can_draw_on_bodypart(owner))
if(!overlay.can_draw_on_bodypart(src, owner))
continue
. += "-[jointext(overlay.generate_icon_cache(), "-")]"
if(ishuman(owner))

View File

@@ -88,10 +88,12 @@
/datum/bodypart_overlay/mutant/mushroom_cap/get_global_feature_list()
return SSaccessories.caps_list
/datum/bodypart_overlay/mutant/mushroom_cap/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/mushroom_cap/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR))
return FALSE
return TRUE
/datum/bodypart_overlay/mutant/mushroom_cap/override_color(obj/item/bodypart/bodypart_owner)

View File

@@ -1127,7 +1127,7 @@
if(!is_husked)
//Draw external organs like horns and frills
for(var/datum/bodypart_overlay/overlay as anything in bodypart_overlays)
if(!dropped && !overlay.can_draw_on_bodypart(owner)) //if you want different checks for dropped bodyparts, you can insert it here
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)

View File

@@ -121,10 +121,12 @@ Unlike normal organs, we're actually inside a persons limbs at all times
feature_key = "horns"
dyable = TRUE
/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR))
return FALSE
return TRUE
/datum/bodypart_overlay/mutant/horns/get_global_feature_list()
@@ -151,7 +153,10 @@ Unlike normal organs, we're actually inside a persons limbs at all times
layers = EXTERNAL_ADJACENT
feature_key = "frills"
/datum/bodypart_overlay/mutant/frills/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/frills/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if(!(human.head?.flags_inv & HIDEEARS))
return TRUE
return FALSE
@@ -182,10 +187,13 @@ Unlike normal organs, we're actually inside a persons limbs at all times
layers = EXTERNAL_ADJACENT
feature_key = "snout"
/datum/bodypart_overlay/mutant/snout/can_draw_on_bodypart(mob/living/carbon/human/human)
if(!(human.wear_mask?.flags_inv & HIDESNOUT) && !(human.head?.flags_inv & HIDESNOUT))
/datum/bodypart_overlay/mutant/snout/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
return FALSE
if((human.head?.flags_inv & HIDESNOUT) || (human.wear_mask?.flags_inv & HIDESNOUT))
return FALSE
return TRUE
/datum/bodypart_overlay/mutant/snout/get_global_feature_list()
return SSaccessories.snouts_list
@@ -272,7 +280,10 @@ 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(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/antennae/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if(!(human.head?.flags_inv & HIDEANTENNAE))
return TRUE
return FALSE
@@ -320,8 +331,10 @@ 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(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/pod_hair/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR))
return FALSE
return TRUE

View File

@@ -37,10 +37,13 @@
/datum/bodypart_overlay/mutant/spines/get_global_feature_list()
return SSaccessories.spines_list
/datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(mob/living/carbon/human/human)
. = ..()
if(human.wear_suit && (human.wear_suit.flags_inv & HIDEJUMPSUIT))
/datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if(human.wear_suit?.flags_inv & HIDEJUMPSUIT)
return FALSE
return TRUE
/datum/bodypart_overlay/mutant/spines/set_dye_color(new_color, obj/item/organ/tail/organ)
var/obj/item/organ/tail/tail = organ?.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)

View File

@@ -147,8 +147,11 @@
/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(mob/living/carbon/human/human)
if(human.wear_suit && (human.wear_suit.flags_inv & HIDEJUMPSUIT))
/datum/bodypart_overlay/mutant/tail/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if(human.wear_suit?.flags_inv & HIDEJUMPSUIT)
return FALSE
return TRUE
@@ -279,10 +282,13 @@
/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(mob/living/carbon/human/human)
. = ..()
if(human.wear_suit && (human.wear_suit.flags_inv & HIDEJUMPSUIT))
/datum/bodypart_overlay/mutant/tail_spines/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if(human.wear_suit?.flags_inv & HIDEJUMPSUIT)
return FALSE
return TRUE
/datum/bodypart_overlay/mutant/tail_spines/set_dye_color(new_color, obj/item/organ/organ)
dye_color = new_color //no update_body_parts() call, tail/set_dye_color will do it.

View File

@@ -111,10 +111,13 @@
/datum/bodypart_overlay/mutant/wings/moth/get_global_feature_list()
return SSaccessories.moth_wings_list
/datum/bodypart_overlay/mutant/wings/moth/can_draw_on_bodypart(mob/living/carbon/human/human)
if(!(human.wear_suit?.flags_inv & HIDEMUTWINGS))
/datum/bodypart_overlay/mutant/wings/moth/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
return FALSE
if(human.wear_suit?.flags_inv & HIDEMUTWINGS)
return FALSE
return TRUE
/datum/bodypart_overlay/mutant/wings/moth/get_base_icon_state()
return burnt ? burn_datum.icon_state : sprite_datum.icon_state

View File

@@ -24,7 +24,10 @@
layers = ALL_EXTERNAL_OVERLAYS
feature_key = "wings"
/datum/bodypart_overlay/mutant/wings/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/wings/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if(!human.wear_suit)
return TRUE
if(!(human.wear_suit.flags_inv & HIDEJUMPSUIT))

View File

@@ -173,7 +173,10 @@
/datum/bodypart_overlay/mutant/cat_ears/get_global_feature_list()
return SSaccessories.ears_list
/datum/bodypart_overlay/mutant/cat_ears/can_draw_on_bodypart(mob/living/carbon/human/human)
/datum/bodypart_overlay/mutant/cat_ears/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
var/mob/living/carbon/human/human = bodypart_owner.owner
if(!istype(human))
return TRUE
if((human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR))
return FALSE
return TRUE