diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index c867e642b4..9fe7f221e1 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -74,6 +74,7 @@ drop_l_hand() if(healths) + healths.overlays = null // This is specific to humans but the relevant code is here; shouldn't mess with other mobs. healths.icon_state = "health6" timeofdeath = world.time diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 7a29b140b2..c2906783ec 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1032,37 +1032,38 @@ var/obj/machinery/camera/cam = client.eye client.screen |= cam.client_huds - if(stat == UNCONSCIOUS && health <= 0) - //Critical damage passage overlay - var/severity = 0 - switch(health) - if(-20 to -10) severity = 1 - if(-30 to -20) severity = 2 - if(-40 to -30) severity = 3 - if(-50 to -40) severity = 4 - if(-60 to -50) severity = 5 - if(-70 to -60) severity = 6 - if(-80 to -70) severity = 7 - if(-90 to -80) severity = 8 - if(-95 to -90) severity = 9 - if(-INFINITY to -95) severity = 10 - overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity) - else - clear_fullscreen("crit") - //Oxygen damage overlay - if(oxyloss) + if(stat != DEAD) + if(stat == UNCONSCIOUS && health <= 0) + //Critical damage passage overlay var/severity = 0 - switch(oxyloss) - if(10 to 20) severity = 1 - if(20 to 25) severity = 2 - if(25 to 30) severity = 3 - if(30 to 35) severity = 4 - if(35 to 40) severity = 5 - if(40 to 45) severity = 6 - if(45 to INFINITY) severity = 7 - overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity) + switch(health) + if(-20 to -10) severity = 1 + if(-30 to -20) severity = 2 + if(-40 to -30) severity = 3 + if(-50 to -40) severity = 4 + if(-60 to -50) severity = 5 + if(-70 to -60) severity = 6 + if(-80 to -70) severity = 7 + if(-90 to -80) severity = 8 + if(-95 to -90) severity = 9 + if(-INFINITY to -95) severity = 10 + overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity) else - clear_fullscreen("oxy") + clear_fullscreen("crit") + //Oxygen damage overlay + if(oxyloss) + var/severity = 0 + switch(oxyloss) + if(10 to 20) severity = 1 + if(20 to 25) severity = 2 + if(25 to 30) severity = 3 + if(30 to 35) severity = 4 + if(35 to 40) severity = 5 + if(40 to 45) severity = 6 + if(45 to INFINITY) severity = 7 + overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity) + else + clear_fullscreen("oxy") //Fire and Brute damage overlay (BSSR) var/hurtdamage = src.getBruteLoss() + src.getFireLoss() + damageoverlaytemp @@ -1138,19 +1139,37 @@ if (analgesic > 100) healths.icon_state = "health_numb" else - switch(hal_screwyhud) - if(1) healths.icon_state = "health6" - if(2) healths.icon_state = "health7" - else - //switch(health - halloss) - switch(100 - (!can_feel_pain() ? 0 : traumatic_shock)) - if(100 to INFINITY) healths.icon_state = "health0" - if(80 to 100) healths.icon_state = "health1" - if(60 to 80) healths.icon_state = "health2" - if(40 to 60) healths.icon_state = "health3" - if(20 to 40) healths.icon_state = "health4" - if(0 to 20) healths.icon_state = "health5" - else healths.icon_state = "health6" + // Generate a by-limb health display. + healths.icon_state = "blank" + healths.overlays = null + + var/no_damage = 1 + var/trauma_val = 0 // Used in calculating softcrit/hardcrit indicators. + if(!(species.flags & NO_PAIN)) + trauma_val = max(traumatic_shock,halloss)/species.total_health + var/limb_trauma_val = trauma_val*0.3 + // Collect and apply the images all at once to avoid appearance churn. + var/list/health_images = list() + for(var/obj/item/organ/external/E in organs) + if(no_damage && (E.brute_dam || E.burn_dam)) + no_damage = 0 + health_images += E.get_damage_hud_image(limb_trauma_val) + + // Apply a fire overlay if we're burning. + if(on_fire) + health_images += image('icons/mob/screen1_health.dmi',"burning") + + // Show a general pain/crit indicator if needed. + if(trauma_val) + if(!(species.flags & NO_PAIN)) + if(trauma_val > 0.7) + health_images += image('icons/mob/screen1_health.dmi',"softcrit") + if(trauma_val >= 1) + health_images += image('icons/mob/screen1_health.dmi',"hardcrit") + else if(no_damage) + health_images += image('icons/mob/screen1_health.dmi',"fullhealth") + + healths.overlays += health_images if(nutrition_icon) switch(nutrition) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index def9ae59f2..5a8fcba715 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -108,6 +108,7 @@ // HUD data vars. var/datum/hud_data/hud var/hud_type + var/health_hud_intensity = 1 // This modifies how intensely the health hud is colored. // Body/form vars. var/list/inherent_verbs // Species-specific verbs. diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm index 6074934cec..738284dd38 100644 --- a/code/modules/mob/living/carbon/human/species/station/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm @@ -14,6 +14,7 @@ mob_size = MOB_SMALL has_fine_manipulation = 0 show_ssd = null + health_hud_intensity = 2 gibbed_anim = "gibbed-m" dusted_anim = "dust-m" diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 2ada0dd7c7..5eae3da61e 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -23,6 +23,7 @@ var/datum/species/shapeshifter/promethean/prometheans flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT appearance_flags = HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_HAIR_COLOR | RADIATION_GLOWS spawn_flags = SPECIES_IS_RESTRICTED + health_hud_intensity = 2 breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 12e87f9328..d6744f252e 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -11,6 +11,7 @@ name_language = "Schechi" min_age = 12 max_age = 45 + health_hud_intensity = 3 blood_color = "#D514F7" flesh_color = "#5F7BB0" diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index a903433fda..bcd204e499 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -13,6 +13,7 @@ name_language = null // Use the first-name last-name generator rather than a language scrambler min_age = 17 max_age = 110 + health_hud_intensity = 1.5 spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR @@ -36,6 +37,7 @@ num_alternate_languages = 2 secondary_langs = list("Sinta'unathi") name_language = "Sinta'unathi" + health_hud_intensity = 2.5 min_age = 18 max_age = 60 @@ -96,6 +98,7 @@ num_alternate_languages = 2 secondary_langs = list("Siik'tajr") name_language = "Siik'tajr" + health_hud_intensity = 2.5 min_age = 17 max_age = 80 @@ -151,6 +154,7 @@ num_alternate_languages = 2 secondary_langs = list("Skrellian", "Schechi") name_language = "Skrellian" + health_hud_intensity = 2 min_age = 19 max_age = 80 @@ -193,6 +197,7 @@ show_ssd = "completely quiescent" num_alternate_languages = 1 name_language = "Rootspeak" + health_hud_intensity = 2.5 min_age = 1 max_age = 300 diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index d3b309fd84..d50d5009e7 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -68,6 +68,8 @@ var/stage = 0 var/cavity = 0 + // HUD element variable, see organ_icon.dm get_damage_hud_image() + var/image/hud_damage_image /obj/item/organ/external/Destroy() diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 035a0692c3..e68df75218 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -89,6 +89,9 @@ var/global/list/limb_icon_cache = list() if(owner && owner.gender == MALE) gender = "m" + icon_cache_key = "[icon_name]_[species ? species.name : "Human"]" + world << "ICON: Added species. icon_cache_key is now [icon_cache_key]." + if(force_icon) mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]") else @@ -134,22 +137,30 @@ var/global/list/limb_icon_cache = list() applying.SetIntensity(0.7) else if(status & ORGAN_DEAD) + icon_cache_key += "_dead" applying.ColorTone(rgb(10,50,0)) applying.SetIntensity(0.7) + world << "ICON: Added deadness. icon_cache_key is now [icon_cache_key]." if(!isnull(s_tone)) if(s_tone >= 0) applying.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) else applying.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + icon_cache_key += "_tone_[s_tone]" + world << "ICON: Added skin tone. icon_cache_key is now [icon_cache_key]." else if(s_col && s_col.len >= 3) applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) + icon_cache_key += "_color_[s_col[1]]_[s_col[2]]_[s_col[3]]" + world << "ICON: Added skin color. icon_cache_key is now [icon_cache_key]." // Translucency. if(nonsolid) applying += rgb(,,,180) // SO INTUITIVE TY BYOND return applying +/obj/item/organ/external/var/icon_cache_key + // new damage icon system // adjusted to set damage_state to brute/burn code only (without r_name0 as before) /obj/item/organ/external/update_icon() @@ -158,3 +169,49 @@ var/global/list/limb_icon_cache = list() damage_state = n_is return 1 return 0 + + +// Returns an image for use by the human health dolly HUD element. +// If the user has traumatic shock, it will be passed in as a minimum +// damage amount to represent the pain of the injuries involved. + +// Global scope, used in code below. +var/list/flesh_hud_colours = list("#02BA08","#9ECF19","#DEDE10","#FFAA00","#FF0000","#AA0000","#660000") +var/list/robot_hud_colours = list("#CFCFCF","#AFAFAF","#8F8F8F","#6F6F6F","#4F4F4F","#2F2F2F","#000000") + +/obj/item/organ/external/proc/get_damage_hud_image(var/min_dam_state) + world << "get_damage_hud_image([min_dam_state]) called." + + // Generate the greyscale base icon and cache it for later. + // icon_cache_key is set by any get_icon() calls that are made. + // This looks convoluted, but it's this way to avoid icon proc calls. + if(!hud_damage_image) + var/cache_key = "dambase-[icon_cache_key]" + if(!icon_cache_key || !limb_icon_cache[cache_key]) + limb_icon_cache[cache_key] = icon(get_icon(), null, SOUTH) + var/image/temp = image(limb_icon_cache[cache_key]) + if((robotic < ORGAN_ROBOT) && species) + // Calculate the required colour matrix. + var/r = 0.30 * species.health_hud_intensity + var/g = 0.59 * species.health_hud_intensity + var/b = 0.11 * species.health_hud_intensity + temp.color = list(r, r, r, g, g, g, b, b, b) + else if(model) + var/datum/robolimb/R = all_robolimbs[model] + if(istype(R)) + var/r = 0.30 * R.health_hud_intensity + var/g = 0.59 * R.health_hud_intensity + var/b = 0.11 * R.health_hud_intensity + temp.color = list(r, r, r, g, g, g, b, b, b) + hud_damage_image = image(null) + hud_damage_image.overlays += temp + + // Calculate the required color index. + var/dam_state = min(1,((brute_dam+burn_dam)/max_damage)) + // Apply traumatic shock min damage state. + if(!isnull(min_dam_state) && dam_state < min_dam_state) + dam_state = min_dam_state + // Apply colour and return product. + var/list/hud_colours = (robotic < ORGAN_ROBOT) ? flesh_hud_colours : robot_hud_colours + hud_damage_image.color = hud_colours[max(1,min(ceil(dam_state*hud_colours.len),hud_colours.len))] + return hud_damage_image diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index e1dac6efe9..b0f16372ee 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -42,6 +42,7 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ var/list/species_cannot_use = list("Teshari") var/list/monitor_styles //If empty, the model of limbs offers a head compatible with monitors. var/parts = BP_ALL //Defines what parts said brand can replace on a body. + var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator. /datum/robolimb/nanotrasen company = "NanoTrasen" diff --git a/icons/mob/screen1_health.dmi b/icons/mob/screen1_health.dmi new file mode 100644 index 0000000000..6905268a13 Binary files /dev/null and b/icons/mob/screen1_health.dmi differ