diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm
index c4db590e90..6049fd7918 100644
--- a/code/__DEFINES/cleaning.dm
+++ b/code/__DEFINES/cleaning.dm
@@ -5,8 +5,3 @@
#define CLEAN_STRONG 4 // Industrial strength
#define CLEAN_IMPRESSIVE 5 // Cleaning strong enough your granny would be proud
#define CLEAN_GOD 6 // Cleans things spotless down to the atomic structure
-
-//How strong things have to be to wipe forensic evidence...
-#define CLEAN_STRENGTH_FINGERPRINTS CLEAN_IMPRESSIVE
-#define CLEAN_STRENGTH_BLOOD CLEAN_WEAK
-#define CLEAN_STRENGTH_FIBERS CLEAN_IMPRESSIVE
diff --git a/code/__DEFINES/forensics.dm b/code/__DEFINES/forensics.dm
deleted file mode 100644
index bb512edcde..0000000000
--- a/code/__DEFINES/forensics.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-#define IF_HAS_BLOOD_DNA(__thing) GET_COMPONENT_FROM(__FR##__thing, /datum/component/forensics, __thing); if(__FR##__thing && length(__FR##__thing.blood_DNA))
-#define IF_HAS_BLOOD_DNA_AND(__thing, __conditions...) GET_COMPONENT_FROM(__FR##__thing, /datum/component/forensics, __thing); if(__FR##__thing && length(__FR##__thing.blood_DNA) && (##__conditions))
diff --git a/code/datums/components/cleaning.dm b/code/datums/components/cleaning.dm
index 05c26efcc1..08ac57b79a 100644
--- a/code/datums/components/cleaning.dm
+++ b/code/datums/components/cleaning.dm
@@ -12,28 +12,28 @@
if(!isturf(tile))
return
- SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ tile.clean_blood()
for(var/A in tile)
if(is_cleanable(A))
qdel(A)
- else if(istype(A, /obj/item))
- var/obj/item/I = A
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(ismob(I.loc))
- var/mob/M = I.loc
+ else if(isitem(A))
+ var/obj/item/cleaned_item = A
+ cleaned_item.clean_blood()
+ if(ismob(cleaned_item.loc))
+ var/mob/M = cleaned_item.loc
M.regenerate_icons()
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.head.clean_blood()
if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.wear_suit.clean_blood()
else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.w_uniform.clean_blood()
if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.shoes.clean_blood()
+ cleaned_human.clean_blood()
cleaned_human.wash_cream()
cleaned_human.regenerate_icons()
to_chat(cleaned_human, "[AM] cleans your face!")
diff --git a/code/datums/components/decals/blood.dm b/code/datums/components/decals/blood.dm
deleted file mode 100644
index 3daa4b5944..0000000000
--- a/code/datums/components/decals/blood.dm
+++ /dev/null
@@ -1,40 +0,0 @@
-/datum/component/decal/blood
- dupe_mode = COMPONENT_DUPE_UNIQUE
-
-/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
- if(!isitem(parent))
- return COMPONENT_INCOMPATIBLE
- . = ..()
- RegisterSignal(parent, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
-
-/datum/component/decal/blood/generate_appearance(_icon, _icon_state, _dir, _layer, _color)
- var/obj/item/I = parent
- if(!_icon)
- _icon = 'icons/effects/blood.dmi'
- if(!_icon_state)
- _icon_state = "itemblood"
- var/icon = initial(I.icon)
- var/icon_state = initial(I.icon_state)
- if(!icon || !icon_state)
- // It's something which takes on the look of other items, probably
- icon = I.icon
- icon_state = I.icon_state
- var/static/list/blood_splatter_appearances = list()
- //try to find a pre-processed blood-splatter. otherwise, make a new one
- var/index = "[REF(icon)]-[icon_state]"
- pic = blood_splatter_appearances[index]
-
- if(!pic)
- var/icon/blood_splatter_icon = icon(initial(I.icon), initial(I.icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
- blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
- blood_splatter_icon.Blend(icon(_icon, _icon_state), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
- pic = mutable_appearance(blood_splatter_icon, initial(I.icon_state))
- pic.color = I.blood_color //add the blood's color with DNA information
- blood_splatter_appearances[index] = pic
- return TRUE
-
-/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
- var/atom/A = parent
- override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a"
- override[EXAMINE_POSITION_BEFORE] = " blood-stained "
- return COMPONENT_EXNAME_CHANGED
\ No newline at end of file
diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm
deleted file mode 100644
index 4ee8b93cc7..0000000000
--- a/code/datums/components/forensics.dm
+++ /dev/null
@@ -1,213 +0,0 @@
-/datum/component/forensics
- dupe_mode = COMPONENT_DUPE_UNIQUE
- can_transfer = TRUE
- var/list/fingerprints //assoc print = print
- var/list/hiddenprints //assoc ckey = realname/gloves/ckey
- var/list/blood_DNA //assoc dna = bloodtype
- var/list/fibers //assoc print = print
- var/list/blood_mix_types // data("[blood_type]" = sting list
- var/blood_mix_color
-
-/datum/component/forensics/InheritComponent(datum/component/forensics/F, original) //Use of | and |= being different here is INTENTIONAL.
- fingerprints = fingerprints | F.fingerprints
- hiddenprints = hiddenprints | F.hiddenprints
- blood_DNA = blood_DNA | F.blood_DNA
- fibers = fibers | F.fibers
- blood_mix_types = blood_mix_types | F.blood_mix_types
- blood_mix_color = blood_mix_color | F.blood_mix_color
- check_blood()
- return ..()
-
-/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers, new_blood_mix_types, new_blood_mix_color)
- if(!isatom(parent))
- return COMPONENT_INCOMPATIBLE
- fingerprints = new_fingerprints
- hiddenprints = new_hiddenprints
- blood_DNA = new_blood_DNA
- fibers = new_fibers
- blood_mix_types = new_blood_mix_types
- blood_mix_color = new_blood_mix_color
- check_blood()
-
-/datum/component/forensics/RegisterWithParent()
- check_blood()
- RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act)
-// RegisterSignal(parent, COMSIG_BLOOD_COLOR, .proc/
-
-/datum/component/forensics/UnregisterFromParent()
- UnregisterSignal(parent, list(COMSIG_COMPONENT_CLEAN_ACT))
-
-/datum/component/forensics/PostTransfer()
- if(!isatom(parent))
- return COMPONENT_INCOMPATIBLE
-
-/datum/component/forensics/proc/wipe_fingerprints()
- fingerprints = null
- return TRUE
-
-/datum/component/forensics/proc/wipe_hiddenprints()
- return //no.
-
-/datum/component/forensics/proc/wipe_blood_DNA()
- blood_DNA = null
- blood_mix_types = null
- blood_mix_color = null
- return TRUE
-
-/datum/component/forensics/proc/wipe_fibers()
- fibers = null
- return TRUE
-
-/datum/component/forensics/proc/clean_act(datum/source, strength)
- if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
- wipe_fingerprints()
- if(strength >= CLEAN_STRENGTH_BLOOD)
- wipe_blood_DNA()
- if(strength >= CLEAN_STRENGTH_FIBERS)
- wipe_fibers()
-
-/datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text)
- if(!length(_fingerprints))
- return
- LAZYINITLIST(fingerprints)
- for(var/i in _fingerprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
- fingerprints[i] = i
- return TRUE
-
-/datum/component/forensics/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
- if(!M)
- return
- add_hiddenprint(M)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- add_fibers(H)
- if(H.gloves) //Check if the gloves (if any) hide fingerprints
- var/obj/item/clothing/gloves/G = H.gloves
- if(G.transfer_prints)
- ignoregloves = TRUE
- if(!ignoregloves)
- H.gloves.add_fingerprint(H, TRUE) //ignoregloves = 1 to avoid infinite loop.
- return
- var/full_print = md5(H.dna.uni_identity)
- LAZYSET(fingerprints, full_print, full_print)
- return TRUE
-
-/datum/component/forensics/proc/add_fiber_list(list/_fibertext) //list(text)
- if(!length(_fibertext))
- return
- LAZYINITLIST(fibers)
- for(var/i in _fibertext) //We use an associative list, make sure we don't just merge a non-associative list into ours.
- fibers[i] = i
- return TRUE
-
-/datum/component/forensics/proc/add_fibers(mob/living/carbon/human/M)
- var/fibertext
- var/item_multiplier = isitem(src)?1.2:1
- if(M.wear_suit)
- fibertext = "Material from \a [M.wear_suit]."
- if(prob(10*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- if(!(M.wear_suit.body_parts_covered & CHEST))
- if(M.w_uniform)
- fibertext = "Fibers from \a [M.w_uniform]."
- if(prob(12*item_multiplier) && !LAZYACCESS(fibers, fibertext)) //Wearing a suit means less of the uniform exposed.
- LAZYSET(fibers, fibertext, fibertext)
- if(!(M.wear_suit.body_parts_covered & HANDS))
- if(M.gloves)
- fibertext = "Material from a pair of [M.gloves.name]."
- if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- else if(M.w_uniform)
- fibertext = "Fibers from \a [M.w_uniform]."
- if(prob(15*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- // "Added fibertext: [fibertext]"
- LAZYSET(fibers, fibertext, fibertext)
- if(M.gloves)
- fibertext = "Material from a pair of [M.gloves.name]."
- if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- else if(M.gloves)
- fibertext = "Material from a pair of [M.gloves.name]."
- if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- return TRUE
-
-/datum/component/forensics/proc/add_hiddenprint_list(list/_hiddenprints) //list(ckey = text)
- if(!length(_hiddenprints))
- return
- LAZYINITLIST(hiddenprints)
- for(var/i in _hiddenprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
- hiddenprints[i] = _hiddenprints[i]
- return TRUE
-
-/datum/component/forensics/proc/add_hiddenprint(mob/living/M)
- if(!M || !M.key)
- return
- var/hasgloves = ""
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(H.gloves)
- hasgloves = "(gloves)"
- var/current_time = TIME_STAMP("hh:mm:ss", FALSE)
- if(!LAZYACCESS(hiddenprints, M.key))
- LAZYSET(hiddenprints, M.key, "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]")
- else
- var/laststamppos = findtext(LAZYACCESS(hiddenprints, M.key), " Last: ")
- if(laststamppos)
- LAZYSET(hiddenprints, M.key, copytext(hiddenprints[M.key], 1, laststamppos))
- hiddenprints[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]" //made sure to be existing by if(!LAZYACCESS);else
- var/atom/A = parent
- A.fingerprintslast = M.ckey
- return TRUE
-
-/datum/component/forensics/proc/add_blood_DNA(list/dna) //list(dna_enzymes = type)
- if(!length(dna))
- return
- LAZYINITLIST(blood_DNA)
- LAZYINITLIST(blood_mix_types)
- for(var/i in dna)
- blood_DNA[i] = dna[i]
- for(var/type in blood_DNA)
- if(type in blood_DNA[type])
- blood_mix_types += blood_DNA[type]
-
- blood_list_check(blood_mix_types)
- check_blood()
- return TRUE
-
-/datum/component/forensics/proc/check_blood()
- if(!isitem(parent) || !ismob(parent))
- return
- if(!length(blood_DNA))
- return
-
-/datum/component/forensics/proc/blood_list_check(list/blood_types, blood_type) //This is a messy attempt at trying to reduce lists of items and mobs with blood colors on them
- if(blood_type in GLOB.regular_bloods)
- blood_type = "A+" //generic so we don't have 8 different types of human blood
- if(blood_type in blood_mix_types)
- return
- else
- LAZYADD(blood_mix_types, blood_type)
-
- if(blood_mix_types.len)
- blood_DNA_to_color(blood_mix_types)
- else
- return
-
-/datum/component/forensics/proc/blood_DNA_to_color(list/bloods)
- var/final_rgb = "#940000" //We default to red just in case
- if(bloods.len)
- var/sum = 0 //this is all shitcode, but it works; trust me
- final_rgb = bloodtype_to_color(bloods[1])
- sum = bloods[bloods[1]]
- if(bloods.len > 1)
- var/i = 2
- while(i <= bloods.len)
- var/tmp = bloods[bloods[i]]
- final_rgb = BlendRGB(final_rgb, bloodtype_to_color(bloods[i]), tmp/(tmp+sum))
- sum += tmp
- i++
- else
- final_rgb = BlendRGB(final_rgb, bloodtype_to_color(bloods))
-
- blood_mix_color = final_rgb
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 0ba8d7411b..50f6cdf968 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -36,6 +36,9 @@
var/rad_insulation = RAD_NO_INSULATION
var/icon/blood_splatter_icon
+ var/list/fingerprints
+ var/list/fingerprintshidden
+ var/list/blood_DNA
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
@@ -244,23 +247,22 @@
return TRUE
return FALSE
-/atom/proc/get_examine_name(mob/user)
- . = "\a [src]"
- var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]")
- if(article)
- . = "[article] [src]"
- override[EXAMINE_POSITION_ARTICLE] = article
- if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
- . = override.Join("")
-
-/atom/proc/get_examine_string(mob/user, thats = FALSE)
- . = "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]"
-
/atom/proc/examine(mob/user)
- to_chat(user, get_examine_string(user, 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 && !istype(src, /obj/effect/decal))
+ if(gender == PLURAL)
+ f_name = "some "
+ else
+ f_name = "a "
+ f_name += "blood-stained [name]!"
+
+ to_chat(user, "[icon2html(src, user)] That's [f_name]")
if(desc)
to_chat(user, desc)
+ // *****RM
+ //to_chat(user, "[name]: Dn:[density] dir:[dir] cont:[contents] icon:[icon] is:[icon_state] loc:[loc]")
if(reagents)
if(container_type & TRANSPARENT)
@@ -282,8 +284,6 @@
else
to_chat(user, "It's empty.")
- SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user)
-
/atom/proc/relaymove(mob/user)
if(buckle_message_cooldown <= world.time)
buckle_message_cooldown = world.time + 50
@@ -345,18 +345,123 @@
var/new_blood_dna = L.get_blood_dna_list()
if(!new_blood_dna)
return FALSE
- var/old_length = blood_DNA_length()
- add_blood_DNA(new_blood_dna)
- if(blood_DNA_length() == old_length)
+ if(!blood_DNA) //if our list of DNA doesn't exist yet, initialise it.
+ blood_DNA = list()
+ var/old_length = blood_DNA.len
+ blood_DNA |= new_blood_dna
+ if(blood_DNA.len == old_length)
return FALSE
return TRUE
+//to add blood dna info to the object's blood_DNA list
+/atom/proc/transfer_blood_dna(list/blood_dna)
+ if(!blood_DNA)
+ blood_DNA = list()
+ var/old_length = blood_DNA.len
+ blood_DNA |= blood_dna
+ if(blood_DNA.len > old_length)
+ return TRUE//some new blood DNA was added
+
+
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
var/list/blood_dna = M.get_blood_dna_list()
if(!blood_dna)
return FALSE
- return add_blood_DNA(blood_dna)
+ return add_blood(blood_dna)
+
+//to add blood onto something, with blood dna info to include.
+/atom/proc/add_blood(list/blood_dna)
+ return FALSE
+
+/obj/add_blood(list/blood_dna)
+ return transfer_blood_dna(blood_dna)
+
+/obj/item/add_blood(list/blood_dna)
+ if(!..())
+ return FALSE
+ add_blood_overlay()
+ return TRUE //we applied blood to the item
+
+/obj/item/proc/add_blood_overlay()
+ if(!blood_DNA.len)
+ return
+ if(initial(icon) && initial(icon_state))
+ blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
+ blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
+ blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
+ blood_splatter_icon.Blend(blood_DNA_to_color(), ICON_MULTIPLY)
+ add_overlay(blood_splatter_icon)
+
+/obj/item/clothing/gloves/add_blood(mob/living/carbon/M)
+ . = ..()
+ transfer_blood = rand(2, 4)
+ return TRUE
+
+/obj/item/clothing/shoes/add_blood(mob/living/carbon/M)
+ . = ..()
+ transfer_blood = rand(2, 4)
+ return TRUE
+
+/turf/add_blood(list/blood_dna)
+ var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
+ if(!B)
+ B = new /obj/effect/decal/cleanable/blood/splatter(src)
+ B.transfer_blood_dna(blood_dna) //give blood info to the blood decal.
+ return TRUE //we bloodied the floor
+
+/mob/living/carbon/human/add_blood(list/blood_dna)
+ if(wear_suit)
+ wear_suit.add_blood(blood_dna)
+ update_inv_wear_suit()
+ else if(w_uniform)
+ w_uniform.add_blood(blood_dna)
+ update_inv_w_uniform()
+ if(gloves)
+ var/obj/item/clothing/gloves/G = gloves
+ G.add_blood(blood_dna)
+ else
+ transfer_blood_dna(blood_dna)
+ bloody_hands = rand(2, 4)
+ update_inv_gloves() //handles bloody hands overlays and updating
+ if(shoes)
+ var/obj/item/clothing/shoes/S = shoes
+ S.add_blood(blood_dna)
+ else
+ transfer_blood_dna(blood_dna)
+ bloody_feet = rand(2, 4)
+ update_inv_shoes() // get them feet messy for prints!
+ return TRUE
+
+/atom/proc/clean_blood()
+ if(islist(blood_DNA))
+ blood_DNA = null
+ return TRUE
+
+/atom/proc/blood_DNA_to_color()
+ var/list/colors = list()//first we make a list of all bloodtypes present
+ for(var/bloop in blood_DNA)
+ if(colors[blood_DNA[bloop]])
+ colors[blood_DNA[bloop]]++
+ else
+ colors[blood_DNA[bloop]] = 1
+
+ var/final_rgb = "#940000"
+
+ if(colors.len)
+ var/sum = 0 //this is all shitcode, but it works; trust me
+ final_rgb = bloodtype_to_color(colors[1])
+ sum = colors[colors[1]]
+ if(colors.len > 1)
+ var/i = 2
+ while(i <= colors.len)
+ var/tmp = colors[colors[i]]
+ final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum))
+ sum += tmp
+ i++
+
+ return final_rgb
+
/atom/proc/wash_cream()
return TRUE
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index b84db2ca8d..930edfe467 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -246,7 +246,8 @@
visible_message("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.")
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
+ I.clean_blood()
+ I.fingerprints = list()
var/datum/component/radioactive/contamination = I.GetComponent(/datum/component/radioactive)
if(contamination)
qdel(contamination)
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 0a9a135986..1a8dd231f4 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -11,10 +11,6 @@
var/obj/item/color_source
var/max_wash_capacity = 5
-/obj/machinery/washing_machine/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
-
/obj/machinery/washing_machine/examine(mob/user)
..()
to_chat(user, "Alt-click it to start a wash cycle.")
@@ -59,7 +55,8 @@
M.Translate(rand(-3, 3), rand(-1, 3))
animate(src, transform=M, time=2)
-/obj/machinery/washing_machine/proc/clean_blood()
+/obj/machinery/washing_machine/clean_blood()
+ ..()
if(!busy)
bloody_mess = FALSE
update_icon()
@@ -67,7 +64,7 @@
/obj/machinery/washing_machine/proc/wash_cycle()
for(var/X in contents)
var/atom/movable/AM = X
- SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ AM.clean_blood()
AM.machine_wash(src)
busy = FALSE
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index f5e929a7ae..61dff565af 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -82,7 +82,8 @@
add_blood = bloodiness
bloodiness -= add_blood
S.blood_smear[blood_state] = min(MAX_SHOE_BLOODINESS,S.blood_smear[blood_state]+add_blood)
- S.add_blood_DNA(return_blood_DNA())
+ if(blood_DNA && blood_DNA.len)
+ S.add_blood(blood_DNA)
S.blood_state = blood_state
S.blood_color = blood_color
update_icon()
@@ -97,7 +98,8 @@
bloodiness -= add_blood
H.blood_smear[blood_state] = min(MAX_SHOE_BLOODINESS,H.blood_smear[blood_state]+add_blood)
H.bloodiness = add_blood
- H.add_blood_DNA(return_blood_DNA())
+ if(blood_DNA && blood_DNA.len)
+ H.add_blood(blood_DNA)
H.blood_state = blood_state
H.blood_color = blood_color
update_icon()
diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm
index 9b4d65cff4..33d1e41bef 100644
--- a/code/game/objects/effects/decals/cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/cleanable/aliens.dm
@@ -4,10 +4,7 @@
name = "xeno blood"
desc = "It's green and acidic. It looks like... blood?"
color = BLOOD_COLOR_XENO
-
-/obj/effect/decal/cleanable/blood/xeno/Initialize()
- . = ..()
- add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ blood_DNA = list("UNKNOWN DNA" = "X*")
/obj/effect/decal/cleanable/blood/splatter/xeno
color = BLOOD_COLOR_XENO
@@ -64,6 +61,10 @@
/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body
random_icon_states = list("xgiblarvahead", "xgiblarvatorso")
-/obj/effect/decal/cleanable/blood/xeno/tracks/Initialize()
- . = ..()
- add_blood_DNA(list("UNKNOWN DNA" = "X*"))
\ No newline at end of file
+/obj/effect/decal/cleanable/blood/xtracks
+ icon_state = "tracks"
+ random_icon_states = null
+
+/obj/effect/decal/cleanable/blood/xtracks/Initialize()
+ add_blood(list("UNKNOWN DNA" = "X*"))
+ . = ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm
index 31849c7251..7a36ce8f7a 100644
--- a/code/game/objects/effects/decals/cleanable/gibs.dm
+++ b/code/game/objects/effects/decals/cleanable/gibs.dm
@@ -48,6 +48,7 @@
diseases = infective.diseases
var/obj/effect/decal/cleanable/blood/gibs/gibbers = src
var/obj/effect/decal/cleanable/blood/splatter/splat = new /obj/effect/decal/cleanable/blood/splatter(loc, diseases)
+ splat.transfer_blood_dna(blood_DNA)
splat.color = gibbers.blood_color
splat.blood_color = gibbers.blood_color
@@ -87,7 +88,7 @@
. = ..()
setDir(pick(1,2,4,8))
icon_state += "-old"
- add_blood_DNA(list("Non-human DNA" = "A+"))
+ add_blood(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/blood/drip
name = "drips of blood"
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 0a4a266874..0bfec90afd 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -4,40 +4,28 @@
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
+ blood_DNA = list()
blood_state = BLOOD_STATE_BLOOD
color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere.
bloodiness = BLOOD_AMOUNT_PER_DECAL
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
- if(bloodiness)
- if(C.bloodiness < MAX_SHOE_BLOODINESS)
- C.bloodiness += bloodiness
+ if (C.blood_DNA)
+ blood_DNA |= C.blood_DNA.Copy()
update_icon()
- return ..()
+ ..()
-/obj/effect/decal/cleanable/blood/add_blood_DNA(list/blood_dna)
- return TRUE
+/obj/effect/decal/cleanable/blood/transfer_blood_dna()
+ ..()
+ update_icon()
/obj/effect/decal/cleanable/blood/transfer_mob_blood_dna()
. = ..()
update_icon()
/obj/effect/decal/cleanable/blood/update_icon()
- if(!blood_color)
- if(reagents.reagent_list.len)
- for(var/datum/reagent/R in reagents.reagent_list)
- // Get blood data from the blood reagent.
- if(istype(R, /datum/reagent/blood))
- if(R.data["blood_type"])
- blood_color = bloodtype_to_color(R.data["blood_type"])
- else if(istype(R, /datum/reagent/liquidgibs))
- if(R.data["blood_type"])
- blood_color = bloodtype_to_color(R.data["blood_type"])
- else
- return
- else
- color = blood_color
+ color = blood_DNA_to_color()
//obj/effect/decal/cleanable/blood/update_color()
// if(SEND_SIGNAL(COMSIG_BLOOD_COLOR) & COMPONENT_BLOCK_UPDATE_COLOR)
@@ -50,8 +38,9 @@
color = "#3a0505"
/obj/effect/decal/cleanable/blood/old/Initialize(mapload, list/datum/disease/diseases)
- . = ..()
- add_blood_DNA(list("blood_type"= "A+"))
+ ..()
+ icon_state += "-old"
+ add_blood(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
@@ -66,10 +55,7 @@
bloodiness = BLOOD_AMOUNT_PER_DECAL
/obj/effect/decal/cleanable/trail_holder/update_icon()
- GET_COMPONENT(D, /datum/component/forensics)
- if(istype(D) && !blood_color)
- blood_color = D.blood_mix_color
- color = blood_color
+ color = blood_DNA_to_color()
/obj/effect/cleanable/trail_holder/Initialize()
. = ..()
@@ -78,6 +64,10 @@
/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
return TRUE
+/obj/effect/decal/cleanable/trail_holder/transfer_blood_dna()
+ ..()
+ update_icon()
+
/obj/effect/decal/cleanable/trail_holder/transfer_mob_blood_dna()
. = ..()
update_icon()
@@ -122,6 +112,8 @@
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.blood_smear[blood_state])
+ if(color != bloodtype_to_color(S.last_bloodtype))//last entry - we check its color
+ return
S.blood_smear[blood_state] = max(S.blood_smear[blood_state] - BLOOD_LOSS_PER_STEP, 0)
S.blood_color = blood_color
shoe_types |= S.type
@@ -138,6 +130,7 @@
update_icon()
/obj/effect/decal/cleanable/blood/footprints/tracks/update_icon()
+ ..()
cut_overlays()
for(var/Ddir in GLOB.cardinals)
diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm
index 7e960b5d78..0cb17f11be 100644
--- a/code/game/objects/effects/spawners/gibspawner.dm
+++ b/code/game/objects/effects/spawners/gibspawner.dm
@@ -12,8 +12,6 @@
/obj/effect/gibspawner/Initialize(mapload, mob/living/source_mob, list/datum/disease/diseases)
. = ..()
- AddComponent(/datum/component/forensics)
-
if(gibtypes.len != gibamounts.len)
stack_trace("Gib list amount length mismatch!")
return
@@ -74,7 +72,7 @@
var/mob/living/carbon/digester = loc
digester.stomach_contents += gib
- gib.add_blood_DNA(dna_to_add)
+ gib.blood_DNA += dna_to_add
// color them properly, please.
gib.body_colors = body_coloring
gib.update_icon()
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 27ec0a4026..fbad000098 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -43,7 +43,7 @@
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
/obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter
- splatter_type = "xsplatter"
+ color = BLOOD_COLOR_XENO
/obj/effect/temp_visual/dir_setting/speedbike_trail
name = "speedbike trails"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 88eb8e9ad4..e942396c16 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -538,6 +538,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
M.become_blind(EYE_DAMAGE)
to_chat(M, "You go blind!")
+/obj/item/clean_blood()
+ . = ..()
+ if(.)
+ if(blood_splatter_icon)
+ cut_overlay(blood_splatter_icon)
+
+/obj/item/clothing/gloves/clean_blood()
+ . = ..()
+ if(.)
+ transfer_blood = 0
+
/obj/item/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FOUR)
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index 1d302b409e..e371ae7d40 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -88,7 +88,7 @@
var/obj/effect/decal/cleanable/C = locate() in target
qdel(C)
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ target.clean_blood()
target.wash_cream()
return
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index eb0271c1b9..56511b481a 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -136,7 +136,7 @@
else
icon_state = initial(icon_state)
-/obj/item/radio/intercom/add_blood_DNA(list/blood_dna)
+/obj/item/radio/intercom/add_blood(list/blood_dna)
return FALSE
//Created through the autolathe or through deconstructing intercoms. Can be applied to wall to make a new intercom on it!
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 935d2a007e..a5929e95cb 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -22,7 +22,7 @@
user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku!")
return (BRUTELOSS|FIRELOSS)
-/obj/item/melee/transforming/energy/add_blood_DNA(list/blood_dna)
+/obj/item/melee/transforming/energy/add_blood(list/blood_dna)
return FALSE
/obj/item/melee/transforming/energy/is_sharp()
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 3a35f4d8ef..b201ef60a8 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -343,7 +343,7 @@
shard.Consume()
T.CalculateAdjacentTurfs()
-/obj/item/melee/supermatter_sword/add_blood_DNA(list/blood_dna)
+/obj/item/melee/supermatter_sword/add_blood(list/blood_dna)
return FALSE
/obj/item/melee/curator_whip
diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm
index 44ccd7aad5..32428bf298 100644
--- a/code/game/objects/items/mop.dm
+++ b/code/game/objects/items/mop.dm
@@ -26,7 +26,7 @@
/obj/item/mop/proc/clean(turf/A)
if(reagents.has_reagent("water", 1) || reagents.has_reagent("holywater", 1) || reagents.has_reagent("vodka", 1) || reagents.has_reagent("cleaner", 1))
- SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ A.clean_blood()
for(var/obj/effect/O in A)
if(is_cleanable(O))
qdel(O)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 34ae4cb5ef..470261bd6d 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -388,10 +388,10 @@
else
. = ..()
-/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
- add_blood_DNA(from.return_blood_DNA())
- add_fingerprint_list(from.return_fingerprints())
- add_hiddenprint_list(from.return_hiddenprints())
+/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj)
+ blood_DNA = from.blood_DNA
+ fingerprints = from.fingerprints
+ fingerprintshidden = from.fingerprintshidden
fingerprintslast = from.fingerprintslast
//TODO bloody overlay
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index b95d6a897e..6b093841de 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -241,5 +241,5 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
else
return ..(M,user,heal_mode = FALSE)
-/obj/item/storage/book/bible/syndicate/add_blood_DNA(list/blood_dna)
+/obj/item/storage/book/bible/syndicate/add_blood(list/blood_dna)
return FALSE
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index d4ec9217e7..784aed077e 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -341,7 +341,7 @@
icon_state = "dualsaber[item_color][wielded]"
else
icon_state = "dualsaber0"
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ clean_blood()//blood overlays get weird otherwise, because the sprite changes.
/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user)
if(user.has_dna())
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index d70838a30b..a03c0c2b46 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -317,7 +317,7 @@
/obj/machinery/shower/proc/wash_obj(obj/O)
- . = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ . = O.clean_blood()
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
if(isitem(O))
var/obj/item/I = O
@@ -328,7 +328,7 @@
/obj/machinery/shower/proc/wash_turf()
if(isturf(loc))
var/turf/tile = loc
- SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ tile.clean_blood()
tile.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
for(var/obj/effect/E in tile)
if(is_cleanable(E))
@@ -336,7 +336,7 @@
/obj/machinery/shower/proc/wash_mob(mob/living/L)
- SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ L.clean_blood()
L.wash_cream()
L.ExtinguishMob()
L.adjust_fire_stacks(-20) //Douse ourselves with water to avoid fire more easily
@@ -381,7 +381,7 @@
else if(H.w_uniform && wash_obj(H.w_uniform))
H.update_inv_w_uniform()
if(washgloves)
- SEND_SIGNAL(H, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ H.clean_blood()
if(H.shoes && washshoes && wash_obj(H.shoes))
H.update_inv_shoes()
if(H.wear_mask && washmask && wash_obj(H.wear_mask))
@@ -398,9 +398,9 @@
else
if(M.wear_mask && wash_obj(M.wear_mask))
M.update_inv_wear_mask(0)
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ M.clean_blood()
else
- SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ L.clean_blood()
/obj/machinery/shower/proc/contamination_cleanse(atom/movable/thing)
var/datum/component/radioactive/healthy_green_glow = thing.GetComponent(/datum/component/radioactive)
@@ -498,7 +498,7 @@
H.regenerate_icons()
user.drowsyness = max(user.drowsyness - rand(2,3), 0) //Washing your face wakes you up if you're falling asleep
else
- SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ user.clean_blood()
/obj/structure/sink/attackby(obj/item/O, mob/living/user, params)
if(busy)
@@ -554,7 +554,7 @@
busy = FALSE
return 1
busy = FALSE
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ O.clean_blood()
O.acid_level = 0
create_reagents(5)
reagents.add_reagent(dispensedreagent, 5)
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index 63b5f4b160..96a24e0b2c 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -225,7 +225,7 @@
for(var/mob/living/simple_animal/slime/M in src)
M.apply_water()
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ clean_blood()
for(var/obj/effect/O in src)
if(is_cleanable(O))
qdel(O)
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index 923a224b81..949fb2e4ed 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -69,8 +69,10 @@
//Left hand items
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
- msg += "It is holding [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n"
-
+ if(I.blood_DNA)
+ msg += "It is holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
+ else
+ msg += "It is holding [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
//Braindead
if(!client && stat != DEAD)
msg += "The devil seems to be in deep contemplation.\n"
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 7cfefd5413..f985818b76 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -327,11 +327,8 @@
possible = list()
if(!voodoo_link)
return
- var/list/prints = voodoo_link.return_fingerprints()
- if(!length(prints))
- return FALSE
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
- if(prints[md5(H.dna.uni_identity)])
+ if(md5(H.dna.uni_identity) in voodoo_link.fingerprints)
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 922f37b270..caf12d4b86 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -43,6 +43,8 @@
var/blood_state = BLOOD_STATE_NOT_BLOODY
var/list/blood_smear = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
+ var/last_bloodtype = ""//used to track the last bloodtype to have graced these shoes; makes for better performing footprint shenanigans
+ var/last_blood_DNA = ""//same as last one
/obj/item/clothing/Initialize()
. = ..()
@@ -157,6 +159,11 @@
damaged_clothes = 0
cut_overlay(damaged_clothes_icons[index], TRUE)
+/obj/item/clothing/transfer_blood_dna(list/blood_dna)
+ ..()
+ if(blood_dna.len)
+ last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
+ last_blood_DNA = blood_dna[blood_dna.len]
/*
SEE_SELF // can see self, no matter what
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index 50bfeb1407..a661a978b0 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -11,15 +11,6 @@
strip_delay = 20
equip_delay_other = 40
-/obj/item/clothing/gloves/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
-
-/obj/item/clothing/gloves/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
- transfer_blood = 0
-
/obj/item/clothing/gloves/suicide_act(mob/living/carbon/user)
user.visible_message("\the [src] are forcing [user]'s hands around [user.p_their()] neck! It looks like the gloves are possessed!")
return OXYLOSS
@@ -29,9 +20,8 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves")
- IF_HAS_BLOOD_DNA(src)
- GET_COMPONENT(D, /datum/component/forensics)
- . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", color = D.blood_mix_color)
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", color = blood_DNA_to_color())
/obj/item/clothing/gloves/update_clothes_damaged_state(damaging = TRUE)
..()
diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm
index 591b6c1d3b..ccc167dcbc 100644
--- a/code/modules/clothing/head/_head.dm
+++ b/code/modules/clothing/head/_head.dm
@@ -46,9 +46,8 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet")
- IF_HAS_BLOOD_DNA(src)
- GET_COMPONENT(D, /datum/component/forensics)
- . += mutable_appearance('icons/effects/blood.dmi', "helmetblood", color = D.blood_DNA_to_color())
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "helmetblood", color = blood_DNA_to_color())
/obj/item/clothing/head/update_clothes_damaged_state(damaging = TRUE)
..()
diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm
index 13f3a81b99..ae4d324805 100644
--- a/code/modules/clothing/masks/_masks.dm
+++ b/code/modules/clothing/masks/_masks.dm
@@ -17,9 +17,8 @@
if(body_parts_covered & HEAD)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
- IF_HAS_BLOOD_DNA(src)
- GET_COMPONENT(D, /datum/component/forensics)
- . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = D.blood_mix_color)
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color())
/obj/item/clothing/mask/equipped(mob/user, slot)
..()
diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm
index 4179e69a45..ee63c137af 100644
--- a/code/modules/clothing/neck/_neck.dm
+++ b/code/modules/clothing/neck/_neck.dm
@@ -12,8 +12,8 @@
if(body_parts_covered & HEAD)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
- IF_HAS_BLOOD_DNA(src)
- . += mutable_appearance('icons/effects/blood.dmi', "maskblood")
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color())
/obj/item/clothing/neck/tie
name = "tie"
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 4aec17fafe..fb85d057b2 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -19,10 +19,6 @@
var/move_trail = /obj/effect/decal/cleanable/blood/footprints/tracks/shoe
-/obj/item/clothing/shoes/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
-
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
if(rand(2)>1)
user.visible_message("[user] begins tying \the [src] up waaay too tightly! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -46,7 +42,7 @@
. = list()
if(!isinhands)
var/bloody = FALSE
- IF_HAS_BLOOD_DNA(src)
+ if(blood_DNA)
bloody = TRUE
else
bloody = blood_smear[BLOOD_STATE_BLOOD]
@@ -55,9 +51,9 @@
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe")
if(bloody)
if(adjusted == NORMAL_STYLE)
- . += mutable_appearance('icons/effects/blood.dmi', "shoeblood", color = blood_color)
+ . += mutable_appearance('icons/effects/blood.dmi', "shoeblood", color = blood_DNA_to_color())
else
- . += mutable_appearance('modular_citadel/icons/mob/digishoes.dmi', "shoeblood", color = blood_color)
+ . += mutable_appearance('modular_citadel/icons/mob/digishoes.dmi', "shoeblood", color = blood_DNA_to_color())
/obj/item/clothing/shoes/equipped(mob/user, slot)
. = ..()
@@ -93,9 +89,8 @@
var/mob/M = loc
M.update_inv_shoes()
-/obj/item/clothing/shoes/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
+/obj/item/clothing/shoes/clean_blood()
+ ..()
blood_smear = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
blood_state = BLOOD_STATE_NOT_BLOODY
blood_color = null
diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm
index 3a3e5c3d84..74637cd22f 100644
--- a/code/modules/clothing/suits/_suits.dm
+++ b/code/modules/clothing/suits/_suits.dm
@@ -54,12 +54,11 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]")
- IF_HAS_BLOOD_DNA(src)
- GET_COMPONENT(D, /datum/component/forensics)
+ if(blood_DNA)
if(taurmode >= SNEK_TAURIC)
- . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood", color = D.blood_mix_color)
+ . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color())
else
- . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood", color = D.blood_mix_color)
+ . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color())
var/mob/living/carbon/human/M = loc
if(ishuman(M) && M.w_uniform)
var/obj/item/clothing/under/U = M.w_uniform
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index df5004a259..eda0e31e93 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -22,9 +22,8 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform")
- IF_HAS_BLOOD_DNA(src)
- GET_COMPONENT(D, /datum/component/forensics)
- . += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = D.blood_mix_color)
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = blood_DNA_to_color())
if(accessory_overlay)
. += accessory_overlay
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index 0b1d6807bf..d5584bc29f 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -1,121 +1,119 @@
//CONTAINS: Suit fibers and Detective's Scanning Computer
-/atom/proc/return_fingerprints()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.fingerprints
-
-/atom/proc/return_hiddenprints()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.hiddenprints
-
-/atom/proc/return_blood_DNA()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.blood_DNA
-
-/atom/proc/blood_DNA_length()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = length(D.blood_DNA)
-
-/atom/proc/return_fibers()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.fibers
-
-/atom/proc/return_blood_mix_types()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.blood_mix_types
-
-/atom/proc/return_blood_mix_color()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.blood_mix_color
-
-/atom/proc/add_fingerprint_list(list/fingerprints) //ASSOC LIST FINGERPRINT = FINGERPRINT
- if(length(fingerprints))
- . = AddComponent(/datum/component/forensics, fingerprints)
-
-//Set ignoregloves to add prints irrespective of the mob having gloves on.
-/atom/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
- var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
- . = D.add_fingerprint(M, ignoregloves)
-
-/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT
- if(length(fibertext))
- . = AddComponent(/datum/component/forensics, null, null, null, fibertext)
+/atom/var/list/suit_fibers
/atom/proc/add_fibers(mob/living/carbon/human/M)
- var/old = 0
- if(M.gloves && istype(M.gloves, /obj/item/clothing))
+ if(M.gloves && istype(M.gloves, /obj/item/clothing/))
var/obj/item/clothing/gloves/G = M.gloves
- old = length(G.return_blood_DNA())
if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
- if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody
+ if(add_blood(G.blood_DNA)) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
else if(M.bloody_hands > 1)
- old = length(M.return_blood_DNA())
- if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old)
+ if(add_blood(M.blood_DNA))
M.bloody_hands--
- var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
- . = D.add_fibers(M)
+ if(!suit_fibers)
+ suit_fibers = list()
+ var/fibertext
+ var/item_multiplier = isitem(src)?1.2:1
+ if(M.wear_suit)
+ fibertext = "Material from \a [M.wear_suit]."
+ if(prob(10*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += fibertext
+ if(!(M.wear_suit.body_parts_covered & CHEST))
+ if(M.w_uniform)
+ fibertext = "Fibers from \a [M.w_uniform]."
+ if(prob(12*item_multiplier) && !(fibertext in suit_fibers)) //Wearing a suit means less of the uniform exposed.
+ suit_fibers += fibertext
+ if(!(M.wear_suit.body_parts_covered & HANDS))
+ if(M.gloves)
+ fibertext = "Material from a pair of [M.gloves.name]."
+ if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += fibertext
+ else if(M.w_uniform)
+ fibertext = "Fibers from \a [M.w_uniform]."
+ if(prob(15*item_multiplier) && !(fibertext in suit_fibers))
+ // "Added fibertext: [fibertext]"
+ suit_fibers += fibertext
+ if(M.gloves)
+ fibertext = "Material from a pair of [M.gloves.name]."
+ if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += "Material from a pair of [M.gloves.name]."
+ else if(M.gloves)
+ fibertext = "Material from a pair of [M.gloves.name]."
+ if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += "Material from a pair of [M.gloves.name]."
-/atom/proc/add_hiddenprint_list(list/hiddenprints) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM
- if(length(hiddenprints))
- . = AddComponent(/datum/component/forensics, null, hiddenprints)
/atom/proc/add_hiddenprint(mob/living/M)
- var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
- . = D.add_hiddenprint(M)
+ if(!M || !M.key)
+ return
-/atom/proc/add_blood_DNA(list/dna) //ASSOC LIST DNA = BLOODTYPE
- return FALSE
+ if(!fingerprintshidden) //Add the list if it does not exist
+ fingerprintshidden = list()
-/obj/add_blood_DNA(list/dna)
- . = ..()
- if(length(dna))
- . = AddComponent(/datum/component/forensics, null, null, dna)
+ var/hasgloves = ""
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(H.gloves)
+ hasgloves = "(gloves)"
+
+ var/current_time = TIME_STAMP("hh:mm:ss", FALSE)
+ if(!fingerprintshidden[M.key])
+ fingerprintshidden[M.key] = "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]"
+ else
+ var/laststamppos = findtext(fingerprintshidden[M.key], " Last: ")
+ if(laststamppos)
+ fingerprintshidden[M.key] = copytext(fingerprintshidden[M.key], 1, laststamppos)
+ fingerprintshidden[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]"
+
+ fingerprintslast = M.ckey
+
+
+//Set ignoregloves to add prints irrespective of the mob having gloves on.
+/atom/proc/add_fingerprint(mob/living/M, ignoregloves = 0)
+ if(!M || !M.key)
+ return
+
+ add_hiddenprint(M)
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+
+ add_fibers(H)
+
+ if(H.gloves) //Check if the gloves (if any) hide fingerprints
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.transfer_prints)
+ ignoregloves = 1
+
+ if(!ignoregloves)
+ H.gloves.add_fingerprint(H, 1) //ignoregloves = 1 to avoid infinite loop.
+ return
+
+ if(!fingerprints) //Add the list if it does not exist
+ fingerprints = list()
+ var/full_print = md5(H.dna.uni_identity)
+ fingerprints[full_print] = full_print
-/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
- . = ..()
- transfer_blood = rand(2, 4)
-/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
- var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
- if(!B)
- B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
- B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
- return TRUE //we bloodied the floor
-/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
- if(wear_suit)
- wear_suit.add_blood_DNA(blood_dna)
- update_inv_wear_suit()
- else if(w_uniform)
- w_uniform.add_blood_DNA(blood_dna)
- update_inv_w_uniform()
- if(gloves)
- var/obj/item/clothing/gloves/G = gloves
- G.add_blood_DNA(blood_dna)
- else if(length(blood_dna))
- AddComponent(/datum/component/forensics, null, null, blood_dna)
- bloody_hands = rand(2, 4)
- if(head)
- head.add_blood_DNA(blood_dna)
- update_inv_head()
- else if(wear_mask)
- wear_mask.add_blood_DNA(blood_dna)
- update_inv_wear_mask()
- if(wear_neck)
- wear_neck.add_blood_DNA(blood_dna)
- update_inv_neck()
- update_inv_gloves() //handles bloody hands overlays and updating
- return TRUE
/atom/proc/transfer_fingerprints_to(atom/A)
- A.add_fingerprint_list(return_fingerprints())
- A.add_hiddenprint_list(return_hiddenprints())
- A.fingerprintslast = fingerprintslast
+
+ // Make sure everything are lists.
+ if(!islist(A.fingerprints))
+ A.fingerprints = list()
+ if(!islist(A.fingerprintshidden))
+ A.fingerprintshidden = list()
+
+ if(!islist(fingerprints))
+ fingerprints = list()
+ if(!islist(fingerprintshidden))
+ fingerprintshidden = list()
+
+ // Transfer
+ if(fingerprints)
+ A.fingerprints |= fingerprints.Copy() //detective
+ if(fingerprintshidden)
+ A.fingerprintshidden |= fingerprintshidden.Copy() //admin
+ A.fingerprintslast = fingerprintslast
\ No newline at end of file
diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm
index 9f1f2bf380..611001ecf9 100644
--- a/code/modules/detectivework/footprints_and_rag.dm
+++ b/code/modules/detectivework/footprints_and_rag.dm
@@ -1,10 +1,14 @@
/mob
var/bloody_hands = 0
+ var/bloody_feet = 0
/obj/item/clothing/gloves
var/transfer_blood = 0
+/obj/item/clothing/shoes
+ var/transfer_blood = 0
+
/obj/item/reagent_containers/glass/rag
name = "damp rag"
@@ -46,5 +50,6 @@
user.visible_message("[user] starts to wipe down [A] with [src]!", "You start to wipe down [A] with [src]...")
if(do_after(user,30, target = A))
user.visible_message("[user] finishes wiping off [A]!", "You finish wiping off [A].")
- SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ A.clean_blood()
+ A.wash_cream()
return
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index fd7591db81..eace1bf7b1 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -80,14 +80,20 @@
//Make our lists
var/list/fingerprints = list()
- var/list/blood = A.return_blood_DNA()
- var/list/fibers = A.return_fibers()
+ var/list/blood = list()
+ var/list/fibers = list()
var/list/reagents = list()
var/target_name = A.name
// Start gathering
+ if(A.blood_DNA && A.blood_DNA.len)
+ blood = A.blood_DNA.Copy()
+
+ if(A.suit_fibers && A.suit_fibers.len)
+ fibers = A.suit_fibers.Copy()
+
if(ishuman(A))
var/mob/living/carbon/human/H = A
@@ -96,7 +102,8 @@
else if(!ismob(A))
- fingerprints = A.return_fingerprints()
+ if(A.fingerprints && A.fingerprints.len)
+ fingerprints = A.fingerprints.Copy()
// Only get reagents from non-mobs.
if(A.reagents && A.reagents.reagent_list.len)
@@ -110,7 +117,6 @@
if(R.data["blood_DNA"] && R.data["blood_type"])
var/blood_DNA = R.data["blood_DNA"]
var/blood_type = R.data["blood_type"]
- LAZYINITLIST(blood)
blood[blood_DNA] = blood_type
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
@@ -119,7 +125,7 @@
add_log("[STATION_TIME_TIMESTAMP("hh:mm:ss")][get_timestamp()] - [target_name]", 0)
// Fingerprints
- if(length(fingerprints))
+ if(fingerprints && fingerprints.len)
sleep(30)
add_log("Prints:")
for(var/finger in fingerprints)
@@ -127,7 +133,7 @@
found_something = 1
// Blood
- if (length(blood))
+ if (blood && blood.len)
sleep(30)
add_log("Blood:")
found_something = 1
@@ -135,7 +141,7 @@
add_log("Type: [blood[B]] DNA: [B]")
//Fibers
- if(length(fibers))
+ if(fibers && fibers.len)
sleep(30)
add_log("Fibers:")
for(var/fiber in fibers)
@@ -143,7 +149,7 @@
found_something = 1
//Reagents
- if(length(reagents))
+ if(reagents && reagents.len)
sleep(30)
add_log("Reagents:")
for(var/R in reagents)
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index 86bf676f7e..fa6e12e6ce 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -287,7 +287,8 @@
drop.transfer_mob_blood_dna(src)
return
else
- temp_blood_DNA = drop.return_blood_DNA() //we transfer the dna from the drip to the splatter
+ temp_blood_DNA = list()
+ temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
qdel(drop)//the drip is replaced by a bigger splatter
else
drop = new(T, get_static_viruses())
@@ -303,9 +304,9 @@
B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
if(temp_blood_DNA)
if(isalien(src))
- B.add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ B.blood_DNA["UNKNOWN DNA"] = "X*"
else
- B.add_blood_DNA(temp_blood_DNA)
+ B.blood_DNA |= temp_blood_DNA
/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip)
if(!(NOBLOOD in dna.species.species_traits))
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index c42bd82797..a99776d03e 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -11,18 +11,21 @@
if (handcuffed)
msg += "[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!\n"
if (head)
- msg += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head. \n"
+ msg += "[t_He] [t_is] wearing [icon2html(head, user)] \a [src.head] on [t_his] head. \n"
if (wear_mask)
- msg += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_mask, user)] \a [src.wear_mask] on [t_his] face.\n"
if (wear_neck)
- msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_neck, user)] \a [src.wear_neck] around [t_his] neck.\n"
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
- msg += "[t_He] [t_is] holding [I.get_examine_string(user)] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
+ if(I.blood_DNA)
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n"
+ else
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
if (back)
- msg += "[t_He] [t_has] [back.get_examine_string(user)] on [t_his] back.\n"
+ msg += "[t_He] [t_has] [icon2html(back, user)] \a [src.back] on [t_his] back.\n"
var/appears_dead = 0
if (stat == DEAD)
appears_dead = 1
@@ -88,7 +91,7 @@
if(digitalcamo)
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly unsimian manner.\n"
-
+
if(combatmode)
msg += "[t_He] [t_is] visibly tense[resting ? "." : ", and [t_is] standing in combative stance."]\n"
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 26e19ff376..aa0c7283ef 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -37,30 +37,46 @@
if(U.attached_accessory)
accessory_msg += " with [icon2html(U.attached_accessory, user)] \a [U.attached_accessory]"
- msg += "[t_He] [t_is] wearing [w_uniform.get_examine_string(user)][accessory_msg].\n"
+ if(w_uniform.blood_DNA)
+ msg += "[t_He] [t_is] wearing [icon2html(w_uniform, user)] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name][accessory_msg]!\n"
+ else
+ msg += "[t_He] [t_is] wearing [icon2html(w_uniform, user)] \a [w_uniform][accessory_msg].\n"
//head
if(head)
- msg += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head.\n"
+ if(head.blood_DNA)
+ msg += "[t_He] [t_is] wearing [icon2html(head, user)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head!\n"
+ else
+ msg += "[t_He] [t_is] wearing [icon2html(head, user)] \a [head] on [t_his] head.\n"
//suit/armor
if(wear_suit)
- msg += "[t_He] [t_is] wearing [wear_suit.get_examine_string(user)].\n"
+ if(wear_suit.blood_DNA)
+ msg += "[t_He] [t_is] wearing [icon2html(wear_suit, user)] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]!\n"
+ else
+ msg += "[t_He] [t_is] wearing [icon2html(wear_suit, user)] \a [wear_suit].\n"
//suit/armor storage
- if(s_store)
- msg += "[t_He] [t_is] carrying [s_store.get_examine_string(user)] on [t_his] [wear_suit.name].\n"
+ if(s_store.blood_DNA)
+ msg += "[t_He] [t_is] carrying [icon2html(s_store, user)] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]!\n"
+ else
+ msg += "[t_He] [t_is] carrying [icon2html(s_store, user)] \a [s_store] on [t_his] [wear_suit.name].\n"
//back
if(back)
- msg += "[t_He] [t_has] [back.get_examine_string(user)] on [t_his] back.\n"
-
+ if(back.blood_DNA)
+ msg += "[t_He] [t_has] [icon2html(back, user)] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back.\n"
+ else
+ msg += "[t_He] [t_has] [icon2html(back, user)] \a [back] on [t_his] back.\n"
//Hands
for(var/obj/item/I in held_items)
- if(!(I.item_flags & ABSTRACT))
- msg += "[t_He] [t_is] holding [I.get_examine_string(user)] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
-
- GET_COMPONENT(FR, /datum/component/forensics)
+ if(I.blood_DNA)
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n"
+ else
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
//gloves
if(gloves && !(SLOT_GLOVES in obscured))
- msg += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands.\n"
- else if(FR && length(FR.blood_DNA))
+ if(gloves.blood_DNA)
+ msg += "[t_He] [t_has] [icon2html(gloves, user)] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands!\n"
+ else
+ msg += "[t_He] [t_has] [icon2html(gloves, user)] \a [gloves] on [t_his] hands.\n"
+ else if(blood_DNA)
var/hand_number = get_num_arms(FALSE)
if(hand_number)
msg += "[t_He] [t_has] [hand_number > 1 ? "" : "a"] blood-stained hand[hand_number > 1 ? "s" : ""]!\n"
@@ -76,33 +92,47 @@
//belt
if(belt)
- msg += "[t_He] [t_has] [belt.get_examine_string(user)] about [t_his] waist.\n"
+ if(belt.blood_DNA)
+ msg += "[t_He] [t_has] [icon2html(belt, user)] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist!\n"
+ else
+ msg += "[t_He] [t_has] [icon2html(belt, user)] \a [belt] about [t_his] waist.\n"
//shoes
if(shoes && !(SLOT_SHOES in obscured))
- msg += "[t_He] [t_is] wearing [shoes.get_examine_string(user)] on [t_his] feet.\n"
+ if(shoes.blood_DNA)
+ msg += "[t_He] [t_is] wearing [icon2html(shoes, user)] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet!\n"
+ else
+ msg += "[t_He] [t_is] wearing [icon2html(shoes, user)] \a [shoes] on [t_his] feet.\n"
//mask
if(wear_mask && !(SLOT_WEAR_MASK in obscured))
- msg += "[t_He] [t_has] [wear_mask.get_examine_string(user)] on [t_his] face.\n"
+ if(wear_mask.blood_DNA)
+ msg += "[t_He] [t_has] [icon2html(wear_mask, user)] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] on [t_his] face!\n"
+ else
+ msg += "[t_He] [t_has] [icon2html(wear_mask, user)] \a [wear_mask] on [t_his] face.\n"
- if (wear_neck && !(SLOT_NECK in obscured))
- msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
+ //neck
+ if(wear_neck && !(SLOT_NECK in obscured))
+ msg += "[t_He] [t_is] wearing [icon2html(wear_neck, user)] \a [src.wear_neck] around [t_his] neck.\n"
//eyes
if(!(SLOT_GLASSES in obscured))
if(glasses)
- msg += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes.\n"
+ if(glasses.blood_DNA)
+ msg += "[t_He] [t_has] [icon2html(glasses, user)] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes!\n"
+ else
+ msg += "[t_He] [t_has] [icon2html(glasses, user)] \a [glasses] covering [t_his] eyes.\n"
+
else if(eye_color == BLOODCULT_EYE && iscultist(src) && has_trait(CULT_EYES))
msg += "[t_His] eyes are glowing an unnatural red!\n"
//ears
if(ears && !(SLOT_EARS in obscured))
- msg += "[t_He] [t_has] [ears.get_examine_string(user)] on [t_his] ears.\n"
+ msg += "[t_He] [t_has] [icon2html(ears, user)] \a [ears] on [t_his] ears.\n"
//ID
if(wear_id)
- msg += "[t_He] [t_is] wearing [wear_id.get_examine_string(user)].\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_id, user)] \a [wear_id].\n"
//Status effects
msg += status_effect_examines()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 49d2722323..bbf77eb8b5 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -31,8 +31,6 @@
if(CONFIG_GET(flag/disable_stambuffer))
togglesprint()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
-
/mob/living/carbon/human/ComponentInitialize()
. = ..()
@@ -687,16 +685,22 @@
if(..())
dropItemToGround(I)
-/mob/living/carbon/human/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
- if(gloves)
- if(SEND_SIGNAL(gloves, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- update_inv_gloves()
+/mob/living/carbon/human/clean_blood()
+ var/mob/living/carbon/human/H = src
+ if(H.gloves)
+ if(H.gloves.clean_blood())
+ H.update_inv_gloves()
else
- if(bloody_hands)
- bloody_hands = 0
- update_inv_gloves()
+ ..() // Clear the Blood_DNA list
+ if(H.bloody_hands)
+ H.bloody_hands = 0
+ H.update_inv_gloves()
+ if(H.bloody_feet)
+ H.bloody_feet = 0
+ H.update_inv_shoes()
+ bloodiness = 0
+
+ update_icons() //apply the now updated overlays to the mob
/mob/living/carbon/human/wash_cream()
if(creamed) //clean both to prevent a rare bug
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 95139f75ee..1fe16b3a2e 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -45,6 +45,8 @@
var/bloodiness = 0
var/bloodinessmax = 5
+ var/last_bloodtype = ""//used to track the last bloodtype to have graced this filthy spaceman; makes for better performing footprint shenanigans
+ var/last_blood_DNA = ""//same as last one
var/blood_state = BLOOD_STATE_NOT_BLOODY
var/list/blood_smear = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
var/blood_color //For blood smearing stuff
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index dd37563f8f..1620b8eed9 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -147,3 +147,9 @@
return FALSE
return .
+
+/mob/living/carbon/human/transfer_blood_dna(list/blood_dna)
+ ..()
+ if(blood_dna.len)
+ last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
+ last_blood_DNA = blood_dna[blood_dna.len]
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index b2592ae157..024f2590e7 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -57,18 +57,20 @@
var/turf/T = get_turf(src)
if(S.blood_smear && S.blood_smear[S.blood_state])
var/obj/effect/decal/cleanable/blood/footprints/tracks/shoe/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints/tracks/shoe) in T
- if(oldFP && (oldFP.blood_state == S.blood_state && oldFP.color == S.blood_color))
+ if(oldFP && (oldFP.blood_state == S.blood_state && oldFP.color == bloodtype_to_color(S.last_bloodtype)))
return
- S.blood_smear[S.blood_state] = max(0, S.blood_smear[S.blood_state]-BLOOD_LOSS_PER_STEP)
- var/obj/effect/decal/cleanable/blood/footprints/tracks/shoe/FP = new /obj/effect/decal/cleanable/blood/footprints/tracks/shoe(T)
- FP.icon_state = FOOTPRINT_SHOE
- FP.print_state = FOOTPRINT_SHOE
- FP.blood_state = S.blood_state
- FP.blood_color = S.blood_color
- FP.entered_dirs |= dir
- FP.bloodiness = S.blood_smear[S.blood_state]
- FP.update_icon()
- update_inv_shoes()
+ S.blood_smear[S.blood_state] = max(0, S.blood_smear[S.blood_state]-BLOOD_LOSS_PER_STEP)
+ var/obj/effect/decal/cleanable/blood/footprints/tracks/shoe/FP = new /obj/effect/decal/cleanable/blood/footprints/tracks/shoe(T)
+ FP.icon_state = FOOTPRINT_SHOE
+ FP.print_state = FOOTPRINT_SHOE
+ FP.blood_state = S.blood_state
+ FP.entered_dirs |= dir
+ FP.bloodiness = S.blood_smear[S.blood_state]
+ if(S.last_blood_DNA && S.last_bloodtype)
+ FP.blood_DNA += list(S.last_blood_DNA = S.last_bloodtype)
+ //hacky as heck; we need to move the LAST entry to there, otherwise we mix all the blood
+ FP.update_icon()
+ update_inv_shoes()
//End bloody footprints
S.step_action()
@@ -80,27 +82,28 @@
var/step_print = dna.species.get_move_trail(src)
if(bloodiness && blood_smear[blood_state])
var/obj/effect/decal/cleanable/blood/footprints/tracks/oldFP = locate(step_print) in T
- if(oldFP && (oldFP.blood_state == blood_state && oldFP == dna.species.move_trail && oldFP.blood_color == blood_color))
+ if(oldFP && (oldFP.blood_state == blood_state && oldFP.color == bloodtype_to_color(last_bloodtype)))
return
- else
- var/obj/effect/decal/cleanable/blood/footprints/tracks/FP = new step_print(T)
- if(("taur" in dna.species.mutant_bodyparts) && (dna.features["taur"] != "None") && !lying)
- if(dna.features["taur"] in GLOB.noodle_taurs)
- FP.icon_state = FOOTPRINT_SNAKE
- FP.print_state = FOOTPRINT_SNAKE
- else if(dna.features["taur"] in GLOB.paw_taurs)
- FP.icon_state = FOOTPRINT_PAW
- FP.print_state = FOOTPRINT_PAW
- if(!dna.species.move_trail && !lying) //we're assuming people have their chosen snowflake on, so.
- FP.icon_state = FOOTPRINT_SHOE
- FP.print_state = FOOTPRINT_SHOE
+ var/obj/effect/decal/cleanable/blood/footprints/tracks/FP = new step_print(T)
+ if(("taur" in dna.species.mutant_bodyparts) && (dna.features["taur"] != "None") && !lying)
+ if(dna.features["taur"] in GLOB.noodle_taurs)
+ FP.icon_state = FOOTPRINT_SNAKE
+ FP.print_state = FOOTPRINT_SNAKE
+ else if(dna.features["taur"] in GLOB.paw_taurs)
+ FP.icon_state = FOOTPRINT_PAW
+ FP.print_state = FOOTPRINT_PAW
+ if(!dna.species.move_trail && !lying) //we're assuming people have their chosen snowflake on, so.
+ FP.icon_state = FOOTPRINT_SHOE
+ FP.print_state = FOOTPRINT_SHOE
- FP.add_blood_DNA(return_blood_DNA())
- FP.blood_color = blood_color
- FP.entered_dirs |= dir
- FP.bloodiness = blood_smear[blood_state]
- FP.update_icon()
- bloodiness--
+ FP.blood_state = blood_state
+ FP.entered_dirs |= dir
+ FP.bloodiness = blood_smear[blood_state]
+ if(last_blood_DNA && last_bloodtype)
+ FP.blood_DNA += list(last_blood_DNA = last_bloodtype)
+ //hacky as heck; we need to move the LAST entry to there, otherwise we mix all the blood
+ FP.update_icon()
+ bloodiness--
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(dna.species.space_move(src))
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index 41ab5eb79f..10a0bc9e5c 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -474,7 +474,8 @@
if(isturf(next))
if(bloodiness)
var/obj/effect/decal/cleanable/blood/footprints/tracks/wheels/B = new(loc)
- B.add_blood_DNA(return_blood_DNA())
+ if(blood_DNA && blood_DNA.len)
+ B.blood_DNA |= blood_DNA.Copy()
var/newdir = get_dir(next, loc)
if(newdir == dir)
B.setDir(newdir)
@@ -656,7 +657,8 @@
T.add_mob_blood(H)
var/list/blood_dna = H.get_blood_dna_list()
- add_blood_DNA(blood_dna)
+ if(blood_dna)
+ transfer_blood_dna(blood_dna)
bloodiness += 4
// player on mulebot attempted to move
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index cf3742fcc5..4a2e9232dd 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -169,15 +169,23 @@
//Hands
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
- msg += "It has [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n"
-
+ if(I.blood_DNA)
+ msg += "It has [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
+ else
+ msg += "It has [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
//Internal storage
if(internal_storage && !(internal_storage.item_flags & ABSTRACT))
- msg += "It is holding [internal_storage.get_examine_string(user)] in its internal storage.\n"
+ if(internal_storage.blood_DNA)
+ msg += "It is holding [icon2html(internal_storage, user)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!\n"
+ else
+ msg += "It is holding [icon2html(internal_storage, user)] \a [internal_storage] in its internal storage.\n"
//Cosmetic hat - provides no function other than looks
if(head && !(head.item_flags & ABSTRACT))
- msg += "It is wearing [head.get_examine_string(user)] on its head.\n"
+ if(head.blood_DNA)
+ msg += "It is wearing [icon2html(head, user)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on its head!\n"
+ else
+ msg += "It is wearing [icon2html(head, user)] \a [head] on its head.\n"
//Braindead
if(!client && stat != DEAD)
diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
index e7dbbda242..9e962f6afb 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
@@ -23,9 +23,15 @@
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
- msg += "It has [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n"
+ if(I.blood_DNA)
+ msg += "It has [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
+ else
+ msg += "It has [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
if(internal_storage && !(internal_storage.item_flags & ABSTRACT))
- msg += "It is holding [internal_storage.get_examine_string(user)] in its internal storage.\n"
+ if(internal_storage.blood_DNA)
+ msg += "It is holding [icon2html(internal_storage, user)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!\n"
+ else
+ msg += "It is holding [icon2html(internal_storage, user)] \a [internal_storage] in its internal storage.\n"
msg += "*---------*"
to_chat(user, msg)
else
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 3d92912f9c..253d92a57f 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -177,6 +177,6 @@
qdel(target)
return TRUE
var/atom/movable/M = target
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ M.clean_blood()
visible_message("[src] polishes \the [target].")
return TRUE
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 157cf1f03f..1f60f5cdb5 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -169,7 +169,7 @@
if(iscarbon(user))
var/mob/living/carbon/C = user
user_dna = C.dna
- B.add_blood_DNA(user_dna)
+ B.add_blood(user_dna)
var/datum/callback/gibspawner = CALLBACK(GLOBAL_PROC, /proc/spawn_atom_to_turf, /obj/effect/gibspawner/generic, B, 1, FALSE, list(user_dna))
B.throw_at(target, BRAINS_BLOWN_THROW_RANGE, BRAINS_BLOWN_THROW_SPEED, callback=gibspawner)
return(BRUTELOSS)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index efae090707..44185b601f 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -161,10 +161,19 @@
var/splatter_dir = dir
if(starting)
splatter_dir = get_dir(starting, target_loca)
- if(isalien(L))
+ var/obj/item/bodypart/B = L.get_bodypart(def_zone)
+ if(B.status == BODYPART_ROBOTIC) // So if you hit a robotic, it sparks instead of bloodspatters
+ do_sparks(2, FALSE, target.loc)
+ if(prob(25))
+ new /obj/effect/decal/cleanable/oil(target_loca)
+ else if(isalien(L))
new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target_loca, splatter_dir)
else
- new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir)
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color(H.dna.blood_type))
+ else
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color())
if(iscarbon(L))
var/mob/living/carbon/C = L
C.bleed(damage)
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index dfc6df537d..bba9e746be 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -19,27 +19,27 @@
var/turf/T = get_turf(target)
//section shamelessly copypasta'd from the clean component
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ clean_blood()//blood overlays get weird otherwise, because the sprite changes.
for(var/A in T)
if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/I = A
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ I.clean_blood()
if(ismob(I.loc))
var/mob/M = I.loc
M.regenerate_icons()
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.head.clean_blood()
if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.wear_suit.clean_blood()
else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.w_uniform.clean_blood()
if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.shoes.clean_blood()
+ cleaned_human.clean_blood()
cleaned_human.wash_cream()
cleaned_human.regenerate_icons()
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index d91b675e22..a4e56c9429 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -41,12 +41,12 @@
C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM)
if(reac_volume >= 10 && istype(L))
- L.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+ L.add_blood(list(data["blood_DNA"] = data["blood_type"]))
L.color = bloodtype_to_color(data["blood_type"])
/datum/reagent/blood/reaction_obj(obj/O, volume)
if(volume >= 3 && istype(O))
- O.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+ O.add_blood(list(data["blood_DNA"] = data["blood_type"]))
O.color = bloodtype_to_color(data["blood_type"])
/datum/reagent/blood/on_new(list/data)
@@ -1004,7 +1004,7 @@
/datum/reagent/iron/on_mob_life(mob/living/carbon/C)
if(C.blood_volume < BLOOD_VOLUME_NORMAL)
- C.blood_volume += 0.5
+ C.blood_volume += 0.01 //we'll have synthetics from medbay.
..()
/datum/reagent/iron/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
@@ -1128,12 +1128,12 @@
else
if(O)
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ O.clean_blood()
/datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 1)
T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ T.clean_blood()
for(var/obj/effect/decal/cleanable/C in T)
qdel(C)
@@ -1151,26 +1151,26 @@
H.lip_style = null
H.update_body()
for(var/obj/item/I in C.held_items)
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ I.clean_blood()
if(C.wear_mask)
- if(SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ if(C.clean_blood())
C.update_inv_wear_mask()
if(ishuman(M))
var/mob/living/carbon/human/H = C
if(H.head)
- if(SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ if(H.head.clean_blood())
H.update_inv_head()
if(H.wear_suit)
- if(SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ if(H.wear_suit.clean_blood())
H.update_inv_wear_suit()
else if(H.w_uniform)
- if(SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ if(H.w_uniform.clean_blood())
H.update_inv_w_uniform()
if(H.shoes)
- if(SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ if(H.shoes.clean_blood())
H.update_inv_shoes()
H.wash_cream()
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ M.clean_blood()
/datum/reagent/space_cleaner/ez_clean
name = "EZ Clean"
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index a710d127fb..d250dcff0e 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -48,7 +48,7 @@
/obj/item/reagent_containers/blood/random/Initialize()
icon_state = "bloodpack"
- blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L", "SY")
+ blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L", "SY", "HF", "GEL")
return ..()
/obj/item/reagent_containers/blood/APlus
@@ -78,6 +78,12 @@
/obj/item/reagent_containers/blood/synthetics
blood_type = "SY"
+/obj/item/reagent_containers/blood/oilblood
+ blood_type = "HF"
+
+/obj/item/reagent_containers/blood/jellyblood
+ blood_type = "GEL"
+
/obj/item/reagent_containers/blood/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon))
if(!user.is_literate())
diff --git a/icons/mob/dam_mob.dmi b/icons/mob/dam_mob.dmi
index fe92746b43..c34b57b434 100644
Binary files a/icons/mob/dam_mob.dmi and b/icons/mob/dam_mob.dmi differ
diff --git a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
index e6ba224f8d..c6e1a4cbbd 100644
--- a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
+++ b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
@@ -327,7 +327,7 @@
var/mob/M = loc
M.update_inv_hands()
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)//blood overlays get weird otherwise, because the sprite changes. (retained from original desword because I have no idea what this is)
+ clean_blood()//blood overlays get weird otherwise, because the sprite changes.
/obj/item/twohanded/hypereutactic/AltClick(mob/living/user)
if(!in_range(src, user)) //Basic checks to prevent abuse
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 0f71a71add..cb918da21f 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -4,7 +4,7 @@
else
if(O)
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ O.clean_blood()
/datum/reagent/syndicateadrenals
name = "Syndicate Adrenaline"
diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
index 1c857bf8a6..d81fc62d6c 100644
--- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
+++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
@@ -2,7 +2,7 @@
/datum/reagent/consumable/semen
name = "Semen"
id = "semen"
- description = "Sperm from some animal. Useless for anything but insemination, really."
+ description = "Sperm from some animal. I bet you'll drink this out of a bucket someday."
taste_description = "something salty"
taste_mult = 2 //Not very overpowering flavor
data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null)
@@ -21,7 +21,7 @@
S = new(T)
S.reagents.add_reagent("semen", reac_volume)
if(data["blood_DNA"])
- S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+ S.add_blood(list(data["blood_DNA"] = data["blood_type"]))
/obj/effect/decal/cleanable/semen
name = "semen"
@@ -36,10 +36,12 @@
/obj/effect/decal/cleanable/semen/New()
..()
dir = pick(1,2,4,8)
- add_blood_DNA(list("Non-human DNA" = "A+"))
+ add_blood(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S)
- S.add_blood_DNA(return_blood_DNA())
+ if (S.blood_DNA)
+ blood_DNA |= S.blood_DNA.Copy()
+ ..()
/datum/reagent/consumable/femcum
name = "Female Ejaculate"
@@ -67,10 +69,11 @@
/obj/effect/decal/cleanable/femcum/New()
..()
dir = pick(1,2,4,8)
- add_blood_DNA(list("Non-human DNA" = "A+"))
+ add_blood(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F)
- F.add_blood_DNA(return_blood_DNA())
+ if(F.blood_DNA)
+ blood_DNA |= F.blood_DNA.Copy()
..()
/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume)
@@ -84,7 +87,7 @@
S = new(T)
S.reagents.add_reagent("femcum", reac_volume)
if(data["blood_DNA"])
- S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+ S.add_blood(list(data["blood_DNA"] = data["blood_type"]))
//aphrodisiac & anaphrodisiac