This commit is contained in:
Fox-McCloud
2014-12-17 08:17:27 -05:00
parent 4eff415d2f
commit 337dc8e448
+143 -371
View File
@@ -1,401 +1,173 @@
//CONTAINS: Detective's Scanner
// TODO: Split everything into easy to manage procs.
/obj/item/device/detective_scanner
name = "Scanner"
desc = "Used to scan objects for DNA and fingerprints."
name = "forensic scanner"
desc = "Used to remotely scan objects and biomass for DNA and fingerprints. Can print a report of the findings."
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
var/scanning = 0
var/list/log = list()
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
/obj/item/device/detective_scanner/attack_self(var/mob/user)
if(log.len && !scanning)
scanning = 1
user << "<span class='notice'>Printing report, please wait...</span>"
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]'")
spawn(100)
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
// Create our paper
var/obj/item/weapon/paper/P = new(get_turf(src))
P.name = "paper- 'Scanner Report'"
P.info = "<center><font size='6'><B>Scanner Report</B></font></center><HR><BR>"
P.info += list2text(log, "<BR>")
P.info += "<HR><B>Notes:</B><BR>"
P.info_links = P.info
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
if(ismob(loc))
var/mob/M = loc
M.put_in_hands(P)
M << "<span class='notice'>Report printed. Log cleared.<span>"
add_fingerprint(user)
// Clear the logs
log = list()
scanning = 0
else
user << "<span class='notice'>The scanner has no logs or is in use.</span>"
/obj/item/device/detective_scanner/attack(mob/living/M as mob, mob/user as mob)
return
//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
/obj/item/device/detective_scanner/afterattack(atom/A, mob/user as mob, proximity)
scan(A, 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." : "."]" ,\
"\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
/obj/item/device/detective_scanner/proc/scan(var/atom/A, var/mob/user)
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
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))
if(!scanning)
// Can remotely scan objects and mobs.
if(!in_range(A, user) && !(A in view(world.view, 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)
scanning = 1
user.visible_message("\The [user] points the [src.name] at \the [A] and performs a forensic scan.")
user << "<span class='notice'>You scan \the [A]. The scanner is now analysing the results...</span>"
//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
// GATHER INFORMATION
//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
//Make our lists
var/list/fingerprints = list()
var/list/blood = list()
var/list/fibers = list()
var/list/reagents = list()
var/target_name = A.name
// Start gathering
if(A.blood_DNA && A.blood_DNA.len)
blood = A.blood_DNA.Copy()
if(A.suit_fibers && A.suit_fibers.len)
fibers = A.suit_fibers.Copy()
if(ishuman(A))
var/mob/living/carbon/human/H = A
if (istype(H.dna, /datum/dna) && !H.gloves)
fingerprints += md5(H.dna.uni_identity)
else if(!ismob(A))
if(A.fingerprints && A.fingerprints.len)
fingerprints = A.fingerprints.Copy()
// Only get reagents from non-mobs.
if(A.reagents && A.reagents.reagent_list.len)
for(var/datum/reagent/R in A.reagents.reagent_list)
reagents[R.name] = R.volume
// Get blood data from the blood reagent.
if(istype(R, /datum/reagent/blood))
if(R.data["blood_DNA"] && R.data["blood_type"])
var/blood_DNA = R.data["blood_DNA"]
var/blood_type = R.data["blood_type"]
blood[blood_DNA] = blood_type
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
spawn(0)
var/found_something = 0
add_log("<B>[worldtime2text()][get_timestamp()] - [target_name]</B>", 0)
// Fingerprints
if(fingerprints && fingerprints.len)
sleep(30)
add_log("<span class='info'><B>Prints:</B></span>")
for(var/finger in fingerprints)
add_log("[finger]")
found_something = 1
// Blood
if (blood && blood.len)
sleep(30)
add_log("<span class='info'><B>Blood:</B></span>")
found_something = 1
for(var/B in blood)
add_log("Type: <font color='red'>[blood[B]]</font> DNA: <font color='red'>[B]</font>")
//Fibers
if(fibers && fibers.len)
sleep(30)
add_log("<span class='info'><B>Fibers:</B></span>")
for(var/fiber in fibers)
add_log("[fiber]")
found_something = 1
//Reagents
if(reagents && reagents.len)
sleep(30)
add_log("<span class='info'><B>Reagents:</B></span>")
for(var/R in reagents)
add_log("Reagent: <font color='red'>[R]</font> Volume: <font color='red'>[reagents[R]]</font>")
found_something = 1
// Get a new user
var/mob/holder = null
if(ismob(src.loc))
holder = src.loc
if(!found_something)
add_log("<I># No forensic traces found #</I>", 0) // Don't display this to the holder user
if(holder)
holder << "<span class='notice'>Unable to locate any fingerprints, materials, fibers, or blood on \the [target_name]!</span>"
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(holder)
holder << "<span class='notice'>You finish scanning \the [target_name].</span>"
if(add_data(A))
user << "\blue Object already in internal memory. Consolidating data..."
add_log("---------------------------------------------------------", 0)
scanning = 0
return
/obj/item/device/detective_scanner/proc/add_log(var/msg, var/broadcast = 1)
if(scanning)
if(broadcast && ismob(loc))
var/mob/M = loc
M << msg
log += "&nbsp;&nbsp;[msg]"
else
CRASH("[src] \ref[src] is adding a log when it was never put in scanning mode!")
//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 &nbsp;&nbsp;Found [custom_finger.len] intact prints"
for(var/i in custom_finger)
user << "\blue &nbsp;&nbsp;&nbsp;&nbsp;[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 &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(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()
/proc/get_timestamp()
return time2text(world.time + 432000, ":ss")