diff --git a/baystation12.dme b/baystation12.dme index 870226bfa50..3535be05090 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -968,6 +968,7 @@ #include "code\modules\research\server.dm" #include "code\WorkInProgress\AI_Visibility.dm" #include "code\WorkInProgress\buildmode.dm" +#include "code\WorkInProgress\detective_work.dm" #include "code\WorkInProgress\explosion_particles.dm" #include "code\WorkInProgress\mapload\dmm_suite.dm" #include "code\WorkInProgress\mapload\reader.dm" diff --git a/code/WorkInProgress/detective_work.dm b/code/WorkInProgress/detective_work.dm new file mode 100644 index 00000000000..e74ba63c4a3 --- /dev/null +++ b/code/WorkInProgress/detective_work.dm @@ -0,0 +1,330 @@ +//gloves w_uniform wear_suit shoes + +atom/var/list/suit_fibers + +atom/proc/add_fibers(mob/living/carbon/human/M) + if(M.gloves) + if(M.gloves.transfer_blood) + if(add_blood(M.gloves.bloody_hands_mob)) + M.gloves.transfer_blood-- + //world.log << "[M.gloves] added blood to [src] from [M.gloves.bloody_hands_mob]" + else if(M.bloody_hands) + if(add_blood(M.bloody_hands_mob)) + M.bloody_hands-- + //world.log << "[M] added blood to [src] from [M.bloody_hands_mob]" + if(!suit_fibers) suit_fibers = list() + var/fibertext + var/item_multiplier = istype(src,/obj/item)?1.2:1 + if(M.wear_suit) + fibertext = "Material from \a [M.wear_suit]." + if(prob(10*item_multiplier) && !(fibertext in suit_fibers)) + //world.log << "Added fibertext: [fibertext]" + suit_fibers += fibertext + if(!(M.wear_suit.body_parts_covered & 32)) + 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. + //world.log << "Added fibertext: [fibertext]" + suit_fibers += fibertext + if(!(M.wear_suit.body_parts_covered & 64)) + if(M.gloves) + fibertext = "Material from a pair of [M.gloves.name]." + if(prob(20*item_multiplier) && !(fibertext in suit_fibers)) + //world.log << "Added fibertext: [fibertext]" + 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)) + //world.log << "Added fibertext: [fibertext]" + 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)) + //world.log << "Added fibertext: [fibertext]" + suit_fibers += "Material from a pair of [M.gloves.name]." + if(!suit_fibers.len) del suit_fibers + + +obj/machinery/computer/forensic_scanning + name = "High-Res Forensic Scanning Computer" + icon_state = "forensic" + var/obj/item/scanning + var/temp = "" + var/canclear = 1 + var/authenticated = 0 + + var/scan_data = "" + var/scan_name = "" + var/scan_process = 0 + + req_access = list(access_forensics_lockers) + + attack_ai(mob/user) + return attack_hand(user) + + attack_hand(mob/user) + if(..()) + return + user.machine = src + var/dat = "" + var/isai = 0 + if(istype(usr,/mob/living/silicon)) + isai = 1 + if(temp) + dat += "[temp]

" + if(canclear) dat += "{Clear Screen}" + else + if(!authenticated) + dat += "{Log In}" + else + dat += "{Log Out}


" + if(scanning) + if(scan_process) + dat += "Scan Object: {[scanning.name]}
" + dat += "{Cancel Scan} {Print}

" + else + if(isai) dat += "Scan Object: {[scanning.name]}
" + else dat += "Scan Object: {[scanning.name]}
" + dat += "{Scan} {Print}

" + else + if(isai) dat += "{No Object Inserted}
" + else dat += "{No Object Inserted}
" + dat += "{Scan} {Print}

" + dat += "[scan_data]" + if(scan_data && !scan_process) + dat += "
{Erase Data}" + user << browse(dat,"window=scanner") + onclose(user,"scanner") + ex_act() + return + Topic(href,href_list) + switch(href_list["operation"]) + if("login") + var/mob/M = usr + if(istype(M,/mob/living/silicon)) + authenticated = 1 + updateDialog() + return + var/obj/item/weapon/card/id/I = M.equipped() + if (I && istype(I)) + if(src.check_access(I)) + authenticated = 1 + //usr << "\green Access Granted" + //if(!authenticated) + //usr << "\red Access Denied" + if("logout") + authenticated = 0 + if("clear") + if(canclear) + temp = null + if("eject") + if(scanning) + scanning.loc = loc + scanning = null + else + temp = "Eject Failed: No Object" + if("insert") + var/mob/M = usr + var/obj/item/I = M.equipped() + if(I && istype(I)) + scanning = I + M.drop_item() + I.loc = src + else + temp = "Invalid Object Rejected." + if("scan") + if(scanning) + scan_process = 3 + scan_data = "Scanning [scanning]: 25% complete" + updateDialog() + sleep(50) + if(!scan_process) + scan_data = null + updateDialog() + return + scan_data = "Scanning [scanning]: 50% complete" + updateDialog() + scan_process = 2 + sleep(50) + if(!scan_process) + scan_data = null + updateDialog() + return + scan_data = "Scanning [scanning]: 75% complete" + updateDialog() + scan_process = 1 + sleep(50) + if(!scan_process) + scan_data = null + updateDialog() + return + scan_process = 0 + scan_name = scanning.name + scan_data = "[scanning]

" + if (scanning.blood_DNA) + scan_data += "Blood Found:
" + scan_data += "-Blood type: [scanning.blood_type]\nDNA: [scanning.blood_DNA]

" + else + scan_data += "No Blood Found

" + if (!( scanning.fingerprints )) + scan_data += "No Fingerprints Found

" + else + var/list/L = params2list(scanning.fingerprints) + scan_data += "Isolated [L.len] Fingerprints:
" + for(var/i in L) + scan_data += "#[L.Find(i)] - [i]
" + scan_data += "
" + + if(!scanning.suit_fibers) + if(istype(scanning,/obj/item/device/detective_scanner)) + var/obj/item/device/detective_scanner/scanner = scanning + if(scanner.stored_name) + scan_data += "Fibers/Materials Data - [scanner.stored_name]:
" + for(var/data in scanner.stored_fibers) + scan_data += "- [data]
" + else + scan_data += "No Fibers/Materials Data
" + else + scan_data += "No Fibers/Materials Located
" + else + if(istype(scanning,/obj/item/device/detective_scanner)) + var/obj/item/device/detective_scanner/scanner = scanning + if(scanner.stored_name) + scan_data += "Fibers/Materials Data - [scanner.stored_name]:
" + for(var/data in scanner.stored_fibers) + scan_data += "- [data]
" + else + scan_data += "No Fibers/Materials Data
" + + scan_data += "Fibers/Materials Found:
" + for(var/data in scanning.suit_fibers) + scan_data += "- [data]
" + else + temp = "Scan Failed: No Object" + + + if("print") + if(scan_data) + temp = "Scan Data Printed." + var/obj/item/weapon/paper/P = new(loc) + P.name = "Scan Data ([scan_name])" + P.info = "[scan_data]" + else + temp = "Print Failed: No Data" + if("erase") + scan_data = "" + if("cancel") + scan_process = 0 + updateUsrDialog() + + detective + icon_state = "old" + name = "PowerScan Mk.I" + +obj/item/clothing/shoes/var + track_blood = 0 + mob/living/carbon/human/track_blood_mob +mob/var + bloody_hands = 0 + mob/living/carbon/human/bloody_hands_mob + track_blood + mob/living/carbon/human/track_blood_mob +obj/item/clothing/gloves/var + transfer_blood = 0 + mob/living/carbon/human/bloody_hands_mob +/* +obj/decal/cleanable/blood/var/track_amt = 3 + + +turf/Exited(mob/living/carbon/human/M) + if(istype(M,/mob/living)) + if(!istype(src, /turf/space)) // Bloody tracks code starts here + if(M.track_blood > 0) + M.track_blood-- + src.add_bloody_footprints(M.track_blood_mob,1,M.dir,get_tracks(M)) + else if(istype(M,/mob/living/carbon/human)) + if(M.shoes) + if(M.shoes.track_blood > 0) + M.shoes.track_blood-- + src.add_bloody_footprints(M.shoes.track_blood_mob,1,M.dir,M.shoes.name) // And bloody tracks end here + . = ..() +turf/Entered(mob/living/carbon/human/M) + if(istype(M,/mob/living)) + if(M.track_blood > 0) + M.track_blood-- + src.add_bloody_footprints(M.track_blood_mob,0,M.dir,get_tracks(M)) + else if(istype(M,/mob/living/carbon/human)) + if(M.shoes && !istype(src,/turf/space)) + if(M.shoes.track_blood > 0) + M.shoes.track_blood-- + src.add_bloody_footprints(M.shoes.track_blood_mob,0,M.dir,M.shoes.name) + + for(var/obj/decal/cleanable/blood/B in src) + if(B.track_amt <= 0) continue + if(B.type != /obj/decal/cleanable/blood/tracks && B.type != /obj/decal/cleanable/blood/drip) + if(istype(M,/mob/living/carbon/human)) + if(M.shoes) + M.shoes.add_blood(B.blood_owner) + M.shoes.track_blood_mob = B.blood_owner + M.shoes.track_blood = max(M.shoes.track_blood,8) + else + M.add_blood(B.blood_owner) + M.track_blood_mob = B.blood_owner + M.track_blood = max(M.track_blood,8) + B.track_amt-- + break + . = ..() + +turf/proc/add_bloody_footprints(mob/living/carbon/human/M,leaving,d,info) + for(var/obj/decal/cleanable/blood/tracks/T in src) + if(T.dir == d) + if((leaving && T.icon_state == "steps2") || (!leaving && T.icon_state == "steps1")) + T.desc = "These bloody footprints appear to have been made by [info]." + if(istype(M,/mob/living/carbon/human)) + T.blood_DNA = M.dna.unique_enzymes + T.blood_type = M.b_type + return + var/obj/decal/cleanable/blood/tracks/this = new(src) + if(leaving) + this.icon_state = "steps2" + else + this.icon_state = "steps1" + this.dir = d + this.desc = "These bloody footprints appear to have been made by [info]." + if(istype(M,/mob/living/carbon/human)) + this.blood_DNA = M.dna.unique_enzymes + this.blood_type = M.b_type + +proc/get_tracks(mob/M) + if(istype(M,/mob/living)) + if(istype(M,/mob/living/carbon/human)) + . = "human feet" + else if(istype(M,/mob/living/carbon/monkey)) + . = "monkey paws" + else if(istype(M,/mob/living/silicon/robot)) + . = "robot feet" + else + . = "an unknown creature" + +proc/blood_incompatible(donor,receiver) + var + donor_antigen = copytext(donor,1,2) + receiver_antigen = copytext(receiver,1,2) + donor_rh = findtext("+",donor) + receiver_rh = findtext("+",receiver) + if(donor_rh && !receiver_rh) return 1 + switch(receiver_antigen) + if("A") + if(donor_antigen != "A" && donor_antigen != "O") return 1 + if("B") + if(donor_antigen != "B" && donor_antigen != "O") return 1 + if("O") + if(donor_antigen != "O") return 1 + //AB is a universal receiver. + return 0 +*/ \ No newline at end of file diff --git a/code/game/atom_procs.dm b/code/game/atom_procs.dm index 52521e8ebad..bc2deaf3dc0 100644 --- a/code/game/atom_procs.dm +++ b/code/game/atom_procs.dm @@ -81,6 +81,7 @@ /atom/proc/add_fingerprint(mob/living/M as mob) if(isnull(M)) return if(isnull(M.key)) return + add_fibers(M) if (!( src.flags ) & 256) return if (ishuman(M)) diff --git a/code/game/objects/devices/scanners.dm b/code/game/objects/devices/scanners.dm index e0241beb40d..0e0216f7267 100644 --- a/code/game/objects/devices/scanners.dm +++ b/code/game/objects/devices/scanners.dm @@ -65,6 +65,8 @@ MASS SPECTROMETER icon_state = "forensic0" var/amount = 20.0 var/printing = 0.0 + var/list/stored_fibers = null + var/stored_name = null w_class = 3.0 item_state = "electronic" flags = FPRINT | TABLEPASS | ONBELT | CONDUCT | USEDELAY diff --git a/maps/tgstation.2.0.8.dmm b/maps/tgstation.2.0.8.dmm index c7e3f86bf98..6aca44d0e4e 100644 --- a/maps/tgstation.2.0.8.dmm +++ b/maps/tgstation.2.0.8.dmm @@ -769,7 +769,7 @@ "aoO" = (/turf/simulated/floor{dir = 10; icon_state = "carpetside"},/area/security/detectives_office) "aoP" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = "Streight"},/turf/simulated/floor{icon_state = "carpetside"},/area/security/detectives_office) "aoQ" = (/turf/simulated/floor{dir = 6; icon_state = "carpetside"},/area/security/detectives_office) -"aoR" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) +"aoR" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/computer/forensic_scanning,/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) "aoS" = (/obj/structure/closet/lawcloset,/obj/item/device/radio/intercom{name = "Station Intercom (General)"; pixel_y = -29},/turf/simulated/floor{icon_state = "wood"},/area/lawoffice) "aoT" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/turf/simulated/floor{icon_state = "wood"},/area/lawoffice) "aoU" = (/obj/structure/stool/chair,/obj/effect/landmark/start{name = "Lawyer"},/turf/simulated/floor{icon_state = "wood"},/area/lawoffice)