Refactors health doll, replaces "wounded" screen alert (#87011)

## About The Pull Request

The screen alert for being wounded is deleted

Instead, your health doll will now glow red on any (and all) wounded
limbs


https://github.com/user-attachments/assets/83565684-3e19-4753-8034-d8de6574e2b8

To accomplish this, the doll was refactored a bit. No longer operates
off of overlays, now uses vis contents across every limb, and just
updates the icon state of all those vis contents

## Why It's Good For The Game

Wounds really spam the hell out of you with screen alerts and it often
blocks you from seeing more relevant alerts that you care about

The mere presence of a minor dislocation on your leg prevents you from
noticing that you are no longer breathing. This is a bit troublesome

This can be resolved in other ways, of course - adding a priority value
to alerts? - but instead, I think we can just make better use of our
existing hud elements

I find this decently intuitive, at a glance. 
- The old screen alert gave you a tooltip saying you could click the
alert to examine yourself.
- Clicking on the health doll examines yourself the exact same way.
- So, players may see their doll glowing red, and click on it to self
examine, to see the report of them having a wound on their leg or chest
or whatever.

## Changelog

🆑 Melbert
del: Having any wounds no longer gives you an alert in the top right
qol: Having any wounds now make the corresponding bodypart on your
health doll (the lil dude on the right side of the screen) glow red.
refactor: Refactored how the hud's health doll shows up for humans.
Report any oddities
/🆑
This commit is contained in:
MrMelbert
2024-10-06 10:02:03 -05:00
committed by Majkl-J
parent 6428dcf307
commit aec6324344
11 changed files with 101 additions and 66 deletions

View File

@@ -19,7 +19,6 @@
#define ALERT_BUCKLED "buckled"
#define ALERT_HANDCUFFED "handcuffed"
#define ALERT_LEGCUFFED "legcuffed"
#define ALERT_WOUNDED "wound"
#define ALERT_IRRADIATED "irradiated"
#define ALERT_EMBEDDED_OBJECT "embeddedobject"
#define ALERT_SHOES_KNOT "shoealert"

View File

@@ -42,8 +42,8 @@
/// Called from update_health_hud, whenever a bodypart is being updated on the health doll
#define COMSIG_BODYPART_UPDATING_HEALTH_HUD "bodypart_updating_health_hud"
/// Return to override that bodypart's health hud with your own icon
#define COMPONENT_OVERRIDE_BODYPART_HEALTH_HUD (1<<0)
/// Return to override that bodypart's health hud with whatever is returned by the list
#define OVERRIDE_BODYPART_HEALTH_HUD (1<<0)
/// Called from /obj/item/bodypart/check_for_injuries (mob/living/carbon/examiner, list/check_list)
#define COMSIG_BODYPART_CHECKED_FOR_INJURY "bodypart_injury_checked"

View File

@@ -118,7 +118,7 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
var/atom/movable/screen/healths
var/atom/movable/screen/stamina
var/atom/movable/screen/healthdoll
var/atom/movable/screen/healthdoll/healthdoll
var/atom/movable/screen/spacesuit
var/atom/movable/screen/hunger
// subtypes can override this to force a specific UI style

View File

@@ -276,7 +276,7 @@
hunger = new /atom/movable/screen/hunger(null, src)
infodisplay += hunger
healthdoll = new /atom/movable/screen/healthdoll(null, src)
healthdoll = new /atom/movable/screen/healthdoll/human(null, src)
infodisplay += healthdoll
stamina = new /atom/movable/screen/stamina(null, src)

View File

@@ -724,6 +724,88 @@
screen_loc = ui_living_healthdoll
var/filtered = FALSE //so we don't repeatedly create the mask of the mob every update
/atom/movable/screen/healthdoll/human
/// Tracks components of our doll, each limb is a separate atom in our vis_contents
VAR_PRIVATE/list/atom/movable/screen/limbs
/// Lazylist, tracks all body zones that are wounded currently
/// Used so we can sync animations should the list be updated
VAR_PRIVATE/list/animated_zones
/atom/movable/screen/healthdoll/human/Initialize(mapload, datum/hud/hud_owner)
. = ..()
limbs = list()
for(var/i in GLOB.all_body_zones)
var/atom/movable/screen/healthdoll_limb/limb = new(src, null)
// layer chest above other limbs, it's the center after all
limb.layer = i == BODY_ZONE_CHEST ? layer + 0.05 : layer
limbs[i] = limb
// why viscontents? why not overlays? - because i want to animate filters
vis_contents += limb
update_appearance()
/atom/movable/screen/healthdoll/human/Destroy()
QDEL_LIST_ASSOC_VAL(limbs)
vis_contents.Cut()
return ..()
/atom/movable/screen/healthdoll/human/update_icon_state()
. = ..()
var/mob/living/carbon/human/owner = hud?.mymob
if(isnull(owner))
return
if(owner.stat == DEAD)
for(var/limb in limbs)
limbs[limb].icon_state = "[limb]DEAD"
return
var/list/current_animated = LAZYLISTDUPLICATE(animated_zones)
for(var/obj/item/bodypart/body_part as anything in owner.bodyparts)
var/icon_key = 0
var/part_zone = body_part.body_zone
var/list/overridable_key = list(icon_key)
if(body_part.bodypart_disabled)
icon_key = 7
else if(owner.stat == DEAD)
icon_key = "DEAD"
else if(SEND_SIGNAL(body_part, COMSIG_BODYPART_UPDATING_HEALTH_HUD, owner, overridable_key) & OVERRIDE_BODYPART_HEALTH_HUD)
icon_key = overridable_key[1] // thanks i hate it
else if(!owner.has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy))
var/damage = body_part.get_damage() / body_part.max_damage
// calculate what icon state (1-5, or 0 if undamaged) to use based on damage
icon_key = clamp(ceil(damage * 5), 0, 5)
if(length(body_part.wounds))
LAZYSET(animated_zones, part_zone, TRUE)
else
LAZYREMOVE(animated_zones, part_zone)
limbs[part_zone].icon_state = "[part_zone][icon_key]"
// handle leftovers
for(var/missing_zone in owner.get_missing_limbs())
limbs[missing_zone].icon_state = "[missing_zone]6"
LAZYREMOVE(animated_zones, missing_zone)
// time to re-sync animations, something changed
if(animated_zones ~! current_animated)
for(var/animated_zone in animated_zones)
var/atom/wounded_zone = limbs[animated_zone]
var/existing_filter = wounded_zone.get_filter("wound_outline")
if(existing_filter)
animate(existing_filter) // stop animation so we can resync
else
wounded_zone.add_filter("wound_outline", 1, list("type" = "outline", "color" = "#FF0033", "alpha" = 0, "size" = 1.2))
existing_filter = wounded_zone.get_filter("wound_outline")
animate(existing_filter, alpha = 200, time = 1.5 SECONDS, loop = -1)
animate(alpha = 0, time = 1.5 SECONDS)
if(LAZYLEN(current_animated)) // avoid null - list() runtimes please
for(var/lost_zone in current_animated - animated_zones)
limbs[lost_zone].remove_filter("wound_outline")
// Basically just holds an icon we can put a filter on
/atom/movable/screen/healthdoll_limb
screen_loc = ui_living_healthdoll
vis_flags = VIS_INHERIT_ID | VIS_INHERIT_PLANE
/atom/movable/screen/mood
name = "mood"
icon_state = "mood5"
@@ -904,7 +986,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/splash)
animate(get_filter("hunger_outline"), alpha = 200, time = 1.5 SECONDS, loop = -1)
animate(alpha = 0, time = 1.5 SECONDS)
else if(get_filter("hunger_outline"))
else
remove_filter("hunger_outline")
// Update color of the food

View File

@@ -408,10 +408,15 @@
var/list/names = islist(name_or_names) ? name_or_names : list(name_or_names)
. = FALSE
for(var/name in names)
if(filter_data[name])
filter_data -= name
update_filters()
. = TRUE
if(.)
update_filters()
return .
/datum/proc/clear_filters()
ASSERT(isatom(src) || isimage(src))

View File

@@ -124,19 +124,6 @@
//////// WOUNDS /////////
/////////////////////////
// wound alert
/atom/movable/screen/alert/status_effect/wound
name = "Wounded"
desc = "Your body has sustained serious damage, click here to inspect yourself."
/atom/movable/screen/alert/status_effect/wound/Click()
. = ..()
if(!.)
return
var/mob/living/carbon/carbon_owner = owner
carbon_owner.check_self_for_injuries()
// wound status effect base
/datum/status_effect/wound
id = "wound"

View File

@@ -203,8 +203,7 @@
if(status_effect_type)
victim.apply_status_effect(status_effect_type, src)
SEND_SIGNAL(victim, COMSIG_CARBON_GAIN_WOUND, src, limb)
if(!victim.alerts[ALERT_WOUNDED]) // only one alert is shared between all of the wounds
victim.throw_alert(ALERT_WOUNDED, /atom/movable/screen/alert/status_effect/wound)
victim.update_health_hud()
var/demoted
if(old_wound)
@@ -348,13 +347,13 @@
if (ismob(old_victim))
var/mob/mob_victim = old_victim
SEND_SIGNAL(mob_victim, COMSIG_CARBON_POST_LOSE_WOUND, src, old_limb, ignore_limb, replaced)
if(!replaced && !limb)
mob_victim.update_health_hud()
/datum/wound/proc/remove_wound_from_victim()
if(!victim)
return
LAZYREMOVE(victim.all_wounds, src)
if(!victim.all_wounds)
victim.clear_alert(ALERT_WOUNDED)
SEND_SIGNAL(victim, COMSIG_CARBON_LOSE_WOUND, src, limb)
/**

View File

@@ -66,12 +66,11 @@
bodyparts -= source
/// Whenever a bodypart we're tracking has their health hud updated, override it with our fake overlay
/datum/hallucination/fake_health_doll/proc/on_bodypart_hud_update(obj/item/bodypart/source, mob/living/carbon/human/owner)
/datum/hallucination/fake_health_doll/proc/on_bodypart_hud_update(obj/item/bodypart/source, mob/living/carbon/human/owner, list/overridable_key)
SIGNAL_HANDLER
var/mutable_appearance/fake_overlay = mutable_appearance('icons/hud/screen_gen.dmi', "[source.body_zone][bodyparts[source]]")
owner.hud_used.healthdoll.add_overlay(fake_overlay)
return COMPONENT_OVERRIDE_BODYPART_HEALTH_HUD
overridable_key[1] = bodyparts[source]
return OVERRIDE_BODYPART_HEALTH_HUD
/// Signal proc for [COMSIG_BODYPART_CHECKED_FOR_INJURY]. Our bodyparts look a lot more wounded than they actually are.
/datum/hallucination/fake_health_doll/proc/on_bodypart_checked(obj/item/bodypart/source, mob/living/carbon/examiner, list/check_list, list/limb_damage)

View File

@@ -746,46 +746,10 @@
/mob/living/carbon/human/update_health_hud()
if(!client || !hud_used)
return
// Updates the health bar, also sends signal
. = ..()
// Updates the health doll
if(!hud_used.healthdoll)
return
hud_used.healthdoll.cut_overlays()
if(stat == DEAD)
hud_used.healthdoll.icon_state = "healthdoll_DEAD"
return
hud_used.healthdoll.icon_state = "healthdoll_OVERLAY"
for(var/obj/item/bodypart/body_part as anything in bodyparts)
var/icon_num = 0
if(SEND_SIGNAL(body_part, COMSIG_BODYPART_UPDATING_HEALTH_HUD, src) & COMPONENT_OVERRIDE_BODYPART_HEALTH_HUD)
continue
var/damage = body_part.burn_dam + body_part.brute_dam
var/comparison = (body_part.max_damage/5)
if(damage)
icon_num = 1
if(damage > (comparison))
icon_num = 2
if(damage > (comparison*2))
icon_num = 3
if(damage > (comparison*3))
icon_num = 4
if(damage > (comparison*4))
icon_num = 5
if(has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy))
icon_num = 0
if(icon_num)
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[body_part.body_zone][icon_num]"))
for(var/t in get_missing_limbs()) //Missing limbs
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[t]6"))
for(var/t in get_disabled_limbs()) //Disabled limbs
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[t]7"))
// Handles changing limb colors and stuff
hud_used.healthdoll?.update_appearance()
/mob/living/carbon/human/fully_heal(heal_flags = HEAL_ALL)
if(heal_flags & HEAL_NEGATIVE_MUTATIONS)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB