Reworks examine (a little) (#86506)

## About The Pull Request

Basically, reworks how examining things looks to the user.

#86497 is required even though this pretty much replaces the entire PR.

Examining random objects and simplemobs:


![image](https://github.com/user-attachments/assets/a2634a7f-b337-483a-a4e7-699586b4d6ac)


![image](https://github.com/user-attachments/assets/84cfa824-4cb3-4bc1-831c-8db3ccd6b162)

Examining a person:


![image](https://github.com/user-attachments/assets/91dc5492-9ba6-44d1-a284-5c97190b12c6)


![image](https://github.com/user-attachments/assets/7af83bea-e364-4daf-9090-551d2ec2b1a1)

Examining an ID card a person is wearing (by clicking the hyperlink
adorning the ID card when examining them):
(Note, you can only pull up this if you are within 3 tiles of the
person)


![image](https://github.com/user-attachments/assets/d9658605-0830-4cd2-9b6a-3821f19555c6)

## Why It's Good For The Game

Examine is very old and very inconsistent between atoms and mobs. So I
thought I could spruce it up a bit while bringing some consistency
along.

This should also help with losing certain details in massive walls of
examine text - stuff like names will stick out more.

## Changelog

🆑 Melbert
qol: The way examine looks has been updated.
qol: A person's ID card no longer appears with a big icon on examine.
You can now click on their ID card (in the chat box) to get a bigger
picture of it, as well as information about them.
refactor: Much of examine backend code has been refactored, report any
odd looking text.
/🆑
This commit is contained in:
MrMelbert
2024-09-10 15:47:58 -05:00
committed by GitHub
parent 21da683ff7
commit 48bbd6fddf
29 changed files with 811 additions and 701 deletions
@@ -106,7 +106,7 @@
return FALSE
to_chat(src, span_bold(playstyle_string))
/mob/living/basic/construct/examine(mob/user)
/mob/living/basic/construct/get_examine_name(mob/user)
var/text_span
switch(theme)
if(THEME_CULT)
@@ -115,13 +115,20 @@
text_span = "purple"
if(THEME_HOLY)
text_span = "blue"
. = list("<span class='[text_span]'>This is [icon2html(src, user)] \a <b>[src]</b>!\n[desc]")
if(!text_span)
return ..()
return "<span class='[text_span]'>[..()]</span>"
/mob/living/basic/construct/examine(mob/user)
. = list()
if(health < maxHealth)
if(health >= maxHealth/2)
. += span_warning("[p_They()] look[p_s()] slightly dented.")
else
. += span_warning(span_bold("[p_They()] look[p_s()] severely dented!"))
. += "</span>"
return .
/mob/living/basic/construct/narsie_act()
@@ -276,21 +276,21 @@
return icon('icons/mob/butts.dmi', BUTT_SPRITE_DRONE)
/mob/living/basic/drone/examine(mob/user)
. = list("<span class='info'>This is [icon2html(src, user)] \a <b>[src]</b>!")
. = list()
//Hands
for(var/obj/item/held_thing in held_items)
if(held_thing.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM))
continue
. += "It has [held_thing.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(held_thing))]."
. += "It has [held_thing.examine_title(user)] in its [get_held_index_name(get_held_index_of_item(held_thing))]."
//Internal storage
if(internal_storage && !(internal_storage.item_flags & ABSTRACT))
. += "It is holding [internal_storage.get_examine_string(user)] in its internal storage."
. += "It is holding [internal_storage.examine_title(user)] in its internal storage."
//Cosmetic hat - provides no function other than looks
if(head && !(head.item_flags & ABSTRACT))
. += "It is wearing [head.get_examine_string(user)] on its head."
. += "It is wearing [head.examine_title(user)] on its head."
//Braindead
if(!client && stat != DEAD)
@@ -313,8 +313,6 @@
. += span_deadsay("A message repeatedly flashes on its display: \"REBOOT -- REQUIRED\".")
else
. += span_deadsay("A message repeatedly flashes on its display: \"ERROR -- OFFLINE\".")
. += "</span>"
/mob/living/basic/drone/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //Secbots won't hunt maintenance drones.
return -10
@@ -28,7 +28,7 @@
. = ..()
if(isnull(internal_storage) || (internal_storage.item_flags & ABSTRACT))
return
. += span_info("It is holding [internal_storage.get_examine_string(user)] in its internal storage.")
. += span_info("It is holding [internal_storage.examine_title(user)] in its internal storage.")
/mob/living/basic/guardian/dextrous/recall_effects()
. = ..()
+521 -125
View File
@@ -1,4 +1,19 @@
/// Adds a newline to the examine list if the above entry is not empty and it is not the first element in the list
#define ADD_NEWLINE_IF_NECESSARY(list) if(length(list) > 0 && list[length(list)]) { list += "" }
/mob/living/carbon/human/get_examine_name(mob/user)
if(!HAS_TRAIT(user, TRAIT_PROSOPAGNOSIA))
return ..()
return "Unknown"
/mob/living/carbon/human/get_examine_icon(mob/user)
return null
/mob/living/carbon/examine(mob/user)
if(HAS_TRAIT(src, TRAIT_UNKNOWN))
return list(span_warning("You're struggling to make out any details..."))
var/t_He = p_They()
var/t_His = p_Their()
var/t_his = p_their()
@@ -6,157 +21,538 @@
var/t_has = p_have()
var/t_is = p_are()
. = list("<span class='info'>This is [icon2html(src, user)] \a <EM>[src]</EM>!")
var/obscured = check_obscured_slots()
. = list()
. += get_clothing_examine_info(user)
// give us some space between clothing examine and the rest
ADD_NEWLINE_IF_NECESSARY(.)
if (handcuffed)
. += span_warning("[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!")
if (head)
. += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head. "
if(wear_mask && !(obscured & ITEM_SLOT_MASK))
. += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face."
if(wear_neck && !(obscured & ITEM_SLOT_NECK))
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck."
for(var/obj/item/held_thing in held_items)
if(held_thing.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM))
continue
. += "[t_He] [t_is] holding [held_thing.get_examine_string(user)] in [t_his] [get_held_index_name(get_held_index_of_item(held_thing))]."
if (back)
. += "[t_He] [t_has] [back.get_examine_string(user)] on [t_his] back."
var/appears_dead = FALSE
if (stat == DEAD)
var/just_sleeping = FALSE
if(!appears_alive())
appears_dead = TRUE
if(get_organ_by_type(/obj/item/organ/internal/brain))
. += span_deadsay("[t_He] [t_is] limp and unresponsive, with no signs of life.")
else if(get_bodypart(BODY_ZONE_HEAD))
. += span_deadsay("It appears that [t_his] brain is missing...")
var/list/msg = list("<span class='warning'>")
for(var/obj/item/bodypart/bodypart as anything in bodyparts)
for(var/obj/item/embedded_item as anything in bodypart.embedded_objects)
if(embedded_item.is_embed_harmless())
msg += "<B>[t_He] [t_has] [icon2html(embedded_item, user)] \a [embedded_item] stuck to [t_his] [bodypart.name]!</B>\n"
else
msg += "<B>[t_He] [t_has] [icon2html(embedded_item, user)] \a [embedded_item] embedded in [t_his] [bodypart.name]!</B>\n"
for(var/datum/wound/bodypart_wound as anything in bodypart.wounds)
msg += "[bodypart_wound.get_examine_description(user)]\n"
var/obj/item/clothing/glasses/shades = get_item_by_slot(ITEM_SLOT_EYES)
var/are_we_in_weekend_at_bernies = shades?.tint && buckled && istype(buckled, /obj/vehicle/ridden/wheelchair)
for(var/obj/item/bodypart/disabled_limb as anything in get_disabled_limbs())
if(isliving(user) && (HAS_MIND_TRAIT(user, TRAIT_NAIVE) || are_we_in_weekend_at_bernies))
just_sleeping = TRUE
if(!just_sleeping)
// since this is relatively important and giving it space makes it easier to read
ADD_NEWLINE_IF_NECESSARY(.)
if(HAS_TRAIT(src, TRAIT_SUICIDED))
. += span_warning("[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.")
. += generate_death_examine_text()
//Status effects
var/list/status_examines = get_status_effect_examinations()
if (length(status_examines))
. += status_examines
if(get_bodypart(BODY_ZONE_HEAD) && !get_organ_by_type(/obj/item/organ/internal/brain))
. += span_deadsay("It appears that [t_his] brain is missing...")
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/list/disabled = list()
for(var/obj/item/bodypart/body_part as anything in bodyparts)
if(body_part.bodypart_disabled)
disabled += body_part
missing -= body_part.body_zone
for(var/obj/item/embedded as anything in body_part.embedded_objects)
var/stuck_wordage = embedded.is_embed_harmless() ? "stuck to" : "embedded in"
. += span_boldwarning("[t_He] [t_has] [icon2html(embedded, user)] \a [embedded] [stuck_wordage] [t_his] [body_part.plaintext_zone]!")
for(var/datum/wound/iter_wound as anything in body_part.wounds)
. += span_danger(iter_wound.get_examine_description(user))
for(var/obj/item/bodypart/body_part as anything in disabled)
var/damage_text
damage_text = (disabled_limb.brute_dam >= disabled_limb.burn_dam) ? disabled_limb.heavy_brute_msg : disabled_limb.heavy_burn_msg
msg += "<B>[t_His] [disabled_limb.name] is [damage_text]!</B>\n"
if(HAS_TRAIT(body_part, TRAIT_DISABLED_BY_WOUND))
continue // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
if(body_part.get_damage() < body_part.max_damage) //we don't care if it's stamcritted
damage_text = "limp and lifeless"
else
damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg
. += span_boldwarning("[capitalize(t_his)] [body_part.plaintext_zone] is [damage_text]!")
for(var/obj/item/bodypart/missing_limb as anything in get_missing_limbs())
if(missing_limb == BODY_ZONE_HEAD)
msg += "[span_deadsay("<B>[t_His] [parse_zone(missing_limb)] is missing!</B>")]\n"
//stores missing limbs
var/l_limbs_missing = 0
var/r_limbs_missing = 0
for(var/gone in missing)
if(gone == BODY_ZONE_HEAD)
. += span_deadsay("<B>[t_His] [parse_zone(gone)] is missing!</B>")
continue
msg += "[span_warning("<B>[t_His] [parse_zone(missing_limb)] is missing!</B>")]\n"
if(gone == BODY_ZONE_L_ARM || gone == BODY_ZONE_L_LEG)
l_limbs_missing++
else if(gone == BODY_ZONE_R_ARM || gone == BODY_ZONE_R_LEG)
r_limbs_missing++
. += span_boldwarning("[capitalize(t_his)] [parse_zone(gone)] is missing!")
if(l_limbs_missing >= 2 && r_limbs_missing == 0)
. += span_tinydanger("[t_He] look[p_s()] all right now...")
else if(l_limbs_missing == 0 && r_limbs_missing >= 2)
. += span_tinydanger("[t_He] really keep[p_s()] to the left...")
else if(l_limbs_missing >= 2 && r_limbs_missing >= 2)
. += span_tinydanger("[t_He] [p_do()]n't seem all there...")
var/temp = getBruteLoss()
if(!(user == src && has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy))) //fake healthy
var/temp
if(user == src && has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_crit))//fake damage
temp = 50
else
temp = getBruteLoss()
var/list/damage_desc = get_majority_bodypart_damage_desc()
if(temp)
if (temp < 25)
msg += "[t_He] [t_has] minor bruising.\n"
else if (temp < 50)
msg += "[t_He] [t_has] <b>moderate</b> bruising!\n"
if(temp < 25)
. += span_danger("[t_He] [t_has] minor [damage_desc[BRUTE]].")
else if(temp < 50)
. += span_danger("[t_He] [t_has] <b>moderate</b> [damage_desc[BRUTE]]!")
else
msg += "<B>[t_He] [t_has] severe bruising!</B>\n"
. += span_bolddanger("[t_He] [t_has] severe [damage_desc[BRUTE]]!")
temp = getFireLoss()
if(temp)
if (temp < 25)
msg += "[t_He] [t_has] minor burns.\n"
if(temp < 25)
. += span_danger("[t_He] [t_has] minor [damage_desc[BURN]].")
else if (temp < 50)
msg += "[t_He] [t_has] <b>moderate</b> burns!\n"
. += span_danger("[t_He] [t_has] <b>moderate</b> [damage_desc[BURN]]!")
else
msg += "<B>[t_He] [t_has] severe burns!</B>\n"
if(HAS_TRAIT(src, TRAIT_DUMB))
msg += "[t_He] seem[p_s()] to be clumsy and unable to think.\n"
if(has_status_effect(/datum/status_effect/fire_handler/fire_stacks))
msg += "[t_He] [t_is] covered in something flammable.\n"
if(has_status_effect(/datum/status_effect/fire_handler/wet_stacks))
msg += "[t_He] look[p_s()] a little soaked.\n"
. += span_bolddanger("[t_He] [t_has] severe [damage_desc[BURN]]!")
if(pulledby?.grab_state)
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
. += span_warning("[t_He] [t_is] restrained by [pulledby]'s grip.")
if(nutrition < NUTRITION_LEVEL_STARVING - 50)
. += span_warning("[t_He] [t_is] severely malnourished.")
else if(nutrition >= NUTRITION_LEVEL_FAT)
if(user.nutrition < NUTRITION_LEVEL_STARVING - 50)
. += span_hypnophrase("[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.")
else
. += "<b>[t_He] [t_is] quite chubby.</b>"
switch(disgust)
if(DISGUST_LEVEL_GROSS to DISGUST_LEVEL_VERYGROSS)
. += "[t_He] look[p_s()] a bit grossed out."
if(DISGUST_LEVEL_VERYGROSS to DISGUST_LEVEL_DISGUSTED)
. += "[t_He] look[p_s()] really grossed out."
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
. += "[t_He] look[p_s()] extremely disgusted."
var/apparent_blood_volume = blood_volume
if(HAS_TRAIT(src, TRAIT_USES_SKINTONES) && ishuman(src))
var/mob/living/carbon/human/husrc = src // gross istypesrc but easier than refactoring even further for now
if(husrc.skin_tone == "albino")
apparent_blood_volume -= (BLOOD_VOLUME_NORMAL * 0.25) // knocks you down a few pegs
switch(apparent_blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
. += span_warning("[t_He] [t_has] pale skin.")
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
. += span_boldwarning("[t_He] look[p_s()] like pale death.")
if(-INFINITY to BLOOD_VOLUME_BAD)
. += span_deadsay("<b>[t_He] resemble[p_s()] a crushed, empty juice pouch.</b>")
if(is_bleeding())
var/list/obj/item/bodypart/bleeding_limbs = list()
var/list/obj/item/bodypart/grasped_limbs = list()
for(var/obj/item/bodypart/body_part as anything in bodyparts)
if(body_part.get_modified_bleed_rate())
bleeding_limbs += body_part.plaintext_zone
if(body_part.grasped_by)
grasped_limbs += body_part.plaintext_zone
if(LAZYLEN(bleeding_limbs))
var/bleed_text = "<b>"
if(appears_dead)
bleed_text += "<span class='deadsay'>"
bleed_text += "Blood is visible in [t_his] open"
else
bleed_text += "<span class='warning'>"
bleed_text += "[t_He] [t_is] bleeding from [t_his] "
bleed_text += english_list(bleeding_limbs, and_text = " and ")
if(appears_dead)
bleed_text += ", but it has pooled and is not flowing."
else
if(HAS_TRAIT(src, TRAIT_BLOODY_MESS))
bleed_text += " incredibly quickly"
bleed_text += "!"
if(appears_dead)
bleed_text += "<span class='deadsay'>"
else
bleed_text += "<span class='warning'>"
bleed_text += "</b>"
. += bleed_text
if(LAZYLEN(grasped_limbs))
for(var/grasped_part in grasped_limbs)
. += "[t_He] [t_is] holding [t_his] [grasped_part] to slow the bleeding!"
if(reagents.has_reagent(/datum/reagent/teslium, needs_metabolizing = TRUE))
. += span_smallnoticeital("[t_He] [t_is] emitting a gentle blue glow!") // this should be signalized
if(just_sleeping)
. += span_notice("[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.")
else if(!appears_dead)
var/mob/living/living_user = user
if(src != user)
if(HAS_TRAIT(user, TRAIT_EMPATH))
if (combat_mode)
. += "[t_He] seem[p_s()] to be on guard."
if (getOxyLoss() >= 10)
. += "[t_He] seem[p_s()] winded."
if (getToxLoss() >= 10)
. += "[t_He] seem[p_s()] sickly."
if(mob_mood.sanity <= SANITY_DISTURBED)
. += "[t_He] seem[p_s()] distressed."
living_user.add_mood_event("empath", /datum/mood_event/sad_empath, src)
if(is_blind())
. += "[t_He] appear[p_s()] to be staring off into space."
if (HAS_TRAIT(src, TRAIT_DEAF))
. += "[t_He] appear[p_s()] to not be responding to noises."
if (bodytemperature > dna.species.bodytemp_heat_damage_limit)
. += "[t_He] [t_is] flushed and wheezing."
if (bodytemperature < dna.species.bodytemp_cold_damage_limit)
. += "[t_He] [t_is] shivering."
if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.holy_role)
. += "[t_He] [t_has] a holy aura about [t_him]."
living_user.add_mood_event("religious_comfort", /datum/mood_event/religiously_comforted)
switch(stat)
if(UNCONSCIOUS, HARD_CRIT)
. += span_notice("[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.")
if(SOFT_CRIT)
. += span_notice("[t_He] [t_is] barely conscious.")
if(CONSCIOUS)
if(HAS_TRAIT(src, TRAIT_DUMB))
. += "[t_He] [t_has] a stupid expression on [t_his] face."
if(get_organ_by_type(/obj/item/organ/internal/brain) && isnull(ai_controller))
var/npc_message = ""
if(!key)
npc_message = "[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely."
else if(!client)
npc_message ="[t_He] [t_has] a blank, absent-minded stare and appears completely unresponsive to anything. [t_He] may snap out of it soon."
if(npc_message)
// give some space since this is usually near the end
ADD_NEWLINE_IF_NECESSARY(.)
. += span_deadsay(npc_message)
var/scar_severity = 0
for(var/i in all_scars)
var/datum/scar/S = i
if(S.is_visible(user))
scar_severity += S.severity
for(var/datum/scar/scar as anything in all_scars)
if(scar.is_visible(user))
scar_severity += scar.severity
switch(scar_severity)
if(1 to 4)
msg += "[span_tinynoticeital("[t_He] [t_has] visible scarring, you can look again to take a closer look...")]\n"
if(5 to 8)
msg += "[span_smallnoticeital("[t_He] [t_has] several bad scars, you can look again to take a closer look...")]\n"
if(9 to 11)
msg += "[span_notice("<i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i>")]\n"
if(12 to INFINITY)
msg += "[span_notice("<b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b>")]\n"
if(scar_severity >= 1)
// give some space since this is even more usually near the end
ADD_NEWLINE_IF_NECESSARY(.)
switch(scar_severity)
if(1 to 4)
. += span_tinynoticeital("[t_He] [t_has] visible scarring, you can look again to take a closer look...")
if(5 to 8)
. += span_smallnoticeital("[t_He] [t_has] several bad scars, you can look again to take a closer look...")
if(9 to 11)
. += span_notice("<i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i>")
if(12 to INFINITY)
. += span_notice("<b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b>")
msg += "</span>"
if(HAS_TRAIT(src, TRAIT_HUSK))
. += span_warning("This body has been reduced to a grotesque husk.")
if(HAS_MIND_TRAIT(user, TRAIT_MORBID))
if(HAS_TRAIT(src, TRAIT_DISSECTED))
. += span_notice("[user.p_They()] appear[user.p_s()] to have been dissected. Useless for examination... <b><i>for now.</i></b>")
if(HAS_TRAIT(src, TRAIT_SURGICALLY_ANALYZED))
. += span_notice("A skilled hand has mapped this one's internal intricacies. It will be far easier to perform future experimentations upon [user.p_them()]. <b><i>Exquisite.</i></b>")
if(HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FITNESS))
. += compare_fitness(user)
. += msg.Join("")
var/hud_info = get_hud_examine_info(user)
if(length(hud_info))
. += hud_info
if(!appears_dead)
switch(stat)
if(SOFT_CRIT)
. += "[t_His] breathing is shallow and labored."
if(UNCONSCIOUS, HARD_CRIT)
. += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep."
var/trait_exam = common_trait_examine()
if (!isnull(trait_exam))
. += trait_exam
if(mob_mood)
switch(mob_mood.shown_mood)
if(-INFINITY to MOOD_SAD4)
. += "[t_He] look[p_s()] depressed."
if(MOOD_SAD4 to MOOD_SAD3)
. += "[t_He] look[p_s()] very sad."
if(MOOD_SAD3 to MOOD_SAD2)
. += "[t_He] look[p_s()] a bit down."
if(MOOD_HAPPY2 to MOOD_HAPPY3)
. += "[t_He] look[p_s()] quite happy."
if(MOOD_HAPPY3 to MOOD_HAPPY4)
. += "[t_He] look[p_s()] very happy."
if(MOOD_HAPPY4 to INFINITY)
. += "[t_He] look[p_s()] ecstatic."
. += "</span>"
if(isobserver(user))
ADD_NEWLINE_IF_NECESSARY(.)
. += "<b>Quirks:</b> [get_quirk_string(FALSE, CAT_QUIRK_ALL)]"
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .)
/mob/living/carbon/examine_more(mob/user)
. = ..()
. += span_notice("<i>You examine [src] closer, and note the following...</i>")
if(dna) //not all carbons have it. eg - xenos
//On closer inspection, this man isnt a man at all!
var/list/covered_zones = get_covered_body_zones()
for(var/obj/item/bodypart/part as anything in bodyparts)
if(part.body_zone in covered_zones)
continue
if(part.limb_id != dna.species.examine_limb_id)
. += "[span_info("[p_They()] [p_have()] \an [part.name].")]"
var/list/visible_scars
for(var/i in all_scars)
var/datum/scar/S = i
if(S.is_visible(user))
LAZYADD(visible_scars, S)
for(var/i in visible_scars)
var/datum/scar/S = i
var/scar_text = S.get_examine_description(user)
if(scar_text)
. += "[scar_text]"
if(length(.))
.[1] = "<span class='info'>" + .[1]
.[length(.)] += "</span>"
return .
/**
* Shows any and all examine text related to any status effects the user has.
*/
/mob/living/proc/get_status_effect_examinations()
var/list/examine_list = list()
for(var/datum/status_effect/effect as anything in status_effects)
var/effect_text = effect.get_examine_text()
if(!effect_text)
continue
examine_list += effect_text
if(!length(examine_list))
return
return examine_list.Join("<br>")
/// Returns death message for mob examine text
/mob/living/carbon/proc/generate_death_examine_text()
var/mob/dead/observer/ghost = get_ghost(TRUE, TRUE)
var/t_He = p_They()
var/t_his = p_their()
var/t_is = p_are()
//This checks to see if the body is revivable
if(get_organ_by_type(/obj/item/organ/internal/brain) && (client || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE) || (ghost?.can_reenter_corpse && ghost?.client)))
return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life...")
else
return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life and [t_his] soul has departed...")
/// Returns a list of "damtype" => damage description based off of which bodypart description is most common
/mob/living/carbon/proc/get_majority_bodypart_damage_desc()
var/list/seen_damage = list() // This looks like: ({Damage type} = list({Damage description for that damage type} = {number of times it has appeared}, ...), ...)
var/list/most_seen_damage = list() // This looks like: ({Damage type} = {Frequency of the most common description}, ...)
var/list/final_descriptions = list() // This looks like: ({Damage type} = {Most common damage description for that type}, ...)
for(var/obj/item/bodypart/part as anything in bodyparts)
for(var/damage_type in part.damage_examines)
var/damage_desc = part.damage_examines[damage_type]
if(!seen_damage[damage_type])
seen_damage[damage_type] = list()
if(!seen_damage[damage_type][damage_desc])
seen_damage[damage_type][damage_desc] = 1
else
seen_damage[damage_type][damage_desc] += 1
if(seen_damage[damage_type][damage_desc] > most_seen_damage[damage_type])
most_seen_damage[damage_type] = seen_damage[damage_type][damage_desc]
final_descriptions[damage_type] = damage_desc
return final_descriptions
/// Coolects examine information about the mob's clothing and equipment
/mob/living/carbon/proc/get_clothing_examine_info(mob/living/user)
. = list()
var/obscured = check_obscured_slots()
var/t_He = p_They()
var/t_His = p_Their()
var/t_his = p_their()
var/t_has = p_have()
var/t_is = p_are()
//head
if(head && !(obscured & ITEM_SLOT_HEAD) && !(head.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [head.examine_title(user)] on [t_his] head."
//back
if(back && !(back.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [back.examine_title(user)] on [t_his] back."
//Hands
for(var/obj/item/held_thing in held_items)
if(held_thing.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM))
continue
. += "[t_He] [t_is] holding [held_thing.examine_title(user)] in [t_his] [get_held_index_name(get_held_index_of_item(held_thing))]."
//gloves
if(gloves && !(obscured & ITEM_SLOT_GLOVES) && !(gloves.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [gloves.examine_title(user)] on [t_his] hands."
else if(GET_ATOM_BLOOD_DNA_LENGTH(src))
if(num_hands)
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!")
//handcuffed?
if(handcuffed)
var/cables_or_cuffs = istype(handcuffed, /obj/item/restraints/handcuffs/cable) ? "restrained with cable" : "handcuffed"
. += span_warning("[t_He] [t_is] [icon2html(handcuffed, user)] [cables_or_cuffs]!")
//shoes
if(shoes && !(obscured & ITEM_SLOT_FEET) && !(shoes.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [shoes.examine_title(user)] on [t_his] feet."
//mask
if(wear_mask && !(obscured & ITEM_SLOT_MASK) && !(wear_mask.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [wear_mask.examine_title(user)] on [t_his] face."
if(wear_neck && !(obscured & ITEM_SLOT_NECK) && !(wear_neck.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_neck.examine_title(user)] around [t_his] neck."
//eyes
if(!(obscured & ITEM_SLOT_EYES) )
if(glasses && !(glasses.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [glasses.examine_title(user)] covering [t_his] eyes."
else if(HAS_TRAIT(src, TRAIT_UNNATURAL_RED_GLOWY_EYES))
. += span_warning("<B>[t_His] eyes are glowing with an unnatural red aura!</B>")
else if(HAS_TRAIT(src, TRAIT_BLOODSHOT_EYES))
. += span_warning("<B>[t_His] eyes are bloodshot!</B>")
//ears
if(ears && !(obscured & ITEM_SLOT_EARS) && !(ears.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [ears.examine_title(user)] on [t_his] ears."
// Yes there's a lot of copypasta here, we can improve this later when carbons are less dumb in general
/mob/living/carbon/human/get_clothing_examine_info(mob/living/user)
. = list()
var/obscured = check_obscured_slots()
var/t_He = p_They()
var/t_His = p_Their()
var/t_his = p_their()
var/t_has = p_have()
var/t_is = p_are()
//uniform
if(w_uniform && !(obscured & ITEM_SLOT_ICLOTHING) && !(w_uniform.item_flags & EXAMINE_SKIP))
//accessory
var/accessory_message = ""
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/undershirt = w_uniform
var/list/accessories = undershirt.list_accessories_with_icon(user)
if(length(accessories))
accessory_message = " with [english_list(accessories)] attached"
. += "[t_He] [t_is] wearing [w_uniform.examine_title(user)][accessory_message]."
//head
if(head && !(obscured & ITEM_SLOT_HEAD) && !(head.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [head.examine_title(user)] on [t_his] head."
//mask
if(wear_mask && !(obscured & ITEM_SLOT_MASK) && !(wear_mask.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [wear_mask.examine_title(user)] on [t_his] face."
//neck
if(wear_neck && !(obscured & ITEM_SLOT_NECK) && !(wear_neck.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_neck.examine_title(user)] around [t_his] neck."
//eyes
if(!(obscured & ITEM_SLOT_EYES) )
if(glasses && !(glasses.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [glasses.examine_title(user)] covering [t_his] eyes."
else if(HAS_TRAIT(src, TRAIT_UNNATURAL_RED_GLOWY_EYES))
. += span_warning("<B>[t_His] eyes are glowing with an unnatural red aura!</B>")
else if(HAS_TRAIT(src, TRAIT_BLOODSHOT_EYES))
. += span_warning("<B>[t_His] eyes are bloodshot!</B>")
//ears
if(ears && !(obscured & ITEM_SLOT_EARS) && !(ears.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [ears.examine_title(user)] on [t_his] ears."
//suit/armor
if(wear_suit && !(wear_suit.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_suit.examine_title(user)]."
//suit/armor storage
if(s_store && !(obscured & ITEM_SLOT_SUITSTORE) && !(s_store.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] carrying [s_store.examine_title(user)] on [t_his] [wear_suit.name]."
//back
if(back && !(back.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [back.examine_title(user)] on [t_his] back."
//ID
if(wear_id && !(wear_id.item_flags & EXAMINE_SKIP))
var/obj/item/card/id/id = wear_id.GetID()
if(id && get_dist(user, src) <= ID_EXAMINE_DISTANCE)
var/id_href = "<a href='?src=[REF(src)];see_id=1;id_ref=[REF(id)];id_name=[id.registered_name];examine_time=[world.time]'>[wear_id.examine_title(user)]</a>"
. += "[t_He] [t_is] wearing [id_href]."
else
. += "[t_He] [t_is] wearing [wear_id.examine_title(user)]."
//Hands
for(var/obj/item/held_thing in held_items)
if(held_thing.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM))
continue
. += "[t_He] [t_is] holding [held_thing.examine_title(user)] in [t_his] [get_held_index_name(get_held_index_of_item(held_thing))]."
//gloves
if(gloves && !(obscured & ITEM_SLOT_GLOVES) && !(gloves.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [gloves.examine_title(user)] on [t_his] hands."
else if(GET_ATOM_BLOOD_DNA_LENGTH(src) || blood_in_hands)
if(num_hands)
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!")
//handcuffed?
if(handcuffed)
var/cables_or_cuffs = istype(handcuffed, /obj/item/restraints/handcuffs/cable) ? "restrained with cable" : "handcuffed"
. += span_warning("[t_He] [t_is] [icon2html(handcuffed, user)] [cables_or_cuffs]!")
//belt
if(belt && !(belt.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [belt.examine_title(user)] about [t_his] waist."
//shoes
if(shoes && !(obscured & ITEM_SLOT_FEET) && !(shoes.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [shoes.examine_title(user)] on [t_his] feet."
/// Collects info displayed about any HUDs the user has when examining src
/mob/living/carbon/proc/get_hud_examine_info(mob/living/user)
return
/mob/living/carbon/human/get_hud_examine_info(mob/living/user)
var/perpname = get_face_name(get_id_name(""))
if(perpname && (HAS_TRAIT(user, TRAIT_SECURITY_HUD) || HAS_TRAIT(user, TRAIT_MEDICAL_HUD)) && (user.stat == CONSCIOUS || isobserver(user)) && user != src)
var/datum/record/crew/target_record = find_record(perpname)
if(target_record)
. += "Rank: [target_record.rank]"
. += "<a href='?src=[REF(src)];hud=1;photo_front=1;examine_time=[world.time]'>\[Front photo\]</a><a href='?src=[REF(src)];hud=1;photo_side=1;examine_time=[world.time]'>\[Side photo\]</a>"
if(HAS_TRAIT(user, TRAIT_MEDICAL_HUD) && HAS_TRAIT(user, TRAIT_SECURITY_HUD))
. += separator_hr("Medical & Security Analysis")
. += get_medhud_examine_info(user, target_record)
. += get_sechud_examine_info(user, target_record)
else if(HAS_TRAIT(user, TRAIT_MEDICAL_HUD))
. += separator_hr("Medical Analysis")
. += get_medhud_examine_info(user, target_record)
else if(HAS_TRAIT(user, TRAIT_SECURITY_HUD))
. += separator_hr("Security Analysis")
. += get_sechud_examine_info(user, target_record)
/// Collects information displayed about src when examined by a user with a medical HUD.
/mob/living/carbon/proc/get_medhud_examine_info(mob/living/user, datum/record/crew/target_record)
. = list()
var/list/cybers = list()
for(var/obj/item/organ/internal/cyberimp/cyberimp in organs)
if(IS_ROBOTIC_ORGAN(cyberimp) && !(cyberimp.organ_flags & ORGAN_HIDDEN))
cybers += cyberimp.examine_title(user)
if(length(cybers))
. += "<span class='notice ml-1'>Detected cybernetic modifications:</span>"
. += "<span class='notice ml-2'>[english_list(cybers, and_text = ", and")]</span>"
if(target_record)
. += "<a href='?src=[REF(src)];hud=m;physical_status=1;examine_time=[world.time]'>\[[target_record.physical_status]\]</a>"
. += "<a href='?src=[REF(src)];hud=m;mental_status=1;examine_time=[world.time]'>\[[target_record.mental_status]\]</a>"
else
. += "\[Record Missing\]"
. += "\[Record Missing\]"
. += "<a href='?src=[REF(src)];hud=m;evaluation=1;examine_time=[world.time]'>\[Medical evaluation\]</a>"
. += "<a href='?src=[REF(src)];hud=m;quirk=1;examine_time=[world.time]'>\[See quirks\]</a>"
/// Collects information displayed about src when examined by a user with a security HUD.
/mob/living/carbon/proc/get_sechud_examine_info(mob/living/user, datum/record/crew/target_record)
. = list()
var/wanted_status = WANTED_NONE
var/security_note = "None."
if(target_record)
wanted_status = target_record.wanted_status
if(target_record.security_note)
security_note = target_record.security_note
if(ishuman(user))
. += "Criminal status: <a href='?src=[REF(src)];hud=s;status=1;examine_time=[world.time]'>\[[wanted_status]\]</a>"
else
. += "Criminal status: [wanted_status]"
. += "Important Notes: [security_note]"
. += "Security record: <a href='?src=[REF(src)];hud=s;view=1;examine_time=[world.time]'>\[View\]</a>"
if(ishuman(user))
. += "<a href='?src=[REF(src)];hud=s;add_citation=1;examine_time=[world.time]'>\[Add citation\]</a>\
<a href='?src=[REF(src)];hud=s;add_crime=1;examine_time=[world.time]'>\[Add crime\]</a>\
<a href='?src=[REF(src)];hud=s;add_note=1;examine_time=[world.time]'>\[Add note\]</a>"
/mob/living/carbon/human/examine_more(mob/user)
. = ..()
if((wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE)))
return
if(HAS_TRAIT(src, TRAIT_UNKNOWN) || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN))
return
var/age_text
switch(age)
if(-INFINITY to 25)
age_text = "very young"
if(26 to 35)
age_text = "of adult age"
if(36 to 55)
age_text = "middle-aged"
if(56 to 75)
age_text = "rather old"
if(76 to 100)
age_text = "very old"
if(101 to INFINITY)
age_text = "withering away"
. += list(span_notice("[p_They()] appear[p_s()] to be [age_text]."))
#undef ADD_NEWLINE_IF_NECESSARY
@@ -1,450 +0,0 @@
/mob/living/carbon/human/examine(mob/user)
//this is very slightly better than it was because you can use it more places. still can't do \his[src] though.
var/t_He = p_They()
var/t_His = p_Their()
var/t_his = p_their()
var/t_him = p_them()
var/t_has = p_have()
var/t_is = p_are()
var/obscure_name
var/obscure_examine
if(isliving(user))
var/mob/living/L = user
if(HAS_TRAIT(L, TRAIT_PROSOPAGNOSIA) || HAS_TRAIT(L, TRAIT_INVISIBLE_MAN))
obscure_name = TRUE
if(HAS_TRAIT(src, TRAIT_UNKNOWN))
obscure_name = TRUE
obscure_examine = TRUE
. = list("<span class='info'>This is <EM>[!obscure_name ? name : "Unknown"]</EM>!")
if(obscure_examine)
return list("<span class='warning'>You're struggling to make out any details...")
var/obscured = check_obscured_slots()
//uniform
if(w_uniform && !(obscured & ITEM_SLOT_ICLOTHING) && !(w_uniform.item_flags & EXAMINE_SKIP))
//accessory
var/accessory_message = ""
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/undershirt = w_uniform
var/list/accessories = undershirt.list_accessories_with_icon(user)
if(length(accessories))
accessory_message = " with [english_list(accessories)] attached"
. += "[t_He] [t_is] wearing [w_uniform.get_examine_string(user)][accessory_message]."
//head
if(head && !(obscured & ITEM_SLOT_HEAD) && !(head.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head."
//suit/armor
if(wear_suit && !(wear_suit.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_suit.get_examine_string(user)]."
//suit/armor storage
if(s_store && !(obscured & ITEM_SLOT_SUITSTORE) && !(s_store.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] carrying [s_store.get_examine_string(user)] on [t_his] [wear_suit.name]."
//back
if(back && !(back.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [back.get_examine_string(user)] on [t_his] back."
//Hands
for(var/obj/item/held_thing in held_items)
if(held_thing.item_flags & (ABSTRACT|EXAMINE_SKIP|HAND_ITEM))
continue
. += "[t_He] [t_is] holding [held_thing.get_examine_string(user)] in [t_his] [get_held_index_name(get_held_index_of_item(held_thing))]."
//gloves
if(gloves && !(obscured & ITEM_SLOT_GLOVES) && !(gloves.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands."
else if(GET_ATOM_BLOOD_DNA_LENGTH(src))
if(num_hands)
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!")
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/restraints/handcuffs/cable))
. += span_warning("[t_He] [t_is] [icon2html(handcuffed, user)] restrained with cable!")
else
. += span_warning("[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!")
//belt
if(belt && !(belt.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [belt.get_examine_string(user)] about [t_his] waist."
//shoes
if(shoes && !(obscured & ITEM_SLOT_FEET) && !(shoes.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [shoes.get_examine_string(user)] on [t_his] feet."
//mask
if(wear_mask && !(obscured & ITEM_SLOT_MASK) && !(wear_mask.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [wear_mask.get_examine_string(user)] on [t_his] face."
if(wear_neck && !(obscured & ITEM_SLOT_NECK) && !(wear_neck.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck."
//eyes
if(!(obscured & ITEM_SLOT_EYES) )
if(glasses && !(glasses.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes."
else if(HAS_TRAIT(src, TRAIT_UNNATURAL_RED_GLOWY_EYES))
. += "<span class='warning'><B>[t_His] eyes are glowing with an unnatural red aura!</B></span>"
else if(HAS_TRAIT(src, TRAIT_BLOODSHOT_EYES))
. += "<span class='warning'><B>[t_His] eyes are bloodshot!</B></span>"
//ears
if(ears && !(obscured & ITEM_SLOT_EARS) && !(ears.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_has] [ears.get_examine_string(user)] on [t_his] ears."
//ID
if(wear_id && !(wear_id.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_id.get_examine_string(user)]."
. += wear_id.get_id_examine_strings(user)
//Status effects
var/list/status_examines = get_status_effect_examinations()
if (length(status_examines))
. += status_examines
var/appears_dead = FALSE
var/just_sleeping = FALSE
if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
appears_dead = TRUE
var/obj/item/clothing/glasses/G = get_item_by_slot(ITEM_SLOT_EYES)
var/are_we_in_weekend_at_bernies = G?.tint && buckled && istype(buckled, /obj/vehicle/ridden/wheelchair)
if(isliving(user) && (HAS_MIND_TRAIT(user, TRAIT_NAIVE) || are_we_in_weekend_at_bernies))
just_sleeping = TRUE
if(!just_sleeping)
if(HAS_TRAIT(src, TRAIT_SUICIDED))
. += span_warning("[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.")
. += generate_death_examine_text()
if(get_bodypart(BODY_ZONE_HEAD) && !get_organ_by_type(/obj/item/organ/internal/brain))
. += span_deadsay("It appears that [t_his] brain is missing...")
var/list/msg = list()
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/list/disabled = list()
for(var/X in bodyparts)
var/obj/item/bodypart/body_part = X
if(body_part.bodypart_disabled)
disabled += body_part
missing -= body_part.body_zone
for(var/obj/item/I in body_part.embedded_objects)
if(I.is_embed_harmless())
msg += "<B>[t_He] [t_has] [icon2html(I, user)] \a [I] stuck to [t_his] [body_part.name]!</B>\n"
else
msg += "<B>[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [body_part.name]!</B>\n"
for(var/i in body_part.wounds)
var/datum/wound/iter_wound = i
msg += "[iter_wound.get_examine_description(user)]\n"
for(var/X in disabled)
var/obj/item/bodypart/body_part = X
var/damage_text
if(HAS_TRAIT(body_part, TRAIT_DISABLED_BY_WOUND))
continue // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
if(!(body_part.get_damage() >= body_part.max_damage)) //we don't care if it's stamcritted
damage_text = "limp and lifeless"
else
damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg
msg += "<B>[capitalize(t_his)] [body_part.name] is [damage_text]!</B>\n"
//stores missing limbs
var/l_limbs_missing = 0
var/r_limbs_missing = 0
for(var/t in missing)
if(t == BODY_ZONE_HEAD)
msg += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B><span class='warning'>\n"
continue
if(t == BODY_ZONE_L_ARM || t == BODY_ZONE_L_LEG)
l_limbs_missing++
else if(t == BODY_ZONE_R_ARM || t == BODY_ZONE_R_LEG)
r_limbs_missing++
msg += "<B>[capitalize(t_his)] [parse_zone(t)] is missing!</B>\n"
if(l_limbs_missing >= 2 && r_limbs_missing == 0)
msg += "[t_He] look[p_s()] all right now.\n"
else if(l_limbs_missing == 0 && r_limbs_missing >= 2)
msg += "[t_He] really keep[p_s()] to the left.\n"
else if(l_limbs_missing >= 2 && r_limbs_missing >= 2)
msg += "[t_He] [p_do()]n't seem all there.\n"
if(!(user == src && has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy))) //fake healthy
var/temp
if(user == src && has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_crit))//fake damage
temp = 50
else
temp = getBruteLoss()
var/list/damage_desc = get_majority_bodypart_damage_desc()
if(temp)
if(temp < 25)
msg += "[t_He] [t_has] minor [damage_desc[BRUTE]].\n"
else if(temp < 50)
msg += "[t_He] [t_has] <b>moderate</b> [damage_desc[BRUTE]]!\n"
else
msg += "<B>[t_He] [t_has] severe [damage_desc[BRUTE]]!</B>\n"
temp = getFireLoss()
if(temp)
if(temp < 25)
msg += "[t_He] [t_has] minor [damage_desc[BURN]].\n"
else if (temp < 50)
msg += "[t_He] [t_has] <b>moderate</b> [damage_desc[BURN]]!\n"
else
msg += "<B>[t_He] [t_has] severe [damage_desc[BURN]]!</B>\n"
if(has_status_effect(/datum/status_effect/fire_handler/fire_stacks))
msg += "[t_He] [t_is] covered in something flammable.\n"
if(has_status_effect(/datum/status_effect/fire_handler/wet_stacks))
msg += "[t_He] look[p_s()] a little soaked.\n"
if(pulledby?.grab_state)
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
if(nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[t_He] [t_is] severely malnourished.\n"
else if(nutrition >= NUTRITION_LEVEL_FAT)
if(user.nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[t_He] [t_is] quite chubby.\n"
switch(disgust)
if(DISGUST_LEVEL_GROSS to DISGUST_LEVEL_VERYGROSS)
msg += "[t_He] look[p_s()] a bit grossed out.\n"
if(DISGUST_LEVEL_VERYGROSS to DISGUST_LEVEL_DISGUSTED)
msg += "[t_He] look[p_s()] really grossed out.\n"
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
msg += "[t_He] look[p_s()] extremely disgusted.\n"
var/apparent_blood_volume = blood_volume
if(HAS_TRAIT(src, TRAIT_USES_SKINTONES) && (skin_tone == "albino"))
apparent_blood_volume -= 150 // enough to knock you down one tier
switch(apparent_blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
msg += "<b>[t_He] look[p_s()] like pale death.</b>\n"
if(-INFINITY to BLOOD_VOLUME_BAD)
msg += "[span_deadsay("<b>[t_He] resemble[p_s()] a crushed, empty juice pouch.</b>")]\n"
if(is_bleeding())
var/list/obj/item/bodypart/bleeding_limbs = list()
var/list/obj/item/bodypart/grasped_limbs = list()
for(var/obj/item/bodypart/body_part as anything in bodyparts)
if(body_part.get_modified_bleed_rate())
bleeding_limbs += body_part
if(body_part.grasped_by)
grasped_limbs += body_part
var/num_bleeds = LAZYLEN(bleeding_limbs)
var/list/bleed_text
if(appears_dead)
bleed_text = list("<span class='deadsay'><B>Blood is visible in [t_his] open")
else
bleed_text = list("<B>[t_He] [t_is] bleeding from [t_his]")
switch(num_bleeds)
if(1 to 2)
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
if(3 to INFINITY)
for(var/i in 1 to (num_bleeds - 1))
var/obj/item/bodypart/body_part = bleeding_limbs[i]
bleed_text += " [body_part.name],"
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
if(appears_dead)
bleed_text += ", but it has pooled and is not flowing.</span></B>\n"
else
if(reagents.has_reagent(/datum/reagent/toxin/heparin, needs_metabolizing = TRUE))
bleed_text += " incredibly quickly"
bleed_text += "!</B>\n"
for(var/i in grasped_limbs)
var/obj/item/bodypart/grasped_part = i
bleed_text += "[t_He] [t_is] holding [t_his] [grasped_part.name] to slow the bleeding!\n"
msg += bleed_text.Join()
if(reagents.has_reagent(/datum/reagent/teslium, needs_metabolizing = TRUE))
msg += "[t_He] [t_is] emitting a gentle blue glow!\n"
if(just_sleeping)
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n"
if(!appears_dead)
var/mob/living/living_user = user
if(src != user)
if(HAS_TRAIT(user, TRAIT_EMPATH))
if (combat_mode)
msg += "[t_He] seem[p_s()] to be on guard.\n"
if (getOxyLoss() >= 10)
msg += "[t_He] seem[p_s()] winded.\n"
if (getToxLoss() >= 10)
msg += "[t_He] seem[p_s()] sickly.\n"
if(mob_mood.sanity <= SANITY_DISTURBED)
msg += "[t_He] seem[p_s()] distressed.\n"
living_user.add_mood_event("empath", /datum/mood_event/sad_empath, src)
if(is_blind())
msg += "[t_He] appear[p_s()] to be staring off into space.\n"
if (HAS_TRAIT(src, TRAIT_DEAF))
msg += "[t_He] appear[p_s()] to not be responding to noises.\n"
if (bodytemperature > dna.species.bodytemp_heat_damage_limit)
msg += "[t_He] [t_is] flushed and wheezing.\n"
if (bodytemperature < dna.species.bodytemp_cold_damage_limit)
msg += "[t_He] [t_is] shivering.\n"
msg += "</span>"
if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.holy_role)
msg += "[t_He] [t_has] a holy aura about [t_him].\n"
living_user.add_mood_event("religious_comfort", /datum/mood_event/religiously_comforted)
switch(stat)
if(UNCONSCIOUS, HARD_CRIT)
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n"
if(SOFT_CRIT)
msg += "[t_He] [t_is] barely conscious.\n"
if(CONSCIOUS)
if(HAS_TRAIT(src, TRAIT_DUMB))
msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
if(get_organ_by_type(/obj/item/organ/internal/brain) && isnull(ai_controller))
if(!key)
msg += "[span_deadsay("[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.")]\n"
else if(!client)
msg += "[span_deadsay("[t_He] [t_has] a blank, absent-minded stare and appears completely unresponsive to anything. [t_He] may snap out of it soon.")]\n"
var/scar_severity = 0
for(var/i in all_scars)
var/datum/scar/S = i
if(S.is_visible(user))
scar_severity += S.severity
switch(scar_severity)
if(1 to 4)
msg += "[span_tinynoticeital("[t_He] [t_has] visible scarring, you can look again to take a closer look...")]\n"
if(5 to 8)
msg += "[span_smallnoticeital("[t_He] [t_has] several bad scars, you can look again to take a closer look...")]\n"
if(9 to 11)
msg += "[span_notice("<i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i>")]\n"
if(12 to INFINITY)
msg += "[span_notice("<b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b>")]\n"
msg += "</span>" // closes info class
if (length(msg))
. += span_warning("[msg.Join("")]")
var/trait_exam = common_trait_examine()
if (!isnull(trait_exam))
. += trait_exam
if(isliving(user))
var/mob/living/privacy_invader = user
if(HAS_MIND_TRAIT(privacy_invader, TRAIT_MORBID))
if(HAS_TRAIT(src, TRAIT_DISSECTED))
msg += "[span_notice("[t_He] appears to have been dissected. Useless for examination... <b><i>for now.</i></b>")]\n"
if(HAS_TRAIT(src, TRAIT_SURGICALLY_ANALYZED))
msg += "[span_notice("A skilled hand has mapped this one's internal intricacies. It will be far easier to perform future experimentations upon [t_him]. <b><i>Exquisite.</i></b>")]\n"
if(HAS_MIND_TRAIT(privacy_invader, TRAIT_EXAMINE_FITNESS))
. += compare_fitness(user)
var/perpname = get_face_name(get_id_name(""))
if(perpname && (HAS_TRAIT(user, TRAIT_SECURITY_HUD) || HAS_TRAIT(user, TRAIT_MEDICAL_HUD)))
var/datum/record/crew/target_record = find_record(perpname)
if(target_record)
. += "Rank: [target_record.rank]\n<a href='?src=[REF(src)];hud=1;photo_front=1;examine_time=[world.time]'>\[Front photo\]</a><a href='?src=[REF(src)];hud=1;photo_side=1;examine_time=[world.time]'>\[Side photo\]</a>"
if(HAS_TRAIT(user, TRAIT_MEDICAL_HUD))
var/cyberimp_detect
for(var/obj/item/organ/internal/cyberimp/cyberimp in organs)
if(IS_ROBOTIC_ORGAN(cyberimp) && !(cyberimp.organ_flags & ORGAN_HIDDEN))
cyberimp_detect += "[!cyberimp_detect ? "[cyberimp.get_examine_string(user)]" : ", [cyberimp.get_examine_string(user)]"]"
if(cyberimp_detect)
. += "<span class='notice ml-1'>Detected cybernetic modifications:</span>"
. += "<span class='notice ml-2'>[cyberimp_detect]</span>"
if(target_record)
var/health_record = target_record.physical_status
. += "<a href='?src=[REF(src)];hud=m;physical_status=1;examine_time=[world.time]'>\[[health_record]\]</a>"
health_record = target_record.mental_status
. += "<a href='?src=[REF(src)];hud=m;mental_status=1;examine_time=[world.time]'>\[[health_record]\]</a>"
target_record = find_record(perpname)
if(target_record)
. += "<a href='?src=[REF(src)];hud=m;evaluation=1;examine_time=[world.time]'>\[Medical evaluation\]</a><br>"
. += "<a href='?src=[REF(src)];hud=m;quirk=1;examine_time=[world.time]'>\[See quirks\]</a>"
if(HAS_TRAIT(user, TRAIT_SECURITY_HUD))
if((user.stat == CONSCIOUS || isobserver(user)) && user != src)
//|| !user.canmove || user.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
var/wanted_status = WANTED_NONE
var/security_note = "None."
target_record = find_record(perpname)
if(target_record)
wanted_status = target_record.wanted_status
if(target_record.security_note)
security_note = target_record.security_note
if(ishuman(user))
. += "Criminal status: <a href='?src=[REF(src)];hud=s;status=1;examine_time=[world.time]'>\[[wanted_status]\]</a>"
else
. += "Criminal status: [wanted_status]"
. += "Important Notes: [security_note]"
. += "Security record: <a href='?src=[REF(src)];hud=s;view=1;examine_time=[world.time]'>\[View\]</a>"
if(ishuman(user))
. += jointext(list("<a href='?src=[REF(src)];hud=s;add_citation=1;examine_time=[world.time]'>\[Add citation\]</a>",
"<a href='?src=[REF(src)];hud=s;add_crime=1;examine_time=[world.time]'>\[Add crime\]</a>",
"<a href='?src=[REF(src)];hud=s;add_note=1;examine_time=[world.time]'>\[Add note\]</a>"), "")
if(isobserver(user))
. += span_info("\n<b>Quirks:</b> [get_quirk_string(FALSE, CAT_QUIRK_ALL)]")
. += "</span>"
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .)
/**
* Shows any and all examine text related to any status effects the user has.
*/
/mob/living/proc/get_status_effect_examinations()
var/list/examine_list = list()
for(var/datum/status_effect/effect as anything in status_effects)
var/effect_text = effect.get_examine_text()
if(!effect_text)
continue
examine_list += effect_text
if(!length(examine_list))
return
return examine_list.Join("\n")
/mob/living/carbon/human/examine_more(mob/user)
. = ..()
if ((wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE)))
return
var/age_text
switch(age)
if(-INFINITY to 25)
age_text = "very young"
if(26 to 35)
age_text = "of adult age"
if(36 to 55)
age_text = "middle-aged"
if(56 to 75)
age_text = "rather old"
if(76 to 100)
age_text = "very old"
if(101 to INFINITY)
age_text = "withering away"
. += list(span_notice("[p_They()] appear[p_s()] to be [age_text]."))
+54 -1
View File
@@ -88,6 +88,59 @@
/mob/living/carbon/human/Topic(href, href_list)
if(href_list["see_id"])
var/mob/viewer = usr
var/can_see_still = (viewer in viewers(src))
var/obj/item/card/id/id = wear_id?.GetID()
var/same_id = id && (href_list["id_ref"] == REF(id) || href_list["id_name"] == id.registered_name)
if(!same_id && can_see_still)
to_chat(viewer, span_notice("[p_They()] [p_are()] no longer wearing that ID card."))
return
var/viable_time = can_see_still ? 3 MINUTES : 1 MINUTES // assuming 3min is the length of a hop line visit - give some leeway if they're still in sight
if(!same_id || (text2num(href_list["examine_time"]) + viable_time) < world.time)
to_chat(viewer, span_notice("You don't have that good of a memory. Examine [p_them()] again."))
return
if(HAS_TRAIT(src, TRAIT_UNKNOWN))
to_chat(viewer, span_notice("You can't make out that ID anymore."))
return
if(get_dist(viewer, src) > ID_EXAMINE_DISTANCE + 1) // leeway
to_chat(viewer, span_notice("You can't make out that ID from here."))
return
var/id_name = id.registered_name
var/id_age = id.registered_age
var/id_job = id.assignment
// Should probably be recorded on the ID, but this is easier (albiet more restrictive) on chameleon ID users
var/datum/record/crew/record = find_record(id_name)
var/id_blood_type = record?.blood_type
var/id_gender = record?.gender
var/id_species = record?.species
var/id_icon = jointext(id.get_id_examine_strings(viewer), "")
// Fill in some blanks for chameleon IDs to maintain the illusion of a real ID
if(istype(id, /obj/item/card/id/advanced/chameleon))
id_gender ||= gender
id_species ||= dna.species.name
id_blood_type ||= dna.blood_type
var/id_examine = span_slightly_larger(separator_hr("This is <em>[src]'s ID card</em>."))
id_examine += "<div class='img_by_text_container'>"
id_examine += "[id_icon]"
id_examine += "<div class='img_text'>"
id_examine += jointext(list(
"&bull; Name: [id_name || "Unknown"]",
"&bull; Job: [id_job || "Unassigned"]",
"&bull; Age: [id_age || "Unknown"]",
"&bull; Gender: [id_gender || "Unknown"]",
"&bull; Blood Type: [id_blood_type || "?"]",
"&bull; Species: [id_species || "Unknown"]",
), "<br>")
id_examine += "</div>" // container
id_examine += "</div>" // text
to_chat(viewer, examine_block(span_info(id_examine)))
///////HUDs///////
if(href_list["hud"])
if(!ishuman(usr) && !isobserver(usr))
@@ -97,7 +150,7 @@
if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD) && !HAS_TRAIT(human_or_ghost_user, TRAIT_MEDICAL_HUD))
return
if((text2num(href_list["examine_time"]) + 1 MINUTES) < world.time)
to_chat(human_or_ghost_user, "[span_notice("It's too late to use this now!")]")
to_chat(human_or_ghost_user, span_notice("It's too late to use this now!"))
return
var/datum/record/crew/target_record = find_record(perpname)
if(href_list["photo_front"] || href_list["photo_side"])
@@ -4,28 +4,6 @@
return FALSE
return TRUE
///returns a list of "damtype" => damage description based off of which bodypart description is most common
///used in human examines
/mob/living/carbon/human/proc/get_majority_bodypart_damage_desc()
var/list/seen_damage = list() // This looks like: ({Damage type} = list({Damage description for that damage type} = {number of times it has appeared}, ...), ...)
var/list/most_seen_damage = list() // This looks like: ({Damage type} = {Frequency of the most common description}, ...)
var/list/final_descriptions = list() // This looks like: ({Damage type} = {Most common damage description for that type}, ...)
for(var/obj/item/bodypart/part as anything in bodyparts)
for(var/damage_type in part.damage_examines)
var/damage_desc = part.damage_examines[damage_type]
if(!seen_damage[damage_type])
seen_damage[damage_type] = list()
if(!seen_damage[damage_type][damage_desc])
seen_damage[damage_type][damage_desc] = 1
else
seen_damage[damage_type][damage_desc] += 1
if(seen_damage[damage_type][damage_desc] > most_seen_damage[damage_type])
most_seen_damage[damage_type] = seen_damage[damage_type][damage_desc]
final_descriptions[damage_type] = damage_desc
return final_descriptions
//gets assignment from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job", hand_first = TRUE)
@@ -76,10 +54,10 @@
fake_name = "[fake_name]/[id_name]"
else
fake_name = id_name
if (HAS_TRAIT(src, TRAIT_UNKNOWN) || (!face_name && !id_name))
if (HAS_TRAIT(src, TRAIT_UNKNOWN) || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN) || (!face_name && !id_name))
fake_name = "Unknown"
return "[real_name][fake_name ? " (as [fake_name])" : ""]"
if(HAS_TRAIT(src, TRAIT_UNKNOWN))
if(HAS_TRAIT(src, TRAIT_UNKNOWN) || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN))
return "Unknown"
if(face_name)
if(add_id_name && id_name && (id_name != face_name))
@@ -89,8 +67,12 @@
return id_name
return "Unknown"
//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when Fluacided or when updating a human's name variable
/mob/living/carbon/human/proc/get_face_name(if_no_face = "Unknown")
/// Returns "Unknown" if facially disfigured and real_name if not.
/// Useful for setting name when Fluacided or when updating a human's name variable
/mob/living/carbon/proc/get_face_name(if_no_face = "Unknown")
return real_name
/mob/living/carbon/human/get_face_name(if_no_face = "Unknown")
if(HAS_TRAIT(src, TRAIT_UNKNOWN))
return if_no_face //We're Unknown, no face information for you
for(var/obj/item/worn_item in get_equipped_items())
@@ -104,7 +86,10 @@
//gets name from ID or PDA itself, ID inside PDA doesn't matter
//Useful when player is being seen by other mobs
/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown")
/mob/living/carbon/proc/get_id_name(if_no_id = "Unknown")
return
/mob/living/carbon/human/get_id_name(if_no_id = "Unknown")
var/obj/item/storage/wallet/wallet = wear_id
var/obj/item/modular_computer/pda = wear_id
var/obj/item/card/id/id = wear_id
@@ -247,18 +232,6 @@
WRITE_FILE(F["scar[char_index]-[scar_index]"], sanitize_text(valid_scars))
WRITE_FILE(F["current_scar_index"], sanitize_integer(scar_index))
///Returns death message for mob examine text
/mob/living/carbon/human/proc/generate_death_examine_text()
var/mob/dead/observer/ghost = get_ghost(TRUE, TRUE)
var/t_He = p_They()
var/t_his = p_their()
var/t_is = p_are()
//This checks to see if the body is revivable
if(get_organ_by_type(/obj/item/organ/internal/brain) && (client || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE) || (ghost?.can_reenter_corpse && ghost?.client)))
return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life...")
else
return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life and [t_his] soul has departed...")
///copies over clothing preferences like underwear to another human
/mob/living/carbon/human/proc/copy_clothing_prefs(mob/living/carbon/human/destination)
destination.underwear = underwear
@@ -1,5 +1,5 @@
/mob/living/silicon/ai/examine(mob/user)
. = list("<span class='info'>This is [icon2html(src, user)] <EM>[src]</EM>!")
. = list()
if(stat == DEAD)
. += span_deadsay("It appears to be powered-down.")
. += span_notice("Its floor <b>bolts</b> are [is_anchored ? "tightened" : "loose"].")
@@ -26,9 +26,5 @@
. += "The wireless networking light is blinking."
else if (!shunted && !client)
. += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem..."
. += "</span>"
. += ..()
/mob/living/silicon/ai/get_examine_string(mob/user, thats = FALSE)
return null
@@ -1,10 +1,10 @@
/mob/living/silicon/robot/examine(mob/user)
. = list("<span class='info'>This is [icon2html(src, user)] <EM>[src]</EM>!")
. = list()
if(desc)
. += "[desc]"
var/model_name = model ? "\improper [model.name]" : "\improper Default"
. += "\nIt is currently \a \"[span_bold("[model_name]")]\"-type cyborg.\n"
. += "It is currently <b>\a [model_name]-type</b> cyborg."
var/obj/act_module = get_active_held_item()
if(act_module)
@@ -14,13 +14,13 @@
if (getBruteLoss() < maxHealth*0.5)
. += span_warning("It looks slightly dented.")
else
. += span_warning("<B>It looks severely dented!</B>")
. += span_boldwarning("It looks severely dented!")
if (getFireLoss() || getToxLoss())
var/overall_fireloss = getFireLoss() + getToxLoss()
if (overall_fireloss < maxHealth * 0.5)
. += span_warning("It looks slightly charred.")
else
. += span_warning("<B>It looks severely burnt and heat-warped!</B>")
. += span_boldwarning("It looks severely burnt and heat-warped!")
if (health < -maxHealth*0.5)
. += span_warning("It looks barely operational.")
if (fire_stacks < 0)
@@ -46,9 +46,5 @@
. += span_warning("It doesn't seem to be responding.")
if(DEAD)
. += span_deadsay("It looks like its system is corrupted and requires a reset.")
. += "</span>"
. += ..()
/mob/living/silicon/robot/get_examine_string(mob/user, thats = FALSE)
return null
+12 -12
View File
@@ -523,29 +523,29 @@
return
face_atom(examinify)
var/list/result
var/result_combined
if(client)
LAZYINITLIST(client.recent_examines)
var/ref_to_atom = ref(examinify)
var/ref_to_atom = REF(examinify)
var/examine_time = client.recent_examines[ref_to_atom]
if(examine_time && (world.time - examine_time < EXAMINE_MORE_WINDOW))
result = examinify.examine_more(src)
var/list/result = examinify.examine_more(src)
if(!length(result))
result += span_notice("<i>You examine [examinify] closer, but find nothing of interest...</i>")
result_combined = jointext(result, "<br>")
else
result = examinify.examine(src)
SEND_SIGNAL(src, COMSIG_MOB_EXAMINING, examinify, result)
client.recent_examines[ref_to_atom] = world.time // set to when we last normal examine'd them
addtimer(CALLBACK(src, PROC_REF(clear_from_recent_examines), ref_to_atom), RECENT_EXAMINE_MAX_WINDOW)
handle_eye_contact(examinify)
else
result = examinify.examine(src) // if a tree is examined but no client is there to see it, did the tree ever really exist?
if(result.len)
for(var/i in 1 to (length(result) - 1))
result[i] += "\n"
if(!result_combined)
var/list/result = examinify.examine(src)
var/atom_title = examinify.examine_title(src, thats = TRUE)
SEND_SIGNAL(src, COMSIG_MOB_EXAMINING, examinify, result)
result_combined = (atom_title ? "[span_slightly_larger(separator_hr("[atom_title]."))]" : "") + jointext(result, "<br>")
to_chat(src, examine_block("<span class='infoplain'>[result.Join()]</span>"))
to_chat(src, examine_block(span_infoplain(result_combined)))
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, examinify)
/mob/proc/blind_examine_check(atom/examined_thing)
@@ -641,7 +641,7 @@
// check to see if their face is blocked or, if not, a signal blocks it
if(examined_mob.is_face_visible() && SEND_SIGNAL(src, COMSIG_MOB_EYECONTACT, examined_mob, TRUE) != COMSIG_BLOCK_EYECONTACT)
var/msg = span_smallnotice("You make eye contact with [examined_mob].")
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), src, msg), 3) // so the examine signal has time to fire and this will print after
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), src, msg), 0.3 SECONDS) // so the examine signal has time to fire and this will print after
if(!imagined_eye_contact && is_face_visible() && SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT)
var/msg = span_smallnotice("[src] makes eye contact with you.")
-9
View File
@@ -402,15 +402,6 @@
/mob/proc/can_hear()
return !HAS_TRAIT(src, TRAIT_DEAF)
/**
* Examine text for traits shared by multiple types.
*
* I wish examine was less copypasted. (oranges say, be the change you want to see buddy)
*/
/mob/proc/common_trait_examine()
if(HAS_TRAIT(src,TRAIT_HUSK))
. += span_warning("This body has been reduced to a grotesque husk.")
/**
* Get the list of keywords for policy config
*