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.

<img width="76" height="77" alt="image"
src="https://github.com/user-attachments/assets/e6f8ffb8-fffa-49a8-93ed-77db618ff347"
/>

## Why It's Good For The Game

Doesn't make sense that lizards would still have pink sinew despite
their blood being green

## Changelog
🆑
image: Sinew on bones from butchered limbs now inherits its owner's
blood color
/🆑
This commit is contained in:
SmArtKar
2026-01-07 00:12:39 -05:00
committed by GitHub
parent 6a7b5cfb39
commit 89d2a16712
7 changed files with 87 additions and 13 deletions
@@ -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/)
@@ -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)]"
@@ -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
+16 -13
View File
@@ -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)
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 49 KiB

+1
View File
@@ -1508,6 +1508,7 @@
#include "code\datums\elements\befriend_petting.dm"
#include "code\datums\elements\block_turf_fingerprints.dm"
#include "code\datums\elements\blocks_explosives.dm"
#include "code\datums\elements\blood_limb_overlay.dm"
#include "code\datums\elements\blood_reagent.dm"
#include "code\datums\elements\body_temp_sensitive.dm"
#include "code\datums\elements\bombable_turf.dm"