Simplified Detective.

-Changed the focus from the high-res scanner to the regular scanner. It will simply scan the fingerprints and display them to the detective. For extra functionality, it'll store it's findings in a log and then you can print it out in a report by using attack_self().

-Detectives can now use the medical computer.
-Removed the pda forensic scanning functionality.
-Got rid of now useless high-res scanner computer. Got rid of the now useless fingerprint cards.
-Added a medical computer to the detective's office and replaced the useless medical cabinet with an empty one.

Other

-Got rid of diseases magically moving down a stage.
-Optimized playsound()
-Added an attack_self() to sprayers so that you can change the reagent use of them between 5 and 10.




git-svn-id: http://tgstation13.googlecode.com/svn/trunk@5168 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
giacomand@gmail.com
2012-11-23 00:39:18 +00:00
parent 65a2126d9f
commit f1d24f27f9
20 changed files with 197 additions and 1205 deletions

View File

@@ -65,8 +65,10 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
stage = max_stages stage = max_stages
if(stage_prob != 0 && prob(stage_prob) && stage != max_stages && !cure_present) //now the disease shouldn't get back up to stage 4 in no time if(stage_prob != 0 && prob(stage_prob) && stage != max_stages && !cure_present) //now the disease shouldn't get back up to stage 4 in no time
stage++ stage++
if(stage != 1 && (prob(1) || (cure_present && prob(cure_chance)))) //world << "up"
if(cure_present && prob(cure_chance))
stage-- stage--
//world << "down"
else if(stage <= 1 && ((prob(1) && curable) || (cure_present && prob(cure_chance)))) else if(stage <= 1 && ((prob(1) && curable) || (cure_present && prob(cure_chance))))
// world << "Cured as stage act" // world << "Cured as stage act"
cure() cure()

View File

@@ -29,7 +29,7 @@ Bonus
if(prob(SYMPTOM_ACTIVATION_PROB)) if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob var/mob/living/M = A.affected_mob
switch(A.stage) switch(A.stage)
if(5) if(4, 5)
Convert(M) Convert(M)
return return
@@ -39,5 +39,5 @@ Bonus
var/get_damage = rand(1, 2) var/get_damage = rand(1, 2)
M.adjustFireLoss(-get_damage) M.adjustFireLoss(-get_damage)
M.adjustBruteLoss(-get_damage) M.adjustBruteLoss(-get_damage)
M.adjustToxLoss(get_damage * 2) M.adjustToxLoss(get_damage)
return 1 return 1

View File

@@ -112,7 +112,7 @@ Bonus
if(prob(SYMPTOM_ACTIVATION_PROB)) if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob var/mob/living/M = A.affected_mob
switch(A.stage) switch(A.stage)
if(5) if(4, 5)
M.overeatduration = 0 M.overeatduration = 0
M.nutrition = 400 M.nutrition = 400

View File

@@ -617,25 +617,6 @@
/obj/item/weapon/dummy/blob_act() /obj/item/weapon/dummy/blob_act()
return 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"
/* /*
/obj/item/weapon/game_kit /obj/item/weapon/game_kit

View File

@@ -336,8 +336,10 @@ its easier to just keep the beam vertical.
//Add the list if it does not exist. //Add the list if it does not exist.
if(!fingerprintshidden) if(!fingerprintshidden)
fingerprintshidden = list() fingerprintshidden = list()
//Fibers~ //Fibers~
add_fibers(M) add_fibers(M)
//Now, lets get to the dirty work. //Now, lets get to the dirty work.
//First, make sure their DNA makes sense. //First, make sure their DNA makes sense.
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
@@ -346,55 +348,43 @@ its easier to just keep the beam vertical.
H.dna = new /datum/dna(null) H.dna = new /datum/dna(null)
H.dna.real_name = H.real_name H.dna.real_name = H.real_name
H.check_dna() H.check_dna()
//Now, deal with gloves. //Now, deal with gloves.
if (H.gloves && H.gloves != src) if (H.gloves && H.gloves != src)
if(fingerprintslast != H.key) if(fingerprintslast != H.key)
fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key) fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key)
fingerprintslast = H.key fingerprintslast = H.key
H.gloves.add_fingerprint(M) H.gloves.add_fingerprint(M)
//Deal with gloves the pass finger/palm prints. //Deal with gloves the pass finger/palm prints.
if(H.gloves != src) if(H.gloves != src)
if(prob(75) && istype(H.gloves, /obj/item/clothing/gloves/latex)) if(prob(75) && istype(H.gloves, /obj/item/clothing/gloves/latex))
return 0 return 0
else if(H.gloves && !istype(H.gloves, /obj/item/clothing/gloves/latex)) else if(H.gloves && !istype(H.gloves, /obj/item/clothing/gloves/latex))
return 0 return 0
//More adminstuffz //More adminstuffz
if(fingerprintslast != H.key) if(fingerprintslast != H.key)
fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key) fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key)
fingerprintslast = H.key fingerprintslast = H.key
//Make the list if it does not exist. //Make the list if it does not exist.
if(!fingerprints) if(!fingerprints)
fingerprints = list() fingerprints = list()
//Hash this shit. //Hash this shit.
var/full_print = md5(H.dna.uni_identity) var/full_print = md5(H.dna.uni_identity)
//Smudge up dem prints some
for(var/P in fingerprints) // Add the fingerprints
if(P == full_print) fingerprints[full_print] = full_print
continue
var/test_print = stars(fingerprints[P], rand(85,95))
if(stringpercent(test_print) == 32) //She's full of stars! (No actual print left)
fingerprints.Remove(P)
else
fingerprints[P] = test_print
var/print = fingerprints[full_print] //Find if the print is already there.
//It is not! We need to add it!
if(!print)
fingerprints[full_print] = stars(full_print, H.gloves ? rand(10,20) : rand(25,40))
//It's there, lets merge this shit!
else
fingerprints[full_print] = stringmerge(print, stars(full_print, (H.gloves ? rand(10,20) : rand(25,40))))
return 1 return 1
else else
//Smudge up dem prints some //Smudge up dem prints some
for(var/P in fingerprints)
var/test_print = stars(fingerprints[P], rand(85,95))
if(stringpercent(test_print) == 32) //She's full of stars! (No actual print left)
fingerprints.Remove(P)
else
fingerprints[P] = test_print
if(fingerprintslast != M.key) if(fingerprintslast != M.key)
fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key) fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key)
fingerprintslast = M.key fingerprintslast = M.key
//Cleaning up shit. //Cleaning up shit.
if(fingerprints && !fingerprints.len) if(fingerprints && !fingerprints.len)
del(fingerprints) del(fingerprints)
@@ -406,8 +396,8 @@ its easier to just keep the beam vertical.
A.fingerprints = list() A.fingerprints = list()
if(!istype(A.fingerprintshidden,/list)) if(!istype(A.fingerprintshidden,/list))
A.fingerprintshidden = list() A.fingerprintshidden = list()
A.fingerprints |= fingerprints //detective A.fingerprints |= fingerprints.Copy() //detective
A.fingerprintshidden |= fingerprintshidden //admin A.fingerprintshidden |= fingerprintshidden.Copy() //admin
A.fingerprintslast = fingerprintslast A.fingerprintslast = fingerprintslast

View File

@@ -104,14 +104,11 @@
H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(H), slot_l_store) H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(H), slot_l_store)
if(H.backbag == 1)//Why cant some of these things spawn in his office? if(H.backbag == 1)//Why cant some of these things spawn in his office?
var/obj/item/weapon/storage/box/survival/Evipack = new /obj/item/weapon/storage/box/survival(H) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
H.equip_to_slot_or_del(Evipack, slot_r_hand)
new /obj/item/weapon/fcardholder(Evipack)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand)
H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store) H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store)
else else
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/fcardholder(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack) H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack)

View File

@@ -4,7 +4,7 @@
name = "Medical Records" name = "Medical Records"
desc = "This can be used to check medical records." desc = "This can be used to check medical records."
icon_state = "medcomp" icon_state = "medcomp"
req_access = list(access_medical) req_one_access = list(access_medical, access_forensics_lockers)
circuit = "/obj/item/weapon/circuitboard/med_data" circuit = "/obj/item/weapon/circuitboard/med_data"
var/obj/item/weapon/card/id/scan = null var/obj/item/weapon/card/id/scan = null
var/authenticated = null var/authenticated = null

View File

@@ -298,7 +298,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
dat += "<h4>Security Functions</h4>" dat += "<h4>Security Functions</h4>"
dat += "<ul>" dat += "<ul>"
dat += "<li><a href='byond://?src=\ref[src];choice=45'><img src=pda_cuffs.png> Security Records</A></li>" dat += "<li><a href='byond://?src=\ref[src];choice=45'><img src=pda_cuffs.png> Security Records</A></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=Forensic Scan'><img src=pda_scanner.png> [scanmode == 2 ? "Disable" : "Enable"] Forensic Scanner</a></li>"
if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky)) if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky))
dat += "<li><a href='byond://?src=\ref[src];choice=46'><img src=pda_cuffs.png> Security Bot Access</a></li>" dat += "<li><a href='byond://?src=\ref[src];choice=46'><img src=pda_cuffs.png> Security Bot Access</a></li>"
dat += "</ul>" dat += "</ul>"
@@ -513,11 +512,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
scanmode = 0 scanmode = 0
else if((!isnull(cartridge)) && (cartridge.access_medical)) else if((!isnull(cartridge)) && (cartridge.access_medical))
scanmode = 1 scanmode = 1
if("Forensic Scan")
if(scanmode == 2)
scanmode = 0
else if((!isnull(cartridge)) && (cartridge.access_security))
scanmode = 2
if("Reagent Scan") if("Reagent Scan")
if(scanmode == 3) if(scanmode == 3)
scanmode = 0 scanmode = 0
@@ -939,27 +933,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob) /obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob)
switch(scanmode) switch(scanmode)
if(2)
if(!istype(A, /obj/item/weapon/f_card))
if (!A.fingerprints)
user << "\blue Unable to locate any fingerprints on [A]!"
else
user << "\blue Isolated [A:fingerprints.len] fingerprints."
var/list/prints = A:fingerprints
var/list/complete_prints = list()
for(var/i in prints)
var/print = prints[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]"
if(cartridge && cartridge.access_security)
cartridge.add_data(A)
user << "Data added to internal storage. Scan with a High-Resolution Scanner to retreive."
if(3) if(3)
if(!isnull(A.reagents)) if(!isnull(A.reagents))

View File

@@ -600,42 +600,6 @@ Code:
menu += "ERROR: Unable to determine current location." menu += "ERROR: Unable to determine current location."
menu += "<br><br><A href='byond://?src=\ref[src];choice=49'>Refresh GPS Locator</a>" menu += "<br><br><A href='byond://?src=\ref[src];choice=49'>Refresh GPS Locator</a>"
proc/add_data(atom/A as mob|obj|turf|area)
//I love hashtables.
var/list/data_entry = stored_data["\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
sum_list[2] = A.suit_fibers
sum_list[3] = A.blood_DNA
sum_list[4] = "\The [A] in \the [get_area(A)]"
stored_data["\ref [A]"] = sum_list
return 0
/obj/item/weapon/cartridge/Topic(href, href_list) /obj/item/weapon/cartridge/Topic(href, href_list)
..() ..()

View File

@@ -69,167 +69,3 @@
user << "\blue You successfully forge the ID card." user << "\blue You successfully forge the ID card."
else else
..() ..()
/*
* FINGERPRINT HOLDER
*/
/obj/item/weapon/fcardholder/attack_self(mob/user as mob)
var/dat = "<B>Clipboard</B><BR>"
for(var/obj/item/weapon/f_card/P in src)
dat += text("<A href='?src=\ref[];read=\ref[]'>[]</A> <A href='?src=\ref[];remove=\ref[]'>Remove</A><BR>", src, P, P.name, src, P)
user << browse(dat, "window=fcardholder")
onclose(user, "fcardholder")
return
/obj/item/weapon/fcardholder/Topic(href, href_list)
..()
if ((usr.stat || usr.restrained()))
return
if (usr.contents.Find(src))
usr.set_machine(src)
if (href_list["remove"])
var/obj/item/P = locate(href_list["remove"])
if ((P && P.loc == src))
usr.put_in_hands(P)
src.add_fingerprint(usr)
P.add_fingerprint(usr)
src.update()
if (href_list["read"])
var/obj/item/weapon/f_card/P = locate(href_list["read"])
if ((P && P.loc == src))
if (!( istype(usr, /mob/living/carbon/human) ))
usr << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", P.name, P.display()), text("window=[]", P.name))
onclose(usr, "[P.name]")
else
usr << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", P.name, P.display()), text("window=[]", P.name))
onclose(usr, "[P.name]")
src.add_fingerprint(usr)
if (ismob(src.loc))
var/mob/M = src.loc
if (M.machine == src)
spawn( 0 )
src.attack_self(M)
return
return
/obj/item/weapon/fcardholder/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/item/weapon/fcardholder/attack_hand(mob/user as mob)
if (user.contents.Find(src))
spawn( 0 )
src.attack_self(user)
return
src.add_fingerprint(user)
else
return ..()
return
/obj/item/weapon/fcardholder/attackby(obj/item/weapon/P as obj, mob/user as mob)
..()
if (istype(P, /obj/item/weapon/f_card))
if (src.contents.len < 30)
user.drop_item()
P.loc = src
add_fingerprint(user)
src.add_fingerprint(user)
else
user << "\blue Not enough space!!!"
else
if (istype(P, /obj/item/weapon/pen))
var/t = input(user, "Holder Label:", text("[]", src.name), null) as text
if (user.get_active_hand() != P)
return
if ((!in_range(src, usr) && src.loc != user))
return
t = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if (t)
src.name = text("FPCase- '[]'", t)
else
src.name = "Finger Print Case"
else
return
src.update()
spawn( 0 )
attack_self(user)
return
return
/obj/item/weapon/fcardholder/proc/update()
var/i = 0
for(var/obj/item/weapon/f_card/F in src)
i = 1
break
src.icon_state = text("fcardholder[]", (i ? "1" : "0"))
return
/*
* FINGERPRINT CARD
*/
/obj/item/weapon/f_card/examine()
set src in view(2)
..()
usr << text("\blue There are [] on the stack!", src.amount)
usr << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", src.name, display()), text("window=[]", src.name))
onclose(usr, "[src.name]")
return
/obj/item/weapon/f_card/proc/display()
if(!fingerprints || !fingerprints.len)
return "<B>There are no fingerprints on this card.</B>"
else
var/dat = "<B>Fingerprints on Card</B><HR>"
for(var/name in fingerprints)
dat += "[name]<BR>"
return dat
return
/obj/item/weapon/f_card/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/f_card))
if ((src.fingerprints || W.fingerprints))
return
if (src.amount == 10)
return
if (W:amount + src.amount > 10)
src.amount = 10
W:amount = W:amount + src.amount - 10
else
src.amount += W:amount
//W = null
del(W)
src.add_fingerprint(user)
if (W)
W.add_fingerprint(user)
else
if (istype(W, /obj/item/weapon/pen))
var/t = input(user, "Card Label:", text("[]", src.name), null) as text
if (user.get_active_hand() != W)
return
if ((!in_range(src, usr) && src.loc != user))
return
t = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if (t)
src.name = text("FPrintC- '[]'", t)
else
src.name = "Finger Print Card"
W.add_fingerprint(user)
src.add_fingerprint(user)
return
/obj/item/weapon/f_card/add_fingerprint()
..()
if (!istype(usr, /mob/living/silicon))
if (fingerprints)
if (src.amount > 1)
var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card(get_turf(src))
F.amount = --src.amount
amount = 1
icon_state = "fingerprint1"
return

View File

@@ -104,18 +104,6 @@
..() ..()
return return
/obj/item/weapon/storage/fcard_kit/New()
new /obj/item/weapon/f_card(src)
new /obj/item/weapon/f_card(src)
new /obj/item/weapon/f_card(src)
new /obj/item/weapon/f_card(src)
new /obj/item/weapon/f_card(src)
new /obj/item/weapon/f_card(src)
new /obj/item/weapon/f_card(src)
..()
return
/obj/item/weapon/storage/id_kit/New() /obj/item/weapon/storage/id_kit/New()
new /obj/item/weapon/card/id(src) new /obj/item/weapon/card/id(src)

View File

@@ -180,8 +180,6 @@
new /obj/item/clothing/shoes/brown(src) new /obj/item/clothing/shoes/brown(src)
new /obj/item/device/radio/headset/headset_sec(src) new /obj/item/device/radio/headset/headset_sec(src)
new /obj/item/weapon/cartridge/detective(src) new /obj/item/weapon/cartridge/detective(src)
new /obj/item/weapon/storage/fcard_kit(src)
new /obj/item/weapon/fcardholder(src)
new /obj/item/weapon/clipboard(src) new /obj/item/weapon/clipboard(src)
new /obj/item/device/detective_scanner(src) new /obj/item/device/detective_scanner(src)
new /obj/item/weapon/storage/box/evidence(src) new /obj/item/weapon/storage/box/evidence(src)

View File

@@ -19,10 +19,13 @@
if (vary) if (vary)
S.frequency = rand(32000, 55000) S.frequency = rand(32000, 55000)
for (var/mob/M in range(world.view+extrarange, source)) // Plays for people in range.
if(locate(/mob/, M)) for (var/A in range(world.view+extrarange, source)) // Plays for people in range.
if(ismob(A))
var/mob/M = A
var/mob/M2 = locate(/mob/, M) var/mob/M2 = locate(/mob/, M)
if (M2.client) if (M2 && M2.client)
if(M2.ear_deaf <= 0 || !M.ear_deaf) if(M2.ear_deaf <= 0 || !M.ear_deaf)
if(isturf(source)) if(isturf(source))
var/dx = source.x - M2.x var/dx = source.x - M2.x
@@ -30,17 +33,17 @@
M2 << S M2 << S
if (M.client) if (M.client)
if(M.ear_deaf <= 0 || !M.ear_deaf) if(M.ear_deaf <= 0 || !M.ear_deaf)
if(isturf(source)) if(isturf(source))
var/dx = source.x - M.x var/dx = source.x - M.x
S.pan = max(-100, min(100, dx/8.0 * 100)) S.pan = max(-100, min(100, dx/8.0 * 100))
M << S M << S
for(var/obj/structure/closet/L in range(world.view+extrarange, source)) if(istype(A, /obj/structure/closet))
if(locate(/mob/, L)) var/obj/O = A
for(var/mob/M in L) for(var/mob/M in O)
if (M.client) if (M.client)
if(M.ear_deaf <= 0 || !M.ear_deaf) if(M.ear_deaf <= 0 || !M.ear_deaf)
if(isturf(source)) if(isturf(source))

View File

@@ -46,583 +46,4 @@ atom/proc/add_fibers(mob/living/carbon/human/M)
if(prob(20*item_multiplier) && !(fibertext in suit_fibers)) if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
//world.log << "Added fibertext: [fibertext]" //world.log << "Added fibertext: [fibertext]"
suit_fibers += "Material from a pair of [M.gloves.name]." suit_fibers += "Material from a pair of [M.gloves.name]."
if(!suit_fibers.len) del suit_fibers 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 = null
I.w_class = 1
I.icon_state = "evidenceobj"
I.desc = "An empty evidence bag."
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 += "&nbsp<b>Fingerprints:</b><br>"
temp += "&nbsp;&nbsp;&nbsp;&nbsp;[prints.len] Unique fingerprints found.<br>"
var/complete_prints = 0
for(var/print in prints)
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
complete_prints++
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[2]
if(fibers && fibers.len)
temp += "&nbsp<b>Fibers:</b><br>"
for(var/j = 1, j <= fibers.len, j++)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fibers[j]]<br>"
var/list/blood = outputs[3]
if(blood && blood.len)
temp += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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)
P.name = "\improper Database File (Dossier [files.Find(href_list["identifier"])])"
P.overlays += "paper_words"
P.info = "<b>Criminal Evidence Database</b><br><br>"
var/list/dossier = files[href_list["identifier"]]
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 += "&nbsp<b>Fingerprints:</b><br>"
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;[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 += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[2]
if(fibers && fibers.len)
P.info += "&nbsp<b>Fibers:</b><br>"
for(var/j = 1, j <= fibers.len, j++)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fibers[j]]<br>"
var/list/blood = outputs[3]
if(blood && blood.len)
P.info += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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 += "&nbsp<b>Fingerprints:</b><br>"
temp += "&nbsp;&nbsp;&nbsp;&nbsp;[prints.len] Unique fingerprints found.<br>"
var/complete_prints = 0
for(var/print in prints)
if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE)
complete_prints++
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[1]
if(fibers && fibers.len)
temp += "&nbsp<b>Fibers:</b><br>"
for(var/fiber in fibers)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fiber]<br>"
var/list/blood = outputs[2]
if(blood && blood.len)
temp += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
temp += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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 += "&nbsp<b>Fingerprints:</b><br>"
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;[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 += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[prints[print]]<br>"
if(complete_prints)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;And [prints.len - complete_prints] unknown unique prints.<br>"
else
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No prints of sufficient completeness.<br>"
var/list/fibers = outputs[1]
if(fibers && fibers.len)
P.info += "&nbsp<b>Fibers:</b><br>"
for(var/fiber in fibers)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[fiber]<br>"
var/list/blood = outputs[2]
if(blood && blood.len)
P.info += "&nbsp<b>Blood:</b><br>"
for(var/named in blood)
P.info += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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))
if(W:stored)
for(var/atom in W:stored)
var/list/data = W:stored[atom]
add_data_master(atom,data[1],data[2],data[3],data[4])
W: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
templist[2] = atom_blood_DNA
templist[3] = atom_name
templist[4] = atom_fingerprints
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
data_point[2] = atom_suit_fibers
data_point[3] = atom_blood_DNA
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
data_point[2] = atom_suit_fibers
data_point[3] = atom_blood_DNA
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"

View File

@@ -89,6 +89,5 @@
new /obj/item/weapon/evidencebag(src) new /obj/item/weapon/evidencebag(src)
new /obj/item/weapon/evidencebag(src) new /obj/item/weapon/evidencebag(src)
new /obj/item/weapon/evidencebag(src) new /obj/item/weapon/evidencebag(src)
new /obj/item/weapon/f_card(src)
..() ..()
return return

View File

@@ -1,158 +1,25 @@
/*
obj/item/clothing/shoes/var
track_blood = 0
mob/living/carbon/human/track_blood_mob
track_blood_type*/
mob/var
bloody_hands = 0
mob/living/carbon/human/bloody_hands_mob
track_blood
mob/living/carbon/human/track_blood_mob
track_blood_type
obj/item/clothing/gloves/var
transfer_blood = 0
mob/living/carbon/human/bloody_hands_mob
/* /mob
obj/effect/decal/cleanable/var
track_amt = 3
mob/blood_owner
turf/Exited(mob/living/carbon/human/M) var/bloody_hands = 0
if(istype(M,/mob/living) && !istype(M,/mob/living/carbon/metroid)) var/mob/living/carbon/human/bloody_hands_mob
if(!istype(src, /turf/space)) // Bloody tracks code starts here var/track_blood
var/dofoot = 1 var/mob/living/carbon/human/track_blood_mob
if(istype(M,/mob/living/simple_animal)) var/track_blood_type
if(!(istype(M,/mob/living/simple_animal/cat) || istype(M,/mob/living/simple_animal/corgi) || istype(M,/mob/living/simple_animal/constructwraith)))
dofoot = 0
if(dofoot) /obj/item/clothing/gloves
var/transfer_blood = 0
if(!istype(src, /turf/space)) // Bloody tracks code starts here var/mob/living/carbon/human/bloody_hands_mob
if(M.track_blood > 0)
M.track_blood--
src.add_bloody_footprints(M.track_blood_mob,1,M.dir,get_tracks(M),M.track_blood_type)
else if(istype(M,/mob/living/carbon/human))
if(M.shoes && istype(M.shoes,/obj/item/clothing/shoes))
var/obj/item/clothing/shoes/S = M.shoes
if(S.track_blood > 0)
S.track_blood--
src.add_bloody_footprints(S.track_blood_mob,1,M.dir,S.name,S.track_blood_type) // And bloody tracks end here
. = ..()
turf/Entered(mob/living/carbon/human/M)
if(istype(M,/mob/living) && !istype(M,/mob/living/carbon/metroid))
var/dofoot = 1
if(istype(M,/mob/living/simple_animal))
if(!(istype(M,/mob/living/simple_animal/cat) || istype(M,/mob/living/simple_animal/corgi) || istype(M,/mob/living/simple_animal/constructwraith)))
dofoot = 0
if(dofoot)
if(M.track_blood > 0)
M.track_blood--
src.add_bloody_footprints(M.track_blood_mob,0,M.dir,get_tracks(M),M.track_blood_type)
else if(istype(M,/mob/living/carbon/human))
if(M.shoes && istype(M.shoes,/obj/item/clothing/shoes) && !istype(src,/turf/space))
var/obj/item/clothing/shoes/S = M.shoes
if(S.track_blood > 0)
S.track_blood--
src.add_bloody_footprints(S.track_blood_mob,0,M.dir,S.name,S.track_blood_type)
for(var/obj/effect/decal/cleanable/B in src)
if(B:track_amt <= 0) continue
if(B.type != /obj/effect/decal/cleanable/blood/tracks)
if(istype(B, /obj/effect/decal/cleanable/xenoblood) || istype(B, /obj/effect/decal/cleanable/blood) || istype(B, /obj/effect/decal/cleanable/oil) || istype(B, /obj/effect/decal/cleanable/robot_debris))
var/track_type = "blood" /proc/blood_incompatible(donor,receiver)
if(istype(B, /obj/effect/decal/cleanable/xenoblood))
track_type = "xeno"
else if(istype(B, /obj/effect/decal/cleanable/oil) || istype(B, /obj/effect/decal/cleanable/robot_debris))
track_type = "oil"
if(istype(M,/mob/living/carbon/human)) var/donor_antigen = copytext(donor,1,lentext(donor))
if(M.shoes && istype(M.shoes,/obj/item/clothing/shoes)) var/receiver_antigen = copytext(receiver,1,lentext(receiver))
var/obj/item/clothing/shoes/S = M.shoes var/donor_rh = findtext("+",donor)
S.add_blood(B.blood_owner) var/receiver_rh = findtext("+",receiver)
S.track_blood_mob = B.blood_owner
S.track_blood = max(S.track_blood,8)
S.track_blood_type = track_type
else
M.add_blood(B.blood_owner)
M.track_blood_mob = B.blood_owner
M.track_blood = max(M.track_blood,rand(4,8))
M.track_blood_type = track_type
B.track_amt--
break
. = ..()
turf/proc/add_bloody_footprints(mob/living/carbon/human/M,leaving,d,info,bloodcolor)
for(var/obj/effect/decal/cleanable/blood/tracks/T in src)
if(T.dir == d && findtext(T.icon_state, bloodcolor))
if((leaving && T.icon_state == "steps2") || (!leaving && T.icon_state == "steps1"))
T.desc = "These bloody footprints appear to have been made by [info]."
if(!T.blood_DNA)
T.blood_DNA = list()
if(istype(M,/mob/living/carbon/human))
T.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
else if(istype(M,/mob/living/carbon/alien))
T.blood_DNA["UNKNOWN DNA"] = "X*"
else if(istype(M,/mob/living/carbon/monkey))
T.blood_DNA["Non-human DNA"] = "A+"
return
var/obj/effect/decal/cleanable/blood/tracks/this = new(src)
this.icon = 'icons/effects/footprints.dmi'
var/preiconstate = ""
if(info == "animal paws")
preiconstate = "paw"
else if(info == "alien claws")
preiconstate = "claw"
else if(info == "small alien feet")
preiconstate = "paw"
if(leaving)
this.icon_state = "[bloodcolor][preiconstate]2"
else
this.icon_state = "[bloodcolor][preiconstate]1"
this.dir = d
if(bloodcolor == "blood")
this.desc = "These bloody footprints appear to have been made by [info]."
else if(bloodcolor == "xeno")
this.desc = "These acidic bloody footprints appear to have been made by [info]."
else if(bloodcolor == "oil")
this.name = "oil"
this.desc = "These oil footprints appear to have been made by [info]."
if(istype(M,/mob/living/carbon/human))
if(!this.blood_DNA)
this.blood_DNA = list()
this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
proc/get_tracks(mob/M)
if(istype(M,/mob/living))
if(istype(M,/mob/living/carbon/human))
. = "human feet"
else if(istype(M,/mob/living/carbon/monkey) || istype(M,/mob/living/simple_animal/cat) || istype(M,/mob/living/simple_animal/corgi) || istype(M,/mob/living/simple_animal/crab))
. = "animal paws"
else if(istype(M,/mob/living/silicon/robot))
. = "robot feet"
else if(istype(M,/mob/living/carbon/alien/humanoid))
. = "alien claws"
else if(istype(M,/mob/living/carbon/alien/larva))
. = "small alien feet"
else
. = "an unknown creature"*/
proc/blood_incompatible(donor,receiver)
var
donor_antigen = copytext(donor,1,lentext(donor))
receiver_antigen = copytext(receiver,1,lentext(receiver))
donor_rh = findtext("+",donor)
receiver_rh = findtext("+",receiver)
if(donor_rh && !receiver_rh) return 1 if(donor_rh && !receiver_rh) return 1
switch(receiver_antigen) switch(receiver_antigen)
if("A") if("A")
@@ -164,6 +31,7 @@ proc/blood_incompatible(donor,receiver)
//AB is a universal receiver. //AB is a universal receiver.
return 0 return 0
/obj/item/weapon/reagent_containers/glass/rag /obj/item/weapon/reagent_containers/glass/rag
name = "damp rag" name = "damp rag"
desc = "For cleaning up messes, you suppose." desc = "For cleaning up messes, you suppose."
@@ -175,26 +43,26 @@ proc/blood_incompatible(donor,receiver)
volume = 5 volume = 5
can_be_placed_into = null can_be_placed_into = null
attack(atom/target as obj|turf|area, mob/user as mob , flag) /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) 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("\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")
src.reagents.reaction(target, TOUCH) src.reagents.reaction(target, TOUCH)
spawn(5) src.reagents.clear_reagents() spawn(5) src.reagents.clear_reagents()
return
else
..()
afterattack(atom/A as obj|turf|area, mob/user as mob)
if(istype(A) && src in user)
user.visible_message("[user] starts to wipe down [A] with [src]!")
if(do_after(user,30))
user.visible_message("[user] finishes wiping off the [A]!")
A.clean_blood()
return return
else
..()
examine() /obj/item/weapon/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob)
if (!usr) if(istype(A) && src in user)
return user.visible_message("[user] starts to wipe down [A] with [src]!")
usr << "That's \a [src]." if(do_after(user,30))
usr << desc user.visible_message("[user] finishes wiping off the [A]!")
return A.clean_blood()
return
/obj/item/weapon/reagent_containers/glass/rag/examine()
if (!usr)
return
usr << "That's \a [src]."
usr << desc
return

View File

@@ -1,172 +1,130 @@
//CONTAINS: Detective's Scanner //CONTAINS: Detective's Scanner
/obj/item/device/detective_scanner /obj/item/device/detective_scanner
name = "Scanner" name = "Scanner"
desc = "Used to scan objects for DNA and fingerprints." desc = "Used to scan objects for DNA and fingerprints. Can print a report of the findings."
icon_state = "forensic1" icon_state = "forensic1"
var/amount = 20.0
var/list/stored = list()
w_class = 3.0 w_class = 3.0
item_state = "electronic" item_state = "electronic"
flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY
slot_flags = SLOT_BELT slot_flags = SLOT_BELT
var/scanning = 0
var/list/log = list()
attackby(obj/item/weapon/f_card/W as obj, mob/user as mob) /obj/item/device/detective_scanner/attack_self(var/mob/user)
..() if(log.len && !scanning)
if (istype(W, /obj/item/weapon/f_card)) scanning = 1
if (W.fingerprints) user << "<span class='notice'>Printing report, please wait...</span>"
return spawn(100)
if (src.amount == 20) var/obj/item/weapon/paper/P = new(get_turf(src))
return P.info = "<center><font size='4'>Scanner Report</font></center><HR><BR>"
if (W.amount + src.amount > 20) P.info += dd_list2text(log, "<BR>")
src.amount = 20 P.info_links = P.info
W.amount = W.amount + src.amount - 20
user.put_in_hands(P)
log = list()
scanning = 0
if(user)
user << "<span class='notice'>Report printed. Log cleared.<span>"
else
user << "<span class='notice'>The scanner has no logs or is in use.</span>"
/obj/item/device/detective_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob)
if(!scanning)
scanning = 1
spawn(0)
add_log(user, "<font color='blue'>Scanning [M]...</font>")
if (!ishuman(M))
add_log(user, "<span class='warning'>[M] is not human and cannot have the fingerprints.</span>")
else else
src.amount += W.amount if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
//W = null add_log(user, "<span class='info'>No fingerprints found on [M]</span>")
del(W) else
add_fingerprint(user) add_log(user, "<span class='info'>Fingerprints found on [M]. Analysing...</span>")
if (W) sleep(30)
W.add_fingerprint(user) add_log(user, "<span class='info'>[M]'s Fingerprints: [md5(M.dna.uni_identity)]</span>")
return
attack(mob/living/carbon/human/M as mob, mob/user as mob) if ( !M.blood_DNA || !M.blood_DNA.len )
if (!ishuman(M)) add_log(user, "<span class='info'>No blood found on [M]</span>")
user << "\red [M] is not human and cannot have the fingerprints." if(M.blood_DNA)
return 0 del(M.blood_DNA)
if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
user << "\blue No fingerprints found on [M]"
return 0
else
if (src.amount < 1)
user << text("\blue Fingerprints scanned on [M]. Need more cards to print.")
else else
src.amount-- add_log(user, "<span class='info'>Blood found on [M]. Analysing...</span>")
var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc ) sleep(30)
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) for(var/blood in M.blood_DNA)
user << "\blue Blood type: [M.blood_DNA[blood]]\nDNA: [blood]" add_log(user, "<span class='info'>Blood type: [M.blood_DNA[blood]]\nDNA: [blood]</span>")
add_log(null, "<font color='blue'>Ending scan report.</font>")
scanning = 0
return
/obj/item/device/detective_scanner/afterattack(atom/A as obj|turf|area, mob/user as mob)
if(!in_range(A,user))
return
if(!isturf(A) && !isobj(A))
return
if(loc != user)
return return
afterattack(atom/A as obj|turf|area, mob/user as mob) if(!scanning)
if(!in_range(A,user)) scanning = 1
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) add_fingerprint(user)
spawn(0)
//Special case for blood splaters. add_log(user, "<font color='blue'>Scanning [A]...</font>")
if (istype(A, /obj/effect/decal/cleanable/blood) || istype(A, /obj/effect/rune)) //PRINTS
if(!isnull(A.blood_DNA)) if(!A.fingerprints || !A.fingerprints.len)
for(var/blood in A.blood_DNA) if(A.fingerprints)
user << "\blue Blood type: [A.blood_DNA[blood]]\nDNA: [blood]" del(A.fingerprints)
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.")
return 0
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)
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 else
user << "\blue &nbsp;&nbsp;Found [complete_prints.len] intact prints" var/list/completed_prints = list()
for(var/i in complete_prints) // Bah this looks awful but basically it loop throught the last 15 entries.
user << "\blue &nbsp;&nbsp;&nbsp;&nbsp;[i]" for(var/i in A.fingerprints)
var/print = A.fingerprints[i]
//FIBERS completed_prints += print
if(A.suit_fibers) if(completed_prints.len < 1)
user << "\blue Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve." add_log(user, "<span class='info'>No intact prints found</span>")
//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.")
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.")
return 0
return
proc/add_data(atom/A as mob|obj|turf|area)
//I love hashtables.
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 else
data_prints[print] = stringmerge(data_prints[print],A.fingerprints[print]) add_log(user, "<span class='info'>Found [completed_prints.len] intact print[completed_prints.len == 1 ? "" : "s"]. Analysing...</span>")
sleep(30)
for(var/i in completed_prints)
add_log(user, "&nbsp;&nbsp;&nbsp;&nbsp;[i]")
//Now the fibers //FIBERS
var/list/fibers = data_entry[2]
if(!fibers)
fibers = list()
if(A.suit_fibers && A.suit_fibers.len) if(A.suit_fibers && A.suit_fibers.len)
for(var/j = 1, j <= A.suit_fibers.len, j++) //Fibers~~~ add_log(user, "<span class='info'>Fibers found. Analysing...</span>")
if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add! sleep(30)
fibers += A.suit_fibers[j] for(var/fiber in A.suit_fibers)
var/list/blood = data_entry[3] add_log(user, "&nbsp;&nbsp;&nbsp;&nbsp;[fiber]")
if(!blood)
blood = list() //Blood
if(A.blood_DNA && A.blood_DNA.len) if (A.blood_DNA && A.blood_DNA.len)
for(var/main_blood in A.blood_DNA) add_log(user, "<span class='info'>Blood found. Analysing...</span>")
if(!blood[main_blood]) sleep(30)
blood[main_blood] = A.blood_DNA[blood] for(var/blood in A.blood_DNA)
return 1 add_log(user, "&nbsp;&nbsp;&nbsp;&nbsp;Blood type: <font color='red'>[A.blood_DNA[blood]]</font> DNA: <font color='red'>[blood]</font>")
var/list/sum_list[4] //Pack it back up!
sum_list[1] = A.fingerprints //General
sum_list[2] = A.suit_fibers if ((!A.fingerprints || !A.fingerprints.len) && (!A.suit_fibers || !A.suit_fibers.len) && (!A.blood_DNA || !A.blood_DNA.len))
sum_list[3] = A.blood_DNA add_log(null, "Unable to locate any fingerprints, materials, fibers, or blood.")
sum_list[4] = "\The [A] in \the [get_area(A)]" user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
stored["\ref [A]"] = sum_list "<span class='notice'>Unable to locate any fingerprints, materials, fibers, or blood on [A]!</span>",\
return 0 "You hear a faint hum of electrical equipment.")
else
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.")
add_log(null, "<font color='blue'>Ending scan report.</font>")
scanning = 0
return 0
/obj/item/device/detective_scanner/proc/add_log(var/mob/user, var/msg)
if(scanning)
if(user)
user << msg
log += "<span class='prefix'>[time2text(world.time + 432000, "hh:mm:ss")]</span>:&nbsp;&nbsp;[msg]"
else
CRASH("[src] \ref[src] is adding a log when it was never put in scanning mode!")

View File

@@ -71,6 +71,11 @@
log_game("[key_name(user)] fired Space lube from a spray bottle.") log_game("[key_name(user)] fired Space lube from a spray bottle.")
return return
/obj/item/weapon/reagent_containers/spray/attack_self(var/mob/user)
amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10)
user << "<span class='notice'>You switched [amount_per_transfer_from_this == 10 ? "on" : "off"] the pressure nozzle. You'll now use [amount_per_transfer_from_this] units per spray.</span>"
/obj/item/weapon/reagent_containers/spray/examine() /obj/item/weapon/reagent_containers/spray/examine()
set src in usr set src in usr

View File

@@ -48,6 +48,15 @@ Stuff which is in development and not yet visible to players or just code relate
should be listed in the changelog upon commit tho. Thanks. --> should be listed in the changelog upon commit tho. Thanks. -->
<!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here --> <!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here -->
<div class="commit sansserif">
<h2 class="date">23 November 2012</h2>
<h3 class="author">Giacom updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Simplified detective stuff. The high-res scanner is gone and instead the detective's normal scanner will instantly report all fingerprints, dna and cloth fibers in full. This was needed because the system took too long to worth with and disencouraged detectives. Not only that, it made detectives less of a threat from antagonists and made possible scenerios, such as framing someone by changing fingerprints with someone else, non-viable. To replace the computer, the detective will have a full medical computer with access to it. Not only that, but his useless filing cabinet will be replaced with a empty one for serious investigators. Along with this, are fingerprint cards and built-in PDA scanning, as all of security had access to it. The new scanner will also log every finding and you can print them out as a report by clicking the scanner while it is in your hand.</li>
<li class="rscadd">You can toggle the pressure of your sprayer by clicking on it while it is in your hand. With pressure, the sprayer will spray 10 units on the floor, otherwise it sprays 5. You'll need to turn pressure on to spray water on the floor and make it slippery.</li>
</ul>
</div>
<div class="commit sansserif"> <div class="commit sansserif">
<h2 class="date">21 November 2012</h2> <h2 class="date">21 November 2012</h2>
<h3 class="author">Petethegoat updated:</h3> <h3 class="author">Petethegoat updated:</h3>

View File

@@ -780,7 +780,7 @@
"aoZ" = (/obj/machinery/door/airlock/external{name = "External Access"; req_access = null; req_access_txt = "13"},/turf/simulated/floor/plating,/area/maintenance/fpmaint2) "aoZ" = (/obj/machinery/door/airlock/external{name = "External Access"; req_access = null; req_access_txt = "13"},/turf/simulated/floor/plating,/area/maintenance/fpmaint2)
"apa" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/maintenance/fpmaint) "apa" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/maintenance/fpmaint)
"apb" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/obj/machinery/camera{c_tag = "Detective Office Maintenance"; dir = 8},/turf/simulated/floor/plating,/area/maintenance/fpmaint) "apb" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/obj/machinery/camera{c_tag = "Detective Office Maintenance"; dir = 8},/turf/simulated/floor/plating,/area/maintenance/fpmaint)
"apc" = (/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/machinery/light{dir = 8},/obj/structure/filingcabinet/medical,/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) "apc" = (/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/machinery/light{dir = 8},/obj/structure/filingcabinet,/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office)
"apd" = (/turf/simulated/floor/carpet,/area/security/detectives_office) "apd" = (/turf/simulated/floor/carpet,/area/security/detectives_office)
"ape" = (/obj/structure/table/woodentable,/obj/item/weapon/cigpacket,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/item/clothing/glasses/sunglasses,/turf/simulated/floor/carpet,/area/security/detectives_office) "ape" = (/obj/structure/table/woodentable,/obj/item/weapon/cigpacket,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/item/clothing/glasses/sunglasses,/turf/simulated/floor/carpet,/area/security/detectives_office)
"apf" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/turf/simulated/floor/carpet,/area/security/detectives_office) "apf" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/turf/simulated/floor/carpet,/area/security/detectives_office)
@@ -903,7 +903,7 @@
"ars" = (/obj/item/device/radio/intercom{dir = 0; name = "Station Intercom (General)"; pixel_x = -27},/obj/structure/table/woodentable,/obj/item/ammo_magazine/c38,/obj/item/ammo_magazine/c38,/obj/item/weapon/gun/projectile/detective,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; icon_state = "off"; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) "ars" = (/obj/item/device/radio/intercom{dir = 0; name = "Station Intercom (General)"; pixel_x = -27},/obj/structure/table/woodentable,/obj/item/ammo_magazine/c38,/obj/item/ammo_magazine/c38,/obj/item/weapon/gun/projectile/detective,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; icon_state = "off"; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office)
"art" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) "art" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office)
"aru" = (/obj/machinery/camera{c_tag = "Detective's Office"; dir = 1},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) "aru" = (/obj/machinery/camera{c_tag = "Detective's Office"; dir = 1},/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office)
"arv" = (/obj/machinery/computer/forensic_scanning,/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office) "arv" = (/obj/machinery/computer/med_data,/turf/simulated/floor{icon_state = "grimy"},/area/security/detectives_office)
"arw" = (/obj/structure/table/woodentable,/obj/item/device/taperecorder{pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/item/weapon/cartridge/lawyer,/turf/simulated/floor/wood,/area/lawoffice) "arw" = (/obj/structure/table/woodentable,/obj/item/device/taperecorder{pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/item/weapon/cartridge/lawyer,/turf/simulated/floor/wood,/area/lawoffice)
"arx" = (/obj/structure/table/woodentable,/obj/machinery/camera{c_tag = "Law Office"; dir = 1; network = "SS13"},/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/machinery/computer/security/telescreen{desc = "Used for watching Prison Wing holding areas."; name = "Prison Monitor"; network = "Prison"; pixel_x = 0; pixel_y = -30},/turf/simulated/floor/wood,/area/lawoffice) "arx" = (/obj/structure/table/woodentable,/obj/machinery/camera{c_tag = "Law Office"; dir = 1; network = "SS13"},/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/machinery/computer/security/telescreen{desc = "Used for watching Prison Wing holding areas."; name = "Prison Monitor"; network = "Prison"; pixel_x = 0; pixel_y = -30},/turf/simulated/floor/wood,/area/lawoffice)
"ary" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/photocopier,/obj/machinery/door_control{id = "lawyer_blast"; name = "Privacy Shutters"; pixel_x = 25; pixel_y = 8},/turf/simulated/floor/wood,/area/lawoffice) "ary" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/photocopier,/obj/machinery/door_control{id = "lawyer_blast"; name = "Privacy Shutters"; pixel_x = 25; pixel_y = 8},/turf/simulated/floor/wood,/area/lawoffice)