Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bunch of examine + health analyzer updates + Allows you to examine / point at items worn by others #610

Merged
merged 17 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion code/__DEFINES/alerts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions code/__DEFINES/chat.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@
#define debug_world_log(msg) if (GLOB.Debug2) log_world("DEBUG: [msg]")
/// Adds a generic box around whatever message you're sending in chat. Really makes things stand out.
#define examine_block(str) ("<div class='examine_block'>" + str + "</div>")
/// Makes a horizontal line with text in the middle
#define separator_hr(str) ("<div class='separator'>" + str + "</div>")
/// Helper which creates a chat message which may have a tooltip in some contexts, but not others.
#define conditional_tooltip(normal_text, tooltip_text, condition) ((condition) ? (span_tooltip(tooltip_text, normal_text)) : (normal_text))
4 changes: 2 additions & 2 deletions code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions code/__DEFINES/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -978,3 +978,7 @@ GLOBAL_LIST_INIT(layers_to_offset, list(

/// Types of bullets that mining mobs take full damage from
#define MINING_MOB_PROJECTILE_VULNERABILITY list(BRUTE)

/// Distance which you can see someone's ID card
/// Short enough that you can inspect over tables (bartender checking age)
#define ID_EXAMINE_DISTANCE 3
5 changes: 4 additions & 1 deletion code/__DEFINES/span.dm
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,21 @@
#define span_secradio(str) ("<span class='secradio'>" + str + "</span>")
#define span_servradio(str) ("<span class='servradio'>" + str + "</span>")
#define span_singing(str) ("<span class='singing'>" + str + "</span>")
#define span_slightly_larger(str) ("<span class='slightly_larger'>" + str + "</span>")
#define span_slime(str) ("<span class='slime'>" + str + "</span>")
#define span_small(str) ("<span class='small'>" + str + "</span>")
#define span_smalldanger(str) ("<span class='smalldanger'>" + str + "</span>")
#define span_smallnotice(str) ("<span class='smallnotice'>" + str + "</span>")
#define span_smallnoticeital(str) ("<span class='smallnoticeital'>" + str + "</span>")
#define span_spiderbreacher(str) ("<span class='spiderbreacher'>" + str + "</span>")
#define span_spiderbroodmother(str) ("<span class='spiderbroodmother'>" + str + "</span>")
#define span_spiderscout(str) ("<span class='spiderscout'>" + str + "</span>")
#define span_spiderbreacher(str) ("<span class='spiderbreacher'>" + str + "</span>")
#define span_subheader_announcement_text(str) ("<span class='subheader_announcement_text'>" + str + "</span>")
#define span_suicide(str) ("<span class='suicide'>" + str + "</span>")
#define span_suppradio(str) ("<span class='suppradio'>" + str + "</span>")
#define span_syndradio(str) ("<span class='syndradio'>" + str + "</span>")
#define span_tape_recorder(str) ("<span class='tape_recorder'>" + str + "</span>")
#define span_tinydanger(str) ("<span class='tinydanger'>" + str + "</span>")
#define span_tinynotice(str) ("<span class='tinynotice'>" + str + "</span>")
#define span_tinynoticeital(str) ("<span class='tinynoticeital'>" + str + "</span>")
#define span_unconscious(str) ("<span class='unconscious'>" + str + "</span>")
Expand Down
6 changes: 5 additions & 1 deletion code/__DEFINES/surgery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@
#define ORGAN_HIDDEN (1<<9)
/// Has the organ already been inserted inside someone
#define ORGAN_VIRGIN (1<<10)
/// ALWAYS show this when scanned by advanced scanners, even if it is totally healthy
#define ORGAN_PROMINENT (1<<11)
/// An organ that is ostensibly dangerous when inside a body
#define ORGAN_HAZARDOUS (1<<12)

#define ORGAN_IRRADIATED (1<<11)
#define ORGAN_IRRADIATED (1<<13)

/// Helper to figure out if a limb is organic
#define IS_ORGANIC_LIMB(limb) (limb.bodytype & BODYTYPE_ORGANIC)
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/hud/hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ GLOBAL_LIST_INIT(available_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
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/hud/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,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)
Expand Down
84 changes: 83 additions & 1 deletion code/_onclick/hud/screen_objects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,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 BODY_ZONES_ALL)
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"
Expand Down Expand Up @@ -846,7 +928,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
Expand Down
7 changes: 6 additions & 1 deletion code/datums/datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,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))
Expand Down
4 changes: 2 additions & 2 deletions code/datums/elements/ai_held_item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
SIGNAL_HANDLER

var/obj/item/carried_item = get_held_item(source)
if (!carried_item)
if (!carried_item || (carried_item.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM)))
return
examine_text += span_notice("[source.p_They()] [source.p_are()] carrying [carried_item.get_examine_string(user)].")
examine_text += span_notice("[source.p_They()] [source.p_are()] carrying [carried_item.examine_title(user)].")

/// If we died, drop anything we were carrying
/datum/element/ai_held_item/proc/on_death(mob/living/ol_yeller)
Expand Down
2 changes: 1 addition & 1 deletion code/datums/elements/dextrous.dm
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@
for(var/obj/item/held_item in examined.held_items)
if(held_item.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM))
continue
examine_list += span_info("[examined.p_They()] [examined.p_have()] [held_item.get_examine_string(user)] in [examined.p_their()] \
examine_list += span_info("[examined.p_They()] [examined.p_have()] [held_item.examine_title(user)] in [examined.p_their()] \
[examined.get_held_index_name(examined.get_held_index_of_item(held_item))].")
9 changes: 9 additions & 0 deletions code/datums/status_effects/debuffs/fire_stacks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@
/// Type of mob light emitter we use when on fire
var/moblight_type = /obj/effect/dummy/lighting_obj/moblight/fire

/datum/status_effect/fire_handler/fire_stacks/get_examine_text()
if(owner.on_fire)
return

return "[owner.p_They()] [owner.p_are()] covered in something flammable."

/datum/status_effect/fire_handler/fire_stacks/tick(seconds_between_ticks)
if(stacks <= 0)
qdel(src)
Expand Down Expand Up @@ -254,6 +260,9 @@
enemy_types = list(/datum/status_effect/fire_handler/fire_stacks)
stack_modifier = -1

/datum/status_effect/fire_handler/wet_stacks/get_examine_text()
return "[owner.p_They()] look[owner.p_s()] a little soaked."

/datum/status_effect/fire_handler/wet_stacks/tick(seconds_between_ticks)
adjust_stacks(-0.5 * seconds_between_ticks)
if(stacks <= 0)
Expand Down
13 changes: 9 additions & 4 deletions code/datums/status_effects/debuffs/genetic_damage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,20 @@
qdel(src)
return

/datum/status_effect/genetic_damage/proc/on_healthscan(datum/source, list/render_list, advanced)
/datum/status_effect/genetic_damage/proc/on_healthscan(datum/source, list/render_list, advanced, mob/user, mode, tochat)
SIGNAL_HANDLER

var/message = ""
if(advanced)
render_list += "<span class='alert ml-1'>Genetic damage: [round(total_damage / minimum_before_tox_damage * 100, 0.1)]%</span>\n"
message = "Genetic damage: [round(total_damage / minimum_before_tox_damage * 100, 0.1)]%"
else if(total_damage >= minimum_before_tox_damage)
render_list += "<span class='alert ml-1'>Severe genetic damage detected.</span>\n"
message = "Severe genetic damage detected."
else
render_list += "<span class='alert ml-1'>Minor genetic damage detected.</span>\n"
message = "Minor genetic damage detected."

if(message)
render_list += conditional_tooltip("<span class='alert ml-1'>[message]</span>", "Irreparable under normal circumstances - will decay over time.", tochat)
render_list += "<br>"

#undef GORILLA_MUTATION_CHANCE_PER_SECOND
#undef GORILLA_MUTATION_MINIMUM_DAMAGE
9 changes: 6 additions & 3 deletions code/datums/status_effects/debuffs/hallucination.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
))

/// Signal proc for [COMSIG_LIVING_HEALTHSCAN]. Show we're hallucinating to (advanced) scanners.
/datum/status_effect/hallucination/proc/on_health_scan(datum/source, list/render_list, advanced, mob/user, mode)
/datum/status_effect/hallucination/proc/on_health_scan(datum/source, list/render_list, advanced, mob/user, mode, tochat)
SIGNAL_HANDLER

if(!advanced)
return

render_list += "<span class='info ml-1'>Subject is hallucinating.</span>\n"
render_list += conditional_tooltip("<span class='info ml-1'>Subject is hallucinating.</span>", "Supply antipsychotic medication, such as [/datum/reagent/medicine/haloperidol::name] or [/datum/reagent/medicine/synaptizine::name].", tochat)
render_list += "<br>"

/// Signal proc for [COMSIG_CARBON_CHECKING_BODYPART],
/// checking bodyparts while hallucinating can cause them to appear more damaged than they are
Expand Down Expand Up @@ -84,6 +84,9 @@
status_type = STATUS_EFFECT_REFRESH
duration = -1 // This lasts "forever", only goes away with sanity gain

/datum/status_effect/hallucination/sanity/on_health_scan(datum/source, list/render_list, advanced, mob/user, mode, tochat)
return

/datum/status_effect/hallucination/sanity/on_apply()
if(!owner.mob_mood)
return FALSE
Expand Down
13 changes: 0 additions & 13 deletions code/datums/status_effects/wound_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,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"
Expand Down
Loading
Loading