diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 0ccc674cfc..07b53848cf 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -104,13 +104,6 @@ #define isgenital(A) (istype(A, /obj/item/organ/genital)) #define isborer(A) (istype(A, /mob/living/simple_animal/borer)) -#define isipcperson(A) (is_species(A, /datum/species/ipc)) -#define ismammal(A) (is_species(A, /datum/species/mammal)) -#define isavian(A) (is_species(A, /datum/species/avian)) -#define isaquatic(A) (is_species(A, /datum/species/aquatic)) -#define isinsect(A) (is_species(A, /datum/species/insect)) -#define isxenoperson(A) (is_species(A, /datum/species/xeno)) -#define isstartjelly(A) (is_species(A, /datum/species/jelly/roundstartslime)) #define CITADEL_MENTOR_OOC_COLOUR "#224724" diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm index 6049fd7918..c4db590e90 100644 --- a/code/__DEFINES/cleaning.dm +++ b/code/__DEFINES/cleaning.dm @@ -5,3 +5,8 @@ #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 new file mode 100644 index 0000000000..0cda5d997a --- /dev/null +++ b/code/__DEFINES/forensics.dm @@ -0,0 +1,2 @@ +#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)) \ No newline at end of file diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 8ff40c3ef9..ba6ffe12bd 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -60,6 +60,15 @@ #define ishumanbasic(A) (is_species(A, /datum/species/human)) #define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) ) +// Citadel specific species +#define isipcperson(A) (is_species(A, /datum/species/ipc)) +#define ismammal(A) (is_species(A, /datum/species/mammal)) +#define isavian(A) (is_species(A, /datum/species/avian)) +#define isaquatic(A) (is_species(A, /datum/species/aquatic)) +#define isinsect(A) (is_species(A, /datum/species/insect)) +#define isxenoperson(A) (is_species(A, /datum/species/xeno)) +#define isstartjelly(A) (is_species(A, /datum/species/jelly/roundstartslime)) + //more carbon mobs #define ismonkey(A) (istype(A, /mob/living/carbon/monkey)) @@ -175,6 +184,8 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list( #define iscameramob(A) (istype(A, /mob/camera)) +#define isaicamera(A) (istype(A, /mob/camera/aiEye)) + #define iseminence(A) (istype(A, /mob/camera/eminence)) //Footstep helpers diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 1a38e368c2..6b924ef207 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -183,6 +183,9 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) #define BLOOD_COLOR_SYNTHETIC "#3f48aa" #define BLOOD_COLOR_SLIME "#00ff90" #define BLOOD_COLOR_LIZARD "#db004D" +#define BLOOD_COLOR_UNIVERSAL "#db3300" +#define BLOOD_COLOR_BUG "#a37c0f" + //suit sensors: sensor_mode defines diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 77b79cf532..8683f75b08 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -94,72 +94,6 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors "Purple" = "#e300ff"//purple )) -GLOBAL_LIST_INIT(noodle_taurs, list( - "Naga", - "Tentacle" - )) - -GLOBAL_LIST_INIT(paw_taurs, list( - "Fox", - "Wolf", - "Otie", - "Drake", - "Lab", - "Shepherd", - "Husky", - "Eevee", - "Panther", - "Horse", - "Cow", - "Tiger" - )) - - //blood types -GLOBAL_LIST_INIT(regular_bloods,list( - "O-", - "O+", - "A-", - "A+", - "B-", - "B+", - "AB-", - "AB+" - )) - -GLOBAL_LIST_INIT(all_types_bloods,list( - "O-", - "O+", - "A-", - "A+", - "B-", - "B+", - "AB-", - "AB+", - "SY", - "X*", - "HF", - "L", - "U", - "GEL" - )) - -GLOBAL_LIST_INIT(blood_types, list( - "blood", - "syntheticblood", - "xenoblood", - "oilblood", - "jellyblood" - )) - -GLOBAL_LIST_INIT(blood_id_types, list( - "blood" = /datum/reagent/blood, - "syntheticblood" = /datum/reagent/blood/synthetics, - "xenoblood" = /datum/reagent/blood/xenomorph, - "oilblood" = /datum/reagent/blood/oil, - "jellyblood" = /datum/reagent/blood/jellyblood - )) - - //Crew objective and miscreants stuff GLOBAL_VAR_INIT(miscreants_allowed, FALSE) diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index c883254afe..5143cc3028 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -58,3 +58,70 @@ GLOBAL_LIST_EMPTY(latejoiners) //CIT CHANGE - All latejoining people, for traito for(var/i in GLOB.mob_list) var/mob/M = i M.update_config_movespeed() + +GLOBAL_LIST_INIT(noodle_taurs, list( + "Naga", + "Tentacle" + )) + +GLOBAL_LIST_INIT(paw_taurs, list( + "Fox", + "Wolf", + "Otie", + "Drake", + "Lab", + "Shepherd", + "Husky", + "Eevee", + "Panther", + "Horse", + "Cow", + "Tiger" + )) + + //blood types +GLOBAL_LIST_INIT(regular_bloods,list( + "O-", + "O+", + "A-", + "A+", + "B-", + "B+", + "AB-", + "AB+" + )) + +GLOBAL_LIST_INIT(all_types_bloods,list( + "O-", + "O+", + "A-", + "A+", + "B-", + "B+", + "AB-", + "AB+", + "SY", + "X*", + "HF", + "L", + "U", + "GEL", + "BUG" + )) + +GLOBAL_LIST_INIT(blood_types, list( + "blood", + "syntheticblood", + "xenoblood", + "oilblood", + "jellyblood" + )) + +GLOBAL_LIST_INIT(blood_id_types, list( + "blood" = /datum/reagent/blood, + "syntheticblood" = /datum/reagent/blood/synthetics, + "xenoblood" = /datum/reagent/blood/xenomorph, + "oilblood" = /datum/reagent/blood/oil, + "jellyblood" = /datum/reagent/blood/jellyblood + )) + diff --git a/code/datums/components/cleaning.dm b/code/datums/components/cleaning.dm index 08ac57b79a..0cb0fce7b9 100644 --- a/code/datums/components/cleaning.dm +++ b/code/datums/components/cleaning.dm @@ -12,28 +12,28 @@ if(!isturf(tile)) return - tile.clean_blood() + SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) for(var/A in tile) if(is_cleanable(A)) qdel(A) - 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 + 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 M.regenerate_icons() else if(ishuman(A)) var/mob/living/carbon/human/cleaned_human = A if(cleaned_human.lying) if(cleaned_human.head) - cleaned_human.head.clean_blood() + SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) if(cleaned_human.wear_suit) - cleaned_human.wear_suit.clean_blood() + SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) else if(cleaned_human.w_uniform) - cleaned_human.w_uniform.clean_blood() + SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) if(cleaned_human.shoes) - cleaned_human.shoes.clean_blood() - cleaned_human.clean_blood() + 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.wash_cream() cleaned_human.regenerate_icons() - to_chat(cleaned_human, "[AM] cleans your face!") + to_chat(cleaned_human, "[AM] cleans your face!") \ No newline at end of file diff --git a/code/datums/components/decals/blood.dm b/code/datums/components/decals/blood.dm new file mode 100644 index 0000000000..47c7fb8228 --- /dev/null +++ b/code/datums/components/decals/blood.dm @@ -0,0 +1,37 @@ +/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/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)) + + I.blood_overlay = image(blood_splatter_icon) + I.blood_overlay.color = I.blood_DNA_to_color() + I.add_overlay(I.blood_overlay) + + 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 diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm new file mode 100644 index 0000000000..cd3cbbd8c1 --- /dev/null +++ b/code/datums/components/forensics.dm @@ -0,0 +1,184 @@ +/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 + +/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 + check_blood() + return ..() + +/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + fingerprints = new_fingerprints + hiddenprints = new_hiddenprints + blood_DNA = new_blood_DNA + fibers = new_fibers + check_blood() + +/datum/component/forensics/RegisterWithParent() + check_blood() + RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act) + +/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 + if(isitem(parent)) + qdel(parent.GetComponent(/datum/component/decal/blood)) + 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(!isliving(M)) + if(!iscameramob(M)) + return + if(isaicamera(M)) + var/mob/camera/aiEye/ai_camera = M + if(!ai_camera.ai) + return + M = ai_camera.ai + 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/M) + if(!isliving(M)) + if(!iscameramob(M)) + return + if(isaicamera(M)) + var/mob/camera/aiEye/ai_camera = M + if(!ai_camera.ai) + return + M = ai_camera.ai + if(!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) + for(var/i in dna) + blood_DNA[i] = dna[i] + check_blood() + return TRUE + +/datum/component/forensics/proc/check_blood() + if(!isitem(parent)) + return + if(!length(blood_DNA)) + return + parent.LoadComponent(/datum/component/decal/blood) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 8d04ff246a..33e92e4de5 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -303,14 +303,6 @@ if(!dna.species) var/rando_race = pick(GLOB.roundstart_races) dna.species = new rando_race() - if(isjellyperson(dna.species)) - dna.blood_type = "GEL" - if(isipcperson(dna.species)) - dna.blood_type = "HF" - if(isxenoperson(dna.species)) - dna.blood_type = "X*" - if(islizard(dna.species)) - dna.blood_type = "L" //proc used to update the mob's appearance after its dna UI has been changed /mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 71e06abd15..a740edacfc 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -37,9 +37,6 @@ 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 @@ -248,22 +245,24 @@ return TRUE return FALSE -/atom/proc/examine(mob/user) - //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]!" +/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("") - to_chat(user, "[icon2html(src, user)] That's [f_name]") +///Generate the full examine string of this atom (including icon for goonchat) +/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)].") 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(reagents.reagents_holder_flags & TRANSPARENT) @@ -285,6 +284,8 @@ 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 @@ -349,24 +350,12 @@ var/new_blood_dna = L.get_blood_dna_list() if(!new_blood_dna) return FALSE - 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) + var/old_length = blood_DNA_length() + add_blood(new_blood_dna) + if(blood_DNA_length() == 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() @@ -374,101 +363,6 @@ return FALSE 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_overlay = image(blood_splatter_icon) - blood_overlay.color = blood_DNA_to_color() - add_overlay(blood_overlay) - -/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 27faa6bffb..94d3e2f499 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -247,8 +247,7 @@ 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 - I.clean_blood() - I.fingerprints = list() + SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG) var/datum/component/radioactive/contamination = I.GetComponent(/datum/component/radioactive) if(contamination) qdel(contamination) @@ -419,4 +418,4 @@ if(I) I.forceMove(loc) . = TRUE - update_icon() + update_icon() \ No newline at end of file diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 2ff7ee1a13..e117c680ca 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -11,6 +11,10 @@ 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.") @@ -55,8 +59,7 @@ M.Translate(rand(-3, 3), rand(-1, 3)) animate(src, transform=M, time=2) -/obj/machinery/washing_machine/clean_blood() - ..() +/obj/machinery/washing_machine/proc/clean_blood() if(!busy) bloody_mess = FALSE update_icon() @@ -64,7 +67,7 @@ /obj/machinery/washing_machine/proc/wash_cycle() for(var/X in contents) var/atom/movable/AM = X - AM.clean_blood() + SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) AM.machine_wash(src) busy = FALSE @@ -92,12 +95,6 @@ var/obj/item/toy/crayon/CR = WM.color_source add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY) -/obj/item/reagents_containers/rag/towel/machine_wash(obj/machinery/washing_machine/WM) - if(WM.color_source) - if(istype(WM.color_source, /obj/item/toy/crayon)) - var/obj/item/toy/crayon/CR = WM.color_source - add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY) - /mob/living/simple_animal/pet/dog/corgi/machine_wash(obj/machinery/washing_machine/WM) gib() @@ -274,4 +271,4 @@ ..() density = TRUE //because machinery/open_machine() sets it to 0 color_source = null - has_corgi = 0 + has_corgi = 0 \ No newline at end of file diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 6746c41f0b..a56f45a712 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -1,8 +1,7 @@ - /obj/effect/decal/cleanable gender = PLURAL layer = ABOVE_NORMAL_TURF_LAYER - var/list/random_icon_states = list() + var/list/random_icon_states = null var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one? @@ -26,9 +25,9 @@ if(LAZYLEN(diseases_to_add)) AddComponent(/datum/component/infective, diseases_to_add) -/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) +/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal if(mergeable_decal) - qdel(C) + return TRUE /obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks)) @@ -70,9 +69,10 @@ //Add "bloodiness" of this blood's type, to the human's shoes //This is on /cleanable because fuck this ancient mess /obj/effect/decal/cleanable/Crossed(atom/movable/O) + ..() if(ishuman(O)) var/mob/living/carbon/human/H = O - if(H.shoes && blood_state && bloodiness && (!HAS_TRAIT(H,TRAIT_LIGHT_STEP) || !H.mind.assigned_role == "Detective")) + if(H.shoes && blood_state && bloodiness && !HAS_TRAIT(H, TRAIT_LIGHT_STEP)) var/obj/item/clothing/shoes/S = H.shoes var/add_blood = 0 if(bloodiness >= BLOOD_GAIN_PER_STEP) @@ -81,8 +81,7 @@ add_blood = bloodiness bloodiness -= add_blood S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS,S.bloody_shoes[blood_state]+add_blood) - if(blood_DNA && blood_DNA.len) - S.add_blood(blood_DNA) + S.add_blood(return_blood_DNA()) S.blood_state = blood_state update_icon() H.update_inv_shoes() diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index e6edc7661a..3a9f851e4c 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -3,17 +3,17 @@ name = "xeno blood" desc = "It's green and acidic. It looks like... blood?" color = BLOOD_COLOR_XENO - blood_DNA = list("UNKNOWN DNA" = "X*") /obj/effect/decal/cleanable/blood/splatter/xeno color = BLOOD_COLOR_XENO /obj/effect/decal/cleanable/blood/gibs/xeno color = BLOOD_COLOR_XENO + gibs_reagent_id = "liquidxenogibs" + gibs_bloodtype = "X*" /obj/effect/decal/cleanable/blood/gibs/xeno/Initialize(mapload, list/datum/disease/diseases) . = ..() - reagents.add_reagent("liquidxenogibs", 5) update_icon() /obj/effect/decal/cleanable/blood/gibs/xeno/update_icon() @@ -35,7 +35,7 @@ if(infective) diseases = infective.diseases var/obj/effect/decal/cleanable/blood/splatter/xeno/splat = new /obj/effect/decal/cleanable/blood/splatter/xeno(loc, diseases) - splat.transfer_blood_dna(blood_DNA) + splat.add_blood(return_blood_DNA()) if(!step_to(src, get_step(src, direction), 0)) break diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm index c7df4e4ecf..73c89b4db5 100644 --- a/code/game/objects/effects/decals/cleanable/gibs.dm +++ b/code/game/objects/effects/decals/cleanable/gibs.dm @@ -6,11 +6,17 @@ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") mergeable_decal = FALSE var/body_colors = "#e3ba84" //a default color just in case. + var/gibs_reagent_id = "liquidgibs" + var/gibs_bloodtype = "A+" /obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases) . = ..() if(random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0) icon_state = pick(random_icon_states) + if(gibs_reagent_id) + reagents.add_reagent(gibs_reagent_id, 5) + if(gibs_bloodtype) + add_blood(list("Non-human DNA" = gibs_bloodtype)) update_icon() @@ -51,7 +57,7 @@ if(infective) diseases = infective.diseases var/obj/effect/decal/cleanable/blood/splatter/splat = new /obj/effect/decal/cleanable/blood/splatter(loc, diseases) - splat.transfer_blood_dna(blood_DNA) + splat.add_blood(return_blood_DNA()) if(!step_to(src, get_step(src, direction), 0)) break @@ -81,9 +87,8 @@ /obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases) . = ..() - setDir(pick(1,2,4,8)) + setDir(pick(GLOB.cardinals)) icon_state += "-old" - add_blood(list("Non-human DNA" = "A+")) update_icon() /obj/effect/decal/cleanable/blood/drip @@ -101,9 +106,6 @@ /obj/effect/decal/cleanable/blood/gibs/human/Initialize(mapload, list/datum/disease/diseases) . = ..() - reagents.add_reagent("liquidgibs", 5) - if(!blood_DNA.len) - add_blood(list("Non-human DNA" = "A+")) update_icon() /obj/effect/decal/cleanable/blood/gibs/human/up @@ -128,12 +130,11 @@ //Lizards /obj/effect/decal/cleanable/blood/gibs/human/lizard body_colors = "117720" + gibs_reagent_id = "liquidgibs" + gibs_bloodtype = "L" /obj/effect/decal/cleanable/blood/gibs/human/lizard/Initialize(mapload, list/datum/disease/diseases) . = ..() - reagents.add_reagent("liquidgibs", 5) - if(!blood_DNA.len) - add_blood(list("Non-human DNA" = "L")) update_icon() /obj/effect/decal/cleanable/blood/gibs/human/lizard/up @@ -157,12 +158,11 @@ // Slime Gibs /obj/effect/decal/cleanable/blood/gibs/slime desc = "They look gooey and gruesome." + gibs_reagent_id = "liquidslimegibs" + gibs_bloodtype = "GEL" /obj/effect/decal/cleanable/blood/gibs/slime/Initialize(mapload, list/datum/disease/diseases) . = ..() - reagents.add_reagent("liquidslimegibs", 5) - if(!blood_DNA.len) - add_blood(list("Non-human DNA" = "GEL")) update_icon() /obj/effect/decal/cleanable/blood/gibs/slime/update_icon() @@ -197,21 +197,22 @@ /obj/effect/decal/cleanable/blood/gibs/synth desc = "They look sludgy and disgusting." + gibs_reagent_id = "liquidsyntheticgibs" + gibs_bloodtype = "SY" /obj/effect/decal/cleanable/blood/gibs/synth/Initialize(mapload, list/datum/disease/diseases) . = ..() - reagents.add_reagent("liquidsyntheticgibs", 5) + update_icon() //IPCs /obj/effect/decal/cleanable/blood/gibs/ipc desc = "They look sharp yet oozing." body_colors = "00ff00" + gibs_reagent_id = "liquidoilgibs" + gibs_bloodtype = "HF" /obj/effect/decal/cleanable/blood/gibs/ipc/Initialize(mapload, list/datum/disease/diseases) . = ..() - reagents.add_reagent("liquidoilgibs", 5) - if(!blood_DNA.len) - add_blood(list("Non-human DNA" = "HF")) update_icon() /obj/effect/decal/cleanable/blood/gibs/ipc/update_icon() diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 8b582587fe..ceb41dee5c 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -4,16 +4,17 @@ 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 bloodiness = MAX_SHOE_BLOODINESS color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere. /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) - if (C.blood_DNA) - blood_DNA |= C.blood_DNA.Copy() + C.add_blood(return_blood_DNA()) + if (bloodiness) + if (C.bloodiness < MAX_SHOE_BLOODINESS) + C.bloodiness += bloodiness update_icon() - ..() + return ..() /obj/effect/decal/cleanable/blood/transfer_blood_dna() ..() @@ -50,7 +51,6 @@ desc = "Your instincts say you shouldn't be following these." random_icon_states = null var/list/existing_dirs = list() - blood_DNA = list() /obj/effect/decal/cleanable/trail_holder/update_icon() color = blood_DNA_to_color() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 22daea7b56..229d8fcb3a 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -541,17 +541,6 @@ 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 e371ae7d40..1d302b409e 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) - target.clean_blood() + SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) target.wash_cream() return diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index 65246aefa4..7524fc9007 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)) - A.clean_blood() + SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) 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 9b714b7b15..a4b0740c1c 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 as obj) - blood_DNA = from.blood_DNA - fingerprints = from.fingerprints - fingerprintshidden = from.fingerprintshidden +/obj/item/stack/proc/copy_evidences(obj/item/stack/from) + add_blood(from.return_blood_DNA()) + add_fingerprint_list(from.return_fingerprints()) + add_hiddenprint_list(from.return_hiddenprints()) fingerprintslast = from.fingerprintslast //TODO bloody overlay @@ -436,4 +436,4 @@ /datum/stack_recipe_list/New(title, recipes) src.title = title - src.recipes = recipes + src.recipes = recipes \ No newline at end of file diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 34b3c90d07..80b68213aa 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -346,7 +346,7 @@ icon_state = "dualsaber[item_color][wielded]" else icon_state = "dualsaber0" - clean_blood()//blood overlays get weird otherwise, because the sprite changes. + SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) /obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user) if(user.has_dna()) @@ -881,4 +881,4 @@ var/client/C = user.client C.change_view(CONFIG_GET(string/default_view)) user.client.pixel_x = 0 - user.client.pixel_y = 0 + user.client.pixel_y = 0 \ No newline at end of file diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 61aa776f01..ea2bbb0dcd 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) - . = O.clean_blood() + . = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK) 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 - tile.clean_blood() + SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK) 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) - L.clean_blood() + SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK) 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) - H.clean_blood() + SEND_SIGNAL(H, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_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) - M.clean_blood() + SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) else - L.clean_blood() + SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_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 - user.clean_blood() + SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) /obj/structure/sink/attackby(obj/item/O, mob/living/user, params) if(busy) @@ -554,7 +554,7 @@ busy = FALSE return 1 busy = FALSE - O.clean_blood() + SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) O.acid_level = 0 create_reagents(5) reagents.add_reagent(dispensedreagent, 5) @@ -675,4 +675,4 @@ else playsound(loc, 'sound/weapons/tap.ogg', 50, 1) if(BURN) - playsound(loc, 'sound/items/welder.ogg', 80, 1) + playsound(loc, 'sound/items/welder.ogg', 80, 1) \ No newline at end of file diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 62cd626d5d..f6d234b346 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -250,7 +250,7 @@ for(var/mob/living/simple_animal/slime/M in src) M.apply_water() - clean_blood() + SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK) 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 d595428378..1df81a797b 100644 --- a/code/modules/antagonists/devil/true_devil/_true_devil.dm +++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm @@ -69,10 +69,8 @@ //Left hand items for(var/obj/item/I in held_items) if(!(I.item_flags & ABSTRACT)) - 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" + msg += "It is holding [I.get_examine_string(user)] 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 3a5564cf05..08e00ea0f4 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -327,8 +327,11 @@ 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(md5(H.dna.uni_identity) in voodoo_link.fingerprints) + if(prints[md5(H.dna.uni_identity)]) possible |= H /obj/item/voodoo/proc/GiveHint(mob/victim,force=0) diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 2932912ed7..0ae04c1f7a 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -12,6 +12,15 @@ 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 @@ -21,7 +30,7 @@ if(!isinhands) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves") - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) . += 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 ccc167dcbc..98bb3aec13 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -46,7 +46,7 @@ if(!isinhands) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet") - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) . += 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 c00e6f72e0..362ab9b3bd 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -59,7 +59,7 @@ if(body_parts_covered & HEAD) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask") - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color()) /obj/item/clothing/mask/update_clothes_damaged_state(damaging = TRUE) diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 2356bb16eb..0bb7c8ebfd 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -12,7 +12,7 @@ if(body_parts_covered & HEAD) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask") - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color()) /obj/item/clothing/neck/tie diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index d6927f9953..04c5644fb5 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -10,18 +10,22 @@ permeability_coefficient = 0.5 slowdown = SHOES_SLOWDOWN - var/offset = 0 - var/equipped_before_drop = FALSE - var/blood_state = BLOOD_STATE_NOT_BLOODY var/list/bloody_shoes = 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 + var/offset = 0 + var/equipped_before_drop = FALSE //CITADEL EDIT Enables digitigrade shoe styles var/adjusted = NORMAL_STYLE mutantrace_variation = MUTANTRACE_VARIATION + 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/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!") @@ -45,7 +49,7 @@ . = list() if(!isinhands) var/bloody = FALSE - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) bloody = TRUE else bloody = bloody_shoes[BLOOD_STATE_BLOOD] @@ -92,11 +96,11 @@ var/mob/M = loc M.update_inv_shoes() -/obj/item/clothing/shoes/clean_blood() - ..() +/obj/item/clothing/shoes/proc/clean_blood(datum/source, strength) + if(strength < CLEAN_STRENGTH_BLOOD) + return bloody_shoes = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) blood_state = BLOOD_STATE_NOT_BLOODY - blood_color = null if(ismob(loc)) var/mob/M = loc M.update_inv_shoes() diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 2ad1bba042..86d473ca7b 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -53,11 +53,11 @@ if(!isinhands) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]") - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) if(taurmode >= SNEK_TAURIC) - . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color()) + . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood") else - . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color()) + . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood") 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 eda0e31e93..5f123cd745 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -22,7 +22,7 @@ if(!isinhands) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform") - if(blood_DNA) + IF_HAS_BLOOD_DNA(src) . += 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 d5584bc29f..8451019efb 100644 --- a/code/modules/detectivework/detective_work.dm +++ b/code/modules/detectivework/detective_work.dm @@ -1,119 +1,146 @@ //CONTAINS: Suit fibers and Detective's Scanning Computer -/atom/var/list/suit_fibers +/atom/proc/return_fingerprints() + GET_COMPONENT(D, /datum/component/forensics) + if(D) + . = D.fingerprints -/atom/proc/add_fibers(mob/living/carbon/human/M) - if(M.gloves && istype(M.gloves, /obj/item/clothing/)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects - 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) - if(add_blood(M.blood_DNA)) - M.bloody_hands-- - 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/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/add_hiddenprint(mob/living/M) - if(!M || !M.key) - return +/atom/proc/blood_DNA_length() + GET_COMPONENT(D, /datum/component/forensics) + if(D) + . = length(D.blood_DNA) - if(!fingerprintshidden) //Add the list if it does not exist - fingerprintshidden = list() - - 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 +/atom/proc/return_fibers() + GET_COMPONENT(D, /datum/component/forensics) + if(D) + . = D.fibers +/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 = 0) - if(!M || !M.key) - return +/atom/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE) + var/datum/component/forensics/D = AddComponent(/datum/component/forensics) + . = D.add_fingerprint(M, ignoregloves) - add_hiddenprint(M) +/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT + if(length(fibertext)) + . = AddComponent(/datum/component/forensics, null, null, null, fibertext) - if(ishuman(M)) - var/mob/living/carbon/human/H = M +/atom/proc/add_fibers(mob/living/carbon/human/M) + var/old = 0 + 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(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //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(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old) + M.bloody_hands-- + var/datum/component/forensics/D = AddComponent(/datum/component/forensics) + . = D.add_fibers(M) - add_fibers(H) +/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) - 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 +/atom/proc/add_hiddenprint(mob/living/M) + var/datum/component/forensics/D = AddComponent(/datum/component/forensics) + . = D.add_hiddenprint(M) - if(!ignoregloves) - H.gloves.add_fingerprint(H, 1) //ignoregloves = 1 to avoid infinite loop. - return +/atom/proc/add_blood(list/dna) //ASSOC LIST DNA = BLOODTYPE + return FALSE - 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/add_blood(list/dna) + . = ..() + if(length(dna)) + . = AddComponent(/datum/component/forensics, null, null, dna) +/obj/item/clothing/gloves/add_blood(list/blood_dna, list/datum/disease/diseases) + . = ..() + transfer_blood = rand(2, 4) +/turf/add_blood(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(blood_dna) //give blood info to the blood decal. + return TRUE //we bloodied the floor +/mob/living/carbon/human/add_blood(list/blood_dna, list/datum/disease/diseases) + 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 if(length(blood_dna)) + AddComponent(/datum/component/forensics, null, null, blood_dna) + bloody_hands = rand(2, 4) + if(head) + head.add_blood(blood_dna) + update_inv_head() + else if(wear_mask) + wear_mask.add_blood(blood_dna) + update_inv_wear_mask() + if(wear_neck) + wear_neck.add_blood(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() +//to add blood dna info to the object's blood_DNA list +/atom/proc/transfer_blood_dna(list/blood_dna) + var/list/dna = blood_DNA_length() + if(!dna) + dna = list() + var/old_length = dna.len + dna |= blood_dna + if(dna.len > old_length) + return TRUE//some new blood DNA was added - if(!islist(fingerprints)) - fingerprints = list() - if(!islist(fingerprintshidden)) - fingerprintshidden = list() +/atom/proc/blood_DNA_to_color() //handles RGB colorings of blood + var/list/dna = blood_DNA_length() + var/list/colors = list()//first we make a list of all bloodtypes present + for(var/bloop in dna) + if(colors[dna[bloop]]) + colors[dna[bloop]]++ + else + colors[dna[bloop]] = 1 - // Transfer - if(fingerprints) - A.fingerprints |= fingerprints.Copy() //detective - if(fingerprintshidden) - A.fingerprintshidden |= fingerprintshidden.Copy() //admin - A.fingerprintslast = fingerprintslast \ No newline at end of file + var/final_rgb = BLOOD_COLOR_HUMAN + + 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 diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index eace1bf7b1..5940c3328d 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -80,20 +80,14 @@ //Make our lists var/list/fingerprints = list() - var/list/blood = list() - var/list/fibers = list() + var/list/blood = A.return_blood_DNA() + var/list/fibers = A.return_fibers() 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 @@ -102,8 +96,7 @@ else if(!ismob(A)) - if(A.fingerprints && A.fingerprints.len) - fingerprints = A.fingerprints.Copy() + fingerprints = A.return_fingerprints() // Only get reagents from non-mobs. if(A.reagents && A.reagents.reagent_list.len) @@ -117,6 +110,7 @@ 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. @@ -125,7 +119,7 @@ add_log("[STATION_TIME_TIMESTAMP("hh:mm:ss")][get_timestamp()] - [target_name]", 0) // Fingerprints - if(fingerprints && fingerprints.len) + if(length(fingerprints)) sleep(30) add_log("Prints:") for(var/finger in fingerprints) @@ -133,7 +127,7 @@ found_something = 1 // Blood - if (blood && blood.len) + if (length(blood)) sleep(30) add_log("Blood:") found_something = 1 @@ -141,7 +135,7 @@ add_log("Type: [blood[B]] DNA: [B]") //Fibers - if(fibers && fibers.len) + if(length(fibers)) sleep(30) add_log("Fibers:") for(var/fiber in fibers) @@ -149,7 +143,7 @@ found_something = 1 //Reagents - if(reagents && reagents.len) + if(length(reagents)) sleep(30) add_log("Reagents:") for(var/R in reagents) @@ -213,4 +207,4 @@ return to_chat(user, "Scanner Report") for(var/iterLog in log) - to_chat(user, iterLog) + to_chat(user, iterLog) \ No newline at end of file diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 9191f627e5..dbe0e31d3b 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -160,7 +160,7 @@ C.reagents.add_reagent("bonehurtingjuice", amount * 0.5) else C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAXIMUM) - return 1 + return 1 C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAXIMUM) return 1 @@ -232,12 +232,7 @@ return "blood" /mob/living/carbon/get_blood_id() - var/mob/living/carbon/C = src - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(H.dna.species.exotic_blood) - return H.dna.species.exotic_blood - if(dna.species.exotic_blood) + if(dna?.species?.exotic_blood) return dna.species.exotic_blood else if((NOBLOOD in dna.species.species_traits) || (HAS_TRAIT(src, TRAIT_NOCLONE))) return @@ -290,8 +285,7 @@ drop.transfer_mob_blood_dna(src) return else - temp_blood_DNA = list() - temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter + temp_blood_DNA = drop.return_blood_DNA() //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()) @@ -307,9 +301,9 @@ B.transfer_mob_blood_dna(src) //give blood info to the blood decal. if(temp_blood_DNA) if(isalien(src)) - B.blood_DNA["UNKNOWN DNA"] = "X*" + B.add_blood(list("UNKNOWN DNA" = "X*")) else - B.blood_DNA |= temp_blood_DNA + B.add_blood(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/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 9a39d5bc7d..1b2944c1f6 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -24,14 +24,8 @@ if(!stored_dna.species) var/rando_race = pick(GLOB.roundstart_races) stored_dna.species = new rando_race() - if(isjellyperson(stored_dna.species)) - stored_dna.blood_type = "GEL" - if(isipcperson(stored_dna.species)) - stored_dna.blood_type = "HF" - if(isxenoperson(stored_dna.species)) - stored_dna.blood_type = "X*" - if(islizard(stored_dna.species)) - stored_dna.blood_type = "L" + if(stored_dna.species.exotic_bloodtype) + stored_dna.blood_type = stored_dna.species.exotic_bloodtype /mob/living/brain/Destroy() if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting. diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index efdd1a96c5..22da46346c 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -11,21 +11,18 @@ if (handcuffed) msg += "[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!\n" if (head) - msg += "[t_He] [t_is] wearing [icon2html(head, user)] \a [src.head] on [t_his] head. \n" + msg += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head. \n" if (wear_mask) - msg += "[t_He] [t_is] wearing [icon2html(wear_mask, user)] \a [src.wear_mask] on [t_his] face.\n" + msg += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face.\n" if (wear_neck) - msg += "[t_He] [t_is] wearing [icon2html(wear_neck, user)] \a [src.wear_neck] around [t_his] neck.\n" + msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n" for(var/obj/item/I in held_items) if(!(I.item_flags & ABSTRACT)) - 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" + 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 (back) - msg += "[t_He] [t_has] [icon2html(back, user)] \a [src.back] on [t_his] back.\n" + msg += "[t_He] [t_has] [back.get_examine_string(user)] on [t_his] back.\n" var/appears_dead = 0 if (stat == DEAD) appears_dead = 1 diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 0a34b02e4b..632281bb23 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/human/examine(mob/user) //User is the person being examined +/mob/living/carbon/human/examine(mob/user) //this is very slightly better than it was because you can use it more places. still can't do \his[src] though. var/t_He = p_they(TRUE) var/t_His = p_their(TRUE) @@ -37,47 +37,30 @@ if(U.attached_accessory) accessory_msg += " with [icon2html(U.attached_accessory, user)] \a [U.attached_accessory]" - 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" + msg += "[t_He] [t_is] wearing [w_uniform.get_examine_string(user)][accessory_msg].\n" //head if(head) - 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" + msg += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head.\n" //suit/armor if(wear_suit) - 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/armour storage - if(s_store) - 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" + msg += "[t_He] [t_is] wearing [wear_suit.get_examine_string(user)].\n" + //suit/armor storage + if(s_store && !(SLOT_S_STORE in obscured)) + msg += "[t_He] [t_is] carrying [s_store.get_examine_string(user)] on [t_his] [wear_suit.name].\n" //back if(back) - 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" + msg += "[t_He] [t_has] [back.get_examine_string(user)] on [t_his] back.\n" + //Hands for(var/obj/item/I in held_items) - 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(!(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" + + var/datum/component/forensics/FR = GetComponent(/datum/component/forensics) //gloves if(gloves && !(SLOT_GLOVES in obscured)) - 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) + msg += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands.\n" + else if(FR && length(FR.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" @@ -93,47 +76,33 @@ //belt if(belt) - 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" + msg += "[t_He] [t_has] [belt.get_examine_string(user)] about [t_his] waist.\n" //shoes if(shoes && !(SLOT_SHOES in obscured)) - 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" + msg += "[t_He] [t_is] wearing [shoes.get_examine_string(user)] on [t_his] feet.\n" //mask if(wear_mask && !(SLOT_WEAR_MASK in obscured)) - 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" + msg += "[t_He] [t_has] [wear_mask.get_examine_string(user)] on [t_his] face.\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" + msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n" //eyes if(!(SLOT_GLASSES in obscured)) if(glasses) - 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" - + msg += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes.\n" else if(eye_color == BLOODCULT_EYE && iscultist(src) && HAS_TRAIT(src, 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] [icon2html(ears, user)] \a [ears] on [t_his] ears.\n" + msg += "[t_He] [t_has] [ears.get_examine_string(user)] on [t_his] ears.\n" //ID if(wear_id) - msg += "[t_He] [t_is] wearing [icon2html(wear_id, user)] \a [wear_id].\n" + msg += "[t_He] [t_is] wearing [wear_id.get_examine_string(user)].\n" //Status effects msg += status_effect_examines() @@ -183,7 +152,7 @@ var/temp = getBruteLoss() //no need to calculate each of these twice - msg += "" + msg += "" //Everything below gets this span var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) var/list/disabled = list() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index daf5917f87..f6d06c2d07 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -32,6 +32,8 @@ 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,21 +689,16 @@ if(..()) dropItemToGround(I) -/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() +/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() else - ..() // 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()*/ - - update_icons() //apply the now updated overlays to the mob + if(bloody_hands) + bloody_hands = 0 + update_inv_gloves() /mob/living/carbon/human/wash_cream() if(creamed) //clean both to prevent a rare bug @@ -1069,4 +1066,4 @@ race = /datum/species/zombie/infectious /mob/living/carbon/human/species/zombie/krokodil_addict - race = /datum/species/krokodil_addict + race = /datum/species/krokodil_addict \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index f03b75cf11..d0b90387f7 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -64,9 +64,7 @@ FP.blood_state = S.blood_state FP.entered_dirs |= dir FP.bloodiness = S.bloody_shoes[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.add_blood(S.return_blood_DNA()) FP.update_icon() update_inv_shoes() //End bloody footprints diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 73149c422d..caa3a0bcf9 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -269,16 +269,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) regenerate_organs(C,old_species) if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype) - if(isjellyperson(C)) - C.dna.blood_type = "GEL" - if(isipcperson(C)) - C.dna.blood_type = "HF" - if(isxenoperson(C)) - C.dna.blood_type = "X*" - if(islizard(C)) - C.dna.blood_type = "L" - else - C.dna.blood_type = exotic_bloodtype + C.dna.blood_type = exotic_bloodtype if(old_species.mutanthands) for(var/obj/item/I in C.held_items) @@ -319,16 +310,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) /datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) if(C.dna.species.exotic_bloodtype) - if(isjellyperson(C)) - C.dna.blood_type = "GEL" - if(isipcperson(C)) - C.dna.blood_type = "HF" - if(isxenoperson(C)) - C.dna.blood_type = "X*" - if(islizard(C)) - C.dna.blood_type = "L" - else - C.dna.blood_type = random_blood_type() + C.dna.blood_type = random_blood_type() if(DIGITIGRADE in species_traits) C.Digitigrade_Leg_Swap(TRUE) for(var/X in inherent_traits) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 55a6357e02..17b58fd461 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -474,8 +474,7 @@ if(isturf(next)) if(bloodiness) var/obj/effect/decal/cleanable/blood/tracks/B = new(loc) - if(blood_DNA && blood_DNA.len) - B.blood_DNA |= blood_DNA.Copy() + B.add_blood(return_blood_DNA()) var/newdir = get_dir(next, loc) if(newdir == dir) B.setDir(newdir) @@ -488,7 +487,6 @@ B.setDir(newdir) bloodiness-- - var/oldloc = loc var/moved = step_towards(src, next) // attempt to move if(cell) @@ -657,8 +655,7 @@ T.add_mob_blood(H) var/list/blood_dna = H.get_blood_dna_list() - if(blood_dna) - transfer_blood_dna(blood_dna) + add_blood(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 a27a3ab4ed..49bbe31ad3 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -37,7 +37,6 @@ gender = NEUTER mob_biotypes = list(MOB_ROBOTIC) speak_emote = list("chirps") - speech_span = SPAN_ROBOT bubble_icon = "machine" initial_language_holder = /datum/language_holder/drone mob_size = MOB_SIZE_SMALL @@ -93,7 +92,7 @@ var/obj/item/I = new default_hatmask(src) equip_to_slot_or_del(I, SLOT_HEAD) - ADD_TRAIT(access_card, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) + access_card.item_flags |= TRAIT_NODROP alert_drones(DRONE_NET_CONNECT) @@ -170,23 +169,15 @@ //Hands for(var/obj/item/I in held_items) if(!(I.item_flags & ABSTRACT)) - 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" + msg += "It has [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n" + //Internal storage if(internal_storage && !(internal_storage.item_flags & ABSTRACT)) - 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 += "It is holding [internal_storage.get_examine_string(user)] in its internal storage.\n" //Cosmetic hat - provides no function other than looks if(head && !(head.item_flags & ABSTRACT)) - 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" + msg += "It is wearing [head.get_examine_string(user)] on its head.\n" //Braindead if(!client && stat != DEAD) @@ -281,4 +272,4 @@ return 1 /mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE) - return 0 //So they don't die trying to fix wiring + return 0 //So they don't die trying to fix wiring \ No newline at end of file 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 9e962f6afb..28a7dd057a 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -23,15 +23,9 @@ for(var/obj/item/I in held_items) if(!(I.item_flags & ABSTRACT)) - 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" + msg += "It has [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n" if(internal_storage && !(internal_storage.item_flags & ABSTRACT)) - 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 += "It is holding [internal_storage.get_examine_string(user)] in its internal storage.\n" msg += "*---------*" to_chat(user, msg) else @@ -90,4 +84,4 @@ /mob/living/simple_animal/hostile/guardian/dextrous/regenerate_icons() ..() - update_inv_internal_storage() + update_inv_internal_storage() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 253d92a57f..d33fa6334f 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 - M.clean_blood() + SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) visible_message("[src] polishes \the [target].") - return TRUE + return TRUE \ No newline at end of file diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 9e5c9c26c4..bfdcafb95b 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -491,7 +491,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp . = BLOOD_COLOR_HUMAN switch(type) if("U")//Universal blood; a bit orange - . = "#db3300" + . = BLOOD_COLOR_UNIVERSAL if("SY")//Synthetics blood; blue . = BLOOD_COLOR_SYNTHETIC if("L")//lizard, a bit pink/purple @@ -502,6 +502,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp . = BLOOD_COLOR_OIL if("GEL")// slimepeople blood, rgb 0, 255, 144 . = BLOOD_COLOR_SLIME - if("BUG") - . = "#a37c0f" + if("BUG")// yellowish, like, y'know bug guts I guess. + . = BLOOD_COLOR_BUG //add more stuff to the switch if you have more blood colors for different types + // the defines are in _DEFINES/misc.dm diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm index bba9e746be..33e090844e 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 - clean_blood()//blood overlays get weird otherwise, because the sprite changes. + SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) for(var/A in T) if(is_cleanable(A)) qdel(A) else if(istype(A, /obj/item)) var/obj/item/I = A - I.clean_blood() + SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_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) - cleaned_human.head.clean_blood() + SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) if(cleaned_human.wear_suit) - cleaned_human.wear_suit.clean_blood() + SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) else if(cleaned_human.w_uniform) - cleaned_human.w_uniform.clean_blood() + SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) if(cleaned_human.shoes) - cleaned_human.shoes.clean_blood() - cleaned_human.clean_blood() + 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.wash_cream() cleaned_human.regenerate_icons() @@ -57,4 +57,4 @@ /obj/item/projectile/bullet/incendiary/c46x30mm name = "4.6x30mm incendiary bullet" damage = 10 - fire_stacks = 1 + fire_stacks = 1 \ No newline at end of file diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 7bb5acff72..7163d9db13 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -216,7 +216,7 @@ color = BLOOD_COLOR_OIL taste_description = "chunky burnt oil" data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null) - pH = 9.75 + pH = 9.75 /datum/reagent/vaccine //data must contain virus type @@ -738,11 +738,11 @@ mutationtext = "The pain subsides. You feel... attracted to dark, moist areas." /datum/reagent/mutationtoxin/xenoperson - name = "Xeno Mutation Toxin" + name = "Xeno-Hybrid Mutation Toxin" id = "xenopersonmutationtoxin" description = "A glowing toxin." color = "#5EFF3B" //RGB: 94, 255, 59 - race = /datum/species/xenoperson + race = /datum/species/xeno mutationtext = "The pain subsides. You feel... oddly longing for the Queen." //sadly, not the British one. //BLACKLISTED RACES @@ -1241,12 +1241,12 @@ else if(O) O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - O.clean_blood() + SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) /datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume) if(reac_volume >= 1) T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - T.clean_blood() + SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) for(var/obj/effect/decal/cleanable/C in T) qdel(C) @@ -1264,26 +1264,26 @@ H.lip_style = null H.update_body() for(var/obj/item/I in C.held_items) - I.clean_blood() + SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) if(C.wear_mask) - if(C.clean_blood()) + if(SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)) C.update_inv_wear_mask() if(ishuman(M)) var/mob/living/carbon/human/H = C if(H.head) - if(H.head.clean_blood()) + if(SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)) H.update_inv_head() if(H.wear_suit) - if(H.wear_suit.clean_blood()) + if(SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)) H.update_inv_wear_suit() else if(H.w_uniform) - if(H.w_uniform.clean_blood()) + if(SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)) H.update_inv_w_uniform() if(H.shoes) - if(H.shoes.clean_blood()) + if(SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)) H.update_inv_shoes() H.wash_cream() - M.clean_blood() + SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) /datum/reagent/space_cleaner/ez_clean name = "EZ Clean" 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 65301454fa..68ab229f0a 100644 --- a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm +++ b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm @@ -298,7 +298,7 @@ var/mob/M = loc M.update_inv_hands() - clean_blood()//blood overlays get weird otherwise, because the sprite changes. + 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) /obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user) if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked) 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 d218f76310..c8ebde11d9 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1,11 +1,3 @@ -/datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume) - if(istype(O, /obj/effect/decal/cleanable) || istype(O, /obj/item/projectile/bullet/reusable/foam_dart) || istype(O, /obj/item/ammo_casing/caseless/foam_dart)) - qdel(O) - else - if(O) - O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - O.clean_blood() - /datum/reagent/syndicateadrenals name = "Syndicate Adrenaline" id = "syndicateadrenals" diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index 680f7a3408..437a794f98 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -39,9 +39,8 @@ add_blood(list("Non-human DNA" = "A+")) /obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S) - if (S.blood_DNA) - blood_DNA |= S.blood_DNA.Copy() - ..() + S.add_blood(return_blood_DNA()) + return ..() /datum/reagent/consumable/femcum name = "Female Ejaculate" @@ -73,9 +72,8 @@ add_blood(list("Non-human DNA" = "A+")) /obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F) - if(F.blood_DNA) - blood_DNA |= F.blood_DNA.Copy() - ..() + F.add_blood(return_blood_DNA()) + return ..() /datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) if(!istype(T)) diff --git a/tgstation.dme b/tgstation.dme index a7031883dc..9a03e5838d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -46,6 +46,7 @@ #include "code\__DEFINES\flags.dm" #include "code\__DEFINES\food.dm" #include "code\__DEFINES\footsteps.dm" +#include "code\__DEFINES\forensics.dm" #include "code\__DEFINES\hud.dm" #include "code\__DEFINES\integrated_electronics.dm" #include "code\__DEFINES\interaction_flags.dm" @@ -351,6 +352,7 @@ #include "code\datums\components\empprotection.dm" #include "code\datums\components\footstep.dm" #include "code\datums\components\forced_gravity.dm" +#include "code\datums\components\forensics.dm" #include "code\datums\components\infective.dm" #include "code\datums\components\jousting.dm" #include "code\datums\components\knockoff.dm" @@ -378,6 +380,7 @@ #include "code\datums\components\uplink.dm" #include "code\datums\components\wearertargeting.dm" #include "code\datums\components\wet_floor.dm" +#include "code\datums\components\decals\blood.dm" #include "code\datums\components\storage\storage.dm" #include "code\datums\components\storage\concrete\_concrete.dm" #include "code\datums\components\storage\concrete\bag_of_holding.dm"