Say vomit-stained, oil-stained, fuel-stained, etc. in item examine descriptions (#34781)

* Say vomit-stained, oil-stained, fuel-stained, etc. in item examine descriptions.

* Tweak.

* Clamp HSV value to [55, 200].

* an oil-stained chief medical officer's jumpsuit

* .

* Fix stained hands.

* Fix blood-stained hands.

* Update text.dm

---------

Co-authored-by: Hinaichigo <hinaichigo@github.com>
This commit is contained in:
Hinaichigo
2023-07-29 09:54:53 +09:00
committed by GitHub
parent 9ab7c8283a
commit 4bb5a5b0f3
14 changed files with 90 additions and 24 deletions

View File

@@ -6,3 +6,6 @@
#define COLOR_WHITEMODE_BACKGROUND "none"
#define COLOR_WHITEMODE_INFOBACKGROUND "#FFFFFF"
#define COLOR_WHITEMODE_TEXT "#000000"
#define DYNAMIC_TEXT_COLOR_V_MIN 60 //Dynamically-colored text such as that describing blood-stains will have its HSV V brightness clamped to between these.
#define DYNAMIC_TEXT_COLOR_V_MAX 200

View File

@@ -182,3 +182,12 @@
if (findtextEx(haystack, "iVBORw0KGgoAAAANSUhEUgAAACAAAABg"))
return 8
return 0 //unknown pattern, most likely something animated, oh well. be sure to account for that in your proc call.
//clamps the HSV brightness of an RGB color to [lower, upper]
/proc/ColorVClamp(var/rgb, var/lower = 0, var/upper = 255)
var/list/hsv_list = ReadHSV(RGBtoHSV(rgb))
hsv_list[3] = clamp(hsv_list[3], lower, upper)
if (hsv_list.len == 4)
return HSVtoRGB(hsv(hsv_list[1], hsv_list[2], hsv_list[3], hsv_list[4]))
return HSVtoRGB(hsv(hsv_list[1], hsv_list[2], hsv_list[3]))

View File

@@ -500,3 +500,10 @@
else
used_key_list[input_key] = 1
return input_key
//returns the maximum value of an associative list, assuming the values are numbers.
/proc/associative_max(list/L)
var/max
for(var/a in L)
if(max == null || L[a] > max) max = L[a]
return max

View File

@@ -793,3 +793,16 @@ var/quote = ascii2text(34)
else if(copytext(input, inputlength, inputlength + 1) == "s") //If the second-to-last letter isn't "e", and the last letter is "s", remove the "s".
input = copytext(input, 1, inputlength) //"gets" becomes "get"
return input + fromspace
/proc/get_indefinite_article(input, gender = NEUTER)
if (!input)
return
if (gender == PLURAL)
return "some"
else
var/first = copytext(input, 1, 2)
var/upperfirst = uppertext(first)
if (first == upperfirst || findtext("AEIOU", upperfirst))
return "an"
else
return "a"

View File

@@ -443,12 +443,9 @@ its easier to just keep the beam vertical.
/atom/proc/examine(mob/user, var/size = "", var/show_name = TRUE, var/show_icon = TRUE)
//This reformat names to get a/an properly working on item descriptions when they are bloody
var/f_name = "\a [src]."
if(src.blood_DNA && src.blood_DNA.len)
if(gender == PLURAL)
f_name = "some "
else
f_name = "a "
f_name += "<span class='danger'>blood-stained</span> [name]!"
if(blood_DNA && blood_DNA.len)
var/stain_text = get_stain_text(FALSE)
f_name = "[get_indefinite_article(stain_text, gender)] <span class='danger'><span style='color: [get_stain_text_color()]'>[stain_text]</span></span> [name]!"
if(show_name)
to_chat(user, "[show_icon ? bicon(src) : ""] That's [f_name]" + size)
@@ -1004,3 +1001,34 @@ its easier to just keep the beam vertical.
**/
/atom/proc/attempt_heating(atom/A, mob/user)
return
/atom/proc/get_stain_text(colored_text = TRUE) //"blood-and-vomit-stained"
if (blood_DNA?.len)
var/stains[0]
for (var/this_blood_DNA in blood_DNA)
if (this_blood_DNA)
stains[get_stain_name(blood_DNA[this_blood_DNA])]++
if (stains.len)
for (var/thisstain in stains)
. += "[. ? "and-" : ""][thisstain]-"
. += "stained"
if (colored_text && blood_color)
. = "<span style='color: [get_stain_text_color()]'>[.]</span>"
/atom/proc/get_stain_name(var/stain_type) //"AB+" -> "blood", "oil" -> "oil"
if (findtextEx("A+A-B+B-AB+AB-O+O-", stain_type))
return "blood"
else if (stain_type == "N/A")
return "blood" //call everything unspecified "blood" just in case
else
return stain_type
/atom/proc/get_stain_text_color(var/stain_color)
return ColorVClamp(stain_color ? stain_color : blood_color, DYNAMIC_TEXT_COLOR_V_MIN, DYNAMIC_TEXT_COLOR_V_MAX)
/atom/proc/a_stained(colored_text = TRUE)
var/stain_text = get_stain_text(FALSE)
var/indef_art = get_indefinite_article(stain_text, gender)
if (colored_text && blood_color)
stain_text = "<span style='color: [get_stain_text_color()]'>[stain_text]</span>"
return indef_art + " " + stain_text

View File

@@ -14,6 +14,7 @@
persistence_type = null //Yikes!
fake_DNA = "fuel splatters"
stain_name = "fuel"
/obj/effect/decal/cleanable/liquid_fuel/New(newLoc,amt=1)
src.amount = amt

View File

@@ -28,6 +28,7 @@ var/global/list/blood_list = list()
persistence_type = SS_BLOOD
fake_DNA = "old blood splatters"
stain_name = "blood"
/obj/effect/decal/cleanable/blood/New(var/loc, var/age, var/icon_state, var/color, var/dir, var/pixel_x, var/pixel_y, var/basecolor)
if(basecolor)

View File

@@ -152,6 +152,7 @@
persistent_type_replacement = /obj/effect/decal/cleanable/vomit/pre_dry
fake_DNA = "vomit splatters"
stain_name = "vomit"
/obj/effect/decal/cleanable/vomit/pre_dry
name = "dry vomit"

View File

@@ -7,6 +7,7 @@
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
fake_DNA = "robot oil splatters"
stain_name = "oil"
/obj/effect/decal/cleanable/blood/gibs/robot/update_icon()
color = "#FFFFFF"
@@ -43,6 +44,7 @@
basecolor=ROBOT_OIL
fake_DNA = "oil splatters"
stain_name = "oil"
/obj/effect/decal/cleanable/blood/oil/dry()
return

View File

@@ -26,6 +26,7 @@ var/list/infected_cleanables = list()
var/age = 1 //For map persistence. +1 per round that this item has survived. After a certain amount, it will not carry on to the next round anymore.
var/persistent_type_replacement //If defined, the persistent item generated from this will be of this type rather than our own.
var/fake_DNA = "random splatters"//for DNA-less splatters
var/stain_name //a stained item will be described as "<stain_name>-stained" if stain_name isn't null. eg. stain_name = "vomit" -> "vomit-stained"
/obj/effect/decal/cleanable/New(var/loc, var/age, var/icon_state, var/color, var/dir, var/pixel_x, var/pixel_y)
if(age)
@@ -93,7 +94,7 @@ var/list/infected_cleanables = list()
/obj/effect/decal/cleanable/proc/fixDNA()
if (!istype(blood_DNA, /list))
blood_DNA = list()
blood_DNA[fake_DNA] = "N/A"
blood_DNA[fake_DNA] = stain_name ? stain_name : "N/A"
/obj/effect/decal/cleanable/throw_impact(atom/hit_atom)
if (isliving(hit_atom) && blood_DNA?.len)

View File

@@ -293,7 +293,7 @@
for(var/obj/item/I in held_items)
if(I.blood_DNA && I.blood_DNA.len)
msg += "<span class='warning'>It's holding [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_index_limb_name(is_holding_item(I))]!</span>\n"
msg += "<span class='warning'>It's holding [bicon(I)] [I.a_stained()] [I.name] in its [get_index_limb_name(is_holding_item(I))]!</span>\n"
else
msg += "It's holding [bicon(I)] \a [I] in its [get_index_limb_name(is_holding_item(I))].\n"
@@ -321,7 +321,7 @@
slot_examine = " on its ears"
if(clothToExamine.blood_DNA && clothToExamine.blood_DNA.len)
msg += "<span class='warning'>It's wearing [bicon(clothToExamine)] [clothToExamine.gender==PLURAL?"some":"a"] blood-stained [clothToExamine][slot_examine]![clothToExamine.description_accessories()]</span>\n"
msg += "<span class='warning'>It's wearing [bicon(clothToExamine)] [clothToExamine.a_stained()] [clothToExamine][slot_examine]![clothToExamine.description_accessories()]</span>\n"
else
msg += "It's wearing [bicon(clothToExamine)] \a [clothToExamine][slot_examine].[clothToExamine.description_accessories()] \n"

View File

@@ -11,7 +11,7 @@
for(var/obj/item/I in held_items)
if(I.is_visible())
if(I.blood_DNA && I.blood_DNA.len)
msg += "<span class='warning'>It has [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_index_limb_name(is_holding_item(I))]!</span>\n"
msg += "<span class='warning'>It has [bicon(I)] [I.a_stained()] [I.name] in its [get_index_limb_name(is_holding_item(I))]!</span>\n"
else
msg += "It has [bicon(I)] \a [I] in its [get_index_limb_name(is_holding_item(I))].\n"

View File

@@ -58,35 +58,35 @@
//uniform
if(w_uniform && !(slot_w_uniform in obscured) && w_uniform.is_visible())
if(w_uniform.blood_DNA && w_uniform.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name]! [format_examine(w_uniform, "Examine")][w_uniform.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.a_stained()] [w_uniform.name]! [format_examine(w_uniform, "Examine")][w_uniform.description_accessories()]</span>\n"
else
msg += "[t_He] [t_is] wearing [bicon(w_uniform)] \a [w_uniform]. [format_examine(w_uniform, "Examine")][w_uniform.description_accessories()]\n"
//head
if(head && head.is_visible())
if(head.blood_DNA && head.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head! [format_examine(head, "Examine")][head.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(head)] [head.a_stained()] [head.name] on [t_his] head! [format_examine(head, "Examine")][head.description_accessories()]</span>\n"
else
msg += "[t_He] [t_is] wearing [bicon(head)] \a [head] on [t_his] head. [format_examine(head, "Examine")][head.description_accessories()][head.description_hats()]\n"
//suit/armour
if(wear_suit && wear_suit.is_visible())
if(wear_suit.blood_DNA && wear_suit.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]! [format_examine(wear_suit, "Examine")][wear_suit.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.a_stained()] [wear_suit.name]! [format_examine(wear_suit, "Examine")][wear_suit.description_accessories()]</span>\n"
else
msg += "[t_He] [t_is] wearing [bicon(wear_suit)] \a [wear_suit]. [format_examine(wear_suit, "Examine")][wear_suit.description_accessories()]\n"
//suit/armour storage
if(s_store)
if(s_store.blood_DNA && s_store.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]! [format_examine(s_store, "Examine")]</span>\n"
msg += "<span class='warning'>[t_He] [t_is] carrying [bicon(s_store)] [s_store.a_stained()] [s_store.name] on [t_his] [wear_suit.name]! [format_examine(s_store, "Examine")]</span>\n"
else
msg += "[t_He] [t_is] carrying [bicon(s_store)] \a [s_store] on [t_his] [wear_suit.name].\n"
//back
if(back && back.is_visible())
if(back.blood_DNA && back.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back! [format_examine(back, "Examine")][back.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_has] [bicon(back)] [back.a_stained()] [back] on [t_his] back! [format_examine(back, "Examine")][back.description_accessories()]</span>\n"
else
msg += "[t_He] [t_has] [bicon(back)] \a [back] on [t_his] back. [format_examine(back, "Examine")][back.description_accessories()]\n"
@@ -94,18 +94,18 @@
for(var/obj/item/I in held_items)
if(I.is_visible())
if(I.blood_DNA && I.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_is] holding [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_index_limb_name(is_holding_item(I))]! [format_examine(I, "Examine")]</span>\n"
msg += "<span class='warning'>[t_He] [t_is] holding [bicon(I)] [I.a_stained()] [I.name] in [t_his] [get_index_limb_name(is_holding_item(I))]! [format_examine(I, "Examine")]</span>\n"
else
msg += "[t_He] [t_is] holding [bicon(I)] \a [I] in [t_his] [get_index_limb_name(is_holding_item(I))]. [format_examine(I, "Examine")]\n"
//gloves
if(gloves && !(slot_gloves in obscured) && gloves.is_visible())
if(gloves.blood_DNA && gloves.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands! [format_examine(gloves, "Examine")][gloves.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_has] [bicon(gloves)] [gloves.a_stained()] [gloves.name] on [t_his] hands! [format_examine(gloves, "Examine")][gloves.description_accessories()]</span>\n"
else
msg += "[t_He] [t_has] [bicon(gloves)] \a [gloves] on [t_his] hands. [format_examine(gloves, "Examine")][gloves.description_accessories()]\n"
else if(blood_DNA && blood_DNA.len && !(slot_gloves in obscured))
msg += "<span class='warning'>[t_He] [t_has] blood-stained hands!</span>\n"
msg += "<span class='warning'>[t_He] [t_has] <span style='color: [get_stain_text_color(bloody_hands_data["blood_colour"])]'>[get_stain_name(bloody_hands_data["blood_type"])]-stained</span> hands!</span>\n"
//handcuffed?
if((handcuffed && handcuffed.is_visible()) || (mutual_handcuffs && mutual_handcuffs.is_visible()))
@@ -117,28 +117,28 @@
//belt
if(belt && belt.is_visible())
if(belt.blood_DNA && belt.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist! [format_examine(belt, "Examine")][belt.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_has] [bicon(belt)] [belt.a_stained()] [belt.name] about [t_his] waist! [format_examine(belt, "Examine")][belt.description_accessories()]</span>\n"
else
msg += "[t_He] [t_has] [bicon(belt)] \a [belt] about [t_his] waist. [format_examine(belt, "Examine")][belt.description_accessories()]\n"
//shoes
if(shoes && !(slot_shoes in obscured) && shoes.is_visible())
if(shoes.blood_DNA && shoes.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet! [format_examine(shoes, "Examine")][shoes.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_is] wearing [bicon(shoes)] [shoes.a_stained()] [shoes.name] on [t_his] feet! [format_examine(shoes, "Examine")][shoes.description_accessories()]</span>\n"
else
msg += "[t_He] [t_is] wearing [bicon(shoes)] \a [shoes] on [t_his] feet. [format_examine(shoes, "Examine")][shoes.description_accessories()]\n"
//mask
if(wear_mask && !(slot_wear_mask in obscured) && wear_mask.is_visible())
if(wear_mask.blood_DNA && wear_mask.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] [wear_mask.goes_in_mouth ? "in" : "on"] [t_his] [wear_mask.goes_in_mouth ? "mouth" : "face"]! [format_examine(wear_mask, "Examine")][wear_mask.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_has] [bicon(wear_mask)] [wear_mask.a_stained()] [wear_mask.name] [wear_mask.goes_in_mouth ? "in" : "on"] [t_his] [wear_mask.goes_in_mouth ? "mouth" : "face"]! [format_examine(wear_mask, "Examine")][wear_mask.description_accessories()]</span>\n"
else
msg += "[t_He] [t_has] [bicon(wear_mask)] \a [wear_mask] [wear_mask.goes_in_mouth ? "in" : "on"] [t_his] [wear_mask.goes_in_mouth ? "mouth" : "face"]. [format_examine(wear_mask, "Examine")][wear_mask.description_accessories()]\n"
//eyes
if(glasses && !(slot_glasses in obscured) && glasses.is_visible())
if(glasses.blood_DNA && glasses.blood_DNA.len)
msg += "<span class='warning'>[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes! [format_examine(glasses, "Examine")][glasses.description_accessories()]</span>\n"
msg += "<span class='warning'>[t_He] [t_has] [bicon(glasses)] [glasses.a_stained()] [glasses] covering [t_his] eyes! [format_examine(glasses, "Examine")][glasses.description_accessories()]</span>\n"
else
msg += "[t_He] [t_has] [bicon(glasses)] \a [glasses] covering [t_his] eyes. [format_examine(glasses, "Examine")][glasses.description_accessories()]\n"

View File

@@ -8,14 +8,14 @@
msg += "It is wearing [bicon(src.hat)] \a [src.hat] on its head.[hat.description_accessories()][hat.description_hats()]\n"
if (src.wear_mask && !(wear_mask.invisibility || wear_mask.alpha <= 1))
msg += "It has [bicon(src.wear_mask)] \a [src.wear_mask] [wear_mask.goes_in_mouth ? "in" : "over"] its [wear_mask.goes_in_mouth ? "mouth" : "face"].\n"
if (src.glasses && glasses.is_visible())
msg += "It is wearing [bicon(src.glasses)] \a [src.glasses] over its eyes.\n"
for(var/obj/item/I in held_items)
if(I.is_visible())
if(I.blood_DNA && I.blood_DNA.len)
msg += "<span class='warning'>It has [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_index_limb_name(is_holding_item(I))]!</span>\n"
msg += "<span class='warning'>It has [bicon(I)] [I.a_stained()] [I.name] in its [get_index_limb_name(is_holding_item(I))]!</span>\n"
else
msg += "It has [bicon(I)] \a [I] in its [get_index_limb_name(is_holding_item(I))].\n"