Initial commit of detective console rewrite.

Changed forensic data to use record datum instead of unreadable arrays.
Now handheld scanner transfers data by clicking the big console, not by scan.
Rewrote high res scanner console. Now it leaves compiling dossiers to player, via use of filters.
This commit is contained in:
Chinsky
2014-08-18 19:41:11 +04:00
parent 68fc5d91c6
commit b43759fee9
5 changed files with 477 additions and 801 deletions

View File

@@ -1,629 +0,0 @@
//CONTAINS: Suit fibers and Detective's Scanning Computer
atom/var/list/suit_fibers
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) //bloodied gloves transfer blood to touched objects
if(add_blood(G.bloody_hands_mob)) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
else if(M.bloody_hands)
if(add_blood(M.bloody_hands_mob))
M.bloody_hands--
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 & ~FULL_BODY && (M.wear_suit.body_parts_covered & ~UPPER_TORSO || M.wear_suit.body_parts_covered & ~LOWER_TORSO || M.wear_suit.body_parts_covered & ~ARMS || M.wear_suit.body_parts_covered & ~LEGS))
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 & ~HANDS)
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
var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(print) proc, and means about 80% of
//the print must be there for it to be complete. (Prints are 32 digits)
obj/machinery/computer/forensic_scanning
name = "\improper High-Res Forensic Scanning Computer"
icon_state = "forensic"
var/obj/item/scanning
var/temp = ""
var/canclear = 1
var/authenticated = 0
//Here's the structure for files: each entry is a list, and entry one in that list is the string of their
//full and scrambled fingerprint. This acts as the method to arrange evidence. Each subsequent entry is list
//in the form (from entries):
// 1: Object
// 2: All prints on the object
// 3: All fibers on the object
// 4: All blood on the object
//This is then used to show what objects were used to "find" the full print, as well as the fibers on it.
var/list/files
//This holds objects (1) without prints, and their fibers(2) and blood(3).
var/list/misc
var/obj/item/weapon/f_card/card
var/scan_data = ""
var/scan_name = ""
var/scan_process = 0
req_access = list(access_forensics_lockers)
New()
..()
new /obj/item/weapon/book/manual/detective(get_turf(src))
return
attack_ai(mob/user)
return attack_hand(user)
attack_hand(mob/user)
if(..())
return
user.set_machine(src)
var/dat = ""
var/isai = 0
if(istype(usr,/mob/living/silicon))
isai = 1
if(temp)
dat += "<tt>[temp]</tt><br><br>"
if(canclear) dat += "<a href='?src=\ref[src];operation=clear'>{Clear Screen}</a>"
else
if(!authenticated)
dat += "<a href='?src=\ref[src];operation=login'>{Log In}</a>"
else
dat += "<a href='?src=\ref[src];operation=logout'>{Log Out}</a><br><hr><br>"
if(scanning)
if(scan_process)
dat += {"Scan Object: {[scanning.name]}<br>
<a href='?src=\ref[src];operation=cancel'>{Cancel Scan}</a> {Print}<br>"}
else
if(isai) dat += "Scan Object: {[scanning.name]}<br>"
else dat += "Scan Object: <a href='?src=\ref[src];operation=eject'>{[scanning.name]}</a><br>"
dat += "<a href='?src=\ref[src];operation=scan'>{Scan}</a> <a href='?src=\ref[src];operation=print'>{Print}</a><br>"
else
if(isai) dat += "{No Object Inserted}<br>"
else dat += "<a href='?src=\ref[src];operation=insert'>{No Object Inserted}</a><br>"
dat += "{Scan} <a href='?src=\ref[src];operation=print'>{Print}</a><br>"
dat += {"<a href='?src=\ref[src];operation=database'>{Access Database}</a><br><br>"
<tt>[scan_data]</tt>"}
if(scan_data && !scan_process)
dat += "<br><a href='?src=\ref[src];operation=erase'>{Erase Data}</a>"
user << browse(dat,"window=scanner")
onclose(user,"scanner")
Topic(href,href_list)
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
switch(href_list["operation"])
if("login")
var/mob/M = usr
if(istype(M,/mob/living/silicon))
authenticated = 1
updateDialog()
return
if (allowed(M))
authenticated = 1
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.get_active_hand()
if(I && istype(I))
if(istype(I, /obj/item/weapon/evidencebag))
scanning = I.contents[1]
scanning.loc = src
I.overlays -= scanning
I.icon_state = "evidenceobj"
else
scanning = I
M.drop_item()
I.loc = src
else
usr << "Invalid Object Rejected."
if("card") //Processing a fingerprint card.
var/mob/M = usr
var/obj/item/I = M.get_active_hand()
if(!(I && istype(I,/obj/item/weapon/f_card)))
I = card
if(I && istype(I,/obj/item/weapon/f_card))
card = I
if(!card.fingerprints)
card.fingerprints = list()
if(card.amount > 1 || !card.fingerprints.len)
usr << "\red ERROR: No prints/too many cards."
if(card.loc == src)
card.loc = src.loc
card = null
return
M.drop_item()
I.loc = src
process_card()
else
usr << "\red Invalid Object Rejected."
if("database") //Viewing all records in each database
canclear = 1
if(href_list["delete_record"])
delete_dossier(href_list["delete_record"])
if(href_list["delete_aux"])
delete_record(href_list["delete_aux"])
if((!misc || !misc.len) && (!files || !files.len))
temp = "Database is empty."
else
if(files && files.len)
temp = "<b>Criminal Evidence Database</b><br><br>"
temp += "Consolidated data points:<br>"
for(var/print in files)
var/list/file = files[print]
temp += "<a href='?src=\ref[src];operation=record;identifier=[print]'>{[file[2]]}</a><br>"
temp += "<br><a href='?src=\ref[src];operation=card'>{Insert Finger Print Card (To complete a Dossier)}</a><br><br><br>"
else
temp = ""
if(misc && misc.len)
temp += {"<b>Auxiliary Evidence Database</b><br><br>
This is where anything without fingerprints goes.<br><br>"}
for(var/atom in misc)
var/list/data_entry = misc[atom]
temp += "<a href='?src=\ref[src];operation=auxiliary;identifier=[atom]'>{[data_entry[3]]}</a><br>"
if("record") //Viewing a record from the "files" database.
canclear = 0
if(files)
var/list/dossier = files[href_list["identifier"]]
if(href_list["ren"])
var/new_title = copytext(sanitize(input("Rename to what?", "Dossier Editing", "Dossier [files.Find(href_list["identifier"])]") as null|text),1,MAX_MESSAGE_LEN)
if(new_title)
dossier[2] = new_title
else
usr << "Illegal or blank name."
temp = {"<b>Criminal Evidence Database</b><br><br>
Consolidated data points: [dossier[2]]<br>"}
var/print_string = "Fingerprints: Print not complete!<br>"
if(stringpercent(dossier[1]) <= FINGERPRINT_COMPLETE)
print_string = "Fingerprints: (80% or higher completion reached)<br>[dossier[1]]<br>"
temp += print_string
for(var/object in dossier)
if(object == dossier[1] || object == dossier[2])
continue
temp += "<hr>"
var/list/outputs = dossier[object]
var/list/prints = outputs[1]
temp += "<big><b>Object:</b> [outputs[4]]</big><br>"
temp += "&nbsp<b>Fingerprints:</b><br>"
temp += "&nbsp;&nbsp;&nbsp;&nbsp;[prints.len] Unique fingerprints found.<br>"
var/complete_prints = 0
for(var/print in prints)
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
complete_prints++
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[2]
if(fibers && fibers.len)
temp += "&nbsp<b>Fibers:</b><br>"
for(var/j = 1, j <= fibers.len, j++)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fibers[j]]<br>"
var/list/blood = outputs[3]
if(blood && blood.len)
temp += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type: [blood[named]], DNA: [named]<br>"
temp += "<br><a href='?src=\ref[src];operation=record;identifier=[href_list["identifier"]];ren=true'>{Rename this Dossier}</a>"
temp += "<br><a href='?src=\ref[src];operation=database;delete_record=[href_list["identifier"]]'>{Delete this Dossier}</a>"
temp += "<br><a href='?src=\ref[src];operation=databaseprint;identifier=[href_list["identifier"]]'>{Print}</a>"
else
temp = "ERROR. Database not found!<br>"
temp += "<br><a href='?src=\ref[src];operation=database'>{Return}</a>"
if("databaseprint") //Printing from the "files" database.
if(files)
var/obj/item/weapon/paper/P = new(loc)
var/list/dossier = files[href_list["identifier"]]
P.name = "\improper Database File ([dossier[2]])"
P.icon_state = "paper_words"
P.info = "<b>Criminal Evidence Database</b><br><br>"
P.info += "Consolidated data points: [dossier[2]]<br>"
var/print_string = "Fingerprints: Print not complete!<br>"
if(stringpercent(dossier[1]) <= FINGERPRINT_COMPLETE)
print_string = "Fingerprints: (80% or higher completion reached)<br>[dossier[1]]<br>"
P.info += print_string
for(var/object in dossier)
if(object == dossier[1] || object == dossier[2])
continue
P.info += "<hr>"
var/list/outputs = dossier[object]
var/list/prints = outputs[1]
P.info += "<big><b>Object:</b> [outputs[4]]</big><br>"
P.info += "&nbsp<b>Fingerprints:</b><br>"
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;[prints.len] Unique fingerprints found.<br>"
var/complete_prints = 0
for(var/print in prints)
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
complete_prints++
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[2]
if(fibers && fibers.len)
P.info += "&nbsp<b>Fibers:</b><br>"
for(var/j = 1, j <= fibers.len, j++)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fibers[j]]<br>"
var/list/blood = outputs[3]
if(blood && blood.len)
P.info += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type: [blood[named]], DNA: [named]<br>"
else
usr << "ERROR. Database not found!<br>"
if("auxiliary") //Viewing a record from the "misc" database.
canclear = 0
if(misc)
temp = "<b>Auxiliary Evidence Database</b><br><br>"
var/list/outputs = misc[href_list["identifier"]]
temp += "<big><b>Consolidated data points:</b> [outputs[3]]</big><br>"
var/list/prints = outputs[4]
if(prints)
temp += "&nbsp<b>Fingerprints:</b><br>"
temp += "&nbsp;&nbsp;&nbsp;&nbsp;[prints.len] Unique fingerprints found.<br>"
var/complete_prints = 0
for(var/print in prints)
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
complete_prints++
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[1]
if(fibers && fibers.len)
temp += "&nbsp<b>Fibers:</b><br>"
for(var/fiber in fibers)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fiber]<br>"
var/list/blood = outputs[2]
if(blood && blood.len)
temp += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type: [blood[named]], DNA: [named]<br>"
temp += "<br><a href='?src=\ref[src];operation=database;delete_aux=[href_list["identifier"]]'>{Delete This Record}</a>"
temp += "<br><a href='?src=\ref[src];operation=auxiliaryprint;identifier=[href_list["identifier"]]'>{Print}</a>"
else
temp = "ERROR. Database not found!<br>"
temp += "<br><a href='?src=\ref[src];operation=database'>{Return}</a>"
if("auxiliaryprint") //Printing from the "misc" database.
if(misc)
var/obj/item/weapon/paper/P = new(loc)
var/list/outputs = misc[href_list["identifier"]]
P.name = "\improper Auxiliary Database File ([outputs[3]])"
P.icon_state = "paper_words"
P.info = "<b>Auxiliary Evidence Database</b><br><br>"
P.info += "<big><b>Consolidated data points:</b> [outputs[3]]</big><br>"
var/list/prints = outputs[4]
if(prints)
P.info += "&nbsp<b>Fingerprints:</b><br>"
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;[prints.len] Unique fingerprints found.<br>"
var/complete_prints = 0
for(var/print in prints)
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
complete_prints++
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[1]
if(fibers && fibers.len)
P.info += "&nbsp<b>Fibers:</b><br>"
for(var/fiber in fibers)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fiber]<br>"
var/list/blood = outputs[2]
if(blood && blood.len)
P.info += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type: [blood[named]], DNA: [named]<br>"
else
usr << "ERROR. Database not found!<br>"
if("scan")
if(istype(scanning,/obj/item/weapon/f_card))
card = scanning
scanning = initial(scanning)
process_card()
else 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
if(scanning)
scan_process = 0
scan_name = scanning.name
scan_data = "<u>[scanning]</u><br><br>"
if (scanning.blood_DNA)
scan_data += "Blood Found:<br>"
for(var/blood in scanning.blood_DNA)
scan_data += "Blood type: [scanning.blood_DNA[blood]]\nDNA: [blood]<br><br>"
else
scan_data += "No Blood Found<br><br>"
if(!scanning.fingerprints)
scan_data += "No Fingerprints Found<br><br>"
else
scan_data += "Isolated [scanning.fingerprints.len] Fingerprints. Loaded into database.<br>"
add_data(scanning)
if(!scanning.suit_fibers)
scan_data += "No Fibers/Materials Located<br>"
else
scan_data += "Fibers/Materials Found:<br>"
for(var/data in scanning.suit_fibers)
scan_data += "- [data]<br>"
if(istype(scanning,/obj/item/device/detective_scanner) || (istype(scanning, /obj/item/device/pda) && scanning:cartridge && scanning:cartridge.access_security))
scan_data += "<br><b>Data transfered from \the [scanning] to Database.</b><br>"
add_data_scanner(scanning)
else if(!scanning.fingerprints)
scan_data += "<br><b><a href='?src=\ref[src];operation=add'>Add to Database?</a></b><br>"
else
temp = "Scan Failed: No Object"
if("print") //Printing scan data
if(scan_data)
temp = "Scan Data Printed."
var/obj/item/weapon/paper/P = new(loc)
P.name = "\improper Scan Data ([scan_name])"
P.info = "<tt>[scan_data]</tt>"
P.icon_state = "paper_words"
else
temp = "Print Failed: No Data"
if("erase")
scan_data = ""
if("cancel")
scan_process = 0
if("add") //Adding an object (Manually) to the database.
if(scanning)
add_data(scanning)
else
temp = "Data Transfer Failed: No Object."
if("rename")
if(!files || !files[href_list["identifier"]])
temp = "ERROR: Record/Database not found!"
else
var/new_title = copytext(sanitize(input("Rename to what?", "Dossier Editing", "Dossier [files.Find(href_list["identifier"])]") as null|text),1,MAX_MESSAGE_LEN)
if(new_title)
var/list/file = files[href_list["identifier"]]
file[2] = new_title
updateUsrDialog()
ex_act()
return
proc/add_data_scanner(var/obj/item/device/W)
if(istype(W, /obj/item/device/detective_scanner))
var/obj/item/device/detective_scanner/D = W
if(D.stored)
for(var/atom in D.stored)
var/list/data = D.stored[atom]
add_data_master(atom,data[1],data[2],data[3],data[4])
D.stored = list()
else if(istype(W, /obj/item/device/pda) && W:cartridge && W:cartridge.access_security)
if(W:cartridge.stored_data)
for(var/atom in W:cartridge.stored_data)
var/list/data = W:cartridge.stored_data[atom]
add_data_master(atom,data[1],data[2],data[3],data[4])
W:cartridge.stored_data = list()
return
proc/add_data(var/atom/scanned_atom)
return add_data_master("\ref [scanned_atom]", scanned_atom.fingerprints,\
scanned_atom.suit_fibers, scanned_atom.blood_DNA, "[scanned_atom.name] (Direct Scan)")
/********************************
*****DO NOT DIRECTLY CALL ME*****
********************************/
proc/add_data_master(var/atom_reference, var/list/atom_fingerprints, var/list/atom_suit_fibers, var/list/atom_blood_DNA, var/atom_name)
//What follows is massive. It cross references all stored data in the scanner with the other stored data,
//and what is already in the computer. Not sure how bad the lag may/may not be.
if(!misc)
misc = list()
var/list/data_entry = misc[atom_reference]
if(data_entry)
var/list/fibers = data_entry[1]
if(!fibers)
fibers = list()
if(atom_suit_fibers)
for(var/fiber in atom_suit_fibers) //Fibers~~~
if(!fibers.Find(fiber)) //It isn't! Add!
fibers += fiber
var/list/blood = data_entry[2]
if(!blood)
blood = list()
if(atom_blood_DNA)
for(var/main_blood in atom_blood_DNA)
if(!blood[main_blood])
blood[main_blood] = atom_blood_DNA[blood]
var/list/prints = data_entry[4]
if(!prints && atom_fingerprints)
prints = list()
if(atom_fingerprints)
for(var/print in atom_fingerprints)
if(!prints[print])
prints[print] = atom_fingerprints[print]
else
var/list/templist[4]
templist[1] = atom_suit_fibers ? atom_suit_fibers.Copy() : null
templist[2] = atom_blood_DNA ? atom_blood_DNA.Copy() : null
templist[3] = atom_name
templist[4] = atom_fingerprints ? atom_fingerprints.Copy() : null
misc[atom_reference] = templist //Store it!
//Has prints.
if(atom_fingerprints)
if(!files)
files = list()
for(var/main_print in atom_fingerprints)
data_entry = files[main_print]
if(data_entry)//The print is already in here!
var/list/internal_atom = data_entry[atom_reference] //Lets see if we can find the current object
if(internal_atom)
//We must be on a roll! Just update what needs to be updated.
var/list/internal_prints = internal_atom[1]
for(var/print in atom_fingerprints) //Sorry for the double loop! D:
var/associated_print = internal_prints[print]
var/reference_print = atom_fingerprints[print]
if(associated_print && associated_print != reference_print) //It does not match
internal_prints[print] = stringmerge(associated_print, reference_print)
else if(!associated_print)
internal_prints[print] = reference_print
//If the main print was updated, lets update the master as well.
if(print == main_print && (!associated_print || (associated_print && associated_print != reference_print)))
update_fingerprints(main_print, internal_prints[print])
//Fibers.
var/list/fibers = internal_atom[2]
if(!fibers)
fibers = list()
if(atom_suit_fibers)
for(var/fiber in atom_suit_fibers) //Fibers~~~
if(!fibers.Find(fiber)) //It isn't! Add!
fibers += fiber
//Blood.
var/list/blood = internal_atom[3]
if(!blood)
blood = list()
if(atom_blood_DNA)
for(var/main_blood in atom_blood_DNA)
if(!blood[main_blood])
blood[main_blood] = atom_blood_DNA[blood]
continue
//It's not in there! We gotta add it.
update_fingerprints(main_print, atom_fingerprints[main_print])
var/list/data_point[4]
data_point[1] = atom_fingerprints ? atom_fingerprints.Copy() : null
data_point[2] = atom_suit_fibers ? atom_suit_fibers.Copy() : null
data_point[3] = atom_blood_DNA ? atom_blood_DNA.Copy() : null
data_point[4] = atom_name
data_entry[atom_reference] = data_point
continue
//No print at all! New data entry, go!
var/list/data_point[4]
data_point[1] = atom_fingerprints ? atom_fingerprints.Copy() : null
data_point[2] = atom_suit_fibers ? atom_suit_fibers.Copy() : null
data_point[3] = atom_blood_DNA ? atom_blood_DNA.Copy() : null
data_point[4] = atom_name
var/list/new_file[2]
new_file[1] = atom_fingerprints[main_print]
new_file[2] = "Dossier [files.len + 1]"
new_file[atom_reference] = data_point
files[main_print] = new_file
return 1
/********************************
***END DO NOT DIRECTLY CALL ME***
********************************/
proc/update_fingerprints(var/ref_print, var/new_print)
var/list/master = files[ref_print]
if(master)
master[1] = stringmerge(master[1],new_print)
else
CRASH("Fucking hell. Something went wrong, and it tried to update a null print or something. Tell SkyMarshal (and give him this call stack)")
return
proc/process_card() //Same as above, but for fingerprint cards
if(card.fingerprints && !(card.amount > 1) && islist(card.fingerprints) && files && files.len)
usr << "You insert the card, and it is destroyed by the machinery in the process of comparing prints."
var/found = 0
for(var/master_print in card.fingerprints)
var/list/data_entry = files[master_print]
if(data_entry)
found = 1
data_entry[1] = master_print
if(found)
usr << "The machinery finds it can complete a match."
else
usr << "No match found."
del(card)
else
usr << "\red ERROR: No prints/too many cards."
if(card.loc == src)
card.loc = src.loc
card = null
return
return
proc/delete_record(var/atom_ref) //Deletes an entry in the misc database at the given location
if(misc && misc.len)
misc.Remove(atom_ref)
return
proc/delete_dossier(var/print) //Deletes a Dossier at a given location.
if(files && files.len)
files.Remove(print)
return
detective
icon_state = "old"
name = "PowerScan Mk.I"

View File

@@ -0,0 +1,73 @@
//This is the output of the stringpercent(print) proc, and means about 80% of
//the print must be there for it to be complete. (Prints are 32 digits)
var/const/FINGERPRINT_COMPLETE = 6
proc/is_complete_print(var/print)
return stringpercent(print) <= FINGERPRINT_COMPLETE
atom/var/list/suit_fibers
atom/proc/add_fibers(mob/living/carbon/human/M)
if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves))
var/obj/item/clothing/gloves/G = M.gloves
if(G.transfer_blood) //bloodied gloves transfer blood to touched objects
if(add_blood(G.bloody_hands_mob)) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
else if(M.bloody_hands)
if(add_blood(M.bloody_hands_mob))
M.bloody_hands--
if(!suit_fibers) suit_fibers = list()
var/fibertext
var/item_multiplier = istype(src,/obj/item)?1.2:1
var/suit_coverage = 0
if(M.wear_suit)
fibertext = "Material from \a [M.wear_suit]."
if(prob(10*item_multiplier) && !(fibertext in suit_fibers))
suit_fibers += fibertext
suit_coverage = M.wear_suit.body_parts_covered
if(M.w_uniform && (M.w_uniform.body_parts_covered & ~suit_coverage))
fibertext = "Fibers from \a [M.w_uniform]."
if(prob(15*item_multiplier) && !(fibertext in suit_fibers))
suit_fibers += fibertext
if(M.gloves && (M.w_uniform.body_parts_covered & ~suit_coverage))
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]."
/datum/data/record/forensic
name = "forensic data"
var/uid
/datum/data/record/forensic/New(var/atom/A)
uid = "\ref [A]"
fields["name"] = sanitize(A.name)
fields["area"] = sanitize("[get_area(A)]")
fields["fprints"] = A.fingerprints ? A.fingerprints.Copy() : list()
fields["fibers"] = A.suit_fibers ? A.suit_fibers.Copy() : list()
fields["blood"] = A.blood_DNA ? A.blood_DNA.Copy() : list()
fields["time"] = world.time
/datum/data/record/forensic/proc/merge(var/datum/data/record/other)
var/list/prints = fields["fprints"]
var/list/o_prints = other.fields["fprints"]
for(var/print in o_prints)
if(!prints[print])
prints[print] = o_prints[print]
else
prints[print] = stringmerge(prints[print], o_prints[print])
fields["fprints"] = prints
var/list/fibers = fields["fibers"]
var/list/o_fibers = other.fields["fibers"]
fibers |= o_fibers
fields["fibers"] = fibers
var/list/blood = other.fields["blood"]
var/list/o_blood = other.fields["blood"]
blood |= o_blood
fields["blood"] = blood
fields["area"] = other.fields["area"]
fields["time"] = other.fields["time"]

View File

@@ -1,181 +1,107 @@
//CONTAINS: Detective's Scanner
/obj/item/device/detective_scanner
name = "Scanner"
name = "forensic scanner"
desc = "Used to scan objects for DNA and fingerprints."
icon_state = "forensic1"
var/amount = 20.0
var/list/stored = list()
w_class = 3.0
item_state = "electronic"
flags = FPRINT | TABLEPASS | CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
attackby(obj/item/weapon/f_card/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/f_card))
if (W.fingerprints)
return
if (src.amount == 20)
return
if (W.amount + src.amount > 20)
src.amount = 20
W.amount = W.amount + src.amount - 20
else
src.amount += W.amount
//W = null
del(W)
add_fingerprint(user)
if (W)
W.add_fingerprint(user)
return
attack(mob/living/carbon/human/M as mob, mob/user as mob)
if (!ishuman(M))
user << "\red [M] is not human and cannot have the fingerprints."
flick("forensic0",src)
return 0
if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
user << "\blue No fingerprints found on [M]"
flick("forensic0",src)
return 0
else
if (src.amount < 1)
user << text("\blue Fingerprints scanned on [M]. Need more cards to print.")
else
src.amount--
var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
F.amount = 1
F.add_fingerprint(M)
F.icon_state = "fingerprint1"
F.name = text("FPrintC- '[M.name]'")
user << "\blue Done printing."
user << "\blue [M]'s Fingerprints: [md5(M.dna.uni_identity)]"
if ( !M.blood_DNA || !M.blood_DNA.len )
user << "\blue No blood found on [M]"
if(M.blood_DNA)
del(M.blood_DNA)
else
user << "\blue Blood found on [M]. Analysing..."
spawn(15)
for(var/blood in M.blood_DNA)
user << "\blue Blood type: [M.blood_DNA[blood]]\nDNA: [blood]"
return
afterattack(atom/A as obj|turf|area, mob/user as mob, proximity)
if(!proximity) return
if(loc != user)
return
if(istype(A,/obj/machinery/computer/forensic_scanning)) //breaks shit.
return
if(istype(A,/obj/item/weapon/f_card))
user << "The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\""
flick("forensic0",src)
return
add_fingerprint(user)
//Special case for blood splatters, runes and gibs.
if (istype(A, /obj/effect/decal/cleanable/blood) || istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable/blood/gibs))
if(!isnull(A.blood_DNA))
for(var/blood in A.blood_DNA)
user << "\blue Blood type: [A.blood_DNA[blood]]\nDNA: [blood]"
flick("forensic2",src)
return
//General
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"\blue Unable to locate any fingerprints, materials, fibers, or blood on [A]!",\
"You hear a faint hum of electrical equipment.")
flick("forensic0",src)
return 0
if(add_data(A))
user << "\blue Object already in internal memory. Consolidating data..."
flick("forensic2",src)
return
//PRINTS
if(!A.fingerprints || !A.fingerprints.len)
if(A.fingerprints)
del(A.fingerprints)
else
user << "\blue Isolated [A.fingerprints.len] fingerprints: Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
var/list/complete_prints = list()
for(var/i in A.fingerprints)
var/print = A.fingerprints[i]
if(stringpercent(print) <= FINGERPRINT_COMPLETE)
complete_prints += print
if(complete_prints.len < 1)
user << "\blue &nbsp;&nbsp;No intact prints found"
else
user << "\blue &nbsp;&nbsp;Found [complete_prints.len] intact prints"
for(var/i in complete_prints)
user << "\blue &nbsp;&nbsp;&nbsp;&nbsp;[i]"
//FIBERS
if(A.suit_fibers)
user << "\blue Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
flick("forensic2",src)
//Blood
if (A.blood_DNA)
user << "\blue Blood found on [A]. Analysing..."
spawn(15)
for(var/blood in A.blood_DNA)
user << "Blood type: \red [A.blood_DNA[blood]] \t \black DNA: \red [blood]"
if(prob(80) || !A.fingerprints)
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"You finish scanning \the [A].",\
"You hear a faint hum of electrical equipment.")
flick("forensic2",src)
return 0
else
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]\n[user.gender == MALE ? "He" : "She"] seems to perk up slightly at the readout." ,\
"The results of the scan pique your interest.",\
"You hear a faint hum of electrical equipment, and someone making a thoughtful noise.")
flick("forensic2",src)
return 0
return
proc/add_data(atom/A as mob|obj|turf|area)
//I love associative lists.
var/list/data_entry = stored["\ref [A]"]
if(islist(data_entry)) //Yay, it was already stored!
//Merge the fingerprints.
var/list/data_prints = data_entry[1]
for(var/print in A.fingerprints)
var/merged_print = data_prints[print]
if(!merged_print)
data_prints[print] = A.fingerprints[print]
else
data_prints[print] = stringmerge(data_prints[print],A.fingerprints[print])
//Now the fibers
var/list/fibers = data_entry[2]
if(!fibers)
fibers = list()
if(A.suit_fibers && A.suit_fibers.len)
for(var/j = 1, j <= A.suit_fibers.len, j++) //Fibers~~~
if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add!
fibers += A.suit_fibers[j]
var/list/blood = data_entry[3]
if(!blood)
blood = list()
if(A.blood_DNA && A.blood_DNA.len)
for(var/main_blood in A.blood_DNA)
if(!blood[main_blood])
blood[main_blood] = A.blood_DNA[blood]
return 1
var/list/sum_list[4] //Pack it back up!
sum_list[1] = A.fingerprints ? A.fingerprints.Copy() : null
sum_list[2] = A.suit_fibers ? A.suit_fibers.Copy() : null
sum_list[3] = A.blood_DNA ? A.blood_DNA.Copy() : null
sum_list[4] = "\The [A] in \the [get_area(A)]"
stored["\ref [A]"] = sum_list
/obj/item/device/detective_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob)
if (!ishuman(M))
user << "<span class='warning'>[M] is not human and cannot have the fingerprints.</span>"
flick("forensic0",src)
return 0
if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
user << "<span class='notice'>No fingerprints found on [M]</span>"
flick("forensic0",src)
return 0
else
var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
F.amount = 1
F.add_fingerprint(M)
F.icon_state = "fingerprint1"
F.name = text("FPrintC- '[M.name]'")
user << "<span class='notice'>Done printing."
user << "<span class='notice'>[M]'s Fingerprints: [md5(M.dna.uni_identity)]"
if ( M.blood_DNA && M.blood_DNA.len )
user << "<span class='notice'>Blood found on [M]. Analysing...</span>"
spawn(15)
for(var/blood in M.blood_DNA)
user << "<span class='notice'>Blood type: [M.blood_DNA[blood]]\nDNA: [blood]</span>"
return
/obj/item/device/detective_scanner/afterattack(atom/A as obj|turf, mob/user, proximity)
if(!proximity) return
if(ismob(A))
return
if(istype(A,/obj/machinery/computer/forensic_scanning))
user.visible_message("[user] takes a cord out of [src] and hooks its end into [A]" ,\
"<span class='notice'>You download data from [src] to [A]</span>")
var/obj/machinery/computer/forensic_scanning/F = A
F.sync_data(stored)
return
if(istype(A,/obj/item/weapon/f_card))
user << "The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\""
flick("forensic0",src)
return
add_fingerprint(user)
//General
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"<span class='warning'>Unable to locate any fingerprints, materials, fibers, or blood on [A]!</span>",\
"You hear a faint hum of electrical equipment.")
flick("forensic0",src)
return 0
if(add_data(A))
user << "<span class='notice'>Object already in internal memory. Consolidating data...</span>"
flick("forensic2",src)
return
//PRINTS
if(A.fingerprints && A.fingerprints.len)
user << "<span class='notice'>Isolated [A.fingerprints.len] fingerprints:</span>"
user << "Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.</span>"
var/list/complete_prints = list()
for(var/i in A.fingerprints)
var/print = A.fingerprints[i]
if(stringpercent(print) <= FINGERPRINT_COMPLETE)
complete_prints += print
if(complete_prints.len < 1)
user << "<span class='notice'>No intact prints found</span>"
else
user << "<span class='notice'>Found [complete_prints.len] intact prints</span>"
for(var/i in complete_prints)
user << "<span class='notice'>&nbsp;&nbsp;&nbsp;&nbsp;[i]</span>"
//FIBERS
if(A.suit_fibers && A.suit_fibers.len)
user << "<span class='notice'>Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
flick("forensic2",src)
//Blood
if (A.blood_DNA && A.blood_DNA.len)
user << "<span class='notice'>Blood detected. Analysing...</span>"
spawn(15)
for(var/blood in A.blood_DNA)
user << "Blood type: \red [A.blood_DNA[blood]] \t \black DNA: \red [blood]"
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"<span class='notice'>You finish scanning \the [A].</span>",\
"You hear a faint hum of electrical equipment.")
flick("forensic2",src)
return 0
/obj/item/device/detective_scanner/proc/add_data(atom/A as mob|obj|turf|area)
var/datum/data/record/forensic/old = stored["\ref [A]"]
var/datum/data/record/forensic/fresh = new(A)
if(old)
fresh.merge(old)
. = 1
stored["\ref [A]"] = fresh

View File

@@ -0,0 +1,305 @@
/obj/machinery/computer/forensic_scanning
name = "high-res forensic scanning computer"
icon_state = "forensic"
var/screen = "database"
var/authenticated = 0
req_access = list(access_forensics_lockers)
var/scan_progress = -1
var/obj/item/scanning
var/datum/data/record/forensic/current
var/list/filters = list()
var/list/current_list = list()
var/list/files = list()
/obj/machinery/computer/forensic_scanning/proc/get_printable_data(var/datum/data/record/forensic/fresh)
. += "<h2>[fresh.fields["name"]]</h2>"
. += "Scanned in [fresh.fields["area"]] at [worldtime2text(fresh.fields["time"])]<br>"
var/list/prints = fresh.fields["fprints"]
if(prints.len)
. += "<h3>Fingerprints:</h3>"
var/incomplete = 0
for(var/fullprint in prints)
var/print = prints[fullprint]
if(is_complete_print(print))
. += "[print]<br>"
else
incomplete++
if(incomplete)
. += "[incomplete] incomplete fingerprints."
else
. += "<br>No fingerprints recorded.<br>"
var/list/fibers = fresh.fields["fibers"]
if(fibers.len)
. += "<h3>Fibers:</h3>"
. += "<ul>"
for(var/fiber in fibers)
. += "<li>[fiber]</li>"
. += "</ul>"
else
. += "<br>No fibers recorded."
var/list/bloods = fresh.fields["blood"]
if(bloods.len)
. += "<h3>Blood:</h3>"
. += "<ul>"
for(var/blood in bloods)
. += "<li>DNA: [blood] Type: [bloods[blood]]</li>"
. += "</ul>"
else
. += "<br>No blood recorded."
/obj/machinery/computer/forensic_scanning/proc/add_record(var/datum/data/record/forensic/fresh)
var/datum/data/record/forensic/old = files[fresh.uid]
if(old)
fresh.merge(old)
fresh.fields["label"] = old.fields["label"]
files[fresh.uid] = fresh
/obj/machinery/computer/forensic_scanning/proc/process_card(var/obj/item/weapon/f_card/card)
if(card.fingerprints)
usr << "<span class='notice'>\The [src] sucks in \the [card] and whirrs, scanning it.</span>"
var/found = 0
for(var/id in files)
var/datum/data/record/forensic/rec = files[id]
var/list/prints = rec.fields["fprints"]
for(var/master_print in card.fingerprints)
if(prints[master_print])
prints[master_print] = master_print
found = 1
if(found)
usr << "<span class='notice'>Complete match found.</span>"
else
usr << "<span class='notice'>No match found.</span>"
return 1
else
usr << "<span class='warning'>No fingerprints detected on [card].</span>"
return 0
//Takes a list of forensic records, with key being reference to object, and updates internal database.
/obj/machinery/computer/forensic_scanning/proc/sync_data(var/list/newdata)
for(var/id in newdata)
var/datum/data/record/forensic/fresh = newdata[id]
add_record(fresh)
/obj/machinery/computer/forensic_scanning/proc/get_filtered_set()
.= list()
for(var/id in files)
var/datum/data/record/forensic/cur = files[id]
var/add = 1
if(filters["name"])
add = 0
for(var/filter in filters["name"])
if(findtext(cur.fields["name"], filter))
add = 1
break
if(filters["area"])
add = 0
for(var/filter in filters["area"])
if(findtext(cur.fields["area"], filter))
add = 1
break
if(filters["fprints"])
add = 0
var/list/prints = cur.fields["fprints"]
for(var/pid in prints)
var/print = prints[pid]
if (is_complete_print(print))
for(var/filter in filters["fprints"])
if(findtext(print, filter))
add = 1
break
if(filters["fibers"])
add = 0
for(var/fiber in cur.fields["fibers"])
for(var/filter in filters["fibers"])
if(findtext(fiber, filter))
add = 1
break
if(filters["blood"])
add = 0
for(var/DNA in cur.fields["blood"])
for(var/filter in filters["blood"])
if(findtext(DNA, filter))
add = 1
break
if(filters["label"])
add = 0
for(var/filter in filters["label"])
if(cur.fields["label"] && findtext(cur.fields["label"], filter))
add = 1
break
if (add)
.+=cur
/obj/machinery/computer/forensic_scanning/attack_hand(mob/user)
if(..())
return
user.set_machine(src)
var/dat
if(!authenticated)
dat += "<a href='?src=\ref[src];operation=login'>{Log In}</a>"
else
dat += "<a href='?src=\ref[src];operation=logout'>{Log Out}</a>"
dat += " | "
dat += "<a href='?src=\ref[src];operation=screen;screen=database'>Database</a>"
dat += " | "
dat += "<a href='?src=\ref[src];operation=screen;screen=details'>Record details</a>"
dat += " | "
dat += "<a href='?src=\ref[src];operation=screen;screen=scan'>Scanning</a>"
dat +="<br><hr><br>"
switch(screen)
if("database") //Database screen
dat += "Search filters:<br>"
var/list/filternames = list("Object"="name", "Area"="area", "Fingerprints"="fprints", "Fibers"="fibers", "DNA"="blood", "Label"="label")
for(var/filter in filternames)
var/fname = filternames[filter]
dat += "<br>[filter]: <a href='?src=\ref[src];operation=filter;filter=[fname]'>[filters[fname] ? list2text(filters[fname], ",") : "All"]</a>"
current_list = get_filtered_set()
dat+= "<br><hr><br>"
if(current_list.len < 1)
dat += "No data matching your request found."
else
dat += "<table><tr>"
dat += "<th>Object</th><th>Area</th><th>Fingerprints</th><th>Fibers</th><th>Blood</th><th>Label</th></tr>"
for(var/datum/data/record/forensic/record in current_list)
dat += "<tr><td><a href='?src=\ref[src];operation=details;identifier=[record.uid]'>[record.fields["name"]]</td>"
dat += "<td>[record.fields["area"]]</td>"
for(var/criteria in list("fprints", "fibers", "blood"))
var/list/data = record.fields[criteria]
dat += "<td>[data.len ? data.len : "None"]</td>"
dat += "<td>[record.fields["label"] ? record.fields["label"] : ""]</td>"
dat += "<td><a href='?src=\ref[src];operation=delete;identifier=[record.uid]'>Delete</a></td>"
dat += "</tr>"
dat += "</table>"
dat += "<a href='?src=\ref[src];operation=printall'>Print all listed</a><br>"
if("details") //Details screen
if(!current)
dat += "<br>NO RECORD SELECTED"
else
dat += get_printable_data(current)
dat += "<b>Labels:</b> "
dat += "<a href='?src=\ref[src];operation=label'>[current.fields["label"] ? current.fields["label"] : "None"]</a><br>"
dat += "<a href='?src=\ref[src];operation=print'>Print record</a><br>"
if("scan") //Scanning screen
dat += "Object: <a href='?src=\ref[src];operation=object'>[scanning ? scanning.name : "-----"]</a><br>"
if (scanning)
if (scan_progress > 0)
dat += "Scan in progress."
dat += " <a href='?src=\ref[src];operation=cancel'>Cancel</a><br>"
else
dat += "<a href='?src=\ref[src];operation=scan'>Scan</a><br>"
dat += "Insert fingerprint card here: <a href='?src=\ref[src];operation=card'>-----</a>"
user << browse(dat,"window=fscanner")
onclose(user,"fscanner")
/obj/machinery/computer/forensic_scanning/Topic(href,href_list)
switch(href_list["operation"])
if("login")
var/mob/M = usr
if(istype(M,/mob/living/silicon) || allowed(M))
authenticated = 1
if("logout")
authenticated = 0
if("filter")
var/filterstr = stripped_input(usr,"Input the search criteria. Multiple values can be input, separated by a comma.", "Filter setting") as text|null
if(filterstr)
filters[href_list["filter"]] = text2list(filterstr,",")
else
filters[href_list["filter"]] = null
if("screen")
screen = href_list["screen"]
if("details")
if(href_list["identifier"])
screen = "details"
current = files[href_list["identifier"]]
else
usr << "<spawn class='warning'>No record found.</span>"
if("delete")
if(href_list["identifier"])
if(alert("Are you sure you want to delete this record?","Record deletion", "Yes", "No") == "Yes")
files.Remove(href_list["identifier"])
if(current && current.uid == href_list["identifier"])
current = null
if("label")
if(current)
var/label = stripped_input(usr,"Input the label for this record. Multiple values can be input, separated by a comma.", "Labeling record", current.fields["label"]) as text|null
current.fields["label"] = label
if("object")
if(scanning)
scanning.loc = get_turf(src)
scan_progress = -1
scanning = null
else
var/mob/M = usr
var/obj/item/I = M.get_active_hand()
if(I && istype(I))
if(istype(I, /obj/item/weapon/evidencebag))
scanning = I.contents[1]
scanning.loc = src
I.overlays.Cut()
I.w_class = 1
I.icon_state = "evidenceobj"
else
scanning = I
M.drop_item()
I.loc = src
else
usr << "<spawn class='warning'>Invalid object, rejected.</span>"
if("scan")
if(scanning)
scan_progress = 10
if("cancel")
scan_progress = -1
if("card")
var/mob/M = usr
var/obj/item/I = M.get_active_hand()
if(istype(I, /obj/item/weapon/f_card))
if(process_card(I))
M.drop_item()
del(I)
else
usr << "<spawn class='warning'>Invalid fingerprint card, rejected.</span>"
if("print")
if(current)
var/obj/item/weapon/paper/P = new(loc)
P.name = "\improper Forensics Data ([current.fields["name"]])"
P.icon_state = "paper_words"
P.info = "<b>Forensics Database</b> - [worldtime2text(world.time)]<br><br>"
P.info += get_printable_data(current)
if("printall")
var/obj/item/weapon/paper/P = new(loc)
P.name = "\improper Forensics Data"
P.icon_state = "paper_words"
P.info = "<b>Forensics Database</b> - [worldtime2text(world.time)]<br><br>"
for(var/datum/data/record/forensic/cur in current_list)
P.info += get_printable_data(cur)
updateUsrDialog()
/obj/machinery/computer/forensic_scanning/process()
if (!..())
return
if(scanning)
if(scan_progress > 0)
scan_progress--
updateUsrDialog()
if(scan_progress == 0)
scan_progress = -1
ping("Scan complete.")
var/datum/data/record/forensic/fresh = new(scanning)
add_record(fresh)
updateUsrDialog()