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