mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-14 16:44:33 +01:00
Detective Scanner
This commit is contained in:
@@ -5,10 +5,10 @@ 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(G.transfer_blood > 1) //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)
|
||||
else if(M.bloody_hands > 1)
|
||||
if(add_blood(M.bloody_hands_mob))
|
||||
M.bloody_hands--
|
||||
if(!suit_fibers) suit_fibers = list()
|
||||
@@ -19,13 +19,13 @@ atom/proc/add_fibers(mob/living/carbon/human/M)
|
||||
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.wear_suit.body_parts_covered & UPPER_TORSO))
|
||||
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.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))
|
||||
@@ -45,583 +45,4 @@ atom/proc/add_fibers(mob/living/carbon/human/M)
|
||||
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>"
|
||||
dat += "<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>"
|
||||
dat += "<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)
|
||||
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>"
|
||||
temp += "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>"
|
||||
temp += "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 += " <b>Fingerprints:</b><br>"
|
||||
temp += " [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>"
|
||||
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.overlays += "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 += " <b>Fingerprints:</b><br>"
|
||||
P.info += " [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
|
||||
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>"
|
||||
temp += " [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>"
|
||||
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.overlays += "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 += " <b>Fingerprints:</b><br>"
|
||||
P.info += " [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
|
||||
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.overlays += "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"
|
||||
suit_fibers += "Material from a pair of [M.gloves.name]."
|
||||
@@ -1,4 +1,4 @@
|
||||
//CONTAINS: Evidence bags and fingerprint cards
|
||||
//CONTAINS: Evidence bags
|
||||
|
||||
/obj/item/weapon/evidencebag
|
||||
name = "evidence bag"
|
||||
@@ -8,17 +8,22 @@
|
||||
item_state = ""
|
||||
w_class = 1
|
||||
|
||||
/obj/item/weapon/evidencebag/afterattack(obj/item/I, mob/user as mob, proximity)
|
||||
if(!proximity) return
|
||||
if(!in_range(I, user))
|
||||
/obj/item/weapon/evidencebag/afterattack(obj/item/I, mob/user,proximity)
|
||||
if(!proximity || loc == I)
|
||||
return
|
||||
evidencebagEquip(I, user)
|
||||
|
||||
/obj/item/weapon/evidencebag/attackby(obj/item/I, mob/user)
|
||||
if(evidencebagEquip(I, user))
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/evidencebag/proc/evidencebagEquip(obj/item/I, mob/user)
|
||||
if(!istype(I) || I.anchored == 1)
|
||||
return ..()
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/weapon/evidencebag))
|
||||
user << "<span class='notice'>You find putting an evidence bag in another evidence bag to be slightly absurd.</span>"
|
||||
return
|
||||
return 1 //now this is podracing
|
||||
|
||||
if(I.w_class > 3)
|
||||
user << "<span class='notice'>[I] won't fit in [src].</span>"
|
||||
@@ -26,7 +31,7 @@
|
||||
|
||||
if(contents.len)
|
||||
user << "<span class='notice'>[src] already has something inside it.</span>"
|
||||
return ..()
|
||||
return
|
||||
|
||||
if(!isturf(I.loc)) //If it isn't on the floor. Do some checks to see if it's in our hands or a box. Otherwise give up.
|
||||
if(istype(I.loc,/obj/item/weapon/storage)) //in a container.
|
||||
@@ -40,8 +45,8 @@
|
||||
else
|
||||
return
|
||||
|
||||
user.visible_message("[user] puts [I] into [src]", "You put [I] inside [src].",\
|
||||
"You hear a rustle as someone puts something into a plastic bag.")
|
||||
user.visible_message("<span class='notice'>[user] puts [I] into [src].</span>", "<span class='notice'>You put [I] inside [src].</span>",\
|
||||
"<span class='notice'>You hear a rustle as someone puts something into a plastic bag.</span>")
|
||||
|
||||
icon_state = "evidence"
|
||||
|
||||
@@ -58,14 +63,13 @@
|
||||
desc = "An evidence bag containing [I]. [I.desc]"
|
||||
I.loc = src
|
||||
w_class = I.w_class
|
||||
return
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/evidencebag/attack_self(mob/user as mob)
|
||||
if(contents.len)
|
||||
var/obj/item/I = contents[1]
|
||||
user.visible_message("[user] takes [I] out of [src]", "You take [I] out of [src].",\
|
||||
"You hear someone rustle around in a plastic bag, and remove something.")
|
||||
user.visible_message("<span class='notice'>[user] takes [I] out of [src].</span>", "<span class='notice'>You take [I] out of [src].</span>",\
|
||||
"<span class='notice'>You hear someone rustle around in a plastic bag, and remove something.</span>")
|
||||
overlays.Cut() //remove the overlays
|
||||
user.put_in_hands(I)
|
||||
w_class = 1
|
||||
@@ -88,24 +92,4 @@
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/f_card
|
||||
name = "finger print card"
|
||||
desc = "Used to take fingerprints."
|
||||
icon = 'icons/obj/card.dmi'
|
||||
icon_state = "fingerprint0"
|
||||
var/amount = 10.0
|
||||
item_state = "paper"
|
||||
throwforce = 1
|
||||
w_class = 1.0
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
|
||||
|
||||
/obj/item/weapon/fcardholder
|
||||
name = "fingerprint card case"
|
||||
desc = "Apply finger print card."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "fcardholder0"
|
||||
item_state = "clipboard"
|
||||
return
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/mob
|
||||
var/bloody_hands = 0
|
||||
var/mob/living/carbon/human/bloody_hands_mob
|
||||
@@ -26,19 +27,16 @@
|
||||
can_be_placed_into = null
|
||||
flags = FPRINT | TABLEPASS | OPENCONTAINER | NOBLUDGEON
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/rag/attack_self(mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/rag/attack(atom/target as obj|turf|area, mob/user as mob , flag)
|
||||
if(ismob(target) && target.reagents && reagents.total_volume)
|
||||
user.visible_message("\red \The [target] has been smothered with \the [src] by \the [user]!", "\red You smother \the [target] with \the [src]!", "You hear some struggling and muffled cries of surprise")
|
||||
user.visible_message("<span class='danger'>[user] has smothered \the [target] with \the [src]!</span>", "<span class='danger'>You smother \the [target] with \the [src]!</span>", "You hear some struggling and muffled cries of surprise")
|
||||
src.reagents.reaction(target, TOUCH)
|
||||
spawn(5) src.reagents.clear_reagents()
|
||||
src.reagents.clear_reagents()
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob, proximity)
|
||||
/obj/item/weapon/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob,proximity)
|
||||
if(!proximity) return
|
||||
if(istype(A) && src in user)
|
||||
user.visible_message("[user] starts to wipe down [A] with [src]!")
|
||||
@@ -46,10 +44,3 @@
|
||||
user.visible_message("[user] finishes wiping off the [A]!")
|
||||
A.clean_blood()
|
||||
return
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/rag/examine()
|
||||
if (!usr)
|
||||
return
|
||||
usr << "That's \a [src]."
|
||||
usr << desc
|
||||
return
|
||||
@@ -9,7 +9,7 @@
|
||||
while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. vox wearing jumpsuits).
|
||||
*/
|
||||
var/list/sprite_sheets_refit = null
|
||||
|
||||
|
||||
//BS12: Species-restricted clothing check.
|
||||
/obj/item/clothing/mob_can_equip(M as mob, slot)
|
||||
|
||||
@@ -53,12 +53,12 @@
|
||||
icon_override = sprite_sheets[target_species]
|
||||
else
|
||||
icon_override = initial(icon_override)
|
||||
|
||||
|
||||
if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
|
||||
icon = sprite_sheets_obj[target_species]
|
||||
else
|
||||
icon = initial(icon)
|
||||
|
||||
|
||||
//Ears: currently only used for headsets and earmuffs
|
||||
/obj/item/clothing/ears
|
||||
name = "ears"
|
||||
@@ -153,6 +153,7 @@ BLIND // can't see anything
|
||||
body_parts_covered = HANDS
|
||||
slot_flags = SLOT_GLOVES
|
||||
attack_verb = list("challenged")
|
||||
var/transfer_prints = FALSE
|
||||
var/pickpocket = 0 //Master pickpocket?
|
||||
var/clipped = 0
|
||||
species_restricted = list("exclude","Unathi","Tajaran")
|
||||
@@ -181,7 +182,7 @@ BLIND // can't see anything
|
||||
set src in usr
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/clothing/under/proc/set_sensors(mob/usr as mob)
|
||||
var/mob/M = usr
|
||||
if (istype(M, /mob/dead/)) return
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
siemens_coefficient = 0.30
|
||||
permeability_coefficient = 0.01
|
||||
_color="white"
|
||||
transfer_prints = TRUE
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/mask.dmi'
|
||||
|
||||
@@ -1,401 +0,0 @@
|
||||
//CONTAINS: Detective's Scanner
|
||||
|
||||
|
||||
/obj/item/device/detective_scanner
|
||||
name = "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 splaters.
|
||||
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 No intact prints found"
|
||||
else
|
||||
user << "\blue Found [complete_prints.len] intact prints"
|
||||
for(var/i in complete_prints)
|
||||
user << "\blue [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
|
||||
return 0
|
||||
|
||||
/obj/item/device/detective_scanner/forger
|
||||
var/list/custom_forgery[3]
|
||||
var/forging = 0
|
||||
|
||||
New()
|
||||
..()
|
||||
custom_forgery[1] = list()
|
||||
custom_forgery[2] = list()
|
||||
custom_forgery[3] = list()
|
||||
|
||||
attack_self(var/mob/user as mob)
|
||||
var/list/customprints = list()
|
||||
var/list/customfiber = list()
|
||||
var/list/customblood = list()
|
||||
if(forging)
|
||||
user << "\red You are already forging evidence"
|
||||
return 0
|
||||
clear_forgery()
|
||||
//fingerprint loop
|
||||
while(1)
|
||||
var/print = html_encode(input(usr,"Please enter a custom fingerprint or hit cancel to finish fingerprints") as text|null)
|
||||
if(!usr.client)
|
||||
forging = 0
|
||||
break
|
||||
if(!print )
|
||||
break
|
||||
customprints[print] = print
|
||||
while(1)
|
||||
var/fiber = html_encode(input(usr,"Please enter a custom fiber/material trace or hit cancel to finish fibers/materials") as text|null)
|
||||
if(!usr.client)
|
||||
forging = 0
|
||||
break
|
||||
if(!fiber)
|
||||
break
|
||||
customfiber[fiber] = null
|
||||
while(1)
|
||||
var/blood = html_encode(input(usr,"Please enter a custom Blood DNA or hit cancel to finish forging") as text|null)
|
||||
var/bloodtype = html_encode(input(usr,"Please enter a custom Blood Type") as text|null)
|
||||
if(!usr.client)
|
||||
forging = 0
|
||||
break
|
||||
if(!blood)
|
||||
break
|
||||
customblood[blood] = bloodtype
|
||||
forging = 0
|
||||
if(!customprints.len && !customfiber.len)
|
||||
user << "\blue No forgery saved."
|
||||
return
|
||||
user << "\blue Forgery saved and will be tied to the next applicable scanned item."
|
||||
custom_forgery[1] = customprints ? customprints.Copy() : null
|
||||
custom_forgery[2] = customfiber ? customfiber.Copy() : null
|
||||
custom_forgery[3] = customblood ? customblood.Copy() : null
|
||||
|
||||
//shameless copy pasting
|
||||
afterattack(atom/A as obj|turf|area, mob/user as mob)
|
||||
var/list/custom_finger = list()
|
||||
var/list/custom_fiber = list()
|
||||
var/list/custom_blood = list()
|
||||
|
||||
if(custom_forgery)
|
||||
custom_finger = custom_forgery[1]
|
||||
custom_fiber = custom_forgery[2]
|
||||
custom_blood = custom_forgery[3]
|
||||
|
||||
if(!in_range(A,user))
|
||||
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.\""
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
//Special case for blood splaters.
|
||||
if (istype(A, /obj/effect/decal/cleanable/blood) || istype(A, /obj/effect/rune))
|
||||
if(!isnull(A.blood_DNA))
|
||||
for(var/blood in A.blood_DNA)
|
||||
user << "\blue Blood type: [A.blood_DNA[blood]]\nDNA: [blood]"
|
||||
return
|
||||
|
||||
//General
|
||||
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
|
||||
if(!custom_finger.len && !custom_fiber.len && !custom_blood.len)
|
||||
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.")
|
||||
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." : "."]" ,\
|
||||
"\blue Unable to locate any fingerprints, materials, fibers, or blood on [A], loading custom forgery instead.",\
|
||||
"You hear a faint hum of electrical equipment.")
|
||||
|
||||
|
||||
if(add_data(A))
|
||||
user << "\blue Object already in internal memory. Consolidating data..."
|
||||
return
|
||||
|
||||
|
||||
//PRINTS
|
||||
if(!A.fingerprints || !A.fingerprints.len)
|
||||
if(A.fingerprints)
|
||||
del(A.fingerprints)
|
||||
if(custom_finger.len)
|
||||
user << "\blue Isolated [custom_finger.len] fingerprints: Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
|
||||
user << "\blue Found [custom_finger.len] intact prints"
|
||||
for(var/i in custom_finger)
|
||||
user << "\blue [i]"
|
||||
else if(A.fingerprints && A.fingerprints.len)
|
||||
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 No intact prints found"
|
||||
else
|
||||
user << "\blue Found [complete_prints.len] intact prints"
|
||||
for(var/i in complete_prints)
|
||||
user << "\blue [i]"
|
||||
|
||||
//FIBERS
|
||||
if(custom_fiber.len)
|
||||
user << "\blue Forged Fibers/Materials Data Found: Scan with Hi-Res Forensic Scanner to retrieve."
|
||||
else if(A.suit_fibers)
|
||||
user << "\blue Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
|
||||
|
||||
|
||||
//Blood
|
||||
if(custom_blood.len)
|
||||
user << "\blue Forged Blood found. Analysing..."
|
||||
spawn(15)
|
||||
for(var/blood in custom_blood)
|
||||
user << "Blood type: \red [custom_blood[blood]] \t \black DNA: \red [blood]"
|
||||
else 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]"
|
||||
return
|
||||
|
||||
add_data(atom/A as mob|obj|turf|area)
|
||||
//I love associative lists.
|
||||
var/list/data_entry = stored["\ref [A]"]
|
||||
var/list/custom_finger = list()
|
||||
var/list/custom_fiber = list()
|
||||
var/list/custom_blood = list()
|
||||
|
||||
if(custom_forgery)
|
||||
custom_finger = custom_forgery[1]
|
||||
custom_fiber = custom_forgery[2]
|
||||
custom_blood = custom_forgery[3]
|
||||
|
||||
if(islist(data_entry)) //Yay, it was already stored!
|
||||
//Merge the fingerprints.
|
||||
var/list/data_prints = data_entry[1]
|
||||
if(custom_finger.len)
|
||||
for(var/print in custom_finger)
|
||||
var/merged_print = data_prints[print]
|
||||
if(!merged_print)
|
||||
data_prints[print] = custom_finger
|
||||
else
|
||||
data_prints[print] = stringmerge(data_prints[print],custom_finger[print])
|
||||
else
|
||||
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(custom_fiber.len)
|
||||
for(var/j = 1, j <= custom_fiber.len, j++) //Fibers~~~
|
||||
if(!fibers.Find(custom_fiber[j])) //It isn't! Add!
|
||||
fibers += custom_fiber[j]
|
||||
|
||||
else 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(custom_blood.len)
|
||||
for(var/main_blood in custom_blood)
|
||||
if(!blood[main_blood])
|
||||
blood[main_blood] = custom_blood[blood]
|
||||
else 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!
|
||||
if(custom_finger.len || custom_fiber.len || custom_blood.len)
|
||||
sum_list[1] = custom_finger ? custom_finger.Copy() : null
|
||||
sum_list[2] = custom_fiber ? custom_fiber.Copy() : null
|
||||
sum_list[3] = custom_blood ? custom_blood.Copy() : null
|
||||
else
|
||||
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
|
||||
clear_forgery()
|
||||
return 0
|
||||
|
||||
proc/clear_forgery()
|
||||
if(custom_forgery.len)
|
||||
custom_forgery[1] = list()
|
||||
custom_forgery[2] = list()
|
||||
custom_forgery[3] = list()
|
||||
@@ -73,7 +73,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
|
||||
// Damaged heart virtually reduces the blood volume, as the blood isn't
|
||||
// being pumped properly anymore.
|
||||
var/datum/organ/internal/heart/heart = internal_organs_by_name["heart"]
|
||||
|
||||
|
||||
if(heart)
|
||||
if(heart.damage > 1 && heart.damage < heart.min_bruised_damage)
|
||||
blood_volume *= 0.8
|
||||
@@ -314,13 +314,13 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
|
||||
return D
|
||||
return res
|
||||
|
||||
proc/blood_incompatible(donor,receiver)
|
||||
if(!donor || !receiver) return 0
|
||||
var
|
||||
donor_antigen = copytext(donor,1,lentext(donor))
|
||||
receiver_antigen = copytext(receiver,1,lentext(receiver))
|
||||
donor_rh = (findtext(donor,"+")>0)
|
||||
receiver_rh = (findtext(receiver,"+")>0)
|
||||
/proc/blood_incompatible(donor,receiver)
|
||||
|
||||
var/donor_antigen = copytext(donor,1,lentext(donor))
|
||||
var/receiver_antigen = copytext(receiver,1,lentext(receiver))
|
||||
var/donor_rh = findtext("+",donor)
|
||||
var/receiver_rh = findtext("+",receiver)
|
||||
|
||||
if(donor_rh && !receiver_rh) return 1
|
||||
switch(receiver_antigen)
|
||||
if("A")
|
||||
|
||||
Reference in New Issue
Block a user