mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-20 04:26:03 +01:00
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:   Examining a person:   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)  ## 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:
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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]."))
|
||||
@@ -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(
|
||||
"• Name: [id_name || "Unknown"]",
|
||||
"• Job: [id_job || "Unassigned"]",
|
||||
"• Age: [id_age || "Unknown"]",
|
||||
"• Gender: [id_gender || "Unknown"]",
|
||||
"• Blood Type: [id_blood_type || "?"]",
|
||||
"• 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
@@ -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.")
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user