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

This commit is contained in:
Neerti
2015-12-14 15:44:38 -05:00
197 changed files with 14437 additions and 43205 deletions
+22 -22
View File
@@ -1,13 +1,9 @@
/*
Making Bombs with ZAS:
Make burny fire with lots of burning
Draw off 5000K gas from burny fire
Separate gas into oxygen and phoron components
Obtain phoron and oxygen tanks filled up about 50-75% with normal-temp gas
Fill rest with super hot gas from separated canisters, they should be about 125C now.
Attach to transfer valve and open. BOOM.
Get gas to react in an air tank so that it gains pressure. If it gains enough pressure, it goes boom.
The more pressure, the more boom.
If it gains pressure too slowly, it may leak or just rupture instead of exploding.
*/
//#define FIREDBG
@@ -268,16 +264,16 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//determine how far the reaction can progress
var/reaction_limit = min(total_oxidizers*(FIRE_REACTION_FUEL_AMOUNT/FIRE_REACTION_OXIDIZER_AMOUNT), total_fuel) //stoichiometric limit
//calculate the firelevel.
var/firelevel = calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
var/firelevel_ratio = firelevel / vsc.fire_firelevel_multiplier
//vapour fuels are extremely volatile! The reaction progress is a percentage of the total fuel (similar to old zburn).)
var/gas_firelevel = calculate_firelevel(gas_fuel, total_oxidizers, reaction_limit, volume*group_multiplier) / vsc.fire_firelevel_multiplier
var/min_burn = 0.30*volume*group_multiplier/CELL_VOLUME //in moles - so that fires with very small gas concentrations burn out fast
var/gas_reaction_progress = min(max(min_burn, firelevel_ratio*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel)
var/gas_reaction_progress = min(max(min_burn, gas_firelevel*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel)
//liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning. Limit the burn rate to a certain amount per area.
var/liquid_reaction_progress = min((firelevel_ratio*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel)
var/liquid_firelevel = calculate_firelevel(liquid_fuel, total_oxidizers, reaction_limit, 0) / vsc.fire_firelevel_multiplier
var/liquid_reaction_progress = min((liquid_firelevel*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel)
var/firelevel = (gas_fuel*gas_firelevel + liquid_fuel*liquid_firelevel)/total_fuel
var/total_reaction_progress = gas_reaction_progress + liquid_reaction_progress
var/used_fuel = min(total_reaction_progress, reaction_limit)
@@ -286,7 +282,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
#ifdef FIREDBG
log_debug("gas_fuel = [gas_fuel], liquid_fuel = [liquid_fuel], total_oxidizers = [total_oxidizers]")
log_debug("fuel_area = [fuel_area], total_fuel = [total_fuel], reaction_limit = [reaction_limit]")
log_debug("firelevel -> [firelevel] / [vsc.fire_firelevel_multiplier]")
log_debug("firelevel -> [firelevel] (gas: [gas_firelevel], liquid: [liquid_firelevel])")
log_debug("liquid_reaction_progress = [liquid_reaction_progress]")
log_debug("gas_reaction_progress = [gas_reaction_progress]")
log_debug("total_reaction_progress = [total_reaction_progress]")
@@ -315,13 +311,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * (used_gas_fuel + used_liquid_fuel)) / heat_capacity()
update_values()
#ifdef FIREDBG
log_debug("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_fuel]")
log_debug("new temperature = [temperature]")
log_debug("new temperature = [temperature]; new pressure = [return_pressure()]")
#endif
update_values()
return firelevel
datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
@@ -363,27 +359,31 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
break
//returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit, gas_volume)
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
var/firelevel = 0
var/total_combustables = (total_fuel + total_oxidizers)
var/active_combustables = (FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT + 1)*reaction_limit
if(total_combustables > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = min(1, reaction_limit / (total_moles/group_multiplier))
var/damping_multiplier = min(1, active_combustables / (total_moles/group_multiplier))
//weight the damping mult so that it only really brings down the firelevel when the ratio is closer to 0
damping_multiplier = 2*damping_multiplier - (damping_multiplier*damping_multiplier)
//calculates how close the mixture of the reactants is to the optimum
//fires burn better when there is more oxidizer -- too much fuel will choke them out a bit, reducing firelevel.
//fires burn better when there is more oxidizer -- too much fuel will choke the fire out a bit, reducing firelevel.
var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2)))
#ifdef FIREDBG
ASSERT(dampening_multiplier <= 1)
ASSERT(damping_multiplier <= 1)
ASSERT(mix_multiplier <= 1)
#endif
//toss everything together -- should produce a value between 0 and fire_firelevel_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * damping_multiplier
return max( 0, firelevel)
+2 -1
View File
@@ -9,7 +9,8 @@ var/global/vs_control/vsc = new
var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant"
var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires."
var/fire_fuel_energy_release = 397000
//Note that this parameter and the phoron heat capacity have a significant impact on TTV yield.
var/fire_fuel_energy_release = 866000 //J/mol. Adjusted to compensate for fire energy release being fixed, was 397000
var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
+3 -3
View File
@@ -59,15 +59,15 @@
//These control the speed at which fire burns
#define FIRE_GAS_BURNRATE_MULT 1
#define FIRE_LIQUID_BURNRATE_MULT 1
#define FIRE_LIQUID_BURNRATE_MULT 0.225
//If the fire is burning slower than this rate then the reaction is going too slow to be self sustaining and the fire burns itself out.
//This ensures that fires don't grind to a near-halt while still remaining active forever.
#define FIRE_GAS_MIN_BURNRATE 0.01
#define FIRE_LIQUD_MIN_BURNRATE 0.01
#define FIRE_LIQUD_MIN_BURNRATE 0.0025
//How many moles of fuel are contained within one solid/liquid fuel volume unit
#define LIQUIDFUEL_AMOUNT_TO_MOL 1 //mol/volume unit
#define LIQUIDFUEL_AMOUNT_TO_MOL 0.45 //mol/volume unit
// XGM gas flags.
#define XGM_GAS_FUEL 1
+18 -18
View File
@@ -63,24 +63,24 @@
#define LIFE_HUD 10 // STATUS_HUD that only reports dead or alive
//some colors
#define COLOR_WHITE "#FFFFFF"
#define COLOR_SILVER "#C0C0C0"
#define COLOR_GRAY "#808080"
#define COLOR_BLACK "#000000"
#define COLOR_RED "#FF0000"
#define COLOR_MAROON "#800000"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_OLIVE "#808000"
#define COLOR_LIME "#00FF00"
#define COLOR_GREEN "#008000"
#define COLOR_CYAN "#00FFFF"
#define COLOR_TEAL "#008080"
#define COLOR_BLUE "#0000FF"
#define COLOR_NAVY "#000080"
#define COLOR_PINK "#FF00FF"
#define COLOR_PURPLE "#800080"
#define COLOR_ORANGE "#FF9900"
#define COLOR_WHITE "#FFFFFF"
#define COLOR_SILVER "#C0C0C0"
#define COLOR_GRAY "#808080"
#define COLOR_BLACK "#000000"
#define COLOR_RED "#FF0000"
#define COLOR_MAROON "#800000"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_OLIVE "#808000"
#define COLOR_LIME "#00FF00"
#define COLOR_GREEN "#008000"
#define COLOR_CYAN "#00FFFF"
#define COLOR_TEAL "#008080"
#define COLOR_BLUE "#0000FF"
#define COLOR_NAVY "#000080"
#define COLOR_PINK "#FF00FF"
#define COLOR_PURPLE "#800080"
#define COLOR_ORANGE "#FF9900"
#define COLOR_LUMINOL "#66FFFF"
// Shuttles.
// These define the time taken for the shuttle to get to the space station, and the time before it leaves again.
+9 -4
View File
@@ -46,8 +46,12 @@ var/global/list/facial_hair_styles_male_list = list()
var/global/list/facial_hair_styles_female_list = list()
var/global/list/skin_styles_female_list = list() //unused
//Underwear
var/global/list/underwear_m = list("White" = "m1", "Grey" = "m2", "Green" = "m3", "Blue" = "m4", "Black" = "m5", "Mankini" = "m6", "None") //Curse whoever made male/female underwear diffrent colours
var/global/list/underwear_f = list("Red" = "f1", "White" = "f2", "Yellow" = "f3", "Blue" = "f4", "Black" = "f5", "Thong" = "f6", "Black Sports" = "f7","White Sports" = "f8","None")
var/global/list/underwear_m = list(
"White" = "m1", "Grey" = "m2", "Green" = "m3", "Blue" = "m4", "Black" = "m5", "Mankini" = "m6",
"Boxers Heart" = "m7", "Boxers Black" = "m8", "Boxers Grey" = "m9", "Boxers Stripe" = "m10", "None") //Curse whoever made male/female underwear diffrent colours
var/global/list/underwear_f = list(
"Red" = "f1", "White" = "f2", "Yellow" = "f3", "Blue" = "f4", "Black" = "f5", "Thong" = "f6",
"Black Sports" = "f7","White Sports" = "f8", "Black Sports Alt" = "f9", "White Sports Alt" = "f10", "Baby Blue" = "f11", "Green" = "f12", "Pink" = "f13", "None")
//undershirt
var/global/list/undershirt_t = list(
"White tank top" = "u1", "Black tank top" = "u2", "Black shirt" = "u3",
@@ -60,14 +64,15 @@ var/global/list/undershirt_t = list(
"Grey-yellow polo shirt" = "grayyellowpolo_s", "Fire tank top" = "tank_fire_s", "NT shirt" = "shirt_nano_s",
"Blue shirt 2" = "shirt_blue_s", "Red shirt 2" = "shirt_red_s", "Red tank top" = "tank_red_s", "Green shirt 2" = "shirt_green_s",
"Tiedye shirt" = "shirt_tiedye_s", "Green sport shirt" = "greenshirtsport_s", "Red sport shirt" = "redshirtsport_s",
"Blue sport shirt" = "blueshirtsport_s", "None")
"Blue striped shirt" = "shirt_stripes_s", "Blue sport shirt" = "blueshirtsport_s", "None")
//Socks
var/global/list/socks_t = list(
"White normal" = "white_norm", "White short" = "white_short", "White knee" = "white_knee",
"White thigh" = "white_thigh", "Black normal" = "black_norm", "Black short" = "black_short",
"Black knee" = "black_knee", "Black thigh" = "black_thigh", "Thin knee" = "thin_knee",
"Thin thigh" = "thin_thigh", "Pantyhose" = "pantyhose", "Striped thigh" = "striped_thigh",
"Striped knee" = "striped_knee", "Rainbow knee" = "rainbow_knee", "Rainbow thigh" = "rainbow_thigh", "None")
"Striped knee" = "striped_knee", "Rainbow knee" = "rainbow_knee", "Rainbow thigh" = "rainbow_thigh",
"Fishnets" = "fishnet", "Thin white thigh" = "thinwhite_thigh", "Thin white knee" = "thinwhite_knee", "None")
//Backpacks
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt")
+8
View File
@@ -172,6 +172,8 @@ var/list/gamemode_cache = list()
var/enter_allowed = 1
var/use_irc_bot = 0
var/use_node_bot = 0
var/irc_bot_port = 0
var/irc_bot_host = ""
var/irc_bot_export = 0 // whether the IRC bot in use is a Bot32 (or similar) instance; Bot32 uses world.Export() instead of nudge.py/libnudge
var/main_irc = ""
@@ -545,6 +547,12 @@ var/list/gamemode_cache = list()
if("use_irc_bot")
use_irc_bot = 1
if("use_node_bot")
use_node_bot = 1
if("irc_bot_port")
config.irc_bot_port = value
if("irc_bot_export")
irc_bot_export = 1
@@ -48,7 +48,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
if (evac)
emergency_shuttle_docked.Announce("The Emergency Shuttle has docked with the station at docks one and two. You have approximately [round(estimate_launch_time()/60,1)] minutes to board the Emergency Shuttle.")
else
priority_announcement.Announce("The scheduled Crew Transfer Shuttle has docked with the station at docks one and two. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.")
priority_announcement.Announce("The scheduled shuttle to the Vir Regional Spaceport has docked with the station at docks one and two. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.")
//arm the escape pods
if (evac)
@@ -94,7 +94,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
//reset the shuttle transit time if we need to
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
priority_announcement.Announce("A crew transfer has been scheduled. The shuttle has been called. It will arrive at docks one and two in approximately [round(estimate_arrival_time()/60)] minutes.")
priority_announcement.Announce("The regularly scheduled shuttle to the Vir Regional Spaceport will arrive in in approximately [round(estimate_arrival_time()/60)] minutes. Those leaving should proceed to docks one and two.")
//recalls the shuttle
/datum/emergency_shuttle_controller/proc/recall()
+5 -6
View File
@@ -54,6 +54,7 @@
var/datum/changeling/changeling //changeling holder
var/rev_cooldown = 0
var/tcrystals = 0
// the world.time since the mob has been brigged, or -1 if not at all
var/brigged_since = -1
@@ -375,14 +376,12 @@
memory = null//Remove any memory they may have had.
if("crystals")
if (usr.client.holder.rights & R_FUN)
var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink()
// var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() No longer needed, uses stored in mind
var/crystals
if (suplink)
crystals = suplink.uses
crystals = input("Amount of telecrystals for [key]","Operative uplink", crystals) as null|num
crystals = tcrystals
crystals = input("Amount of telecrystals for [key]", crystals) as null|num
if (!isnull(crystals))
if (suplink)
suplink.uses = crystals
tcrystals = crystals
else if (href_list["obj_announce"])
var/obj_count = 1
+18 -4
View File
@@ -43,6 +43,20 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
group = "Security"
hidden = 1
/datum/supply_packs/forensics
name = "Auxiliary forensic tools"
contains = list(/obj/item/weapon/forensics/sample_kit,
/obj/item/weapon/forensics/sample_kit/powder,
/obj/item/weapon/storage/box/swabs,
/obj/item/weapon/storage/box/swabs,
/obj/item/weapon/storage/box/swabs,
/obj/item/weapon/storage/box/slides,
/obj/item/weapon/reagent_containers/spray/luminol)
cost = 30
containertype = /obj/structure/closet/crate
containername = "Auxiliary forensic tools"
group = "Security"
/datum/supply_packs/food
name = "Kitchen supply crate"
contains = list(/obj/item/weapon/reagent_containers/food/condiment/flour,
@@ -124,6 +138,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/reagent_containers/food/drinks/flask/barflask,
/obj/item/weapon/reagent_containers/food/drinks/bottle/patron,
/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager,
/obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey,
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,
/obj/item/weapon/lipstick/random,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale,
@@ -1550,8 +1565,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
num_contained = 4
contains = list(/obj/item/clothing/accessory/storage/black_vest,
/obj/item/clothing/accessory/storage/brown_vest,
/obj/item/clothing/accessory/storage/webbing,
/obj/item/clothing/accessory/storage)
/obj/item/clothing/accessory/storage/webbing)
cost = 15
containertype = "/obj/structure/closet/crate"
containername = "Webbing crate"
@@ -1628,8 +1642,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/detectivegear
name = "Forensic investigation equipment"
contains = list(/obj/item/device/detective_scanner,
/obj/item/weapon/storage/box/evidence,
contains = list(/obj/item/weapon/storage/box/evidence,
/obj/item/weapon/storage/box/evidence,
/obj/item/clothing/suit/storage/vest/detective,
/obj/item/weapon/cartridge/detective,
@@ -1639,6 +1652,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/device/camera,
/obj/item/weapon/folder/red,
/obj/item/weapon/folder/blue,
/obj/item/weapon/storage/belt/detective,
/obj/item/clothing/gloves/black,
/obj/item/device/taperecorder,
/obj/item/device/mass_spectrometer,
+1 -1
View File
@@ -41,7 +41,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
(A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
((A.lights && haspower) ? "The door bolt lights are on." : "The door bolt lights are off!"),
((haspower) ? "The test light is on." : "The test light is off!"),
((A.backupPowerCablesCut()) ? "The backup power light is off!" : "The backup power light is on."),
((A.backup_power_lost_until) ? "The backup power light is off!" : "The backup power light is on."),
((A.aiControlDisabled==0 && !A.emagged && haspower)? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
((A.safe==0 && haspower)? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
((A.normalspeed==0 && haspower)? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
+3
View File
@@ -21,6 +21,9 @@
/decl/xgm_gas/phoron
id = "phoron"
name = "Phoron"
//Note that this has a significant impact on TTV yield.
//Because it is so high, any leftover phoron soaks up a lot of heat and drops the yield pressure.
specific_heat = 200 // J/(mol*K)
//Hypothetical group 14 (same as carbon), period 8 element.
+1 -1
View File
@@ -32,7 +32,7 @@
if(!antag_indicator || !other.current || !recipient.current)
return
var/indicator = (faction_indicator && (other in faction_members)) ? faction_indicator : antag_indicator
return image('icons/mob/mob.dmi', loc = other.current, icon_state = indicator)
return image('icons/mob/mob.dmi', loc = other.current, icon_state = indicator, layer = LIGHTING_LAYER+0.1)
/datum/antagonist/proc/update_all_icons()
if(!antag_indicator)
@@ -43,6 +43,7 @@ var/datum/antagonist/mercenary/mercs
if(player.backbag == 4) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(player.back), slot_in_backpack)
player.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(player), slot_in_backpack)
player.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
if (player.mind == leader)
var/obj/item/device/radio/uplink/U = new(player.loc, player.mind, 40)
+1
View File
@@ -81,6 +81,7 @@ var/datum/antagonist/traitor/traitors
return 0
spawn_uplink(traitor_mob)
traitor_mob.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
// Tell them about people they might want to contact.
var/mob/living/carbon/human/M = get_nt_opposed()
if(M && M != traitor_mob)
+1
View File
@@ -105,6 +105,7 @@ var/list/ghostteleportlocs = list()
power_equip = 0
power_environ = 0
ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg')
base_turf = /turf/space
area/space/atmosalert()
return
+8 -3
View File
@@ -6,12 +6,14 @@
var/list/fingerprintshidden
var/fingerprintslast = null
var/list/blood_DNA
var/was_bloodied
var/blood_color
var/last_bumped = 0
var/pass_flags = 0
var/throwpass = 0
var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom.
var/simulated = 1 //filter for actions - used by lighting overlays
var/fluorescent // Shows up under a UV light.
///Chemistry.
var/datum/reagents/reagents = null
@@ -23,6 +25,9 @@
//Detective Work, used for the duplicate data points kept in the scanners
var/list/original_atom
/atom/proc/reveal_blood()
return
/atom/proc/assume_air(datum/gas_mixture/giver)
return null
@@ -304,7 +309,7 @@ its easier to just keep the beam vertical.
fingerprints = list()
//Hash this shit.
var/full_print = md5(H.dna.uni_identity)
var/full_print = H.get_full_print()
// Add the fingerprints
//
@@ -387,6 +392,7 @@ its easier to just keep the beam vertical.
if(!blood_DNA || !istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it.
blood_DNA = list()
was_bloodied = 1
blood_color = "#A10808"
if(istype(M))
if (!istype(M.dna, /datum/dna))
@@ -406,16 +412,15 @@ its easier to just keep the beam vertical.
if(toxvomit)
this.icon_state = "vomittox_[pick(1,4)]"
/atom/proc/clean_blood()
if(!simulated)
return
fluorescent = 0
src.germ_level = 0
if(istype(blood_DNA, /list))
blood_DNA = null
return 1
/atom/proc/get_global_map_pos()
if(!islist(global_map) || isemptylist(global_map)) return
var/cur_x = null
+1
View File
@@ -13,6 +13,7 @@
var/throw_range = 7
var/moved_recently = 0
var/mob/pulledby = null
var/item_state = null // Used to specify the item state for the on-mob overlays.
var/auto_init = 1
@@ -219,14 +219,12 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
//Run at the start of a round
/proc/Holiday_Game_Start()
world << Holiday
if(Holiday.len != 0)
var/list/holidays = list()
var/list/holiday_blurbs = list()
for(var/p in Holiday)
holidays.Add(p)
holiday_blurbs.Add("[Holiday[p]]")
world << "[p] = [Holiday[p]]"
var/holidays_string = english_list(holidays, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
world << "<font color='blue'>and...</font>"
world << "<h4>Happy [holidays_string] Everybody!</h4>"
+2 -2
View File
@@ -111,12 +111,11 @@
H.equip_to_slot_or_del(new /obj/item/weapon/flame/lighter/zippo(H), slot_l_store)
if(H.backbag == 1)//Why cant some of these things spawn in his office?
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand)
H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store)
else
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack)
if(H.mind.role_alt_title && H.mind.role_alt_title == "Forensic Technician")
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/forensics/blue(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase/crimekit, slot_r_hand)
else
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_trench(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/head/det(H), slot_head)
@@ -149,6 +148,7 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/security(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_s_store)
H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store)
if(H.backbag == 1)
-2
View File
@@ -413,5 +413,3 @@
path = /obj/item/weapon/handcuffs
hidden = 1
category = "General"
-2
View File
@@ -15,6 +15,4 @@
return src.attack_hand(user)
/obj/machinery/button/attackby(obj/item/weapon/W, mob/user as mob)
if(istype(W, /obj/item/device/detective_scanner))
return
return src.attack_hand(user)
+1 -1
View File
@@ -141,7 +141,6 @@
assembly.camera_network = english_list(network, NETWORK_EXODUS, ",", ",")
assembly.update_icon()
assembly.dir = src.dir
assembly = null //so qdel doesn't eat it.
if(stat & BROKEN)
assembly.state = 2
user << "<span class='notice'>You repaired \the [src] frame.</span>"
@@ -149,6 +148,7 @@
assembly.state = 1
user << "<span class='notice'>You cut \the [src] free from the wall.</span>"
new /obj/item/stack/cable_coil(src.loc, length=2)
assembly = null //so qdel doesn't eat it.
qdel(src)
// OTHER
-16
View File
@@ -24,22 +24,6 @@
user << "Error, no route to host."
/obj/machinery/button/remote/attackby(obj/item/weapon/W, mob/user as mob)
/* For later implementation
if (istype(W, /obj/item/weapon/screwdriver))
{
if(wiresexposed)
icon_state = "doorctrl0"
wiresexposed = 0
else
icon_state = "doorctrl-open"
wiresexposed = 1
return
}
*/
if(istype(W, /obj/item/device/detective_scanner))
return
return src.attack_hand(user)
/obj/machinery/button/remote/emag_act(var/remaining_charges, var/mob/user)
+5 -4
View File
@@ -10,7 +10,7 @@
var/electrified_until = 0 //World time when the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
var/main_power_lost_until = 0 //World time when main power is restored.
var/backup_power_lost_until = -1 //World time when backup power is restored.
var/next_beep_at = 0 //World time when we may next beep due to doors being blocked by mobs
var/has_beeped = 0 //If 1, will not beep on failed closing attempt. Resets when door closes.
var/spawnPowerRestoreRunning = 0
var/welded = null
var/locked = 0
@@ -750,7 +750,7 @@ About the new airlock wires panel:
if(src.isElectrified())
if(src.shock(user, 75))
return
if(istype(C, /obj/item/device/detective_scanner) || istype(C, /obj/item/taperoll))
if(istype(C, /obj/item/taperoll))
return
src.add_fingerprint(user)
@@ -958,9 +958,9 @@ About the new airlock wires panel:
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
if(AM.blocks_airlock())
if(world.time > next_beep_at)
if(!has_beeped)
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
next_beep_at = world.time + SecondsToTicks(10)
has_beeped = 1
close_door_at = world.time + 6
return
@@ -970,6 +970,7 @@ About the new airlock wires panel:
take_damage(DOOR_CRUSH_DAMAGE)
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
has_beeped = 0
if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1)
else
-2
View File
@@ -202,8 +202,6 @@
..()
/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I, /obj/item/device/detective_scanner))
return
src.add_fingerprint(user)
if(istype(I, /obj/item/stack/material) && I.get_material_name() == src.get_material_name())
-2
View File
@@ -72,8 +72,6 @@
// src.sd_SetLuminosity(0)
/obj/machinery/sparker/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/detective_scanner))
return
if (istype(W, /obj/item/weapon/screwdriver))
add_fingerprint(user)
src.disable = !src.disable
+13 -8
View File
@@ -549,9 +549,8 @@
nanomanager.update_uis(src)
/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
if(src.panel_open)
user << "<span class='notice'>You insert \the [src] in the product receptor.</span>"
R.amount++
user << "<span class='notice'>You insert \the [src] in the product receptor.</span>"
R.amount++
nanomanager.update_uis(src)
@@ -687,7 +686,8 @@
/obj/item/weapon/reagent_containers/food/drinks/flask/barflask = 2, /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask = 2,
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30,/obj/item/weapon/reagent_containers/food/drinks/ice = 9,
/obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao = 2,
/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine = 5)
/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey = 4)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/tea = 10)
vend_delay = 15
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
@@ -725,11 +725,11 @@
icon_state = "snack"
products = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 6,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 6,/obj/item/weapon/reagent_containers/food/snacks/chips =6,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 6,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 6)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 3)
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 6, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 3)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6)
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2)
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 4)
@@ -781,7 +781,12 @@
/obj/item/weapon/storage/fancy/cigarettes/carcinomas = 5,
/obj/item/weapon/storage/fancy/cigarettes/professionals = 5,
/obj/item/weapon/storage/fancy/cigarettes/killthroat = 5)
prices = list(/obj/item/weapon/storage/fancy/cigarettes = 15,/obj/item/weapon/storage/box/matches = 1,/obj/item/weapon/flame/lighter/random = 2)
prices = list(/obj/item/weapon/storage/fancy/cigarettes = 15,
/obj/item/weapon/storage/fancy/cigarettes/luckystars = 17,
/obj/item/weapon/storage/fancy/cigarettes/jerichos = 22,
/obj/item/weapon/storage/fancy/cigarettes/menthols = 18,
/obj/item/weapon/storage/box/matches = 1,
/obj/item/weapon/flame/lighter/random = 2)
/obj/machinery/vending/medical
@@ -22,6 +22,20 @@ var/global/list/image/splatter_cache=list()
var/amount = 5
var/drytime
/obj/effect/decal/cleanable/blood/reveal_blood()
if(!fluorescent)
fluorescent = 1
basecolor = COLOR_LUMINOL
update_icon()
/obj/effect/decal/cleanable/blood/clean_blood()
fluorescent = 0
if(invisibility != 100)
invisibility = 100
amount = 0
processing_objects -= src
..(ignore=1)
/obj/effect/decal/cleanable/blood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
@@ -29,6 +29,13 @@ var/global/list/image/fluidtrack_cache=list()
src.basecolor=_color
src.wet=_wet
/obj/effect/decal/cleanable/blood/tracks/reveal_blood()
if(!fluorescent)
if(stack && stack.len)
for(var/datum/fluidtrack/track in stack)
track.basecolor = COLOR_LUMINOL
..()
// Footprints, tire trails...
/obj/effect/decal/cleanable/blood/tracks
amount = 0
@@ -114,7 +121,8 @@ var/global/list/image/fluidtrack_cache=list()
updated=1
dirs |= comingdir|realgoing
blood_DNA |= DNA.Copy()
if(islist(blood_DNA))
blood_DNA |= DNA.Copy()
if(updated)
update_icon()
@@ -1,6 +1,12 @@
/obj/effect/decal/cleanable
var/list/random_icon_states = list()
/obj/effect/decal/cleanable/clean_blood(var/ignore = 0)
if(!ignore)
qdel(src)
return
..()
/obj/effect/decal/cleanable/New()
if (random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
+4
View File
@@ -26,6 +26,10 @@
latejoin_gateway += loc
qdel(src)
return
if("JoinLateElevator")
latejoin_elevator += loc
qdel(src)
return
if("JoinLateCryo")
latejoin_cryo += loc
qdel(src)
@@ -105,27 +105,61 @@
qdel(src)
*/
/client/proc/spawn_tanktransferbomb()
set category = "Debug"
set desc = "Spawn a tank transfer valve bomb"
set name = "Instant TTV"
if(!check_rights(R_SPAWN)) return
var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom
var/p = input("Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt)) as num|null
if(p == null) return
var/o = input("Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt)) as num|null
if(o == null) return
var/c = input("Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt)) as num|null
if(c == null) return
new /obj/effect/spawner/newbomb/radio/custom(get_turf(mob), p, o, c)
/obj/effect/spawner/newbomb
name = "bomb"
name = "TTV bomb"
icon = 'icons/mob/screen1.dmi'
icon_state = "x"
var/btype = 0 // 0=radio, 1=prox, 2=time
var/assembly_type = /obj/item/device/assembly/signaler
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
var/phoron_amt = 10.96
var/oxygen_amt = 16.44
var/carbon_amt = 0.0
timer
btype = 2
/obj/effect/spawner/newbomb/timer
name = "TTV bomb - timer"
assembly_type = /obj/item/device/assembly/timer
syndicate
/obj/effect/spawner/newbomb/timer/syndicate
name = "TTV bomb - merc"
//High yield bombs. Yes, it is possible to make these with toxins
phoron_amt = 15.66
oxygen_amt = 24.66
proximity
btype = 1
/obj/effect/spawner/newbomb/proximity
name = "TTV bomb - proximity"
assembly_type = /obj/item/device/assembly/prox_sensor
radio
btype = 0
/obj/effect/spawner/newbomb/New()
/obj/effect/spawner/newbomb/radio/custom/New(var/newloc, ph, ox, co)
if(ph != null) phoron_amt = ph
if(ox != null) oxygen_amt = ox
if(co != null) carbon_amt = co
..()
/obj/effect/spawner/newbomb/New(newloc)
..(newloc)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/phoron/PT = new(V)
var/obj/item/weapon/tank/oxygen/OT = new(V)
@@ -137,28 +171,15 @@
OT.master = V
PT.air_contents.temperature = PHORON_FLASHPOINT
PT.air_contents.adjust_multi("phoron", 12, "carbon_dioxide", 8)
PT.air_contents.gas["phoron"] = phoron_amt
PT.air_contents.gas["carbon_dioxide"] = carbon_amt
PT.air_contents.update_values()
OT.air_contents.temperature = PHORON_FLASHPOINT
OT.air_contents.adjust_gas("oxygen", 20)
OT.air_contents.gas["oxygen"] = oxygen_amt
OT.air_contents.update_values()
var/obj/item/device/assembly/S
switch (src.btype)
// radio
if (0)
S = new/obj/item/device/assembly/signaler(V)
// proximity
if (1)
S = new/obj/item/device/assembly/prox_sensor(V)
// timer
if (2)
S = new/obj/item/device/assembly/timer(V)
var/obj/item/device/assembly/S = new assembly_type(V)
V.attached_device = S
+10 -5
View File
@@ -29,9 +29,9 @@
//It should be used purely for appearance. For gameplay effects caused by items covering body parts, use body_parts_covered.
var/flags_inv = 0
var/body_parts_covered = 0 //see setup.dm for appropriate bit flags
var/item_flags = 0 //Miscellaneous flags pertaining to equippable objects.
//var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible
var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets)
var/permeability_coefficient = 1 // for chemicals/diseases
@@ -45,7 +45,6 @@
var/zoom = 0 //1 if item is actively being used to zoom. For scoped guns and binoculars.
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
var/item_state = null // Used to specify the item state for the on-mob overlays.
//** These specify item/icon overrides for _slots_
@@ -494,6 +493,12 @@ var/list/global/slot_flags_enumeration = list(
var/obj/item/clothing/gloves/G = src
G.transfer_blood = 0
/obj/item/reveal_blood()
if(was_bloodied && !fluorescent)
fluorescent = 1
blood_color = COLOR_LUMINOL
blood_overlay.color = COLOR_LUMINOL
update_icon()
/obj/item/add_blood(mob/living/carbon/human/M as mob)
if (!..())
@@ -608,10 +613,10 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].")
return
/obj/item/proc/pwr_drain()
return 0 // Process Kill
/obj/item/proc/resolve_attackby(atom/A, mob/source)
return A.attackby(src,source)
@@ -272,6 +272,13 @@
item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_cargo/alt
name = "supply bowman headset"
desc = "A bowman headset used by the QM and his slaves."
icon_state = "cargo_headset_alt"
item_state = "cargo_headset_alt"
ks2type = /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_service
name = "service radio headset"
desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean."
@@ -100,17 +100,9 @@
if (src.loc != usr)
return 0
if(tank_one && href_list["tankone"])
split_gases()
valve_open = 0
tank_one.loc = get_turf(src)
tank_one = null
update_icon()
remove_tank(tank_one)
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = 0
tank_two.loc = get_turf(src)
tank_two = null
update_icon()
remove_tank(tank_two)
else if(href_list["open"])
toggle_valve()
else if(attached_device)
@@ -149,20 +141,43 @@
if(attached_device)
overlays += "device"
/obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T)
if(tank_one == T)
split_gases()
tank_one = null
else if(tank_two == T)
split_gases()
tank_two = null
else
return
T.loc = get_turf(src)
update_icon()
/obj/item/device/transfer_valve/proc/merge_gases()
if(valve_open)
return
tank_two.air_contents.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
tank_two.air_contents.merge(temp)
valve_open = 1
/obj/item/device/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
if(!valve_open)
return
valve_open = 0
if(deleted(tank_one) || deleted(tank_two))
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
@@ -170,8 +185,7 @@
*/
/obj/item/device/transfer_valve/proc/toggle_valve()
if(valve_open==0 && (tank_one && tank_two))
valve_open = 1
if(!valve_open && (tank_one && tank_two))
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
@@ -197,16 +211,11 @@
message_admins(log_str, 0, 1)
log_game(log_str)
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
src.update_icon()
sleep(10)
src.update_icon()
else if(valve_open==1 && (tank_one && tank_two))
split_gases()
valve_open = 0
src.update_icon()
src.update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
+2 -1
View File
@@ -27,7 +27,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid
src.uplink_owner = owner
purchase_log = list()
world_uplinks += src
uses = telecrystals
uses = owner.tcrystals
/obj/item/device/uplink/Destroy()
world_uplinks -= src
@@ -87,6 +87,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid
/obj/item/device/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/title = "Remote Uplink"
var/data[0]
uses = user.mind.tcrystals
data["welcome"] = welcome
data["crystals"] = uses
@@ -56,7 +56,7 @@ var/datum/uplink/uplink = new()
return
purchase_log(U)
U.uses -= cost
user.mind.tcrystals -= cost
U.used_TC += cost
return goods
@@ -408,8 +408,8 @@ datum/uplink_item/dd_SortValue()
path = /obj/item/weapon/storage/box/syndie_kit/imp_explosive
/datum/uplink_item/item/implants/imp_uplink
name = "Uplink Implant (Contains 5 Telecrystals)"
item_cost = 10
name = "Uplink Implant" //Original name: "Uplink Implant (Contains 5 Telecrystals)"
item_cost = 5 //Original cost: 10
path = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
/**********
+1
View File
@@ -17,6 +17,7 @@
var/amount = 1
var/max_amount //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount
var/stacktype //determines whether different stack types can merge
var/build_type = null //used when directly applied to a turf
var/uses_charge = 0
var/list/charge_costs = null
var/list/datum/matter_synth/synths = null
@@ -12,7 +12,6 @@
desc = "A non-descript floor tile"
w_class = 3
max_amount = 60
var/build_type = null
/obj/item/stack/tile/New()
..()
+15 -6
View File
@@ -716,7 +716,7 @@
/obj/item/toy/therapy_red
name = "red therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is red."
icon = 'icons/obj/weapons.dmi'
icon = 'icons/obj/toy.dmi'
icon_state = "therapyred"
item_state = "egg4" // It's the red egg in items_left/righthand
w_class = 1
@@ -724,7 +724,7 @@
/obj/item/toy/therapy_purple
name = "purple therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is purple."
icon = 'icons/obj/weapons.dmi'
icon = 'icons/obj/toy.dmi'
icon_state = "therapypurple"
item_state = "egg1" // It's the magenta egg in items_left/righthand
w_class = 1
@@ -732,7 +732,7 @@
/obj/item/toy/therapy_blue
name = "blue therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is blue."
icon = 'icons/obj/weapons.dmi'
icon = 'icons/obj/toy.dmi'
icon_state = "therapyblue"
item_state = "egg2" // It's the blue egg in items_left/righthand
w_class = 1
@@ -740,7 +740,7 @@
/obj/item/toy/therapy_yellow
name = "yellow therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is yellow."
icon = 'icons/obj/weapons.dmi'
icon = 'icons/obj/toy.dmi'
icon_state = "therapyyellow"
item_state = "egg5" // It's the yellow egg in items_left/righthand
w_class = 1
@@ -748,7 +748,7 @@
/obj/item/toy/therapy_orange
name = "orange therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is orange."
icon = 'icons/obj/weapons.dmi'
icon = 'icons/obj/toy.dmi'
icon_state = "therapyorange"
item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless
w_class = 1
@@ -756,7 +756,7 @@
/obj/item/toy/therapy_green
name = "green therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is green."
icon = 'icons/obj/weapons.dmi'
icon = 'icons/obj/toy.dmi'
icon_state = "therapygreen"
item_state = "egg3" // It's the green egg in items_left/righthand
w_class = 1
@@ -886,3 +886,12 @@
item_state = "inflatable"
icon = 'icons/obj/clothing/belts.dmi'
slot_flags = SLOT_BELT
/obj/item/toy/xmastree
name = "Miniature Christmas tree"
desc = "Tiny cute Christmas tree."
icon = 'icons/obj/toy.dmi'
icon_state = "tinyxmastree"
w_class = 1
force = 1
throwforce = 1
@@ -33,7 +33,7 @@ var/list/syndicate_ids = list()
if(istype(O, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/I = O
src.access |= I.access
if(player_is_antag(user))
if(player_is_antag(user.mind))
user << "<span class='notice'>The microscanner activates as you pass it over the ID, copying its access.</span>"
/obj/item/weapon/card/id/syndicate/attack_self(mob/user as mob)
@@ -9,3 +9,16 @@
if(empulse(src, 4, 10))
qdel(src)
return
/obj/item/weapon/grenade/empgrenade/low_yield
name = "low yield emp grenade"
desc = "A weaker variant of the classic emp grenade"
icon_state = "lyemp"
item_state = "lyempgrenade"
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3)
prime()
..()
if(empulse(src, 4, 1))
qdel(src)
return
@@ -1,16 +1,78 @@
//obj/item/weapon/grenade/explosive
//desc = "A fragmentation grenade, optimized for harming personnel without causing massive structural damage."
//name = "frag grenade"
//icon = 'icons/obj/grenade.dmi'
//det_time = 50
//icon_state = "frggrenade"
//item_state = "frggrenade"
//origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 3)
//obj/item/weapon/grenade/explosive/prime()
// ..()
//spawn(0)
//explosion(src.loc,-1,-1,2) //If you're within two tiles of the grenade, you get hit twice, which tends to do 50+ brute and cause fractures.
//explosion(src.loc,-1,-1,3) //This is preferable to increasing the severity, so we don't decap with frags.
//qdel(src)
//return
//Explosive grenade projectile, borrowed from fragmentation grenade code.
/obj/item/projectile/bullet/pellet/fragment
damage = 10
range_step = 2
base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone
spread_step = 20
silenced = 1 //embedding messages are still produced so it's kind of weird when enabled.
no_attack_log = 1
muzzle_type = null
/obj/item/weapon/grenade/explosive
name = "fragmentation grenade"
desc = "A fragmentation grenade, optimized for harming personnel without causing massive structural damage."
name = "frag grenade"
icon = 'icons/obj/grenade.dmi'
det_time = 50
icon_state = "frggrenade"
item_state = "frggrenade"
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 3)
var/num_fragments = 50 //total number of fragments produced by the grenade
var/fragment_damage = 10
var/damage_step = 2 //projectiles lose a fragment each time they travel this distance. Can be a non-integer.
var/explosion_size = 2 //size of the center explosion
//The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
var/spread_range = 7
/obj/item/weapon/grenade/explosive/prime()
..()
spawn(0)
explosion(src.loc,-1,-1,2) //If you're within two tiles of the grenade, you get hit twice, which tends to do 50+ brute and cause fractures.
explosion(src.loc,-1,-1,3) //This is preferable to increasing the severity, so we don't decap with frags.
qdel(src)
return
var/turf/O = get_turf(src)
if(!O) return
if(explosion_size)
explosion(O, -1, -1, 2, round(explosion_size/2), 0)
var/list/target_turfs = getcircle(O, spread_range)
var/fragments_per_projectile = round(num_fragments/target_turfs.len)
for(var/turf/T in target_turfs)
var/obj/item/projectile/bullet/pellet/fragment/P = new (O)
P.damage = fragment_damage
P.pellets = fragments_per_projectile
P.range_step = damage_step
P.shot_from = src.name
P.launch(T)
//var/cone = new /obj/item/weapon/caution/cone (T)
//spawn(100) qdel(cone)
//Make sure to hit any mobs in the source turf
for(var/mob/living/M in O)
//lying on a frag grenade while the grenade is on the ground causes you to absorb most of the shrapnel.
//you will most likely be dead, but others nearby will be spared the fragments that hit you instead.
if(M.lying && isturf(src.loc))
P.attack_mob(M, 0, 0)
else
P.attack_mob(M, 0, 100) //otherwise, allow a decent amount of fragments to pass
qdel(src)
+18 -7
View File
@@ -12,6 +12,7 @@
throw_range = 5
origin_tech = list(TECH_MATERIAL = 1)
matter = list(DEFAULT_WALL_MATERIAL = 500)
var/elastic
var/dispenser = 0
var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
@@ -53,20 +54,20 @@
var/mob/living/carbon/human/H = target
if(!istype(H))
return
return 0
if (!H.has_organ_for_slot(slot_handcuffed))
user << "<span class='danger'>\The [H] needs at least two wrists before you can cuff them together!</span>"
return
return 0
if(istype(H.gloves,/obj/item/clothing/gloves/rig)) // Can't cuff someone who's in a deployed hardsuit.
user << "<span class='danger'>The cuffs won't fit around \the [H.gloves]!</span>"
return
if(istype(H.gloves,/obj/item/clothing/gloves/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
user << "<span class='danger'>\The [src] won't fit around \the [H.gloves]!</span>"
return 0
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
if(!do_after(user,30))
return
return 0
H.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been handcuffed (attempt) by [user.name] ([user.ckey])</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Attempted to handcuff [H.name] ([H.ckey])</font>")
@@ -84,7 +85,7 @@
cuffs.loc = target
target.handcuffed = cuffs
target.update_inv_handcuffed()
return
return 1
var/last_chew = 0
/mob/living/carbon/human/RestrainedClickOn(var/atom/A)
@@ -118,6 +119,7 @@ var/last_chew = 0
breakouttime = 300 //Deciseconds = 30s
cuff_sound = 'sound/weapons/cablecuff.ogg'
cuff_type = "cable restraints"
elastic = 1
/obj/item/weapon/handcuffs/cable/red
color = "#DD0000"
@@ -156,3 +158,12 @@ var/last_chew = 0
/obj/item/weapon/handcuffs/cyborg
dispenser = 1
/obj/item/weapon/handcuffs/cable/tape
name = "tape restraints"
desc = "DIY!"
icon_state = "tape_cross"
item_state = null
icon = 'icons/obj/bureaucracy.dmi'
breakouttime = 200
cuff_type = "duct tape"
@@ -6,7 +6,8 @@
/obj/item/weapon/implant/uplink/New()
activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
hidden_uplink = new(src)
hidden_uplink.uses = 5
//hidden_uplink.uses = 5
//Code currently uses a mind var for telecrystals, balancing is currently an issue. Will investigate.
..()
return
@@ -10,6 +10,7 @@
default_material = "wood"
force_divisor = 1.1 // 22 when wielded with weight 20 (steel)
unwielded_force_divisor = 0.7 // 15 when unwielded based on above.
slot_flags = SLOT_BACK
//Predefined materials go here.
/obj/item/weapon/material/twohanded/baseballbat/metal/New(var/newloc)
@@ -75,6 +75,17 @@
icon_state = "knife"
force_divisor = 0.1 // 6 when wielded with hardness 60 (steel)
// Identical to the tactical knife but nowhere near as stabby.
// Kind of like the toy esword compared to the real thing.
/obj/item/weapon/material/kitchen/utensil/knife/boot
name = "boot knife"
desc = "A small fixed-blade knife for putting inside a boot."
icon = 'icons/obj/weapons.dmi'
icon_state = "tacknife"
item_state = "knife"
applies_material_colour = 0
unbreakable = 1
/obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "<span class='warning'>You accidentally cut yourself with the [src].</span>"
+178 -54
View File
@@ -18,8 +18,22 @@ var/list/tape_roll_applications = list()
anchored = 1
var/lifted = 0
var/crumpled = 0
var/tape_dir = 0
var/icon_base
/obj/item/tape/update_icon()
//Possible directional bitflags: 0 (AIRLOCK), 1 (NORTH), 2 (SOUTH), 4 (EAST), 8 (WEST), 3 (VERTICAL), 12 (HORIZONTAL)
switch (tape_dir)
if(0) // AIRLOCK
icon_state = "[icon_base]_door_[crumpled]"
if(3) // VERTICAL
icon_state = "[icon_base]_v_[crumpled]"
if(12) // HORIZONTAL
icon_state = "[icon_base]_h_[crumpled]"
else // END POINT (1|2|4|8)
icon_state = "[icon_base]_dir_[crumpled]"
dir = tape_dir
/obj/item/tape/New()
..()
if(!hazard_overlays)
@@ -32,7 +46,7 @@ var/list/tape_roll_applications = list()
/obj/item/taperoll/police
name = "police tape"
desc = "A roll of police tape used to block off crime scenes from the public."
icon_state = "police_start"
icon_state = "police"
tape_type = /obj/item/tape/police
icon_base = "police"
@@ -45,7 +59,7 @@ var/list/tape_roll_applications = list()
/obj/item/taperoll/engineering
name = "engineering tape"
desc = "A roll of engineering tape used to block off working areas from the public."
icon_state = "engineering_start"
icon_state = "engineering"
tape_type = /obj/item/tape/engineering
icon_base = "engineering"
@@ -55,58 +69,150 @@ var/list/tape_roll_applications = list()
req_one_access = list(access_engine,access_atmospherics)
icon_base = "engineering"
/obj/item/taperoll/atmos
name = "atmospherics tape"
desc = "A roll of atmospherics tape used to block off working areas from the public."
icon_state = "atmos"
tape_type = /obj/item/tape/atmos
icon_base = "atmos"
/obj/item/tape/atmos
name = "atmospherics tape"
desc = "A length of atmospherics tape. Better not cross it."
req_one_access = list(access_engine,access_atmospherics)
icon_base = "atmos"
/obj/item/taperoll/update_icon()
overlays.Cut()
if(ismob(loc))
if(!start)
overlays += "start"
else
overlays += "stop"
/obj/item/taperoll/dropped(mob/user)
update_icon()
return ..()
/obj/item/taperoll/pickup(mob/user)
update_icon()
return ..()
/obj/item/taperoll/attack_hand()
update_icon()
return ..()
/obj/item/taperoll/attack_self(mob/user as mob)
if(icon_state == "[icon_base]_start")
if(!start)
start = get_turf(src)
usr << "<span class='notice'>You place the first end of \the [src].</span>"
icon_state = "[icon_base]_stop"
update_icon()
else
icon_state = "[icon_base]_start"
end = get_turf(src)
if(start.y != end.y && start.x != end.x || start.z != end.z)
start = null
update_icon()
usr << "<span class='notice'>\The [src] can only be laid horizontally or vertically.</span>"
return
if(start == end)
// spread tape in all directions, provided there is a wall/window
var/turf/T
var/possible_dirs = 0
for(var/dir in cardinal)
T = get_step(start, dir)
if(T && T.density)
possible_dirs += dir
else
for(var/obj/structure/window/W in T)
if(W.is_fulltile() || W.dir == reverse_dir[dir])
possible_dirs += dir
if(!possible_dirs)
start = null
update_icon()
usr << "<span class='notice'>You can't place \the [src] here.</span>"
return
if(possible_dirs & (NORTH|SOUTH))
var/obj/item/tape/TP = new tape_type(start)
for(var/dir in list(NORTH, SOUTH))
if (possible_dirs & dir)
TP.tape_dir += dir
TP.update_icon()
if(possible_dirs & (EAST|WEST))
var/obj/item/tape/TP = new tape_type(start)
for(var/dir in list(EAST, WEST))
if (possible_dirs & dir)
TP.tape_dir += dir
TP.update_icon()
start = null
update_icon()
usr << "<span class='notice'>You finish placing \the [src].</span>"
return
var/turf/cur = start
var/dir
if (start.x == end.x)
var/d = end.y-start.y
if(d) d = d/abs(d)
end = get_turf(locate(end.x,end.y+d,end.z))
dir = "v"
else
var/d = end.x-start.x
if(d) d = d/abs(d)
end = get_turf(locate(end.x+d,end.y,end.z))
dir = "h"
var/orientation = get_dir(start, end)
var/dir = 0
switch(orientation)
if(NORTH, SOUTH) dir = NORTH|SOUTH // North-South taping
if(EAST, WEST) dir = EAST|WEST // East-West taping
var/can_place = 1
while (cur!=end && can_place)
while (can_place)
if(cur.density == 1)
can_place = 0
else if (istype(cur, /turf/space))
can_place = 0
else
for(var/obj/O in cur)
if(!istype(O, /obj/item/tape) && O.density)
if(O.density)
can_place = 0
break
if(cur == end)
break
cur = get_step_towards(cur,end)
if (!can_place)
start = null
update_icon()
usr << "<span class='warning'>You can't run \the [src] through that!</span>"
return
cur = start
var/tapetest = 0
while (cur!=end)
for(var/obj/item/tape/Ptest in cur)
if(Ptest.icon_state == "[Ptest.icon_base]_[dir]")
var/tapetest
var/tape_dir
while (1)
tapetest = 0
tape_dir = dir
if(cur == start)
var/turf/T = get_step(start, reverse_dir[orientation])
if(T && !T.density)
tape_dir = orientation
for(var/obj/structure/window/W in T)
if(W.is_fulltile() || W.dir == orientation)
tape_dir = dir
else if(cur == end)
var/turf/T = get_step(end, orientation)
if(T && !T.density)
tape_dir = reverse_dir[orientation]
for(var/obj/structure/window/W in T)
if(W.is_fulltile() || W.dir == reverse_dir[orientation])
tape_dir = dir
for(var/obj/item/tape/T in cur)
if((T.tape_dir == tape_dir) && (T.icon_base == icon_base))
tapetest = 1
if(tapetest != 1)
var/obj/item/tape/P = new tape_type(cur)
P.icon_state = "[P.icon_base]_[dir]"
break
if(!tapetest)
var/obj/item/tape/T = new tape_type(cur)
T.tape_dir = tape_dir
T.update_icon()
if(tape_dir & SOUTH)
T.layer += 0.1 // Must always show above other tapes
if(cur == end)
break
cur = get_step_towards(cur,end)
start = null
update_icon()
usr << "<span class='notice'>You finish placing \the [src].</span>"
return
/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob, proximity)
if(!proximity)
@@ -116,7 +222,7 @@ var/list/tape_roll_applications = list()
var/turf/T = get_turf(A)
var/obj/item/tape/P = new tape_type(T.x,T.y,T.z)
P.loc = locate(T.x,T.y,T.z)
P.icon_state = "[src.icon_base]_door"
P.update_icon()
P.layer = 3.2
user << "<span class='notice'>You finish placing \the [src].</span>"
@@ -140,7 +246,7 @@ var/list/tape_roll_applications = list()
/obj/item/tape/proc/crumple()
if(!crumpled)
crumpled = 1
icon_state = "[icon_state]_c"
update_icon()
name = "crumpled [name]"
/obj/item/tape/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
@@ -149,6 +255,8 @@ var/list/tape_roll_applications = list()
add_fingerprint(M)
if (!allowed(M)) //only select few learn art of not crumpling the tape
M << "<span class='warning'>You are not supposed to go past [src]...</span>"
if(M.a_intent == I_HELP)
return 0
crumple()
return ..(mover)
@@ -158,13 +266,45 @@ var/list/tape_roll_applications = list()
/obj/item/tape/attack_hand(mob/user as mob)
if (user.a_intent == I_HELP && src.allowed(user))
user.show_viewers("<span class='notice'>\The [user] lifts \the [src], allowing passage.</span>")
crumple()
lifted = 1
spawn(200)
lifted = 0
for(var/obj/item/tape/T in gettapeline())
T.lift(100) //~10 seconds
else
breaktape(null, user)
/obj/item/tape/proc/lift(time)
lifted = 1
layer = 8
spawn(time)
lifted = 0
layer = initial(layer)
// Returns a list of all tape objects connected to src, including itself.
/obj/item/tape/proc/gettapeline()
var/list/dirs = list()
if(tape_dir & NORTH)
dirs += NORTH
if(tape_dir & SOUTH)
dirs += SOUTH
if(tape_dir & WEST)
dirs += WEST
if(tape_dir & EAST)
dirs += EAST
var/list/obj/item/tape/tapeline = list()
for (var/obj/item/tape/T in get_turf(src))
tapeline += T
for(var/dir in dirs)
var/turf/cur = get_step(src, dir)
var/not_found = 0
while (!not_found)
not_found = 1
for (var/obj/item/tape/T in cur)
tapeline += T
not_found = 0
cur = get_step(cur, dir)
return tapeline
/obj/item/tape/proc/breaktape(obj/item/weapon/W as obj, mob/user as mob)
@@ -173,27 +313,11 @@ var/list/tape_roll_applications = list()
return
user.show_viewers("<span class='notice'>\The [user] breaks \the [src]!</span>")
var/dir[2]
var/icon_dir = src.icon_state
if(icon_dir == "[src.icon_base]_h")
dir[1] = EAST
dir[2] = WEST
if(icon_dir == "[src.icon_base]_v")
dir[1] = NORTH
dir[2] = SOUTH
for(var/i=1;i<3;i++)
var/N = 0
var/turf/cur = get_step(src,dir[i])
while(N != 1)
N = 1
for (var/obj/item/tape/P in cur)
if(P.icon_state == icon_dir)
N = 0
qdel(P)
cur = get_step(cur,dir[i])
qdel(src)
return
for (var/obj/item/tape/T in gettapeline())
if(T == src)
continue
if(T.tape_dir & get_dir(T, src))
qdel(T)
qdel(src) //TODO: Dropping a trash item holding fibers/fingerprints of all broken tape parts
return
@@ -148,8 +148,8 @@
icon_state = "duffle"
item_state = "duffle"
slowdown = 1
max_storage_space = 56
storage_slots = 20
max_storage_space = 38
storage_slots = 12
/obj/item/weapon/storage/backpack/dufflebag/syndie
name = "suspicious looking dufflebag"
@@ -139,6 +139,37 @@
/obj/item/weapon/gun/projectile/colt/detective
)
/obj/item/weapon/storage/belt/detective
name = "forensic utility belt"
desc = "A belt for holding forensics equipment."
icon_state = "securitybelt"
item_state = "security"
storage_slots = 7
max_w_class = 3
can_hold = list(
/obj/item/device/taperecorder,
/obj/item/clothing/glasses,
/obj/item/device/flashlight,
/obj/item/weapon/reagent_containers/spray/luminol,
/obj/item/weapon/sample,
/obj/item/weapon/forensics/sample_kit/powder,
/obj/item/weapon/forensics/swab,
/obj/item/device/uv_light,
/obj/item/weapon/forensics/slide,
/obj/item/weapon/forensics/sample_kit,
/obj/item/weapon/photo,
/obj/item/device/camera_film,
/obj/item/device/camera,
/obj/item/weapon/autopsy_scanner,
/obj/item/device/mass_spectrometer,
/obj/item/device/reagent_scanner,
/obj/item/weapon/reagent_containers/dropper,
/obj/item/weapon/reagent_containers/syringe,
/obj/item/device/pda,
/obj/item/device/radio/headset,
/obj/item/taperoll/police
)
/obj/item/weapon/storage/belt/soulstone
name = "soul stone belt"
desc = "Designed for ease of access to the shards during a fight, as to not let a single enemy spirit slip away"
@@ -298,6 +298,19 @@
new /obj/item/weapon/grenade/empgrenade(src)
new /obj/item/weapon/grenade/empgrenade(src)
/obj/item/weapon/storage/box/empslite
name = "box of low yield emp grenades"
desc = "A box containing 5 low yield EMP grenades.<br> WARNING: Do not use near unshielded electronics or biomechanical augmentations, death or permanent paralysis may occur."
icon_state = "emp"
New()
..()
new /obj/item/weapon/grenade/empgrenade/low_yield(src)
new /obj/item/weapon/grenade/empgrenade/low_yield(src)
new /obj/item/weapon/grenade/empgrenade/low_yield(src)
new /obj/item/weapon/grenade/empgrenade/low_yield(src)
new /obj/item/weapon/grenade/empgrenade/low_yield(src)
/obj/item/weapon/storage/box/smokes
name = "box of smoke bombs"
desc = "A box containing 5 smoke bombs."
@@ -327,7 +340,7 @@
/obj/item/weapon/storage/box/frags
name = "box of fragmentation grenades (WARNING)"
desc = "A box containing 7 military grade fragmentation grenades.<br> WARNING: These devices are extremely dangerous and can cause limb loss or death in repeated use."
desc = "A box containing 5 military grade fragmentation grenades.<br> WARNING: These devices are extremely dangerous and can cause limb loss or death in repeated use."
icon_state = "frag"
@@ -338,8 +351,7 @@
new /obj/item/weapon/grenade/explosive(src)
new /obj/item/weapon/grenade/explosive(src)
new /obj/item/weapon/grenade/explosive(src)
new /obj/item/weapon/grenade/explosive(src)
new /obj/item/weapon/grenade/explosive(src)
/obj/item/weapon/storage/box/trackimp
name = "boxed tracking implant kit"
desc = "Box full of scum-bag tracking utensils."
@@ -135,7 +135,7 @@
throwforce = 2
slot_flags = SLOT_BELT
storage_slots = 6
can_hold = list(/obj/item/clothing/mask/smokable/cigarette)
can_hold = list(/obj/item/clothing/mask/smokable/cigarette, /obj/item/weapon/flame/lighter)
icon_type = "cigarette"
/obj/item/weapon/storage/fancy/cigarettes/New()
@@ -4,6 +4,7 @@
name = "jetpack (empty)"
desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution."
icon_state = "jetpack"
gauge_icon = null
w_class = 4.0
item_state = "jetpack"
distribute_pressure = ONE_ATMOSPHERE*O2STANDARD
@@ -85,6 +85,7 @@
name = "phoron tank"
desc = "Contains dangerous phoron. Do not inhale. Warning: extremely flammable."
icon_state = "phoron"
gauge_icon = null
flags = CONDUCT
slot_flags = null //they have no straps!
@@ -114,6 +115,8 @@
name = "emergency oxygen tank"
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
icon_state = "emergency"
gauge_icon = "indicator_emergency"
gauge_cap = 4
flags = CONDUCT
slot_flags = SLOT_BELT
w_class = 2.0
@@ -142,12 +145,15 @@
/obj/item/weapon/tank/emergency_oxygen/double
name = "double emergency oxygen tank"
icon_state = "emergency_double"
gauge_icon = "indicator_emergency_double"
volume = 10
/obj/item/weapon/tank/emergency_nitrogen
name = "emergency nitrogen tank"
desc = "An emergency air tank hastily painted red and issued to Vox crewmembers."
icon_state = "emergency_nitro"
gauge_icon = "indicator_emergency"
gauge_cap = 4
flags = CONDUCT
slot_flags = SLOT_BELT
w_class = 2.0
+41 -3
View File
@@ -1,9 +1,17 @@
#define TANK_MAX_RELEASE_PRESSURE (3*ONE_ATMOSPHERE)
#define TANK_DEFAULT_RELEASE_PRESSURE 24
#define TANK_IDEAL_PRESSURE 1015 //Arbitrary.
var/list/global/tank_gauge_cache = list()
/obj/item/weapon/tank
name = "tank"
icon = 'icons/obj/tank.dmi'
var/gauge_icon = "indicator_tank"
var/last_gauge_pressure
var/gauge_cap = 6
flags = CONDUCT
slot_flags = SLOT_BACK
w_class = 3
@@ -31,8 +39,8 @@
src.air_contents = new /datum/gas_mixture()
src.air_contents.volume = volume //liters
src.air_contents.temperature = T20C
processing_objects.Add(src)
update_gauge()
return
/obj/item/weapon/tank/Destroy()
@@ -41,6 +49,10 @@
processing_objects.Remove(src)
if(istype(loc, /obj/item/device/transfer_valve))
var/obj/item/device/transfer_valve/TTV = loc
TTV.remove_tank(src)
..()
/obj/item/weapon/tank/examine(mob/user)
@@ -216,8 +228,28 @@
/obj/item/weapon/tank/process()
//Allow for reactions
air_contents.react() //cooking up air tanks - add phoron and oxygen, then heat above PHORON_MINIMUM_BURN_TEMPERATURE
if(gauge_icon)
update_gauge()
check_status()
/obj/item/weapon/tank/proc/update_gauge()
var/gauge_pressure = 0
if(air_contents)
gauge_pressure = air_contents.return_pressure()
if(gauge_pressure > TANK_IDEAL_PRESSURE)
gauge_pressure = -1
else
gauge_pressure = round((gauge_pressure/TANK_IDEAL_PRESSURE)*gauge_cap)
if(gauge_pressure == last_gauge_pressure)
return
last_gauge_pressure = gauge_pressure
overlays.Cut()
var/indicator = "[gauge_icon][(gauge_pressure == -1) ? "overload" : gauge_pressure]"
if(!tank_gauge_cache[indicator])
tank_gauge_cache[indicator] = image(icon, indicator)
overlays += tank_gauge_cache[indicator]
/obj/item/weapon/tank/proc/check_status()
//Handle exploding, leaking, and rupturing of the tank
@@ -249,7 +281,10 @@
qdel(src)
else if(pressure > TANK_RUPTURE_PRESSURE)
//world << "<span class='notice'>[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]</span>"
#ifdef FIREDBG
log_debug("\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]")
#endif
if(integrity <= 0)
var/turf/simulated/T = get_turf(src)
if(!T)
@@ -261,7 +296,10 @@
integrity--
else if(pressure > TANK_LEAK_PRESSURE)
//world << "<span class='notice'>[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]</span>"
#ifdef FIREDBG
log_debug("\blue[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]")
#endif
if(integrity <= 0)
var/turf/simulated/T = get_turf(src)
if(!T)
+63 -9
View File
@@ -5,18 +5,71 @@
icon_state = "taperoll"
w_class = 1
/* -- Disabled for now until it has a use --
/obj/item/weapon/tape_roll/attack_self(mob/user as mob)
user << "You remove a length of tape from [src]."
var/obj/item/weapon/ducttape/tape = new()
user.put_in_hands(tape)
*/
/obj/item/weapon/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user)
if(istype(H))
if(user.zone_sel.selecting == "eyes")
if(!H.organs_by_name["head"])
user << "<span class='warning'>\The [H] doesn't have a head.</span>"
return
if(!H.has_eyes())
user << "<span class='warning'>\The [H] doesn't have any eyes.</span>"
return
if(H.glasses)
user << "<span class='warning'>\The [H] is already wearing somethign on their eyes.</span>"
return
if(H.head && (H.head.body_parts_covered & FACE))
user << "<span class='warning'>Remove their [H.head] first.</span>"
return
user.visible_message("<span class='danger'>\The [user] begins taping over \the [H]'s eyes!</span>")
if(!do_after(user, 30))
return
// Repeat failure checks.
if(!H || !src || !H.organs_by_name["head"] || !H.has_eyes() || H.glasses || (H.head && (H.head.body_parts_covered & FACE)))
return
user.visible_message("<span class='danger'>\The [user] has taped up \the [H]'s eyes!</span>")
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/blindfold/tape(H), slot_glasses)
else if(user.zone_sel.selecting == "mouth" || user.zone_sel.selecting == "head")
if(!H.organs_by_name["head"])
user << "<span class='warning'>\The [H] doesn't have a head.</span>"
return
if(!H.check_has_mouth())
user << "<span class='warning'>\The [H] doesn't have a mouth.</span>"
return
if(H.wear_mask)
user << "<span class='warning'>\The [H] is already wearing a mask.</span>"
return
if(H.head && (H.head.body_parts_covered & FACE))
user << "<span class='warning'>Remove their [H.head] first.</span>"
return
user.visible_message("<span class='danger'>\The [user] begins taping up \the [H]'s mouth!</span>")
if(!do_after(user, 30))
return
// Repeat failure checks.
if(!H || !src || !H.organs_by_name["head"] || !H.check_has_mouth() || H.wear_mask || (H.head && (H.head.body_parts_covered & FACE)))
return
user.visible_message("<span class='danger'>\The [user] has taped up \the [H]'s mouth!</span>")
H.equip_to_slot_or_del(new /obj/item/clothing/mask/muzzle/tape(H), slot_wear_mask)
else if(user.zone_sel.selecting == "r_hand" || user.zone_sel.selecting == "l_hand")
var/obj/item/weapon/handcuffs/cable/tape/T = new(user)
if(!T.place_handcuffs(H, user))
user.unEquip(T)
qdel(T)
else
return ..()
return 1
/obj/item/weapon/tape_roll/proc/stick(var/obj/item/weapon/W, mob/user)
if(!istype(W, /obj/item/weapon/paper))
return
user.drop_from_inventory(W)
var/obj/item/weapon/ducttape/tape = new(get_turf(src))
tape.attach(W)
@@ -52,7 +105,7 @@
return
user << "You remove \the [initial(name)] from [stuck]."
user.drop_from_inventory(src)
stuck.forceMove(get_turf(src))
user.put_in_hands(stuck)
@@ -61,6 +114,7 @@
qdel(src)
/obj/item/weapon/ducttape/afterattack(var/A, mob/user, flag, params)
if(!in_range(user, A) || istype(A, /obj/machinery/door) || !stuck)
return
+1
View File
@@ -116,6 +116,7 @@
/obj/attack_ghost(mob/user)
ui_interact(user)
..()
/obj/proc/interact(mob/user)
return
@@ -10,6 +10,12 @@
New()
..()
if(prob(75))
new /obj/item/weapon/storage/backpack(src)
else
new /obj/item/weapon/storage/backpack/satchel_norm(src)
if(prob(25))
new /obj/item/weapon/storage/backpack/dufflebag(src)
new /obj/item/clothing/under/rank/cargotech(src)
new /obj/item/clothing/under/rank/cargotech/skirt(src)
new /obj/item/clothing/under/rank/cargotech/jeans(src)
@@ -17,6 +23,7 @@
new /obj/item/clothing/suit/storage/hooded/wintercoat/cargo(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/device/radio/headset/headset_cargo(src)
new /obj/item/device/radio/headset/headset_cargo/alt(src)
new /obj/item/clothing/gloves/black(src)
new /obj/item/clothing/head/soft(src)
// new /obj/item/weapon/cartridge/quartermaster(src)
@@ -34,12 +41,19 @@
New()
..()
if(prob(75))
new /obj/item/weapon/storage/backpack(src)
else
new /obj/item/weapon/storage/backpack/satchel_norm(src)
if(prob(25))
new /obj/item/weapon/storage/backpack/dufflebag(src)
new /obj/item/clothing/under/rank/cargo(src)
new /obj/item/clothing/under/rank/cargo/skirt(src)
new /obj/item/clothing/under/rank/cargo/jeans(src)
new /obj/item/clothing/under/rank/cargo/jeans/female(src)
new /obj/item/clothing/shoes/brown(src)
new /obj/item/device/radio/headset/headset_cargo(src)
new /obj/item/device/radio/headset/headset_cargo/alt(src)
new /obj/item/clothing/gloves/black(src)
// new /obj/item/weapon/cartridge/quartermaster(src)
new /obj/item/clothing/suit/fire/firefighter(src)
@@ -160,6 +160,6 @@
new /obj/item/clothing/suit/storage/hazardvest(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/weapon/cartridge/atmos(src)
new /obj/item/taperoll/engineering(src)
new /obj/item/taperoll/atmos(src)
new /obj/item/clothing/suit/storage/hooded/wintercoat/engineering/atmos(src)
return
@@ -278,10 +278,10 @@
new /obj/item/clothing/head/det(src)
new /obj/item/clothing/head/det/grey(src)
new /obj/item/clothing/shoes/laceup(src)
new /obj/item/weapon/storage/belt/detective(src)
new /obj/item/weapon/storage/box/evidence(src)
new /obj/item/device/radio/headset/headset_sec(src)
new /obj/item/device/radio/headset/headset_sec/alt(src)
new /obj/item/device/detective_scanner(src)
new /obj/item/clothing/suit/storage/vest/detective(src)
new /obj/item/ammo_magazine/c45m/rubber(src)
new /obj/item/ammo_magazine/c45m/rubber(src)
@@ -60,8 +60,8 @@
new /obj/item/weapon/pinpointer/nukeop(src)
new /obj/item/weapon/pinpointer/nukeop(src)
new /obj/item/device/pda/syndicate(src)
var/obj/item/device/radio/uplink/U = new(src)
U.hidden_uplink.uses = 40
new /obj/item/device/radio/uplink(src)
//U.hidden_uplink.uses = 40
return
/obj/structure/closet/syndicate/resources/
+2 -2
View File
@@ -20,8 +20,8 @@
/obj/structure/mopbucket/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/mop))
if(reagents.total_volume < 1)
user << "<span class='warning'>[src] is out of water!</span>"
user << "<span class='warning'>\The [src] is out of water!</span>"
else
reagents.trans_to_obj(I, 5)
user << "<span class='notice'>You wet [I] in [src].</span>"
user << "<span class='notice'>You wet \the [I] in \the [src].</span>"
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
+13 -1
View File
@@ -199,4 +199,16 @@
/obj/structure/sign/directions/cargo
name = "\improper Cargo department"
desc = "A direction sign, pointing out which way the Cargo department is."
icon_state = "direction_crg"
icon_state = "direction_crg"
/obj/structure/sign/christmas/lights
name = "Christmas lights"
desc = "Flashy and pretty."
icon = 'icons/obj/christmas.dmi'
icon_state = "xmaslights"
/obj/structure/sign/christmas/wreath
name = "wreath"
desc = "Prickly and festive."
icon = 'icons/obj/christmas.dmi'
icon_state = "doorwreath"
+7 -2
View File
@@ -316,11 +316,11 @@
/obj/machinery/shower/proc/process_heat(mob/living/M)
if(!on || !istype(M)) return
var/temperature = temperature_settings[watertemp]
var/temp_adj = between(BODYTEMP_COOLING_MAX, temperature - M.bodytemperature, BODYTEMP_HEATING_MAX)
M.bodytemperature += temp_adj
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(temperature >= H.species.heat_level_1)
@@ -411,6 +411,11 @@
// Short of a rewrite, this is necessary to stop monkeycubes being washed.
else if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/monkeycube))
return
else if(istype(O, /obj/item/weapon/mop))
O.reagents.add_reagent("water", 5)
user << "<span class='notice'>You wet \the [O] in \the [src].</span>"
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
return
var/turf/location = user.loc
if(!isturf(location)) return
+1 -1
View File
@@ -186,7 +186,7 @@
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
user.do_attack_animation(src)
usr.visible_message("<span class='danger'>[usr.name] bangs against the [src.name]!</span>",
"<<span class='danger'>You bang against the [src.name]!</span>",
"<span class='danger'>You bang against the [src.name]!</span>",
"You hear a banging sound.")
else
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
+7
View File
@@ -14,6 +14,11 @@
var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
var/dirt = 0
/turf/simulated/clean_blood()
for(var/obj/effect/decal/cleanable/blood/B in contents)
B.clean_blood()
..()
/turf/simulated/New()
..()
if(istype(loc, /area/chapel))
@@ -127,6 +132,8 @@
if(istype(M))
for(var/obj/effect/decal/cleanable/blood/B in contents)
if(!B.blood_DNA)
B.blood_DNA = list()
if(!B.blood_DNA[M.dna.unique_enzymes])
B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
B.virus2 = virus_copylist(M.virus2)
+1 -1
View File
@@ -57,7 +57,7 @@
var/decl/flooring/F = flooring_types[flooring_type]
if(!F.build_type)
continue
if(C.type == F.build_type)
if((S.type == F.build_type) || (S.build_type == F.build_type))
use_flooring = F
break
if(!use_flooring)
+3
View File
@@ -216,3 +216,6 @@ var/const/enterloopsanity = 100
if(A.density && !(A.flags & ON_BORDER))
return 1
return 0
/turf/proc/update_blood_overlays()
return
+5 -4
View File
@@ -66,10 +66,11 @@ var/list/wizardstart = list()
var/list/newplayer_start = list()
//Spawnpoints.
var/list/latejoin = list()
var/list/latejoin_gateway = list()
var/list/latejoin_cryo = list()
var/list/latejoin_cyborg = list()
var/list/latejoin = list()
var/list/latejoin_gateway = list()
var/list/latejoin_elevator = list()
var/list/latejoin_cryo = list()
var/list/latejoin_cyborg = list()
var/list/prisonwarp = list() // Prisoners go to these
var/list/holdingfacility = list() // Captured people go here
+16
View File
@@ -1326,3 +1326,19 @@ proc/admin_notice(var/message, var/rights)
message_admins("[key_name(usr)] attempting to force mode latespawn.")
ticker.mode.next_spawn = 0
ticker.mode.try_latespawn()
/datum/admins/proc/set_tcrystals(mob/living/carbon/human/H as mob)
set category = "Debug"
set name = "Set Telecrystals"
set desc = "Allows admins to change telecrystals of a user."
var/crystals
if(check_rights(R_ADMIN))
crystals = input("Amount of telecrystals for [H.ckey]", crystals) as null|num
if (!isnull(crystals))
H.mind.tcrystals = crystals
var/msg = "[key_name(usr)] has modified [H.ckey]'s telecrystals to [crystals]."
message_admins(msg)
else
usr << "You do not have access to this command."
+4 -2
View File
@@ -13,7 +13,8 @@ var/list/admin_verbs_default = list(
// /client/proc/deadchat /*toggles deadchat on/off*/
)
var/list/admin_verbs_admin = list(
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/datum/admins/proc/set_tcrystals,
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
/datum/admins/proc/show_game_mode, /*Configuration window for the current game mode.*/
@@ -283,7 +284,8 @@ var/list/admin_verbs_hideable = list(
/client/proc/enable_debug_verbs,
/client/proc/roll_dices,
/proc/possess,
/proc/release
/proc/release,
/datum/admins/proc/set_tcrystals
)
var/list/admin_verbs_mod = list(
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
+1
View File
@@ -162,6 +162,7 @@ var/list/debug_verbs = list (
,/client/proc/testZAScolors_remove
,/client/proc/setup_supermatter_engine
,/client/proc/atmos_toggle_debug
,/client/proc/spawn_tanktransferbomb
)
+68 -1
View File
@@ -424,6 +424,54 @@ var/global/list/gear_datums = list()
slot = slot_w_uniform
cost = 1
/datum/gear/bluejumpsuit
display_name = "jumpsuit, blue"
path = /obj/item/clothing/under/color/blue
slot = slot_w_uniform
cost = 1
/datum/gear/greenjumpsuit
display_name = "jumpsuit, green"
path = /obj/item/clothing/under/color/green
slot = slot_w_uniform
cost = 1
/datum/gear/greyjumpsuit
display_name = "jumpsuit, grey"
path = /obj/item/clothing/under/color/grey
slot = slot_w_uniform
cost = 1
/datum/gear/pinkjumpsuit
display_name = "jumpsuit, pink"
path = /obj/item/clothing/under/color/pink
slot = slot_w_uniform
cost = 1
/datum/gear/whitejumpsuit
display_name = "jumpsuit, white"
path = /obj/item/clothing/under/color/white
slot = slot_w_uniform
cost = 1
/datum/gear/yellowjumpsuit
display_name = "jumpsuit, yellow"
path = /obj/item/clothing/under/color/yellow
slot = slot_w_uniform
cost = 1
/datum/gear/lightbluejumpsuit
display_name = "jumpsuit, lightblue"
path = /obj/item/clothing/under/lightblue
slot = slot_w_uniform
cost = 1
/datum/gear/redjumpsuit
display_name = "jumpsuit, red"
path = /obj/item/clothing/under/color/red
slot = slot_w_uniform
cost = 1
/datum/gear/skirt_blue
display_name = "plaid skirt, blue"
path = /obj/item/clothing/under/dress/plaid_blue
@@ -934,6 +982,7 @@ var/global/list/gear_datums = list()
/datum/gear/scarf_orange
display_name = "scarf, orange"
path = /obj/item/clothing/accessory/scarf/orange
slot = slot_tie
cost = 1
@@ -1015,7 +1064,7 @@ var/global/list/gear_datums = list()
/datum/gear/leather_coat
display_name = "leather coat"
path = /obj/item/clothing/suit/leathercoat/alt
path = /obj/item/clothing/suit/leathercoat
cost = 2
slot = slot_wear_suit
@@ -1079,6 +1128,12 @@ var/global/list/gear_datums = list()
cost = 2
slot = slot_wear_suit
/datum/gear/mil_alt
display_name = "military jacket, alt"
path = /obj/item/clothing/suit/jacket/miljacket2
cost = 2
slot = slot_wear_suit
/datum/gear/hazard_vest
display_name = "hazard vest"
path = /obj/item/clothing/suit/storage/hazardvest
@@ -1561,6 +1616,12 @@ var/global/list/gear_datums = list()
sort_category = "misc"
cost = 1
/datum/gear/boot_knife
display_name = "boot knife"
path = /obj/item/weapon/material/kitchen/utensil/knife/boot
sort_category = "misc"
cost = 3
/datum/gear/cane
display_name = "cane"
path = /obj/item/weapon/cane
@@ -1657,6 +1718,12 @@ var/global/list/gear_datums = list()
cost = 1
sort_category = "ears"
/datum/gear/headphones
display_name = "headphones"
path = /obj/item/clothing/ears/earmuffs/headphones
cost = 1
sort_category = "ears"
/datum/gear/skrell_chain
display_name = "skrell headtail-wear, female, chain"
path = /obj/item/clothing/ears/skrell/chain
@@ -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"
+83
View File
@@ -2,6 +2,7 @@
name = "clothing"
siemens_coefficient = 0.9
var/list/species_restricted = null //Only these species can wear this kit.
var/gunshot_residue //Used by forensics.
/*
Sprites used when the clothing item is refit. This is done by setting icon_override.
@@ -15,6 +16,11 @@
/obj/item/clothing/proc/update_clothing_icon()
return
// Aurora forensics port.
/obj/item/clothing/clean_blood()
..()
gunshot_residue = null
//BS12: Species-restricted clothing check.
/obj/item/clothing/mob_can_equip(M as mob, slot)
@@ -157,6 +163,32 @@
item_state = "earmuffs"
slot_flags = SLOT_EARS | SLOT_TWOEARS
/obj/item/clothing/ears/earmuffs/headphones
name = "headphones"
desc = "Unce unce unce unce."
var/headphones_on = 0
icon_state = "headphones_off"
item_state = "headphones"
slot_flags = SLOT_EARS | SLOT_TWOEARS
/obj/item/clothing/ears/earmuffs/headphones/verb/togglemusic()
set name = "Toggle Headphone Music"
set category = "Object"
set src in usr
if(!istype(usr, /mob/living)) return
if(usr.stat) return
if(headphones_on)
icon_state = "headphones_off"
headphones_on = 0
usr << "<span class='notice'>You turn the music off.</span>"
else
icon_state = "headphones_on"
headphones_on = 1
usr << "<span class='notice'>You turn the music on.</span>"
update_clothing_icon()
///////////////////////////////////////////////////////////////////////
//Glasses
/*
@@ -387,6 +419,9 @@ BLIND // can't see anything
body_parts_covered = FEET
slot_flags = SLOT_FEET
var/can_hold_knife
var/obj/item/holding
permeability_coefficient = 0.50
slowdown = SHOES_SLOWDOWN
force = 2
@@ -397,6 +432,54 @@ BLIND // can't see anything
"Resomi" = 'icons/mob/species/resomi/shoes.dmi',
)
/obj/item/clothing/shoes/proc/draw_knife()
set name = "Draw Boot Knife"
set desc = "Pull out your boot knife."
set category = "IC"
set src in usr
if(usr.stat || usr.restrained() || usr.incapacitated())
return
holding.forceMove(get_turf(usr))
if(usr.put_in_hands(holding))
usr.visible_message("<span class='danger'>\The [usr] pulls a knife out of their boot!</span>")
holding = null
else
usr << "<span class='warning'>Your need an empty, unbroken hand to do that.</span>"
holding.forceMove(src)
if(!holding)
verbs -= /obj/item/clothing/shoes/proc/draw_knife
update_icon()
return
/obj/item/clothing/shoes/attackby(var/obj/item/I, var/mob/user)
if(can_hold_knife && istype(I, /obj/item/weapon/material/shard) || \
istype(I, /obj/item/weapon/material/butterfly) || \
istype(I, /obj/item/weapon/material/kitchen/utensil) || \
istype(I, /obj/item/weapon/material/hatchet/tacknife))
if(holding)
user << "<span class='warning'>\The [src] is already holding \a [holding].</span>"
return
user.unEquip(I)
I.forceMove(src)
holding = I
user.visible_message("<span class='notice'>\The [user] shoves \the [I] into \the [src].</span>")
verbs |= /obj/item/clothing/shoes/proc/draw_knife
update_icon()
else
return ..()
/obj/item/clothing/shoes/update_icon()
overlays.Cut()
if(holding)
overlays += image(icon, "[icon_state]_knife")
return ..()
/obj/item/clothing/shoes/proc/handle_movement(var/turf/walking, var/running)
return
+8
View File
@@ -183,6 +183,14 @@
item_state = "blindfold"
//vision_flags = BLIND // This flag is only supposed to be used if it causes permanent blindness, not temporary because of glasses
/obj/item/clothing/glasses/sunglasses/blindfold/tape
name = "length of tape"
desc = "It's a robust DIY blindfold!"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "tape_cross"
item_state = null
w_class = 1
/obj/item/clothing/glasses/sunglasses/prescription
name = "prescription sunglasses"
prescription = 1
+15
View File
@@ -16,6 +16,13 @@
icon_state = "healthhud"
body_parts_covered = 0
/obj/item/clothing/glasses/hud/health/prescription
name = "Prescription Health Scanner HUD"
desc = "A medical HUD integrated with a set of prescription glasses"
icon_state = "healthhud"
prescription = 1
icon_state = "healthhudpresc"
item_state = "healthhudpresc"
/obj/item/clothing/glasses/hud/health/process_hud(var/mob/M)
process_med_hud(M, 1)
@@ -27,6 +34,14 @@
body_parts_covered = 0
var/global/list/jobs[0]
/obj/item/clothing/glasses/hud/security/prescription
name = "Prescription Security HUD"
desc = "A security HUD integrated with a set of prescription glasses"
icon_state = "securityhud"
prescription = 1
icon_state = "sechudpresc"
item_state = "sechudpresc"
/obj/item/clothing/glasses/hud/security/jensenshades
name = "Augmented shades"
desc = "Polarized bioneural eyewear, designed to augment your vision."
@@ -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!")
+2
View File
@@ -15,6 +15,7 @@
force = 3
armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0)
siemens_coefficient = 0.7
can_hold_knife = 1
/obj/item/clothing/shoes/jackboots/unathi
name = "toe-less jackboots"
@@ -30,3 +31,4 @@
item_state = "workboots"
armor = list(melee = 40, bullet = 0, laser = 0, energy = 15, bomb = 20, bio = 0, rad = 20)
siemens_coefficient = 0.7
can_hold_knife = 1
@@ -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
+1 -1
View File
@@ -122,7 +122,7 @@
name = "black medical space helmet"
desc = "A black helmet sporting a medical cross and durable plating. Hopefully the wearer abides by space geneva."
icon_state = "syndicate-helm-black-med"
item_state_slots = list(slot_head_str = "syndicate-black-med")
item_state_slots = list(slot_head_str = "syndicate-helm-black-med")
/obj/item/clothing/suit/space/syndicate/black/med
name = "black medical space suit"
@@ -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")
+4 -4
View File
@@ -91,7 +91,7 @@
/obj/item/clothing/suit/armor/laserproof/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
var/reflectchance = 40 - round(damage/3)
if(!(def_zone in list("chest", "groin")))
reflectchance /= 2
@@ -171,12 +171,12 @@
if(!turfs.len) turfs += pick(/turf in orange(6))
var/turf/picked = pick(turfs)
if(!isturf(picked)) return
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc)
spark_system.start()
playsound(user.loc, "sparks", 50, 1)
user.loc = picked
return PROJECTILE_FORCE_MISS
return 0
@@ -275,7 +275,7 @@
icon_state = "kvest"
item_state = "kvest"
armor = list(melee = 50, bullet = 15, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0)
allowed = list(/obj/item/weapon/gun,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner)
allowed = list(/obj/item/weapon/gun,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs)
/obj/item/clothing/suit/storage/vest/officer
name = "officer armor vest"
+2 -2
View File
@@ -96,7 +96,7 @@
item_state = "det_suit"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/flame/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder)
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/flame/lighter,/obj/item/device/taperecorder)
armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/suit/storage/det_trench/grey
@@ -109,7 +109,7 @@
desc = "A forensics technician jacket."
item_state = "det_suit"
body_parts_covered = UPPER_TORSO|ARMS
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner,/obj/item/device/taperecorder)
allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/taperecorder)
armor = list(melee = 10, bullet = 10, laser = 15, energy = 10, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/suit/storage/forensics/red
+8 -11
View File
@@ -212,18 +212,12 @@
//coats
/obj/item/clothing/suit/leathercoat
name = "leather coat"
desc = "A long, thick black leather coat."
icon_state = "leathercoat"
item_state = "leathercoat"
/obj/item/clothing/suit/leathercoat/alt
name = "leather coat"
desc = "A long, thick black leather coat."
icon_state = "leathercoat_alt"
item_state = "leathercoat_alt"
/obj/item/clothing/suit/leathercoat/alt/sec
/obj/item/clothing/suit/leathercoat/sec
name = "leather coat"
desc = "A long, thick black leather coat."
icon_state = "leathercoat_sec"
@@ -367,6 +361,12 @@
icon_state = "militaryjacket"
item_state = "militaryjacket"
/obj/item/clothing/suit/jacket/miljacket2
name = "military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
icon_state = "militaryjacket2"
item_state = "militaryjacket2"
/obj/item/clothing/suit/storage/toggle/bomber
name = "bomber jacket"
desc = "A thick, well-worn WW2 leather bomber jacket."
@@ -397,11 +397,8 @@
body_parts_covered = UPPER_TORSO|ARMS
/obj/item/clothing/suit/storage/leather_jacket/alt
name = "leather jacket"
desc = "A black leather coat."
icon_state = "leather_jacket_alt"
item_state = "leather_jacket_alt"
body_parts_covered = UPPER_TORSO|ARMS
/obj/item/clothing/suit/storage/leather_jacket/nanotrasen
desc = "A black leather coat. A corporate logo is proudly displayed on the back."
@@ -409,7 +406,7 @@
//This one has buttons for some reason
/obj/item/clothing/suit/storage/toggle/brown_jacket
name = "leather jacket"
name = "brown jacket"
desc = "A brown leather coat."
icon_state = "brown_jacket"
item_state = "brown_jacket"
@@ -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
+4
View File
@@ -1,3 +1,7 @@
/obj/item/weapon/forensics
icon = 'icons/obj/forensics.dmi'
w_class = 1
//This is the output of the stringpercent(print) proc, and means about 80% of
//the print must be there for it to be complete. (Prints are 32 digits)
var/const/FINGERPRINT_COMPLETE = 6
@@ -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"
@@ -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"
@@ -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"
-115
View File
@@ -1,115 +0,0 @@
/obj/item/device/detective_scanner
name = "forensic scanner"
desc = "Used to scan objects for DNA and fingerprints."
icon_state = "forensic1"
var/list/stored = list()
w_class = 3.0
item_state = "electronic"
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
/obj/item/device/detective_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob)
if (!ishuman(M))
user << "<span class='warning'>[M] is not human and cannot have the fingerprints.</span>"
flick("forensic0",src)
return 0
if (( !( istype(M.dna, /datum/dna) ) || M.gloves) )
user << "<span class='notice'>No fingerprints found on [M]</span>"
flick("forensic0",src)
return 0
else
var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc )
F.amount = 1
F.add_fingerprint(M)
F.icon_state = "fingerprint1"
F.name = text("FPrintC- '[M.name]'")
user << "<span class='notice'>Done printing.</span>"
user << "<span class='notice'>[M]'s Fingerprints: [md5(M.dna.uni_identity)]</span>"
if ( M.blood_DNA && M.blood_DNA.len )
user << "<span class='notice'>Blood found on [M]. Analysing...</span>"
spawn(15)
for(var/blood in M.blood_DNA)
user << "<span class='notice'>Blood type: [M.blood_DNA[blood]]\nDNA: [blood]</span>"
return
/obj/item/device/detective_scanner/afterattack(atom/A as obj|turf, mob/user, proximity)
if(!proximity) return
if(ismob(A))
return
if(istype(A,/obj/machinery/computer/forensic_scanning))
user.visible_message("[user] takes a cord out of [src] and hooks its end into [A]" ,\
"<span class='notice'>You download data from [src] to [A]</span>")
var/obj/machinery/computer/forensic_scanning/F = A
F.sync_data(stored)
return
if(istype(A,/obj/item/weapon/f_card))
user << "The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\""
flick("forensic0",src)
return
add_fingerprint(user)
//General
if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA)
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"<span class='warning'>Unable to locate any fingerprints, materials, fibers, or blood on [A]!</span>",\
"You hear a faint hum of electrical equipment.")
flick("forensic0",src)
return 0
if(add_data(A))
user << "<span class='notice'>Object already in internal memory. Consolidating data...</span>"
flick("forensic2",src)
return
//PRINTS
if(A.fingerprints && A.fingerprints.len)
user << "<span class='notice'>Isolated [A.fingerprints.len] fingerprints:</span>"
user << "Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.</span>"
var/list/complete_prints = list()
for(var/i in A.fingerprints)
var/print = A.fingerprints[i]
if(stringpercent(print) <= FINGERPRINT_COMPLETE)
complete_prints += print
if(complete_prints.len < 1)
user << "<span class='notice'>No intact prints found</span>"
else
user << "<span class='notice'>Found [complete_prints.len] intact prints</span>"
for(var/i in complete_prints)
user << "<span class='notice'>&nbsp;&nbsp;&nbsp;&nbsp;[i]</span>"
//FIBERS
if(A.suit_fibers && A.suit_fibers.len)
user << "<span class='notice'>Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve."
flick("forensic2",src)
//Blood
if (A.blood_DNA && A.blood_DNA.len)
user << "<span class='notice'>Blood detected. Analysing...</span>"
spawn(15)
for(var/blood in A.blood_DNA)
user << "Blood type: \red [A.blood_DNA[blood]] \t \black DNA: \red [blood]"
user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\
"<span class='notice'>You finish scanning \the [A].</span>",\
"You hear a faint hum of electrical equipment.")
flick("forensic2",src)
return 0
/obj/item/device/detective_scanner/proc/add_data(atom/A as mob|obj|turf|area)
var/datum/data/record/forensic/old = stored["\ref [A]"]
var/datum/data/record/forensic/fresh = new(A)
if(old)
fresh.merge(old)
. = 1
stored["\ref [A]"] = fresh
/obj/item/device/detective_scanner/verb/wipe()
set name = "Wipe Forensic Data"
set category = "Object"
set src in view(1)
if (alert("Are you sure you want to wipe all data from [src]?",,"Yes","No") == "Yes")
stored = list()
usr << "<span class='notice'>Forensic data erase complete.</span>"
@@ -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()
@@ -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"
@@ -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)
@@ -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)
@@ -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)

Some files were not shown because too many files have changed in this diff Show More