mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-01-30 19:03:05 +00:00
Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 12/14/2015_communicators_v2
This commit is contained in:
@@ -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."
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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!")
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
0
code/modules/detectivework/footprints.dm
Normal file
0
code/modules/detectivework/footprints.dm
Normal 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
|
||||
|
||||
153
code/modules/detectivework/microscope/dnascanner.dm
Normal file
153
code/modules/detectivework/microscope/dnascanner.dm
Normal 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"
|
||||
116
code/modules/detectivework/microscope/microscope.dm
Normal file
116
code/modules/detectivework/microscope/microscope.dm
Normal 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"
|
||||
42
code/modules/detectivework/microscope/slides.dm
Normal file
42
code/modules/detectivework/microscope/slides.dm
Normal 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"
|
||||
@@ -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'> [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>"
|
||||
@@ -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()
|
||||
17
code/modules/detectivework/tools/crimekit.dm
Normal file
17
code/modules/detectivework/tools/crimekit.dm
Normal 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)
|
||||
@@ -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"
|
||||
13
code/modules/detectivework/tools/luminol.dm
Normal file
13
code/modules/detectivework/tools/luminol.dm
Normal 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)
|
||||
@@ -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)
|
||||
158
code/modules/detectivework/tools/sample_kits.dm
Normal file
158
code/modules/detectivework/tools/sample_kits.dm
Normal 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)
|
||||
45
code/modules/detectivework/tools/storage.dm
Normal file
45
code/modules/detectivework/tools/storage.dm
Normal 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)
|
||||
120
code/modules/detectivework/tools/swabs.dm
Normal file
120
code/modules/detectivework/tools/swabs.dm
Normal 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
|
||||
69
code/modules/detectivework/tools/uvlight.dm
Normal file
69
code/modules/detectivework/tools/uvlight.dm
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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>"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user