diff --git a/baystation12.dme b/baystation12.dme
index 340036c01aa..880ba77035f 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -95,6 +95,7 @@
#define FILE_DIR "code/modules/clothing/uniforms"
#define FILE_DIR "code/modules/critters"
#define FILE_DIR "code/modules/critters/hivebots"
+#define FILE_DIR "code/modules/flufftext"
#define FILE_DIR "code/modules/food"
#define FILE_DIR "code/modules/mining"
#define FILE_DIR "code/modules/mob"
@@ -658,7 +659,6 @@
#include "code\game\objects\items\weapons\cigs_lighters.dm"
#include "code\game\objects\items\weapons\clown_items.dm"
#include "code\game\objects\items\weapons\dna_injector.dm"
-#include "code\game\objects\items\weapons\evidence.dm"
#include "code\game\objects\items\weapons\explosives.dm"
#include "code\game\objects\items\weapons\flamethrower.dm"
#include "code\game\objects\items\weapons\grenades.dm"
@@ -677,6 +677,7 @@
#include "code\game\objects\items\weapons\stungloves.dm"
#include "code\game\objects\items\weapons\surgery_tools.dm"
#include "code\game\objects\items\weapons\swords_axes_etc.dm"
+#include "code\game\objects\items\weapons\syndie.dm"
#include "code\game\objects\items\weapons\table_rack_parts.dm"
#include "code\game\objects\items\weapons\teleportation.dm"
#include "code\game\objects\items\weapons\tiles_wires.dm"
@@ -795,6 +796,8 @@
#include "code\modules\critters\critter_defenses.dm"
#include "code\modules\critters\critters.dm"
#include "code\modules\critters\hivebots\hivebot.dm"
+#include "code\modules\flufftext\Dreaming.dm"
+#include "code\modules\flufftext\TextFilters.dm"
#include "code\modules\food\food.dm"
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\mining\datum_processing_recipe.dm"
@@ -828,6 +831,7 @@
#include "code\modules\mob\living\say.dm"
#include "code\modules\mob\living\blob\blob.dm"
#include "code\modules\mob\living\carbon\carbon.dm"
+#include "code\modules\mob\living\carbon\give.dm"
#include "code\modules\mob\living\carbon\shock.dm"
#include "code\modules\mob\living\carbon\alien\alien.dm"
#include "code\modules\mob\living\carbon\alien\say.dm"
@@ -1027,6 +1031,7 @@
#include "code\WorkInProgress\Ported\ZeroPoint\LaserComputer.dm"
#include "code\WorkInProgress\Ported\ZeroPoint\SuperMatter.dm"
#include "code\WorkInProgress\SkyMarshal\coatrack.dm"
+#include "code\WorkInProgress\SkyMarshal\evidence.dm"
#include "code\WorkInProgress\SkyMarshal\traitoritems.dm"
#include "code\WorkInProgress\SkyMarshal\wardrobes.dm"
#include "code\WorkInProgress\Tastyfish\Eliza.dm"
diff --git a/code/game/objects/items/weapons/evidence.dm b/code/WorkInProgress/SkyMarshal/evidence.dm
similarity index 78%
rename from code/game/objects/items/weapons/evidence.dm
rename to code/WorkInProgress/SkyMarshal/evidence.dm
index c162f9ac70b..e78bf737a73 100644
--- a/code/game/objects/items/weapons/evidence.dm
+++ b/code/WorkInProgress/SkyMarshal/evidence.dm
@@ -16,8 +16,6 @@
*/
/obj/item/weapon/evidencebag/afterattack(obj/item/O, mob/user as mob)
-
-//Now you can put it into a briefcase, if it is in your hand. Otherwise, if it is evidence on the ground, it picks it up.
if(istype(O, /obj/item/weapon/storage) && O in user)
user << "You put the evidence bag into the [O]."
return ..()
@@ -30,19 +28,17 @@
if(src.contents.len > 0)
user << "The [src] already has something inside it."
return ..()
- if(istype(O.loc, /obj/item/weapon/storage))
- user << "This is broke as hell."
- return
-/* var/obj/item/weapon/storage/U = O.loc
- w_class = O.w_class
- for(var/i, i < U.contents.len, i++)
- if(O in U.contents[i])
- U.contents[i] = null
- O.loc = src
- continue*/
+ if(istype(O.loc,/obj/item/weapon/storage))
+ var/obj/item/weapon/storage/U = O.loc
+ user.client.screen -= O
+ U.contents.Remove(O)
+ if(istype(O.loc,/obj/item/clothing/suit/storage/))
+ var/obj/item/clothing/suit/storage/U = O.loc
+ user.client.screen -= O
+ U.contents.Remove(O)
user << "You put the [O] inside the [src]."
icon_state = "evidence"
- src.underlays += O
+ src.overlays += O
desc = "An evidence bag containing \a [O]. [O.desc]"
O.loc = src
w_class = O.w_class
@@ -53,7 +49,7 @@
if (src.contents.len > 0)
var/obj/item/I = src.contents[1]
user << "You take the [I] out of the [src]."
- src.underlays -= I
+ src.overlays -= I
I.loc = get_turf(user.loc)
w_class = 1
src.icon_state = "evidenceobj"
@@ -72,7 +68,7 @@
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)
+ new /obj/item/weapon/evidencebag(src)
new /obj/item/weapon/f_card(src)
..()
return
\ No newline at end of file
diff --git a/code/WorkInProgress/SkyMarshal/wardrobes.dm b/code/WorkInProgress/SkyMarshal/wardrobes.dm
index 80c0c6c310f..9cb9942a944 100644
--- a/code/WorkInProgress/SkyMarshal/wardrobes.dm
+++ b/code/WorkInProgress/SkyMarshal/wardrobes.dm
@@ -5,6 +5,7 @@
icon_state = "wardrobe"
item_state = "wardrobe"
w_class = 4
+ layer = 2.9
var
descriptor = "various clothing."
@@ -34,7 +35,7 @@
examine()
set src in usr
..()
- usr << "It claims to contain [contents.len ? descriptor : descriptor + "...but it looks empty"]"
+ usr << "It claims to contain [contents.len ? descriptor : descriptor + "... but it looks empty"]"
return
update_icon()
@@ -481,7 +482,6 @@
new /obj/item/weapon/pen(src)
new /obj/item/weapon/clipboard(src)
new /obj/item/device/pda/quartermaster(src)
- new /obj/item/clothing/gloves/black(src)
new /obj/item/clothing/glasses/sunglasses(src)
new /obj/item/device/radio/headset/heads/qm(src)
new /obj/item/clothing/shoes/black(src)
@@ -497,7 +497,6 @@
new /obj/item/weapon/storage/box(BPK)
new /obj/item/weapon/pen(src)
new /obj/item/device/pda/quartermaster(src)
- new /obj/item/clothing/gloves/black(src)
new /obj/item/device/radio/headset/headset_cargo(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/under/rank/cargo(src)
@@ -518,7 +517,6 @@
new /obj/item/weapon/pickaxe(src)
new /obj/item/weapon/crowbar(src)
new /obj/item/clothing/glasses/meson(src)
- new /obj/item/clothing/gloves/black(src)
new /obj/item/device/radio/headset/headset_mine(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/under/rank/miner(src)
diff --git a/code/WorkInProgress/detective_work.dm b/code/WorkInProgress/detective_work.dm
index 8a7db0cf947..da6d6e92881 100644
--- a/code/WorkInProgress/detective_work.dm
+++ b/code/WorkInProgress/detective_work.dm
@@ -49,24 +49,42 @@ atom/proc/add_fibers(mob/living/carbon/human/M)
suit_fibers += "Material from a pair of [M.gloves.name]."
if(!suit_fibers.len) del suit_fibers
+#define 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 = "High-Res Forensic Scanning Computer"
icon_state = "forensic"
- var/obj/item/scanning
- var/temp = ""
- var/canclear = 1
- var/authenticated = 0
+ var
+ obj/item/scanning
+ temp = ""
+ canclear = 1
+ authenticated = 0
- var/scan_data = ""
- var/scan_name = ""
- var/scan_process = 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.
+ list/files
+//This holds objects (1) without prints, and their fibers(2) and blood(3).
+ list/misc
+ obj/item/weapon/f_card/card
+
+ scan_data = ""
+ scan_name = ""
+ scan_process = 0
req_access = list(access_forensics_lockers)
+
attack_ai(mob/user)
return attack_hand(user)
+
attack_hand(mob/user)
if(..())
return
@@ -86,22 +104,217 @@ obj/machinery/computer/forensic_scanning
if(scanning)
if(scan_process)
dat += "Scan Object: {[scanning.name]}
"
- dat += "{Cancel Scan} {Print}
"
+ dat += "{Cancel Scan} {Print}
"
else
if(isai) dat += "Scan Object: {[scanning.name]}
"
else dat += "Scan Object: {[scanning.name]}
"
- dat += "{Scan} {Print}
"
+ dat += "{Scan} {Print}
"
else
if(isai) dat += "{No Object Inserted}
"
else dat += "{No Object Inserted}
"
- dat += "{Scan} {Print}
"
+ dat += "{Scan} {Print}
"
+ dat += "{Access Database}
"
dat += "[scan_data]"
if(scan_data && !scan_process)
dat += "
{Erase Data}"
user << browse(dat,"window=scanner")
onclose(user,"scanner")
+
+
ex_act()
return
+
+
+ proc/add_data_scanner(var/obj/item/device/detective_scanner/W)
+ for(var/i = 1, i < (W.stored.len + 1), i++)
+ var/list/data = W.stored[i]
+ add_data(data[1],1,data[2],data[3],data[4])
+
+
+ proc/add_data(var/atom/A, var/override = 0, var/tempfingerprints, var/tempsuit_fibers,var/tempblood_DNA)
+//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.
+ var
+ backup_prints
+ backup_fibers
+ backup_DNA
+ if(override)
+ backup_prints = A.fingerprints
+ A.fingerprints = tempfingerprints
+ backup_fibers = A.suit_fibers
+ A.suit_fibers = tempsuit_fibers
+ backup_DNA = A.blood_DNA
+ A.blood_DNA = tempblood_DNA
+ if((!A.fingerprints || !length(A.fingerprints))) //No prints
+ var/merged = 0
+ if(!misc)
+ misc = list()
+ if(misc)
+ for(var/i = 1, i < (misc.len + 1), i++) //Lets see if we can find it.
+ var/list/templist = misc[i]
+ var/check = templist[1]
+ if(check == A) //There it is!
+ merged = 1
+ var/list/fibers = templist[2]
+ if(!fibers)
+ fibers = list()
+ if(A.suit_fibers)
+ for(var/j = 1, j < (A.suit_fibers.len + 1), j++) //Fibers~~~
+ if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add!
+ fibers += A.suit_fibers[j]
+ var/list/blood = templist[3]
+ if(!blood)
+ blood = list()
+ if(A.blood_DNA)
+ for(var/j = 1, j < (A.blood_DNA.len + 1), j++) //Blood~~~
+ if(!blood.Find(A.blood_DNA[j])) //It isn't! Add!
+ blood += A.blood_DNA[j]
+ var/list/sum_list[3] //Pack it back up!
+ sum_list[1] = A
+ sum_list[2] = fibers
+ sum_list[3] = blood
+ misc[i] = sum_list //Store it!
+ break //We found it, we're done here.
+ if(!merged) //Nope! Guess we have to add it!
+ var/list/templist[3]
+ templist[1] = A
+ templist[2] = A.suit_fibers
+ templist[3] = A.blood_DNA
+ misc.len++
+ misc[misc.len] = templist //Store it!
+ return !merged
+ else //Has prints.
+ var/list/found_prints[A.fingerprints.len + 1]
+ for(var/i = 1, i < (found_prints.len + 1), i++)
+ found_prints[i] = 0
+ if(!files)
+ files = list()
+ for(var/i = 1, i < (files.len + 1), i++) //Lets see if we can find the owner of the prints
+ var/list/perp_list = files[i]
+ var/list/perp_prints = params2list(perp_list[1])
+ var/perp = perp_prints[1]
+ var/found2 = 0
+ for(var/m = 1, m < (A.fingerprints.len + 1), m++) //Compare database prints with prints on object.
+ var/list/test_prints_list = params2list(A.fingerprints[m])
+ var/checker = test_prints_list[1]
+ if(checker == perp) //Found 'em! Merge!
+ found_prints[m] = 1
+ for(var/n = 2, n < (perp_list.len + 1), n++) //Lets see if it is already in the database
+ var/list/target = perp_list[n]
+ if(target[1] == A) //Found the original object!
+ found2 = 1
+ var/list/prints = target[2]
+ if(!prints)
+ prints = list()
+ if(A.fingerprints)
+ for(var/j = 1, j < (A.fingerprints.len + 1), j++) //Fingerprints~~~
+ var/list/print_test1 = params2list(A.fingerprints[j])
+ var/test_print1 = print_test1[1]
+ var/found = 0
+ for(var/k = 1, k <= (prints.len + 1), k++) //Lets see if the print is already in there
+ var/list/print_test2 = params2list(prints[k])
+ var/test_print2 = print_test2[1]
+ if(test_print2 == test_print1) //It is! Merge!
+ prints[k] = test_print2 + "&" + stringmerge(print_test2[2],print_test1[2])
+ found = 1
+ break //We found it, we're done here.
+ if(!found) //It isn't! Add!
+ prints += A.fingerprints[j]
+ var/list/fibers = target[3]
+ if(!fibers)
+ fibers = list()
+ if(A.suit_fibers)
+ 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 = target[4]
+ if(!blood)
+ blood = list()
+ if(A.blood_DNA)
+ for(var/j = 1, j < A.blood_DNA.len, j++) //Blood~~~
+ if(!blood.Find(A.blood_DNA[j])) //It isn't! Add!
+ blood += A.blood_DNA[j]
+ var/list/sum_list[4] //Pack it back up!
+ sum_list[1] = A
+ sum_list[2] = prints
+ sum_list[3] = fibers
+ sum_list[4] = blood
+ perp_list[n] = sum_list //Store it!
+ files[i] = perp_list
+ break //We found it, we're done here.
+ if(!found2) //Add a new datapoint to this perp!
+ var/list/sum_list[4]
+ sum_list[1] = A
+ sum_list[2] = A.fingerprints
+ sum_list[3] = A.suit_fibers
+ sum_list[4] = A.blood_DNA
+ perp_list.len++
+ perp_list[perp_list.len] = sum_list
+ files[i] = perp_list
+ for(var/m = 1, m < found_prints.len, m++) //Uh Oh! A print wasn't used! New datapoint!
+ if(found_prints[m] == 0)
+ var/list/newperp[2]
+ var/list/sum_list[4]
+ sum_list[1] = A
+ sum_list[2] = A.fingerprints
+ sum_list[3] = A.suit_fibers
+ sum_list[4] = A.blood_DNA
+ newperp[2] = sum_list
+ newperp[1] = A.fingerprints[m]
+ if(!files)
+ files = newperp
+ else
+ files.len++
+ files[files.len] = newperp
+ update_fingerprints() //Lets update the calculated sum of the stored prints.
+ if(override)
+ A.fingerprints = backup_prints
+ A.suit_fibers = backup_fibers
+ A.blood_DNA = backup_DNA
+ return
+
+
+ proc/update_fingerprints() //I am tired, but this updates the master print, which is used to determine completion of a print.
+ for(var/k = 1, k < (files.len + 1), k++)
+ var/list/perp_list = files[k]
+ var/list/perp_prints = params2list(perp_list[1])
+ var/perp = perp_prints[1]
+ var/list/found_prints = list()
+ for(var/i = 2, i < (perp_list.len + 1), i++)
+ var/list/test_list = perp_list[i]
+ var/list/test_prints = test_list[2]
+ for(var/j = 1, j < (test_prints.len + 1), j++)
+ var/list/test_list_2 = params2list(test_prints[j])
+ var/test_prints_2 = test_list_2[1]
+ if(test_prints_2 == perp)
+ found_prints += test_list_2[2]
+ break
+ for(var/prints in found_prints)
+ perp_prints[2] = stringmerge(perp_prints[2],prints)
+ perp_list[1] = perp + "&" + perp_prints[2]
+ files[k] = perp_list
+ return
+
+ proc/process_card() //I am tired, but this updates the master print from a fingerprint card
+ //which is used to determine completion of a print.
+ if(card.fingerprints)
+ for(var/k = 1, k < (card.fingerprints.len + 1), k++)
+ var/list/test_prints = params2list(card.fingerprints[k])
+ var/print = test_prints[1]
+ for(var/i = 1, i < (files.len + 1), i++)
+ var/list/test_list = files[i]
+ var/list/perp_prints = params2list(test_list[1])
+ var/perp = perp_prints[1]
+ if(perp == print)
+ test_list[1] = print + "&" + print
+ files[i] = test_list
+ break
+ del(card)
+ return
+
+ proc/get_name(var/atom/A)
+ return A.name
+
Topic(href,href_list)
switch(href_list["operation"])
if("login")
@@ -135,7 +348,7 @@ obj/machinery/computer/forensic_scanning
if(istype(I, /obj/item/weapon/evidencebag))
scanning = I.contents[1]
scanning.loc = src
- I.underlays = null
+ I.overlays -= scanning
I.icon_state = "evidenceobj"
else
scanning = I
@@ -143,6 +356,141 @@ obj/machinery/computer/forensic_scanning
I.loc = src
else
temp = "Invalid Object Rejected."
+ if("card")
+ var/mob/M = usr
+ var/obj/item/I = M.equipped()
+ if(I && istype(I,/obj/item/weapon/f_card))
+ card = I
+ M.drop_item()
+ I.loc = src
+ process_card()
+ usr << "You insert the card, and it is destroyed by the machinery in the process of comparing prints."
+ else
+ usr << "\red Invalid Object Rejected."
+ if("database")
+ canclear = 1
+ if(!misc && !files)
+ temp = "Database is empty."
+ else
+ if(files)
+ temp = "Criminal Evidence Database
"
+ temp += "Consolidated data points:
"
+ for(var/i = 1, i < (files.len + 1), i++)
+ temp += "{Dossier [i]}
"
+ temp += "
{Insert Finger Print Card}
"
+ else
+ temp = ""
+ if(misc)
+ temp += "Auxiliary Evidence Database
"
+ temp += "This is where anything without fingerprints goes.
"
+ for(var/i = 1, i < (misc.len + 1), i++)
+ var/list/temp_list = misc[i]
+ var/item_name = get_name(temp_list[1])
+ temp += "{[item_name]}
"
+ if("record")
+ canclear = 0
+ if(files)
+ temp = "Criminal Evidence Database
"
+ temp += "Consolidated data points: Dossier [href_list["identifier"]]
"
+ var/identifier = text2num(href_list["identifier"])
+ var/list/dossier = files[identifier]
+ var/list/prints = params2list(dossier[1])
+ var/print_string = "Fingerprints: Print not complete!
"
+ if(stringpercent(prints[2]) <= FINGERPRINT_COMPLETE)
+ print_string = "Fingerprints: (80% or higher completion reached)
" + prints[2] + "
"
+ temp += print_string
+ for(var/i = 2, i < (dossier.len + 1), i++)
+ var/list/outputs = dossier[i]
+ var/item_name = get_name(outputs[1])
+ var/list/prints_len = outputs[2]
+ temp += "Object: [item_name]
"
+ temp += " [prints_len.len] Unique fingerprints found.
"
+ var/list/fibers = outputs[3]
+ if(fibers)
+ var/dat = "[fibers[1]]"
+ for(var/j = 2, j < (fibers.len + 1), j++)
+ dat += ",
[fibers[j]]"
+ temp += " Fibers: [dat]
"
+ else
+ temp += " No fibers found.
"
+ var/list/blood = outputs[4]
+ if(blood)
+ var/dat = "[blood[1]]"
+ if(blood.len > 1)
+ for(var/j = 2, j < (blood.len + 1), j++)
+ dat += ",
[blood[j]]"
+ temp += " Blood: [dat]
"
+ else
+ temp += " No blood found.
"
+ else
+ temp = "ERROR. Database not found!
"
+ temp += "
{Print}"
+ temp += "
{Return}"
+ if("databaseprint")
+ if(files)
+ var/obj/item/weapon/paper/P = new(loc)
+ P.name = "Database File (Dossier [href_list["identifier"]])"
+ P.overlays += "paper_words"
+ P.info = "Criminal Evidence Database
"
+ P.info += "Consolidated data points: Dossier [href_list["identifier"]]
"
+ var/list/dossier = files[text2num(href_list["identifier"])]
+ var/list/prints = params2list(dossier[1])
+ var/print_string = "Fingerprints: Print not complete!
"
+ if(stringpercent(prints[2]) <= FINGERPRINT_COMPLETE)
+ print_string = "Fingerprints: " + prints[2] + "
"
+ P.info += print_string
+ for(var/i = 2, i < (dossier.len + 1), i++)
+ var/list/outputs = dossier[i]
+ var/item_name = get_name(outputs[1])
+ var/list/prints_len = outputs[2]
+ P.info += "Object: [item_name]
"
+ P.info += " [prints_len.len] Unique fingerprints found.
"
+ var/list/fibers = outputs[3]
+ if(fibers)
+ var/dat = "[fibers[1]]"
+ for(var/j = 2, j < (fibers.len + 1), j++)
+ dat += ",
[fibers[j]]"
+ P.info += " Fibers: [dat]
"
+ else
+ P.info += " No fibers found.
"
+ var/list/blood = outputs[4]
+ if(blood)
+ var/dat = "[blood[1]]"
+ if(blood.len > 1)
+ for(var/j = 2, j < (blood.len + 1), j++)
+ dat += ",
[blood[j]]"
+ P.info += " Blood: [dat]
"
+ else
+ P.info += " No blood found."
+ else
+ usr << "ERROR. Database not found!
"
+ if("auxiliary")
+ canclear = 0
+ if(misc)
+ temp = "Auxiliary Evidence Database
"
+ var/identifier = text2num(href_list["identifier"])
+ var/list/outputs = misc[identifier]
+ var/item_name = get_name(outputs[1])
+ temp += "Consolidated data points: [item_name]
"
+ var/list/fibers = outputs[2]
+ if(fibers)
+ var/dat = "[fibers[1]]"
+ for(var/j = 2, j < (fibers.len + 1), j++)
+ dat += ",
[fibers[j]]"
+ temp += " Fibers: [dat]
"
+ else
+ temp += " No fibers found."
+ var/list/blood = outputs[3]
+ if(blood)
+ var/dat = "[blood[1]]"
+ for(var/j = 2, j < (blood.len + 1), j++)
+ dat += ",
[blood[j]]"
+ temp += " Blood: [dat]
"
+ else
+ temp += " No blood found.
"
+ else
+ temp = "ERROR. Database not found!
"
+ temp += "
{Return}"
if("scan")
if(scanning)
scan_process = 3
@@ -174,20 +522,20 @@ obj/machinery/computer/forensic_scanning
scan_data = "[scanning]
"
if (scanning.blood_DNA)
scan_data += "Blood Found:
"
- scan_data += "-Blood type: [scanning.blood_type]\nDNA: [scanning.blood_DNA]
"
+ for(var/i = 1, i < (scanning.blood_DNA.len + 1), i++)
+ var/list/templist = scanning.blood_DNA[i]
+ scan_data += "-Blood type: [templist[2]]\nDNA: [templist[1]]
"
else
scan_data += "No Blood Found
"
- if (!( scanning.fingerprints ))
+ if (!length(scanning.fingerprints))
scan_data += "No Fingerprints Found
"
else
- var/list/L = params2list(scanning.fingerprints)
- scan_data += "Isolated [L.len] Fingerprints:
"
- for(var/i in L)
- scan_data += "#[L.Find(i)] - [i]
"
- scan_data += "
"
+ var/list/L = scanning.fingerprints
+ scan_data += "Isolated [L.len] Fingerprints. Loaded into database.
"
+ add_data(scanning)
if(!scanning.suit_fibers)
- if(istype(scanning,/obj/item/device/detective_scanner))
+ /*if(istype(scanning,/obj/item/device/detective_scanner))
var/obj/item/device/detective_scanner/scanner = scanning
if(scanner.stored_name)
scan_data += "Fibers/Materials Data - [scanner.stored_name]:
"
@@ -195,21 +543,26 @@ obj/machinery/computer/forensic_scanning
scan_data += "- [data]
"
else
scan_data += "No Fibers/Materials Data
"
- else
- scan_data += "No Fibers/Materials Located
"
+ else*/
+ scan_data += "No Fibers/Materials Located
"
else
- if(istype(scanning,/obj/item/device/detective_scanner))
+ /*if(istype(scanning,/obj/item/device/detective_scanner))
var/obj/item/device/detective_scanner/scanner = scanning
if(scanner.stored_name)
scan_data += "Fibers/Materials Data - [scanner.stored_name]:
"
for(var/data in scanner.stored_fibers)
scan_data += "- [data]
"
else
- scan_data += "No Fibers/Materials Data
"
+ scan_data += "No Fibers/Materials Data
"*/
scan_data += "Fibers/Materials Found:
"
for(var/data in scanning.suit_fibers)
scan_data += "- [data]
"
+ if(istype(scanning,/obj/item/device/detective_scanner))
+ scan_data += "
Data transfered from Scanner to Database.
"
+ add_data_scanner(scanning)
+ else if(!length(scanning.fingerprints))
+ scan_data += "
Add to Database?
"
else
temp = "Scan Failed: No Object"
@@ -227,6 +580,11 @@ obj/machinery/computer/forensic_scanning
scan_data = ""
if("cancel")
scan_process = 0
+ if("add")
+ if(scanning)
+ add_data(scanning)
+ else
+ temp = "Data Transfer Failed: No Object."
updateUsrDialog()
detective
@@ -244,10 +602,12 @@ mob/var
obj/item/clothing/gloves/var
transfer_blood = 0
mob/living/carbon/human/bloody_hands_mob
-/*
-obj/decal/cleanable/blood/var/track_amt = 3
+obj/effect/decal/cleanable/blood/var
+ track_amt = 3
+ mob/blood_owner
+
turf/Exited(mob/living/carbon/human/M)
if(istype(M,/mob/living))
if(!istype(src, /turf/space)) // Bloody tracks code starts here
@@ -271,9 +631,9 @@ turf/Entered(mob/living/carbon/human/M)
M.shoes.track_blood--
src.add_bloody_footprints(M.shoes.track_blood_mob,0,M.dir,M.shoes.name)
- for(var/obj/decal/cleanable/blood/B in src)
+ for(var/obj/effect/decal/cleanable/blood/B in src)
if(B.track_amt <= 0) continue
- if(B.type != /obj/decal/cleanable/blood/tracks && B.type != /obj/decal/cleanable/blood/drip)
+ if(B.type != /obj/effect/decal/cleanable/blood/tracks)
if(istype(M,/mob/living/carbon/human))
if(M.shoes)
M.shoes.add_blood(B.blood_owner)
@@ -282,30 +642,31 @@ turf/Entered(mob/living/carbon/human/M)
else
M.add_blood(B.blood_owner)
M.track_blood_mob = B.blood_owner
- M.track_blood = max(M.track_blood,8)
+ M.track_blood = max(M.track_blood,rand(4,8))
B.track_amt--
break
. = ..()
turf/proc/add_bloody_footprints(mob/living/carbon/human/M,leaving,d,info)
- for(var/obj/decal/cleanable/blood/tracks/T in src)
+ for(var/obj/effect/decal/cleanable/blood/tracks/T in src)
if(T.dir == d)
if((leaving && T.icon_state == "steps2") || (!leaving && T.icon_state == "steps1"))
T.desc = "These bloody footprints appear to have been made by [info]."
if(istype(M,/mob/living/carbon/human))
- T.blood_DNA = M.dna.unique_enzymes
- T.blood_type = M.b_type
+ T.blood_DNA.len++
+ T.blood_DNA[T.blood_DNA.len] = list(M.dna.unique_enzymes,M.b_type)
return
- var/obj/decal/cleanable/blood/tracks/this = new(src)
+ var/obj/effect/decal/cleanable/blood/tracks/this = new(src)
+ this.icon = 'footprints.dmi'
if(leaving)
- this.icon_state = "steps2"
+ this.icon_state = "blood2"
else
- this.icon_state = "steps1"
+ this.icon_state = "blood1"
this.dir = d
this.desc = "These bloody footprints appear to have been made by [info]."
if(istype(M,/mob/living/carbon/human))
- this.blood_DNA = M.dna.unique_enzymes
- this.blood_type = M.b_type
+ this.blood_DNA.len++
+ this.blood_DNA[this.blood_DNA.len] = list(M.dna.unique_enzymes,M.b_type)
proc/get_tracks(mob/M)
if(istype(M,/mob/living))
@@ -320,8 +681,8 @@ proc/get_tracks(mob/M)
proc/blood_incompatible(donor,receiver)
var
- donor_antigen = copytext(donor,1,2)
- receiver_antigen = copytext(receiver,1,2)
+ 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
@@ -333,5 +694,4 @@ proc/blood_incompatible(donor,receiver)
if("O")
if(donor_antigen != "O") return 1
//AB is a universal receiver.
- return 0
-*/
\ No newline at end of file
+ return 0
\ No newline at end of file
diff --git a/code/WorkInProgress/meteors.dm b/code/WorkInProgress/meteors.dm
new file mode 100644
index 00000000000..35c370fb0b0
--- /dev/null
+++ b/code/WorkInProgress/meteors.dm
@@ -0,0 +1,154 @@
+#define METEOR_TEMPERATURE
+
+/var/const/meteor_wave_delay = 625 //minimum wait between waves in tenths of seconds
+//set to at least 100 unless you want evarr ruining every round
+
+/var/const/meteors_in_wave = 20
+/var/const/meteors_in_small_wave = 10
+
+/proc/meteor_wave(var/number = meteors_in_wave)
+ if(!ticker || wavesecret)
+ return
+
+ var/startx
+ var/starty
+ var/endx
+ var/endy
+ var/turf/pickedstart
+ var/turf/pickedgoal
+ switch(pick(1,2,3,4))
+ if(1) //NORTH
+ starty = world.maxy-3
+ startx = rand(1, world.maxx-1)
+ endy = 1
+ endx = rand(1, world.maxx-1)
+ if(2) //EAST
+ starty = rand(1,world.maxy-1)
+ startx = world.maxx-3
+ endy = rand(1, world.maxy-1)
+ endx = 1
+ if(3) //SOUTH
+ starty = 3
+ startx = rand(1, world.maxx-1)
+ endy = world.maxy-1
+ endx = rand(1, world.maxx-1)
+ if(4) //WEST
+ starty = rand(1, world.maxy-1)
+ startx = 3
+ endy = rand(1,world.maxy-1)
+ endx = world.maxx-1
+ pickedstart = locate(startx, starty, 1)
+ pickedgoal = locate(endx, endy, 1)
+ wavesecret = 1
+ for(var/i = 0 to number)
+ spawn(rand(10,100))
+ spawn_meteor(pickedstart, pickedgoal)
+ spawn(meteor_wave_delay)
+ wavesecret = 0
+
+/proc/spawn_meteors(var/turf/pickedstart, var/turf/pickedgoal, var/number = meteors_in_small_wave)
+ for(var/i = 0; i < number; i++)
+ spawn(0)
+ spawn_meteor(pickedstart, pickedgoal)
+
+/proc/spawn_meteor(var/turf/pickedstart, var/turf/pickedgoal)
+
+ var/route = rand(1,5)
+ var/turf/tempgoal = pickedgoal
+ for(var/i, i < route, i++)
+ tempgoal = get_step(tempgoal,rand(1,8))
+
+ var/obj/effect/meteor/M
+ switch(rand(1, 100))
+ if(1 to 15)
+ M = new /obj/effect/meteor/big(pickedstart)
+ if(16 to 75)
+ M = new /obj/effect/meteor( pickedstart )
+ if(76 to 100)
+ M = new /obj/effect/meteor/small( pickedstart )
+
+ M.dest = tempgoal
+
+ do
+ sleep(1)
+ walk_towards(M, M.dest, 1)
+ while (!istype(M.loc, /turf/space) || pickedstart.loc.name != "Space" ) //FUUUCK, should never happen.
+
+ return
+
+/obj/effect/meteor
+ name = "meteor"
+ icon = 'meteor.dmi'
+ icon_state = "flaming"
+ density = 1
+ anchored = 1.0
+ var/hits = 1
+ var/dest
+ pass_flags = PASSTABLE
+
+/obj/effect/meteor/small
+ name = "small meteor"
+ icon_state = "smallf"
+ pass_flags = PASSTABLE | PASSGRILLE
+
+/obj/effect/meteor/Move()
+ var/turf/T = src.loc
+ if (istype(T, /turf))
+ T.hotspot_expose(METEOR_TEMPERATURE, 1000)
+ ..()
+ return
+
+/obj/effect/meteor/Bump(atom/A)
+ spawn(0)
+ for(var/mob/M in range(10, src))
+ if(!M.stat && !istype(M, /mob/living/silicon/ai)) //bad idea to shake an ai's view
+ shake_camera(M, 3, 1)
+ if (A)
+ A.meteorhit(src)
+ playsound(src.loc, 'meteorimpact.ogg', 40, 1)
+ if (--src.hits <= 0)
+ if(prob(15))// && !istype(A, /obj/structure/grille))
+ explosion(src.loc, 4, 5, 6, 7, 0)
+ playsound(src.loc, "explosion", 50, 1)
+ del(src)
+ return
+
+
+/obj/effect/meteor/ex_act(severity)
+
+ if (severity < 4)
+ del(src)
+ return
+
+/obj/effect/meteor/big
+ name = "big meteor"
+ hits = 5
+
+ ex_act(severity)
+ return
+
+ Bump(atom/A)
+ spawn(0)
+ for(var/mob/M in range(10, src))
+ if(!M.stat && !istype(M, /mob/living/silicon/ai)) //bad idea to shake an ai's view
+ shake_camera(M, 3, 1)
+ if (A)
+ if(isobj(A))
+ del(A)
+ else
+ A.meteorhit(src)
+ src.hits--
+ return
+ playsound(src.loc, 'meteorimpact.ogg', 40, 1)
+ if (--src.hits <= 0)
+ if(prob(15) && !istype(A, /obj/structure/grille))
+ explosion(src.loc, 1, 2, 3, 4, 0)
+ playsound(src.loc, "explosion", 50, 1)
+ del(src)
+ return
+
+/obj/effect/meteor/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/pickaxe))
+ del(src)
+ return
+ ..()
\ No newline at end of file
diff --git a/code/defines/atom.dm b/code/defines/atom.dm
index 151b81198af..5db2913830a 100644
--- a/code/defines/atom.dm
+++ b/code/defines/atom.dm
@@ -2,11 +2,10 @@
layer = 2
var/level = 2
var/flags = FPRINT
- var/fingerprints = null
+ var/list/fingerprints = list()
var/list/fingerprintshidden = new/list()
var/fingerprintslast = null
- var/blood_DNA = null
- var/blood_type = null
+ var/list/blood_DNA = null
var/last_bumped = 0
var/pass_flags = 0
diff --git a/code/defines/global.dm b/code/defines/global.dm
index d4e5dd29bc4..170b887a2be 100644
--- a/code/defines/global.dm
+++ b/code/defines/global.dm
@@ -169,6 +169,7 @@ var
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
const/MAX_MESSAGE_LEN = 1024
const/MAX_PAPER_MESSAGE_LEN = 3072
+ const/MAX_BOOK_MESSAGE_LEN = 9216
list/paper_blacklist = list("script","frame","iframe","input","button","a","embed","object")
diff --git a/code/defines/mob/mob.dm b/code/defines/mob/mob.dm
index ee7a1bfa9b9..a20e0b28f98 100644
--- a/code/defines/mob/mob.dm
+++ b/code/defines/mob/mob.dm
@@ -164,7 +164,7 @@
var/logged_in = 0
var/underwear = 1//Human
- var/be_syndicate = 0//This really should be a client variable.
+ var/be_syndicate = 0 //This really should be a client variable. EDIT: Hijacked for my own nefarious purposes! --SkyMarshal
var/be_random_name = 0
var/const/blindness = 1//Carbon
var/const/deafness = 2//Carbon
diff --git a/code/defines/obj/closet.dm b/code/defines/obj/closet.dm
index 5ff8567d826..5c2d5442c9d 100644
--- a/code/defines/obj/closet.dm
+++ b/code/defines/obj/closet.dm
@@ -13,6 +13,7 @@
var/health = 100 //Might be a bit much, dono can always change later //Nerfed -Pete
var/lastbang //
var/lasttry = 0
+ layer = 2.8
/obj/structure/closet/acloset
name = "Strange closet"
diff --git a/code/defines/obj/decal.dm b/code/defines/obj/decal.dm
index 29e1ee6519f..86fb51cc2a3 100644
--- a/code/defines/obj/decal.dm
+++ b/code/defines/obj/decal.dm
@@ -49,9 +49,9 @@
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
var/list/viruses = list()
- blood_DNA = null
- blood_type = null
+ blood_DNA = list()
var/datum/disease2/disease/virus2 = null
+ var/OriginalMob = null
Del()
for(var/datum/disease/D in viruses)
diff --git a/code/defines/procs/gamehelpers.dm b/code/defines/procs/gamehelpers.dm
index 587d98969fc..e9b2c0207fc 100644
--- a/code/defines/procs/gamehelpers.dm
+++ b/code/defines/procs/gamehelpers.dm
@@ -187,4 +187,107 @@
var/dy = T.y - centerturf.y
if(dx*dx + dy*dy <= rsq)
turfs += T
- return turfs
\ No newline at end of file
+ return turfs
+
+proc/check_can_reach(atom/user, atom/target)
+ var/direct = get_dir(user, target)
+ var/obj/item/weapon/dummy/D = new /obj/item/weapon/dummy( user.loc )
+ var/ok = 0
+ if ( (direct - 1) & direct)
+
+ // ------- CLICKED OBJECT IS LOCATED IN A DIAGONAL POSITION FROM THE PERSON -------
+
+ var/turf/Step_1
+ var/turf/Step_2
+ switch(direct)
+ if(5.0)
+ Step_1 = get_step(user, NORTH)
+ Step_2 = get_step(user, EAST)
+
+ if(6.0)
+ Step_1 = get_step(user, SOUTH)
+ Step_2 = get_step(user, EAST)
+
+ if(9.0)
+ Step_1 = get_step(user, NORTH)
+ Step_2 = get_step(user, WEST)
+
+ if(10.0)
+ Step_1 = get_step(user, SOUTH)
+ Step_2 = get_step(user, WEST)
+
+ else
+ if(Step_1 && Step_2)
+
+ // ------- BOTH CARDINAL DIRECTIONS OF THE DIAGONAL EXIST IN THE GAME WORLD -------
+
+ var/check_1 = 0
+ var/check_2 = 0
+ if(step_to(D, Step_1))
+ check_1 = 1
+ for(var/obj/border_obstacle in Step_1)
+ if(border_obstacle.flags & ON_BORDER)
+ if(!border_obstacle.CheckExit(D, target))
+ check_1 = 0
+ // ------- YOU TRIED TO CLICK ON AN ITEM THROUGH A WINDOW (OR SIMILAR THING THAT LIMITS ON BORDERS) ON ONE OF THE DIRECITON TILES -------
+ for(var/obj/border_obstacle in get_turf(target))
+ if((border_obstacle.flags & ON_BORDER) && (target != border_obstacle))
+ if(!border_obstacle.CanPass(D, D.loc, 1, 0))
+ // ------- YOU TRIED TO CLICK ON AN ITEM THROUGH A WINDOW (OR SIMILAR THING THAT LIMITS ON BORDERS) ON THE TILE YOU'RE ON -------
+ check_1 = 0
+
+ D.loc = user.loc
+ if(step_to(D, Step_2))
+ check_2 = 1
+
+ for(var/obj/border_obstacle in Step_2)
+ if(border_obstacle.flags & ON_BORDER)
+ if(!border_obstacle.CheckExit(D, target))
+ check_2 = 0
+ for(var/obj/border_obstacle in get_turf(target))
+ if((border_obstacle.flags & ON_BORDER) && (target != border_obstacle))
+ if(!border_obstacle.CanPass(D, D.loc, 1, 0))
+ check_2 = 0
+
+
+ if(check_1 || check_2)
+ ok = 1
+ // ------- YOU CAN REACH THE ITEM THROUGH AT LEAST ONE OF THE TWO DIRECTIONS. GOOD. -------
+
+ /*
+ More info:
+ If you're trying to click an item in the north-east of your mob, the above section of code will first check if tehre's a tile to the north or you and to the east of you
+ These two tiles are Step_1 and Step_2. After this, a new dummy object is created on your location. It then tries to move to Step_1, If it succeeds, objects on the turf you're on and
+ the turf that Step_1 is are checked for items which have the ON_BORDER flag set. These are itmes which limit you on only one tile border. Windows, for the most part.
+ CheckExit() and CanPass() are use to determine this. The dummy object is then moved back to your location and it tries to move to Step_2. Same checks are performed here.
+ If at least one of the two checks succeeds, it means you can reach the item and ok is set to 1.
+ */
+ else
+ // ------- OBJECT IS ON A CARDINAL TILE (NORTH, SOUTH, EAST OR WEST OR THE TILE YOU'RE ON) -------
+ if(target.loc == user.loc)
+ ok = 1
+ // ------- OBJECT IS ON THE SAME TILE AS YOU -------
+ else
+ ok = 1
+
+ //Now, check objects to block exit that are on the border
+ for(var/obj/border_obstacle in user.loc)
+ if(border_obstacle.flags & ON_BORDER)
+ if(!border_obstacle.CheckExit(D, target))
+ ok = 0
+
+ //Next, check objects to block entry that are on the border
+ for(var/obj/border_obstacle in get_turf(target))
+ if((border_obstacle.flags & ON_BORDER) && (target != border_obstacle))
+ if(!border_obstacle.CanPass(D, D.loc, 1, 0))
+ ok = 0
+ /*
+ See the previous More info, for... more info...
+ */
+
+ if(get_dist(user, target) > 1)
+ return 0
+
+ del(D)
+ // ------- DUMMY OBJECT'S SERVED IT'S PURPOSE, IT'S REWARDED WITH A SWIFT DELETE -------
+ return ok
\ No newline at end of file
diff --git a/code/defines/procs/helpers.dm b/code/defines/procs/helpers.dm
index a30f6fa1725..cfd3dbfb00b 100644
--- a/code/defines/procs/helpers.dm
+++ b/code/defines/procs/helpers.dm
@@ -1490,4 +1490,37 @@ proc/get_opposite(var/checkdir)
list += found_string
found_char = findtext(cur_text,character,last_found)
list += copytext(cur_text,last_found,length(cur_text)+1)
- return list
\ No newline at end of file
+ return list
+
+/proc/stringmerge(var/text,var/compare,replace = "*")
+//This proc fills in all spaces with the "replace" var (* by default) with whatever
+//is in the other string at the same spot (assuming it is not a replace char).
+//This is used for fingerprints
+ var/newtext = text
+ if(lentext(text) != lentext(compare))
+ return 0
+ for(var/i = 1, i < lentext(text), i++)
+ var/a = copytext(text,i,i+1)
+ var/b = copytext(compare,i,i+1)
+//if it isn't both the same letter, or if they are both the replacement character
+//(no way to know what it was supposed to be)
+ if(a != b)
+ if(a == replace) //if A is the replacement char
+ newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1)
+ else if(b == replace) //if B is the replacement char
+ newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1)
+ else //The lists disagree, Uh-oh!
+ return 0
+ return newtext
+
+/proc/stringpercent(var/text,character = "*")
+//This proc returns the number of chars of the string that is the character
+//This is used for detective work to determine fingerprint completion.
+ if(!text || !character)
+ return 0
+ var/count = 0
+ for(var/i = 1, i < lentext(text), i++)
+ var/a = copytext(text,i,i+1)
+ if(a == character)
+ count++
+ return count
\ No newline at end of file
diff --git a/code/game/atom_procs.dm b/code/game/atom_procs.dm
index f94a756c300..b4cde466f12 100644
--- a/code/game/atom_procs.dm
+++ b/code/game/atom_procs.dm
@@ -93,22 +93,25 @@
src.fingerprintshidden += text("(Wearing gloves). Real name: [], Key: []",H.real_name, H.key)
src.fingerprintslast = H.key
return 0
- if (!( src.fingerprints ))
- src.fingerprints = text("[]", md5(H.dna.uni_identity))
- if(src.fingerprintslast != H.key)
- src.fingerprintshidden += text("Real name: [], Key: []",H.real_name, H.key)
- src.fingerprintslast = H.key
- return 1
else
- var/list/L = params2list(src.fingerprints)
- L -= md5(H.dna.uni_identity)
- while(L.len >= 3)
- L -= L[1]
- L += md5(H.dna.uni_identity)
- src.fingerprints = list2params(L)
if(src.fingerprintslast != H.key)
src.fingerprintshidden += text("Real name: [], Key: []",H.real_name, H.key)
src.fingerprintslast = H.key
+ var/new_prints = 0
+ var/prints
+ for(var/i = 1, i < (src.fingerprints.len + 1), i++)
+ var/list/L = params2list(src.fingerprints[i])
+ if(L[1] == md5(H.dna.uni_identity))
+ new_prints = i
+ prints = L[2]
+ break
+ else
+ src.fingerprints[i] = L[1] + "&" + stars(L[2], rand(80,90))
+ if(new_prints)
+ src.fingerprints[new_prints] = text("[]&[]", md5(H.dna.uni_identity), stringmerge(prints,stars(md5(H.dna.uni_identity), rand(15,30))))
+ else if(new_prints == 0)
+ src.fingerprints += text("[]&[]", md5(H.dna.uni_identity), stars(md5(H.dna.uni_identity), rand(15,30)))
+ return 1
else
if(src.fingerprintslast != M.key)
src.fingerprintshidden += text("Real name: [], Key: []",M.real_name, M.key)
@@ -130,26 +133,37 @@
I.Blend(new /icon('blood.dmi', "itemblood"),ICON_MULTIPLY)
I.Blend(new /icon(src.icon, src.icon_state),ICON_UNDERLAY)
src.icon = I
- src.blood_DNA = M.dna.unique_enzymes
- src.blood_type = M.b_type
+ if(src.blood_DNA)
+ src.blood_DNA.len++
+ src.blood_DNA[src.blood_DNA.len] = list(M.dna.unique_enzymes,M.b_type)
+ else
+ var/list/blood_DNA_temp[1]
+ blood_DNA_temp[1] = list(M.dna.unique_enzymes, M.b_type)
+ src.blood_DNA = blood_DNA_temp
else if (istype(src, /turf/simulated))
var/turf/simulated/source2 = src
var/list/objsonturf = range(0,src)
- var/i
- for(i=1, i<=objsonturf.len, i++)
- if(istype(objsonturf[i],/obj/effect/decal/cleanable/blood))
- return
+ if(objsonturf)
+ for(var/i=1, i<=objsonturf.len, i++)
+ if(istype(objsonturf[i],/obj/effect/decal/cleanable/blood))
+ return
var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(source2)
- this.blood_DNA = M.dna.unique_enzymes
- this.blood_type = M.b_type
+ var/list/blood_DNA_temp[1]
+ blood_DNA_temp[1] = list(M.dna.unique_enzymes, M.b_type)
+ this.blood_DNA = blood_DNA_temp
this.virus2 = M.virus2
for(var/datum/disease/D in M.viruses)
var/datum/disease/newDisease = new D.type
this.viruses += newDisease
newDisease.holder = this
else if (istype(src, /mob/living/carbon/human))
- src.blood_DNA = M.dna.unique_enzymes
- src.blood_type = M.b_type
+ if(src.blood_DNA)
+ src.blood_DNA.len++
+ src.blood_DNA[src.blood_DNA.len] = list(M.dna.unique_enzymes,M.b_type)
+ else
+ var/list/blood_DNA_temp[1]
+ blood_DNA_temp[1] = list(M.dna.unique_enzymes, M.b_type)
+ src.blood_DNA = blood_DNA_temp
else
return
else
diff --git a/code/game/dna.dm b/code/game/dna.dm
index 4d1f23c3a0d..acb1d477f68 100644
--- a/code/game/dna.dm
+++ b/code/game/dna.dm
@@ -4,6 +4,7 @@
var/struc_enzymes = null
var/uni_identity = null
var/original_name = "Unknown"
+ var/b_type = "A+"
/datum/dna/proc/check_integrity()
//Lazy.
diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
index c163c809d0e..f0ecb88ddca 100644
--- a/code/game/gamemodes/autotraitor/autotraitor.dm
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -59,9 +59,6 @@
/datum/game_mode/traitor/autotraitor/post_setup()
..()
- for(var/mob/T in world)
- if(T.mind in possible_traitors)
- T.be_syndicate = 1
abandon_allowed = 1
traitorcheckloop()
@@ -79,7 +76,7 @@
playercount += 1
if (player.client && player.mind && player.mind.special_role && player.stat != 2)
traitorcount += 1
- if (player.client && player.mind && !player.mind.special_role && player.stat != 2 && player.be_syndicate && !jobban_isbanned(player, "Syndicate"))
+ if (player.client && player.mind && !player.mind.special_role && player.stat != 2 && (player.be_syndicate & BE_TRAITOR) && !jobban_isbanned(player, "Syndicate"))
possible_traitors += player
//message_admins("Live Players: [playercount]")
//message_admins("Live Traitors: [traitorcount]")
@@ -162,7 +159,7 @@
if(emergency_shuttle.departed)
return
//message_admins("Late Join Check")
- if(character.be_syndicate == 1 && !jobban_isbanned(character, "Syndicate"))
+ if((character.be_syndicate & BE_TRAITOR) && !jobban_isbanned(character, "Syndicate"))
//message_admins("Late Joiner has Be Syndicate")
//message_admins("Checking number of players")
var/playercount = 0
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 0b7c6552303..70e1d553f87 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -53,7 +53,9 @@ Devices and Tools;
/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox;
/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module;
/obj/item/device/radio/headset/traitor:3:Headset with Binary Translator;
-/obj/item/weapon/plastique:2:C-4;
+/obj/item/weapon/plastique:2:C-4 (Destroys walls);
+/obj/item/weapon/syndie/c4explosive:4:Low Power Explosive Charge, with Detonator;
+/obj/item/weapon/syndie/c4explosive/heavy:7:High (!) Power Explosive Charge, with Detonator;
/obj/item/device/powersink:5:Powersink (DANGER!);
/obj/machinery/singularity_beacon/syndicate:7:Singularity Beacon (DANGER!);
Whitespace:Seperator;
@@ -64,7 +66,8 @@ Implants;
/obj/item/weapon/storage/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals);
Whitespace:Seperator;
Badassery;
-/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"}
+/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);
+Whitespace:Seperator;"}
/datum/game_mode/proc/announce() //to be calles when round starts
world << "Notice: [src] did not define announce()"
diff --git a/code/game/gamemodes/revolution/rp-revolution.dm b/code/game/gamemodes/revolution/rp-revolution.dm
index ce0ade235c9..c63637a9c8d 100644
--- a/code/game/gamemodes/revolution/rp-revolution.dm
+++ b/code/game/gamemodes/revolution/rp-revolution.dm
@@ -183,7 +183,7 @@
for(var/mob/living/carbon/human/player in world)
if(player.client)
- if(player.be_syndicate)
+ if(player.be_syndicate & BE_REV)
candidates += player.mind
if(candidates.len < 1)
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 5e69cb55c3c..000a13d8dac 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -109,7 +109,8 @@
objective = steal_objective
var/inthere = 0
for(var/j, j<= target.len, j++)
- if(target[j] == objective)
+ var/datum/objective/temp = target[j]
+ if(temp:target == objective:target)
inthere = 1
break
if(!inthere)
@@ -137,6 +138,10 @@
/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor)
traitor.current << "You are the traitor."
+ traitor.current << "\red REPEAT"
+ traitor.current << "\red You are the traitor."
+ spawn(rand(600,1800)) //Strumpetplaya - Just another friendly reminder so people don't forget they're the traitor.
+ traitor.current << "\red In case you missed it the first time - YOU ARE THE TRAITOR!"
var/obj_count = 1
for(var/datum/objective/objective in traitor.objectives)
traitor.current << "Objective #[obj_count]: [objective.explanation_text]"
@@ -175,6 +180,8 @@
else
killer << "Unfortunately, the Syndicate did not provide you with a code response."
killer << "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe."
+ spawn(30)
+ killer << sound('AISyndiHack.ogg',volume=50)
//End code phrase.
@@ -318,4 +325,6 @@
else
traitor_mob << "Unfortunately, the Syndicate did not provide you with a code response."
traitor_mob << "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe."
+ spawn(30)
+ traitor_mob << sound('syndicate intro.ogg',volume=50)
//End code phrase.
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index 4a0ccefa6d4..fac3a9671ff 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -82,7 +82,6 @@
H.equip_if_possible(new /obj/item/clothing/under/rank/cargo(H), H.slot_w_uniform)
H.equip_if_possible(new /obj/item/clothing/shoes/black(H), H.slot_shoes)
H.equip_if_possible(new /obj/item/device/pda/quartermaster(H), H.slot_belt)
- H.equip_if_possible(new /obj/item/clothing/gloves/black(H), H.slot_gloves)
H.equip_if_possible(new /obj/item/clothing/glasses/sunglasses(H), H.slot_glasses)
H.equip_if_possible(new /obj/item/weapon/clipboard(H), H.slot_r_store)
return 1
@@ -104,7 +103,6 @@
H.equip_if_possible(new /obj/item/clothing/under/rank/cargo(H), H.slot_w_uniform)
H.equip_if_possible(new /obj/item/clothing/shoes/black(H), H.slot_shoes)
H.equip_if_possible(new /obj/item/device/pda/quartermaster(H), H.slot_belt)
- H.equip_if_possible(new /obj/item/clothing/gloves/black(H), H.slot_gloves)
return 1
@@ -124,7 +122,6 @@
H.equip_if_possible(new /obj/item/weapon/storage/backpack/industrial (H), H.slot_back)
H.equip_if_possible(new /obj/item/clothing/under/rank/miner(H), H.slot_w_uniform)
H.equip_if_possible(new /obj/item/clothing/shoes/black(H), H.slot_shoes)
- H.equip_if_possible(new /obj/item/clothing/gloves/black(H), H.slot_gloves)
H.equip_if_possible(new /obj/item/weapon/crowbar(H), H.slot_in_backpack)
H.equip_if_possible(new /obj/item/weapon/satchel(H), H.slot_in_backpack)
return 1
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 2d24ac4c8b8..33d47cd9a42 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -89,8 +89,8 @@
"carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa
"plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa
"other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa
- "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.40,ONE_ATMOSPHERE*1.60), /* kpa */
- "temperature" = new/datum/tlv(40, 60, 100, 120), // K
+ "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.20,ONE_ATMOSPHERE*0.35,ONE_ATMOSPHERE*0.8,ONE_ATMOSPHERE*0.9), /* kpa */
+ "temperature" = new/datum/tlv(40, 60, 150, 160), // K
)
//all air alarms in area are connected via magic
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index 4b63a63689f..441a7f06fbe 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -805,8 +805,8 @@
H.apply_damage(0.5*damage, BRUTE, "r_arm")
var/obj/effect/decal/cleanable/blood/B = new(src.loc)
- B.blood_DNA = H.dna.unique_enzymes
- B.blood_type = H.b_type
+ B.blood_DNA.len++
+ B.blood_DNA[B.blood_DNA.len] = list(H.dna.unique_enzymes, H.b_type)
bloodiness += 4
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 5389935bd46..d5144e09d02 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -429,6 +429,8 @@ About the new airlock wires panel:
return 0
if(!prob(prb))
return 0 //you lucked out, no shock for you
+ if(istype(usr.equipped(),/obj/item/weapon/shard))
+ return 0
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start() //sparks always.
@@ -817,10 +819,10 @@ About the new airlock wires panel:
usr.machine = src
if (href_list["wires"])
var/t1 = text2num(href_list["wires"])
- if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) ))
+ if (!istype(usr.equipped(), /obj/item/weapon/wirecutters) || !istype(usr.equipped(),/obj/item/weapon/shard))
usr << "You need wirecutters!"
return
- if (src.isWireColorCut(t1))
+ if (src.isWireColorCut(t1) && istype(usr.equipped(), /obj/item/weapon/wirecutters))
src.mend(t1)
else
src.cut(t1)
diff --git a/code/game/magic/cultist/ritual.dm b/code/game/magic/cultist/ritual.dm
index 04e8ca46bb9..65e74484210 100644
--- a/code/game/magic/cultist/ritual.dm
+++ b/code/game/magic/cultist/ritual.dm
@@ -555,8 +555,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
R.word2 = w2
R.word3 = w3
R.check_icon()
- R.blood_DNA = H.dna.unique_enzymes
- R.blood_type = H.b_type
+ R.blood_DNA.len++
+ R.blood_DNA[R.blood_DNA.len] = list(H.dna.unique_enzymes, H.b_type)
return
else
user << "The book seems full of illegible scribbles. Is this a joke?"
@@ -601,8 +601,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
var/obj/effect/rune/R = new /obj/effect/rune
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
- R.blood_DNA = H.dna.unique_enzymes
- R.blood_type = H.b_type
+ R.blood_DNA.len++
+ R.blood_DNA[R.blood_DNA.len] = list(H.dna.unique_enzymes, H.b_type)
switch(r)
if("teleport")
var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")
diff --git a/code/game/magic/cultist/runes.dm b/code/game/magic/cultist/runes.dm
index c92c206c71d..95511f603d7 100644
--- a/code/game/magic/cultist/runes.dm
+++ b/code/game/magic/cultist/runes.dm
@@ -898,7 +898,7 @@ var/list/sacrificed = list()
culcount++
if(culcount >= 5)
for(var/obj/effect/rune/R in world)
- if(R.blood_DNA == src.blood_DNA && R.blood_type == src.blood_type)
+ if(R.blood_DNA == src.blood_DNA)
for(var/mob/living/M in orange(2,R))
M.take_overall_damage(0,15)
if (R.invisibility>M.see_invisible)
@@ -908,7 +908,7 @@ var/list/sacrificed = list()
var/turf/T = get_turf(R)
T.hotspot_expose(700,125)
for(var/obj/effect/decal/cleanable/blood/B in world)
- if(B.blood_DNA == src.blood_DNA && B.blood_type == src.blood_type)
+ if(B.blood_DNA == src.blood_DNA)
for(var/mob/living/M in orange(1,B))
M.take_overall_damage(0,5)
M << "\red Blood suddenly ignites, burning you!"
diff --git a/code/game/magic/library.dm b/code/game/magic/library.dm
index 82378071c9e..aced80ed11a 100644
--- a/code/game/magic/library.dm
+++ b/code/game/magic/library.dm
@@ -232,11 +232,11 @@
if ((!in_range(src, usr) && src.loc != user && src.loc.loc != user && user.equipped() != W))
return
- if(lentext(t) >= MAX_PAPER_MESSAGE_LEN)
+ if(lentext(t) >= MAX_BOOK_MESSAGE_LEN)
var/cont = input(user, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
if(cont == "no")
break
- while(lentext(t) > MAX_PAPER_MESSAGE_LEN)
+ while(lentext(t) > MAX_BOOK_MESSAGE_LEN)
if ((!in_range(src, usr) && src.loc != user && src.loc.loc != user && user.equipped() != W))
return
diff --git a/code/game/objects/blood.dm b/code/game/objects/blood.dm
index da37b28f3de..26c01049058 100644
--- a/code/game/objects/blood.dm
+++ b/code/game/objects/blood.dm
@@ -20,6 +20,8 @@
sleep(3)
if (i > 0)
var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
+ b.blood_DNA = blood_DNA
+ b.OriginalMob = OriginalMob
for(var/datum/disease/D in src.viruses)
b.viruses += D
if (step_to(src, get_step(src, direction), 0))
diff --git a/code/game/objects/closets/secure/security.dm b/code/game/objects/closets/secure/security.dm
index fb964a64f95..a1da4000097 100644
--- a/code/game/objects/closets/secure/security.dm
+++ b/code/game/objects/closets/secure/security.dm
@@ -85,7 +85,7 @@
/obj/structure/closet/secure_closet/detective
name = "Detective"
req_access = list(access_forensics_lockers)
- icon_state = "cabinetdetective"
+ icon_state = "cabinetdetective_locked"
icon_closed = "cabinetdetective"
icon_locked = "cabinetdetective_locked"
icon_opened = "cabinetdetective_open"
diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm
index 7bcda1ad743..c9abad11b99 100644
--- a/code/game/objects/devices/PDA/PDA.dm
+++ b/code/game/objects/devices/PDA/PDA.dm
@@ -743,7 +743,9 @@
else
user << "\blue Blood found on [C]. Analysing..."
spawn(15)
- user << "\blue Blood type: [C:blood_type]\nDNA: [C:blood_DNA]"
+ for(var/i = 1, i < C:blood_DNA.len, i++)
+ var/list/templist = C:blood_DNA[i]
+ user << "\blue Blood type: [templist[2]]\nDNA: [templist[1]]"
if(4)
for (var/mob/O in viewers(C, null))
@@ -761,10 +763,9 @@
if (!A.fingerprints)
user << "\blue Unable to locate any fingerprints on [A]!"
else
- var/list/L = params2list(A:fingerprints)
- user << "\blue Isolated [L.len] fingerprints."
- for(var/i in L)
- user << "\blue \t [i]"
+ user << "\blue Isolated [A:fingerprints.len] fingerprints."
+// for(var/i in L)
+// user << "\blue \t [i]"
if(3)
if(!isnull(A.reagents))
diff --git a/code/game/objects/devices/scanners.dm b/code/game/objects/devices/scanners.dm
index 0e0216f7267..ab5f245e499 100644
--- a/code/game/objects/devices/scanners.dm
+++ b/code/game/objects/devices/scanners.dm
@@ -65,107 +65,189 @@ MASS SPECTROMETER
icon_state = "forensic0"
var/amount = 20.0
var/printing = 0.0
- var/list/stored_fibers = null
- var/stored_name = null
+ var/list/stored = list()
w_class = 3.0
item_state = "electronic"
flags = FPRINT | TABLEPASS | ONBELT | CONDUCT | USEDELAY
-/obj/item/device/detective_scanner/attackby(obj/item/weapon/f_card/W as obj, mob/user as mob)
- ..()
+ attackby(obj/item/weapon/f_card/W as obj, mob/user as mob)
+ ..()
+ if (istype(W, /obj/item/weapon/f_card))
+ if (W.fingerprints)
+ return
+ if (src.amount == 20)
+ return
+ if (W.amount + src.amount > 20)
+ src.amount = 20
+ W.amount = W.amount + src.amount - 20
+ else
+ src.amount += W.amount
+ //W = null
+ del(W)
+ src.add_fingerprint(user)
+ if (W)
+ W.add_fingerprint(user)
+ return
- if (istype(W, /obj/item/weapon/f_card))
- if (W.fingerprints)
- return
- if (src.amount == 20)
- return
- if (W.amount + src.amount > 20)
- src.amount = 20
- W.amount = W.amount + src.amount - 20
+ attack_self(mob/user as mob)
+ src.printing = !( src.printing )
+ if(src.printing)
+ user << "\blue Printing turned on"
else
- src.amount += W.amount
- //W = null
- del(W)
- src.add_fingerprint(user)
- if (W)
- W.add_fingerprint(user)
- return
-
-/obj/item/device/detective_scanner/attack_self(mob/user as mob)
-
- src.printing = !( src.printing )
- if(src.printing)
- user << "\blue Printing turned on"
- else
- user << "\blue Printing turned off"
- src.icon_state = text("forensic[]", src.printing)
- add_fingerprint(user)
- return
-
-/obj/item/device/detective_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob)
-
- if (!ishuman(M))
- user << "\red [M] is not humas and cannot have the fingerprints."
- return 0
- if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
- user << "\blue No fingerprints found on [M]"
- return 0
- else
- if ((src.amount < 1 && src.printing))
- user << text("\blue Fingerprints scanned on [M]. Need more cards to print.")
- src.printing = 0
+ user << "\blue Printing turned off"
src.icon_state = text("forensic[]", src.printing)
- if (src.printing)
- src.amount--
- var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
- F.amount = 1
- F.fingerprints = md5(M.dna.uni_identity)
- F.icon_state = "fingerprint1"
- F.name = text("FPrintC- '[M.name]'")
- user << "\blue Done printing."
- user << text("\blue [M]'s Fingerprints: [md5(M.dna.uni_identity)]")
- if ( !(M.blood_DNA) )
- user << "\blue No blood found on [M]"
- else
- user << "\blue Blood found on [M]. Analysing..."
- spawn(15)
- user << "\blue Blood type: [M.blood_type]\nDNA: [M.blood_DNA]"
- return
+ add_fingerprint(user)
+ return
-/obj/item/device/detective_scanner/afterattack(atom/A as mob|obj|turf|area, mob/user as mob)
+ attack(mob/living/carbon/human/M as mob, mob/user as mob)
+ if (!ishuman(M))
+ user << "\red [M] is not human and cannot have the fingerprints."
+ return 0
+ if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
+ user << "\blue No fingerprints found on [M]"
+ return 0
+ else
+ if ((src.amount < 1 && src.printing))
+ user << text("\blue Fingerprints scanned on [M]. Need more cards to print.")
+ src.printing = 0
+ src.icon_state = text("forensic[]", src.printing)
+ if (src.printing)
+ src.amount--
+ var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
+ F.amount = 1
+ F.fingerprints = md5(M.dna.uni_identity)
+ F.icon_state = "fingerprint1"
+ F.name = text("FPrintC- '[M.name]'")
+ user << "\blue Done printing."
+ user << text("\blue [M]'s Fingerprints: [md5(M.dna.uni_identity)]")
+ if ( !(M.blood_DNA) )
+ user << "\blue No blood found on [M]"
+ else
+ user << "\blue Blood found on [M]. Analysing..."
+ spawn(15)
+ for(var/i = 1, i < M.blood_DNA.len, i++)
+ var/list/templist = M.blood_DNA[i]
+ user << "\blue Blood type: [templist[2]]\nDNA: [templist[1]]"
+ return
- src.add_fingerprint(user)
- if (istype(A, /obj/effect/decal/cleanable/blood) || istype(A, /obj/effect/rune))
- if(A.blood_DNA)
- user << "\blue Blood type: [A.blood_type]\nDNA: [A.blood_DNA]"
- else if (A.blood_DNA)
- user << "\blue Blood found on [A]. Analysing..."
- sleep(15)
- user << "\blue Blood type: [A.blood_type]\nDNA: [A.blood_DNA]"
- else
- user << "\blue No blood found on [A]."
- if (!( A.fingerprints ))
- user << "\blue Unable to locate any fingerprints on [A]!"
- return 0
- else
- if ((src.amount < 1 && src.printing))
- user << "\blue Fingerprints found. Need more cards to print."
- src.printing = 0
- src.icon_state = text("forensic[]", src.printing)
- if (src.printing)
- src.amount--
- var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
- F.amount = 1
- F.fingerprints = A.fingerprints
- F.icon_state = "fingerprint1"
- user << "\blue Done printing."
- var/list/L = params2list(A.fingerprints)
- user << text("\blue Isolated [L.len] fingerprints.")
- for(var/i in L)
- user << text("\blue \t [i]")
- //Foreach goto(186)
- return
+ afterattack(atom/A as obj|turf|area, mob/user as mob)
+ if(src.loc != user)
+ return 0
+ src.add_fingerprint(user)
+ if (istype(A, /obj/effect/decal/cleanable/blood) || istype(A, /obj/effect/rune))
+ if(!isnull(A.blood_DNA.len))
+ for(var/i = 1, i < A.blood_DNA.len, i++)
+ var/list/templist = A.blood_DNA[i]
+ user << "\blue Blood type: [templist[2]]\nDNA: [templist[1]]"
+ return
+ var/duplicate = 0
+ if ((!A.fingerprints || A.fingerprints.len == 0) && !(A.suit_fibers) && !(A.blood_DNA))
+ user << "\blue Unable to locate any fingerprints, materials, fibers, or blood on [A]!"
+ return 0
+ else if (A.blood_DNA)
+ user << "\blue Blood found on [A]. Analysing..."
+ sleep(15)
+ if(!duplicate)
+ duplicate = 1
+ var/i = add_data(A)
+ if(i)
+ user << "\blue Blood already in memory."
+ for(var/i = 1, i < (A.blood_DNA.len + 1), i++)
+ var/list/templist = A.blood_DNA[i]
+ user << "\blue Blood type: [templist[2]]\nDNA: [templist[1]]"
+ else
+ user << "\blue No Blood Located"
+ if(!A.fingerprints || A.fingerprints.len == 0)
+ user << "\blue No Fingerprints Located."
+ else
+ user << text("\blue Isolated [A.fingerprints.len] fingerprints: Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.")
+ if(!duplicate)
+ duplicate = 1
+ var/i = add_data(A)
+ if(i)
+ user << "\blue Fingerprints already in memory."
+ if(!A.suit_fibers)
+ user << "\blue No Fibers/Materials Located."
+ else
+ user << "\blue Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
+
+ if(!duplicate)
+ duplicate = 1
+ var/i = add_data(A)
+ if(i)
+ user << "\blue Fibers/Materials already in memory."
+ // else
+ // if ((src.amount < 1 && src.printing))
+ // user << "\blue Fingerprints found. Need more cards to print."
+ // src.printing = 0
+ // src.icon_state = text("forensic[]", src.printing)
+ // if (src.printing)
+ // src.amount--
+ // var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
+ // F.amount = 1
+ // F.fingerprints = A.fingerprints
+ // F.icon_state = "fingerprint1"
+ // user << "\blue Done printing."
+ // for(var/i in L)
+ // user << text("\blue \t [i]")
+ // //Foreach goto(186)
+ return
+
+ proc/add_data(atom/A as mob|obj|turf|area)
+ var/merged = 0
+ for(var/i = 1, i < (stored.len + 1), i++) //Lets see if the object is already in there!
+ var/list/temp = stored[i]
+ var/checker = temp[1]
+ if(checker == A) //It is! Merge!
+ merged = 1
+ var/list/prints = temp[2]
+ if(!prints)
+ prints = list()
+ if(A.fingerprints)
+ for(var/j = 1, j < (A.fingerprints.len + 1), j++) //Fingerprints~~~
+ var/list/print_test1 = params2list(A.fingerprints[j])
+ var/test_print1 = print_test1[1]
+ var/found = 0
+ for(var/k = 1, k < (prints.len + 1), k++) //Lets see if the print is already in there
+ var/list/print_test2 = params2list(prints[k])
+ var/test_print2 = print_test2[1]
+ if(test_print2 == test_print1) //It is! Merge!
+ prints[k] = test_print2 + "&" + stringmerge(print_test2[2],print_test1[2])
+ found = 1
+ break //We found it, we're done here.
+ if(!found) //It isn't! Add!
+ prints += A.fingerprints[j]
+ var/list/fibers = temp[3]
+ if(!fibers)
+ fibers = list()
+ if(A.suit_fibers)
+ for(var/j = 1, j < (A.suit_fibers.len + 1), j++) //Fibers~~~
+ if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add!
+ fibers += A.suit_fibers[j]
+ var/list/blood = temp[4]
+ if(!blood)
+ blood = list()
+ if(A.blood_DNA)
+ for(var/j = 1, j < (A.blood_DNA.len + 1), j++) //Blood~~~
+ if(!blood.Find(A.blood_DNA[j])) //It isn't! Add!
+ blood += A.blood_DNA[j]
+ var/list/sum_list[4] //Pack it back up!
+ sum_list[1] = A
+ sum_list[2] = prints
+ sum_list[3] = fibers
+ sum_list[4] = blood
+ stored[i] = sum_list //Store it!
+ break //We found it, we're done here.
+ if(!merged) //Uh, oh! New data point!
+ var/list/sum_list[4] //Pack it back up!
+ sum_list[1] = A
+ sum_list[2] = A.fingerprints
+ sum_list[3] = A.suit_fibers
+ sum_list[4] = A.blood_DNA
+ stored.len++
+ stored[stored.len] = sum_list
+ return merged
/obj/item/device/healthanalyzer
@@ -181,50 +263,50 @@ MASS SPECTROMETER
m_amt = 200
origin_tech = "magnets=1;biotech=1"
-/obj/item/device/healthanalyzer/attack(mob/M as mob, mob/user as mob)
- if ((user.mutations & CLUMSY || user.getBrainLoss() >= 60) && prob(50))
- user << text("\red You try to analyze the floor's vitals!")
+ attack(mob/M as mob, mob/user as mob)
+ if ((user.mutations & CLUMSY || user.getBrainLoss() >= 60) && prob(50))
+ user << text("\red You try to analyze the floor's vitals!")
+ for(var/mob/O in viewers(M, null))
+ O.show_message(text("\red [user] has analyzed the floor's vitals!"), 1)
+ user.show_message(text("\blue Analyzing Results for The floor:\n\t Overall Status: Healthy"), 1)
+ user.show_message(text("\blue \t Damage Specifics: [0]-[0]-[0]-[0]"), 1)
+ user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
+ user.show_message("\blue Body Temperature: ???", 1)
+ return
+ if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ usr << "\red You don't have the dexterity to do this!"
+ return
for(var/mob/O in viewers(M, null))
- O.show_message(text("\red [user] has analyzed the floor's vitals!"), 1)
- user.show_message(text("\blue Analyzing Results for The floor:\n\t Overall Status: Healthy"), 1)
- user.show_message(text("\blue \t Damage Specifics: [0]-[0]-[0]-[0]"), 1)
+ O.show_message(text("\red [] has analyzed []'s vitals!", user, M), 1)
+ //Foreach goto(67)
+ var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss())))
+ if((M.reagents && M.reagents.has_reagent("zombiepowder")) || (M.changeling && M.changeling.changeling_fakedeath))
+ user.show_message(text("\blue Analyzing Results for []:\n\t Overall Status: []", M, "dead"), 1)
+ user.show_message(text("\blue \t Damage Specifics: []-[]-[]-[]", fake_oxy < 50 ? "\red [fake_oxy]" : fake_oxy , M.getToxLoss() > 50 ? "\red [M.getToxLoss()]" : M.getToxLoss(), M.getFireLoss() > 50 ? "\red[M.getFireLoss()]" : M.getFireLoss(), M.getBruteLoss() > 50 ? "\red[M.getBruteLoss()]" : M.getBruteLoss()), 1)
+ else
+ user.show_message(text("\blue Analyzing Results for []:\n\t Overall Status: []", M, (M.stat > 1 ? "dead" : text("[]% healthy", M.health))), 1)
+ user.show_message(text("\blue \t Damage Specifics: []-[]-[]-[]", M.getOxyLoss() > 50 ? "\red [M.getOxyLoss()]" : M.getOxyLoss(), M.getToxLoss() > 50 ? "\red [M.getToxLoss()]" : M.getToxLoss(), M.getFireLoss() > 50 ? "\red[M.getFireLoss()]" : M.getFireLoss(), M.getBruteLoss() > 50 ? "\red[M.getBruteLoss()]" : M.getBruteLoss()), 1)
user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
- user.show_message("\blue Body Temperature: ???", 1)
+ user.show_message("\blue Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
+ if((M.changeling && M.changeling.changeling_fakedeath) || (M.reagents && M.reagents.has_reagent("zombiepowder")))
+ user.show_message(text("\blue [] | [] | [] | []", fake_oxy > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", M.getToxLoss() > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", M.getFireLoss() > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", M.getBruteLoss() > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1)
+ else
+ user.show_message(text("\blue [] | [] | [] | []", M.getOxyLoss() > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", M.getToxLoss() > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", M.getFireLoss() > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", M.getBruteLoss() > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1)
+ if (M.getCloneLoss())
+ user.show_message(text("\red Subject appears to have been imperfectly cloned."), 1)
+ for(var/datum/disease/D in M.viruses)
+ if(!D.hidden[SCANNER])
+ user.show_message(text("\red Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]"))
+ if (M.reagents && M.reagents.get_reagent_amount("inaprovaline"))
+ user.show_message(text("\blue Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals."), 1)
+ if (M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0)
+ user.show_message(text("\red Subject is brain dead."), 1)
+ else if (M.getBrainLoss() >= 60)
+ user.show_message(text("\red Severe brain damage detected. Subject likely to have mental retardation."), 1)
+ else if (M.getBrainLoss() >= 10)
+ user.show_message(text("\red Significant brain damage detected. Subject may have had a concussion."), 1)
+ src.add_fingerprint(user)
return
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- usr << "\red You don't have the dexterity to do this!"
- return
- for(var/mob/O in viewers(M, null))
- O.show_message(text("\red [] has analyzed []'s vitals!", user, M), 1)
- //Foreach goto(67)
- var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss())))
- if((M.reagents && M.reagents.has_reagent("zombiepowder")) || (M.changeling && M.changeling.changeling_fakedeath))
- user.show_message(text("\blue Analyzing Results for []:\n\t Overall Status: []", M, "dead"), 1)
- user.show_message(text("\blue \t Damage Specifics: []-[]-[]-[]", fake_oxy < 50 ? "\red [fake_oxy]" : fake_oxy , M.getToxLoss() > 50 ? "\red [M.getToxLoss()]" : M.getToxLoss(), M.getFireLoss() > 50 ? "\red[M.getFireLoss()]" : M.getFireLoss(), M.getBruteLoss() > 50 ? "\red[M.getBruteLoss()]" : M.getBruteLoss()), 1)
- else
- user.show_message(text("\blue Analyzing Results for []:\n\t Overall Status: []", M, (M.stat > 1 ? "dead" : text("[]% healthy", M.health))), 1)
- user.show_message(text("\blue \t Damage Specifics: []-[]-[]-[]", M.getOxyLoss() > 50 ? "\red [M.getOxyLoss()]" : M.getOxyLoss(), M.getToxLoss() > 50 ? "\red [M.getToxLoss()]" : M.getToxLoss(), M.getFireLoss() > 50 ? "\red[M.getFireLoss()]" : M.getFireLoss(), M.getBruteLoss() > 50 ? "\red[M.getBruteLoss()]" : M.getBruteLoss()), 1)
- user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
- user.show_message("\blue Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
- if((M.changeling && M.changeling.changeling_fakedeath) || (M.reagents && M.reagents.has_reagent("zombiepowder")))
- user.show_message(text("\blue [] | [] | [] | []", fake_oxy > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", M.getToxLoss() > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", M.getFireLoss() > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", M.getBruteLoss() > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1)
- else
- user.show_message(text("\blue [] | [] | [] | []", M.getOxyLoss() > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", M.getToxLoss() > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", M.getFireLoss() > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", M.getBruteLoss() > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1)
- if (M.getCloneLoss())
- user.show_message(text("\red Subject appears to have been imperfectly cloned."), 1)
- for(var/datum/disease/D in M.viruses)
- if(!D.hidden[SCANNER])
- user.show_message(text("\red Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]"))
- if (M.reagents && M.reagents.get_reagent_amount("inaprovaline"))
- user.show_message(text("\blue Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals."), 1)
- if (M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0)
- user.show_message(text("\red Subject is brain dead."), 1)
- else if (M.getBrainLoss() >= 60)
- user.show_message(text("\red Severe brain damage detected. Subject likely to have mental retardation."), 1)
- else if (M.getBrainLoss() >= 10)
- user.show_message(text("\red Significant brain damage detected. Subject may have had a concussion."), 1)
- src.add_fingerprint(user)
- return
/obj/item/device/analyzer
diff --git a/code/game/objects/gibs.dm b/code/game/objects/gibs.dm
index 15dcb69af2e..f60aaa89e2c 100644
--- a/code/game/objects/gibs.dm
+++ b/code/game/objects/gibs.dm
@@ -1,7 +1,7 @@
//HUMANS
-/proc/gibs(atom/location, var/list/viruses)
- new /obj/effect/gibspawner/human(get_turf(location),viruses)
+/proc/gibs(atom/location, var/list/viruses, var/datum/dna/MobDNA)
+ new /obj/effect/gibspawner/human(get_turf(location),viruses,MobDNA)
/proc/xgibs(atom/location, var/list/viruses)
new /obj/effect/gibspawner/xeno(get_turf(location),viruses)
@@ -16,13 +16,13 @@
var/list/gibamounts = list()
var/list/gibdirections = list() //of lists
- New(location, var/list/viruses)
+ New(location, var/list/viruses, var/datum/dna/MobDNA)
..()
if(istype(loc,/turf)) //basically if a badmin spawns it
- Gib(loc,viruses)
+ Gib(loc,viruses,MobDNA)
- proc/Gib(atom/location, var/list/viruses = list())
+ proc/Gib(atom/location, var/list/viruses = list(), var/datum/dna/MobDNA = null)
if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
world << "\red Gib list length mismatch!"
return
@@ -50,6 +50,11 @@
gib.viruses += viruus
viruus.holder = gib
viruus.spread_type = CONTACT_FEET
+ if(MobDNA)
+ gib.blood_DNA.len++
+ gib.blood_DNA[gib.blood_DNA.len] = list(MobDNA.unique_enzymes, MobDNA.b_type)
+ if(MobDNA.original_name != "Unknown")
+ gib.OriginalMob = MobDNA.original_name
var/list/directions = gibdirections[i]
if(directions.len)
gib.streak(directions)
diff --git a/code/game/objects/items/item.dm b/code/game/objects/items/item.dm
index 7805cc1ac94..a2167decfb4 100644
--- a/code/game/objects/items/item.dm
+++ b/code/game/objects/items/item.dm
@@ -162,7 +162,7 @@
if(isalien(user)) // -- TLE
var/mob/living/carbon/alien/A = user
- if(!A.has_fine_manipulation || w_class >= 4)
+ if(!A.has_fine_manipulation || w_class <= 4)
user << "Your claws aren't capable of such fine manipulation."
return
@@ -196,20 +196,23 @@
/obj/item/attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/packageWrap))
+ var/location = get_turf(src.loc)
if(istype(src,/obj/item/weapon/storage) && istype(src.loc, /mob)) //Put it into the bag
return
- if(istype(src.loc,/obj/item/weapon/storage) || istype(src.loc,/obj/item/clothing/suit/storage/)) //Taking stuff out of storage duplicates it.
- user << "\blue Do not do this, it is broken as all hell. Take it out of the container first."
- return
- for(var/obj/item/T in user) //Lets remove it from their inventory
- if(T == src)
- user.remove_from_mob(T)
- break
+ if(istype(src.loc,/obj/item/weapon/storage)) //Taking stuff out of storage duplicates it.
+ var/obj/item/weapon/storage/U = src.loc
+ user.client.screen -= src
+ U.contents.Remove(src)
+ if(istype(src.loc,/obj/item/clothing/suit/storage/))
+ var/obj/item/clothing/suit/storage/X = src.loc
+ user.client.screen -= src
+ X.contents.Remove(src)
+ if(src in user)
+ user.remove_from_mob(src)
var/obj/item/weapon/packageWrap/O = W
if (O.amount > 1)
- var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(src.loc))
+ var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(location)
P.wrapped = src
-
src.loc = P
O.amount -= 1
else if(istype(W,/obj/item/wardrobe))
@@ -225,6 +228,7 @@
user << "\blue The wardrobe is full."
return
user << "\blue You pick up all the items."
+ user.visible_message("\blue [user] gathers up the pile of stuff, and puts it into \the [W]")
I.update_icon()
/obj/item/attack_self(mob/user as mob)
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 8352ccf7183..482271c349b 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -201,11 +201,11 @@ FINGERPRINT CARD
/obj/item/weapon/f_card/proc/display()
- if (src.fingerprints)
+ if (length(src.fingerprints))
var/dat = "Fingerprints on Card