12/21 modernizations from TG live (#103)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes
This commit is contained in:
Poojawa
2016-12-22 03:57:55 -06:00
committed by GitHub
parent f5e143a452
commit cf59ac1c3d
2215 changed files with 707445 additions and 87041 deletions
@@ -46,7 +46,6 @@
/obj/effect/hotspot
anchored = 1
mouse_opacity = 0
unacidable = 1//So you can't melt fire with acid.
icon = 'icons/effects/fire.dmi'
icon_state = "1"
layer = ABOVE_OPEN_TURF_LAYER
@@ -59,7 +58,6 @@
/obj/effect/hotspot/New()
..()
set_light(3,1,LIGHT_COLOR_FIRE)
SSair.hotspots += src
perform_exposure()
setDir(pick(cardinal))
@@ -71,6 +69,8 @@
if(!istype(location) || !(location.air))
return 0
location.active_hotspot = src
if(volume > CELL_VOLUME*0.95)
bypassing = 1
else
@@ -89,9 +89,9 @@
location.assume_air(affected)
for(var/A in loc)
var/atom/item = A
if(item && item != src) // It's possible that the item is deleted in temperature_expose
item.fire_act(null, temperature, volume)
var/atom/AT = A
if(AT && AT != src) // It's possible that the item is deleted in temperature_expose
AT.fire_act(temperature, volume)
return 0
@@ -147,9 +147,10 @@
return 1
/obj/effect/hotspot/Destroy()
SetLuminosity(0)
SSair.hotspots -= src
DestroyTurf()
if(istype(loc, /turf))
if(isturf(loc))
var/turf/open/T = loc
if(T.active_hotspot == src)
T.active_hotspot = null
@@ -158,8 +159,7 @@
return QDEL_HINT_PUTINPOOL
/obj/effect/hotspot/proc/DestroyTurf()
if(istype(loc, /turf))
if(isturf(loc))
var/turf/T = loc
if(T.to_be_destroyed)
var/chance_of_deletion
@@ -176,4 +176,4 @@
/obj/effect/hotspot/Crossed(mob/living/L)
..()
if(isliving(L))
L.fire_act()
L.fire_act(temperature, volume)
@@ -1,8 +1,16 @@
/turf/proc/CanAtmosPass(turf/T)
/atom/var/CanAtmosPass = ATMOS_PASS_YES
/atom/proc/CanAtmosPass(turf/T)
switch (CanAtmosPass)
if (ATMOS_PASS_PROC)
return ATMOS_PASS_YES
if (ATMOS_PASS_DENSITY)
return !density
else
return CanAtmosPass
/turf/closed/CanAtmosPass(turf/T)
return 0
/turf/closed/CanAtmosPass = ATMOS_PASS_NO
/turf/open/CanAtmosPass = ATMOS_PASS_PROC
/turf/open/CanAtmosPass(turf/T)
var/R
if(blocks_air || T.blocks_air)
@@ -10,7 +18,7 @@
for(var/obj/O in contents+T.contents)
var/turf/other = (O.loc == src ? T : src)
if(!O.CanAtmosPass(other))
if(!CANATMOSPASS(O, other))
R = 1
if(O.BlockSuperconductivity()) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments
var/D = get_dir(src, T)
@@ -24,53 +32,44 @@
return !R
/atom/movable/proc/CanAtmosPass()
return 1
/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
return (!density || !height)
/turf/CanPass(atom/movable/mover, turf/target, height=1.5)
if(!target) return 0
if(istype(mover)) // turf/Enter(...) will perform more advanced checks
return !density
else // Now, doing more detailed checks for air movement and air group formation
if(target.blocks_air||blocks_air)
return 0
for(var/obj/obstacle in src)
if(!obstacle.CanPass(mover, target, height))
return 0
for(var/obj/obstacle in target)
if(!obstacle.CanPass(mover, src, height))
return 0
return 1
/atom/movable/proc/BlockSuperconductivity() // objects that block air and don't let superconductivity act. Only firelocks atm.
return 0
/turf/proc/CalculateAdjacentTurfs()
var/list/atmos_adjacent_turfs = src.atmos_adjacent_turfs
for(var/direction in cardinal)
var/turf/open/T = get_step(src, direction)
if(!istype(T))
var/turf/T = get_step(src, direction)
if(!T)
continue
if(CanAtmosPass(T))
atmos_adjacent_turfs |= T
T.atmos_adjacent_turfs |= src
if(CANATMOSPASS(T, src))
LAZYINITLIST(atmos_adjacent_turfs)
LAZYINITLIST(T.atmos_adjacent_turfs)
atmos_adjacent_turfs[T] = TRUE
T.atmos_adjacent_turfs[src] = TRUE
else
atmos_adjacent_turfs -= T
T.atmos_adjacent_turfs -= src
if (atmos_adjacent_turfs)
atmos_adjacent_turfs -= T
if (T.atmos_adjacent_turfs)
T.atmos_adjacent_turfs -= src
UNSETEMPTY(T.atmos_adjacent_turfs)
UNSETEMPTY(atmos_adjacent_turfs)
src.atmos_adjacent_turfs = atmos_adjacent_turfs
//returns a list of adjacent turfs that can share air with this one.
//alldir includes adjacent diagonal tiles that can share
// air with both of the related adjacent cardinal tiles
/turf/proc/GetAtmosAdjacentTurfs(alldir = 0)
var/adjacent_turfs = atmos_adjacent_turfs.Copy()
var/adjacent_turfs
if (atmos_adjacent_turfs)
adjacent_turfs = atmos_adjacent_turfs.Copy()
else
adjacent_turfs = list()
if (!alldir)
return adjacent_turfs
var/turf/curloc = src
for (var/direction in diagonals)
@@ -79,10 +78,10 @@
for (var/checkDirection in cardinal)
var/turf/checkTurf = get_step(S, checkDirection)
if(!(checkTurf in S.atmos_adjacent_turfs))
if(!S.atmos_adjacent_turfs || !S.atmos_adjacent_turfs[checkTurf])
continue
if (checkTurf in adjacent_turfs)
if (adjacent_turfs[checkTurf])
matchingDirections++
if (matchingDirections >= 2)
@@ -91,29 +90,29 @@
return adjacent_turfs
/atom/movable/proc/air_update_turf(command = 0)
if(!istype(loc,/turf) && command)
/atom/proc/air_update_turf(command = 0)
if(!isturf(loc) && command)
return
var/turf/T = get_turf(loc)
T.air_update_turf(command)
/turf/proc/air_update_turf(command = 0)
/turf/air_update_turf(command = 0)
if(command)
CalculateAdjacentTurfs()
SSair.add_to_active(src,command)
/atom/movable/proc/move_update_air(turf/T)
if(istype(T,/turf))
if(isturf(T))
T.air_update_turf(1)
air_update_turf(1)
/atom/movable/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make a easy proc to spawn your plasma fires
/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make a easy proc to spawn your plasma fires
var/turf/open/T = get_turf(src)
if(!istype(T))
return
T.atmos_spawn_air(text)
/turf/open/proc/atmos_spawn_air(text)
/turf/open/atmos_spawn_air(text)
if(!text || !air)
return
@@ -5,7 +5,7 @@
var/temperature_archived
//list of open turfs adjacent to us
var/list/atmos_adjacent_turfs = list()
var/list/atmos_adjacent_turfs
//bitfield of dirs in which we are superconducitng
var/atmos_supeconductivity = 0
@@ -33,7 +33,7 @@
var/atmos_cooldown = 0
var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time
var/list/atmos_overlay_types = list() //gas IDs of current active gas overlays
var/list/atmos_overlay_types //gas IDs of current active gas overlays
/turf/open/New()
..()
@@ -98,13 +98,17 @@
/turf/open/proc/update_visuals()
var/list/new_overlay_types = tile_graphic()
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
overlays -= overlay
atmos_overlay_types -= overlay
if (atmos_overlay_types)
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
overlays -= overlay
for(var/overlay in new_overlay_types-atmos_overlay_types) //doesn't add overlays that already exist
add_overlay(overlay)
if (new_overlay_types.len)
if (atmos_overlay_types)
add_overlay(new_overlay_types - atmos_overlay_types) //don't add overlays that already exist
else
add_overlay(new_overlay_types)
UNSETEMPTY(new_overlay_types)
atmos_overlay_types = new_overlay_types
/turf/open/proc/tile_graphic()
@@ -130,7 +134,7 @@
//cache for sanic speed
var/list/adjacent_turfs = atmos_adjacent_turfs
var/datum/excited_group/our_excited_group = excited_group
var/adjacent_turfs_length = adjacent_turfs.len
var/adjacent_turfs_length = LAZYLEN(adjacent_turfs)
atmos_cooldown++
if (planetary_atmos)
adjacent_turfs_length++
@@ -246,16 +250,24 @@
for(var/atom/movable/M in src)
M.experience_pressure_difference(pressure_difference, pressure_direction)
/atom/movable/var/pressure_resistance = 5
/atom/movable/var/pressure_resistance = 10
/atom/movable/var/last_high_pressure_movement_air_cycle = 0
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction)
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
var/const/PROBABILITY_OFFSET = 25
var/const/PROBABILITY_BASE_PRECENT = 75
set waitfor = 0
. = 0
if(!anchored && !pulledby)
if (!anchored && !pulledby)
. = 1
if(pressure_difference > pressure_resistance && last_high_pressure_movement_air_cycle < SSair.times_fired)
last_high_pressure_movement_air_cycle = SSair.times_fired
step(src, direction)
if (last_high_pressure_movement_air_cycle < SSair.times_fired)
var/move_prob = 100
if (pressure_resistance > 0)
move_prob = (pressure_difference/pressure_resistance*PROBABILITY_BASE_PRECENT)-PROBABILITY_OFFSET
move_prob += pressure_resistance_prob_delta
if (move_prob > PROBABILITY_OFFSET && prob(move_prob))
step(src, direction)
last_high_pressure_movement_air_cycle = SSair.times_fired
///////////////////////////EXCITED GROUPS/////////////////////////////
@@ -445,4 +457,4 @@
(heat_capacity*sharer.heat_capacity/(heat_capacity+sharer.heat_capacity))
temperature -= heat/heat_capacity
sharer.temperature += heat/sharer.heat_capacity
sharer.temperature += heat/sharer.heat_capacity
@@ -6,7 +6,6 @@ What are the archived variables for?
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
var/list/meta_gas_info = meta_gas_list() //see ATMOSPHERICS/gas_types.dm
var/list/gaslist_cache = null
@@ -39,6 +38,7 @@ var/list/gaslist_cache = null
var/volume //liters
var/last_share
var/tmp/fuel_burnt
var/atom/holder
/datum/gas_mixture/New(volume = CELL_VOLUME)
..()
@@ -179,6 +179,17 @@ var/list/gaslist_cache = null
//Prevents whatever mechanism is causing it to hit negative temperatures.
//world << "post [temperature], [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]]
*/
if(holder)
if(cached_gases["freon"])
if(cached_gases["freon"][MOLES] >= MOLES_PLASMA_VISIBLE)
if(holder.freon_gas_act())
cached_gases["freon"][MOLES] -= MOLES_PLASMA_VISIBLE
if(cached_gases["water_vapor"])
if(cached_gases["water_vapor"][MOLES] >= MOLES_PLASMA_VISIBLE)
if(holder.water_vapor_gas_act())
cached_gases["water_vapor"][MOLES] -= MOLES_PLASMA_VISIBLE
fuel_burnt = 0
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
//world << "pre [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]"
@@ -333,7 +344,6 @@ var/list/gaslist_cache = null
amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/list/cached_gases = gases
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
@@ -361,6 +371,7 @@ var/list/gaslist_cache = null
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
return removed
@@ -372,7 +383,7 @@ var/list/gaslist_cache = null
copy.temperature = temperature
for(var/id in cached_gases)
add_gas(id)
copy.add_gas(id)
copy_gases[id][MOLES] = cached_gases[id][MOLES]
return copy
@@ -385,6 +396,7 @@ var/list/gaslist_cache = null
for(var/id in sample_gases)
assert_gas(id)
cached_gases[id][MOLES] = sample_gases[id][MOLES]
//remove all gases not in the sample
cached_gases &= sample_gases
@@ -51,6 +51,20 @@ var/list/hardcoded_gases = list("o2","n2","co2","plasma") //the main four gases,
gas_overlay = "plasma"
moles_visible = MOLES_PLASMA_VISIBLE
/datum/gas/water_vapor
id = "water_vapor"
specific_heat = 40
name = "Water Vapor"
gas_overlay = "water_vapor"
moles_visible = MOLES_PLASMA_VISIBLE
/datum/gas/freon
id = "freon"
specific_heat = 2000
name = "Freon"
gas_overlay = "freon"
moles_visible = MOLES_PLASMA_VISIBLE
/datum/gas/nitrous_oxide
id = "n2o"
specific_heat = 40
@@ -73,11 +87,11 @@ var/list/hardcoded_gases = list("o2","n2","co2","plasma") //the main four gases,
specific_heat = 20
name = "BZ"
/obj/effect/overlay/gas/
/obj/effect/overlay/gas
icon = 'icons/effects/tile_effects.dmi'
mouse_opacity = 0
layer = FLY_LAYER
appearance_flags = RESET_COLOR|TILE_BOUND
appearance_flags = TILE_BOUND
/obj/effect/overlay/gas/New(state)
. = ..()
+48 -17
View File
@@ -55,6 +55,11 @@
active_power_usage = 8
power_channel = ENVIRON
req_access = list(access_atmospherics)
obj_integrity = 250
max_integrity = 250
integrity_failure = 80
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 90, acid = 30)
resistance_flags = FIRE_PROOF
var/danger_level = 0
var/mode = AALARM_MODE_SCRUBBING
@@ -76,7 +81,9 @@
"co2" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
"plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"n2o" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"bz" = new/datum/tlv(-1, -1, 0.2, 0.5)
"bz" = new/datum/tlv(-1, -1, 0.2, 0.5),
"freon" = new/datum/tlv(-1, -1, 0.2, 0.5),
"water_vapor" = new/datum/tlv(-1, -1, 0.2, 0.5)
)
/obj/machinery/airalarm/server // No checks here.
@@ -89,6 +96,8 @@
"plasma" = new/datum/tlv(-1, -1, -1, -1),
"n2o" = new/datum/tlv(-1, -1, -1, -1),
"bz" = new/datum/tlv(-1, -1, -1, -1),
"freon" = new/datum/tlv(-1, -1, -1, -1),
"water_vapor" = new/datum/tlv(-1, -1, -1, -1)
)
/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
@@ -101,6 +110,8 @@
"plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"n2o" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"bz" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"freon" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"water_vapor" = new/datum/tlv(-1, -1, 0.2, 0.5)
)
//all air alarms in area are connected via magic
@@ -225,22 +236,24 @@
if(!info || info["frequency"] != frequency)
continue
data["scrubbers"] += list(list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"scrubbing" = info["scrubbing"],
"widenet" = info["widenet"],
"filter_co2" = info["filter_co2"],
"filter_toxins" = info["filter_toxins"],
"filter_n2o" = info["filter_n2o"],
"filter_bz" = info["filter_bz"]
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"scrubbing" = info["scrubbing"],
"widenet" = info["widenet"],
"filter_co2" = info["filter_co2"],
"filter_toxins" = info["filter_toxins"],
"filter_n2o" = info["filter_n2o"],
"filter_bz" = info["filter_bz"],
"filter_freon" = info["filter_freon"],
"filter_water_vapor" = info["filter_water_vapor"]
))
data["mode"] = mode
data["modes"] = list()
data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0))
data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0))
data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0))
data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 0))
data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 1))
data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1))
data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1))
data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1))
@@ -289,7 +302,7 @@
if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
. = TRUE
if("power", "co2_scrub", "tox_scrub", "n2o_scrub", "bz_scrub", "widenet", "scrubbing")
if("power", "co2_scrub", "tox_scrub", "n2o_scrub", "bz_scrub", "freon_scrub","water_vapor_scrub", "widenet", "scrubbing")
send_signal(device_id, list("[action]" = text2num(params["val"])))
. = TRUE
if("excheck")
@@ -356,7 +369,7 @@
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start() //sparks always.
if (electrocute_mob(user, get_area(src), src))
if (electrocute_mob(user, get_area(src), src, 1, TRUE))
return 1
else
return 0
@@ -407,6 +420,8 @@
"tox_scrub" = 0,
"n2o_scrub" = 0,
"bz_scrub" = 0,
"freon_scrub"= 0,
"water_vapor_scrub"= 0,
"scrubbing" = 1,
"widenet" = 0,
))
@@ -424,6 +439,8 @@
"tox_scrub" = 1,
"n2o_scrub" = 1,
"bz_scrub" = 1,
"freon_scrub"= 1,
"water_vapor_scrub"= 1,
"scrubbing" = 1,
"widenet" = 1,
))
@@ -454,6 +471,8 @@
"tox_scrub" = 0,
"n2o_scrub" = 0,
"bz_scrub" = 0,
"freon_scrub"= 0,
"water_vapor_scrub"= 0,
"scrubbing" = 1,
"widenet" = 0,
))
@@ -614,8 +633,7 @@
if(istype(W, /obj/item/weapon/wirecutters) && panel_open && wires.is_all_cut())
playsound(src.loc, W.usesound, 50, 1)
user << "<span class='notice'>You cut the final wires.</span>"
var/obj/item/stack/cable_coil/cable = new /obj/item/stack/cable_coil(loc)
cable.amount = 5
new /obj/item/stack/cable_coil(loc, 5)
buildstage = 1
update_icon()
return
@@ -643,7 +661,7 @@
user.visible_message("[user.name] removes the electronics from [src.name].",\
"<span class='notice'>You start prying out the circuit...</span>")
playsound(src.loc, W.usesound, 50, 1)
if (do_after(user, 20/W.toolspeed, target = src))
if (do_after(user, 20*W.toolspeed, target = src))
if (buildstage == 1)
user <<"<span class='notice'>You remove the air alarm electronics.</span>"
new /obj/item/weapon/electronics/airalarm( src.loc )
@@ -699,4 +717,17 @@
return
emagged = TRUE
visible_message("<span class='warning'>Sparks fly out of the [src]!</span>", "<span class='notice'>You emag the [src], disabling its safeties.</span>")
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
/obj/machinery/airalarm/obj_break(damage_flag)
..()
update_icon()
/obj/machinery/airalarm/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
new /obj/item/stack/sheet/metal(loc, 2)
var/obj/item/I = new /obj/item/weapon/electronics/airalarm(loc)
if(!disassembled)
I.obj_integrity = I.max_integrity * 0.5
new /obj/item/stack/cable_coil(loc, 3)
qdel(src)
@@ -16,36 +16,36 @@ Pipelines + Other Objects -> Pipe network
power_channel = ENVIRON
on_blueprints = TRUE
layer = GAS_PIPE_LAYER //under wires
resistance_flags = FIRE_PROOF
obj_integrity = 200
max_integrity = 200
var/nodealert = 0
var/can_unwrench = 0
var/initialize_directions = 0
var/pipe_color
var/obj/item/pipe/stored
var/global/list/iconsetids = list()
var/global/list/pipeimages = list()
var/image/pipe_vision_img = null
var/device_type = 0
var/list/obj/machinery/atmospherics/nodes = list()
var/list/obj/machinery/atmospherics/nodes
/obj/machinery/atmospherics/New(loc, process = TRUE)
nodes.len = device_type
nodes = new(device_type)
if (!armor)
armor = list(melee = 25, bullet = 10, laser = 10, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 100, acid = 70)
..()
if(process)
SSair.atmos_machinery += src
SetInitDirections()
if(can_unwrench)
stored = new(src, make_from=src)
/obj/machinery/atmospherics/Destroy()
for(DEVICE_TYPE_LOOP)
nullifyNode(I)
SSair.atmos_machinery -= src
if(stored)
qdel(stored)
stored = null
dropContents()
if(pipe_vision_img)
@@ -136,13 +136,13 @@ Pipelines + Other Objects -> Pipe network
var/unsafe_wrenching = FALSE
var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
playsound(src.loc, W.usesound, 50, 1)
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (internal_pressure > 2*ONE_ATMOSPHERE)
user << "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>"
unsafe_wrenching = TRUE //Oh dear oh dear
if (do_after(user, 20/W.toolspeed, target = src) && !qdeleted(src))
if (do_after(user, 20*W.toolspeed, target = src) && !qdeleted(src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You unfasten \the [src].</span>", \
@@ -152,11 +152,10 @@ Pipelines + Other Objects -> Pipe network
//You unwrenched a pipe full of pressure? Let's splat you into the wall, silly.
if(unsafe_wrenching)
unsafe_pressure_release(user, internal_pressure)
Deconstruct()
deconstruct(TRUE)
else
return ..()
/obj/machinery/atmospherics/proc/can_unwrench(mob/user)
return can_unwrench
@@ -179,13 +178,14 @@ Pipelines + Other Objects -> Pipe network
user.visible_message("<span class='danger'>[user] is sent flying by pressure!</span>","<span class='userdanger'>The pressure sends you flying!</span>")
user.throw_at(target, range, speed)
/obj/machinery/atmospherics/Deconstruct()
if(can_unwrench)
stored.loc = src.loc
transfer_fingerprints_to(stored)
stored = null
qdel(src)
/obj/machinery/atmospherics/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
if(can_unwrench)
var/obj/item/pipe/stored = new(loc, make_from=src)
if(!disassembled)
stored.obj_integrity = stored.max_integrity * 0.5
transfer_fingerprints_to(stored)
..()
/obj/machinery/atmospherics/proc/getpipeimage(iconset, iconstate, direction, col=rgb(255,255,255))
@@ -208,13 +208,10 @@ Pipelines + Other Objects -> Pipe network
return img
/obj/machinery/atmospherics/construction(pipe_type, obj_color)
/obj/machinery/atmospherics/on_construction(pipe_type, obj_color)
if(can_unwrench)
color = obj_color
add_atom_colour(obj_color, FIXED_COLOUR_PRIORITY)
pipe_color = obj_color
stored.setDir(src.dir )//need to define them here, because the obj directions...
stored.pipe_type = pipe_type //... were not set at the time the stored pipe was created
stored.color = obj_color
var/turf/T = loc
level = T.intact ? 2 : 1
atmosinit()
@@ -226,7 +223,7 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/singularity_pull(S, current_size)
if(current_size >= STAGE_FIVE)
Deconstruct()
deconstruct(FALSE)
//Find a connecting /obj/machinery/atmospherics in specified direction
@@ -283,7 +280,10 @@ Pipelines + Other Objects -> Pipe network
return list()
/obj/machinery/atmospherics/update_remote_sight(mob/user)
user.sight |= (SEE_TURFS|BLIND)
if(isborer(user))
user.sight |= (SEE_PIXELS)
else
user.sight |= (SEE_TURFS|BLIND)
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
/obj/machinery/atmospherics/proc/can_see_pipes()
@@ -65,7 +65,7 @@ Acts like a normal vent, but has an input AND output.
..()
if(!on)
return 0
return FALSE
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -85,6 +85,9 @@ Acts like a normal vent, but has an input AND output.
var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
//Removed can be null if there is no atmosphere in air1
if(!removed)
return FALSE
loc.assume_air(removed)
air_update_turf()
@@ -105,6 +108,9 @@ Acts like a normal vent, but has an input AND output.
var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
//removed can be null if there is no air in the location
if(!removed)
return FALSE
air2.merge(removed)
air_update_turf()
@@ -112,7 +118,7 @@ Acts like a normal vent, but has an input AND output.
var/datum/pipeline/parent2 = PARENT2
parent2.update = 1
return 1
return TRUE
//Radio remote control
@@ -195,4 +201,4 @@ Acts like a normal vent, but has an input AND output.
#undef EXT_BOUND
#undef INPUT_MIN
#undef OUTPUT_MAX
#undef OUTPUT_MAX
@@ -54,6 +54,10 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
close()
return
open()
investigate_log("Valve, [src.name], was manipiulated by [key_name(usr)] at [x], [y], [z], [loc.loc]", "atmos")
message_admins("Valve, [src.name], was manipulated by [key_name(usr)] at [x], [y], [z], [loc.loc]")
log_admin("[key_name(usr)] manipulated a manual valve at [x], [y], [z]")
/obj/machinery/atmospherics/components/binary/valve/digital // can be controlled by AI
name = "digital valve"
@@ -119,7 +119,10 @@ Thus, the two variables affect pump operation are set in New():
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
investigate_log("Volume Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [loc.loc]", "atmos")
message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [loc.loc]")
log_admin("[key_name(usr)] manipulated a volume pump at [x], [y], [z]")
. = TRUE
if("rate")
var/rate = params["rate"]
@@ -135,7 +138,9 @@ Thus, the two variables affect pump operation are set in New():
. = TRUE
if(.)
transfer_rate = Clamp(rate, 0, MAX_TRANSFER_RATE)
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
investigate_log("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [loc.loc]", "atmos")
message_admins("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [loc.loc]")
log_admin("[key_name(usr)] manipulated a volume pump at [x], [y], [z]")
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/receive_signal(datum/signal/signal)
@@ -174,5 +179,9 @@ Thus, the two variables affect pump operation are set in New():
if(!(stat & NOPOWER) && on)
user << "<span class='warning'>You cannot unwrench this [src], turn it off first!</span>"
else
investigate_log("Volume Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [loc.loc]", "atmos")
message_admins("Volume Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [loc.loc]")
log_admin("[key_name(usr)] unwrenched a volume pump at [x], [y], [z]")
return 1
@@ -7,12 +7,12 @@ On top of that, now people can add component-speciic procs/vars if they want!
var/welded = 0 //Used on pumps and scrubbers
var/showpipe = 0
var/list/datum/pipeline/parents = list()
var/list/datum/gas_mixture/airs = list()
var/list/datum/pipeline/parents
var/list/datum/gas_mixture/airs
/obj/machinery/atmospherics/components/New()
parents.len = device_type
airs.len = device_type
parents = new(device_type)
airs = new(device_type)
..()
for(DEVICE_TYPE_LOOP)
@@ -72,7 +72,7 @@ Pipenet stuff; housekeeping
qdel(AIR_I)
AIR_I = null
/obj/machinery/atmospherics/components/construction()
/obj/machinery/atmospherics/components/on_construction()
..()
update_parents()
@@ -83,18 +83,25 @@
if(!removed)
return
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
if(filter_type && removed.gases[filter_type])
var/filtering = filter_type ? TRUE : FALSE
if(filtering && !istext(filter_type))
WARNING("Wrong gas ID in [src]'s filter_type var. filter_type == [filter_type]")
filtering = FALSE
if(filtering && removed.gases[filter_type])
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
filtered_out.assert_gas(filter_type)
filtered_out.gases[filter_type][MOLES] = removed.gases[filter_type][MOLES]
removed.gases[filter_type][MOLES] = 0
removed.garbage_collect()
else
filtered_out = null
air2.merge(filtered_out)
air2.merge(filtered_out)
air3.merge(removed)
update_parents()
@@ -109,7 +116,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_filter", name, 475, 140, master_ui, state)
ui = new(user, src, ui_key, "atmos_filter", name, 475, 155, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
@@ -1,15 +1,18 @@
/obj/machinery/atmospherics/components/unary/cryo_cell
name = "cryo cell"
icon = 'icons/obj/cryogenics.dmi'
icon_state = "pod0"
icon_state = "cell-off"
density = 1
anchored = 1
obj_integrity = 350
max_integrity = 350
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 30, acid = 30)
var/on = FALSE
state_open = FALSE
var/autoeject = FALSE
var/volume = 100
var/running_bob_animation = 0
var/efficiency = 1
var/sleep_factor = 750
var/paralyze_factor = 1000
@@ -35,7 +38,7 @@
/obj/item/weapon/stock_parts/console_screen = 1,
/obj/item/stack/sheet/glass = 2)
/obj/machinery/atmospherics/components/unary/cryo_cell/construction()
/obj/machinery/atmospherics/components/unary/cryo_cell/on_construction()
..(dir, dir)
/obj/machinery/atmospherics/components/unary/cryo_cell/RefreshParts()
@@ -50,63 +53,39 @@
conduction_coefficient = initial(conduction_coefficient) * C
/obj/machinery/atmospherics/components/unary/cryo_cell/Destroy()
beaker = null
if(beaker)
qdel(beaker)
beaker = null
return ..()
/obj/machinery/atmospherics/components/unary/cryo_cell/contents_explosion(severity, target)
..()
if(beaker)
beaker.ex_act(severity, target)
/obj/machinery/atmospherics/components/unary/cryo_cell/handle_atom_del(atom/A)
..()
if(A == beaker)
beaker = null
updateUsrDialog()
/obj/machinery/atmospherics/components/unary/cryo_cell/on_deconstruction()
if(beaker)
beaker.forceMove(loc)
beaker = null
/obj/machinery/atmospherics/components/unary/cryo_cell/update_icon()
handle_update_icon()
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/handle_update_icon() //making another proc to avoid spam in update_icon
overlays.Cut() //empty the overlay proc, just in case
if(panel_open)
icon_state = "pod0-o"
icon_state = "cell-o"
else if(state_open)
icon_state = "pod0"
icon_state = "cell-open"
else if(on && is_operational())
if(occupant)
var/image/pickle = image(occupant.icon, occupant.icon_state)
pickle.overlays = occupant.overlays
pickle.pixel_y = 22
overlays += pickle
icon_state = "pod1"
var/up = 0 //used to see if we are going up or down, 1 is down, 2 is up
spawn(0) // Without this, the icon update will block. The new thread will die once the occupant leaves.
running_bob_animation = 1
while(occupant)
overlays -= "lid1" //have to remove the overlays first, to force an update- remove cloning pod overlay
overlays -= pickle //remove mob overlay
switch(pickle.pixel_y) //this looks messy as fuck but it works, switch won't call itself twice
if(23) //inbetween state, for smoothness
switch(up) //this is set later in the switch, to keep track of where the mob is supposed to go
if(2) //2 is up
pickle.pixel_y = 24 //set to highest
if(1) //1 is down
pickle.pixel_y = 22 //set to lowest
if(22) //mob is at it's lowest
pickle.pixel_y = 23 //set to inbetween
up = 2 //have to go up
if(24) //mob is at it's highest
pickle.pixel_y = 23 //set to inbetween
up = 1 //have to go down
overlays += pickle //re-add the mob to the icon
overlays += "lid1" //re-add the overlay of the pod, they are inside it, not floating
sleep(7) //don't want to jiggle violently, just slowly bob
return
running_bob_animation = 0
icon_state = "cell-occupied"
else
icon_state = "pod1"
overlays += "lid0" //have to remove the overlays first, to force an update- remove cloning pod overlay
icon_state = "cell-on"
else
icon_state = "pod0"
overlays += "lid0" //if no occupant, just put the lid overlay on, and ignore the rest
icon_state = "cell-off"
/obj/machinery/atmospherics/components/unary/cryo_cell/process()
..()
@@ -127,18 +106,18 @@
return
else if(occupant.stat == DEAD) // We don't bother with dead people.
return
if(air1.gases.len)
if(occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
occupant.Sleeping((occupant.bodytemperature / sleep_factor) * 100)
occupant.Paralyse((occupant.bodytemperature / paralyze_factor) * 100)
if(occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
occupant.Sleeping((occupant.bodytemperature / sleep_factor) * 100)
occupant.Paralyse((occupant.bodytemperature / paralyze_factor) * 100)
if(beaker)
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
if(beaker)
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
return 1
/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos()
@@ -146,7 +125,7 @@
if(!on)
return
var/datum/gas_mixture/air1 = AIR1
if(!NODE1 || !AIR1 || air1.gases["o2"][MOLES] < 5) // Turn off if the machine won't work.
if(!NODE1 || !AIR1 || !air1.gases.len || air1.gases["o2"][MOLES] < 5) // Turn off if the machine won't work.
on = FALSE
update_icon()
return
@@ -179,14 +158,14 @@
on = FALSE
..()
if(beaker)
beaker.loc = src
beaker.forceMove(src)
/obj/machinery/atmospherics/components/unary/cryo_cell/close_machine(mob/living/carbon/user)
if((isnull(user) || istype(user)) && state_open && !panel_open)
..(user)
return occupant
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/user)
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user)
user << "<span class='notice'>You struggle inside the cryotube, kicking the release with your foot... (This will take around 30 seconds.)</span>"
audible_message("<span class='notice'>You hear a thump from [src].</span>")
if(do_after(user, 300))
@@ -254,7 +233,7 @@
occupantData["stat"] = occupant.stat
occupantData["health"] = occupant.health
occupantData["maxHealth"] = occupant.maxHealth
occupantData["minHealth"] = config.health_threshold_dead
occupantData["minHealth"] = HEALTH_THRESHOLD_DEAD
occupantData["bruteLoss"] = occupant.getBruteLoss()
occupantData["oxyLoss"] = occupant.getOxyLoss()
occupantData["toxLoss"] = occupant.getToxLoss()
@@ -295,7 +274,7 @@
. = TRUE
if("ejectbeaker")
if(beaker)
beaker.loc = loc
beaker.forceMove(loc)
beaker = null
. = TRUE
update_icon()
@@ -14,7 +14,7 @@
if(NODE1)
icon_state = "he_intact"
var/obj/machinery/atmospherics/node = NODE1
color = node.color
add_atom_colour(node.color, FIXED_COLOUR_PRIORITY)
else
icon_state = "he_exposed"
@@ -4,6 +4,8 @@
icon_state = "generic"
name = "pressure tank"
desc = "A large vessel containing pressurized gas."
obj_integrity = 800
max_integrity = 800
var/volume = 10000 //in liters, 1 meters by 1 meters by 2 meters
density = 1
var/gas_type = 0
@@ -46,4 +48,4 @@
var/datum/gas_mixture/air_contents = AIR1
air_contents.assert_gases("o2", "n2")
air_contents.gases["o2"][MOLES] = AIR_CONTENTS * 0.2
air_contents.gases["n2"][MOLES] = AIR_CONTENTS * 0.8
air_contents.gases["n2"][MOLES] = AIR_CONTENTS * 0.8
@@ -6,6 +6,9 @@
var/icon_state_open = "cold_off"
density = TRUE
anchored = TRUE
obj_integrity = 300
max_integrity = 300
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 80, acid = 30)
var/on = FALSE
var/min_temperature = 0
@@ -49,7 +52,7 @@
else
return ..()
/obj/machinery/atmospherics/components/unary/thermomachine/construction()
/obj/machinery/atmospherics/components/unary/thermomachine/on_construction()
..(dir,dir)
/obj/machinery/atmospherics/components/unary/thermomachine/RefreshParts()
@@ -247,9 +247,9 @@
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if (WT.remove_fuel(0,user))
playsound(loc, 'sound/items/Welder.ogg', 40, 1)
playsound(loc, WT.usesound, 40, 1)
user << "<span class='notice'>You begin welding the vent...</span>"
if(do_after(user, 20/W.toolspeed, target = src))
if(do_after(user, 20*W.toolspeed, target = src))
if(!src || !WT.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
if(!welded)
@@ -260,6 +260,7 @@
welded = 0
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return 0
else
return ..()
@@ -290,6 +291,7 @@
welded = 0
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
@@ -298,4 +300,4 @@
#undef NO_BOUND
#undef SIPHONING
#undef RELEASING
#undef RELEASING
@@ -20,6 +20,9 @@
var/scrub_Toxins = 0
var/scrub_N2O = 0
var/scrub_BZ = 0
var/scrub_Freon = 0
var/scrub_WaterVapor = 0
var/volume_rate = 200
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
@@ -69,6 +72,10 @@
amount += idle_power_usage
if(scrub_BZ)
amount += idle_power_usage
if(scrub_Freon)
amount += idle_power_usage
if(scrub_WaterVapor)
amount += idle_power_usage
else //scrubbing == SIPHONING
amount = active_power_usage
@@ -119,6 +126,8 @@
"filter_toxins" = scrub_Toxins,
"filter_n2o" = scrub_N2O,
"filter_bz" = scrub_BZ,
"filter_freon" = scrub_Freon,
"filter_water_vapor" = scrub_WaterVapor,
"sigtype" = "status"
)
@@ -175,9 +184,10 @@
//Take a gas sample
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
var/list/removed_gases = removed.gases
if (isnull(removed)) //in space
//Nothing left to remove from the tile
if (isnull(removed))
return
var/list/removed_gases = removed.gases
//Filter it
var/datum/gas_mixture/filtered_out = new
@@ -209,6 +219,16 @@
filtered_out.gases["bz"][MOLES] = removed_gases["bz"][MOLES]
removed.gases["bz"][MOLES] = 0
if(scrub_Freon && removed_gases["freon"])
filtered_out.assert_gas("freon")
filtered_out.gases["freon"][MOLES] = removed_gases["freon"][MOLES]
removed.gases["freon"][MOLES] = 0
if(scrub_WaterVapor && removed_gases["water_vapor"])
filtered_out.assert_gas("water_vapor")
filtered_out.gases["water_vapor"][MOLES] = removed_gases["water_vapor"][MOLES]
removed.gases["water_vapor"][MOLES] = 0
removed.garbage_collect()
//Remix the resulting gases
@@ -289,6 +309,16 @@
if("toggle_bz_scrub" in signal.data)
scrub_BZ = !scrub_BZ
if("freon_scrub" in signal.data)
scrub_Freon = text2num(signal.data["freon_scrub"])
if("toggle_freon_scrub" in signal.data)
scrub_Freon = !scrub_Freon
if("water_vapor_scrub" in signal.data)
scrub_WaterVapor = text2num(signal.data["water_vapor_scrub"])
if("toggle_water_vapor_scrub" in signal.data)
scrub_WaterVapor = !scrub_WaterVapor
if("init" in signal.data)
name = signal.data["init"]
return
@@ -309,9 +339,9 @@
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0,user))
playsound(loc, 'sound/items/Welder.ogg', 40, 1)
playsound(loc, WT.usesound, 40, 1)
user << "<span class='notice'>Now welding the scrubber.</span>"
if(do_after(user, 20/W.toolspeed, target = src))
if(do_after(user, 20*W.toolspeed, target = src))
if(!src || !WT.isOn())
return
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
@@ -323,6 +353,7 @@
welded = 0
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return 0
else
return ..()
@@ -344,6 +375,7 @@
welded = 0
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
@@ -1,13 +1,16 @@
/datum/pipeline
var/datum/gas_mixture/air
var/list/datum/gas_mixture/other_airs = list()
var/list/datum/gas_mixture/other_airs
var/list/obj/machinery/atmospherics/pipe/members = list()
var/list/obj/machinery/atmospherics/components/other_atmosmch = list()
var/list/obj/machinery/atmospherics/pipe/members
var/list/obj/machinery/atmospherics/components/other_atmosmch
var/update = 1
/datum/pipeline/New()
other_airs = list()
members = list()
other_atmosmch = list()
SSair.networks += src
/datum/pipeline/Destroy()
@@ -41,6 +44,7 @@ var/pipenetwarnings = 10
addMachineryMember(base)
if(!air)
air = new
air.holder = src
var/list/possible_expansions = list(base)
while(possible_expansions.len>0)
for(var/obj/machinery/atmospherics/borderline in possible_expansions)
@@ -143,7 +147,7 @@ var/pipenetwarnings = 10
var/target_temperature
var/target_heat_capacity
if(istype(target, /turf/open))
if(isopenturf(target))
var/turf/open/modeled_location = target
target_temperature = modeled_location.GetTemperature()
@@ -193,6 +197,12 @@ var/pipenetwarnings = 10
air.temperature -= heat/total_heat_capacity
update = 1
/datum/pipeline/proc/return_air()
. = other_airs + air
if(null in .)
stack_trace("[src] has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().")
return removeNullsFromList(.)
/datum/pipeline/proc/reconcile_air()
var/list/datum/gas_mixture/GL = list()
var/list/datum/pipeline/PL = list()
@@ -200,8 +210,7 @@ var/pipenetwarnings = 10
for(var/i = 1; i <= PL.len; i++) //can't do a for-each here because we may add to the list within the loop
var/datum/pipeline/P = PL[i]
GL += P.air
GL += P.other_airs
GL += P.return_air()
for(var/obj/machinery/atmospherics/components/binary/valve/V in P.other_atmosmch)
if(V.open)
PL |= V.PARENT1
@@ -11,6 +11,10 @@
use_power = 1
idle_power_usage = 2
active_power_usage = 4
obj_integrity = 150
max_integrity = 150
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 40, acid = 0)
/obj/machinery/meter/New()
..()
@@ -94,9 +98,9 @@
/obj/machinery/meter/attackby(obj/item/weapon/W, mob/user, params)
if (istype(W, /obj/item/weapon/wrench))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
playsound(src.loc, W.usesound, 50, 1)
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40/W.toolspeed, target = src))
if (do_after(user, 40*W.toolspeed, target = src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You unfasten \the [src].</span>", \
@@ -137,4 +141,3 @@
/obj/machinery/meter/turf/initialize()
if (!target)
src.target = loc
@@ -20,7 +20,7 @@
/obj/machinery/zvent/process_atmos()
//all this object does, is make its turf share air with the ones above and below it, if they have a vent too.
if (istype(loc,/turf)) //if we're not on a valid turf, forget it
if(isturf(loc)) //if we're not on a valid turf, forget it
for (var/new_z in list(-1,1)) //change this list if a fancier system of z-levels gets implemented
var/turf/open/zturf_conn = locate(x,y,z+new_z)
if (istype(zturf_conn))
@@ -1,4 +1,4 @@
/obj/machinery/atmospherics/pipe/heat_exchanging/
/obj/machinery/atmospherics/pipe/heat_exchanging
icon = 'icons/obj/atmospherics/pipes/heat.dmi'
level = 2
var/initialize_directions_he
@@ -7,11 +7,11 @@
color = "#404040"
buckle_lying = 1
var/icon_temperature = T20C //stop small changes in temperature causing icon refresh
burn_state = LAVA_PROOF
resistance_flags = LAVA_PROOF | FIRE_PROOF
/obj/machinery/atmospherics/pipe/heat_exchanging/New()
..()
color = "#404040"
add_atom_colour("#404040", FIXED_COLOUR_PRIORITY)
/obj/machinery/atmospherics/pipe/heat_exchanging/can_be_node(obj/machinery/atmospherics/pipe/heat_exchanging/target)
if(!istype(target))
@@ -50,7 +50,7 @@
var/hc = pipe_air.heat_capacity()
var/mob/living/heat_source = buckled_mobs[1]
//Best guess-estimate of the total bodytemperature of all the mobs, since they share the same environment it's ~ok~ to guess like this
var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs.len * 3500))
var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0))
for(var/m in buckled_mobs)
var/mob/living/L = m
L.bodytemperature = avg_temp
@@ -14,7 +14,7 @@
buckle_lying = -1
/obj/machinery/atmospherics/pipe/New()
color = pipe_color
add_atom_colour(pipe_color, FIXED_COLOUR_PRIORITY)
volume = 35 * device_type
..()
@@ -38,7 +38,7 @@
..()
/obj/machinery/atmospherics/pipe/hide(i)
if(level == 1 && istype(loc, /turf))
if(level == 1 && isturf(loc))
invisibility = i ? INVISIBILITY_MAXIMUM : 0
update_icon()
@@ -97,4 +97,9 @@
N.update_icon()
/obj/machinery/atmospherics/pipe/returnPipenets()
. = list(parent)
. = list(parent)
/obj/machinery/atmospherics/pipe/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
if(damage_flag == "melee" && damage_amount < 12)
return 0
. = ..()
@@ -17,9 +17,13 @@
var/gas_type = ""
var/release_pressure = ONE_ATMOSPHERE
var/health = 100
armor = list(melee = 50, bullet = 50, laser = 50, energy = 100, bomb = 10, bio = 100, rad = 100, fire = 80, acid = 50)
obj_integrity = 250
max_integrity = 250
integrity_failure = 100
pressure_resistance = 7 * ONE_ATMOSPHERE
var/temperature_resistance = 1000 + T0C
var/starter_temp
var/update = 0
var/static/list/label2types = list(
@@ -30,6 +34,8 @@
"n2o" = /obj/machinery/portable_atmospherics/canister/nitrous_oxide,
"bz" = /obj/machinery/portable_atmospherics/canister/bz,
"air" = /obj/machinery/portable_atmospherics/canister/air,
"freon" = /obj/machinery/portable_atmospherics/canister/freon,
"water vapor" = /obj/machinery/portable_atmospherics/canister/water_vapor,
"caution" = /obj/machinery/portable_atmospherics/canister,
)
@@ -38,47 +44,67 @@
desc = "Nitrogen gas. Reportedly useful for something."
icon_state = "red"
gas_type = "n2"
/obj/machinery/portable_atmospherics/canister/oxygen
name = "o2 canister"
desc = "Oxygen. Necessary for human life."
icon_state = "blue"
gas_type = "o2"
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
name = "co2 canister"
desc = "Carbon dioxide. What the fuck is carbon dioxide?"
icon_state = "black"
gas_type = "co2"
/obj/machinery/portable_atmospherics/canister/toxins
name = "plasma canister"
desc = "Plasma gas. The reason YOU are here. Highly toxic."
icon_state = "orange"
gas_type = "plasma"
/obj/machinery/portable_atmospherics/canister/agent_b
name = "agent b canister"
desc = "Oxygen Agent B. You're not quite sure what it does."
gas_type = "agent_b"
/obj/machinery/portable_atmospherics/canister/bz
name = "BZ canister"
desc = "BZ, a powerful hallucinogenic nerve agent."
icon_state = "purple"
gas_type = "bz"
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
name = "n2o canister"
desc = "Nitrous oxide gas. Known to cause drowsiness."
icon_state = "redws"
gas_type = "n2o"
/obj/machinery/portable_atmospherics/canister/air
name = "air canister"
desc = "Pre-mixed air."
icon_state = "grey"
/obj/machinery/portable_atmospherics/canister/freon
name = "freon canister"
desc = "Freon. Great for the atmosphere!"
icon_state = "freon"
gas_type = "freon"
starter_temp = 120
/obj/machinery/portable_atmospherics/canister/water_vapor
name = "water vapor canister"
desc = "Water Vapor. We get it, you vape."
icon_state = "water_vapor"
gas_type = "water_vapor"
filled = 1
/obj/machinery/portable_atmospherics/canister/New(loc, datum/gas_mixture/existing_mixture)
..()
if(existing_mixture)
air_contents.copy_from(existing_mixture)
else
create_gas()
pump = new(src, FALSE)
pump.on = TRUE
pump.stat = 0
@@ -94,8 +120,11 @@
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(gas_type)
air_contents.add_gas(gas_type)
if(starter_temp)
air_contents.temperature = starter_temp
air_contents.gases[gas_type][MOLES] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
if(starter_temp)
air_contents.temperature = starter_temp
/obj/machinery/portable_atmospherics/canister/air/create_gas()
air_contents.add_gases("o2","n2")
air_contents.gases["o2"][MOLES] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
@@ -155,40 +184,56 @@
/obj/machinery/portable_atmospherics/canister/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > temperature_resistance)
take_damage(5, BRUTE, 0)
take_damage(5, BURN, 0)
/obj/machinery/portable_atmospherics/canister/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
switch(damage_type)
if(BRUTE)
if(sound_effect)
if(damage)
playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
else
playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
if(BURN)
if(sound_effect)
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
/obj/machinery/portable_atmospherics/canister/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
if(!(stat & BROKEN))
canister_break()
if(disassembled)
new /obj/item/stack/sheet/metal (loc, 10)
else
return
if(stat & BROKEN)
new /obj/item/stack/sheet/metal (loc, 5)
qdel(src)
/obj/machinery/portable_atmospherics/canister/attackby(obj/item/weapon/W, mob/user, params)
if(user.a_intent != INTENT_HARM && istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(stat & BROKEN)
if(!WT.remove_fuel(0, user))
return
playsound(loc, WT.usesound, 40, 1)
user << "<span class='notice'>You begin cutting [src] apart...</span>"
if(do_after(user, 30, target = src))
deconstruct(TRUE)
else
user << "<span class='notice'>You cannot slice [src] apart when it isn't broken.</span>"
return 1
else
return ..()
/obj/machinery/portable_atmospherics/canister/obj_break(damage_flag)
if((stat & BROKEN) || (flags & NODECONSTRUCT))
return
health = max( health - damage, 0)
if(!health)
disconnect()
var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
var/turf/T = get_turf(src)
T.assume_air(expelled_gas)
air_update_turf()
canister_break()
stat |= BROKEN
density = 0
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
update_icon()
investigate_log("was destroyed.", "atmos")
/obj/machinery/portable_atmospherics/canister/proc/canister_break()
disconnect()
var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
var/turf/T = get_turf(src)
T.assume_air(expelled_gas)
air_update_turf()
if(holding)
holding.loc = T
holding = null
stat |= BROKEN
density = 0
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
update_icon()
investigate_log("was destroyed.", "atmos")
if(holding)
holding.forceMove(T)
holding = null
/obj/machinery/portable_atmospherics/canister/process_atmos()
..()
@@ -209,39 +254,6 @@
air_update_turf() // Update the environment if needed.
update_icon()
/obj/machinery/portable_atmospherics/canister/blob_act(obj/effect/blob/B)
take_damage(100, BRUTE, 0)
/obj/machinery/portable_atmospherics/canister/burn()
take_damage(health, BURN, 1)
..()
/obj/machinery/portable_atmospherics/canister/bullet_act(obj/item/projectile/P)
. = ..()
take_damage(P.damage / 2, P.damage_type, 0)
/obj/machinery/portable_atmospherics/canister/ex_act(severity, target)
switch(severity)
if(1)
if((stat & BROKEN) || prob(30))
qdel(src)
else
take_damage(100, BRUTE, 0)
if(2)
if(stat & BROKEN)
qdel(src)
else
take_damage(rand(40, 110), BRUTE, 0)
if(3)
take_damage(rand(15, 40), BRUTE, 0)
/obj/machinery/portable_atmospherics/canister/attacked_by(obj/item/I, mob/user)
if(I.force)
user.visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", "<span class='danger'>You hit [src] with [I]!</span>")
investigate_log("was smacked with \a [I] by [key_name(user)].", "atmos")
add_fingerprint(user)
take_damage(I.force, I.damtype, 1)
/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -276,6 +288,9 @@
var/newtype = label2types[label]
if(newtype)
var/obj/machinery/portable_atmospherics/canister/replacement = new newtype(loc, air_contents)
if(connected_port)
replacement.connected_port = connected_port
replacement.connected_port.connected_device = replacement
replacement.interact(usr)
qdel(src)
if("pressure")
@@ -308,9 +323,22 @@
var/plasma = air_contents.gases["plasma"]
var/n2o = air_contents.gases["n2o"]
var/bz = air_contents.gases["bz"]
if(n2o || plasma || bz)
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""][(n2o || plasma) && bz ? " & " : ""][bz ? "BZ" : ""]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_admin("[key_name(usr)] opened a canister that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""][(n2o || plasma) && bz ? " & " : ""][bz ? "BZ" : ""] at [x], [y], [z]")
var/freon = air_contents.gases["freon"]
if(n2o || plasma || bz || freon)
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains the following: (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_admin("[key_name(usr)] opened a canister that contains the following at [x], [y], [z]:")
if(plasma)
log_admin("Plasma")
message_admins("Plasma")
if(n2o)
log_admin("N2O")
message_admins("N2O")
if(bz)
log_admin("BZ Gas")
message_admins("BZ Gas")
if(freon)
log_admin("Freon")
message_admins("Freon")
else
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into \the [holding || "air"].<br>"
investigate_log(logmsg, "atmos")
@@ -2,6 +2,10 @@
name = "portable_atmospherics"
icon = 'icons/obj/atmos.dmi'
use_power = 0
obj_integrity = 250
max_integrity = 250
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 60, acid = 30)
var/datum/gas_mixture/air_contents
var/obj/machinery/atmospherics/components/unary/portables_connector/connected_port
@@ -18,6 +22,7 @@
air_contents = new
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.holder = src
return 1
@@ -57,6 +62,11 @@
anchored = 1 //Prevent movement
return 1
/obj/machinery/portable_atmospherics/Move()
. = ..()
if(.)
disconnect()
/obj/machinery/portable_atmospherics/proc/disconnect()
if(!connected_port)
return 0
@@ -81,7 +91,7 @@
if(!(stat & BROKEN))
if(connected_port)
disconnect()
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
playsound(src.loc, W.usesound, 50, 1)
user.visible_message( \
"[user] disconnects [src].", \
"<span class='notice'>You unfasten [src] from the port.</span>", \
@@ -96,7 +106,7 @@
if(!connect(possible_port))
user << "<span class='notice'>[name] failed to connect to the port.</span>"
return
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
playsound(src.loc, W.usesound, 50, 1)
user.visible_message( \
"[user] connects [src].", \
"<span class='notice'>You fasten [src] to the port.</span>", \
@@ -105,4 +115,12 @@
else if(istype(W, /obj/item/device/analyzer) && Adjacent(user))
atmosanalyzer_scan(air_contents, user)
else
return ..()
return ..()
/obj/machinery/portable_atmospherics/attacked_by(obj/item/I, mob/user)
if(I.force < 10 && !(stat & BROKEN))
take_damage(0)
else
investigate_log("was smacked with \a [I] by [key_name(user)].", "atmos")
add_fingerprint(user)
..()
@@ -7,7 +7,7 @@
var/volume_rate = 1000
volume = 1000
var/list/scrubbing = list("plasma", "co2", "n2o", "agent_b", "bz")
var/list/scrubbing = list("plasma", "co2", "n2o", "agent_b", "bz", "freon", "water_vapor")
/obj/machinery/portable_atmospherics/scrubber/Destroy()
var/turf/T = get_turf(src)