From 89d2a167123dad4fcfa5cab4bdbc7e0484460c48 Mon Sep 17 00:00:00 2001
From: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Date: Wed, 7 Jan 2026 06:12:39 +0100
Subject: [PATCH] Sinew on bones from butchered limbs now inherits its owner's
blood color (#94726)
## About The Pull Request
As title says, bones now get a colored overlay corresponding to their
limb's blood color instead of constantly having pink sinew.
## Why It's Good For The Game
Doesn't make sense that lizards would still have pink sinew despite
their blood being green
## Changelog
:cl:
image: Sinew on bones from butchered limbs now inherits its owner's
blood color
/:cl:
---
.../signals/signals_mob/signals_mob_carbon.dm | 6 +++
code/datums/elements/blood_limb_overlay.dm | 39 ++++++++++++++++++
.../mob/living/carbon/carbon_update_icons.dm | 1 +
code/modules/surgery/bodyparts/_bodyparts.dm | 29 +++++++------
.../bodyparts/species_parts/misc_bodyparts.dm | 24 +++++++++++
icons/mob/human/bodyparts.dmi | Bin 49075 -> 50516 bytes
tgstation.dme | 1 +
7 files changed, 87 insertions(+), 13 deletions(-)
create mode 100644 code/datums/elements/blood_limb_overlay.dm
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm
index a463510a438..a632a7dd222 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm
@@ -63,6 +63,12 @@
/// Sent to a limb when something *attempts* to change its surgery state (old_state, new_state, changed_states)
#define COMSIG_BODYPART_UPDATING_SURGERY_STATE "bodypart_updating_surgery_state"
+/// Called from /obj/item/bodypart/proc/get_limb_icon(dropped, mob/living/carbon/update_on) : (list/limb_icons, dropped, mob/living/carbon/update_on)
+#define COMSIG_BODYPART_GET_LIMB_ICON "bodypart_get_limb_icon"
+
+/// Called from /obj/item/bodypart/proc/generate_icon_key() : (list/icon_keys)
+#define COMSIG_BODYPART_GENERATE_ICON_KEY "bodypart_generate_icon_key"
+
///from /item/organ/proc/Insert() (/obj/item/organ/)
#define COMSIG_CARBON_GAIN_ORGAN "carbon_gain_organ"
///from /item/organ/proc/Remove() (/obj/item/organ/)
diff --git a/code/datums/elements/blood_limb_overlay.dm b/code/datums/elements/blood_limb_overlay.dm
new file mode 100644
index 00000000000..0738bc16b13
--- /dev/null
+++ b/code/datums/elements/blood_limb_overlay.dm
@@ -0,0 +1,39 @@
+/// An element which adds a blood overlay to limbs its attached to
+/datum/element/blood_limb_overlay
+
+/datum/element/blood_limb_overlay/Attach(datum/target)
+ . = ..()
+ if (!isbodypart(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_BODYPART_GET_LIMB_ICON, PROC_REF(on_limb_icon))
+ RegisterSignal(target, COMSIG_BODYPART_GENERATE_ICON_KEY, PROC_REF(on_icon_key))
+
+/datum/element/blood_limb_overlay/Detach(datum/source)
+ . = ..()
+ UnregisterSignal(source, list(COMSIG_BODYPART_GET_LIMB_ICON, COMSIG_BODYPART_GENERATE_ICON_KEY))
+
+/datum/element/blood_limb_overlay/proc/on_limb_icon(obj/item/bodypart/source, list/limb_icons, dropped, mob/living/carbon/update_on)
+ SIGNAL_HANDLER
+
+ if (!LAZYLEN(source.blood_dna_info) || source.is_invisible)
+ return
+
+ var/image/limb = limb_icons[1]
+ var/image/blood_visual = image(limb.icon, "[limb.icon_state]_blood", dir = (dropped ? SOUTH : null))
+ // We need to convert it to HSV and then adjust the colors to make them look brighter on the grayscale blood overlay
+ var/list/target_color = rgb2num(get_color_from_blood_list(source.blood_dna_info), COLORSPACE_HSV)
+ blood_visual.color = rgb(target_color[1], ceil(target_color[2] * 0.4), clamp(ceil(target_color[3] * 1.33), 0, 100), space = COLORSPACE_HSV)
+ limb.overlays += blood_visual
+ if (!source.aux_zone)
+ return
+
+ var/image/aux = limb_icons[2]
+ var/image/aux_blood_visual = image(aux.icon, "[aux.icon_state]_blood", dir = (dropped ? SOUTH : null))
+ aux_blood_visual.color = blood_visual.color
+ aux.overlays += aux_blood_visual
+
+/datum/element/blood_limb_overlay/proc/on_icon_key(obj/item/bodypart/source, list/icon_keys)
+ SIGNAL_HANDLER
+
+ if (LAZYLEN(source.blood_dna_info) && !source.is_invisible)
+ icon_keys += "-blood-[get_color_from_blood_list(source.blood_dna_info)]"
diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm
index cf17720ee6e..19d5039de92 100644
--- a/code/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/code/modules/mob/living/carbon/carbon_update_icons.dm
@@ -537,6 +537,7 @@
if(ishuman(owner))
var/mob/living/carbon/human/human_owner = owner
. += "-[human_owner.mob_height]"
+ SEND_SIGNAL(src, COMSIG_BODYPART_GENERATE_ICON_KEY, .)
return .
///Generates a cache key specifically for husks
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 04005ff4eff..475cb1ffcd3 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -1264,19 +1264,6 @@
icon_state = "" //to erase the default sprite, we're building the visual aspects of the bodypart through overlays alone.
. = list()
-
- if(dropped && dmg_overlay_type)
- if(brutestate)
- // divided into two overlays: one that gets colored and one that doesn't.
- var/image/brute_blood_overlay = image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0", -DAMAGE_LAYER, dir = SOUTH)
- brute_blood_overlay.color = get_color_from_blood_list(update_on ? update_on.get_blood_dna_list() : blood_dna_info) // living mobs can just get it fresh, dropped limbs use blood_dna_info
- var/mutable_appearance/brute_damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0_overlay", -DAMAGE_LAYER, appearance_flags = RESET_COLOR)
- if(brute_damage_overlay)
- brute_blood_overlay.overlays += brute_damage_overlay
- . += brute_blood_overlay
- if(burnstate)
- . += image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_0[burnstate]", -DAMAGE_LAYER, dir = SOUTH)
-
var/image_dir = null
if (dropped)
image_dir = SOUTH
@@ -1284,6 +1271,7 @@
// Handles invisibility (not alpha or actual invisibility but invisibility)
if(is_invisible)
. += image(icon_invisible, "invisible_[body_zone]", -BODYPARTS_LAYER, dir = image_dir)
+ SEND_SIGNAL(src, COMSIG_BODYPART_GET_LIMB_ICON, ., dropped, update_on)
return .
// Normal non-husk handling
@@ -1307,6 +1295,18 @@
aux = image(limb.icon, "[limb_id]_[aux_zone]", -aux_layer, dir = image_dir)
. += aux
+ if(dropped && dmg_overlay_type)
+ if(brutestate)
+ // divided into two overlays: one that gets colored and one that doesn't.
+ var/image/brute_blood_overlay = image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0", -DAMAGE_LAYER, dir = SOUTH)
+ brute_blood_overlay.color = get_color_from_blood_list(update_on ? update_on.get_blood_dna_list() : blood_dna_info) // living mobs can just get it fresh, dropped limbs use blood_dna_info
+ var/mutable_appearance/brute_damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0_overlay", -DAMAGE_LAYER, appearance_flags = RESET_COLOR)
+ if(brute_damage_overlay)
+ brute_blood_overlay.overlays += brute_damage_overlay
+ . += brute_blood_overlay
+ if(burnstate)
+ . += image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_0[burnstate]", -DAMAGE_LAYER, dir = SOUTH)
+
if(is_husked)
. += huskify_image(thing_to_husk = limb)
if(aux)
@@ -1357,6 +1357,7 @@
// And finally put bodypart_overlays on if not husked
if(is_husked)
+ SEND_SIGNAL(src, COMSIG_BODYPART_GET_LIMB_ICON, ., dropped, update_on)
return .
// Draw external organs like horns and frills
@@ -1383,6 +1384,8 @@
for(var/datum/layer in .)
overlay.modify_bodypart_appearance(layer)
+
+ SEND_SIGNAL(src, COMSIG_BODYPART_GET_LIMB_ICON, ., dropped, update_on)
return .
/obj/item/bodypart/proc/huskify_image(image/thing_to_husk)
diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
index 8ff6971118e..c504f51c38a 100644
--- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
@@ -435,10 +435,18 @@
// These are always disabled
disabling_threshold_percentage = 0
+/obj/item/bodypart/head/skeleton/nonfunctional/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/blood_limb_overlay)
+
/obj/item/bodypart/chest/skeleton/nonfunctional
limb_id = BODYPART_ID_BONE
disabling_threshold_percentage = 0
+/obj/item/bodypart/chest/skeleton/nonfunctional/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/blood_limb_overlay)
+
/obj/item/bodypart/chest/skeleton/nonfunctional/on_adding(mob/living/carbon/new_owner)
. = ..()
// Treat people with bone chests as husks for all purposes for now
@@ -453,18 +461,34 @@
limb_id = BODYPART_ID_BONE
disabling_threshold_percentage = 0
+/obj/item/bodypart/arm/left/skeleton/nonfunctional/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/blood_limb_overlay)
+
/obj/item/bodypart/arm/right/skeleton/nonfunctional
limb_id = BODYPART_ID_BONE
disabling_threshold_percentage = 0
+/obj/item/bodypart/arm/right/skeleton/nonfunctional/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/blood_limb_overlay)
+
/obj/item/bodypart/leg/left/skeleton/nonfunctional
limb_id = BODYPART_ID_BONE
disabling_threshold_percentage = 0
+/obj/item/bodypart/leg/left/skeleton/nonfunctional/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/blood_limb_overlay)
+
/obj/item/bodypart/leg/right/skeleton/nonfunctional
limb_id = BODYPART_ID_BONE
disabling_threshold_percentage = 0
+/obj/item/bodypart/leg/right/skeleton/nonfunctional/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/blood_limb_overlay)
+
///MUSHROOM
/obj/item/bodypart/head/mushroom
limb_id = SPECIES_MUSHROOM
diff --git a/icons/mob/human/bodyparts.dmi b/icons/mob/human/bodyparts.dmi
index 7fd40bb0bf2be64d829d21969c259d271fd7ab98..b37d44f6f8b4ae730a906f7671ea73b106bb47a2 100644
GIT binary patch
delta 10807
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
delta 9355
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æ}4o@Q@)!+SZ;^E?2NJ*_LD6YQfI0F3*6
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