diff --git a/code/__DEFINES/bodyparts.dm b/code/__DEFINES/bodyparts.dm index 04947265cbe..82f153b5568 100644 --- a/code/__DEFINES/bodyparts.dm +++ b/code/__DEFINES/bodyparts.dm @@ -1,6 +1,9 @@ ///The standard amount of bodyparts a carbon has. Currently 6, HEAD/L_ARM/R_ARM/CHEST/L_LEG/R_LEG #define BODYPARTS_DEFAULT_MAXIMUM 6 +// The lowest alpha a dropped limb's sprite will render at, unlike a attached limb which can be 0 +#define LIMB_DROPPED_MIN_ALPHA 40 /// BUBBER EDIT ADDITION + /// Limb Health /// The max damage a limb can take before it stops taking damage. diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 03fe07df0c5..dd401d18b5b 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -543,6 +543,10 @@ . += draw_color if(is_invisible) . += "invisible" + // BUBBER EDIT ADDITION START - per-limb alpha + if(limb_alpha != 255) + . += "alpha_[limb_alpha]" + // BUBBER EDIT ADDITION END for(var/datum/bodypart_overlay/overlay as anything in bodypart_overlays) if(!overlay.can_draw_on_bodypart(src, owner, is_husked)) continue @@ -571,6 +575,8 @@ . += body_zone if(is_invisible) . += "invisible" + if(limb_alpha != 255) + . += "alpha_[limb_alpha]" // BUBBER EDIT ADDITION - per-limb alpha . += "[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)) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 9cd19e026b7..1bccd9bc15f 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -1216,6 +1216,14 @@ if(owner_species && owner_species.specific_alpha != 255) alpha = owner_species.specific_alpha + // BUBBER EDIT ADDITION START - per-limb alpha. + // preference (stored in dna.features) overrides it for this specific zone if present over species alpha + limb_alpha = owner_species?.specific_alpha || 255 + var/limb_alpha_key = "limb_alpha_[body_zone]" + if(limb_alpha_key in human_owner.dna.features) + limb_alpha = human_owner.dna.features[limb_alpha_key] + // BUBBER EDIT ADDITION END + if(body_zone in owner_species.body_markings) markings = LAZYCOPY(owner_species.body_markings[body_zone]) if(aux_zone && (aux_zone in owner_species.body_markings)) @@ -1327,12 +1335,19 @@ var/image/limb = image(used_icon, used_state, -BODYPARTS_LAYER, dir = image_dir) var/image/aux = null + // BUBBER EDIT ADDITION - per-limb alpha. While worn the chosen alpha is used verbatim (0 = invisible), + // while dropped it is floored so the limb stays visible and pickup-able on the ground. + var/used_alpha = dropped ? max(limb_alpha, LIMB_DROPPED_MIN_ALPHA) : limb_alpha + limb.alpha = used_alpha + // BUBBER EDIT ADDITION END + icon_exists_or_scream(limb.icon, limb.icon_state) //Prints a stack trace on the first failure of a given iconstate. . += limb if(aux_zone) //Hand shit aux = image(limb.icon, "[limb_id]_[aux_zone]", -aux_layer, dir = image_dir) + aux.alpha = used_alpha // BUBBER EDIT ADDITION - per-limb alpha . += aux if(dropped && dmg_overlay_type) @@ -1356,10 +1371,12 @@ update_draw_color() if(draw_color) - var/limb_color = alpha != 255 ? "[draw_color][num2hex(alpha, 2)]" : "[draw_color]" // SKYRAT EDIT ADDITION - Alpha values on limbs. We check if the limb is attached and if the owner has an alpha value to append - limb.color = limb_color // SKYRAT EDIT CHANGE - ORIGINAL: limb.color = "[draw_color]" + // BUBBER EDIT CHANGE - per-limb transparency is now handled via limb.alpha (see above) rather than + // baking an alpha channel into the draw color. ORIGINAL SKYRAT: limb.color = "[draw_color][num2hex(alpha, 2)]" + limb.color = "[draw_color]" if(aux_zone) - aux.color = limb_color // SKYRAT EDIT CHANGE - ORIGINAL: aux.color = "[draw_color]" + aux.color = "[draw_color]" + // BUBBER EDIT END var/atom/location = loc || owner || src if(blocks_emissive != EMISSIVE_BLOCK_NONE) diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_jelly_roundstartslime.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_jelly_roundstartslime.png index 7d2fb75e560..6e82d165901 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_jelly_roundstartslime.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_jelly_roundstartslime.png differ diff --git a/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm index b1b1e00212a..9dbaadeca8d 100644 --- a/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/_mutant_bodyparts.dm @@ -5,6 +5,10 @@ var/list/aux_zone_markings /// The alpha override of our markings. var/markings_alpha + /// The alpha the limb's sprite overlays are rendered at. Driven by the per-limb alpha + /// preferences (and species specific_alpha). 0 is fully invisible while worn; while dropped + /// the rendered sprite is floored at LIMB_DROPPED_MIN_ALPHA so the limb stays pickup-able. + var/limb_alpha = 255 /// What is our normal limb ID? used for squashing legs. var/base_limb_id = SPECIES_MAMMAL diff --git a/modular_zubbers/code/modules/client/preferences/limb_alpha.dm b/modular_zubbers/code/modules/client/preferences/limb_alpha.dm new file mode 100644 index 00000000000..3449ef0c965 --- /dev/null +++ b/modular_zubbers/code/modules/client/preferences/limb_alpha.dm @@ -0,0 +1,72 @@ +/** + * Per-limb alpha (transparency) preferences. + */ + +/// Toggle that reveals the per-limb (arm/leg) alpha sliders. +/datum/preference/toggle/limb_alpha_per_limb + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + savefile_identifier = PREFERENCE_CHARACTER + savefile_key = "limb_alpha_per_limb" + default_value = FALSE + can_randomize = FALSE + +/datum/preference/toggle/limb_alpha_per_limb/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return + +/datum/preference/numeric/limb_alpha + abstract_type = /datum/preference/numeric/limb_alpha + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + savefile_identifier = PREFERENCE_CHARACTER + minimum = 0 + maximum = 255 + can_randomize = FALSE + /// The BODY_ZONE_* this slider controls. Also forms the dna.features key. + var/limb_zone + /// If FALSE, the slider is hidden entirely. Kept around so head/chest can be re-enabled later. + var/enabled = TRUE + +/datum/preference/numeric/limb_alpha/create_default_value() + return maximum + +/datum/preference/numeric/limb_alpha/is_accessible(datum/preferences/preferences) + if(!enabled) + return FALSE + if(!..()) + return FALSE + if(!preferences.read_preference(/datum/preference/toggle/limb_alpha_per_limb)) + return FALSE + return TRUE + +/datum/preference/numeric/limb_alpha/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + if(!enabled) + value = maximum + else if(preferences && !preferences.read_preference(/datum/preference/toggle/limb_alpha_per_limb)) + value = maximum + target.dna.features["limb_alpha_[limb_zone]"] = value + return TRUE + +// Head and chest are intentionally disabled for now (the sliders/keys are kept so they can be +// re-enabled by simply flipping `enabled` back to TRUE). +/datum/preference/numeric/limb_alpha/head + savefile_key = "limb_alpha_head" + limb_zone = BODY_ZONE_HEAD + +/datum/preference/numeric/limb_alpha/chest + savefile_key = "limb_alpha_chest" + limb_zone = BODY_ZONE_CHEST + +/datum/preference/numeric/limb_alpha/l_arm + savefile_key = "limb_alpha_l_arm" + limb_zone = BODY_ZONE_L_ARM + +/datum/preference/numeric/limb_alpha/r_arm + savefile_key = "limb_alpha_r_arm" + limb_zone = BODY_ZONE_R_ARM + +/datum/preference/numeric/limb_alpha/l_leg + savefile_key = "limb_alpha_l_leg" + limb_zone = BODY_ZONE_L_LEG + +/datum/preference/numeric/limb_alpha/r_leg + savefile_key = "limb_alpha_r_leg" + limb_zone = BODY_ZONE_R_LEG diff --git a/tgstation.dme b/tgstation.dme index 72201237fe4..ea2e1ca1f12 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -9563,6 +9563,7 @@ #include "modular_zubbers\code\modules\client\flavor_text\flavor_text.dm" #include "modular_zubbers\code\modules\client\preferences\blooper.dm" #include "modular_zubbers\code\modules\client\preferences\footstep_sound.dm" +#include "modular_zubbers\code\modules\client\preferences\limb_alpha.dm" #include "modular_zubbers\code\modules\client\preferences\permanent_limp.dm" #include "modular_zubbers\code\modules\client\preferences\player_panel.dm" #include "modular_zubbers\code\modules\client\preferences\screen.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/limb_alpha.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/limb_alpha.tsx new file mode 100644 index 00000000000..e70954a3cd9 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/bubbers/limb_alpha.tsx @@ -0,0 +1,53 @@ +import { + CheckboxInput, + type Feature, + FeatureSliderInput, + type FeatureToggle, +} from '../../base'; + +// Names share the "Limb Transparency" prefix so the panel (which sorts secondary features +// alphabetically by name) keeps them grouped together, toggle first. +export const limb_alpha_per_limb: FeatureToggle = { + name: 'Limb Transparency', + description: + 'Reveals the per-limb transparency sliders for your arms and legs. While off, those limbs stay fully opaque.', + component: CheckboxInput, +}; + +export const limb_alpha_head: Feature = { + name: 'Limb Transparency: Head', + description: + 'How opaque your head is. 0 is fully invisible while worn; dropped limbs stay faintly visible so they can be picked up.', + component: FeatureSliderInput, +}; + +export const limb_alpha_chest: Feature = { + name: 'Limb Transparency: Chest', + description: + 'How opaque your chest is. 0 is fully invisible while worn; dropped limbs stay faintly visible so they can be picked up.', + component: FeatureSliderInput, +}; + +export const limb_alpha_l_arm: Feature = { + name: 'Limb Transparency: Left Arm', + description: 'How opaque your left arm is.', + component: FeatureSliderInput, +}; + +export const limb_alpha_r_arm: Feature = { + name: 'Limb Transparency: Right Arm', + description: 'How opaque your right arm is.', + component: FeatureSliderInput, +}; + +export const limb_alpha_l_leg: Feature = { + name: 'Limb Transparency: Left Leg', + description: 'How opaque your left leg is.', + component: FeatureSliderInput, +}; + +export const limb_alpha_r_leg: Feature = { + name: 'Limb Transparency: Right Leg', + description: 'How opaque your right leg is.', + component: FeatureSliderInput, +};