diff --git a/code/__DEFINES/alerts.dm b/code/__DEFINES/alerts.dm index e6f4feb259a..17db402c6c0 100644 --- a/code/__DEFINES/alerts.dm +++ b/code/__DEFINES/alerts.dm @@ -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" 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 b95ffba607f..80c6f89a108 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -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" diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index fabf2cf8f74..142455b1dcd 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -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 diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index cf3153bf8f0..6315bad8506 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -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) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index df330c0070b..472fe0a9b50 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -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 diff --git a/code/datums/datum.dm b/code/datums/datum.dm index d170aeca852..d4abc7c69ad 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -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)) diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index fc3f3140593..30361dc9cf1 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -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" diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 5e5258c86de..fdecc89680a 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -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) /** diff --git a/code/modules/hallucination/screwy_health_doll.dm b/code/modules/hallucination/screwy_health_doll.dm index 7bab267563c..2a8eeba16e2 100644 --- a/code/modules/hallucination/screwy_health_doll.dm +++ b/code/modules/hallucination/screwy_health_doll.dm @@ -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) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index be81700a896..fd8f5fdf40b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -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) diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi index 86383abbef1..5b1c24d7789 100644 Binary files a/icons/hud/screen_gen.dmi and b/icons/hud/screen_gen.dmi differ