mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
668 lines
25 KiB
Plaintext
668 lines
25 KiB
Plaintext
//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 & 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
|
|
|
|
/atom/proc/add_custom_fibers(var/txt, var/duplicates = TRUE)
|
|
if(!suit_fibers)
|
|
suit_fibers = list()
|
|
|
|
if(duplicates)
|
|
suit_fibers += txt
|
|
else
|
|
suit_fibers |= txt
|
|
|
|
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
|
|
circuit = "/obj/item/weapon/circuitboard/forensic_computer"
|
|
light_color = LIGHT_COLOR_RED
|
|
|
|
//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)
|
|
|
|
/obj/machinery/computer/forensic_scanning/attack_ai(mob/user)
|
|
src.add_hiddenprint(user)
|
|
return attack_hand(user)
|
|
|
|
/obj/machinery/computer/forensic_scanning/attack_hand(mob/user)
|
|
if(..())
|
|
return
|
|
user.set_machine(src)
|
|
var/dat = ""
|
|
var/isai = FALSE
|
|
if(isAI(user))
|
|
isai = TRUE
|
|
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")
|
|
|
|
|
|
/obj/machinery/computer/forensic_scanning/Topic(href,href_list)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
switch(href_list["operation"])
|
|
if("login")
|
|
var/mob/M = usr
|
|
if(issilicon(M))
|
|
authenticated = 1
|
|
updateDialog()
|
|
if(allowed(M))
|
|
authenticated = 1
|
|
if("logout")
|
|
authenticated = 0
|
|
if("clear")
|
|
if(canclear)
|
|
temp = null
|
|
if("eject")
|
|
if(scanning)
|
|
scanning.forceMove(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(isgripper(I))
|
|
var/obj/item/weapon/gripper/G = I
|
|
if(G.wrapped)
|
|
scanning = G.wrapped //We add it as scanned object first because we'll lose the wrapped reference once we drop it.
|
|
G.drop_item(G.wrapped, src)
|
|
else
|
|
if(istype(I, /obj/item/weapon/storage/evidencebag) && I.contents.len)
|
|
var/obj/item/weapon/storage/evidencebag/EVB = I
|
|
scanning = EVB.contents[1]
|
|
EVB.remove_from_storage(scanning, src, TRUE, TRUE)
|
|
else
|
|
if(M.drop_item(I, src))
|
|
scanning = I
|
|
else
|
|
to_chat(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)
|
|
to_chat(usr, "<span class='warning'>ERROR: No prints/too many cards.</span>")
|
|
if(card.loc == src)
|
|
card.forceMove(src.loc)
|
|
card = null
|
|
return
|
|
if(M.drop_item(I, src))
|
|
process_card()
|
|
else
|
|
to_chat(usr, "<span class='warning'>Invalid Object Rejected.</span>")
|
|
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>
|
|
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
|
|
to_chat(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>
|
|
 <b>Fingerprints:</b><br>
|
|
[prints.len] Unique fingerprints found.<br>"}
|
|
var/complete_prints = 0
|
|
for(var/print in prints)
|
|
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
|
|
complete_prints++
|
|
temp += " [prints[print]]<br>"
|
|
if(complete_prints)
|
|
temp += " And [prints.len - complete_prints] unknown unique prints.<br>"
|
|
else
|
|
temp += " No prints of sufficient completeness.<br>"
|
|
var/list/fibers = outputs[2]
|
|
if(fibers && fibers.len)
|
|
temp += " <b>Fibers:</b><br>"
|
|
for(var/j = 1, j <= fibers.len, j++)
|
|
temp += " [fibers[j]]<br>"
|
|
var/list/blood = outputs[3]
|
|
if(blood && blood.len)
|
|
temp += " <b>Blood:</b><br>"
|
|
for(var/named in blood)
|
|
temp += " 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>
|
|
<br><a href='?src=\ref[src];operation=database;delete_record=[href_list["identifier"]]'>{Delete this Dossier}</a>
|
|
<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.overlays += image(icon = P.icon, icon_state = "paper_words")
|
|
|
|
P.info = {"<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>"
|
|
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>
|
|
 <b>Fingerprints:</b><br>
|
|
[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 += " [prints[print]]<br>"
|
|
if(complete_prints)
|
|
P.info += " And [prints.len - complete_prints] unknown unique prints.<br>"
|
|
else
|
|
P.info += " No prints of sufficient completeness.<br>"
|
|
var/list/fibers = outputs[2]
|
|
if(fibers && fibers.len)
|
|
P.info += " <b>Fibers:</b><br>"
|
|
for(var/j = 1, j <= fibers.len, j++)
|
|
P.info += " [fibers[j]]<br>"
|
|
var/list/blood = outputs[3]
|
|
if(blood && blood.len)
|
|
P.info += " <b>Blood:</b><br>"
|
|
for(var/named in blood)
|
|
P.info += " Type: [blood[named]], DNA: [named]<br>"
|
|
else
|
|
to_chat(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 += {" <b>Fingerprints:</b><br>
|
|
[prints.len] Unique fingerprints found.<br>"}
|
|
var/complete_prints = 0
|
|
for(var/print in prints)
|
|
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
|
|
complete_prints++
|
|
temp += " [prints[print]]<br>"
|
|
if(complete_prints)
|
|
temp += " And [prints.len - complete_prints] unknown unique prints.<br>"
|
|
else
|
|
temp += " No prints of sufficient completeness.<br>"
|
|
var/list/fibers = outputs[1]
|
|
if(fibers && fibers.len)
|
|
temp += " <b>Fibers:</b><br>"
|
|
for(var/fiber in fibers)
|
|
temp += " [fiber]<br>"
|
|
var/list/blood = outputs[2]
|
|
if(blood && blood.len)
|
|
temp += " <b>Blood:</b><br>"
|
|
for(var/named in blood)
|
|
temp += " Type: [blood[named]], DNA: [named]<br>"
|
|
|
|
temp += {"<br><a href='?src=\ref[src];operation=database;delete_aux=[href_list["identifier"]]'>{Delete This Record}</a>
|
|
<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.overlays += image(icon = P.icon, icon_state = "paper_words")
|
|
|
|
P.info = {"<b>Auxiliary Evidence Database</b><br><br>
|
|
<big><b>Consolidated data points:</b> [outputs[3]]</big><br>"}
|
|
var/list/prints = outputs[4]
|
|
if(prints)
|
|
|
|
P.info += {" <b>Fingerprints:</b><br>
|
|
[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 += " [prints[print]]<br>"
|
|
if(complete_prints)
|
|
P.info += " And [prints.len - complete_prints] unknown unique prints.<br>"
|
|
else
|
|
P.info += " No prints of sufficient completeness.<br>"
|
|
var/list/fibers = outputs[1]
|
|
if(fibers && fibers.len)
|
|
P.info += " <b>Fibers:</b><br>"
|
|
for(var/fiber in fibers)
|
|
P.info += " [fiber]<br>"
|
|
var/list/blood = outputs[2]
|
|
if(blood && blood.len)
|
|
P.info += " <b>Blood:</b><br>"
|
|
for(var/named in blood)
|
|
P.info += " Type: [blood[named]], DNA: [named]<br>"
|
|
else
|
|
to_chat(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>"
|
|
|
|
var/is_scanner = istype(scanning, /obj/item/device/detective_scanner)
|
|
if(istype(scanning, /obj/item/device/pda))
|
|
var/obj/item/device/pda/the_pda = scanning
|
|
if(the_pda.cartridge && the_pda.cartridge.access_security)
|
|
is_scanner = TRUE
|
|
|
|
if(is_scanner)
|
|
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.overlays += image(icon = P.icon, 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()
|
|
|
|
/obj/machinery/computer/forensic_scanning/ex_act()
|
|
return
|
|
|
|
|
|
/obj/machinery/computer/forensic_scanning/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))
|
|
var/obj/item/device/pda/the_pda = W
|
|
if(the_pda.cartridge && the_pda.cartridge.access_security)
|
|
if(the_pda.cartridge.stored_data)
|
|
for(var/atom in the_pda.cartridge.stored_data)
|
|
var/list/data = the_pda.cartridge.stored_data[atom]
|
|
add_data_master(atom,data[1],data[2],data[3],data[4])
|
|
the_pda.cartridge.stored_data = list()
|
|
return
|
|
|
|
/obj/machinery/computer/forensic_scanning/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*****
|
|
********************************/
|
|
/obj/machinery/computer/forensic_scanning/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***
|
|
********************************/
|
|
|
|
/obj/machinery/computer/forensic_scanning/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
|
|
|
|
/obj/machinery/computer/forensic_scanning/proc/process_card() //Same as above, but for fingerprint cards
|
|
if(card.fingerprints && !(card.amount > 1) && islist(card.fingerprints) && files && files.len)
|
|
to_chat(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)
|
|
to_chat(usr, "The machinery finds it can complete a match.")
|
|
else
|
|
to_chat(usr, "No match found.")
|
|
qdel(card)
|
|
card = null
|
|
else
|
|
to_chat(usr, "<span class='warning'>ERROR: No prints/too many cards.</span>")
|
|
if(card.loc == src)
|
|
card.forceMove(src.loc)
|
|
card = null
|
|
return
|
|
return
|
|
|
|
/obj/machinery/computer/forensic_scanning/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
|
|
|
|
/obj/machinery/computer/forensic_scanning/proc/delete_dossier(var/print) //Deletes a Dossier at a given location.
|
|
if(files && files.len)
|
|
files.Remove(print)
|
|
return
|
|
|
|
/obj/machinery/computer/forensic_scanning/detective
|
|
icon_state = "old"
|
|
name = "PowerScan Mk.I"
|