Force LF line endings with gitattributes and convert repo (#52266)

Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
jdawg1290
2020-07-16 03:02:40 +03:00
committed by GitHub
co-authored by Aleksej Komarov
parent 39e8bd721f
commit 62676e72a8
1133 changed files with 266492 additions and 266454 deletions
+102 -102
View File
@@ -1,102 +1,102 @@
//CONTAINS: Suit fibers and Detective's Scanning Computer
/atom/proc/return_fingerprints()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.fingerprints
/atom/proc/return_hiddenprints()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.hiddenprints
/atom/proc/return_blood_DNA()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.blood_DNA
/atom/proc/blood_DNA_length()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = length(D.blood_DNA)
/atom/proc/return_fibers()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.fibers
/atom/proc/add_fingerprint_list(list/fingerprints) //ASSOC LIST FINGERPRINT = FINGERPRINT
if(length(fingerprints))
. = AddComponent(/datum/component/forensics, fingerprints)
//Set ignoregloves to add prints irrespective of the mob having gloves on.
/atom/proc/add_fingerprint(mob/M, ignoregloves = FALSE)
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_fingerprint(M, ignoregloves)
/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT
if(length(fibertext))
. = AddComponent(/datum/component/forensics, null, null, null, fibertext)
/atom/proc/add_fibers(mob/living/carbon/human/M)
var/old = 0
if(M.gloves && istype(M.gloves, /obj/item/clothing))
var/obj/item/clothing/gloves/G = M.gloves
old = length(G.return_blood_DNA())
if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
else if(M.bloody_hands > 1)
old = length(M.return_blood_DNA())
if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old)
M.bloody_hands--
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_fibers(M)
/atom/proc/add_hiddenprint_list(list/hiddenprints) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM
if(length(hiddenprints))
. = AddComponent(/datum/component/forensics, null, hiddenprints)
/atom/proc/add_hiddenprint(mob/M)
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_hiddenprint(M)
/atom/proc/add_blood_DNA(list/dna) //ASSOC LIST DNA = BLOODTYPE
return FALSE
/obj/add_blood_DNA(list/dna)
. = ..()
if(length(dna))
. = AddComponent(/datum/component/forensics, null, null, dna)
/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
. = ..()
transfer_blood = rand(2, 4)
/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
return TRUE //we bloodied the floor
/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
if(wear_suit)
wear_suit.add_blood_DNA(blood_dna)
update_inv_wear_suit()
else if(w_uniform)
w_uniform.add_blood_DNA(blood_dna)
update_inv_w_uniform()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
G.add_blood_DNA(blood_dna)
else if(length(blood_dna))
AddComponent(/datum/component/forensics, null, null, blood_dna)
bloody_hands = rand(2, 4)
update_inv_gloves() //handles bloody hands overlays and updating
return TRUE
/atom/proc/transfer_fingerprints_to(atom/A)
A.add_fingerprint_list(return_fingerprints())
A.add_hiddenprint_list(return_hiddenprints())
A.fingerprintslast = fingerprintslast
//CONTAINS: Suit fibers and Detective's Scanning Computer
/atom/proc/return_fingerprints()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.fingerprints
/atom/proc/return_hiddenprints()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.hiddenprints
/atom/proc/return_blood_DNA()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.blood_DNA
/atom/proc/blood_DNA_length()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = length(D.blood_DNA)
/atom/proc/return_fibers()
var/datum/component/forensics/D = GetComponent(/datum/component/forensics)
if(D)
. = D.fibers
/atom/proc/add_fingerprint_list(list/fingerprints) //ASSOC LIST FINGERPRINT = FINGERPRINT
if(length(fingerprints))
. = AddComponent(/datum/component/forensics, fingerprints)
//Set ignoregloves to add prints irrespective of the mob having gloves on.
/atom/proc/add_fingerprint(mob/M, ignoregloves = FALSE)
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_fingerprint(M, ignoregloves)
/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT
if(length(fibertext))
. = AddComponent(/datum/component/forensics, null, null, null, fibertext)
/atom/proc/add_fibers(mob/living/carbon/human/M)
var/old = 0
if(M.gloves && istype(M.gloves, /obj/item/clothing))
var/obj/item/clothing/gloves/G = M.gloves
old = length(G.return_blood_DNA())
if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
else if(M.bloody_hands > 1)
old = length(M.return_blood_DNA())
if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old)
M.bloody_hands--
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_fibers(M)
/atom/proc/add_hiddenprint_list(list/hiddenprints) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM
if(length(hiddenprints))
. = AddComponent(/datum/component/forensics, null, hiddenprints)
/atom/proc/add_hiddenprint(mob/M)
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_hiddenprint(M)
/atom/proc/add_blood_DNA(list/dna) //ASSOC LIST DNA = BLOODTYPE
return FALSE
/obj/add_blood_DNA(list/dna)
. = ..()
if(length(dna))
. = AddComponent(/datum/component/forensics, null, null, dna)
/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
. = ..()
transfer_blood = rand(2, 4)
/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
return TRUE //we bloodied the floor
/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
if(wear_suit)
wear_suit.add_blood_DNA(blood_dna)
update_inv_wear_suit()
else if(w_uniform)
w_uniform.add_blood_DNA(blood_dna)
update_inv_w_uniform()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
G.add_blood_DNA(blood_dna)
else if(length(blood_dna))
AddComponent(/datum/component/forensics, null, null, blood_dna)
bloody_hands = rand(2, 4)
update_inv_gloves() //handles bloody hands overlays and updating
return TRUE
/atom/proc/transfer_fingerprints_to(atom/A)
A.add_fingerprint_list(return_fingerprints())
A.add_hiddenprint_list(return_hiddenprints())
A.fingerprintslast = fingerprintslast
+97 -97
View File
@@ -1,97 +1,97 @@
//CONTAINS: Evidence bags
/obj/item/evidencebag
name = "evidence bag"
desc = "An empty evidence bag."
icon = 'icons/obj/storage.dmi'
icon_state = "evidenceobj"
inhand_icon_state = ""
w_class = WEIGHT_CLASS_TINY
/obj/item/evidencebag/afterattack(obj/item/I, mob/user,proximity)
. = ..()
if(!proximity || loc == I)
return
evidencebagEquip(I, user)
/obj/item/evidencebag/attackby(obj/item/I, mob/user, params)
if(evidencebagEquip(I, user))
return 1
/obj/item/evidencebag/handle_atom_del(atom/A)
cut_overlays()
w_class = initial(w_class)
icon_state = initial(icon_state)
desc = initial(desc)
/obj/item/evidencebag/proc/evidencebagEquip(obj/item/I, mob/user)
if(!istype(I) || I.anchored == 1)
return
if(SEND_SIGNAL(loc, COMSIG_CONTAINS_STORAGE) && SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE))
to_chat(user, "<span class='warning'>No matter what way you try, you can't get [I] to fit inside [src].</span>")
return TRUE //begone infinite storage ghosts, begone from me
if(istype(I, /obj/item/evidencebag))
to_chat(user, "<span class='warning'>You find putting an evidence bag in another evidence bag to be slightly absurd.</span>")
return TRUE //now this is podracing
if(loc in I.GetAllContents()) // fixes tg #39452, evidence bags could store their own location, causing I to be stored in the bag while being present inworld still, and able to be teleported when removed.
to_chat(user, "<span class='warning'>You find putting [I] in [src] while it's still inside it quite difficult!</span>")
return
if(I.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user, "<span class='warning'>[I] won't fit in [src]!</span>")
return
if(contents.len)
to_chat(user, "<span class='warning'>[src] already has something inside it!</span>")
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(SEND_SIGNAL(I.loc, COMSIG_CONTAINS_STORAGE)) //in a container.
SEND_SIGNAL(I.loc, COMSIG_TRY_STORAGE_TAKE, I, src)
if(!user.dropItemToGround(I))
return
user.visible_message("<span class='notice'>[user] puts [I] into [src].</span>", "<span class='notice'>You put [I] inside [src].</span>",\
"<span class='hear'>You hear a rustle as someone puts something into a plastic bag.</span>")
icon_state = "evidence"
var/mutable_appearance/in_evidence = new(I)
in_evidence.plane = FLOAT_PLANE
in_evidence.layer = FLOAT_LAYER
in_evidence.pixel_x = 0
in_evidence.pixel_y = 0
add_overlay(in_evidence)
add_overlay("evidence") //should look nicer for transparent stuff. not really that important, but hey.
desc = "An evidence bag containing [I]. [I.desc]"
I.forceMove(src)
w_class = I.w_class
return 1
/obj/item/evidencebag/attack_self(mob/user)
if(contents.len)
var/obj/item/I = contents[1]
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='hear'>You hear someone rustle around in a plastic bag, and remove something.</span>")
cut_overlays() //remove the overlays
user.put_in_hands(I)
w_class = WEIGHT_CLASS_TINY
icon_state = "evidenceobj"
desc = "An empty evidence bag."
else
to_chat(user, "<span class='notice'>[src] is empty.</span>")
icon_state = "evidenceobj"
return
/obj/item/storage/box/evidence
name = "evidence bag box"
desc = "A box claiming to contain evidence bags."
/obj/item/storage/box/evidence/PopulateContents()
for(var/i in 1 to 6)
new /obj/item/evidencebag(src)
//CONTAINS: Evidence bags
/obj/item/evidencebag
name = "evidence bag"
desc = "An empty evidence bag."
icon = 'icons/obj/storage.dmi'
icon_state = "evidenceobj"
inhand_icon_state = ""
w_class = WEIGHT_CLASS_TINY
/obj/item/evidencebag/afterattack(obj/item/I, mob/user,proximity)
. = ..()
if(!proximity || loc == I)
return
evidencebagEquip(I, user)
/obj/item/evidencebag/attackby(obj/item/I, mob/user, params)
if(evidencebagEquip(I, user))
return 1
/obj/item/evidencebag/handle_atom_del(atom/A)
cut_overlays()
w_class = initial(w_class)
icon_state = initial(icon_state)
desc = initial(desc)
/obj/item/evidencebag/proc/evidencebagEquip(obj/item/I, mob/user)
if(!istype(I) || I.anchored == 1)
return
if(SEND_SIGNAL(loc, COMSIG_CONTAINS_STORAGE) && SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE))
to_chat(user, "<span class='warning'>No matter what way you try, you can't get [I] to fit inside [src].</span>")
return TRUE //begone infinite storage ghosts, begone from me
if(istype(I, /obj/item/evidencebag))
to_chat(user, "<span class='warning'>You find putting an evidence bag in another evidence bag to be slightly absurd.</span>")
return TRUE //now this is podracing
if(loc in I.GetAllContents()) // fixes tg #39452, evidence bags could store their own location, causing I to be stored in the bag while being present inworld still, and able to be teleported when removed.
to_chat(user, "<span class='warning'>You find putting [I] in [src] while it's still inside it quite difficult!</span>")
return
if(I.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user, "<span class='warning'>[I] won't fit in [src]!</span>")
return
if(contents.len)
to_chat(user, "<span class='warning'>[src] already has something inside it!</span>")
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(SEND_SIGNAL(I.loc, COMSIG_CONTAINS_STORAGE)) //in a container.
SEND_SIGNAL(I.loc, COMSIG_TRY_STORAGE_TAKE, I, src)
if(!user.dropItemToGround(I))
return
user.visible_message("<span class='notice'>[user] puts [I] into [src].</span>", "<span class='notice'>You put [I] inside [src].</span>",\
"<span class='hear'>You hear a rustle as someone puts something into a plastic bag.</span>")
icon_state = "evidence"
var/mutable_appearance/in_evidence = new(I)
in_evidence.plane = FLOAT_PLANE
in_evidence.layer = FLOAT_LAYER
in_evidence.pixel_x = 0
in_evidence.pixel_y = 0
add_overlay(in_evidence)
add_overlay("evidence") //should look nicer for transparent stuff. not really that important, but hey.
desc = "An evidence bag containing [I]. [I.desc]"
I.forceMove(src)
w_class = I.w_class
return 1
/obj/item/evidencebag/attack_self(mob/user)
if(contents.len)
var/obj/item/I = contents[1]
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='hear'>You hear someone rustle around in a plastic bag, and remove something.</span>")
cut_overlays() //remove the overlays
user.put_in_hands(I)
w_class = WEIGHT_CLASS_TINY
icon_state = "evidenceobj"
desc = "An empty evidence bag."
else
to_chat(user, "<span class='notice'>[src] is empty.</span>")
icon_state = "evidenceobj"
return
/obj/item/storage/box/evidence
name = "evidence bag box"
desc = "A box claiming to contain evidence bags."
/obj/item/storage/box/evidence/PopulateContents()
for(var/i in 1 to 6)
new /obj/item/evidencebag(src)
@@ -1,45 +1,45 @@
/obj/item/clothing/gloves
var/transfer_blood = 0
/obj/item/reagent_containers/glass/rag
name = "damp rag"
desc = "For cleaning up messes, you suppose."
w_class = WEIGHT_CLASS_TINY
icon = 'icons/obj/toy.dmi'
icon_state = "rag"
item_flags = NOBLUDGEON
reagent_flags = OPENCONTAINER
amount_per_transfer_from_this = 5
possible_transfer_amounts = list()
volume = 5
spillable = FALSE
/obj/item/reagent_containers/glass/rag/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is smothering [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (OXYLOSS)
/obj/item/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user,proximity)
. = ..()
if(!proximity)
return
if(iscarbon(A) && A.reagents && reagents.total_volume)
var/mob/living/carbon/C = A
var/reagentlist = pretty_string_from_reagent_list(reagents)
var/log_object = "containing [reagentlist]"
if(user.a_intent == INTENT_HARM && !C.is_mouth_covered())
reagents.trans_to(C, reagents.total_volume, transfered_by = user, method = INGEST)
C.visible_message("<span class='danger'>[user] smothers \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] smothers you with \the [src]!</span>", "<span class='hear'>You hear some struggling and muffled cries of surprise.</span>")
log_combat(user, C, "smothered", src, log_object)
else
reagents.expose(C, TOUCH)
reagents.clear_reagents()
C.visible_message("<span class='notice'>[user] touches \the [C] with \the [src].</span>")
log_combat(user, C, "touched", src, log_object)
else if(istype(A) && (src in user))
user.visible_message("<span class='notice'>[user] starts to wipe down [A] with [src]!</span>", "<span class='notice'>You start to wipe down [A] with [src]...</span>")
if(do_after(user,30, target = A))
user.visible_message("<span class='notice'>[user] finishes wiping off [A]!</span>", "<span class='notice'>You finish wiping off [A].</span>")
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
/obj/item/clothing/gloves
var/transfer_blood = 0
/obj/item/reagent_containers/glass/rag
name = "damp rag"
desc = "For cleaning up messes, you suppose."
w_class = WEIGHT_CLASS_TINY
icon = 'icons/obj/toy.dmi'
icon_state = "rag"
item_flags = NOBLUDGEON
reagent_flags = OPENCONTAINER
amount_per_transfer_from_this = 5
possible_transfer_amounts = list()
volume = 5
spillable = FALSE
/obj/item/reagent_containers/glass/rag/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is smothering [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (OXYLOSS)
/obj/item/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user,proximity)
. = ..()
if(!proximity)
return
if(iscarbon(A) && A.reagents && reagents.total_volume)
var/mob/living/carbon/C = A
var/reagentlist = pretty_string_from_reagent_list(reagents)
var/log_object = "containing [reagentlist]"
if(user.a_intent == INTENT_HARM && !C.is_mouth_covered())
reagents.trans_to(C, reagents.total_volume, transfered_by = user, method = INGEST)
C.visible_message("<span class='danger'>[user] smothers \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] smothers you with \the [src]!</span>", "<span class='hear'>You hear some struggling and muffled cries of surprise.</span>")
log_combat(user, C, "smothered", src, log_object)
else
reagents.expose(C, TOUCH)
reagents.clear_reagents()
C.visible_message("<span class='notice'>[user] touches \the [C] with \the [src].</span>")
log_combat(user, C, "touched", src, log_object)
else if(istype(A) && (src in user))
user.visible_message("<span class='notice'>[user] starts to wipe down [A] with [src]!</span>", "<span class='notice'>You start to wipe down [A] with [src]...</span>")
if(do_after(user,30, target = A))
user.visible_message("<span class='notice'>[user] finishes wiping off [A]!</span>", "<span class='notice'>You finish wiping off [A].</span>")
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+215 -215
View File
@@ -1,215 +1,215 @@
//CONTAINS: Detective's Scanner
// TODO: Split everything into easy to manage procs.
/obj/item/detective_scanner
name = "forensic scanner"
desc = "Used to remotely scan objects and biomass for DNA and fingerprints. Can print a report of the findings."
icon = 'icons/obj/device.dmi'
icon_state = "forensicnew"
w_class = WEIGHT_CLASS_SMALL
inhand_icon_state = "electronic"
worn_icon_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
item_flags = NOBLUDGEON
slot_flags = ITEM_SLOT_BELT
var/scanning = 0
var/list/log = list()
var/range = 8
var/view_check = TRUE
var/forensicPrintCount = 0
actions_types = list(/datum/action/item_action/display_detective_scan_results)
/datum/action/item_action/display_detective_scan_results
name = "Display Forensic Scanner Results"
/datum/action/item_action/display_detective_scan_results/Trigger()
var/obj/item/detective_scanner/scanner = target
if(istype(scanner))
scanner.displayDetectiveScanResults(usr)
/obj/item/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
scanning = 1
to_chat(user, "<span class='notice'>Printing report, please wait...</span>")
addtimer(CALLBACK(src, .proc/PrintReport), 100)
else
to_chat(user, "<span class='notice'>The scanner has no logs or is in use.</span>")
/obj/item/detective_scanner/attack(mob/living/M, mob/user)
return
/obj/item/detective_scanner/proc/PrintReport()
// Create our paper
var/obj/item/paper/P = new(get_turf(src))
//This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm
var frNum = ++forensicPrintCount
P.name = text("FR-[] 'Forensic Record'", frNum)
P.info = text("<center><B>Forensic Record - (FR-[])</B></center><HR><BR>", frNum)
P.info += jointext(log, "<BR>")
P.info += "<HR><B>Notes:</B><BR>"
P.update_icon()
if(ismob(loc))
var/mob/M = loc
M.put_in_hands(P)
to_chat(M, "<span class='notice'>Report printed. Log cleared.</span>")
// Clear the logs
log = list()
scanning = 0
/obj/item/detective_scanner/afterattack(atom/A, mob/user, params)
. = ..()
scan(A, user)
return FALSE
/obj/item/detective_scanner/proc/scan(atom/A, mob/user)
set waitfor = 0
if(!scanning)
// Can remotely scan objects and mobs.
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
return
scanning = 1
user.visible_message("<span class='notice'>\The [user] points the [src.name] at \the [A] and performs a forensic scan.</span>")
to_chat(user, "<span class='notice'>You scan \the [A]. The scanner is now analysing the results...</span>")
// GATHER INFORMATION
//Make our lists
var/list/fingerprints = list()
var/list/blood = A.return_blood_DNA()
var/list/fibers = A.return_fibers()
var/list/reagents = list()
var/target_name = A.name
// Start gathering
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(!H.gloves)
fingerprints += md5(H.dna.uni_identity)
else if(!ismob(A))
fingerprints = A.return_fingerprints()
// 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"]
LAZYINITLIST(blood)
blood[blood_DNA] = blood_type
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
var/found_something = 0
add_log("<B>[station_time_timestamp()][get_timestamp()] - [target_name]</B>", 0)
// Fingerprints
if(length(fingerprints))
sleep(30)
add_log("<span class='info'><B>Prints:</B></span>")
for(var/finger in fingerprints)
add_log("[finger]")
found_something = 1
// Blood
if (length(blood))
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 (UE): <font color='red'>[B]</font>")
//Fibers
if(length(fibers))
sleep(30)
add_log("<span class='info'><B>Fibers:</B></span>")
for(var/fiber in fibers)
add_log("[fiber]")
found_something = 1
//Reagents
if(length(reagents))
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)
to_chat(holder, "<span class='warning'>Unable to locate any fingerprints, materials, fibers, or blood on \the [target_name]!</span>")
else
if(holder)
to_chat(holder, "<span class='notice'>You finish scanning \the [target_name].</span>")
add_log("---------------------------------------------------------", 0)
scanning = 0
return
/obj/item/detective_scanner/proc/add_log(msg, broadcast = 1)
if(scanning)
if(broadcast && ismob(loc))
var/mob/M = loc
to_chat(M, msg)
log += "&nbsp;&nbsp;[msg]"
else
CRASH("[src] [REF(src)] is adding a log when it was never put in scanning mode!")
/proc/get_timestamp()
return time2text(world.time + 432000, ":ss")
/obj/item/detective_scanner/AltClick(mob/living/user)
// Best way for checking if a player can use while not incapacitated, etc
if(!user.canUseTopic(src, be_close=TRUE))
return
if(!LAZYLEN(log))
to_chat(user, "<span class='notice'>Cannot clear logs, the scanner has no logs.</span>")
return
if(scanning)
to_chat(user, "<span class='notice'>Cannot clear logs, the scanner is in use.</span>")
return
to_chat(user, "<span class='notice'>The scanner logs are cleared.</span>")
log = list()
/obj/item/detective_scanner/examine(mob/user)
. = ..()
if(LAZYLEN(log) && !scanning)
. += "<span class='notice'>Alt-click to clear scanner logs.</span>"
/obj/item/detective_scanner/proc/displayDetectiveScanResults(mob/living/user)
// No need for can-use checks since the action button should do proper checks
if(!LAZYLEN(log))
to_chat(user, "<span class='notice'>Cannot display logs, the scanner has no logs.</span>")
return
if(scanning)
to_chat(user, "<span class='notice'>Cannot display logs, the scanner is in use.</span>")
return
to_chat(user, "<span class='notice'><B>Scanner Report</B></span>")
for(var/iterLog in log)
to_chat(user, iterLog)
//CONTAINS: Detective's Scanner
// TODO: Split everything into easy to manage procs.
/obj/item/detective_scanner
name = "forensic scanner"
desc = "Used to remotely scan objects and biomass for DNA and fingerprints. Can print a report of the findings."
icon = 'icons/obj/device.dmi'
icon_state = "forensicnew"
w_class = WEIGHT_CLASS_SMALL
inhand_icon_state = "electronic"
worn_icon_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
item_flags = NOBLUDGEON
slot_flags = ITEM_SLOT_BELT
var/scanning = 0
var/list/log = list()
var/range = 8
var/view_check = TRUE
var/forensicPrintCount = 0
actions_types = list(/datum/action/item_action/display_detective_scan_results)
/datum/action/item_action/display_detective_scan_results
name = "Display Forensic Scanner Results"
/datum/action/item_action/display_detective_scan_results/Trigger()
var/obj/item/detective_scanner/scanner = target
if(istype(scanner))
scanner.displayDetectiveScanResults(usr)
/obj/item/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
scanning = 1
to_chat(user, "<span class='notice'>Printing report, please wait...</span>")
addtimer(CALLBACK(src, .proc/PrintReport), 100)
else
to_chat(user, "<span class='notice'>The scanner has no logs or is in use.</span>")
/obj/item/detective_scanner/attack(mob/living/M, mob/user)
return
/obj/item/detective_scanner/proc/PrintReport()
// Create our paper
var/obj/item/paper/P = new(get_turf(src))
//This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm
var frNum = ++forensicPrintCount
P.name = text("FR-[] 'Forensic Record'", frNum)
P.info = text("<center><B>Forensic Record - (FR-[])</B></center><HR><BR>", frNum)
P.info += jointext(log, "<BR>")
P.info += "<HR><B>Notes:</B><BR>"
P.update_icon()
if(ismob(loc))
var/mob/M = loc
M.put_in_hands(P)
to_chat(M, "<span class='notice'>Report printed. Log cleared.</span>")
// Clear the logs
log = list()
scanning = 0
/obj/item/detective_scanner/afterattack(atom/A, mob/user, params)
. = ..()
scan(A, user)
return FALSE
/obj/item/detective_scanner/proc/scan(atom/A, mob/user)
set waitfor = 0
if(!scanning)
// Can remotely scan objects and mobs.
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
return
scanning = 1
user.visible_message("<span class='notice'>\The [user] points the [src.name] at \the [A] and performs a forensic scan.</span>")
to_chat(user, "<span class='notice'>You scan \the [A]. The scanner is now analysing the results...</span>")
// GATHER INFORMATION
//Make our lists
var/list/fingerprints = list()
var/list/blood = A.return_blood_DNA()
var/list/fibers = A.return_fibers()
var/list/reagents = list()
var/target_name = A.name
// Start gathering
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(!H.gloves)
fingerprints += md5(H.dna.uni_identity)
else if(!ismob(A))
fingerprints = A.return_fingerprints()
// 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"]
LAZYINITLIST(blood)
blood[blood_DNA] = blood_type
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
var/found_something = 0
add_log("<B>[station_time_timestamp()][get_timestamp()] - [target_name]</B>", 0)
// Fingerprints
if(length(fingerprints))
sleep(30)
add_log("<span class='info'><B>Prints:</B></span>")
for(var/finger in fingerprints)
add_log("[finger]")
found_something = 1
// Blood
if (length(blood))
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 (UE): <font color='red'>[B]</font>")
//Fibers
if(length(fibers))
sleep(30)
add_log("<span class='info'><B>Fibers:</B></span>")
for(var/fiber in fibers)
add_log("[fiber]")
found_something = 1
//Reagents
if(length(reagents))
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)
to_chat(holder, "<span class='warning'>Unable to locate any fingerprints, materials, fibers, or blood on \the [target_name]!</span>")
else
if(holder)
to_chat(holder, "<span class='notice'>You finish scanning \the [target_name].</span>")
add_log("---------------------------------------------------------", 0)
scanning = 0
return
/obj/item/detective_scanner/proc/add_log(msg, broadcast = 1)
if(scanning)
if(broadcast && ismob(loc))
var/mob/M = loc
to_chat(M, msg)
log += "&nbsp;&nbsp;[msg]"
else
CRASH("[src] [REF(src)] is adding a log when it was never put in scanning mode!")
/proc/get_timestamp()
return time2text(world.time + 432000, ":ss")
/obj/item/detective_scanner/AltClick(mob/living/user)
// Best way for checking if a player can use while not incapacitated, etc
if(!user.canUseTopic(src, be_close=TRUE))
return
if(!LAZYLEN(log))
to_chat(user, "<span class='notice'>Cannot clear logs, the scanner has no logs.</span>")
return
if(scanning)
to_chat(user, "<span class='notice'>Cannot clear logs, the scanner is in use.</span>")
return
to_chat(user, "<span class='notice'>The scanner logs are cleared.</span>")
log = list()
/obj/item/detective_scanner/examine(mob/user)
. = ..()
if(LAZYLEN(log) && !scanning)
. += "<span class='notice'>Alt-click to clear scanner logs.</span>"
/obj/item/detective_scanner/proc/displayDetectiveScanResults(mob/living/user)
// No need for can-use checks since the action button should do proper checks
if(!LAZYLEN(log))
to_chat(user, "<span class='notice'>Cannot display logs, the scanner has no logs.</span>")
return
if(scanning)
to_chat(user, "<span class='notice'>Cannot display logs, the scanner is in use.</span>")
return
to_chat(user, "<span class='notice'><B>Scanner Report</B></span>")
for(var/iterLog in log)
to_chat(user, iterLog)