Forensics Datum (#17796)

* forensics datum initial work

* typo fix

* glove recursion fix

* missing bloodtype on organ data

* removed frustrating and unneeded b_type var from humans

* no leaky

* listcheck

* documenting

* documentation
This commit is contained in:
Will
2025-06-05 23:30:11 -07:00
committed by GitHub
parent be6680da62
commit ae718f07e3
62 changed files with 603 additions and 400 deletions
-2
View File
@@ -1,6 +1,5 @@
/mob
var/bloody_hands = 0
var/mob/living/carbon/human/bloody_hands_mob
var/track_blood = 0
var/list/feet_blood_DNA
var/track_blood_type
@@ -8,7 +7,6 @@
/obj/item/clothing/gloves
var/transfer_blood = 0
var/mob/living/carbon/human/bloody_hands_mob
/obj/item/clothing/shoes/
var/track_blood = 0
+12 -10
View File
@@ -6,7 +6,7 @@
/obj/item/sample/Initialize(mapload, var/atom/supplied)
. = ..()
if(supplied)
if(supplied && supplied.forensic_data)
copy_evidence(supplied)
name = "[initial(name)] (\the [supplied])"
@@ -16,9 +16,10 @@
icon_state = "fingerprint1"
/obj/item/sample/proc/copy_evidence(var/atom/supplied)
if(supplied.suit_fibers && supplied.suit_fibers.len)
evidence = supplied.suit_fibers.Copy()
supplied.suit_fibers.Cut()
var/list/fibre_data = supplied.forensic_data.get_fibres()
if(fibre_data && fibre_data.len)
evidence = fibre_data.Copy()
supplied.forensic_data.clear_fibres()
/obj/item/sample/proc/merge_evidence(var/obj/item/sample/supplied, var/mob/user)
if(!supplied.evidence || !supplied.evidence.len)
@@ -116,10 +117,11 @@
return 0
/obj/item/sample/print/copy_evidence(var/atom/supplied)
if(supplied.fingerprints && supplied.fingerprints.len)
for(var/print in supplied.fingerprints)
evidence[print] = supplied.fingerprints[print]
supplied.fingerprints.Cut()
var/list/print_data = supplied.forensic_data.get_prints()
if(print_data && print_data.len)
for(var/print in print_data)
evidence[print] = print_data[print]
supplied.forensic_data.clear_prints()
/obj/item/forensics/sample_kit
name = "fiber collection kit"
@@ -130,7 +132,7 @@
var/evidence_path = /obj/item/sample/fibers
/obj/item/forensics/sample_kit/proc/can_take_sample(var/mob/user, var/atom/supplied)
return (supplied.suit_fibers && supplied.suit_fibers.len)
return supplied.forensic_data?.has_fibres()
/obj/item/forensics/sample_kit/proc/take_sample(var/mob/user, var/atom/supplied)
var/obj/item/sample/S = new evidence_path(get_turf(user), supplied)
@@ -155,4 +157,4 @@
evidence_path = /obj/item/sample/print
/obj/item/forensics/sample_kit/powder/can_take_sample(var/mob/user, var/atom/supplied)
return (supplied.fingerprints && supplied.fingerprints.len)
return supplied.forensic_data?.has_prints()
+16 -13
View File
@@ -34,11 +34,12 @@
to_chat(user, span_notice("Done printing."))
// to_chat(user, span_notice("[M]'s Fingerprints: [md5(M.dna.uni_identity)]"))
if(reveal_blood && M.blood_DNA && M.blood_DNA.len)
if(reveal_blood && M.forensic_data?.has_blooddna())
to_chat(user, span_notice("Blood found on [M]. Analysing..."))
spawn(15)
for(var/blood in M.blood_DNA)
to_chat(user, span_notice("Blood type: [M.blood_DNA[blood]]\nDNA: [blood]"))
var/list/blooddna = M.forensic_data.get_blooddna()
for(var/blood in blooddna)
to_chat(user, span_notice("Blood type: [blooddna[blood]]\nDNA: [blood]"))
return
/obj/item/detective_scanner/afterattack(atom/A as obj|turf, mob/user, proximity)
@@ -67,7 +68,7 @@
return 0
//General
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
if (!A.forensic_data?.has_prints() && !A.forensic_data?.has_fibres() && !A.forensic_data.has_blooddna())
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
span_warning("Unable to locate any fingerprints, materials, fibers, or blood on [A]!"),\
"You hear a faint hum of electrical equipment.")
@@ -80,14 +81,15 @@
return
//PRINTS
if(A.fingerprints && A.fingerprints.len)
to_chat(user, span_notice("Isolated [A.fingerprints.len] fingerprints:"))
if(A.forensic_data?.has_prints())
to_chat(user, span_notice("Isolated [A.forensic_data?.get_prints().len] fingerprints:"))
if(!reveal_incompletes)
to_chat(user, span_warning("Rapid Analysis Imperfect: Scan samples with H.R.F.S. equipment to determine nature of incomplete prints."))
var/list/complete_prints = list()
var/list/incomplete_prints = list()
for(var/i in A.fingerprints)
var/print = A.fingerprints[i]
var/list/print_data = A.forensic_data?.get_prints()
for(var/i in print_data)
var/print = print_data[i]
if(stringpercent(print) <= FINGERPRINT_COMPLETE)
complete_prints += print
else
@@ -107,21 +109,22 @@
//FIBERS
if(A.suit_fibers && A.suit_fibers.len)
if(A.forensic_data?.has_fibres())
to_chat(user,span_notice("Fibers/Materials detected.[reveal_fibers ? " Analysing..." : " Acquisition of fibers for H.R.F.S. analysis advised."]"))
flick("[icon_state]1",src)
if(reveal_fibers && do_after(user, 5 SECONDS))
to_chat(user, span_notice("Apparel samples scanned:"))
for(var/sample in A.suit_fibers)
for(var/sample in A.forensic_data.get_fibres())
to_chat(user, " - " + span_notice("[sample]"))
//Blood
if (A.blood_DNA && A.blood_DNA.len)
if (A.forensic_data?.has_blooddna())
to_chat(user, span_notice("Blood detected.[reveal_blood ? " Analysing..." : " Acquisition of swab for H.R.F.S. analysis advised."]"))
if(reveal_blood && do_after(user, 5 SECONDS))
flick("[icon_state]1",src)
for(var/blood in A.blood_DNA)
to_chat(user, "Blood type: " + span_warning("[A.blood_DNA[blood]]") + " DNA: " + span_warning("[blood]"))
var/list/blood_data = A.forensic_data.get_blooddna()
for(var/blood in blood_data)
to_chat(user, "Blood type: " + span_warning("[blood_data[blood]]") + " DNA: " + span_warning("[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_notice("You finish scanning \the [A]."),\
+6 -6
View File
@@ -59,7 +59,7 @@
return
user.visible_message("[user] swabs [H]'s palm for a sample.")
sample_type = "GSR"
gsr = H.gunshot_residue
gsr = H.forensic_data?.get_gunshotresidue()
else
return
@@ -80,7 +80,7 @@
add_fingerprint(user)
var/list/choices = list()
if(A.blood_DNA)
if(A.forensic_data?.has_blooddna())
choices |= "Blood"
if(istype(A, /obj/item/clothing))
choices |= "Gunshot Residue"
@@ -99,16 +99,16 @@
var/sample_type
if(choice == "Blood")
if(!A.blood_DNA || !A.blood_DNA.len) return
dna = A.blood_DNA.Copy()
if(!A.forensic_data?.has_blooddna()) return
dna = A.forensic_data?.get_blooddna().Copy()
sample_type = "blood"
else if(choice == "Gunshot Residue")
var/obj/item/clothing/B = A
if(!istype(B) || !B.gunshot_residue)
if(!istype(B) || !B.forensic_data?.get_gunshotresidue())
to_chat(user, span_warning("There is no residue on \the [A]."))
return
gsr = B.gunshot_residue
gsr = B.forensic_data?.get_gunshotresidue()
sample_type = "residue"
if(sample_type)