Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 12/14/2015_communicators_v2

This commit is contained in:
Neerti
2015-12-14 15:44:38 -05:00
197 changed files with 14437 additions and 43205 deletions

View File

@@ -1326,3 +1326,19 @@ proc/admin_notice(var/message, var/rights)
message_admins("[key_name(usr)] attempting to force mode latespawn.")
ticker.mode.next_spawn = 0
ticker.mode.try_latespawn()
/datum/admins/proc/set_tcrystals(mob/living/carbon/human/H as mob)
set category = "Debug"
set name = "Set Telecrystals"
set desc = "Allows admins to change telecrystals of a user."
var/crystals
if(check_rights(R_ADMIN))
crystals = input("Amount of telecrystals for [H.ckey]", crystals) as null|num
if (!isnull(crystals))
H.mind.tcrystals = crystals
var/msg = "[key_name(usr)] has modified [H.ckey]'s telecrystals to [crystals]."
message_admins(msg)
else
usr << "You do not have access to this command."

View File

@@ -13,7 +13,8 @@ var/list/admin_verbs_default = list(
// /client/proc/deadchat /*toggles deadchat on/off*/
)
var/list/admin_verbs_admin = list(
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/datum/admins/proc/set_tcrystals,
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
/datum/admins/proc/show_game_mode, /*Configuration window for the current game mode.*/
@@ -283,7 +284,8 @@ var/list/admin_verbs_hideable = list(
/client/proc/enable_debug_verbs,
/client/proc/roll_dices,
/proc/possess,
/proc/release
/proc/release,
/datum/admins/proc/set_tcrystals
)
var/list/admin_verbs_mod = list(
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/

View File

@@ -162,6 +162,7 @@ var/list/debug_verbs = list (
,/client/proc/testZAScolors_remove
,/client/proc/setup_supermatter_engine
,/client/proc/atmos_toggle_debug
,/client/proc/spawn_tanktransferbomb
)

View File

@@ -424,6 +424,54 @@ var/global/list/gear_datums = list()
slot = slot_w_uniform
cost = 1
/datum/gear/bluejumpsuit
display_name = "jumpsuit, blue"
path = /obj/item/clothing/under/color/blue
slot = slot_w_uniform
cost = 1
/datum/gear/greenjumpsuit
display_name = "jumpsuit, green"
path = /obj/item/clothing/under/color/green
slot = slot_w_uniform
cost = 1
/datum/gear/greyjumpsuit
display_name = "jumpsuit, grey"
path = /obj/item/clothing/under/color/grey
slot = slot_w_uniform
cost = 1
/datum/gear/pinkjumpsuit
display_name = "jumpsuit, pink"
path = /obj/item/clothing/under/color/pink
slot = slot_w_uniform
cost = 1
/datum/gear/whitejumpsuit
display_name = "jumpsuit, white"
path = /obj/item/clothing/under/color/white
slot = slot_w_uniform
cost = 1
/datum/gear/yellowjumpsuit
display_name = "jumpsuit, yellow"
path = /obj/item/clothing/under/color/yellow
slot = slot_w_uniform
cost = 1
/datum/gear/lightbluejumpsuit
display_name = "jumpsuit, lightblue"
path = /obj/item/clothing/under/lightblue
slot = slot_w_uniform
cost = 1
/datum/gear/redjumpsuit
display_name = "jumpsuit, red"
path = /obj/item/clothing/under/color/red
slot = slot_w_uniform
cost = 1
/datum/gear/skirt_blue
display_name = "plaid skirt, blue"
path = /obj/item/clothing/under/dress/plaid_blue
@@ -934,6 +982,7 @@ var/global/list/gear_datums = list()
/datum/gear/scarf_orange
display_name = "scarf, orange"
path = /obj/item/clothing/accessory/scarf/orange
slot = slot_tie
cost = 1
@@ -1015,7 +1064,7 @@ var/global/list/gear_datums = list()
/datum/gear/leather_coat
display_name = "leather coat"
path = /obj/item/clothing/suit/leathercoat/alt
path = /obj/item/clothing/suit/leathercoat
cost = 2
slot = slot_wear_suit
@@ -1079,6 +1128,12 @@ var/global/list/gear_datums = list()
cost = 2
slot = slot_wear_suit
/datum/gear/mil_alt
display_name = "military jacket, alt"
path = /obj/item/clothing/suit/jacket/miljacket2
cost = 2
slot = slot_wear_suit
/datum/gear/hazard_vest
display_name = "hazard vest"
path = /obj/item/clothing/suit/storage/hazardvest
@@ -1561,6 +1616,12 @@ var/global/list/gear_datums = list()
sort_category = "misc"
cost = 1
/datum/gear/boot_knife
display_name = "boot knife"
path = /obj/item/weapon/material/kitchen/utensil/knife/boot
sort_category = "misc"
cost = 3
/datum/gear/cane
display_name = "cane"
path = /obj/item/weapon/cane
@@ -1657,6 +1718,12 @@ var/global/list/gear_datums = list()
cost = 1
sort_category = "ears"
/datum/gear/headphones
display_name = "headphones"
path = /obj/item/clothing/ears/earmuffs/headphones
cost = 1
sort_category = "ears"
/datum/gear/skrell_chain
display_name = "skrell headtail-wear, female, chain"
path = /obj/item/clothing/ears/skrell/chain

View File

@@ -38,6 +38,14 @@ var/list/spawntypes = list()
..()
turfs = latejoin_gateway
/datum/spawnpoint/elevator
display_name = "Elevator"
msg = "has arrived from the residential district"
/datum/spawnpoint/elevator/New()
..()
turfs = latejoin_elevator
/datum/spawnpoint/cryo
display_name = "Cryogenic Storage"
msg = "has completed cryogenic revival"

View File

@@ -2,6 +2,7 @@
name = "clothing"
siemens_coefficient = 0.9
var/list/species_restricted = null //Only these species can wear this kit.
var/gunshot_residue //Used by forensics.
/*
Sprites used when the clothing item is refit. This is done by setting icon_override.
@@ -15,6 +16,11 @@
/obj/item/clothing/proc/update_clothing_icon()
return
// Aurora forensics port.
/obj/item/clothing/clean_blood()
..()
gunshot_residue = null
//BS12: Species-restricted clothing check.
/obj/item/clothing/mob_can_equip(M as mob, slot)
@@ -157,6 +163,32 @@
item_state = "earmuffs"
slot_flags = SLOT_EARS | SLOT_TWOEARS
/obj/item/clothing/ears/earmuffs/headphones
name = "headphones"
desc = "Unce unce unce unce."
var/headphones_on = 0
icon_state = "headphones_off"
item_state = "headphones"
slot_flags = SLOT_EARS | SLOT_TWOEARS
/obj/item/clothing/ears/earmuffs/headphones/verb/togglemusic()
set name = "Toggle Headphone Music"
set category = "Object"
set src in usr
if(!istype(usr, /mob/living)) return
if(usr.stat) return
if(headphones_on)
icon_state = "headphones_off"
headphones_on = 0
usr << "<span class='notice'>You turn the music off.</span>"
else
icon_state = "headphones_on"
headphones_on = 1
usr << "<span class='notice'>You turn the music on.</span>"
update_clothing_icon()
///////////////////////////////////////////////////////////////////////
//Glasses
/*
@@ -387,6 +419,9 @@ BLIND // can't see anything
body_parts_covered = FEET
slot_flags = SLOT_FEET
var/can_hold_knife
var/obj/item/holding
permeability_coefficient = 0.50
slowdown = SHOES_SLOWDOWN
force = 2
@@ -397,6 +432,54 @@ BLIND // can't see anything
"Resomi" = 'icons/mob/species/resomi/shoes.dmi',
)
/obj/item/clothing/shoes/proc/draw_knife()
set name = "Draw Boot Knife"
set desc = "Pull out your boot knife."
set category = "IC"
set src in usr
if(usr.stat || usr.restrained() || usr.incapacitated())
return
holding.forceMove(get_turf(usr))
if(usr.put_in_hands(holding))
usr.visible_message("<span class='danger'>\The [usr] pulls a knife out of their boot!</span>")
holding = null
else
usr << "<span class='warning'>Your need an empty, unbroken hand to do that.</span>"
holding.forceMove(src)
if(!holding)
verbs -= /obj/item/clothing/shoes/proc/draw_knife
update_icon()
return
/obj/item/clothing/shoes/attackby(var/obj/item/I, var/mob/user)
if(can_hold_knife && istype(I, /obj/item/weapon/material/shard) || \
istype(I, /obj/item/weapon/material/butterfly) || \
istype(I, /obj/item/weapon/material/kitchen/utensil) || \
istype(I, /obj/item/weapon/material/hatchet/tacknife))
if(holding)
user << "<span class='warning'>\The [src] is already holding \a [holding].</span>"
return
user.unEquip(I)
I.forceMove(src)
holding = I
user.visible_message("<span class='notice'>\The [user] shoves \the [I] into \the [src].</span>")
verbs |= /obj/item/clothing/shoes/proc/draw_knife
update_icon()
else
return ..()
/obj/item/clothing/shoes/update_icon()
overlays.Cut()
if(holding)
overlays += image(icon, "[icon_state]_knife")
return ..()
/obj/item/clothing/shoes/proc/handle_movement(var/turf/walking, var/running)
return

View File

@@ -183,6 +183,14 @@
item_state = "blindfold"
//vision_flags = BLIND // This flag is only supposed to be used if it causes permanent blindness, not temporary because of glasses
/obj/item/clothing/glasses/sunglasses/blindfold/tape
name = "length of tape"
desc = "It's a robust DIY blindfold!"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "tape_cross"
item_state = null
w_class = 1
/obj/item/clothing/glasses/sunglasses/prescription
name = "prescription sunglasses"
prescription = 1

View File

@@ -16,6 +16,13 @@
icon_state = "healthhud"
body_parts_covered = 0
/obj/item/clothing/glasses/hud/health/prescription
name = "Prescription Health Scanner HUD"
desc = "A medical HUD integrated with a set of prescription glasses"
icon_state = "healthhud"
prescription = 1
icon_state = "healthhudpresc"
item_state = "healthhudpresc"
/obj/item/clothing/glasses/hud/health/process_hud(var/mob/M)
process_med_hud(M, 1)
@@ -27,6 +34,14 @@
body_parts_covered = 0
var/global/list/jobs[0]
/obj/item/clothing/glasses/hud/security/prescription
name = "Prescription Security HUD"
desc = "A security HUD integrated with a set of prescription glasses"
icon_state = "securityhud"
prescription = 1
icon_state = "sechudpresc"
item_state = "sechudpresc"
/obj/item/clothing/glasses/hud/security/jensenshades
name = "Augmented shades"
desc = "Polarized bioneural eyewear, designed to augment your vision."

View File

@@ -8,6 +8,14 @@
gas_transfer_coefficient = 0.90
voicechange = 1
/obj/item/clothing/mask/muzzle/tape
name = "length of tape"
desc = "It's a robust DIY muzzle!"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "tape_cross"
item_state = null
w_class = 1
/obj/item/clothing/mask/muzzle/New()
..()
say_messages = list("Mmfph!", "Mmmf mrrfff!", "Mmmf mnnf!")

View File

@@ -15,6 +15,7 @@
force = 3
armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0)
siemens_coefficient = 0.7
can_hold_knife = 1
/obj/item/clothing/shoes/jackboots/unathi
name = "toe-less jackboots"
@@ -30,3 +31,4 @@
item_state = "workboots"
armor = list(melee = 40, bullet = 0, laser = 0, energy = 15, bomb = 20, bio = 0, rad = 20)
siemens_coefficient = 0.7
can_hold_knife = 1

View File

@@ -121,6 +121,11 @@
if(T.contains_dense_objects())
H << "<span class='warning'>You cannot teleport to a location with solid objects.</span>"
return 0
if(T.z != H.z || get_dist(T, get_turf(H)) > world.view)
H << "<span class='warning'>You cannot teleport to such a distant object.</span>"
return 0
phase_out(H,get_turf(H))
H.forceMove(T)

View File

@@ -7,14 +7,13 @@
icon_state = "space"
desc = "A special helmet designed for work in a hazardous, low-pressure environment."
item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | AIRTIGHT
flags_inv = BLOCKHAIR
item_state_slots = list(
slot_l_hand_str = "s_helmet",
slot_r_hand_str = "s_helmet",
)
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR
body_parts_covered = HEAD|FACE|EYES
cold_protection = HEAD
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE

View File

@@ -122,7 +122,7 @@
name = "black medical space helmet"
desc = "A black helmet sporting a medical cross and durable plating. Hopefully the wearer abides by space geneva."
icon_state = "syndicate-helm-black-med"
item_state_slots = list(slot_head_str = "syndicate-black-med")
item_state_slots = list(slot_head_str = "syndicate-helm-black-med")
/obj/item/clothing/suit/space/syndicate/black/med
name = "black medical space suit"

View File

@@ -8,7 +8,7 @@
armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20)
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
flags_inv = HIDEEARS | BLOCKHAIR
// flags_inv = HIDEEARS|BLOCKHAIR
//Species-specific stuff.
species_restricted = list("Human")

View File

@@ -91,7 +91,7 @@
/obj/item/clothing/suit/armor/laserproof/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
var/reflectchance = 40 - round(damage/3)
if(!(def_zone in list("chest", "groin")))
reflectchance /= 2
@@ -171,12 +171,12 @@
if(!turfs.len) turfs += pick(/turf in orange(6))
var/turf/picked = pick(turfs)
if(!isturf(picked)) return
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
playsound(user.loc, "sparks", 50, 1)
user.loc = picked
return PROJECTILE_FORCE_MISS
return 0
@@ -275,7 +275,7 @@
icon_state = "kvest"
item_state = "kvest"
armor = list(melee = 50, bullet = 15, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0)
allowed = list(/obj/item/weapon/gun,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner)
allowed = list(/obj/item/weapon/gun,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs)
/obj/item/clothing/suit/storage/vest/officer
name = "officer armor vest"

View File

@@ -96,7 +96,7 @@
item_state = "det_suit"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/flame/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder)
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/flame/lighter,/obj/item/device/taperecorder)
armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/suit/storage/det_trench/grey
@@ -109,7 +109,7 @@
desc = "A forensics technician jacket."
item_state = "det_suit"
body_parts_covered = UPPER_TORSO|ARMS
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner,/obj/item/device/taperecorder)
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/taperecorder)
armor = list(melee = 10, bullet = 10, laser = 15, energy = 10, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/suit/storage/forensics/red

View File

@@ -212,18 +212,12 @@
//coats
/obj/item/clothing/suit/leathercoat
name = "leather coat"
desc = "A long, thick black leather coat."
icon_state = "leathercoat"
item_state = "leathercoat"
/obj/item/clothing/suit/leathercoat/alt
name = "leather coat"
desc = "A long, thick black leather coat."
icon_state = "leathercoat_alt"
item_state = "leathercoat_alt"
/obj/item/clothing/suit/leathercoat/alt/sec
/obj/item/clothing/suit/leathercoat/sec
name = "leather coat"
desc = "A long, thick black leather coat."
icon_state = "leathercoat_sec"
@@ -367,6 +361,12 @@
icon_state = "militaryjacket"
item_state = "militaryjacket"
/obj/item/clothing/suit/jacket/miljacket2
name = "military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
icon_state = "militaryjacket2"
item_state = "militaryjacket2"
/obj/item/clothing/suit/storage/toggle/bomber
name = "bomber jacket"
desc = "A thick, well-worn WW2 leather bomber jacket."
@@ -397,11 +397,8 @@
body_parts_covered = UPPER_TORSO|ARMS
/obj/item/clothing/suit/storage/leather_jacket/alt
name = "leather jacket"
desc = "A black leather coat."
icon_state = "leather_jacket_alt"
item_state = "leather_jacket_alt"
body_parts_covered = UPPER_TORSO|ARMS
/obj/item/clothing/suit/storage/leather_jacket/nanotrasen
desc = "A black leather coat. A corporate logo is proudly displayed on the back."
@@ -409,7 +406,7 @@
//This one has buttons for some reason
/obj/item/clothing/suit/storage/toggle/brown_jacket
name = "leather jacket"
name = "brown jacket"
desc = "A brown leather coat."
icon_state = "brown_jacket"
item_state = "brown_jacket"

View File

@@ -20,6 +20,11 @@
holstered.add_fingerprint(user)
w_class = max(w_class, holstered.w_class)
user.visible_message("<span class='notice'>[user] holsters \the [holstered].</span>", "<span class='notice'>You holster \the [holstered].</span>")
name = "occupied [initial(name)]"
/obj/item/clothing/accessory/holster/proc/clear_holster()
holstered = null
name = initial(name)
/obj/item/clothing/accessory/holster/proc/unholster(mob/user as mob)
if(!holstered)
@@ -40,8 +45,8 @@
)
user.put_in_hands(holstered)
holstered.add_fingerprint(user)
holstered = null
w_class = initial(w_class)
clear_holster()
/obj/item/clothing/accessory/holster/attack_hand(mob/user as mob)
if (has_suit) //if we are part of a suit

View File

View File

@@ -1,3 +1,7 @@
/obj/item/weapon/forensics
icon = 'icons/obj/forensics.dmi'
w_class = 1
//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)
var/const/FINGERPRINT_COMPLETE = 6

View File

@@ -0,0 +1,153 @@
//DNA machine
/obj/machinery/dnaforensics
name = "DNA analyzer"
desc = "A high tech machine that is designed to read DNA samples properly."
icon = 'icons/obj/forensics.dmi'
icon_state = "dnaopen"
anchored = 1
density = 1
var/obj/item/weapon/forensics/swab/bloodsamp = null
var/closed = 0
var/scanning = 0
var/scanner_progress = 0
var/scanner_rate = 2.50
var/last_process_worldtime = 0
var/report_num = 0
/obj/machinery/dnaforensics/attackby(var/obj/item/W, mob/user as mob)
if(bloodsamp)
user << "<span class='warning'>There is already a sample in the machine.</span>"
return
if(closed)
user << "<span class='warning'>Open the cover before inserting the sample.</span>"
return
var/obj/item/weapon/forensics/swab/swab = W
if(istype(swab) && swab.is_used())
user.unEquip(W)
src.bloodsamp = swab
swab.loc = src
user << "<span class='notice'>You insert \the [W] into \the [src].</span>"
else
user << "<span class='warning'>\The [src] only accepts used swabs.</span>"
return
/obj/machinery/dnaforensics/ui_interact(mob/user, ui_key = "main",var/datum/nanoui/ui = null)
if(stat & (NOPOWER)) return
if(user.stat || user.restrained()) return
var/list/data = list()
data["scan_progress"] = round(scanner_progress)
data["scanning"] = scanning
data["bloodsamp"] = (bloodsamp ? bloodsamp.name : "")
data["bloodsamp_desc"] = (bloodsamp ? (bloodsamp.desc ? bloodsamp.desc : "No information on record.") : "")
data["lidstate"] = closed
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
if (!ui)
ui = new(user, src, ui_key, "dnaforensics.tmpl", "QuikScan DNA Analyzer", 540, 326)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/dnaforensics/Topic(href, href_list)
if(..()) return 1
if(stat & (NOPOWER))
return 0 // don't update UIs attached to this object
if(href_list["scanItem"])
if(scanning)
scanning = 0
else
if(bloodsamp)
if(closed == 1)
scanner_progress = 0
scanning = 1
usr << "<span class='notice'>Scan initiated.</span>"
update_icon()
else
usr << "<span class='notice'>Please close sample lid before initiating scan.</span>"
else
usr << "<span class='warning'>Insert an item to scan.</span>"
if(href_list["ejectItem"])
if(bloodsamp)
bloodsamp.forceMove(src.loc)
bloodsamp = null
if(href_list["toggleLid"])
toggle_lid()
return 1
/obj/machinery/dnaforensics/process()
if(scanning)
if(!bloodsamp || bloodsamp.loc != src)
bloodsamp = null
scanning = 0
else if(scanner_progress >= 100)
complete_scan()
return
else
//calculate time difference
var/deltaT = (world.time - last_process_worldtime) * 0.1
scanner_progress = min(100, scanner_progress + scanner_rate * deltaT)
last_process_worldtime = world.time
/obj/machinery/dnaforensics/proc/complete_scan()
src.visible_message("<span class='notice'>\icon[src] makes an insistent chime.</span>", 2)
update_icon()
if(bloodsamp)
var/obj/item/weapon/paper/P = new(src)
P.name = "[src] report #[++report_num]: [bloodsamp.name]"
P.stamped = list(/obj/item/weapon/stamp)
P.overlays = list("paper_stamped")
//dna data itself
var/data = "No scan information available."
if(bloodsamp.dna != null)
data = "Spectometric analysis on provided sample has determined the presence of [bloodsamp.dna.len] strings of DNA.<br><br>"
for(var/blood in bloodsamp.dna)
data += "\blue Blood type: [bloodsamp.dna[blood]]<br>\nDNA: [blood]<br><br>"
else
data += "No DNA found.<br>"
P.info = "<b>[src] analysis report #[report_num]</b><br>"
P.info += "<b>Scanned item:</b><br>[bloodsamp.name]<br>[bloodsamp.desc]<br><br>" + data
P.forceMove(src.loc)
P.update_icon()
scanning = 0
update_icon()
return
/obj/machinery/dnaforensics/attack_ai(mob/user as mob)
ui_interact(user)
/obj/machinery/dnaforensics/attack_hand(mob/user as mob)
ui_interact(user)
/obj/machinery/dnaforensics/verb/toggle_lid()
set category = "Object"
set name = "Toggle Lid"
set src in oview(1)
if(usr.stat || !isliving(usr))
return
if(scanning)
usr << "<span class='warning'>You can't do that while [src] is scanning!</span>"
return
closed = !closed
src.update_icon()
/obj/machinery/dnaforensics/update_icon()
..()
if(!(stat & NOPOWER) && scanning)
icon_state = "dnaworking"
else if(closed)
icon_state = "dnaclosed"
else
icon_state = "dnaopen"

View File

@@ -0,0 +1,116 @@
//microscope code itself
/obj/machinery/microscope
name = "high powered electron microscope"
desc = "A highly advanced microscope capable of zooming up to 3000x."
icon = 'icons/obj/forensics.dmi'
icon_state = "microscope"
anchored = 1
density = 1
var/obj/item/weapon/sample = null
var/report_num = 0
/obj/machinery/microscope/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(sample)
user << "<span class='warning'>There is already a slide in the microscope.</span>"
return
if(istype(W, /obj/item/weapon/forensics/slide) || istype(W, /obj/item/weapon/sample/print))
user << "<span class='notice'>You insert \the [W] into the microscope.</span>"
user.unEquip(W)
W.forceMove(src)
sample = W
update_icon()
return
/obj/machinery/microscope/attack_hand(mob/user)
if(!sample)
user << "<span class='warning'>The microscope has no sample to examine.</span>"
return
user << "<span class='notice'>The microscope whirrs as you examine \the [sample].</span>"
if(!do_after(user, 25) || !sample)
return
user << "<span class='notice'>Printing findings now...</span>"
var/obj/item/weapon/paper/report = new(get_turf(src))
report.stamped = list(/obj/item/weapon/stamp)
report.overlays = list("paper_stamped")
report_num++
if(istype(sample, /obj/item/weapon/forensics/slide))
var/obj/item/weapon/forensics/slide/slide = sample
if(slide.has_swab)
var/obj/item/weapon/forensics/swab/swab = slide.has_swab
report.name = "GSR report #[++report_num]: [swab.name]"
report.info = "<b>Scanned item:</b><br>[swab.name]<br><br>"
if(swab.gsr)
report.info += "Residue from a [swab.gsr] bullet detected."
else
report.info += "No gunpowder residue found."
else if(slide.has_sample)
var/obj/item/weapon/sample/fibers/fibers = slide.has_sample
report.name = "Fiber report #[++report_num]: [fibers.name]"
report.info = "<b>Scanned item:</b><br>[fibers.name]<br><br>"
if(fibers.evidence)
report.info = "Molecular analysis on provided sample has determined the presence of unique fiber strings.<br><br>"
for(var/fiber in fibers.evidence)
report.info += "<span class='notice'>Most likely match for fibers: [fiber]</span><br><br>"
else
report.info += "No fibers found."
else
report.name = "Empty slide report #[report_num]"
report.info = "Evidence suggests that there's nothing in this slide."
else if(istype(sample, /obj/item/weapon/sample/print))
report.name = "Fingerprint report #[report_num]: [sample.name]"
report.info = "<b>Fingerprint analysis report #[report_num]</b>: [sample.name]<br>"
var/obj/item/weapon/sample/print/card = sample
if(card.evidence && card.evidence.len)
report.info += "Surface analysis has determined unique fingerprint strings:<br><br>"
for(var/prints in card.evidence)
report.info += "<span class='notice'>Fingerprint string: </span>"
if(!is_complete_print(prints))
report.info += "INCOMPLETE PRINT"
else
report.info += "[prints]"
report.info += "<br>"
else
report.info += "No information available."
if(report)
report.update_icon()
if(report.info)
user << report.info
return
/obj/machinery/microscope/proc/remove_sample(var/mob/living/remover)
if(!istype(remover) || remover.incapacitated() || !Adjacent(remover))
return ..()
if(!sample)
remover << "<span class='warning'>\The [src] does not have a sample in it.</span>"
return
remover << "<span class='notice'>You remove \the [sample] from \the [src].</span>"
sample.forceMove(get_turf(src))
remover.put_in_hands(sample)
sample = null
update_icon()
/obj/machinery/microscope/AltClick()
remove_sample(usr)
/obj/machinery/microscope/MouseDrop(var/atom/other)
if(usr == other)
remove_sample(usr)
else
return ..()
/obj/machinery/microscope/update_icon()
icon_state = "microscope"
if(sample)
icon_state += "slide"

View File

@@ -0,0 +1,42 @@
/obj/item/weapon/forensics/slide
name = "microscope slide"
desc = "A pair of thin glass panes used in the examination of samples beneath a microscope."
icon_state = "slide"
var/obj/item/weapon/forensics/swab/has_swab
var/obj/item/weapon/sample/fibers/has_sample
/obj/item/weapon/forensics/slide/attackby(var/obj/item/weapon/W, var/mob/user)
if(has_swab || has_sample)
user << "<span class='warning'>There is already a sample in the slide.</span>"
return
if(istype (W, /obj/item/weapon/forensics/swab))
has_swab = W
else if(istype(W, /obj/item/weapon/sample/fibers))
has_sample = W
else
user << "<span class='warning'>You don't think this will fit.</span>"
return
user << "<span class='notice'>You insert the sample into the slide.</span>"
user.unEquip(W)
W.forceMove(src)
update_icon()
/obj/item/weapon/forensics/slide/attack_self(var/mob/user)
if(has_swab || has_sample)
user << "<span class='notice'>You remove \the sample from \the [src].</span>"
if(has_swab)
has_swab.loc = get_turf(src)
has_swab = null
if(has_sample)
has_sample.forceMove(get_turf(src))
has_sample = null
update_icon()
return
/obj/item/weapon/forensics/slide/update_icon()
if(!has_swab && !has_sample)
icon_state = "slide"
else if(has_swab)
icon_state = "slideswab"
else if(has_sample)
icon_state = "slidefiber"

View File

@@ -1,115 +0,0 @@
/obj/item/device/detective_scanner
name = "forensic scanner"
desc = "Used to scan objects for DNA and fingerprints."
icon_state = "forensic1"
var/list/stored = list()
w_class = 3.0
item_state = "electronic"
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
/obj/item/device/detective_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob)
if (!ishuman(M))
user << "<span class='warning'>[M] is not human and cannot have the fingerprints.</span>"
flick("forensic0",src)
return 0
if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
user << "<span class='notice'>No fingerprints found on [M]</span>"
flick("forensic0",src)
return 0
else
var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
F.amount = 1
F.add_fingerprint(M)
F.icon_state = "fingerprint1"
F.name = text("FPrintC- '[M.name]'")
user << "<span class='notice'>Done printing.</span>"
user << "<span class='notice'>[M]'s Fingerprints: [md5(M.dna.uni_identity)]</span>"
if ( M.blood_DNA && M.blood_DNA.len )
user << "<span class='notice'>Blood found on [M]. Analysing...</span>"
spawn(15)
for(var/blood in M.blood_DNA)
user << "<span class='notice'>Blood type: [M.blood_DNA[blood]]\nDNA: [blood]</span>"
return
/obj/item/device/detective_scanner/afterattack(atom/A as obj|turf, mob/user, proximity)
if(!proximity) return
if(ismob(A))
return
if(istype(A,/obj/machinery/computer/forensic_scanning))
user.visible_message("[user] takes a cord out of [src] and hooks its end into [A]" ,\
"<span class='notice'>You download data from [src] to [A]</span>")
var/obj/machinery/computer/forensic_scanning/F = A
F.sync_data(stored)
return
if(istype(A,/obj/item/weapon/f_card))
user << "The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\""
flick("forensic0",src)
return
add_fingerprint(user)
//General
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"<span class='warning'>Unable to locate any fingerprints, materials, fibers, or blood on [A]!</span>",\
"You hear a faint hum of electrical equipment.")
flick("forensic0",src)
return 0
if(add_data(A))
user << "<span class='notice'>Object already in internal memory. Consolidating data...</span>"
flick("forensic2",src)
return
//PRINTS
if(A.fingerprints && A.fingerprints.len)
user << "<span class='notice'>Isolated [A.fingerprints.len] fingerprints:</span>"
user << "Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.</span>"
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 << "<span class='notice'>No intact prints found</span>"
else
user << "<span class='notice'>Found [complete_prints.len] intact prints</span>"
for(var/i in complete_prints)
user << "<span class='notice'>&nbsp;&nbsp;&nbsp;&nbsp;[i]</span>"
//FIBERS
if(A.suit_fibers && A.suit_fibers.len)
user << "<span class='notice'>Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
flick("forensic2",src)
//Blood
if (A.blood_DNA && A.blood_DNA.len)
user << "<span class='notice'>Blood detected. Analysing...</span>"
spawn(15)
for(var/blood in A.blood_DNA)
user << "Blood type: \red [A.blood_DNA[blood]] \t \black DNA: \red [blood]"
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"<span class='notice'>You finish scanning \the [A].</span>",\
"You hear a faint hum of electrical equipment.")
flick("forensic2",src)
return 0
/obj/item/device/detective_scanner/proc/add_data(atom/A as mob|obj|turf|area)
var/datum/data/record/forensic/old = stored["\ref [A]"]
var/datum/data/record/forensic/fresh = new(A)
if(old)
fresh.merge(old)
. = 1
stored["\ref [A]"] = fresh
/obj/item/device/detective_scanner/verb/wipe()
set name = "Wipe Forensic Data"
set category = "Object"
set src in view(1)
if (alert("Are you sure you want to wipe all data from [src]?",,"Yes","No") == "Yes")
stored = list()
usr << "<span class='notice'>Forensic data erase complete.</span>"

View File

@@ -1,313 +0,0 @@
/obj/machinery/computer/forensic_scanning
name = "high-res forensic scanning computer"
icon_keyboard = "security_key"
icon_screen = "forensic"
var/screen = "database"
var/authenticated = 0
req_access = list(access_forensics_lockers)
var/scan_progress = -1
var/obj/item/scanning
var/datum/data/record/forensic/current
var/list/filters = list()
var/list/current_list = list()
var/list/files = list()
/obj/machinery/computer/forensic_scanning/proc/get_printable_data(var/datum/data/record/forensic/fresh)
. += "<h2>[fresh.fields["name"]]</h2>"
. += "Scanned in [fresh.fields["area"]] at [worldtime2text(fresh.fields["time"])]<br>"
var/list/prints = fresh.fields["fprints"]
if(prints.len)
. += "<h3>Fingerprints:</h3>"
var/incomplete = 0
for(var/fullprint in prints)
var/print = prints[fullprint]
if(is_complete_print(print))
. += "[print]<br>"
else
incomplete++
if(incomplete)
. += "[incomplete] incomplete fingerprints."
else
. += "<br>No fingerprints recorded.<br>"
var/list/fibers = fresh.fields["fibers"]
if(fibers.len)
. += "<h3>Fibers:</h3>"
. += "<ul>"
for(var/fiber in fibers)
. += "<li>[fiber]</li>"
. += "</ul>"
else
. += "<br>No fibers recorded."
var/list/bloods = fresh.fields["blood"]
if(bloods.len)
. += "<h3>Blood:</h3>"
. += "<ul>"
for(var/blood in bloods)
. += "<li>DNA: [blood] Type: [bloods[blood]]</li>"
. += "</ul>"
else
. += "<br>No blood recorded."
/obj/machinery/computer/forensic_scanning/proc/add_record(var/datum/data/record/forensic/fresh)
var/datum/data/record/forensic/old = files[fresh.uid]
if(old)
fresh.merge(old)
fresh.fields["label"] = old.fields["label"]
files[fresh.uid] = fresh
//updating partial prints on other things
var/list/fprints = fresh.fields["fprints"]
if(fprints.len)
for(var/id in files)
var/datum/data/record/forensic/rec = files[id]
if(rec.update_prints(fprints))
files[id] = rec
/obj/machinery/computer/forensic_scanning/proc/process_card(var/obj/item/weapon/f_card/card)
if(card.fingerprints)
usr << "<span class='notice'>\The [src] sucks in \the [card] and whirrs, scanning it.</span>"
var/found = 0
for(var/id in files)
var/datum/data/record/forensic/rec = files[id]
found = rec.update_prints(card.fingerprints)
if (found)
files[id] = rec
if(found)
usr << "<span class='notice'>Complete match found.</span>"
else
usr << "<span class='notice'>No match found.</span>"
return 1
else
usr << "<span class='warning'>No fingerprints detected on [card].</span>"
return 0
//Takes a list of forensic records, with key being reference to object, and updates internal database.
/obj/machinery/computer/forensic_scanning/proc/sync_data(var/list/newdata)
for(var/id in newdata)
var/datum/data/record/forensic/fresh = newdata[id]
add_record(fresh)
/obj/machinery/computer/forensic_scanning/proc/get_filtered_set()
.= list()
for(var/id in files)
var/datum/data/record/forensic/cur = files[id]
var/add = 1
if(filters["name"])
add = 0
for(var/filter in filters["name"])
if(findtext(cur.fields["name"], filter))
add = 1
break
if(filters["area"])
add = 0
for(var/filter in filters["area"])
if(findtext(cur.fields["area"], filter))
add = 1
break
if(filters["fprints"])
add = 0
var/list/prints = cur.fields["fprints"]
for(var/pid in prints)
var/print = prints[pid]
if (is_complete_print(print))
for(var/filter in filters["fprints"])
if(findtext(print, filter))
add = 1
break
if(filters["fibers"])
add = 0
for(var/fiber in cur.fields["fibers"])
for(var/filter in filters["fibers"])
if(findtext(fiber, filter))
add = 1
break
if(filters["blood"])
add = 0
for(var/DNA in cur.fields["blood"])
for(var/filter in filters["blood"])
if(findtext(DNA, filter))
add = 1
break
if(filters["label"])
add = 0
for(var/filter in filters["label"])
if(cur.fields["label"] && findtext(cur.fields["label"], filter))
add = 1
break
if (add)
.+=cur
/obj/machinery/computer/forensic_scanning/attack_hand(mob/user)
if(..())
return
user.set_machine(src)
var/dat
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>"
dat += " | "
dat += "<a href='?src=\ref[src];operation=screen;screen=database'>Database</a>"
dat += " | "
dat += "<a href='?src=\ref[src];operation=screen;screen=details'>Record details</a>"
dat += " | "
dat += "<a href='?src=\ref[src];operation=screen;screen=scan'>Scanning</a>"
dat +="<br><hr><br>"
switch(screen)
if("database") //Database screen
dat += "Search filters:<br>"
var/list/filternames = list("Object"="name", "Area"="area", "Fingerprints"="fprints", "Fibers"="fibers", "DNA"="blood", "Label"="label")
for(var/filter in filternames)
var/fname = filternames[filter]
dat += "<br>[filter]: <a href='?src=\ref[src];operation=filter;filter=[fname]'>[filters[fname] ? list2text(filters[fname], ",") : "All"]</a>"
current_list = get_filtered_set()
dat+= "<br><hr><br>"
if(current_list.len < 1)
dat += "No data matching your request found."
else
dat += "<table><tr>"
dat += "<th>Object</th><th>Area</th><th>Fingerprints</th><th>Fibers</th><th>Blood</th><th>Label</th></tr>"
for(var/datum/data/record/forensic/record in current_list)
dat += "<tr><td><a href='?src=\ref[src];operation=details;identifier=[record.uid]'>[record.fields["name"]]</td>"
dat += "<td>[record.fields["area"]]</td>"
for(var/criteria in list("fprints", "fibers", "blood"))
var/list/data = record.fields[criteria]
dat += "<td>[data.len ? data.len : "None"]</td>"
dat += "<td>[record.fields["label"] ? record.fields["label"] : ""]</td>"
dat += "<td><a href='?src=\ref[src];operation=delete;identifier=[record.uid]'>Delete</a></td>"
dat += "</tr>"
dat += "</table>"
dat += "<a href='?src=\ref[src];operation=printall'>Print all listed</a><br>"
if("details") //Details screen
if(!current)
dat += "<br>NO RECORD SELECTED"
else
dat += get_printable_data(current)
dat += "<br><b>Labels:</b> "
dat += "<a href='?src=\ref[src];operation=label'>[current.fields["label"] ? current.fields["label"] : "None"]</a><br>"
dat += "<a href='?src=\ref[src];operation=print'>Print record</a><br>"
if("scan") //Scanning screen
dat += "Object: <a href='?src=\ref[src];operation=object'>[scanning ? scanning.name : "-----"]</a><br>"
if (scanning)
if (scan_progress > 0)
dat += "Scan in progress."
dat += " <a href='?src=\ref[src];operation=cancel'>Cancel</a><br>"
else
dat += "<a href='?src=\ref[src];operation=scan'>Scan</a><br>"
dat += "Insert fingerprint card here: <a href='?src=\ref[src];operation=card'>-----</a>"
user << browse(dat,"window=fscanner")
onclose(user,"fscanner")
/obj/machinery/computer/forensic_scanning/Topic(href,href_list)
if(..()) return 1
switch(href_list["operation"])
if("login")
var/mob/M = usr
if(istype(M,/mob/living/silicon) || allowed(M))
authenticated = 1
if("logout")
authenticated = 0
if("filter")
var/filterstr = sanitize(input("Input the search criteria. Multiple values can be input, separated by a comma.", "Filter setting") as text|null)
if(filterstr)
filters[href_list["filter"]] = text2list(filterstr,",")
else
filters[href_list["filter"]] = null
if("screen")
screen = href_list["screen"]
if("details")
if(href_list["identifier"])
screen = "details"
current = files[href_list["identifier"]]
else
usr << "<span class='warning'>No record found.</span>"
if("delete")
if(href_list["identifier"])
if(alert("Are you sure you want to delete this record?","Record deletion", "Yes", "No") == "Yes")
files.Remove(href_list["identifier"])
if(current && current.uid == href_list["identifier"])
current = null
if("label")
if(current)
var/label = sanitize(input(usr,"Input the label for this record. Multiple values can be input, separated by a comma.", "Labeling record", current.fields["label"]) as text|null)
current.fields["label"] = label
if("object")
if(scanning)
scanning.loc = get_turf(src)
scan_progress = -1
scanning = null
else
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.Cut()
I.w_class = 1
I.icon_state = "evidenceobj"
else
scanning = I
M.drop_item()
I.loc = src
else
usr << "<span class='warning'>Invalid object, rejected.</span>"
if("scan")
if(scanning)
scan_progress = 10
if("cancel")
scan_progress = -1
if("card")
var/mob/M = usr
var/obj/item/I = M.get_active_hand()
if(istype(I, /obj/item/weapon/f_card))
if(process_card(I))
M.drop_item()
qdel(I)
else
usr << "<span class='warning'>Invalid fingerprint card, rejected.</span>"
if("print")
if(current)
var/obj/item/weapon/paper/P = new(loc)
P.name = "\improper Forensics Data ([current.fields["name"]])"
P.icon_state = "paper_words"
P.info = "<b>Forensics Database</b> - [worldtime2text(world.time)]<br><br>"
P.info += get_printable_data(current)
if("printall")
var/obj/item/weapon/paper/P = new(loc)
P.name = "\improper Forensics Data"
P.icon_state = "paper_words"
P.info = "<b>Forensics Database</b> - [worldtime2text(world.time)]<br><br>"
for(var/datum/data/record/forensic/cur in current_list)
P.info += get_printable_data(cur)
updateUsrDialog()
/obj/machinery/computer/forensic_scanning/process()
if (!..())
return
if(scanning)
if(scan_progress > 0)
scan_progress--
updateUsrDialog()
if(scan_progress == 0)
scan_progress = -1
ping("Scan complete.")
var/datum/data/record/forensic/fresh = new(scanning)
add_record(fresh)
updateUsrDialog()

View File

@@ -0,0 +1,17 @@
//crime scene kit
/obj/item/weapon/storage/briefcase/crimekit
name = "crime scene kit"
desc = "A stainless steel-plated carrycase for all your forensic needs. Feels heavy."
icon = 'icons/obj/forensics.dmi'
icon_state = "case"
item_state = "case"
storage_slots = 14
/obj/item/weapon/storage/briefcase/crimekit/New()
..()
new /obj/item/weapon/storage/box/swabs(src)
new /obj/item/weapon/storage/box/fingerprints(src)
new /obj/item/weapon/reagent_containers/spray/luminol(src)
new /obj/item/device/uv_light(src)
new /obj/item/weapon/forensics/sample_kit(src)
new /obj/item/weapon/forensics/sample_kit/powder(src)

View File

@@ -96,56 +96,3 @@
/obj/item/weapon/evidencebag/examine(mob/user)
..(user)
if (stored_item) user.examinate(stored_item)
/obj/item/weapon/storage/box/evidence
name = "evidence bag box"
desc = "A box claiming to contain evidence bags. Also holds fingerprint cards."
icon = 'icons/obj/storage.dmi'
icon_state = "box"
storage_slots= 14
max_w_class = 3
max_storage_space = 38
can_hold = list(/obj/item/weapon/f_card, /obj/item/weapon/evidencebag)
use_to_pickup = 1
New()
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)
..()
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
slot_flags = SLOT_EARS
throw_speed = 3
throw_range = 5
/obj/item/weapon/f_card/add_fingerprint(mob/living/M as mob, ignoregloves = 0)
if(..())
var/mob/living/carbon/human/H = M
var/full_print = md5(H.dna.uni_identity)
fingerprints[full_print] = full_print
/obj/item/weapon/f_card/examine(mob/user)
..()
if(fingerprints.len)
user << "<span class='notice'>Fingerprints on this card:</span>"
for(var/print in fingerprints)
user << "<span class='notice'>\t[fingerprints[print]]</span>"
/obj/item/weapon/fcardholder
name = "fingerprint card case"
desc = "Apply finger print card."
icon = 'icons/obj/items.dmi'
icon_state = "fcardholder0"
item_state = "clipboard"

View File

@@ -0,0 +1,13 @@
/obj/item/weapon/reagent_containers/spray/luminol
name = "luminol bottle"
desc = "A bottle containing an odourless, colorless liquid."
icon = 'icons/obj/forensics.dmi'
icon_state = "luminol"
item_state = "cleaner"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10)
volume = 250
/obj/item/weapon/reagent_containers/spray/luminol/New()
..()
reagents.add_reagent("luminol", 250)

View File

@@ -71,7 +71,7 @@
icon_state = "raglit"
else
icon_state = "rag"
var/obj/item/weapon/reagent_containers/food/drinks/bottle/B = loc
if(istype(B))
B.update_icon()
@@ -83,7 +83,7 @@
if(reagents.total_volume)
var/target_text = trans_dest? "\the [trans_dest]" : "\the [user.loc]"
user.visible_message("<span class='danger'>\The [user] begins to wring out [src] over [target_text].</span>", "<span class='notice'>You begin to wring out [src] over [target_text].</span>")
if(do_after(user, reagents.total_volume*5)) //50 for a fully soaked rag
if(trans_dest)
reagents.trans_to(trans_dest, reagents.total_volume)
@@ -114,29 +114,29 @@
if(user.zone_sel.selecting == "mouth")
user.do_attack_animation(src)
user.visible_message(
"<span class='danger'>\The [user] smothers [target] with [src]!</span>",
"<span class='warning'>You smother [target] with [src]!</span>",
"<span class='danger'>\The [user] smothers [target] with [src]!</span>",
"<span class='warning'>You smother [target] with [src]!</span>",
"You hear some struggling and muffled cries of surprise"
)
//it's inhaled, so... maybe CHEM_BLOOD doesn't make a whole lot of sense but it's the best we can do for now
reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
update_name()
else
wipe_down(target, user)
return
return ..()
/obj/item/weapon/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob, proximity)
if(!proximity)
if(!proximity)
return
if(istype(A, /obj/structure/reagent_dispensers))
if(!reagents.get_free_space())
user << "<span class='warning'>\The [src] is already soaked.</span>"
return
if(A.reagents && A.reagents.trans_to_obj(src, reagents.maximum_volume))
user.visible_message("<span class='notice'>\The [user] soaks [src] using [A].</span>", "<span class='notice'>You soak [src] using [A].</span>")
update_name()
@@ -167,7 +167,7 @@
return
if(!can_ignite())
return
//also copied from matches
if(reagents.get_reagent_amount("phoron")) // the phoron explodes when exposed to fire
visible_message("<span class='danger'>\The [src] conflagrates violently!</span>")
@@ -176,7 +176,7 @@
e.start()
qdel(src)
return
processing_objects += src
set_light(2, null, "#E38F46")
on_fire = 1
@@ -187,7 +187,7 @@
processing_objects -= src
set_light(0)
on_fire = 0
//rags sitting around with 1 second of burn time left is dumb.
//ensures players always have a few seconds of burn time left when they light their rag
if(burn_time <= 5)
@@ -209,7 +209,7 @@
var/turf/location = get_turf(src)
if(location)
location.hotspot_expose(700, 5)
if(burn_time <= 0)
processing_objects -= src
new /obj/effect/decal/cleanable/ash(location)

View File

@@ -0,0 +1,158 @@
/obj/item/weapon/sample
name = "forensic sample"
icon = 'icons/obj/forensics.dmi'
w_class = 1
var/list/evidence = list()
/obj/item/weapon/sample/New(var/newloc, var/atom/supplied)
..(newloc)
if(supplied)
copy_evidence(supplied)
name = "[initial(name)] (\the [supplied])"
/obj/item/weapon/sample/print/New(var/newloc, var/atom/supplied)
..(newloc, supplied)
if(evidence && evidence.len)
icon_state = "fingerprint1"
/obj/item/weapon/sample/proc/copy_evidence(var/atom/supplied)
if(supplied.suit_fibers && supplied.suit_fibers.len)
evidence = supplied.suit_fibers.Copy()
supplied.suit_fibers.Cut()
/obj/item/weapon/sample/proc/merge_evidence(var/obj/item/weapon/sample/supplied, var/mob/user)
if(!supplied.evidence || !supplied.evidence.len)
return 0
evidence |= supplied.evidence
name = "[initial(name)] (combined)"
user << "<span class='notice'>You transfer the contents of \the [supplied] into \the [src].</span>"
return 1
/obj/item/weapon/sample/print/merge_evidence(var/obj/item/weapon/sample/supplied, var/mob/user)
if(!supplied.evidence || !supplied.evidence.len)
return 0
for(var/print in supplied.evidence)
if(evidence[print])
evidence[print] = stringmerge(evidence[print],supplied.evidence[print])
else
evidence[print] = supplied.evidence[print]
name = "[initial(name)] (combined)"
user << "<span class='notice'>You overlay \the [src] and \the [supplied], combining the print records.</span>"
return 1
/obj/item/weapon/sample/attackby(var/obj/O, var/mob/user)
if(O.type == src.type)
user.unEquip(O)
if(merge_evidence(O, user))
qdel(O)
return 1
return ..()
/obj/item/weapon/sample/fibers
name = "fiber bag"
desc = "Used to hold fiber evidence for the detective."
icon_state = "fiberbag"
/obj/item/weapon/sample/print
name = "fingerprint card"
desc = "Records a set of fingerprints."
icon = 'icons/obj/card.dmi'
icon_state = "fingerprint0"
item_state = "paper"
/obj/item/weapon/sample/print/attack_self(var/mob/user)
if(evidence && evidence.len)
return
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.gloves)
user << "<span class='warning'>Take \the [H.gloves] off first.</span>"
return
user << "<span class='notice'>You firmly press your fingertips onto the card.</span>"
var/fullprint = H.get_full_print()
evidence[fullprint] = fullprint
name = "[initial(name)] (\the [H])"
icon_state = "fingerprint1"
/obj/item/weapon/sample/print/attack(var/mob/living/M, var/mob/user)
if(!ishuman(M))
return ..()
if(evidence && evidence.len)
return 0
var/mob/living/carbon/human/H = M
if(H.gloves)
user << "<span class='warning'>\The [H] is wearing gloves.</span>"
return 1
if(user != H && H.a_intent != "help" && !H.lying)
user.visible_message("<span class='danger'>\The [user] tries to take prints from \the [H], but they move away.</span>")
return 1
if(user.zone_sel.selecting == "r_hand" || user.zone_sel.selecting == "l_hand")
var/has_hand
var/obj/item/organ/external/O = H.organs_by_name["r_hand"]
if(istype(O) && !O.is_stump())
has_hand = 1
else
O = H.organs_by_name["l_hand"]
if(istype(O) && !O.is_stump())
has_hand = 1
if(!has_hand)
user << "<span class='warning'>They don't have any hands.</span>"
return 1
user.visible_message("[user] takes a copy of \the [H]'s fingerprints.")
var/fullprint = H.get_full_print()
evidence[fullprint] = fullprint
copy_evidence(src)
name = "[initial(name)] (\the [H])"
icon_state = "fingerprint1"
return 1
return 0
/obj/item/weapon/sample/print/copy_evidence(var/atom/supplied)
if(supplied.fingerprints && supplied.fingerprints.len)
for(var/print in supplied.fingerprints)
evidence[print] = supplied.fingerprints[print]
supplied.fingerprints.Cut()
/obj/item/weapon/forensics/sample_kit
name = "fiber collection kit"
desc = "A magnifying glass and tweezers. Used to lift suit fibers."
icon_state = "m_glass"
w_class = 2
var/evidence_type = "fiber"
var/evidence_path = /obj/item/weapon/sample/fibers
/obj/item/weapon/forensics/sample_kit/proc/can_take_sample(var/mob/user, var/atom/supplied)
return (supplied.suit_fibers && supplied.suit_fibers.len)
/obj/item/weapon/forensics/sample_kit/proc/take_sample(var/mob/user, var/atom/supplied)
var/obj/item/weapon/sample/S = new evidence_path(get_turf(user), supplied)
user << "<span class='notice'>You transfer [S.evidence.len] [S.evidence.len > 1 ? "[evidence_type]s" : "[evidence_type]"] to \the [S].</span>"
/obj/item/weapon/forensics/sample_kit/afterattack(var/atom/A, var/mob/user, var/proximity)
if(!proximity)
return
add_fingerprint(user)
if(can_take_sample(user, A))
take_sample(user,A)
return 1
else
user << "<span class='warning'>You are unable to locate any [evidence_type]s on \the [A].</span>"
return ..()
/obj/item/weapon/forensics/sample_kit/powder
name = "fingerprint powder"
desc = "A jar containing aluminum powder and a specialized brush."
icon_state = "dust"
evidence_type = "fingerprint"
evidence_path = /obj/item/weapon/sample/print
/obj/item/weapon/forensics/sample_kit/powder/can_take_sample(var/mob/user, var/atom/supplied)
return (supplied.fingerprints && supplied.fingerprints.len)

View File

@@ -0,0 +1,45 @@
/obj/item/weapon/storage/box/swabs
name = "box of swab kits"
desc = "Sterilized equipment within. Do not contaminate."
icon = 'icons/obj/forensics.dmi'
icon_state = "dnakit"
can_hold = list(/obj/item/weapon/forensics/swab)
storage_slots = 14
/obj/item/weapon/storage/box/swabs/New()
..()
for(var/i=0;i<storage_slots,i++) // Fill 'er up.
new /obj/item/weapon/forensics/swab(src)
/obj/item/weapon/storage/box/slides
name = "microscope slide box"
icon_state = "solution_trays"
storage_slots = 7
/obj/item/weapon/storage/box/slides/New()
..()
for(var/i=0;i<storage_slots,i++)
new /obj/item/weapon/forensics/slide(src)
/obj/item/weapon/storage/box/evidence
name = "evidence bag box"
desc = "A box claiming to contain evidence bags."
storage_slots = 6
/obj/item/weapon/storage/box/evidence/New()
..()
for(var/i=0;i<storage_slots,i++)
new /obj/item/weapon/evidencebag(src)
/obj/item/weapon/storage/box/fingerprints
name = "box of fingerprint cards"
desc = "Sterilized equipment within. Do not contaminate."
icon = 'icons/obj/forensics.dmi'
icon_state = "dnakit"
can_hold = list(/obj/item/weapon/sample/print)
storage_slots = 14
/obj/item/weapon/storage/box/fingerprints/New()
..()
for(var/i=0;i<storage_slots,i++)
new /obj/item/weapon/sample/print(src)

View File

@@ -0,0 +1,120 @@
/obj/item/weapon/forensics/swab
name = "swab kit"
desc = "A sterilized cotton swab and vial used to take forensic samples."
icon_state = "swab"
var/gsr = 0
var/list/dna
var/used
/obj/item/weapon/forensics/swab/proc/is_used()
return used
/obj/item/weapon/forensics/swab/attack(var/mob/living/M, var/mob/user)
if(!ishuman(M))
return ..()
if(is_used())
return
var/mob/living/carbon/human/H = M
var/sample_type
if(H.wear_mask)
user << "<span class='warning'>\The [H] is wearing a mask.</span>"
return
if(!H.dna || !H.dna.unique_enzymes)
user << "<span class='warning'>They don't seem to have DNA!</span>"
return
if(user != H && H.a_intent != "help" && !H.lying)
user.visible_message("<span class='danger'>\The [user] tries to take a swab sample from \the [H], but they move away.</span>")
return
if(user.zone_sel.selecting == "mouth")
if(!H.organs_by_name["head"])
user << "<span class='warning'>They don't have a head.</span>"
return
if(!H.check_has_mouth())
user << "<span class='warning'>They don't have a mouth.</span>"
return
user.visible_message("[user] swabs \the [H]'s mouth for a saliva sample.")
dna = list(H.dna.unique_enzymes)
sample_type = "DNA"
else if(user.zone_sel.selecting == "r_hand" || user.zone_sel.selecting == "l_hand")
var/has_hand
var/obj/item/organ/external/O = H.organs_by_name["r_hand"]
if(istype(O) && !O.is_stump())
has_hand = 1
else
O = H.organs_by_name["l_hand"]
if(istype(O) && !O.is_stump())
has_hand = 1
if(!has_hand)
user << "<span class='warning'>They don't have any hands.</span>"
return
user.visible_message("[user] swabs [H]'s palm for a sample.")
sample_type = "GSR"
gsr = H.gunshot_residue
else
return
if(sample_type)
set_used(sample_type, H)
return
return 1
/obj/item/weapon/forensics/swab/afterattack(var/atom/A, var/mob/user, var/proximity)
if(!proximity || istype(A, /obj/item/weapon/forensics/slide) || istype(A, /obj/machinery/dnaforensics))
return
if(is_used())
user << "<span class='warning'>This swab has already been used.</span>"
return
add_fingerprint(user)
var/list/choices = list()
if(A.blood_DNA)
choices |= "Blood"
if(istype(A, /obj/item/clothing))
choices |= "Gunshot Residue"
var/choice
if(!choices.len)
user << "<span class='warning'>There is no evidence on \the [A].</span>"
return
else if(choices.len == 1)
choice = choices[1]
else
choice = input("What kind of evidence are you looking for?","Evidence Collection") as null|anything in choices
if(!choice)
return
var/sample_type
if(choice == "Blood")
if(!A.blood_DNA || !A.blood_DNA.len) return
dna = A.blood_DNA.Copy()
sample_type = "blood"
else if(choice == "Gunshot Residue")
var/obj/item/clothing/B = A
if(!istype(B) || !B.gunshot_residue)
user << "<span class='warning'>There is no residue on \the [A].</span>"
return
gsr = B.gunshot_residue
sample_type = "residue"
if(sample_type)
user.visible_message("\The [user] swabs \the [A] for a sample.", "You swab \the [A] for a sample.")
set_used(sample_type, A)
/obj/item/weapon/forensics/swab/proc/set_used(var/sample_str, var/atom/source)
name = "[initial(name)] ([sample_str] - [source])"
desc = "[initial(desc)] The label on the vial reads 'Sample of [sample_str] from [source].'."
icon_state = "swab_used"
used = 1

View File

@@ -0,0 +1,69 @@
/obj/item/device/uv_light
name = "\improper UV light"
desc = "A small handheld black light."
icon_state = "uv_off"
slot_flags = SLOT_BELT
w_class = 2
item_state = "electronic"
matter = list(DEFAULT_WALL_MATERIAL = 150)
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
var/list/scanned = list()
var/list/stored_alpha = list()
var/list/reset_objects = list()
var/range = 3
var/on = 0
var/step_alpha = 50
/obj/item/device/uv_light/attack_self(var/mob/user)
on = !on
if(on)
set_light(range, 2, "#007fff")
processing_objects |= src
icon_state = "uv_on"
else
set_light(0)
clear_last_scan()
processing_objects -= src
icon_state = "uv_off"
/obj/item/device/uv_light/proc/clear_last_scan()
if(scanned.len)
for(var/atom/O in scanned)
O.invisibility = scanned[O]
if(O.fluorescent == 2) O.fluorescent = 1
scanned.Cut()
if(stored_alpha.len)
for(var/atom/O in stored_alpha)
O.alpha = stored_alpha[O]
if(O.fluorescent == 2) O.fluorescent = 1
stored_alpha.Cut()
if(reset_objects.len)
for(var/obj/item/I in reset_objects)
I.overlays -= I.blood_overlay
if(I.fluorescent == 2) I.fluorescent = 1
reset_objects.Cut()
/obj/item/device/uv_light/process()
clear_last_scan()
if(on)
step_alpha = round(255/range)
var/turf/origin = get_turf(src)
if(!origin)
return
for(var/turf/T in range(range, origin))
var/use_alpha = 255 - (step_alpha * get_dist(origin, T))
for(var/atom/A in T.contents)
if(A.fluorescent == 1)
A.fluorescent = 2 //To prevent light crosstalk.
if(A.invisibility)
scanned[A] = A.invisibility
A.invisibility = 0
stored_alpha[A] = A.alpha
A.alpha = use_alpha
if(istype(A, /obj/item))
var/obj/item/O = A
if(O.was_bloodied && !(O.blood_overlay in O.overlays))
O.overlays |= O.blood_overlay
reset_objects |= O

View File

@@ -77,7 +77,7 @@
else
body = "[pick("The alien species designated \'United Exolitics\'","The alien species designated \'REDACTED\'","An unknown alien species")] have raided [affected_dest.name] today, stealing wildlife, farm animals, medical research materials and kidnapping civilians. It seems they desire to learn more about us, so the Navy will be standing by to accomodate them next time they try."
if(AI_LIBERATION)
body = "A [pick("\'REDACTED\' was detected on","S.E.L.F operative infiltrated","malignant computer virus was detected on","rogue [pick("slicer","hacker")] was apprehended on")] [affected_dest.name] today, and managed to infect [pick("\'REDACTED\'","a sentient sub-system","a class one AI","a sentient defence installation")] before it could be stopped. Many lives were lost as it systematically begin murdering civilians, and considerable work must be done to repair the affected areas."
body = "A [pick("\'REDACTED\' was detected on","S.E.L.F operative infiltrated","malignant computer virus was detected on","rogue [pick("slicer","hacker")] was apprehended on")] [affected_dest.name] today, and managed to infect [pick("\'REDACTED\'","a sentient sub-system","a class one AI","a sentient defence installation")] before it could be stopped, causing serious damage. Considerable work must be done to repair the affected areas."
if(MOURNING)
body = "[pick("The popular","The well-liked","The eminent","The well-known")] [pick("professor","entertainer","singer","researcher","public servant","administrator","ship captain","\'REDACTED\'")], [pick( random_name(pick(MALE,FEMALE)), 40; "\'REDACTED\'" )] has [pick("passed away","committed suicide","been murdered","died in a freakish accident")] on [affected_dest.name] today. The entire planet is in mourning, and prices have dropped for industrial goods as worker morale drops."
if(CULT_CELL_REVEALED)

View File

@@ -1,21 +1,25 @@
/proc/send2irc(var/channel, var/msg)
if(config.use_irc_bot && config.irc_bot_host)
if(config.irc_bot_export)
spawn(-1) // spawn here prevents hanging in the case that the bot isn't reachable
world.Export("http://[config.irc_bot_host]:45678?[list2params(list(pwd=config.comms_password, chan=channel, mesg=msg))]")
if (config.use_irc_bot)
if (config.use_node_bot)
shell("node bridge.js -h \"[config.irc_bot_host]\" -p \"[config.irc_bot_port]\" -c \"[channel]\" -m \"[msg]\"")
else
if(config.use_lib_nudge)
var/nudge_lib
if(world.system_type == MS_WINDOWS)
nudge_lib = "lib\\nudge.dll"
if (config.irc_bot_host)
if(config.irc_bot_export)
spawn(-1) // spawn here prevents hanging in the case that the bot isn't reachable
world.Export("http://[config.irc_bot_host]:45678?[list2params(list(pwd=config.comms_password, chan=channel, mesg=msg))]")
else
nudge_lib = "lib/nudge.so"
if(config.use_lib_nudge)
var/nudge_lib
if(world.system_type == MS_WINDOWS)
nudge_lib = "lib\\nudge.dll"
else
nudge_lib = "lib/nudge.so"
spawn(0)
call(nudge_lib, "nudge")("[config.comms_password]","[config.irc_bot_host]","[channel]","[msg]")
else
spawn(0)
ext_python("ircbot_message.py", "[config.comms_password] [config.irc_bot_host] [channel] [msg]")
spawn(0)
call(nudge_lib, "nudge")("[config.comms_password]","[config.irc_bot_host]","[channel]","[msg]")
else
spawn(0)
ext_python("ircbot_message.py", "[config.comms_password] [config.irc_bot_host] [channel] [msg]")
return
/proc/send2mainirc(var/msg)

View File

@@ -5,6 +5,7 @@
icon = 'icons/obj/hydroponics_products.dmi'
icon_state = "blank"
desc = "Nutritious! Probably."
slot_flags = SLOT_HOLSTER
var/plantname
var/datum/seed/seed

View File

@@ -25,10 +25,23 @@
material = "carbon"
/obj/item/weapon/ore/glass
name = "impure silicates"
name = "sand"
icon_state = "ore_glass"
origin_tech = list(TECH_MATERIAL = 1)
material = "sand"
slot_flags = SLOT_HOLSTER
// POCKET SAND!
/obj/item/weapon/ore/glass/throw_impact(atom/hit_atom)
..()
var/mob/living/carbon/human/H = hit_atom
if(istype(H) && H.has_eyes() && prob(85))
H << "<span class='danger'>Some of \the [src] gets in your eyes!</span>"
H.eye_blind += 5
H.eye_blurry += 10
spawn(1)
if(istype(loc, /turf/)) qdel(src)
/obj/item/weapon/ore/phoron
name = "phoron crystals"

View File

@@ -59,7 +59,7 @@ var/global/list/ore_data = list()
/ore/glass
name = "sand"
display_name = "impure silicates"
display_name = "sand"
smelts_to = "glass"
compresses_to = "sandstone"

View File

@@ -5,7 +5,7 @@ var/list/holder_mob_icon_cache = list()
name = "holder"
desc = "You shouldn't ever see this."
icon = 'icons/obj/objects.dmi'
slot_flags = SLOT_HEAD
slot_flags = SLOT_HEAD | SLOT_HOLSTER
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
@@ -45,6 +45,7 @@ var/list/holder_mob_icon_cache = list()
overlays.Cut()
icon = M.icon
icon_state = M.icon_state
item_state = M.item_state
color = M.color
name = M.name
desc = M.desc
@@ -61,7 +62,7 @@ var/list/holder_mob_icon_cache = list()
//Mob specific holders.
/obj/item/weapon/holder/diona
origin_tech = list(TECH_MAGNET = 3, TECH_BIO = 5)
slot_flags = SLOT_HEAD | SLOT_OCLOTHING
slot_flags = SLOT_HEAD | SLOT_OCLOTHING | SLOT_HOLSTER
/obj/item/weapon/holder/drone
origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 5)

View File

@@ -83,7 +83,11 @@
break
. += copytext(message, 1, min_index)
if(copytext(message, min_index, min_index+1) == uppertext(min_char))
. += capitalize(pick(map[min_char]))
switch(text2ascii(message, min_index+1))
if(65 to 90) // A-Z, uppercase; uppercase R/S followed by another uppercase letter, uppercase the entire replacement string
. += uppertext(pick(map[min_char]))
else
. += capitalize(pick(map[min_char]))
else
. += pick(map[min_char])
message = copytext(message, min_index + 1)

View File

@@ -4,6 +4,7 @@
adult_form = /mob/living/carbon/human
speak_emote = list("chirrups")
icon_state = "nymph"
item_state = "nymph"
language = "Rootspeak"
death_msg = "expires with a pitiful chirrup..."
universal_understand = 1

View File

@@ -318,9 +318,7 @@
H.germ_level = 0
update_icons() //apply the now updated overlays to the mob
//Throwing stuff
/mob/proc/throw_item(atom/target)
return

View File

@@ -215,6 +215,7 @@
msg += "<span class='warning'>[T.He] [T.is] on fire!.</span>\n"
msg += "<span class='warning'>"
/*
if(nutrition < 100)
msg += "[T.He] [T.is] severely malnourished.\n"
else if(nutrition >= 500)
@@ -222,6 +223,7 @@
msg += "[T.He] [T.is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else*/
msg += "[T.He] [T.is] quite chubby.\n"
*/
msg += "</span>"

View File

@@ -1018,8 +1018,14 @@
verbs += /mob/living/carbon/human/proc/bloody_doodle
return 1 //we applied blood to the item
/mob/living/carbon/human/proc/get_full_print()
if(!dna ||!dna.uni_identity)
return
return md5(dna.uni_identity)
/mob/living/carbon/human/clean_blood(var/clean_feet)
.=..()
gunshot_residue = null
if(clean_feet && !shoes && istype(feet_blood_DNA, /list) && feet_blood_DNA.len)
feet_blood_color = null
qdel(feet_blood_DNA)
@@ -1282,11 +1288,10 @@
if(C.body_parts_covered & FEET)
feet_exposed = 0
flavor_text = flavor_texts["general"]
flavor_text += "\n\n"
flavor_text = ""
for (var/T in flavor_texts)
if(flavor_texts[T] && flavor_texts[T] != "")
if((T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
if((T == "general") || (T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
flavor_text += flavor_texts[T]
flavor_text += "\n\n"
if(!shrink)
@@ -1408,3 +1413,13 @@
get_scooped(H)
return
return ..()
/mob/living/carbon/human/verb/pull_punches()
set name = "Pull Punches"
set desc = "Try not to hurt them."
set category = "IC"
if(stat) return
pulling_punches = !pulling_punches
src << "<span class='notice'>You are now [pulling_punches ? "pulling your punches" : "not pulling your punches"].</span>"
return

View File

@@ -1,6 +1,10 @@
/mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone)
for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks)
if(u_attack.is_usable(src, target, hit_zone))
if(pulling_punches)
var/datum/unarmed_attack/soft_variant = u_attack.get_sparring_variant()
if(soft_variant)
return soft_variant
return u_attack
return null
@@ -221,7 +225,7 @@
attack.apply_effects(H, src, armour, rand_damage, hit_zone)
// Finally, apply damage to target
apply_damage(real_damage, BRUTE, affecting, armour, sharp=attack.sharp, edge=attack.edge)
apply_damage(real_damage, (attack.deal_halloss ? HALLOSS : BRUTE), affecting, armour, sharp=attack.sharp, edge=attack.edge)
if(I_DISARM)
M.attack_log += text("\[[time_stamp()]\] <font color='red'>Disarmed [src.name] ([src.ckey])</font>")

View File

@@ -81,6 +81,8 @@
var/hand_blood_color
var/list/flavor_texts = list()
var/gunshot_residue
var/pulling_punches // Are you trying not to hurt your opponent?
mob_bump_flag = HUMAN
mob_push_flags = ~HEAVY

View File

@@ -1,3 +1,5 @@
var/global/list/sparring_attack_cache = list()
//Species unarmed attacks
/datum/unarmed_attack
var/attack_verb = list("attack") // Empty hand hurt intent verb.
@@ -8,10 +10,19 @@
var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent.
var/sharp = 0
var/edge = 0
var/deal_halloss
var/sparring_variant_type = /datum/unarmed_attack/light_strike
var/eye_attack_text
var/eye_attack_text_victim
/datum/unarmed_attack/proc/get_sparring_variant()
if(sparring_variant_type)
if(!sparring_attack_cache[sparring_variant_type])
sparring_attack_cache[sparring_variant_type] = new sparring_variant_type()
return sparring_attack_cache[sparring_variant_type]
/datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone)
if(user.restrained())
return 0
@@ -84,7 +95,7 @@
/datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
var/obj/item/organ/eyes/eyes = target.internal_organs_by_name["eyes"]
eyes.take_damage(rand(3,4), 1)
user.visible_message("<span class='danger'>[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!</span>")
target << "<span class='danger'>You experience[(target.species.flags & NO_PAIN)? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(target.species.flags & NO_PAIN)? "." : "!"]</span>"
@@ -233,4 +244,14 @@
switch(attack_damage)
if(1 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
/datum/unarmed_attack/light_strike
deal_halloss = 3
attack_noun = list("tap","light strike")
attack_verb = list("tapped", "lightly struck")
damage = 2
shredding = 0
damage = 0
sharp = 0
edge = 0

View File

@@ -20,7 +20,7 @@
return
..()
if(handcuffed)
spawn() escape_handcuffs()
else if(legcuffed)
@@ -47,6 +47,11 @@
breakouttime = HC.breakouttime
displaytime = breakouttime / 600 //Minutes
var/mob/living/carbon/human/H = src
if(istype(H) && H.gloves && istype(H.gloves,/obj/item/clothing/gloves/rig))
breakouttime /= 2
displaytime /= 2
visible_message(
"<span class='danger'>\The [src] attempts to remove \the [HC]!</span>",
"<span class='warning'>You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)</span>"

View File

@@ -98,6 +98,9 @@ default behaviour is:
if(!can_move_mob(tmob, 0, 0))
now_pushing = 0
return
if(a_intent == I_HELP || src.restrained())
now_pushing = 0
return
if(istype(tmob, /mob/living/carbon/human) && (FAT in tmob.mutations))
if(prob(40) && !(FAT in src.mutations))
src << "<span class='danger'>You fail to push [tmob]'s fat ass out of the way.</span>"
@@ -601,18 +604,24 @@ default behaviour is:
if(istype(M))
M.drop_from_inventory(H)
M << "<span class='warning'>[H] wriggles out of your grip!</span>"
src << "<span class='warning'>You wriggle out of [M]'s grip!</span>"
else if(istype(H.loc,/obj/item))
src << "<span class='warning'>You struggle free of [H.loc].</span>"
H.forceMove(get_turf(H))
M << "<span class='warning'>\The [H] wriggles out of your grip!</span>"
src << "<span class='warning'>You wriggle out of \the [M]'s grip!</span>"
if(istype(M))
// Update whether or not this mob needs to pass emotes to contents.
for(var/atom/A in M.contents)
if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder))
return
M.status_flags &= ~PASSEMOTES
M.status_flags &= ~PASSEMOTES
else if(istype(H.loc,/obj/item/clothing/accessory/holster))
var/obj/item/clothing/accessory/holster/holster = H.loc
if(holster.holstered == H)
holster.clear_holster()
src << "<span class='warning'>You extricate yourself from \the [holster].</span>"
H.forceMove(get_turf(H))
else if(istype(H.loc,/obj/item))
src << "<span class='warning'>You struggle free of \the [H.loc].</span>"
H.forceMove(get_turf(H))
/mob/living/proc/escape_buckle()
if(buckled)

View File

@@ -665,7 +665,7 @@ var/global/list/robot_modules = list(
no_slip = 1
networks = list(NETWORK_ENGINEERING)
/obj/item/weapon/robot_module/drone/New()
/obj/item/weapon/robot_module/drone/New(var/mob/living/silicon/robot/robot)
src.modules += new /obj/item/weapon/weldingtool(src)
src.modules += new /obj/item/weapon/screwdriver(src)
src.modules += new /obj/item/weapon/wrench(src)
@@ -675,6 +675,11 @@ var/global/list/robot_modules = list(
src.modules += new /obj/item/device/lightreplacer(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/soap(src)
src.modules += new /obj/item/weapon/extinguisher(src)
robot.internals = new/obj/item/weapon/tank/jetpack/carbondioxide(src)
src.modules += robot.internals
src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src)
src.emag.name = "Plasma Cutter"

View File

@@ -8,6 +8,7 @@
response_disarm = "prods"
response_harm = "stomps on"
icon_state = "brainslug"
item_state = "brainslug"
icon_living = "brainslug"
icon_dead = "brainslug_dead"
speed = 5

View File

@@ -3,6 +3,7 @@
name = "cat"
desc = "A domesticated, feline pet. Has a tendency to adopt crewmembers."
icon_state = "cat2"
item_state = "cat2"
icon_living = "cat2"
icon_dead = "cat2_dead"
speak = list("Meow!","Esp!","Purr!","HSSSSS")
@@ -221,6 +222,7 @@
desc = "Her fur has the look and feel of velvet, and her tail quivers occasionally."
gender = FEMALE
icon_state = "cat"
item_state = "cat"
icon_living = "cat"
icon_dead = "cat_dead"
befriend_job = "Chief Medical Officer"
@@ -229,6 +231,7 @@
name = "kitten"
desc = "D'aaawwww"
icon_state = "kitten"
item_state = "kitten"
icon_living = "kitten"
icon_dead = "kitten_dead"
gender = NEUTER
@@ -245,6 +248,7 @@
desc = "That's Bones the cat. He's a laid back, black cat. Meow."
gender = MALE
icon_state = "cat3"
item_state = "cat3"
icon_living = "cat3"
icon_dead = "cat3_dead"
holder_type = /obj/item/weapon/holder/cat/fluff/bones

View File

@@ -3,6 +3,7 @@
real_name = "mouse"
desc = "It's a small rodent."
icon_state = "mouse_gray"
item_state = "mouse_gray"
icon_living = "mouse_gray"
icon_dead = "mouse_gray_dead"
speak = list("Squeek!","SQUEEK!","Squeek?")
@@ -63,6 +64,7 @@
if(!body_color)
body_color = pick( list("brown","gray","white") )
icon_state = "mouse_[body_color]"
item_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
desc = "It's a small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself."

View File

@@ -316,4 +316,6 @@ proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
if(source.data["virus2"])
B.virus2 = virus_copylist(source.data["virus2"])
B.fluorescent = 0
B.invisibility = 0
return B

View File

@@ -262,13 +262,13 @@ var/list/organ_cache = list()
return
switch (severity)
if (1.0)
take_damage(0,20)
take_damage(20)
return
if (2.0)
take_damage(0,7)
take_damage(7)
return
if(3.0)
take_damage(0,3)
take_damage(3)
/obj/item/organ/proc/removed(var/mob/living/user)

View File

@@ -22,6 +22,38 @@
desc = "A white folder."
icon_state = "folder_white"
/obj/item/weapon/folder/blue_captain
desc = "A blue folder with Captain markings."
icon_state = "folder_captain"
/obj/item/weapon/folder/blue_hop
desc = "A blue folder with HoP markings."
icon_state = "folder_hop"
/obj/item/weapon/folder/white_cmo
desc = "A white folder with CMO markings."
icon_state = "folder_cmo"
/obj/item/weapon/folder/white_rd
desc = "A white folder with RD markings."
icon_state = "folder_rd"
/obj/item/weapon/folder/white_rd/New()
//add some memos
var/obj/item/weapon/paper/P = new()
P.name = "Memo RE: proper analysis procedure"
P.info = "<br>We keep test dummies in pens here for a reason"
src.contents += P
update_icon()
/obj/item/weapon/folder/yellow_ce
desc = "A yellow folder with CE markings."
icon_state = "folder_ce"
/obj/item/weapon/folder/red_hos
desc = "A red folder with HoS markings."
icon_state = "folder_hos"
/obj/item/weapon/folder/update_icon()
overlays.Cut()
if(contents.len)
@@ -87,20 +119,20 @@
onclose(usr, "[P.name]")
else if(href_list["rename"])
var/obj/item/weapon/O = locate(href_list["rename"])
if(O && (O.loc == src))
if(istype(O, /obj/item/weapon/paper))
var/obj/item/weapon/paper/to_rename = O
to_rename.rename()
else if(istype(O, /obj/item/weapon/photo))
var/obj/item/weapon/photo/to_rename = O
to_rename.rename()
else if(istype(O, /obj/item/weapon/paper_bundle))
var/obj/item/weapon/paper_bundle/to_rename = O
to_rename.rename()
//Update everything
attack_self(usr)
update_icon()

View File

@@ -871,26 +871,34 @@ obj/structure/cable/proc/cableColor(var/colorC)
update_wclass()
/obj/item/stack/cable_coil/yellow
stacktype = /obj/item/stack/cable_coil
color = COLOR_YELLOW
/obj/item/stack/cable_coil/blue
stacktype = /obj/item/stack/cable_coil
color = COLOR_BLUE
/obj/item/stack/cable_coil/green
stacktype = /obj/item/stack/cable_coil
color = COLOR_LIME
/obj/item/stack/cable_coil/pink
stacktype = /obj/item/stack/cable_coil
color = COLOR_PINK
/obj/item/stack/cable_coil/orange
stacktype = /obj/item/stack/cable_coil
color = COLOR_ORANGE
/obj/item/stack/cable_coil/cyan
stacktype = /obj/item/stack/cable_coil
color = COLOR_CYAN
/obj/item/stack/cable_coil/white
stacktype = /obj/item/stack/cable_coil
color = COLOR_WHITE
/obj/item/stack/cable_coil/random/New()
stacktype = /obj/item/stack/cable_coil
color = pick(COLOR_RED, COLOR_BLUE, COLOR_LIME, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN)
..()

View File

@@ -7,6 +7,8 @@
slot_flags = SLOT_BELT | SLOT_EARS
throwforce = 1
w_class = 1
var/leaves_residue = 1
var/caliber = "" //Which kind of guns it can be loaded into
var/projectile_type //The bullet type to create when New() is called
var/obj/item/projectile/BB = null //The loaded bullet - make it so that the projectiles are created only when needed?

View File

@@ -309,6 +309,14 @@
return !P.launch_from_gun(target, user, src, target_zone, x_offset, y_offset)
//apart of reskins that have two sprites, touching may result in frustration and breaks
/obj/item/weapon/gun/projectile/colt/detective/attack_hand(var/mob/living/user)
if(!unique_reskin && loc == user)
reskin_gun(user)
return
..()
//Suicide handling.
/obj/item/weapon/gun/var/mouthshoot = 0 //To stop people from suiciding twice... >.>
/obj/item/weapon/gun/proc/handle_suicide(mob/living/user)
@@ -389,5 +397,4 @@
return new_mode
/obj/item/weapon/gun/attack_self(mob/user)
switch_firemodes(user)
switch_firemodes(user)

View File

@@ -68,6 +68,16 @@
/obj/item/weapon/gun/projectile/proc/process_chambered()
if (!chambered) return
// Aurora forensics port, gunpowder residue.
if(chambered.leaves_residue)
var/mob/living/carbon/human/H = loc
if(istype(H))
if(!H.gloves)
H.gunshot_residue = chambered.caliber
else
var/obj/item/clothing/G = H.gloves
G.gunshot_residue = chambered.caliber
switch(handle_casings)
if(EJECT_CASINGS) //eject casing onto ground.
chambered.loc = get_turf(src)

View File

@@ -30,7 +30,7 @@
/obj/item/weapon/gun/projectile/automatic/c20r
name = "submachine gun"
desc = "The C-20r is a lightweight and rapid firing SMG, for when you REALLY need someone dead. Uses 12mm rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp."
desc = "The C-20r is a lightweight and rapid firing SMG, for when you REALLY need someone dead. Uses 10mm rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp."
icon_state = "c20r"
item_state = "c20r"
w_class = 3

View File

@@ -1,4 +1,5 @@
/obj/item/weapon/gun/projectile/colt
var/unique_reskin
name = "vintage .45 pistol"
desc = "A cheap Martian knock-off of a Colt M1911. Uses .45 rounds."
magazine_type = /obj/item/ammo_magazine/c45m
@@ -12,6 +13,18 @@
desc = "A Martian recreation of an old Terran pistol. Uses .45 rounds."
magazine_type = /obj/item/ammo_magazine/c45m/rubber
/obj/item/weapon/gun/projectile/colt/detective/update_icon()
if(ammo_magazine)
if(unique_reskin)
icon_state = unique_reskin
else
icon_state = initial(icon_state)
else
if(unique_reskin)
icon_state = "[unique_reskin]-e"
else
icon_state = "[initial(icon_state)]-e"
/obj/item/weapon/gun/projectile/colt/detective/verb/rename_gun()
set name = "Name Gun"
set category = "Object"
@@ -40,9 +53,14 @@
options["NT Mk. 58"] = "secguncomp"
options["NT Mk. 58 Custom"] = "secgundark"
options["Colt M1911"] = "colt"
options["USP"] = "usp"
options["H&K VP"] = "VP78"
options["P08 Luger"] = "p08"
options["P08 Luger, Brown"] = "p08b"
var/choice = input(M,"What do you want to skin the gun to?","Reskin Gun") in options
if(src && choice && !M.stat && in_range(M,src))
icon_state = options[choice]
unique_reskin = options[choice]
M << "Your gun is now skinned as [choice]. Say hello to your new friend."
return 1
@@ -56,6 +74,13 @@
fire_sound = 'sound/weapons/Gunshot_light.ogg'
load_method = MAGAZINE
/obj/item/weapon/gun/projectile/sec/update_icon()
..()
if(ammo_magazine)
icon_state = "secguncomp"
else
icon_state = "secguncomp-e"
/obj/item/weapon/gun/projectile/sec/flash
name = ".45 signal pistol"
magazine_type = /obj/item/ammo_magazine/c45m/flash
@@ -65,6 +90,13 @@
name = "custom .45 Pistol"
icon_state = "secgundark"
/obj/item/weapon/gun/projectile/sec/wood/update_icon()
..()
if(ammo_magazine)
icon_state = "secgundark"
else
icon_state = "secgundark-e"
/obj/item/weapon/gun/projectile/silenced
name = "silenced pistol"
desc = "A small, quiet, easily concealable gun. Uses .45 rounds."

View File

@@ -115,10 +115,3 @@
/datum/reagent/proc/reaction_mob(var/mob/target)
touch_mob(target)
/datum/reagent/woodpulp
name = "Wood Pulp"
id = "woodpulp"
description = "A mass of wood fibers."
reagent_state = LIQUID
color = "#B97A57"

View File

@@ -1969,11 +1969,11 @@
/datum/reagent/ethanol/specialwhiskey // I have no idea what this is and where it comes from
name = "Special Blend Whiskey"
id = "specialwhiskey"
description = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
color = "#664300"
strength = 25
description = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything. The smell of it singes your nostrils."
color = "#523600"
strength = 7
glass_icon_state = "whiskeyglass"
glass_name = "glass of special blend whiskey"
glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything. The smell of it singes your nostrils."
glass_center_of_mass = list("x"=16, "y"=12)

View File

@@ -375,19 +375,27 @@
/datum/reagent/sterilizine
name = "Sterilizine"
id = "sterilizine"
description = "Sterilizes wounds in preparation for surgery."
description = "Sterilizes wounds in preparation for surgery and thoroughly removes blood."
reagent_state = LIQUID
color = "#C8A5DC"
touch_met = 5
/datum/reagent/sterilizine/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
M.germ_level -= min(removed*20, M.germ_level)
for(var/obj/item/I in M.contents)
I.was_bloodied = null
M.was_bloodied = null
/datum/reagent/sterilizine/touch_obj(var/obj/O)
O.germ_level -= min(volume*20, O.germ_level)
O.was_bloodied = null
/datum/reagent/sterilizine/touch_turf(var/turf/T)
T.germ_level -= min(volume*20, T.germ_level)
for(var/obj/item/I in T.contents)
I.was_bloodied = null
for(var/obj/effect/decal/cleanable/blood/B in T)
qdel(B)
/datum/reagent/leporazine
name = "Leporazine"

View File

@@ -278,10 +278,7 @@
touch_met = 50
/datum/reagent/space_cleaner/touch_obj(var/obj/O)
if(istype(O, /obj/effect/decal/cleanable))
qdel(O)
else
O.clean_blood()
O.clean_blood()
/datum/reagent/space_cleaner/touch_turf(var/turf/T)
if(volume >= 1)
@@ -382,3 +379,23 @@
id = "glue"
description = "An extremely powerful bonding agent."
color = "#FFFFCC"
/datum/reagent/woodpulp
name = "Wood Pulp"
id = "woodpulp"
description = "A mass of wood fibers."
reagent_state = LIQUID
color = "#B97A57"
/datum/reagent/luminol
name = "Luminol"
id = "luminol"
description = "A compound that interacts with blood on the molecular level."
reagent_state = LIQUID
color = "#F2F3F4"
/datum/reagent/luminol/touch_obj(var/obj/O)
O.reveal_blood()
/datum/reagent/luminol/touch_mob(var/mob/living/L)
L.reveal_blood()

View File

@@ -2051,30 +2051,10 @@
required_reagents = list("space_up" = 1, "bluecuracao" = 1, "melonliquor" = 1)
result_amount = 3
/* Removed xenoarcheology stuff
datum
chemical_reaction
lithiumsodiumtungstate //LiNa2WO4, not the easiest chem to mix
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
result = "lithiumsodiumtungstate"
required_reagents = list("lithium" = 1, "sodium" = 2, "tungsten" = 1, "oxygen" = 4)
result_amount = 8
/datum/chemical_reaction/luminol
name = "Luminol"
id = "luminol"
result = "luminol"
required_reagents = list("hydrogen" = 2, "carbon" = 2, "ammonia" = 2)
result_amount = 6
density_separated_liquid
name = "Density separated sample"
id = "density_separated_sample"
result = "density_separated_sample"
secondary_results = list("chemical_waste" = 1)
required_reagents = list("ground_rock" = 1, "lithiumsodiumtungstate" = 2)
result_amount = 2
analysis_liquid
name = "Analysis sample"
id = "analysis_sample"
result = "analysis_sample"
secondary_results = list("chemical_waste" = 1)
required_reagents = list("density_separated_sample" = 5)
result_amount = 4
requires_heating = 1
*/

View File

@@ -121,7 +121,7 @@
recharge_time = 3
volume = 60
possible_transfer_amounts = list(5, 10, 20, 30)
reagent_ids = list("beer", "kahlua", "whiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac", "ale", "mead", "water", "sugar", "ice", "tea", "icetea", "cola", "spacemountainwind", "dr_gibb", "space_up", "tonic", "sodawater", "lemon_lime", "orangejuice", "limejuice", "watermelonjuice")
reagent_ids = list("beer", "kahlua", "whiskey", "specialwhiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac", "ale", "mead", "water", "sugar", "ice", "tea", "icetea", "cola", "spacemountainwind", "dr_gibb", "space_up", "tonic", "sodawater", "lemon_lime", "orangejuice", "limejuice", "watermelonjuice")
/obj/item/weapon/reagent_containers/borghypo/service/attack(var/mob/M, var/mob/user)
return

View File

@@ -231,6 +231,15 @@
..()
reagents.add_reagent("whiskey", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey
name = "Special Blend Whiskey"
desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
icon_state = "whiskeybottle2"
center_of_mass = list("x"=16, "y"=3)
New()
..()
reagents.add_reagent("specialwhiskey", 100)
/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka
name = "Tunguska Triple Distilled"
desc = "Aah, vodka. Prime choice of drink AND fuel by Russians worldwide."

View File

@@ -914,7 +914,7 @@
/obj/item/weapon/reagent_containers/food/snacks/pie/throw_impact(atom/hit_atom)
..()
new/obj/effect/decal/cleanable/pie_smudge(src.loc)
src.visible_message("\red [src.name] splats.","\red You hear a splat.")
src.visible_message("<span class='danger'>\The [src.name] splats.</span>","<span class='danger'>You hear a splat.</span>")
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis

View File

@@ -221,20 +221,31 @@
flags = OPENCONTAINER
unacidable = 0
attackby(var/obj/D, mob/user as mob)
if(isprox(D))
user << "You add [D] to [src]."
qdel(D)
user.put_in_hands(new /obj/item/weapon/bucket_sensor)
user.drop_from_inventory(src)
qdel(src)
/obj/item/weapon/reagent_containers/glass/bucket/attackby(var/obj/D, mob/user as mob)
update_icon()
overlays.Cut()
if(isprox(D))
user << "You add [D] to [src]."
qdel(D)
user.put_in_hands(new /obj/item/weapon/bucket_sensor)
user.drop_from_inventory(src)
qdel(src)
return
else if(istype(D, /obj/item/weapon/mop))
if(reagents.total_volume < 1)
user << "<span class='warning'>\The [src] is empty!</span>"
else
reagents.trans_to_obj(D, 5)
user << "<span class='notice'>You wet \the [D] in \the [src].</span>"
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
return
else
return ..()
if (!is_open_container())
var/image/lid = image(icon, src, "lid_[initial(icon_state)]")
overlays += lid
/obj/item/weapon/reagent_containers/glass/bucket/update_icon()
overlays.Cut()
if (!is_open_container())
var/image/lid = image(icon, src, "lid_[initial(icon_state)]")
overlays += lid
/*
/obj/item/weapon/reagent_containers/glass/blender_jug

View File

@@ -55,7 +55,7 @@
/obj/item/weapon/reagent_containers/spray/proc/Spray_at(atom/A as mob|obj, mob/user as mob, proximity)
if (A.density && proximity)
A.visible_message("[usr] sprays [A] with [src].")
A.visible_message("[usr] sprays [A] with [src].")
reagents.splash(A, amount_per_transfer_from_this)
else
spawn(0)
@@ -107,6 +107,14 @@
..()
reagents.add_reagent("cleaner", volume)
/obj/item/weapon/reagent_containers/spray/sterilizine
name = "sterilizine"
desc = "Great for hiding incriminating bloodstains and sterilizing scalpels."
/obj/item/weapon/reagent_containers/spray/sterilizine/New()
..()
reagents.add_reagent("sterilizine", volume)
/obj/item/weapon/reagent_containers/spray/pepper
name = "pepperspray"
desc = "Manufactured by UhangInc, used to blind and down an opponent quickly."
@@ -161,12 +169,12 @@
volume = 600
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
/obj/item/weapon/reagent_containers/spray/chemsprayer/Spray_at(atom/A as mob|obj)
/obj/item/weapon/reagent_containers/spray/chemsprayer/Spray_at(atom/A as mob|obj)
var/direction = get_dir(src, A)
var/turf/T = get_turf(A)
var/turf/T1 = get_step(T,turn(direction, 90))
var/turf/T2 = get_step(T,turn(direction, -90))
var/list/the_targets = list(T, T1, T2)
var/turf/T2 = get_step(T,turn(direction, -90))
var/list/the_targets = list(T, T1, T2)
for(var/a = 1 to 3)
spawn(0)