"
+ */
/obj/effect/countdown/transformer
name = "transformer countdown"
diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm
index b7fe891900b..630860f7ea9 100644
--- a/code/game/objects/effects/decals/cleanable/robots.dm
+++ b/code/game/objects/effects/decals/cleanable/robots.dm
@@ -82,6 +82,7 @@
decal_reagent = /datum/reagent/fuel/oil
reagent_amount = 30
+
/obj/effect/decal/cleanable/oil/attackby(obj/item/I, mob/living/user)
var/attacked_by_hot_thing = I.get_temperature()
if(attacked_by_hot_thing)
@@ -91,6 +92,7 @@
return
return ..()
+/*
/obj/effect/decal/cleanable/oil/fire_act(exposed_temperature, exposed_volume)
if(exposed_temperature < 480)
return
@@ -98,7 +100,7 @@
var/turf/T = get_turf(src)
qdel(src)
new /obj/effect/hotspot(T)
-
+*/
/obj/effect/decal/cleanable/oil/streak
icon_state = "streak1"
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index a3191f31189..2ba5541c969 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -35,24 +35,22 @@
/obj/effect/particle_effect/foam/firefighting/Initialize(mapload)
. = ..()
- RemoveElement(/datum/element/atmos_sensitive)
/obj/effect/particle_effect/foam/firefighting/process()
..()
var/turf/open/T = get_turf(src)
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
- if(hotspot && istype(T) && T.air)
+ if(hotspot && istype(T) && T.zone)
qdel(hotspot)
- var/datum/gas_mixture/G = T.air
- if(G.gases[/datum/gas/plasma])
- var/plas_amt = min(30,G.gases[/datum/gas/plasma][MOLES]) //Absorb some plasma
- G.gases[/datum/gas/plasma][MOLES] -= plas_amt
+ var/datum/gas_mixture/G = T.return_air()
+ if(G.getGroupGas(GAS_PLASMA))
+ var/plas_amt = min(30, G.gas[GAS_PLASMA]) //Absorb some plasma
+ G.adjustGas(GAS_PLASMA, -plas_amt)
absorbed_plasma += plas_amt
if(G.temperature > T20C)
G.temperature = max(G.temperature/2,T20C)
- G.garbage_collect()
- T.air_update_turf(FALSE, FALSE)
+ //T.air_update_turf(FALSE, FALSE)
/obj/effect/particle_effect/foam/firefighting/kill_foam()
STOP_PROCESSING(SSfastprocess, src)
@@ -96,7 +94,6 @@
create_reagents(1000) //limited by the size of the reagent holder anyway.
START_PROCESSING(SSfastprocess, src)
playsound(src, 'sound/effects/bubbles2.ogg', 80, TRUE, -3)
- AddElement(/datum/element/atmos_sensitive, mapload)
/obj/effect/particle_effect/foam/ComponentInitialize()
. = ..()
@@ -193,12 +190,10 @@
F.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
F.metal = metal
-/obj/effect/particle_effect/foam/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 475
-
/obj/effect/particle_effect/foam/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
- kill_foam()
+ if(exposed_temperature > 475)
+ if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
+ kill_foam()
///////////////////////////////////////////////
@@ -276,19 +271,21 @@
desc = "A lightweight foamed metal wall."
gender = PLURAL
max_integrity = 20
+ can_atmos_pass = CANPASS_NEVER
+ obj_flags = CAN_BE_HIT | BLOCK_Z_IN_DOWN | BLOCK_Z_IN_UP
/obj/structure/foamedmetal/Initialize()
. = ..()
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
/obj/structure/foamedmetal/Destroy()
- air_update_turf(TRUE, FALSE)
+ set_density(0)
+ update_nearby_tiles()
. = ..()
/obj/structure/foamedmetal/Move()
- var/turf/T = loc
. = ..()
- move_update_air(T)
+ update_nearby_tiles()
/obj/structure/foamedmetal/attack_paw(mob/user, list/modifiers)
return attack_hand(user, modifiers)
@@ -324,17 +321,17 @@
if(isopenturf(loc))
var/turf/open/O = loc
O.ClearWet()
- if(O.air)
- var/datum/gas_mixture/G = O.air
+ if(O.return_air())
+ var/datum/gas_mixture/G = O.return_air()
G.temperature = 293.15
for(var/obj/effect/hotspot/H in O)
qdel(H)
- var/list/G_gases = G.gases
+ var/list/G_gases = G.gas
for(var/I in G_gases)
- if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen)
+ if(I == GAS_OXYGEN || I == GAS_NITROGEN)
continue
- G_gases[I][MOLES] = 0
- G.garbage_collect()
+ G_gases[I] = 0
+ AIR_UPDATE_VALUES(G)
for(var/obj/machinery/atmospherics/components/unary/U in O)
if(!U.welded)
U.welded = TRUE
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index 69609a41026..c498d78fbf2 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -77,7 +77,7 @@
if(!t_loc)
return
var/list/newsmokes = list()
- for(var/turf/T in t_loc.get_atmos_adjacent_turfs())
+ for(var/turf/T in get_adjacent_open_turfs(t_loc))
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
if(foundsmoke)
continue
@@ -173,15 +173,12 @@
var/datum/gas_mixture/G = T.air
if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
G.temperature = temperature
- T.air_update_turf(FALSE, FALSE)
+ //T.air_update_turf(FALSE, FALSE)
for(var/obj/effect/hotspot/H in T)
qdel(H)
- var/list/G_gases = G.gases
- if(G_gases[/datum/gas/plasma])
- G.assert_gas(/datum/gas/nitrogen)
- G_gases[/datum/gas/nitrogen][MOLES] += (G_gases[/datum/gas/plasma][MOLES])
- G_gases[/datum/gas/plasma][MOLES] = 0
- G.garbage_collect()
+ if(G.getGroupGas(GAS_PLASMA))
+ G.adjustGas(GAS_NITROGEN, G.gas[GAS_PLASMA])
+ G.adjustGas(GAS_PLASMA, -G.gas[GAS_PLASMA])
if (weldvents)
for(var/obj/machinery/atmospherics/components/unary/U in T)
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber.
diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm
index 4141788552f..9bfce3659f0 100644
--- a/code/game/objects/effects/effect_system/effects_water.dm
+++ b/code/game/objects/effects/effect_system/effects_water.dm
@@ -7,12 +7,18 @@
var/life = 15
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
/obj/effect/particle_effect/water/Initialize(mapload)
. = ..()
QDEL_IN(src, 70)
/obj/effect/particle_effect/water/Move(turf/newloc)
+ //WOW. OKAY. THIS IS REALLY HACKY. THIS NEEDS TO BE STANDARDIZED.
+ var/datum/gas_mixture/env = get_step(src, 0)?.return_air()
+ var/diff_temp = (temperature - env.temperature) / env.group_multiplier / 2 //MAGIC NUMBER ALERT!!!!!!!
+ if(abs(diff_temp) >= ATOM_TEMPERATURE_EQUILIBRIUM_THRESHOLD)
+ var/altered_temp = max(env.temperature + (ATOM_TEMPERATURE_EQUILIBRIUM_CONSTANT * diff_temp), 0)
+ env.temperature = (diff_temp > 0) ? min(temperature, altered_temp) : max(temperature, altered_temp)
+
if (--src.life < 1)
qdel(src)
return FALSE
@@ -28,6 +34,11 @@
///Extinguisher snowflake
/obj/effect/particle_effect/water/extinguisher
+/obj/effect/particle_effect/water/extinguisher/Initialize(mapload)
+ . = ..()
+ if(reagents)
+ temperature = reagents.chem_temp
+
/obj/effect/particle_effect/water/extinguisher/Move()
. = ..()
if(!reagents)
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 92ab7d3f0cb..01ab5d3e5ec 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -5,9 +5,11 @@
icon = 'icons/effects/effects.dmi'
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
move_resist = INFINITY
+ flags_2 = NO_TEMP_CHANGE_2
obj_flags = NONE
vis_flags = VIS_INHERIT_PLANE
blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ simulated = FALSE
/obj/effect/attackby(obj/item/weapon, mob/user, params)
if(SEND_SIGNAL(weapon, COMSIG_ITEM_ATTACK_EFFECT, src, user, params) & COMPONENT_NO_AFTERATTACK)
@@ -34,9 +36,6 @@
/obj/effect/attack_hulk(mob/living/carbon/human/user)
return FALSE
-/obj/effect/experience_pressure_difference()
- return
-
/obj/effect/ex_act(severity, target)
return FALSE
@@ -60,3 +59,7 @@
/obj/effect/dummy/singularity_act()
return
+
+//PARIAH EDIT - PLASMA CONTAMINATION
+/obj/effect/contaminate()
+ return
diff --git a/code/game/objects/effects/forcefields.dm b/code/game/objects/effects/forcefields.dm
index 9c41da052a8..5fc593ba9f6 100644
--- a/code/game/objects/effects/forcefields.dm
+++ b/code/game/objects/effects/forcefields.dm
@@ -5,7 +5,7 @@
anchored = TRUE
opacity = FALSE
density = TRUE
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
var/timeleft = 300 //Set to 0 for permanent forcefields (ugh)
/obj/effect/forcefield/Initialize(mapload)
@@ -21,7 +21,7 @@
name = "glowing wall"
icon = 'icons/effects/cult/effects.dmi'
icon_state = "cultshield"
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
timeleft = 200
/// A form of the cult forcefield that lasts permanently.
diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm
index 505caab018b..415254f7fd7 100644
--- a/code/game/objects/effects/glowshroom.dm
+++ b/code/game/objects/effects/glowshroom.dm
@@ -100,7 +100,6 @@ GLOBAL_VAR_INIT(glowshrooms, 0)
else //if on the floor, glowshroom on-floor sprite
icon_state = base_icon_state
- AddElement(/datum/element/atmos_sensitive, mapload)
COOLDOWN_START(src, spread_cooldown, rand(min_delay_spread, max_delay_spread))
START_PROCESSING(SSobj, src)
@@ -136,7 +135,8 @@ GLOBAL_VAR_INIT(glowshrooms, 0)
/obj/structure/glowshroom/proc/Spread()
var/turf/ownturf = get_turf(src)
- if(!TURF_SHARES(ownturf)) //If we are in a 1x1 room
+ var/list/turf/shares = get_adjacent_open_turfs(ownturf)
+ if(!length(shares)) //If we are in a 1x1 room
return //Deal with it not now
var/list/possible_locs = list()
@@ -146,7 +146,7 @@ GLOBAL_VAR_INIT(glowshrooms, 0)
for(var/turf/open/floor/earth in oview(2,src))
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
continue
- if(!TURF_SHARES(earth))
+ if(!length(get_adjacent_open_turfs(earth)))
continue
possible_locs += earth
@@ -242,10 +242,11 @@ GLOBAL_VAR_INIT(glowshrooms, 0)
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)
/obj/structure/glowshroom/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 300
+ return (exposed_temperature > 300) ? TRUE : FALSE
/obj/structure/glowshroom/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(5, BURN, 0, 0)
+ if(exposed_temperature > 300)
+ take_damage(5, BURN, 0, 0)
/obj/structure/glowshroom/acid_act(acidpwr, acid_volume)
visible_message(span_danger("[src] melts away!"))
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 0faa180d74f..957717fa2d5 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -113,7 +113,9 @@
var/gas_type = "o2"
/obj/effect/mine/gas/mineEffect(mob/victim)
- atmos_spawn_air("[gas_type]=[gas_amount]")
+ if(isopenturf(loc))
+ var/turf/open/openloc = loc
+ openloc.atmos_spawn_air(gas_type, gas_amount)
/obj/effect/mine/gas/plasma
diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm
index 64fc60062e6..28622eac887 100644
--- a/code/game/objects/effects/spawners/bombspawner.dm
+++ b/code/game/objects/effects/spawners/bombspawner.dm
@@ -6,16 +6,16 @@
name = "bomb"
icon = 'icons/hud/screen_gen.dmi'
icon_state = "x"
- /* Gasmixes for tank_one and tank_two of the ttv respectively.
+ /* Gasmixes for tank_one and tank_two of the ttv respectively.
* Populated on /obj/effect/spawner/newbomb/Initialize, depopulated right after by the children procs.
*/
var/datum/gas_mixture/first_gasmix
var/datum/gas_mixture/second_gasmix
-/**
+/**
* The part of code that actually spawns the bomb. Always call the parent's initialize first for subtypes of these.
*
- * Arguments:
+ * Arguments:
* * assembly - An assembly typepath to add to the ttv.
*/
/obj/effect/spawner/newbomb/Initialize(mapload, assembly = null)
@@ -25,8 +25,8 @@
ttv.tank_two = new /obj/item/tank/internals/oxygen (ttv)
first_gasmix = ttv.tank_one.return_air()
second_gasmix = ttv.tank_two.return_air()
- first_gasmix.remove_ratio(1)
- second_gasmix.remove_ratio(1)
+ first_gasmix.removeRatio(1)
+ second_gasmix.removeRatio(1)
if(ispath(assembly, /obj/item/assembly))
var/obj/item/assembly/newassembly = new assembly (ttv)
ttv.attached_device = newassembly
@@ -85,7 +85,7 @@
first_gasmix.assert_gas(/datum/gas/hypernoblium)
first_gasmix.assert_gas(/datum/gas/tritium)
second_gasmix.assert_gas(/datum/gas/oxygen)
-
+
first_gasmix.gases[/datum/gas/hypernoblium][MOLES] = REACTION_OPPRESSION_THRESHOLD - 0.01
first_gasmix.gases[/datum/gas/tritium][MOLES] = 0.5 * calculate_pressure(first_gasmix, TANK_LEAK_PRESSURE - 1)
second_gasmix.gases[/datum/gas/oxygen][MOLES] = calculate_pressure(second_gasmix, TANK_LEAK_PRESSURE-1)
diff --git a/code/game/objects/effects/spiderwebs.dm b/code/game/objects/effects/spiderwebs.dm
index 8ec5ec113c5..1053a438b84 100644
--- a/code/game/objects/effects/spiderwebs.dm
+++ b/code/game/objects/effects/spiderwebs.dm
@@ -9,7 +9,6 @@
/obj/structure/spider/Initialize(mapload)
. = ..()
- AddElement(/datum/element/atmos_sensitive, mapload)
/obj/structure/spider/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
if(damage_type == BURN)//the stickiness of the web mutes all attack sounds except fire damage type
@@ -25,10 +24,11 @@
. = ..()
/obj/structure/spider/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 300
+ return (exposed_temperature > 300) ? TRUE : FALSE
/obj/structure/spider/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(5, BURN, 0, 0)
+ if(exposed_temperature > 300)
+ take_damage(5, BURN, 0, 0)
/obj/structure/spider/stickyweb
///Whether or not the web is from the genetics power
@@ -77,7 +77,7 @@
desc = "A solid thick wall of web, airtight enough to block air flow."
icon_state = "sealedweb"
sealed = TRUE
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
/obj/structure/spider/stickyweb/genetic //for the spider genes in genetics
genetic = TRUE
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index f5201360e52..953d2859998 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -84,11 +84,11 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons
var/stealthy_audio = FALSE
///How large is the object, used for stuff like whether it can fit in backpacks or not
- var/w_class = WEIGHT_CLASS_NORMAL
+ w_class = WEIGHT_CLASS_NORMAL
///This is used to determine on which slots an item can fit.
var/slot_flags = 0
pass_flags = PASSTABLE
- pressure_resistance = 4
+ //pressure_resistance = 4
/// This var exists as a weird proxy "owner" ref
/// It's used in a few places. Stop using it, and optimially replace all uses please
var/obj/item/master = null
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index b5356af6618..52637a0ac6d 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -1005,7 +1005,7 @@ GLOBAL_VAR_INIT(icon_holographic_window, init_holographic_window())
for(var/direction in GLOB.cardinals)
var/turf/C = get_step(W, direction)
var/list/dupes = checkdupes(C)
- if((isspaceturf(C) || TURF_SHARES(C)) && !dupes.len)
+ if((isspaceturf(C) || (get_step(src, 0).open_directions & direction)) && !dupes.len)
candidates += C
if(!candidates.len)
to_chat(user, span_warning("Valid target not found..."))
diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm
index f376c9d6358..a68703cfdfb 100644
--- a/code/game/objects/items/RPD.dm
+++ b/code/game/objects/items/RPD.dm
@@ -510,7 +510,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
for (var/obj/machinery/atmospherics/O in S.nodes)
O.atmos_init()
O.add_member(src)
- SSair.add_to_rebuild_queue(S)
+ SSairmachines.add_to_rebuild_queue(S)
// Finally, update our internal state - update_pipe_icon also updates dir and connections
S.update_pipe_icon()
user.visible_message(span_notice("[user] reprograms the \the [S]."),span_notice("You reprogram \the [S]."))
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index e8147324351..194db8520f9 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -219,10 +219,6 @@
var/prevname = "[A.name]"
set_area_machinery_title(A, new_name, prevname)
A.name = new_name
- if(A.firedoors)
- for(var/D in A.firedoors)
- var/obj/machinery/door/firedoor/FD = D
- FD.CalculateAffectingAreas()
A.update_areasize()
return TRUE
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index a5708a81ff4..fb6fc5a87da 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -195,7 +195,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(!reagents.has_reagent(/datum/reagent/oxygen)) //cigarettes need oxygen
var/datum/gas_mixture/air = return_air()
- if(!air || !air.has_gas(/datum/gas/oxygen, 1)) //or oxygen on a tile to burn
+ if(!air || !air.hasGas(GAS_OXYGEN, 1)) //or oxygen on a tile to burn
to_chat(user, span_notice("Your [name] needs a source of oxygen to burn."))
return ..()
@@ -316,7 +316,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
user?.IgniteMob()
if(!reagents.has_reagent(/datum/reagent/oxygen)) //cigarettes need oxygen
var/datum/gas_mixture/air = return_air()
- if(!air || !air.has_gas(/datum/gas/oxygen, 1)) //or oxygen on a tile to burn
+ if(!air || !air.hasGas(GAS_OXYGEN, 1)) //or oxygen on a tile to burn
extinguish()
return
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index cc3b1fb8e27..f7c5cb4dcd2 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -227,7 +227,7 @@
/obj/item/circuitboard/computer/turbine_computer
name = "Turbine Computer (Computer Board)"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/computer/turbine_computer
+ //build_path = /obj/machinery/computer/turbine_computer
//Generic
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 155e4cb2267..9c08b272314 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -201,7 +201,7 @@
/obj/item/circuitboard/machine/turbine_compressor
name = "Turbine - Inlet Compressor (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/power/turbine/inlet_compressor/constructed
+ //build_path = /obj/machinery/power/turbine/inlet_compressor/constructed
req_components = list(
/obj/item/stack/cable_coil = 5,
/obj/item/stack/sheet/iron = 5)
@@ -209,7 +209,7 @@
/obj/item/circuitboard/machine/turbine_rotor
name = "Turbine - Core Rotor (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/power/turbine/core_rotor/constructed
+ //build_path = /obj/machinery/power/turbine/core_rotor/constructed
req_components = list(
/obj/item/stack/cable_coil = 5,
/obj/item/stack/sheet/iron = 5)
@@ -217,7 +217,7 @@
/obj/item/circuitboard/machine/turbine_stator
name = "Turbine - Turbine Outlet (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/power/turbine/turbine_outlet/constructed
+ //build_path = /obj/machinery/power/turbine/turbine_outlet/constructed
req_components = list(
/obj/item/stack/cable_coil = 5,
/obj/item/stack/sheet/iron = 5)
@@ -288,65 +288,66 @@
. = ..()
. += span_notice("It is set to layer [pipe_layer].")
-/obj/item/circuitboard/machine/HFR_fuel_input
- name = "HFR Fuel Input (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/atmospherics/components/unary/hypertorus/fuel_input
- req_components = list(
- /obj/item/stack/sheet/plasteel = 5)
-
-/obj/item/circuitboard/machine/HFR_waste_output
- name = "HFR Waste Output (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/atmospherics/components/unary/hypertorus/waste_output
- req_components = list(
- /obj/item/stack/sheet/plasteel = 5)
-
-/obj/item/circuitboard/machine/HFR_moderator_input
- name = "HFR Moderator Input (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/atmospherics/components/unary/hypertorus/moderator_input
- req_components = list(
- /obj/item/stack/sheet/plasteel = 5)
-
-/obj/item/circuitboard/machine/HFR_core
- name = "HFR core (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/atmospherics/components/unary/hypertorus/core
- req_components = list(
- /obj/item/stack/cable_coil = 10,
- /obj/item/stack/sheet/glass = 10,
- /obj/item/stack/sheet/plasteel = 10)
-
-/obj/item/circuitboard/machine/HFR_corner
- name = "HFR Corner (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/hypertorus/corner
- req_components = list(
- /obj/item/stack/sheet/plasteel = 5)
-
-/obj/item/circuitboard/machine/HFR_interface
- name = "HFR Interface (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/hypertorus/interface
- req_components = list(
- /obj/item/stack/cable_coil = 10,
- /obj/item/stack/sheet/glass = 10,
- /obj/item/stack/sheet/plasteel = 5)
-
-/obj/item/circuitboard/machine/crystallizer
- name = "Crystallizer (Machine Board)"
- greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/atmospherics/components/binary/crystallizer
- req_components = list(
- /obj/item/stack/cable_coil = 10,
- /obj/item/stack/sheet/glass = 10,
- /obj/item/stack/sheet/plasteel = 5)
+//FIXME: HYPERGARBAGE DONUT CREATION CODE
+// /obj/item/circuitboard/machine/HFR_fuel_input
+// name = "HFR Fuel Input (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/atmospherics/components/unary/hypertorus/fuel_input
+// req_components = list(
+// /obj/item/stack/sheet/plasteel = 5)
+
+// /obj/item/circuitboard/machine/HFR_waste_output
+// name = "HFR Waste Output (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/atmospherics/components/unary/hypertorus/waste_output
+// req_components = list(
+// /obj/item/stack/sheet/plasteel = 5)
+
+// /obj/item/circuitboard/machine/HFR_moderator_input
+// name = "HFR Moderator Input (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/atmospherics/components/unary/hypertorus/moderator_input
+// req_components = list(
+// /obj/item/stack/sheet/plasteel = 5)
+
+// /obj/item/circuitboard/machine/HFR_core
+// name = "HFR core (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/atmospherics/components/unary/hypertorus/core
+// req_components = list(
+// /obj/item/stack/cable_coil = 10,
+// /obj/item/stack/sheet/glass = 10,
+// /obj/item/stack/sheet/plasteel = 10)
+
+// /obj/item/circuitboard/machine/HFR_corner
+// name = "HFR Corner (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/hypertorus/corner
+// req_components = list(
+// /obj/item/stack/sheet/plasteel = 5)
+
+// /obj/item/circuitboard/machine/HFR_interface
+// name = "HFR Interface (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/hypertorus/interface
+// req_components = list(
+// /obj/item/stack/cable_coil = 10,
+// /obj/item/stack/sheet/glass = 10,
+// /obj/item/stack/sheet/plasteel = 5)
+
+// /obj/item/circuitboard/machine/crystallizer
+// name = "Crystallizer (Machine Board)"
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/atmospherics/components/binary/crystallizer
+// req_components = list(
+// /obj/item/stack/cable_coil = 10,
+// /obj/item/stack/sheet/glass = 10,
+// /obj/item/stack/sheet/plasteel = 5)
/obj/item/circuitboard/machine/bluespace_sender
name = "Bluespace Sender (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/atmospherics/components/unary/bluespace_sender
+ //build_path = /obj/machinery/atmospherics/components/unary/bluespace_sender
req_components = list(
/obj/item/stack/cable_coil = 10,
/obj/item/stack/sheet/glass = 10,
@@ -482,7 +483,7 @@
/obj/item/circuitboard/machine/electrolyzer
name = "Electrolyzer (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_GENERIC
- build_path = /obj/machinery/electrolyzer
+ //build_path = /obj/machinery/electrolyzer
req_components = list(
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/capacitor = 2,
diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm
index 0a46b63e6cc..53a88c6febb 100644
--- a/code/game/objects/items/devices/forcefieldprojector.dm
+++ b/code/game/objects/items/devices/forcefieldprojector.dm
@@ -103,7 +103,7 @@
density = TRUE
mouse_opacity = MOUSE_OPACITY_OPAQUE
resistance_flags = INDESTRUCTIBLE
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_NEVER
armor = list(MELEE = 0, BULLET = 25, LASER = 50, ENERGY = 50, BOMB = 25, BIO = 100, FIRE = 100, ACID = 100)
var/obj/item/forcefield_projector/generator
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 905e7fdecab..389802bead0 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -139,10 +139,10 @@
var/temp_to_give = internal_heat / FRACTION_TO_RELEASE
internal_heat -= temp_to_give
var/datum/gas_mixture/environment = our_turf.return_air()
- var/delta_temperature = temp_to_give / environment.heat_capacity()
+ var/delta_temperature = temp_to_give / environment.getHeatCapacity()
if(delta_temperature)
environment.temperature += delta_temperature
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
if(admins_warned && internal_heat < max_heat * 0.75)
admins_warned = FALSE
message_admins("Power sink at ([x],[y],[z] - JMP) has cooled down and will not explode.")
diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm
index cf5316866e9..a783192826a 100644
--- a/code/game/objects/items/devices/scanners/gas_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm
@@ -101,7 +101,7 @@
ui.open()
/obj/item/analyzer/ui_static_data(mob/user)
- return return_atmos_handbooks()
+ return //return_atmos_handbooks()
/obj/item/analyzer/ui_data(mob/user)
LAZYINITLIST(last_gasmix_data)
@@ -125,7 +125,7 @@
/**
* Outputs a message to the user describing the target's gasmixes.
- *
+ *
* Gets called by analyzer_act, which in turn is called by tool_act.
* Also used in other chat-based gas scans.
*/
@@ -133,7 +133,7 @@
var/mixture = target.return_analyzable_air()
if(!mixture)
return FALSE
-
+
var/icon = target
var/message = list()
if(!silent && isliving(user))
@@ -150,24 +150,25 @@
message += span_boldnotice("Node [mix_number]")
mix_name += " - Node [mix_number]"
- var/total_moles = air.total_moles()
- var/pressure = air.return_pressure()
- var/volume = air.return_volume() //could just do mixture.volume... but safety, I guess?
- var/temperature = air.return_temperature()
+ var/total_moles = air.get_moles()
+ var/pressure = air.returnPressure()
+ var/volume = air.get_volume() //could just do mixture.volume... but safety, I guess?
+ var/temperature = air.get_temperature()
if(total_moles > 0)
message += span_notice("Moles: [round(total_moles, 0.01)] mol")
-
- var/list/cached_gases = air.gases
+
+ var/list/cached_gases = air.gas
for(var/id in cached_gases)
- var/gas_concentration = cached_gases[id][MOLES]/total_moles
- message += span_notice("[cached_gases[id][GAS_META][META_GAS_NAME]]: [round(cached_gases[id][MOLES], 0.01)] mol ([round(gas_concentration*100, 0.01)] %)")
+ var/gas_concentration = cached_gases[id]/total_moles
+ var/amount = round(air.gas[id], 0.01)
+ message += span_notice("[xgm_gas_data.name[id]]: [amount >= 0.01 ? "[amount] mol" : "Trace amounts." ] ([round(gas_concentration*100, 0.01)] %)")
message += span_notice("Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)")
message += span_notice("Volume: [volume] L")
message += span_notice("Pressure: [round(pressure, 0.01)] kPa")
else
message += airs.len > 1 ? span_notice("This node is empty!") : span_notice("[target] is empty!")
-
+
gasmix_data += list(gas_mixture_parser(air, mix_name))
if(istype(tool))
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index 8009ffa92cd..3cb05feeef8 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -148,8 +148,8 @@
if(change_volume)
target_mix.volume += other_mix.volume
-
- target_mix.merge(other_mix.remove_ratio(1))
+
+ target_mix.merge(other_mix.removeRatio(1))
return TRUE
/obj/item/transfer_valve/proc/split_gases()
@@ -160,7 +160,7 @@
var/volume_ratio = mix_one.volume/mix_two.volume
var/datum/gas_mixture/temp
- temp = mix_two.remove_ratio(volume_ratio)
+ temp = mix_two.removeRatio(volume_ratio)
mix_one.merge(temp)
mix_two.volume -= mix_one.volume
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index 730df0413be..005988ebd8d 100644
--- a/code/game/objects/items/flamethrower.dm
+++ b/code/game/objects/items/flamethrower.dm
@@ -202,13 +202,10 @@
for(var/turf/T in turflist)
if(T == previousturf)
continue //so we don't burn the tile we be standin on
- var/list/turfs_sharing_with_prev = previousturf.get_atmos_adjacent_turfs(alldir=1)
+ /*var/list/turfs_sharing_with_prev = previousturf.TryGetNonDenseNeighbour()
if(!(T in turfs_sharing_with_prev))
- break
- if(igniter)
- igniter.ignite_turf(src,T)
- else
- default_ignite(T)
+ break*/
+ ignite_turf(T)
sleep(1)
previousturf = T
operating = FALSE
@@ -217,18 +214,18 @@
attack_self(M)
-/obj/item/flamethrower/proc/default_ignite(turf/target, release_amount = 0.05)
+/obj/item/flamethrower/proc/ignite_turf(turf/target, release_amount = 5)
//TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this...
//Transfer 5% of current tank air contents to turf
- var/datum/gas_mixture/tank_mix = ptank.return_air()
- var/datum/gas_mixture/air_transfer = tank_mix.remove_ratio(release_amount)
-
- if(air_transfer.gases[/datum/gas/plasma])
- air_transfer.gases[/datum/gas/plasma][MOLES] *= 5 //Suffering
+ var/datum/gas_mixture/ptank_mix = ptank.return_air()
+ var/datum/gas_mixture/air_transfer = ptank_mix.removeRatio(release_amount)
+ //air_transfer.toxins = air_transfer.toxins * 5 // This is me not comprehending the air system. I realize this is retarded and I could probably make it work without fucking it up like this, but there you have it. -- TLE
+ var/obj/effect/decal/cleanable/oil/l_fuel = new(target,air_transfer.getByFlag(XGM_GAS_FUEL),get_dir(loc,target))
+ l_fuel.reagent_amount = release_amount
+ air_transfer.removeByFlag(XGM_GAS_FUEL, 0)
target.assume_air(air_transfer)
//Burn it based on transfered gas
- target.hotspot_expose((tank_mix.temperature*2) + 380,500)
- //location.hotspot_expose(1000,500,1)
+ target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500) // -- More of my "how do I shot fire?" dickery. -- TLE
/obj/item/flamethrower/Initialize(mapload)
. = ..()
@@ -257,7 +254,7 @@
owner.visible_message(span_danger("\The [attack_text] hits the fuel tank on [owner]'s [name], rupturing it! What a shot!"))
var/turf/target_turf = get_turf(owner)
log_game("A projectile ([hitby]) detonated a flamethrower tank held by [key_name(owner)] at [COORD(target_turf)]")
- igniter.ignite_turf(src,target_turf, release_amount = 100)
+ ignite_turf(target_turf, release_amount = 100)
qdel(ptank)
return 1 //It hit the flamethrower, not them
@@ -265,15 +262,10 @@
/obj/item/assembly/igniter/proc/flamethrower_process(turf/open/location)
location.hotspot_expose(heat,2)
-/obj/item/assembly/igniter/proc/ignite_turf(obj/item/flamethrower/F,turf/open/location,release_amount = 0.05)
- F.default_ignite(location,release_amount)
-
/obj/item/flamethrower/proc/instant_refill()
SIGNAL_HANDLER
if(ptank)
var/datum/gas_mixture/tank_mix = ptank.return_air()
- tank_mix.assert_gas(/datum/gas/plasma)
- tank_mix.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*ptank.volume/(R_IDEAL_GAS_EQUATION*T20C)
- else
+ tank_mix.setGasMoles(GAS_PLASMA,(10*ONE_ATMOSPHERE)*ptank.volume/(R_IDEAL_GAS_EQUATION*T20C))
ptank = new /obj/item/tank/internals/plasma/full(src)
update_appearance()
diff --git a/code/game/objects/items/grenades/atmos_grenades.dm b/code/game/objects/items/grenades/atmos_grenades.dm
index 27223969a34..70df29ce9b6 100644
--- a/code/game/objects/items/grenades/atmos_grenades.dm
+++ b/code/game/objects/items/grenades/atmos_grenades.dm
@@ -39,7 +39,7 @@
playsound(src, 'sound/effects/spray2.ogg', 100, TRUE)
var/list/connected_turfs = detect_room(origin = get_turf(src), max_size = fix_range)
var/datum/gas_mixture/base_mix = new
- base_mix.parse_gas_string(OPENTURF_DEFAULT_ATMOS)
+ base_mix.gas = OPENTURF_DEFAULT_ATMOS
for(var/turf/open/turf_fix in connected_turfs)
if(turf_fix.blocks_air)
continue
@@ -69,7 +69,9 @@
continue
var/distance_from_center = max(get_dist(turf_loc, loc), 1)
var/turf/open/floor_loc = turf_loc
- floor_loc.atmos_spawn_air("n2=[n2_gas_amount / distance_from_center];o2=[o2_gas_amount / distance_from_center];TEMP=273")
+ //floor_loc.atmos_spawn_air("n2=[n2_gas_amount / distance_from_center];o2=[o2_gas_amount / distance_from_center];TEMP=273")
+ floor_loc.atmos_spawn_air(GAS_NITROGEN, n2_gas_amount/distance_from_center, 273)
+ floor_loc.atmos_spawn_air(GAS_OXYGEN, o2_gas_amount/distance_from_center, 273)
qdel(src)
/obj/item/grenade/gas_crystal/nitrous_oxide_crystal
@@ -93,7 +95,8 @@
continue
var/distance_from_center = max(get_dist(turf_loc, loc), 1)
var/turf/open/floor_loc = turf_loc
- floor_loc.atmos_spawn_air("n2o=[n2o_gas_amount / distance_from_center];TEMP=273")
+ //floor_loc.atmos_spawn_air("n2o=[n2o_gas_amount / distance_from_center];TEMP=273")
+ floor_loc.atmos_spawn_air(GAS_N2O, n2o_gas_amount/distance_from_center, 273)
qdel(src)
/obj/item/grenade/gas_crystal/crystal_foam
diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm
index 86c531d8030..27f2ceb8a5b 100644
--- a/code/game/objects/items/latexballoon.dm
+++ b/code/game/objects/items/latexballoon.dm
@@ -13,7 +13,6 @@
/obj/item/latexballon/Initialize(mapload)
. = ..()
- AddElement(/datum/element/atmos_sensitive, mapload)
/obj/item/latexballon/proc/blow(obj/item/tank/tank, mob/user)
if (icon_state == "latexballon_bursted")
@@ -24,11 +23,9 @@
to_chat(user, span_notice("You blow up [src] with [tank]."))
air_contents = tank.remove_air_volume(3)
-/obj/item/latexballon/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature > T0C+100)
-
/obj/item/latexballon/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- burst()
+ if(exposed_temperature > T0C + 100)
+ burst()
/obj/item/latexballon/proc/burst()
if (!air_contents || icon_state != "latexballon_blow")
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 371a2eeb34f..37dc275e1fb 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -171,6 +171,7 @@
playsound(get_turf(src), hitsound, 75, TRUE, -1)
return TOXLOSS
+/*
/obj/item/melee/supermatter_sword
name = "supermatter sword"
desc = "In a station full of bad ideas, this might just be the worst."
@@ -272,7 +273,7 @@
/obj/item/melee/supermatter_sword/add_blood_DNA(list/blood_dna)
return FALSE
-
+*/
/obj/item/melee/curator_whip
name = "curator's whip"
desc = "Somewhat eccentric and outdated, it still stings like hell to be hit by."
@@ -414,6 +415,7 @@
playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE)
to_chat(user, span_notice("You put [src] away."))
+
/obj/item/melee/cleric_mace
name = "cleric mace"
desc = "The grandson of the club, yet the grandfather of the baseball bat. Most notably used by holy orders in days past."
diff --git a/code/game/objects/items/powerfist.dm b/code/game/objects/items/powerfist.dm
index e4bb53e9841..72700022e5b 100644
--- a/code/game/objects/items/powerfist.dm
+++ b/code/game/objects/items/powerfist.dm
@@ -92,14 +92,14 @@
target.visible_message(span_danger("[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!"), \
span_userdanger("[user]'s punches you!"))
return
- if(!molar_cmp_equals(gasused.total_moles(), gasperfist * fisto_setting))
+ /*if(!molar_cmp_equals(gasused.get_moles(), gasperfist * fisto_setting))
to_chat(user, span_warning("\The [src]'s piston-ram lets out a weak hiss, it needs more gas!"))
playsound(loc, 'sound/weapons/punch4.ogg', 50, TRUE)
target.apply_damage((force / 2), BRUTE)
target.visible_message(span_danger("[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!"), \
span_userdanger("[user]'s punch strikes with force!"))
return
-
+ */
target.apply_damage(force * fisto_setting, BRUTE, wound_bonus = CANT_WOUND)
target.visible_message(span_danger("[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!"), \
span_userdanger("You cry out in pain as [user]'s punch flings you backwards!"))
diff --git a/code/game/objects/items/secret_documents.dm b/code/game/objects/items/secret_documents.dm
index 8c5780b1785..3c42f9c9396 100644
--- a/code/game/objects/items/secret_documents.dm
+++ b/code/game/objects/items/secret_documents.dm
@@ -18,7 +18,7 @@
throw_range = 1
throw_speed = 1
layer = MOB_LAYER
- pressure_resistance = 2
+ //pressure_resistance = 2
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
///Nanotrasen documents
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index d28712ee522..620ec9c1609 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -157,7 +157,6 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
/obj/item/stack/sheet/wethide/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
. = ..()
AddElement(/datum/element/dryable, /obj/item/stack/sheet/leather)
- AddElement(/datum/element/atmos_sensitive, mapload)
AddComponent(/datum/component/grillable, /obj/item/stack/sheet/leather, rand(1 SECONDS, 3 SECONDS), TRUE)
/obj/item/stack/sheet/wethide/burn()
@@ -279,15 +278,13 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
//Step two - washing..... it's actually in washing machine code.
//Step three - drying
-/obj/item/stack/sheet/wethide/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature > drying_threshold_temperature)
-
/obj/item/stack/sheet/wethide/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- wetness--
- if(wetness == 0)
- new /obj/item/stack/sheet/leather(drop_location(), 1)
- wetness = initial(wetness)
- use(1)
+ if(exposed_temperature > drying_threshold_temperature)
+ wetness--
+ if(wetness == 0)
+ new /obj/item/stack/sheet/leather(drop_location(), 1)
+ wetness = initial(wetness)
+ use(1)
/obj/item/stack/sheet/wethide/microwave_act(obj/machinery/microwave/MW)
..()
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 66372fcc4eb..d85f33be32b 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -457,7 +457,8 @@ GLOBAL_LIST_INIT(abductor_recipes, list ( \
return ..()
/obj/item/stack/sheet/mineral/coal/fire_act(exposed_temperature, exposed_volume)
- atmos_spawn_air("co2=[amount*10];TEMP=[exposed_temperature]")
+ var/turf/muhturf = get_turf(src)
+ muhturf.atmos_spawn_air(GAS_CO2, amount*10, exposed_temperature)
qdel(src)
/obj/item/stack/sheet/mineral/coal/five
diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index 3e3eb90e583..b6d359da97b 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -8,7 +8,7 @@
w_class = WEIGHT_CLASS_BULKY
distribute_pressure = ONE_ATMOSPHERE * O2STANDARD
actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization)
- var/gas_type = /datum/gas/oxygen
+ var/gas_type = GAS_OXYGEN
var/on = FALSE
var/stabilizers = FALSE
var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not
@@ -41,8 +41,7 @@
/obj/item/tank/jetpack/populate_gas()
if(gas_type)
var/datum/gas_mixture/our_mix = return_air()
- our_mix.assert_gas(gas_type)
- our_mix.gases[gas_type][MOLES] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
+ our_mix.adjustGas(gas_type, (6*ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/jetpack/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/toggle_jetpack))
@@ -124,12 +123,12 @@
return COMSIG_MOVABLE_STOP_SPACEMOVE
/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user)
- if((num < 0.005 || air_contents.total_moles() < num))
+ if((num < 0.005 || air_contents.get_moles() < num))
turn_off(user)
return
var/datum/gas_mixture/removed = remove_air(num)
- if(removed.total_moles() < 0.005)
+ if(removed.get_moles() < 0.005)
turn_off(user)
return
@@ -210,4 +209,4 @@
icon_state = "jetpack-black"
inhand_icon_state = "jetpack-black"
distribute_pressure = 0
- gas_type = /datum/gas/carbon_dioxide
+ gas_type = GAS_CO2
diff --git a/code/game/objects/items/tanks/n2_tanks.dm b/code/game/objects/items/tanks/n2_tanks.dm
index 5325575a54b..bd6108c7a47 100644
--- a/code/game/objects/items/tanks/n2_tanks.dm
+++ b/code/game/objects/items/tanks/n2_tanks.dm
@@ -10,12 +10,10 @@
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
/obj/item/tank/internals/nitrogen/populate_gas()
- air_contents.assert_gas(/datum/gas/nitrogen)
- air_contents.gases[/datum/gas/nitrogen][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_NITROGEN, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/nitrogen/full/populate_gas()
- air_contents.assert_gas(/datum/gas/nitrogen)
- air_contents.gases[/datum/gas/nitrogen][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_NITROGEN, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/nitrogen/belt
icon_state = "nitrogen_extended"
@@ -26,8 +24,7 @@
supports_variations_flags = CLOTHING_VOX_VARIATION
/obj/item/tank/internals/nitrogen/belt/full/populate_gas()
- air_contents.assert_gas(/datum/gas/nitrogen)
- air_contents.gases[/datum/gas/nitrogen][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_NITROGEN, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/nitrogen/belt/emergency
name = "emergency nitrogen tank"
@@ -36,5 +33,5 @@
volume = 3
/obj/item/tank/internals/nitrogen/belt/emergency/populate_gas()
- air_contents.assert_gas(/datum/gas/nitrogen)
- air_contents.gases[/datum/gas/nitrogen][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_NITROGEN, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
+
diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm
index 4776a225371..55e584fee54 100644
--- a/code/game/objects/items/tanks/tank_types.dm
+++ b/code/game/objects/items/tanks/tank_types.dm
@@ -23,8 +23,7 @@
/obj/item/tank/internals/oxygen/populate_gas()
- air_contents.assert_gas(/datum/gas/oxygen)
- air_contents.gases[/datum/gas/oxygen][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_OXYGEN,(6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/oxygen/yellow
@@ -57,9 +56,8 @@
supports_variations_flags = CLOTHING_TESHARI_VARIATION
/obj/item/tank/internals/anesthetic/populate_gas()
- air_contents.assert_gases(/datum/gas/oxygen, /datum/gas/nitrous_oxide)
- air_contents.gases[/datum/gas/oxygen][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
- air_contents.gases[/datum/gas/nitrous_oxide][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
+ air_contents.adjustGas(GAS_OXYGEN,(3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD)
+ air_contents.adjustGas(GAS_NITROGEN, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD)
/*
* Plasma
@@ -76,8 +74,7 @@
/obj/item/tank/internals/plasma/populate_gas()
- air_contents.assert_gas(/datum/gas/plasma)
- air_contents.gases[/datum/gas/plasma][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_PLASMA, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/flamethrower))
@@ -93,8 +90,7 @@
return ..()
/obj/item/tank/internals/plasma/full/populate_gas()
- air_contents.assert_gas(/datum/gas/plasma)
- air_contents.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_PLASMA, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/plasma/empty/populate_gas()
return
@@ -113,12 +109,10 @@
distribute_pressure = TANK_PLASMAMAN_RELEASE_PRESSURE
/obj/item/tank/internals/plasmaman/populate_gas()
- air_contents.assert_gas(/datum/gas/plasma)
- air_contents.gases[/datum/gas/plasma][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_PLASMA, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/plasmaman/full/populate_gas()
- air_contents.assert_gas(/datum/gas/plasma)
- air_contents.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_PLASMA, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/plasmaman/belt
@@ -133,8 +127,7 @@
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
/obj/item/tank/internals/plasmaman/belt/full/populate_gas()
- air_contents.assert_gas(/datum/gas/plasma)
- air_contents.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_PLASMA, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/plasmaman/belt/empty/populate_gas()
return
@@ -161,8 +154,7 @@
/obj/item/tank/internals/emergency_oxygen/populate_gas()
- air_contents.assert_gas(/datum/gas/oxygen)
- air_contents.gases[/datum/gas/oxygen][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
+ air_contents.adjustGas(GAS_OXYGEN, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/tank/internals/emergency_oxygen/empty/populate_gas()
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index 093048267da..6e47c2f618f 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -17,7 +17,7 @@
slot_flags = ITEM_SLOT_BACK
worn_icon = 'icons/mob/clothing/back.dmi' //since these can also get thrown into suit storage slots. if something goes on the belt, set this to null.
hitsound = 'sound/weapons/smash.ogg'
- pressure_resistance = ONE_ATMOSPHERE * 5
+ //pressure_resistance = ONE_ATMOSPHERE * 5
force = 5
throwforce = 10
throw_speed = 1
@@ -89,7 +89,7 @@
AddComponent(/datum/component/atmos_reaction_recorder, reset_criteria = list(COMSIG_GASMIX_MERGING = air_contents, COMSIG_GASMIX_REMOVING = air_contents), target_list = reaction_info)
- // This is separate from the reaction recorder.
+ // This is separate from the reaction recorder.
// In this case we are only listening to determine if the tank is overpressurized but not destroyed.
RegisterSignal(air_contents, COMSIG_GASMIX_MERGED, .proc/merging_information)
@@ -119,7 +119,7 @@
. += span_notice("If you want any more information you'll need to get closer.")
return
- . += span_notice("The pressure gauge reads [round(src.air_contents.return_pressure(),0.01)] kPa.")
+ . += span_notice("The pressure gauge reads [round(src.air_contents.returnPressure(),0.01)] kPa.")
var/celsius_temperature = air_contents.temperature-T0C
var/descriptive
@@ -150,7 +150,7 @@
var/mob/living/carbon/human/H = user
user.visible_message(span_suicide("[user] is putting [src]'s valve to [user.p_their()] lips! It looks like [user.p_theyre()] trying to commit suicide!"))
playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
- if(!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
+ if(!QDELETED(H) && air_contents && air_contents.returnPressure() >= 1000)
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
H.inflate_gib()
return MANUAL_SUICIDE
@@ -185,7 +185,7 @@
/obj/item/tank/ui_data(mob/user)
. = list(
- "tankPressure" = round(air_contents.return_pressure()),
+ "tankPressure" = round(air_contents.returnPressure()),
"releasePressure" = round(distribute_pressure)
)
@@ -222,6 +222,7 @@
return air_contents.remove(amount)
/obj/item/tank/return_air()
+ RETURN_TYPE(/datum/gas_mixture)
START_PROCESSING(SSobj, src)
return air_contents
@@ -244,7 +245,7 @@
if(!air_contents)
return null
- var/tank_pressure = air_contents.return_pressure()
+ var/tank_pressure = air_contents.returnPressure()
var/actual_distribute_pressure = clamp(tank_pressure, 0, distribute_pressure)
// Lets do some algebra to understand why this works, yeah?
@@ -263,7 +264,7 @@
return
//Allow for reactions
- excited = (excited | air_contents.react(src))
+ excited = (excited | air_contents.react())
excited = (excited | handle_tolerances(delta_time))
excited = (excited | leaking)
@@ -276,7 +277,7 @@
var/atom/location = loc
if(!location)
return
- var/datum/gas_mixture/leaked_gas = air_contents.remove_ratio(0.25)
+ var/datum/gas_mixture/leaked_gas = air_contents.removeRatio(0.25)
location.assume_air(leaked_gas)
/**
@@ -290,8 +291,8 @@
if(!air_contents)
return FALSE
- var/pressure = air_contents.return_pressure()
- var/temperature = air_contents.return_temperature()
+ var/pressure = air_contents.returnPressure()
+ var/temperature = air_contents.get_temperature()
if(temperature >= TANK_MELT_TEMPERATURE)
var/temperature_damage_ratio = (temperature - TANK_MELT_TEMPERATURE) / temperature
take_damage(max_integrity * temperature_damage_ratio * delta_time, BURN, FIRE, FALSE, NONE)
@@ -323,24 +324,56 @@
if(!air_contents)
return ..()
+ var/turf/T = get_turf(src)
+ if(!T)
+ return ..()
+ T.hotspot_expose(air_contents.temperature, 70, 1)
+ T.assume_air(air_contents)
/// Handle fragmentation
- var/pressure = air_contents.return_pressure()
+ var/pressure = air_contents.returnPressure()
if(pressure > TANK_FRAGMENT_PRESSURE)
if(!istype(loc, /obj/item/transfer_valve))
log_bomber(get_mob_by_key(fingerprintslast), "was last key to touch", src, "which ruptured explosively")
- //Give the gas a chance to build up more pressure through reacting
- air_contents.react(src)
- pressure = air_contents.return_pressure()
-
- // As of writing this this is calibrated to maxcap at 140L and 160atm.
- var/power = (air_contents.volume * (pressure - TANK_FRAGMENT_PRESSURE)) / TANK_FRAGMENT_SCALE
- log_atmos("[type] exploded with a power of [power] and a mix of ", air_contents)
- dyn_explosion(src, power, flash_range = 1.5, ignorecap = FALSE)
+ //Give the gas a chance to build up more pressure through reacting. Alot.
+ air_contents.react()
+ air_contents.react()
+ air_contents.react()
+
+ pressure = air_contents.returnPressure()
+
+ var/strength = ((pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE)
+ var/mult = ((air_contents.volume/140)**(1/2)) * (air_contents.total_moles**2/3)/((29*0.64) **2/3)
+
+ log_atmos("[type] exploded with a power of [strength * mult] and a mix of ", air_contents)
+ explosion(
+ src,
+ round(mult*strength*0.15),
+ round(mult*strength*0.35),
+ round(mult*strength*0.80),
+ round(mult*strength*1.20),
+ )
+ var/num_fragments = round(rand(8,10) * sqrt(strength * mult))
+ ///Holy. Fucking. Shit. This is AGONIZING. Give me /obj/proc/fragmentate() PLEASE.
+ AddComponent(/datum/component/pellet_cloud, projectile_type = /obj/projectile/bullet/shrapnel, magnitude = num_fragments)
+ SEND_SIGNAL(src, COMSIG_TANK_SNOWFLAKE_PELLET_TRIGGER)
+
+ else if (pressure > TANK_RUPTURE_PRESSURE)
+ playsound(T, 'sound/weapons/gun/shotgun/shot.ogg', 20, 1)
+ visible_message("[icon2html(src, viewers(get_turf(src)))] \The [src] flies apart!", "You hear a bang!")
+
+ var/strength = 1+((pressure-TANK_LEAK_PRESSURE)/TANK_FRAGMENT_SCALE)
+
+ var/mult = (air_contents.total_moles**2/3)/((29*0.64) **2/3) //tanks appear to be experiencing a reduction on scale of about 0.64 total moles
+
+ var/num_fragments = round(rand(6,8) * sqrt(strength * mult)) //Less chunks, but bigger
+ AddComponent(/datum/component/pellet_cloud, projectile_type = /obj/projectile/bullet/shrapnel/mega, magnitude = num_fragments)
+ SEND_SIGNAL(src, COMSIG_TANK_SNOWFLAKE_PELLET_TRIGGER)
+
return ..()
/obj/item/tank/proc/merging_information()
SIGNAL_HANDLER
- if(air_contents.return_pressure() > TANK_FRAGMENT_PRESSURE)
+ if(air_contents.returnPressure() > TANK_FRAGMENT_PRESSURE)
explosion_info += TANK_MERGE_OVERPRESSURE
/obj/item/tank/proc/explosion_information()
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 17f039c0d0f..41ed4bd98c5 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -131,7 +131,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
var/turf/T = loc
if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE))
return
- if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
+ if(uses_integrity && exposed_temperature && !(resistance_flags & FIRE_PROOF))
take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0)
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF))
resistance_flags |= ON_FIRE
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 288ec91c7c3..71eec65afd6 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -30,6 +30,9 @@
vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of obj in openspace.
+ ///How large is the object, used for stuff like whether it can fit in backpacks or not
+ var/w_class = null
+
/// Map tag for something. Tired of it being used on snowflake items. Moved here for some semblance of a standard.
/// Next pr after the network fix will have me refactor door interactions, so help me god.
var/id_tag = null
@@ -116,8 +119,8 @@
if(breath_request>0)
var/datum/gas_mixture/environment = return_air()
- var/breath_percentage = BREATH_VOLUME / environment.return_volume()
- return remove_air(environment.total_moles() * breath_percentage)
+ var/breath_percentage = BREATH_VOLUME / environment.get_volume()
+ return remove_air(environment.get_moles() * breath_percentage)
else
return null
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 08773b1cf19..a69ef63a050 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -1,7 +1,7 @@
/// Inert structures, such as girders, machine frames, and crates/lockers.
/obj/structure
icon = 'icons/obj/structures.dmi'
- pressure_resistance = 8
+ //pressure_resistance = 8
max_integrity = 300
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
layer = BELOW_OBJ_LAYER
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index a59bfebb0be..6667cdae921 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -63,22 +63,22 @@
canSmoothWith = list(SMOOTH_GROUP_ALIEN_RESIN)
max_integrity = 200
var/resintype = null
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
/obj/structure/alien/resin/Initialize(mapload)
. = ..()
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
/obj/structure/alien/resin/Destroy()
- air_update_turf(TRUE, FALSE)
+ //air_update_turf(TRUE, FALSE)
. = ..()
-
+/*
/obj/structure/alien/resin/Move()
var/turf/T = loc
. = ..()
move_update_air(T)
-
+*/
/obj/structure/alien/resin/wall
name = "resin wall"
desc = "Thick resin solidified into a wall."
@@ -166,8 +166,6 @@
set_base_icon()
- AddElement(/datum/element/atmos_sensitive, mapload)
-
/obj/structure/alien/weeds/Destroy()
if(parent_node)
UnregisterSignal(parent_node, COMSIG_PARENT_QDELETING)
@@ -202,7 +200,7 @@
qdel(src)
return
//lets try to grow in a direction
- for(var/turf/check_turf in src_turf.get_atmos_adjacent_turfs())
+ for(var/turf/check_turf in get_adjacent_open_turfs(src_turf))
//we cannot grow on blacklisted turfs
if(is_type_in_list(check_turf, blacklisted_turfs))
continue
@@ -244,13 +242,11 @@
* Called to delete the weed
*/
/obj/structure/alien/weeds/proc/do_qdel()
- qdel(src)
-
-/obj/structure/alien/weeds/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 300
+ qdel(src) //WHY THE FUCK DOES THIS EXIST? WHAT THE FUCK?
/obj/structure/alien/weeds/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(5, BURN, 0, 0)
+ if(exposed_temperature > T0C + 100)
+ take_damage(5, BURN, 0, 0)
/obj/structure/alien/weeds/node
name = "glowing resin"
@@ -353,8 +349,6 @@
if(status == BURST)
atom_integrity = integrity_failure * max_integrity
- AddElement(/datum/element/atmos_sensitive, mapload)
-
/obj/structure/alien/egg/update_icon_state()
switch(status)
if(GROWING)
@@ -426,10 +420,11 @@
break
/obj/structure/alien/egg/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 500
+ return exposed_temperature > 500 ? TRUE : 0
/obj/structure/alien/egg/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(5, BURN, 0, 0)
+ if(exposed_temperature > 500)
+ take_damage(5, BURN, 0, 0)
/obj/structure/alien/egg/atom_break(damage_flag)
. = ..()
diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm
index 6bfb760817f..43cfa1e1b1c 100644
--- a/code/game/objects/structures/bonfire.dm
+++ b/code/game/objects/structures/bonfire.dm
@@ -61,6 +61,7 @@
return ..()
if(used_item.get_temperature())
start_burning()
+
if(grill)
if(istype(used_item, /obj/item/melee/roastingstick))
return FALSE
@@ -76,6 +77,7 @@
used_item.pixel_y = used_item.base_pixel_y + clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(world.icon_size/2), world.icon_size/2)
else
return ..()
+ return ..()
/obj/structure/bonfire/attack_hand(mob/user, list/modifiers)
@@ -98,9 +100,9 @@
/obj/structure/bonfire/proc/check_oxygen()
if(isopenturf(loc))
var/turf/open/bonfire_turf = loc
- if(bonfire_turf.air)
- var/loc_gases = bonfire_turf.air.gases
- if(loc_gases[/datum/gas/oxygen] && loc_gases[/datum/gas/oxygen][MOLES] >= 5)
+ var/datum/gas_mixture/local_gas = bonfire_turf.return_air()
+ if(local_gas)
+ if(local_gas.hasGas(GAS_OXYGEN, 5))
return TRUE
return FALSE
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 8c5695d6185..f169e6a6d28 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -697,9 +697,6 @@
/obj/structure/closet/AllowDrop()
return TRUE
-/obj/structure/closet/return_temperature()
- return
-
/obj/structure/closet/proc/locker_carbon(datum/source, mob/living/carbon/shover, mob/living/carbon/target, shove_blocked)
SIGNAL_HANDLER
if(!opened && (locked || welded)) //Yes this could be less code, no I don't care
diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm
index 8aa3ce169af..267cacfa139 100644
--- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm
+++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm
@@ -325,9 +325,8 @@
air_contents = new(50) //liters
air_contents.temperature = T20C
- air_contents.assert_gases(/datum/gas/oxygen, /datum/gas/nitrous_oxide)
- air_contents.gases[/datum/gas/oxygen][MOLES] = (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
- air_contents.gases[/datum/gas/nitrous_oxide][MOLES] = (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
+ air_contents.adjustGas(GAS_OXYGEN, (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD)
+ air_contents.adjustGas(GAS_N2O, (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD)
/obj/structure/closet/body_bag/environmental/prisoner/syndicate/Destroy()
if(air_contents)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 49c62124bcd..031ce0748b5 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -11,7 +11,7 @@
new /obj/item/radio/headset/heads/ce(src)
new /obj/item/megaphone/command(src)
new /obj/item/areaeditor/blueprints(src)
- new /obj/item/holosign_creator/atmos(src)
+ new /obj/item/storage/briefcase/inflatable(src)
new /obj/item/assembly/flash/handheld(src)
new /obj/item/door_remote/chief_engineer(src)
new /obj/item/pipe_dispenser(src)
@@ -78,7 +78,7 @@
new /obj/item/pipe_dispenser(src)
new /obj/item/storage/toolbox/mechanical(src)
new /obj/item/tank/internals/emergency_oxygen/engi(src)
- new /obj/item/holosign_creator/atmos(src)
+ new /obj/item/storage/briefcase/inflatable(src)
new /obj/item/watertank/atmos(src)
new /obj/item/clothing/suit/fire/atmos(src)
new /obj/item/clothing/mask/gas/atmos(src)
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 0c0a849ef62..04b8a0d52ec 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -17,7 +17,7 @@
smoothing_groups = list(SMOOTH_GROUP_CLOSED_TURFS, SMOOTH_GROUP_WALLS)
canSmoothWith = list(SMOOTH_GROUP_SHUTTERS_BLASTDOORS, SMOOTH_GROUP_WALLS, SMOOTH_GROUP_AIRLOCK, SMOOTH_GROUP_WINDOW_FULLTILE)
can_be_unanchored = FALSE
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_PROC
rad_insulation = RAD_MEDIUM_INSULATION
material_flags = MATERIAL_EFFECTS
greyscale_config = /datum/greyscale_config/low_wall
@@ -37,7 +37,7 @@
/obj/structure/falsewall/Initialize()
. = ..()
color = null //Clear the color that's a mapping aid
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
set_wall_information(plating_material, reinf_material, wall_paint, stripe_paint)
/obj/structure/falsewall/update_greyscale()
@@ -86,7 +86,12 @@
set_opacity(density)
opening = FALSE
update_appearance()
- air_update_turf(TRUE, !density)
+ update_nearby_tiles()
+
+/obj/structure/falsewall/zas_canpass(turf/other)
+ if(QDELETED(src))
+ return AIR_ALLOWED
+ return ZONE_BLOCKED
/obj/structure/falsewall/update_icon(updates=ALL)//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open
. = ..()
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 8cb167389ce..56dac602b34 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -9,6 +9,8 @@
anchored = TRUE
density = TRUE
max_integrity = 200
+ rad_insulation = RAD_VERY_LIGHT_INSULATION
+ can_atmos_pass = CANPASS_ALWAYS
var/state = GIRDER_NORMAL
var/girderpasschance = GIRDER_PASSCHANCE_NORMAL // percentage chance that a projectile passes through the girder.
var/can_displace = TRUE //If the girder can be moved around by wrenching it
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 7afae3d0c5e..da5d3c9d5bc 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -11,8 +11,9 @@
density = TRUE
anchored = TRUE
pass_flags_self = PASSGRILLE
+ can_atmos_pass = CANPASS_ALWAYS
flags_1 = CONDUCT_1
- pressure_resistance = 5*ONE_ATMOSPHERE
+ //pressure_resistance = 5*ONE_ATMOSPHERE
armor = list(MELEE = 50, BULLET = 70, LASER = 70, ENERGY = 100, BOMB = 10, BIO = 100, FIRE = 0, ACID = 0)
max_integrity = 50
integrity_failure = 0.4
@@ -23,10 +24,6 @@
var/rods_amount = 2
var/rods_broken = TRUE
-/obj/structure/grille/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/atmos_sensitive, mapload)
-
/obj/structure/grille/Destroy()
update_cable_icons_on_turf(get_turf(src))
return ..()
@@ -257,11 +254,9 @@
return FALSE
return FALSE
-/obj/structure/grille/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > T0C + 1500 && !broken
-
/obj/structure/grille/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(1, BURN, 0, 0)
+ if(exposed_temperature > T0C + 1500 && !broken)
+ take_damage(1, BURN, 0, 0)
/obj/structure/grille/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(isobj(AM))
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index 0e8c5023747..a851d1ea07c 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -94,7 +94,7 @@
icon_state = "holo_firelock"
density = FALSE
anchored = TRUE
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
alpha = 150
rad_insulation = RAD_LIGHT_INSULATION
@@ -106,7 +106,7 @@
. = ..()
var/turf/local = get_turf(loc)
ADD_TRAIT(local, TRAIT_FIREDOOR_STOP, TRAIT_GENERIC)
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
/obj/structure/holosign/barrier/atmos/block_superconductivity() //Didn't used to do this, but it's "normal", and will help ease heat flow transitions with the players.
return TRUE
@@ -114,7 +114,7 @@
/obj/structure/holosign/barrier/atmos/Destroy()
var/turf/local = get_turf(loc)
REMOVE_TRAIT(local, TRAIT_FIREDOOR_STOP, TRAIT_GENERIC)
- air_update_turf(TRUE, FALSE)
+ update_nearby_tiles()
return ..()
/obj/structure/holosign/barrier/cyborg
diff --git a/code/game/objects/structures/industrial_lift.dm b/code/game/objects/structures/industrial_lift.dm
index 2209e12dfe9..c7e4f7bea2b 100644
--- a/code/game/objects/structures/industrial_lift.dm
+++ b/code/game/objects/structures/industrial_lift.dm
@@ -8,7 +8,7 @@
var/list/lift_platforms
/// Typepath list of what to ignore smashing through, controls all lifts
var/list/ignored_smashthroughs = list(
- /obj/machinery/power/supermatter_crystal,
+ //obj/machinery/power/supermatter_crystal,
/obj/structure/holosign
)
diff --git a/code/game/objects/structures/low_wall.dm b/code/game/objects/structures/low_wall.dm
index 76b0954ade5..770364e7112 100644
--- a/code/game/objects/structures/low_wall.dm
+++ b/code/game/objects/structures/low_wall.dm
@@ -9,6 +9,7 @@
density = TRUE
anchored = TRUE
pass_flags_self = PASSTABLE | LETPASSTHROW
+ can_atmos_pass = CANPASS_ALWAYS
layer = LOW_WALL_LAYER
max_integrity = 150
smoothing_flags = SMOOTH_BITMASK
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 0f709dcd547..ccfc6c74bf0 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -13,7 +13,7 @@
icon_state = "metal"
max_integrity = 200
armor = list(MELEE = 10, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 10, BIO = 100, FIRE = 50, ACID = 50)
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
rad_insulation = RAD_MEDIUM_INSULATION
material_flags = MATERIAL_EFFECTS
material_modifier = 0.25
@@ -33,18 +33,15 @@
var/obj/item/stack/initialized_mineral = new sheetType // Okay this kinda sucks.
set_custom_materials(initialized_mineral.mats_per_unit, sheetAmount)
qdel(initialized_mineral)
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
/obj/structure/mineral_door/Destroy()
- if(!door_opened)
- air_update_turf(TRUE, FALSE)
. = ..()
+ update_nearby_tiles()
/obj/structure/mineral_door/Move()
- var/turf/T = loc
. = ..()
- if(!door_opened)
- move_update_air(T)
+ update_nearby_tiles()
/obj/structure/mineral_door/Bumped(atom/movable/AM)
..()
@@ -104,7 +101,7 @@
set_density(FALSE)
door_opened = TRUE
layer = OPEN_DOOR_LAYER
- air_update_turf(TRUE, FALSE)
+ update_nearby_tiles()
update_appearance()
isSwitchingStates = FALSE
@@ -125,7 +122,7 @@
set_opacity(TRUE)
door_opened = FALSE
layer = initial(layer)
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
update_appearance()
isSwitchingStates = FALSE
@@ -144,7 +141,7 @@
/obj/structure/mineral_door/set_anchored(anchorvalue) //called in default_unfasten_wrench() chain
. = ..()
set_opacity(anchored ? !door_opened : FALSE)
- air_update_turf(TRUE, anchorvalue)
+ //air_update_turf(TRUE, anchorvalue)
/obj/structure/mineral_door/wrench_act(mob/living/user, obj/item/tool)
. = ..()
diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm
index 8604fd64825..587e1c90f79 100644
--- a/code/game/objects/structures/plasticflaps.dm
+++ b/code/game/objects/structures/plasticflaps.dm
@@ -7,7 +7,7 @@
armor = list(MELEE = 100, BULLET = 80, LASER = 80, ENERGY = 100, BOMB = 50, BIO = 100, FIRE = 50, ACID = 50)
density = FALSE
anchored = TRUE
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
/obj/structure/plasticflaps/opaque
opacity = TRUE
@@ -35,13 +35,13 @@
return TRUE
set_anchored(!anchored)
update_atmos_behaviour()
- air_update_turf(TRUE)
+ //air_update_turf(TRUE)
to_chat(user, span_notice("You [uraction] the floor."))
return TRUE
///Update the flaps behaviour to gases, if not anchored will let air pass through
/obj/structure/plasticflaps/proc/update_atmos_behaviour()
- can_atmos_pass = anchored ? ATMOS_PASS_YES : ATMOS_PASS_NO
+ can_atmos_pass = anchored ? CANPASS_ALWAYS : CANPASS_NEVER
/obj/structure/plasticflaps/wirecutter_act(mob/living/user, obj/item/W)
. = ..()
@@ -113,10 +113,12 @@
/obj/structure/plasticflaps/Initialize(mapload)
. = ..()
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
+/*
/obj/structure/plasticflaps/Destroy()
var/atom/oldloc = loc
. = ..()
if (oldloc)
- oldloc.air_update_turf(TRUE, FALSE)
+ oldloc./air_update_turf(TRUE, FALSE)
+*/
diff --git a/code/game/objects/structures/tram_walls.dm b/code/game/objects/structures/tram_walls.dm
index feee62e3799..616ad57c3b7 100644
--- a/code/game/objects/structures/tram_walls.dm
+++ b/code/game/objects/structures/tram_walls.dm
@@ -16,7 +16,7 @@
smoothing_groups = list(SMOOTH_GROUP_CLOSED_TURFS, SMOOTH_GROUP_WALLS)
canSmoothWith = list(SMOOTH_GROUP_WALLS)
can_be_unanchored = FALSE
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
rad_insulation = RAD_MEDIUM_INSULATION
material_flags = MATERIAL_EFFECTS
var/mineral = /obj/item/stack/sheet/iron
@@ -29,7 +29,7 @@
var/obj/item/stack/initialized_mineral = new mineral
set_custom_materials(initialized_mineral.mats_per_unit, mineral_amount)
qdel(initialized_mineral)
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
/obj/structure/tramwall/attackby(obj/item/welder, mob/user, params)
if(welder.tool_behaviour == TOOL_WELDER)
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index 951e1acbee2..63774fa5f9f 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -169,8 +169,7 @@
if(QDELETED(pod))
return
var/datum/gas_mixture/floor_mixture = loc.return_air()
- if(pod.air_contents.equalize(floor_mixture)) //equalize the pod's mix with the tile it's on
- air_update_turf(FALSE, FALSE)
+ pod.air_contents.shareRatio(floor_mixture, 1)
/obj/structure/transit_tube/station/init_tube_dirs()
switch(dir)
diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
index 1d1d5028d00..6006a945626 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
@@ -14,9 +14,8 @@
/obj/structure/transit_tube_pod/Initialize(mapload)
. = ..()
- air_contents.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
- air_contents.gases[/datum/gas/oxygen][MOLES] = MOLES_O2STANDARD
- air_contents.gases[/datum/gas/nitrogen][MOLES] = MOLES_N2STANDARD
+ air_contents.adjustGas(GAS_OXYGEN, MOLES_O2STANDARD)
+ air_contents.adjustGas(GAS_NITROGEN, MOLES_N2STANDARD)
air_contents.temperature = T20C
/obj/structure/transit_tube_pod/Destroy()
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 3852bc3267f..24115f9b8e6 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -27,13 +27,13 @@
var/facing = "l" //Does the windoor open to the left or right?
var/secure = FALSE //Whether or not this creates a secure windoor
var/state = "01" //How far the door assembly has progressed
- can_atmos_pass = ATMOS_PASS_PROC
+ can_atmos_pass = CANPASS_PROC
/obj/structure/windoor_assembly/Initialize(mapload, loc, set_dir)
. = ..()
if(set_dir)
setDir(set_dir)
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = .proc/on_exit,
@@ -41,16 +41,17 @@
AddElement(/datum/element/connect_loc, loc_connections)
AddComponent(/datum/component/simple_rotation, ROTATION_NEEDS_ROOM)
+ update_nearby_tiles()
/obj/structure/windoor_assembly/Destroy()
set_density(FALSE)
- air_update_turf(TRUE, FALSE)
+ update_nearby_tiles()
return ..()
/obj/structure/windoor_assembly/Move()
- var/turf/T = loc
+ update_nearby_tiles()
. = ..()
- move_update_air(T)
+ update_nearby_tiles()
/obj/structure/windoor_assembly/update_icon_state()
icon_state = "[facing]_[secure ? "secure_" : ""]windoor_assembly[state]"
@@ -69,11 +70,13 @@
if(istype(mover, /obj/structure/windoor_assembly) || istype(mover, /obj/machinery/door/window))
return valid_window_location(loc, mover.dir, is_fulltile = FALSE)
-/obj/structure/windoor_assembly/can_atmos_pass(turf/T, vertical = FALSE)
+/obj/structure/windoor_assembly/zas_canpass(turf/T)
+ if(QDELETED(src))
+ return AIR_ALLOWED
if(get_dir(loc, T) == dir)
- return !density
+ return density ? AIR_BLOCKED|ZONE_BLOCKED : ZONE_BLOCKED
else
- return TRUE
+ return ZONE_BLOCKED
/obj/structure/windoor_assembly/proc/on_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index bc8c17299e0..5ddd86e803e 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -4,14 +4,14 @@
icon_state = "window"
density = TRUE
layer = ABOVE_OBJ_LAYER //Just above doors
- pressure_resistance = 4*ONE_ATMOSPHERE
+ //pressure_resistance = 4*ONE_ATMOSPHERE
anchored = TRUE //initially is 0 for tile smoothing
flags_1 = ON_BORDER_1
max_integrity = 25
can_be_unanchored = TRUE
resistance_flags = ACID_PROOF
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 80, ACID = 100)
- can_atmos_pass = ATMOS_PASS_PROC
+ can_atmos_pass = CANPASS_PROC
rad_insulation = RAD_VERY_LIGHT_INSULATION
pass_flags_self = PASSGLASS
set_dir_on_move = FALSE
@@ -33,6 +33,10 @@
var/hit_sound = 'sound/effects/glasshit.ogg'
/// If some inconsiderate jerk has had their blood spilled on this window, thus making it cleanable
var/bloodied = FALSE
+ ///Snowflake for fire act damage
+ var/damage_per_fire_tick = 1
+ ///The amount of heat needed to start damaging the window
+ var/melting_point = T0C + 3000 //See, because some dipass decided to make the station 50% glass, NT opted to infuse all the windows with plasma.
/obj/structure/window/examine(mob/user)
. = ..()
@@ -58,7 +62,7 @@
if(reinf && anchored)
state = RWINDOW_SECURE
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
if(fulltile)
setDir()
@@ -69,7 +73,6 @@
flags_1 |= ALLOW_DARK_PAINTS_1
RegisterSignal(src, COMSIG_OBJ_PAINTED, .proc/on_painted)
- AddElement(/datum/element/atmos_sensitive, mapload)
AddComponent(/datum/component/simple_rotation, ROTATION_NEEDS_ROOM, AfterRotation = CALLBACK(src,.proc/AfterRotation))
var/static/list/loc_connections = list(
@@ -248,7 +251,7 @@
/obj/structure/window/set_anchored(anchorvalue)
..()
- air_update_turf(TRUE, anchorvalue)
+ //air_update_turf(TRUE, anchorvalue)
update_nearby_icons()
/obj/structure/window/proc/check_state(checked_state)
@@ -277,9 +280,22 @@
/obj/structure/window/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
+ var/initial_damage_percentage = get_integrity_percentage()
. = ..()
if(.) //received damage
update_nearby_icons()
+ if(atom_integrity > 0)
+ playsound(src, get_sfx(SFX_GLASS_CRACK), 100, TRUE)
+ var/damage_percentage = get_integrity_percentage()
+ if (damage_percentage >= 75 && initial_damage_percentage < 75)
+ visible_message(span_warning("\The [src] looks like it's about to shatter!"))
+ playsound(loc, get_sfx(SFX_GLASS_CRACK), 100, 1)
+ else if (damage_percentage >= 50 && initial_damage_percentage < 50)
+ visible_message(span_warning("\The [src] looks seriously damaged!"))
+ playsound(loc, get_sfx(SFX_GLASS_CRACK), 100, 1)
+ else if (damage_percentage >= 25 && initial_damage_percentage < 25)
+ visible_message(span_warning("Cracks begin to appear in \the [src]!"))
+ playsound(loc, get_sfx(SFX_GLASS_CRACK), 100, 1)
/obj/structure/window/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
@@ -291,12 +307,16 @@
if(BURN)
playsound(src, 'sound/items/welder.ogg', 100, TRUE)
+/obj/structure/window/ex_act(severity, target)
+ return ..(min(EXPLODE_DEVASTATE, severity + 1), target)
+
/obj/structure/window/deconstruct(disassembled = TRUE)
if(QDELETED(src))
return
if(!disassembled)
playsound(src, break_sound, 70, TRUE)
+ visible_message(span_danger("\The [src] shatters into pieces!"), null, "You hear glass shatter!")
if(!(flags_1 & NODECONSTRUCT_1))
for(var/obj/item/shard/debris in spawnDebris(drop_location()))
transfer_fingerprints_to(debris) // transfer fingerprints to shards only
@@ -313,7 +333,7 @@
. += new /obj/item/shard(location)
/obj/structure/window/proc/AfterRotation(mob/user, degrees)
- air_update_turf(TRUE, FALSE)
+ update_nearby_tiles()
/obj/structure/window/proc/on_painted(obj/structure/window/source, is_dark_color)
SIGNAL_HANDLER
@@ -324,20 +344,32 @@
/obj/structure/window/Destroy()
set_density(FALSE)
- air_update_turf(TRUE, FALSE)
update_nearby_icons()
- return ..()
+ can_atmos_pass = CANPASS_ALWAYS //hacky-sacky
+ update_nearby_tiles()
+
+ if(!fulltile)
+ var/turf/open/T = get_step(src, dir)
+ if(istype(T))
+ SSzas.mark_for_update(T)
+
+ . = ..()
/obj/structure/window/Move()
- var/turf/T = loc
+ update_nearby_tiles()
. = ..()
- if(anchored)
- move_update_air(T)
-/obj/structure/window/can_atmos_pass(turf/T, vertical = FALSE)
+/obj/structure/window/zas_canpass(turf/T)
+ if(QDELETED(src))
+ return AIR_ALLOWED
if(!anchored || !density)
- return TRUE
- return !(fulltile || dir == get_dir(loc, T))
+ return ZONE_BLOCKED
+ if(!fulltile)
+ if(get_dir(loc, T) & dir)
+ return AIR_BLOCKED|ZONE_BLOCKED
+ else
+ return AIR_ALLOWED
+ return AIR_BLOCKED|ZONE_BLOCKED
//This proc is used to update the icons of nearby windows.
/obj/structure/window/proc/update_nearby_icons()
@@ -362,11 +394,9 @@
crack_overlay = mutable_appearance('icons/obj/structures.dmi', "damage[ratio]", -(layer+0.1), appearance_flags = RESET_COLOR)
. += crack_overlay
-/obj/structure/window/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > T0C + heat_resistance
-
-/obj/structure/window/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(round(air.return_volume() / 100), BURN, 0, 0)
+/obj/structure/window/fire_act(exposed_temperature, exposed_volume)
+ if (exposed_temperature > melting_point)
+ take_damage(round(exposed_volume / 100), BURN, 0, 0)
/obj/structure/window/get_dumping_location()
return null
@@ -408,6 +438,7 @@
glass_type = /obj/item/stack/sheet/rglass
rad_insulation = RAD_HEAVY_INSULATION
receive_ricochet_chance_mod = 1.1
+ melting_point = T0C + 4000
//this is shitcode but all of construction is shitcode and needs a refactor, it works for now
//If you find this like 4 years later and construction still hasn't been refactored, I'm so sorry for this //Adding a timestamp, I found this in 2020, I hope it's from this year -Lemon
@@ -518,10 +549,10 @@
explosion_block = 1
glass_type = /obj/item/stack/sheet/plasmaglass
rad_insulation = RAD_NO_INSULATION
+ melting_point = 25000 //Yeah fuck you
/obj/structure/window/plasma/Initialize(mapload, direct)
. = ..()
- RemoveElement(/datum/element/atmos_sensitive)
/obj/structure/window/plasma/spawnDebris(location)
. = list()
@@ -555,6 +586,7 @@
damage_deflection = 21
explosion_block = 2
glass_type = /obj/item/stack/sheet/plasmarglass
+ melting_point = 25000
/obj/structure/window/reinforced/plasma/block_superconductivity()
return TRUE
@@ -616,6 +648,7 @@
smoothing_groups = list(SMOOTH_GROUP_WINDOW_FULLTILE)
canSmoothWith = list(SMOOTH_GROUP_WINDOW_FULLTILE, SMOOTH_GROUP_WALLS, SMOOTH_GROUP_AIRLOCK, SMOOTH_GROUP_SHUTTERS_BLASTDOORS)
glass_amount = 2
+ melting_point = 25000
/obj/structure/window/plasma/fulltile/unanchored
anchored = FALSE
@@ -636,6 +669,7 @@
smoothing_groups = list(SMOOTH_GROUP_WINDOW_FULLTILE)
canSmoothWith = list(SMOOTH_GROUP_WINDOW_FULLTILE, SMOOTH_GROUP_WALLS, SMOOTH_GROUP_AIRLOCK, SMOOTH_GROUP_SHUTTERS_BLASTDOORS)
glass_amount = 2
+ melting_point = 28000
/obj/structure/window/reinforced/plasma/fulltile/unanchored
anchored = FALSE
@@ -680,6 +714,8 @@
/obj/structure/window/reinforced/fulltile/ice
max_integrity = 150
glass_amount = 2
+ melting_point = T0C
+ damage_per_fire_tick = 15
//there is a sub shuttle window in survival_pod.dm for mining pods
/obj/structure/window/reinforced/shuttle//this is called reinforced because it is reinforced w/titanium
@@ -706,6 +742,8 @@
glass_type = /obj/item/stack/sheet/titaniumglass
glass_amount = 2
receive_ricochet_chance_mod = 1.2
+ melting_point = 8000
+ damage_per_fire_tick = 5
damage_deflection = 11
/obj/structure/window/reinforced/shuttle/narsie_act()
@@ -741,6 +779,7 @@
glass_type = /obj/item/stack/sheet/plastitaniumglass
glass_amount = 2
rad_insulation = RAD_HEAVY_INSULATION
+ melting_point = 10000000 //Yeah this thing isnt melting
/obj/structure/window/reinforced/plasma/plastitanium/unanchored
anchored = FALSE
@@ -763,13 +802,15 @@
glass_type = /obj/item/stack/sheet/paperframes
heat_resistance = 233
decon_speed = 10
- can_atmos_pass = ATMOS_PASS_YES
+ can_atmos_pass = CANPASS_ALWAYS
resistance_flags = FLAMMABLE
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 0, ACID = 0)
knock_sound = SFX_PAGE_TURN
bash_sound = 'sound/weapons/slashmiss.ogg'
break_sound = 'sound/items/poster_ripped.ogg'
hit_sound = 'sound/weapons/slashmiss.ogg'
+ melting_point = T0C
+ damage_per_fire_tick = 15
var/static/mutable_appearance/torn = mutable_appearance('icons/obj/smooth_structures/paperframes.dmi',icon_state = "torn", layer = ABOVE_OBJ_LAYER - 0.1)
var/static/mutable_appearance/paper = mutable_appearance('icons/obj/smooth_structures/paperframes.dmi',icon_state = "paper", layer = ABOVE_OBJ_LAYER - 0.1)
@@ -811,7 +852,7 @@
/obj/structure/window/paperframe/attackby(obj/item/W, mob/living/user)
if(W.get_temperature())
- fire_act(W.get_temperature())
+ fire_act(null, W.get_temperature(), null)
return
if(user.combat_mode)
return ..()
diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm
index 4ddf62bfdd8..a0c2d6075a7 100644
--- a/code/game/shuttle_engines.dm
+++ b/code/game/shuttle_engines.dm
@@ -10,7 +10,7 @@
smoothing_groups = list(SMOOTH_GROUP_SHUTTLE_PARTS)
max_integrity = 500
armor = list(MELEE = 100, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 50, ACID = 70) //default + ignores melee
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
/obj/structure/shuttle/engine
name = "engine"
diff --git a/code/game/sound.dm b/code/game/sound.dm
index b544b90401b..735ab0c72c3 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -140,7 +140,7 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
var/datum/gas_mixture/source_env = turf_source.return_air()
if(hearer_env && source_env)
- var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure())
+ var/pressure = min(hearer_env.returnPressure(), source_env.returnPressure())
if(pressure < ONE_ATMOSPHERE)
pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0)
else //space
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index e449993a1ee..a6aa1a60e8a 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -14,9 +14,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
qdel(thing, force=TRUE)
if(turf_type)
- var/turf/newT = ChangeTurf(turf_type, baseturf_type, flags)
- SSair.remove_from_active(newT)
- CALCULATE_ADJACENT_TURFS(newT, KILL_EXCITED)
+ ChangeTurf(turf_type, baseturf_type, flags)
/turf/proc/copyTurf(turf/T)
if(T.type != type)
@@ -43,8 +41,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
var/datum/component/wet_floor/WF = T.AddComponent(/datum/component/wet_floor)
WF.InheritComponent(slip)
if (copy_air)
- var/turf/open/openTurf = T
- openTurf.air.copy_from(air)
+ T.return_air().copyFrom(return_air())
//wrapper for ChangeTurf()s that you want to prevent/affect without overriding ChangeTurf() itself
/turf/proc/TerraformTurf(path, new_baseturf, flags)
@@ -92,12 +89,16 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
SEND_SIGNAL(src, COMSIG_TURF_CHANGE, path, new_baseturfs, flags, post_change_callbacks)
changing_turf = TRUE
+
qdel(src) //Just get the side effects and call Destroy
+
//We do this here so anything that doesn't want to persist can clear itself
var/list/old_comp_lookup = comp_lookup?.Copy()
var/list/old_signal_procs = signal_procs?.Copy()
var/turf/W = new path(src)
+ SSzas.mark_for_update(src) //handle the addition of the new turf.
+
// WARNING WARNING
// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS
// It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf
@@ -153,32 +154,22 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
return W
+/*
/turf/open/ChangeTurf(path, list/new_baseturfs, flags) //Resist the temptation to make this default to keeping air.
if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open))
var/datum/gas_mixture/stashed_air = new()
- stashed_air.copy_from(air)
- var/stashed_state = excited
- var/datum/excited_group/stashed_group = excited_group
+ stashed_air.copyFrom(air)
. = ..() //If path == type this will return us, don't bank on making a new type
if (!.) // changeturf failed or didn't do anything
return
var/turf/open/newTurf = .
- newTurf.air.copy_from(stashed_air)
- newTurf.excited = stashed_state
- newTurf.excited_group = stashed_group
- #ifdef VISUALIZE_ACTIVE_TURFS
- if(stashed_state)
- newTurf.add_atom_colour(COLOR_VIBRANT_LIME, TEMPORARY_COLOUR_PRIORITY)
- #endif
- if(stashed_group)
- if(stashed_group.should_display || SSair.display_all_groups)
- stashed_group.display_turf(newTurf)
+ newTurf.air.copyFrom(stashed_air)
+ SSzas.mark_for_update(newTurf)
else
- SSair.remove_from_active(src) //Clean up wall excitement, and refresh excited groups
if(ispath(path,/turf/closed) || ispath(path,/turf/cordon))
flags |= CHANGETURF_RECALC_ADJACENT
return ..()
-
+*/
/// Take off the top layer turf and replace it with the next baseturf down
/turf/proc/ScrapeAway(amount=1, flags)
if(!amount)
@@ -299,65 +290,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
//If you modify this function, ensure it works correctly with lateloaded map templates.
/turf/proc/AfterChange(flags, oldType) //called after a turf has been replaced in ChangeTurf()
levelupdate()
- if(flags & CHANGETURF_RECALC_ADJACENT)
- immediate_calculate_adjacent_turfs()
- if(ispath(oldType, /turf/closed) && istype(src, /turf/open))
- SSair.add_to_active(src)
- else //In effect, I want closed turfs to make their tile active when sheered, but we need to queue it since they have no adjacent turfs
- CALCULATE_ADJACENT_TURFS(src, (!(ispath(oldType, /turf/closed) && istype(src, /turf/open)) ? NORMAL_TURF : MAKE_ACTIVE))
- //update firedoor adjacency
- var/list/turfs_to_check = get_adjacent_open_turfs(src) | src
- for(var/I in turfs_to_check)
- var/turf/T = I
- for(var/obj/machinery/door/firedoor/FD in T)
- FD.CalculateAffectingAreas()
-
HandleTurfChange(src)
/turf/open/AfterChange(flags, oldType)
..()
RemoveLattice()
if(!(flags & (CHANGETURF_IGNORE_AIR | CHANGETURF_INHERIT_AIR)))
- Assimilate_Air()
-
-//////Assimilate Air//////
-/turf/open/proc/Assimilate_Air()
- var/turf_count = LAZYLEN(atmos_adjacent_turfs)
- if(blocks_air || !turf_count) //if there weren't any open turfs, no need to update.
- return
-
- var/datum/gas_mixture/total = new//Holders to assimilate air from nearby turfs
- var/list/total_gases = total.gases
- //Stolen blatently from self_breakdown
- var/list/turf_list = atmos_adjacent_turfs + src
- var/turflen = turf_list.len
- var/energy = 0
- var/heat_cap = 0
-
- for(var/t in turf_list)
- var/turf/open/T = t
- //Cache?
- var/datum/gas_mixture/turf/mix = T.air
- //"borrowing" this code from merge(), I need to play with the temp portion. Lets expand it out
- //temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
- var/capacity = mix.heat_capacity()
- energy += mix.temperature * capacity
- heat_cap += capacity
-
- var/list/giver_gases = mix.gases
- for(var/giver_id in giver_gases)
- ASSERT_GAS(giver_id, total)
- total_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
-
- total.temperature = energy / heat_cap
- for(var/id in total_gases)
- total_gases[id][MOLES] /= turflen
-
- for(var/t in turf_list)
- var/turf/open/T = t
- T.air.copy_from(total)
- T.update_visuals()
- SSair.add_to_active(T)
+ //Assimilate_Air()
+ SSzas.mark_for_update(src)
/turf/proc/ReplaceWithLattice()
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
diff --git a/code/game/turfs/closed/_closed.dm b/code/game/turfs/closed/_closed.dm
index 35be7b8136c..f52f33f61dc 100644
--- a/code/game/turfs/closed/_closed.dm
+++ b/code/game/turfs/closed/_closed.dm
@@ -2,13 +2,14 @@
layer = CLOSED_TURF_LAYER
opacity = TRUE
density = TRUE
- blocks_air = TRUE
+ blocks_air = AIR_BLOCKED
rad_insulation = RAD_MEDIUM_INSULATION
pass_flags_self = PASSCLOSEDTURF
-
+/*
/turf/closed/AfterChange()
. = ..()
SSair.high_pressure_delta -= src
+*/
/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm
index b3a40a1b96d..746963b1d25 100644
--- a/code/game/turfs/closed/minerals.dm
+++ b/code/game/turfs/closed/minerals.dm
@@ -10,7 +10,7 @@
smoothing_groups = list(SMOOTH_GROUP_CLOSED_TURFS, SMOOTH_GROUP_MINERAL_WALLS)
canSmoothWith = list(SMOOTH_GROUP_MINERAL_WALLS)
baseturfs = /turf/open/misc/asteroid/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
opacity = TRUE
density = TRUE
plane = GAME_PLANE_UPPER
@@ -130,10 +130,11 @@
var/old_type = type
if(defer_change) // TODO: make the defer change var a var for any changeturf flag
flags = CHANGETURF_DEFER_CHANGE
- var/turf/open/mined = ScrapeAway(null, flags)
+ ScrapeAway(null, flags)
+ SSzas.mark_for_update(src)
addtimer(CALLBACK(src, .proc/AfterChange, flags, old_type), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE) //beautiful destruction
- mined.update_visuals()
+ //mined.update_visuals()
/turf/closed/mineral/attack_animal(mob/living/simple_animal/user, list/modifiers)
if((user.environment_smash & ENVIRONMENT_SMASH_WALLS) || (user.environment_smash & ENVIRONMENT_SMASH_RWALLS))
@@ -223,7 +224,7 @@
/turf/closed/mineral/random/high_chance/volcanic
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
mineralSpawnChanceList = list(
/obj/item/stack/ore/uranium = 35, /obj/item/stack/ore/diamond = 30, /obj/item/stack/ore/gold = 45, /obj/item/stack/ore/titanium = 45,
@@ -248,7 +249,7 @@
/turf/closed/mineral/random/volcanic
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
mineralChance = 10
@@ -268,7 +269,7 @@
defer_change = TRUE
turf_type = /turf/open/misc/asteroid/snow/icemoon
baseturfs = /turf/open/misc/asteroid/snow/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
weak_turf = TRUE
/turf/closed/mineral/random/snow/Change_Ore(ore_type, random = 0)
@@ -310,7 +311,7 @@
/turf/closed/mineral/random/labormineral/volcanic
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
mineralSpawnChanceList = list(
/obj/item/stack/ore/uranium = 3, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 8, /obj/item/stack/ore/titanium = 8,
@@ -329,7 +330,7 @@
defer_change = TRUE
turf_type = /turf/open/misc/asteroid/snow/icemoon
baseturfs = /turf/open/misc/asteroid/snow/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
defer_change = TRUE
mineralSpawnChanceList = list(
/obj/item/stack/ore/uranium = 3, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 8, /obj/item/stack/ore/titanium = 8,
@@ -356,7 +357,7 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
baseturfs = /turf/open/misc/asteroid/snow/ice
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
defer_change = TRUE
/turf/closed/mineral/uranium
@@ -374,7 +375,7 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
baseturfs = /turf/open/misc/asteroid/snow/ice
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
defer_change = TRUE
/turf/closed/mineral/gold
@@ -384,7 +385,7 @@
/turf/closed/mineral/gold/volcanic
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/silver
@@ -394,7 +395,7 @@
/turf/closed/mineral/silver/ice/icemoon
turf_type = /turf/open/misc/asteroid/snow/ice/icemoon
baseturfs = /turf/open/misc/asteroid/snow/ice/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/titanium
mineralType = /obj/item/stack/ore/titanium
@@ -411,7 +412,7 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
baseturfs = /turf/open/misc/asteroid/snow/ice
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
defer_change = TRUE
/turf/closed/mineral/bananium
@@ -427,13 +428,13 @@
/turf/closed/mineral/bscrystal/volcanic
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/volcanic
turf_type = /turf/open/misc/asteroid/basalt
baseturfs = /turf/open/misc/asteroid/basalt
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
/turf/closed/mineral/volcanic/lava_land_surface
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
@@ -449,7 +450,7 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
canSmoothWith = list(SMOOTH_GROUP_CLOSED_TURFS)
baseturfs = /turf/open/misc/ashplanet/wateryrock
- initial_gas_mix = OPENTURF_LOW_PRESSURE
+ initial_gas = OPENTURF_LOW_PRESSURE
turf_type = /turf/open/misc/ashplanet/rocky
defer_change = TRUE
@@ -462,14 +463,14 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
canSmoothWith = list(SMOOTH_GROUP_CLOSED_TURFS)
baseturfs = /turf/open/misc/asteroid/snow
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
turf_type = /turf/open/misc/asteroid/snow
defer_change = TRUE
/turf/closed/mineral/snowmountain/icemoon
turf_type = /turf/open/misc/asteroid/snow/icemoon
baseturfs = /turf/open/misc/asteroid/snow/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/snowmountain/cavern
name = "ice cavern rock"
@@ -484,7 +485,7 @@
/turf/closed/mineral/snowmountain/cavern/icemoon
baseturfs = /turf/open/misc/asteroid/snow/ice/icemoon
turf_type = /turf/open/misc/asteroid/snow/ice/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
//yoo RED ROCK RED ROCK
@@ -598,14 +599,15 @@
var/old_type = type
if(defer_change) // TODO: make the defer change var a var for any changeturf flag
flags = CHANGETURF_DEFER_CHANGE
- var/turf/open/mined = ScrapeAway(null, flags)
+ ScrapeAway(null, flags)
+ SSzas.mark_for_update(src)
addtimer(CALLBACK(src, .proc/AfterChange, flags, old_type), 1, TIMER_UNIQUE)
- mined.update_visuals()
+ //mined.update_visuals()
/turf/closed/mineral/gibtonite/volcanic
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/gibtonite/ice
@@ -615,20 +617,20 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/misc/asteroid/snow/ice
baseturfs = /turf/open/misc/asteroid/snow/ice
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
defer_change = TRUE
/turf/closed/mineral/gibtonite/ice/icemoon
turf_type = /turf/open/misc/asteroid/snow/ice/icemoon
baseturfs = /turf/open/misc/asteroid/snow/ice/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/strong
name = "Very strong rock"
desc = "Seems to be stronger than the other rocks in the area. Only a master of mining techniques could destroy this."
turf_type = /turf/open/misc/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
defer_change = 1
smooth_icon = 'icons/turf/walls/legacy/rock_wall.dmi'
base_icon_state = "rock_wall"
@@ -656,10 +658,11 @@
var/old_type = type
if(defer_change) // TODO: make the defer change var a var for any changeturf flag
flags = CHANGETURF_DEFER_CHANGE
- var/turf/open/mined = ScrapeAway(null, flags)
+ ScrapeAway(null, flags)
+ SSzas.mark_for_update(src)
addtimer(CALLBACK(src, .proc/AfterChange, flags, old_type), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE) //beautiful destruction
- mined.update_visuals()
+ //mined.update_visuals()
H.mind?.adjust_experience(/datum/skill/mining, 100) //yay!
/turf/closed/mineral/strong/proc/drop_ores()
diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm
index 09b995b0dee..8a110cfb643 100644
--- a/code/game/turfs/closed/walls.dm
+++ b/code/game/turfs/closed/walls.dm
@@ -7,10 +7,9 @@
icon_state = "wall-0"
base_icon_state = "wall"
explosion_block = 1
-
+ blocks_air = AIR_BLOCKED
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 62500 //a little over 5 cm thick , 62500 for 1 m by 2.5 m by 0.25 m iron wall. also indicates the temperature at wich the wall will melt (currently only able to melt with H/E pipes)
-
baseturfs = /turf/open/floor/plating
flags_ricochet = RICOCHET_HARD
diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm
index 5e93cc1cf66..185c457e323 100644
--- a/code/game/turfs/open/_open.dm
+++ b/code/game/turfs/open/_open.dm
@@ -1,12 +1,14 @@
/turf/open
plane = FLOOR_PLANE
var/slowdown = 0 //negative for faster, positive for slower
-
+ initial_gas = OPENTURF_DEFAULT_ATMOS
+ z_flags = Z_ATMOS_IN_UP|Z_ATMOS_OUT_UP
var/footstep = null
var/barefootstep = null
var/clawfootstep = null
var/heavyfootstep = null
+
//direction is direction of travel of A
/turf/open/zPassIn(atom/movable/A, direction, turf/source)
if(direction == DOWN)
@@ -35,7 +37,7 @@
/turf/open/update_icon()
. = ..()
- update_visuals()
+ //update_visuals()
/turf/open/indestructible
name = "floor"
@@ -46,6 +48,7 @@
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
tiled_dirt = TRUE
+ simulated = FALSE
/turf/open/indestructible/Melt()
to_be_destroyed = FALSE
@@ -97,7 +100,7 @@
icon = 'icons/turf/floors.dmi'
icon_state = "necro1"
baseturfs = /turf/open/indestructible/necropolis
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
footstep = FOOTSTEP_LAVA
barefootstep = FOOTSTEP_LAVA
clawfootstep = FOOTSTEP_LAVA
@@ -110,23 +113,21 @@
icon_state = "necro[rand(2,3)]"
/turf/open/indestructible/necropolis/air
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ initial_gas = OPENTURF_DEFAULT_ATMOS
/turf/open/indestructible/boss //you put stone tiles on this and use it as a base
name = "necropolis floor"
icon = 'icons/turf/boss_floors.dmi'
icon_state = "boss"
baseturfs = /turf/open/indestructible/boss
- planetary_atmos = TRUE
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
/turf/open/indestructible/boss/air
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ initial_gas = OPENTURF_DEFAULT_ATMOS
/turf/open/indestructible/hierophant
icon = 'icons/turf/floors/hierophant_floor.dmi'
- planetary_atmos = TRUE
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
baseturfs = /turf/open/indestructible/hierophant
smoothing_flags = SMOOTH_CORNERS
tiled_dirt = FALSE
@@ -148,7 +149,7 @@
/turf/open/indestructible/binary
name = "tear in the fabric of reality"
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
baseturfs = /turf/open/indestructible/binary
icon_state = "binary"
footstep = null
@@ -160,7 +161,7 @@
icon_state = "bluespace"
blocks_air = TRUE
baseturfs = /turf/open/indestructible/airblock
-
+/*
/turf/open/Initalize_Atmos(times_fired)
excited = FALSE
update_visuals()
@@ -174,16 +175,17 @@
//testing("Active turf found. Return value of compare(): [is_active]")
excited = TRUE
SSair.active_turfs += src
+*/
/turf/open/GetHeatCapacity()
- . = air.heat_capacity()
+ . = air.getHeatCapacity()
-/turf/open/GetTemperature()
- . = air.temperature
+/turf/open/return_temperature()
+ . = return_air().temperature
/turf/open/TakeTemperature(temp)
air.temperature += temp
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
/turf/open/proc/freeze_turf()
for(var/obj/I in contents)
diff --git a/code/game/turfs/open/ashplanet.dm b/code/game/turfs/open/ashplanet.dm
index 920728f1cf9..2087bd32200 100644
--- a/code/game/turfs/open/ashplanet.dm
+++ b/code/game/turfs/open/ashplanet.dm
@@ -7,8 +7,7 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
desc = "The ground is covered in volcanic ash."
baseturfs = /turf/open/misc/ashplanet/wateryrock //I assume this will be a chasm eventually, once this becomes an actual surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = LAVALAND_DEFAULT_ATMOS
footstep = FOOTSTEP_SAND
barefootstep = FOOTSTEP_SAND
diff --git a/code/game/turfs/open/asteroid.dm b/code/game/turfs/open/asteroid.dm
index 2a0769a1c24..74c1d36ac0a 100644
--- a/code/game/turfs/open/asteroid.dm
+++ b/code/game/turfs/open/asteroid.dm
@@ -14,6 +14,8 @@
clawfootstep = FOOTSTEP_SAND
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
+ simulated = TRUE //Kilostation
+
/// Base turf type to be created by the tunnel
var/turf_type = /turf/open/misc/asteroid
/// Probability floor has a different icon state
@@ -106,6 +108,9 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
digResult = /obj/item/stack/ore/glass/basalt
broken_state = "basalt_dug"
+ initial_gas = LAVALAND_DEFAULT_ATMOS
+ simulated = FALSE //OH *FUCK* NO.
+
/turf/open/misc/asteroid/basalt/getDug()
set_light(0)
GLOB.dug_up_basalt |= src
@@ -119,7 +124,7 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
baseturfs = /turf/open/lava/smooth
/turf/open/misc/asteroid/basalt/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/misc/asteroid/basalt/Initialize(mapload)
. = ..()
@@ -135,17 +140,18 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
///////Surface. The surface is warm, but survivable without a suit. Internals are required. The floors break to chasms, which drop you into the underground.
/turf/open/misc/asteroid/basalt/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = LAVALAND_DEFAULT_ATMOS
baseturfs = /turf/open/lava/smooth/lava_land_surface
/turf/open/misc/asteroid/lowpressure
- initial_gas_mix = OPENTURF_LOW_PRESSURE
+ initial_gas = OPENTURF_LOW_PRESSURE
baseturfs = /turf/open/misc/asteroid/lowpressure
turf_type = /turf/open/misc/asteroid/lowpressure
/turf/open/misc/asteroid/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
+ temperature = T0C
+
baseturfs = /turf/open/misc/asteroid/airless
turf_type = /turf/open/misc/asteroid/airless
@@ -158,10 +164,13 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
icon_state = "snow"
base_icon_state = "snow"
broken_state = "snow_dug"
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
slowdown = 2
flags_1 = NONE
- planetary_atmos = TRUE
+
+ simulated = FALSE
+ initial_gas = ICEMOON_DEFAULT_ATMOS
+
bullet_sizzle = TRUE
bullet_bounce_sound = null
digResult = /obj/item/stack/sheet/mineral/snow
@@ -178,19 +187,16 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
/turf/open/misc/asteroid/snow/icemoon
baseturfs = /turf/open/openspace/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
slowdown = 0
/turf/open/lava/plasma/ice_moon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
baseturfs = /turf/open/lava/plasma/ice_moon
- planetary_atmos = TRUE
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/misc/asteroid/snow/ice
name = "icy snow"
desc = "Looks colder."
baseturfs = /turf/open/misc/asteroid/snow/ice
- initial_gas_mix = "n2=82;plasma=24;TEMP=120"
floor_variance = 0
icon_state = "snow-ice"
base_icon_state = "snow-ice"
@@ -204,27 +210,27 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
/turf/open/misc/asteroid/snow/ice/icemoon
baseturfs = /turf/open/misc/asteroid/snow/ice/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
- planetary_atmos = TRUE
+
slowdown = 0
/turf/open/misc/asteroid/snow/ice/burn_tile()
return FALSE
/turf/open/misc/asteroid/snow/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/misc/asteroid/snow/temperatre
- initial_gas_mix = "o2=22;n2=82;TEMP=255.37"
+ temperature = 255.37
//Used in SnowCabin.dm
/turf/open/misc/asteroid/snow/snow_cabin
temperature = 180
/turf/open/misc/asteroid/snow/atmosphere
- initial_gas_mix = FROZEN_ATMOS
- planetary_atmos = FALSE
+ temperature = 180
+
/turf/open/misc/asteroid/snow/standard_air
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
- planetary_atmos = FALSE
+ initial_gas = OPENTURF_DEFAULT_ATMOS
+ temperature = T0C
+
diff --git a/code/game/turfs/open/basalt.dm b/code/game/turfs/open/basalt.dm
index ce1b547fdcc..1c70f46de50 100644
--- a/code/game/turfs/open/basalt.dm
+++ b/code/game/turfs/open/basalt.dm
@@ -4,7 +4,7 @@
desc = "Rough volcanic floor that can be dug up for basalt."
icon = 'icons/turf/floors.dmi'
icon_state = "basalt"
- initial_gas_mix = OPENTURF_LOW_PRESSURE
+ initial_gas = OPENTURF_LOW_PRESSURE
/turf/open/misc/basalt/Initialize(mapload)
. = ..()
@@ -14,4 +14,4 @@
set_basalt_light(src)
/turf/open/misc/basalt/safe
- planetary_atmos = FALSE
+
diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm
index 7fbc2a0e82d..54bde9b1231 100644
--- a/code/game/turfs/open/chasm.dm
+++ b/code/game/turfs/open/chasm.dm
@@ -77,8 +77,8 @@
// Chasms for Lavaland, with planetary atmos and lava glow
/turf/open/chasm/lavaland
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = LAVALAND_DEFAULT_ATMOS
+
baseturfs = /turf/open/chasm/lavaland
light_range = 1.9 //slightly less range than lava
light_power = 0.65 //less bright, too
@@ -89,8 +89,8 @@
icon = 'icons/turf/floors/icechasms.dmi'
icon_state = "icechasms-255"
base_icon_state = "icechasms"
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = ICEMOON_DEFAULT_ATMOS
+
baseturfs = /turf/open/chasm/icemoon
light_range = 1.9
light_power = 0.65
@@ -101,8 +101,8 @@
icon = 'icons/turf/floors/junglechasm.dmi'
icon_state = "junglechasm-255"
base_icon_state = "junglechasm"
- initial_gas_mix = OPENTURF_LOW_PRESSURE
- planetary_atmos = TRUE
+ initial_gas = OPENTURF_LOW_PRESSURE
+
baseturfs = /turf/open/chasm/jungle
/turf/open/chasm/jungle/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm
index d0be8a5e753..b0f342ff46d 100644
--- a/code/game/turfs/open/floor/fancy_floor.dm
+++ b/code/game/turfs/open/floor/fancy_floor.dm
@@ -72,7 +72,7 @@
temperature = 180
/turf/open/floor/wood/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/wood/tile
icon_state = "wood_tile"
@@ -157,7 +157,7 @@
icon_state = "snow"
flags_1 = NONE
floor_tile = null
- initial_gas_mix = FROZEN_ATMOS
+ temperature = 180
bullet_bounce_sound = null
tiled_dirt = FALSE
@@ -353,34 +353,34 @@
//*****Airless versions of all of the above.*****
/turf/open/floor/carpet/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/black/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/blue/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/cyan/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/green/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/orange/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/purple/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/red/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/royalblack/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/royalblue/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/narsie_act(force, ignore_mobs, probability = 20)
. = (prob(probability) || force)
@@ -670,91 +670,91 @@
canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_PINK_NODOTS)
/turf/open/floor/carpet/neon/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/white/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/black/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/red/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/orange/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/yellow/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/lime/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/green/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/teal/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/cyan/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/blue/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/purple/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/violet/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/pink/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/white/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/black/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/red/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/orange/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/yellow/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/lime/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/green/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/teal/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/cyan/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/blue/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/purple/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/violet/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/carpet/neon/simple/pink/nodots/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/fakepit
desc = "A clever illusion designed to look like a bottomless pit."
diff --git a/code/game/turfs/open/floor/glass.dm b/code/game/turfs/open/floor/glass.dm
index 4bddbbb5a3a..fb75dfc0774 100644
--- a/code/game/turfs/open/floor/glass.dm
+++ b/code/game/turfs/open/floor/glass.dm
@@ -46,7 +46,7 @@
icon_state = "reinf_glass-0"
base_icon_state = "reinf_glass"
floor_tile = /obj/item/stack/tile/rglass
- initial_gas_mix = "ICEMOON_ATMOS"
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/glass/reinforced/setup_broken_states()
return list("reinf_glass-damaged1", "reinf_glass-damaged2", "reinf_glass-damaged3")
diff --git a/code/game/turfs/open/floor/hull.dm b/code/game/turfs/open/floor/hull.dm
index de34e3a2d7f..c65e96f6ad6 100644
--- a/code/game/turfs/open/floor/hull.dm
+++ b/code/game/turfs/open/floor/hull.dm
@@ -3,7 +3,7 @@
name = "exterior hull plating"
desc = "Sturdy exterior hull plating that separates you from the uncaring vacuum of space."
icon_state = "regular_hull"
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
temperature = TCMB
/turf/open/floor/engine/hull/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) //no rcd destroying this flooring
diff --git a/code/game/turfs/open/floor/iron_floor.dm b/code/game/turfs/open/floor/iron_floor.dm
index cafd386c142..2948d5e9df2 100644
--- a/code/game/turfs/open/floor/iron_floor.dm
+++ b/code/game/turfs/open/floor/iron_floor.dm
@@ -27,13 +27,15 @@
/turf/open/floor/iron/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/telecomms
- initial_gas_mix = TCOMMS_ATMOS
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
/turf/open/floor/iron/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
+ temperature = 80
/turf/open/floor/iron/edge
icon_state = "floor_edge"
@@ -146,19 +148,19 @@
floor_tile = /obj/item/stack/tile/iron/dark/textured_large
/turf/open/floor/iron/dark/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/dark/telecomms
- initial_gas_mix = TCOMMS_ATMOS
-
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
/turf/open/floor/iron/dark/side/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/dark/corner/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/checker/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/white
icon_state = "white"
@@ -226,19 +228,19 @@
floor_tile = /obj/item/stack/tile/iron/white/textured_large
/turf/open/floor/iron/white/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/white/telecomms
- initial_gas_mix = TCOMMS_ATMOS
-
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
/turf/open/floor/iron/white/side/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/white/corner/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/cafeteria/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/recharge_floor
icon_state = "recharge_floor"
@@ -285,7 +287,7 @@
floor_tile = /obj/item/stack/tile/iron/showroomfloor
/turf/open/floor/iron/showroomfloor/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/solarpanel
icon_state = "solarpanel"
@@ -293,8 +295,7 @@
floor_tile = /obj/item/stack/tile/iron/solarpanel
/turf/open/floor/iron/solarpanel/airless
- initial_gas_mix = AIRLESS_ATMOS
-
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/freezer
icon_state = "freezerfloor"
@@ -302,14 +303,11 @@
floor_tile = /obj/item/stack/tile/iron/freezer
/turf/open/floor/iron/freezer/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/iron/kitchen_coldroom
name = "cold room floor"
-
-/turf/open/floor/iron/kitchen_coldroom/Initialize(mapload)
- initial_gas_mix = KITCHEN_COLDROOM_ATMOS
- return ..()
+ initial_gas = KITCHEN_COLDROOM_ATMOS
/turf/open/floor/iron/kitchen_coldroom/freezerfloor
icon_state = "freezerfloor"
diff --git a/code/game/turfs/open/floor/mineral_floor.dm b/code/game/turfs/open/floor/mineral_floor.dm
index d816680006f..8157fce2dc2 100644
--- a/code/game/turfs/open/floor/mineral_floor.dm
+++ b/code/game/turfs/open/floor/mineral_floor.dm
@@ -77,35 +77,35 @@
return // titanium does not rust
/turf/open/floor/mineral/titanium/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/yellow
icon_state = "titanium_yellow"
floor_tile = /obj/item/stack/tile/mineral/titanium/yellow
/turf/open/floor/mineral/titanium/yellow/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/blue
icon_state = "titanium_blue"
floor_tile = /obj/item/stack/tile/mineral/titanium/blue
/turf/open/floor/mineral/titanium/blue/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/white
icon_state = "titanium_white"
floor_tile = /obj/item/stack/tile/mineral/titanium/white
/turf/open/floor/mineral/titanium/white/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/purple
icon_state = "titanium_purple"
floor_tile = /obj/item/stack/tile/mineral/titanium/purple
/turf/open/floor/mineral/titanium/purple/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
// OLD TITANIUM (titanium floor tiles before PR #50454)
/turf/open/floor/mineral/titanium/tiled
@@ -117,35 +117,35 @@
return list("titanium_dam1_old","titanium_dam2_old","titanium_dam3_old","titanium_dam4_old","titanium_dam5_old")
/turf/open/floor/mineral/titanium/tiled/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/tiled/yellow
icon_state = "titanium_tiled_yellow"
floor_tile = /obj/item/stack/tile/mineral/titanium/tiled/yellow
/turf/open/floor/mineral/titanium/tiled/yellow/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/tiled/blue
icon_state = "titanium_tiled_blue"
floor_tile = /obj/item/stack/tile/mineral/titanium/tiled/blue
/turf/open/floor/mineral/titanium/tiled/blue/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/tiled/white
icon_state = "titanium_tiled_white"
floor_tile = /obj/item/stack/tile/mineral/titanium/tiled/white
/turf/open/floor/mineral/titanium/tiled/white/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/titanium/tiled/purple
icon_state = "titanium_tiled_purple"
floor_tile = /obj/item/stack/tile/mineral/titanium/tiled/purple
/turf/open/floor/mineral/titanium/tiled/purple/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
//PLASTITANIUM (syndieshuttle)
/turf/open/floor/mineral/plastitanium
@@ -161,14 +161,14 @@
return // plastitanium does not rust
/turf/open/floor/mineral/plastitanium/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/mineral/plastitanium/red
icon_state = "plastitanium_red"
floor_tile = /obj/item/stack/tile/mineral/plastitanium/red
/turf/open/floor/mineral/plastitanium/red/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
//Used in SnowCabin.dm
/turf/open/floor/mineral/plastitanium/red/snow_cabin
@@ -221,7 +221,7 @@
sound_cooldown = world.time + 10
/turf/open/floor/mineral/bananium/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
//DIAMOND
diff --git a/code/game/turfs/open/floor/misc_floor.dm b/code/game/turfs/open/floor/misc_floor.dm
index bb65ee31383..73bf110c48b 100644
--- a/code/game/turfs/open/floor/misc_floor.dm
+++ b/code/game/turfs/open/floor/misc_floor.dm
@@ -34,10 +34,11 @@
on = FALSE
/turf/open/floor/circuit/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/circuit/telecomms
- initial_gas_mix = TCOMMS_ATMOS
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
/turf/open/floor/circuit/telecomms/mainframe
name = "mainframe base"
@@ -61,10 +62,11 @@
floor_tile = /obj/item/stack/tile/circuit/green/anim
/turf/open/floor/circuit/green/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/circuit/green/telecomms
- initial_gas_mix = TCOMMS_ATMOS
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
/turf/open/floor/circuit/green/telecomms/mainframe
name = "mainframe base"
@@ -85,10 +87,11 @@
floor_tile = /obj/item/stack/tile/circuit/red/anim
/turf/open/floor/circuit/red/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/circuit/red/telecomms
- initial_gas_mix = TCOMMS_ATMOS
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
/turf/open/floor/pod
name = "pod floor"
@@ -153,12 +156,12 @@
floor_tile = /obj/item/stack/tile/bronze/filled
/turf/open/floor/bronze/filled/lavaland
- planetary_atmos = TRUE
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+
+ initial_gas = LAVALAND_DEFAULT_ATMOS
/turf/open/floor/bronze/filled/icemoon
- planetary_atmos = TRUE
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/white
name = "white floor"
@@ -213,7 +216,7 @@
AddElement(/datum/element/rust)
/turf/open/floor/plating/plasma
- initial_gas_mix = ATMOS_TANK_PLASMA
+ initial_gas = ATMOSTANK_PLASMA
/turf/open/floor/plating/plasma/rust/Initialize(mapload)
. = ..()
@@ -263,4 +266,4 @@
return
/turf/open/floor/cult/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm
index a12b19bb245..61a1df96939 100644
--- a/code/game/turfs/open/floor/plating.dm
+++ b/code/game/turfs/open/floor/plating.dm
@@ -15,6 +15,7 @@
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
+
var/attachment_holes = TRUE
/// If true, will allow tiles to replace us if the tile [wants to] [/obj/item/stack/tile/var/replace_plating].
diff --git a/code/game/turfs/open/floor/plating/misc_plating.dm b/code/game/turfs/open/floor/plating/misc_plating.dm
index cad8d5d3c35..fbe06d95201 100644
--- a/code/game/turfs/open/floor/plating/misc_plating.dm
+++ b/code/game/turfs/open/floor/plating/misc_plating.dm
@@ -1,14 +1,14 @@
/turf/open/floor/plating/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/plating/lowpressure
- initial_gas_mix = OPENTURF_LOW_PRESSURE
+ initial_gas = OPENTURF_LOW_PRESSURE
baseturfs = /turf/open/floor/plating/lowpressure
/turf/open/floor/plating/icemoon
icon_state = "plating"
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/plating/abductor
name = "alien floor"
@@ -44,20 +44,19 @@
icon = 'icons/turf/snow.dmi'
icon_state = "snowplating"
base_icon_state = "snowplating"
- initial_gas_mix = FROZEN_ATMOS
temperature = 180
attachment_holes = FALSE
- planetary_atmos = TRUE
+
footstep = FOOTSTEP_SAND
barefootstep = FOOTSTEP_SAND
clawfootstep = FOOTSTEP_SAND
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/turf/open/floor/plating/snowed/cavern
- initial_gas_mix = "n2=82;plasma=24;TEMP=120"
+ temperature = 120
/turf/open/floor/plating/snowed/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/plating/snowed/smoothed
icon = 'icons/turf/floors/snow_turf.dmi'
@@ -66,7 +65,7 @@
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_FLOOR_SNOWED)
canSmoothWith = list(SMOOTH_GROUP_FLOOR_SNOWED)
- planetary_atmos = TRUE
+
/turf/open/floor/plating/snowed/temperatre
temperature = 255.37
@@ -76,12 +75,12 @@
temperature = 180
/turf/open/floor/plating/snowed/smoothed/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/plating/lavaland_atmos
- planetary_atmos = TRUE
+
baseturfs = /turf/open/lava/smooth/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
/turf/open/floor/plating/elevatorshaft
name = "elevator shaft"
diff --git a/code/game/turfs/open/floor/reinf_floor.dm b/code/game/turfs/open/floor/reinf_floor.dm
index b5c1c3cd71e..0b9c2394b3c 100644
--- a/code/game/turfs/open/floor/reinf_floor.dm
+++ b/code/game/turfs/open/floor/reinf_floor.dm
@@ -19,7 +19,7 @@
. += span_notice("The reinforcement rods are wrenched firmly in place.")
/turf/open/floor/engine/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/engine/break_tile()
return //unbreakable
@@ -100,90 +100,92 @@
/turf/open/floor/engine/n2o
article = "an"
name = "\improper N2O floor"
- initial_gas_mix = ATMOS_TANK_N2O
+ initial_gas = ATMOSTANK_NITROUSOXIDE
/turf/open/floor/engine/co2
name = "\improper CO2 floor"
- initial_gas_mix = ATMOS_TANK_CO2
+ initial_gas = ATMOSTANK_CO2
/turf/open/floor/engine/plasma
name = "plasma floor"
- initial_gas_mix = ATMOS_TANK_PLASMA
+ initial_gas = ATMOSTANK_PLASMA
/turf/open/floor/engine/o2
name = "\improper O2 floor"
- initial_gas_mix = ATMOS_TANK_O2
+ initial_gas = ATMOSTANK_OXYGEN
/turf/open/floor/engine/n2
article = "an"
name = "\improper N2 floor"
- initial_gas_mix = ATMOS_TANK_N2
+ initial_gas = ATMOSTANK_NITROGEN
-/turf/open/floor/engine/bz
+
+/*/turf/open/floor/engine/bz
name = "\improper BZ floor"
- initial_gas_mix = ATMOS_TANK_BZ
+ initial_gas = ATMOS_TANK_BZ
/turf/open/floor/engine/freon
name = "\improper Freon floor"
- initial_gas_mix = ATMOS_TANK_FREON
+ initial_gas = ATMOS_TANK_FREON
/turf/open/floor/engine/halon
name = "\improper Halon floor"
- initial_gas_mix = ATMOS_TANK_HALON
+ initial_gas = ATMOS_TANK_HALON
/turf/open/floor/engine/healium
name = "\improper Healium floor"
- initial_gas_mix = ATMOS_TANK_HEALIUM
-
+ initial_gas = ATMOS_TANK_HEALIUM
+*/
/turf/open/floor/engine/h2
article = "an"
name = "\improper H2 floor"
- initial_gas_mix = ATMOS_TANK_H2
+ initial_gas = ATMOSTANK_HYDROGEN
+/*
/turf/open/floor/engine/hypernoblium
name = "\improper Hypernoblium floor"
- initial_gas_mix = ATMOS_TANK_HYPERNOBLIUM
+ initial_gas = ATMOS_TANK_HYPERNOBLIUM
/turf/open/floor/engine/miasma
name = "\improper Miasma floor"
- initial_gas_mix = ATMOS_TANK_MIASMA
+ initial_gas = ATMOS_TANK_MIASMA
/turf/open/floor/engine/nitrium
name = "\improper nitrium floor"
- initial_gas_mix = ATMOS_TANK_NITRIUM
+ initial_gas = ATMOS_TANK_NITRIUM
/turf/open/floor/engine/pluoxium
name = "\improper Pluoxium floor"
- initial_gas_mix = ATMOS_TANK_PLUOXIUM
+ initial_gas = ATMOS_TANK_PLUOXIUM
/turf/open/floor/engine/proto_nitrate
name = "\improper Proto-Nitrate floor"
- initial_gas_mix = ATMOS_TANK_PROTO_NITRATE
+ initial_gas = ATMOS_TANK_PROTO_NITRATE
/turf/open/floor/engine/tritium
name = "\improper Tritium floor"
- initial_gas_mix = ATMOS_TANK_TRITIUM
+ initial_gas = ATMOS_TANK_TRITIUM
/turf/open/floor/engine/h2o
article = "an"
name = "\improper H2O floor"
- initial_gas_mix = ATMOS_TANK_H2O
+ initial_gas = ATMOS_TANK_H2O
/turf/open/floor/engine/zauker
name = "\improper Zauker floor"
- initial_gas_mix = ATMOS_TANK_ZAUKER
+ initial_gas = ATMOS_TANK_ZAUKER
/turf/open/floor/engine/helium
name = "\improper Helium floor"
- initial_gas_mix = ATMOS_TANK_HELIUM
+ initial_gas = ATMOS_TANK_HELIUM
/turf/open/floor/engine/antinoblium
name = "\improper Antinoblium floor"
- initial_gas_mix = ATMOS_TANK_ANTINOBLIUM
-
+ initial_gas = ATMOS_TANK_ANTINOBLIUM
+*/
/turf/open/floor/engine/air
name = "air floor"
- initial_gas_mix = ATMOS_TANK_AIRMIX
+ initial_gas = ATMOSTANK_AIRMIX
@@ -215,11 +217,12 @@
QDEL_NULL(realappearance)
/turf/open/floor/engine/cult/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/engine/vacuum
name = "vacuum floor"
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/floor/engine/telecomms
- initial_gas_mix = TCOMMS_ATMOS
+ initial_gas = TCOMMS_ATMOS
+ temperature = 80
diff --git a/code/game/turfs/open/grass.dm b/code/game/turfs/open/grass.dm
index b1ecd34165d..1f65573db01 100644
--- a/code/game/turfs/open/grass.dm
+++ b/code/game/turfs/open/grass.dm
@@ -29,4 +29,4 @@
icon = smooth_icon
/turf/open/misc/grass/lavaland
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
diff --git a/code/game/turfs/open/ice.dm b/code/game/turfs/open/ice.dm
index 4a9a55b53da..c02c5712f2c 100644
--- a/code/game/turfs/open/ice.dm
+++ b/code/game/turfs/open/ice.dm
@@ -4,9 +4,9 @@
icon = 'icons/turf/floors/ice_turf.dmi'
icon_state = "ice_turf-0"
base_icon_state = "ice_turf-0"
- initial_gas_mix = FROZEN_ATMOS
temperature = 180
- planetary_atmos = TRUE
+ temperature = 180
+
baseturfs = /turf/open/misc/ice
slowdown = 1
bullet_sizzle = TRUE
@@ -34,8 +34,10 @@
/turf/open/misc/ice/icemoon
baseturfs = /turf/open/openspace/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+ initial_gas = ICEMOON_DEFAULT_ATMOS
slowdown = 0
+ simulated = FALSE
/turf/open/misc/ice/icemoon/no_planet_atmos
- planetary_atmos = FALSE
+ simulated = TRUE
+
diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm
index 5c82669420f..84d032626b6 100644
--- a/code/game/turfs/open/lava.dm
+++ b/code/game/turfs/open/lava.dm
@@ -12,6 +12,8 @@
light_color = LIGHT_COLOR_LAVA
bullet_bounce_sound = 'sound/items/welder2.ogg'
+ simulated = FALSE
+
footstep = FOOTSTEP_LAVA
barefootstep = FOOTSTEP_LAVA
clawfootstep = FOOTSTEP_LAVA
@@ -44,7 +46,7 @@
return
/turf/open/lava/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/lava/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
if(burn_stuff(arrived))
@@ -98,7 +100,7 @@
/turf/open/lava/GetHeatCapacity()
. = 700000
-/turf/open/lava/GetTemperature()
+/turf/open/lava/return_temperature()
. = 5000
/turf/open/lava/TakeTemperature(temp)
@@ -233,9 +235,9 @@
canSmoothWith = list(SMOOTH_GROUP_FLOOR_LAVA)
/turf/open/lava/smooth/lava_land_surface
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = LAVALAND_DEFAULT_ATMOS
+
baseturfs = /turf/open/lava/smooth/lava_land_surface
/turf/open/lava/smooth/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm
index f2d890b5c63..e774eacfacd 100644
--- a/code/game/turfs/open/openspace.dm
+++ b/code/game/turfs/open/openspace.dm
@@ -18,16 +18,21 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
baseturfs = /turf/open/openspace
overfloor_placed = FALSE
underfloor_accessibility = UNDERFLOOR_INTERACTABLE
+ #ifndef ZASDBG //Multi-Z zone debugging
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ #endif
pathing_pass_method = TURF_PATHING_PASS_PROC
+
+ z_flags = Z_ATMOS_IN_DOWN|Z_ATMOS_IN_UP|Z_ATMOS_OUT_DOWN|Z_ATMOS_OUT_UP
+
var/can_cover_up = TRUE
var/can_build_on = TRUE
/turf/open/openspace/airless
- initial_gas_mix = AIRLESS_ATMOS
+ initial_gas = AIRLESS_ATMOS
/turf/open/openspace/airless/planetary
- planetary_atmos = TRUE
+ simulated = FALSE
/turf/open/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
@@ -166,8 +171,9 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
/turf/open/openspace/icemoon
name = "ice chasm"
baseturfs = /turf/open/openspace/icemoon
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = ICEMOON_DEFAULT_ATMOS
+ simulated = FALSE
+
var/replacement_turf = /turf/open/misc/asteroid/snow/icemoon
/// Replaces itself with replacement_turf if the turf below this one is in a no ruins allowed area (usually ruins themselves)
var/protect_ruin = TRUE
diff --git a/code/game/turfs/open/planet.dm b/code/game/turfs/open/planet.dm
index 6c1ae311ae9..e1166876be0 100644
--- a/code/game/turfs/open/planet.dm
+++ b/code/game/turfs/open/planet.dm
@@ -6,8 +6,8 @@
icon_state = "dirt"
base_icon_state = "dirt"
baseturfs = /turf/open/chasm/jungle
- initial_gas_mix = OPENTURF_LOW_PRESSURE
- planetary_atmos = TRUE
+ initial_gas = OPENTURF_LOW_PRESSURE
+
footstep = FOOTSTEP_SAND
barefootstep = FOOTSTEP_SAND
clawfootstep = FOOTSTEP_SAND
@@ -20,7 +20,7 @@
/turf/open/misc/dirt/jungle
slowdown = 0.5
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ initial_gas = OPENTURF_DEFAULT_ATMOS
/turf/open/misc/dirt/jungle/dark
icon_state = "greenerdirt"
@@ -46,8 +46,8 @@
/turf/open/misc/grass/jungle
name = "jungle grass"
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
- planetary_atmos = TRUE
+ initial_gas = OPENTURF_DEFAULT_ATMOS
+
baseturfs = /turf/open/misc/dirt
desc = "Greener on the other side."
icon_state = "junglegrass"
diff --git a/code/game/turfs/open/snow.dm b/code/game/turfs/open/snow.dm
index 4017240e3fd..bb2ab0eeb52 100644
--- a/code/game/turfs/open/snow.dm
+++ b/code/game/turfs/open/snow.dm
@@ -4,8 +4,8 @@
icon = 'icons/turf/snow.dmi'
desc = "Looks cold."
icon_state = "snow"
- planetary_atmos = TRUE
- initial_gas_mix = FROZEN_ATMOS
+
+ temperature = 180
slowdown = 2
bullet_sizzle = TRUE
footstep = FOOTSTEP_SAND
@@ -23,5 +23,5 @@
/turf/open/misc/snow/actually_safe
slowdown = 0
- planetary_atmos = FALSE
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+
+ initial_gas = OPENTURF_DEFAULT_ATMOS
diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm
index 1a81515e940..2d68c3082de 100644
--- a/code/game/turfs/open/space/space.dm
+++ b/code/game/turfs/open/space/space.dm
@@ -4,17 +4,19 @@
name = "\proper space"
overfloor_placed = FALSE
underfloor_accessibility = UNDERFLOOR_INTERACTABLE
-
+ z_flags = Z_ATMOS_IN_DOWN|Z_ATMOS_IN_UP|Z_ATMOS_OUT_DOWN|Z_ATMOS_OUT_UP
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
+ simulated = FALSE
var/destination_z
var/destination_x
var/destination_y
- var/static/datum/gas_mixture/immutable/space/space_gas = new
- run_later = TRUE
+ initial_gas = AIRLESS_ATMOS
+
+ // run_later = TRUE
plane = PLANE_SPACE
layer = SPACE_LAYER
light_power = 0.25
@@ -34,7 +36,6 @@
/turf/open/space/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
icon_state = SPACE_ICON_STATE
- air = space_gas
vis_contents.Cut() //removes inherited overlays
visibilityChanged()
@@ -55,8 +56,10 @@
if(our_area.area_has_base_lighting && always_lit) //Only provide your own lighting if the area doesn't for you
add_overlay(GLOB.fullbright_overlay)
+ /*
if(requires_activation)
SSair.add_to_active(src, TRUE)
+ */
if (light_system == STATIC_LIGHT && light_power && light_range)
update_light()
@@ -81,9 +84,10 @@
var/turf/T = locate(destination_x, destination_y, destination_z)
user.forceMove(T)
+/*
/turf/open/space/Initalize_Atmos(times_fired)
return
-
+*/
/turf/open/space/TakeTemperature(temp)
/turf/open/space/RemoveLattice()
@@ -91,10 +95,10 @@
/turf/open/space/AfterChange()
..()
- atmos_overlay_types = null
+ //atmos_overlay_types = null
-/turf/open/space/Assimilate_Air()
- return
+/*/turf/open/space/Assimilate_Air()
+ return*/
//IT SHOULD RETURN NULL YOU MONKEY, WHY IN TARNATION WHAT THE FUCKING FUCK
/turf/open/space/remove_air(amount)
@@ -224,6 +228,7 @@
/turf/open/space/openspace
icon = 'icons/turf/floors.dmi'
icon_state = "invisible"
+ simulated = TRUE
/turf/open/space/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
diff --git a/code/game/turfs/open/space/transit.dm b/code/game/turfs/open/space/transit.dm
index 9e1e9643b26..a3a659c3070 100644
--- a/code/game/turfs/open/space/transit.dm
+++ b/code/game/turfs/open/space/transit.dm
@@ -5,6 +5,7 @@
baseturfs = /turf/open/space/transit
flags_1 = NOJAUNT //This line goes out to every wizard that ever managed to escape the den. I'm sorry.
explosion_block = INFINITY
+ z_flags = NONE
/turf/open/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
. = ..()
diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm
index 02e19e94890..8965c75b04d 100644
--- a/code/game/turfs/open/water.dm
+++ b/code/game/turfs/open/water.dm
@@ -4,8 +4,8 @@
icon = 'icons/turf/floors.dmi'
icon_state = "riverwater_motion"
baseturfs = /turf/open/chasm/lavaland
- initial_gas_mix = OPENTURF_LOW_PRESSURE
- planetary_atmos = TRUE
+ initial_gas = OPENTURF_LOW_PRESSURE
+
slowdown = 1
bullet_sizzle = TRUE
bullet_bounce_sound = null //needs a splashing sound one day.
@@ -17,10 +17,9 @@
heavyfootstep = FOOTSTEP_WATER
/turf/open/water/jungle
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ initial_gas = OPENTURF_DEFAULT_ATMOS
/turf/open/water/beach
- planetary_atmos = FALSE
gender = PLURAL
desc = "You get the feeling that nobody's bothered to actually make this water functional..."
icon = 'icons/misc/beach.dmi'
@@ -30,4 +29,4 @@
//Same turf, but instead used in the Beach Biodome
/turf/open/water/beach/biodome
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ initial_gas = OPENTURF_DEFAULT_ATMOS
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index daaf6759fae..d0f9c0a1a2b 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -21,13 +21,12 @@ GLOBAL_LIST_EMPTY(station_turfs)
// This shouldn't be modified directly, use the helper procs.
var/list/baseturfs = /turf/baseturf_bottom
- var/temperature = T20C
///Used for fire, if a melting temperature was reached, it will be destroyed
var/to_be_destroyed = 0
///The max temperature of the fire which it was subjected to
var/max_fire_temperature_sustained = 0
- var/blocks_air = FALSE
+ var/blocks_air = AIR_ALLOWED
var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes
@@ -97,6 +96,10 @@ GLOBAL_LIST_EMPTY(station_turfs)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
+ // if(!blocks_air || !simulated)
+ // air = new
+ // air.copyFrom(src.return_air())
+
// by default, vis_contents is inherited from the turf that was here before
vis_contents.Cut()
@@ -124,8 +127,10 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(our_area.area_has_base_lighting && always_lit) //Only provide your own lighting if the area doesn't for you
add_overlay(GLOB.fullbright_overlay)
+ /*
if(requires_activation)
CALCULATE_ADJACENT_TURFS(src, KILL_EXCITED)
+ */
if (light_power && light_range)
update_light()
@@ -155,9 +160,10 @@ GLOBAL_LIST_EMPTY(station_turfs)
return INITIALIZE_HINT_NORMAL
+/*
/turf/proc/Initalize_Atmos(times_fired)
CALCULATE_ADJACENT_TURFS(src, NORMAL_TURF)
-
+*/
/turf/Destroy(force)
. = QDEL_HINT_IWILLGC
if(!changing_turf)
@@ -176,10 +182,26 @@ GLOBAL_LIST_EMPTY(station_turfs)
for(var/A in B.contents)
qdel(A)
return
+
visibilityChanged()
QDEL_LIST(blueprint_data)
flags_1 &= ~INITIALIZED_1
requires_activation = FALSE
+
+ ///ZAS THINGS
+ if(connections)
+ connections.erase_all()
+
+ if(simulated && zone)
+ ///Try to gracefully remove
+ if(can_safely_remove_from_zone())
+ copy_zone_air()
+ zone.remove_turf(src)
+
+ else //Just rebuild the fucker
+ INVOKE_ASYNC(zone, /zone.proc/rebuild) //rebuild() contains CHECK_TICK
+ ///NO MORE ZAS THINGS
+
..()
vis_contents.Cut()
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index bac1ed9a07b..7d1b17eebc7 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -20,7 +20,7 @@ GLOBAL_PROTECT(admin_verbs_default)
/client/proc/mark_datum_mapview,
/client/proc/tag_datum_mapview,
/client/proc/debugstatpanel,
- /client/proc/fix_air, /*resets air in designated radius to its default atmos composition*/
+ /client/proc/fixatmos, /*resets air in designated radius to its default atmos composition*/
/client/proc/requests
)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
@@ -199,6 +199,9 @@ GLOBAL_PROTECT(admin_verbs_debug)
/client/proc/cmd_admin_toggle_fov,
/client/proc/cmd_admin_debug_traitor_objectives,
/client/proc/spawn_debug_full_crew,
+ //ZAS Debug Verbs
+ /client/proc/Zone_Info, //Right-Click Gas Debug Info
+ /client/proc/Test_ZAS_Connection, //ZAS Connection Test
/client/proc/jumptocoord,
/client/proc/jumptokey,
/client/proc/jumptoarea,
@@ -525,35 +528,38 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set name = "Drop Bomb"
set desc = "Cause an explosion of varying strength at your location."
- var/list/choices = list("Small Bomb (1, 2, 3, 3)", "Medium Bomb (2, 3, 4, 4)", "Big Bomb (3, 5, 7, 5)", "Maxcap", "Custom Bomb")
+ var/list/choices = list("Small Bomb (1, 2, 3, 0, 3)", "Medium Bomb (1, 2, 3, 0, 3)", "Big Bomb (3, 5, 7, 0, 5)", "Maxcap (4, 8, 16, 16, 20 by default)", "Custom Bomb")
var/choice = tgui_input_list(src, "What size explosion would you like to produce? NOTE: You can do all this rapidly and in an IC manner (using cruise missiles!) with the Config/Launch Supplypod verb. WARNING: These ignore the maxcap", "Drop Bomb", choices)
if(isnull(choice))
return
var/turf/epicenter = mob.loc
switch(choice)
- if("Small Bomb (1, 2, 3, 3)")
+ if("Small Bomb (1, 2, 3, 0, 3)")
explosion(epicenter, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3, flash_range = 3, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
- if("Medium Bomb (2, 3, 4, 4)")
+ if("Medium Bomb (1, 2, 3, 0, 3)")
explosion(epicenter, devastation_range = 2, heavy_impact_range = 3, light_impact_range = 4, flash_range = 4, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
- if("Big Bomb (3, 5, 7, 5)")
+ if("Big Bomb (3, 5, 7, 0, 5)")
explosion(epicenter, devastation_range = 3, heavy_impact_range = 5, light_impact_range = 7, flash_range = 5, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
- if("Maxcap")
- explosion(epicenter, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
+ if("Maxcap (4, 8, 16, 16, 20 by default)")
+ explosion(epicenter, devastation_range = zas_settings.maxex_devastation_range, heavy_impact_range = zas_settings.maxex_heavy_range, light_impact_range = zas_settings.maxex_light_range, flame_range = zas_settings.maxex_fire_range, flash_range = zas_settings.maxex_flash_range, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
if("Custom Bomb")
var/range_devastation = input("Devastation range (in tiles):") as null|num
- if(range_devastation == null)
+ if(isnull(range_devastation))
return
var/range_heavy = input("Heavy impact range (in tiles):") as null|num
- if(range_heavy == null)
+ if(isnull(range_heavy))
return
var/range_light = input("Light impact range (in tiles):") as null|num
- if(range_light == null)
+ if(isnull(range_light))
+ return
+ var/range_flame = input("Flame range (in tiles):") as null|num
+ if(isnull(range_flame))
return
var/range_flash = input("Flash range (in tiles):") as null|num
- if(range_flash == null)
+ if(isnull(range_flash))
return
- if(range_devastation > GLOB.MAX_EX_DEVESTATION_RANGE || range_heavy > GLOB.MAX_EX_HEAVY_RANGE || range_light > GLOB.MAX_EX_LIGHT_RANGE || range_flash > GLOB.MAX_EX_FLASH_RANGE)
+ if(range_devastation > zas_settings.maxex_devastation_range || range_heavy > zas_settings.maxex_heavy_range || range_light > zas_settings.maxex_light_range || range_flash > zas_settings.maxex_flash_range || range_flame > zas_settings.maxex_fire_range)
if(tgui_alert(usr, "Bomb is bigger than the maxcap. Continue?",,list("Yes","No")) != "Yes")
return
epicenter = mob.loc //We need to reupdate as they may have moved again
@@ -614,7 +620,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set category = "Debug"
if(!check_rights(R_DEBUG))
return
- SSair.ui_interact(mob)
+ //SSair.ui_interact(mob)
/client/proc/reload_cards()
set name = "Reload Cards"
diff --git a/code/modules/admin/outfit_editor.dm b/code/modules/admin/outfit_editor.dm
index e57d0a9e79a..ebe90196aa5 100644
--- a/code/modules/admin/outfit_editor.dm
+++ b/code/modules/admin/outfit_editor.dm
@@ -16,7 +16,7 @@
if(ispath(target))
drip = new /datum/outfit
- drip.copy_from(new target)
+ drip.copyFrom(new target)
else if(istype(target))
drip = target
else
diff --git a/code/modules/admin/verbs/commandreport.dm b/code/modules/admin/verbs/commandreport.dm
index 8cf537a61ff..4d5d60f4034 100644
--- a/code/modules/admin/verbs/commandreport.dm
+++ b/code/modules/admin/verbs/commandreport.dm
@@ -27,7 +27,7 @@
set category = "Admin.Events"
set name = "Create Command Report"
- if(!check_rights(R_ADMIN) || !check_rights(R_DEBUG))
+ if(!holder)
return
SSblackbox.record_feedback("tally", "admin_verb", 1, "Create Command Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/fix_air.dm b/code/modules/admin/verbs/fix_air.dm
index d1f535cb0f6..4bf696557e0 100644
--- a/code/modules/admin/verbs/fix_air.dm
+++ b/code/modules/admin/verbs/fix_air.dm
@@ -1,21 +1,55 @@
-// Proc taken from yogstation, credit to nichlas0010 for the original
-/client/proc/fix_air(turf/open/T in world)
- set name = "Fix Air"
- set category = "Admin.Game"
- set desc = "Fixes air in specified radius."
-
- if(!holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
+//Lifted 1:1 from Baystation
+/client/proc/fixatmos()
+ set category = "Admin"
+ set name = "Fix Atmospherics Grief"
+
+ if(!check_rights(R_ADMIN|R_DEBUG)) return
+
+ if(alert("WARNING: Executing this command will perform a full reset of atmosphere. All pipelines will lose any gas that may be in them, and all zones will be reset to contain air mix as on roundstart. The supermatter engine will also be stopped (to prevent overheat due to removal of coolant). Do not use unless the map is suffering serious atmospheric issues due to grief or bug.", "Full Atmosphere Reboot", "No", "Yes") == "No")
return
- if(check_rights(R_ADMIN,1))
- var/range=input("Enter range:","Num",2) as num
- message_admins("[key_name_admin(usr)] fixed air with range [range] in area [T.loc.name]")
- log_game("[key_name_admin(usr)] fixed air with range [range] in area [T.loc.name]")
- var/datum/gas_mixture/GM = new
- for(var/turf/open/F in range(range,T))
- if(F.blocks_air)
- //skip walls
- continue
- GM.parse_gas_string(F.initial_gas_mix)
- F.copy_air(GM)
- F.update_visuals()
+ if(!fix_atmos_grief())
+ to_chat(world, span_danger("Atmospherics reboot failed!"))
+
+/proc/fix_atmos_grief()
+ log_admin("Full atmosphere reset initiated by [usr].")
+ to_chat(world, "Initiating restart of atmosphere. The server may lag a bit.")
+ sleep(10)
+ var/current_time = world.timeofday
+
+ // Depower the supermatter, as it would quickly blow up once we remove all gases from the pipes.
+ /*for(var/obj/machinery/power/supermatter_crystal/S in GLOB.machines)
+ S.power = 0*/
+ to_chat(usr, "\[1/5\] - Supermatter depowered")
+
+ // Remove all gases from all pipenets
+ for(var/datum/pipeline/PN as anything in SSairmachines.networks)
+ for(var/datum/gas_mixture/G in list(PN.air) & PN.other_airs)
+ G.gas = list()
+ AIR_UPDATE_VALUES(G)
+
+ to_chat(usr, "\[2/5\] - All pipenets purged of gas.")
+
+ // Delete all zones.
+ for(var/zone/Z in world)
+ Z.invalidate()
+
+ to_chat(usr, "\[3/5\] - All ZAS Zones removed.")
+
+ var/list/unsorted_overlays = list()
+ for(var/id in xgm_gas_data.tile_overlay)
+ unsorted_overlays |= xgm_gas_data.tile_overlay[id]
+
+ for(var/turf/T in world)
+ if(!T.simulated)
+ continue
+ T.air = null
+ T.overlays.Remove(unsorted_overlays)
+ T.zone = null
+
+ to_chat(usr, "\[4/5\] - All turfs reset to roundstart values.")
+
+ SSzas.Reboot()
+
+ to_chat(usr, "\[5/5\] - ZAS Rebooted")
+ to_chat(world, "Atmosphere restart completed in [(world.timeofday - current_time)/10] seconds.")
+ return TRUE
diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm
index 427dc6f577b..62e5fde8552 100644
--- a/code/modules/admin/verbs/secrets.dm
+++ b/code/modules/admin/verbs/secrets.dm
@@ -451,12 +451,12 @@ GLOBAL_DATUM(everyone_a_traitor, /datum/everyone_is_a_traitor_controller)
return
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Bomb Cap"))
- var/newBombCap = input(holder,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be above 4)", "New Bomb Cap", GLOB.MAX_EX_LIGHT_RANGE) as num|null
- if (!CONFIG_SET(number/bombcap, newBombCap))
+ var/newBombCap = input(holder,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be above 4)", "New Bomb Cap", zas_settings.maxex_light_range) as num|null
+ if(!newBombCap)
return
-
- message_admins(span_boldannounce("[key_name_admin(holder)] changed the bomb cap to [GLOB.MAX_EX_DEVESTATION_RANGE], [GLOB.MAX_EX_HEAVY_RANGE], [GLOB.MAX_EX_LIGHT_RANGE]"))
- log_admin("[key_name(holder)] changed the bomb cap to [GLOB.MAX_EX_DEVESTATION_RANGE], [GLOB.MAX_EX_HEAVY_RANGE], [GLOB.MAX_EX_LIGHT_RANGE]")
+ zas_settings.set_bomb_cap(newBombCap)
+ message_admins(span_boldannounce("[key_name_admin(holder)] changed the bomb cap to [zas_settings.maxex_devastation_range], [zas_settings.maxex_heavy_range], [zas_settings.maxex_light_range], [zas_settings.maxex_fire_range], [zas_settings.maxex_flash_range]"))
+ log_admin("[key_name_admin(holder)] changed the bomb cap to [zas_settings.maxex_devastation_range], [zas_settings.maxex_heavy_range], [zas_settings.maxex_light_range], [zas_settings.maxex_fire_range], [zas_settings.maxex_flash_range]")
//buttons that are fun for exactly you and nobody else.
if("monkey")
if(!is_funmin)
diff --git a/code/modules/antagonists/abductor/equipment/glands/plasma.dm b/code/modules/antagonists/abductor/equipment/glands/plasma.dm
index 9dc1cc0f9c7..41377d2db17 100644
--- a/code/modules/antagonists/abductor/equipment/glands/plasma.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/plasma.dm
@@ -18,5 +18,5 @@
owner.visible_message(span_danger("[owner] vomits a cloud of plasma!"))
var/turf/open/T = get_turf(owner)
if(istype(T))
- T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
+ T.atmos_spawn_air(GAS_PLASMA, 20, T20C)
owner.vomit()
diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm
index 457da47373f..7455b755489 100644
--- a/code/modules/antagonists/blob/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob_mobs.dm
@@ -282,7 +282,7 @@
verb_exclaim = "roars"
verb_yell = "bellows"
force_threshold = 10
- pressure_resistance = 50
+ //pressure_resistance = 50
mob_size = MOB_SIZE_LARGE
hud_type = /datum/hud/living/blobbernaut
diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm
index e04f47e3eaa..379f99ac02b 100644
--- a/code/modules/antagonists/blob/structures/_blob.dm
+++ b/code/modules/antagonists/blob/structures/_blob.dm
@@ -9,7 +9,7 @@
anchored = TRUE
layer = BELOW_MOB_LAYER
pass_flags_self = PASSBLOB
- can_atmos_pass = ATMOS_PASS_PROC
+ can_atmos_pass = CANPASS_PROC
obj_flags = CAN_BE_HIT|BLOCK_Z_OUT_DOWN // stops blob mobs from falling on multiz.
/// How many points the blob gets back when it removes a blob of that type. If less than 0, blob cannot be removed.
var/point_return = 0
@@ -42,7 +42,7 @@
setDir(pick(GLOB.cardinals))
update_appearance()
if(atmosblock)
- air_update_turf(TRUE, TRUE)
+ update_nearby_tiles()
ConsumeTile()
if(!QDELETED(src)) //Consuming our tile can in rare cases cause us to del
AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOB, CELL_VIRUS_TABLE_GENERIC, 2, 2)
@@ -69,7 +69,7 @@
/obj/structure/blob/Destroy()
if(atmosblock)
atmosblock = FALSE
- air_update_turf(TRUE, FALSE)
+ update_nearby_tiles()
if(overmind)
overmind.all_blobs -= src
overmind.blobs_legit -= src //if it was in the legit blobs list, it isn't now
@@ -98,8 +98,10 @@
/obj/structure/blob/block_superconductivity()
return atmosblock
-/obj/structure/blob/can_atmos_pass(turf/T, vertical = FALSE)
- return !atmosblock
+/obj/structure/blob/zas_canpass(turf/T)
+ if(QDELETED(src))
+ return AIR_ALLOWED
+ return atmosblock ? (AIR_BLOCKED|ZONE_BLOCKED) : AIR_ALLOWED
/obj/structure/blob/update_icon() //Updates color based on overmind color if we have an overmind.
. = ..()
diff --git a/code/modules/antagonists/blob/structures/shield.dm b/code/modules/antagonists/blob/structures/shield.dm
index d086050210c..a329a247081 100644
--- a/code/modules/antagonists/blob/structures/shield.dm
+++ b/code/modules/antagonists/blob/structures/shield.dm
@@ -32,7 +32,7 @@
. = ..()
if(. && atom_integrity > 0)
atmosblock = atom_integrity < (max_integrity * 0.5)
- air_update_turf(TRUE, atmosblock)
+ //air_update_turf(TRUE, atmosblock)
/obj/structure/blob/shield/update_icon_state()
icon_state = "[initial(icon_state)][(atom_integrity < (max_integrity * 0.5)) ? "_damaged" : null]"
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 1ebd987a682..f91a8fc9cd8 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -771,7 +771,8 @@ structure_check() searches for nearby cultist structures required for the invoca
if(QDELETED(src))
return
do_area_burn(T, 1.5)
- new /obj/effect/hotspot(T)
+ //new /obj/effect/hotspot(T)
+ T.create_fire(1, 10)
qdel(src)
/obj/effect/rune/blood_boil/proc/do_area_burn(turf/T, multiplier)
diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm
index d7542b55b02..b9b977f4f03 100644
--- a/code/modules/antagonists/heretic/knowledge/void_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm
@@ -48,7 +48,7 @@
return FALSE
var/turf/open/our_turf = loc
- if(our_turf.GetTemperature() > T0C)
+ if(our_turf.return_temperature() > T0C)
loc.balloon_alert(user, "ritual failed, not cold enough!")
return FALSE
@@ -189,7 +189,7 @@
return FALSE
var/turf/open/our_turf = loc
- if(our_turf.GetTemperature() > T0C)
+ if(our_turf.return_temperature() > T0C)
loc.balloon_alert(user, "ritual failed, not cold enough!")
return FALSE
diff --git a/code/modules/antagonists/heretic/magic/ash_ascension.dm b/code/modules/antagonists/heretic/magic/ash_ascension.dm
index e43b7fb4c94..49c1e4460dd 100644
--- a/code/modules/antagonists/heretic/magic/ash_ascension.dm
+++ b/code/modules/antagonists/heretic/magic/ash_ascension.dm
@@ -39,7 +39,8 @@
return
for(var/turf/nearby_turf as anything in RANGE_TURFS(1, current_user))
- new /obj/effect/hotspot(nearby_turf)
+ //new /obj/effect/hotspot(nearby_turf)
+ nearby_turf.create_fire(1, 10)
nearby_turf.hotspot_expose(750, 25 * delta_time, 1)
for(var/mob/living/fried_living in nearby_turf.contents - current_user)
fried_living.adjustFireLoss(2.5 * delta_time)
@@ -65,7 +66,8 @@
var/current_range = 1
for(var/i in 0 to max_range)
for(var/turf/nearby_turf as anything in spiral_range_turfs(current_range, centre))
- new /obj/effect/hotspot(nearby_turf)
+ //new /obj/effect/hotspot(nearby_turf)
+ nearby_turf.create_fire(1, 10)
nearby_turf.hotspot_expose(750, 50, 1)
for(var/mob/living/fried_living in nearby_turf.contents - centre)
fried_living.adjustFireLoss(5)
@@ -133,7 +135,8 @@
L.adjustFireLoss(20)
to_chat(L, span_userdanger("You're hit by [source]'s eldritch flames!"))
- new /obj/effect/hotspot(T)
+ //new /obj/effect/hotspot(T)
+ T.create_fire(1, 10)
T.hotspot_expose(700,50,1)
// deals damage to mechs
for(var/obj/vehicle/sealed/mecha/M in T.contents)
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index 7f43464b01f..89186cc4ed2 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -3,7 +3,7 @@
GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/obj/machinery/field/containment,
- /obj/machinery/power/supermatter_crystal,
+ //obj/machinery/power/supermatter_crystal,
/obj/machinery/doomsday_device,
/obj/machinery/nuclearbomb,
/obj/machinery/nuclearbomb/selfdestruct,
@@ -29,12 +29,12 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/obj/machinery/atmospherics/components/unary/portables_connector,
/obj/machinery/atmospherics/components/unary/passive_vent,
/obj/machinery/atmospherics/components/unary/heat_exchanger,
- /obj/machinery/atmospherics/components/unary/hypertorus/core,
- /obj/machinery/atmospherics/components/unary/hypertorus/waste_output,
- /obj/machinery/atmospherics/components/unary/hypertorus/moderator_input,
- /obj/machinery/atmospherics/components/unary/hypertorus/fuel_input,
- /obj/machinery/hypertorus/interface,
- /obj/machinery/hypertorus/corner,
+ // /obj/machinery/atmospherics/components/unary/hypertorus/core,
+ // /obj/machinery/atmospherics/components/unary/hypertorus/waste_output,
+ // /obj/machinery/atmospherics/components/unary/hypertorus/moderator_input,
+ // /obj/machinery/atmospherics/components/unary/hypertorus/fuel_input,
+ // /obj/machinery/hypertorus/interface,
+ // /obj/machinery/hypertorus/corner,
/obj/machinery/atmospherics/components/binary/valve,
/obj/machinery/portable_atmospherics/canister,
)))
diff --git a/code/modules/art/statues.dm b/code/modules/art/statues.dm
index 241e598ae8a..882f235cb27 100644
--- a/code/modules/art/statues.dm
+++ b/code/modules/art/statues.dm
@@ -6,7 +6,7 @@
density = TRUE
anchored = FALSE
max_integrity = 100
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
material_modifier = 0.5
material_flags = MATERIAL_EFFECTS | MATERIAL_AFFECT_STATISTICS
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm
index d033f862b88..f32083ae17d 100644
--- a/code/modules/assembly/bomb.dm
+++ b/code/modules/assembly/bomb.dm
@@ -151,10 +151,8 @@
START_PROCESSING(SSobj, src)
var/datum/gas_mixture/our_mix = return_air()
- our_mix.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
- var/fuel_moles = our_mix.gases[/datum/gas/plasma][MOLES] + our_mix.gases[/datum/gas/oxygen][MOLES]/6
- our_mix.garbage_collect()
- var/datum/gas_mixture/bomb_mixture = our_mix.copy()
+ var/fuel_moles = our_mix.getGroupGas(GAS_PLASMA) + our_mix.getGroupGas(GAS_OXYGEN)/6
+ var/datum/gas_mixture/bomb_mixture = our_mix.copyFrom()
var/strength = 1
var/turf/ground_zero = get_turf(loc)
@@ -204,7 +202,7 @@
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
var/datum/gas_mixture/our_mix = return_air()
- var/datum/gas_mixture/removed = remove_air(our_mix.total_moles())
+ var/datum/gas_mixture/removed = remove_air(our_mix.get_moles())
var/turf/T = get_turf(src)
if(!T)
return
diff --git a/code/modules/atmospherics/Atmospherics.md b/code/modules/atmospherics/Atmospherics.md
index 6d61a8cf16b..c5963cf03ff 100644
--- a/code/modules/atmospherics/Atmospherics.md
+++ b/code/modules/atmospherics/Atmospherics.md
@@ -116,7 +116,7 @@ var/datum/gas_mixture/air = new
air.assert_gas(/datum/gas/oxygen)
air.gases[/datum/gas/oxygen][MOLES] = 100
world << air.gases[/datum/gas/oxygen][GAS_META][META_GAS_NAME] //outputs "Oxygen"
-world << air.gases.heat_capacity() //outputs 2000 (100 mol * 20 J/K/mol)
+world << air.gases.getHeatCapacity() //outputs 2000 (100 mol * 20 J/K/mol)
air.gases[/datum/gas/oxygen][MOLES] -= 110
air.garbage_collect() //oxygen is now removed from the gases list, since it was empty
```
@@ -128,16 +128,16 @@ Of particular note in this snippet are the two procs assert_gas() and garbage_co
* *`/datum/gas_mixture/proc/assert_gas()`* - Used before accessing a particular type of gas.
* *`/datum/gas_mixture/proc/assert_gases()`* - Shorthand for calling assert_gas() multiple times.
* *`/datum/gas_mixture/proc/garbage_collect()`* - Used after removing any number of moles from a mixture.
-* *`/datum/gas_mixture/proc/return_pressure()`* - Pressure is what should be displayed to players to quantify gas; measured in kilopascals.
+* *`/datum/gas_mixture/proc/returnPressure()`* - Pressure is what should be displayed to players to quantify gas; measured in kilopascals.
* *`/datum/gas_mixture/var/temperature`* - Measured in kelvins. Useful constants are T0C and T20C for 0 and 20 degrees Celsius respectively, and TCMB,the temperature of space and the lower bound for temperature in atmos.
* *`/datum/gas_mixture/var/volume`* - Measured in liters.
While we're on the subject, `/datum/gas_mixture` has two subtypes.
-The first is `/datum/gas_mixture/turf`, which exists for literally one purpose. When a turf is empty, we want it to have the same heat capacity as space. This lets us achieve that by overriding `heat_capacity()`
+The first is `/datum/gas_mixture/turf`, which exists for literally one purpose. When a turf is empty, we want it to have the same heat capacity as space. This lets us achieve that by overriding `getHeatCapacity()`
The second is `/datum/gas_mixture/immutable`, which itself has two subtypes.
The type is built to allow for gasmixtures that serve as infinite sources of "something", which can't be changed or mutated.
-It's used by `/datum/gas_mixture/immutable/space`, which implements some particular things for `heat_capacity()` and some optimizations for gas operations.
+It's used by `/datum/gas_mixture/immutable/space`, which implements some particular things for `getHeatCapacity()` and some optimizations for gas operations.
It's also implemented by `/datum/gas_mixture/immutable/planetary`, which is used for planetary turfs, and has some code that makes actually having a gasmix possible.
diff --git a/code/modules/atmospherics/ZAS/Airflow.dm b/code/modules/atmospherics/ZAS/Airflow.dm
new file mode 100644
index 00000000000..67227f99ec4
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Airflow.dm
@@ -0,0 +1,237 @@
+/*
+Contains helper procs for airflow, handled in /connection_group.
+This entire system is an absolute mess.
+*/
+#define AIRBORNE_DAMAGE(airborne_thing) (min(airborne_thing.airflow_speed, (airborne_thing.airborne_acceleration*2)) * zas_settings.airflow_damage)
+
+/mob
+ var/tmp/last_airflow_stun = 0
+
+/atom/movable
+ ///The location the atom is trying to step towards during airflow.
+ var/tmp/turf/airflow_dest
+ ///The speed the object is travelling during airflow
+ var/tmp/airflow_speed = 0
+ ///Time (ticks) spent in airflow
+ var/tmp/airflow_time = 0
+ ///Time (ticks) since last airflow movement
+ var/tmp/last_airflow = 0
+ var/tmp/airborne_acceleration = 0
+
+ var/tmp/airflow_xo
+ var/tmp/airflow_yo
+ ///If the movable is dense by default, it won't step into tiles containing other dense objects
+ var/tmp/airflow_originally_not_dense
+ var/tmp/airflow_process_delay
+ var/tmp/airflow_skip_speedcheck
+
+///Applies the effects of the mob colliding with another movable due to airflow.
+/mob/proc/airflow_stun(delta_p)
+ return
+
+/mob/living/airflow_stun(delta_p)
+ if(stat == 2)
+ return FALSE
+ if(pulledby || pulling)
+ return FALSE
+ if(last_airflow_stun > world.time - zas_settings.airflow_stun_cooldown)
+ return FALSE
+ if(!(status_flags & CANSTUN) && !(status_flags & CANKNOCKDOWN))
+ return FALSE
+ if(buckled)
+ return FALSE
+ if(body_position == LYING_DOWN) //Lying down protects you from Z A S M O M E N T S
+ return FALSE
+ if(HAS_TRAIT(src, TRAIT_NEGATES_GRAVITY)) //Magboots
+ return FALSE
+ if(IsKnockdown()) //Uhhh maybe?
+ return FALSE
+
+ Knockdown(zas_settings.airflow_stun * clamp((delta_p / zas_settings.airflow_stun_pressure), 1, 3))
+ visible_message(
+ span_danger("[src] is thrown to the floor by a gust of air!"),
+ span_danger("A sudden rush of air knocks you over!"),
+ span_hear("You hear a gust of air, followed by a soft thud.")
+ )
+
+ last_airflow_stun = world.time
+
+/mob/living/silicon/airflow_stun(delta_p)
+ return
+
+/mob/living/simple_animal/slime/airflow_stun(delta_p)
+ return
+
+///Checks to see if airflow can move this movable.
+/atom/movable/proc/check_airflow_movable(n)
+ //We're just hoping nothing goes wrong
+ return TRUE
+
+/mob/check_airflow_movable(n)
+ if(status_flags & GODMODE)
+ return FALSE
+ if(n < zas_settings.airflow_heavy_pressure)
+ return FALSE
+ if(HAS_TRAIT(src, TRAIT_NEGATES_GRAVITY)) //Magboots
+ return FALSE
+ return ..()
+
+/mob/living/silicon/check_airflow_movable()
+ return 0
+
+/obj/check_airflow_movable(n)
+ if(anchored)
+ return FALSE
+ if(n < zas_settings.airflow_dense_pressure)
+ if(airflow_dest)
+ if(!airflow_originally_not_dense)
+ return FALSE
+ else if(density)
+ return FALSE
+ return ..()
+
+/obj/item/check_airflow_movable(n)
+ switch(w_class)
+ if(0,1,2)
+ if(n < zas_settings.airflow_lightest_pressure) return 0
+ if(3)
+ if(n < zas_settings.airflow_light_pressure) return 0
+ if(4,5)
+ if(n < zas_settings.airflow_medium_pressure) return 0
+ if(6)
+ if(n < zas_settings.airflow_heavy_pressure) return 0
+ if(7 to INFINITY)
+ if(n < zas_settings.airflow_dense_pressure) return 0
+ return ..()
+
+/atom/movable/Bump(atom/A)
+ if(airflow_speed > 0 && airflow_dest)
+ var/turf/T = get_turf(A)
+ if(airborne_acceleration > 1)
+ airflow_hit(A)
+ A.airflow_hit_act(src)
+ else if(istype(src, /mob/living/carbon/human) && ismovable(A) && !(A:airflow_originally_not_dense))
+ to_chat(src, "You are pinned against [A] by airflow!")
+ src:Stun(1 SECONDS) // :)
+ /*
+ If the turf of the atom we bumped is NOT dense, then we check if the flying object is dense.
+ We check the special var because flying objects gain density so they can Bump() objects.
+ If the object is NOT normally dense, we remove our density and the target's density,
+ enabling us to step into their turf. Then, we set the density back to the way its supposed to be for airflow.
+ */
+ if(!T.density)
+ if(ismovable(A) && A:airflow_originally_not_dense)
+ set_density(FALSE)
+ A.set_density(FALSE)
+ step_towards(src, airflow_dest)
+ set_density(TRUE)
+ A.set_density(TRUE)
+ else
+ airflow_speed = 0
+ airflow_time = 0
+ airborne_acceleration = 0
+ . = ..()
+
+///Called when src collides with A during airflow
+/atom/movable/proc/airflow_hit(atom/A)
+ SHOULD_CALL_PARENT(TRUE)
+ airflow_speed = 0
+ airflow_dest = null
+ airborne_acceleration = 0
+ A.airflow_hit_act(src)
+
+/mob/living/airflow_hit(atom/A)
+ var/b_loss = AIRBORNE_DAMAGE(src)
+ apply_damage(b_loss, BRUTE)
+ return ..()
+
+/mob/living/carbon/airflow_hit(atom/A)
+ if(istype(A, /obj/structure) || iswallturf(A))
+ if(airflow_speed > 10)
+ Paralyze(round(airflow_speed * zas_settings.airflow_stun))
+ Stun(round(airflow_speed * zas_settings.airflow_stun) + 3)
+ loc.add_blood_DNA(return_blood_DNA())
+ visible_message(
+ span_danger("[src] splats against \the [A]!"),
+ span_userdanger("You slam into \the [A] with tremendous force!"),
+ span_hear("You hear a loud thud.")
+ )
+ INVOKE_ASYNC(emote("scream"))
+ else
+ Stun(round(airflow_speed * zas_settings.airflow_stun/2))
+ visible_message(
+ span_danger("[src] slams into \the [A]!"),
+ span_userdanger("You're thrown against \the [A] by pressure!"),
+ span_hear("You hear a loud thud.")
+ )
+
+ return ..()
+
+///Called when "flying" calls airflow_hit() on src
+/atom/proc/airflow_hit_act(atom/movable/flying)
+ return
+
+/mob/living/airflow_hit_act(atom/movable/flying)
+ . = ..()
+ src.visible_message(
+ span_danger("A flying [flying.name] slams into \the [src]!"),
+ span_danger("You're hit by a flying [flying]!"),
+ span_danger("You hear a soft thud.")
+ )
+
+ playsound(src.loc, "punch", 25, 1, -1)
+ var/weak_amt
+ if(istype(flying,/obj/item))
+ weak_amt = flying:w_class*2 ///Heheheh
+ else if(!flying.airflow_originally_not_dense) //If the object is dense by default (this var is stupidly named)
+ weak_amt = 5 //Getting crushed by a flying canister or computer is going to fuck you up
+ else
+ weak_amt = rand(1, 3)
+
+ src.Knockdown(weak_amt SECONDS)
+
+/obj/airflow_hit_act(atom/movable/flying)
+ . = ..()
+ if(!flying.airflow_originally_not_dense)
+ src.visible_message(
+ span_danger("A flying [flying.name] slams into \the [src]!"),
+ null,
+ span_danger("You hear a loud slam!")
+ )
+
+ playsound(src.loc, "smash.ogg", 25, 1, -1)
+
+ if(!uses_integrity)
+ return
+
+ take_damage(zas_settings.airflow_damage, BRUTE)
+
+/mob/living/carbon/human/airflow_hit_act(atom/movable/flying)
+ . = ..()
+
+ if (prob(33))
+ loc.add_blood_DNA(return_blood_DNA())
+
+ var/b_loss = AIRBORNE_DAMAGE(flying)
+
+ apply_damage(b_loss/3, BRUTE, BODY_ZONE_HEAD)
+
+ apply_damage(b_loss/3, BRUTE, BODY_ZONE_CHEST)
+
+
+ if(airflow_speed > 10)
+ Paralyze(round(flying.airflow_speed * zas_settings.airflow_stun))
+ Stun(round(flying.airflow_speed * zas_settings.airflow_stun) + 3)
+ else
+ Stun(round(flying.airflow_speed * zas_settings.airflow_stun/2))
+
+/zone/proc/movables()
+ RETURN_TYPE(/list)
+ . = list()
+ for(var/turf/T in contents)
+ for(var/atom/movable/A as anything in T)
+ if(!A.simulated || A.anchored)
+ continue
+ . += A
+
+#undef AIRBORNE_DAMAGE
diff --git a/code/modules/atmospherics/ZAS/Atom.dm b/code/modules/atmospherics/ZAS/Atom.dm
new file mode 100644
index 00000000000..c0bb67ae42b
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Atom.dm
@@ -0,0 +1,43 @@
+//Convenience function for atoms to update turfs they occupy
+/atom/movable/proc/update_nearby_tiles()
+ for(var/turf/turf in locs)
+ if(!turf.simulated)
+ continue
+ SSzas.mark_for_update(turf)
+
+ return 1
+
+
+//Returns:
+// 0 / AIR_ALLOWED - Not blocked. Air and zones can mingle with this turf as they please.
+// AIR_BLOCKED - Blocked. Air cannot move into, out of, or over this turf.
+// ZONE_BLOCKED - Air can flow in this turf, but zones may not merge over it.
+///Checks whether or not ZAS can occupy this atom's turf. Invoked by the ATMOS_CANPASS_TURF macro.
+/atom/proc/zas_canpass(turf/other)
+ #ifdef ZASDBG
+ ASSERT(isturf(other))
+ #endif
+ if(can_atmos_pass == CANPASS_PROC)
+ CRASH("Atmos pass assigned proc when proc doesn't exist.")
+ else
+ CRASH("FUCK. zas_canpass() invoked when the atom doesn't even use it")
+
+// This is a legacy proc only here for compatibility - you probably should just use ATMOS_CANPASS_TURF directly.
+/turf/zas_canpass(turf/other)
+ #ifdef ZASDBG
+ ASSERT(isturf(other))
+ #endif
+
+ . = 0
+ ATMOS_CANPASS_TURF(., src, other)
+ stack_trace("Turf ZAS canpass invoked.")
+
+/atom/proc/zas_mark_update()
+ var/turf/local_turf = get_turf(loc)
+ if(!local_turf)
+ return
+ SSzas.mark_for_update(local_turf)
+
+/atom
+ var/simulated = TRUE
+ var/can_atmos_pass = CANPASS_ALWAYS
diff --git a/code/modules/atmospherics/ZAS/Connection.dm b/code/modules/atmospherics/ZAS/Connection.dm
new file mode 100644
index 00000000000..2aa037d09c7
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Connection.dm
@@ -0,0 +1,240 @@
+#define CONNECTION_DIRECT 2
+#define CONNECTION_SPACE 4
+#define CONNECTION_INVALID 8
+
+/*
+
+Overview:
+ Connections are made between turfs by SSzas.connect(). They represent a single point where two zones converge.
+
+Class Vars:
+ A - Always a simulated turf.
+ B - A simulated or unsimulated turf.
+
+ zoneA - The archived zone of A. Used to check that the zone hasn't changed.
+ zoneB - The archived zone of B. May be null in case of unsimulated connections.
+
+ edge - Stores the edge this connection is in. Can reference an edge that is no longer processed
+ after this connection is removed, so make sure to check edge.coefficient > 0 before re-adding it.
+
+Class Procs:
+
+ mark_direct()
+ Marks this connection as direct. Does not update the edge.
+ Called when the connection is made and there are no doors between A and B.
+ Also called by update() as a correction.
+
+ mark_indirect()
+ Unmarks this connection as direct. Does not update the edge.
+ Called by update() as a correction.
+
+ mark_space()
+ Marks this connection as unsimulated. Updating the connection will check the validity of this.
+ Called when the connection is made.
+ This will not be called as a correction, any connections failing a check against this mark are erased and rebuilt.
+
+ direct()
+ Returns 1 if no doors are in between A and B.
+
+ valid()
+ Returns 1 if the connection has not been erased.
+
+ erase()
+ Called by update() and connection_manager/erase_all().
+ Marks the connection as erased and removes it from its edge.
+
+ update()
+ Called by connection_manager/update_all().
+ Makes numerous checks to decide whether the connection is still valid. Erases it automatically if not.
+
+*/
+
+/connection
+ var/turf/A
+ var/turf/B
+ var/zone/zoneA
+ var/zone/zoneB
+
+ var/connection_edge/edge
+
+ ///Invalid or Valid
+ var/state = 0
+
+ #ifdef ZASDBG
+ ///Set to true during testing to get verbose debug information
+ var/tmp/verbose = FALSE
+ #endif
+
+/connection/New(turf/A, turf/B)
+ #ifdef ZASDBG
+ //ASSERT(TURF_HAS_VALID_ZONE(A))
+ //ASSERT(SSzas.has_valid_zone(B))
+ #endif
+ src.A = A
+ src.B = B
+ zoneA = A.zone
+ if(!B.simulated)
+ mark_space()
+ edge = SSzas.get_edge(A.zone,B)
+ edge.add_connection(src)
+ else
+ zoneB = B.zone
+ edge = SSzas.get_edge(A.zone,B.zone)
+ edge.add_connection(src)
+
+///Unmarks this connection as direct. Does not update the edge. Called by update() as a correction.
+/connection/proc/mark_direct()
+ if(!direct())
+ state |= CONNECTION_DIRECT
+ edge.direct++
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Marked direct.")
+ #endif
+
+///Unmarks this connection as direct. Does not update the edge. Called by update() as a correction.
+/connection/proc/mark_indirect()
+ if(direct())
+ state &= ~CONNECTION_DIRECT
+ edge.direct--
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Marked indirect.")
+ #endif
+
+///Marks this connection as unsimulated. Updating the connection will check the validity of this. See file header for more information.
+/connection/proc/mark_space()
+ state |= CONNECTION_SPACE
+
+///Returns 1 if no doors are in between A and B.
+/connection/proc/direct()
+ return (state & CONNECTION_DIRECT)
+
+///Returns 1 if the connection has not been erased.
+/connection/proc/valid()
+ return !(state & CONNECTION_INVALID)
+
+///Called by update() and connection_manager/erase_all(). Marks the connection as erased and removes it from its edge.
+/connection/proc/erase()
+ edge.remove_connection(src)
+ state |= CONNECTION_INVALID
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Connection Erased: [state]")
+ #endif
+
+///Makes numerous checks to decide whether the connection is still valid. Erases it automatically if not.
+/connection/proc/update()
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Updated, \...")
+ #endif
+
+ if(!A.simulated) //If turf A isn't simulated, erase this connection.
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Invalid A. Erasing...")
+ #endif
+
+ erase()
+ return
+
+ var/block_status = SSzas.air_blocked(A,B)
+ if(block_status & AIR_BLOCKED) //If turfs A and B cant mingle, erase this connection
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Blocked connection. Erasing...")
+ #endif
+
+ erase()
+ return
+
+ else if(block_status & ZONE_BLOCKED) //If they can mingle but they can't merge zones, mark this connection as indirect
+ mark_indirect()
+ else
+ mark_direct()
+
+ var/b_is_space = !B.simulated
+
+ if(state & CONNECTION_SPACE)
+ if(!b_is_space) //If this is an unsimulated connection and B isn't unsimulated, erase.
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Invalid B. Erasing...")
+ #endif
+ erase()
+ return
+
+ if(A.zone != zoneA) //If turf A's zone has changed, attempt to migrate the connection to the new zone. Otherwise, erase.
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Zone changed, \...")
+ #endif
+
+ if(!A.zone) //No zone, erase.
+ erase()
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Turf A's zone has disappeared. Erasing...")
+ #endif
+ return
+
+ else
+ edge.remove_connection(src)
+ edge = SSzas.get_edge(A.zone, B)
+ edge.add_connection(src)
+ zoneA = A.zone
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Connection is valid.")
+ #endif
+ return
+
+ else if(b_is_space) //If B is unsimulated and this isn't an unsimulated connection, erase.
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Turf B is unsimulated, but this is a simulated connection. Erasing...")
+ #endif
+ erase()
+ return
+
+ if(A.zone == B.zone) //If both turfs share a zone, erase.
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Turf A and Turf B share a zone. Erasing...")
+ #endif
+ erase()
+ return
+
+ if(A.zone != zoneA || (zoneB && (B.zone != zoneB))) //If either turf's zone changed
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Zones changed, \...")
+ #endif
+
+ if(A.zone && B.zone) //Find where we're supposed to be and move us there
+ edge.remove_connection(src)
+ edge = SSzas.get_edge(A.zone, B.zone)
+ edge.add_connection(src)
+ zoneA = A.zone
+ zoneB = B.zone
+ else
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Turf A or B lost it's zone. Erasing...")
+ #endif
+ erase()
+ return
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Connection is valid.")
+ #endif
+
+/connection_edge/proc/queue_spacewind()
+ return
diff --git a/code/modules/atmospherics/ZAS/ConnectionGroup.dm b/code/modules/atmospherics/ZAS/ConnectionGroup.dm
new file mode 100644
index 00000000000..b5908e65387
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/ConnectionGroup.dm
@@ -0,0 +1,311 @@
+/*
+
+Overview:
+ These are what handle gas transfers between zones and into space.
+ They are found in a zone's edges list and in SSzas.edges.
+ Each edge updates every air tick due to their role in gas transfer.
+ They come in two flavors, /connection_edge/zone and /connection_edge/unsimulated.
+ As the type names might suggest, they handle inter-zone and spacelike connections respectively.
+
+Class Vars:
+
+ A - This always holds a zone. In unsimulated edges, it holds the only zone.
+
+ connecting_turfs - This holds a list of connected turfs, mainly for the sake of airflow.
+
+ coefficent - This is a marker for how many connections are on this edge. Used to determine the ratio of flow.
+
+ connection_edge/zone
+
+ B - This holds the second zone with which the first zone equalizes.
+
+ direct - This counts the number of direct (i.e. with no doors) connections on this edge.
+ Any value of this is sufficient to make the zones mergeable.
+
+ connection_edge/unsimulated
+
+ B - This holds an unsimulated turf which has the gas values this edge is mimicing.
+
+ air - Retrieved from B on creation and used as an argument for the legacy ShareSpace() proc.
+
+Class Procs:
+
+ add_connection(connection/c)
+ Adds a connection to this edge. Usually increments the coefficient and adds a turf to connecting_turfs.
+
+ remove_connection(connection/c)
+ Removes a connection from this edge. This works even if c is not in the edge, so be careful.
+ If the coefficient reaches zero as a result, the edge is erased.
+
+ contains_zone(zone/Z)
+ Returns true if either A or B is equal to Z. Unsimulated connections return true only on A.
+
+ erase()
+ Removes this connection from processing and zone edge lists.
+
+ tick()
+ Called every air tick on edges in the processing list. Equalizes gas.
+
+ flow(list/movable, differential, repelled)
+ Airflow proc causing all objects in movable to be checked against a pressure differential.
+ If repelled is true, the objects move away from any turf in connecting_turfs, otherwise they approach.
+ A check against zas_settings.lightest_airflow_pressure should generally be performed before calling this.
+
+ get_connected_zone(zone/from)
+ Helper proc that allows getting the other zone of an edge given one of them.
+ Only on /connection_edge/zone, otherwise use A.
+
+*/
+
+
+/connection_edge
+ var/zone/A
+
+ var/list/connecting_turfs = list()
+ var/direct = 0
+ var/sleeping = 1
+ var/coefficient = 0
+
+ ///The last time the "woosh" airflow sound played, world.time
+ var/last_woosh
+
+ #ifdef ZASDBG
+ ///Set this to TRUE during testing to get verbose debug information.
+ var/tmp/verbose = FALSE
+ #endif
+
+/connection_edge/New()
+ CRASH("Cannot make connection edge without specifications.")
+
+///Adds a connection to this edge. Usually increments the coefficient and adds a turf to connecting_turfs.
+/connection_edge/proc/add_connection(connection/c)
+ coefficient++
+ if(c.direct())
+ direct++
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Connection added: [type] Coefficient: [coefficient]")
+ #endif
+
+///Removes a connection from this edge. This works even if c is not in the edge, so be careful.
+/connection_edge/proc/remove_connection(connection/c)
+ coefficient--
+ if(coefficient <= 0)
+ erase()
+ if(c.direct())
+ direct--
+
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Connection removed: [type] Coefficient: [coefficient-1]")
+ #endif
+
+///Returns true if either A or B is equal to Z. Unsimulated connections return true only on A.
+/connection_edge/proc/contains_zone(zone/Z)
+ return
+
+///Removes this connection from processing and zone edge lists.
+/connection_edge/proc/erase()
+ SSzas.remove_edge(src)
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("[type] Erased.")
+ #endif
+
+///Called every air tick on edges in the processing list. Equalizes gas.
+/connection_edge/proc/tick()
+ return
+
+///Checks both connection ends to see if they need to process.
+/connection_edge/proc/recheck()
+ return
+
+///Airflow proc causing all objects in movable to be checked against a pressure differential. See file header for more info.
+/connection_edge/proc/flow(list/movable, differential, repelled)
+ for(var/i in 1 to length(movable))
+ var/atom/movable/M = movable[i]
+ //Non simulated objects dont get tossed
+ if(!M.simulated) continue
+
+ //If they're already being tossed, don't do it again.
+ if(M.last_airflow > world.time - zas_settings.airflow_delay) continue
+ if(M.airflow_speed) continue
+
+ //Check for knocking people over
+ if(ismob(M) && differential > zas_settings.airflow_stun_pressure)
+ if(M:status_flags & GODMODE) continue
+ if(!M:airflow_stun())
+ to_chat(M, "Air suddenly rushes past you!")
+
+ if(M.check_airflow_movable(differential))
+ //Check for things that are in range of the midpoint turfs.
+ var/list/close_turfs = list()
+ for(var/turf/U in connecting_turfs)
+ if(get_dist(M,U) < world.view) close_turfs += U
+ if(!close_turfs.len) continue
+
+ M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards.
+
+ //Soul code im too scared to touch
+ if(repelled) spawn if(M) M.RepelAirflowDest(differential/5)
+ else spawn if(M) M.GotoAirflowDest(differential/10)
+
+
+
+
+/connection_edge/zone
+ var/zone/B
+
+/connection_edge/zone/New(zone/A, zone/B)
+
+ src.A = A
+ src.B = B
+ A.edges.Add(src)
+ B.edges.Add(src)
+ //id = edge_id(A,B)
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("New edge between [A] and [B]")
+ #endif
+
+/connection_edge/zone/add_connection(connection/c)
+ . = ..()
+ connecting_turfs.Add(c.A)
+
+/connection_edge/zone/remove_connection(connection/c)
+ connecting_turfs.Remove(c.A)
+ return ..()
+
+/connection_edge/zone/contains_zone(zone/Z)
+ return A == Z || B == Z
+
+/connection_edge/zone/erase()
+ A.edges.Remove(src)
+ B.edges.Remove(src)
+ return ..()
+
+/connection_edge/zone/tick()
+ if(A.invalid || B.invalid)
+ erase()
+ return
+
+ var/equiv = A.air.shareRatio(B.air, coefficient)
+
+ queue_spacewind()
+
+ if(equiv)
+ if(direct)
+ erase()
+ SSzas.merge(A, B)
+ return
+ else
+ A.air.equalize(B.air)
+ SSzas.mark_edge_sleeping(src)
+
+ SSzas.mark_zone_update(A)
+ SSzas.mark_zone_update(B)
+
+/connection_edge/zone/recheck()
+ if(!A.air.compare(B.air, vacuum_exception = 1))
+ // Edges with only one side being vacuum need processing no matter how close.
+ SSzas.mark_edge_active(src)
+
+/connection_edge/zone/queue_spacewind()
+ var/differential = A.air.returnPressure() - B.air.returnPressure()
+ if(abs(differential) >= zas_settings.airflow_lightest_pressure)
+ var/list/attracted
+ var/list/repelled
+ if(differential > 0)
+ attracted = A.movables()
+ repelled = B.movables()
+ else
+ attracted = B.movables()
+ repelled = A.movables()
+
+ WOOSH
+
+ flow(attracted, abs(differential), 0)
+ flow(repelled, abs(differential), 1)
+
+///Helper proc to get connections for a zone.
+/connection_edge/zone/proc/get_connected_zone(zone/from)
+ if(A == from)
+ return B
+ else
+ return A
+
+/connection_edge/unsimulated
+ var/turf/B
+ var/datum/gas_mixture/air
+
+/connection_edge/unsimulated/New(zone/A, turf/B)
+ src.A = A
+ src.B = B
+ A.edges.Add(src)
+ air = B.return_air()
+ #ifdef ZASDBG
+ if(verbose)
+ log_admin("New edge from [A] to [B] ([B.x], [B.y], [B.z]).")
+ #endif
+
+
+/connection_edge/unsimulated/add_connection(connection/c)
+ . = ..()
+ connecting_turfs.Add(c.B)
+ air.group_multiplier = coefficient
+
+/connection_edge/unsimulated/remove_connection(connection/c)
+ connecting_turfs.Remove(c.B)
+ air.group_multiplier = coefficient
+ return ..()
+
+/connection_edge/unsimulated/erase()
+ A.edges.Remove(src)
+ return ..()
+
+/connection_edge/unsimulated/contains_zone(zone/Z)
+ return A == Z
+
+/connection_edge/unsimulated/tick()
+ if(A.invalid)
+ erase()
+ return
+
+ var/equiv = A.air.shareSpace(air)
+
+ queue_spacewind()
+
+ if(equiv)
+ A.air.copyFrom(air)
+ SSzas.mark_edge_sleeping(src)
+
+ SSzas.mark_zone_update(A)
+
+/connection_edge/unsimulated/recheck()
+ // Edges with only one side being vacuum need processing no matter how close.
+ // Note: This handles the glaring flaw of a room holding pressure while exposed to space, but
+ // does not specially handle the less common case of a simulated room exposed to an unsimulated pressurized turf.
+ if(!A.air.compare(air, vacuum_exception = 1))
+ SSzas.mark_edge_active(src)
+
+/connection_edge/unsimulated/queue_spacewind()
+ var/differential = A.air.returnPressure() - air.returnPressure()
+ if(abs(differential) >= zas_settings.airflow_lightest_pressure)
+ var/list/attracted = A.movables()
+
+ WOOSH
+
+ flow(attracted, abs(differential), differential < 0)
+
+/proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
+ //This implements a simplistic version of the Stefan-Boltzmann law.
+ var/energy_delta = ((A.temperature - B.temperature) ** 4) * STEFAN_BOLTZMANN_CONSTANT * connecting_tiles * 2.5
+ var/maximum_energy_delta = max(0, min(A.temperature * A.getHeatCapacity() * A.group_multiplier, B.temperature * B.getHeatCapacity() * B.group_multiplier))
+ if(maximum_energy_delta > abs(energy_delta))
+ if(energy_delta < 0)
+ maximum_energy_delta *= -1
+ energy_delta = maximum_energy_delta
+
+ A.temperature -= energy_delta / (A.getHeatCapacity() * A.group_multiplier)
+ B.temperature += energy_delta / (B.getHeatCapacity() * B.group_multiplier)
diff --git a/code/modules/atmospherics/ZAS/ConnectionManager.dm b/code/modules/atmospherics/ZAS/ConnectionManager.dm
new file mode 100644
index 00000000000..c54099da70d
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/ConnectionManager.dm
@@ -0,0 +1,107 @@
+/*
+
+Overview:
+ The connection_manager class stores connections in each cardinal direction on a turf.
+ It isn't always present if a turf has no connections, check if(connections) before using.
+ Contains procs for mass manipulation of connection data.
+
+Class Vars:
+
+ NSEWUD - Connections to this turf in each cardinal direction.
+
+Class Procs:
+
+ get(d)
+ Returns the connection (if any) in this direction.
+ Preferable to accessing the connection directly because it checks validity.
+
+ place(connection/c, d)
+ Called by air_master.connect(). Sets the connection in the specified direction to c.
+
+ update_all()
+ Called after turf/update_air_properties(). Updates the validity of all connections on this turf.
+
+ erase_all()
+ Called when the turf is changed with ChangeTurf(). Erases all existing connections.
+
+Macros:
+ check(connection/c)
+ Checks for connection validity. It's possible to have a reference to a connection that has been erased.
+
+
+*/
+
+// macro-ized to cut down on proc calls
+#define check(c) (c && c.valid())
+
+/turf
+ var/tmp/connection_manager/connections
+
+/connection_manager/
+ var/connection/N
+ var/connection/S
+ var/connection/E
+ var/connection/W
+
+#ifdef MULTIZAS
+ var/connection/U
+ var/connection/D
+#endif
+
+/connection_manager/proc/get(d)
+ switch(d)
+ if(NORTH)
+ if(check(N)) return N
+ else return null
+ if(SOUTH)
+ if(check(S)) return S
+ else return null
+ if(EAST)
+ if(check(E)) return E
+ else return null
+ if(WEST)
+ if(check(W)) return W
+ else return null
+
+ #ifdef MULTIZAS
+ if(UP)
+ if(check(U)) return U
+ else return null
+ if(DOWN)
+ if(check(D)) return D
+ else return null
+ #endif
+
+/connection_manager/proc/place(connection/c, d)
+ switch(d)
+ if(NORTH) N = c
+ if(SOUTH) S = c
+ if(EAST) E = c
+ if(WEST) W = c
+
+ #ifdef MULTIZAS
+ if(UP) U = c
+ if(DOWN) D = c
+ #endif
+
+/connection_manager/proc/update_all()
+ if(check(N)) N.update()
+ if(check(S)) S.update()
+ if(check(E)) E.update()
+ if(check(W)) W.update()
+ #ifdef MULTIZAS
+ if(check(U)) U.update()
+ if(check(D)) D.update()
+ #endif
+
+/connection_manager/proc/erase_all()
+ if(check(N)) N.erase()
+ if(check(S)) S.erase()
+ if(check(E)) E.erase()
+ if(check(W)) W.erase()
+ #ifdef MULTIZAS
+ if(check(U)) U.erase()
+ if(check(D)) D.erase()
+ #endif
+
+#undef check
diff --git a/code/modules/atmospherics/ZAS/Debug.dm b/code/modules/atmospherics/ZAS/Debug.dm
new file mode 100644
index 00000000000..22d92de2125
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Debug.dm
@@ -0,0 +1,94 @@
+#ifdef ZASDBG
+
+GLOBAL_REAL_VAR(obj/effect/zasdbg/assigned/zasdbgovl_assigned) = new
+GLOBAL_REAL_VAR(obj/effect/zasdbg/created/zasdbgovl_created) = new
+GLOBAL_REAL_VAR(obj/effect/zasdbg/merged/zasdbgovl_merged) = new
+GLOBAL_REAL_VAR(obj/effect/zasdbg/invalid_zone/zasdbgovl_invalid_zone) = new
+GLOBAL_REAL_VAR(obj/effect/zasdbg/blocked/zasdbgovl_blocked) = new
+GLOBAL_REAL_VAR(obj/effect/zasdbg/mark/zasdbgovl_mark) = new
+
+GLOBAL_REAL_VAR(list/zasdbgovl_dirblock) = list(
+ "north" = new /obj/effect/zasdbg/air_blocked/north,
+ "east" = new /obj/effect/zasdbg/air_blocked/east,
+ "south" = new /obj/effect/zasdbg/air_blocked/south,
+ "west" = new /obj/effect/zasdbg/air_blocked/west,
+)
+///Retrives the directional block indicator overlay for a given direction
+#define ZAS_DIRECTIONAL_BLOCKER(d) (zasdbgovl_dirblock[dir2text(d)])
+
+GLOBAL_REAL_VAR(list/zasdbgovl_dirzoneblock) = list(
+ "north" = new /obj/effect/zasdbg/zone_blocked/north,
+ "east" = new /obj/effect/zasdbg/zone_blocked/east,
+ "south" = new /obj/effect/zasdbg/zone_blocked/south,
+ "west" = new /obj/effect/zasdbg/zone_blocked/west,
+)
+///Retrieves the zone blocked debug overlay for a given direction
+#define ZAS_ZONE_BLOCKER(d) (zasdbgovl_dirzoneblock[dir2text(d)])
+
+/obj/effect/zasdbg
+ icon = 'modular_pariah/master_files/icons/testing/Zone.dmi'
+ invisibility = INVISIBILITY_OBSERVER
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ plane = ABOVE_GAME_PLANE
+ layer = FLY_LAYER
+ vis_flags = NONE
+
+/obj/effect/zasdbg/assigned
+ icon_state = "assigned"
+/obj/effect/zasdbg/created
+ icon_state = "created"
+/obj/effect/zasdbg/merged
+ icon_state = "merged"
+/obj/effect/zasdbg/invalid_zone
+ icon_state = "invalid"
+/obj/effect/zasdbg/blocked
+ icon_state = "fullblock"
+/obj/effect/zasdbg/mark
+ icon_state = "mark"
+
+/obj/effect/zasdbg/zone_blocked
+ icon_state = "zoneblock"
+
+/obj/effect/zasdbg/zone_blocked/north
+ dir = NORTH
+/obj/effect/zasdbg/zone_blocked/east
+ dir = EAST
+/obj/effect/zasdbg/zone_blocked/south
+ dir = SOUTH
+/obj/effect/zasdbg/zone_blocked/west
+ dir = WEST
+
+/obj/effect/zasdbg/air_blocked
+ icon_state = "block"
+
+/obj/effect/zasdbg/air_blocked/north
+ dir = NORTH
+/obj/effect/zasdbg/air_blocked/east
+ dir = EAST
+/obj/effect/zasdbg/air_blocked/south
+ dir = SOUTH
+/obj/effect/zasdbg/air_blocked/west
+ dir = WEST
+
+
+/turf/var/tmp/obj/effect/zasdbg/dbg_img
+/turf/proc/dbg(obj/effect/zasdbg/img)
+ vis_contents -= dbg_img
+ vis_contents += img
+ dbg_img = img
+
+/proc/soft_assert(thing,fail)
+ if(!thing) message_admins(fail)
+
+/datum/proc/zas_log(string)
+ return
+
+/turf/zas_log(string)
+ to_chat(world, "[span_admin("ZAS:")] ([src.x], [src.y], [src.z]): [string]")
+
+/connection/zas_log(string)
+ to_chat(world, "[span_admin("ZAS:")] connection output: [string]")
+
+/connection_edge/zas_log(string)
+ to_chat(world, "[span_admin("ZAS:")] connection edge output: [string]")
+#endif
diff --git a/code/modules/atmospherics/ZAS/Diagnostic.dm b/code/modules/atmospherics/ZAS/Diagnostic.dm
new file mode 100644
index 00000000000..ca0d4543ebe
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Diagnostic.dm
@@ -0,0 +1,93 @@
+/client/proc/Zone_Info(turf/T as null|turf)
+ set category = "Debug"
+ if(T)
+ if(T.simulated && T.zone)
+ T.zone.dbg_data(src)
+ else
+ to_chat(mob, span_admin("ZASDBG: No zone here."))
+ var/datum/gas_mixture/mix = T.return_air()
+ to_chat(mob,span_admin( "ZASDBG_MAIN: [mix.returnPressure()] kPa [mix.temperature] k"))
+ for(var/g in mix.gas)
+ to_chat(mob, span_admin("ZASDBG_GAS: [g]: [mix.gas[g]]\n"))
+
+ if((T.zone && (length(T.zone.contents) > ZONE_MIN_SIZE)))
+ to_chat(mob, span_notice("This turf's zone is below the minimum size, and will merge over zone blockers."))
+ else
+ if(zone_debug_images)
+ for(var/zone in zone_debug_images)
+ images -= zone_debug_images[zone]
+ zone_debug_images = null
+
+/client/var/list/zone_debug_images
+
+/client/proc/Test_ZAS_Connection(turf/T as turf)
+ set category = "Debug"
+ if(!T.simulated)
+ return
+
+ var/direction_list = list(\
+ "North" = NORTH,\
+ "South" = SOUTH,\
+ "East" = EAST,\
+ "West" = WEST,\
+ #ifdef MULTIZAS
+ "Up" = UP,\
+ "Down" = DOWN,\
+ #endif
+ "N/A" = null)
+ var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list
+ if(!direction)
+ return
+
+ if(direction == "N/A")
+ to_chat(mob, "Testing self-blocking...")
+ var/canpass_self
+ ATMOS_CANPASS_TURF(canpass_self, T, T)
+ if(!(canpass_self & AIR_BLOCKED))
+ to_chat(mob, "The turf can pass air! :D")
+ else
+ to_chat(mob, "No air passage :x")
+ return
+
+ var/turf/other_turf = get_step(T, direction_list[direction])
+ if(!other_turf.simulated)
+ return
+
+ var/t_block
+ ATMOS_CANPASS_TURF(t_block, T, other_turf)
+ var/o_block
+ ATMOS_CANPASS_TURF(o_block, other_turf, T)
+
+ to_chat(mob, "Testing connection between ([T.x], [T.y], [T.z]) and ([other_turf.x], [other_turf.y], [other_turf.z])...")
+ if(o_block & AIR_BLOCKED)
+ if(t_block & AIR_BLOCKED)
+ to_chat(mob, "Neither turf can connect. :(")
+
+ else
+ to_chat(mob, "The initial turf only can connect. :\\")
+ else
+ if(t_block & AIR_BLOCKED)
+ to_chat(mob, "The other turf can connect, but not the initial turf. :/")
+
+ else
+ to_chat(mob, "Both turfs can connect! :)")
+
+ to_chat(mob, "Additionally, \...")
+
+ if(o_block & ZONE_BLOCKED)
+ if(t_block & ZONE_BLOCKED)
+ to_chat(mob, "neither turf can merge.")
+ else
+ to_chat(mob, "the other turf cannot merge.")
+ else
+ if(t_block & ZONE_BLOCKED)
+ to_chat(mob, "the initial turf cannot merge.")
+ else
+ to_chat(mob, "both turfs can merge.")
+
+/*
+/client/proc/ZASSettings()
+ set category = "Debug"
+
+ zas_settings.SetDefault(mob)
+*/
diff --git a/code/modules/atmospherics/ZAS/Fire.dm b/code/modules/atmospherics/ZAS/Fire.dm
new file mode 100644
index 00000000000..a5f8538a7fd
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Fire.dm
@@ -0,0 +1,497 @@
+/*
+
+Making Bombs with ZAS:
+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
+
+/turf/var/obj/effect/hotspot/fire = null
+
+//Some legacy definitions so fires can be started.
+/atom/movable/proc/is_burnable()
+ return FALSE
+
+/mob/is_burnable()
+ return simulated
+
+/turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
+
+
+/turf/hotspot_expose(exposed_temperature, exposed_volume, soh)
+ if(!simulated)
+ return 0
+ if(fire_protection > world.time-300)
+ return 0
+ if(locate(/obj/effect/hotspot) in src)
+ return 1
+ var/datum/gas_mixture/air_contents = return_air()
+ if(!air_contents || exposed_temperature < PHORON_MINIMUM_BURN_TEMPERATURE)
+ return 0
+
+ var/igniting = 0
+ var/obj/effect/decal/cleanable/oil/liquid = locate() in src
+
+ if(air_contents.check_combustability(liquid))
+ igniting = 1
+
+ create_fire(exposed_temperature)
+ return igniting
+
+/zone/proc/process_fire()
+ var/datum/gas_mixture/burn_gas = air.removeRatio(zas_settings.fire_consumption_rate, fire_tiles.len)
+
+ var/firelevel = burn_gas.react(src, fire_tiles, force_burn = 1, no_check = 1)
+
+ air.merge(burn_gas)
+
+ if(firelevel)
+ for(var/turf/T in fire_tiles)
+ if(T.fire)
+ T.fire.firelevel = firelevel
+ else
+ var/obj/effect/decal/cleanable/oil/fuel = locate() in T
+ fire_tiles -= T
+ fuel_objs -= fuel
+ else
+ for(var/turf/T in fire_tiles)
+ if(istype(T.fire))
+ qdel(T.fire)
+ fire_tiles.Cut()
+ //Gotta make sure we don't leave any left over signals
+ for(var/fuel in fuel_objs)
+ UnregisterSignal(fuel, COMSIG_PARENT_QDELETING)
+ fuel_objs.Cut()
+
+ if(!fire_tiles.len)
+ SSzas.active_fire_zones.Remove(src)
+
+/zone/proc/remove_liquidfuel(used_liquid_fuel, remove_fire=0)
+ if(!fuel_objs.len)
+ return
+
+ //As a simplification, we remove fuel equally from all fuel sources. It might be that some fuel sources have more fuel,
+ //some have less, but whatever. It will mean that sometimes we will remove a tiny bit less fuel then we intended to.
+
+ var/fuel_to_remove = used_liquid_fuel/(fuel_objs.len*LIQUIDFUEL_AMOUNT_TO_MOL) //convert back to liquid volume units
+
+ for(var/O in fuel_objs)
+ var/obj/effect/decal/cleanable/oil/fuel = O
+ if(!istype(fuel))
+ fuel_objs -= fuel
+ continue
+
+ fuel.reagent_amount -= fuel_to_remove
+ if(fuel.reagent_amount <= 0)
+ fuel_objs -= fuel
+ if(remove_fire)
+ var/turf/T = fuel.loc
+ if(istype(T) && T.fire)
+ qdel(T.fire)
+ qdel(fuel)
+
+///Creates a fire with firelevel (fl). If create_own_fuel is given, it will create that many units of welding fuel on the turf.
+/turf/proc/create_fire(fl, create_own_fuel)
+ return 0
+
+/turf/open/create_fire(fl, create_own_fuel)
+ if(!simulated)
+ return
+ if(fire)
+ fire.firelevel = max(fl, fire.firelevel)
+ return
+
+ if(!zone)
+ return
+
+ fire = new(src, fl)
+ SSzas.active_fire_zones |= zone
+
+ var/obj/effect/decal/cleanable/oil/fuel = locate() in src
+ if(create_own_fuel)
+ if(!fuel)
+ fuel = new /obj/effect/decal/cleanable/oil(src)
+ fuel.reagent_amount = create_own_fuel
+ else
+ fuel.reagent_amount += create_own_fuel
+
+ zone.fire_tiles |= src
+ if(fuel)
+ zone.fuel_objs += fuel
+
+ return src
+
+/turf/open/space/create_fire()
+ return
+
+/obj/effect/hotspot
+ anchored = TRUE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ icon = 'modular_pariah/master_files/icons/effects/fire.dmi'
+ icon_state = "1"
+ layer = GASFIRE_LAYER
+ plane = ABOVE_GAME_PLANE
+ blend_mode = BLEND_ADD
+ light_system = MOVABLE_LIGHT
+ light_range = LIGHT_RANGE_FIRE
+ light_power = 1
+ light_color = LIGHT_COLOR_FIRE
+
+ var/firelevel = 1 //Calculated by gas_mixture.calculate_firelevel()
+
+/obj/effect/hotspot/process()
+ . = 1
+ if(QDELETED(src))
+ return PROCESS_KILL
+
+ var/turf/my_tile = loc
+ if(istype(my_tile, /turf/open/space) || !my_tile.zone)
+ if(my_tile && my_tile.fire == src)
+ my_tile.fire = null
+ qdel(src)
+ return PROCESS_KILL
+
+ var/datum/gas_mixture/air_contents = my_tile.return_air()
+
+ if(firelevel > 6)
+ icon_state = "3"
+ set_light_power(2)
+ set_light_range(7)
+ else if(firelevel > 2.5)
+ icon_state = "2"
+ set_light_power(1.5)
+ set_light_range(5)
+ else
+ icon_state = "1"
+ set_light_power(1)
+ set_light_range(3)
+
+ for(var/mob/living/L in loc)
+ L.FireBurn(firelevel, air_contents.temperature, air_contents.returnPressure()) //Burn the mobs!
+
+ loc.fire_act(air_contents.temperature, air_contents.volume)
+ for(var/atom/A as anything in loc)
+ A.fire_act(air_contents.temperature, air_contents.volume)
+
+ //spread
+ for(var/direction in GLOB.cardinals)
+ var/turf/enemy_tile = get_step(my_tile, direction)
+ if(!istype(enemy_tile, /turf/open/space))
+ if(my_tile.open_directions & direction) //Grab all valid bordering tiles
+ if(!enemy_tile.zone || enemy_tile.fire)
+ continue
+
+ //if(!enemy_tile.zone.fire_tiles.len) TODO - optimize
+ var/datum/gas_mixture/acs = enemy_tile.return_air()
+ var/obj/effect/decal/cleanable/oil/liquid = locate() in enemy_tile
+ if(!acs || !acs.check_combustability(liquid))
+ continue
+
+ //If extinguisher mist passed over the turf it's trying to spread to, don't spread and
+ //reduce firelevel.
+ if(enemy_tile.fire_protection > world.time-30)
+ firelevel -= 1.5
+ continue
+
+ //Spread the fire.
+ //Atmos Canpass probably needs to be checked here
+ if(prob(50 + 50 * (firelevel/zas_settings.fire_firelevel_multiplier)))
+ enemy_tile.create_fire(firelevel)
+
+ else
+ enemy_tile.adjacent_fire_act(loc, air_contents, air_contents.temperature, air_contents.volume)
+
+ animate(src, color = fire_color(air_contents.temperature), 5)
+ set_light_color(color)
+
+/obj/effect/hotspot/New(newLoc,fl)
+ ..()
+
+ if(!istype(loc, /turf))
+ qdel(src)
+ return
+
+ setDir(pick(GLOB.cardinals))
+
+ var/datum/gas_mixture/air_contents = loc.return_air()
+ color = fire_color(air_contents.temperature)
+ set_light_range(3)
+ set_light_power(1)
+ set_light_color(color)
+ firelevel = fl
+ SSzas.active_hotspots.Add(src)
+
+/obj/effect/hotspot/proc/fire_color(env_temperature)
+ var/temperature = max(4000*sqrt(firelevel/zas_settings.fire_firelevel_multiplier), env_temperature)
+ return heat2color(temperature)
+
+/obj/effect/hotspot/Destroy()
+ var/turf/T = loc
+ if (istype(T))
+ set_light(0)
+ T.fire = null
+ SSzas.active_hotspots.Remove(src)
+ . = ..()
+
+/turf/var/fire_protection = 0
+/turf/proc/apply_fire_protection()
+ fire_protection = world.time
+
+/turf/open/space/apply_fire_protection()
+ return
+
+//Returns the firelevel
+/datum/gas_mixture/proc/react(zone/zone, force_burn, no_check = 0)
+ . = 0
+ if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && (no_check ||check_recombustability(zone? zone.fuel_objs : null)))
+
+ #ifdef FIREDBG
+ log_admin("***************** FIREDBG *****************")
+ log_admin("Burning [zone? zone.name : "zoneless gas_mixture"]!")
+ #endif
+
+ var/gas_fuel = 0
+ var/liquid_fuel = 0
+ var/total_fuel = 0
+ var/total_oxidizers = 0
+
+ //*** Get the fuel and oxidizer amounts
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & XGM_GAS_FUEL)
+ gas_fuel += gas[g]
+ if(xgm_gas_data.flags[g] & XGM_GAS_OXIDIZER)
+ total_oxidizers += gas[g]
+ gas_fuel *= group_multiplier
+ total_oxidizers *= group_multiplier
+
+ //Liquid Fuel
+ var/fuel_area = 0
+ if(zone)
+ for(var/obj/effect/decal/cleanable/oil/fuel in zone.fuel_objs)
+ liquid_fuel += fuel.reagent_amount*LIQUIDFUEL_AMOUNT_TO_MOL
+ fuel_area++
+
+ total_fuel = gas_fuel + liquid_fuel
+ if(total_fuel <= 0.005)
+ return 0
+
+ //*** Determine how fast the fire burns
+
+ //get the current thermal energy of the gas mix
+ //this must be taken here to prevent the addition or deletion of energy by a changing heat capacity
+ var/starting_energy = temperature * getHeatCapacity()
+
+ //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
+
+ //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) / zas_settings.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, 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_firelevel = calculate_firelevel(liquid_fuel, total_oxidizers, reaction_limit, 0) / zas_settings.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)
+ var/used_oxidizers = used_fuel*(FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT)
+
+ #ifdef FIREDBG
+ log_admin("gas_fuel = [gas_fuel], liquid_fuel = [liquid_fuel], total_oxidizers = [total_oxidizers]")
+ log_admin("fuel_area = [fuel_area], total_fuel = [total_fuel], reaction_limit = [reaction_limit]")
+ log_admin("firelevel -> [firelevel] (gas: [gas_firelevel], liquid: [liquid_firelevel])")
+ log_admin("liquid_reaction_progress = [liquid_reaction_progress]")
+ log_admin("gas_reaction_progress = [gas_reaction_progress]")
+ log_admin("total_reaction_progress = [total_reaction_progress]")
+ log_admin("used_fuel = [used_fuel], used_oxidizers = [used_oxidizers]; ")
+ #endif
+
+ //if the reaction is progressing too slow then it isn't self-sustaining anymore and burns out
+ if(zone) //be less restrictive with canister and tank reactions
+ if((!liquid_fuel || used_fuel <= FIRE_LIQUD_MIN_BURNRATE) && (!gas_fuel || used_fuel <= FIRE_GAS_MIN_BURNRATE*zone.contents.len))
+ return 0
+
+
+ //*** Remove fuel and oxidizer, add carbon dioxide and heat
+
+ //remove and add gasses as calculated
+ var/used_gas_fuel = min(max(0.25, used_fuel*(gas_reaction_progress/total_reaction_progress)), gas_fuel) //remove in proportion to the relative reaction progress
+ var/used_liquid_fuel = min(max(0.25, used_fuel-used_gas_fuel), liquid_fuel)
+
+ //removeByFlag() and adjustGas() handle the group_multiplier for us.
+ removeByFlag(XGM_GAS_OXIDIZER, used_oxidizers)
+ var/datum/gas_mixture/burned_fuel = removeByFlag(XGM_GAS_FUEL, used_gas_fuel)
+ for(var/g in burned_fuel.gas)
+ adjustGas(xgm_gas_data.burn_product[g], burned_fuel.gas[g])
+
+ if(zone)
+ zone.remove_liquidfuel(used_liquid_fuel, !check_combustability())
+
+ //calculate the energy produced by the reaction and then set the new temperature of the mix
+ temperature = (starting_energy + zas_settings.fire_fuel_energy_release * (used_gas_fuel + used_liquid_fuel)) / getHeatCapacity()
+ AIR_UPDATE_VALUES(src)
+
+ #ifdef FIREDBG
+ log_admin("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_fuel]")
+ log_admin("new temperature = [temperature]; new pressure = [returnPressure()]")
+ #endif
+
+ if (temperature<220)
+ firelevel = 0
+
+ return firelevel
+
+/datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
+ . = 0
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & XGM_GAS_OXIDIZER && gas[g] >= 0.1)
+ . = 1
+ break
+
+ if(!.)
+ return 0
+
+ if(fuel_objs && fuel_objs.len)
+ return 1
+
+ . = 0
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & XGM_GAS_FUEL && gas[g] >= 0.1)
+ . = 1
+ break
+
+/datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/oil/liquid)
+ . = 0
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & XGM_GAS_OXIDIZER && QUANTIZE(gas[g] * zas_settings.fire_consumption_rate) >= 0.1)
+ . = 1
+ break
+
+ if(!.)
+ return 0
+
+ if(liquid)
+ return 1
+
+ . = 0
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & XGM_GAS_FUEL && QUANTIZE(gas[g] * zas_settings.fire_consumption_rate) >= 0.1)
+ . = 1
+ break
+
+//returns a value between 0 and zas_settings.fire_firelevel_multiplier
+/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_moles && total_combustables > 0)
+ //slows down the burning when the concentration of the reactants is low
+ 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 the fire out a bit, reducing firelevel.
+ var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2)))
+
+ #ifdef FIREDBG
+ ASSERT(damping_multiplier <= 1)
+ ASSERT(mix_multiplier <= 1)
+ #endif
+
+ //toss everything together -- should produce a value between 0 and fire_firelevel_multiplier
+ firelevel = zas_settings.fire_firelevel_multiplier * mix_multiplier * damping_multiplier
+
+ return max( 0, firelevel)
+
+
+/mob/living/proc/FireBurn(firelevel, last_temperature, pressure)
+ var/mx = 5 * firelevel/zas_settings.fire_firelevel_multiplier * min(pressure / ONE_ATMOSPHERE, 1)
+ apply_damage(2.5*mx, BURN)
+ return mx
+
+
+/mob/living/carbon/human/FireBurn(firelevel, last_temperature, pressure)
+ //Burns mobs due to fire. Respects heat transfer coefficients on various body parts.
+ //Due to TG reworking how fireprotection works, this is kinda less meaningful.
+
+ var/head_exposure = 1
+ var/chest_exposure = 1
+ var/groin_exposure = 1
+ var/legs_exposure = 1
+ var/arms_exposure = 1
+
+ //Get heat transfer coefficients for clothing.
+
+ for(var/obj/item/clothing/C in get_equipped_items())
+ if( C.max_heat_protection_temperature >= last_temperature )
+ if(C.body_parts_covered & HEAD)
+ head_exposure = 0
+ if(C.body_parts_covered & CHEST)
+ chest_exposure = 0
+ if(C.body_parts_covered & GROIN)
+ groin_exposure = 0
+ if(C.body_parts_covered & LEGS)
+ legs_exposure = 0
+ if(C.body_parts_covered & ARMS)
+ arms_exposure = 0
+ //minimize this for low-pressure environments
+ var/mx = 5 * firelevel/zas_settings.fire_firelevel_multiplier * min(pressure / ONE_ATMOSPHERE, 1)
+
+ //Always check these damage procs first if fire damage isn't working. They're probably what's wrong.
+
+ apply_damage(0.9*mx*head_exposure, BURN, BODY_ZONE_HEAD)
+ apply_damage(2.5*mx*chest_exposure, BURN, BODY_ZONE_CHEST)
+ apply_damage(0.6*mx*legs_exposure, BURN, BODY_ZONE_L_LEG)
+ apply_damage(0.6*mx*legs_exposure, BURN, BODY_ZONE_R_LEG)
+ apply_damage(0.4*mx*arms_exposure, BURN, BODY_ZONE_L_ARM)
+ apply_damage(0.4*mx*arms_exposure, BURN, BODY_ZONE_R_ARM)
+
+ //return a truthy value of whether burning actually happened
+ return mx * (head_exposure + chest_exposure + groin_exposure + legs_exposure + arms_exposure)
+
+/turf/proc/burn()
+ burn_tile()
+ var/chance_of_deletion
+ if (heat_capacity) //beware of division by zero
+ chance_of_deletion = max_fire_temperature_sustained / heat_capacity * 8 //there is no problem with prob(23456), min() was redundant --rastaf0
+ else
+ chance_of_deletion = 100
+ if(prob(chance_of_deletion))
+ Melt()
+ max_fire_temperature_sustained = 0
+ else
+ to_be_destroyed = FALSE
+
+
+/turf/proc/adjacent_fire_act(turf/open/floor/source, datum/gas_mixture/adj_air, adj_temp, adj_volume)
+ return
+
+/turf/open/floor/adjacent_fire_act(turf/open/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume)
+ var/dir_to = get_dir(src, adj_turf)
+
+ for(var/obj/structure/window/W in src)
+ if(W.dir == dir_to || W.fulltile) //Same direction or diagonal (full tile)
+ W.fire_act(adj_temp, adj_volume)
+
+/turf/closed/wall/adjacent_fire_act(turf/open/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume)
+ if(!uses_integrity)
+ burn(adj_temp)
+ else if (adj_temp > heat_capacity)
+ take_damage(log(Frand(0.9, 1.1) * (adj_temp - heat_capacity)), BURN)
+
+ return ..()
+
+/obj/effect/dummy/lighting_obj/moblight/fire
+ name = "fire"
+ light_color = LIGHT_COLOR_FIRE
+ light_range = LIGHT_RANGE_FIRE
diff --git a/code/modules/atmospherics/ZAS/Plasma.dm b/code/modules/atmospherics/ZAS/Plasma.dm
new file mode 100644
index 00000000000..a1f1e623b1d
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Plasma.dm
@@ -0,0 +1,176 @@
+GLOBAL_DATUM_INIT(contamination_overlay, /image, image('modular_pariah/master_files/icons/effects/contamination.dmi'))
+
+/datum/pl_control
+ var/plasma_dmg = 3
+ var/plasma_dmg_name = "Plasma Damage Amount"
+ var/plasma_dmg_desc = "Self Descriptive"
+
+ var/cloth_contamination = FALSE
+ var/cloth_contamination_name = "Phoron Contamination"
+ var/cloth_contamination_desc = "If this is on, phoron can contiminate items."
+
+ var/plasmaguard_only = FALSE
+ var/plamaguard_only_name = "\"PlasmaGuard Only\""
+ var/plasmaguard_only_desc = "If this is on, only biosuits and spacesuits protect against contamination and ill effects."
+
+ var/genetic_corruption = FALSE
+ var/genetic_corruption_name = "Genetic Corruption Chance"
+ var/genetic_corruption_desc = "Chance of genetic corruption as well as toxic damage, X in 10,000."
+
+ var/skin_burns = TRUE
+ var/skin_burns_name = "Skin Burns"
+ var/skin_burns_desc = "Phoron has an effect similar to mustard gas on the un-suited."
+
+ var/eye_burns = TRUE
+ var/eye_burns_name = "Eye Burns"
+ var/eye_burns_desc = "Phoron burns the eyes of anyone not wearing eye protection."
+
+ var/contamination_loss = 0.02
+ var/contamination_loss_name = "Contamination Loss"
+ var/contamination_loss_desc = "How much toxin damage is dealt from contaminated clothing" //Per tick? ASK ARYN
+
+ var/phoron_hallucination = 0
+ var/phoron_hallucination_name = "Phoron Hallucination"
+ var/phoron_hallucination_desc = "Does being in phoron cause you to hallucinate?"
+
+
+/atom/proc/can_contaminate()
+ return
+
+/atom/proc/contaminate()
+ return
+
+/atom/proc/decontaminate()
+ return
+
+/obj/item/can_contaminate()
+ //Clothing can be contaminated, with exceptions for certain items which cannot be washed in washing_machine.dm
+ if(obj_flags & PLASMAGUARD)
+ return FALSE
+ return TRUE
+
+/obj/item/contaminate()
+ //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was.
+ if(!(flags_2 & CONTAMINATED_2))
+ flags_2 |= CONTAMINATED_2
+ add_overlay(GLOB.contamination_overlay)
+
+/obj/item/decontaminate()
+ flags_2 &= ~CONTAMINATED_2
+ cut_overlay(GLOB.contamination_overlay)
+
+
+/mob/living/carbon/human/contaminate()
+ //See if anything can be contaminated.
+
+ if(!pl_suit_protected())
+ suit_contamination()
+
+ if(!pl_head_protected())
+ if(prob(1))
+ suit_contamination() //Phoron can sometimes get through such an open suit.
+
+//Cannot wash backpacks currently.
+// if(istype(back,/obj/item/storage/backpack))
+// back.contaminate()
+
+/atom/proc/expose_plasma()
+ return
+
+/mob/living/carbon/human/expose_plasma()
+ //Handles all the bad things phoron can do.
+
+ //Contamination
+ if(zas_settings.plc.cloth_contamination)
+ contaminate()
+
+ //Anything else requires them to not be dead.
+ if(stat >= 2)
+ return
+
+ //Burn skin if exposed.
+ if(zas_settings.plc.skin_burns)
+ if(!pl_head_protected() || !pl_suit_protected())
+ //burn_skin(0.75)
+ if(prob(20))
+ to_chat(src, "Your skin burns!")
+ updatehealth()
+
+ //Burn eyes if exposed.
+ if(zas_settings.plc.eye_burns)
+ if(!is_eyes_covered())
+ burn_eyes()
+
+ //Genetic Corruption
+ if(zas_settings.plc.genetic_corruption)
+ if(rand(1,10000) < zas_settings.plc.genetic_corruption)
+ easy_random_mutate(NEGATIVE)
+ to_chat(src, "High levels of toxins cause you to spontaneously mutate!")
+ domutcheck(src, null)
+
+/mob/proc/burn_eyes()
+ return
+
+/mob/living/carbon/human/burn_eyes()
+ var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES)
+ if(E && !E.status == ORGAN_ROBOTIC)
+ if(prob(20))
+ to_chat(src, "Your eyes burn!")
+ E.applyOrganDamage(2.5)
+ eye_blurry = min(eye_blurry+1.5,50)
+ if (prob(max(0, E.damage - 15) + 1) &&!eye_blind)
+ to_chat(src, "You are blinded!")
+ eye_blind += 20
+
+/mob/living/carbon/human/proc/pl_head_protected()
+ //Checks if the head is adequately sealed.
+ if(head)
+ if(zas_settings.plc.plasmaguard_only)
+ if(head.obj_flags & PLASMAGUARD)
+ return TRUE
+ else if(is_eyes_covered())
+ return TRUE
+ return FALSE
+
+/mob/living/carbon/human/proc/pl_suit_protected()
+ //Checks if the suit is adequately sealed.
+ var/coverage = NONE
+ for(var/obj/item/protection in list(wear_suit, gloves, shoes))
+ if(!protection)
+ continue
+ if(istype(protection, /obj/item/clothing))
+ var/obj/item/clothing/clothing_item = protection
+ if(zas_settings.plc.plasmaguard_only && !((clothing_item.clothing_flags & THICKMATERIAL) || (clothing_item.clothing_flags & GAS_FILTERING) || (clothing_item.obj_flags & PLASMAGUARD)))
+ return FALSE
+
+ else if(zas_settings.plc.plasmaguard_only && !(protection.obj_flags & PLASMAGUARD))
+ return FALSE
+
+ coverage |= protection.body_parts_covered
+
+ if(zas_settings.plc.plasmaguard_only)
+ return TRUE
+
+ return (~(coverage) & (CHEST|LEGS|FEET|ARMS|HANDS) == 0)
+
+/mob/living/carbon/human/proc/suit_contamination()
+ //Runs over the things that can be contaminated and does so.
+ if (w_uniform && w_uniform.can_contaminate())
+ w_uniform.contaminate()
+ if (shoes && shoes.can_contaminate())
+ shoes.contaminate()
+ if (gloves && gloves.can_contaminate())
+ gloves.contaminate()
+
+
+/turf/Entered(obj/item/I)
+ . = ..()
+ //Items that are in plasma, but not on a mob, can still be contaminated.
+ if(istype(I) && SSzas && zas_settings?.plc.cloth_contamination && I.can_contaminate())
+ var/datum/gas_mixture/env = return_air()
+ if(!env)
+ return
+ for(var/g in env.gas)
+ if(xgm_gas_data.flags[g] & XGM_GAS_CONTAMINANT && env.gas[g] > xgm_gas_data.overlay_limit[g] + 1)
+ I.contaminate()
+ break
diff --git a/code/modules/atmospherics/ZAS/Temperature.dm b/code/modules/atmospherics/ZAS/Temperature.dm
new file mode 100644
index 00000000000..b864c9b3499
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Temperature.dm
@@ -0,0 +1,73 @@
+#define MIN_TEMPERATURE_COEFFICIENT 1
+#define MAX_TEMPERATURE_COEFFICIENT 10
+
+/atom/var/temperature = T20C
+/atom/var/temperature_coefficient = MAX_TEMPERATURE_COEFFICIENT
+
+/atom/movable/Entered(atom/movable/atom, atom/old_loc, list/atom/old_locs)
+ . = ..()
+ QUEUE_TEMPERATURE_ATOMS(atom)
+
+/obj/temperature_coefficient = null
+
+/mob/temperature_coefficient = null
+
+/turf/temperature_coefficient = MIN_TEMPERATURE_COEFFICIENT
+
+/obj/Initialize()
+ . = ..()
+ temperature_coefficient = isnull(temperature_coefficient) ? clamp(MAX_TEMPERATURE_COEFFICIENT - w_class, MIN_TEMPERATURE_COEFFICIENT, MAX_TEMPERATURE_COEFFICIENT) : temperature_coefficient
+
+/atom/proc/adjust_temperature(adjust_temp, atom/heat_source)
+ if(ATOM_IS_TEMPERATURE_SENSITIVE(src))
+ var/diff_temp = (adjust_temp - temperature)
+ if(diff_temp >= 0)
+ var/altered_temp = max(temperature + (ATOM_TEMPERATURE_EQUILIBRIUM_CONSTANT * temperature_coefficient * diff_temp), 0)
+ ADJUST_ATOM_TEMPERATURE(src, min(adjust_temp, altered_temp))
+
+/mob/living/Initialize()
+ . = ..()
+ temperature_coefficient = isnull(temperature_coefficient) ? clamp(MAX_TEMPERATURE_COEFFICIENT - FLOOR(mob_size/4, 1), MIN_TEMPERATURE_COEFFICIENT, MAX_TEMPERATURE_COEFFICIENT) : temperature_coefficient
+
+/atom/proc/process_atmos_exposure(delta_time)
+ // Get our location temperature if possible.
+ // Nullspace is room temperature, clearly.
+ var/adjust_temp
+ var/datum/gas_mixture/local_air
+ if(loc)
+ if(!isturf(loc))
+ adjust_temp = loc.temperature
+ else
+ var/turf/T = get_turf(loc)
+ if(T.zone && T.zone.air)
+ adjust_temp = T.zone.air.temperature
+ SEND_SIGNAL(T, COMSIG_TURF_EXPOSE, T.zone.air, T.zone.air.temperature)
+ atmos_expose(T.zone.air, T.zone.air.temperature)
+ local_air = T.zone.air
+ else
+ adjust_temp = T.temperature
+ else
+ adjust_temp = T20C
+
+ var/diff_temp = adjust_temp - temperature
+ if(abs(diff_temp) >= ATOM_TEMPERATURE_EQUILIBRIUM_THRESHOLD)
+ var/altered_temp = max(temperature + (ATOM_TEMPERATURE_EQUILIBRIUM_CONSTANT * temperature_coefficient * diff_temp), 0)
+ ADJUST_ATOM_TEMPERATURE(src, (diff_temp > 0) ? min(adjust_temp, altered_temp) : max(adjust_temp, altered_temp))
+
+ else if(local_air && (should_atmos_process(local_air, local_air.temperature)))
+ return
+
+ else
+ temperature = adjust_temp
+ return PROCESS_KILL
+
+#undef MIN_TEMPERATURE_COEFFICIENT
+#undef MAX_TEMPERATURE_COEFFICIENT
+
+///This is your process() proc
+/atom/proc/atmos_expose(datum/gas_mixture/air, exposed_temperature)
+ return
+
+///Return TRUE if the atom should keep processing regardless of normal conditions.
+/atom/proc/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
+ return
diff --git a/code/modules/atmospherics/ZAS/Turf.dm b/code/modules/atmospherics/ZAS/Turf.dm
new file mode 100644
index 00000000000..940fd90669a
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Turf.dm
@@ -0,0 +1,380 @@
+/turf
+ ///The turf's current zone parent.
+ var/zone/zone
+ ///All directions in which a turf that can contain air is present.
+ var/open_directions
+ ///Can atmos pass down through this turf?
+ var/z_flags = NONE
+
+/turf
+ ///Does this turf need to be ran through SSzas? (SSzas.mark_for_update(turf) OR turf.update_nearby_tiles())
+ var/needs_air_update = 0
+ ///The local gas mixture of this turf. Use return_air(). This will always exist even if not in use, because GCing air contents would be too expensive.
+ var/datum/gas_mixture/air
+ var/heat_capacity = INFINITY
+ var/thermal_conductivity = 0.05
+ ///A gas_mixture gas list to be used as the initial value. Ex: list(GAS_OXYGEN = 50)
+ var/list/initial_gas
+#ifdef ZASDBG
+ ///Set to TRUE during debugging to get chat output on the atmos status of this turf
+ var/tmp/verbose = FALSE
+#endif
+
+///Adds the graphic_add list to vis_contents, removes graphic_remove.
+/turf/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
+ if(graphic_add && graphic_add.len)
+ vis_contents += graphic_add
+ if(graphic_remove && graphic_remove.len)
+ vis_contents -= graphic_remove
+
+///Updates the turf's air source properties, breaking or creating zone connections as necessary.
+/turf/proc/update_air_properties()
+ var/self_block
+ ATMOS_CANPASS_TURF(self_block, src, src)
+ if(self_block & AIR_BLOCKED)
+ #ifdef ZASDBG
+ src.dbg(zasdbgovl_blocked)
+ #endif
+ return TRUE
+
+ ///EXPERIMENTAL
+ open_directions = NONE
+
+ #ifdef MULTIZAS
+ for(var/d = 1, d < 64, d *= 2)
+ #else
+ for(var/d = 1, d < 16, d *= 2)
+ #endif
+
+ var/turf/target = get_step(src, d)
+
+ if(!target)
+ continue
+ var/us_blocks_target
+ ATMOS_CANPASS_TURF(us_blocks_target, src, target)
+
+ if(us_blocks_target & AIR_BLOCKED)
+ continue
+
+ var/target_blocks_us
+ ATMOS_CANPASS_TURF(target_blocks_us, target, src)
+ if(target_blocks_us & AIR_BLOCKED)
+ #ifdef ZASDBG
+ //target.dbg(ZAS_DIRECTIONAL_BLOCKER(turn(d, 180)))
+ #endif
+ continue
+
+ open_directions |= d
+
+ if(target.simulated)
+ if(TURF_HAS_VALID_ZONE(target))
+ SSzas.connect(target, src)
+
+// Helper for can_safely_remove_from_zone().
+#define GET_ZONE_NEIGHBOURS(T, ret) \
+ ret = 0; \
+ if (T.zone) { \
+ for (var/_gzn_dir in gzn_check) { \
+ var/turf/other = get_step(T, _gzn_dir); \
+ if (other && other.simulated && other.zone == T.zone) { \
+ var/block; \
+ ATMOS_CANPASS_TURF(block, other, T); \
+ if (!(block & AIR_BLOCKED)) { \
+ ret |= _gzn_dir; \
+ } \
+ } \
+ } \
+ }
+
+/*
+ Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
+ Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
+ This implementation may produce false negatives but it (hopefully) will not produce any false postiives.
+*/
+///Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
+/turf/proc/can_safely_remove_from_zone()
+ if(!zone)
+ return 1
+
+ var/check_dirs
+ GET_ZONE_NEIGHBOURS(src, check_dirs)
+ . = check_dirs
+ for(var/dir in csrfz_check)
+ //for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
+ if((dir & check_dirs) == dir)
+ //check that they are connected by the corner turf
+ var/turf/T = get_step(src, dir)
+ if (!T?.simulated)
+ . &= ~dir
+ continue
+
+ var/connected_dirs
+ GET_ZONE_NEIGHBOURS(T, connected_dirs)
+ if(connected_dirs && (dir & GLOB.reverse_dir[connected_dirs]) == dir)
+ . &= ~dir //they are, so unflag the cardinals in question
+
+ //it is safe to remove src from the zone if all cardinals are connected by corner turfs
+ . = !.
+
+/turf/open/update_air_properties()
+ if(!simulated)
+ return ..()
+
+ if(zone && zone.invalid) //this turf's zone is in the process of being rebuilt
+ copy_zone_air() //not very efficient :(
+ zone = null //Easier than iterating through the list at the zone.
+
+ var/self_block
+ ATMOS_CANPASS_TURF(self_block, src, src)
+ if(self_block & AIR_BLOCKED)
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Self-blocked.")
+ src.dbg(zasdbgovl_blocked)
+ #endif
+ if(zone)
+ var/zone/z = zone
+
+ if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
+ copy_zone_air() //we aren't rebuilding, but hold onto the old air so it can be readded
+ z.remove_turf(src)
+ else
+ z.rebuild()
+
+ return 1
+
+ var/previously_open = open_directions
+ open_directions = 0
+
+ var/list/postponed
+
+ #ifdef MULTIZAS
+ for(var/d = 1, d < 64, d *= 2)
+ #else
+ for(var/d = 1, d < 16, d *= 2)
+ #endif
+ var/turf/target = get_step(src, d)
+
+ if(!target) //edge of map
+ continue
+
+ ///The air mobility of target >> src
+ var/target_to_us
+ ATMOS_CANPASS_TURF(target_to_us, src, target)
+ if(target_to_us & AIR_BLOCKED)
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("[dir2text(d)] is blocked.")
+ //src.dbg(ZAS_DIRECTIONAL_BLOCKER(d))
+ #endif
+
+ continue
+
+ ///The air mobility of src >> target
+ var/us_to_target
+ ATMOS_CANPASS_TURF(us_to_target, target, src)
+ if(us_to_target & AIR_BLOCKED)
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("[dir2text(d)] is blocked.")
+ //target.dbg(ZAS_DIRECTIONAL_BLOCKER(turn(d, 180)))
+ #endif
+
+ //Check that our zone hasn't been cut off recently.
+ //This happens when windows move or are constructed. We need to rebuild.
+ if((previously_open & d) && target.simulated)
+ var/turf/sim_target = target
+ if(zone && sim_target.zone == zone)
+ zone.rebuild()
+ return
+ continue
+
+ open_directions |= d
+
+ if(target.simulated)
+ var/turf/sim_target = target
+ sim_target.open_directions |= GLOB.reverse_dir[d]
+
+ if(TURF_HAS_VALID_ZONE(sim_target))
+ //Might have assigned a zone, since this happens for each direction.
+ if(!zone)
+ //We do not merge if
+ // they are blocking us and we are not blocking them, or if
+ // we are blocking them and not blocking ourselves - this prevents tiny zones from forming on doorways.
+ if(((target_to_us & ZONE_BLOCKED) && !(us_to_target & ZONE_BLOCKED)) || ((us_to_target & ZONE_BLOCKED) && !(self_block & ZONE_BLOCKED)))
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("[dir2text(d)] is zone blocked.")
+ //dbg(ZAS_ZONE_BLOCKER(d))
+ #endif
+
+ //Postpone this tile rather than exit, since a connection can still be made.
+ LAZYADD(postponed, sim_target)
+
+ else
+ sim_target.zone.add_turf(src)
+
+ #ifdef ZASDBG
+ dbg(zasdbgovl_assigned)
+ if(verbose)
+ zas_log("Added to [zone]")
+ #endif
+
+ else if(sim_target.zone != zone)
+ #ifdef ZASDBG
+ if(verbose)
+ zas_log("Connecting to [sim_target.zone]")
+ #endif
+
+ SSzas.connect(src, sim_target)
+
+ #ifdef ZASDBG
+ else if(verbose)
+ zas_log("[dir2text(d)] has same zone.")
+
+ else if(verbose)
+ zas_log("[dir2text(d)] has an invalid or rebuilding zone.")
+ #endif
+ else
+ //Postponing connections to tiles until a zone is assured.
+ LAZYADD(postponed, target)
+
+ if(!TURF_HAS_VALID_ZONE(src)) //Still no zone, make a new one.
+ var/zone/newzone = new
+ newzone.add_turf(src)
+
+ #ifdef ZASDBG
+ dbg(zasdbgovl_created)
+ if(verbose)
+ zas_log("New zone created for src.")
+
+ ASSERT(zone)
+ #endif
+
+ //At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
+
+ //Loop through all previous connection attempts and try again
+ for(var/turf/T as anything in postponed)
+ if(T.zone == src.zone) //Don't try to connect to yourself
+ continue
+ SSzas.connect(src, T)
+
+
+/turf/proc/post_update_air_properties()
+ if(connections)
+ connections.update_all()
+
+///Currently unused.
+/atom/movable/proc/block_superconductivity()
+ return
+
+///Wrapper for [/datum/gas_mixture/proc/remove()]
+/turf/remove_air(amount as num)
+ var/datum/gas_mixture/GM = return_air()
+ return GM.remove(amount)
+
+///Merges a given gas mixture with the turf's current air source.
+/turf/assume_air(datum/gas_mixture/giver)
+ if(!simulated)
+ return
+ var/datum/gas_mixture/my_air = return_air()
+ my_air.merge(giver)
+
+///Basically adjustGasWithTemp() but a turf proc.
+/turf/proc/assume_gas(gasid, moles, temp = null)
+ if(!simulated)
+ return
+
+ var/datum/gas_mixture/my_air = return_air()
+
+ if(isnull(temp))
+ my_air.adjustGas(gasid, moles)
+ else
+ my_air.adjustGasWithTemp(gasid, moles, temp)
+
+ return 1
+
+///Return the currently used gas_mixture datum.
+/turf/return_air()
+ RETURN_TYPE(/datum/gas_mixture)
+ if(!simulated)
+ if(air)
+ return air
+ var/datum/gas_mixture/GM = new
+
+ if(initial_gas)
+ GM.gas = initial_gas.Copy()
+ GM.temperature = temperature
+ AIR_UPDATE_VALUES(GM)
+ air = GM
+
+ if(zone)
+ if(!zone.invalid)
+ SSzas.mark_zone_update(zone)
+ return zone.air
+ else
+ if(!air)
+ make_air()
+ copy_zone_air()
+ return air
+ else
+ if(!air)
+ make_air()
+ return air
+
+///Initializes the turf's "air" datum to it's initial values.
+/turf/proc/make_air()
+ air = new/datum/gas_mixture
+ air.temperature = temperature
+ if(initial_gas)
+ air.gas = initial_gas.Copy()
+ AIR_UPDATE_VALUES(air)
+
+///Copies this turf's group share from the zone. Usually used before removing it from the zone.
+/turf/proc/copy_zone_air()
+ if(!air)
+ air = new/datum/gas_mixture
+ air.copyFrom(zone.air)
+ air.group_multiplier = 1
+
+///Creates a gas_mixture datum with the given parameters and merges it into the turf's air source.
+/turf/proc/atmos_spawn_air(gas_id, amount, initial_temperature)
+ if(!simulated)
+ return
+ var/datum/gas_mixture/new_gas = new
+ var/datum/gas_mixture/existing_gas = return_air()
+ if(isnull(initial_temperature))
+ new_gas.adjustGas(gas_id, amount)
+ else
+ new_gas.adjustGasWithTemp(gas_id, amount, initial_temperature)
+ existing_gas.merge(new_gas)
+
+/turf/open/space/atmos_spawn_air()
+ return
+
+///Checks a turf to see if any of it's contents are dense. Is NOT recursive.
+/turf/proc/contains_dense_objects()
+ if(density)
+ return 1
+ for(var/atom/movable/A as anything in src)
+ if(A.density && !(A.flags_1 & ON_BORDER_1))
+ return 1
+ return 0
+
+///I literally don't know where this proc came from.
+/turf/proc/TryGetNonDenseNeighbour()
+ for(var/d in GLOB.cardinals)
+ var/turf/T = get_step(src, d)
+ if (T && !T.contains_dense_objects())
+ return T
+
+///Returns a list of adjacent turfs that can contain air. Returns null if none.
+/turf/proc/get_atmos_adjacent_turfs()
+ var/list/adjacent_turfs = list()
+ for(var/direct in GLOB.cardinals)
+ if(open_directions & direct)
+ adjacent_turfs += get_step(src, direct)
+ return length(adjacent_turfs) ? adjacent_turfs : null
+
+/turf/open/return_analyzable_air()
+ return return_air()
diff --git a/code/modules/atmospherics/ZAS/XGM/gas_data.dm b/code/modules/atmospherics/ZAS/XGM/gas_data.dm
new file mode 100644
index 00000000000..68b4e127a0f
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/XGM/gas_data.dm
@@ -0,0 +1,129 @@
+GLOBAL_REAL(xgm_gas_data, /datum/xgm_gas_data) = new
+/datum/xgm_gas_data
+ //Simple list of all the gas IDs.
+ var/list/gases = list()
+ //The friendly, human-readable name for the gas.
+ var/list/name = list()
+ //Specific heat of the gas. Used for calculating heat capacity.
+ var/list/specific_heat = list()
+ //Molar mass of the gas. Used for calculating specific entropy.
+ var/list/molar_mass = list()
+ //Tile overlays. /obj/effect/gas_overlay, created from references to 'icons/effects/tile_effects.dmi'
+ var/list/tile_overlay = list()
+ //Optional color for tile overlay
+ var/list/tile_overlay_color = list()
+ //Overlay limits. There must be at least this many moles for the overlay to appear.
+ var/list/overlay_limit = list()
+ //Flags.
+ var/list/flags = list()
+ //Products created when burned. For fuel only for now (not oxidizers)
+ var/list/burn_product = list()
+ // Reagent created when inhaled by lungs.
+ var/list/breathed_product = list()
+ // Temperature in K that the gas will condense.
+ var/list/condensation_points = list()
+ // Reagent path resulting from condesation.
+ var/list/condensation_products = list()
+ //If it shouldn't autogenerate a codex entry
+ var/list/hidden_from_codex = list()
+
+ //Holds the symbols
+ var/list/symbol_html = list()
+ var/list/symbol = list()
+
+ //Base sell values
+ var/list/base_value = list()
+ //Purchasable?
+ var/list/purchaseable = list()
+
+/datum/xgm_gas
+ var/id = ""
+ var/name = "Unnamed Gas"
+ var/specific_heat = 20 // J/(mol*K)
+ var/molar_mass = 0.032 // kg/mol
+
+ var/tile_overlay = "generic"
+ var/tile_color = null
+ var/overlay_limit = null
+
+ var/flags = 0
+ var/burn_product = GAS_CO2
+ var/breathed_product
+ var/condensation_point = INFINITY
+ var/condensation_product
+ var/hidden_from_codex
+ var/symbol_html = "X"
+ var/symbol = "X"
+ var/base_value = 1
+ var/purchaseable = FALSE
+
+/datum/xgm_gas_data/New()
+ for(var/p in subtypesof(/datum/xgm_gas))
+ var/datum/xgm_gas/gas = new p //avoid initial() because of potential New() actions
+
+ //if(gas.id in xgm_gas_data.gases)
+ //stack_trace("Duplicate gas id `[gas.id]` in `[p]`")
+
+ gases += gas.id
+ name[gas.id] = gas.name
+ specific_heat[gas.id] = gas.specific_heat
+ molar_mass[gas.id] = gas.molar_mass
+ if(gas.overlay_limit)
+ overlay_limit[gas.id] = gas.overlay_limit
+ tile_overlay[gas.id] = gas.tile_overlay
+ tile_overlay_color[gas.id] = gas.tile_color
+ flags[gas.id] = gas.flags
+ burn_product[gas.id] = gas.burn_product
+
+ symbol_html[gas.id] = gas.symbol_html
+ symbol[gas.id] = gas.symbol
+
+ if(!isnull(gas.condensation_product) && !isnull(gas.condensation_point))
+ condensation_points[gas.id] = gas.condensation_point
+ condensation_products[gas.id] = gas.condensation_product
+
+ breathed_product[gas.id] = gas.breathed_product
+ hidden_from_codex[gas.id] = gas.hidden_from_codex
+
+ base_value[gas.id] = gas.base_value
+ purchaseable[gas.id] = gas.purchaseable
+
+ if(flags & XGM_GAS_COMMON)
+ GLOB.common_gases += p
+
+ if(flags & XGM_GAS_NOBLE)
+ GLOB.noble_gases += p
+
+ return 1
+
+/obj/effect/gas_overlay
+ name = "gas"
+ desc = "You shouldn't be clicking this."
+ icon = 'modular_pariah/master_files/icons/effects/gas_overlays.dmi'
+ icon_state = "generic"
+ layer = GAS_LAYER
+ plane = ABOVE_GAME_PLANE
+ appearance_flags = RESET_COLOR|PIXEL_SCALE|TILE_BOUND
+ mouse_opacity = 0
+ vis_flags = NONE
+ var/gas_id
+
+/obj/effect/gas_overlay/proc/update_alpha_animation(new_alpha)
+ animate(src, alpha = new_alpha)
+ alpha = new_alpha
+ animate(src, alpha = 0.8 * new_alpha, time = 10, easing = SINE_EASING | EASE_OUT, loop = -1)
+ animate(alpha = new_alpha, time = 10, easing = SINE_EASING | EASE_IN, loop = -1)
+
+/obj/effect/gas_overlay/Initialize(mapload, gas)
+ . = ..()
+ gas_id = gas
+ if(xgm_gas_data.tile_overlay[gas_id])
+ icon_state = xgm_gas_data.tile_overlay[gas_id]
+ color = xgm_gas_data.tile_overlay_color[gas_id]
+
+/proc/typecache_of_gases_with_no_overlays()
+ . = list()
+ for (var/gastype in subtypesof(/datum/xgm_gas))
+ var/datum/xgm_gas/gasvar = gastype
+ if (!initial(gasvar.tile_overlay))
+ .[gastype] = TRUE
diff --git a/code/modules/atmospherics/ZAS/XGM/gases.dm b/code/modules/atmospherics/ZAS/XGM/gases.dm
new file mode 100644
index 00000000000..706c7b7178c
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/XGM/gases.dm
@@ -0,0 +1,287 @@
+//WHEN ADDING A NEW GAS, ADD IT TO constants.js!!
+
+/datum/xgm_gas/alium
+ id = GAS_ALIEN
+ name = "Aliether"
+ hidden_from_codex = TRUE
+ symbol_html = "X"
+ symbol = "X"
+
+/datum/xgm_gas/alium/New()
+ var/num = rand(100,999)
+ name = "Compound #[num]"
+ specific_heat = rand(1, 400) // J/(mol*K)
+ molar_mass = rand(20,800)/1000 // kg/mol
+ if(prob(40))
+ flags |= XGM_GAS_FUEL
+ else if(prob(40)) //it's prooobably a bad idea for gas being oxidizer to itself.
+ flags |= XGM_GAS_OXIDIZER
+ if(prob(40))
+ flags |= XGM_GAS_CONTAMINANT
+ if(prob(40))
+ flags |= XGM_GAS_FUSION_FUEL
+ if(!flags)
+ flags |= XGM_GAS_NOBLE
+
+ symbol_html = "X[num]"
+ symbol = "X-[num]"
+ if(prob(50))
+ tile_color = RANDOM_RGB
+ overlay_limit = 0.5
+
+//COMMON GASES
+/datum/xgm_gas/oxygen
+ id = GAS_OXYGEN
+ name = "Oxygen"
+ specific_heat = 20 // J/(mol*K)
+ molar_mass = 0.032 // kg/mol
+ flags = XGM_GAS_OXIDIZER | XGM_GAS_FUSION_FUEL | XGM_GAS_COMMON
+ symbol_html = "O2"
+ symbol = "O2"
+ purchaseable = TRUE
+ base_value = 0.2
+
+/datum/xgm_gas/nitrogen
+ id = GAS_NITROGEN
+ name = "Nitrogen"
+ specific_heat = 20 // J/(mol*K)
+ molar_mass = 0.028 // kg/mol
+ flags = XGM_GAS_COMMON
+ symbol_html = "N2"
+ symbol = "N2"
+ purchaseable = TRUE
+ base_value = 0.1
+
+/datum/xgm_gas/carbon_dioxide
+ id = GAS_CO2
+ name = "Carbon Dioxide"
+ specific_heat = 30 // J/(mol*K)
+ molar_mass = 0.044 // kg/mol
+ flags = XGM_GAS_COMMON
+ symbol_html = "CO2"
+ symbol = "CO2"
+ purchaseable = TRUE
+ base_value = 0.2
+
+/datum/xgm_gas/sleeping_agent
+ id = GAS_N2O
+ name = "Nitrous Oxide"
+ specific_heat = 40 // J/(mol*K)
+ molar_mass = 0.044 // kg/mol. N2O
+ tile_overlay = "sleeping_agent"
+ overlay_limit = 0.5
+ flags = XGM_GAS_OXIDIZER | XGM_GAS_COMMON //N2O is a powerful oxidizer
+ //breathed_product = /datum/reagent/nitrous_oxide
+ symbol_html = "N2O"
+ symbol = "N2O"
+ base_value = 3
+
+/datum/xgm_gas/vapor
+ id = GAS_STEAM
+ name = "Steam"
+ tile_overlay = "generic"
+ overlay_limit = 0.5
+ specific_heat = 30 // J/(mol*K)
+ molar_mass = 0.020 // kg/mol
+ flags = XGM_GAS_COMMON
+ breathed_product = /datum/reagent/water
+ condensation_point = 308.15 // 35C. Dew point is ~20C but this is better for gameplay considerations.
+ symbol_html = "H2O"
+ symbol = "H2O"
+
+/datum/xgm_gas/phoron
+ id = GAS_PLASMA
+ name = "Plasma"
+
+ //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.
+ //Using multiplicity rule, it's atomic number is 162
+ //and following a N/Z ratio of 1.5, the molar mass of a monatomic gas is:
+ molar_mass = 0.405 // kg/mol
+
+ tile_overlay = "plasma"
+ overlay_limit = MOLES_PHORON_VISIBLE
+ flags = XGM_GAS_FUEL | XGM_GAS_CONTAMINANT | XGM_GAS_FUSION_FUEL | XGM_GAS_COMMON
+ breathed_product = /datum/reagent/toxin/plasma
+ symbol_html = "Ph"
+ symbol = "Ph"
+ base_value = 2
+
+//SM & R-UST GASES
+/datum/xgm_gas/hydrogen
+ id = GAS_HYDROGEN
+ name = "Hydrogen"
+ specific_heat = 100 // J/(mol*K)
+ molar_mass = 0.002 // kg/mol
+ flags = XGM_GAS_FUEL|XGM_GAS_FUSION_FUEL
+ burn_product = GAS_STEAM
+ symbol_html = "H2"
+ symbol = "H2"
+
+/datum/xgm_gas/hydrogen/deuterium
+ id = GAS_DEUTERIUM
+ name = "Deuterium"
+ specific_heat = 80
+ molar_mass = 0.004
+ symbol_html = "2H"
+ symbol = "2H"
+
+/datum/xgm_gas/hydrogen/tritium
+ id = GAS_TRITIUM
+ name = "Tritium"
+ molar_mass = 0.006
+ specific_heat = 60
+ symbol_html = "3H"
+ symbol = "T"
+
+//NOBLE GASES
+/datum/xgm_gas/helium
+ id = GAS_HELIUM
+ name = "Helium"
+ specific_heat = 80 // J/(mol*K)
+ molar_mass = 0.004 // kg/mol
+ flags = XGM_GAS_FUSION_FUEL | XGM_GAS_NOBLE
+ symbol_html = "He"
+ symbol = "He"
+
+/datum/xgm_gas/argon
+ id = GAS_ARGON
+ name = "Argon"
+ specific_heat = 10 // J/(mol*K)
+ molar_mass = 0.018 // kg/mol
+ flags = XGM_GAS_NOBLE
+ symbol_html = "Ar"
+ symbol = "Ar"
+ purchaseable = TRUE
+ base_value = 0.2
+
+// If narcosis is ever simulated, krypton has a narcotic potency seven times greater than regular airmix.
+/datum/xgm_gas/krypton
+ id = GAS_KRYPTON
+ name = "Krypton"
+ specific_heat = 5 // J/(mol*K)
+ molar_mass = 0.036 // kg/mol
+ flags = XGM_GAS_NOBLE
+ symbol_html = "Kr"
+ symbol = "Kr"
+ purchaseable = TRUE
+ base_value = 0.2
+
+/datum/xgm_gas/neon
+ id = GAS_NEON
+ name = "Neon"
+ specific_heat = 20 // J/(mol*K)
+ molar_mass = 0.01 // kg/mol
+ flags = XGM_GAS_NOBLE
+ symbol_html = "Ne"
+ symbol = "Ne"
+ purchaseable = TRUE
+ base_value = 0.2
+
+/datum/xgm_gas/xenon
+ id = GAS_XENON
+ name = "Xenon"
+ specific_heat = 3 // J/(mol*K)
+ molar_mass = 0.054 // kg/mol
+ flags = XGM_GAS_NOBLE
+ breathed_product = /datum/reagent/nitrous_oxide/xenon
+ symbol_html = "Xe"
+ symbol = "Xe"
+ purchaseable = TRUE
+ base_value = 5
+
+/datum/xgm_gas/boron
+ id = GAS_BORON
+ name = "Boron"
+ specific_heat = 11
+ molar_mass = 0.011
+ flags = XGM_GAS_FUSION_FUEL | XGM_GAS_NOBLE
+ breathed_product = /datum/reagent/toxin/boron
+ symbol_html = "B"
+ symbol = "B"
+
+//MISC ELEMENTS
+/datum/xgm_gas/methane
+ id = GAS_METHANE
+ name = "Methane"
+ specific_heat = 30 // J/(mol*K)
+ molar_mass = 0.016 // kg/mol
+ flags = XGM_GAS_FUEL
+ symbol_html = "CH4"
+ symbol = "CH4"
+
+/datum/xgm_gas/ammonia
+ id = GAS_AMMONIA
+ name = "Ammonia"
+ specific_heat = 20 // J/(mol*K)
+ molar_mass = 0.017 // kg/mol
+ breathed_product = /datum/reagent/ammonia
+ symbol_html = "NH3"
+ symbol = "NH3"
+
+/datum/xgm_gas/chlorine
+ id = GAS_CHLORINE
+ name = "Chlorine"
+ tile_color = "#c5f72d"
+ overlay_limit = 0.5
+ specific_heat = 5 // J/(mol*K)
+ molar_mass = 0.017 // kg/mol
+ tile_overlay = "chlorine"
+ overlay_limit = 0.1
+ flags = XGM_GAS_OXIDIZER
+ breathed_product = /datum/reagent/chlorine
+ symbol_html = "Cl"
+ symbol = "Cl"
+ purchaseable = TRUE
+ base_value = 7
+
+//MISC COMPOUNDS
+/datum/xgm_gas/methyl_bromide
+ id = GAS_METHYL_BROMIDE
+ name = "Methyl Bromide"
+ specific_heat = 42.59 // J/(mol*K)
+ molar_mass = 0.095 // kg/mol
+ //breathed_product = /datum/reagent/toxin/methyl_bromide
+ symbol_html = "CH3Br"
+ symbol = "CH3Br"
+
+/datum/xgm_gas/nitrodioxide
+ id = GAS_NO2
+ name = "Nitrogen Dioxide"
+ tile_color = "#ca6409"
+ specific_heat = 37 // J/(mol*K)
+ molar_mass = 0.054 // kg/mol
+ flags = XGM_GAS_OXIDIZER
+ breathed_product = /datum/reagent/toxin
+ symbol_html = "NO2"
+ symbol = "NO2"
+
+/datum/xgm_gas/nitricoxide
+ id = GAS_NO
+ name = "Nitric Oxide"
+ specific_heat = 10 // J/(mol*K)
+ molar_mass = 0.030 // kg/mol
+ flags = XGM_GAS_OXIDIZER
+ symbol_html = "NO"
+ symbol = "NO"
+
+/datum/xgm_gas/sulfurdioxide
+ id = GAS_SULFUR
+ name = "Sulfur Dioxide"
+ specific_heat = 30 // J/(mol*K)
+ molar_mass = 0.044 // kg/mol
+ symbol_html = "SO2"
+ symbol = "SO2"
+
+/datum/xgm_gas/carbon_monoxide
+ id = GAS_CO
+ name = "Carbon Monoxide"
+ specific_heat = 30 // J/(mol*K)
+ molar_mass = 0.028 // kg/mol
+ breathed_product = /datum/reagent/carbon_monoxide
+ symbol_html = "CO"
+ symbol = "CO"
+
diff --git a/code/modules/atmospherics/ZAS/XGM/xgm_gas_mixture.dm b/code/modules/atmospherics/ZAS/XGM/xgm_gas_mixture.dm
new file mode 100644
index 00000000000..4ababf6b6e6
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/XGM/xgm_gas_mixture.dm
@@ -0,0 +1,554 @@
+/datum/gas_mixture
+ //Associative list of gas moles.
+ //Gases with 0 moles are not tracked and are pruned by updateValues()
+ var/list/gas = list()
+ //Temperature in Kelvin of this gas mix.
+ var/temperature = 0
+
+ //Sum of all the gas moles in this mix. Updated by updateValues()
+ var/total_moles = 0
+ //Volume of this mix.
+ var/volume = CELL_VOLUME
+ //Size of the group this gas_mixture is representing. 1 for singletons.
+ var/group_multiplier = 1
+
+ //List of active tile overlays for this gas_mixture. Updated by checkTileGraphic()
+ var/list/graphic = list()
+ //Cache of gas overlay objects
+ var/list/tile_overlay_cache
+
+/datum/gas_mixture/New(_volume = CELL_VOLUME, _temperature = 0, _group_multiplier = 1)
+ volume = _volume
+ temperature = _temperature
+ group_multiplier = _group_multiplier
+
+///Returns the volume of a specific gas within the entire zone.
+/datum/gas_mixture/proc/getGroupGas(gasid)
+ if(!gas.len)
+ return 0 //if the list is empty BYOND treats it as a non-associative list, which runtimes
+ return gas[gasid] * group_multiplier
+
+///Returns the volume of the entire zone's gas contents.
+/datum/gas_mixture/proc/getGroupMoles()
+ return total_moles * group_multiplier
+
+///Takes a gas string and the amount of moles to adjust by. Calls updateValues() if update isn't 0.
+/datum/gas_mixture/proc/adjustGas(gasid, moles, update = TRUE)
+ if(moles == 0)
+ return
+
+ if (group_multiplier != 1)
+ gas[gasid] += moles/group_multiplier
+ else
+ gas[gasid] += moles
+
+ if(update)
+ AIR_UPDATE_VALUES(src)
+
+///Sets the given gas id's mole count to the specified amount.
+/datum/gas_mixture/proc/setGasMoles(gasid, moles, update = TRUE, divide_among_group = FALSE)
+ //Generally setGasMoles actions pre-calculate, just in case.
+ if(divide_among_group && group_multiplier != 1 && moles != 0)
+ gas[gasid] = moles/group_multiplier
+ else
+ gas[gasid] = moles
+
+ if(update)
+ AIR_UPDATE_VALUES(src)
+
+///Same as adjustGas(), but takes a temperature which is mixed in with the gas.
+/datum/gas_mixture/proc/adjustGasWithTemp(gasid, moles, temp, update = 1)
+ if(moles == 0)
+ return
+
+ if(moles > 0 && abs(temperature - temp) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = getHeatCapacity()
+ var/giver_heat_capacity = xgm_gas_data.specific_heat[gasid] * moles
+ var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
+ if(combined_heat_capacity != 0)
+ temperature = (temp * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
+
+ if (group_multiplier != 1)
+ gas[gasid] += moles/group_multiplier
+ else
+ gas[gasid] += moles
+
+ if(update)
+ AIR_UPDATE_VALUES(src)
+
+
+///Variadic version of adjustGas(). Takes any number of gas and mole pairs and applies them.
+/datum/gas_mixture/proc/adjustMultipleGases()
+ ASSERT(!(args.len % 2))
+
+ for(var/i in 1 to args.len-1 step 2)
+ adjustGas(args[i], args[i+1], update = 0)
+
+ AIR_UPDATE_VALUES(src)
+
+
+///Variadic version of adjustGasWithTemp(). Takes any number of gas, mole and temperature associations and applies them.
+/datum/gas_mixture/proc/adjustMultipleGasesWithTemp()
+ ASSERT(!(args.len % 3))
+
+ for(var/i in 1 to args.len-1 step 3)
+ adjustGasWithTemp(args[i], args[i + 1], args[i + 2], update = 0)
+
+ AIR_UPDATE_VALUES(src)
+
+
+///Merges all the gas from another mixture into this one. Respects group_multipliers and adjusts temperature correctly. Does not modify giver in any way.
+/datum/gas_mixture/proc/merge(const/datum/gas_mixture/giver)
+ if(!giver)
+ return
+
+ if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = getHeatCapacity()
+ var/giver_heat_capacity = giver.getHeatCapacity()
+ var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
+ if(combined_heat_capacity != 0)
+ temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
+
+ if((group_multiplier != 1)||(giver.group_multiplier != 1))
+ for(var/g in giver.gas)
+ gas[g] += giver.gas[g] * giver.group_multiplier / group_multiplier
+ else
+ for(var/g in giver.gas)
+ gas[g] += giver.gas[g]
+
+ AIR_UPDATE_VALUES(src)
+
+///Used to equalize the mixture between two zones before sleeping an edge.
+/datum/gas_mixture/proc/equalize(datum/gas_mixture/sharer)
+ var/our_heatcap = getHeatCapacity()
+ var/share_heatcap = sharer.getHeatCapacity()
+
+ // Special exception: there isn't enough air around to be worth processing this edge next tick, zap both to zero.
+ if(total_moles + sharer.total_moles <= MINIMUM_AIR_TO_SUSPEND)
+ gas.Cut()
+ sharer.gas.Cut()
+
+ for(var/g in gas|sharer.gas)
+ var/comb = gas[g] + sharer.gas[g]
+ comb /= volume + sharer.volume
+ gas[g] = comb * volume
+ sharer.gas[g] = comb * sharer.volume
+
+ if(our_heatcap + share_heatcap)
+ temperature = ((temperature * our_heatcap) + (sharer.temperature * share_heatcap)) / (our_heatcap + share_heatcap)
+ sharer.temperature = temperature
+
+ AIR_UPDATE_VALUES(src)
+ AIR_UPDATE_VALUES(sharer)
+
+ return 1
+
+
+///Returns the heat capacity of the gas mix based on the specific heat of the gases.
+/datum/gas_mixture/proc/getHeatCapacity()
+ . = 0
+ for(var/g in gas)
+ . += xgm_gas_data.specific_heat[g] * gas[g]
+ . *= group_multiplier
+
+
+///Adds or removes thermal energy. Returns the actual thermal energy change, as in the case of removing energy we can't go below TCMB.
+/datum/gas_mixture/proc/addThermalEnergy(thermal_energy)
+
+ if (total_moles == 0)
+ return 0
+
+ var/heat_capacity = getHeatCapacity()
+ if (thermal_energy < 0)
+ if (temperature < TCMB)
+ return 0
+ var/thermal_energy_limit = -(temperature - TCMB)*heat_capacity //ensure temperature does not go below TCMB
+ thermal_energy = max( thermal_energy, thermal_energy_limit ) //thermal_energy and thermal_energy_limit are negative here.
+ temperature += thermal_energy/heat_capacity
+ return thermal_energy
+
+///Returns the thermal energy change required to get to a new temperature
+/datum/gas_mixture/proc/getThermalEnergyChange(new_temperature)
+ return getHeatCapacity()*(max(new_temperature, 0) - temperature)
+
+
+///Technically vacuum doesn't have a specific entropy. Just use a really big number (infinity would be ideal) here so that it's easy to add gas to vacuum and hard to take gas out.
+#define SPECIFIC_ENTROPY_VACUUM 150000
+
+
+///Returns the ideal gas specific entropy of the whole mix. This is the entropy per mole of /mixed/ gas.
+/datum/gas_mixture/proc/specificGroupEntropy()
+ if (!gas.len || total_moles == 0)
+ return SPECIFIC_ENTROPY_VACUUM
+
+ . = 0
+ for(var/g in gas)
+ . += gas[g] * specificEntropyGas(g)
+ . /= total_moles
+
+
+/*
+ It's arguable whether this should even be called entropy anymore. It's more "based on" entropy than actually entropy now.
+
+ Returns the ideal gas specific entropy of a specific gas in the mix. This is the entropy due to that gas per mole of /that/ gas in the mixture, not the entropy due to that gas per mole of gas mixture.
+
+ For the purposes of SS13, the specific entropy is just a number that tells you how hard it is to move gas. You can replace this with whatever you want.
+ Just remember that returning a SMALL number == adding gas to this gas mix is HARD, taking gas away is EASY, and that returning a LARGE number means the opposite (so a vacuum should approach infinity).
+
+ So returning a constant/(partial pressure) would probably do what most players expect. Although the version I have implemented below is a bit more nuanced than simply 1/P in that it scales in a way
+ which is bit more realistic (natural log), and returns a fairly accurate entropy around room temperatures and pressures.
+*/
+/datum/gas_mixture/proc/specificEntropyGas(gasid)
+ if (!(gasid in gas) || gas[gasid] == 0)
+ return SPECIFIC_ENTROPY_VACUUM //that gas isn't here
+
+ //group_multiplier gets divided out in volume/gas[gasid] - also, V/(m*T) = R/(partial pressure)
+ var/molar_mass = xgm_gas_data.molar_mass[gasid]
+ var/specific_heat = xgm_gas_data.specific_heat[gasid]
+ var/safe_temp = max(temperature, TCMB) // We're about to divide by this.
+ return R_IDEAL_GAS_EQUATION * ( log( (IDEAL_GAS_ENTROPY_CONSTANT*volume/(gas[gasid] * safe_temp)) * (molar_mass*specific_heat*safe_temp)**(2/3) + 1 ) + 15 )
+
+///Updates the total_moles count and trims any empty gases. DO NOT USE. USE AIR_UPDATE_VALUES(air)!!!
+/datum/gas_mixture/proc/updateValues()
+ var/list/cached_gas = gas
+ total_moles = 0
+ for(var/g in cached_gas)
+ if(cached_gas[g] <= 0)
+ cached_gas -= g
+ else
+ total_moles += cached_gas[g]
+
+
+///Returns the pressure of the gas mix. Only accurate if there have been no gas modifications since updateValues() has been called.
+/datum/gas_mixture/proc/returnPressure()
+ if(volume)
+ return total_moles * R_IDEAL_GAS_EQUATION * temperature / volume
+ return 0
+
+
+///Removes moles from the gas mixture and returns a gas_mixture containing the removed air.
+/datum/gas_mixture/proc/remove(amount)
+ RETURN_TYPE(/datum/gas_mixture)
+
+ amount = min(amount, total_moles * group_multiplier) //Can not take more air than the gas mixture has!
+ if(amount <= 0)
+ return null
+
+ var/datum/gas_mixture/removed = new
+
+ for(var/g in gas)
+ removed.gas[g] = QUANTIZE((gas[g] / total_moles) * amount)
+ gas[g] -= removed.gas[g] / group_multiplier
+ if(gas[g] <= ATMOS_PRECISION) //Removing floating point errors from the equation
+ gas -= g
+
+ removed.temperature = temperature
+ AIR_UPDATE_VALUES(src)
+ AIR_UPDATE_VALUES(removed)
+
+ return removed
+
+
+///Removes a ratio of gas from the mixture and returns a gas_mixture containing the removed air.
+/datum/gas_mixture/proc/removeRatio(ratio, out_group_multiplier = 1)
+ if(ratio <= 0)
+ return null
+ out_group_multiplier = clamp(out_group_multiplier, 1, group_multiplier)
+
+ ratio = min(ratio, 1)
+
+ var/datum/gas_mixture/removed = new
+ removed.group_multiplier = out_group_multiplier
+
+ for(var/g in gas)
+ removed.gas[g] = (gas[g] * ratio * group_multiplier / out_group_multiplier)
+ gas[g] = gas[g] * (1 - ratio)
+
+ removed.temperature = temperature
+ removed.volume = volume * group_multiplier / out_group_multiplier
+ AIR_UPDATE_VALUES(src)
+ AIR_UPDATE_VALUES(removed)
+
+ return removed
+
+///Removes a volume of gas from the mixture and returns a gas_mixture containing the removed air with the given volume.
+/datum/gas_mixture/proc/removeVolume(removed_volume)
+ var/datum/gas_mixture/removed = removeRatio(removed_volume/(volume*group_multiplier), 1)
+ removed.volume = removed_volume
+ return removed
+
+///Removes moles from the gas mixture, limited by a given flag. Returns a gax_mixture containing the removed air.
+/datum/gas_mixture/proc/removeByFlag(flag, amount)
+ var/datum/gas_mixture/removed = new
+
+ if(!flag || amount <= 0)
+ return removed
+
+ var/sum = 0
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & flag)
+ sum += gas[g]
+
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & flag)
+ removed.gas[g] = QUANTIZE((gas[g] / sum) * amount)
+ gas[g] -= removed.gas[g] / group_multiplier
+
+ removed.temperature = temperature
+ AIR_UPDATE_VALUES(src)
+ AIR_UPDATE_VALUES(removed)
+
+ return removed
+
+///Returns the amount of gas that has the given flag, in moles..
+/datum/gas_mixture/proc/getByFlag(flag)
+ . = 0
+ for(var/g in gas)
+ if(xgm_gas_data.flags[g] & flag)
+ . += gas[g]
+
+///Copies gas and temperature from another gas_mixture.
+/datum/gas_mixture/proc/copyFrom(const/datum/gas_mixture/sample, partial = 1)
+ var/list/cached_gas = gas
+ var/list/sample_gas = sample.gas.Copy()
+
+ //remove all gases not in the sample
+ cached_gas &= sample_gas
+
+ temperature = sample.temperature
+ for(var/id in sample_gas)
+ cached_gas[id] = sample_gas[id] * partial
+ AIR_UPDATE_VALUES(src)
+ return 1
+
+
+///Checks if we are within acceptable range of another gas_mixture to suspend processing or merge.
+/datum/gas_mixture/proc/compare(const/datum/gas_mixture/sample, vacuum_exception = 0)
+ if(!sample) return 0
+
+ if(vacuum_exception)
+ // Special case - If one of the two is zero pressure, the other must also be zero.
+ // This prevents suspending processing when an air-filled room is next to a vacuum,
+ // an edge case which is particually obviously wrong to players
+ if(total_moles == 0 && sample.total_moles != 0 || sample.total_moles == 0 && total_moles != 0)
+ return 0
+
+ var/list/marked = list()
+ for(var/g in gas)
+ if((abs(gas[g] - sample.gas[g]) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((gas[g] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]) || \
+ (gas[g] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g])))
+ return 0
+ marked[g] = 1
+
+ if(abs(returnPressure() - sample.returnPressure()) > MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND)
+ return 0
+
+ for(var/g in sample.gas)
+ if(!marked[g])
+ if((abs(gas[g] - sample.gas[g]) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((gas[g] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]) || \
+ (gas[g] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g])))
+ return 0
+
+ if(total_moles > MINIMUM_AIR_TO_SUSPEND)
+ if((abs(temperature - sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
+ ((temperature < (1 - MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || \
+ (temperature > (1 + MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
+ return 0
+
+ return 1
+
+///Rechecks the gas_mixture and adjusts the graphic list if needed. ///Two lists can be passed by reference if you need know specifically which graphics were added and removed.
+/datum/gas_mixture/proc/checkTileGraphic(list/graphic_add = null, list/graphic_remove = null)
+ for(var/obj/effect/gas_overlay/O in graphic)
+ if(gas[O.gas_id] <= xgm_gas_data.overlay_limit[O.gas_id])
+ LAZYADD(graphic_remove, O)
+ for(var/g in xgm_gas_data.overlay_limit)
+ //Overlay isn't applied for this gas, check if it's valid and needs to be added.
+ if(gas[g] > xgm_gas_data.overlay_limit[g])
+ var/tile_overlay = getTileOverlay(g)
+ if(!(tile_overlay in graphic))
+ LAZYADD(graphic_add, tile_overlay)
+ . = 0
+ //Apply changes
+ if(graphic_add && graphic_add.len)
+ graphic |= graphic_add
+ . = 1
+ if(graphic_remove && graphic_remove.len)
+ graphic -= graphic_remove
+ . = 1
+ if(graphic.len)
+ var/pressure_mod = clamp(returnPressure() / ONE_ATMOSPHERE, 0, 2)
+ for(var/obj/effect/gas_overlay/O in graphic)
+ var/concentration_mod = clamp(gas[O.gas_id] / total_moles, 0.1, 1)
+ var/new_alpha = min(240, round(pressure_mod * concentration_mod * 180, 5))
+ if(new_alpha != O.alpha)
+ O.update_alpha_animation(new_alpha)
+
+/datum/gas_mixture/proc/getTileOverlay(gas_id)
+ if(!LAZYACCESS(tile_overlay_cache, gas_id))
+ LAZYSET(tile_overlay_cache, gas_id, new/obj/effect/gas_overlay(null, gas_id))
+ return tile_overlay_cache[gas_id]
+
+///Simpler version of merge(), adjusts gas amounts directly and doesn't account for temperature or group_multiplier.
+/datum/gas_mixture/proc/add(datum/gas_mixture/right_side)
+ for(var/g in right_side.gas)
+ gas[g] += right_side.gas[g]
+
+ AIR_UPDATE_VALUES(src)
+ return 1
+
+
+///Simpler version of remove(), adjusts gas amounts directly and doesn't account for group_multiplier.
+/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side)
+ for(var/g in right_side.gas)
+ gas[g] -= right_side.gas[g]
+
+ AIR_UPDATE_VALUES(src)
+ return 1
+
+
+///Multiply all gas amounts by a factor.
+/datum/gas_mixture/proc/multiply(factor)
+ for(var/g in gas)
+ gas[g] *= factor
+
+ AIR_UPDATE_VALUES(src)
+ return 1
+
+
+///Divide all gas amounts by a factor.
+/datum/gas_mixture/proc/divide(factor)
+ for(var/g in gas)
+ gas[g] /= factor
+
+ AIR_UPDATE_VALUES(src)
+ return 1
+
+
+///Shares gas with another gas_mixture based on the amount of connecting tiles and a fixed lookup table.
+/datum/gas_mixture/proc/shareRatio(datum/gas_mixture/other, connecting_tiles, share_size = null, one_way = 0)
+ var/static/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66)
+ //Shares a specific ratio of gas between mixtures using simple weighted averages.
+ var/ratio = sharing_lookup_table[6]
+
+ var/size = max(1, group_multiplier)
+ if(isnull(share_size))
+ share_size = max(1, other.group_multiplier)
+
+ var/full_heat_capacity = getHeatCapacity()
+ var/s_full_heat_capacity = other.getHeatCapacity()
+
+ var/list/avg_gas = list()
+
+ for(var/g in gas)
+ avg_gas[g] += gas[g] * size
+
+ for(var/g in other.gas)
+ avg_gas[g] += other.gas[g] * share_size
+
+ for(var/g in avg_gas)
+ avg_gas[g] /= (size + share_size)
+
+ var/temp_avg = 0
+ if(full_heat_capacity + s_full_heat_capacity)
+ temp_avg = (temperature * full_heat_capacity + other.temperature * s_full_heat_capacity) / (full_heat_capacity + s_full_heat_capacity)
+
+ //WOOT WOOT TOUCH THIS AND YOU ARE A RETARD.
+ if(sharing_lookup_table.len >= connecting_tiles) //6 or more interconnecting tiles will max at 42% of air moved per tick.
+ ratio = sharing_lookup_table[connecting_tiles]
+ //WOOT WOOT TOUCH THIS AND YOU ARE A RETARD
+
+ for(var/g in avg_gas)
+ gas[g] = max(0, (gas[g] - avg_gas[g]) * (1 - ratio) + avg_gas[g])
+ if(!one_way)
+ other.gas[g] = max(0, (other.gas[g] - avg_gas[g]) * (1 - ratio) + avg_gas[g])
+
+ temperature = max(0, (temperature - temp_avg) * (1-ratio) + temp_avg)
+ if(!one_way)
+ other.temperature = max(0, (other.temperature - temp_avg) * (1-ratio) + temp_avg)
+
+ AIR_UPDATE_VALUES(src)
+ AIR_UPDATE_VALUES(other)
+
+ return compare(other)
+
+
+///A wrapper around share_ratio for spacing gas at the same rate as if it were going into a large airless room.
+/datum/gas_mixture/proc/shareSpace(datum/gas_mixture/unsim_air)
+ return shareRatio(unsim_air, unsim_air.group_multiplier, max(1, max(group_multiplier + 3, 1) + unsim_air.group_multiplier), one_way = 1)
+
+/datum/gas_mixture/proc/getMass()
+ for(var/g in gas)
+ . += gas[g] * xgm_gas_data.molar_mass[g] * group_multiplier
+
+/datum/gas_mixture/proc/specificGroupMass()
+ var/M = getGroupMoles()
+ if(M)
+ return getMass()/M
+
+///Returns TRUE if the given gas has a volume equal to or greater than the given amount in one group share of gas.
+/datum/gas_mixture/proc/hasGas(gas_id, required_amount)
+ var/amt = gas[gas_id]
+ return (amt >= required_amount)
+
+////LINDA COMPATABILITY PROCS////
+/datum/gas_mixture/proc/get_volume()
+ return max(0, volume)
+
+/datum/gas_mixture/proc/get_temperature()
+ return temperature
+
+/datum/gas_mixture/proc/get_moles()
+ //updateValues()
+ return total_moles
+
+////END LINDA COMPATABILITY////
+
+///Returns the gas list with an update.
+/datum/gas_mixture/proc/getGases()
+ RETURN_TYPE(/list)
+ //updateValues()
+ return gas
+
+/datum/gas_mixture/proc/returnVisuals()
+ AIR_UPDATE_VALUES(src)
+ checkTileGraphic()
+ return graphic
+
+///Returns a gas_mixture datum with identical contents.
+/datum/gas_mixture/proc/copy()
+ RETURN_TYPE(/datum/gas_mixture)
+ var/datum/gas_mixture/new_gas = new
+ AIR_UPDATE_VALUES(src)
+ new_gas.gas = src.gas
+ new_gas.temperature = src.temperature
+ new_gas.total_moles = src.total_moles
+ return new_gas
+
+/turf/open/proc/copy_air_with_tile(turf/open/target_turf)
+ if(istype(target_turf))
+ return_air().copyFrom(target_turf.return_air())
+
+/datum/gas_mixture/proc/leak_to_enviroment(datum/gas_mixture/environment)
+ pump_gas_passive(src, environment, calculate_transfer_moles(src, environment, src.returnPressure() - environment.returnPressure()))
+
+/**
+ * Takes the amount of the gas you want to PP as an argument
+ * So I don't have to do some hacky switches/defines/magic strings
+ * eg:
+ * Plas_PP = get_partial_pressure(gas_mixture.plasma)
+ * O2_PP = get_partial_pressure(gas_mixture.oxygen)
+ * getBreathPartialPressure(gas_pp) --> gas_pp/get_moles()*breath_pp = pp
+ * getTrueBreathPressure(pp) --> gas_pp = pp/breath_pp*get_moles()
+ *
+ * 10/20*5 = 2.5
+ * 10 = 2.5/5*20
+ */
+
+/datum/gas_mixture/proc/getBreathPartialPressure(gas_pressure)
+ return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
+///inverse
+/datum/gas_mixture/proc/getTrueBreathPressure(partial_pressure)
+ return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
diff --git a/code/modules/atmospherics/ZAS/ZAS_Settings.dm b/code/modules/atmospherics/ZAS/ZAS_Settings.dm
new file mode 100644
index 00000000000..159d54a52e6
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/ZAS_Settings.dm
@@ -0,0 +1,105 @@
+/datum/zas_controller
+ var/datum/pl_control/plc = new
+
+ var/fire_consumption_rate = 0.25
+ var/fire_consumption_rate_NAME = "Fire - Air Consumption Ratio"
+ var/fire_consumption_rate_DESC = "Ratio of air removed and combusted per tick."
+
+ var/fire_firelevel_multiplier = 25
+ 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."
+
+ //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"
+
+
+ var/IgnitionLevel = 0.5
+ var/IgnitionLevel_DESC = "Determines point at which fire can ignite"
+
+ var/airflow_lightest_pressure = 20
+ var/airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %"
+ var/airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move."
+
+ var/airflow_light_pressure = 35
+ var/airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %"
+ var/airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move."
+
+ var/airflow_medium_pressure = 50
+ var/airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %"
+ var/airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move."
+
+ var/airflow_heavy_pressure = 65
+ var/airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %"
+ var/airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move."
+
+ var/airflow_dense_pressure = 85
+ var/airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %"
+ var/airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move."
+
+ var/airflow_stun_pressure = 60
+ var/airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %"
+ var/airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow."
+
+ var/airflow_stun_cooldown = 60
+ var/airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown"
+ var/airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again."
+
+ var/airflow_stun = 1 SECONDS
+ var/airflow_stun_NAME = "Airflow Impact - Stunning"
+ var/airflow_stun_DESC = "How much a mob is stunned when hit by an object."
+
+ var/airflow_damage = 3
+ var/airflow_damage_NAME = "Airflow Impact - Damage"
+ var/airflow_damage_DESC = "Damage from airflow impacts."
+
+ var/airflow_speed_decay = 1.5
+ var/airflow_speed_decay_NAME = "Airflow Speed Decay"
+ var/airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays."
+
+ var/airflow_delay = 30
+ var/airflow_delay_NAME = "Airflow Retrigger Delay"
+ var/airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again."
+
+ var/airflow_mob_slowdown = 1
+ var/airflow_mob_slowdown_NAME = "Airflow Slowdown"
+ var/airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow."
+
+ var/connection_insulation = 1
+ var/connection_insulation_NAME = "Connections - Insulation"
+ var/connection_insulation_DESC = "Boolean, should doors forbid heat transfer?"
+
+ var/connection_temperature_delta = 10
+ var/connection_temperature_delta_NAME = "Connections - Temperature Difference"
+ var/connection_temperature_delta_DESC = "The smallest temperature difference which will cause heat to travel through doors."
+
+ var/maxex_devastation_range = 4
+ var/max_explosion_range_NAME = "Explosion Devastation Range"
+ var/max_explosion_range_DESC = "By default, 1/4th of fire range."
+
+ var/maxex_heavy_range = 8
+ var/max_heavy_range_NAME = "Explosion Heavy Range"
+ var/max_heavy_range_DESC = "By default, 1/2 of light range"
+
+ var/maxex_light_range = 16
+ var/max_light_range_NAME = "Explosion Light Range"
+ var/max_light_range_DESC = "By default, this is the baseline for other explosion values."
+
+ var/maxex_fire_range = 16
+ var/max_fire_range_NAME = "Explosion Fire Range"
+ var/max_fire_range_DESC = "By default, equal to light range."
+
+ var/maxex_flash_range = 20
+ var/max_flash_range_NAME = "Explosion Flash Range"
+ var/max_flash_range_DESC = "By default, 5/4ths of light range."
+
+/datum/zas_controller/proc/set_bomb_cap(val)
+ if(!isnum(val))
+ CRASH("Non-number given to set_bomb_cap.")
+
+ maxex_devastation_range = val/4
+ maxex_heavy_range = val/2
+ maxex_light_range = val
+ maxex_fire_range = val
+ maxex_flash_range = val*1.2
diff --git a/code/modules/atmospherics/ZAS/Zone.dm b/code/modules/atmospherics/ZAS/Zone.dm
new file mode 100644
index 00000000000..b0711f66969
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/Zone.dm
@@ -0,0 +1,252 @@
+/*
+
+Overview:
+ Each zone is a self-contained area where gas values would be the same if tile-based equalization were run indefinitely.
+ If you're unfamiliar with ZAS, FEA's air groups would have similar functionality if they didn't break in a stiff breeze.
+
+Class Vars:
+ name - A name of the format "Zone [#]", used for debugging.
+ invalid - True if the zone has been erased and is no longer eligible for processing.
+ needs_update - True if the zone has been added to the update list.
+ edges - A list of edges that connect to this zone.
+ air - The gas mixture that any turfs in this zone will return. Values are per-tile with a group multiplier.
+
+Class Procs:
+ add_turf(turf/T)
+ Adds a turf to the contents, sets its zone and merges its air.
+
+ remove_turf(turf/T)
+ Removes a turf, sets its zone to null and erases any gas graphics.
+ Invalidates the zone if it has no more tiles.
+
+ merge_into(zone/into)
+ Invalidates this zone and adds all its former contents to into.
+
+ invalidate()
+ Marks this zone as invalid and removes it from processing.
+
+ rebuild()
+ Invalidates the zone and marks all its former tiles for updates.
+
+ add_tile_air(turf/simulated/T)
+ Adds the air contained in T.air to the zone's air supply. Called when adding a turf.
+
+ tick()
+ Called only when the gas content is changed. Archives values and changes gas graphics.
+
+ dbg_data(mob/M)
+ Sends M a printout of important figures for the zone.
+
+*/
+
+
+/zone
+ ///A simple numerical value
+ var/name
+ ///If a zone is "invalid" it will not process
+ var/invalid = 0
+ var/list/contents = list()
+ ///All fire tiles in this zone
+ var/list/fire_tiles = list()
+ ///All physical sources of fire fuel in this zone
+ var/list/fuel_objs = list()
+ ///Does SSzas need to update this zone? (SSzas.mark_zone_update(zone))
+ var/needs_update = 0
+ ///A list of /connection_edge/
+ var/list/edges = list()
+ ///The zone's gas contents
+ var/datum/gas_mixture/air = new
+ ///Air overlays to add next process
+ var/list/graphic_add = list()
+ ///Air overlays to remove next process
+ var/list/graphic_remove = list()
+ var/last_air_temperature = TCMB
+
+/zone/New()
+ SSzas.add_zone(src)
+ air.temperature = TCMB
+ air.group_multiplier = 1
+ air.volume = CELL_VOLUME
+
+///Adds the given turf to the zone
+/zone/proc/add_turf(turf/T)
+#ifdef ZASDBG
+ ASSERT(!invalid)
+ ASSERT(istype(T))
+ ASSERT(!TURF_HAS_VALID_ZONE(T))
+#endif
+
+ var/datum/gas_mixture/turf_air = T.return_air()
+ add_tile_air(turf_air)
+ T.zone = src
+ contents.Add(T)
+ if(T.fire)
+ var/obj/effect/decal/cleanable/oil/fuel = locate() in T
+ fire_tiles.Add(T)
+ SSzas.active_fire_zones |= src
+ if(fuel)
+ fuel_objs += fuel
+ RegisterSignal(fuel, COMSIG_PARENT_QDELETING, .proc/handle_fuel_del)
+ T.update_graphic(air.graphic)
+
+///Removes the given turf from the zone. Will invalidate the zone if it was the last turf.
+/zone/proc/remove_turf(turf/T)
+#ifdef ZASDBG
+ ASSERT(!invalid)
+ ASSERT(istype(T))
+ ASSERT(T.zone == src)
+ soft_assert(T in contents, "Lists are weird broseph")
+#endif
+ contents.Remove(T)
+ fire_tiles.Remove(T)
+ if(T.fire)
+ var/obj/effect/decal/cleanable/oil/fuel = locate() in T
+ fuel_objs -= fuel
+ T.zone = null
+ T.update_graphic(graphic_remove = air.graphic)
+ if(contents.len)
+ air.group_multiplier = contents.len
+ else
+ invalidate()
+
+///Merges src into the given zone
+/zone/proc/merge_into(zone/into)
+#ifdef ZASDBG
+ ASSERT(!invalid)
+ ASSERT(istype(into))
+ ASSERT(into != src)
+ ASSERT(!into.invalid)
+#endif
+ invalidate()
+
+ for(var/turf/T in contents)
+ if(!T.simulated)
+ continue
+ into.add_turf(T)
+ T.update_graphic(graphic_remove = air.graphic)
+ #ifdef ZASDBG
+ T.dbg(zasdbgovl_merged)
+ #endif
+
+ //rebuild the old zone's edges so that they will be possessed by the new zone
+ for(var/connection_edge/E in edges)
+ if(E.contains_zone(into))
+ continue //don't need to rebuild this edge
+ for(var/turf/T in E.connecting_turfs)
+ SSzas.mark_for_update(T)
+
+///Marks the zone as invalid, removing it from the SSzas zone list.
+/zone/proc/invalidate()
+ invalid = 1
+ SSzas.remove_zone(src)
+ #ifdef ZASDBG
+ for(var/turf/T in contents)
+ if(!T.simulated)
+ T.dbg(zasdbgovl_invalid_zone)
+ #endif
+
+///Invalidates the zone and marks all of it's contents for update.
+/zone/proc/rebuild()
+ if(invalid)
+ return //Short circuit for explosions where rebuild is called many times over.
+ invalidate()
+
+ for(var/turf/T as anything in contents)
+ if(!T.simulated)
+ continue
+ T.update_graphic(graphic_remove = air.graphic) //we need to remove the overlays so they're not doubled when the zone is rebuilt
+ #ifdef ZASDBG
+ //T.dbg(invalid_zone)
+ #endif
+ T.needs_air_update = 0 //Reset the marker so that it will be added to the list.
+ SSzas.mark_for_update(T)
+
+ CHECK_TICK
+
+///Assumes a given gas mixture, dividing it amongst the zone.
+/zone/proc/add_tile_air(datum/gas_mixture/tile_air)
+ air.group_multiplier = 1
+ air.multiply(contents.len)
+ air.merge(tile_air)
+ air.divide(contents.len+1)
+ air.group_multiplier = contents.len+1
+
+///Zone's process proc.
+/zone/proc/tick()
+
+ // Update fires.
+ if(air.temperature >= PHORON_FLASHPOINT && !length(fire_tiles) && length(contents) && !(src in SSzas.active_fire_zones) && air.check_combustability())
+ var/turf/T = pick(contents)
+ if(T.simulated)
+ T.create_fire(zas_settings.fire_firelevel_multiplier)
+
+ // Update gas overlays.
+ if(air.checkTileGraphic(graphic_add, graphic_remove))
+ for(var/turf/T as anything in contents)
+ if(T.simulated)
+ T.update_graphic(graphic_add, graphic_remove)
+ graphic_add.len = 0
+ graphic_remove.len = 0
+
+ // Update connected edges.
+ for(var/connection_edge/E as anything in edges)
+ if(E.sleeping)
+ E.recheck()
+
+ // Handle condensation from the air.
+ /*
+ for(var/g in air.gas)
+ var/product = xgm_gas_data.condensation_products[g]
+ if(product && air.temperature <= xgm_gas_data.condensation_points[g])
+ var/condensation_area = air.group_multiplier
+ while(condensation_area > 0)
+ condensation_area--
+ var/turf/flooding = pick(contents)
+ var/condense_amt = min(air.gas[g], rand(3,5))
+ if(condense_amt < 1)
+ break
+ air.adjustGas(g, -condense_amt)
+ flooding.add_fluid(condense_amt, product)
+ */
+
+ // Update atom temperature.
+ if(abs(air.temperature - last_air_temperature) >= ATOM_TEMPERATURE_EQUILIBRIUM_THRESHOLD)
+ last_air_temperature = air.temperature
+ for(var/turf/T as anything in contents)
+ if(!T.simulated)
+ continue
+ for(var/atom/movable/checking as anything in T.contents)
+ if(checking.simulated)
+ QUEUE_TEMPERATURE_ATOMS(checking)
+ CHECK_TICK
+
+///Prints debug information to the given mob. Used by the "Zone Info" verb. Does not require ZASDBG compile define.
+/zone/proc/dbg_data(mob/M)
+ to_chat(M, name)
+ for(var/g in air.gas)
+ to_chat(M, "[xgm_gas_data.name[g]]: [air.gas[g]]")
+ to_chat(M, "P: [air.returnPressure()] kPa V: [air.volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)")
+ to_chat(M, "O2 per N2: [(air.gas[GAS_NITROGEN] ? air.gas[GAS_OXYGEN]/air.gas[GAS_NITROGEN] : "N/A")] Moles: [air.total_moles]")
+ to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])")
+ to_chat(M, "Edges: [edges.len]")
+ if(invalid) to_chat(M, "Invalid!")
+ var/zone_edges = 0
+ var/space_edges = 0
+ var/space_coefficient = 0
+ for(var/connection_edge/E in edges)
+ if(E.type == /connection_edge/zone)
+ zone_edges++
+ else
+ space_edges++
+ space_coefficient += E.coefficient
+ to_chat(M, "[E:air:returnPressure()]kPa")
+
+ to_chat(M, "Zone Edges: [zone_edges]")
+ to_chat(M, "Space Edges: [space_edges] ([space_coefficient] connections)\n")
+
+ //for(var/turf/T in unsimulated_contents)
+// to_chat(M, "[T] at ([T.x],[T.y])")
+
+///If fuel disappears from anything that isn't a fire burning it out, we gotta clear it's ref
+/zone/proc/handle_fuel_del(datum/source)
+ fuel_objs -= src
diff --git a/code/modules/atmospherics/ZAS/_docs.dm b/code/modules/atmospherics/ZAS/_docs.dm
new file mode 100644
index 00000000000..822c8ac7b2a
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/_docs.dm
@@ -0,0 +1,28 @@
+/*
+
+Zone Air System:
+
+This air system divides the station into impermeable areas called zones.
+When something happens, i.e. a door opening or a wall being taken down,
+zones equalize and eventually merge. Making an airtight area closes the connection again.
+
+Control Flow:
+Every air tick:
+ Marked turfs are updated with update_air_properties(), followed by post_update_air_properties().
+ Edges, including those generated by connections in the previous step, are processed. This is where gas is exchanged.
+ Fire is processed.
+ Marked zones have their air archived.
+
+Important Functions:
+
+SSair.mark_for_update(turf)
+ When stuff happens, call this. It works on everything. You basically don't need to worry about any other
+ functions besides CanPass().
+
+Notes for people who used ZAS before:
+ There is no connected_zones anymore.
+ To get the zones that are connected to a zone, use this loop:
+ for(var/connection_edge/zone/edge in zone.edges)
+ var/zone/connected_zone = edge.get_connected_zone(zone)
+
+*/
diff --git a/code/modules/atmospherics/ZAS/atmos_primitives.dm b/code/modules/atmospherics/ZAS/atmos_primitives.dm
new file mode 100644
index 00000000000..161d371ef7e
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/atmos_primitives.dm
@@ -0,0 +1,529 @@
+/*
+ Atmos processes
+
+ These procs generalize various processes used by atmos machinery, such as pumping, filtering, or scrubbing gas, allowing them to be reused elsewhere.
+ If no gas was moved/pumped/filtered/whatever, they return a negative number.
+ Otherwise they return the amount of energy needed to do whatever it is they do (equivalently power if done over 1 second).
+ In the case of free-flowing gas you can do things with gas and still use 0 power, hence the distinction between negative and non-negative return values.
+*/
+
+/*
+/obj/machinery/atmospherics/var/last_flow_rate = 0
+/obj/machinery/atmospherics/var/last_power_draw = 0
+/obj/machinery/portable_atmospherics/var/last_flow_rate = 0
+
+*/
+
+// These balance how easy or hard it is to create huge pressure gradients with pumps and filters.
+// Lower values means it takes longer to create large pressures differences.
+// Has no effect on pumping gasses from high pressure to low, only from low to high.
+#define ATMOS_PUMP_EFFICIENCY 2.5
+#define ATMOS_FILTER_EFFICIENCY 2.5
+
+// Will not bother pumping or filtering if the gas source as fewer than this amount of moles, to help with performance.
+#define MINIMUM_MOLES_TO_PUMP 0.01
+#define MINIMUM_MOLES_TO_FILTER 0.04 //0.04
+
+
+/obj/machinery/atmospherics/var/debug = 0
+
+/client/proc/atmos_toggle_debug(obj/machinery/atmospherics/M in world)
+ set name = "Toggle Debug Messages"
+ set category = "Debug"
+ M.debug = !M.debug
+ to_chat(usr, "[M]: Debug messages toggled [M.debug? "on" : "off"].")
+
+//Generalized gas pumping proc.
+//Moves gas from one gas_mixture to another and returns the amount of power needed (assuming 1 second), or -1 if no gas was pumped.
+//transfer_moles - Limits the amount of moles to transfer. The actual amount of gas moved may also be limited by available_power, if given.
+//available_power - the maximum amount of power that may be used when moving gas. If null then the transfer is not limited by power.
+/proc/pump_gas(datum/gas_mixture/source, datum/gas_mixture/sink, transfer_moles = null, available_power = null)
+ if (source.total_moles < MINIMUM_MOLES_TO_PUMP)
+ sink.merge(source.remove(INFINITY))
+ return -1
+
+ if (isnull(transfer_moles))
+ transfer_moles = source.total_moles
+ else
+ transfer_moles = min(source.total_moles, transfer_moles)
+
+ //Calculate the amount of energy required and limit transfer_moles based on available power
+ var/specific_power = calculate_specific_power(source, sink)/ATMOS_PUMP_EFFICIENCY //this has to be calculated before we modify any gas mixtures
+ if (!isnull(available_power) && specific_power > 0)
+ transfer_moles = min(transfer_moles, available_power / specific_power)
+
+ if (transfer_moles < MINIMUM_MOLES_TO_PUMP) //if we can't transfer enough gas just stop to avoid further processing
+ return -1
+
+ var/datum/gas_mixture/removed = source.remove(transfer_moles)
+ if (!removed) //Just in case
+ return -1
+
+ var/power_draw = specific_power*transfer_moles
+
+ sink.merge(removed)
+
+ return power_draw
+
+//Gas 'pumping' proc for the case where the gas flow is passive and driven entirely by pressure differences (but still one-way).
+/proc/pump_gas_passive(datum/gas_mixture/source, datum/gas_mixture/sink, transfer_moles = null)
+ if (source.total_moles < MINIMUM_MOLES_TO_PUMP) //if we can't transfer enough gas just stop to avoid further processing
+ return -1
+
+ if (isnull(transfer_moles))
+ transfer_moles = source.total_moles
+ else
+ transfer_moles = min(source.total_moles, transfer_moles)
+
+ var/equalize_moles = calculate_equalize_moles(source, sink)
+ transfer_moles = min(transfer_moles, equalize_moles)
+
+ if (transfer_moles < MINIMUM_MOLES_TO_PUMP) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ /*
+ //Update flow rate meter
+ if (istype(M, /obj/machinery/atmospherics))
+ var/obj/machinery/atmospherics/A = M
+ A.last_flow_rate = (transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
+ if (A.debug)
+ A.visible_message("[A]: moles transferred = [transfer_moles] mol")
+
+ if (istype(M, /obj/machinery/portable_atmospherics))
+ var/obj/machinery/portable_atmospherics/P = M
+ P.last_flow_rate = (transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
+ */
+
+ var/datum/gas_mixture/removed = source.remove(transfer_moles)
+ if(!removed) //Just in case
+ return -1
+ sink.merge(removed)
+
+ return 0
+
+//Generalized gas scrubbing proc.
+//Selectively moves specified gasses one gas_mixture to another and returns the amount of power needed (assuming 1 second), or -1 if no gas was filtered.
+//filtering - A list of gasids to be scrubbed from source
+//total_transfer_moles - Limits the amount of moles to scrub. The actual amount of gas scrubbed may also be limited by available_power, if given.
+//available_power - the maximum amount of power that may be used when scrubbing gas. If null then the scrubbing is not limited by power.
+/proc/scrub_gas(list/filtering, datum/gas_mixture/source, datum/gas_mixture/sink, total_transfer_moles = null, available_power = null)
+ if (source.total_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &=
+
+ //Determine the specific power of each filterable gas type, and the total amount of filterable gas (gasses selected to be scrubbed)
+ var/total_filterable_moles = 0 //the total amount of filterable gas
+ var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type
+ for (var/g in filtering)
+ if (source.gas[g] < MINIMUM_MOLES_TO_FILTER)
+ total_filterable_moles += source.gas[g] //Just get rid of it, ffs
+ continue
+
+ var/specific_power = calculate_specific_power_gas(g, source, sink)/ATMOS_FILTER_EFFICIENCY
+ specific_power_gas[g] = specific_power
+ total_filterable_moles += source.gas[g]
+
+ ///Just transfer it, who really cares at a scale this small.
+ if (total_filterable_moles < MINIMUM_MOLES_TO_FILTER)
+ for(var/g in filtering)
+ source.setGasMoles(g, 0)
+ sink.adjustGasWithTemp(g, source.gas[g] * source.group_multiplier, source.temperature)
+ return -1
+
+ //now that we know the total amount of filterable gas, we can calculate the amount of power needed to scrub one mole of gas
+ var/total_specific_power = 0 //the power required to remove one mole of filterable gas
+ for (var/g in filtering)
+ var/ratio = source.gas[g]/total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas
+ total_specific_power += specific_power_gas[g]*ratio
+
+ //Figure out how much of each gas to filter
+ if (isnull(total_transfer_moles))
+ total_transfer_moles = total_filterable_moles
+ else
+ total_transfer_moles = min(total_transfer_moles, total_filterable_moles)
+
+ //limit transfer_moles based on available power
+ if (!isnull(available_power) && total_specific_power > 0)
+ total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power)
+
+ if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ var/power_draw = 0
+ for (var/g in filtering)
+ var/transfer_moles = source.gas[g]
+ //filter gas in proportion to the mole ratio
+ transfer_moles = min(transfer_moles, total_transfer_moles*(source.gas[g]/total_filterable_moles))
+
+ //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop.
+ source.adjustGas(g, -transfer_moles, update=0)
+ sink.adjustGasWithTemp(g, transfer_moles, source.temperature, update=0)
+
+ power_draw += specific_power_gas[g]*transfer_moles
+
+ //Remix the resulting gases
+ AIR_UPDATE_VALUES(sink)
+ AIR_UPDATE_VALUES(source)
+
+ return power_draw
+
+//Generalized gas filtering proc.
+//Filtering is a bit different from scrubbing. Instead of selectively moving the targeted gas types from one gas mix to another, filtering splits
+//the input gas into two outputs: one that contains /only/ the targeted gas types, and another that completely clean of the targeted gas types.
+//filtering - A list of gasids to be filtered. These gasses get moved to sink_filtered, while the other gasses get moved to sink_clean.
+//total_transfer_moles - Limits the amount of moles to input. The actual amount of gas filtered may also be limited by available_power, if given.
+//available_power - the maximum amount of power that may be used when filtering gas. If null then the filtering is not limited by power.
+/proc/filter_gas(list/filtering, datum/gas_mixture/source, datum/gas_mixture/sink_filtered, datum/gas_mixture/sink_clean, total_transfer_moles = null, available_power = null)
+ if (source.total_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &=
+
+ var/total_specific_power = 0 //the power required to remove one mole of input gas
+ var/total_filterable_moles = 0 //the total amount of filterable gas
+ var/total_unfilterable_moles = 0 //the total amount of non-filterable gas
+ var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type
+ for (var/g in source.gas)
+ if (source.gas[g] < MINIMUM_MOLES_TO_FILTER)
+ continue
+
+ if (g in filtering)
+ specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_filtered)/ATMOS_FILTER_EFFICIENCY
+ total_filterable_moles += source.gas[g]
+ else
+ specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_clean)/ATMOS_FILTER_EFFICIENCY
+ total_unfilterable_moles += source.gas[g]
+
+ var/ratio = source.gas[g]/source.total_moles //converts the specific power per mole of pure gas to specific power per mole of input gas mix
+ total_specific_power += specific_power_gas[g]*ratio
+
+ //Figure out how much of each gas to filter
+ if (isnull(total_transfer_moles))
+ total_transfer_moles = source.total_moles
+ else
+ total_transfer_moles = min(total_transfer_moles, source.total_moles)
+
+ //limit transfer_moles based on available power
+ if (!isnull(available_power) && total_specific_power > 0)
+ total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power)
+
+ if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ var/datum/gas_mixture/removed = source.remove(total_transfer_moles)
+ if (!removed) //Just in case
+ return -1
+
+ var/filtered_power_used = 0 //power used to move filterable gas to sink_filtered
+ var/unfiltered_power_used = 0 //power used to move unfilterable gas to sink_clean
+ for (var/g in removed.gas)
+ var/power_used = specific_power_gas[g]*removed.gas[g]
+ if (g in filtering)
+ //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop.
+ sink_filtered.adjustGasWithTemp(g, removed.gas[g], removed.temperature, update=0)
+ removed.adjustGas(g, -removed.gas[g], update=0)
+ filtered_power_used += power_used
+ else
+ unfiltered_power_used += power_used
+
+ AIR_UPDATE_VALUES(sink_filtered)
+ AIR_UPDATE_VALUES(removed)
+
+ sink_clean.merge(removed)
+
+ return filtered_power_used + unfiltered_power_used
+
+//For omni devices. Instead filtering is an associative list mapping gasids to gas mixtures.
+//I don't like the copypasta, but I decided to keep both versions of gas filtering as filter_gas is slightly faster (doesn't create as many temporary lists, doesn't call updateValues() as much)
+//filter_gas can be removed and replaced with this proc if need be.
+/proc/filter_gas_multi(list/filtering, datum/gas_mixture/source, datum/gas_mixture/sink_clean, total_transfer_moles = null, available_power = null)
+ if (source.total_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &=
+
+ var/total_specific_power = 0 //the power required to remove one mole of input gas
+ var/total_filterable_moles = 0 //the total amount of filterable gas
+ var/total_unfilterable_moles = 0 //the total amount of non-filterable gas
+ var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type
+ for (var/g in source.gas)
+ if (source.gas[g] < MINIMUM_MOLES_TO_FILTER)
+ continue
+
+ if (g in filtering)
+ var/datum/gas_mixture/sink_filtered = filtering[g]
+ specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_filtered)/ATMOS_FILTER_EFFICIENCY
+ total_filterable_moles += source.gas[g]
+ else
+ specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_clean)/ATMOS_FILTER_EFFICIENCY
+ total_unfilterable_moles += source.gas[g]
+
+ var/ratio = source.gas[g]/source.total_moles //converts the specific power per mole of pure gas to specific power per mole of input gas mix
+ total_specific_power += specific_power_gas[g]*ratio
+
+ //Figure out how much of each gas to filter
+ if (isnull(total_transfer_moles))
+ total_transfer_moles = source.total_moles
+ else
+ total_transfer_moles = min(total_transfer_moles, source.total_moles)
+
+ //limit transfer_moles based on available power
+ if (!isnull(available_power) && total_specific_power > 0)
+ total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power)
+
+ if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ var/datum/gas_mixture/removed = source.remove(total_transfer_moles)
+ if (!removed) //Just in case
+ return -1
+
+ var/list/filtered_power_used = list() //power used to move filterable gas to the filtered gas mixes
+ var/unfiltered_power_used = 0 //power used to move unfilterable gas to sink_clean
+ for (var/g in removed.gas)
+ var/power_used = specific_power_gas[g]*removed.gas[g]
+
+ if (g in filtering)
+ var/datum/gas_mixture/sink_filtered = filtering[g]
+ //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop.
+ sink_filtered.adjustGasWithTemp(g, removed.gas[g], removed.temperature, update=1)
+ removed.adjustGas(g, -removed.gas[g], update=0)
+ if (power_used)
+ filtered_power_used[sink_filtered] = power_used
+ else
+ unfiltered_power_used += power_used
+
+ AIR_UPDATE_VALUES(removed)
+
+ var/power_draw = unfiltered_power_used
+ for (var/datum/gas_mixture/sink_filtered in filtered_power_used)
+ power_draw += filtered_power_used[sink_filtered]
+
+ sink_clean.merge(removed)
+
+ return power_draw
+
+//Similar deal as the other atmos process procs.
+//mix_sources maps input gas mixtures to mix ratios. The mix ratios MUST add up to 1.
+/proc/mix_gas(list/mix_sources, datum/gas_mixture/sink, total_transfer_moles = null, available_power = null)
+ if (!mix_sources.len)
+ return -1
+
+ var/total_specific_power = 0 //the power needed to mix one mole of gas
+ var/total_mixing_moles = null //the total amount of gas that can be mixed, given our mix ratios
+ var/total_input_volume = 0 //for flow rate calculation
+ var/total_input_moles = 0 //for flow rate calculation
+ var/list/source_specific_power = list()
+ for (var/datum/gas_mixture/source in mix_sources)
+ if (source.total_moles < MINIMUM_MOLES_TO_FILTER)
+ return -1 //either mix at the set ratios or mix no gas at all
+
+ var/mix_ratio = mix_sources[source]
+ if (!mix_ratio)
+ continue //this gas is not being mixed in
+
+ //mixing rate is limited by the source with the least amount of available gas
+ var/this_mixing_moles = source.total_moles/mix_ratio
+ if (isnull(total_mixing_moles) || total_mixing_moles > this_mixing_moles)
+ total_mixing_moles = this_mixing_moles
+
+ source_specific_power[source] = calculate_specific_power(source, sink)*mix_ratio/ATMOS_FILTER_EFFICIENCY
+ total_specific_power += source_specific_power[source]
+ total_input_volume += source.volume
+ total_input_moles += source.total_moles
+
+ if (total_mixing_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ if (isnull(total_transfer_moles))
+ total_transfer_moles = total_mixing_moles
+ else
+ total_transfer_moles = min(total_mixing_moles, total_transfer_moles)
+
+ //limit transfer_moles based on available power
+ if (!isnull(available_power) && total_specific_power > 0)
+ total_transfer_moles = min(total_transfer_moles, available_power / total_specific_power)
+
+ if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
+ return -1
+
+ /*
+ //Update flow rate var
+ if (istype(M, /obj/machinery/atmospherics))
+ var/obj/machinery/atmospherics/A = M
+ A.last_flow_rate = (total_transfer_moles/total_input_moles)*total_input_volume //group_multiplier gets divided out here
+ if (istype(M, /obj/machinery/portable_atmospherics))
+ var/obj/machinery/portable_atmospherics/P = M
+ P.last_flow_rate = (total_transfer_moles/total_input_moles)*total_input_volume //group_multiplier gets divided out here
+ */
+
+ var/total_power_draw = 0
+ for (var/datum/gas_mixture/source in mix_sources)
+ var/mix_ratio = mix_sources[source]
+ if (!mix_ratio)
+ continue
+
+ var/transfer_moles = total_transfer_moles * mix_ratio
+
+ var/datum/gas_mixture/removed = source.remove(transfer_moles)
+
+ var/power_draw = transfer_moles * source_specific_power[source]
+ total_power_draw += power_draw
+
+ sink.merge(removed)
+
+ return total_power_draw
+
+/*
+ Helper procs for various things.
+*/
+
+//Calculates the amount of power needed to move one mole from source to sink.
+/proc/calculate_specific_power(datum/gas_mixture/source, datum/gas_mixture/sink)
+ //Calculate the amount of energy required
+ var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
+ var/specific_entropy = sink.specificGroupEntropy() - source.specificGroupEntropy() //sink is gaining moles, source is loosing
+ var/specific_power = 0 // W/mol
+
+ //If specific_entropy is < 0 then power is required to move gas
+ if (specific_entropy < 0)
+ specific_power = -specific_entropy*air_temperature //how much power we need per mole
+
+ return specific_power
+
+//Calculates the amount of power needed to move one mole of a certain gas from source to sink.
+/proc/calculate_specific_power_gas(gasid, datum/gas_mixture/source, datum/gas_mixture/sink)
+ //Calculate the amount of energy required
+ var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
+ var/specific_entropy = sink.specificEntropyGas(gasid) - source.specificEntropyGas(gasid) //sink is gaining moles, source is loosing
+ var/specific_power = 0 // W/mol
+
+ //If specific_entropy is < 0 then power is required to move gas
+ if (specific_entropy < 0)
+ specific_power = -specific_entropy*air_temperature //how much power we need per mole
+
+ return specific_power
+
+//Calculates the APPROXIMATE amount of moles that would need to be transferred to change the pressure of sink by pressure_delta
+//If set, sink_volume_mod adjusts the effective output volume used in the calculation. This is useful when the output gas_mixture is
+//part of a pipenetwork, and so it's volume isn't representative of the actual volume since the gas will be shared across the pipenetwork when it processes.
+/proc/calculate_transfer_moles(datum/gas_mixture/source, datum/gas_mixture/sink, pressure_delta, sink_volume_mod=0)
+ if(source.temperature == 0 || source.total_moles == 0) return 0
+
+ var/output_volume = (sink.volume * sink.group_multiplier) + sink_volume_mod
+ var/source_total_moles = source.total_moles * source.group_multiplier
+
+ var/air_temperature = source.temperature
+ if(sink.total_moles > 0 && sink.temperature > 0)
+ //estimate the final temperature of the sink after transfer
+ var/estimate_moles = pressure_delta*output_volume/(sink.temperature * R_IDEAL_GAS_EQUATION)
+ var/sink_heat_capacity = sink.getHeatCapacity()
+ var/transfer_heat_capacity = source.getHeatCapacity()*estimate_moles/source_total_moles
+ air_temperature = (sink.temperature*sink_heat_capacity + source.temperature*transfer_heat_capacity) / (sink_heat_capacity + transfer_heat_capacity)
+
+ #ifdef UNIT_TESTS
+ if(air_temperature == 0)
+ CRASH("Air temperature is 0. Source: ([json_encode(source.gas)], [source.temperature] | Sink: ([json_encode(sink.gas)], [sink.temperature])")
+ if((output_volume/(air_temperature*R_IDEAL_GAS_EQUATION)) == 0)
+ CRASH("Transfer moles is about to divide by 0. Source Total Moles: [source_total_moles] | Output Volume: [output_volume]")
+ #endif
+ //get the number of moles that would have to be transfered to bring sink to the target pressure
+ return pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
+
+//Calculates the APPROXIMATE amount of moles that would need to be transferred to bring source and sink to the same pressure
+/proc/calculate_equalize_moles(datum/gas_mixture/source, datum/gas_mixture/sink)
+ if(source.temperature == 0) return 0
+
+ //Make the approximation that the sink temperature is unchanged after transferring gas
+ var/source_volume = source.volume * source.group_multiplier
+ var/sink_volume = sink.volume * sink.group_multiplier
+
+ var/source_pressure = source.returnPressure()
+ var/sink_pressure = sink.returnPressure()
+
+ return (source_pressure - sink_pressure)/(R_IDEAL_GAS_EQUATION * (source.temperature/source_volume + sink.temperature/sink_volume))
+
+//Determines if the atmosphere is safe (for humans). Safe atmosphere:
+// - Is between 80 and 120kPa
+// - Has between 17% and 30% oxygen
+// - Has temperature between -10C and 50C
+// - Has no or only minimal phoron or N2O
+/proc/get_atmosphere_issues(datum/gas_mixture/atmosphere, returntext = 0)
+ var/list/status = list()
+ if(!atmosphere)
+ status.Add("No atmosphere present.")
+
+ // Temperature check
+ if((atmosphere.temperature > (T0C + 50)) || (atmosphere.temperature < (T0C - 10)))
+ status.Add("Temperature too [atmosphere.temperature > (T0C + 50) ? "high" : "low"].")
+
+ // Pressure check
+ var/pressure = atmosphere.returnPressure()
+ if((pressure > 120) || (pressure < 80))
+ status.Add("Pressure too [pressure > 120 ? "high" : "low"].")
+
+ // Gas concentration checks
+ var/oxygen = 0
+ var/phoron = 0
+ var/carbondioxide = 0
+ var/nitrousoxide = 0
+ var/hydrogen = 0
+ if(atmosphere.total_moles) // Division by zero prevention
+ oxygen = (atmosphere.gas[GAS_OXYGEN] / atmosphere.total_moles) * 100 // Percentage of the gas
+ phoron = (atmosphere.gas[GAS_PLASMA] / atmosphere.total_moles) * 100
+ carbondioxide = (atmosphere.gas[GAS_CO2] / atmosphere.total_moles) * 100
+ nitrousoxide = (atmosphere.gas[GAS_N2O] / atmosphere.total_moles) * 100
+ hydrogen = (atmosphere.gas[GAS_HYDROGEN] / atmosphere.total_moles) * 100
+
+ if(!oxygen)
+ status.Add("No oxygen.")
+ else if((oxygen > 30) || (oxygen < 17))
+ status.Add("Oxygen too [oxygen > 30 ? "high" : "low"].")
+
+
+
+ if(phoron > 0.1) // Toxic even in small amounts.
+ status.Add("Phoron contamination.")
+ if(nitrousoxide > 0.1) // Probably slightly less dangerous but still.
+ status.Add("N2O contamination.")
+ if(hydrogen > 2.5) // Not too dangerous, but flammable.
+ status.Add("Hydrogen contamination.")
+ if(carbondioxide > 5) // Not as dangerous until very large amount is present.
+ status.Add("CO2 concentration high.")
+
+
+ if(returntext)
+ return jointext(status, " ")
+ else
+ return status.len
+
+//surface must be the surface area in m^2
+/proc/radiate_heat_to_space(datum/gas_mixture/air, surface, thermal_conductivity)
+ var/gas_density = air.total_moles/air.volume
+ thermal_conductivity *= min(gas_density / ( RADIATOR_OPTIMUM_PRESSURE/(R_IDEAL_GAS_EQUATION*GAS_CRITICAL_TEMPERATURE) ), 1) //mult by density ratio
+
+ var/heat_gain = get_thermal_radiation(air.temperature, surface, RADIATOR_EXPOSED_SURFACE_AREA_RATIO, thermal_conductivity)
+
+ air.addThermalEnergy(heat_gain)
+
+//Returns the amount of heat gained while in space due to thermal radiation (usually a negative value)
+//surface - the surface area in m^2
+//exposed_surface_ratio - the proportion of the surface that is exposed to sunlight
+//thermal_conductivity - a multipler on the heat transfer rate. See OPEN_HEAT_TRANSFER_COEFFICIENT and friends
+/proc/get_thermal_radiation(surface_temperature, surface, exposed_surface_ratio, thermal_conductivity)
+ //*** Gain heat from sunlight, then lose heat from radiation.
+
+ // We only get heat from the star on the exposed surface area.
+ // If the HE pipes gain more energy from AVERAGE_SOLAR_RADIATION than they can radiate, then they have a net heat increase.
+ . = AVERAGE_SOLAR_RADIATION * (exposed_surface_ratio * surface) * thermal_conductivity
+
+ // Previously, the temperature would enter equilibrium at 26C or 294K.
+ // Only would happen if both sides (all 2 square meters of surface area) were exposed to sunlight. We now assume it aligned edge on.
+ // It currently should stabilise at 129.6K or -143.6C
+ . -= surface * STEFAN_BOLTZMANN_CONSTANT * thermal_conductivity * (surface_temperature - COSMIC_RADIATION_TEMPERATURE) ** 4
+
+#undef MINIMUM_MOLES_TO_PUMP
+#undef MINIMUM_MOLES_TO_FILTER
+#undef ATMOS_PUMP_EFFICIENCY
+#undef ATMOS_FILTER_EFFICIENCY
diff --git a/code/modules/atmospherics/ZAS/zas_extras/gas_reagents.dm b/code/modules/atmospherics/ZAS/zas_extras/gas_reagents.dm
new file mode 100644
index 00000000000..66197ddb6a5
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/zas_extras/gas_reagents.dm
@@ -0,0 +1,50 @@
+//Apparently on TG, N2O fluid doesn't make you giggle, so this is almost an exact copy.
+/datum/reagent/nitrous_oxide/xenon
+ name = "Xenon"
+ description = "A nontoxic gas used as a general anaesthetic."
+ reagent_state = GAS
+ metabolization_rate = 0.3 * REAGENTS_METABOLISM
+ color = "#808080"
+ taste_description = "sweetness"
+ ph = 5.8
+ chemical_flags = REAGENT_NO_RANDOM_RECIPE
+
+/datum/reagent/carbon_monoxide
+ name = "Carbon Monoxide"
+ description = "A dangerous carbon comubstion byproduct."
+ taste_description = "stale air"
+ color = "#808080"
+ metabolization_rate = 0.3 * REAGENTS_METABOLISM
+ chemical_flags = REAGENT_NO_RANDOM_RECIPE
+
+/datum/reagent/carbon_monoxide/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
+ var/warning_message
+ var/warning_prob = 10
+ if(volume >= 3)
+ warning_message = pick("extremely dizzy","short of breath","faint","confused")
+ warning_prob = 15
+ M.adjustOxyLoss(rand(10,20))
+ M.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2, override = TRUE)
+ else if(volume >= 1.5)
+ warning_message = pick("dizzy","short of breath","faint","momentarily confused")
+ M.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2, override = TRUE)
+ M.adjustOxyLoss(rand(3,5))
+ else if(volume >= 0.25)
+ warning_message = pick("a little dizzy","short of breath")
+ warning_prob = 10
+ if(warning_message && prob(warning_prob))
+ to_chat(M, "You feel [warning_message].")
+
+ return ..()
+
+/datum/reagent/carbon_monoxide/on_mob_end_metabolize(mob/living/L)
+ . = ..()
+ L.clear_alert(ALERT_TOO_MUCH_CO2, clear_override = TRUE)
+
+/datum/reagent/toxin/boron
+ name = "Boron"
+ description = "A chemical that is highly valued for its potential in fusion energy."
+ taste_description = "metal"
+ reagent_state = SOLID
+ color = "#837e79"
+ toxpwr = 7
diff --git a/code/modules/atmospherics/ZAS/zas_extras/inflatable.dm b/code/modules/atmospherics/ZAS/zas_extras/inflatable.dm
new file mode 100644
index 00000000000..d5a35bff08b
--- /dev/null
+++ b/code/modules/atmospherics/ZAS/zas_extras/inflatable.dm
@@ -0,0 +1,333 @@
+/obj/item/inflatable
+ name = "inflatable"
+ w_class = WEIGHT_CLASS_NORMAL
+ icon = 'modular_pariah/master_files/icons/obj/inflatable.dmi'
+ max_integrity = 10
+ var/deploy_path = null
+
+/obj/item/inflatable/attack_self(mob/user, modifiers)
+ if(!deploy_path)
+ return
+ var/turf/T = get_turf(src)
+ if (isspaceturf(T))
+ to_chat(user, span_warning("You cannot use \the [src] in open space."))
+ return
+
+ user.visible_message(
+ span_notice("\The [user] starts inflating \an [src]."),
+ span_notice("You start inflating \the [src]."),
+ span_notice("You can hear rushing air."),
+ vision_distance = 5
+ )
+ if (!do_after(user, 1 SECONDS))
+ return
+
+ user.visible_message(
+ span_notice("\The [user] finishes inflating \an [src]."),
+ span_notice("You inflate \the [src]."),
+ vision_distance = 5
+ )
+ playsound(loc, 'sound/items/zip.ogg', 75, 1)
+ var/obj/structure/inflatable/R = new deploy_path(T)
+ transfer_fingerprints_to(R)
+ R.add_fingerprint(user)
+ update_integrity(R.get_integrity())
+ qdel(src)
+
+/obj/item/inflatable/wall
+ name = "inflatable wall"
+ desc = "A folded membrane which rapidly expands into a large cubical shape on activation."
+ icon_state = "folded_wall"
+ deploy_path = /obj/structure/inflatable/wall
+
+/obj/item/inflatable/door
+ name = "inflatable door"
+ desc = "A folded membrane which rapidly expands into a simple door on activation."
+ icon_state = "folded_door"
+ deploy_path = /obj/structure/inflatable/door
+
+/obj/structure/inflatable
+ name = "inflatable"
+ desc = "An inflated membrane. Do not puncture."
+ density = TRUE
+ anchored = TRUE
+ opacity = 0
+ icon = 'modular_pariah/master_files/icons/obj/inflatable.dmi'
+ icon_state = "wall"
+ can_atmos_pass = CANPASS_DENSITY
+ max_integrity = 10
+
+
+ var/undeploy_path = null
+ var/taped
+
+ var/max_pressure_diff = 50 * ONE_ATMOSPHERE // In Baystation this is a Rigsuit level of protection
+ var/max_temp = 5000 //In Baystation this is the heat protection value of a space suit.
+
+/obj/structure/inflatable/wall
+ name = "inflatable wall"
+ undeploy_path = /obj/item/inflatable/wall
+ can_atmos_pass = CANPASS_NEVER
+
+/obj/structure/inflatable/New(location)
+ ..()
+ update_nearby_tiles()
+
+/obj/structure/inflatable/Initialize()
+ . = ..()
+ START_PROCESSING(SSobj, src)
+
+/obj/structure/inflatable/Destroy()
+ update_nearby_tiles()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/structure/inflatable/process()
+ check_environment()
+
+/obj/structure/inflatable/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
+ playsound(src, 'sound/effects/glasshit.ogg', 75, TRUE)
+
+/obj/structure/inflatable/proc/check_environment()
+ var/min_pressure = INFINITY
+ var/max_pressure = 0
+ var/max_local_temp = 0
+
+ for(var/check_dir in GLOB.cardinals)
+ var/turf/T = get_step(src, check_dir)
+ var/datum/gas_mixture/env = T.return_air()
+ var/pressure = env.returnPressure()
+ min_pressure = min(min_pressure, pressure)
+ max_pressure = max(max_pressure, pressure)
+ max_local_temp = max(max_local_temp, env.temperature)
+
+ if(prob(50) && (max_pressure - min_pressure > max_pressure_diff || max_local_temp > max_temp))
+ var/initial_damage_percentage = round(atom_integrity / max_integrity * 100)
+ take_damage(1)
+ var/damage_percentage = round(atom_integrity / max_integrity * 100)
+ if (damage_percentage >= 70 && initial_damage_percentage < 70)
+ visible_message(span_warning("\The [src] is barely holding up!"))
+ else if (damage_percentage >= 30 && initial_damage_percentage < 30)
+ visible_message(span_warning("\The [src] is taking damage!"))
+
+/obj/structure/inflatable/examine(mob/user)
+ . = ..()
+ if (taped)
+ to_chat(user, span_notice("It's being held together by duct tape."))
+
+/obj/structure/inflatable/attackby(obj/item/W, mob/user, params)
+ if(!istype(W)) //|| istype(W, /obj/item/inflatable_dispenser))
+ return
+
+ if(!isturf(user.loc))
+ return //can't do this stuff whilst inside objects and such
+ if(isliving(user))
+ var/mob/living/living_user = user
+ if(living_user.combat_mode)
+ if (W.sharpness & SHARP_POINTY || W.force > 10)
+ attack_generic(user, W.force, BRUTE)
+ return
+
+ if(istype(W, /obj/item/stack/sticky_tape) && (max_integrity - atom_integrity) >= 3)
+ if(taped)
+ to_chat(user, span_notice("\The [src] can't be patched any more with \the [W]!"))
+ return TRUE
+ else
+ taped = TRUE
+ to_chat(user, span_notice("You patch some damage in \the [src] with \the [W]!"))
+ repair_damage(3)
+ return TRUE
+
+ ..()
+
+/obj/structure/inflatable/atom_break(damage_flag)
+ . = ..()
+ deflate(TRUE)
+
+/obj/structure/inflatable/proc/deflate(violent)
+ playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ if(violent)
+ visible_message("[src] rapidly deflates!")
+ var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc)
+ src.transfer_fingerprints_to(R)
+ qdel(src)
+ else
+ if(!undeploy_path)
+ return
+ visible_message("\The [src] slowly deflates.")
+ addtimer(CALLBACK(src, .proc/after_deflate), 5 SECONDS, TIMER_STOPPABLE)
+
+/obj/structure/inflatable/proc/after_deflate()
+ if(QDELETED(src))
+ return
+ var/obj/item/inflatable/R = new undeploy_path(src.loc)
+ src.transfer_fingerprints_to(R)
+ R.update_integrity(src.get_integrity())
+ qdel(src)
+
+/obj/structure/inflatable/verb/hand_deflate()
+ set name = "Deflate"
+ set category = "Object"
+ set src in oview(1)
+
+ if(!usr.Adjacent(src))
+ return FALSE
+ if(!usr.Adjacent(src))
+ return FALSE
+ if(!iscarbon(usr))
+ return FALSE
+
+ var/mob/living/carbon/user = usr
+ if(user.handcuffed || user.stat != CONSCIOUS || user.incapacitated())
+ return FALSE
+
+ verbs -= /obj/structure/inflatable/verb/hand_deflate
+ deflate()
+ return TRUE
+
+/obj/structure/inflatable/attack_generic(mob/user, damage, attack_verb)
+ . = ..()
+ if(.)
+ user.visible_message("[user] [attack_verb] open the [src]!")
+ else
+ user.visible_message("[user] [attack_verb] at [src]!")
+
+
+/obj/structure/inflatable/door //Based on mineral door code
+ name = "inflatable door"
+ density = TRUE
+ anchored = TRUE
+ opacity = 0
+
+ icon_state = "door_closed"
+ undeploy_path = /obj/item/inflatable/door
+
+ var/state = 0 //closed, 1 == open
+ var/isSwitchingStates = 0
+
+/obj/structure/inflatable/door/attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral
+ if(isAI(user)) //so the AI can't open it
+ return
+
+/obj/structure/inflatable/door/attack_robot(mob/living/user)
+ if(get_dist(user,src) <= 1) //not remotely though
+ return TryToSwitchState(user)
+
+/obj/structure/inflatable/door/attack_hand(mob/user as mob)
+ . = ..()
+ if(.)
+ return
+ return TryToSwitchState(user)
+
+/obj/structure/inflatable/door/proc/TryToSwitchState(atom/user)
+ if(isSwitchingStates) return
+ if(ismob(user))
+ var/mob/M = user
+ if(M.client)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(!C.handcuffed)
+ SwitchState()
+ else
+ SwitchState()
+
+/obj/structure/inflatable/door/proc/SwitchState()
+ if(state)
+ Close()
+ else
+ Open()
+
+/obj/structure/inflatable/door/proc/Open()
+ isSwitchingStates = 1
+ flick("door_opening",src)
+ addtimer(CALLBACK(src, .proc/FinishOpen), 1 SECONDS, TIMER_STOPPABLE)
+
+/obj/structure/inflatable/door/proc/FinishOpen()
+ set_density(0)
+ set_opacity(0)
+ state = 1
+ update_icon()
+ isSwitchingStates = 0
+ update_nearby_tiles()
+
+/obj/structure/inflatable/door/proc/Close()
+ // If the inflatable is blocked, don't close
+ for(var/turf/T in locs)
+ for(var/atom/movable/AM as anything in T)
+ if(AM.density)
+ return
+
+ isSwitchingStates = 1
+ flick("door_closing",src)
+ addtimer(CALLBACK(src, .proc/FinishClose), 1 SECONDS, TIMER_STOPPABLE)
+
+/obj/structure/inflatable/door/proc/FinishClose()
+ set_density(1)
+ set_opacity(0)
+ state = 0
+ update_icon()
+ isSwitchingStates = 0
+ update_nearby_tiles()
+
+/obj/structure/inflatable/door/update_icon()
+ . = ..()
+ if(state)
+ icon_state = "door_open"
+ else
+ icon_state = "door_closed"
+
+
+/obj/structure/inflatable/door/deflate(violent=0)
+ playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ if(violent)
+ visible_message("[src] rapidly deflates!")
+ var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc)
+ src.transfer_fingerprints_to(R)
+ qdel(src)
+ else
+ visible_message("[src] slowly deflates.")
+ spawn(50)
+ var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc)
+ src.transfer_fingerprints_to(R)
+ qdel(src)
+
+/obj/item/inflatable/torn
+ name = "torn inflatable wall"
+ desc = "A folded membrane which rapidly expands into a large cubical shape on activation. It is too torn to be usable."
+ icon = 'modular_pariah/master_files/icons/obj/inflatable.dmi'
+ icon_state = "folded_wall_torn"
+
+/obj/item/inflatable/torn/attack_self(mob/user)
+ to_chat(user, "The inflatable wall is too torn to be inflated!")
+ add_fingerprint(user)
+
+/obj/item/inflatable/door/torn
+ name = "torn inflatable door"
+ desc = "A folded membrane which rapidly expands into a simple door on activation. It is too torn to be usable."
+ icon = 'modular_pariah/master_files/icons/obj/inflatable.dmi'
+ icon_state = "folded_door_torn"
+
+/obj/item/inflatable/door/torn/attack_self(mob/user)
+ to_chat(user, "The inflatable door is too torn to be inflated!")
+ add_fingerprint(user)
+
+/obj/item/storage/briefcase/inflatable
+ name = "inflatable barrier box"
+ desc = "Contains inflatable walls and doors. THE SPRITE IS A PLACEHOLDER, OKAY?"
+ w_class = WEIGHT_CLASS_NORMAL
+ max_integrity = 150
+ force = 8
+ hitsound = SFX_SWING_HIT
+ throw_speed = 2
+ throw_range = 4
+ var/startswith = list(/obj/item/inflatable/door = 2, /obj/item/inflatable/wall = 3)
+
+/obj/item/storage/briefcase/inflatable/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+ STR.set_holdable(list(/obj/item/inflatable))
+
+/obj/item/storage/briefcase/inflatable/PopulateContents()
+ for(var/path in startswith)
+ for(var/i in 1 to startswith[path])
+ new path(src)
diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm
deleted file mode 100644
index 897ccb1feb2..00000000000
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ /dev/null
@@ -1,312 +0,0 @@
-/// Returns reactions which will contribute to a hotspot's size.
-/proc/init_hotspot_reactions()
- var/list/fire_reactions = list()
- for (var/datum/gas_reaction/reaction as anything in subtypesof(/datum/gas_reaction))
- if(initial(reaction.expands_hotspot))
- fire_reactions += reaction
-
- return fire_reactions
-
-/atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- return null
-
-
-
-/turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
- return
-
-/**
- * Handles the creation of hotspots and initial activation of turfs.
- * Setting the conditions for the reaction to actually happen for gasmixtures
- * is handled by the hotspot itself, specifically perform_exposure().
- */
-/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh)
- //If the air doesn't exist we just return false
- var/list/air_gases = air?.gases
- if(!air_gases)
- return
-
- . = air_gases[/datum/gas/oxygen]
- var/oxy = . ? .[MOLES] : 0
- if (oxy < 0.5)
- return
- . = air_gases[/datum/gas/plasma]
- var/plas = . ? .[MOLES] : 0
- . = air_gases[/datum/gas/tritium]
- var/trit = . ? .[MOLES] : 0
- . = air_gases[/datum/gas/hydrogen]
- var/h2 = . ? .[MOLES] : 0
- . = air_gases[/datum/gas/freon]
- var/freon = . ? .[MOLES] : 0
- if(active_hotspot)
- if(soh)
- if(plas > 0.5 || trit > 0.5 || h2 > 0.5)
- if(active_hotspot.temperature < exposed_temperature)
- active_hotspot.temperature = exposed_temperature
- if(active_hotspot.volume < exposed_volume)
- active_hotspot.volume = exposed_volume
- else if(freon > 0.5)
- if(active_hotspot.temperature > exposed_temperature)
- active_hotspot.temperature = exposed_temperature
- if(active_hotspot.volume < exposed_volume)
- active_hotspot.volume = exposed_volume
- return
-
- if(((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (plas > 0.5 || trit > 0.5 || h2 > 0.5)) || \
- ((exposed_temperature < FREON_MAXIMUM_BURN_TEMPERATURE) && (freon > 0.5)))
-
- active_hotspot = new /obj/effect/hotspot(src, exposed_volume*25, exposed_temperature)
-
- active_hotspot.just_spawned = (current_cycle < SSair.times_fired)
- //remove just_spawned protection if no longer processing this cell
- SSair.add_to_active(src)
-
-/**
- * Hotspot objects interfaces with the temperature of turf gasmixtures while also providing visual effects.
- * One important thing to note about hotspots are that they can roughly be divided into two categories based on the bypassing variable.
- */
-/obj/effect/hotspot
- anchored = TRUE
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- icon = 'icons/effects/fire.dmi'
- icon_state = "1"
- layer = GASFIRE_LAYER
- plane = ABOVE_GAME_PLANE
- blend_mode = BLEND_ADD
- light_system = MOVABLE_LIGHT
- light_range = LIGHT_RANGE_FIRE
- light_power = 1
- light_color = LIGHT_COLOR_FIRE
-
- /**
- * Volume is the representation of how big and healthy a fire is.
- * Hotspot volume will be divided by turf volume to get the ratio for temperature setting on non bypassing mode.
- * Also some visual stuffs for fainter fires.
- */
- var/volume = 125
- /// Temperature handles the initial ignition and the colouring.
- var/temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
- /// Whether the hotspot is new or not. Used for bypass logic.
- var/just_spawned = TRUE
- /// Whether the hotspot becomes passive and follows the gasmix temp instead of changing it.
- var/bypassing = FALSE
- var/visual_update_tick = 0
- ///Are we burning freon?
- var/cold_fire = FALSE
-
-
-/obj/effect/hotspot/Initialize(mapload, starting_volume, starting_temperature)
- . = ..()
- SSair.hotspots += src
- if(!isnull(starting_volume))
- volume = starting_volume
- if(!isnull(starting_temperature))
- temperature = starting_temperature
- perform_exposure()
- setDir(pick(GLOB.cardinals))
- air_update_turf(FALSE, FALSE)
- var/static/list/loc_connections = list(
- COMSIG_ATOM_ENTERED = .proc/on_entered,
- )
- AddElement(/datum/element/connect_loc, loc_connections)
-
-/**
- * Perform interactions between the hotspot and the gasmixture.
- *
- * For the first tick, hotspots will take a sample of the air in the turf,
- * set the temperature equal to a certain amount, and then reacts it.
- * In some implementations the ratio comes out to around 1, so all of the air in the turf.
- *
- * Afterwards if the reaction is big enough it mostly just tags along the fire,
- * copying the temperature and handling the colouring.
- * If the reaction is too small it will perform like the first tick.
- *
- * Also calls fire_act() which handles burning.
- */
-/obj/effect/hotspot/proc/perform_exposure()
- var/turf/open/location = loc
- var/datum/gas_mixture/reference
- if(!istype(location) || !(location.air))
- return
-
- location.active_hotspot = src
-
- bypassing = !just_spawned && (volume > CELL_VOLUME*0.95)
-
- //Passive mode
- if(bypassing || cold_fire)
- reference = location.air // Our color and volume will depend on the turf's gasmix
- //Active mode
- else
- var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.volume)
- if(affected) //in case volume is 0
- reference = affected // Our color and volume will depend on this small sparked gasmix
- affected.temperature = temperature
- affected.react(src)
- location.assume_air(affected)
-
- if(reference)
- volume = 0
- var/list/cached_results = reference.reaction_results
- for (var/reaction in SSair.hotspot_reactions)
- volume += cached_results[reaction] * FIRE_GROWTH_RATE
- temperature = reference.temperature
-
- // Handles the burning of atoms.
- if(cold_fire)
- return
- for(var/A in location)
- var/atom/AT = A
- if(!QDELETED(AT) && AT != src)
- AT.fire_act(temperature, volume)
- return
-
-/// Mathematics to be used for color calculation.
-/obj/effect/hotspot/proc/gauss_lerp(x, x1, x2)
- var/b = (x1 + x2) * 0.5
- var/c = (x2 - x1) / 6
- return NUM_E ** -((x - b) ** 2 / (2 * c) ** 2)
-
-/obj/effect/hotspot/proc/update_color()
- cut_overlays()
-
- var/heat_r = heat2colour_r(temperature)
- var/heat_g = heat2colour_g(temperature)
- var/heat_b = heat2colour_b(temperature)
- var/heat_a = 255
- var/greyscale_fire = 1 //This determines how greyscaled the fire is.
-
- if(cold_fire)
- heat_r = 0
- heat_g = LERP(255, temperature, 1.2)
- heat_b = LERP(255, temperature, 0.9)
- heat_a = 100
- else if(temperature < 5000) //This is where fire is very orange, we turn it into the normal fire texture here.
- var/normal_amt = gauss_lerp(temperature, 1000, 3000)
- heat_r = LERP(heat_r,255,normal_amt)
- heat_g = LERP(heat_g,255,normal_amt)
- heat_b = LERP(heat_b,255,normal_amt)
- heat_a -= gauss_lerp(temperature, -5000, 5000) * 128
- greyscale_fire -= normal_amt
- if(temperature > 40000) //Past this temperature the fire will gradually turn a bright purple
- var/purple_amt = temperature < LERP(40000,200000,0.5) ? gauss_lerp(temperature, 40000, 200000) : 1
- heat_r = LERP(heat_r,255,purple_amt)
- if(temperature > 200000 && temperature < 500000) //Somewhere at this temperature nitryl happens.
- var/sparkle_amt = gauss_lerp(temperature, 200000, 500000)
- var/mutable_appearance/sparkle_overlay = mutable_appearance('icons/effects/effects.dmi', "shieldsparkles")
- sparkle_overlay.blend_mode = BLEND_ADD
- sparkle_overlay.alpha = sparkle_amt * 255
- add_overlay(sparkle_overlay)
- if(temperature > 400000 && temperature < 1500000) //Lightning because very anime.
- var/mutable_appearance/lightning_overlay = mutable_appearance(icon, "overcharged")
- lightning_overlay.blend_mode = BLEND_ADD
- add_overlay(lightning_overlay)
- if(temperature > 4500000) //This is where noblium happens. Some fusion-y effects.
- var/fusion_amt = temperature < LERP(4500000,12000000,0.5) ? gauss_lerp(temperature, 4500000, 12000000) : 1
- var/mutable_appearance/fusion_overlay = mutable_appearance('icons/effects/atmospherics.dmi', "fusion_gas")
- fusion_overlay.blend_mode = BLEND_ADD
- fusion_overlay.alpha = fusion_amt * 255
- var/mutable_appearance/rainbow_overlay = mutable_appearance('icons/hud/screen_gen.dmi', "druggy")
- rainbow_overlay.blend_mode = BLEND_ADD
- rainbow_overlay.alpha = fusion_amt * 255
- rainbow_overlay.appearance_flags = RESET_COLOR
- heat_r = LERP(heat_r,150,fusion_amt)
- heat_g = LERP(heat_g,150,fusion_amt)
- heat_b = LERP(heat_b,150,fusion_amt)
- add_overlay(fusion_overlay)
- add_overlay(rainbow_overlay)
-
- set_light_color(rgb(LERP(250, heat_r, greyscale_fire), LERP(160, heat_g, greyscale_fire), LERP(25, heat_b, greyscale_fire)))
-
- heat_r /= 255
- heat_g /= 255
- heat_b /= 255
-
- color = list(LERP(0.3, 1, 1-greyscale_fire) * heat_r,0.3 * heat_g * greyscale_fire,0.3 * heat_b * greyscale_fire, 0.59 * heat_r * greyscale_fire,LERP(0.59, 1, 1-greyscale_fire) * heat_g,0.59 * heat_b * greyscale_fire, 0.11 * heat_r * greyscale_fire,0.11 * heat_g * greyscale_fire,LERP(0.11, 1, 1-greyscale_fire) * heat_b, 0,0,0)
- alpha = heat_a
-
-#define INSUFFICIENT(path) (!location.air.gases[path] || location.air.gases[path][MOLES] < 0.5)
-
-/**
- * Regular process proc for hotspots governed by the controller.
- * Handles the calling of perform_exposure() which handles the bulk of temperature processing.
- * Burning or fire_act() are also called by perform_exposure().
- * Also handles the dying and qdeletion of the hotspot and hotspot creations on adjacent cardinal turfs.
- * And some visual stuffs too! Colors and fainter icons for specific conditions.
- */
-/obj/effect/hotspot/process()
- if(just_spawned)
- just_spawned = FALSE
- return
-
- var/turf/open/location = loc
- if(!istype(location))
- qdel(src)
- return
-
- if(location.excited_group)
- location.excited_group.reset_cooldowns()
-
- cold_fire = FALSE
- if(temperature <= FREON_MAXIMUM_BURN_TEMPERATURE)
- cold_fire = TRUE
-
- if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST && !cold_fire) || (volume <= 1))
- qdel(src)
- return
-
- //Not enough / nothing to burn
- if(!location.air || (INSUFFICIENT(/datum/gas/plasma) && INSUFFICIENT(/datum/gas/tritium) && INSUFFICIENT(/datum/gas/hydrogen) && INSUFFICIENT(/datum/gas/freon)) || INSUFFICIENT(/datum/gas/oxygen))
- qdel(src)
- return
-
- perform_exposure()
-
- if(bypassing)
- icon_state = "3"
- if(!cold_fire)
- location.burn_tile()
-
- //Possible spread due to radiated heat.
- if(location.air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD || cold_fire)
- var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE
- if(cold_fire)
- radiated_temperature = location.air.temperature * COLD_FIRE_SPREAD_RADIOSITY_SCALE
- for(var/t in location.atmos_adjacent_turfs)
- var/turf/open/T = t
- if(!T.active_hotspot)
- T.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
-
- else
- if(volume > CELL_VOLUME*0.4)
- icon_state = "2"
- else
- icon_state = "1"
-
- if((visual_update_tick++ % 7) == 0)
- update_color()
-
- return TRUE
-
-/obj/effect/hotspot/Destroy()
- SSair.hotspots -= src
- var/turf/open/T = loc
- if(istype(T) && T.active_hotspot == src)
- T.active_hotspot = null
- return ..()
-
-/obj/effect/hotspot/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
- SIGNAL_HANDLER
- if(isliving(arrived) && !cold_fire)
- var/mob/living/immolated = arrived
- immolated.fire_act(temperature, volume)
-
-/obj/effect/hotspot/singularity_pull()
- return
-
-/obj/effect/dummy/lighting_obj/moblight/fire
- name = "fire"
- light_color = LIGHT_COLOR_FIRE
- light_range = LIGHT_RANGE_FIRE
-
-#undef INSUFFICIENT
diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm
deleted file mode 100644
index 28743a43c47..00000000000
--- a/code/modules/atmospherics/environmental/LINDA_system.dm
+++ /dev/null
@@ -1,160 +0,0 @@
-/atom
- ///Check if atmos can pass in this atom (ATMOS_PASS_YES, ATMOS_PASS_NO, ATMOS_PASS_DENSITY, ATMOS_PASS_PROC)
- var/can_atmos_pass = ATMOS_PASS_YES
-
-/atom/proc/can_atmos_pass(turf/target_turf, vertical = FALSE)
- switch (can_atmos_pass)
- if (ATMOS_PASS_PROC)
- return ATMOS_PASS_YES
- if (ATMOS_PASS_DENSITY)
- return !density
- else
- return can_atmos_pass
-
-/turf
- can_atmos_pass = ATMOS_PASS_NO
-
-/turf/open
- can_atmos_pass = ATMOS_PASS_PROC
-
-///Do NOT use this to see if 2 turfs are connected, it mutates state, and we cache that info anyhow.
-///Use TURFS_CAN_SHARE or TURF_SHARES depending on your usecase
-/turf/open/can_atmos_pass(turf/target_turf, vertical = FALSE)
- var/can_pass = TRUE
- var/direction = vertical ? get_dir_multiz(src, target_turf) : get_dir(src, target_turf)
- var/opposite_direction = REVERSE_DIR(direction)
- if(vertical && !(zAirOut(direction, target_turf) && target_turf.zAirIn(direction, src)))
- can_pass = FALSE
- if(blocks_air || target_turf.blocks_air)
- can_pass = FALSE
- //This path is a bit weird, if we're just checking with ourselves no sense asking objects on the turf
- if (target_turf == src)
- return can_pass
-
- //Can't just return if canpass is false here, we need to set superconductivity
- for(var/obj/checked_object in contents + target_turf.contents)
- var/turf/other = (checked_object.loc == src ? target_turf : src)
- if(CANATMOSPASS(checked_object, other, vertical))
- continue
- can_pass = FALSE
- //the direction and open/closed are already checked on can_atmos_pass() so there are no arguments
- if(checked_object.block_superconductivity())
- atmos_supeconductivity |= direction
- target_turf.atmos_supeconductivity |= opposite_direction
- return FALSE //no need to keep going, we got all we asked (Is this even faster? fuck you it's soul)
-
- //Superconductivity is a bitfield of directions we can't conduct with
- //Yes this is really weird. Fuck you
- atmos_supeconductivity &= ~direction
- target_turf.atmos_supeconductivity &= ~opposite_direction
-
- return can_pass
-
-/atom/movable/proc/block_superconductivity() // objects that block air and don't let superconductivity act
- return FALSE
-
-/turf/proc/immediate_calculate_adjacent_turfs()
- //Basic optimization, if we can't share why bother asking other people ya feel?
- var/canpass = CANATMOSPASS(src, src, FALSE)
- for(var/direction in GLOB.cardinals_multiz)
- var/turf/current_turf = get_step_multiz(src, direction)
- if(!isopenturf(current_turf)) // not interested in you brother
- continue
- //Can you and me form a deeper relationship, or is this just a passing wind
- // (direction & (UP | DOWN)) is just "is this vertical" by the by
- if(canpass && CANATMOSPASS(current_turf, src, (direction & (UP|DOWN))) && !(blocks_air || current_turf.blocks_air))
- LAZYINITLIST(atmos_adjacent_turfs)
- LAZYINITLIST(current_turf.atmos_adjacent_turfs)
- atmos_adjacent_turfs[current_turf] = TRUE
- current_turf.atmos_adjacent_turfs[src] = TRUE
- else
- if (atmos_adjacent_turfs)
- atmos_adjacent_turfs -= current_turf
- if (current_turf.atmos_adjacent_turfs)
- current_turf.atmos_adjacent_turfs -= src
- UNSETEMPTY(current_turf.atmos_adjacent_turfs)
- UNSETEMPTY(atmos_adjacent_turfs)
- src.atmos_adjacent_turfs = atmos_adjacent_turfs
- SEND_SIGNAL(src, COMSIG_TURF_CALCULATED_ADJACENT_ATMOS)
-
-/**
- * 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/get_atmos_adjacent_turfs(alldir = 0)
- var/adjacent_turfs
- if (atmos_adjacent_turfs)
- adjacent_turfs = atmos_adjacent_turfs.Copy()
- else
- adjacent_turfs = list()
-
- if (!alldir)
- return adjacent_turfs
-
- var/turf/current_location = src
-
- for (var/direction in GLOB.diagonals_multiz)
- var/matching_directions = 0
- var/turf/checked_turf = get_step_multiz(current_location, direction)
- if(!checked_turf)
- continue
-
- for (var/check_direction in GLOB.cardinals_multiz)
- var/turf/secondary_turf = get_step(checked_turf, check_direction)
- if(!checked_turf.atmos_adjacent_turfs || !checked_turf.atmos_adjacent_turfs[secondary_turf])
- continue
-
- if (adjacent_turfs[secondary_turf])
- matching_directions++
-
- if (matching_directions >= 2)
- adjacent_turfs += checked_turf
- break
-
- return adjacent_turfs
-
-/atom/proc/air_update_turf(update = FALSE, remove = FALSE)
- var/turf/local_turf = get_turf(loc)
- if(!local_turf)
- return
- local_turf.air_update_turf(update, remove)
-
-/**
- * A helper proc for dealing with atmos changes
- *
- * Ok so this thing is pretty much used as a catch all for all the situations someone might wanna change something
- * About a turfs atmos. It's real clunky, and someone needs to clean it up, but not today.
- * Arguments:
- * * update - Has the state of the structures in the world changed? If so, update our adjacent atmos turf list, if not, don't.
- * * remove - Are you removing an active turf (Read wall), or adding one
-*/
-/turf/air_update_turf(update = FALSE, remove = FALSE)
- if(update)
- immediate_calculate_adjacent_turfs()
- if(remove)
- SSair.remove_from_active(src)
- else
- SSair.add_to_active(src)
-
-/atom/movable/proc/move_update_air(turf/target_turf)
- if(isturf(target_turf))
- target_turf.air_update_turf(TRUE, FALSE) //You're empty now
- air_update_turf(TRUE, TRUE) //You aren't
-
-/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires
- var/turf/open/local_turf = get_turf(src)
- if(!istype(local_turf))
- return
- local_turf.atmos_spawn_air(text)
-
-/turf/open/atmos_spawn_air(text)
- if(!text || !air)
- return
-
- var/datum/gas_mixture/turf_mixture = new
- turf_mixture.parse_gas_string(text)
-
- air.merge(turf_mixture)
- archive()
- SSair.add_to_active(src)
diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
deleted file mode 100644
index adc1573c64d..00000000000
--- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
+++ /dev/null
@@ -1,664 +0,0 @@
-/turf
- ///used for temperature calculations in superconduction
- var/thermal_conductivity = 0.05
- ///Amount of heat necessary to activate some atmos processes (there is a weird usage of this var because is compared directly to the temperature instead of heat energy)
- var/heat_capacity = INFINITY //This should be opt in rather then opt out
- ///Archived version of the temperature on a turf
- var/temperature_archived
- ///All currently stored conductivities changes
- var/list/thermal_conductivities
-
- ///list of turfs adjacent to us that air can flow onto
- var/list/atmos_adjacent_turfs
- ///bitfield of dirs in which we are superconducitng
- var/atmos_supeconductivity = NONE
-
- ///used to determine whether we should archive
- var/archived_cycle = 0
- var/current_cycle = 0
-
- /**
- * used for mapping and for breathing while in walls (because that's a thing that needs to be accounted for...)
- * string parsed by /datum/gas/proc/copy_from_turf
- * approximation of MOLES_O2STANDARD and MOLES_N2STANDARD pending byond allowing constant expressions to be embedded in constant strings
- * If someone will place 0 of some gas there, SHIT WILL BREAK. Do not do that.
- **/
- var/initial_gas_mix = OPENTURF_DEFAULT_ATMOS
-
-/turf/open
- //used for spacewind
- ///Pressure difference between two turfs
- var/pressure_difference = 0
- ///Where the difference come from (from higher pressure to lower pressure)
- var/pressure_direction = 0
-
- ///Excited group we are part of
- var/datum/excited_group/excited_group
- ///Are we active?
- var/excited = FALSE
- ///Our gas mix
- var/datum/gas_mixture/turf/air
-
- ///If there is an active hotspot on us store a reference to it here
- var/obj/effect/hotspot/active_hotspot
- /// air will slowly revert to initial_gas_mix
- var/planetary_atmos = FALSE
- /// once our paired turfs are finished with all other shares, do one 100% share
- /// exists so things like space can ask to take 100% of a tile's gas
- var/run_later = FALSE
-
- ///gas IDs of current active gas overlays
- var/list/atmos_overlay_types
- var/significant_share_ticker = 0
- #ifdef TRACK_MAX_SHARE
- var/max_share = 0
- #endif
-
-/turf/open/Initialize(mapload)
- if(!blocks_air)
- air = new
- air.copy_from_turf(src)
- if(planetary_atmos)
- if(!SSair.planetary[initial_gas_mix])
- var/datum/gas_mixture/immutable/planetary/mix = new
- mix.parse_string_immutable(initial_gas_mix)
- SSair.planetary[initial_gas_mix] = mix
- . = ..()
-
-/turf/open/Destroy()
- if(active_hotspot)
- QDEL_NULL(active_hotspot)
- // Adds the adjacent turfs to the current atmos processing
- for(var/near_turf in atmos_adjacent_turfs)
- SSair.add_to_active(near_turf)
- return ..()
-
-/////////////////GAS MIXTURE PROCS///////////////////
-
-/turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
- if(!giver)
- return FALSE
- air.merge(giver)
- update_visuals()
- air_update_turf(FALSE, FALSE)
- return TRUE
-
-/turf/open/remove_air(amount)
- var/datum/gas_mixture/ours = return_air()
- var/datum/gas_mixture/removed = ours.remove(amount)
- update_visuals()
- air_update_turf(FALSE, FALSE)
- return removed
-
-/turf/open/proc/copy_air_with_tile(turf/open/target_turf)
- if(istype(target_turf))
- air.copy_from(target_turf.air)
-
-/turf/open/proc/copy_air(datum/gas_mixture/copy)
- if(copy)
- air.copy_from(copy)
-
-/turf/return_air()
- RETURN_TYPE(/datum/gas_mixture)
- var/datum/gas_mixture/copied_mixture = new
- copied_mixture.copy_from_turf(src)
- return copied_mixture
-
-/turf/open/return_air()
- RETURN_TYPE(/datum/gas_mixture)
- return air
-
-/turf/open/return_analyzable_air()
- return return_air()
-
-/turf/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature >= heat_capacity || to_be_destroyed)
-
-/turf/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- if(exposed_temperature >= heat_capacity)
- to_be_destroyed = TRUE
- if(to_be_destroyed && exposed_temperature >= max_fire_temperature_sustained)
- max_fire_temperature_sustained = min(exposed_temperature, max_fire_temperature_sustained + heat_capacity / 4) //Ramp up to 100% yeah?
- if(to_be_destroyed && !changing_turf)
- burn()
-
-/turf/proc/burn()
- burn_tile()
- var/chance_of_deletion
- if (heat_capacity) //beware of division by zero
- chance_of_deletion = max_fire_temperature_sustained / heat_capacity * 8 //there is no problem with prob(23456), min() was redundant --rastaf0
- else
- chance_of_deletion = 100
- if(prob(chance_of_deletion))
- Melt()
- max_fire_temperature_sustained = 0
- else
- to_be_destroyed = FALSE
-
-/turf/open/burn()
- if(!active_hotspot) //Might not even be needed since excited groups are no longer cringe
- ..()
-
-/turf/temperature_expose(datum/gas_mixture/air, exposed_temperature)
- atmos_expose(air, exposed_temperature)
-
-/turf/open/temperature_expose(datum/gas_mixture/air, exposed_temperature)
- SEND_SIGNAL(src, COMSIG_TURF_EXPOSE, air, exposed_temperature)
- check_atmos_process(src, air, exposed_temperature) //Manually do this to avoid needing to use elements, don't want 200 second atom init times
-
-/turf/proc/archive()
- temperature_archived = temperature
-
-/turf/open/archive()
- LINDA_CYCLE_ARCHIVE(src)
-
-/////////////////////////GAS OVERLAYS//////////////////////////////
-
-
-/turf/open/proc/update_visuals()
- var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance
-
- if(!air) // 2019-05-14: was not able to get this path to fire in testing. Consider removing/looking at callers -Naksu
- if (atmos_overlay_types)
- for(var/overlay in atmos_overlay_types)
- vis_contents -= overlay
- src.atmos_overlay_types = null
- return
-
- var/list/gases = air.gases
-
- var/list/new_overlay_types
- GAS_OVERLAYS(gases, new_overlay_types)
-
- if (atmos_overlay_types)
- for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
- vis_contents -= overlay
-
- if (length(new_overlay_types))
- if (atmos_overlay_types)
- vis_contents += new_overlay_types - atmos_overlay_types //don't add overlays that already exist
- else
- vis_contents += new_overlay_types
-
- UNSETEMPTY(new_overlay_types)
- src.atmos_overlay_types = new_overlay_types
-
-/proc/typecache_of_gases_with_no_overlays()
- . = list()
- for (var/gastype in subtypesof(/datum/gas))
- var/datum/gas/gasvar = gastype
- if (!initial(gasvar.gas_overlay))
- .[gastype] = TRUE
-
-/////////////////////////////SIMULATION///////////////////////////////////
-#ifdef TRACK_MAX_SHARE
-#define LAST_SHARE_CHECK \
- var/last_share = our_air.last_share;\
- max_share = max(last_share, max_share);\
- if(last_share > MINIMUM_AIR_TO_SUSPEND){\
- our_excited_group.reset_cooldowns();\
- cached_ticker = 0;\
- enemy_tile.significant_share_ticker = 0;\
- } else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\
- our_excited_group.dismantle_cooldown = 0;\
- cached_ticker = 0;\
- enemy_tile.significant_share_ticker = 0;\
- }
-#else
-#define LAST_SHARE_CHECK \
- var/last_share = our_air.last_share;\
- if(last_share > MINIMUM_AIR_TO_SUSPEND){\
- our_excited_group.reset_cooldowns();\
- cached_ticker = 0;\
- enemy_tile.significant_share_ticker = 0;\
- } else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\
- our_excited_group.dismantle_cooldown = 0;\
- cached_ticker = 0;\
- enemy_tile.significant_share_ticker = 0;\
- }
-#endif
-#ifdef TRACK_MAX_SHARE
-#define PLANET_SHARE_CHECK \
- var/last_share = our_air.last_share;\
- max_share = max(last_share, max_share);\
- if(last_share > MINIMUM_AIR_TO_SUSPEND){\
- our_excited_group.reset_cooldowns();\
- cached_ticker = 0;\
- } else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\
- our_excited_group.dismantle_cooldown = 0;\
- cached_ticker = 0;\
- }
-#else
-#define PLANET_SHARE_CHECK \
- var/last_share = our_air.last_share;\
- if(last_share > MINIMUM_AIR_TO_SUSPEND){\
- our_excited_group.reset_cooldowns();\
- cached_ticker = 0;\
- } else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\
- our_excited_group.dismantle_cooldown = 0;\
- cached_ticker = 0;\
- }
-#endif
-
-/turf/proc/process_cell(fire_count)
- SSair.remove_from_active(src)
-
-/turf/open/process_cell(fire_count)
- if(archived_cycle < fire_count) //archive self if not already done
- LINDA_CYCLE_ARCHIVE(src)
-
- current_cycle = fire_count
- var/cached_ticker = significant_share_ticker
- cached_ticker += 1
-
- //cache for sanic speed
- var/list/adjacent_turfs = atmos_adjacent_turfs
- var/datum/excited_group/our_excited_group = excited_group
- var/our_share_coeff = 1/(LAZYLEN(adjacent_turfs) + 1)
-
- var/datum/gas_mixture/our_air = air
-
- var/list/share_end
-
- #ifdef TRACK_MAX_SHARE
- max_share = 0 //Gotta reset our tracker
- #endif
-
- for(var/turf/open/enemy_tile as anything in adjacent_turfs)
- // This var is only rarely set, exists so turfs can request to share at the end of our sharing
- // We need this so we can assume share is communative, which we need to do to avoid a hellish amount of garbage_collect()s
- if(enemy_tile.run_later)
- LAZYADD(share_end, enemy_tile)
-
- if(fire_count <= enemy_tile.current_cycle)
- continue
- LINDA_CYCLE_ARCHIVE(enemy_tile)
-
- /******************* GROUP HANDLING START *****************************************************************/
-
- var/should_share_air = FALSE
- var/datum/gas_mixture/enemy_air = enemy_tile.air
-
- //cache for sanic speed
- var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group
- //If we are both in an excited group, and they aren't the same, merge.
- //If we are both in an excited group, and you're active, share
- //If we pass compare, and if we're not already both in a group, lets join up
- //If we both pass compare, add to active and share
- if(our_excited_group && enemy_excited_group)
- if(our_excited_group != enemy_excited_group)
- //combine groups (this also handles updating the excited_group var of all involved turfs)
- our_excited_group.merge_groups(enemy_excited_group)
- our_excited_group = excited_group //update our cache
- if(our_excited_group && enemy_excited_group && enemy_tile.excited) //If you're both excited, no need to compare right?
- should_share_air = TRUE
- else if(our_air.compare(enemy_air)) //Lets see if you're up for it
- SSair.add_to_active(enemy_tile) //Add yourself young man
- var/datum/excited_group/existing_group = our_excited_group || enemy_excited_group || new
- if(!our_excited_group)
- existing_group.add_turf(src)
- if(!enemy_excited_group)
- existing_group.add_turf(enemy_tile)
- our_excited_group = excited_group
- should_share_air = TRUE
-
- //air sharing
- if(should_share_air)
- var/difference = our_air.share(enemy_air, our_share_coeff, 1 / (LAZYLEN(enemy_tile.atmos_adjacent_turfs) + 1))
- if(difference)
- if(difference > 0)
- consider_pressure_difference(enemy_tile, difference)
- else
- enemy_tile.consider_pressure_difference(src, -difference)
- //This acts effectivly as a very slow timer, the max deltas of the group will slowly lower until it breaksdown, they then pop up a bit, and fall back down until irrelevant
- LAST_SHARE_CHECK
-
-
- /******************* GROUP HANDLING FINISH *********************************************************************/
-
- if (planetary_atmos) //share our air with the "atmosphere" "above" the turf
- var/datum/gas_mixture/planetary_mix = SSair.planetary[initial_gas_mix]
- // archive ourself again so we don't accidentally share more gas than we currently have
- LINDA_CYCLE_ARCHIVE(src)
- if(our_air.compare(planetary_mix))
- if(!our_excited_group)
- var/datum/excited_group/new_group = new
- new_group.add_turf(src)
- our_excited_group = excited_group
- // shares 4/5 of our difference in moles with the atmosphere
- our_air.share(planetary_mix, 0.8, 0.8)
- // temperature share with the atmosphere with an inflated heat capacity to simulate faster sharing with a large atmosphere
- our_air.temperature_share(planetary_mix, OPEN_HEAT_TRANSFER_COEFFICIENT, planetary_mix.temperature_archived, planetary_mix.heat_capacity() * 5)
- planetary_mix.garbage_collect()
- PLANET_SHARE_CHECK
-
- for(var/turf/open/enemy_tile as anything in share_end)
- var/datum/gas_mixture/enemy_mix = enemy_tile.air
- archive()
- // We share 100% of our mix in this step. Let's jive
- var/difference = our_air.share(enemy_mix, 1, 1)
- LAST_SHARE_CHECK
- if(!difference)
- continue
- if(difference > 0)
- consider_pressure_difference(enemy_tile, difference)
- else
- enemy_tile.consider_pressure_difference(src, difference)
-
- our_air.react(src)
-
- update_visuals()
- if(!consider_superconductivity(starting = TRUE) && !active_hotspot) //Might need to include the return of react() here
- if(!our_excited_group) //If nothing of interest is happening, kill the active turf
- SSair.remove_from_active(src) //This will kill any connected excited group, be careful (This broke atmos for 4 years)
- if(cached_ticker > EXCITED_GROUP_DISMANTLE_CYCLES) //If you're stalling out, take a rest
- SSair.sleep_active_turf(src)
-
- significant_share_ticker = cached_ticker //Save our changes
- temperature_expose(our_air, our_air.temperature)
-
-//////////////////////////SPACEWIND/////////////////////////////
-
-/turf/open/proc/consider_pressure_difference(turf/target_turf, difference)
- SSair.high_pressure_delta |= src
- if(difference > pressure_difference)
- pressure_direction = get_dir(src, target_turf)
- pressure_difference = difference
-
-/turf/open/proc/high_pressure_movements()
- var/atom/movable/moving_atom
- for(var/thing in src)
- moving_atom = thing
- if (!moving_atom.anchored && !moving_atom.pulledby && moving_atom.last_high_pressure_movement_air_cycle < SSair.times_fired)
- moving_atom.experience_pressure_difference(pressure_difference, pressure_direction)
-
-/atom/movable
- ///How much delta pressure is needed for us to move
- var/pressure_resistance = 10
- var/last_high_pressure_movement_air_cycle = 0
-
-/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
- set waitfor = FALSE
- if(SEND_SIGNAL(src, COMSIG_ATOM_PRE_PRESSURE_PUSH) & COMSIG_ATOM_BLOCKS_PRESSURE)
- return
- var/const/PROBABILITY_OFFSET = 25
- var/const/PROBABILITY_BASE_PRECENT = 75
- var/max_force = sqrt(pressure_difference) * (MOVE_FORCE_DEFAULT / 5)
- 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) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO))))
- step(src, direction)
- last_high_pressure_movement_air_cycle = SSair.times_fired
-
-///////////////////////////EXCITED GROUPS/////////////////////////////
-
-/datum/excited_group
- ///Stores a reference to the turfs we are controlling
- var/list/turf_list = list()
- ///If this is over EXCITED_GROUP_BREAKDOWN_CYCLES we call self_breakdown()
- var/breakdown_cooldown = 0
- ///If this is over EXCITED_GROUP_DISMANTLE_CYCLES we call dismantle()
- var/dismantle_cooldown = 0
- ///Used for debug to show the excited groups active and their turfs
- var/should_display = FALSE
- ///Id of the index color of the displayed group
- var/display_id = 0
- ///Wrapping loop of the index colors
- var/static/wrapping_id = 0
-
-/datum/excited_group/New()
- SSair.excited_groups += src
-
-/datum/excited_group/proc/add_turf(turf/open/target_turf)
- turf_list += target_turf
- target_turf.excited_group = src
- dismantle_cooldown = 0
- if(should_display || SSair.display_all_groups)
- display_turf(target_turf)
-
-/datum/excited_group/proc/merge_groups(datum/excited_group/target_group)
- if(turf_list.len > target_group.turf_list.len)
- SSair.excited_groups -= target_group
- for(var/turf/open/group_member as anything in target_group.turf_list)
- group_member.excited_group = src
- turf_list += group_member
- should_display = target_group.should_display | should_display
- if(should_display || SSair.display_all_groups)
- target_group.hide_turfs()
- display_turfs()
- breakdown_cooldown = min(breakdown_cooldown, target_group.breakdown_cooldown) //Take the smaller of the two options
- dismantle_cooldown = 0
- else
- SSair.excited_groups -= src
- for(var/turf/open/group_member as anything in turf_list)
- group_member.excited_group = target_group
- target_group.turf_list += group_member
- target_group.should_display = target_group.should_display | should_display
- if(target_group.should_display || SSair.display_all_groups)
- hide_turfs()
- target_group.display_turfs()
- target_group.breakdown_cooldown = min(breakdown_cooldown, target_group.breakdown_cooldown)
- target_group.dismantle_cooldown = 0
-
-/datum/excited_group/proc/reset_cooldowns()
- breakdown_cooldown = 0
- dismantle_cooldown = 0
-
-/datum/excited_group/proc/self_breakdown(roundstart = FALSE, poke_turfs = FALSE)
- var/datum/gas_mixture/shared_mix = new
-
- //make local for sanic speed
- var/list/shared_gases = shared_mix.gases
- var/list/turf_list = src.turf_list
- var/turflen = turf_list.len
- var/imumutable_in_group = FALSE
- var/energy = 0
- var/heat_cap = 0
-
- for(var/turf/open/group_member as anything in turf_list)
- //Cache?
- var/datum/gas_mixture/turf/mix = group_member.air
- if (roundstart && istype(group_member.air, /datum/gas_mixture/immutable))
- imumutable_in_group = TRUE
- shared_mix.copy_from(group_member.air) //This had better be immutable young man
- shared_gases = shared_mix.gases //update the cache
- break
- //"borrowing" this code from merge(), I need to play with the temp portion. Lets expand it out
- //temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
- var/capacity = mix.heat_capacity()
- energy += mix.temperature * capacity
- heat_cap += capacity
-
- var/list/giver_gases = mix.gases
- for(var/giver_id in giver_gases)
- ASSERT_GAS(giver_id, shared_mix)
- shared_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
-
- if(!imumutable_in_group)
- shared_mix.temperature = energy / heat_cap
- for(var/id in shared_gases)
- shared_gases[id][MOLES] /= turflen
- shared_mix.garbage_collect()
-
- for(var/turf/open/group_member as anything in turf_list)
- if(group_member.planetary_atmos) //We do this as a hack to try and minimize unneeded excited group spread over planetary turfs
- group_member.air.copy_from(SSair.planetary[group_member.initial_gas_mix]) //Comes with a cost of "slower" drains, but it's worth it
- else
- group_member.air.copy_from(shared_mix) //Otherwise just set the mix to a copy of our equalized mix
- group_member.update_visuals()
- if(poke_turfs) //Because we only activate all these once every breakdown, in event of lag due to this code and slow space + vent things, increase the wait time for breakdowns
- SSair.add_to_active(group_member)
- group_member.significant_share_ticker = EXCITED_GROUP_DISMANTLE_CYCLES //Max out the ticker, if they don't share next tick, nuke em
-
- breakdown_cooldown = 0
-
-///Dismantles the excited group, puts allll the turfs to sleep
-/datum/excited_group/proc/dismantle()
- for(var/turf/open/current_turf as anything in turf_list)
- current_turf.excited = FALSE
- current_turf.significant_share_ticker = 0
- SSair.active_turfs -= current_turf
- #ifdef VISUALIZE_ACTIVE_TURFS //Use this when you want details about how the turfs are moving, display_all_groups should work for normal operation
- current_turf.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, COLOR_VIBRANT_LIME)
- #endif
- garbage_collect()
-
-//Breaks down the excited group, this doesn't sleep the turfs mind, just removes them from the group
-/datum/excited_group/proc/garbage_collect()
- if(display_id) //If we ever did make those changes
- hide_turfs()
- for(var/turf/open/current_turf as anything in turf_list)
- current_turf.excited_group = null
- turf_list.Cut()
- SSair.excited_groups -= src
- if(SSair.currentpart == SSAIR_EXCITEDGROUPS)
- SSair.currentrun -= src
-
-/datum/excited_group/proc/display_turfs()
- if(display_id == 0) //Hasn't been shown before
- wrapping_id = wrapping_id % GLOB.colored_turfs.len
- wrapping_id++ //We do this after because lists index at 1
- display_id = wrapping_id
- for(var/thing in turf_list)
- var/turf/display = thing
- display.vis_contents += GLOB.colored_turfs[display_id]
-
-/datum/excited_group/proc/hide_turfs()
- for(var/thing in turf_list)
- var/turf/display = thing
- display.vis_contents -= GLOB.colored_turfs[display_id]
- display_id = 0
-
-/datum/excited_group/proc/display_turf(turf/thing)
- if(display_id == 0) //Hasn't been shown before
- wrapping_id = wrapping_id % GLOB.colored_turfs.len
- wrapping_id++ //We do this after because lists index at 1
- display_id = wrapping_id
- thing.vis_contents += GLOB.colored_turfs[display_id]
-
-////////////////////////SUPERCONDUCTIVITY/////////////////////////////
-
-/**
-ALLLLLLLLLLLLLLLLLLLLRIGHT HERE WE GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
-
-Read the code for more details, but first, a brief concept discussion/area
-
-Our goal here is to "model" heat moving through solid objects, so walls, windows, and sometimes doors.
-We do this by heating up the floor itself with the heat of the gasmix ontop of it, this is what the coeffs are for here, they slow that movement
-Then we go through the process below.
-
-If an active turf is fitting, we add it to processing, conduct with any covered tiles, (read windows and sometimes walls)
-Then we space some of our heat, and think about if we should stop conducting.
-**/
-
-/turf/proc/conductivity_directions()
- if(archived_cycle < SSair.times_fired)
- archive()
- return ALL_CARDINALS
-
-///Returns a set of directions that we should be conducting in, NOTE, atmos_supeconductivity is ACTUALLY inversed, don't worrry about it
-/turf/open/conductivity_directions()
- if(blocks_air)
- return ..()
- for(var/direction in GLOB.cardinals)
- var/turf/checked_turf = get_step(src, direction)
- if(!(checked_turf in atmos_adjacent_turfs) && !(atmos_supeconductivity & direction))
- . |= direction
-
-///These two procs are a bit of a web, I belive in you
-/turf/proc/neighbor_conduct_with_src(turf/open/other)
- if(!other.blocks_air) //Solid but neighbor is open
- other.temperature_share_open_to_solid(src)
- else //Both tiles are solid
- other.share_temperature_mutual_solid(src, thermal_conductivity)
- temperature_expose(null, temperature)
-
-/turf/open/neighbor_conduct_with_src(turf/other)
- if(blocks_air)
- return ..()
-
- if(!other.blocks_air) //Both tiles are open
- var/turf/open/open_other = other
- open_other.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
- else //Open but neighbor is solid
- temperature_share_open_to_solid(other)
- SSair.add_to_active(src)
-
-/turf/proc/super_conduct()
- var/conductivity_directions = conductivity_directions()
-
- if(conductivity_directions)
- //Conduct with tiles around me
- for(var/direction in GLOB.cardinals)
- if(!(conductivity_directions & direction))
- continue
- var/turf/neighbor = get_step(src, direction)
-
- if(!neighbor.thermal_conductivity)
- continue
-
- if(neighbor.archived_cycle < SSair.times_fired)
- neighbor.archive()
-
- neighbor.neighbor_conduct_with_src(src)
-
- neighbor.consider_superconductivity()
-
- radiate_to_spess()
-
- finish_superconduction()
-
-/turf/proc/finish_superconduction(temp = temperature)
- //Make sure still hot enough to continue conducting heat
- if(temp < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)
- SSair.active_super_conductivity -= src
- return FALSE
-
-/turf/open/finish_superconduction()
- //Conduct with air on my tile if I have it
- if(!blocks_air)
- temperature = air.temperature_share(null, thermal_conductivity, temperature, heat_capacity)
- ..((blocks_air ? temperature : air.temperature))
-
-///Should we attempt to superconduct?
-/turf/proc/consider_superconductivity(starting)
- if(!thermal_conductivity)
- return FALSE
-
- SSair.active_super_conductivity |= src
- return TRUE
-
-/turf/open/consider_superconductivity(starting)
- if(air.temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
- return FALSE
- if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant.
- return FALSE
- return ..()
-
-/turf/closed/consider_superconductivity(starting)
- if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
- return FALSE
- return ..()
-
-/turf/proc/radiate_to_spess() //Radiate excess tile heat to space
- if(temperature <= T0C) //Considering 0 degC as te break even point for radiation in and out
- return
- var/delta_temperature = (temperature_archived - TCMB) //hardcoded space temperature
- if(heat_capacity <= 0 || abs(delta_temperature) <= MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- return
- var/heat = thermal_conductivity * delta_temperature * \
- (heat_capacity * HEAT_CAPACITY_VACUUM / (heat_capacity + HEAT_CAPACITY_VACUUM))
- temperature -= heat/heat_capacity
-
-/turf/open/proc/temperature_share_open_to_solid(turf/sharer)
- sharer.temperature = air.temperature_share(null, sharer.thermal_conductivity, sharer.temperature, sharer.heat_capacity)
-
-/turf/proc/share_temperature_mutual_solid(turf/sharer, conduction_coefficient) //This is all just heat sharing, don't get freaked out
- var/delta_temperature = (temperature_archived - sharer.temperature_archived)
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER && heat_capacity && sharer.heat_capacity)
- var/heat = conduction_coefficient * delta_temperature * \
- (heat_capacity * sharer.heat_capacity / (heat_capacity + sharer.heat_capacity)) //The larger the combined capacity the less is shared
- temperature -= heat / heat_capacity //The higher your own heat cap the less heat you get from this arrangement
- sharer.temperature += heat / sharer.heat_capacity
diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm
deleted file mode 100644
index c7d96d7c721..00000000000
--- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
-What are the archived variables for?
-Calculations are done using the archived variables with the results merged into the regular variables.
-This prevents race conditions that arise based on the order of tile processing.
-*/
-
-#define QUANTIZE(variable) (round((variable), (MOLAR_ACCURACY)))
-GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
-GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
-
-/proc/init_gaslist_cache()
- var/list/gases = list()
- for(var/id in GLOB.meta_gas_info)
- var/list/cached_gas = new(3)
-
- gases[id] = cached_gas
-
- cached_gas[MOLES] = 0
- cached_gas[ARCHIVE] = 0
- cached_gas[GAS_META] = GLOB.meta_gas_info[id]
- return gases
-
-/datum/gas_mixture
- var/list/gases
- var/temperature = 0 //kelvins
- var/tmp/temperature_archived = 0
- var/volume = CELL_VOLUME //liters
- var/last_share = 0
- /// Tells us what reactions have happened in our gasmix. Assoc list of reaction - moles reacted pair.
- var/list/reaction_results
- /// Whether to call garbage_collect() on the sharer during shares, used for immutable mixtures
- var/gc_share = FALSE
-
-/datum/gas_mixture/New(volume)
- gases = new
- if (!isnull(volume))
- src.volume = volume
- reaction_results = new
-
-//listmos procs
-//use the macros in performance intensive areas. for their definitions, refer to code/__DEFINES/atmospherics.dm
-
-///assert_gas(gas_id) - used to guarantee that the gas list for this id exists in gas_mixture.gases.
-///Must be used before adding to a gas. May be used before reading from a gas.
-/datum/gas_mixture/proc/assert_gas(gas_id)
- ASSERT_GAS(gas_id, src)
-
-///assert_gases(args) - shorthand for calling ASSERT_GAS() once for each gas type.
-/datum/gas_mixture/proc/assert_gases(...)
- for(var/id in args)
- ASSERT_GAS(id, src)
-
-///add_gas(gas_id) - similar to assert_gas(), but does not check for an existing gas list for this id. This can clobber existing gases.
-///Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
-/datum/gas_mixture/proc/add_gas(gas_id)
- ADD_GAS(gas_id, gases)
-
-///add_gases(args) - shorthand for calling add_gas() once for each gas_type.
-/datum/gas_mixture/proc/add_gases(...)
- var/cached_gases = gases
- for(var/id in args)
- ADD_GAS(id, cached_gases)
-
-///garbage_collect() - removes any gas list which is empty.
-///If called with a list as an argument, only removes gas lists with IDs from that list.
-///Must be used after subtracting from a gas. Must be used after assert_gas()
-///if assert_gas() was called only to read from the gas.
-///By removing empty gases, processing speed is increased.
-/datum/gas_mixture/proc/garbage_collect(list/tocheck)
- var/list/cached_gases = gases
- for(var/id in (tocheck || cached_gases))
- if(QUANTIZE(cached_gases[id][MOLES]) <= 0)
- cached_gases -= id
-
-//PV = nRT
-
-///joules per kelvin
-/datum/gas_mixture/proc/heat_capacity(data = MOLES)
- var/list/cached_gases = gases
- . = 0
- for(var/id in cached_gases)
- var/gas_data = cached_gases[id]
- . += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
-
-/// Same as above except vacuums return HEAT_CAPACITY_VACUUM
-/datum/gas_mixture/turf/heat_capacity(data = MOLES)
- var/list/cached_gases = gases
- . = 0
- for(var/id in cached_gases)
- var/gas_data = cached_gases[id]
- . += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
- if(!.)
- . += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space
-
-/// Calculate moles
-/datum/gas_mixture/proc/total_moles()
- var/cached_gases = gases
- TOTAL_MOLES(cached_gases, .)
-
-/// Checks to see if gas amount exists in mixture.
-/// Do NOT use this in code where performance matters!
-/// It's better to batch calls to garbage_collect(), especially in places where you're checking many gastypes
-/datum/gas_mixture/proc/has_gas(gas_id, amount=0)
- ASSERT_GAS(gas_id, src)
- var/is_there_gas = amount < gases[gas_id][MOLES]
- garbage_collect()
- return is_there_gas
-
-/// Calculate pressure in kilopascals
-/datum/gas_mixture/proc/return_pressure()
- if(volume) // to prevent division by zero
- var/cached_gases = gases
- TOTAL_MOLES(cached_gases, .)
- . *= R_IDEAL_GAS_EQUATION * temperature / volume
- return
- return 0
-
-/// Calculate temperature in kelvins
-/datum/gas_mixture/proc/return_temperature()
- return temperature
-
-/// Calculate volume in liters
-/datum/gas_mixture/proc/return_volume()
- return max(0, volume)
-
-/// Gets the gas visuals for everything in this mixture
-/datum/gas_mixture/proc/return_visuals()
- var/list/output
- GAS_OVERLAYS(gases, output)
- return output
-
-/// Calculate thermal energy in joules
-/datum/gas_mixture/proc/thermal_energy()
- return THERMAL_ENERGY(src) //see code/__DEFINES/atmospherics.dm; use the define in performance critical areas
-
-///Update archived versions of variables. Returns: 1 in all cases
-/datum/gas_mixture/proc/archive()
- var/list/cached_gases = gases
-
- temperature_archived = temperature
- for(var/id in cached_gases)
- cached_gases[id][ARCHIVE] = cached_gases[id][MOLES]
-
- return TRUE
-
-///Merges all air from giver into self. Deletes giver. Returns: 1 if we are mutable, 0 otherwise
-/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
- if(!giver)
- return FALSE
-
- //heat transfer
- if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity()
- var/giver_heat_capacity = giver.heat_capacity()
- var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
- if(combined_heat_capacity)
- temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
-
- var/list/cached_gases = gases //accessing datum vars is slower than proc vars
- var/list/giver_gases = giver.gases
- //gas transfer
- for(var/giver_id in giver_gases)
- ASSERT_GAS(giver_id, src)
- cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
-
- SEND_SIGNAL(src, COMSIG_GASMIX_MERGED)
- return TRUE
-
-///Proportionally removes amount of gas from the gas_mixture.
-///Returns: gas_mixture with the gases removed
-/datum/gas_mixture/proc/remove(amount)
- var/sum
- var/list/cached_gases = gases
- TOTAL_MOLES(cached_gases, sum)
- amount = min(amount, sum) //Can not take more air than tile has!
- if(amount <= 0)
- return null
- var/ratio = amount / sum
- var/datum/gas_mixture/removed = new type
- var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
-
- removed.temperature = temperature
- for(var/id in cached_gases)
- ADD_GAS(id, removed.gases)
- removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
- cached_gases[id][MOLES] -= removed_gases[id][MOLES]
- garbage_collect()
-
- SEND_SIGNAL(src, COMSIG_GASMIX_REMOVED)
- return removed
-
-///Proportionally removes amount of gas from the gas_mixture.
-///Returns: gas_mixture with the gases removed
-/datum/gas_mixture/proc/remove_ratio(ratio)
- if(ratio <= 0)
- var/datum/gas_mixture/removed = new(volume)
- return removed
- ratio = min(ratio, 1)
-
- var/list/cached_gases = gases
- var/datum/gas_mixture/removed = new type
- var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
-
- removed.temperature = temperature
- for(var/id in cached_gases)
- ADD_GAS(id, removed.gases)
- removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
- cached_gases[id][MOLES] -= removed_gases[id][MOLES]
-
- garbage_collect()
-
- SEND_SIGNAL(src, COMSIG_GASMIX_REMOVED)
- return removed
-
-///Removes an amount of a specific gas from the gas_mixture.
-///Returns: gas_mixture with the gas removed
-/datum/gas_mixture/proc/remove_specific(gas_id, amount)
- var/list/cached_gases = gases
- amount = min(amount, cached_gases[gas_id][MOLES])
- if(amount <= 0)
- return null
- var/datum/gas_mixture/removed = new type
- var/list/removed_gases = removed.gases
- removed.temperature = temperature
- ADD_GAS(gas_id, removed.gases)
- removed_gases[gas_id][MOLES] = amount
- cached_gases[gas_id][MOLES] -= amount
-
- garbage_collect(list(gas_id))
- return removed
-
-/datum/gas_mixture/proc/remove_specific_ratio(gas_id, ratio)
- if(ratio <= 0)
- return null
- ratio = min(ratio, 1)
-
- var/list/cached_gases = gases
- var/datum/gas_mixture/removed = new type
- var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
-
- removed.temperature = temperature
- ADD_GAS(gas_id, removed.gases)
- removed_gases[gas_id][MOLES] = QUANTIZE(cached_gases[gas_id][MOLES] * ratio)
- cached_gases[gas_id][MOLES] -= removed_gases[gas_id][MOLES]
-
- garbage_collect(list(gas_id))
-
- return removed
-
-///Distributes the contents of two mixes equally between themselves
-//Returns: bool indicating whether gases moved between the two mixes
-/datum/gas_mixture/proc/equalize(datum/gas_mixture/other)
- . = FALSE
- if(abs(return_temperature() - other.return_temperature()) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
- . = TRUE
- var/self_heat_cap = heat_capacity()
- var/other_heat_cap = other.heat_capacity()
- var/new_temp = (temperature * self_heat_cap + other.temperature * other_heat_cap) / (self_heat_cap + other_heat_cap)
- temperature = new_temp
- other.temperature = new_temp
-
- var/min_p_delta = 0.1
- var/total_volume = volume + other.volume
- var/list/gas_list = gases | other.gases
- for(var/gas_id in gas_list)
- assert_gas(gas_id)
- other.assert_gas(gas_id)
- //math is under the assumption temperatures are equal
- if(abs(gases[gas_id][MOLES] / volume - other.gases[gas_id][MOLES] / other.volume) > min_p_delta / (R_IDEAL_GAS_EQUATION * temperature))
- . = TRUE
- var/total_moles = gases[gas_id][MOLES] + other.gases[gas_id][MOLES]
- gases[gas_id][MOLES] = total_moles * (volume/total_volume)
- other.gases[gas_id][MOLES] = total_moles * (other.volume/total_volume)
- garbage_collect()
- other.garbage_collect()
-
-///Creates new, identical gas mixture
-///Returns: duplicate gas mixture
-/datum/gas_mixture/proc/copy()
- var/list/cached_gases = gases
- var/datum/gas_mixture/copy = new type
- var/list/copy_gases = copy.gases
-
- copy.temperature = temperature
- for(var/id in cached_gases)
- ADD_GAS(id, copy.gases)
- copy_gases[id][MOLES] = cached_gases[id][MOLES]
-
- return copy
-
-///Copies variables from sample, moles multiplicated by partial
-///Returns: 1 if we are mutable, 0 otherwise
-/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample, partial = 1)
- var/list/cached_gases = gases //accessing datum vars is slower than proc vars
- var/list/sample_gases = sample.gases
-
- //remove all gases not in the sample
- cached_gases &= sample_gases
-
- temperature = sample.temperature
- for(var/id in sample_gases)
- ASSERT_GAS(id,src)
- cached_gases[id][MOLES] = sample_gases[id][MOLES] * partial
-
- return 1
-
-///Copies all gas info from the turf into the gas list along with temperature
-///Returns: TRUE if we are mutable, FALSE otherwise
-/datum/gas_mixture/proc/copy_from_turf(turf/model)
- parse_gas_string(model.initial_gas_mix)
-
- //acounts for changes in temperature
- var/turf/model_parent = model.parent_type
- if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
- temperature = model.temperature
-
- return TRUE
-
-///Copies variables from a particularly formatted string.
-///Returns: 1 if we are mutable, 0 otherwise
-/datum/gas_mixture/proc/parse_gas_string(gas_string)
- gas_string = SSair.preprocess_gas_string(gas_string)
-
- var/list/gases = src.gases
- var/list/gas = params2list(gas_string)
- if(gas["TEMP"])
- temperature = text2num(gas["TEMP"])
- temperature_archived = temperature
- gas -= "TEMP"
- else // if we do not have a temp in the new gas mix lets assume room temp.
- temperature = T20C
- gases.Cut()
- for(var/id in gas)
- var/path = id
- if(!ispath(path))
- path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around
- ADD_GAS(path, gases)
- gases[path][MOLES] = text2num(gas[id])
- return 1
-
-/// Performs air sharing calculations between two gas_mixtures
-/// share() is communitive, which means A.share(B) needs to be the same as B.share(A)
-/// If we don't retain this, we will get negative moles. Don't do it
-/// Returns: amount of gas exchanged (+ if sharer received)
-/datum/gas_mixture/proc/share(datum/gas_mixture/sharer, our_coeff, sharer_coeff)
- var/list/cached_gases = gases
- var/list/sharer_gases = sharer.gases
-
- var/list/only_in_sharer = sharer_gases - cached_gases
- var/list/only_in_cached = cached_gases - sharer_gases
-
- var/temperature_delta = temperature_archived - sharer.temperature_archived
- var/abs_temperature_delta = abs(temperature_delta)
-
- var/old_self_heat_capacity = 0
- var/old_sharer_heat_capacity = 0
- if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- old_self_heat_capacity = heat_capacity()
- old_sharer_heat_capacity = sharer.heat_capacity()
-
- var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
- var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
-
- var/moved_moles = 0
- var/abs_moved_moles = 0
-
- //GAS TRANSFER
-
- //Prep
- for(var/id in only_in_sharer) //create gases not in our cache
- ADD_GAS(id, cached_gases)
- for(var/id in only_in_cached) //create gases not in the sharing mix
- ADD_GAS(id, sharer_gases)
-
- for(var/id in cached_gases) //transfer gases
- var/gas = cached_gases[id]
- var/sharergas = sharer_gases[id]
- var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE]) //the amount of gas that gets moved between the mixtures
-
- if(!delta)
- continue
-
- // If we have more gas then they do, gas is moving from us to them
- // This means we want to scale it by our coeff. Vis versa for their case
- if(delta > 0)
- delta = delta * our_coeff
- else
- delta = delta * sharer_coeff
-
- if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/gas_heat_capacity = delta * gas[GAS_META][META_GAS_SPECIFIC_HEAT]
- if(delta > 0)
- heat_capacity_self_to_sharer += gas_heat_capacity
- else
- heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative.
-
- gas[MOLES] -= delta
- sharergas[MOLES] += delta
- moved_moles += delta
- abs_moved_moles += abs(delta)
-
- last_share = abs_moved_moles
-
- //THERMAL ENERGY TRANSFER
- if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
- var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
-
- //transfer of thermal energy (via changed heat capacity) between self and sharer
- if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
- temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
-
- if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
- sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
- //thermal energy of the system (self and sharer) is unchanged
-
- if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
- if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity
- temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
-
- if(length(only_in_sharer + only_in_cached)) //if all gases were present in both mixtures, we know that no gases are 0
- garbage_collect(only_in_cached) //any gases the sharer had, we are guaranteed to have. gases that it didn't have we are not.
- sharer.garbage_collect(only_in_sharer) //the reverse is equally true
- else if (initial(sharer.gc_share))
- sharer.garbage_collect()
-
- if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
- var/our_moles
- TOTAL_MOLES(cached_gases,our_moles)
- var/their_moles
- TOTAL_MOLES(sharer_gases,their_moles)
- return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume
-
-///Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length
-///Returns: new temperature of the sharer
-/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
- //transfer of thermal energy (via conduction) between self and sharer
- if(sharer)
- sharer_temperature = sharer.temperature_archived
- var/temperature_delta = temperature_archived - sharer_temperature
- if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity(ARCHIVE)
- sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity(ARCHIVE)
-
- if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*temperature_delta* \
- (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
-
- temperature = max(temperature - heat/self_heat_capacity, TCMB)
- sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB)
- if(sharer)
- sharer.temperature = sharer_temperature
- if (initial(sharer.gc_share))
- sharer.garbage_collect()
- return sharer_temperature
- //thermal energy of the system (self and sharer) is unchanged
-
-///Compares sample to self to see if within acceptable ranges that group processing may be enabled
-///Returns: a string indicating what check failed, or "" if check passes
-/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
- var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
- var/list/cached_gases = gases
-
- for(var/id in cached_gases | sample_gases) // compare gases from either mixture
- var/gas_moles = cached_gases[id]
- gas_moles = gas_moles ? gas_moles[MOLES] : 0
- var/sample_moles = sample_gases[id]
- sample_moles = sample_moles ? sample_moles[MOLES] : 0
- var/delta = abs(gas_moles - sample_moles)
- if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \
- delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)
- return id
-
- var/our_moles
- TOTAL_MOLES(cached_gases, our_moles)
- if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE) //Don't consider temp if there's not enough mols
- var/temp = temperature
- var/sample_temp = sample.temperature
-
- var/temperature_delta = abs(temp - sample_temp)
- if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
- return "temp"
-
- return ""
-
-///Performs various reactions such as combustion and fabrication
-///Returns: 1 if any reaction took place; 0 otherwise
-/datum/gas_mixture/proc/react(datum/holder)
- . = NO_REACTION
- var/list/cached_gases = gases
- if(!length(cached_gases))
- return
-
- var/list/pre_formation = list()
- var/list/mid_formation = list()
- var/list/post_formation = list()
- var/list/fires = list()
- var/list/gas_reactions = SSair.gas_reactions
- for(var/gas_id in cached_gases)
- var/list/reaction_set = gas_reactions[gas_id]
- if(!reaction_set)
- continue
- pre_formation += reaction_set[1]
- mid_formation += reaction_set[2]
- post_formation += reaction_set[3]
- fires += reaction_set[4]
-
- var/list/reactions = pre_formation + mid_formation + post_formation + fires
-
- if(!length(reactions))
- return
-
- //Fuck you
- if(cached_gases[/datum/gas/hypernoblium] && cached_gases[/datum/gas/hypernoblium][MOLES] >= REACTION_OPPRESSION_THRESHOLD && temperature > 20)
- return STOP_REACTIONS
-
- reaction_results = new
- //It might be worth looking into updating these after each reaction, but that makes us care more about order of operations, so be careful
- var/temp = temperature
- reaction_loop:
- for(var/datum/gas_reaction/reaction as anything in reactions)
-
- var/list/reqs = reaction.requirements
- if((reqs["MIN_TEMP"] && temp < reqs["MIN_TEMP"]) || (reqs["MAX_TEMP"] && temp > reqs["MAX_TEMP"]))
- continue
-
- for(var/id in reqs)
- if (id == "MIN_TEMP" || id == "MAX_TEMP")
- continue
- if(!cached_gases[id] || cached_gases[id][MOLES] < reqs[id])
- continue reaction_loop
-
- //at this point, all requirements for the reaction are satisfied. we can now react()
- . |= reaction.react(src, holder)
-
-
- if(.) //If we changed the mix to any degree
- garbage_collect()
- SEND_SIGNAL(src, COMSIG_GASMIX_REACTED)
-
-
-/**
- * Takes the amount of the gas you want to PP as an argument
- * So I don't have to do some hacky switches/defines/magic strings
- * eg:
- * Plas_PP = get_partial_pressure(gas_mixture.plasma)
- * O2_PP = get_partial_pressure(gas_mixture.oxygen)
- * get_breath_partial_pressure(gas_pp) --> gas_pp/total_moles()*breath_pp = pp
- * get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
- *
- * 10/20*5 = 2.5
- * 10 = 2.5/5*20
- */
-
-/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
- return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
-///inverse
-/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure)
- return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
-
-/**
- * Counts how much pressure will there be if we impart MOLAR_ACCURACY amounts of our gas to the output gasmix.
- * We do all of this without actually transferring it so dont worry about it changing the gasmix.
- * Returns: Resulting pressure (number).
- * Args:
- * - output_air (gasmix).
- */
-/datum/gas_mixture/proc/gas_pressure_minimum_transfer(datum/gas_mixture/output_air)
- var/resulting_energy = output_air.thermal_energy() + (MOLAR_ACCURACY / total_moles() * thermal_energy())
- var/resulting_capacity = output_air.heat_capacity() + (MOLAR_ACCURACY / total_moles() * heat_capacity())
- return (output_air.total_moles() + MOLAR_ACCURACY) * R_IDEAL_GAS_EQUATION * (resulting_energy / resulting_capacity) / output_air.volume
-
-
-/** Returns the amount of gas to be pumped to a specific container.
- * Args:
- * - output_air. The gas mix we want to pump to.
- * - target_pressure. The target pressure we want.
- * - ignore_temperature. Returns a cheaper form of gas calculation, useful if the temperature difference between the two gasmixes is low or nonexistant.
- */
-/datum/gas_mixture/proc/gas_pressure_calculate(datum/gas_mixture/output_air, target_pressure, ignore_temperature = FALSE)
- if((total_moles() <= 0) || (temperature <= 0))
- return FALSE
-
- var/pressure_delta = 0
- if((output_air.temperature <= 0) || (output_air.total_moles() <= 0))
- ignore_temperature = TRUE
- pressure_delta = target_pressure
- else
- pressure_delta = target_pressure - output_air.return_pressure()
-
- if(pressure_delta < 0.01 || gas_pressure_minimum_transfer(output_air) > target_pressure)
- return FALSE
-
- if(ignore_temperature)
- return (pressure_delta*output_air.volume)/(temperature * R_IDEAL_GAS_EQUATION)
-
- // Lower and upper bound for the moles we must transfer to reach the pressure. The answer is bound to be here somewhere.
- var/pv = target_pressure * output_air.volume
- var/rt_low = R_IDEAL_GAS_EQUATION * max(temperature, output_air.temperature) // Low refers to the resulting mole, this number is actually higher.
- var/rt_high = R_IDEAL_GAS_EQUATION * min(temperature, output_air.temperature)
- // These works by assuming our gas has extremely high heat capacity
- // and the resultant gasmix will hit either the highest or lowest temperature possible.
- var/lower_limit = max((pv / rt_low) - output_air.total_moles(), 0)
- var/upper_limit = (pv / rt_high) - output_air.total_moles() // In theory this should never go below zero, the pressure_delta check above should account for this.
-
- /*
- * We have PV=nRT as a nice formula, we can rearrange it into nT = PV/R
- * But now both n and T can change, since any incoming moles also change our temperature.
- * So we need to unify both our n and T, somehow.
- *
- * We can rewrite T as (our old thermal energy + incoming thermal energy) divided by (our old heat capacity + incoming heat capacity)
- * T = (W1 + n/N2 * W2) / (C1 + n/N2 * C2). C being heat capacity, W being work, N being total moles.
- *
- * In total we now have our equation be: (N1 + n) * (W1 + n/N2 * W2) / (C1 + n/N2 * C2) = PV/R
- * Now you can rearrange this and find out that it's a quadratic equation and pretty much solvable with the formula. Will be a bit messy though.
- *
- * W2/N2n^2 +
- * (N1*W2/N2)n + W1n - ((PV/R)*C2/N2)n +
- * (-(PV/R)*C1) + N1W1 = 0
- *
- * We will represent each of these terms with A, B, and C. A for the n^2 part, B for the n^1 part, and C for the n^0 part.
- * We then put this into the famous (-b +/- sqrt(b^2-4ac)) / 2a formula.
- *
- * Oh, and one more thing. By "our" we mean the gasmix in the argument. We are the incoming one here. We are number 2, target is number 1.
- * If all this counting fucks up, we revert first to Newton's approximation, then the old simple formula.
- */
-
- // Our thermal energy and moles
- var/w2 = thermal_energy()
- var/n2 = total_moles()
- var/c2 = heat_capacity()
-
- // Target thermal energy and moles
- var/w1 = output_air.thermal_energy()
- var/n1 = output_air.total_moles()
- var/c1 = output_air.heat_capacity()
-
- /// The PV/R part in our equation.
- var/pvr = pv / R_IDEAL_GAS_EQUATION
-
- /// x^2 in the quadratic
- var/a_value = w2/n2
- /// x^1 in the quadratic
- var/b_value = ((n1*w2)/n2) + w1 - (pvr*c2/n2)
- /// x^0 in the quadratic
- var/c_value = (-1*pvr*c1) + n1 * w1
-
- . = gas_pressure_quadratic(a_value, b_value, c_value, lower_limit, upper_limit)
- if(.)
- return
- . = gas_pressure_approximate(a_value, b_value, c_value, lower_limit, upper_limit)
- if(.)
- return
- // Inaccurate and will probably explode but whatever.
- return (pressure_delta*output_air.volume)/(temperature * R_IDEAL_GAS_EQUATION)
-
-/// Actually tries to solve the quadratic equation.
-/// Do mind that the numbers can get very big and might hit BYOND's single point float limit.
-/datum/gas_mixture/proc/gas_pressure_quadratic(a, b, c, lower_limit, upper_limit)
- var/solution
- if(!IS_INF_OR_NAN(a) && !IS_INF_OR_NAN(b) && !IS_INF_OR_NAN(c))
- solution = max(SolveQuadratic(a, b, c))
- if((solution > lower_limit) && (solution < upper_limit)) //SolveQuadratic can return nulls so be careful here
- return solution
- stack_trace("Failed to solve pressure quadratic equation. A: [a]. B: [b]. C:[c]. Current value = [solution]. Expected lower limit: [lower_limit]. Expected upper limit: [upper_limit].")
- return FALSE
-
-/// Approximation of the quadratic equation using Newton-Raphson's Method.
-/// We use the slope of an approximate value to get closer to the root of a given equation.
-/datum/gas_mixture/proc/gas_pressure_approximate(a, b, c, lower_limit, upper_limit)
- var/solution
- if(!IS_INF_OR_NAN(a) && !IS_INF_OR_NAN(b) && !IS_INF_OR_NAN(c))
- /// We need to start off at a reasonably good estimate. For very big numbers the amount of moles is most likely small so better start with lower_limit.
- solution = lower_limit
- for (var/iteration in 1 to ATMOS_PRESSURE_APPROXIMATION_ITERATIONS)
- var/diff = (a*solution**2 + b*solution + c) / (2*a*solution + b) // f(sol) / f'(sol)
- solution -= diff // xn+1 = xn - f(sol) / f'(sol)
- if(abs(diff) < MOLAR_ACCURACY && (solution > lower_limit) && (solution < upper_limit))
- return solution
- stack_trace("Newton's Approximation for pressure failed after [ATMOS_PRESSURE_APPROXIMATION_ITERATIONS] iterations. A: [a]. B: [b]. C:[c]. Current value: [solution]. Expected lower limit: [lower_limit]. Expected upper limit: [upper_limit].")
- return FALSE
-
-/// Pumps gas from src to output_air. Amount depends on target_pressure
-/datum/gas_mixture/proc/pump_gas_to(datum/gas_mixture/output_air, target_pressure, specific_gas = null)
- var/temperature_delta = abs(temperature - output_air.temperature)
- var/datum/gas_mixture/removed
- var/transfer_moles
-
- if(specific_gas)
- // This is necessary because the specific heat capacity of a gas might be different from our gasmix.
- var/datum/gas_mixture/temporary = remove_specific_ratio(specific_gas, 1)
- transfer_moles = temporary.gas_pressure_calculate(output_air, target_pressure, temperature_delta <= 5)
- removed = temporary.remove_specific(specific_gas, transfer_moles)
- merge(temporary)
- else
- transfer_moles = gas_pressure_calculate(output_air, target_pressure, temperature_delta <= 5)
- removed = remove(transfer_moles)
-
- if(!removed)
- return FALSE
-
- output_air.merge(removed)
- return TRUE
-
-/// Releases gas from src to output air. This means that it can not transfer air to gas mixture with higher pressure.
-/datum/gas_mixture/proc/release_gas_to(datum/gas_mixture/output_air, target_pressure, rate=1)
- var/output_starting_pressure = output_air.return_pressure()
- var/input_starting_pressure = return_pressure()
-
- //Need at least 10 KPa difference to overcome friction in the mechanism
- if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10))
- return FALSE
- //Can not have a pressure delta that would cause output_pressure > input_pressure
- target_pressure = output_starting_pressure + min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2)
- var/temperature_delta = abs(temperature - output_air.temperature)
-
- var/transfer_moles = gas_pressure_calculate(output_air, target_pressure, temperature_delta <= 5)
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = remove(transfer_moles * rate)
-
- if(!removed)
- return FALSE
-
- output_air.merge(removed)
- return TRUE
diff --git a/code/modules/atmospherics/gasmixtures/gas_types.dm b/code/modules/atmospherics/gasmixtures/gas_types.dm
deleted file mode 100644
index d1b97d5338c..00000000000
--- a/code/modules/atmospherics/gasmixtures/gas_types.dm
+++ /dev/null
@@ -1,287 +0,0 @@
-GLOBAL_LIST_INIT(hardcoded_gases, list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma)) //the main four gases, which were at one time hardcoded
-//Now this is what I call history
-GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/pluoxium))) //unable to react amongst themselves
-
-/proc/meta_gas_list()
- . = subtypesof(/datum/gas)
- for(var/gas_path in .)
- var/list/gas_info = new(8)
- var/datum/gas/gas = gas_path
-
- gas_info[META_GAS_SPECIFIC_HEAT] = initial(gas.specific_heat)
- gas_info[META_GAS_NAME] = initial(gas.name)
-
- gas_info[META_GAS_MOLES_VISIBLE] = initial(gas.moles_visible)
- if(initial(gas.moles_visible) != null)
- gas_info[META_GAS_OVERLAY] = new /list(TOTAL_VISIBLE_STATES)
- for(var/i in 1 to TOTAL_VISIBLE_STATES)
- gas_info[META_GAS_OVERLAY][i] = new /obj/effect/overlay/gas(initial(gas.gas_overlay), log(4, (i+0.4*TOTAL_VISIBLE_STATES) / (0.35*TOTAL_VISIBLE_STATES)) * 255)
-
- gas_info[META_GAS_FUSION_POWER] = initial(gas.fusion_power)
- gas_info[META_GAS_DANGER] = initial(gas.dangerous)
- gas_info[META_GAS_ID] = initial(gas.id)
- gas_info[META_GAS_DESC] = initial(gas.desc)
- .[gas_path] = gas_info
-
-/proc/gas_id2path(id)
- var/list/meta_gas = GLOB.meta_gas_info
- if(id in meta_gas)
- return id
- for(var/path in meta_gas)
- if(meta_gas[path][META_GAS_ID] == id)
- return path
- return ""
-
-/*||||||||||||||/----------\||||||||||||||*\
-||||||||||||||||[GAS DATUMS]||||||||||||||||
-||||||||||||||||\__________/||||||||||||||||
-||||These should never be instantiated. ||||
-||||They exist only to make it easier ||||
-||||to add a new gas. They are accessed ||||
-||||only by meta_gas_list(). ||||
-\*||||||||||||||||||||||||||||||||||||||||*/
-
-/datum/gas
- var/id = ""
- var/specific_heat = 0
- var/name = ""
- var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi
- var/moles_visible = null
- var/dangerous = FALSE //currently used by canisters
- var/fusion_power = 0 //How much the gas accelerates a fusion reaction
- var/rarity = 0 // relative rarity compared to other gases, used when setting up the reactions list.
- var/purchaseable = FALSE
- var/base_value = 0
- var/desc
-
-/datum/gas/oxygen
- id = "o2"
- specific_heat = 20
- name = "Oxygen"
- rarity = 900
- purchaseable = TRUE
- base_value = 0.2
- desc = "The gas most life forms need to be able to survive. Also an oxidizer."
-
-/datum/gas/nitrogen
- id = "n2"
- specific_heat = 20
- name = "Nitrogen"
- rarity = 1000
- purchaseable = TRUE
- base_value = 0.1
- desc = "A very common gas that used to pad artifical atmospheres to habitable pressure."
-
-/datum/gas/carbon_dioxide //what the fuck is this?
- id = "co2"
- specific_heat = 30
- name = "Carbon Dioxide"
- dangerous = TRUE
- rarity = 700
- purchaseable = TRUE
- base_value = 0.2
- desc = "What the fuck is carbon dioxide?"
-
-/datum/gas/plasma
- id = "plasma"
- specific_heat = 200
- name = "Plasma"
- gas_overlay = "plasma"
- moles_visible = MOLES_GAS_VISIBLE
- dangerous = TRUE
- rarity = 800
- base_value = 2
- desc = "A flammable gas with many other curious properties. It's research is one of NT's primary objective."
-
-/datum/gas/water_vapor
- id = "water_vapor"
- specific_heat = 40
- name = "Water Vapor"
- gas_overlay = "water_vapor"
- moles_visible = MOLES_GAS_VISIBLE
- fusion_power = 8
- rarity = 500
- purchaseable = TRUE
- base_value = 0.5
- desc = "Water, in gas form. Makes things slippery."
-
-/datum/gas/hypernoblium
- id = "nob"
- specific_heat = 2000
- name = "Hyper-noblium"
- gas_overlay = "freon"
- moles_visible = MOLES_GAS_VISIBLE
- dangerous = TRUE
- fusion_power = 10
- rarity = 50
- base_value = 5
- desc = "The most noble gas of them all. High quantities of hyper-noblium actively prevents reactions from occuring."
-
-/datum/gas/nitrous_oxide
- id = "n2o"
- specific_heat = 40
- name = "Nitrous Oxide"
- gas_overlay = "nitrous_oxide"
- moles_visible = MOLES_GAS_VISIBLE * 2
- fusion_power = 10
- dangerous = TRUE
- rarity = 600
- purchaseable = TRUE
- base_value = 3
- desc = "Causes drowsiness, euphoria, and eventually unconsciousness."
-
-/datum/gas/nitrium
- id = "nitrium"
- specific_heat = 10
- name = "Nitrium"
- fusion_power = 7
- gas_overlay = "nitrium"
- moles_visible = MOLES_GAS_VISIBLE
- dangerous = TRUE
- rarity = 1
- base_value = 100
- desc = "An experimental performance enhancing gas. Nitrium can have amplified effects as more of it gets into your bloodstream."
-
-/datum/gas/tritium
- id = "tritium"
- specific_heat = 10
- name = "Tritium"
- gas_overlay = "tritium"
- moles_visible = MOLES_GAS_VISIBLE
- dangerous = TRUE
- fusion_power = 5
- rarity = 300
- base_value = 5
- desc = "A highly flammable and radioctive gas."
-
-/datum/gas/bz
- id = "bz"
- specific_heat = 20
- name = "BZ"
- dangerous = TRUE
- fusion_power = 8
- rarity = 400
- purchaseable = TRUE
- base_value = 2
- desc = "A powerful hallucinogenic nerve agent able to induce cognitive damage."
-
-/datum/gas/pluoxium
- id = "pluox"
- specific_heat = 80
- name = "Pluoxium"
- fusion_power = -10
- rarity = 200
- base_value = 5
- desc = "A gas that could supply even more oxygen to the bloodstream when inhaled, without being an oxidizer."
-
-/datum/gas/miasma
- id = "miasma"
- specific_heat = 20
- name = "Miasma"
- dangerous = TRUE
- gas_overlay = "miasma"
- moles_visible = MOLES_GAS_VISIBLE * 60
- rarity = 250
- base_value = 2
- desc = "Not necessarily a gas, miasma refers to biological pollutants found in the atmosphere."
-
-/datum/gas/freon
- id = "freon"
- specific_heat = 600
- name = "Freon"
- dangerous = TRUE
- gas_overlay = "freon"
- moles_visible = MOLES_GAS_VISIBLE *30
- fusion_power = -5
- rarity = 10
- base_value = 15
- desc = "A coolant gas. Mainly used for it's endothermic reaction with oxygen."
-
-/datum/gas/hydrogen
- id = "hydrogen"
- specific_heat = 15
- name = "Hydrogen"
- dangerous = TRUE
- fusion_power = 2
- rarity = 600
- base_value = 1
- desc = "A highly flammable gas."
-
-/datum/gas/healium
- id = "healium"
- specific_heat = 10
- name = "Healium"
- dangerous = TRUE
- gas_overlay = "healium"
- moles_visible = MOLES_GAS_VISIBLE
- rarity = 300
- base_value = 19
- desc = "Causes deep, regenerative sleep."
-
-/datum/gas/proto_nitrate
- id = "proto_nitrate"
- specific_heat = 30
- name = "Proto Nitrate"
- dangerous = TRUE
- gas_overlay = "proto_nitrate"
- moles_visible = MOLES_GAS_VISIBLE
- rarity = 200
- base_value = 5
- desc = "A very volatile gas that reacts differently with various gases."
-
-/datum/gas/zauker
- id = "zauker"
- specific_heat = 350
- name = "Zauker"
- dangerous = TRUE
- gas_overlay = "zauker"
- moles_visible = MOLES_GAS_VISIBLE
- rarity = 1
- base_value = 100
- desc = "A highly toxic gas, it's production is highly regulated on top of being difficult. It also breaks down when in contact with nitrogen."
-
-/datum/gas/halon
- id = "halon"
- specific_heat = 175
- name = "Halon"
- dangerous = TRUE
- gas_overlay = "halon"
- moles_visible = MOLES_GAS_VISIBLE
- rarity = 300
- base_value = 9
- desc = "A potent fire supressant. Removes oxygen from high temperature fires and cools down the area"
-
-/datum/gas/helium
- id = "helium"
- specific_heat = 15
- name = "Helium"
- fusion_power = 7
- rarity = 50
- base_value = 6
- desc = "A very inert gas produced by the fusion of hydrogen and it's derivatives."
-
-/datum/gas/antinoblium
- id = "antinoblium"
- specific_heat = 1
- name = "Antinoblium"
- dangerous = TRUE
- gas_overlay = "antinoblium"
- moles_visible = MOLES_GAS_VISIBLE
- fusion_power = 20
- rarity = 1
- base_value = 10
- desc = "We still don't know what it does, but it sells for a lot."
-
-/obj/effect/overlay/gas
- icon = 'icons/effects/atmospherics.dmi'
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- anchored = TRUE // should only appear in vis_contents, but to be safe
- layer = FLY_LAYER
- plane = ABOVE_GAME_PLANE
- appearance_flags = TILE_BOUND
- vis_flags = NONE
-
-/obj/effect/overlay/gas/New(state, alph)
- . = ..()
- icon_state = state
- alpha = alph
diff --git a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm
deleted file mode 100644
index e6cd8f75499..00000000000
--- a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm
+++ /dev/null
@@ -1,96 +0,0 @@
-//"immutable" gas mixture used for immutable calculations
-//it can be changed, but any changes will ultimately be undone before they can have any effect
-
-/datum/gas_mixture/immutable
- var/initial_temperature
- gc_share = TRUE
-
-/datum/gas_mixture/immutable/New()
- ..()
- garbage_collect()
-
-/datum/gas_mixture/immutable/garbage_collect()
- temperature = initial_temperature
- temperature_archived = initial_temperature
- gases.Cut()
-
-/datum/gas_mixture/immutable/archive()
- return TRUE //nothing changes, so we do nothing and the archive is successful
-
-/datum/gas_mixture/immutable/merge()
- return FALSE //we're immutable.
-
-/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, our_coeff, sharer_coeff)
- . = ..()
- sharer.temperature = initial_temperature
- garbage_collect()
-
-/datum/gas_mixture/immutable/react()
- return FALSE //we're immutable.
-
-/datum/gas_mixture/immutable/copy()
- return new type //we're immutable, so we can just return a new instance.
-
-/datum/gas_mixture/immutable/copy_from()
- return FALSE //we're immutable.
-
-/datum/gas_mixture/immutable/copy_from_turf()
- return FALSE //we're immutable.
-
-/datum/gas_mixture/immutable/parse_gas_string()
- return FALSE //we're immutable.
-
-/datum/gas_mixture/immutable/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
- . = ..()
- temperature = initial_temperature
-
-//used by space tiles
-/datum/gas_mixture/immutable/space
- initial_temperature = TCMB
-
-/datum/gas_mixture/immutable/space/heat_capacity()
- return HEAT_CAPACITY_VACUUM
-
-/datum/gas_mixture/immutable/space/remove()
- return copy() //we're always empty, so we can just return a copy.
-
-/datum/gas_mixture/immutable/space/remove_ratio()
- return copy() //we're always empty, so we can just return a copy.
-
-//planet side stuff
-/datum/gas_mixture/immutable/planetary
- var/list/initial_gas = list()
-
-/datum/gas_mixture/immutable/planetary/garbage_collect()
- ..()
- gases.Cut()
- for(var/id in initial_gas)
- ADD_GAS(id, gases)
- gases[id][MOLES] = initial_gas[id][MOLES]
- gases[id][ARCHIVE] = initial_gas[id][ARCHIVE]
-
-/datum/gas_mixture/immutable/planetary/proc/parse_string_immutable(gas_string) //I know I know, I need this tho
- gas_string = SSair.preprocess_gas_string(gas_string)
-
- var/list/mix = initial_gas
- var/list/gas = params2list(gas_string)
- if(gas["TEMP"])
- initial_temperature = text2num(gas["TEMP"])
- temperature_archived = initial_temperature
- temperature = initial_temperature
- gas -= "TEMP"
- mix.Cut()
- for(var/id in gas)
- var/path = id
- if(!ispath(path))
- path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around
- ADD_GAS(path, mix)
- mix[path][MOLES] = text2num(gas[id])
- mix[path][ARCHIVE] = mix[path][MOLES]
-
- for(var/id in mix)
- ADD_GAS(id, gases)
- gases[id][MOLES] = mix[id][MOLES]
- gases[id][ARCHIVE] = mix[id][MOLES]
-
-
diff --git a/code/modules/atmospherics/gasmixtures/reaction_factors.dm b/code/modules/atmospherics/gasmixtures/reaction_factors.dm
deleted file mode 100644
index 2d04de63e3c..00000000000
--- a/code/modules/atmospherics/gasmixtures/reaction_factors.dm
+++ /dev/null
@@ -1,216 +0,0 @@
-/datum/gas_reaction/water_vapor/init_factors()
- factor = list(
- /datum/gas/water_vapor = "Condensation will consume [MOLES_GAS_VISIBLE] moles, freezing will not consume any. Both needs a minimum of [MOLES_GAS_VISIBLE] moles to occur.",
- "Temperature" = "Freezes a turf at [WATER_VAPOR_DEPOSITION_POINT] Kelvins or below, wets it at [WATER_VAPOR_CONDENSATION_POINT] Kelvins or below.",
- "Location" = "Can only happen on turfs.",
- )
-
-/datum/gas_reaction/miaster/init_factors()
- factor = list(
- /datum/gas/miasma = "Miasma is consumed at 1 reaction rate.",
- /datum/gas/oxygen = "Oxygen is produced at 1 reaction rate.",
- "Temperature" = "Higher temperature increases the reaction rate.",
- "Energy" = "[MIASTER_STERILIZATION_ENERGY] joules of energy is released per rate.",
- )
-
-/datum/gas_reaction/plasmafire/init_factors()
- factor = list(
- /datum/gas/oxygen = "Oxygen consumption is determined by the temperature, ranging from [OXYGEN_BURN_RATIO_BASE] of the reaction rate at [PLASMA_MINIMUM_BURN_TEMPERATURE] Kelvins to [OXYGEN_BURN_RATIO_BASE-1] at [PLASMA_UPPER_TEMPERATURE] Kelvins. Higher oxygen concentration up to [PLASMA_OXYGEN_FULLBURN]x times the plasma increases the reaction rate.",
- /datum/gas/plasma = "Plasma is consumed at 1 reaction rate. It's relationship with oxygen also determines reaction speed",
- /datum/gas/tritium = "Tritium is formed at 1 reaction rate if there are 97 times more oxygen than plasma.",
- /datum/gas/water_vapor = "Water vapor is formed at 0.25 reaction rate if tritium isn't being formed.",
- /datum/gas/carbon_dioxide = "Carbon Dioxide is formed at 0.75 reaction rate if tritium isn't being formed.",
- "Temperature" = "Minimum temperature of [PLASMA_MINIMUM_BURN_TEMPERATURE] kelvin to occur. Higher temperature up to [PLASMA_UPPER_TEMPERATURE] increases the oxygen efficiency and also the reaction rate.",
- "Energy" = "[FIRE_PLASMA_ENERGY_RELEASED] joules of energy is released per reaction rate",
- )
-
-/datum/gas_reaction/h2fire/init_factors()
- factor = list(
- /datum/gas/oxygen = "Oxygen is consumed equal to the amount of hydrogen available on the fast burn. Not consumed on the slow burn. Needs to be more than the hydrogen amount to trigger fast burn. Acts as the reaction rate on slow burn.",
- /datum/gas/hydrogen = "[(1/HYDROGEN_BURN_H2_FACTOR)*100]% of the hydrogen is always consumed on the fast burn. [(1/HYDROGEN_BURN_OXY_FACTOR)*100]% of the oxygen amount is consumed on the slow burn. Need to be less than the oxygen amount to trigger fast burn. Acts as the reaction rate on fast burn.",
- /datum/gas/water_vapor = "Water vapor is formed at [1/HYDROGEN_BURN_H2_FACTOR] reaction rate for the fast burn, [1/HYDROGEN_BURN_OXY_FACTOR]% reaction rate for the slow burn.",
- "Temperature" = "Minimum temperature of [FIRE_MINIMUM_TEMPERATURE_TO_EXIST] kelvin to occur",
- "Energy" = "[FIRE_HYDROGEN_ENERGY_RELEASED*HYDROGEN_OXYBURN_MULTIPLIER] joules of energy is released per rate for the fast burn, [FIRE_HYDROGEN_ENERGY_RELEASED] joules for the slow burn. Needs [MINIMUM_TRITIUM_OXYBURN_ENERGY] joules to start the fast burn.",
- )
-
-/datum/gas_reaction/tritfire/init_factors()
- factor = list(
- /datum/gas/oxygen = "Oxygen is consumed equal to the amount of tritium available on the fast burn. Not consumed on the slow burn. Need to be more than the tritium amount to trigger fast burn. Acts as the reaction rate on slow burn.",
- /datum/gas/tritium = "[(1/TRITIUM_BURN_TRIT_FACTOR)*100]% of the tritium is always consumed on the fast burn. [(1/TRITIUM_BURN_OXY_FACTOR)*100]% of the oxygen amount is consumed on the slow burn. Need to be less than the oxygen amount to trigger fast burn. Acts as the reaction rate on fast burn.",
- /datum/gas/water_vapor = "Water vapor is formed at [1/TRITIUM_BURN_TRIT_FACTOR]% reaction rate for the fast burn, [1/TRITIUM_BURN_OXY_FACTOR]% reaction rate for the slow burn.",
- "Temperature" = "Minimum temperature of [FIRE_MINIMUM_TEMPERATURE_TO_EXIST] kelvin to occur",
- "Energy" = "[FIRE_TRITIUM_ENERGY_RELEASED*TRITIUM_OXYBURN_MULTIPLIER] joules of energy is released per rate for the fast burn, [FIRE_TRITIUM_ENERGY_RELEASED] joules for the slow burn. Needs [MINIMUM_TRITIUM_OXYBURN_ENERGY] joules to start the fast burn.",
- "Radiation" = "This reaction emits radiation proportional to the amount of energy released.",
- )
-
-/datum/gas_reaction/freonfire/init_factors()
- factor = list(
- /datum/gas/oxygen = "Oxygen consumption is determined by the temperature, ranging from [OXYGEN_BURN_RATIO_BASE] of the reaction rate at [FREON_LOWER_TEMPERATURE] Kelvins to [OXYGEN_BURN_RATIO_BASE-1] at [FREON_MAXIMUM_BURN_TEMPERATURE] Kelvins. Higher oxygen concentration up to [FREON_OXYGEN_FULLBURN] times the freon increases the reaction rate.",
- /datum/gas/freon = "Freon is consumed at 1 reaction rate. It's relationship with oxygen also determines reaction speed",
- /datum/gas/carbon_dioxide = "Carbon Dioxide is formed at 1 reaction rate.",
- "Temperature" = "Can only occur between [FREON_LOWER_TEMPERATURE] - [FREON_MAXIMUM_BURN_TEMPERATURE] Kelvin",
- "Energy" = "[FIRE_FREON_ENERGY_CONSUMED] joules of energy is absorbed per reaction rate",
- "Hot Ice" = "This reaction has a small chance to produce hot ice when occuring between [HOT_ICE_FORMATION_MINIMUM_TEMPERATURE]-[HOT_ICE_FORMATION_MAXIMUM_TEMPERATURE] kelvins",
- )
-
-
-/datum/gas_reaction/nitrousformation/init_factors()
- factor = list(
- /datum/gas/oxygen = "10 moles of Oxygen needs to be present for the reaction to occur. Oxygen is consumed at 1 reaction rate",
- /datum/gas/nitrogen = " 20 moles of Nitrogen needs to be present for the reaction to occur. Nitrogen is consumed at 2 reaction rate",
- /datum/gas/bz = "5 moles of BZ needs to be present for the reaction to occur. Not consumed.",
- /datum/gas/nitrous_oxide = "Nitrous oxide is produced at 1 reaction rate",
- "Temperature" = "Can only occur between [N2O_FORMATION_MIN_TEMPERATURE] - [N2O_FORMATION_MAX_TEMPERATURE] Kelvin",
- "Energy" = "[N2O_FORMATION_ENERGY] joules of energy is released per reaction rate",
- )
-
-/datum/gas_reaction/nitrous_decomp/init_factors()
- factor = list(
- /datum/gas/nitrous_oxide = "Nitrous Oxide is consumed at 1 reaction rate. Minimum of [MINIMUM_MOLE_COUNT * 2] to occur.", //okay this one isn't made into a define yet.
- /datum/gas/oxygen = "Oxygen is formed at 0.5 reaction rate",
- /datum/gas/nitrogen = "Nitrogen is formed at 1 reaction rate",
- "Temperature" = "Higher temperature increases the reaction rate. Can only happen between [N2O_DECOMPOSITION_MIN_TEMPERATURE] - [N2O_DECOMPOSITION_MAX_TEMPERATURE] kelvin.",
- "Energy" = "[N2O_DECOMPOSITION_ENERGY] joules of energy is released per reaction rate",
- )
-
-/datum/gas_reaction/bzformation/init_factors()
- factor = list(
- /datum/gas/plasma = "Plasma is consumed at 2 reaction rate. If there is more plasma than nitrous oxide reaction rate is slowed down.",
- /datum/gas/nitrous_oxide = "Nitrous oxide is consumed at 1 reaction rate. If there is less nitrous oxide than plasma the reaction rate is slowed down.",
- /datum/gas/bz = "BZ is formed at 2.5 reaction rate. A small malus up to half a mole per tick is applied if the reaction rate is constricted by nitrous oxide.",
- /datum/gas/oxygen = "Oxygen is produced from the BZ malus. This only happens when the reaction rate is being constricted by the amount of nitrous oxide present. I.E. amount of nitrous oxide is less than the reaction rate.", // Less than the reaction rate AND half the plasma, but suppose that's not necessary to mention.
- "Pressure" = "The lower the pressure the faster the reaction rate goes.",
- "Energy" = "[FIRE_CARBON_ENERGY_RELEASED] joules of energy is released per reaction rate",
- )
-
-/datum/gas_reaction/pluox_formation/init_factors()
- factor = list(
- /datum/gas/carbon_dioxide = "Carbon dioxide is consumed at 1 reaction rate",
- /datum/gas/oxygen = "Oxygen is consumed at 0.5 reaction rate",
- /datum/gas/tritium = "Tritium is consumed at 0.01 reaction rate",
- /datum/gas/pluoxium = "Pluoxium is produced at 1 reaction rate",
- /datum/gas/hydrogen = "Hydrogen is produced at 0.01 reaction rate",
- "Energy" = "[PLUOXIUM_FORMATION_ENERGY] joules of energy is released per reaction rate",
- "Temperature" = "Can only occur between [PLUOXIUM_FORMATION_MIN_TEMP] - [PLUOXIUM_FORMATION_MAX_TEMP] Kelvin",
- )
-
-/datum/gas_reaction/nitrium_formation/init_factors()
- factor = list(
- /datum/gas/bz = "5 moles of BZ needs to be present for the reaction to occur. BZ is consumed at 0.05 reaction rate.",
- /datum/gas/tritium = "20 moles of tritium needs to be present for the reaction to occur. Tritium is consumed at 1 reaction rate",
- /datum/gas/nitrogen = "10 moles of tritium needs to be present for the reaction to occur. Nitrogen is consumed at 1 reaction rate",
- /datum/gas/nitrium = "Nitrium is produced at 1 reaction rate",
- "Temperature" = "Can only occur above [NITRIUM_FORMATION_MIN_TEMP] kelvins",
- "Energy" = "[NITRIUM_FORMATION_ENERGY] joules of energy is absorbed per reaction rate",
- )
-
-/datum/gas_reaction/nitrium_decomposition/init_factors()
- factor = list(
- /datum/gas/oxygen = "[MINIMUM_MOLE_COUNT] moles of oxygen need to be present for the reaction to occur. Not consumed.",
- /datum/gas/nitrium = "Nitrium is consumed at 1 reaction rate",
- /datum/gas/hydrogen = "Hydrogen is produced at 1 reaction rate",
- /datum/gas/nitrogen = "Nitrogen is produced at 1 reaction rate",
- "Temperature" = " Can only occur below [NITRIUM_DECOMPOSITION_MAX_TEMP]. Higher temperature increases the reaction rate.",
- "Energy" = "[NITRIUM_DECOMPOSITION_ENERGY] joules of energy is released per reaction rate",
- )
-
-/datum/gas_reaction/freonformation/init_factors()
- factor = list(
- /datum/gas/plasma = "40 moles of plasma needs to be present for the reaction to occur. Plasma is consumed at 1.5 reaction rate.",
- /datum/gas/carbon_dioxide = "20 moles of carbon dioxide needs to be present for the reaction to occur. Carbon dioxide is consumed at 0.75 reaction rate.",
- /datum/gas/bz = "20 moles of BZ needs to be present for the reaction to occur. BZ is consumed at 0.25 reaction rate.",
- /datum/gas/freon = "Freon is produced at 2.5 reaction rate",
- "Energy" = "[FREON_FORMATION_ENERGY] joules of energy is absorbed per reaction rate",
- "Temperature" = "Minimum temperature of [FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100] Kelvin to occur",
- )
-
-/datum/gas_reaction/nobliumformation/init_factors()
- factor = list(
- /datum/gas/nitrogen = "10 moles of nitrogen needs to be present for the reaction to occur. Nitrogen is consumed at 10 reaction rate",
- /datum/gas/tritium = "5 moles of tritium needs to be present for the reaction to occur. Tritium is consumed at 5 reaction rate",
- /datum/gas/hypernoblium = "Hyper-Noblium is produced at 1 reaction rate",
- "Energy" = "[NOBLIUM_FORMATION_ENERGY] joules of energy is released per reaction rate.",
- /datum/gas/bz = "BZ is not consumed in the reaction but will lower the amount of energy released. It also reduces amount of trit consumed by a ratio between trit and bz, greater bz than trit will reduce more.",
- "Temperature" = "Can only occur between [NOBLIUM_FORMATION_MIN_TEMP] - [NOBLIUM_FORMATION_MAX_TEMP] kelvin",
- )
-
-/datum/gas_reaction/halon_formation/init_factors()
- factor = list(
- /datum/gas/bz = "BZ is consumed at 0.25 reaction rate",
- /datum/gas/tritium = "Tritium is consumed at 4 reaction rate",
- /datum/gas/halon = "Halon is produced at 4.25 reaction rate",
- "Energy" = "[HALON_FORMATION_ENERGY] joules of energy is released per reaction rate",
- "Temperature" = "Can only occur between [HALON_FORMATION_MIN_TEMPERATURE] - [HALON_FORMATION_MAX_TEMPERATURE] kelvin",
- )
-
-/datum/gas_reaction/halon_o2removal/init_factors()
- factor = list(
- /datum/gas/halon = "Halon is consumed at 1 reaction rate",
- /datum/gas/oxygen = "Oxygen is consumed at 20 reaction rate",
- /datum/gas/carbon_dioxide = "Carbon dioxide is produced at 5 reaction rate.",
- "Energy" = "[HALON_COMBUSTION_ENERGY] joules of energy is absorbed per reaction rate",
- "Temperature" = "Can only occur above [FIRE_MINIMUM_TEMPERATURE_TO_EXIST] kelvin. Higher temperature increases the reaction rate.",
- )
-
-/datum/gas_reaction/healium_formation/init_factors()
- factor = list(
- /datum/gas/bz = "BZ is consumed at 0.25 reaction rate",
- /datum/gas/freon = "Freon is consumed at 2.75 reaction rate",
- /datum/gas/healium = "Healium is produced at 3 reaction rate",
- "Temperature" = "Can only occur between [HEALIUM_FORMATION_MIN_TEMP] - [HEALIUM_FORMATION_MAX_TEMP]. Higher temperature increases the reaction rate.",
- "Energy" = "[HEALIUM_FORMATION_ENERGY] joules of energy is released per reaction rate.",
- )
-
-/datum/gas_reaction/zauker_formation/init_factors()
- factor = list(
- /datum/gas/hypernoblium = "Hyper-Noblium is consumed at 0.01 reaction rate",
- /datum/gas/nitrium = "Nitrium is consumed at 0.5 reaction rate",
- /datum/gas/zauker = "Zauker is produced at 0.5 reaction rate",
- "Temperature" = "Can only occur between [ZAUKER_FORMATION_MIN_TEMPERATURE] - [ZAUKER_FORMATION_MAX_TEMPERATURE] kelvin",
- "Energy" = "[ZAUKER_FORMATION_ENERGY] joules of energy is absorbed per reaction rate",
- )
-
-/datum/gas_reaction/zauker_decomp/init_factors() //Fixed reaction rate
- factor = list(
- /datum/gas/zauker = "Zauker is consumed at 1 reaction rate",
- /datum/gas/nitrogen = "At least [MINIMUM_MOLE_COUNT] moles of Nitrogen needs to be present for this reaction to occur. Nitrogen is produced at 0.7 reaction rate",
- /datum/gas/oxygen = "Oxygen is produced at 0.3 reaction rate",
- "Energy" = "[ZAUKER_DECOMPOSITION_ENERGY] joules of energy is released per reaction rate",
- )
-
-/datum/gas_reaction/proto_nitrate_formation/init_factors()
- factor = list(
- /datum/gas/pluoxium = "Pluoxium is consumed at 0.2 reaction rate",
- /datum/gas/hydrogen = "Hydrogen is consumed at 2 reaction rate",
- /datum/gas/proto_nitrate = "Proto-Nitrate is produced at 2.2 reaction rate",
- "Energy" = "[PN_FORMATION_ENERGY] joules of energy is released per reaction rate",
- "Temperature" = "Can only occur between [PN_FORMATION_MIN_TEMPERATURE] - [PN_FORMATION_MAX_TEMPERATURE] kelvin. Higher temperature increases the reaction rate.",
- )
-
-/datum/gas_reaction/proto_nitrate_hydrogen_response/init_factors() // Fixed reaction rate
- factor = list(
- /datum/gas/hydrogen = "[PN_HYDROGEN_CONVERSION_THRESHOLD] moles of hydrogen needs to be present for the reaction to occur. Hydrogen is consumed at 1 reaction rate.",
- /datum/gas/proto_nitrate = "[MINIMUM_MOLE_COUNT] moles of proto-nitrate needs to be present for the reaction to occur. Proto nitrate is produced at 0.5 reaction rate.",
- "Energy" = "[PN_HYDROGEN_CONVERSION_ENERGY] joules of energy is absorbed per reaction rate",
- )
-
-/datum/gas_reaction/proto_nitrate_tritium_response/init_factors() // Fixed reaction rate
- factor = list(
- /datum/gas/tritium = "Tritium is consumed at 1 reaction rate.",
- /datum/gas/proto_nitrate = "Proto nitrate is consumed at 0.01 reaction rate.",
- /datum/gas/hydrogen = "Hydrogen is produced at 1 reaction rate.",
- "Energy" = "[PN_TRITIUM_CONVERSION_ENERGY] joules of energy is released per reaction rate",
- "Radiation" = "This reaction emits radiation proportional to the reaction rate.",
- )
-
-/datum/gas_reaction/proto_nitrate_bz_response/init_factors() // Fixed reaction rate
- factor = list(
- /datum/gas/proto_nitrate = "[MINIMUM_MOLE_COUNT] moles of proto-nitrate needs to be present for the reaction to occur",
- /datum/gas/bz = "BZ is consumed at 1 reaction rate.",
- /datum/gas/nitrogen = "Nitrogen is produced at 0.4 reaction rate.",
- /datum/gas/helium = "Helium is produced at 1.6 reaction rate.",
- /datum/gas/plasma = "Plasma is produced at 0.8 reaction rate.",
- "Energy" = "[PN_BZASE_ENERGY] joules of energy is released per reaction rate",
- "Radiation" = "This reaction emits radiation proportional to the reaction rate.",
- "Hallucinations" = "This reaction can cause various carbon based lifeforms in the vicinity to hallucinate.",
- )
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
deleted file mode 100644
index 33fc13f7094..00000000000
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ /dev/null
@@ -1,1194 +0,0 @@
-//Most other defines used in reactions are located in ..\__DEFINES\reactions.dm
-#define SET_REACTION_RESULTS(amount) air.reaction_results[type] = amount
-
-/proc/init_gas_reactions()
- var/list/priority_reactions = list()
-
- //Builds a list of gas id to reaction group
- for(var/gas_id in GLOB.meta_gas_info)
- priority_reactions[gas_id] = list(
- PRIORITY_PRE_FORMATION = list(),
- PRIORITY_FORMATION = list(),
- PRIORITY_POST_FORMATION = list(),
- PRIORITY_FIRE = list()
- )
-
- for(var/datum/gas_reaction/reaction as anything in subtypesof(/datum/gas_reaction))
- if(initial(reaction.exclude))
- continue
- reaction = new reaction
- var/datum/gas/reaction_key
- for (var/req in reaction.requirements)
- if (ispath(req))
- var/datum/gas/req_gas = req
- if (!reaction_key || initial(reaction_key.rarity) > initial(req_gas.rarity))
- reaction_key = req_gas
- reaction.major_gas = reaction_key
- priority_reactions[reaction_key][reaction.priority_group] += reaction
-
- //Culls empty gases
- for(var/gas_id in GLOB.meta_gas_info)
- var/passed = FALSE
- for(var/list/priority_grouping in priority_reactions[gas_id])
- if(length(priority_grouping))
- passed = TRUE
- break
- if(passed)
- continue
- priority_reactions[gas_id] = null
-
- return priority_reactions
-
-/datum/gas_reaction
- /**
- * Regarding the requirements list: the minimum or maximum requirements must be non-zero.
- * When in doubt, use MINIMUM_MOLE_COUNT.
- * Another thing to note is that reactions will not fire if we have any requirements outside of gas id path or MIN_TEMP or MAX_TEMP.
- * More complex implementations will require modifications to gas_mixture.react()
- */
- var/list/requirements
- var/major_gas //the highest rarity gas used in the reaction.
- var/exclude = FALSE //do it this way to allow for addition/removal of reactions midmatch in the future
- ///The priority group this reaction is a part of. You can think of these as processing in batches, put your reaction into the one that's most fitting
- var/priority_group
- var/name = "reaction"
- var/id = "r"
- /// Whether the presence of our reaction should make fires bigger or not.
- var/expands_hotspot = FALSE
- /// A short string describing this reaction.
- var/desc
- /** REACTION FACTORS
- *
- * Describe (to a human) factors influencing this reaction in an assoc list format.
- * Also include gases formed by the reaction
- * Implement various interaction for different keys under subsystem/air/proc/atmos_handbook_init()
- *
- * E.G.
- * factor["Temperature"] = "Minimum temperature of 20 kelvins, maximum temperature of 100 kelvins"
- * factor["o2"] = "Minimum oxygen amount of 20 moles, more oxygen increases reaction rate up to 150 moles"
- */
- var/list/factor
-
-/datum/gas_reaction/New()
- init_reqs()
- init_factors()
-
-/datum/gas_reaction/proc/init_reqs() // Override this
- CRASH("Reaction [type] made without specifying requirements.")
-
-/datum/gas_reaction/proc/init_factors()
-
-/datum/gas_reaction/proc/react(datum/gas_mixture/air, atom/location)
- return NO_REACTION
-
-
-/**
- * Steam Condensation/Deposition:
- *
- * Makes turfs slippery.
- * Can frost things if the gas is cold enough.
- */
-/datum/gas_reaction/water_vapor
- priority_group = PRIORITY_POST_FORMATION
- name = "Water Vapor Condensation"
- id = "vapor"
- desc = "Water vapor condensation that can make things slippery."
-
-/datum/gas_reaction/water_vapor/init_reqs()
- requirements = list(
- /datum/gas/water_vapor = MOLES_GAS_VISIBLE,
- "MAX_TEMP" = WATER_VAPOR_CONDENSATION_POINT,
- )
-
-/datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder)
- . = NO_REACTION
- if(!isturf(holder))
- return
-
- var/turf/open/location = holder
- switch(air.temperature)
- if(-INFINITY to WATER_VAPOR_DEPOSITION_POINT)
- if(location?.freeze_turf())
- SET_REACTION_RESULTS(0)
- . = REACTING
- if(WATER_VAPOR_DEPOSITION_POINT to WATER_VAPOR_CONDENSATION_POINT)
- location.water_vapor_gas_act()
- air.gases[/datum/gas/water_vapor][MOLES] -= MOLES_GAS_VISIBLE
- SET_REACTION_RESULTS(MOLES_GAS_VISIBLE)
- . = REACTING
-
-
-/**
- * Dry Heat Sterilization:
- *
- * Clears out pathogens in the air.
- */
-/datum/gas_reaction/miaster
- priority_group = PRIORITY_POST_FORMATION
- name = "Dry Heat Sterilization"
- id = "sterilization"
- desc = "Pathogens cannot survive in a hot environment. Miasma decomposes on high temperature."
-
-/datum/gas_reaction/miaster/init_reqs()
- requirements = list(
- /datum/gas/miasma = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = MIASTER_STERILIZATION_TEMP,
- )
-
-/datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- // As the name says it, it needs to be dry
- if(cached_gases[/datum/gas/water_vapor] && cached_gases[/datum/gas/water_vapor][MOLES] / air.total_moles() > MIASTER_STERILIZATION_MAX_HUMIDITY)
- return NO_REACTION
-
- //Replace miasma with oxygen
- var/cleaned_air = min(cached_gases[/datum/gas/miasma][MOLES], MIASTER_STERILIZATION_RATE_BASE + (air.temperature - MIASTER_STERILIZATION_TEMP) / MIASTER_STERILIZATION_RATE_SCALE)
- cached_gases[/datum/gas/miasma][MOLES] -= cleaned_air
- ASSERT_GAS(/datum/gas/oxygen, air)
- cached_gases[/datum/gas/oxygen][MOLES] += cleaned_air
-
- //Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
- air.temperature += cleaned_air * MIASTER_STERILIZATION_ENERGY
- SET_REACTION_RESULTS(cleaned_air)
-
- return REACTING
-
-
-// Fire:
-
-/**
- * Plasma combustion:
- *
- * Combustion of oxygen and plasma (mostly treated as hydrocarbons).
- * The reaction rate is dependent on the temperature of the gasmix.
- * May produce either tritium or carbon dioxide and water vapor depending on the fuel/oxydizer ratio of the gasmix.
- */
-/datum/gas_reaction/plasmafire
- priority_group = PRIORITY_FIRE
- name = "Plasma Combustion"
- id = "plasmafire"
- expands_hotspot = TRUE
- desc = "Combustion of oxygen and plasma. Able to produce tritium or carbon dioxade and water vapor."
-
-/datum/gas_reaction/plasmafire/init_reqs()
- requirements = list(
- /datum/gas/plasma = MINIMUM_MOLE_COUNT,
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = PLASMA_MINIMUM_BURN_TEMPERATURE,
- )
-
-/datum/gas_reaction/plasmafire/react(datum/gas_mixture/air, datum/holder)
- // This reaction should proceed faster at higher temperatures.
- var/temperature = air.temperature
- var/temperature_scale = 0
- if(temperature > PLASMA_UPPER_TEMPERATURE)
- temperature_scale = 1
- else
- temperature_scale = (temperature - PLASMA_MINIMUM_BURN_TEMPERATURE) / (PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
- if(temperature_scale <= 0)
- return NO_REACTION
-
- var/oxygen_burn_ratio = OXYGEN_BURN_RATIO_BASE - temperature_scale
- var/plasma_burn_rate = 0
- var/super_saturation = FALSE // Whether we should make tritium.
- var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
- switch(cached_gases[/datum/gas/oxygen][MOLES] / cached_gases[/datum/gas/plasma][MOLES])
- if(SUPER_SATURATION_THRESHOLD to INFINITY)
- plasma_burn_rate = (cached_gases[/datum/gas/plasma][MOLES] / PLASMA_BURN_RATE_DELTA) * temperature_scale
- super_saturation = TRUE // Begin to form tritium
- if(PLASMA_OXYGEN_FULLBURN to SUPER_SATURATION_THRESHOLD)
- plasma_burn_rate = (cached_gases[/datum/gas/plasma][MOLES] / PLASMA_BURN_RATE_DELTA) * temperature_scale
- else
- plasma_burn_rate = ((cached_gases[/datum/gas/oxygen][MOLES] / PLASMA_OXYGEN_FULLBURN) / PLASMA_BURN_RATE_DELTA) * temperature_scale
-
- if(plasma_burn_rate < MINIMUM_HEAT_CAPACITY)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- plasma_burn_rate = min(plasma_burn_rate, cached_gases[/datum/gas/plasma][MOLES], cached_gases[/datum/gas/oxygen][MOLES] * INVERSE(oxygen_burn_ratio)) //Ensures matter is conserved properly
- cached_gases[/datum/gas/plasma][MOLES] = QUANTIZE(cached_gases[/datum/gas/plasma][MOLES] - plasma_burn_rate)
- cached_gases[/datum/gas/oxygen][MOLES] = QUANTIZE(cached_gases[/datum/gas/oxygen][MOLES] - (plasma_burn_rate * oxygen_burn_ratio))
- if (super_saturation)
- ASSERT_GAS(/datum/gas/tritium, air)
- cached_gases[/datum/gas/tritium][MOLES] += plasma_burn_rate
- else
- ASSERT_GAS(/datum/gas/carbon_dioxide, air)
- ASSERT_GAS(/datum/gas/water_vapor, air)
- cached_gases[/datum/gas/carbon_dioxide][MOLES] += plasma_burn_rate * 0.75
- cached_gases[/datum/gas/water_vapor][MOLES] += plasma_burn_rate * 0.25
-
- SET_REACTION_RESULTS((plasma_burn_rate) * (1 + oxygen_burn_ratio))
- var/energy_released = FIRE_PLASMA_ENERGY_RELEASED * plasma_burn_rate
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
-
- // Let the floor know a fire is happening
- var/turf/open/location = holder
- if(istype(location))
- temperature = air.temperature
- if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
- location.hotspot_expose(temperature, CELL_VOLUME)
-
- return REACTING
-
-
-/**
- * Hydrogen combustion:
- *
- * Combustion of oxygen and hydrogen.
- * Highly exothermic.
- * Creates hotspots.
- */
-/datum/gas_reaction/h2fire
- priority_group = PRIORITY_FIRE
- name = "Hydrogen Combustion"
- id = "h2fire"
- expands_hotspot = TRUE
- desc = "Combustion of hydrogen with oxygen. Can be extremely fast and energetic if a few conditions are fulfilled."
-
-/datum/gas_reaction/h2fire/init_reqs()
- requirements = list(
- /datum/gas/hydrogen = MINIMUM_MOLE_COUNT,
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = HYDROGEN_MINIMUM_BURN_TEMPERATURE,
- )
-
-/datum/gas_reaction/h2fire/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
- var/old_heat_capacity = air.heat_capacity()
- var/temperature = air.temperature
-
- var/burned_fuel
- var/fire_scale
- if(cached_gases[/datum/gas/oxygen][MOLES] < cached_gases[/datum/gas/hydrogen][MOLES] || MINIMUM_HYDROGEN_OXYBURN_ENERGY > (temperature * old_heat_capacity))
- burned_fuel = cached_gases[/datum/gas/oxygen][MOLES] / HYDROGEN_BURN_OXY_FACTOR // const must be at least one
- fire_scale = 1
-
- cached_gases[/datum/gas/hydrogen][MOLES] -= burned_fuel
- ASSERT_GAS(/datum/gas/water_vapor, air)
- cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel / HYDROGEN_BURN_OXY_FACTOR
- else
- burned_fuel = cached_gases[/datum/gas/hydrogen][MOLES]
- fire_scale = HYDROGEN_OXYBURN_MULTIPLIER
-
- cached_gases[/datum/gas/hydrogen][MOLES] -= burned_fuel / HYDROGEN_BURN_H2_FACTOR
- cached_gases[/datum/gas/oxygen][MOLES] -= burned_fuel
- ASSERT_GAS(/datum/gas/water_vapor, air)
- cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel / HYDROGEN_BURN_H2_FACTOR
-
- SET_REACTION_RESULTS(burned_fuel * fire_scale) // This is actually a lie. We use 10x less moles here but make 10x more energy.
-
- var/energy_released = FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel * fire_scale
- if(energy_released > 0)
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
-
- //let the floor know a fire is happening
- var/turf/open/location = holder
- if(istype(location))
- temperature = air.temperature
- if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
- location.hotspot_expose(temperature, CELL_VOLUME)
-
- return burned_fuel ? REACTING : NO_REACTION
-
-
-/**
- * Tritium combustion:
- *
- * Combustion of oxygen and tritium (treated as hydrogen).
- * Highly exothermic.
- * Creates hotspots.
- * Creates radiation.
- */
-/datum/gas_reaction/tritfire
- priority_group = PRIORITY_FIRE
- name = "Tritium Combustion"
- id = "tritfire"
- expands_hotspot = TRUE
- desc = "Combustion of tritium with oxygen. Can be extremely fast and energetic if a few conditions are fulfilled."
-
-/datum/gas_reaction/tritfire/init_reqs()
- requirements = list(
- /datum/gas/tritium = MINIMUM_MOLE_COUNT,
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = TRITIUM_MINIMUM_BURN_TEMPERATURE,
- )
-
-/datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
- var/old_heat_capacity = air.heat_capacity()
- var/temperature = air.temperature
-
- var/burned_fuel
- var/effect_scale
- if(cached_gases[/datum/gas/oxygen][MOLES] < cached_gases[/datum/gas/tritium][MOLES] || MINIMUM_TRITIUM_OXYBURN_ENERGY > (temperature * old_heat_capacity))
- burned_fuel = cached_gases[/datum/gas/oxygen][MOLES] / TRITIUM_BURN_OXY_FACTOR // const must be at least one
- effect_scale = 1
-
- cached_gases[/datum/gas/tritium][MOLES] -= burned_fuel
- ASSERT_GAS(/datum/gas/water_vapor, air)
- cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel / TRITIUM_BURN_OXY_FACTOR
- else
- burned_fuel = cached_gases[/datum/gas/tritium][MOLES]
- effect_scale = TRITIUM_OXYBURN_MULTIPLIER
-
- cached_gases[/datum/gas/tritium][MOLES] -= burned_fuel / TRITIUM_BURN_TRIT_FACTOR
- cached_gases[/datum/gas/oxygen][MOLES] -= burned_fuel
- ASSERT_GAS(/datum/gas/water_vapor, air)
- cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel / TRITIUM_BURN_TRIT_FACTOR
-
-
- SET_REACTION_RESULTS(burned_fuel * effect_scale)
-
- var/turf/open/location
- if(istype(holder, /datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet.
- var/datum/pipeline/pipenet = holder
- location = pick(pipenet.members)
- else if(isatom(holder))
- location = holder
-
- var/energy_released = FIRE_TRITIUM_ENERGY_RELEASED * burned_fuel * effect_scale
- if(location && burned_fuel > TRITIUM_RADIATION_MINIMUM_MOLES && energy_released > TRITIUM_RADIATION_RELEASE_THRESHOLD * (air.volume / CELL_VOLUME) ** ATMOS_RADIATION_VOLUME_EXP && prob(10))
- radiation_pulse(location, max_range = min(TRITIUM_MINIMUM_RADIATION_RANGE + sqrt(burned_fuel * effect_scale / TRITIUM_OXYBURN_MULTIPLIER) / TRITIUM_RADIATION_RANGE_DIVISOR, 20), threshold = TRITIUM_RADIATION_THRESHOLD_BASE * INVERSE(TRITIUM_RADIATION_THRESHOLD_BASE + (burned_fuel * effect_scale / TRITIUM_OXYBURN_MULTIPLIER)), chance = 100 * (1 - 0.5 ** (energy_released / TRITIUM_RADIATION_CHANCE_ENERGY_THRESHOLD_BASE)))
-
- if(energy_released > 0)
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
-
- //let the floor know a fire is happening
- if(istype(location))
- temperature = air.temperature
- if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
- location.hotspot_expose(temperature, CELL_VOLUME)
-
- return burned_fuel ? REACTING : NO_REACTION
-
-
-
-/**
- * Freon combustion:
- *
- * Combustion of oxygen and freon.
- * Endothermic.
- */
-/datum/gas_reaction/freonfire
- priority_group = PRIORITY_FIRE
- name = "Freon Combustion"
- id = "freonfire"
- expands_hotspot = TRUE
- desc = "Reaction between oxygen and freon that consumes a huge amount of energy and can cool things significantly. Also able to produce hot ice."
-
-/datum/gas_reaction/freonfire/init_reqs()
- requirements = list(
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- /datum/gas/freon = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = FREON_TERMINAL_TEMPERATURE,
- "MAX_TEMP" = FREON_MAXIMUM_BURN_TEMPERATURE,
- )
-
-/datum/gas_reaction/freonfire/react(datum/gas_mixture/air, datum/holder)
- if(!isturf(holder))
- return NO_REACTION
-
- var/temperature = air.temperature
- var/temperature_scale
- if(temperature < FREON_TERMINAL_TEMPERATURE) //stop the reaction when too cold
- temperature_scale = 0
- else if(temperature < FREON_LOWER_TEMPERATURE)
- temperature_scale = 0.5
- else
- temperature_scale = (FREON_MAXIMUM_BURN_TEMPERATURE - temperature) / (FREON_MAXIMUM_BURN_TEMPERATURE - FREON_TERMINAL_TEMPERATURE) //calculate the scale based on the temperature
- if (temperature_scale <= 0)
- return NO_REACTION
-
- var/oxygen_burn_ratio = OXYGEN_BURN_RATIO_BASE - temperature_scale
- var/freon_burn_rate
- var/list/cached_gases = air.gases
- if(cached_gases[/datum/gas/oxygen][MOLES] < cached_gases[/datum/gas/freon][MOLES] * FREON_OXYGEN_FULLBURN)
- freon_burn_rate = (cached_gases[/datum/gas/freon][MOLES] / FREON_BURN_RATE_DELTA) * temperature_scale
- else
- freon_burn_rate = ((cached_gases[/datum/gas/oxygen][MOLES] / FREON_OXYGEN_FULLBURN) / FREON_BURN_RATE_DELTA) * temperature_scale
-
- if (freon_burn_rate < MINIMUM_HEAT_CAPACITY)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- freon_burn_rate = min(freon_burn_rate, cached_gases[/datum/gas/freon][MOLES], cached_gases[/datum/gas/oxygen][MOLES] * INVERSE(oxygen_burn_ratio)) //Ensures matter is conserved properly
- cached_gases[/datum/gas/freon][MOLES] = QUANTIZE(cached_gases[/datum/gas/freon][MOLES] - freon_burn_rate)
- cached_gases[/datum/gas/oxygen][MOLES] = QUANTIZE(cached_gases[/datum/gas/oxygen][MOLES] - (freon_burn_rate * oxygen_burn_ratio))
- ASSERT_GAS(/datum/gas/carbon_dioxide, air)
- cached_gases[/datum/gas/carbon_dioxide][MOLES] += freon_burn_rate
-
- if(temperature < HOT_ICE_FORMATION_MAXIMUM_TEMPERATURE && temperature > HOT_ICE_FORMATION_MINIMUM_TEMPERATURE && prob(HOT_ICE_FORMATION_PROB))
- new /obj/item/stack/sheet/hot_ice(holder)
-
- SET_REACTION_RESULTS(freon_burn_rate * (1 + oxygen_burn_ratio))
- var/energy_consumed = FIRE_FREON_ENERGY_CONSUMED * freon_burn_rate
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max((temperature * old_heat_capacity - energy_consumed) / new_heat_capacity, TCMB)
-
- var/turf/open/location = holder
- if(istype(location))
- temperature = air.temperature
- if(temperature < FREON_MAXIMUM_BURN_TEMPERATURE)
- location.hotspot_expose(temperature, CELL_VOLUME)
-
- return REACTING
-
-
-// N2O
-
-/**
- * Nitrous oxide Formation:
- *
- * Formation of N2O.
- * Endothermic.
- * Requires BZ as a catalyst.
- */
-/datum/gas_reaction/nitrousformation //formation of n2o, exothermic, requires bz as catalyst
- priority_group = PRIORITY_FORMATION
- name = "Nitrous Oxide Formation"
- id = "nitrousformation"
- desc = "Production of nitrous oxide with BZ as a catalyst."
-
-/datum/gas_reaction/nitrousformation/init_reqs()
- requirements = list(
- /datum/gas/oxygen = 10,
- /datum/gas/nitrogen = 20,
- /datum/gas/bz = 5,
- "MIN_TEMP" = N2O_FORMATION_MIN_TEMPERATURE,
- "MAX_TEMP" = N2O_FORMATION_MAX_TEMPERATURE,
- )
-
-/datum/gas_reaction/nitrousformation/react(datum/gas_mixture/air)
- var/list/cached_gases = air.gases
- var/heat_efficency = min(cached_gases[/datum/gas/oxygen][MOLES], cached_gases[/datum/gas/nitrogen][MOLES] * INVERSE(2))
- if ((cached_gases[/datum/gas/oxygen][MOLES] - heat_efficency < 0 ) || (cached_gases[/datum/gas/nitrogen][MOLES] - heat_efficency * 2 < 0))
- return NO_REACTION // Shouldn't produce gas from nothing.
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/oxygen][MOLES] -= heat_efficency
- cached_gases[/datum/gas/nitrogen][MOLES] -= heat_efficency * 2
- ASSERT_GAS(/datum/gas/nitrous_oxide, air)
- cached_gases[/datum/gas/nitrous_oxide][MOLES] += heat_efficency
-
- SET_REACTION_RESULTS(heat_efficency)
- var/energy_released = heat_efficency * N2O_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((air.temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB) // The air cools down when reacting.
- return REACTING
-
-
-/**
- * Nitrous Oxide Decomposition
- *
- * Decomposition of N2O.
- * Exothermic.
- */
-/datum/gas_reaction/nitrous_decomp
- priority_group = PRIORITY_POST_FORMATION
- name = "Nitrous Oxide Decomposition"
- id = "nitrous_decomp"
- desc = "Decomposition of nitrous oxide under high temperature."
-
-/datum/gas_reaction/nitrous_decomp/init_reqs()
- requirements = list(
- /datum/gas/nitrous_oxide = MINIMUM_MOLE_COUNT * 2,
- "MIN_TEMP" = N2O_DECOMPOSITION_MIN_TEMPERATURE,
- "MAX_TEMP" = N2O_DECOMPOSITION_MAX_TEMPERATURE,
- )
-
-/datum/gas_reaction/nitrous_decomp/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
- var/temperature = air.temperature
- var/burned_fuel = (cached_gases[/datum/gas/nitrous_oxide][MOLES] / N2O_DECOMPOSITION_RATE_DIVISOR) * ((temperature - N2O_DECOMPOSITION_MIN_SCALE_TEMP) * (temperature - N2O_DECOMPOSITION_MAX_SCALE_TEMP) / (N2O_DECOMPOSITION_SCALE_DIVISOR))
- if(burned_fuel <= 0)
- return NO_REACTION
- if(cached_gases[/datum/gas/nitrous_oxide][MOLES] - burned_fuel < 0)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/nitrous_oxide][MOLES] -= burned_fuel
- ASSERT_GAS(/datum/gas/nitrogen, air)
- cached_gases[/datum/gas/nitrogen][MOLES] += burned_fuel
- ASSERT_GAS(/datum/gas/oxygen, air)
- cached_gases[/datum/gas/oxygen][MOLES] += burned_fuel / 2
-
- SET_REACTION_RESULTS(burned_fuel)
- var/energy_released = N2O_DECOMPOSITION_ENERGY * burned_fuel
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
- return REACTING
-
-
-// BZ
-
-/**
- * BZ Formation
- *
- * Formation of BZ by combining plasma and nitrous oxide at low pressures.
- * Exothermic.
- */
-/datum/gas_reaction/bzformation
- priority_group = PRIORITY_FORMATION
- name = "BZ Gas Formation"
- id = "bzformation"
- desc = "Production of BZ using plasma and nitrous oxide."
-
-/datum/gas_reaction/bzformation/init_reqs()
- requirements = list(
- /datum/gas/nitrous_oxide = 10,
- /datum/gas/plasma = 10,
- "MAX_TEMP" = BZ_FORMATION_MAX_TEMPERATURE,
- )
-
-/datum/gas_reaction/bzformation/react(datum/gas_mixture/air)
- var/list/cached_gases = air.gases
- var/pressure = air.return_pressure()
- // This slows down in relation to pressure, very quickly. Please don't expect it to be anything more then a snail
-
- // Bigger is better for these two values.
- var/pressure_efficiency = (0.1 * ONE_ATMOSPHERE) / pressure // More pressure = more bad
- var/ratio_efficiency = min(cached_gases[/datum/gas/nitrous_oxide][MOLES] / cached_gases[/datum/gas/plasma][MOLES], 1) // Malus to production if more plasma than n2o.
-
- var/reaction_efficency = min(pressure_efficiency * ratio_efficiency, cached_gases[/datum/gas/nitrous_oxide][MOLES], cached_gases[/datum/gas/plasma][MOLES] * INVERSE(2))
-
- if ((cached_gases[/datum/gas/nitrous_oxide][MOLES] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma][MOLES] - (2 * reaction_efficency) < 0) || reaction_efficency <= 0) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/bz, air)
- if (reaction_efficency == cached_gases[/datum/gas/nitrous_oxide][MOLES])
- ASSERT_GAS(/datum/gas/oxygen, air)
- cached_gases[/datum/gas/bz][MOLES] += (reaction_efficency * 2.5) - min(pressure, 0.5)
- cached_gases[/datum/gas/oxygen][MOLES] += min(pressure, 0.5)
- else
- cached_gases[/datum/gas/bz][MOLES] += reaction_efficency * 2.5
-
- cached_gases[/datum/gas/nitrous_oxide][MOLES] -= reaction_efficency
- cached_gases[/datum/gas/plasma][MOLES] -= 2 * reaction_efficency
-
- SET_REACTION_RESULTS(reaction_efficency)
- var/energy_released = 2 * reaction_efficency * FIRE_CARBON_ENERGY_RELEASED
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((air.temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB)
- return REACTING
-
-
-// Pluoxium
-
-/**
- * Pluoxium Formation:
- *
- * Consumes a tiny amount of tritium to convert CO2 and oxygen to pluoxium.
- * Exothermic.
- */
-/datum/gas_reaction/pluox_formation
- priority_group = PRIORITY_FORMATION
- name = "Pluoxium Formation"
- id = "pluox_formation"
- desc = "Alternate production for pluoxium which uses tritium."
-
-/datum/gas_reaction/pluox_formation/init_reqs()
- requirements = list(
- /datum/gas/carbon_dioxide = MINIMUM_MOLE_COUNT,
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- /datum/gas/tritium = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = PLUOXIUM_FORMATION_MIN_TEMP,
- "MAX_TEMP" = PLUOXIUM_FORMATION_MAX_TEMP,
- )
-
-/datum/gas_reaction/pluox_formation/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/produced_amount = min(PLUOXIUM_FORMATION_MAX_RATE, cached_gases[/datum/gas/carbon_dioxide][MOLES], cached_gases[/datum/gas/oxygen][MOLES] * INVERSE(0.5), cached_gases[/datum/gas/tritium][MOLES] * INVERSE(0.01))
- if (produced_amount <= 0 || cached_gases[/datum/gas/carbon_dioxide][MOLES] - produced_amount < 0 || cached_gases[/datum/gas/oxygen][MOLES] - produced_amount * 0.5 < 0 || cached_gases[/datum/gas/tritium][MOLES] - produced_amount * 0.01 < 0)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/carbon_dioxide][MOLES] -= produced_amount
- cached_gases[/datum/gas/oxygen][MOLES] -= produced_amount * 0.5
- cached_gases[/datum/gas/tritium][MOLES] -= produced_amount * 0.01
- ASSERT_GAS(/datum/gas/pluoxium, air)
- cached_gases[/datum/gas/pluoxium][MOLES] += produced_amount
- ASSERT_GAS(/datum/gas/hydrogen, air)
- cached_gases[/datum/gas/hydrogen][MOLES] += produced_amount * 0.01
-
- SET_REACTION_RESULTS(produced_amount)
- var/energy_released = produced_amount * PLUOXIUM_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max((air.temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)
- return REACTING
-
-
-// Nitrium
-
-/**
- * Nitrium Formation:
- *
- * The formation of nitrium.
- * Endothermic.
- * Requires BZ.
- */
-/datum/gas_reaction/nitrium_formation
- priority_group = PRIORITY_FORMATION
- name = "Nitrium Formation"
- id = "nitrium_formation"
- desc = "Production of nitrium from BZ, tritium, and nitrogen."
-
-/datum/gas_reaction/nitrium_formation/init_reqs()
- requirements = list(
- /datum/gas/tritium = 20,
- /datum/gas/nitrogen = 10,
- /datum/gas/bz = 5,
- "MIN_TEMP" = NITRIUM_FORMATION_MIN_TEMP,
- )
-
-/datum/gas_reaction/nitrium_formation/react(datum/gas_mixture/air)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
- var/heat_efficency = min(temperature / NITRIUM_FORMATION_TEMP_DIVISOR, cached_gases[/datum/gas/tritium][MOLES], cached_gases[/datum/gas/nitrogen][MOLES], cached_gases[/datum/gas/bz][MOLES] * INVERSE(0.05))
-
- if( heat_efficency <= 0 || (cached_gases[/datum/gas/tritium][MOLES] - heat_efficency < 0 ) || (cached_gases[/datum/gas/nitrogen][MOLES] - heat_efficency < 0) || (cached_gases[/datum/gas/bz][MOLES] - heat_efficency * 0.05 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/nitrium, air)
- cached_gases[/datum/gas/tritium][MOLES] -= heat_efficency
- cached_gases[/datum/gas/nitrogen][MOLES] -= heat_efficency
- cached_gases[/datum/gas/bz][MOLES] -= heat_efficency * 0.05 //bz gets consumed to balance the nitrium production and not make it too common and/or easy
- cached_gases[/datum/gas/nitrium][MOLES] += heat_efficency
-
- SET_REACTION_RESULTS(heat_efficency)
- var/energy_used = heat_efficency * NITRIUM_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB) //the air cools down when reacting
- return REACTING
-
-
-/**
- * Nitrium Decomposition:
- *
- * The decomposition of nitrium.
- * Exothermic.
- * Requires oxygen as catalyst.
- */
-/datum/gas_reaction/nitrium_decomposition
- priority_group = PRIORITY_PRE_FORMATION
- name = "Nitrium Decomposition"
- id = "nitrium_decomp"
- desc = "Decomposition of nitrium when exposed to oxygen under normal temperatures."
-
-/datum/gas_reaction/nitrium_decomposition/init_reqs()
- requirements = list(
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- /datum/gas/nitrium = MINIMUM_MOLE_COUNT,
- "MAX_TEMP" = NITRIUM_DECOMPOSITION_MAX_TEMP,
- )
-
-/datum/gas_reaction/nitrium_decomposition/react(datum/gas_mixture/air)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
-
- //This reaction is agressively slow. like, a tenth of a mole per fire slow. Keep that in mind
- var/heat_efficency = min(temperature / NITRIUM_DECOMPOSITION_TEMP_DIVISOR, cached_gases[/datum/gas/nitrium][MOLES])
-
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/nitrium][MOLES] - heat_efficency < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- air.assert_gases(/datum/gas/nitrogen, /datum/gas/hydrogen)
- cached_gases[/datum/gas/nitrium][MOLES] -= heat_efficency
- cached_gases[/datum/gas/hydrogen][MOLES] += heat_efficency
- cached_gases[/datum/gas/nitrogen][MOLES] += heat_efficency
-
- SET_REACTION_RESULTS(heat_efficency)
- var/energy_released = heat_efficency * NITRIUM_DECOMPOSITION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB) //the air heats up when reacting
- return REACTING
-
-
-/**
- * Freon formation:
- *
- * The formation of freon.
- * Endothermic.
- */
-/datum/gas_reaction/freonformation
- priority_group = PRIORITY_FORMATION
- name = "Freon Formation"
- id = "freonformation"
- desc = "Production of freon using plasma, carbon dioxide, and BZ under high temperature."
-
-/datum/gas_reaction/freonformation/init_reqs() //minimum requirements for freon formation
- requirements = list(
- /datum/gas/plasma = 40,
- /datum/gas/carbon_dioxide = 20,
- /datum/gas/bz = 20,
- "MIN_TEMP" = FREON_FORMATION_MIN_TEMPERATURE,
- )
-
-/datum/gas_reaction/freonformation/react(datum/gas_mixture/air)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
- var/heat_efficency = min(temperature / FREON_FORMATION_TEMP_DIVISOR, cached_gases[/datum/gas/plasma][MOLES] * INVERSE(1.5), cached_gases[/datum/gas/carbon_dioxide][MOLES] * INVERSE(0.75), cached_gases[/datum/gas/bz][MOLES] * INVERSE(0.25))
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/plasma][MOLES] - heat_efficency * 1.5 < 0 ) || (cached_gases[/datum/gas/carbon_dioxide][MOLES] - heat_efficency * 0.75 < 0) || (cached_gases[/datum/gas/bz][MOLES] - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/freon, air)
- cached_gases[/datum/gas/plasma][MOLES] -= heat_efficency * 1.5 // 6
- cached_gases[/datum/gas/carbon_dioxide][MOLES] -= heat_efficency * 0.75 // 3
- cached_gases[/datum/gas/bz][MOLES] -= heat_efficency * 0.25 // 1
- cached_gases[/datum/gas/freon][MOLES] += heat_efficency * 2.5 // 10
-
- SET_REACTION_RESULTS(heat_efficency * 2.5)
- var/energy_used = heat_efficency * FREON_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity - energy_used)/new_heat_capacity), TCMB)
- return REACTING
-
-
-/**
- * Hyper-Noblium Formation:
- *
- * Extremely exothermic.
- * Requires very low temperatures.
- * Due to its high mass, hyper-noblium uses large amounts of nitrogen and tritium.
- * BZ can be used as a catalyst to make it less exothermic.
- */
-/datum/gas_reaction/nobliumformation
- priority_group = PRIORITY_FORMATION
- name = "Hyper-Noblium Condensation"
- id = "nobformation"
- desc = "Production of hyper-noblium from nitrogen and tritium under very low temperatures. Extremely energetic."
-
-/datum/gas_reaction/nobliumformation/init_reqs()
- requirements = list(
- /datum/gas/nitrogen = 10,
- /datum/gas/tritium = 5,
- "MIN_TEMP" = NOBLIUM_FORMATION_MIN_TEMP,
- "MAX_TEMP" = NOBLIUM_FORMATION_MAX_TEMP,
- )
-
-/datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air)
- var/list/cached_gases = air.gases
- var/nob_formed = min((cached_gases[/datum/gas/nitrogen][MOLES] + cached_gases[/datum/gas/tritium][MOLES]) * 0.01, cached_gases[/datum/gas/tritium][MOLES] * INVERSE(5), cached_gases[/datum/gas/nitrogen][MOLES] * INVERSE(10))
-
- if (nob_formed <= 0 || (cached_gases[/datum/gas/tritium][MOLES] - 5 * nob_formed < 0) || (cached_gases[/datum/gas/nitrogen][MOLES] - 10 * nob_formed < 0))
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- air.assert_gases(/datum/gas/hypernoblium, /datum/gas/bz)
- var/reduction_factor = clamp(cached_gases[/datum/gas/tritium][MOLES]/(cached_gases[/datum/gas/tritium][MOLES] + cached_gases[/datum/gas/bz][MOLES]), 0.001 , 1) //reduces trit consumption in presence of bz upward to 0.1% reduction
- cached_gases[/datum/gas/tritium][MOLES] -= 5 * nob_formed * reduction_factor
- cached_gases[/datum/gas/nitrogen][MOLES] -= 10 * nob_formed
- cached_gases[/datum/gas/hypernoblium][MOLES] += nob_formed // I'm not going to nitpick, but N20H10 feels like it should be an explosive more than anything.
- SET_REACTION_RESULTS(nob_formed)
- var/energy_released = nob_formed * (NOBLIUM_FORMATION_ENERGY / (max(cached_gases[/datum/gas/bz][MOLES], 1)))
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((air.temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB)
- return REACTING
-
-
-// Halon
-
-/**
- * Halon Formation:
- *
- * Exothermic
- */
-/datum/gas_reaction/halon_formation
- priority_group = PRIORITY_FORMATION
- name = "Halon Formation"
- id = "halon_formation"
- desc = "Production of halon from BZ and tritium."
-
-/datum/gas_reaction/halon_formation/init_reqs()
- requirements = list(
- /datum/gas/bz = MINIMUM_MOLE_COUNT,
- /datum/gas/tritium = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = HALON_FORMATION_MIN_TEMPERATURE,
- "MAX_TEMP" = HALON_FORMATION_MAX_TEMPERATURE,
- )
-
-/datum/gas_reaction/halon_formation/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
- var/heat_efficency = min(temperature * 0.01, cached_gases[/datum/gas/tritium][MOLES] * INVERSE(4), cached_gases[/datum/gas/bz][MOLES] * INVERSE(0.25))
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/tritium][MOLES] - heat_efficency * 4 < 0 ) || (cached_gases[/datum/gas/bz][MOLES] - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/halon, air)
- cached_gases[/datum/gas/tritium][MOLES] -= heat_efficency * 4
- cached_gases[/datum/gas/bz][MOLES] -= heat_efficency * 0.25
- cached_gases[/datum/gas/halon][MOLES] += heat_efficency * 4.25
-
- SET_REACTION_RESULTS(heat_efficency * 4.25)
- var/energy_released = heat_efficency * HALON_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB)
- return REACTING
-
-
-/**
- * Halon Combustion:
- *
- * Consumes a large amount of oxygen relative to the amount of halon consumed.
- * Produces carbon dioxide.
- * Endothermic.
- */
-/datum/gas_reaction/halon_o2removal
- priority_group = PRIORITY_PRE_FORMATION
- name = "Halon Oxygen Absorption"
- id = "halon_o2removal"
- desc = "Halon interaction with oxygen that can be used to snuff fires out."
-
-/datum/gas_reaction/halon_o2removal/init_reqs()
- requirements = list(
- /datum/gas/halon = MINIMUM_MOLE_COUNT,
- /datum/gas/oxygen = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST,
- )
-
-/datum/gas_reaction/halon_o2removal/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
-
- var/heat_efficency = min(temperature / ( FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 10), cached_gases[/datum/gas/halon][MOLES], cached_gases[/datum/gas/oxygen][MOLES] * INVERSE(20))
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/halon][MOLES] - heat_efficency < 0 ) || (cached_gases[/datum/gas/oxygen][MOLES] - heat_efficency * 20 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/carbon_dioxide, air)
- cached_gases[/datum/gas/halon][MOLES] -= heat_efficency
- cached_gases[/datum/gas/oxygen][MOLES] -= heat_efficency * 20
- cached_gases[/datum/gas/carbon_dioxide][MOLES] += heat_efficency * 5
-
- SET_REACTION_RESULTS(heat_efficency * 5)
- var/energy_used = heat_efficency * HALON_COMBUSTION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)
- return REACTING
-
-
-// Healium
-
-/**
- * Healium Formation:
- *
- * Exothermic
- */
-/datum/gas_reaction/healium_formation
- priority_group = PRIORITY_FORMATION
- name = "Healium Formation"
- id = "healium_formation"
- desc = "Production of healium using BZ and freon."
-
-/datum/gas_reaction/healium_formation/init_reqs()
- requirements = list(
- /datum/gas/bz = MINIMUM_MOLE_COUNT,
- /datum/gas/freon = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = HEALIUM_FORMATION_MIN_TEMP,
- "MAX_TEMP" = HEALIUM_FORMATION_MAX_TEMP,
- )
-
-/datum/gas_reaction/healium_formation/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
- var/heat_efficency = min(temperature * 0.3, cached_gases[/datum/gas/freon][MOLES] * INVERSE(2.75), cached_gases[/datum/gas/bz][MOLES] * INVERSE(0.25))
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/freon][MOLES] - heat_efficency * 2.75 < 0 ) || (cached_gases[/datum/gas/bz][MOLES] - heat_efficency * 0.25 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/healium, air)
- cached_gases[/datum/gas/freon][MOLES] -= heat_efficency * 2.75
- cached_gases[/datum/gas/bz][MOLES] -= heat_efficency * 0.25
- cached_gases[/datum/gas/healium][MOLES] += heat_efficency * 3
-
- SET_REACTION_RESULTS(heat_efficency * 3)
- var/energy_released = heat_efficency * HEALIUM_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB)
- return REACTING
-
-/**
- * Zauker Formation:
- *
- * Exothermic.
- * Requires Hypernoblium.
- */
-/datum/gas_reaction/zauker_formation
- priority_group = PRIORITY_FORMATION
- name = "Zauker Formation"
- id = "zauker_formation"
- desc = "Production of zauker using hyper-noblium and nitrium under very high temperatures."
-
-/datum/gas_reaction/zauker_formation/init_reqs()
- requirements = list(
- /datum/gas/hypernoblium = MINIMUM_MOLE_COUNT,
- /datum/gas/nitrium = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = ZAUKER_FORMATION_MIN_TEMPERATURE,
- "MAX_TEMP" = ZAUKER_FORMATION_MAX_TEMPERATURE,
- )
-
-/datum/gas_reaction/zauker_formation/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
-
- var/heat_efficency = min(temperature * ZAUKER_FORMATION_TEMPERATURE_SCALE, cached_gases[/datum/gas/hypernoblium][MOLES] * INVERSE(0.01), cached_gases[/datum/gas/nitrium][MOLES] * INVERSE(0.5))
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/hypernoblium][MOLES] - heat_efficency * 0.01 < 0 ) || (cached_gases[/datum/gas/nitrium][MOLES] - heat_efficency * 0.5 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/zauker, air)
- cached_gases[/datum/gas/hypernoblium][MOLES] -= heat_efficency * 0.01
- cached_gases[/datum/gas/nitrium][MOLES] -= heat_efficency * 0.5
- cached_gases[/datum/gas/zauker][MOLES] += heat_efficency * 0.5
-
- SET_REACTION_RESULTS(heat_efficency * 0.5)
- var/energy_used = heat_efficency * ZAUKER_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity - energy_used) / new_heat_capacity), TCMB)
- return REACTING
-
-
-/**
- * Zauker Decomposition:
- *
- * Occurs in the presence of nitrogen to prevent zauker floods.
- * Exothermic.
- */
-/datum/gas_reaction/zauker_decomp
- priority_group = PRIORITY_POST_FORMATION
- name = "Zauker Decomposition"
- id = "zauker_decomp"
- desc = "Decomposition of zauker when exposed to nitrogen."
-
-/datum/gas_reaction/zauker_decomp/init_reqs()
- requirements = list(
- /datum/gas/nitrogen = MINIMUM_MOLE_COUNT,
- /datum/gas/zauker = MINIMUM_MOLE_COUNT,
- )
-
-/datum/gas_reaction/zauker_decomp/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
- var/burned_fuel = min(ZAUKER_DECOMPOSITION_MAX_RATE, cached_gases[/datum/gas/nitrogen][MOLES], cached_gases[/datum/gas/zauker][MOLES])
- if (burned_fuel <= 0 || cached_gases[/datum/gas/zauker][MOLES] - burned_fuel < 0)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/zauker][MOLES] -= burned_fuel
- ASSERT_GAS(/datum/gas/oxygen, air)
- cached_gases[/datum/gas/oxygen][MOLES] += burned_fuel * 0.3
- ASSERT_GAS(/datum/gas/nitrogen, air)
- cached_gases[/datum/gas/nitrogen][MOLES] += burned_fuel * 0.7
-
- SET_REACTION_RESULTS(burned_fuel)
- var/energy_released = ZAUKER_DECOMPOSITION_ENERGY * burned_fuel
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max((air.temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)
- return REACTING
-
-
-// Proto-Nitrate
-
-/**
- * Proto-Nitrate formation:
- *
- * Exothermic.
- */
-/datum/gas_reaction/proto_nitrate_formation
- priority_group = PRIORITY_FORMATION
- name = "Proto Nitrate Formation"
- id = "proto_nitrate_formation"
- desc = "Production of proto-nitrate from pluoxium and hydrogen under high temperatures."
-
-/datum/gas_reaction/proto_nitrate_formation/init_reqs()
- requirements = list(
- /datum/gas/pluoxium = MINIMUM_MOLE_COUNT,
- /datum/gas/hydrogen = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = PN_FORMATION_MIN_TEMPERATURE,
- "MAX_TEMP" = PN_FORMATION_MAX_TEMPERATURE,
- )
-
-/datum/gas_reaction/proto_nitrate_formation/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
-
- var/heat_efficency = min(temperature * 0.005, cached_gases[/datum/gas/pluoxium][MOLES] * INVERSE(0.2), cached_gases[/datum/gas/hydrogen][MOLES] * INVERSE(2))
- if (heat_efficency <= 0 || (cached_gases[/datum/gas/pluoxium][MOLES] - heat_efficency * 0.2 < 0 ) || (cached_gases[/datum/gas/hydrogen][MOLES] - heat_efficency * 2 < 0)) //Shouldn't produce gas from nothing.
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- ASSERT_GAS(/datum/gas/proto_nitrate, air)
- cached_gases[/datum/gas/hydrogen][MOLES] -= heat_efficency * 2
- cached_gases[/datum/gas/pluoxium][MOLES] -= heat_efficency * 0.2
- cached_gases[/datum/gas/proto_nitrate][MOLES] += heat_efficency * 2.2
-
- SET_REACTION_RESULTS(heat_efficency * 2.2)
- var/energy_released = heat_efficency * PN_FORMATION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB)
- return REACTING
-
-/**
- * Proto-Nitrate Hydrogen Conversion
- *
- * Converts hydrogen into proto-nitrate.
- * Endothermic.
- */
-/datum/gas_reaction/proto_nitrate_hydrogen_response
- priority_group = PRIORITY_PRE_FORMATION
- name = "Proto Nitrate Hydrogen Response"
- id = "proto_nitrate_hydrogen_response"
- desc = "Conversion of hydrogen into proto nitrate."
-
-/datum/gas_reaction/proto_nitrate_hydrogen_response/init_reqs()
- requirements = list(
- /datum/gas/proto_nitrate = MINIMUM_MOLE_COUNT,
- /datum/gas/hydrogen = PN_HYDROGEN_CONVERSION_THRESHOLD,
- )
-
-/datum/gas_reaction/proto_nitrate_hydrogen_response/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/produced_amount = min(PN_HYDROGEN_CONVERSION_MAX_RATE, cached_gases[/datum/gas/hydrogen][MOLES], cached_gases[/datum/gas/proto_nitrate][MOLES])
- if (produced_amount <= 0 || cached_gases[/datum/gas/hydrogen][MOLES] - produced_amount < 0)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/hydrogen][MOLES] -= produced_amount
- cached_gases[/datum/gas/proto_nitrate][MOLES] += produced_amount * 0.5
-
- SET_REACTION_RESULTS(produced_amount * 0.5)
- var/energy_used = produced_amount * PN_HYDROGEN_CONVERSION_ENERGY
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max((air.temperature * old_heat_capacity - energy_used) / new_heat_capacity, TCMB)
- return REACTING
-
-/**
- * Proto-Nitrate Tritium De-irradiation
- *
- * Converts tritium to hydrogen.
- * Releases radiation.
- * Exothermic.
- */
-/datum/gas_reaction/proto_nitrate_tritium_response
- priority_group = PRIORITY_PRE_FORMATION
- name = "Proto Nitrate Tritium Response"
- id = "proto_nitrate_tritium_response"
- desc = "Conversion of tritium into hydrogen that consumes a small amount of proto-nitrate."
-
-/datum/gas_reaction/proto_nitrate_tritium_response/init_reqs()
- requirements = list(
- /datum/gas/proto_nitrate = MINIMUM_MOLE_COUNT,
- /datum/gas/tritium = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = PN_TRITIUM_CONVERSION_MIN_TEMP,
- "MAX_TEMP" = PN_TRITIUM_CONVERSION_MAX_TEMP,
- )
-
-/datum/gas_reaction/proto_nitrate_tritium_response/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
- var/produced_amount = min(air.temperature / 34 * (cached_gases[/datum/gas/tritium][MOLES] * cached_gases[/datum/gas/proto_nitrate][MOLES]) / (cached_gases[/datum/gas/tritium][MOLES] + 10 * cached_gases[/datum/gas/proto_nitrate][MOLES]), cached_gases[/datum/gas/tritium][MOLES], cached_gases[/datum/gas/proto_nitrate][MOLES] * INVERSE(0.01))
- if(cached_gases[/datum/gas/tritium][MOLES] - produced_amount < 0 || cached_gases[/datum/gas/proto_nitrate][MOLES] - produced_amount * 0.01 < 0)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/proto_nitrate][MOLES] -= produced_amount * 0.01
- cached_gases[/datum/gas/tritium][MOLES] -= produced_amount
- ASSERT_GAS(/datum/gas/hydrogen, air)
- cached_gases[/datum/gas/hydrogen][MOLES] += produced_amount
-
- SET_REACTION_RESULTS(produced_amount)
- var/turf/open/location
- var/energy_released = produced_amount * PN_TRITIUM_CONVERSION_ENERGY
- if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet.
- var/datum/pipeline/pipenet = holder
- location = pick(pipenet.members)
- else if(isatom(holder))
- location = holder
- if (location && energy_released > PN_BZASE_RAD_RELEASE_THRESHOLD * (air.volume / CELL_VOLUME) ** ATMOS_RADIATION_VOLUME_EXP)
- radiation_pulse(location, max_range = min(sqrt(produced_amount) / PN_TRITIUM_RAD_RANGE_DIVISOR, 20), threshold = PN_TRITIUM_RAD_THRESHOLD_BASE * INVERSE(PN_TRITIUM_RAD_THRESHOLD_BASE + produced_amount), chance = 50)
-
- if(energy_released)
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max((temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)
- return REACTING
-
-/**
- * Proto-Nitrate BZase Action
- *
- * Breaks BZ down into nitrogen, helium, and plasma in the presence of proto-nitrate.
- */
-/datum/gas_reaction/proto_nitrate_bz_response
- priority_group = PRIORITY_PRE_FORMATION
- name = "Proto Nitrate BZ Response"
- id = "proto_nitrate_bz_response"
- desc = "Breakdown of BZ into nitrogen, helium, and plasma by proto-nitrate under low temperatures."
-
-/datum/gas_reaction/proto_nitrate_bz_response/init_reqs()
- requirements = list(
- /datum/gas/proto_nitrate = MINIMUM_MOLE_COUNT,
- /datum/gas/bz = MINIMUM_MOLE_COUNT,
- "MIN_TEMP" = PN_BZASE_MIN_TEMP,
- "MAX_TEMP" = PN_BZASE_MAX_TEMP,
- )
-
-/datum/gas_reaction/proto_nitrate_bz_response/react(datum/gas_mixture/air, datum/holder)
- var/list/cached_gases = air.gases
- var/temperature = air.temperature
- var/consumed_amount = min(air.temperature / 2240 * cached_gases[/datum/gas/bz][MOLES] * cached_gases[/datum/gas/proto_nitrate][MOLES] / (cached_gases[/datum/gas/bz][MOLES] + cached_gases[/datum/gas/proto_nitrate][MOLES]), cached_gases[/datum/gas/bz][MOLES], cached_gases[/datum/gas/proto_nitrate][MOLES])
- if (consumed_amount <= 0 || cached_gases[/datum/gas/bz][MOLES] - consumed_amount < 0)
- return NO_REACTION
-
- var/old_heat_capacity = air.heat_capacity()
- cached_gases[/datum/gas/bz][MOLES] -= consumed_amount
- ASSERT_GAS(/datum/gas/nitrogen, air)
- cached_gases[/datum/gas/nitrogen][MOLES] += consumed_amount * 0.4
- ASSERT_GAS(/datum/gas/helium, air)
- cached_gases[/datum/gas/helium][MOLES] += consumed_amount * 1.6
- ASSERT_GAS(/datum/gas/plasma, air)
- cached_gases[/datum/gas/plasma][MOLES] += consumed_amount * 0.8
-
- SET_REACTION_RESULTS(consumed_amount)
- var/turf/open/location
- var/energy_released = consumed_amount * PN_BZASE_ENERGY
- if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet.
- var/datum/pipeline/pipenet = holder
- location = pick(pipenet.members)
- else if(isatom(holder))
- location = holder
- if (location && energy_released > PN_TRITIUM_CONVERSION_RAD_RELEASE_THRESHOLD * (air.volume / CELL_VOLUME) ** ATMOS_RADIATION_VOLUME_EXP)
- radiation_pulse(location, max_range = min(sqrt(consumed_amount) / PN_BZASE_RAD_RANGE_DIVISOR, 20), threshold = PN_BZASE_RAD_THRESHOLD_BASE * INVERSE(PN_BZASE_RAD_THRESHOLD_BASE + consumed_amount), chance = 50)
- for(var/mob/living/carbon/L in location)
- L.hallucination += consumed_amount
-
- var/new_heat_capacity = air.heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max((temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB)
- return REACTING
-
-#undef SET_REACTION_RESULTS
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 66227aa3098..e733948234b 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -53,16 +53,19 @@
#define AALARM_MODE_SCRUBBING 1
#define AALARM_MODE_VENTING 2 //makes draught
-#define AALARM_MODE_PANIC 3 //like siphon, but stronger (enables widenet)
+#define AALARM_MODE_PANIC 3 //like siphon, but stronger (enables quicksucc)
#define AALARM_MODE_REPLACEMENT 4 //sucks off all air, then refill and swithes to scrubbing
#define AALARM_MODE_OFF 5
#define AALARM_MODE_FLOOD 6 //Emagged mode; turns off scrubbers and pressure checks on vents
#define AALARM_MODE_SIPHON 7 //Scrubbers suck air
-#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and widenet scrubbing.
+#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and quicksucc scrubbing.
#define AALARM_MODE_REFILL 9 //just like normal, but with triple the air output
#define AALARM_REPORT_TIMEOUT 100
+#define AALARM_THERMOSTAT_HEATING_POWER 40000 //T2 space heater
+#define AALARM_THERMOSTAT_HEATING_EFFICIENCY 30000 //T2 space heater
+
/obj/machinery/airalarm
name = "air alarm"
desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous."
@@ -79,45 +82,57 @@
var/danger_level = 0
var/mode = AALARM_MODE_SCRUBBING
+
+ //Fire alarm related vars//
+
+ ///The fire alert type currently active
+ var/alert_type = FIRE_CLEAR
///A reference to the area we are in
var/area/my_area
+ ///The loopingsound for when there's shit fucky
+ var/datum/looping_sound/firealarm/soundloop
var/locked = TRUE
var/aidisabled = 0
var/shorted = 0
var/buildstage = AIRALARM_BUILD_COMPLETE // 2 = complete, 1 = no wires, 0 = circuit gone
+ ///How far the thermostat may deviate from T2OC
+ var/thermostat_deviation_max = 20
+ ///The current thermostat target temp
+ var/thermostat_target = T20C
+
var/frequency = FREQ_ATMOS_CONTROL
var/alarm_frequency = FREQ_ATMOS_ALARMS
var/datum/radio_frequency/radio_connection
///Represents a signel source of atmos alarms, complains to all the listeners if one of our thresholds is violated
var/datum/alarm_handler/alarm_manager
- var/static/list/atmos_connections = list(COMSIG_TURF_EXPOSE = .proc/check_air_dangerlevel)
-
- var/list/TLV = list( // Breathable air.
- "pressure" = new/datum/tlv(HAZARD_LOW_PRESSURE, WARNING_LOW_PRESSURE, WARNING_HIGH_PRESSURE, HAZARD_HIGH_PRESSURE), // kPa. Values are hazard_min, warning_min, warning_max, hazard_max
+ var/list/datum/tlv/TLV = list(
+ "pressure" = new/datum/tlv(HAZARD_LOW_PRESSURE, WARNING_LOW_PRESSURE, WARNING_HIGH_PRESSURE, HAZARD_HIGH_PRESSURE),
"temperature" = new/datum/tlv(BODYTEMP_COLD_WARNING_1, BODYTEMP_COLD_WARNING_1+10, BODYTEMP_HEAT_WARNING_1-27, BODYTEMP_HEAT_WARNING_1),
- /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
- /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
- /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
- /datum/gas/miasma = new/datum/tlv/(-1, -1, 15, 30),
- /datum/gas/plasma = new/datum/tlv/dangerous,
- /datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
- /datum/gas/bz = new/datum/tlv/dangerous,
- /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
- /datum/gas/water_vapor = new/datum/tlv/dangerous,
- /datum/gas/tritium = new/datum/tlv/dangerous,
- /datum/gas/nitrium = new/datum/tlv/dangerous,
- /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
- /datum/gas/freon = new/datum/tlv/dangerous,
- /datum/gas/hydrogen = new/datum/tlv/dangerous,
- /datum/gas/healium = new/datum/tlv/dangerous,
- /datum/gas/proto_nitrate = new/datum/tlv/dangerous,
- /datum/gas/zauker = new/datum/tlv/dangerous,
- /datum/gas/helium = new/datum/tlv/dangerous,
- /datum/gas/antinoblium = new/datum/tlv/dangerous,
- /datum/gas/halon = new/datum/tlv/dangerous
+ GAS_OXYGEN = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ GAS_NITROGEN = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_CO2 = new/datum/tlv(-1, -1, 5, 10),
+ GAS_PLASMA = new/datum/tlv/dangerous,
+ GAS_N2O = new/datum/tlv/dangerous,
+ GAS_METHYL_BROMIDE = new/datum/tlv/dangerous,
+ GAS_METHANE = new/datum/tlv/dangerous,
+ GAS_HYDROGEN = new/datum/tlv/dangerous,
+ GAS_CHLORINE = new/datum/tlv/dangerous,
+ GAS_CO = new/datum/tlv/dangerous,
+ GAS_NO2 = new/datum/tlv/dangerous,
+ GAS_XENON = new/datum/tlv/dangerous,
+ GAS_TRITIUM = new/datum/tlv/dangerous,
+ GAS_DEUTERIUM = new/datum/tlv/dangerous,
+ GAS_METHANE = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_HELIUM = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_KRYPTON = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_NEON = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_NO = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_STEAM = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_SULFUR = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_ARGON = new/datum/tlv(-1, -1, 1000, 1000),
)
/obj/machinery/airalarm/Initialize(mapload, ndir, nbuild)
@@ -134,25 +149,59 @@
name = "[get_area_name(src)] Air Alarm"
alarm_manager = new(src)
- my_area = get_area(src)
+ soundloop = new(src, FALSE)
+ RegisterSignal(src, COMSIG_FIRE_ALERT, .proc/handle_alert)
update_appearance()
set_frequency(frequency)
- AddElement(/datum/element/connect_loc, atmos_connections)
AddComponent(/datum/component/usb_port, list(
/obj/item/circuit_component/air_alarm,
))
-
-
+ SSairmachines.start_processing_machine(src)
+
+ /*
+ if(mapload)
+ var/turf/my_turf = get_turf(src)
+ if(my_turf && (initial(my_turf.temperature) != T20C))
+ var/difftemp = T20C - initial(my_turf.temperature)
+ TLV["temperature"].warning_min -= difftemp
+ TLV["temperature"].hazard_min -= difftemp
+ TLV["temperature"].warning_max -= difftemp
+ TLV["temperature"].hazard_max -= difftemp
+ */
+
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/machinery/airalarm/LateInitialize()
+ . = ..()
+ set_area(get_area(src))
/obj/machinery/airalarm/Destroy()
- if(my_area)
- my_area = null
+ set_area(null)
SSradio.remove_object(src, frequency)
+ SSairmachines.stop_processing_machine(src)
QDEL_NULL(wires)
QDEL_NULL(alarm_manager)
+ QDEL_NULL(soundloop)
return ..()
+/obj/machinery/airalarm/Moved(atom/OldLoc, Dir)
+ . = ..()
+ var/new_area = get_area(src)
+ if(my_area != new_area)
+ set_area(new_area)
+
+/obj/machinery/airalarm/proc/set_area(new_area)
+ SHOULD_NOT_SLEEP(TRUE)
+
+ if(my_area)
+ LAZYREMOVE(my_area.airalarms, src)
+ if(!new_area)
+ return
+ my_area = new_area
+ if(my_area)
+ LAZYADD(my_area.airalarms, src)
+
/obj/machinery/airalarm/examine(mob/user)
. = ..()
switch(buildstage)
@@ -185,15 +234,15 @@
"danger_level" = danger_level,
)
- data["atmos_alarm"] = !!my_area.active_alarms[ALARM_ATMOS]
- data["fire_alarm"] = my_area.fire
+ data["atmos_alarm"] = !!my_area.active_alarms[ALARM_ATMOS] //Casting to boolean
+ data["fire_alarm"] = !!alert_type //Same here
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.return_air()
var/datum/tlv/cur_tlv
data["environment_data"] = list()
- var/pressure = environment.return_pressure()
+ var/pressure = environment.returnPressure()
cur_tlv = TLV["pressure"]
data["environment_data"] += list(list(
"name" = "Pressure",
@@ -209,19 +258,24 @@
"unit" = "K ([round(temperature - T0C, 0.1)]C)",
"danger_level" = cur_tlv.get_danger_level(temperature)
))
- var/total_moles = environment.total_moles()
+ var/total_moles = environment.get_moles()
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
- for(var/gas_id in environment.gases)
+ for(var/gas_id in environment.gas)
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
continue
cur_tlv = TLV[gas_id]
data["environment_data"] += list(list(
- "name" = environment.gases[gas_id][GAS_META][META_GAS_NAME],
- "value" = environment.gases[gas_id][MOLES] / total_moles * 100,
+ "name" = xgm_gas_data.name[gas_id],
+ "value" = environment.gas[gas_id] / total_moles * 100,
"unit" = "%",
- "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id][MOLES] * partial_pressure)
+ "danger_level" = cur_tlv.get_danger_level(environment.gas[gas_id]* partial_pressure)
))
+ data["thermostat"] = list(
+ "deviation" = thermostat_deviation_max,
+ "target" = thermostat_target - T0C //Convert kelvin to Celsius for the UI
+ )
+
if(!locked || user.has_unlimited_silicon_privilege)
data["vents"] = list()
for(var/id_tag in my_area.air_vent_info)
@@ -253,7 +307,7 @@
"long_name" = sanitize(long_name),
"power" = info["power"],
"scrubbing" = info["scrubbing"],
- "widenet" = info["widenet"],
+ "quicksucc" = info["quicksucc"],
"filter_types" = info["filter_types"]
))
data["mode"] = mode
@@ -286,11 +340,11 @@
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "warning_max", "selected" = selected.warning_max))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "hazard_max", "selected" = selected.hazard_max))
- for(var/gas_id in GLOB.meta_gas_info)
+ for(var/gas_id in ASSORTED_GASES)
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
continue
selected = TLV[gas_id]
- thresholds += list(list("name" = GLOB.meta_gas_info[gas_id][META_GAS_NAME], "settings" = list()))
+ thresholds += list(list("name" = xgm_gas_data.name[gas_id], "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "hazard_min", "selected" = selected.hazard_min))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "warning_min", "selected" = selected.warning_min))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "warning_max", "selected" = selected.warning_max))
@@ -304,6 +358,15 @@
if(. || buildstage != AIRALARM_BUILD_COMPLETE)
return
+
+ if(action == "target") //Setting the thermostat doesn't require any access
+ var/target = text2num(params["target"])
+ if(target != null)
+ thermostat_target = target
+ . = TRUE
+ thermostat_target = clamp(target, 20 - thermostat_deviation_max, 20 + thermostat_deviation_max)
+ thermostat_target += T0C //Convert back to Kelvin //-270.45 is TCMB
+
if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled))
return
var/device_id = params["id_tag"]
@@ -312,7 +375,7 @@
if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
. = TRUE
- if("power", "toggle_filter", "widenet", "scrubbing", "direction")
+ if("power", "toggle_filter", "quicksucc", "scrubbing", "direction")
send_signal(device_id, list("[action]" = params["val"]), usr)
. = TRUE
if("excheck")
@@ -350,7 +413,7 @@
investigate_log(" treshold value for [env]:[name] was set to [value] by [key_name(usr)]",INVESTIGATE_ATMOS)
var/turf/our_turf = get_turf(src)
var/datum/gas_mixture/environment = our_turf.return_air()
- check_air_dangerlevel(our_turf, environment, environment.temperature)
+ check_air_dangerlevel(environment)
. = TRUE
if("mode")
mode = text2num(params["mode"])
@@ -365,6 +428,10 @@
if(alarm_manager.clear_alarm(ALARM_ATMOS))
post_alert(0)
. = TRUE
+ if("fire_alarm")
+ my_area.communicate_fire_alert(alert_type ? FIRE_CLEAR : FIRE_RAISED_AIRALARM)
+ . = TRUE
+
update_appearance()
@@ -436,9 +503,9 @@
for(var/device_id in my_area.air_scrub_info)
send_signal(device_id, list(
"power" = 1,
- "set_filters" = list(/datum/gas/carbon_dioxide),
+ "set_filters" = list(GAS_CO2),
"scrubbing" = 1,
- "widenet" = 0
+ "quicksucc" = 0
), signal_source)
for(var/device_id in my_area.air_vent_info)
send_signal(device_id, list(
@@ -450,28 +517,9 @@
for(var/device_id in my_area.air_scrub_info)
send_signal(device_id, list(
"power" = 1,
- "set_filters" = list(
- /datum/gas/carbon_dioxide,
- /datum/gas/miasma,
- /datum/gas/plasma,
- /datum/gas/water_vapor,
- /datum/gas/hypernoblium,
- /datum/gas/nitrous_oxide,
- /datum/gas/nitrium,
- /datum/gas/tritium,
- /datum/gas/bz,
- /datum/gas/pluoxium,
- /datum/gas/freon,
- /datum/gas/hydrogen,
- /datum/gas/healium,
- /datum/gas/proto_nitrate,
- /datum/gas/zauker,
- /datum/gas/helium,
- /datum/gas/antinoblium,
- /datum/gas/halon,
- ),
+ "set_filters" = ASSORTED_GASES,
"scrubbing" = 1,
- "widenet" = 1
+ "quicksucc" = 1
), signal_source)
for(var/device_id in my_area.air_vent_info)
send_signal(device_id, list(
@@ -483,7 +531,7 @@
for(var/device_id in my_area.air_scrub_info)
send_signal(device_id, list(
"power" = 1,
- "widenet" = 0,
+ "quicksucc" = 0,
"scrubbing" = 0
), signal_source)
for(var/device_id in my_area.air_vent_info)
@@ -496,9 +544,9 @@
for(var/device_id in my_area.air_scrub_info)
send_signal(device_id, list(
"power" = 1,
- "set_filters" = list(/datum/gas/carbon_dioxide),
+ "set_filters" = list(GAS_CO2),
"scrubbing" = 1,
- "widenet" = 0
+ "quicksucc" = 0
), signal_source)
for(var/device_id in my_area.air_vent_info)
send_signal(device_id, list(
@@ -511,7 +559,7 @@
for(var/device_id in my_area.air_scrub_info)
send_signal(device_id, list(
"power" = 1,
- "widenet" = 1,
+ "quicksucc" = 1,
"scrubbing" = 0
), signal_source)
for(var/device_id in my_area.air_vent_info)
@@ -522,7 +570,7 @@
for(var/device_id in my_area.air_scrub_info)
send_signal(device_id, list(
"power" = 1,
- "widenet" = 0,
+ "quicksucc" = 0,
"scrubbing" = 0
), signal_source)
for(var/device_id in my_area.air_vent_info)
@@ -560,7 +608,9 @@
var/area/our_area = get_area(src)
var/color
- switch(max(danger_level, !!our_area.active_alarms[ALARM_ATMOS]))
+ var/alert = max(danger_level, !!our_area.active_alarms[ALARM_ATMOS])
+ alert ||= !!alert_type //Fires should only display yellow alerts
+ switch(alert)
if(0)
color = "#03A728" // green
if(1)
@@ -592,7 +642,10 @@
var/area/our_area = get_area(src)
var/state
- switch(max(danger_level, !!our_area.active_alarms[ALARM_ATMOS]))
+
+ var/alert = max(danger_level, !!our_area.active_alarms[ALARM_ATMOS])
+ alert ||= !!alert_type //Fires should only display yellow alerts
+ switch(alert)
if(0)
state = "alarm0"
if(1)
@@ -603,38 +656,77 @@
. += mutable_appearance(icon, state)
. += emissive_appearance(icon, state, alpha = src.alpha)
+/obj/machinery/airalarm/fire_act(exposed_temperature, exposed_volume)
+ . = ..()
+ if(!danger_level)
+ check_air_dangerlevel(loc.return_air())
+
+/obj/machinery/airalarm/process_atmos()
+ if((machine_stat & (NOPOWER|BROKEN)) || shorted)
+ return
+
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ check_air_dangerlevel(loc.return_air())
+
+ if(!my_area.apc?.terminal)
+ COOLDOWN_START(src, hibernating, 5 SECONDS)
+ return
+
+ var/obj/machinery/power/terminal/local_term = my_area.apc.terminal
+
+ var/heat_capacity = environment.getHeatCapacity()
+
+ if(!heat_capacity) //No air
+ return
+
+ var/required_energy = abs(environment.temperature - thermostat_target) * heat_capacity
+ required_energy = min(required_energy, AALARM_THERMOSTAT_HEATING_POWER)
+
+ if(required_energy < 1 && !danger_level)
+ COOLDOWN_START(src, hibernating, 5 SECONDS)
+ return
+
+ var/delta_temperature = required_energy / heat_capacity
+ if(!delta_temperature)
+ return
+
+ if(environment.temperature > thermostat_target)
+ delta_temperature *= -1
+
+ var/energy2use = required_energy / AALARM_THERMOSTAT_HEATING_EFFICIENCY
+ if(!local_term.avail(energy2use))
+ return
+
+ local_term.use_power(energy2use)
+ environment.temperature += delta_temperature
+
/**
* main proc for throwing a shitfit if the air isnt right.
* goes into warning mode if gas parameters are beyond the tlv warning bounds, goes into hazard mode if gas parameters are beyond tlv hazard bounds
*
*/
-/obj/machinery/airalarm/proc/check_air_dangerlevel(turf/location, datum/gas_mixture/environment, exposed_temperature)
- SIGNAL_HANDLER
- if((machine_stat & (NOPOWER|BROKEN)) || shorted)
- return
-
+/obj/machinery/airalarm/proc/check_air_dangerlevel(datum/gas_mixture/environment)
var/datum/tlv/current_tlv
//cache for sanic speed (lists are references anyways)
var/list/cached_tlv = TLV
- var/list/env_gases = environment.gases
- var/partial_pressure = R_IDEAL_GAS_EQUATION * exposed_temperature / environment.volume
+ var/list/env_gases = environment.gas
+ //var/partial_pressure = R_IDEAL_GAS_EQUATION * exposed_temperature / environment.volume
current_tlv = cached_tlv["pressure"]
- var/environment_pressure = environment.return_pressure()
+ var/environment_pressure = environment.returnPressure()
var/pressure_dangerlevel = current_tlv.get_danger_level(environment_pressure)
current_tlv = cached_tlv["temperature"]
- var/temperature_dangerlevel = current_tlv.get_danger_level(exposed_temperature)
+ var/temperature_dangerlevel = current_tlv.get_danger_level(environment.temperature)
var/gas_dangerlevel = 0
for(var/gas_id in env_gases)
if(!(gas_id in cached_tlv)) // We're not interested in this gas, it seems.
continue
current_tlv = cached_tlv[gas_id]
- gas_dangerlevel = max(gas_dangerlevel, current_tlv.get_danger_level(env_gases[gas_id][MOLES] * partial_pressure))
-
- environment.garbage_collect()
+ gas_dangerlevel = max(gas_dangerlevel, current_tlv.get_danger_level(environment.gas[gas_id]))
var/old_danger_level = danger_level
danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel)
@@ -648,7 +740,7 @@
/obj/machinery/airalarm/proc/post_alert(alert_level)
var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency)
-
+ my_area.communicate_fire_alert(alert_level ? FIRE_RAISED_AIRALARM : FIRE_CLEAR)
if(!frequency)
return
@@ -668,7 +760,7 @@
/obj/machinery/airalarm/proc/apply_danger_level()
var/new_area_danger_level = 0
- for(var/obj/machinery/airalarm/AA in my_area)
+ for(var/obj/machinery/airalarm/AA in my_area?.airalarms)
if (!(AA.machine_stat & (NOPOWER|BROKEN)) && !AA.shorted)
new_area_danger_level = clamp(max(new_area_danger_level, AA.danger_level), 0, 1)
@@ -677,6 +769,7 @@
did_anything_happen = alarm_manager.send_alarm(ALARM_ATMOS)
else
did_anything_happen = alarm_manager.clear_alarm(ALARM_ATMOS)
+
if(did_anything_happen) //if something actually changed
post_alert(new_area_danger_level)
@@ -836,53 +929,26 @@
TLV = list(
"pressure" = new/datum/tlv/no_checks,
"temperature" = new/datum/tlv/no_checks,
- /datum/gas/oxygen = new/datum/tlv/no_checks,
- /datum/gas/nitrogen = new/datum/tlv/no_checks,
- /datum/gas/carbon_dioxide = new/datum/tlv/no_checks,
- /datum/gas/miasma = new/datum/tlv/no_checks,
- /datum/gas/plasma = new/datum/tlv/no_checks,
- /datum/gas/nitrous_oxide = new/datum/tlv/no_checks,
- /datum/gas/bz = new/datum/tlv/no_checks,
- /datum/gas/hypernoblium = new/datum/tlv/no_checks,
- /datum/gas/water_vapor = new/datum/tlv/no_checks,
- /datum/gas/tritium = new/datum/tlv/no_checks,
- /datum/gas/nitrium = new/datum/tlv/no_checks,
- /datum/gas/pluoxium = new/datum/tlv/no_checks,
- /datum/gas/freon = new/datum/tlv/no_checks,
- /datum/gas/hydrogen = new/datum/tlv/no_checks,
- /datum/gas/healium = new/datum/tlv/dangerous,
- /datum/gas/proto_nitrate = new/datum/tlv/dangerous,
- /datum/gas/zauker = new/datum/tlv/dangerous,
- /datum/gas/helium = new/datum/tlv/dangerous,
- /datum/gas/antinoblium = new/datum/tlv/dangerous,
- /datum/gas/halon = new/datum/tlv/dangerous,
+ GAS_OXYGEN = new/datum/tlv/no_checks,
+ GAS_NITROGEN = new/datum/tlv/no_checks,
+ GAS_CO2 = new/datum/tlv/no_checks,
+ GAS_PLASMA = new/datum/tlv/no_checks,
+ GAS_N2O = new/datum/tlv/no_checks,
)
+ thermostat_target = 80
+ thermostat_deviation_max = 250
/obj/machinery/airalarm/kitchen_cold_room // Kitchen cold rooms start off at -14°C or 259.15K.
TLV = list(
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE * 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(COLD_ROOM_TEMP-40, COLD_ROOM_TEMP-20, COLD_ROOM_TEMP+20, COLD_ROOM_TEMP+40),
- /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
- /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
- /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
- /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
- /datum/gas/plasma = new/datum/tlv/dangerous,
- /datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
- /datum/gas/bz = new/datum/tlv/dangerous,
- /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
- /datum/gas/water_vapor = new/datum/tlv/dangerous,
- /datum/gas/tritium = new/datum/tlv/dangerous,
- /datum/gas/nitrium = new/datum/tlv/dangerous,
- /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
- /datum/gas/freon = new/datum/tlv/dangerous,
- /datum/gas/hydrogen = new/datum/tlv/dangerous,
- /datum/gas/healium = new/datum/tlv/dangerous,
- /datum/gas/proto_nitrate = new/datum/tlv/dangerous,
- /datum/gas/zauker = new/datum/tlv/dangerous,
- /datum/gas/helium = new/datum/tlv/dangerous,
- /datum/gas/antinoblium = new/datum/tlv/dangerous,
- /datum/gas/halon = new/datum/tlv/dangerous,
+ GAS_OXYGEN = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ GAS_NITROGEN = new/datum/tlv(-1, -1, 1000, 1000),
+ GAS_CO2 = new/datum/tlv(-1, -1, 5, 10),
+ GAS_PLASMA = new/datum/tlv/dangerous,
)
+ thermostat_target = COLD_ROOM_TEMP
+ thermostat_deviation_max = 34
/obj/machinery/airalarm/unlocked
locked = FALSE
@@ -928,8 +994,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
var/datum/port/input/request_data
var/datum/port/output/pressure
- var/datum/port/output/temperature
var/datum/port/output/gas_amount
+ var/datum/port/output/my_temperature
var/obj/machinery/airalarm/connected_alarm
var/list/options_map
@@ -942,7 +1008,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
request_data = add_input_port("Request Atmosphere Data", PORT_TYPE_SIGNAL)
pressure = add_output_port("Pressure", PORT_TYPE_NUMBER)
- temperature = add_output_port("Temperature", PORT_TYPE_NUMBER)
+ my_temperature = add_output_port("Temperature", PORT_TYPE_NUMBER)
gas_amount = add_output_port("Chosen Gas Amount", PORT_TYPE_NUMBER)
/obj/item/circuit_component/air_alarm/populate_options()
@@ -954,9 +1020,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
"Temperature" = "temperature"
)
- for(var/gas_id in GLOB.meta_gas_info)
- component_options[GLOB.meta_gas_info[gas_id][META_GAS_NAME]] = gas_id2path(gas_id)
-
+ for(var/gas_id in ASSORTED_GASES)
+ component_options |= gas_id
air_alarm_options = add_option_port("Air Alarm Options", component_options)
options_map = component_options
@@ -978,10 +1043,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
if(COMPONENT_TRIGGERED_BY(request_data, port))
var/turf/alarm_turf = get_turf(connected_alarm)
var/datum/gas_mixture/environment = alarm_turf.return_air()
- pressure.set_output(round(environment.return_pressure()))
- temperature.set_output(round(environment.temperature))
+ pressure.set_output(round(environment.returnPressure()))
+ my_temperature.set_output(round(environment.temperature))
if(ispath(options_map[current_option]))
- gas_amount.set_output(round(environment.gases[options_map[current_option]][MOLES]))
+ gas_amount.set_output(round(environment.gas[options_map[current_option]]))
return
var/datum/tlv/settings = connected_alarm.TLV[options_map[current_option]]
@@ -990,6 +1055,27 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
settings.warning_max = max_1
settings.hazard_max = max_2
+/obj/machinery/airalarm/proc/handle_alert(datum/source, code)
+ SIGNAL_HANDLER
+
+ if(alert_type == code)
+ return
+
+ switch(code)
+ if(FIRE_RAISED_AIRALARM)
+ alarm_manager.send_alarm(ALARM_FIRE)
+ soundloop.start()
+ if(FIRE_RAISED_PULL) //We will never recieve a pulled signal if we aren't currently clear
+ soundloop.start()
+ alarm_manager.send_alarm(ALARM_FIRE)
+ else
+ alarm_manager.clear_alarm(ALARM_FIRE)
+ soundloop.stop()
+
+ alert_type = code
+
+
+
#undef AALARM_MODE_SCRUBBING
#undef AALARM_MODE_VENTING
#undef AALARM_MODE_PANIC
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 10759536c12..408152718a6 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -52,13 +52,13 @@
///Whether it can be painted
var/paintable = TRUE
- ///Is the thing being rebuilt by SSair or not. Prevents list bloat
+ ///Is the thing being rebuilt by SSzas or not. Prevents list bloat
var/rebuilding = FALSE
///The bitflag that's being checked on ventcrawling. Default is to allow ventcrawling and seeing pipes.
var/vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE
-
- ///keeps the name of the object from being overridden if it's vareditted.
+
+ ///keeps the name of the object from being overridden if it's vareditted.
var/override_naming
/obj/machinery/atmospherics/LateInitialize()
@@ -83,20 +83,20 @@
armor = list(MELEE = 25, BULLET = 10, LASER = 10, ENERGY = 100, BOMB = 0, BIO = 100, FIRE = 100, ACID = 70)
..()
if(process)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
set_init_directions(init_dir)
/obj/machinery/atmospherics/Initialize(mapload)
if(mapload && name != initial(name))
override_naming = TRUE
- return ..()
+ return ..()
/obj/machinery/atmospherics/Destroy()
for(var/i in 1 to device_type)
nullify_node(i)
- SSair.stop_processing_machine(src)
- SSair.rebuild_queue -= src
+ SSairmachines.stop_processing_machine(src)
+ SSairmachines.rebuild_queue -= src
if(pipe_vision_img)
qdel(pipe_vision_img)
@@ -114,7 +114,7 @@
on = active
SEND_SIGNAL(src, COMSIG_ATMOS_MACHINE_SET_ON, on)
-/// This should only be called by SSair as part of the rebuild queue.
+/// This should only be called by SSzas as part of the rebuild queue.
/// Handles rebuilding pipelines after init or they've been changed.
/obj/machinery/atmospherics/proc/rebuild_pipes()
var/list/targets = get_rebuild_targets()
@@ -367,7 +367,7 @@
add_fingerprint(user)
var/unsafe_wrenching = FALSE
- var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
+ var/internal_pressure = int_air.returnPressure()-env_air.returnPressure()
to_chat(user, span_notice("You begin to unfasten \the [src]..."))
@@ -413,7 +413,7 @@
if(!pressures)
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
- pressures = int_air.return_pressure() - env_air.return_pressure()
+ pressures = int_air.returnPressure() - env_air.returnPressure()
user.visible_message(span_danger("[user] is sent flying by pressure!"),span_userdanger("The pressure sends you flying!"))
@@ -470,7 +470,7 @@
for(var/obj/machinery/atmospherics/A in nodes)
A.atmos_init()
A.add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
/obj/machinery/atmospherics/update_name()
if(!override_naming)
diff --git a/code/modules/atmospherics/machinery/bluespace_vendor.dm b/code/modules/atmospherics/machinery/bluespace_vendor.dm
deleted file mode 100644
index d0ab9135d61..00000000000
--- a/code/modules/atmospherics/machinery/bluespace_vendor.dm
+++ /dev/null
@@ -1,282 +0,0 @@
-/obj/item/wallframe/bluespace_vendor_mount
- name = "bluespace vendor wall mount"
- desc = "Used for placing bluespace vendors."
- icon = 'icons/obj/atmospherics/components/bluespace_gas_selling.dmi'
- icon_state = "bluespace_vendor_open"
- result_path = /obj/machinery/bluespace_vendor/built
- pixel_shift = 30
-
-///Defines for the mode of the vendor
-#define BS_MODE_OFF 1
-#define BS_MODE_IDLE 2
-#define BS_MODE_PUMPING 3
-#define BS_MODE_OPEN 4
-
-/obj/machinery/bluespace_vendor
- icon = 'icons/obj/atmospherics/components/bluespace_gas_selling.dmi'
- icon_state = "bluespace_vendor_off"
- name = "Bluespace Gas Vendor"
- desc = "Sells gas tanks with custom mixes for all the family!"
-
- max_integrity = 300
- armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 0, BIO = 100, FIRE = 80, ACID = 30)
- layer = OBJ_LAYER
-
- ///The bluespace sender that this vendor is connected to
- var/obj/machinery/atmospherics/components/unary/bluespace_sender/connected_machine
- ///Amount of usable tanks inside the machine
- var/empty_tanks = 10
- ///Reference to the current in use tank to be filled
- var/obj/item/tank/internals/generic/internal_tank
- ///Path of the gas selected from the UI to be pumped inside the tanks
- var/selected_gas
- ///Is the vendor trying to move gases from the network to the tanks?
- var/pumping = FALSE
- ///Has the user prepared a tank to be filled with gases?
- var/inserted_tank = FALSE
- ///Amount of the tank already filled with gas (from 0 to 100)
- var/tank_filling_amount = 0
- ///Base price of the tank
- var/tank_cost = 10
- ///Stores the current price of the gases inside the tank
- var/gas_price = 0
- ///Helper for mappers, will automatically connect to the sender (ensure to only place one sender per map)
- var/map_spawned = TRUE
- ///Base icon name for updating the appearance
- var/base_icon = "bluespace_vendor"
- ///Current operating mode of the vendor
- var/mode = BS_MODE_OFF
-
-//The one that the players make
-/obj/machinery/bluespace_vendor/built
- map_spawned = FALSE
- mode = BS_MODE_OPEN
-
-MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/bluespace_vendor, 30)
-
-/obj/machinery/bluespace_vendor/New(loc, ndir, nbuild)
- . = ..()
-
- if(nbuild)
- panel_open = TRUE
-
- update_appearance()
-
-/obj/machinery/bluespace_vendor/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/payment, tank_cost, SSeconomy.get_dep_account(ACCOUNT_ENG), PAYMENT_ANGRY)
-
-/obj/machinery/bluespace_vendor/LateInitialize()
- . = ..()
- if(!map_spawned)
- return
- for(var/obj/machinery/atmospherics/components/unary/bluespace_sender/sender in GLOB.machines)
- register_machine(sender)
-
-/obj/machinery/bluespace_vendor/Destroy()
- unregister_machine()
- return ..()
-
-/obj/machinery/bluespace_vendor/update_icon_state()
- switch(mode)
- if(BS_MODE_OFF)
- icon_state = "[base_icon]_off"
- if(BS_MODE_IDLE)
- icon_state = "[base_icon]_idle"
- if(BS_MODE_PUMPING)
- icon_state = "[base_icon]_pumping"
- if(BS_MODE_OPEN)
- icon_state = "[base_icon]_open"
- return ..()
-
-/obj/machinery/bluespace_vendor/Exited(atom/movable/gone, direction)
- if(gone == internal_tank)
- internal_tank = null
- return ..()
-
-/obj/machinery/bluespace_vendor/process()
- if(mode == BS_MODE_OPEN)
- return
- if(!selected_gas)
- return
- var/gas_path = gas_id2path(selected_gas)
-
- if(!connected_machine.bluespace_network.gases[gas_path])
- pumping = FALSE
- selected_gas = null
- mode = BS_MODE_IDLE
- update_appearance()
- return
-
- connected_machine.bluespace_network.pump_gas_to(internal_tank.return_air(), (tank_filling_amount * 0.01) * 10 * ONE_ATMOSPHERE, gas_path)
-
-/obj/machinery/bluespace_vendor/multitool_act(mob/living/user, obj/item/multitool/multitool)
- if(!istype(multitool))
- return
- if(!istype(multitool.buffer, /obj/machinery/atmospherics/components/unary/bluespace_sender))
- to_chat(user, span_notice("Wrong machine type in [multitool] buffer..."))
- return
- if(connected_machine)
- to_chat(user, span_notice("Changing [src] bluespace network..."))
- if(!do_after(user, 0.2 SECONDS, src))
- return
- playsound(get_turf(user), 'sound/machines/click.ogg', 10, TRUE)
- register_machine(multitool.buffer)
- to_chat(user, span_notice("You link [src] to the console in [multitool]'s buffer."))
- return TRUE
-
-/obj/machinery/bluespace_vendor/attackby(obj/item/item, mob/living/user)
- if(!pumping && default_deconstruction_screwdriver(user, "[base_icon]_open", "[base_icon]_off", item))
- check_mode()
- return
- if(default_deconstruction_crowbar(item, FALSE, custom_deconstruct = TRUE))
- new/obj/item/wallframe/bluespace_vendor_mount(user.loc)
- qdel(src)
- return
-
- if(istype(item, /obj/item/stack/sheet/iron))
- var/obj/item/stack/sheet/iron/iron = item
- if (iron.use(1))
- empty_tanks++
- return TRUE
- return ..()
-
-/obj/machinery/bluespace_vendor/examine(mob/user)
- . = ..()
- if(empty_tanks > 1)
- . += span_notice("There are currently [empty_tanks] empty tanks available, more can be made by inserting iron sheets in the machine.")
- else if(empty_tanks == 1)
- . += span_notice("There is only one empty tank available, please refill the machine by using iron sheets.")
- else
- . += span_notice("There is no available tank, please refill the machine by using iron sheets.")
-
-///Check what is the current operating mode
-/obj/machinery/bluespace_vendor/proc/check_mode()
- if(panel_open)
- mode = BS_MODE_OPEN
- else if(connected_machine)
- mode = BS_MODE_IDLE
- else
- mode = BS_MODE_OFF
- update_appearance()
-
-///Register the sender as the connected_machine
-/obj/machinery/bluespace_vendor/proc/register_machine(machine)
- connected_machine = machine
- LAZYADD(connected_machine.vendors, src)
- RegisterSignal(connected_machine, COMSIG_PARENT_QDELETING, .proc/unregister_machine)
- mode = BS_MODE_IDLE
- update_appearance()
-
-///Unregister the connected_machine (either when qdel this or the sender)
-/obj/machinery/bluespace_vendor/proc/unregister_machine()
- SIGNAL_HANDLER
- if(connected_machine)
- UnregisterSignal(connected_machine, COMSIG_PARENT_QDELETING)
- LAZYREMOVE(connected_machine.vendors, src)
- connected_machine = null
- mode = BS_MODE_OFF
- update_appearance()
-
-///Check the price of the current tank, if the user doesn't have the money the gas will be merged back into the network
-/obj/machinery/bluespace_vendor/proc/check_price(mob/user)
- var/temp_price = 0
- var/datum/gas_mixture/working_mix = internal_tank.return_air()
- var/list/gases = working_mix.gases
- for(var/gas_id in gases)
- temp_price += gases[gas_id][MOLES] * connected_machine.base_prices[gas_id]
- gas_price = temp_price
-
- if(attempt_charge(src, user, gas_price) & COMPONENT_OBJ_CANCEL_CHARGE)
- var/datum/gas_mixture/remove = working_mix.remove_ratio(1)
- connected_machine.bluespace_network.merge(remove)
- return
- connected_machine.credits_gained += gas_price + tank_cost
-
- if(internal_tank && Adjacent(user)) //proper capitalysm take money before goods
- inserted_tank = FALSE
- user.put_in_hands(internal_tank)
-
-/obj/machinery/bluespace_vendor/ui_interact(mob/user, datum/tgui/ui)
- if(!connected_machine || mode == BS_MODE_OPEN)
- return
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "BluespaceVendor", name)
- ui.open()
-
-/obj/machinery/bluespace_vendor/ui_data(mob/user)
- var/list/data = list()
- var/list/bluespace_gasdata = list()
- if(connected_machine.bluespace_network.total_moles())
- for(var/gas_id in connected_machine.bluespace_network.gases)
- bluespace_gasdata.Add(list(list(
- "name" = connected_machine.bluespace_network.gases[gas_id][GAS_META][META_GAS_NAME],
- "id" = connected_machine.bluespace_network.gases[gas_id][GAS_META][META_GAS_ID],
- "amount" = round(connected_machine.bluespace_network.gases[gas_id][MOLES], 0.01),
- "price" = connected_machine.base_prices[gas_id],
- )))
- else
- for(var/gas_id in connected_machine.bluespace_network.gases)
- bluespace_gasdata.Add(list(list(
- "name" = connected_machine.bluespace_network.gases[gas_id][GAS_META][META_GAS_NAME],
- "id" = "",
- "amount" = 0,
- "price" = 0,
- )))
- data["bluespace_network_gases"] = bluespace_gasdata
- data["pumping"] = pumping
- data["tank_filling_amount"] = tank_filling_amount
- data["selected_gas"] = selected_gas
- data["tank_amount"] = empty_tanks
- data["inserted_tank"] = inserted_tank
- var/total_tank_pressure
- if(internal_tank)
- var/datum/gas_mixture/working_mix = internal_tank.return_air()
- total_tank_pressure = working_mix.return_pressure()
- else
- total_tank_pressure = 0
- data["tank_full"] = total_tank_pressure
- return data
-
-/obj/machinery/bluespace_vendor/ui_act(action, params)
- . = ..()
- if(.)
- return
-
- if(mode == BS_MODE_OPEN)
- return
-
- switch(action)
- if("start_pumping")
- if(inserted_tank && !pumping)
- pumping = TRUE
- selected_gas = params["gas_id"]
- mode = BS_MODE_PUMPING
- update_appearance()
- . = TRUE
- if("stop_pumping")
- if(inserted_tank && pumping)
- pumping = FALSE
- selected_gas = null
- mode = BS_MODE_IDLE
- update_appearance()
- . = TRUE
- if("pumping_rate")
- tank_filling_amount = clamp(params["rate"], 0, 100)
- . = TRUE
- if("tank_prepare")
- if(empty_tanks && !inserted_tank)
- inserted_tank = TRUE
- internal_tank = new(src)
- empty_tanks = max(empty_tanks - 1, 0)
- . = TRUE
- if("tank_expel")
- if(inserted_tank && !pumping)
- check_price(usr)
- . = TRUE
-
-#undef BS_MODE_OFF
-#undef BS_MODE_IDLE
-#undef BS_MODE_PUMPING
-#undef BS_MODE_OPEN
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
index af52c1a78a8..38299c8745f 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
@@ -42,8 +42,8 @@
var/datum/gas_mixture/air1 = airs[1]
var/datum/gas_mixture/air2 = airs[2]
- var/output_starting_pressure = air1.return_pressure()
- var/input_starting_pressure = air2.return_pressure()
+ var/output_starting_pressure = air1.returnPressure()
+ var/input_starting_pressure = air2.returnPressure()
if(output_starting_pressure >= input_starting_pressure-10)
//Need at least 10 KPa difference to overcome friction in the mechanism
@@ -122,7 +122,7 @@
if(node2)
node2.atmos_init()
node2.add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
return TRUE
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index 45efa9e16e1..a1506654512 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -60,7 +60,7 @@
var/datum/gas_mixture/air2 = airs[2]
var/datum/gas_mixture/environment = loc.return_air()
- var/environment_pressure = environment.return_pressure()
+ var/environment_pressure = environment.returnPressure()
if(pump_direction) //input -> external
var/pressure_delta = 10000
@@ -68,7 +68,7 @@
if(pressure_checks&EXT_BOUND)
pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
if(pressure_checks&INPUT_MIN)
- pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
+ pressure_delta = min(pressure_delta, (air1.returnPressure() - input_pressure_min))
if(pressure_delta <= 0)
return
@@ -92,7 +92,7 @@
if(pressure_checks&EXT_BOUND)
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
if(pressure_checks&INPUT_MIN)
- pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
+ pressure_delta = min(pressure_delta, (output_pressure_max - air2.returnPressure()))
if(pressure_delta <= 0)
return
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
index f149ccfd6d6..c0c02aee01a 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
@@ -57,7 +57,13 @@ Passive gate is similar to the regular pump except:
var/datum/gas_mixture/air1 = airs[1]
var/datum/gas_mixture/air2 = airs[2]
- if(air1.release_gas_to(air2, target_pressure))
+ var/input_starting_pressure = air1.returnPressure()
+
+ var/pressure_delta = input_starting_pressure - target_pressure
+
+ var/transfer_moles = (target_pressure/air1.volume)*air1.total_moles
+ transfer_moles = min(transfer_moles, calculate_transfer_moles(air1, air2, pressure_delta))
+ if(pump_gas_passive(air1, air2, calculate_transfer_moles(air1, air2, pressure_delta)) >= 0)//pump_gas() will return a negative number if no flow occurred
update_parents()
//Radio remote control
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm
index e0cb334b048..ec581bc9708 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm
@@ -55,8 +55,9 @@
var/datum/gas_mixture/air1 = airs[1]
var/datum/gas_mixture/air2 = airs[2]
- if(air1.return_pressure() > target_pressure)
- if(air1.release_gas_to(air2, air1.return_pressure()))
+ if(air1.returnPressure() > target_pressure)
+ var/transfer_moles = (target_pressure/air1.volume)*air1.total_moles
+ if(pump_gas_passive(air1, air2, calculate_transfer_moles(air1, air2, transfer_moles)))
update_parents()
is_gas_flowing = TRUE
else
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
index 1f372947f6e..6ef2f5db36f 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
@@ -64,8 +64,9 @@
var/datum/gas_mixture/air1 = airs[1]
var/datum/gas_mixture/air2 = airs[2]
-
- if(air1.pump_gas_to(air2, target_pressure))
+ //var/transfer_moles = (target_pressure/air1.volume)*air1.total_moles
+ var/transfer_moles = calculate_transfer_moles(air1, air2, target_pressure - air2.returnPressure())
+ if(pump_gas(air1, air2, transfer_moles))
update_parents()
/**
@@ -281,7 +282,7 @@
return
var/datum/gas_mixture/air_input = connected_pump.airs[1]
var/datum/gas_mixture/air_output = connected_pump.airs[2]
- input_pressure.set_output(air_input.return_pressure())
- output_pressure.set_output(air_output.return_pressure())
- input_temperature.set_output(air_input.return_temperature())
- output_temperature.set_output(air_output.return_temperature())
+ input_pressure.set_output(air_input.returnPressure())
+ output_pressure.set_output(air_output.returnPressure())
+ input_temperature.set_output(air_input.get_temperature())
+ output_temperature.set_output(air_output.get_temperature())
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
index b9295a4d2cd..a6de5c17fa4 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
@@ -59,14 +59,16 @@
if(!inverted)
if(air1.temperature < target_temperature)
- if(air1.release_gas_to(air2, air1.return_pressure()))
+ var/transfer_moles = (ATMOS_DEFAULT_VOLUME_PUMP/air1.volume)*air1.total_moles
+ if(pump_gas_passive(air1, air2, calculate_transfer_moles(air1, air2, transfer_moles)))
update_parents()
is_gas_flowing = TRUE
else
is_gas_flowing = FALSE
else
if(air1.temperature > target_temperature)
- if(air1.release_gas_to(air2, air1.return_pressure()))
+ var/transfer_moles = (ATMOS_DEFAULT_VOLUME_PUMP/air1.volume)*air1.total_moles
+ if(pump_gas_passive(air1, air2, calculate_transfer_moles(air1, air2, transfer_moles)))
update_parents()
is_gas_flowing = TRUE
else
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
index 742964c2d85..0948bea9e08 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
@@ -37,16 +37,16 @@
var/datum/gas_mixture/air_input = airs[1]
var/datum/gas_mixture/air_output = airs[2]
- if(!QUANTIZE(air_input.total_moles()) || !QUANTIZE(air_output.total_moles())) //Don't transfer if there's no gas
+ if(!QUANTIZE(air_input.get_moles()) || !QUANTIZE(air_output.get_moles())) //Don't transfer if there's no gas
return
- var/datum/gas_mixture/remove_input = air_input.remove_ratio(0.9)
- var/datum/gas_mixture/remove_output = air_output.remove_ratio(0.9)
+ var/datum/gas_mixture/remove_input = air_input.removeRatio(0.9)
+ var/datum/gas_mixture/remove_output = air_output.removeRatio(0.9)
var/coolant_temperature_delta = remove_input.temperature - remove_output.temperature
if(coolant_temperature_delta > 0)
- var/input_capacity = remove_input.heat_capacity()
- var/output_capacity = remove_output.heat_capacity()
+ var/input_capacity = remove_input.getHeatCapacity()
+ var/output_capacity = remove_output.getHeatCapacity()
var/cooling_heat_amount = (heat_transfer_rate * 0.01) * coolant_temperature_delta * (input_capacity * output_capacity / (input_capacity + output_capacity))
remove_input.temperature = max(remove_input.temperature - (cooling_heat_amount / input_capacity), TCMB)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
index 5109e2eb280..82b65c908bb 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
@@ -67,8 +67,8 @@
// Pump mechanism just won't do anything if the pressure is too high/too low unless you overclock it.
- var/input_starting_pressure = air1.return_pressure()
- var/output_starting_pressure = air2.return_pressure()
+ var/input_starting_pressure = air1.returnPressure()
+ var/output_starting_pressure = air2.returnPressure()
if((input_starting_pressure < 0.01) || ((output_starting_pressure > 9000))&&!overclocked)
return
@@ -79,15 +79,15 @@
var/transfer_ratio = transfer_rate / air1.volume
- var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
+ var/datum/gas_mixture/removed = air1.removeRatio(transfer_ratio)
- if(!removed.total_moles())
+ if(!removed.get_moles())
return
if(overclocked)//Some of the gas from the mixture leaks to the environment when overclocked
var/turf/open/T = loc
if(istype(T))
- var/datum/gas_mixture/leaked = removed.remove_ratio(VOLUME_PUMP_LEAK_AMOUNT)
+ var/datum/gas_mixture/leaked = removed.removeRatio(VOLUME_PUMP_LEAK_AMOUNT)
T.assume_air(leaked)
air2.merge(removed)
@@ -324,7 +324,7 @@
return
var/datum/gas_mixture/air_input = connected_pump.airs[1]
var/datum/gas_mixture/air_output = connected_pump.airs[2]
- input_pressure.set_output(air_input.return_pressure())
- output_pressure.set_output(air_output.return_pressure())
- input_temperature.set_output(air_input.return_temperature())
- output_temperature.set_output(air_output.return_temperature())
+ input_pressure.set_output(air_input.returnPressure())
+ output_pressure.set_output(air_output.returnPressure())
+ input_temperature.set_output(air_input.get_temperature())
+ output_temperature.set_output(air_output.get_temperature())
diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm
index bc98e87f3c6..eb751daa617 100644
--- a/code/modules/atmospherics/machinery/components/components_base.dm
+++ b/code/modules/atmospherics/machinery/components/components_base.dm
@@ -197,7 +197,7 @@
* This way gases won't get stuck
*/
/obj/machinery/atmospherics/components/proc/update_parents()
- if(!SSair.initialized)
+ if(!SSzas.initialized)
return
if(rebuilding)
update_parents_after_rebuild = TRUE
@@ -206,7 +206,7 @@
var/datum/pipeline/parent = parents[i]
if(!parent)
WARNING("Component is missing a pipenet! Rebuilding...")
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
else
parent.update = TRUE
diff --git a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm
deleted file mode 100644
index 97ae989e1d7..00000000000
--- a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm
+++ /dev/null
@@ -1,214 +0,0 @@
-#define ELECTROLYZER_MODE_STANDBY "standby"
-#define ELECTROLYZER_MODE_WORKING "working"
-
-/obj/machinery/electrolyzer
- anchored = FALSE
- density = TRUE
- interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN
- icon = 'icons/obj/atmos.dmi'
- icon_state = "electrolyzer-off"
- name = "space electrolyzer"
- desc = "Thanks to the fast and dynamic response of our electrolyzers, on-site hydrogen production is guaranteed. Warranty void if used by clowns"
- max_integrity = 250
- armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, FIRE = 80, ACID = 10)
- circuit = /obj/item/circuitboard/machine/electrolyzer
- /// We don't use area power, we always use the cell
- use_power = NO_POWER_USE
- ///used to check if there is a cell in the machine
- var/obj/item/stock_parts/cell/cell
- ///check if the machine is on or off
- var/on = FALSE
- ///check what mode the machine should be (WORKING, STANDBY)
- var/mode = ELECTROLYZER_MODE_STANDBY
- ///Increase the amount of moles worked on, changed by upgrading the manipulator tier
- var/working_power = 1
- ///Decrease the amount of power usage, changed by upgrading the capacitor tier
- var/efficiency = 0.5
-
-/obj/machinery/electrolyzer/get_cell()
- return cell
-
-/obj/machinery/electrolyzer/Initialize(mapload)
- . = ..()
- if(ispath(cell))
- cell = new cell(src)
- SSair.start_processing_machine(src)
- update_appearance()
-
-/obj/machinery/electrolyzer/Destroy()
- if(cell)
- QDEL_NULL(cell)
- return ..()
-
-/obj/machinery/electrolyzer/on_deconstruction()
- if(cell)
- LAZYADD(component_parts, cell)
- cell = null
- return ..()
-
-/obj/machinery/electrolyzer/examine(mob/user)
- . = ..()
- . += "\The [src] is [on ? "on" : "off"], and the hatch is [panel_open ? "open" : "closed"]."
-
- if(cell)
- . += "The charge meter reads [cell ? round(cell.percent(), 1) : 0]%."
- else
- . += "There is no power cell installed."
-
-/obj/machinery/electrolyzer/update_icon_state()
- icon_state = "electrolyzer-[on ? "[mode]" : "off"]"
- return ..()
-
-/obj/machinery/electrolyzer/update_overlays()
- . = ..()
- if(panel_open)
- . += "electrolyzer-open"
-
-/obj/machinery/electrolyzer/process_atmos()
-
- if(!is_operational && on)
- on = FALSE
- if(!on)
- return PROCESS_KILL
-
- if((!cell || cell.charge <= 0) && !anchored)
- on = FALSE
- update_appearance()
- return PROCESS_KILL
-
- var/turf/our_turf = loc
- if(!istype(our_turf))
- if(mode != ELECTROLYZER_MODE_STANDBY)
- mode = ELECTROLYZER_MODE_STANDBY
- update_appearance()
- return
-
- var/new_mode = on ? ELECTROLYZER_MODE_WORKING : ELECTROLYZER_MODE_STANDBY //change the mode to working if the machine is on
-
- if(mode != new_mode) //check if the mode is set correctly
- mode = new_mode
- update_appearance()
-
- if(mode == ELECTROLYZER_MODE_STANDBY)
- return
-
- var/datum/gas_mixture/env = our_turf.return_air() //get air from the turf
-
- if(!env)
- return
-
- call_reactions(env)
-
- air_update_turf(FALSE, FALSE)
-
- if(anchored)
- return
-
- cell.use((5 * (3 * working_power) * working_power) / (efficiency + working_power))
-
-/obj/machinery/electrolyzer/proc/call_reactions(datum/gas_mixture/env)
- for(var/reaction in GLOB.electrolyzer_reactions)
- var/datum/electrolyzer_reaction/current_reaction = GLOB.electrolyzer_reactions[reaction]
-
- if(!current_reaction.reaction_check(env))
- continue
-
- current_reaction.react(loc, env, working_power)
-
- env.garbage_collect()
-
-/obj/machinery/electrolyzer/RefreshParts()
- . = ..()
- var/manipulator = 0
- var/cap = 0
- for(var/obj/item/stock_parts/manipulator/M in component_parts)
- manipulator += M.rating
- for(var/obj/item/stock_parts/capacitor/M in component_parts)
- cap += M.rating
-
- working_power = manipulator //used in the amount of moles processed
-
- efficiency = (cap + 1) * 0.5 //used in the amount of charge in power cell uses
-
-/obj/machinery/electrolyzer/screwdriver_act(mob/living/user, obj/item/tool)
- tool.play_tool_sound(src, 50)
- panel_open = !panel_open
- user.visible_message(span_notice("\The [user] [panel_open ? "opens" : "closes"] the hatch on \the [src]."), span_notice("You [panel_open ? "open" : "close"] the hatch on \the [src]."))
- update_appearance()
- return TRUE
-
-/obj/machinery/electrolyzer/wrench_act(mob/living/user, obj/item/tool)
- . = ..()
- default_unfasten_wrench(user, tool)
- return TOOL_ACT_TOOLTYPE_SUCCESS
-
-/obj/machinery/electrolyzer/crowbar_act(mob/living/user, obj/item/tool)
- return default_deconstruction_crowbar(tool)
-
-/obj/machinery/electrolyzer/default_unfasten_wrench(mob/user, obj/item/wrench, time)
- . = ..()
- if(anchored)
- update_use_power(ACTIVE_POWER_USE)
- else
- update_use_power(NO_POWER_USE)
-
-/obj/machinery/electrolyzer/attackby(obj/item/I, mob/user, params)
- add_fingerprint(user)
- if(istype(I, /obj/item/stock_parts/cell))
- if(!panel_open)
- to_chat(user, span_warning("The hatch must be open to insert a power cell!"))
- return
- if(cell)
- to_chat(user, span_warning("There is already a power cell inside!"))
- return
- if(!user.transferItemToLoc(I, src))
- return
- cell = I
- I.add_fingerprint(usr)
-
- user.visible_message(span_notice("\The [user] inserts a power cell into \the [src]."), span_notice("You insert the power cell into \the [src]."))
- SStgui.update_uis(src)
-
- return
- return ..()
-
-/obj/machinery/electrolyzer/ui_state(mob/user)
- return GLOB.physical_state
-
-/obj/machinery/electrolyzer/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "Electrolyzer", name)
- ui.open()
-
-/obj/machinery/electrolyzer/ui_data()
- var/list/data = list()
- data["open"] = panel_open
- data["on"] = on
- data["hasPowercell"] = !isnull(cell)
- data["anchored"] = anchored
- if(cell)
- data["powerLevel"] = round(cell.percent(), 1)
- return data
-
-/obj/machinery/electrolyzer/ui_act(action, params)
- . = ..()
- if(.)
- return
- switch(action)
- if("power")
- on = !on
- mode = ELECTROLYZER_MODE_STANDBY
- usr.visible_message(span_notice("[usr] switches [on ? "on" : "off"] \the [src]."), span_notice("You switch [on ? "on" : "off"] \the [src]."))
- update_appearance()
- if (on)
- SSair.start_processing_machine(src)
- . = TRUE
- if("eject")
- if(panel_open && cell)
- cell.forceMove(drop_location())
- cell = null
- . = TRUE
-
-#undef ELECTROLYZER_MODE_STANDBY
-#undef ELECTROLYZER_MODE_WORKING
diff --git a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm
deleted file mode 100644
index 8098608640c..00000000000
--- a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm
+++ /dev/null
@@ -1,63 +0,0 @@
-GLOBAL_LIST_INIT(electrolyzer_reactions, electrolyzer_reactions_list())
-
-/*
- * Global proc to build the electrolyzer reactions list
- */
-/proc/electrolyzer_reactions_list()
- var/list/built_reaction_list = list()
- for(var/reaction_path in subtypesof(/datum/electrolyzer_reaction))
- var/datum/electrolyzer_reaction/reaction = new reaction_path()
-
- built_reaction_list[reaction.id] = reaction
-
- return built_reaction_list
-
-/datum/electrolyzer_reaction
- var/list/requirements
- var/name = "reaction"
- var/id = "r"
-
-/datum/electrolyzer_reaction/proc/react(turf/location, datum/gas_mixture/air_mixture, working_power)
- return
-
-/datum/electrolyzer_reaction/proc/reaction_check(datum/gas_mixture/air_mixture)
- var/temp = air_mixture.temperature
- var/list/cached_gases = air_mixture.gases
- if((requirements["MIN_TEMP"] && temp < requirements["MIN_TEMP"]) || (requirements["MAX_TEMP"] && temp > requirements["MAX_TEMP"]))
- return FALSE
- for(var/id in requirements)
- if (id == "MIN_TEMP" || id == "MAX_TEMP")
- continue
- if(!cached_gases[id] || cached_gases[id][MOLES] < requirements[id])
- return FALSE
- return TRUE
-
-/datum/electrolyzer_reaction/h2o_conversion
- name = "H2O Conversion"
- id = "h2o_conversion"
- requirements = list(
- /datum/gas/water_vapor = MINIMUM_MOLE_COUNT
- )
-
-/datum/electrolyzer_reaction/h2o_conversion/react(turf/location, datum/gas_mixture/air_mixture, working_power)
-
- air_mixture.assert_gases(/datum/gas/water_vapor, /datum/gas/oxygen, /datum/gas/hydrogen)
- var/proportion = min(air_mixture.gases[/datum/gas/water_vapor][MOLES], (2.5 * (working_power ** 2)))
- air_mixture.gases[/datum/gas/water_vapor][MOLES] -= proportion * 2
- air_mixture.gases[/datum/gas/oxygen][MOLES] += proportion
- air_mixture.gases[/datum/gas/hydrogen][MOLES] += proportion * 2
-
-/datum/electrolyzer_reaction/nob_conversion
- name = "Hypernob conversion"
- id = "nob_conversion"
- requirements = list(
- /datum/gas/hypernoblium = MINIMUM_MOLE_COUNT,
- "MAX_TEMP" = 150
- )
-
-/datum/electrolyzer_reaction/nob_conversion/react(turf/location, datum/gas_mixture/air_mixture, working_power)
-
- air_mixture.assert_gases(/datum/gas/hypernoblium, /datum/gas/antinoblium)
- var/proportion = min(air_mixture.gases[/datum/gas/hypernoblium][MOLES], (1.5 * (working_power ** 2)))
- air_mixture.gases[/datum/gas/hypernoblium][MOLES] -= proportion
- air_mixture.gases[/datum/gas/antinoblium][MOLES] += proportion * 0.5
diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm
deleted file mode 100644
index d51fbdbefee..00000000000
--- a/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * This section contain the hfr core with all the variables and the Initialize() and Destroy() procs
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core
- name = "HFR core"
- desc = "This is the Hypertorus Fusion Reactor core, an advanced piece of technology to finely tune the reaction inside of the machine. It has I/O for cooling gases."
- icon = 'icons/obj/atmospherics/components/hypertorus.dmi'
- icon_state = "core_off"
- circuit = /obj/item/circuitboard/machine/HFR_core
- use_power = IDLE_POWER_USE
- idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION
- ///Vars for the state of the icon of the object (open, off, active)
- icon_state_open = "core_open"
- icon_state_off = "core_off"
- icon_state_active = "core_active"
-
- /**
- * Processing checks
- */
-
- ///Checks if the user has started the machine
- var/start_power = FALSE
- ///Checks for the cooling to start
- var/start_cooling = FALSE
- ///Checks for the fuel to be injected
- var/start_fuel = FALSE
- ///Checks for the moderators to be injected
- var/start_moderator = FALSE
-
- /**
- * Hypertorus internal objects and gasmixes
- */
-
- ///Stores the informations of the interface machine
- var/obj/machinery/hypertorus/interface/linked_interface
- ///Stores the information of the moderator input
- var/obj/machinery/atmospherics/components/unary/hypertorus/moderator_input/linked_moderator
- ///Stores the information of the fuel input
- var/obj/machinery/atmospherics/components/unary/hypertorus/fuel_input/linked_input
- ///Stores the information of the waste output
- var/obj/machinery/atmospherics/components/unary/hypertorus/waste_output/linked_output
- ///Stores the information of the corners of the machine
- var/list/corners = list()
- ///Stores the three inputs/outputs of the HFR, needed for cracking the parts
- var/list/machine_parts = list()
- ///Stores the information of the fusion gasmix
- var/datum/gas_mixture/internal_fusion
- ///Stores the information of the moderators gasmix
- var/datum/gas_mixture/moderator_internal
- ///Set the filtering list of the waste remove
- var/list/moderator_scrubbing = list(
- /datum/gas/helium,
- )
- ///Set the amount of moles per tick should be removed from the moderator by filtering
- var/moderator_filtering_rate = 100
- ///Stores the current fuel mix that the user has selected
- var/datum/hfr_fuel/selected_fuel
-
- /**
- * Fusion vars
- */
-
- ///E=mc^2 with some addition to allow it gameplaywise
- var/energy = 0
- ///Temperature of the center of the fusion reaction
- var/core_temperature = T20C
- /**Power emitted from the center of the fusion reaction: Internal power = densityH2 * densityTrit(Pi * (2 * rH2 * rTrit)**2) * Energy
- * density is calculated with moles/volume, rH2 and rTrit are values calculated with moles/(radius of the gas)
- both of the density can be varied by the power_modifier
- **/
- var/internal_power = 0
- /**The effective power transmission of the fusion reaction, power_output = efficiency * (internal_power - conduction - radiation)
- * Conduction is the heat value that is transmitted by the molecular interactions and it gets removed from the internal_power lowering the effective output
- * Radiation is the irradiation released by the fusion reaction, it comprehends all wavelenghts in the spectrum, it lowers the effective output of the reaction
- **/
- var/power_output = 0
- ///Instability effects how chaotic the behavior of the reaction is
- var/instability = 0
- ///Difference between the gases temperature and the internal temperature of the reaction
- var/delta_temperature = 0
- ///Energy from the reaction lost from the molecule colliding between themselves.
- var/conduction = 0
- ///The remaining wavelength that actually can do damage to mobs.
- var/radiation = 0
- ///Efficiency of the reaction, it increases with the amount of plasma
- var/efficiency = 0
- ///Hotter air is easier to heat up and cool down
- var/heat_limiter_modifier = 0
- ///How much the reaction can cool itself
- var/heat_output_max = 0
- ///How much the reaction can heat itself
- var/heat_output_min = 0
- ///The amount of heat that is finally emitted, based on the power output. Min and max are variables that depends of the modifier
- var/heat_output = 0
-
- ///Check if the user want to remove the waste gases
- var/waste_remove = FALSE
- ///User controlled variable to control the flow of the fusion by changing the contact of the material
- var/heating_conductor = 100
- ///User controlled variable to control the flow of the fusion by changing the volume of the gasmix by controlling the power of the magnetic fields
- var/magnetic_constrictor = 100
- ///User controlled variable to control the flow of the fusion by changing the instability of the reaction
- var/current_damper = 0
- ///Stores the current fusion mix power level
- var/power_level = 0
- ///Stores the iron content produced by the fusion
- var/iron_content = 0
- ///User controlled variable to control the flow of the fusion by changing the amount of fuel injected
- var/fuel_injection_rate = 25
- ///User controlled variable to control the flow of the fusion by changing the amount of moderators injected
- var/moderator_injection_rate = 25
-
- ///Integrity of the machine, if reaches 900 the machine will explode
- var/critical_threshold_proximity = 0
- ///Store the integrity for calculations
- var/critical_threshold_proximity_archived = 0
- ///Our "Shit is no longer fucked" message. We send it when critical_threshold_proximity is less then critical_threshold_proximity_archived
- var/safe_alert = "Main containment field returning to safe operating parameters."
- ///The point at which we should start sending messeges about the critical_threshold_proximity to the engi channels.
- var/warning_point = 50
- ///The alert we send when we've reached warning_point
- var/warning_alert = "Danger! Magnetic containment field faltering!"
- ///The point at which we start sending messages to the common channel
- var/emergency_point = 700
- ///The alert we send when we've reached emergency_point
- var/emergency_alert = "HYPERTORUS MELTDOWN IMMINENT."
- ///The point at which we melt
- var/melting_point = 900
- ///Boolean used for logging if we've passed the emergency point
- var/has_reached_emergency = FALSE
- ///Time in 1/10th of seconds since the last sent warning
- var/lastwarning = 0
-
- ///Our internal radio
- var/obj/item/radio/radio
- ///The key our internal radio uses
- var/radio_key = /obj/item/encryptionkey/headset_eng
- ///The engineering channel
- var/engineering_channel = "Engineering"
- ///The common channel
- var/common_channel = null
-
- ///Our soundloop
- var/datum/looping_sound/hypertorus/soundloop
- ///cooldown tracker for accent sounds
- var/last_accent_sound = 0
-
- ///These vars store the temperatures to be used in the GUI
- var/fusion_temperature_archived = 0
- var/fusion_temperature = 0
- var/moderator_temperature_archived = 0
- var/moderator_temperature = 0
- var/coolant_temperature_archived = 0
- var/coolant_temperature = 0
- var/output_temperature_archived = 0
- var/output_temperature = 0
- ///Time between current and _archived temperatures
- var/temperature_period = 1
- ///Var used in the meltdown phase
- var/final_countdown = FALSE
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/Initialize(mapload)
- . = ..()
- internal_fusion = new
- internal_fusion.volume = 5000
- moderator_internal = new
- moderator_internal.volume = 10000
-
- radio = new(src)
- radio.keyslot = new radio_key
- radio.set_listening(FALSE)
- radio.recalculateChannels()
- investigate_log("has been created.", INVESTIGATE_HYPERTORUS)
-
- RegisterSignal(src.loc, COMSIG_ATOM_ENTERED, .proc/on_entered)
-
- for(var/atom/movable/movable_object in src.loc)
- SEND_SIGNAL(movable_object, COMSIG_MOVABLE_SECLUDED_LOCATION)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
- SIGNAL_HANDLER
- SEND_SIGNAL(arrived, COMSIG_MOVABLE_SECLUDED_LOCATION) // to prevent stationloving items (eg. nuke disk) being teleported onto core
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/Destroy()
- unregister_signals(TRUE)
- if(internal_fusion)
- internal_fusion = null
- if(moderator_internal)
- moderator_internal = null
- if(linked_input)
- QDEL_NULL(linked_input)
- if(linked_output)
- QDEL_NULL(linked_output)
- if(linked_moderator)
- QDEL_NULL(linked_moderator)
- if(linked_interface)
- QDEL_NULL(linked_interface)
- for(var/obj/machinery/hypertorus/corner/corner in corners)
- QDEL_NULL(corner)
- QDEL_NULL(radio)
- QDEL_NULL(soundloop)
- machine_parts = null
- return..()
diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_defines.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_defines.dm
deleted file mode 100644
index 8234f02ba0c..00000000000
--- a/code/modules/atmospherics/machinery/components/fusion/hfr_defines.dm
+++ /dev/null
@@ -1,150 +0,0 @@
-///Speed of light, in m/s
-#define LIGHT_SPEED 299792458
-///Calculation between the plank constant and the lambda of the lightwave
-#define PLANCK_LIGHT_CONSTANT 2e-16
-///Radius of the h2 calculated based on the amount of number of atom in a mole (and some addition for balancing issues)
-#define CALCULATED_H2RADIUS 120e-4
-///Radius of the trit calculated based on the amount of number of atom in a mole (and some addition for balancing issues)
-#define CALCULATED_TRITRADIUS 230e-3
-///Power conduction in the void, used to calculate the efficiency of the reaction
-#define VOID_CONDUCTION 1e-2
-///Mole count required (tritium/hydrogen) to start a fusion reaction
-#define FUSION_MOLE_THRESHOLD 25
-///Used to reduce the gas_power to a more useful amount
-#define INSTABILITY_GAS_POWER_FACTOR 0.003
-///Used to calculate the toroidal_size for the instability
-#define TOROID_VOLUME_BREAKEVEN 1000
-///Constant used when calculating the chance of emitting a radioactive particle
-#define PARTICLE_CHANCE_CONSTANT (-20000000)
-///Conduction of heat inside the fusion reactor
-#define METALLIC_VOID_CONDUCTIVITY 0.38
-///Conduction of heat near the external cooling loop
-#define HIGH_EFFICIENCY_CONDUCTIVITY 0.975
-///Sets the minimum amount of power the machine uses
-#define MIN_POWER_USAGE 50000
-///Sets the multiplier for the damage
-#define DAMAGE_CAP_MULTIPLIER 0.005
-///Sets the range of the hallucinations
-#define HALLUCINATION_HFR(P) (min(7, round(abs(P) ** 0.25)))
-///Chance in percentage points per fusion level of iron accumulation when operating at unsafe levels
-#define IRON_CHANCE_PER_FUSION_LEVEL 17
-///Amount of iron accumulated per second whenever we fail our saving throw, using the chance above
-#define IRON_ACCUMULATED_PER_SECOND 0.005
-///Maximum amount of iron that can be healed per second. Calculated to mostly keep up with fusion level 5.
-#define IRON_OXYGEN_HEAL_PER_SECOND (IRON_ACCUMULATED_PER_SECOND * (100 - IRON_CHANCE_PER_FUSION_LEVEL) / 100)
-///Amount of oxygen in moles required to fully remove 100% iron content. Currently about 2409mol. Calculated to consume at most 10mol/s.
-#define OXYGEN_MOLES_CONSUMED_PER_IRON_HEAL (10 / IRON_OXYGEN_HEAL_PER_SECOND)
-
-//If integrity percent remaining is less than these values, the monitor sets off the relevant alarm.
-#define HYPERTORUS_MELTING_PERCENT 5
-#define HYPERTORUS_EMERGENCY_PERCENT 25
-#define HYPERTORUS_DANGER_PERCENT 50
-#define HYPERTORUS_WARNING_PERCENT 100
-
-#define WARNING_TIME_DELAY 60
-///to prevent accent sounds from layering
-#define HYPERTORUS_ACCENT_SOUND_MIN_COOLDOWN 3 SECONDS
-
-#define HYPERTORUS_COUNTDOWN_TIME 30 SECONDS
-
-//
-// Damage source: Too much mass in the fusion mix at high fusion levels
-//
-
-// Currently, this is 2700 moles at 1 Kelvin, linearly scaling down to a maximum of 1800 safe moles at 1e8 degrees kelvin
-// Settings:
-/// Start taking overfull damage at this power level
-#define HYPERTORUS_OVERFULL_MIN_POWER_LEVEL 6
-/// Take 0 damage beneath this much fusion mass at 1 degree Kelvin
-#define HYPERTORUS_OVERFULL_MAX_SAFE_COLD_FUSION_MOLES 2700
-/// Take 0 damage beneath this much fusion mass at FUSION_TEMPERATURE_MAX degrees Kelvin
-#define HYPERTORUS_OVERFULL_MAX_SAFE_HOT_FUSION_MOLES 1800
-// From there, how quickly should things get bad?
-/// Every 200 moles, 1 point of damage per second
-#define HYPERTORUS_OVERFULL_MOLAR_SLOPE (1/200)
-// Derived:
-// Given these settings, derive the rest of the equation.
-// Damage is the dependent variable, fusion_moles and damage_source_temperature are the independent variables
-// So the equation takes the form:
-// damage = molar_slope * fusion_moles + temperature_slope * damage_source_temperature + constant
-// Derive these constants here for readability
-// Derive the temperature slope from the molar slope
-#define HYPERTORUS_OVERFULL_TEMPERATURE_SLOPE (HYPERTORUS_OVERFULL_MOLAR_SLOPE * (HYPERTORUS_OVERFULL_MAX_SAFE_COLD_FUSION_MOLES - HYPERTORUS_OVERFULL_MAX_SAFE_HOT_FUSION_MOLES) / (FUSION_MAXIMUM_TEMPERATURE - 1))
-// Derive the constant to set damage = 0 at our desired thresholds above
-#define HYPERTORUS_OVERFULL_CONSTANT (-(HYPERTORUS_OVERFULL_MOLAR_SLOPE * HYPERTORUS_OVERFULL_MAX_SAFE_HOT_FUSION_MOLES + HYPERTORUS_OVERFULL_TEMPERATURE_SLOPE * FUSION_MAXIMUM_TEMPERATURE))
-
-//
-// Heal source: Small enough mass in the fusion mix
-//
-
-// Settings:
-/// Start healing when fusion mass is below this threshold
-#define HYPERTORUS_SUBCRITICAL_MOLES 1200
-/// Heal one point per second per this many moles under the threshold
-#define HYPERTORUS_SUBCRITICAL_SCALE 400
-
-//
-// Heal source: Cold enough coolant
-//
-
-// Settings:
-/// Heal up to this many points of damage per second at 1 degree kelvin
-#define HYPERTORUS_COLD_COOLANT_MAX_RESTORE 2.5
-/// Start healing below this temperature
-#define HYPERTORUS_COLD_COOLANT_THRESHOLD (10 ** 5)
-// Derived:
-#define HYPERTORUS_COLD_COOLANT_SCALE (HYPERTORUS_COLD_COOLANT_MAX_RESTORE / log(10, HYPERTORUS_COLD_COOLANT_THRESHOLD))
-
-//
-// Damage source: Iron content
-//
-
-// Settings:
-/// Start taking damage over this threshold, up to a maximum of (1 - HYPERTORUS_MAX_SAFE_IRON) per tick at 100% iron
-#define HYPERTORUS_MAX_SAFE_IRON 0.35
-
-//
-// Damage source: Extreme levels of mass in fusion mix at any power level
-//
-
-// Note: Ignores the damage cap!
-// Settings:
-/// Start taking damage over this threshold
-#define HYPERTORUS_HYPERCRITICAL_MOLES 10000
-/// Take this much damage per mole over the threshold per second
-#define HYPERTORUS_HYPERCRITICAL_SCALE 0.002
-/// Take at most this much damage per second
-#define HYPERTORUS_HYPERCRITICAL_MAX_DAMAGE 20
-
-// If the moderator goes hypercritical, it cracks and starts to spill
-// If our pressure is weak, it can still spill, just weakly and infrequently
-// Even a small amount is still extremely hazardous with fusion temperatures
-#define HYPERTORUS_WEAK_SPILL_RATE 0.0005
-#define HYPERTORUS_WEAK_SPILL_CHANCE 1
-/// Start spilling superhot moderator gas when over this pressure threshold
-#define HYPERTORUS_MEDIUM_SPILL_PRESSURE 10000
-/// How much we should spill initially
-#define HYPERTORUS_MEDIUM_SPILL_INITIAL 0.25
-/// How much of the moderator mix we should spill per second until mended
-#define HYPERTORUS_MEDIUM_SPILL_RATE 0.01
-/// If the moderator gas goes over this threshold, REALLY spill it
-#define HYPERTORUS_STRONG_SPILL_PRESSURE 12000
-/// How much we should spill initially
-#define HYPERTORUS_STRONG_SPILL_INITIAL 0.75
-/// How much of the moderator mix we should spill per second until mended
-#define HYPERTORUS_STRONG_SPILL_RATE 0.05
-
-
-//
-// Explosion flags for use in fuel recipes
-//
-#define HYPERTORUS_FLAG_BASE_EXPLOSION (1<<0)
-#define HYPERTORUS_FLAG_MEDIUM_EXPLOSION (1<<1)
-#define HYPERTORUS_FLAG_DEVASTATING_EXPLOSION (1<<2)
-#define HYPERTORUS_FLAG_RADIATION_PULSE (1<<3)
-#define HYPERTORUS_FLAG_EMP (1<<4)
-#define HYPERTORUS_FLAG_MINIMUM_SPREAD (1<<5)
-#define HYPERTORUS_FLAG_MEDIUM_SPREAD (1<<6)
-#define HYPERTORUS_FLAG_BIG_SPREAD (1<<7)
-#define HYPERTORUS_FLAG_MASSIVE_SPREAD (1<<8)
-#define HYPERTORUS_FLAG_CRITICAL_MELTDOWN (1<<9)
diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm
deleted file mode 100644
index c7a9545a7d2..00000000000
--- a/code/modules/atmospherics/machinery/components/fusion/hfr_fuel_datums.dm
+++ /dev/null
@@ -1,140 +0,0 @@
-///Global list of recipes for atmospheric machines to use
-GLOBAL_LIST_INIT(hfr_fuels_list, hfr_fuels_create_list())
-
-/*
- * Global proc to build the gas recipe global list
- */
-/proc/hfr_fuels_create_list()
- . = list()
- for(var/fuel_mix_path in subtypesof(/datum/hfr_fuel))
- var/datum/hfr_fuel/fuel_mix = new fuel_mix_path()
-
- .[fuel_mix.id] = fuel_mix
-
-/datum/hfr_fuel
- ///Id for the mix
- var/id = ""
- ///The gases that are going to be used as fuel ("GasX + GasY fuel")
- var/name = ""
- ///Multiplier for the minimum heat output of the HFR (min 0.01)
- var/negative_temperature_multiplier = 1
- ///Multiplier for the maximum heat output of the HFR (min 0.01)
- var/positive_temperature_multiplier = 1
- ///Multiplier for the energy released (min 0.01)
- var/energy_concentration_multiplier = 1
- ///Multiplier for the fuel consumption (min 0.01)
- var/fuel_consumption_multiplier = 1
- ///Multiplier for the gas production (min 0.01)
- var/gas_production_multiplier = 1
- ///Max allowed temperature multiplier, scales the max temperature we can hit, see FUSION_MAXIMUM_TEMPERATURE (Maxed at 1, don't go getting any ideas)
- var/temperature_change_multiplier = 1
- ///These are the main fuels, only 2 gases that are the ones being consumed by the fusion reaction (eg. H2 and trit)
- var/requirements = list()
- ///Gases that gets produced directly in the internal gasmix
- var/primary_products = list()
- ///Gases that gets produced in the moderator gasmix or directly ejected (must be 6 gases), the order indicate at what power level the gases are going to be made (from power level 1 to 6)
- var/secondary_products = list()
- ///Flags to decide what behaviour the meltdown will have depending on the fuel mix used
- var/meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION
-
-/datum/hfr_fuel/New()
- . = ..()
- temperature_change_multiplier = min(temperature_change_multiplier, 1)
-
-/datum/hfr_fuel/plasma_oxy_fuel
- id = "plasma_o2_fuel"
- name = "Plasma + Oxygen fuel"
- negative_temperature_multiplier = 2.5
- positive_temperature_multiplier = 0.1
- energy_concentration_multiplier = 10
- fuel_consumption_multiplier = 3.3
- gas_production_multiplier = 1.4
- temperature_change_multiplier = 0.6
- requirements = list(/datum/gas/plasma, /datum/gas/oxygen)
- primary_products = list(/datum/gas/carbon_dioxide, /datum/gas/water_vapor)
- secondary_products = list(/datum/gas/carbon_dioxide, /datum/gas/water_vapor, /datum/gas/freon, /datum/gas/nitrous_oxide, /datum/gas/pluoxium, /datum/gas/halon)
- meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION | HYPERTORUS_FLAG_MINIMUM_SPREAD
-
-/datum/hfr_fuel/hydrogen_oxy_fuel
- id = "h2_o2_fuel"
- name = "Hydrogen + Oxygen fuel"
- negative_temperature_multiplier = 2
- positive_temperature_multiplier = 0.6
- energy_concentration_multiplier = 3
- fuel_consumption_multiplier = 1.1
- gas_production_multiplier = 0.9
- temperature_change_multiplier = 0.75
- requirements = list(/datum/gas/hydrogen, /datum/gas/oxygen)
- primary_products = list(/datum/gas/helium, /datum/gas/nitrogen)
- secondary_products = list(/datum/gas/helium, /datum/gas/plasma, /datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/bz, /datum/gas/hypernoblium)
- meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_MEDIUM_SPREAD
-
-/datum/hfr_fuel/tritium_oxy_fuel
- id = "t2_o2_fuel"
- name = "Tritium + Oxygen fuel"
- negative_temperature_multiplier = 2.1
- positive_temperature_multiplier = 0.5
- energy_concentration_multiplier = 2
- fuel_consumption_multiplier = 1.2
- gas_production_multiplier = 0.8
- temperature_change_multiplier = 0.8
- requirements = list(/datum/gas/tritium, /datum/gas/oxygen)
- primary_products = list(/datum/gas/helium, /datum/gas/pluoxium)
- secondary_products = list(/datum/gas/helium, /datum/gas/plasma, /datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/bz, /datum/gas/hypernoblium)
- meltdown_flags = HYPERTORUS_FLAG_BASE_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_MEDIUM_SPREAD
-
-/datum/hfr_fuel/hydrogen_tritium_fuel
- id = "h2_t2_fuel"
- name = "Hydrogen + Tritium fuel"
- negative_temperature_multiplier = 1
- positive_temperature_multiplier = 1
- energy_concentration_multiplier = 1
- fuel_consumption_multiplier = 1
- gas_production_multiplier = 1
- temperature_change_multiplier = 0.85
- requirements = list(/datum/gas/hydrogen, /datum/gas/tritium)
- primary_products = list(/datum/gas/helium)
- secondary_products = list(/datum/gas/helium, /datum/gas/plasma, /datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/bz, /datum/gas/hypernoblium)
- meltdown_flags = HYPERTORUS_FLAG_MEDIUM_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_MEDIUM_SPREAD
-
-/datum/hfr_fuel/hypernob_hydrogen_fuel
- id = "hypernob_hydrogen_fuel"
- name = "Hypernoblium + Hydrogen fuel"
- negative_temperature_multiplier = 0.2
- positive_temperature_multiplier = 2.2
- energy_concentration_multiplier = 0.2
- fuel_consumption_multiplier = 0.55
- gas_production_multiplier = 1.4
- temperature_change_multiplier = 0.9
- requirements = list(/datum/gas/hypernoblium, /datum/gas/hydrogen)
- primary_products = list(/datum/gas/antinoblium)
- secondary_products = list(/datum/gas/antinoblium, /datum/gas/helium, /datum/gas/proto_nitrate, /datum/gas/zauker, /datum/gas/healium, /datum/gas/miasma)
- meltdown_flags = HYPERTORUS_FLAG_DEVASTATING_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_BIG_SPREAD
-
-/datum/hfr_fuel/hypernob_trit_fuel
- id = "hypernob_trit_fuel"
- name = "Hypernoblium + Tritium fuel"
- negative_temperature_multiplier = 0.1
- positive_temperature_multiplier = 2.5
- energy_concentration_multiplier = 0.1
- fuel_consumption_multiplier = 0.45
- gas_production_multiplier = 1.7
- temperature_change_multiplier = 0.95
- requirements = list(/datum/gas/hypernoblium, /datum/gas/tritium)
- primary_products = list(/datum/gas/antinoblium)
- secondary_products = list(/datum/gas/antinoblium, /datum/gas/helium, /datum/gas/proto_nitrate, /datum/gas/zauker, /datum/gas/healium, /datum/gas/miasma)
- meltdown_flags = HYPERTORUS_FLAG_DEVASTATING_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_BIG_SPREAD
-
-/datum/hfr_fuel/hypernob_antinob_fuel
- id = "hypernob_antinob_fuel"
- name = "Hypernoblium + Antinoblium fuel"
- negative_temperature_multiplier = 0.01
- positive_temperature_multiplier = 3.5
- energy_concentration_multiplier = 2
- fuel_consumption_multiplier = 0.01
- gas_production_multiplier = 3
- temperature_change_multiplier = 1
- requirements = list(/datum/gas/hypernoblium, /datum/gas/antinoblium)
- primary_products = list(/datum/gas/helium)
- secondary_products = list(/datum/gas/plasma, /datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/proto_nitrate, /datum/gas/nitrium, /datum/gas/miasma)
- meltdown_flags = HYPERTORUS_FLAG_DEVASTATING_EXPLOSION | HYPERTORUS_FLAG_RADIATION_PULSE | HYPERTORUS_FLAG_EMP | HYPERTORUS_FLAG_MASSIVE_SPREAD | HYPERTORUS_FLAG_CRITICAL_MELTDOWN
diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm
deleted file mode 100644
index 6c7551e0c35..00000000000
--- a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm
+++ /dev/null
@@ -1,579 +0,0 @@
-/**
- * Main Fusion processes
- * process() Organizes all other calls, and is the best starting point for top-level logic.
- * fusion_process() handles all the main fusion reaction logic and consequences (lightning, radiation, particles) from an active fusion reaction.
- */
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/process(delta_time)
- /*
- *Pre-checks
- */
- //first check if the machine is active
- if(!active)
- return
-
- //then check if the other machines are still there
- if(!check_part_connectivity())
- deactivate()
- return
-
- assert_gases()
-
- // Run the reaction if it is either live or being started
- if (start_power || power_level)
- play_ambience()
- fusion_process(delta_time)
- // Note that we process damage/healing even if the fusion process aborts.
- // Running out of fuel won't save you if your moderator and coolant are exploding on their own.
- check_spill()
- process_damageheal(delta_time)
- check_alert()
- if (start_power)
- remove_waste(delta_time)
- update_pipenets()
-
- check_deconstructable()
-
-/**
- * Called by process()
- * Contains the main fusion calculations and checks, for more informations check the comments along the code.
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/fusion_process(delta_time)
-//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again). Again! Again but with machine!
-//Fusion Rework Counter: Please increment this if you make a major overhaul to this system again.
-//7 reworks
-
- if (check_power_use())
- if (start_cooling)
- inject_from_side_components(delta_time)
- process_internal_cooling(delta_time)
- else
- // No power forces bad settings
- magnetic_constrictor = 100
- heating_conductor = 500
- current_damper = 0
- fuel_injection_rate = 20
- moderator_injection_rate = 50
- waste_remove = FALSE
- iron_content += 0.02 * power_level * delta_time
-
- update_temperature_status(delta_time)
-
- //Store the temperature of the gases after one cicle of the fusion reaction
- var/archived_heat = internal_fusion.temperature
- //Store the volume of the fusion reaction multiplied by the force of the magnets that controls how big it will be
- var/volume = internal_fusion.volume * (magnetic_constrictor * 0.01)
-
- var/energy_concentration_multiplier = 1
- var/positive_temperature_multiplier = 1
- var/negative_temperature_multiplier = 1
-
- //We scale it down by volume/2 because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions.
- var/scale_factor = volume * 0.5
-
- /// Store the fuel gases and the byproduct gas quantities
- var/list/fuel_list = list()
- /// Scaled down moles of gases, no less than 0
- var/list/scaled_fuel_list = list()
-
- if (selected_fuel)
- energy_concentration_multiplier = selected_fuel.energy_concentration_multiplier
- positive_temperature_multiplier = selected_fuel.positive_temperature_multiplier
- negative_temperature_multiplier = selected_fuel.negative_temperature_multiplier
-
- for(var/gas_id in selected_fuel.requirements | selected_fuel.primary_products)
- var/amount = internal_fusion.gases[gas_id][MOLES]
- fuel_list[gas_id] = amount
- scaled_fuel_list[gas_id] = max((amount - FUSION_MOLE_THRESHOLD) / scale_factor, 0)
-
- /// Store the moderators gases quantities
- var/list/moderator_list = list()
- /// Scaled down moles of gases, no less than 0
- var/list/scaled_moderator_list = list()
- for(var/gas_id in moderator_internal.gases)
- var/amount = moderator_internal.gases[gas_id][MOLES]
- moderator_list[gas_id] = amount
- scaled_moderator_list[gas_id] = max((amount - FUSION_MOLE_THRESHOLD) / scale_factor, 0)
-
- /*
- *FUSION MAIN PROCESS
- */
- //This section is used for the instability calculation for the fusion reaction
- //The size of the phase space hypertorus
- var/toroidal_size = (2 * PI) + TORADIANS(arctan((volume - TOROID_VOLUME_BREAKEVEN) / TOROID_VOLUME_BREAKEVEN))
- //Calculation of the gas power, only for theoretical instability calculations
- var/gas_power = 0
- for (var/gas_id in internal_fusion.gases)
- gas_power += (internal_fusion.gases[gas_id][GAS_META][META_GAS_FUSION_POWER] * internal_fusion.gases[gas_id][MOLES])
- for (var/gas_id in moderator_internal.gases)
- gas_power += (moderator_internal.gases[gas_id][GAS_META][META_GAS_FUSION_POWER] * moderator_internal.gases[gas_id][MOLES] * 0.75)
-
- instability = MODULUS((gas_power * INSTABILITY_GAS_POWER_FACTOR)**2, toroidal_size) + (current_damper * 0.01) - iron_content * 0.05
- //Effective reaction instability (determines if the energy is used/released)
- var/internal_instability = 0
- if(instability * 0.5 < FUSION_INSTABILITY_ENDOTHERMALITY)
- internal_instability = 1
- else
- internal_instability = -1
-
- /*
- *Modifiers
- */
- ///Those are the scaled gases that gets consumed and adjust energy
- // Gases that increase the amount of energy
- var/energy_modifiers = scaled_moderator_list[/datum/gas/nitrogen] * 0.35 + \
- scaled_moderator_list[/datum/gas/carbon_dioxide] * 0.55 + \
- scaled_moderator_list[/datum/gas/nitrous_oxide] * 0.95 + \
- scaled_moderator_list[/datum/gas/zauker] * 1.55 + \
- scaled_moderator_list[/datum/gas/antinoblium] * 20
- // Gases that decrease the amount of energy
- energy_modifiers -= scaled_moderator_list[/datum/gas/hypernoblium] * 10 + \
- scaled_moderator_list[/datum/gas/water_vapor] * 0.75 + \
- scaled_moderator_list[/datum/gas/nitrium] * 0.15 + \
- scaled_moderator_list[/datum/gas/healium] * 0.45 + \
- scaled_moderator_list[/datum/gas/freon] * 1.15
- ///Between 0.25 and 100, this value is used to modify the behaviour of the internal energy and the core temperature based on the gases present in the mix
- var/power_modifier = scaled_moderator_list[/datum/gas/oxygen] * 0.55 + \
- scaled_moderator_list[/datum/gas/carbon_dioxide] * 0.95 + \
- scaled_moderator_list[/datum/gas/nitrium] * 1.45 + \
- scaled_moderator_list[/datum/gas/zauker] * 5.55 + \
- scaled_moderator_list[/datum/gas/plasma] * 0.05 - \
- scaled_moderator_list[/datum/gas/nitrous_oxide] * 0.05 - \
- scaled_moderator_list[/datum/gas/freon] * 0.75
- ///Minimum 0.25, this value is used to modify the behaviour of the energy emission based on the gases present in the mix
- var/heat_modifier = scaled_moderator_list[/datum/gas/plasma] * 1.25 - \
- scaled_moderator_list[/datum/gas/nitrogen] * 0.75 - \
- scaled_moderator_list[/datum/gas/nitrous_oxide] * 1.45 - \
- scaled_moderator_list[/datum/gas/freon] * 0.95
- ///Between 0.005 and 1000, this value modify the radiation emission of the reaction, higher values increase the emission
- var/radiation_modifier = scaled_moderator_list[/datum/gas/freon] * 1.15 - \
- scaled_moderator_list[/datum/gas/nitrogen] * 0.45 - \
- scaled_moderator_list[/datum/gas/plasma] * 0.95 + \
- scaled_moderator_list[/datum/gas/bz] * 1.9 + \
- scaled_moderator_list[/datum/gas/proto_nitrate] * 0.1 + \
- scaled_moderator_list[/datum/gas/antinoblium] * 10
-
- if (selected_fuel)
- // These should probably be static coefficients read from a table rather than things that depend on the current recipe
- // the same is true for the effects above
- energy_modifiers += scaled_fuel_list[selected_fuel.requirements[1]] + \
- scaled_fuel_list[selected_fuel.requirements[2]]
- energy_modifiers -= scaled_fuel_list[selected_fuel.primary_products[1]]
-
- power_modifier += scaled_fuel_list[selected_fuel.requirements[2]] * 1.05 - \
- scaled_fuel_list[selected_fuel.primary_products[1]] * 0.55
-
- heat_modifier += scaled_fuel_list[selected_fuel.requirements[1]] * 1.15 + \
- scaled_fuel_list[selected_fuel.primary_products[1]] * 1.05
-
- radiation_modifier += scaled_fuel_list[selected_fuel.primary_products[1]]
-
- power_modifier = clamp(power_modifier, 0.25, 100)
- heat_modifier = clamp(heat_modifier, 0.25, 100)
- radiation_modifier = clamp(radiation_modifier, 0.005, 1000)
-
- /*
- *Main calculations (energy, internal power, core temperature, delta temperature,
- *conduction, radiation, efficiency, power output, heat limiter modifier and heat output)
- */
- internal_power = 0
- efficiency = VOID_CONDUCTION * 1
-
- if (selected_fuel)
- // Power of the gas mixture
- internal_power = (scaled_fuel_list[selected_fuel.requirements[1]] * power_modifier / 100) * (scaled_fuel_list[selected_fuel.requirements[2]] * power_modifier / 100) * (PI * (2 * (scaled_fuel_list[selected_fuel.requirements[1]] * CALCULATED_H2RADIUS) * (scaled_fuel_list[selected_fuel.requirements[2]] * CALCULATED_TRITRADIUS))**2) * energy
-
- // Efficiency of the reaction, it increases with the amount of byproduct
- efficiency = VOID_CONDUCTION * clamp(scaled_fuel_list[selected_fuel.primary_products[1]], 1, 100)
-
- //Can go either positive or negative depending on the instability and the negative energy modifiers
- //E=mc^2 with some changes for gameplay purposes
- energy = (energy_modifiers * LIGHT_SPEED ** 2) * max(internal_fusion.temperature * heat_modifier / 100, 1)
- energy = energy / energy_concentration_multiplier
- energy = clamp(energy, 0, 1e35) //ugly way to prevent NaN error
- //Temperature inside the center of the gas mixture
- core_temperature = internal_power * power_modifier / 1000
- core_temperature = max(TCMB, core_temperature)
- //Difference between the gases temperature and the internal temperature of the reaction
- delta_temperature = archived_heat - core_temperature
- //Energy from the reaction lost from the molecule colliding between themselves.
- conduction = - delta_temperature * (magnetic_constrictor * 0.001)
- //The remaining wavelength that actually can do damage to mobs.
- radiation = max(-(PLANCK_LIGHT_CONSTANT / 5e-18) * radiation_modifier * delta_temperature, 0)
- power_output = efficiency * (internal_power - conduction - radiation)
- //Hotter air is easier to heat up and cool down
- heat_limiter_modifier = 10 * (10 ** power_level) * (heating_conductor / 100)
- //The amount of heat that is finally emitted, based on the power output. Min and max are variables that depends of the modifier
- heat_output_min = - heat_limiter_modifier * 0.01 * negative_temperature_multiplier
- heat_output_max = heat_limiter_modifier * positive_temperature_multiplier
- heat_output = clamp(internal_instability * power_output * heat_modifier / 100, heat_output_min, heat_output_max)
-
- // Is the fusion process actually going to run?
- // Note we have to always perform the above calculations to keep the UI updated, so we can't use this to early return.
- if (!check_fuel())
- return
-
- // Phew. Lets calculate what this means in practice.
- var/fuel_consumption_rate = clamp(fuel_injection_rate * 0.01 * 5 * power_level, 0.05, 30)
- var/consumption_amount = fuel_consumption_rate * delta_time
- var/production_amount
- switch(power_level)
- if(3,4)
- production_amount = clamp(heat_output * 5e-4, 0, fuel_consumption_rate) * delta_time
- else
- production_amount = clamp(heat_output / 10 ** (power_level+1), 0, fuel_consumption_rate) * delta_time
-
- // antinob production is special, and uses its own calculations from how stale the fusion mix is (via byproduct ratio and fresh fuel rate)
- var/dirty_production_rate = scaled_fuel_list[scaled_fuel_list[3]] / fuel_injection_rate
-
- // Run the effects of our selected fuel recipe
-
- var/datum/gas_mixture/internal_output = new
- moderator_fuel_process(delta_time, production_amount, consumption_amount, internal_output, moderator_list, selected_fuel, fuel_list)
-
- // Run the common effects, committing changes where applicable
-
- // This is repetition, but is here as a placeholder for what will need to be done to allow concurrently running multiple recipes
- var/common_production_amount = production_amount * selected_fuel.gas_production_multiplier
- moderator_common_process(delta_time, common_production_amount, internal_output, moderator_list, dirty_production_rate, heat_output, radiation_modifier)
-
-/**
- * Perform recipe specific actions. Fuel consumption and recipe based gas production happens here.
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/moderator_fuel_process(delta_time, production_amount, consumption_amount, datum/gas_mixture/internal_output, moderator_list, datum/hfr_fuel/fuel, fuel_list)
- // Adjust fusion consumption/production based on this recipe's characteristics
- var/fuel_consumption = consumption_amount * 0.85 * selected_fuel.fuel_consumption_multiplier
- var/scaled_production = production_amount * selected_fuel.gas_production_multiplier
-
- for(var/gas_id in fuel.requirements)
- internal_fusion.gases[gas_id][MOLES] -= min(fuel_list[gas_id], fuel_consumption)
- for(var/gas_id in fuel.primary_products)
- internal_fusion.gases[gas_id][MOLES] += fuel_consumption * 0.5
-
- // Each recipe provides a tier list of six output gases.
- // Which gases are produced depend on what the fusion level is.
- var/list/tier = fuel.secondary_products
- switch(power_level)
- if(1)
- moderator_internal.gases[tier[1]][MOLES] += scaled_production * 0.95
- moderator_internal.gases[tier[2]][MOLES] += scaled_production * 0.75
- if(2)
- moderator_internal.gases[tier[1]][MOLES] += scaled_production * 1.65
- moderator_internal.gases[tier[2]][MOLES] += scaled_production
- if(moderator_list[/datum/gas/plasma] > 50)
- moderator_internal.gases[tier[3]][MOLES] += scaled_production * 1.15
- if(3)
- moderator_internal.gases[tier[2]][MOLES] += scaled_production * 0.5
- moderator_internal.gases[tier[3]][MOLES] += scaled_production * 0.45
- if(4)
- moderator_internal.gases[tier[3]][MOLES] += scaled_production * 1.65
- moderator_internal.gases[tier[4]][MOLES] += scaled_production * 1.25
- if(5)
- moderator_internal.gases[tier[4]][MOLES] += scaled_production * 0.65
- moderator_internal.gases[tier[5]][MOLES] += scaled_production
- moderator_internal.gases[tier[6]][MOLES] += scaled_production * 0.75
- if(6)
- moderator_internal.gases[tier[5]][MOLES] += scaled_production * 0.35
- moderator_internal.gases[tier[6]][MOLES] += scaled_production
-
-/**
- * Perform common fusion actions:
- *
- * - Gases that get produced irrespective of recipe
- * - Temperature modifiers, radiation modifiers, and the application of each
- * - Committing staged output, performing filtering, and making !FUN! emissions
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/moderator_common_process(delta_time, scaled_production, datum/gas_mixture/internal_output, moderator_list, dirty_production_rate, heat_output, radiation_modifier)
- switch(power_level)
- if(1)
- if(moderator_list[/datum/gas/plasma] > 100)
- moderator_internal.gases[/datum/gas/nitrous_oxide] += scaled_production * 0.5
- moderator_internal.gases[/datum/gas/plasma][MOLES] -= min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 0.85)
- if(moderator_list[/datum/gas/bz] > 150)
- internal_output.assert_gases(/datum/gas/halon)
- internal_output.gases[/datum/gas/halon][MOLES] += scaled_production * 0.55
- moderator_internal.gases[/datum/gas/bz][MOLES] -= min(moderator_internal.gases[/datum/gas/bz][MOLES], scaled_production * 0.95)
- if(2)
- if(moderator_list[/datum/gas/plasma] > 50)
- internal_output.assert_gases(/datum/gas/bz)
- internal_output.gases[/datum/gas/bz][MOLES] += scaled_production * 1.8
- moderator_internal.gases[/datum/gas/plasma][MOLES] -= min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 1.75)
- if(moderator_list[/datum/gas/proto_nitrate] > 20)
- radiation *= 1.55
- heat_output *= 1.025
- internal_output.assert_gases(/datum/gas/nitrium)
- internal_output.gases[/datum/gas/nitrium][MOLES] += scaled_production * 1.05
- moderator_internal.gases[/datum/gas/proto_nitrate][MOLES] -= min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 1.35)
- if(3, 4)
- if(moderator_list[/datum/gas/plasma] > 10)
- internal_output.assert_gases(/datum/gas/freon, /datum/gas/nitrium)
- internal_output.gases[/datum/gas/freon][MOLES] += scaled_production * 0.15
- internal_output.gases[/datum/gas/nitrium][MOLES] += scaled_production * 1.05
- moderator_internal.gases[/datum/gas/plasma][MOLES] -= min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 0.45)
- if(moderator_list[/datum/gas/freon] > 50)
- heat_output *= 0.9
- radiation *= 0.8
- if(moderator_list[/datum/gas/proto_nitrate]> 15)
- internal_output.assert_gases(/datum/gas/nitrium, /datum/gas/halon)
- internal_output.gases[/datum/gas/nitrium][MOLES] += scaled_production * 1.25
- internal_output.gases[/datum/gas/halon][MOLES] += scaled_production * 1.15
- moderator_internal.gases[/datum/gas/proto_nitrate][MOLES] -= min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 1.55)
- radiation *= 1.95
- heat_output *= 1.25
- if(moderator_list[/datum/gas/bz] > 100)
- internal_output.assert_gases(/datum/gas/healium, /datum/gas/proto_nitrate)
- internal_output.gases[/datum/gas/proto_nitrate][MOLES] += scaled_production * 1.5
- internal_output.gases[/datum/gas/healium][MOLES] += scaled_production * 1.5
- induce_hallucination(50 * power_level, delta_time)
- if(5)
- if(moderator_list[/datum/gas/plasma] > 15)
- internal_output.assert_gases(/datum/gas/freon)
- internal_output.gases[/datum/gas/freon][MOLES] += scaled_production *0.25
- moderator_internal.gases[/datum/gas/plasma][MOLES] -= min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 1.45)
- if(moderator_list[/datum/gas/freon] > 500)
- heat_output *= 0.5
- radiation *= 0.2
- if(moderator_list[/datum/gas/proto_nitrate] > 50)
- internal_output.assert_gases(/datum/gas/nitrium, /datum/gas/pluoxium)
- internal_output.gases[/datum/gas/nitrium][MOLES] += scaled_production * 1.95
- internal_output.gases[/datum/gas/pluoxium][MOLES] += scaled_production
- moderator_internal.gases[/datum/gas/proto_nitrate][MOLES] -= min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 1.35)
- radiation *= 1.95
- heat_output *= 1.25
- if(moderator_list[/datum/gas/bz] > 100)
- internal_output.assert_gases(/datum/gas/healium)
- internal_output.gases[/datum/gas/healium][MOLES] += scaled_production
- induce_hallucination(500, delta_time)
- moderator_internal.gases[/datum/gas/freon][MOLES] += scaled_production * 1.15
- if(moderator_list[/datum/gas/healium] > 100)
- if(critical_threshold_proximity > 400)
- critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[/datum/gas/healium] / 100 * delta_time ), 0)
- moderator_internal.gases[/datum/gas/healium][MOLES] -= min(moderator_internal.gases[/datum/gas/healium][MOLES], scaled_production * 20)
- if(moderator_internal.temperature < 1e7 || (moderator_list[/datum/gas/plasma] > 100 && moderator_list[/datum/gas/bz] > 50))
- internal_output.assert_gases(/datum/gas/antinoblium)
- internal_output.gases[/datum/gas/antinoblium][MOLES] += dirty_production_rate * 0.9 / 0.065 * delta_time
- if(6)
- if(moderator_list[/datum/gas/plasma] > 30)
- moderator_internal.gases[/datum/gas/bz][MOLES] += scaled_production * 1.15
- moderator_internal.gases[/datum/gas/plasma][MOLES] -= min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 1.45)
- if(moderator_list[/datum/gas/proto_nitrate])
- internal_output.assert_gases(/datum/gas/zauker, /datum/gas/nitrium)
- internal_output.gases[/datum/gas/zauker][MOLES] += scaled_production * 5.35
- internal_output.gases[/datum/gas/nitrium][MOLES] += scaled_production * 2.15
- moderator_internal.gases[/datum/gas/proto_nitrate][MOLES] -= min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 3.35)
- radiation *= 2
- heat_output *= 2.25
- if(moderator_list[/datum/gas/bz])
- induce_hallucination(900, delta_time, force=TRUE)
- moderator_internal.gases[/datum/gas/antinoblium][MOLES] += clamp(dirty_production_rate / 0.045, 0, 10) * delta_time
- if(moderator_list[/datum/gas/healium] > 100)
- if(critical_threshold_proximity > 400)
- critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[/datum/gas/healium] / 100 * delta_time ), 0)
- moderator_internal.gases[/datum/gas/healium][MOLES] -= min(moderator_internal.gases[/datum/gas/healium][MOLES], scaled_production * 20)
- internal_fusion.gases[/datum/gas/antinoblium][MOLES] += dirty_production_rate * 0.01 / 0.095 * delta_time
-
- //Modifies the internal_fusion temperature with the amount of heat output
- var/temperature_modifier = selected_fuel.temperature_change_multiplier
- if(internal_fusion.temperature <= FUSION_MAXIMUM_TEMPERATURE * temperature_modifier)
- internal_fusion.temperature = clamp(internal_fusion.temperature + heat_output,TCMB,FUSION_MAXIMUM_TEMPERATURE * temperature_modifier)
- else
- internal_fusion.temperature -= heat_limiter_modifier * 0.01 * delta_time
-
- //heat up and output what's in the internal_output into the linked_output port
- if(internal_output.total_moles() > 0)
- if(moderator_internal.total_moles() > 0)
- internal_output.temperature = moderator_internal.temperature * HIGH_EFFICIENCY_CONDUCTIVITY
- else
- internal_output.temperature = internal_fusion.temperature * METALLIC_VOID_CONDUCTIVITY
- linked_output.airs[1].merge(internal_output)
-
- evaporate_moderator(delta_time)
-
- check_nuclear_particles(moderator_list)
-
- check_lightning_arcs(moderator_list)
-
- // Oxygen burns away iron content rapidly
- if(moderator_list[/datum/gas/oxygen] > 150)
- if(iron_content > 0)
- var/max_iron_removable = IRON_OXYGEN_HEAL_PER_SECOND
- var/iron_removed = min(max_iron_removable * delta_time, iron_content)
- iron_content -= iron_removed
- moderator_internal.gases[/datum/gas/oxygen][MOLES] -= iron_removed * OXYGEN_MOLES_CONSUMED_PER_IRON_HEAL
-
- check_gravity_pulse(delta_time)
-
- emit_rads()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/evaporate_moderator(delta_time)
- // Don't evaporate if the reaction is dead
- if (!power_level)
- return
- // All gases in the moderator slowly burn away over time, whether used for production or not
- if(moderator_internal.total_moles() > 0)
- moderator_internal.remove(moderator_internal.total_moles() * (1 - (1 - 0.0005 * power_level) ** delta_time))
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/process_damageheal(delta_time)
- // Archive current health for damage cap purposes
- critical_threshold_proximity_archived = critical_threshold_proximity
-
- // If we're operating at an extreme power level, take increasing damage for the amount of fusion mass over a low threshold
- if(power_level >= HYPERTORUS_OVERFULL_MIN_POWER_LEVEL)
- var/overfull_damage_taken = HYPERTORUS_OVERFULL_MOLAR_SLOPE * internal_fusion.total_moles() + HYPERTORUS_OVERFULL_TEMPERATURE_SLOPE * coolant_temperature + HYPERTORUS_OVERFULL_CONSTANT
- critical_threshold_proximity = max(critical_threshold_proximity + max(overfull_damage_taken * delta_time, 0), 0)
-
- // If we're running on a thin fusion mix, heal up
- if(internal_fusion.total_moles() < HYPERTORUS_SUBCRITICAL_MOLES && power_level <= 5)
- var/subcritical_heal_restore = (internal_fusion.total_moles() - HYPERTORUS_SUBCRITICAL_MOLES) / HYPERTORUS_SUBCRITICAL_SCALE
- critical_threshold_proximity = max(critical_threshold_proximity + min(subcritical_heal_restore * delta_time, 0), 0)
-
- // If coolant is sufficiently cold, heal up
- if(internal_fusion.total_moles() > 0 && (airs[1].total_moles() && coolant_temperature < HYPERTORUS_COLD_COOLANT_THRESHOLD) && power_level <= 4)
- var/cold_coolant_heal_restore = log(10, max(coolant_temperature, 1) * HYPERTORUS_COLD_COOLANT_SCALE) - (HYPERTORUS_COLD_COOLANT_MAX_RESTORE * 2)
- critical_threshold_proximity = max(critical_threshold_proximity + min(cold_coolant_heal_restore * delta_time, 0), 0)
-
- critical_threshold_proximity += max(iron_content - HYPERTORUS_MAX_SAFE_IRON, 0) * delta_time
-
- // Apply damage cap
- critical_threshold_proximity = min(critical_threshold_proximity_archived + (delta_time * DAMAGE_CAP_MULTIPLIER * melting_point), critical_threshold_proximity)
-
- // If we have a preposterous amount of mass in the fusion mix, things get bad extremely fast
- if(internal_fusion.total_moles() >= HYPERTORUS_HYPERCRITICAL_MOLES)
- var/hypercritical_damage_taken = max((internal_fusion.total_moles() - HYPERTORUS_HYPERCRITICAL_MOLES) * HYPERTORUS_HYPERCRITICAL_SCALE, 0)
- critical_threshold_proximity = max(critical_threshold_proximity + min(hypercritical_damage_taken, HYPERTORUS_HYPERCRITICAL_MAX_DAMAGE), 0) * delta_time
-
- // High power fusion might create other matter other than helium, iron is dangerous inside the machine, damage can be seen
- if(power_level > 4 && prob(IRON_CHANCE_PER_FUSION_LEVEL * power_level))//at power level 6 is 100%
- iron_content += IRON_ACCUMULATED_PER_SECOND * delta_time
- if(iron_content > 0 && power_level <= 4 && prob(25 / (power_level + 1)))
- iron_content = max(iron_content - 0.01 * delta_time, 0)
- iron_content = clamp(iron_content, 0, 1)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_nuclear_particles(moderator_list)
- // New nuclear particle emission sytem.
- if(power_level < 4)
- return
- if(moderator_list[/datum/gas/bz] < (150 / power_level))
- return
- var/obj/machinery/hypertorus/corner/picked_corner = pick(corners)
- picked_corner.loc.fire_nuclear_particle(turn(picked_corner.dir, 180))
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_lightning_arcs(moderator_list)
- if(power_level < 4)
- return
- if(moderator_list[/datum/gas/antinoblium] <= 50 && critical_threshold_proximity <= 500)
- return
- var/zap_number = power_level - 2
-
- if(critical_threshold_proximity > 650 && prob(20))
- zap_number += 1
-
- var/cutoff = 1500
- cutoff = clamp(3000 - (power_level * (internal_fusion.total_moles() * 0.45)), 450, 3000)
-
- var/zaps_aspect = DEFAULT_ZAP_ICON_STATE
- var/flags = ZAP_SUPERMATTER_FLAGS
- switch(power_level)
- if(5)
- zaps_aspect = SLIGHTLY_CHARGED_ZAP_ICON_STATE
- flags |= (ZAP_MOB_DAMAGE)
- if(6)
- zaps_aspect = OVER_9000_ZAP_ICON_STATE
- flags |= (ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE)
-
- playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10)
- for(var/i in 1 to zap_number)
- supermatter_zap(src, 5, power_level * 300, flags, zap_cutoff = cutoff, power_level = src.power_level * 1000, zap_icon = zaps_aspect)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_gravity_pulse(delta_time)
- if(DT_PROB(100 - critical_threshold_proximity / 15, delta_time))
- return
- var/grav_range = round(log(2.5, critical_threshold_proximity))
- for(var/mob/alive_mob in GLOB.alive_mob_list)
- if(alive_mob.z != z || get_dist(alive_mob, src) > grav_range || alive_mob.mob_negates_gravity())
- continue
- step_towards(alive_mob, loc)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/remove_waste(delta_time)
- //Gases can be removed from the moderator internal by using the interface.
- if(!waste_remove)
- return
- var/filtering_amount = moderator_scrubbing.len
- for(var/gas in moderator_internal.gases & moderator_scrubbing)
- var/datum/gas_mixture/removed = moderator_internal.remove_specific(gas, (moderator_filtering_rate / filtering_amount) * delta_time)
- if(removed)
- linked_output.airs[1].merge(removed)
-
- if (selected_fuel)
- var/datum/gas_mixture/internal_remove
- for(var/gas_id in selected_fuel.primary_products)
- if(internal_fusion.gases[gas_id][MOLES] > 0)
- internal_remove = internal_fusion.remove_specific(gas_id, internal_fusion.gases[gas_id][MOLES] * (1 - (1 - 0.25) ** delta_time))
- linked_output.airs[1].merge(internal_remove)
- internal_fusion.garbage_collect()
- moderator_internal.garbage_collect()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/process_internal_cooling(delta_time)
- if(moderator_internal.total_moles() > 0 && internal_fusion.total_moles() > 0)
- //Modifies the moderator_internal temperature based on energy conduction and also the fusion by the same amount
- var/fusion_temperature_delta = internal_fusion.temperature - moderator_internal.temperature
- var/fusion_heat_amount = (1 - (1 - METALLIC_VOID_CONDUCTIVITY) ** delta_time) * fusion_temperature_delta * (internal_fusion.heat_capacity() * moderator_internal.heat_capacity() / (internal_fusion.heat_capacity() + moderator_internal.heat_capacity()))
- internal_fusion.temperature = max(internal_fusion.temperature - fusion_heat_amount / internal_fusion.heat_capacity(), TCMB)
- moderator_internal.temperature = max(moderator_internal.temperature + fusion_heat_amount / moderator_internal.heat_capacity(), TCMB)
-
- if(airs[1].total_moles() * 0.05 <= MINIMUM_MOLE_COUNT)
- return
- var/datum/gas_mixture/cooling_port = airs[1]
- var/datum/gas_mixture/cooling_remove = cooling_port.remove(0.05 * cooling_port.total_moles())
- //Cooling of the moderator gases with the cooling loop in and out the core
- if(moderator_internal.total_moles() > 0)
- var/coolant_temperature_delta = cooling_remove.temperature - moderator_internal.temperature
- var/cooling_heat_amount = (1 - (1 - HIGH_EFFICIENCY_CONDUCTIVITY) ** delta_time) * coolant_temperature_delta * (cooling_remove.heat_capacity() * moderator_internal.heat_capacity() / (cooling_remove.heat_capacity() + moderator_internal.heat_capacity()))
- cooling_remove.temperature = max(cooling_remove.temperature - cooling_heat_amount / cooling_remove.heat_capacity(), TCMB)
- moderator_internal.temperature = max(moderator_internal.temperature + cooling_heat_amount / moderator_internal.heat_capacity(), TCMB)
-
- else if(internal_fusion.total_moles() > 0)
- var/coolant_temperature_delta = cooling_remove.temperature - internal_fusion.temperature
- var/cooling_heat_amount = (1 - (1 - METALLIC_VOID_CONDUCTIVITY) ** delta_time) * coolant_temperature_delta * (cooling_remove.heat_capacity() * internal_fusion.heat_capacity() / (cooling_remove.heat_capacity() + internal_fusion.heat_capacity()))
- cooling_remove.temperature = max(cooling_remove.temperature - cooling_heat_amount / cooling_remove.heat_capacity(), TCMB)
- internal_fusion.temperature = max(internal_fusion.temperature + cooling_heat_amount / internal_fusion.heat_capacity(), TCMB)
- cooling_port.merge(cooling_remove)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/inject_from_side_components(delta_time)
- update_pipenets()
-
- //Check and stores the gases from the moderator input in the moderator internal gasmix
- var/datum/gas_mixture/moderator_port = linked_moderator.airs[1]
- if(start_moderator && moderator_port.total_moles())
- moderator_internal.merge(moderator_port.remove(moderator_injection_rate * delta_time))
- linked_moderator.update_parents()
-
- //Check if the fuels are present and move them inside the fuel internal gasmix
- if(!start_fuel || !selected_fuel || !check_gas_requirements())
- return
-
- var/datum/gas_mixture/fuel_port = linked_input.airs[1]
- for(var/gas_type in selected_fuel.requirements)
- internal_fusion.assert_gas(gas_type)
- internal_fusion.merge(fuel_port.remove_specific(gas_type, fuel_injection_rate * delta_time / length(selected_fuel.requirements)))
- linked_input.update_parents()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_deconstructable()
- if(!active)
- return
- if(power_level > 0)
- fusion_started = TRUE
- linked_input.fusion_started = TRUE
- linked_output.fusion_started = TRUE
- linked_moderator.fusion_started = TRUE
- linked_interface.fusion_started = TRUE
- for(var/obj/machinery/hypertorus/corner/corner in corners)
- corner.fusion_started = TRUE
- else
- fusion_started = FALSE
- linked_input.fusion_started = FALSE
- linked_output.fusion_started = FALSE
- linked_moderator.fusion_started = FALSE
- linked_interface.fusion_started = FALSE
- for(var/obj/machinery/hypertorus/corner/corner in corners)
- corner.fusion_started = FALSE
diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm
deleted file mode 100644
index 6d95c1b396c..00000000000
--- a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm
+++ /dev/null
@@ -1,518 +0,0 @@
-/**
- * This file contain the eight parts surrounding the main core, those are: fuel input, moderator input, waste output, interface and the corners
- * The file also contain the guicode of the machine
- */
-/obj/machinery/atmospherics/components/unary/hypertorus
- icon = 'icons/obj/atmospherics/components/hypertorus.dmi'
- icon_state = "core"
-
- name = "thermomachine"
- desc = "Heats or cools gas in connected pipes."
- anchored = TRUE
- density = TRUE
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
- flags_1 = PREVENT_CONTENTS_EXPLOSION_1
- layer = OBJ_LAYER
- pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
- circuit = /obj/item/circuitboard/machine/thermomachine
- ///Vars for the state of the icon of the object (open, off, active)
- var/icon_state_open
- var/icon_state_off
- var/icon_state_active
- ///Check if the machine has been activated
- var/active = FALSE
- ///Check if fusion has started
- var/fusion_started = FALSE
- ///Check if the machine is cracked open
- var/cracked = FALSE
-
-/obj/machinery/atmospherics/components/unary/hypertorus/Initialize(mapload)
- . = ..()
- initialize_directions = dir
-
-/obj/machinery/atmospherics/components/unary/hypertorus/examine(mob/user)
- . = ..()
- . += span_notice("[src] can be rotated by first opening the panel with a screwdriver and then using a wrench on it.")
-
-/obj/machinery/atmospherics/components/unary/hypertorus/attackby(obj/item/I, mob/user, params)
- if(!fusion_started)
- if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_off, I))
- return
- if(default_change_direction_wrench(user, I))
- return
- if(default_deconstruction_crowbar(I))
- return
- return ..()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/welder_act(mob/living/user, obj/item/tool)
- if(!cracked)
- return FALSE
- if(user.combat_mode)
- return FALSE
- balloon_alert(user, "You start repairing the crack...")
- if(tool.use_tool(src, user, 10 SECONDS, volume=30, amount=5))
- balloon_alert(user, "You repaired the crack.")
- cracked = FALSE
- update_appearance()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/default_change_direction_wrench(mob/user, obj/item/I)
- . = ..()
- if(.)
- set_init_directions()
- var/obj/machinery/atmospherics/node = nodes[1]
- if(node)
- node.disconnect(src)
- nodes[1] = null
- if(parents[1])
- nullify_pipenet(parents[1])
- atmos_init()
- node = nodes[1]
- if(node)
- node.atmos_init()
- node.add_member(src)
- SSair.add_to_rebuild_queue(src)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/update_icon_state()
- if(panel_open)
- icon_state = icon_state_open
- return ..()
- if(active)
- icon_state = icon_state_active
- return ..()
- icon_state = icon_state_off
- return ..()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/update_overlays()
- . = ..()
- if(!cracked)
- return
- var/image/crack = image(icon, icon_state = "crack")
- crack.dir = dir
- . += crack
-
-/obj/machinery/atmospherics/components/unary/hypertorus/fuel_input
- name = "HFR fuel input port"
- desc = "Input port for the Hypertorus Fusion Reactor, designed to take in only Hydrogen and Tritium in gas forms."
- icon_state = "fuel_input_off"
- icon_state_open = "fuel_input_open"
- icon_state_off = "fuel_input_off"
- icon_state_active = "fuel_input_active"
- circuit = /obj/item/circuitboard/machine/HFR_fuel_input
-
-/obj/machinery/atmospherics/components/unary/hypertorus/waste_output
- name = "HFR waste output port"
- desc = "Waste port for the Hypertorus Fusion Reactor, designed to output the hot waste gases coming from the core of the machine."
- icon_state = "waste_output_off"
- icon_state_open = "waste_output_open"
- icon_state_off = "waste_output_off"
- icon_state_active = "waste_output_active"
- circuit = /obj/item/circuitboard/machine/HFR_waste_output
-
-/obj/machinery/atmospherics/components/unary/hypertorus/moderator_input
- name = "HFR moderator input port"
- desc = "Moderator port for the Hypertorus Fusion Reactor, designed to move gases inside the machine to cool and control the flow of the reaction."
- icon_state = "moderator_input_off"
- icon_state_open = "moderator_input_open"
- icon_state_off = "moderator_input_off"
- icon_state_active = "moderator_input_active"
- circuit = /obj/item/circuitboard/machine/HFR_moderator_input
-
-/*
-* Interface and corners
-*/
-/obj/machinery/hypertorus
- name = "hypertorus_core"
- desc = "hypertorus_core"
- icon = 'icons/obj/atmospherics/components/hypertorus.dmi'
- icon_state = "core"
- move_resist = INFINITY
- anchored = TRUE
- density = TRUE
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
- flags_1 = PREVENT_CONTENTS_EXPLOSION_1
- power_channel = AREA_USAGE_ENVIRON
- var/active = FALSE
- var/icon_state_open
- var/icon_state_off
- var/icon_state_active
- var/fusion_started = FALSE
-
-/obj/machinery/hypertorus/examine(mob/user)
- . = ..()
- . += span_notice("[src] can be rotated by first opening the panel with a screwdriver and then using a wrench on it.")
-
-/obj/machinery/hypertorus/attackby(obj/item/I, mob/user, params)
- if(!fusion_started)
- if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_off, I))
- return
- if(default_change_direction_wrench(user, I))
- return
- if(default_deconstruction_crowbar(I))
- return
- return ..()
-
-/obj/machinery/hypertorus/update_icon_state()
- if(panel_open)
- icon_state = icon_state_open
- return ..()
- if(active)
- icon_state = icon_state_active
- return ..()
- icon_state = icon_state_off
- return ..()
-
-/obj/machinery/hypertorus/interface
- name = "HFR interface"
- desc = "Interface for the HFR to control the flow of the reaction."
- icon_state = "interface_off"
- circuit = /obj/item/circuitboard/machine/HFR_interface
- var/obj/machinery/atmospherics/components/unary/hypertorus/core/connected_core
- icon_state_off = "interface_off"
- icon_state_open = "interface_open"
- icon_state_active = "interface_active"
-
-/obj/machinery/hypertorus/interface/Destroy()
- if(connected_core)
- connected_core = null
- return..()
-
-/obj/machinery/hypertorus/interface/multitool_act(mob/living/user, obj/item/I)
- . = ..()
- var/turf/T = get_step(src,turn(dir,180))
- var/obj/machinery/atmospherics/components/unary/hypertorus/core/centre = locate() in T
-
- if(!centre || !centre.check_part_connectivity())
- to_chat(user, span_notice("Check all parts and then try again."))
- return TRUE
- new/obj/item/paper/guides/jobs/atmos/hypertorus(loc)
- connected_core = centre
-
- connected_core.activate(user)
- return TRUE
-
-/obj/machinery/hypertorus/interface/ui_interact(mob/user, datum/tgui/ui)
- if(active)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "Hypertorus", name)
- ui.open()
- else
- to_chat(user, span_notice("Activate the machine first by using a multitool on the interface."))
-
-/obj/machinery/hypertorus/interface/proc/gas_list_to_gasid_list(list/gas_list)
- var/list/gasid_list = list()
- for(var/gas_type in gas_list)
- var/datum/gas/gas = gas_type
- gasid_list += initial(gas.id)
- return gasid_list
-
-
-
-/obj/machinery/hypertorus/interface/ui_static_data()
- var/data = list()
- data["base_max_temperature"] = FUSION_MAXIMUM_TEMPERATURE
- data["selectable_fuel"] = list(list("name" = "Nothing", "id" = null))
- for(var/path in GLOB.hfr_fuels_list)
- var/datum/hfr_fuel/recipe = GLOB.hfr_fuels_list[path]
-
- data["selectable_fuel"] += list(list(
- "name" = recipe.name,
- "id" = recipe.id,
- "requirements" = gas_list_to_gasid_list(recipe.requirements),
- "fusion_byproducts" = gas_list_to_gasid_list(recipe.primary_products),
- "product_gases" = gas_list_to_gasid_list(recipe.secondary_products),
- "recipe_cooling_multiplier" = recipe.negative_temperature_multiplier,
- "recipe_heating_multiplier" = recipe.positive_temperature_multiplier,
- "energy_loss_multiplier" = recipe.energy_concentration_multiplier,
- "fuel_consumption_multiplier" = recipe.fuel_consumption_multiplier,
- "gas_production_multiplier" = recipe.gas_production_multiplier,
- "temperature_multiplier" = recipe.temperature_change_multiplier,
- ))
- return data
-
-/obj/machinery/hypertorus/interface/ui_data()
- var/data = list()
-
- if(connected_core.selected_fuel)
- data["selected"] = connected_core.selected_fuel.id
- else
- data["selected"] = ""
-
- //Internal Fusion gases
- var/list/fusion_gasdata = list()
- if(connected_core.internal_fusion.total_moles())
- for(var/gas_type in connected_core.internal_fusion.gases)
- var/datum/gas/gas = gas_type
- fusion_gasdata.Add(list(list(
- "id"= initial(gas.id),
- "amount" = round(connected_core.internal_fusion.gases[gas][MOLES], 0.01),
- )))
- else
- for(var/gas_type in connected_core.internal_fusion.gases)
- var/datum/gas/gas = gas_type
- fusion_gasdata.Add(list(list(
- "id"= initial(gas.id),
- "amount" = 0,
- )))
- //Moderator gases
- var/list/moderator_gasdata = list()
- if(connected_core.moderator_internal.total_moles())
- for(var/gas_type in connected_core.moderator_internal.gases)
- var/datum/gas/gas = gas_type
- moderator_gasdata.Add(list(list(
- "id"= initial(gas.id),
- "amount" = round(connected_core.moderator_internal.gases[gas][MOLES], 0.01),
- )))
- else
- for(var/gas_type in connected_core.moderator_internal.gases)
- var/datum/gas/gas = gas_type
- moderator_gasdata.Add(list(list(
- "id"= initial(gas.id),
- "amount" = 0,
- )))
-
- data["fusion_gases"] = fusion_gasdata
- data["moderator_gases"] = moderator_gasdata
-
- data["energy_level"] = connected_core.energy
- data["heat_limiter_modifier"] = connected_core.heat_limiter_modifier
- data["heat_output_min"] = connected_core.heat_output_min
- data["heat_output_max"] = connected_core.heat_output_max
- data["heat_output"] = connected_core.heat_output
- data["instability"] = connected_core.instability
-
- data["heating_conductor"] = connected_core.heating_conductor
- data["magnetic_constrictor"] = connected_core.magnetic_constrictor
- data["fuel_injection_rate"] = connected_core.fuel_injection_rate
- data["moderator_injection_rate"] = connected_core.moderator_injection_rate
- data["current_damper"] = connected_core.current_damper
-
- data["power_level"] = connected_core.power_level
- data["apc_energy"] = connected_core.get_area_cell_percent()
- data["iron_content"] = connected_core.iron_content
- data["integrity"] = connected_core.get_integrity_percent()
-
- data["start_power"] = connected_core.start_power
- data["start_cooling"] = connected_core.start_cooling
- data["start_fuel"] = connected_core.start_fuel
- data["start_moderator"] = connected_core.start_moderator
-
- data["internal_fusion_temperature"] = connected_core.fusion_temperature
- data["moderator_internal_temperature"] = connected_core.moderator_temperature
- data["internal_output_temperature"] = connected_core.output_temperature
- data["internal_coolant_temperature"] = connected_core.coolant_temperature
-
- data["internal_fusion_temperature_archived"] = connected_core.fusion_temperature_archived
- data["moderator_internal_temperature_archived"] = connected_core.moderator_temperature_archived
- data["internal_output_temperature_archived"] = connected_core.output_temperature_archived
- data["internal_coolant_temperature_archived"] = connected_core.coolant_temperature_archived
- data["temperature_period"] = connected_core.temperature_period
-
- data["waste_remove"] = connected_core.waste_remove
- data["filter_types"] = list()
- for(var/path in GLOB.meta_gas_info)
- var/list/gas = GLOB.meta_gas_info[path]
- data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in connected_core.moderator_scrubbing)))
-
- data["cooling_volume"] = connected_core.airs[1].volume
- data["mod_filtering_rate"] = connected_core.moderator_filtering_rate
-
- return data
-
-/obj/machinery/hypertorus/interface/ui_act(action, params)
- . = ..()
- if(.)
- return
- switch(action)
- if("start_power")
- connected_core.start_power = !connected_core.start_power
- connected_core.update_use_power(connected_core.start_power ? ACTIVE_POWER_USE : IDLE_POWER_USE)
- . = TRUE
- if("start_cooling")
- connected_core.start_cooling = !connected_core.start_cooling
- . = TRUE
- if("start_fuel")
- connected_core.start_fuel = !connected_core.start_fuel
- . = TRUE
- if("start_moderator")
- connected_core.start_moderator = !connected_core.start_moderator
- . = TRUE
- if("heating_conductor")
- var/heating_conductor = text2num(params["heating_conductor"])
- if(heating_conductor != null)
- connected_core.heating_conductor = clamp(heating_conductor, 50, 500)
- . = TRUE
- if("magnetic_constrictor")
- var/magnetic_constrictor = text2num(params["magnetic_constrictor"])
- if(magnetic_constrictor != null)
- connected_core.magnetic_constrictor = clamp(magnetic_constrictor, 50, 1000)
- . = TRUE
- if("fuel_injection_rate")
- var/fuel_injection_rate = text2num(params["fuel_injection_rate"])
- if(fuel_injection_rate != null)
- connected_core.fuel_injection_rate = clamp(fuel_injection_rate, 0.5, 150)
- . = TRUE
- if("moderator_injection_rate")
- var/moderator_injection_rate = text2num(params["moderator_injection_rate"])
- if(moderator_injection_rate != null)
- connected_core.moderator_injection_rate = clamp(moderator_injection_rate, 0.5, 150)
- . = TRUE
- if("current_damper")
- var/current_damper = text2num(params["current_damper"])
- if(current_damper != null)
- connected_core.current_damper = clamp(current_damper, 0, 1000)
- . = TRUE
- if("waste_remove")
- connected_core.waste_remove = !connected_core.waste_remove
- . = TRUE
- if("filter")
- connected_core.moderator_scrubbing ^= gas_id2path(params["mode"])
- . = TRUE
- if("mod_filtering_rate")
- var/mod_filtering_rate = text2num(params["mod_filtering_rate"])
- if(mod_filtering_rate != null)
- connected_core.moderator_filtering_rate = clamp(mod_filtering_rate, 5, 200)
- . = TRUE
- if("fuel")
- connected_core.selected_fuel = null
- var/fuel_mix = "nothing"
- var/datum/hfr_fuel/fuel = null
- if(params["mode"] != "")
- fuel = GLOB.hfr_fuels_list[params["mode"]]
- if(fuel)
- connected_core.selected_fuel = fuel
- fuel_mix = fuel.name
- if(connected_core.internal_fusion.total_moles())
- connected_core.dump_gases()
- connected_core.update_parents() //prevent the machine from stopping because of the recipe change and the pipenet not updating
- connected_core.linked_input.update_parents()
- connected_core.linked_output.update_parents()
- connected_core.linked_moderator.update_parents()
- investigate_log("was set to recipe [fuel_mix ? fuel_mix : "null"] by [key_name(usr)]", INVESTIGATE_ATMOS)
- . = TRUE
- if("cooling_volume")
- var/cooling_volume = text2num(params["cooling_volume"])
- if(cooling_volume != null)
- connected_core.airs[1].volume = clamp(cooling_volume, 50, 2000)
- . = TRUE
-
-/obj/machinery/hypertorus/corner
- name = "HFR corner"
- desc = "Structural piece of the machine."
- icon_state = "corner_off"
- circuit = /obj/item/circuitboard/machine/HFR_corner
- icon_state_off = "corner_off"
- icon_state_open = "corner_open"
- icon_state_active = "corner_active"
- dir = SOUTHEAST
-
-/obj/item/paper/guides/jobs/atmos/hypertorus
- name = "paper- 'Quick guide to safe handling of the HFR'"
- info = "How to safely(TM) operate the Hypertorus \
- -Build the machine as it�s shown in the main guide. \
- -Make a 50/50 gasmix of tritium and hydrogen totalling around 2000 moles. \
- -Start the machine, fill up the cooling loop with plasma/hypernoblium and use space or freezers to cool it. \
- -Connect the fuel mix into the fuel injector port, allow only 1000 moles into the machine to ease the kickstart of the reaction \
- -Set the Heat conductor to 500 when starting the reaction, reset it to 100 when power level is higher than 1 \
- -In the event of a meltdown, set the heat conductor to max and set the current damper to max. Set the fuel injection to min. \
- If the heat output doesn�t go negative, try changing the magnetic costrictors untill heat output goes negative. \
- Make the cooling stronger, put high heat capacity gases inside the moderator (hypernoblium will help dealing with the problem)
\
- Warnings: \
- -You cannot dismantle the machine if the power level is over 0 \
- -You cannot power of the machine if the power level is over 0 \
- -You cannot dispose of waste gases if power level is over 5 \
- -You cannot remove gases from the fusion mix if they are not helium and antinoblium \
- -Hypernoblium will decrease the power of the mix by a lot \
- -Antinoblium will INCREASE the power of the mix by a lot more \
- -High heat capacity gases are harder to heat/cool \
- -Low heat capacity gases are easier to heat/cool \
- -The machine consumes 50 KW per power level, reaching 350 KW at power level 6 so prepare the SM accordingly \
- -In case of a power shortage, the fusion reaction will CONTINUE but the cooling will STOP
\
- The writer of the quick guide will not be held responsible for misuses and meltdown caused by the use of the guide, \
- use more advanced guides to understando how the various gases will act as moderators."
-
-/obj/item/hfr_box
- name = "HFR box"
- desc = "If you see this, call the police."
- icon = 'icons/obj/atmospherics/components/hypertorus.dmi'
- icon_state = "box"
- ///What kind of box are we handling?
- var/box_type = "impossible"
- ///What's the path of the machine we making
- var/part_path
-
-/obj/item/hfr_box/corner
- name = "HFR box corner"
- desc = "Place this as the corner of your 3x3 multiblock fusion reactor"
- icon_state = "box_corner"
- box_type = "corner"
- part_path = /obj/machinery/hypertorus/corner
-
-/obj/item/hfr_box/body
- name = "HFR box body"
- desc = "Place this on the sides of the core box of your 3x3 multiblock fusion reactor"
- box_type = "body"
- icon_state = "box_body"
-
-/obj/item/hfr_box/body/fuel_input
- name = "HFR box fuel input"
- part_path = /obj/machinery/atmospherics/components/unary/hypertorus/fuel_input
-
-/obj/item/hfr_box/body/moderator_input
- name = "HFR box moderator input"
- part_path = /obj/machinery/atmospherics/components/unary/hypertorus/moderator_input
-
-/obj/item/hfr_box/body/waste_output
- name = "HFR box waste output"
- part_path = /obj/machinery/atmospherics/components/unary/hypertorus/waste_output
-
-/obj/item/hfr_box/body/interface
- name = "HFR box interface"
- part_path = /obj/machinery/hypertorus/interface
-
-/obj/item/hfr_box/core
- name = "HFR box core"
- desc = "Activate this with a multitool to deploy the full machine after setting up the other boxes"
- icon_state = "box_core"
- box_type = "core"
- part_path = /obj/machinery/atmospherics/components/unary/hypertorus/core
-
-/obj/item/hfr_box/core/multitool_act(mob/living/user, obj/item/I)
- . = ..()
- var/list/parts = list()
- for(var/obj/item/hfr_box/box in orange(1,src))
- var/direction = get_dir(src, box)
- if(box.box_type == "corner")
- if(ISDIAGONALDIR(direction))
- box.dir = direction
- parts |= box
- continue
- if(box.box_type == "body")
- if(direction in GLOB.cardinals)
- box.dir = direction
- parts |= box
- continue
- if(parts.len == 8)
- build_reactor(parts)
- return
-
-/obj/item/hfr_box/core/proc/build_reactor(list/parts)
- for(var/obj/item/hfr_box/box in parts)
- if(box.box_type == "corner")
- var/obj/machinery/hypertorus/corner/corner = new box.part_path(box.loc)
- corner.dir = box.dir
- qdel(box)
- continue
- if(box.box_type == "body")
- var/location = get_turf(box)
- if(box.part_path != /obj/machinery/hypertorus/interface)
- var/obj/machinery/atmospherics/components/unary/hypertorus/part = new box.part_path(location, TRUE, box.dir)
- part.dir = box.dir
- else
- var/obj/machinery/hypertorus/interface/part = new box.part_path(location)
- part.dir = box.dir
- qdel(box)
- continue
-
- new/obj/machinery/atmospherics/components/unary/hypertorus/core(loc, TRUE)
- qdel(src)
diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm
deleted file mode 100644
index c8085b9c35d..00000000000
--- a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm
+++ /dev/null
@@ -1,619 +0,0 @@
-/**
- * This section contain all procs that helps building, destroy and control the hfr
- */
-
-/**
- * Called by multitool_act() in hfr_parts.dm, by atmos_process() in hfr_main_processes.dm and by fusion_process() in the same file
- * This proc checks the surrounding of the core to ensure that the machine has been build correctly, returns false if there is a missing piece/wrong placed one
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_part_connectivity()
- . = TRUE
- if(!anchored || panel_open)
- return FALSE
-
- for(var/obj/machinery/hypertorus/object in orange(1,src))
- if(. == FALSE)
- break
-
- if(object.panel_open)
- . = FALSE
-
- if(istype(object,/obj/machinery/hypertorus/corner))
- var/dir = get_dir(src,object)
- if(dir in GLOB.cardinals)
- . = FALSE
- switch(dir)
- if(SOUTHEAST)
- if(object.dir != dir)
- . = FALSE
- if(SOUTHWEST)
- if(object.dir != dir)
- . = FALSE
- if(NORTHEAST)
- if(object.dir != dir)
- . = FALSE
- if(NORTHWEST)
- if(object.dir != dir)
- . = FALSE
- corners |= object
- continue
-
- if(get_step(object,turn(object.dir,180)) != loc)
- . = FALSE
-
- if(istype(object,/obj/machinery/hypertorus/interface))
- if(linked_interface && linked_interface != object)
- . = FALSE
- linked_interface = object
-
- for(var/obj/machinery/atmospherics/components/unary/hypertorus/object in orange(1,src))
- if(. == FALSE)
- break
-
- if(object.panel_open)
- . = FALSE
-
- if(get_step(object,turn(object.dir,180)) != loc)
- . = FALSE
-
- if(istype(object,/obj/machinery/atmospherics/components/unary/hypertorus/fuel_input))
- if(linked_input && linked_input != object)
- . = FALSE
- linked_input = object
- machine_parts |= object
-
- if(istype(object,/obj/machinery/atmospherics/components/unary/hypertorus/waste_output))
- if(linked_output && linked_output != object)
- . = FALSE
- linked_output = object
- machine_parts |= object
-
- if(istype(object,/obj/machinery/atmospherics/components/unary/hypertorus/moderator_input))
- if(linked_moderator && linked_moderator != object)
- . = FALSE
- linked_moderator = object
- machine_parts |= object
-
- if(!linked_interface || !linked_input || !linked_moderator || !linked_output || corners.len != 4)
- . = FALSE
-
-/**
- * Called by multitool_act() in hfr_parts.dm
- * It sets the pieces to active, allowing the player to start the main reaction
- * Arguments:
- * * -user: the player doing the action
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/activate(mob/living/user)
- if(active)
- to_chat(user, span_notice("You already activated the machine."))
- return
- to_chat(user, span_notice("You link all parts toghether."))
- active = TRUE
- update_appearance()
- linked_interface.active = TRUE
- linked_interface.update_appearance()
- RegisterSignal(linked_interface, COMSIG_PARENT_QDELETING, .proc/unregister_signals)
- linked_input.active = TRUE
- linked_input.update_appearance()
- RegisterSignal(linked_input, COMSIG_PARENT_QDELETING, .proc/unregister_signals)
- linked_output.active = TRUE
- linked_output.update_appearance()
- RegisterSignal(linked_output, COMSIG_PARENT_QDELETING, .proc/unregister_signals)
- linked_moderator.active = TRUE
- linked_moderator.update_appearance()
- RegisterSignal(linked_moderator, COMSIG_PARENT_QDELETING, .proc/unregister_signals)
- for(var/obj/machinery/hypertorus/corner/corner in corners)
- corner.active = TRUE
- corner.update_appearance()
- RegisterSignal(corner, COMSIG_PARENT_QDELETING, .proc/unregister_signals)
- soundloop = new(src, TRUE)
- soundloop.volume = 5
-
-/**
- * Called when a part gets deleted around the hfr, called on Destroy() of the hfr core in hfr_core.dm
- * Unregister the signals attached to the core from the various machines, if only_signals is false it will also call deactivate()
- * Arguments:
- * * only_signals: default FALSE, if true the proc will not call the deactivate() proc
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/unregister_signals(only_signals = FALSE)
- SIGNAL_HANDLER
- if(linked_interface)
- UnregisterSignal(linked_interface, COMSIG_PARENT_QDELETING)
- if(linked_input)
- UnregisterSignal(linked_input, COMSIG_PARENT_QDELETING)
- if(linked_output)
- UnregisterSignal(linked_output, COMSIG_PARENT_QDELETING)
- if(linked_moderator)
- UnregisterSignal(linked_moderator, COMSIG_PARENT_QDELETING)
- for(var/obj/machinery/hypertorus/corner/corner in corners)
- UnregisterSignal(corner, COMSIG_PARENT_QDELETING)
- if(!only_signals)
- deactivate()
-
-/**
- * Called by unregister_signals() in this file, called when the main fusion processes check_part_connectivity() returns false
- * Deactivate the various machines by setting the active var to false, updates the machines icon and set the linked machine vars to null
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/deactivate()
- if(!active)
- return
- active = FALSE
- update_appearance()
- if(linked_interface)
- linked_interface.active = FALSE
- linked_interface.update_appearance()
- linked_interface = null
- if(linked_input)
- linked_input.active = FALSE
- linked_input.update_appearance()
- linked_input = null
- if(linked_output)
- linked_output.active = FALSE
- linked_output.update_appearance()
- linked_output = null
- if(linked_moderator)
- linked_moderator.active = FALSE
- linked_moderator.update_appearance()
- linked_moderator = null
- if(corners.len)
- for(var/obj/machinery/hypertorus/corner/corner in corners)
- corner.active = FALSE
- corner.update_appearance()
- corners = list()
- QDEL_NULL(soundloop)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/assert_gases()
- //Assert the gases that will be used/created during the process
-
- internal_fusion.assert_gas(/datum/gas/antinoblium)
-
- moderator_internal.assert_gases(arglist(GLOB.meta_gas_info))
-
- if (!selected_fuel)
- return
-
- internal_fusion.assert_gases(arglist(selected_fuel.requirements | selected_fuel.primary_products))
-
-/**
- * Updates all related pipenets from all connected components
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/update_pipenets()
- update_parents()
- linked_input.update_parents()
- linked_output.update_parents()
- linked_moderator.update_parents()
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/update_temperature_status(delta_time)
- fusion_temperature_archived = fusion_temperature
- fusion_temperature = internal_fusion.temperature
- moderator_temperature_archived = moderator_temperature
- moderator_temperature = moderator_internal.temperature
- coolant_temperature_archived = coolant_temperature
- coolant_temperature = airs[1].temperature
- output_temperature_archived = output_temperature
- output_temperature = linked_output.airs[1].temperature
- temperature_period = delta_time
-
- //Set the power level of the fusion process
- switch(fusion_temperature)
- if(-INFINITY to 500)
- power_level = 0
- if(500 to 1e3)
- power_level = 1
- if(1e3 to 1e4)
- power_level = 2
- if(1e4 to 1e5)
- power_level = 3
- if(1e5 to 1e6)
- power_level = 4
- if(1e6 to 1e7)
- power_level = 5
- else
- power_level = 6
-
-/**
- * Infrequently plays accent sounds, and adjusts main loop parameters
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/play_ambience()
- // We play delam/neutral sounds at a rate determined by power and critical_threshold_proximity
- if(last_accent_sound < world.time && prob(20))
- var/aggression = min(((critical_threshold_proximity / 800) * ((power_level) / 5)), 1.0) * 100
- if(critical_threshold_proximity >= 300)
- playsound(src, SFX_HYPERTORUS_MELTING, max(50, aggression), FALSE, 40, 30, falloff_distance = 10)
- else
- playsound(src, SFX_HYPERTORUS_CALM, max(50, aggression), FALSE, 25, 25, falloff_distance = 10)
- var/next_sound = round((100 - aggression) * 5) + 5
- last_accent_sound = world.time + max(HYPERTORUS_ACCENT_SOUND_MIN_COOLDOWN, next_sound)
-
- var/ambient_hum = 1
- if (check_fuel())
- ambient_hum = power_level + 1
- soundloop.volume = clamp(ambient_hum * 8, 0, 50)
-
-/**
- * Called by the main fusion processes in hfr_main_processes.dm
- * Getter for fusion fuel moles
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_fuel()
- if(!selected_fuel)
- return FALSE
- if(!internal_fusion.total_moles())
- return FALSE
- for(var/gas_type in selected_fuel.requirements)
- internal_fusion.assert_gas(gas_type)
- if(internal_fusion.gases[gas_type][MOLES] < FUSION_MOLE_THRESHOLD)
- return FALSE
- return TRUE
-
-/**
- * Called by the main fusion processes in hfr_main_processes.dm
- * Check the power use of the machine, return TRUE if there is enough power in the powernet
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_power_use()
- if(machine_stat & (NOPOWER|BROKEN))
- return FALSE
- if(use_power == ACTIVE_POWER_USE)
- update_mode_power_usage(ACTIVE_POWER_USE, (power_level + 1) * MIN_POWER_USAGE) //Max around 350 KW
-
- return TRUE
-
-///Checks if the gases in the input are the ones needed by the recipe
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_gas_requirements()
- var/datum/gas_mixture/contents = linked_input.airs[1]
- for(var/gas_type in selected_fuel.requirements)
- if(!contents.gases[gas_type] || !contents.gases[gas_type][MOLES])
- return FALSE
- return TRUE
-
-///Removes the gases from the internal gasmix when the recipe is changed
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/dump_gases()
- var/datum/gas_mixture/remove = internal_fusion.remove(internal_fusion.total_moles())
- linked_output.airs[1].merge(remove)
- internal_fusion.garbage_collect()
- linked_input.airs[1].garbage_collect()
-
-/**
- * Called by alarm() in this file
- * Check the integrity level and returns the status of the machine
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/get_status()
- var/integrity = get_integrity_percent()
- if(integrity < HYPERTORUS_MELTING_PERCENT)
- return HYPERTORUS_MELTING
-
- if(integrity < HYPERTORUS_EMERGENCY_PERCENT)
- return HYPERTORUS_EMERGENCY
-
- if(integrity < HYPERTORUS_DANGER_PERCENT)
- return HYPERTORUS_DANGER
-
- if(integrity < HYPERTORUS_WARNING_PERCENT)
- return HYPERTORUS_WARNING
-
- if(power_level > 0)
- return HYPERTORUS_NOMINAL
- return HYPERTORUS_INACTIVE
-
-/**
- * Called by check_alert() in this file
- * Play a sound from the machine, the type depends on the status of the hfr
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/alarm()
- switch(get_status())
- if(HYPERTORUS_MELTING)
- playsound(src, 'sound/misc/bloblarm.ogg', 100, FALSE, 40, 30, falloff_distance = 10)
- if(HYPERTORUS_EMERGENCY)
- playsound(src, 'sound/machines/engine_alert1.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
- if(HYPERTORUS_DANGER)
- playsound(src, 'sound/machines/engine_alert2.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
- if(HYPERTORUS_WARNING)
- playsound(src, 'sound/machines/terminal_alert.ogg', 75)
-
-/**
- * Getter for the machine integrity
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/get_integrity_percent()
- var/integrity = critical_threshold_proximity / melting_point
- integrity = round(100 - integrity * 100, 0.01)
- integrity = integrity < 0 ? 0 : integrity
- return integrity
-
-/**
- * Get how charged the area's APC is
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/get_area_cell_percent()
- // Make sure to get APC levels from the same area the core draws from
- // Just in case people build an HFR across boundaries
- var/area/area = get_area(src)
- if (!area)
- return 0
- var/obj/machinery/power/apc/apc = area.apc
- if (!apc)
- return 0
- var/obj/item/stock_parts/cell/cell = apc.cell
- if (!cell)
- return 0
- return cell.percent()
-
-/**
- * Called by process_atmos() in hfr_main_processes.dm
- * Called after checking the damage of the machine, calls alarm() and countdown()
- * Broadcast messages into engi and common radio
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_alert()
- if(critical_threshold_proximity < warning_point)
- return
- if((REALTIMEOFDAY - lastwarning) / 10 >= WARNING_TIME_DELAY)
- alarm()
-
- if(critical_threshold_proximity > emergency_point)
- radio.talk_into(src, "[emergency_alert] Integrity: [get_integrity_percent()]%", common_channel)
- lastwarning = REALTIMEOFDAY
- if(!has_reached_emergency)
- investigate_log("has reached the emergency point for the first time.", INVESTIGATE_HYPERTORUS)
- message_admins("[src] has reached the emergency point [ADMIN_JMP(src)].")
- has_reached_emergency = TRUE
- else if(critical_threshold_proximity >= critical_threshold_proximity_archived) // The damage is still going up
- radio.talk_into(src, "[warning_alert] Integrity: [get_integrity_percent()]%", engineering_channel)
- lastwarning = REALTIMEOFDAY - (WARNING_TIME_DELAY * 5)
-
- else // Phew, we're safe
- radio.talk_into(src, "[safe_alert] Integrity: [get_integrity_percent()]%", engineering_channel)
- lastwarning = REALTIMEOFDAY
-
- //Melt
- if(critical_threshold_proximity > melting_point)
- countdown()
-
-/**
- * Called by check_alert() in this file
- * Called when the damage has reached critical levels, start the countdown before the destruction, calls meltdown()
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/countdown()
- set waitfor = FALSE
-
- if(final_countdown) // We're already doing it go away
- return
- final_countdown = TRUE
-
- var/critical = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_CRITICAL_MELTDOWN
- if(critical)
- priority_announce("WARNING - The explosion will likely cover a big part of the station and the coming EMP will wipe out most of the electronics. \
- Get as far away as possible from the reactor or find a way to shut it down.", "Alert")
- var/speaking = "[emergency_alert] The Hypertorus fusion reactor has reached critical integrity failure. Emergency magnetic dampeners online."
- radio.talk_into(src, speaking, common_channel, language = get_selected_language())
- for(var/i in HYPERTORUS_COUNTDOWN_TIME to 0 step -10)
- if(critical_threshold_proximity < melting_point) // Cutting it a bit close there engineers
- radio.talk_into(src, "[safe_alert] Failsafe has been disengaged.", common_channel)
- final_countdown = FALSE
- return
- else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy
- sleep(10)
- continue
- else if(i > 50)
- if(i == 10 SECONDS && critical)
- sound_to_playing_players('sound/machines/hypertorus/HFR_critical_explosion.ogg')
- speaking = "[DisplayTimeText(i, TRUE)] remain before total integrity failure."
- else
- speaking = "[i*0.1]..."
- radio.talk_into(src, speaking, common_channel)
- sleep(10)
-
- meltdown()
-
-/**
- * Called by countdown() in this file
- * Create the explosion + the gas emission before deleting the machine core.
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/meltdown()
- var/flash_explosion = 0
- var/light_impact_explosion = 0
- var/heavy_impact_explosion = 0
- var/devastating_explosion = 0
- var/em_pulse = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_EMP
- var/rad_pulse = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_RADIATION_PULSE
- var/emp_light_size = 0
- var/emp_heavy_size = 0
- var/rad_pulse_size = 0
- var/gas_spread = 0
- var/gas_pockets = 0
- var/critical = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_CRITICAL_MELTDOWN
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_BASE_EXPLOSION)
- flash_explosion = power_level * 3
- light_impact_explosion = power_level * 2
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MEDIUM_EXPLOSION)
- flash_explosion = power_level * 6
- light_impact_explosion = power_level * 5
- heavy_impact_explosion = power_level * 0.5
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_DEVASTATING_EXPLOSION)
- flash_explosion = power_level * 8
- light_impact_explosion = power_level * 7
- heavy_impact_explosion = power_level * 2
- devastating_explosion = power_level
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MINIMUM_SPREAD)
- if(em_pulse)
- emp_light_size = power_level * 3
- emp_heavy_size = power_level * 1
- if(rad_pulse)
- rad_pulse_size = 2 * power_level + 8
- gas_pockets = 5
- gas_spread = power_level * 2
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MEDIUM_SPREAD)
- if(em_pulse)
- emp_light_size = power_level * 5
- emp_heavy_size = power_level * 3
- if(rad_pulse)
- rad_pulse_size = power_level + 24
- gas_pockets = 7
- gas_spread = power_level * 4
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_BIG_SPREAD)
- if(em_pulse)
- emp_light_size = power_level * 7
- emp_heavy_size = power_level * 5
- if(rad_pulse)
- rad_pulse_size = power_level + 34
- gas_pockets = 10
- gas_spread = power_level * 6
-
- if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MASSIVE_SPREAD)
- if(em_pulse)
- emp_light_size = power_level * 9
- emp_heavy_size = power_level * 7
- if(rad_pulse)
- rad_pulse_size = power_level + 44
- gas_pockets = 15
- gas_spread = power_level * 8
-
- var/list/around_turfs = circle_range_turfs(src, gas_spread)
- for(var/turf/turf as anything in around_turfs)
- if(isclosedturf(turf) || isspaceturf(turf))
- around_turfs -= turf
- continue
- var/datum/gas_mixture/remove_fusion
- if(internal_fusion.total_moles() > 0)
- remove_fusion = internal_fusion.remove_ratio(0.2)
- var/datum/gas_mixture/remove
- for(var/i in 1 to gas_pockets)
- remove = remove_fusion.remove_ratio(1/gas_pockets)
- var/turf/local = pick(around_turfs)
- local.assume_air(remove)
- loc.assume_air(internal_fusion)
- var/datum/gas_mixture/remove_moderator
- if(moderator_internal.total_moles() > 0)
- remove_moderator = moderator_internal.remove_ratio(0.2)
- var/datum/gas_mixture/remove
- for(var/i in 1 to gas_pockets)
- remove = remove_moderator.remove_ratio(1/gas_pockets)
- var/turf/local = pick(around_turfs)
- local.assume_air(remove)
- loc.assume_air(moderator_internal)
-
- //Max explosion ranges: devastation = 12, heavy = 24, light = 42
- explosion(
- origin = src,
- devastation_range = critical ? devastating_explosion * 2 : devastating_explosion,
- heavy_impact_range = critical ? heavy_impact_explosion * 2 : heavy_impact_explosion,
- light_impact_range = light_impact_explosion,
- flash_range = flash_explosion,
- adminlog = TRUE,
- ignorecap = TRUE
- )
-
- if(rad_pulse)
- radiation_pulse(
- source = loc,
- max_range = rad_pulse_size,
- threshold = 0.05,
- )
-
- if(em_pulse)
- empulse(
- epicenter = loc,
- heavy_range = critical ? emp_heavy_size * 2 : emp_heavy_size,
- light_range = critical ? emp_light_size * 2 : emp_heavy_size,
- log = TRUE
- )
-
- qdel(src)
-
-/**
- * Induce hallucinations in nearby humans.
- *
- * force will make hallucinations ignore meson protection.
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/induce_hallucination(strength, delta_time, force=FALSE)
- for(var/mob/living/carbon/human/human in view(src, HALLUCINATION_HFR(heat_output)))
- if(!force && istype(human.glasses, /obj/item/clothing/glasses/meson))
- continue
- var/distance_root = sqrt(1 / max(1, get_dist(human, src)))
- human.hallucination += strength * distance_root * delta_time
- human.hallucination = clamp(human.hallucination, 0, 200)
-
-/**
- * Emit radiation
- */
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/emit_rads()
- radiation_pulse(
- src,
- max_range = 6,
- threshold = 0.3,
- )
-
-/*
- * HFR cracking related procs
- */
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_cracked_parts()
- for(var/obj/machinery/atmospherics/components/unary/hypertorus/part in machine_parts)
- if(part.cracked)
- return TRUE
- return FALSE
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/create_crack()
- var/obj/machinery/atmospherics/components/unary/hypertorus/part = pick(machine_parts)
- part.cracked = TRUE
- part.update_appearance()
- return part
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/spill_gases(obj/origin, datum/gas_mixture/target_mix, ratio)
- var/datum/gas_mixture/remove_mixture = target_mix.remove_ratio(ratio)
- var/turf/origin_turf = origin.loc
- if(!origin_turf)
- return
- origin_turf.assume_air(remove_mixture)
-
-/obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_spill(delta_time)
- var/obj/machinery/atmospherics/components/unary/hypertorus/cracked_part = check_cracked_parts()
- if (cracked_part)
- // We have an existing crack
- var/leak_rate
- if (moderator_internal.return_pressure() < HYPERTORUS_MEDIUM_SPILL_PRESSURE)
- // Not high pressure, but can still leak
- if (!prob(HYPERTORUS_WEAK_SPILL_CHANCE))
- return
- leak_rate = HYPERTORUS_WEAK_SPILL_RATE
- else if (moderator_internal.return_pressure() < HYPERTORUS_STRONG_SPILL_PRESSURE)
- // Lots of gas in here, out we go
- leak_rate = HYPERTORUS_MEDIUM_SPILL_RATE
- else
- // Gotta go fast
- leak_rate = HYPERTORUS_STRONG_SPILL_RATE
- spill_gases(cracked_part, moderator_internal, ratio = 1 - (1 - leak_rate) ** delta_time)
- return
-
- if (moderator_internal.total_moles() < HYPERTORUS_HYPERCRITICAL_MOLES)
- return
- cracked_part = create_crack()
- // See if we do anything in the initial rupture
- if (moderator_internal.return_pressure() < HYPERTORUS_MEDIUM_SPILL_PRESSURE)
- return
- if (moderator_internal.return_pressure() < HYPERTORUS_STRONG_SPILL_PRESSURE)
- // Medium explosion on initial rupture
- explosion(
- origin = cracked_part,
- devastation_range = 0,
- heavy_impact_range = 0,
- light_impact_range = 1,
- flame_range = 3,
- flash_range = 3
- )
- spill_gases(cracked_part, moderator_internal, ratio = HYPERTORUS_MEDIUM_SPILL_INITIAL)
- return
- // Enough pressure for a strong explosion. Oh dear, oh dear.
- explosion(
- origin = cracked_part,
- devastation_range = 0,
- heavy_impact_range = 1,
- light_impact_range = 3,
- flame_range = 5,
- flash_range = 5
- )
- spill_gases(cracked_part, moderator_internal, ratio = HYPERTORUS_STRONG_SPILL_INITIAL)
- return
-
diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm
deleted file mode 100644
index 11521031303..00000000000
--- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/atmos_machines_recipes.dm
+++ /dev/null
@@ -1,183 +0,0 @@
-///Global list of recipes for atmospheric machines to use
-GLOBAL_LIST_INIT(gas_recipe_meta, gas_recipes_list())
-
-/*
- * Global proc to build the gas recipe global list
- */
-/proc/gas_recipes_list()
- . = list()
- for(var/recipe_path in subtypesof(/datum/gas_recipe))
- var/datum/gas_recipe/recipe = new recipe_path()
-
- .[recipe.id] = recipe
-
-/datum/gas_recipe
- ///Id of the recipe for easy identification in the code
- var/id = ""
- ///What machine the recipe is for
- var/machine_type = ""
- ///Displayed name of the recipe
- var/name = ""
- ///Minimum temperature for the recipe
- var/min_temp = TCMB
- ///Maximum temperature for the recipe
- var/max_temp = INFINITY
- /**
- * Amount of thermal energy released/consumed by the reaction.
- * Positive numbers make the reaction release energy (exothermic) while negative numbers make the reaction consume energy (endothermic).
- */
- var/energy_release = 0
- var/dangerous = FALSE
- ///Gas required for the recipe to work
- var/list/requirements
- ///Products made from the recipe
- var/list/products
-
-/datum/gas_recipe/crystallizer
- machine_type = "Crystallizer"
-
-/datum/gas_recipe/crystallizer/hypern_crystalium
- id = "hyper_crystalium"
- name = "Hypernoblium Crystal"
- min_temp = 3
- max_temp = 250
- energy_release = -250000
- requirements = list(/datum/gas/oxygen = 2000, /datum/gas/hypernoblium = 175)
- products = list(/obj/item/hypernoblium_crystal = 1)
-
-/datum/gas_recipe/crystallizer/metallic_hydrogen
- id = "metal_h"
- name = "Metallic hydrogen"
- min_temp = 50000
- max_temp = 150000
- energy_release = -2500000
- requirements = list(/datum/gas/hydrogen = 300, /datum/gas/bz = 50)
- products = list(/obj/item/stack/sheet/mineral/metal_hydrogen = 1)
-
-/datum/gas_recipe/crystallizer/healium_grenade
- id = "healium_g"
- name = "Healium crystal"
- min_temp = 200
- max_temp = 400
- energy_release = -2000000
- requirements = list(/datum/gas/healium = 100, /datum/gas/oxygen = 120, /datum/gas/plasma = 50)
- products = list(/obj/item/grenade/gas_crystal/healium_crystal = 1)
-
-/datum/gas_recipe/crystallizer/proto_nitrate_grenade
- id = "proto_nitrate_g"
- name = "Proto nitrate crystal"
- min_temp = 200
- max_temp = 400
- energy_release = 1500000
- requirements = list(/datum/gas/proto_nitrate = 100, /datum/gas/nitrogen = 80, /datum/gas/oxygen = 80)
- products = list(/obj/item/grenade/gas_crystal/proto_nitrate_crystal = 1)
-
-/datum/gas_recipe/crystallizer/hot_ice
- id = "hot_ice"
- name = "Hot ice"
- min_temp = 15
- max_temp = 35
- energy_release = -3000000
- requirements = list(/datum/gas/freon = 60, /datum/gas/plasma = 160, /datum/gas/oxygen = 80)
- products = list(/obj/item/stack/sheet/hot_ice = 1)
-
-/datum/gas_recipe/crystallizer/ammonia_crystal
- id = "ammonia_crystal"
- name = "Ammonia crystal"
- min_temp = 200
- max_temp = 240
- energy_release = 950000
- requirements = list(/datum/gas/hydrogen = 50, /datum/gas/nitrogen = 40)
- products = list(/obj/item/stack/ammonia_crystals = 2)
-
-/datum/gas_recipe/crystallizer/shard
- id = "crystal_shard"
- name = "Supermatter crystal shard"
- min_temp = TCMB
- max_temp = 5
- energy_release = 150000000
- dangerous = TRUE
- requirements = list(/datum/gas/hypernoblium = 250, /datum/gas/antinoblium = 250, /datum/gas/bz = 200, /datum/gas/plasma = 5000, /datum/gas/oxygen = 4500)
- products = list(/obj/machinery/power/supermatter_crystal/shard = 1)
-
-/datum/gas_recipe/crystallizer/n2o_crystal
- id = "n2o_crystal"
- name = "Nitrous oxide crystal"
- min_temp = 50
- max_temp = 350
- energy_release = 3500000
- requirements = list(/datum/gas/nitrous_oxide = 150, /datum/gas/bz = 30)
- products = list(/obj/item/grenade/gas_crystal/nitrous_oxide_crystal = 1)
-
-/datum/gas_recipe/crystallizer/diamond
- id = "diamond"
- name = "Diamond"
- min_temp = 10000
- max_temp = 30000
- energy_release = 9500000
- requirements = list(/datum/gas/carbon_dioxide = 1500)
- products = list(/obj/item/stack/sheet/mineral/diamond = 1)
-
-/datum/gas_recipe/crystallizer/plasma_sheet
- id = "plasma_sheet"
- name = "Plasma sheet"
- min_temp = 10
- max_temp = 20
- energy_release = 3500000
- requirements = list(/datum/gas/plasma = 450)
- products = list(/obj/item/stack/sheet/mineral/plasma = 1)
-
-/datum/gas_recipe/crystallizer/crystal_cell
- id = "crystal_cell"
- name = "Crystal Cell"
- min_temp = 50
- max_temp = 90
- energy_release = -800000
- requirements = list(/datum/gas/plasma = 800, /datum/gas/helium = 100, /datum/gas/bz = 50)
- products = list(/obj/item/stock_parts/cell/crystal_cell = 1)
-
-/datum/gas_recipe/crystallizer/zaukerite
- id = "zaukerite"
- name = "Zaukerite sheet"
- min_temp = 5
- max_temp = 20
- energy_release = 2900000
- requirements = list(/datum/gas/antinoblium = 5, /datum/gas/zauker = 20, /datum/gas/bz = 7.5)
- products = list(/obj/item/stack/sheet/mineral/zaukerite = 2)
-
-/datum/gas_recipe/crystallizer/fuel_pellet
- id = "fuel_basic"
- name = "standard fuel pellet"
- energy_release = -6000000
- requirements = list(/datum/gas/oxygen = 50, /datum/gas/plasma = 100)
- products = list(/obj/item/fuel_pellet = 1)
-
-/datum/gas_recipe/crystallizer/fuel_pellet_advanced
- id = "fuel_advanced"
- name = "advanced fuel pellet"
- energy_release = -6000000
- requirements = list(/datum/gas/tritium = 100, /datum/gas/hydrogen = 100)
- products = list(/obj/item/fuel_pellet/advanced = 1)
-
-/datum/gas_recipe/crystallizer/fuel_pellet_exotic
- id = "fuel_exotic"
- name = "exotic fuel pellet"
- energy_release = -6000000
- requirements = list(/datum/gas/hypernoblium = 100, /datum/gas/nitrium = 100)
- products = list(/obj/item/fuel_pellet/exotic = 1)
-
-/datum/gas_recipe/crystallizer/crystal_foam
- id = "crystal_foam"
- name = "Crystal foam grenade"
- energy_release = 140000
- requirements = list(/datum/gas/carbon_dioxide = 150, /datum/gas/nitrous_oxide = 100, /datum/gas/water_vapor = 25)
- products = list(/obj/item/grenade/gas_crystal/crystal_foam = 1)
-
-/datum/gas_recipe/crystallizer/crystallized_nitrium
- id = "crystallized_nitrium"
- name = "Nitrium crystal"
- min_temp = 10
- max_temp = 25
- energy_release = -45000
- requirements = list(/datum/gas/nitrium = 150, /datum/gas/oxygen = 70, /datum/gas/bz = 50)
- products = list(/obj/item/nitrium_crystal = 1)
diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm
deleted file mode 100644
index 261a0c80e52..00000000000
--- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm
+++ /dev/null
@@ -1,338 +0,0 @@
-#define MIN_PROGRESS_AMOUNT 3
-#define MIN_DEVIATION_RATE 0.90
-#define MAX_DEVIATION_RATE 1.1
-#define HIGH_CONDUCTIVITY_RATIO 0.95
-
-/obj/machinery/atmospherics/components/binary/crystallizer
- icon = 'icons/obj/atmospherics/components/machines.dmi'
- icon_state = "crystallizer-off"
- name = "crystallizer"
- desc = "Used to crystallize or solidify gases."
- layer = ABOVE_MOB_LAYER
- plane = GAME_PLANE_UPPER
- density = TRUE
- max_integrity = 300
- armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 0, BIO = 100, FIRE = 80, ACID = 30)
- circuit = /obj/item/circuitboard/machine/crystallizer
- pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
- vent_movement = NONE
-
- ///Base icon state for the machine to be used in update_icon()
- var/base_icon = "crystallizer"
- ///Internal Gas mix used for processing the gases that have been put in
- var/datum/gas_mixture/internal
- ///Var that controls how much gas gets injected in moles per tick
- var/gas_input = 0
- ///Saves the progress during the processing of the items
- var/progress_bar = 0
- ///Stores the amount of lost quality
- var/quality_loss = 0
- ///Stores the recipe selected by the user in the GUI
- var/datum/gas_recipe/selected_recipe = null
- ///Stores the total amount of moles needed for the current recipe
- var/total_recipe_moles = 0
-
-/obj/machinery/atmospherics/components/binary/crystallizer/Initialize(mapload)
- . = ..()
- internal = new
-
-/obj/machinery/atmospherics/components/binary/crystallizer/attackby(obj/item/I, mob/user, params)
- if(!on)
- if(default_deconstruction_screwdriver(user, "[base_icon]-open", "[base_icon]-off", I))
- return
- if(default_change_direction_wrench(user, I))
- return
- if(default_deconstruction_crowbar(I))
- return
- return ..()
-
-/obj/machinery/atmospherics/components/binary/crystallizer/default_change_direction_wrench(mob/user, obj/item/I)
- . = ..()
- if(!.)
- return FALSE
- set_init_directions()
- var/obj/machinery/atmospherics/node1 = nodes[1]
- var/obj/machinery/atmospherics/node2 = nodes[2]
- if(node1)
- if(src in node1.nodes) //Only if it's actually connected. On-pipe version would is one-sided.
- node1.disconnect(src)
- nodes[1] = null
- if(node2)
- if(src in node2.nodes) //Only if it's actually connected. On-pipe version would is one-sided.
- node2.disconnect(src)
- nodes[2] = null
-
- if(parents[1])
- nullify_pipenet(parents[1])
- if(parents[2])
- nullify_pipenet(parents[2])
-
- atmos_init()
- node1 = nodes[1]
- if(node1)
- node1.atmos_init()
- node1.add_member(src)
- node2 = nodes[2]
- if(node2)
- node2.atmos_init()
- node2.add_member(src)
- SSair.add_to_rebuild_queue(src)
- return TRUE
-
-/obj/machinery/atmospherics/components/binary/crystallizer/update_overlays()
- . = ..()
- cut_overlays()
- var/mutable_appearance/pipe_appearance1 = mutable_appearance('icons/obj/atmospherics/pipes/pipe_underlays.dmi', "intact_[dir]_[piping_layer]", layer = GAS_SCRUBBER_LAYER)
- pipe_appearance1.color = COLOR_LIME
- var/mutable_appearance/pipe_appearance2 = mutable_appearance('icons/obj/atmospherics/pipes/pipe_underlays.dmi', "intact_[turn(dir, 180)]_[piping_layer]", layer = GAS_SCRUBBER_LAYER)
- pipe_appearance2.color = COLOR_MOSTLY_PURE_RED
- . += pipe_appearance1
- . += pipe_appearance2
-
-/obj/machinery/atmospherics/components/binary/crystallizer/update_icon_state()
- . = ..()
- if(panel_open)
- icon_state = "[base_icon]-open"
- else if(on && is_operational)
- icon_state = "[base_icon]-on"
- else
- icon_state = "[base_icon]-off"
-
-/obj/machinery/atmospherics/components/binary/crystallizer/attackby_secondary(mob/user)
- if(!can_interact(user))
- return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
- update_icon()
-
-///Checks if the reaction temperature is inside the range of temperature + a little deviation
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/check_temp_requirements()
- if(internal.temperature >= selected_recipe.min_temp * MIN_DEVIATION_RATE && internal.temperature <= selected_recipe.max_temp * MAX_DEVIATION_RATE)
- return TRUE
- return FALSE
-
-///Injects the gases from the input inside the internal gasmix, the amount is dependant on the gas_input var
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/inject_gases()
- var/datum/gas_mixture/contents = airs[2]
- for(var/gas_type in selected_recipe.requirements)
- if(!contents.gases[gas_type] || !contents.gases[gas_type][MOLES])
- continue
- if(internal.gases[gas_type] && internal.gases[gas_type][MOLES] >= selected_recipe.requirements[gas_type] * 2)
- continue
- internal.merge(contents.remove_specific(gas_type, contents.gases[gas_type][MOLES] * gas_input))
-
-///Checks if the gases required are all inside
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/internal_check()
- var/gas_check = 0
- for(var/gas_type in selected_recipe.requirements)
- if(!internal.gases[gas_type] || !internal.gases[gas_type][MOLES])
- return FALSE
- if(internal.gases[gas_type][MOLES] >= selected_recipe.requirements[gas_type])
- gas_check++
- if(gas_check == selected_recipe.requirements.len)
- return TRUE
- return FALSE
-
-///Calculation for the heat of the various gas mixes and controls the quality of the item
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/heat_calculations()
- var/progress_amount_to_quality = MIN_PROGRESS_AMOUNT * 4.5 / (round(log(10, total_recipe_moles * 0.1), 0.01))
- if((internal.temperature >= (selected_recipe.min_temp * MIN_DEVIATION_RATE) && internal.temperature <= selected_recipe.min_temp) || \
- (internal.temperature >= selected_recipe.max_temp && internal.temperature <= (selected_recipe.max_temp * MAX_DEVIATION_RATE)))
- quality_loss = min(quality_loss + progress_amount_to_quality, 100)
-
- var/median_temperature = (selected_recipe.max_temp + selected_recipe.min_temp) / 2
- if(internal.temperature >= (median_temperature * MIN_DEVIATION_RATE) && internal.temperature <= (median_temperature * MAX_DEVIATION_RATE))
- quality_loss = max(quality_loss - progress_amount_to_quality, -85)
-
- internal.temperature = max(internal.temperature + (selected_recipe.energy_release / internal.heat_capacity()), TCMB)
- update_parents()
-
-///Conduction between the internal gasmix and the moderating (cooling/heating) gasmix.
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/heat_conduction()
- var/datum/gas_mixture/cooling_port = airs[1]
- if(cooling_port.total_moles() > MINIMUM_MOLE_COUNT)
- if(internal.total_moles() > 0)
- var/coolant_temperature_delta = cooling_port.temperature - internal.temperature
- var/cooling_heat_capacity = cooling_port.heat_capacity()
- var/internal_heat_capacity = internal.heat_capacity()
- var/cooling_heat_amount = HIGH_CONDUCTIVITY_RATIO * coolant_temperature_delta * (cooling_heat_capacity * internal_heat_capacity / (cooling_heat_capacity + internal_heat_capacity))
- cooling_port.temperature = max(cooling_port.temperature - cooling_heat_amount / cooling_heat_capacity, TCMB)
- internal.temperature = max(internal.temperature + cooling_heat_amount / internal_heat_capacity, TCMB)
- update_parents()
-
-///Calculate the total moles needed for the recipe
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/moles_calculations()
- var/amounts = 0
- for(var/gas_type in selected_recipe.requirements)
- amounts += selected_recipe.requirements[gas_type]
- total_recipe_moles = amounts
-
-///Removes the gases from the internal gasmix when the recipe is changed
-/obj/machinery/atmospherics/components/binary/crystallizer/proc/dump_gases()
- var/datum/gas_mixture/remove = internal.remove(internal.total_moles())
- airs[2].merge(remove)
- internal.garbage_collect()
-
-/obj/machinery/atmospherics/components/binary/crystallizer/process_atmos()
- if(!on || !is_operational || selected_recipe == null)
- return
-
- inject_gases()
-
- if(!internal.total_moles())
- return
-
- heat_conduction()
-
- if(internal_check())
- if(check_temp_requirements())
- heat_calculations()
- progress_bar = min(progress_bar + (MIN_PROGRESS_AMOUNT * 5 / (round(log(10, total_recipe_moles * 0.1), 0.01))), 100)
- else
- quality_loss = min(quality_loss + 0.5, 100)
- progress_bar = max(progress_bar - 1, 0)
- if(progress_bar != 100)
- update_parents()
- return
- progress_bar = 0
-
- for(var/gas_type in selected_recipe.requirements)
- var/required_gas_moles = selected_recipe.requirements[gas_type]
- var/amount_consumed = required_gas_moles + (required_gas_moles * (quality_loss * 0.01))
- if(internal.gases[gas_type][MOLES] < amount_consumed)
- quality_loss = min(quality_loss + 10, 100)
- internal.remove_specific(gas_type, amount_consumed)
-
- var/total_quality = clamp(50 - quality_loss, 0, 100)
- var/quality_control
- switch(total_quality)
- if(100)
- quality_control = "Masterwork"
- if(95 to 99)
- quality_control = "Supreme"
- if(75 to 94)
- quality_control = "Good"
- if(65 to 74)
- quality_control = "Decent"
- if(55 to 64)
- quality_control = "Average"
- if(35 to 54)
- quality_control = "Ok"
- if(15 to 34)
- quality_control = "Poor"
- if(5 to 14)
- quality_control = "Ugly"
- if(1 to 4)
- quality_control = "Cracked"
- if(0)
- quality_control = "Oh God why"
-
- for(var/path in selected_recipe.products)
- var/amount_produced = selected_recipe.products[path]
- for(var/i in 1 to amount_produced)
- var/obj/creation = new path(get_step(src, SOUTH))
- creation.name = "[quality_control] [creation.name]"
- if(selected_recipe.dangerous)
- investigate_log("has been created in the crystallizer.", INVESTIGATE_ENGINE)
- message_admins("[src] has been created in the crystallizer [ADMIN_JMP(src)].")
-
-
- quality_loss = 0
- update_parents()
-
-/obj/machinery/atmospherics/components/binary/crystallizer/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "Crystallizer", name)
- ui.open()
-
-/obj/machinery/atmospherics/components/binary/crystallizer/ui_static_data()
- var/data = list()
- data["selected_recipes"] = list(list("name" = "Nothing", "id" = ""))
- for(var/path in GLOB.gas_recipe_meta)
- var/datum/gas_recipe/recipe = GLOB.gas_recipe_meta[path]
- if(recipe.machine_type != "Crystallizer")
- continue
- data["selected_recipes"] += list(list("name" = recipe.name, "id" = recipe.id))
- return data
-
-/obj/machinery/atmospherics/components/binary/crystallizer/ui_data()
- var/data = list()
- data["on"] = on
-
- if(selected_recipe)
- data["selected"] = selected_recipe.id
- else
- data["selected"] = ""
-
- var/list/internal_gas_data = list()
- if(internal.total_moles())
- for(var/gasid in internal.gases)
- internal_gas_data.Add(list(list(
- "name"= internal.gases[gasid][GAS_META][META_GAS_NAME],
- "amount" = round(internal.gases[gasid][MOLES], 0.01),
- )))
- else
- for(var/gasid in internal.gases)
- internal_gas_data.Add(list(list(
- "name"= internal.gases[gasid][GAS_META][META_GAS_NAME],
- "amount" = 0,
- )))
- data["internal_gas_data"] = internal_gas_data
-
- var/list/requirements
- if(!selected_recipe)
- requirements = list("Select a recipe to see the requirements")
- else
- requirements = list("To create [selected_recipe.name] you will need:")
- for(var/gas_type in selected_recipe.requirements)
- var/datum/gas/gas_required = gas_type
- var/amount_consumed = selected_recipe.requirements[gas_type]
- requirements += "-[amount_consumed] moles of [initial(gas_required.name)]"
- requirements += "In a temperature range between [selected_recipe.min_temp] K and [selected_recipe.max_temp] K"
- requirements += "The crystallization reaction will be [selected_recipe.energy_release ? (selected_recipe.energy_release > 0 ? "exothermic" : "endothermic") : "thermally neutral"]"
- data["requirements"] = requirements.Join("\n")
-
- var/temperature
- if(internal.total_moles())
- temperature = internal.temperature
- else
- temperature = 0
- data["internal_temperature"] = temperature
- data["progress_bar"] = progress_bar
- data["gas_input"] = gas_input
- return data
-
-/obj/machinery/atmospherics/components/binary/crystallizer/ui_act(action, params)
- . = ..()
- if(.)
- return
- switch(action)
- if("power")
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", INVESTIGATE_ATMOS)
- . = TRUE
- if("recipe")
- selected_recipe = null
- var/recipe_name = "nothing"
- var/datum/gas_recipe/recipe = GLOB.gas_recipe_meta[params["mode"]]
- if(internal.total_moles())
- dump_gases()
- quality_loss = 0
- progress_bar = 0
- if(recipe && recipe.id != "")
- selected_recipe = recipe
- recipe_name = recipe.name
- update_parents() //prevent the machine from stopping because of the recipe change and the pipenet not updating
- moles_calculations()
- investigate_log("was set to recipe [recipe_name ? recipe_name : "null"] by [key_name(usr)]", INVESTIGATE_ATMOS)
- . = TRUE
- if("gas_input")
- var/_gas_input = params["gas_input"]
- gas_input = clamp(_gas_input, 0, 250)
- update_icon()
-
-#undef MIN_PROGRESS_AMOUNT
-#undef MIN_DEVIATION_RATE
-#undef MAX_DEVIATION_RATE
-#undef HIGH_CONDUCTIVITY_RATIO
diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm
deleted file mode 100644
index b5ec772c258..00000000000
--- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm
+++ /dev/null
@@ -1,30 +0,0 @@
-/obj/item/hypernoblium_crystal
- name = "Hypernoblium Crystal"
- desc = "Crystalized oxygen and hypernoblium stored in a bottle to pressureproof your clothes."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "potblue"
- var/uses = 2
-
-/obj/item/hypernoblium_crystal/afterattack(obj/item/clothing/worn_item, mob/user, proximity)
- . = ..()
- if(!proximity)
- return
- if(!istype(worn_item))
- to_chat(user, span_warning("The crystal can only be used on clothing!"))
- return
- if(istype(worn_item, /obj/item/clothing/suit/space))
- to_chat(user, span_warning("The [worn_item] is already pressure-resistant!"))
- return
- if(worn_item.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && worn_item.clothing_flags & STOPSPRESSUREDAMAGE)
- to_chat(user, span_warning("[worn_item] is already pressure-resistant!"))
- return
- to_chat(user, span_notice("You see how the [worn_item] changes color, it's now pressure proof."))
- worn_item.name = "pressure-resistant [worn_item.name]"
- worn_item.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- worn_item.add_atom_colour("#00fff7", FIXED_COLOUR_PRIORITY)
- worn_item.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- worn_item.cold_protection = worn_item.body_parts_covered
- worn_item.clothing_flags |= STOPSPRESSUREDAMAGE
- uses--
- if(!uses)
- qdel(src)
diff --git a/code/modules/atmospherics/machinery/components/tank.dm b/code/modules/atmospherics/machinery/components/tank.dm
index 803453d6e06..8ea5cf113d5 100644
--- a/code/modules/atmospherics/machinery/components/tank.dm
+++ b/code/modules/atmospherics/machinery/components/tank.dm
@@ -136,15 +136,13 @@
var/pressure_limit = max_pressure * safety_margin
var/moles_to_add = (pressure_limit * air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
- air_contents.assert_gas(gastype)
- air_contents.gases[gastype][MOLES] += moles_to_add
- air_contents.archive()
+ air_contents.adjustGas(gastype, moles_to_add)
/obj/machinery/atmospherics/components/tank/process_atmos()
- if(air_contents.react(src))
+ if(air_contents.react())
update_parents()
- if(air_contents.return_pressure() > max_pressure)
+ if(air_contents.returnPressure() > max_pressure)
take_damage(0.1, BRUTE, sound_effect = FALSE)
if(prob(40))
playsound(src, pick(breaking_sounds), 30, vary = TRUE)
@@ -192,7 +190,7 @@
continue
node.atmos_init()
node.add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
update_parents()
@@ -218,7 +216,7 @@
return
var/shares = length(merger.members) + length(leaving_members) - length(joining_members)
for(var/obj/machinery/atmospherics/components/tank/leaver as anything in leaving_members)
- var/datum/gas_mixture/gas_share = air_contents.remove_ratio(1 / shares--)
+ var/datum/gas_mixture/gas_share = air_contents.removeRatio(1 / shares--)
air_contents.volume -= leaver.volume
leaver.air_contents = gas_share
leaver.update_appearance()
@@ -270,7 +268,7 @@
window = image(icon, icon_state = "window-bg", layer = FLOAT_LAYER)
var/list/new_underlays = list()
- for(var/obj/effect/overlay/gas/gas as anything in air_contents.return_visuals())
+ for(var/obj/effect/gas_overlay/gas as anything in air_contents.returnVisuals())
var/image/new_underlay = image(gas.icon, icon_state = gas.icon_state, layer = FLOAT_LAYER)
new_underlay.filters = alpha_mask_filter(icon = icon(icon, icon_state = "window-bg"))
new_underlays += new_underlay
@@ -324,7 +322,7 @@
var/time_taken = 4 SECONDS
var/unsafe = FALSE
- var/internal_pressure = air_contents.return_pressure() - airmix.return_pressure()
+ var/internal_pressure = air_contents.returnPressure() - airmix.returnPressure()
if(internal_pressure > 2 * ONE_ATMOSPHERE)
time_taken *= 2
to_chat(user, span_warning("The tank seems to be pressurized, are you sure this is a good idea?"))
@@ -365,25 +363,25 @@
/obj/machinery/atmospherics/components/tank/air/Initialize(mapload)
. = ..()
- fill_to_pressure(/datum/gas/oxygen, safety_margin = (O2STANDARD * 0.5))
- fill_to_pressure(/datum/gas/nitrogen, safety_margin = (N2STANDARD * 0.5))
+ fill_to_pressure(GAS_OXYGEN, safety_margin = (O2STANDARD * 0.5))
+ fill_to_pressure(GAS_NITROGEN, safety_margin = (N2STANDARD * 0.5))
/obj/machinery/atmospherics/components/tank/carbon_dioxide
- gas_type = /datum/gas/carbon_dioxide
+ gas_type = GAS_CO2
/obj/machinery/atmospherics/components/tank/plasma
- gas_type = /datum/gas/plasma
+ gas_type = GAS_PLASMA
/obj/machinery/atmospherics/components/tank/nitrogen
- gas_type = /datum/gas/nitrogen
+ gas_type = GAS_NITROGEN
/obj/machinery/atmospherics/components/tank/oxygen
- gas_type = /datum/gas/oxygen
+ gas_type = GAS_OXYGEN
/obj/machinery/atmospherics/components/tank/nitrous
- gas_type = /datum/gas/nitrous_oxide
+ gas_type = GAS_N2O
-/obj/machinery/atmospherics/components/tank/bz
+/*ics/components/tank/bz
gas_type = /datum/gas/bz
/obj/machinery/atmospherics/components/tank/freon
@@ -427,6 +425,7 @@
/obj/machinery/atmospherics/components/tank/antinoblium
gas_type = /datum/gas/antinoblium
+*/
///////////////////////////////////////////////////////////////////
// Tank Frame Structure
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 6f7af747d85..7df1a82b953 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -79,16 +79,16 @@
// If the side output is full, we try to send the non-filtered gases to the main output port (air3).
// Any gas that can't be moved due to its destination being too full is sent back to the input (air1).
- var/side_output_full = air2.return_pressure() >= MAX_OUTPUT_PRESSURE
- var/main_output_full = air3.return_pressure() >= MAX_OUTPUT_PRESSURE
+ var/side_output_full = air2.returnPressure() >= MAX_OUTPUT_PRESSURE
+ var/main_output_full = air3.returnPressure() >= MAX_OUTPUT_PRESSURE
// If both output ports are full, there's nothing we can do. Don't bother removing anything from the input.
if (side_output_full && main_output_full)
return
- var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
+ var/datum/gas_mixture/removed = air1.removeRatio(transfer_ratio)
- if(!removed || !removed.total_moles())
+ if(!removed || !removed.get_moles())
return
var/filtering = TRUE
@@ -99,19 +99,18 @@
// If no filter is set, we just try to forward everything to air3 to avoid gas being outright lost.
if(filtering)
var/datum/gas_mixture/filtered_out = new
-
- for(var/gas in removed.gases & filter_type)
- var/datum/gas_mixture/removing = removed.remove_specific_ratio(gas, 1)
- if(removing)
- filtered_out.merge(removing)
+ var/datum/gas_mixture/merge_to
// Send things to the side output if we can, return them to the input if we can't.
// This means that other gases continue to flow to the main output if the side output is blocked.
if (side_output_full)
- air1.merge(filtered_out)
+ merge_to = air1
else
- air2.merge(filtered_out)
+ merge_to = air2
+ filter_gas(filter_type, removed, filtered_out, removed)
+ // Send things to the side output if we can, return them to the input if we can't.
+ // This means that other gases continue to flow to the main output if the side output is blocked.
+ merge_to.merge(filtered_out)
// Make sure we don't send any now-empty gas entries to the main output
- removed.garbage_collect()
// Send things to the main output if we can, return them to the input if we can't.
// This lets filtered gases continue to flow to the side output in a manner consistent with the main output behavior.
@@ -134,14 +133,14 @@
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
var/data = list()
+ var/static/all_gases = xgm_gas_data.gases
data["on"] = on
data["rate"] = round(transfer_rate)
data["max_rate"] = round(MAX_TRANSFER_RATE)
data["filter_types"] = list()
- for(var/path in GLOB.meta_gas_info)
- var/list/gas = GLOB.meta_gas_info[path]
- data["filter_types"] += list(list("name" = gas[META_GAS_NAME], "gas_id" = gas[META_GAS_ID], "enabled" = (path in filter_type)))
+ for(var/gas in ASSORTED_GASES)
+ data["filter_types"] += list(list("name" = xgm_gas_data.name[gas], "gas_id" = gas, "enabled" = (gas in filter_type)))
return data
@@ -166,15 +165,15 @@
transfer_rate = clamp(rate, 0, MAX_TRANSFER_RATE)
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", INVESTIGATE_ATMOS)
if("toggle_filter")
- if(!gas_id2path(params["val"]))
+ if(!params["val"])
return TRUE
- filter_type ^= gas_id2path(params["val"])
+ filter_type ^= params["val"]
var/change
- if(gas_id2path(params["val"]) in filter_type)
+ if(params["val"] in filter_type)
change = "added"
else
change = "removed"
- var/gas_name = GLOB.meta_gas_info[gas_id2path(params["val"])][META_GAS_NAME]
+ var/gas_name = xgm_gas_data.name[params["val"]]
investigate_log("[key_name(usr)] [change] [gas_name] from the filter type.", INVESTIGATE_ATMOS)
. = TRUE
update_appearance()
@@ -232,19 +231,20 @@
icon_state = "filter_on-0"
/obj/machinery/atmospherics/components/trinary/filter/atmos/n2
name = "nitrogen filter"
- filter_type = list(/datum/gas/nitrogen)
+ filter_type = list(GAS_N2O)
/obj/machinery/atmospherics/components/trinary/filter/atmos/o2
name = "oxygen filter"
- filter_type = list(/datum/gas/oxygen)
+ filter_type = list(GAS_OXYGEN)
/obj/machinery/atmospherics/components/trinary/filter/atmos/co2
name = "carbon dioxide filter"
- filter_type = list(/datum/gas/carbon_dioxide)
+ filter_type = list(GAS_CO2)
/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o
name = "nitrous oxide filter"
- filter_type = list(/datum/gas/nitrous_oxide)
+ filter_type = list(GAS_N2O)
/obj/machinery/atmospherics/components/trinary/filter/atmos/plasma
name = "plasma filter"
- filter_type = list(/datum/gas/plasma)
+ filter_type = list(GAS_PLASMA)
+/*
/obj/machinery/atmospherics/components/trinary/filter/atmos/bz
name = "bz filter"
filter_type = list(/datum/gas/bz)
@@ -257,9 +257,11 @@
/obj/machinery/atmospherics/components/trinary/filter/atmos/healium
name = "healium filter"
filter_type = list(/datum/gas/healium)
+*/
/obj/machinery/atmospherics/components/trinary/filter/atmos/h2
name = "hydrogen filter"
- filter_type = list(/datum/gas/hydrogen)
+ filter_type = list(GAS_HYDROGEN)
+/*
/obj/machinery/atmospherics/components/trinary/filter/atmos/hypernoblium
name = "hypernoblium filter"
filter_type = list(/datum/gas/hypernoblium)
@@ -292,25 +294,26 @@
/obj/machinery/atmospherics/components/trinary/filter/atmos/antinoblium
name = "antinoblium filter"
filter_type = list(/datum/gas/antinoblium)
-
+*/
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped //This feels wrong, I know
icon_state = "filter_on-0_f"
flipped = TRUE
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2
name = "nitrogen filter"
- filter_type = list(/datum/gas/nitrogen)
+ filter_type = list(GAS_NITROGEN)
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/o2
name = "oxygen filter"
- filter_type = list(/datum/gas/oxygen)
+ filter_type = list(GAS_OXYGEN)
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2
name = "carbon dioxide filter"
- filter_type = list(/datum/gas/carbon_dioxide)
+ filter_type = list(GAS_CO2)
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2o
name = "nitrous oxide filter"
- filter_type = list(/datum/gas/nitrous_oxide)
+ filter_type = list(GAS_N2O)
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/plasma
name = "plasma filter"
- filter_type = list(/datum/gas/plasma)
+ filter_type = list(GAS_PLASMA)
+ /*
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/bz
name = "bz filter"
filter_type = list(/datum/gas/bz)
@@ -323,9 +326,11 @@
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/healium
name = "healium filter"
filter_type = list(/datum/gas/healium)
+*/
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/h2
name = "hydrogen filter"
- filter_type = list(/datum/gas/hydrogen)
+ filter_type = list(GAS_HYDROGEN)
+/*
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/hypernoblium
name = "hypernoblium filter"
filter_type = list(/datum/gas/hypernoblium)
@@ -356,6 +361,7 @@
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/antinoblium
name = "antinoblium filter"
filter_type = list(/datum/gas/antinoblium)
+*/
// These two filter types have critical_machine flagged to on and thus causes the area they are in to be exempt from the Grid Check event.
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
index ce8036ee05a..06df3448db1 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
@@ -64,7 +64,7 @@
var/datum/gas_mixture/air3 = airs[3]
- var/output_starting_pressure = air3.return_pressure()
+ var/output_starting_pressure = air3.returnPressure()
if(output_starting_pressure >= target_pressure)
//No need to mix if target is already full!
@@ -76,8 +76,8 @@
var/transfer_moles1 = air1.temperature ? node1_concentration * general_transfer / air1.temperature : 0
var/transfer_moles2 = air2.temperature ? node2_concentration * general_transfer / air2.temperature : 0
- var/air1_moles = air1.total_moles()
- var/air2_moles = air2.total_moles()
+ var/air1_moles = air1.get_moles()
+ var/air2_moles = air2.get_moles()
if(!node2_concentration)
if(air1.temperature <= 0)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm b/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm
deleted file mode 100644
index 745176c1b7e..00000000000
--- a/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm
+++ /dev/null
@@ -1,178 +0,0 @@
-/obj/machinery/atmospherics/components/unary/bluespace_sender
- icon = 'icons/obj/atmospherics/components/bluespace_gas_selling.dmi'
- icon_state = "bluespace_sender_off"
- name = "Bluespace Gas Sender"
- desc = "Sends gases to the bluespace network to be shared with the connected vendors, who knows what's beyond!"
-
- density = TRUE
- max_integrity = 300
- armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 0, BIO = 100, FIRE = 80, ACID = 30)
- layer = OBJ_LAYER
- circuit = /obj/item/circuitboard/machine/bluespace_sender
- pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
-
- ///Base icon name for updating the appearance
- var/base_icon = "bluespace_sender"
- ///Gas mixture containing the inserted gases and that is connected to the vendors
- var/datum/gas_mixture/bluespace_network
- ///Rate of gas transfer inside the network (from 0 to 1)
- var/gas_transfer_rate = 0.5
- ///A base price for each and every gases, in case you don't want to change them
- var/list/base_prices = list()
- ///List storing all the vendors connected to the machine
- var/list/vendors
- ///Amount of credits gained from each vendor
- var/credits_gained = 0
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/Initialize(mapload)
- . = ..()
- initialize_directions = dir
- bluespace_network = new
- for(var/gas_id in GLOB.meta_gas_info)
- bluespace_network.assert_gas(gas_id)
- for(var/gas_id in GLOB.meta_gas_info)
- var/datum/gas/gas = gas_id
- base_prices[gas_id] = initial(gas.base_value)
-
- update_appearance()
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/Destroy()
- if(bluespace_network.total_moles())
- var/turf/local_turf = get_turf(src)
- local_turf.assume_air(bluespace_network)
- return ..()
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/update_icon_state()
- if(panel_open)
- icon_state = "[base_icon]_open"
- return ..()
- if(on && is_operational)
- icon_state = "[base_icon]_on"
- return ..()
- icon_state = "[base_icon]_off"
- return ..()
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/update_overlays()
- . = ..()
- . += get_pipe_image(icon, "pipe", dir, , piping_layer)
- if(showpipe)
- . += get_pipe_image(icon, "pipe", initialize_directions)
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/process_atmos()
- if(!is_operational || !on || !nodes[1]) //if it has no power or its switched off, dont process atmos
- return
-
- var/datum/gas_mixture/content = airs[1]
- var/datum/gas_mixture/remove = content.remove_ratio(gas_transfer_rate)
- bluespace_network.merge(remove)
- bluespace_network.temperature = T20C
- update_parents()
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/attackby(obj/item/item, mob/user, params)
- if(!on)
- if(default_deconstruction_screwdriver(user, "[base_icon]_open", "[base_icon]_off", item))
- update_appearance()
- return
- if(default_change_direction_wrench(user, item))
- return
- if(item.tool_behaviour == TOOL_CROWBAR && panel_open && bluespace_network.total_moles() > 0)
- say("WARNING - Bluespace network can contain hazardous gases, deconstruct with caution!")
- if(!do_after(user, 3 SECONDS, src))
- return
- if(default_deconstruction_crowbar(item))
- return
- return ..()
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/default_change_direction_wrench(mob/user, obj/item/item)
- if(!..())
- return FALSE
- set_init_directions()
- var/obj/machinery/atmospherics/node = nodes[1]
- if(node)
- if(src in node.nodes) //Only if it's actually connected. On-pipe version would is one-sided.
- node.disconnect(src)
- nodes[1] = null
- if(parents[1])
- nullify_pipenet(parents[1])
-
- atmos_init()
- node = nodes[1]
- if(node)
- node.atmos_init()
- node.add_member(src)
- SSair.add_to_rebuild_queue(src)
- return TRUE
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/multitool_act(mob/living/user, obj/item/item)
- var/obj/item/multitool/multitool = item
- multitool.buffer = src
- to_chat(user, span_notice("You store linkage information in [item]'s buffer."))
- return TRUE
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "BluespaceSender", name)
- ui.open()
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/ui_data(mob/user)
- var/list/data = list()
- data["on"] = on
- data["gas_transfer_rate"] = gas_transfer_rate
- var/list/bluespace_gasdata = list()
- if(bluespace_network.total_moles())
- for(var/gas_id in bluespace_network.gases)
- bluespace_gasdata.Add(list(list(
- "name" = bluespace_network.gases[gas_id][GAS_META][META_GAS_NAME],
- "id" = bluespace_network.gases[gas_id][GAS_META][META_GAS_ID],
- "amount" = round(bluespace_network.gases[gas_id][MOLES], 0.01),
- "price" = base_prices[gas_id],
- )))
- else
- for(var/gas_id in bluespace_network.gases)
- bluespace_gasdata.Add(list(list(
- "name" = bluespace_network.gases[gas_id][GAS_META][META_GAS_NAME],
- "id" = "",
- "amount" = 0,
- "price" = 0,
- )))
- data["bluespace_network_gases"] = bluespace_gasdata
- var/list/vendors_list = list()
- if(vendors)
- for(var/obj/machinery/bluespace_vendor/vendor in vendors)
- vendors_list.Add(list(list(
- "name" = vendor.name,
- "area" = get_area(vendor),
- )))
- data["vendors_list"] = vendors_list
- data["credits"] = credits_gained
- return data
-
-/obj/machinery/atmospherics/components/unary/bluespace_sender/ui_act(action, params)
- . = ..()
- if(.)
- return
-
- switch(action)
- if("power")
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", INVESTIGATE_ATMOS)
- update_appearance()
- . = TRUE
-
- if("rate")
- gas_transfer_rate = clamp(params["rate"], 0, 1)
- . = TRUE
-
- if("price")
- var/gas_type = gas_id2path(params["gas_type"])
- base_prices[gas_type] = clamp(params["gas_price"], 0, 100)
- . = TRUE
-
- if("retrieve")
- if(bluespace_network.total_moles() > 0)
- var/datum/gas_mixture/remove = bluespace_network.remove(bluespace_network.total_moles())
- airs[1].merge(remove)
- update_parents()
- bluespace_network.garbage_collect()
- . = TRUE
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index 0bdce079ac4..aaf25208977 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -272,7 +272,7 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
var/datum/gas_mixture/air1 = airs[1]
- if(air1.total_moles() > CRYO_MIN_GAS_MOLES)
+ if(air1.get_moles() > CRYO_MIN_GAS_MOLES)
if(beaker)
beaker.reagents.trans_to(occupant, (CRYO_TX_QTY / (efficiency * CRYO_MULTIPLY_FACTOR)) * delta_time, efficiency * CRYO_MULTIPLY_FACTOR, methods = VAPOR) // Transfer reagents.
consume_gas = TRUE
@@ -286,11 +286,13 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
var/datum/gas_mixture/air1 = airs[1]
- if(!nodes[1] || !airs[1] || !air1.gases.len || air1.total_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work.
+ /* PARIAH EDIT REMOVAL - HUGBOX BARGAGE
+ if(!nodes[1] || !airs[1] || !air1.gas.len || air1.get_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work.
var/msg = "Insufficient cryogenic gas, shutting down."
radio.talk_into(src, msg, radio_channel)
set_on(FALSE)
return
+ */
if(occupant)
var/mob/living/mob_occupant = occupant
@@ -302,7 +304,7 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
cold_protection = H.get_cold_protection(air1.temperature)
if(abs(temperature_delta) > 1)
- var/air_heat_capacity = air1.heat_capacity()
+ var/air_heat_capacity = air1.getHeatCapacity()
var/heat = ((1 - cold_protection) * 0.1 + conduction_coefficient) * temperature_delta * (air_heat_capacity * heat_capacity / (air_heat_capacity + heat_capacity))
@@ -314,9 +316,6 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
var/mob/living/carbon/human/humi = mob_occupant
humi.adjust_coretemperature(humi.bodytemperature - humi.coretemperature)
-
- air1.garbage_collect()
-
if(air1.temperature > 2000)
take_damage(clamp((air1.temperature)/200, 10, 20), BURN)
@@ -328,7 +327,7 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
return null
var/datum/gas_mixture/air1 = airs[1]
var/breath_percentage = breath_request / air1.volume
- return air1.remove(air1.total_moles() * breath_percentage)
+ return air1.remove(air1.get_moles() * breath_percentage)
/obj/machinery/atmospherics/components/unary/cryo_cell/assume_air(datum/gas_mixture/giver)
airs[1].merge(giver)
@@ -543,7 +542,7 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
/obj/machinery/atmospherics/components/unary/cryo_cell/return_temperature()
var/datum/gas_mixture/G = airs[1]
- if(G.total_moles() > 10)
+ if(G.get_moles() > 10)
return G.temperature
return ..()
@@ -563,7 +562,7 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
if(node)
node.atmos_init()
node.add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
#undef MAX_TEMPERATURE
#undef CRYO_MULTIPLY_FACTOR
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm
index 5c6cacb5518..21bfb75214a 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm
@@ -53,17 +53,17 @@
if(!partner)
partner_ref = null
return
- if(SSair.times_fired <= update_cycle)
+ if(SSzas.times_fired <= update_cycle)
return
- update_cycle = SSair.times_fired
- partner.update_cycle = SSair.times_fired
+ update_cycle = SSzas.times_fired
+ partner.update_cycle = SSzas.times_fired
var/datum/gas_mixture/air_contents = airs[1]
var/datum/gas_mixture/partnerair_contents = partner.airs[1]
- var/air_heat_capacity = air_contents.heat_capacity()
- var/other_air_heat_capacity = partnerair_contents.heat_capacity()
+ var/air_heat_capacity = air_contents.getHeatCapacity()
+ var/other_air_heat_capacity = partnerair_contents.getHeatCapacity()
var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity
var/old_temperature = air_contents.temperature
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index 2b29c650fc3..5cad9c733b3 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -55,7 +55,7 @@
var/datum/gas_mixture/air_contents = airs[1]
if(air_contents.temperature > 0)
- var/transfer_moles = (air_contents.return_pressure() * volume_rate) / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
+ var/transfer_moles = (air_contents.returnPressure() * volume_rate) / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
if(!transfer_moles)
return
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
index f461cbe8988..a482283b9ba 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
@@ -28,7 +28,7 @@
var/datum/gas_mixture/internal = airs[1]
if(internal.equalize(external))
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
update_parents()
/obj/machinery/atmospherics/components/unary/passive_vent/layer2
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
index 4a5b65293ea..e95e534ccc0 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
@@ -143,10 +143,10 @@
// The gas we want to cool/heat
var/datum/gas_mixture/port = airs[1]
- if(!port.total_moles()) // Nothing to cool? go home lad
+ if(!port.get_moles()) // Nothing to cool? go home lad
return
- var/port_capacity = port.heat_capacity()
+ var/port_capacity = port.getHeatCapacity()
// The difference between target and what we need to heat/cool. Positive if heating, negative if cooling.
var/temperature_target_delta = target_temperature - port.temperature
@@ -227,7 +227,7 @@
if(node1)
node1.atmos_init()
node1.add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
/obj/machinery/atmospherics/components/unary/thermomachine/proc/disconnect_pipes()
var/obj/machinery/atmospherics/node1 = nodes[1]
@@ -269,7 +269,7 @@
var/datum/gas_mixture/port = airs[1]
data["temperature"] = port.temperature
- data["pressure"] = port.return_pressure()
+ data["pressure"] = port.returnPressure()
return data
/obj/machinery/atmospherics/components/unary/thermomachine/ui_act(action, params)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index 8a25fd86da3..f3ad7ace8e2 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -5,6 +5,7 @@
#define SIPHONING 0
#define RELEASING 1
+#define DEFAULT_PRESSURE_DELTA 10000
/obj/machinery/atmospherics/components/unary/vent_pump
icon_state = "vent_map-3"
@@ -80,6 +81,10 @@
icon_state = "vent_in-off"
return
+ if(!COOLDOWN_FINISHED(src, hibernating))
+ icon_state = "vent_hibernating"
+ return
+
if(icon_state == ("vent_out-off" || "vent_in-off" || "vent_off"))
if(pump_direction & RELEASING)
icon_state = "vent_out"
@@ -104,47 +109,49 @@
var/turf/open/us = loc
if(!istype(us))
return
+
var/datum/gas_mixture/air_contents = airs[1]
var/datum/gas_mixture/environment = us.return_air()
- var/environment_pressure = environment.return_pressure()
-
- if(pump_direction & RELEASING) // internal -> external
- var/pressure_delta = 10000
-
- if(pressure_checks&EXT_BOUND)
- pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
- if(pressure_checks&INT_BOUND)
- pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound))
-
- if(pressure_delta > 0)
- if(air_contents.temperature > 0)
- var/transfer_moles = (pressure_delta * environment.volume) / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
- var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
-
- if(!removed || !removed.total_moles())
- return
-
- loc.assume_air(removed)
- update_parents()
+ var/pressure_delta = get_pressure_delta(environment)
+ if((environment.temperature || air_contents.temperature) && pressure_delta > 0.5)
+ if(pump_direction & RELEASING) //internal -> external
+ var/transfer_moles = calculate_transfer_moles(air_contents, environment, pressure_delta)
+ if(pump_gas(air_contents, environment, transfer_moles) == -1)
+ COOLDOWN_START(src, hibernating, 15 SECONDS)
+ update_parents()
- else // external -> internal
- var/pressure_delta = 10000
- if(pressure_checks&EXT_BOUND)
- pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
- if(pressure_checks&INT_BOUND)
- pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure()))
+ else //external -> internal
+ var/transfer_moles = calculate_transfer_moles(environment, air_contents, pressure_delta)
- if(pressure_delta > 0 && environment.temperature > 0)
- var/transfer_moles = (pressure_delta * air_contents.volume) / (environment.temperature * R_IDEAL_GAS_EQUATION)
+ //limit flow rate from turfs
+ transfer_moles = min(transfer_moles, environment.total_moles*air_contents.volume/environment.volume) //group_multiplier gets divided out here
+ if(pump_gas(environment, air_contents, transfer_moles) == -1)
+ COOLDOWN_START(src, hibernating, 15 SECONDS)
+ update_parents()
- var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
+ else
+ if(pump_direction && (pressure_checks&EXT_BOUND))
+ COOLDOWN_START(src, hibernating, 15 SECONDS)
- if(!removed || !removed.total_moles()) //No venting from space 4head
- return
+ update_icon_nopipes()
- air_contents.merge(removed)
- update_parents()
+/obj/machinery/atmospherics/components/unary/vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
+ var/pressure_delta = DEFAULT_PRESSURE_DELTA
+ var/environment_pressure = environment.returnPressure()
+ var/datum/gas_mixture/air_contents = airs[1]
+ if(pump_direction) //internal -> external
+ if(pressure_checks & EXT_BOUND)
+ pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
+ if(pressure_checks & INT_BOUND)
+ pressure_delta = min(pressure_delta, air_contents.returnPressure() - internal_pressure_bound) //decreasing the pressure here
+ else //external -> internal
+ if(pressure_checks & EXT_BOUND)
+ pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
+ if(pressure_checks & INT_BOUND)
+ pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.returnPressure()) //increasing the pressure here
+
+ return pressure_delta
//Radio remote control
/obj/machinery/atmospherics/components/unary/vent_pump/proc/set_frequency(new_frequency)
@@ -205,6 +212,8 @@
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return
+ COOLDOWN_RESET(src, hibernating)
+
var/atom/signal_sender = signal.data["user"]
if("purge" in signal.data)
@@ -298,6 +307,8 @@
. = ..()
if(welded)
. += "It seems welded shut."
+ if(!COOLDOWN_FINISHED(src, hibernating))
+ . += span_notice("It is sleeping to conserve power.")
/obj/machinery/atmospherics/components/unary/vent_pump/power_change()
. = ..()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 5cbb5185176..659829a0ced 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -21,13 +21,11 @@
///The mode of the scrubber (SCRUBBING or SIPHONING)
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
///The list of gases we are filtering
- var/list/filter_types = list(/datum/gas/carbon_dioxide)
+ var/list/filter_types = list(GAS_CO2)
///Rate of the scrubber to remove gases from the air
var/volume_rate = 200
- ///is this scrubber acting on the 3x3 area around it.
- var/widenet = FALSE
- ///List of the turfs near the scrubber, used for widenet
- var/list/turf/adjacent_turfs = list()
+ ///A fast-siphon toggle, siphons at 9x speed for 9x the power cost.
+ var/quicksucc = FALSE
///Frequency id for connecting to the NTNet
var/frequency = FREQ_ATMOS_CONTROL
@@ -38,8 +36,6 @@
///Radio connection from the air alarm
var/radio_filter_in
- COOLDOWN_DECLARE(check_turfs_cooldown)
-
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
if(!id_tag)
id_tag = SSnetworks.assign_random_name()
@@ -47,11 +43,11 @@
for(var/to_filter in filter_types)
if(istext(to_filter))
filter_types -= to_filter
- filter_types += gas_id2path(to_filter)
+ filter_types += to_filter
/obj/machinery/atmospherics/components/unary/vent_scrubber/Initialize(mapload)
. = ..()
- AddElement(/datum/element/atmos_sensitive, mapload)
+ SSairmachines.start_processing_machine(src)
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
var/area/scrub_area = get_area(src)
@@ -61,7 +57,7 @@
SSradio.remove_object(src,frequency)
radio_connection = null
- adjacent_turfs.Cut()
+ SSairmachines.stop_processing_machine(src)
return ..()
///adds a gas or list of gases to our filter_types. used so that the scrubber can check if its supposed to be processing after each change
@@ -70,22 +66,18 @@
filter_or_filters = list(filter_or_filters)
for(var/gas_to_filter in filter_or_filters)
- var/translated_gas = istext(gas_to_filter) ? gas_id2path(gas_to_filter) : gas_to_filter
-
- if(ispath(translated_gas, /datum/gas))
- filter_types |= translated_gas
- continue
+ filter_types |= gas_to_filter
- var/turf/open/our_turf = get_turf(src)
+ var/turf/our_turf = get_turf(src)
- if(!isopenturf(our_turf))
+ if(!our_turf.simulated)
return FALSE
var/datum/gas_mixture/turf_gas = our_turf.air
if(!turf_gas)
return FALSE
- check_atmos_process(our_turf, turf_gas, turf_gas.temperature)
+ COOLDOWN_RESET(src, hibernating)
return TRUE
///remove a gas or list of gases from our filter_types.used so that the scrubber can check if its supposed to be processing after each change
@@ -94,22 +86,18 @@
filter_or_filters = list(filter_or_filters)
for(var/gas_to_filter in filter_or_filters)
- var/translated_gas = istext(gas_to_filter) ? gas_id2path(gas_to_filter) : gas_to_filter
-
- if(ispath(translated_gas, /datum/gas))
- filter_types -= translated_gas
- continue
+ filter_types -= gas_to_filter
- var/turf/open/our_turf = get_turf(src)
+ var/turf/our_turf = get_turf(src)
var/datum/gas_mixture/turf_gas
- if(isopenturf(our_turf))
- turf_gas = our_turf.air
+ if(our_turf.simulated)
+ turf_gas = our_turf.return_air()
if(!turf_gas)
return FALSE
- check_atmos_process(our_turf, turf_gas, turf_gas.temperature)
+ COOLDOWN_RESET(src, hibernating)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/toggle_filters(filter_or_filters)
@@ -117,25 +105,21 @@
filter_or_filters = list(filter_or_filters)
for(var/gas_to_filter in filter_or_filters)
- var/translated_gas = istext(gas_to_filter) ? gas_id2path(gas_to_filter) : gas_to_filter
-
- if(ispath(translated_gas, /datum/gas))
- if(translated_gas in filter_types)
- filter_types -= translated_gas
- else
- filter_types |= translated_gas
+ if(gas_to_filter in filter_types)
+ filter_types -= gas_to_filter
+ else
+ filter_types |= gas_to_filter
- var/turf/open/our_turf = get_turf(src)
+ var/turf/our_turf = get_turf(src)
- if(!isopenturf(our_turf))
+ if(!our_turf.simulated)
return FALSE
- var/datum/gas_mixture/turf_gas = our_turf.air
+ var/datum/gas_mixture/turf_gas = our_turf.return_air()
if(!turf_gas)
return FALSE
-
- check_atmos_process(our_turf, turf_gas, turf_gas.temperature)
+ COOLDOWN_RESET(src, hibernating)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes()
@@ -154,8 +138,14 @@
icon_state = "scrub_off"
return
- if(scrubbing & SCRUBBING)
- if(widenet)
+ if(!COOLDOWN_FINISHED(src, hibernating))
+ if(quicksucc)
+ icon_state = "scrub_wide_hibernating"
+ else
+ icon_state = "scrub_hibernating"
+
+ else if(scrubbing & SCRUBBING)
+ if(quicksucc)
icon_state = "scrub_wide"
else
icon_state = "scrub_on"
@@ -172,9 +162,8 @@
return FALSE
var/list/f_types = list()
- for(var/path in GLOB.meta_gas_info)
- var/list/gas = GLOB.meta_gas_info[path]
- f_types += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in filter_types)))
+ for(var/gas_id in ASSORTED_GASES)
+ f_types += list(list("gas_id" = gas_id, "gas_name" = gas_id, "enabled" = (gas_id in filter_types)))
var/datum/signal/signal = new(list(
"tag" = id_tag,
@@ -183,7 +172,7 @@
"timestamp" = world.time,
"power" = on,
"scrubbing" = scrubbing,
- "widenet" = widenet,
+ "quicksucc" = quicksucc,
"filter_types" = f_types,
"sigtype" = "status"
))
@@ -213,43 +202,29 @@
if(frequency)
set_frequency(frequency)
broadcast_status()
- check_turfs()
. = ..()
-/obj/machinery/atmospherics/components/unary/vent_scrubber/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
+/obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos()
if(welded || !is_operational)
- return FALSE
- if(!nodes[1] || !on || (!filter_types && scrubbing != SIPHONING))
- on = FALSE
- return FALSE
-
- var/list/changed_gas = air.gases
-
- if(!changed_gas)
- return FALSE
-
- if(scrubbing == SIPHONING || length(filter_types & changed_gas))
- return TRUE
-
- return FALSE
-
-/obj/machinery/atmospherics/components/unary/vent_scrubber/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- if(welded || !is_operational)
- return FALSE
- if(!nodes[1] || !on)
+ return
+ if(!on || !nodes[1])
on = FALSE
- return FALSE
+ return
var/turf/open/us = loc
if(!istype(us))
return
- scrub(us)
- if(widenet)
- if(COOLDOWN_FINISHED(src, check_turfs_cooldown))
- check_turfs()
- COOLDOWN_START(src, check_turfs_cooldown, 2 SECONDS)
-
- for(var/turf/tile in adjacent_turfs)
- scrub(tile)
+
+ var/should_cooldown = TRUE
+ if(scrub(us))
+ should_cooldown = FALSE
+ if(quicksucc)
+ for(var/i in 1 to 9) //quicksucc is actually now just "fast mode"
+ if(scrub(us))
+ should_cooldown = FALSE
+ if(should_cooldown)
+ COOLDOWN_START(src, hibernating, 15 SECONDS)
+ update_icon_nopipes()
+
return TRUE
///filtered gases at or below this amount automatically get removed from the mix
@@ -260,97 +235,76 @@
return FALSE
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/air_contents = airs[1]
- var/list/env_gases = environment.gases
- if(air_contents.return_pressure() >= 50 * ONE_ATMOSPHERE)
+ if(air_contents.returnPressure() >= 50 * ONE_ATMOSPHERE)
return FALSE
if(scrubbing == SCRUBBING)
- if(length(env_gases & filter_types))
+ if(length(environment.gas & filter_types))
+ . = TRUE
///contains all of the gas we're sucking out of the tile, gets put into our parent pipenet
var/datum/gas_mixture/filtered_out = new
- var/list/filtered_gases = filtered_out.gases
filtered_out.temperature = environment.temperature
- ///maximum percentage of the turfs gas we can filter
- var/removal_ratio = min(1, volume_rate / environment.volume)
-
var/total_moles_to_remove = 0
- for(var/gas in filter_types & env_gases)
- total_moles_to_remove += env_gases[gas][MOLES]
+ for(var/gas in filter_types & environment.gas)
+ total_moles_to_remove += environment.gas[gas]
if(total_moles_to_remove == 0)//sometimes this gets non gc'd values
- environment.garbage_collect()
return FALSE
- for(var/gas in filter_types & env_gases)
- filtered_out.add_gas(gas)
- //take this gases portion of removal_ratio of the turfs air, or all of that gas if less than or equal to MINIMUM_MOLES_TO_SCRUB
- var/transfered_moles = max(QUANTIZE(env_gases[gas][MOLES] * removal_ratio * (env_gases[gas][MOLES] / total_moles_to_remove)), min(MINIMUM_MOLES_TO_SCRUB, env_gases[gas][MOLES]))
-
- filtered_gases[gas][MOLES] = transfered_moles
- env_gases[gas][MOLES] -= transfered_moles
-
- environment.garbage_collect()
+ //take this gases portion of removal_ratio of the turfs air, or all of that gas if less than or equal to MINIMUM_MOLES_TO_SCRUB
+ //var/transfer_moles = min(environment.total_moles, volume_rate/environment.volume)*environment.total_moles
+ var/transfer_moles = min(environment.total_moles, environment.total_moles*volume_rate/environment.volume)
+ if(scrub_gas(filter_types, environment, filtered_out, transfer_moles, INFINITY) == -1)
+ . = FALSE
//Remix the resulting gases
air_contents.merge(filtered_out)
update_parents()
+ return .
else //Just siphoning all air
- var/transfer_moles = environment.total_moles() * (volume_rate / environment.volume)
+ var/transfer_moles = environment.get_moles() * (volume_rate / environment.volume)
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
air_contents.merge(removed)
update_parents()
+ return TRUE
- return TRUE
#undef MINIMUM_MOLES_TO_SCRUB
-///we populate a list of turfs with nonatmos-blocked cardinal turfs AND
-/// diagonal turfs that can share atmos with *both* of the cardinal turfs
-/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/check_turfs()
- adjacent_turfs.Cut()
- var/turf/local_turf = get_turf(src)
- adjacent_turfs = local_turf.get_atmos_adjacent_turfs(alldir = TRUE)
-
/obj/machinery/atmospherics/components/unary/vent_scrubber/receive_signal(datum/signal/signal)
if(!is_operational || !signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return
+ COOLDOWN_RESET(src, hibernating)
- var/old_widenet = widenet
+ var/old_quicksucc = quicksucc
var/old_scrubbing = scrubbing
var/old_filter_length = length(filter_types)
- ///whether we should attempt to start processing due to settings allowing us to take gas out of our environment
- var/try_start_processing = FALSE
-
- var/turf/open/our_turf = get_turf(src)
- var/datum/gas_mixture/turf_gas = our_turf?.air
+ //var/turf/open/our_turf = get_turf(src)
+ //var/datum/gas_mixture/turf_gas = our_turf?.return_air()
var/atom/signal_sender = signal.data["user"]
if("power" in signal.data)
on = text2num(signal.data["power"])
- try_start_processing = TRUE
if("power_toggle" in signal.data)
on = !on
- try_start_processing = TRUE
- if("widenet" in signal.data)
- widenet = text2num(signal.data["widenet"])
- if("toggle_widenet" in signal.data)
- widenet = !widenet
+ if("quicksucc" in signal.data)
+ quicksucc = text2num(signal.data["quicksucc"])
+ if("toggle_quicksucc" in signal.data)
+ quicksucc = !quicksucc
if("scrubbing" in signal.data)
scrubbing = text2num(signal.data["scrubbing"])
- try_start_processing = TRUE
if("toggle_scrubbing" in signal.data)
scrubbing = !scrubbing
- try_start_processing = TRUE
if(scrubbing != old_scrubbing)
investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
@@ -373,13 +327,8 @@
broadcast_status()
update_appearance()
- if(!our_turf || !turf_gas)
- try_start_processing = FALSE
-
- if(try_start_processing)//check if our changes should make us start processing
- check_atmos_process(our_turf, turf_gas, turf_gas.temperature)
- if(length(filter_types) == old_filter_length && old_scrubbing == scrubbing && old_widenet == widenet)
+ if(length(filter_types) == old_filter_length && old_scrubbing == scrubbing && old_quicksucc == quicksucc)
return
idle_power_usage = initial(idle_power_usage)
@@ -393,8 +342,8 @@
new_power_usage = active_power_usage
update_use_power(ACTIVE_POWER_USE)
- if(widenet)
- new_power_usage += new_power_usage * (length(adjacent_turfs) * (length(adjacent_turfs) / 2))
+ if(quicksucc)
+ new_power_usage += new_power_usage * 9
update_mode_power_usage(scrubbing == SCRUBBING ? IDLE_POWER_USE : ACTIVE_POWER_USE, new_power_usage)
@@ -431,6 +380,8 @@
. = ..()
if(welded)
. += "It seems welded shut."
+ if(!COOLDOWN_FINISHED(src, hibernating))
+ . += span_notice("It is sleeping to conserve power.")
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user, list/modifiers)
if(!welded || !(do_after(user, 20, target = src)))
diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm
index dcb96442951..b1c0850f11e 100644
--- a/code/modules/atmospherics/machinery/datum_pipeline.dm
+++ b/code/modules/atmospherics/machinery/datum_pipeline.dm
@@ -14,19 +14,19 @@
other_airs = list()
members = list()
other_atmos_machines = list()
- SSair.networks += src
+ SSairmachines.networks += src
/datum/pipeline/Destroy()
- SSair.networks -= src
+ SSairmachines.networks -= src
if(building)
- SSair.remove_from_expansion(src)
+ SSairmachines.remove_from_expansion(src)
if(air?.volume)
temporarily_store_air()
for(var/obj/machinery/atmospherics/pipe/considered_pipe in members)
considered_pipe.parent = null
if(QDELETED(considered_pipe))
continue
- SSair.add_to_rebuild_queue(considered_pipe)
+ SSairmachines.add_to_rebuild_queue(considered_pipe)
for(var/obj/machinery/atmospherics/components/considered_component in other_atmos_machines)
considered_component.nullify_pipenet(src)
return ..()
@@ -36,7 +36,7 @@
return
reconcile_air()
//Only react if the mix has changed, and don't keep updating if it hasn't
- update = air.react(src)
+ update = air.react()
///Preps a pipeline for rebuilding, insterts it into the rebuild queue
/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base)
@@ -56,7 +56,7 @@
air = new
air.volume = volume
- SSair.add_to_expansion(src, base)
+ SSairmachines.add_to_expansion(src, base)
///Has the same effect as build_pipeline(), but this doesn't queue its work, so overrun abounds. It's useful for the pregame
/datum/pipeline/proc/build_pipeline_blocking(obj/machinery/atmospherics/base)
@@ -182,35 +182,67 @@
for(var/obj/machinery/atmospherics/pipe/member in members)
member.air_temporary = new
member.air_temporary.volume = member.volume
- member.air_temporary.copy_from(air, member.volume / air.volume)
+ member.air_temporary.copyFrom(air, member.volume / air.volume)
member.air_temporary.temperature = air.temperature
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
- var/total_heat_capacity = air.heat_capacity()
- var/partial_heat_capacity = total_heat_capacity * (share_volume / air.volume)
- var/target_temperature
- var/target_heat_capacity
+ var/total_heat_capacity = air.getHeatCapacity()
+ var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
+ if(target.simulated)
+ var/turf/modeled_location = target
- var/turf/modeled_location = target
- target_temperature = modeled_location.GetTemperature()
- target_heat_capacity = modeled_location.GetHeatCapacity()
+ if(modeled_location.blocks_air)
- var/delta_temperature = air.temperature - target_temperature
- var/sharer_heat_capacity = target_heat_capacity
+ if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
+ var/delta_temperature = air.temperature - modeled_location.temperature
- if((sharer_heat_capacity <= 0) || (partial_heat_capacity <= 0))
- return TRUE
- var/heat = thermal_conductivity * delta_temperature * (partial_heat_capacity * sharer_heat_capacity / (partial_heat_capacity + sharer_heat_capacity))
+ var/heat = thermal_conductivity*delta_temperature* \
+ (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity))
- var/self_temperature_delta = - heat / total_heat_capacity
- var/sharer_temperature_delta = heat / sharer_heat_capacity
+ air.temperature -= heat/total_heat_capacity
+ modeled_location.temperature += heat/modeled_location.heat_capacity
- air.temperature += self_temperature_delta
- modeled_location.TakeTemperature(sharer_temperature_delta)
- if(modeled_location.blocks_air)
- modeled_location.temperature_expose(air, modeled_location.temperature)
+ else
+ var/delta_temperature = 0
+ var/sharer_heat_capacity = 0
+
+ if(modeled_location.zone)
+ delta_temperature = (air.temperature - modeled_location.zone.air.temperature)
+ sharer_heat_capacity = modeled_location.zone.air.getHeatCapacity()
+ else
+ delta_temperature = (air.temperature - modeled_location.air.temperature)
+ sharer_heat_capacity = modeled_location.air.getHeatCapacity()
+
+ var/self_temperature_delta = 0
+ var/sharer_temperature_delta = 0
+
+ if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
+ var/heat = thermal_conductivity*delta_temperature* \
+ (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
+
+ self_temperature_delta = -heat/total_heat_capacity
+ sharer_temperature_delta = heat/sharer_heat_capacity
+ else
+ return 1
+
+ air.temperature += self_temperature_delta
+
+ if(modeled_location.zone)
+ modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier
+ else
+ modeled_location.air.temperature += sharer_temperature_delta
+
+
+ else
+ if((target.heat_capacity>0) && (partial_heat_capacity>0))
+ var/delta_temperature = air.temperature - target.temperature
+
+ var/heat = thermal_conductivity*delta_temperature* \
+ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
+
+ air.temperature -= heat/total_heat_capacity
update = TRUE
@@ -238,33 +270,70 @@
pipeline_list |= atmos_machine.return_pipenets_for_reconcilation(src)
gas_mixture_list |= atmos_machine.return_airs_for_reconcilation(src)
+
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/datum/gas_mixture/total_gas_mixture = new(0)
- var/list/total_gases = total_gas_mixture.gases
-
for(var/datum/gas_mixture/gas_mixture as anything in gas_mixture_list)
total_gas_mixture.volume += gas_mixture.volume
// This is sort of a combined merge + heat_capacity calculation
- var/list/giver_gases = gas_mixture.gases
+ var/list/giver_gases = gas_mixture.gas
//gas transfer
for(var/giver_id in giver_gases)
- var/giver_gas_data = giver_gases[giver_id]
- ASSERT_GAS(giver_id, total_gas_mixture)
- total_gases[giver_id][MOLES] += giver_gas_data[MOLES]
- total_heat_capacity += giver_gas_data[MOLES] * giver_gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
+ var/moles = giver_gases[giver_id]
+ total_gas_mixture.adjustGas(giver_id, moles)
total_thermal_energy += THERMAL_ENERGY(gas_mixture)
+ total_heat_capacity = total_gas_mixture.getHeatCapacity()
total_gas_mixture.temperature = total_heat_capacity ? (total_thermal_energy / total_heat_capacity) : 0
- total_gas_mixture.garbage_collect()
-
if(total_gas_mixture.volume > 0)
//Update individual gas_mixtures by volume ratio
for(var/mixture in gas_mixture_list)
var/datum/gas_mixture/gas_mixture = mixture
- gas_mixture.copy_from(total_gas_mixture, gas_mixture.volume / total_gas_mixture.volume)
+ gas_mixture.copyFrom(total_gas_mixture, gas_mixture.volume / total_gas_mixture.volume)
+
+/*
+/proc/equalize_gases(list/datum/gas_mixture/gases)
+ //Calculate totals from individual components
+ var/total_volume = 0
+ var/total_thermal_energy = 0
+ var/total_heat_capacity = 0
+
+ var/list/total_gas = list()
+ for(var/datum/gas_mixture/gasmix in gases)
+ total_volume += gasmix.volume
+ var/temp_heatcap = gasmix.getHeatCapacity()
+ total_thermal_energy += gasmix.temperature * temp_heatcap
+ total_heat_capacity += temp_heatcap
+ for(var/g in gasmix.getGases())
+ total_gas[g] += gasmix.gas[g]
+
+ if(total_volume > 0)
+ var/datum/gas_mixture/combined = new(total_volume)
+ combined.gas = total_gas
+
+ //Calculate temperature
+ if(total_heat_capacity > 0)
+ combined.temperature = total_thermal_energy / total_heat_capacity
+ combined.updateValues()
+
+ //Allow for reactions
+ combined.react()
+
+ //Average out the gases
+ for(var/g in combined.getGases())
+ combined.gas[g] /= total_volume
+
+ //Update individual gas_mixtures
+ for(var/datum/gas_mixture/gasmix in gases)
+ gasmix.gas = combined.gas.Copy()
+ gasmix.temperature = combined.temperature
+ gasmix.multiply(gasmix.volume)
+
+ return 1
+*/
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index 5a337707c57..c32aff0eb6d 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -17,7 +17,7 @@
var/target_layer = PIPING_LAYER_DEFAULT
/obj/machinery/meter/Destroy()
- SSair.stop_processing_machine(src)
+ SSairmachines.stop_processing_machine(src)
target = null
return ..()
@@ -25,7 +25,7 @@
if(!isnull(new_piping_layer))
target_layer = new_piping_layer
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
if(!target)
reattach_to_layer()
@@ -49,10 +49,10 @@
/obj/machinery/meter/on_set_is_operational(old_value)
if(is_operational)
- SSair.start_processing_machine(src)//dont set icon_state here because it will be reset on next process() if it ever happens
+ SSairmachines.start_processing_machine(src)//dont set icon_state here because it will be reset on next process() if it ever happens
else
icon_state = "meter"
- SSair.stop_processing_machine(src)
+ SSairmachines.stop_processing_machine(src)
/obj/machinery/meter/process_atmos()
var/datum/gas_mixture/pipe_air = target.return_air()
@@ -60,7 +60,7 @@
icon_state = "meter0"
return FALSE
- var/env_pressure = pipe_air.return_pressure()
+ var/env_pressure = pipe_air.returnPressure()
if(env_pressure <= 0.15 * ONE_ATMOSPHERE)
icon_state = "meter0"
else if(env_pressure <= 1.8 * ONE_ATMOSPHERE)
@@ -106,7 +106,7 @@
if (target)
var/datum/gas_mixture/pipe_air = target.return_air()
if(pipe_air)
- . = "The pressure gauge reads [round(pipe_air.return_pressure(), 0.01)] kPa; [round(pipe_air.temperature,0.01)] K ([round(pipe_air.temperature-T0C,0.01)]°C)."
+ . = "The pressure gauge reads [round(pipe_air.returnPressure(), 0.01)] kPa; [round(pipe_air.temperature,0.01)] K ([round(pipe_air.temperature-T0C,0.01)]°C)."
else
. = "The sensor error light is blinking."
else
@@ -153,7 +153,7 @@
///Pressure of the pipenet
var/datum/port/output/pressure
///Temperature of the pipenet
- var/datum/port/output/temperature
+ var/datum/port/output/net_temperature
///The component parent object
var/obj/machinery/meter/connected_meter
@@ -162,7 +162,7 @@
request_data = add_input_port("Request Meter Data", PORT_TYPE_SIGNAL, trigger = .proc/request_meter_data)
pressure = add_output_port("Pressure", PORT_TYPE_NUMBER)
- temperature = add_output_port("Temperature", PORT_TYPE_NUMBER)
+ net_temperature = add_output_port("Temperature", PORT_TYPE_NUMBER)
/obj/item/circuit_component/atmos_meter/register_usb_parent(atom/movable/shell)
. = ..()
@@ -178,8 +178,8 @@
if(!connected_meter)
return
var/datum/gas_mixture/environment = connected_meter.target.return_air()
- pressure.set_output(environment.return_pressure())
- temperature.set_output(environment.temperature)
+ pressure.set_output(environment.returnPressure())
+ net_temperature.set_output(environment.temperature)
// TURF METER - REPORTS A TILE'S AIR CONTENTS
// why are you yelling?
diff --git a/code/modules/atmospherics/machinery/other/miner.dm b/code/modules/atmospherics/machinery/other/miner.dm
index 56552eeedf0..bf142a0b058 100644
--- a/code/modules/atmospherics/machinery/other/miner.dm
+++ b/code/modules/atmospherics/machinery/other/miner.dm
@@ -47,7 +47,7 @@
set_broken(TRUE)
return FALSE
var/turf/open/OT = T
- if(OT.planetary_atmos)
+ if(!OT.simulated)
broken_message = span_boldwarning("DEVICE NOT ENCLOSED IN A PRESSURIZED ENVIRONMENT")
set_broken(TRUE)
return FALSE
@@ -56,11 +56,11 @@
set_broken(TRUE)
return FALSE
var/datum/gas_mixture/G = OT.return_air()
- if(G.return_pressure() > (max_ext_kpa - ((spawn_mol*spawn_temp*R_IDEAL_GAS_EQUATION)/(CELL_VOLUME))))
+ if(G.returnPressure() > (max_ext_kpa - ((spawn_mol*spawn_temp*R_IDEAL_GAS_EQUATION)/(CELL_VOLUME))))
broken_message = span_boldwarning("EXTERNAL PRESSURE OVER THRESHOLD")
set_broken(TRUE)
return FALSE
- if(G.total_moles() > max_ext_mol)
+ if(G.get_moles() > max_ext_mol)
broken_message = span_boldwarning("EXTERNAL AIR CONCENTRATION OVER THRESHOLD")
set_broken(TRUE)
return FALSE
@@ -84,7 +84,7 @@
active_power_usage = idle_power_usage
var/turf/T = get_turf(src)
var/datum/gas_mixture/G = T.return_air()
- var/P = G.return_pressure()
+ var/P = G.returnPressure()
switch(power_draw)
if(GASMINER_POWER_NONE)
update_use_power(ACTIVE_POWER_USE, 0)
@@ -134,9 +134,7 @@
if(!isopenturf(O))
return FALSE
var/datum/gas_mixture/merger = new
- merger.assert_gas(spawn_id)
- merger.gases[spawn_id][MOLES] = spawn_mol * delta_time
- merger.temperature = spawn_temp
+ merger.adjustGasWithTemp(spawn_id, spawn_mol * delta_time, spawn_temp)
O.assume_air(merger)
/obj/machinery/atmospherics/miner/attack_ai(mob/living/silicon/user)
@@ -147,99 +145,99 @@
/obj/machinery/atmospherics/miner/n2o
name = "\improper N2O Gas Miner"
overlay_color = "#FFCCCC"
- spawn_id = /datum/gas/nitrous_oxide
+ //spawn_id = /datum/gas/nitrous_oxide
/obj/machinery/atmospherics/miner/nitrogen
name = "\improper N2 Gas Miner"
overlay_color = "#CCFFCC"
- spawn_id = /datum/gas/nitrogen
+ //spawn_id = /datum/gas/nitrogen
/obj/machinery/atmospherics/miner/oxygen
name = "\improper O2 Gas Miner"
overlay_color = "#007FFF"
- spawn_id = /datum/gas/oxygen
+ //spawn_id = /datum/gas/oxygen
/obj/machinery/atmospherics/miner/plasma
name = "\improper Plasma Gas Miner"
overlay_color = "#FF0000"
- spawn_id = /datum/gas/plasma
+ //spawn_id = /datum/gas/plasma
/obj/machinery/atmospherics/miner/carbon_dioxide
name = "\improper CO2 Gas Miner"
overlay_color = "#CDCDCD"
- spawn_id = /datum/gas/carbon_dioxide
+ //spawn_id = /datum/gas/carbon_dioxide
/obj/machinery/atmospherics/miner/bz
name = "\improper BZ Gas Miner"
overlay_color = "#FAFF00"
- spawn_id = /datum/gas/bz
+ //spawn_id = /datum/gas/bz
/obj/machinery/atmospherics/miner/water_vapor
name = "\improper Water Vapor Gas Miner"
overlay_color = "#99928E"
- spawn_id = /datum/gas/water_vapor
+ //spawn_id = /datum/gas/water_vapor
/obj/machinery/atmospherics/miner/freon
name = "\improper Freon Gas Miner"
overlay_color = "#61edff"
- spawn_id = /datum/gas/freon
+ //spawn_id = /datum/gas/freon
/obj/machinery/atmospherics/miner/halon
name = "\improper Halon Gas Miner"
overlay_color = "#5f0085"
- spawn_id = /datum/gas/halon
+ //spawn_id = /datum/gas/halon
/obj/machinery/atmospherics/miner/healium
name = "\improper Healium Gas Miner"
overlay_color = "#da4646"
- spawn_id = /datum/gas/healium
+ //spawn_id = /datum/gas/healium
/obj/machinery/atmospherics/miner/hydrogen
name = "\improper Hydrogen Gas Miner"
overlay_color = "#ffffff"
- spawn_id = /datum/gas/hydrogen
+ //spawn_id = /datum/gas/hydrogen
/obj/machinery/atmospherics/miner/hypernoblium
name = "\improper Hypernoblium Gas Miner"
overlay_color = "#00f7ff"
- spawn_id = /datum/gas/hypernoblium
+ //spawn_id = /datum/gas/hypernoblium
/obj/machinery/atmospherics/miner/miasma
name = "\improper Miasma Gas Miner"
overlay_color = "#395806"
- spawn_id = /datum/gas/miasma
+ //spawn_id = /datum/gas/miasma
/obj/machinery/atmospherics/miner/nitrium
name = "\improper Nitrium Gas Miner"
overlay_color = "#752b00"
- spawn_id = /datum/gas/nitrium
+ //spawn_id = /datum/gas/nitrium
/obj/machinery/atmospherics/miner/pluoxium
name = "\improper Pluoxium Gas Miner"
overlay_color = "#4b54a3"
- spawn_id = /datum/gas/pluoxium
+ //spawn_id = /datum/gas/pluoxium
/obj/machinery/atmospherics/miner/proto_nitrate
name = "\improper Proto-Nitrate Gas Miner"
overlay_color = "#00571d"
- spawn_id = /datum/gas/proto_nitrate
+ //spawn_id = /datum/gas/proto_nitrate
/obj/machinery/atmospherics/miner/tritium
name = "\improper Tritium Gas Miner"
overlay_color = "#15ff00"
- spawn_id = /datum/gas/tritium
+ //spawn_id = /datum/gas/tritium
/obj/machinery/atmospherics/miner/zauker
name = "\improper Zauker Gas Miner"
overlay_color = "#022e00"
- spawn_id = /datum/gas/zauker
+ //spawn_id = /datum/gas/zauker
/obj/machinery/atmospherics/miner/helium
name = "\improper Helium Gas Miner"
overlay_color = "#022e00"
- spawn_id = /datum/gas/helium
+ //spawn_id = /datum/gas/helium
/obj/machinery/atmospherics/miner/antinoblium
name = "\improper Antinoblium Gas Miner"
overlay_color = "#022e00"
- spawn_id = /datum/gas/antinoblium
+ //spawn_id = /datum/gas/antinoblium
diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm
index 373689d9e13..04369c32521 100644
--- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm
@@ -23,23 +23,26 @@
var/datum/gas_mixture/pipe_air = return_air()
var/turf/local_turf = loc
- if(istype(local_turf))
+ if(!istype(local_turf))
+ CRASH("Processing HE pipe not in a")
+ if(isspaceturf(local_turf))
+ radiate_heat_to_space(pipe_air, 2, 1) //the magic "2" is the surface area in square meters.
+ else
if(islava(local_turf))
environment_temperature = 5000 //Yuck
else if(local_turf.blocks_air)
environment_temperature = local_turf.temperature
else
var/turf/open/open_local = local_turf
- environment_temperature = open_local.GetTemperature()
- else
- environment_temperature = local_turf.temperature
- if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
- parent.temperature_interact(local_turf, volume, thermal_conductivity)
+ environment_temperature = open_local.return_temperature()
+
+ if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
+ parent.temperature_interact(local_turf, volume, thermal_conductivity)
//heatup/cooldown any mobs buckled to ourselves based on our temperature
if(has_buckled_mobs())
- var/hc = pipe_air.heat_capacity()
+ var/hc = pipe_air.getHeatCapacity()
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 ? buckled_mobs.len * 3500 : 0))
diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
index 9a3abdb16c5..c0e38bb42b1 100644
--- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm
+++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
@@ -34,7 +34,7 @@
/obj/machinery/atmospherics/pipe/layer_manifold/proc/nullify_all_nodes()
for(var/obj/machinery/atmospherics/node in nodes)
node.disconnect(src)
- SSair.add_to_rebuild_queue(node)
+ SSairmachines.add_to_rebuild_queue(node)
front_nodes = null
back_nodes = null
nodes = list()
diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm
index 2f6d7d45297..ee01bc2f2d1 100644
--- a/code/modules/atmospherics/machinery/pipes/pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipes.dm
@@ -33,7 +33,7 @@
var/obj/machinery/atmospherics/old_node = nodes[i]
. = ..()
if(old_node)
- SSair.add_to_rebuild_queue(old_node)
+ SSairmachines.add_to_rebuild_queue(old_node)
/obj/machinery/atmospherics/pipe/destroy_network()
QDEL_NULL(parent)
diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm
index 2d41670c6e6..580b0928c25 100644
--- a/code/modules/atmospherics/machinery/portable/canister.dm
+++ b/code/modules/atmospherics/machinery/portable/canister.dm
@@ -5,30 +5,25 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
/proc/init_gas_id_to_canister()
return sort_list(list(
- "n2" = /obj/machinery/portable_atmospherics/canister/nitrogen,
- "o2" = /obj/machinery/portable_atmospherics/canister/oxygen,
- "co2" = /obj/machinery/portable_atmospherics/canister/carbon_dioxide,
- "plasma" = /obj/machinery/portable_atmospherics/canister/plasma,
- "n2o" = /obj/machinery/portable_atmospherics/canister/nitrous_oxide,
- "nitrium" = /obj/machinery/portable_atmospherics/canister/nitrium,
- "bz" = /obj/machinery/portable_atmospherics/canister/bz,
+ GAS_NITROGEN = /obj/machinery/portable_atmospherics/canister/nitrogen,
+ GAS_OXYGEN = /obj/machinery/portable_atmospherics/canister/oxygen,
+ GAS_CO2 = /obj/machinery/portable_atmospherics/canister/carbon_dioxide,
+ GAS_PLASMA = /obj/machinery/portable_atmospherics/canister/plasma,
+ GAS_N2O = /obj/machinery/portable_atmospherics/canister/nitrous_oxide,
+ GAS_XENON = /obj/machinery/portable_atmospherics/canister/xenon,
+ GAS_KRYPTON = /obj/machinery/portable_atmospherics/canister/krypton,
+ GAS_ARGON = /obj/machinery/portable_atmospherics/canister/argon,
+ GAS_CHLORINE = /obj/machinery/portable_atmospherics/canister/chlorine,
+ GAS_NEON = /obj/machinery/portable_atmospherics/canister/neon,
"air" = /obj/machinery/portable_atmospherics/canister/air,
- "water_vapor" = /obj/machinery/portable_atmospherics/canister/water_vapor,
- "tritium" = /obj/machinery/portable_atmospherics/canister/tritium,
- "hyper-noblium" = /obj/machinery/portable_atmospherics/canister/nob,
- "pluoxium" = /obj/machinery/portable_atmospherics/canister/pluoxium,
+ GAS_HYDROGEN = /obj/machinery/portable_atmospherics/canister/hydrogen,
+ GAS_DEUTERIUM = /obj/machinery/portable_atmospherics/canister/deuterium,
+ GAS_TRITIUM = /obj/machinery/portable_atmospherics/canister/tritium,
"caution" = /obj/machinery/portable_atmospherics/canister,
- "miasma" = /obj/machinery/portable_atmospherics/canister/miasma,
- "freon" = /obj/machinery/portable_atmospherics/canister/freon,
- "hydrogen" = /obj/machinery/portable_atmospherics/canister/hydrogen,
- "healium" = /obj/machinery/portable_atmospherics/canister/healium,
- "proto_nitrate" = /obj/machinery/portable_atmospherics/canister/proto_nitrate,
- "zauker" = /obj/machinery/portable_atmospherics/canister/zauker,
- "helium" = /obj/machinery/portable_atmospherics/canister/helium,
- "antinoblium" = /obj/machinery/portable_atmospherics/canister/antinoblium,
- "halon" = /obj/machinery/portable_atmospherics/canister/halon
+ GAS_STEAM = /obj/machinery/portable_atmospherics/canister/water_vapor,
))
+
/obj/machinery/portable_atmospherics/canister
name = "canister"
desc = "A canister for the storage of gas."
@@ -41,7 +36,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
armor = list(MELEE = 50, BULLET = 50, LASER = 50, ENERGY = 100, BOMB = 10, BIO = 100, FIRE = 80, ACID = 50)
max_integrity = 300
integrity_failure = 0.4
- pressure_resistance = 7 * ONE_ATMOSPHERE
+ //pressure_resistance = 7 * ONE_ATMOSPHERE
req_access = list()
var/icon/canister_overlay_file = 'icons/obj/atmospherics/canisters.dmi'
@@ -54,7 +49,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
var/filled = 0.5
///Maximum pressure allowed on initialize inside the canister, multiplied by the filled var
var/maximum_pressure = 90 * ONE_ATMOSPHERE
- ///Stores the path of the gas for mapped canisters
+ ///Stores the id of the gas for mapped canisters
var/gas_type
///Player controlled var that set the release pressure of the canister
var/release_pressure = ONE_ATMOSPHERE
@@ -100,12 +95,11 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
internal_cell = new /obj/item/stock_parts/cell/high(src)
if(existing_mixture)
- air_contents.copy_from(existing_mixture)
+ air_contents.copyFrom(existing_mixture)
else
create_gas()
- if(ispath(gas_type, /datum/gas))
- desc = "[GLOB.meta_gas_info[gas_type][META_GAS_NAME]]. [GLOB.meta_gas_info[gas_type][META_GAS_DESC]]"
+ desc = "[xgm_gas_data.name[gas_type]]."
update_window()
@@ -113,7 +107,6 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
pressure_limit = initial(pressure_limit) * (1 + 0.2 * random_quality)
update_appearance()
- AddElement(/datum/element/atmos_sensitive, mapload)
AddElement(/datum/element/volatile_gas_storage)
AddComponent(/datum/component/gas_leaker, leak_rate=0.01)
@@ -138,167 +131,119 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
// Basic canister per gas below here
/obj/machinery/portable_atmospherics/canister/air
- name = "Air canister"
+ name = "air canister"
desc = "Pre-mixed air."
greyscale_config = /datum/greyscale_config/canister
greyscale_colors = "#c6c0b5"
-/obj/machinery/portable_atmospherics/canister/antinoblium
- name = "Antinoblium canister"
- gas_type = /datum/gas/antinoblium
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#9b5d7f#368bff"
-
-/obj/machinery/portable_atmospherics/canister/bz
- name = "\improper BZ canister"
- gas_type = /datum/gas/bz
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#9b5d7f#d0d2a0"
-
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
- name = "Carbon dioxide canister"
- gas_type = /datum/gas/carbon_dioxide
+ name = "carbon dioxide canister"
+ gas_type = GAS_CO2
greyscale_config = /datum/greyscale_config/canister
greyscale_colors = "#4e4c48"
-/obj/machinery/portable_atmospherics/canister/freon
- name = "Freon canister"
- gas_type = /datum/gas/freon
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#6696ee#fefb30"
-
-/obj/machinery/portable_atmospherics/canister/halon
- name = "Halon canister"
- gas_type = /datum/gas/halon
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#9b5d7f#368bff"
-
-/obj/machinery/portable_atmospherics/canister/healium
- name = "Healium canister"
- gas_type = /datum/gas/healium
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#009823#ff0e00"
-
-/obj/machinery/portable_atmospherics/canister/helium
- name = "Helium canister"
- gas_type = /datum/gas/helium
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#9b5d7f#368bff"
+/obj/machinery/portable_atmospherics/canister/carbon_monoxide
+ name = "carbon monoxide canister"
+ gas_type = GAS_CO
+ greyscale_config = /datum/greyscale_config/canister
+ greyscale_colors = "#808080"
-/obj/machinery/portable_atmospherics/canister/hydrogen
- name = "Hydrogen canister"
- gas_type = /datum/gas/hydrogen
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/stripe
- greyscale_colors = "#bdc2c0#ffffff"
+/obj/machinery/portable_atmospherics/canister/xenon
+ name = "xenon canister"
+ gas_type = GAS_XENON
+ greyscale_config = /datum/greyscale_config/canister
+ greyscale_colors = "#808080"
-/obj/machinery/portable_atmospherics/canister/miasma
- name = "Miasma canister"
- gas_type = /datum/gas/miasma
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#009823#f7d5d3"
+/obj/machinery/portable_atmospherics/canister/krypton
+ name = "krypton canister"
+ gas_type = GAS_KRYPTON
+ greyscale_config = /datum/greyscale_config/canister
+ greyscale_colors = "#44E022"
/obj/machinery/portable_atmospherics/canister/nitrogen
- name = "Nitrogen canister"
- gas_type = /datum/gas/nitrogen
+ name = "nitrogen canister"
+ gas_type = GAS_NITROGEN
greyscale_config = /datum/greyscale_config/canister
greyscale_colors = "#d41010"
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
- name = "Nitrous oxide canister"
- gas_type = /datum/gas/nitrous_oxide
+ name = "nitrous oxide canister"
+ gas_type = GAS_N2O
greyscale_config = /datum/greyscale_config/canister/double_stripe
greyscale_colors = "#c63e3b#f7d5d3"
-/obj/machinery/portable_atmospherics/canister/nitrium
- name = "Nitrium canister"
- gas_type = /datum/gas/nitrium
+/obj/machinery/portable_atmospherics/canister/chlorine
+ name = "chlorine canister"
+ gas_type = GAS_CHLORINE
greyscale_config = /datum/greyscale_config/canister
- greyscale_colors = "#7b4732"
+ greyscale_colors = "#b9d41b"
-/obj/machinery/portable_atmospherics/canister/nob
- name = "Hyper-noblium canister"
- gas_type = /datum/gas/hypernoblium
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#6399fc#b2b2b2"
+/obj/machinery/portable_atmospherics/canister/argon
+ name = "argon canister"
+ gas_type = GAS_ARGON
+ greyscale_config = /datum/greyscale_config/canister
+ greyscale_colors = "#CC4DCD"
+
+/obj/machinery/portable_atmospherics/canister/neon
+ name = "neon canister"
+ gas_type = GAS_NEON
+ greyscale_config = /datum/greyscale_config/canister
+ greyscale_colors = "#FF825C"
/obj/machinery/portable_atmospherics/canister/oxygen
- name = "Oxygen canister"
- gas_type = /datum/gas/oxygen
+ name = "oxygen canister"
+ gas_type = GAS_OXYGEN
greyscale_config = /datum/greyscale_config/canister/stripe
greyscale_colors = "#2786e5#e8fefe"
-/obj/machinery/portable_atmospherics/canister/pluoxium
- name = "Pluoxium canister"
- gas_type = /datum/gas/pluoxium
+/obj/machinery/portable_atmospherics/canister/boron
+ name = "boron canister"
+ gas_type = GAS_BORON
greyscale_config = /datum/greyscale_config/canister
- greyscale_colors = "#2786e5"
-
-/obj/machinery/portable_atmospherics/canister/proto_nitrate
- name = "Proto Nitrate canister"
- gas_type = /datum/gas/proto_nitrate
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#008200#33cc33"
+ greyscale_colors = "#32DF1F"
/obj/machinery/portable_atmospherics/canister/plasma
- name = "Plasma canister"
- gas_type = /datum/gas/plasma
+ name = "plasma canister"
+ gas_type = GAS_PLASMA
greyscale_config = /datum/greyscale_config/canister/hazard
greyscale_colors = "#f62800#000000"
+/obj/machinery/portable_atmospherics/canister/hydrogen
+ name = "hydrogen canister"
+ gas_type = GAS_HYDROGEN
+ greyscale_config = /datum/greyscale_config/canister/hazard
+ greyscale_colors = "#3fcd40#000000"
+
+/obj/machinery/portable_atmospherics/canister/deuterium
+ name = "hydrogen canister"
+ gas_type = GAS_DEUTERIUM
+ greyscale_config = /datum/greyscale_config/canister/hazard
+ greyscale_colors = "#E81BFF#000000"
+
/obj/machinery/portable_atmospherics/canister/tritium
- name = "Tritium canister"
- gas_type = /datum/gas/tritium
+ name = "tritium canister"
+ gas_type = GAS_TRITIUM
greyscale_config = /datum/greyscale_config/canister/hazard
greyscale_colors = "#3fcd40#000000"
/obj/machinery/portable_atmospherics/canister/water_vapor
- name = "Water vapor canister"
- gas_type = /datum/gas/water_vapor
+ name = "steam canister"
+ gas_type = GAS_STEAM
filled = 1
greyscale_config = /datum/greyscale_config/canister/double_stripe
greyscale_colors = "#4c4e4d#f7d5d3"
-/obj/machinery/portable_atmospherics/canister/zauker
- name = "Zauker canister"
- gas_type = /datum/gas/zauker
- filled = 1
- greyscale_config = /datum/greyscale_config/canister/double_stripe
- greyscale_colors = "#009a00#006600"
-
// Special canisters below here
-
-/obj/machinery/portable_atmospherics/canister/fusion_test
- name = "fusion test canister"
- desc = "Don't be a badmin."
- heat_limit = 1e12
- pressure_limit = 1e14
-
-/obj/machinery/portable_atmospherics/canister/fusion_test/create_gas()
- air_contents.add_gases(/datum/gas/hydrogen, /datum/gas/tritium)
- air_contents.gases[/datum/gas/hydrogen][MOLES] = 300
- air_contents.gases[/datum/gas/tritium][MOLES] = 300
- air_contents.temperature = 10000
- SSair.start_processing_machine(src)
-
/obj/machinery/portable_atmospherics/canister/anesthetic_mix
- name = "Anesthetic mix"
+ name = "anesthetic mix"
desc = "A mixture of N2O and Oxygen"
greyscale_config = /datum/greyscale_config/canister/double_stripe
greyscale_colors = "#9fba6c#3d4680"
/obj/machinery/portable_atmospherics/canister/anesthetic_mix/create_gas()
- air_contents.add_gases(/datum/gas/oxygen, /datum/gas/nitrous_oxide)
- air_contents.gases[/datum/gas/oxygen][MOLES] = (O2_ANESTHETIC * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
- air_contents.gases[/datum/gas/nitrous_oxide][MOLES] = (N2O_ANESTHETIC * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
- SSair.start_processing_machine(src)
+ air_contents.adjustGas(GAS_OXYGEN, (O2_ANESTHETIC * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature))
+ air_contents.adjustGas(GAS_N2O, (N2O_ANESTHETIC * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature))
+ SSairmachines.start_processing_machine(src)
/**
* Getter for the amount of time left in the timer of prototype canisters
@@ -336,7 +281,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
/obj/machinery/portable_atmospherics/canister/proto/default/oxygen
name = "prototype canister"
desc = "A prototype canister for a prototype bike, what could go wrong?"
- gas_type = /datum/gas/oxygen
+ gas_type = GAS_OXYGEN
filled = 1
release_pressure = ONE_ATMOSPHERE*2
@@ -347,17 +292,15 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(!gas_type)
return
- 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)
- SSair.start_processing_machine(src)
+ air_contents.adjustGas(gas_type,(maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature))
+ SSairmachines.start_processing_machine(src)
/obj/machinery/portable_atmospherics/canister/air/create_gas()
- air_contents.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
- air_contents.gases[/datum/gas/oxygen][MOLES] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
- air_contents.gases[/datum/gas/nitrogen][MOLES] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
- SSair.start_processing_machine(src)
+ air_contents.adjustGas(GAS_OXYGEN, (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature))
+ air_contents.adjustGas(GAS_NITROGEN, (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature))
+ SSairmachines.start_processing_machine(src)
/obj/machinery/portable_atmospherics/canister/update_icon_state()
if(machine_stat & BROKEN)
@@ -383,7 +326,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
if(connected_port)
. += mutable_appearance(canister_overlay_file, "can-connector")
- var/air_pressure = air_contents.return_pressure()
+ var/air_pressure = air_contents.returnPressure()
switch(air_pressure)
if((40 * ONE_ATMOSPHERE) to INFINITY)
@@ -415,10 +358,10 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
cut_overlay(window)
window = image(icon, icon_state="window-base", layer=FLOAT_LAYER)
var/list/window_overlays = list()
- for(var/visual in air_contents.return_visuals())
+ /*for(var/visual in air_contents.returnVisuals())
var/image/new_visual = image(visual, layer=FLOAT_LAYER)
new_visual.filters = alpha_filter
- window_overlays += new_visual
+ window_overlays += new_visual*/
window.overlays = window_overlays
add_overlay(window)
@@ -426,7 +369,8 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
return (exposed_temperature > temperature_resistance && !shielding_powered)
/obj/machinery/portable_atmospherics/canister/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(5, BURN, 0)
+ if(exposed_temperature > temperature_resistance &&!shielding_powered)
+ take_damage(5, BURN, 0)
/obj/machinery/portable_atmospherics/canister/deconstruct(disassembled = TRUE)
if((flags_1 & NODECONSTRUCT_1))
@@ -479,7 +423,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
. = ..()
if(!I.tool_start_check(user, amount=0))
return TRUE
- var/pressure = air_contents.return_pressure()
+ var/pressure = air_contents.returnPressure()
if(pressure > 300)
to_chat(user, span_alert("The pressure gauge on [src] indicates a high pressure inside... maybe you want to reconsider?"))
message_admins("[src] deconstructed by [ADMIN_LOOKUPFLW(user)]")
@@ -518,7 +462,6 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
. = ..()
if(!. || QDELETED(src))
return
- SSair.start_processing_machine(src)
/obj/machinery/portable_atmospherics/canister/atom_break(damage_flag)
. = ..()
@@ -531,7 +474,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
*/
/obj/machinery/portable_atmospherics/canister/proc/canister_break()
disconnect()
- var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
+ var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.get_moles())
var/turf/T = get_turf(src)
T.assume_air(expelled_gas)
@@ -560,8 +503,8 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
/obj/machinery/portable_atmospherics/canister/process(delta_time)
- var/our_pressure = air_contents.return_pressure()
- var/our_temperature = air_contents.return_temperature()
+ var/our_pressure = air_contents.returnPressure()
+ var/our_temperature = air_contents.get_temperature()
protected_contents = FALSE
if(shielding_powered)
@@ -590,14 +533,25 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
// Handle gas transfer.
if(valve_open)
var/turf/location = get_turf(src)
- var/datum/gas_mixture/target_air = holding?.return_air() || location.return_air()
- excited = TRUE
+ var/datum/gas_mixture/environment
+ if(holding)
+ environment = holding.air_contents
+ else
+ environment = location.return_air()
+
+ var/env_pressure = environment.returnPressure()
+ var/pressure_delta = release_pressure - env_pressure
+
+ if((air_contents.temperature > 0) && (pressure_delta > 0))
+ var/transfer_moles = calculate_transfer_moles(air_contents, environment, pressure_delta)
+ transfer_moles = min(transfer_moles, (release_pressure/air_contents.volume)*air_contents.total_moles) //flow rate limit
- if(air_contents.release_gas_to(target_air, release_pressure) && !holding)
- air_update_turf(FALSE, FALSE)
+ pump_gas_passive(air_contents, environment, transfer_moles)
- var/our_pressure = air_contents.return_pressure()
- var/our_temperature = air_contents.return_temperature()
+ air_contents.react()
+
+ var/our_pressure = air_contents.returnPressure()
+ var/our_temperature = air_contents.get_temperature()
///function used to check the limit of the canisters and also set the amount of damage that the canister can receive, if the heat and pressure are way higher than the limit the more damage will be done
if(!protected_contents && (our_temperature > heat_limit || our_pressure > pressure_limit))
@@ -605,8 +559,6 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
excited = TRUE
update_appearance()
- return ..()
-
/obj/machinery/portable_atmospherics/canister/ui_state(mob/user)
return GLOB.physical_state
@@ -629,7 +581,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
/obj/machinery/portable_atmospherics/canister/ui_data()
. = list(
"portConnected" = !!connected_port,
- "tankPressure" = round(air_contents.return_pressure()),
+ "tankPressure" = round(air_contents.returnPressure()),
"releasePressure" = round(release_pressure),
"valveOpen" = !!valve_open,
"isPrototype" = !!prototype,
@@ -652,7 +604,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
. += list(
"holdingTank" = list(
"name" = holding.name,
- "tankPressure" = round(holding_mix.return_pressure())
+ "tankPressure" = round(holding_mix.returnPressure())
)
)
. += list(
@@ -715,17 +667,15 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
var/n = 0
valve_open = !valve_open
if(valve_open)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
logmsg = "Valve was opened by [key_name(usr)], starting a transfer into \the [holding || "air"]. "
if(!holding)
var/list/gaseslog = list() //list for logging all gases in canister
- for(var/id in air_contents.gases)
- var/gas = air_contents.gases[id]
- gaseslog[gas[GAS_META][META_GAS_NAME]] = gas[MOLES] //adds gases to gaseslog
- if(!gas[GAS_META][META_GAS_DANGER])
+ for(var/gas in air_contents.gas)
+ gaseslog[xgm_gas_data.name[gas]] = air_contents.gas[gas] //adds gases to gaseslog
+ if(!(xgm_gas_data.flags[gas] & XGM_GAS_CONTAMINANT|XGM_GAS_FUEL))
continue
- if(gas[MOLES] > (gas[GAS_META][META_GAS_MOLES_VISIBLE] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
- danger = TRUE //at least 1 danger gas
+ danger = TRUE //at least 1 danger gas
logmsg = "[key_name(usr)] opened a canister that contains the following:"
admin_msg = "[key_name(usr)] opened a canister that contains the following at [ADMIN_VERBOSEJMP(src)]:"
for(var/name in gaseslog)
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index c7f922c92f5..4ffb3acd0d0 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -22,12 +22,12 @@
air_contents = new
air_contents.volume = volume
air_contents.temperature = T20C
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
/obj/machinery/portable_atmospherics/Destroy()
disconnect()
air_contents = null
- SSair.stop_processing_machine(src)
+ SSairmachines.stop_processing_machine(src)
return ..()
@@ -44,13 +44,13 @@
/obj/machinery/portable_atmospherics/process_atmos()
if(!connected_port) // Pipe network handles reactions if connected, and we can't stop processing if there's a port effecting our mix
- excited = (excited | air_contents.react(src))
+ excited = (excited | air_contents.react())
if(!excited)
return PROCESS_KILL
excited = FALSE
/obj/machinery/portable_atmospherics/return_air()
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
return air_contents
/obj/machinery/portable_atmospherics/return_analyzable_air()
@@ -80,7 +80,7 @@
pixel_x = new_port.pixel_x
pixel_y = new_port.pixel_y
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
update_appearance()
return TRUE
@@ -101,7 +101,7 @@
pixel_x = 0
pixel_y = 0
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
update_appearance()
return TRUE
@@ -139,7 +139,7 @@
holding = new_tank
RegisterSignal(holding, COMSIG_PARENT_QDELETING, .proc/unregister_holding)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
update_appearance()
return TRUE
@@ -193,10 +193,10 @@
add_fingerprint(user)
return ..()
-/// Holding tanks can get to zero integrity and be destroyed without other warnings due to pressure change.
+/// Holding tanks can get to zero integrity and be destroyed without other warnings due to pressure change.
/// This checks for that case and removes our reference to it.
/obj/machinery/portable_atmospherics/proc/unregister_holding()
SIGNAL_HANDLER
-
+
UnregisterSignal(holding, COMSIG_PARENT_QDELETING)
holding = null
diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm
index 7390affc0d1..c11e1788e9d 100644
--- a/code/modules/atmospherics/machinery/portable/pump.dm
+++ b/code/modules/atmospherics/machinery/portable/pump.dm
@@ -44,8 +44,8 @@
. += "siphon-connector"
/obj/machinery/portable_atmospherics/pump/process_atmos()
- var/pressure = air_contents.return_pressure()
- var/temperature = air_contents.return_temperature()
+ var/pressure = air_contents.returnPressure()
+ var/temperature = air_contents.get_temperature()
///function used to check the limit of the pumps and also set the amount of damage that the pump can receive, if the heat and pressure are way higher than the limit the more damage will be done
if(temperature > heat_limit || pressure > pressure_limit)
take_damage(clamp((temperature/heat_limit) * (pressure/pressure_limit), 5, 50), BURN, 0)
@@ -57,18 +57,33 @@
excited = TRUE
+ var/pressure_delta
+ var/output_volume
+ var/air_temperature
var/turf/local_turf = get_turf(src)
- var/datum/gas_mixture/sending
- var/datum/gas_mixture/receiving
- if(direction == PUMP_OUT) // Hook up the internal pump.
- sending = (holding ? holding.return_air() : air_contents)
- receiving = (holding ? air_contents : local_turf.return_air())
+ var/datum/gas_mixture/environment
+ if(holding)
+ environment = holding.air_contents
+ else
+ environment = local_turf.return_air()
+
+ if(direction == PUMP_OUT)
+ pressure_delta = target_pressure - environment.returnPressure()
+ output_volume = environment.volume * environment.group_multiplier
+ air_temperature = environment.temperature? environment.temperature : air_contents.temperature
else
- sending = (holding ? air_contents : local_turf.return_air())
- receiving = (holding ? holding.return_air() : air_contents)
+ pressure_delta = environment.returnPressure() - target_pressure
+ output_volume = air_contents.volume * air_contents.group_multiplier
+ air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature
+
+ var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
- if(sending.pump_gas_to(receiving, target_pressure) && !holding)
- air_update_turf(FALSE, FALSE) // Update the environment if needed.
+ if (pressure_delta > 0.01)
+ if (direction == PUMP_OUT)
+ pump_gas(air_contents, environment, transfer_moles)
+ else
+ pump_gas(environment, air_contents, transfer_moles)
+ //air_update_turf(FALSE, FALSE) // Update the environment if needed.
return ..()
@@ -81,7 +96,7 @@
if(prob(50 / severity))
on = !on
if(on)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
if(prob(100 / severity))
direction = PUMP_OUT
target_pressure = rand(0, 100 * ONE_ATMOSPHERE)
@@ -109,7 +124,7 @@
data["on"] = on
data["direction"] = direction == PUMP_IN ? TRUE : FALSE
data["connected"] = connected_port ? TRUE : FALSE
- data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
+ data["pressure"] = round(air_contents.returnPressure() ? air_contents.returnPressure() : 0)
data["target_pressure"] = round(target_pressure ? target_pressure : 0)
data["default_pressure"] = round(PUMP_DEFAULT_PRESSURE)
data["min_pressure"] = round(PUMP_MIN_PRESSURE)
@@ -119,7 +134,7 @@
data["holding"] = list()
data["holding"]["name"] = holding.name
var/datum/gas_mixture/holding_mix = holding.return_air()
- data["holding"]["pressure"] = round(holding_mix.return_pressure())
+ data["holding"]["pressure"] = round(holding_mix.returnPressure())
else
data["holding"] = null
return data
@@ -132,10 +147,10 @@
if("power")
on = !on
if(on)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
if(on && !holding)
- var/plasma = air_contents.gases[/datum/gas/plasma]
- var/n2o = air_contents.gases[/datum/gas/nitrous_oxide]
+ var/plasma = air_contents.getGroupGas(GAS_PLASMA)
+ var/n2o = air_contents.getGroupGas(GAS_N2O)
if(n2o || plasma)
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]")
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]")
diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm
index 1f907236f97..4afb885df45 100644
--- a/code/modules/atmospherics/machinery/portable/scrubber.dm
+++ b/code/modules/atmospherics/machinery/portable/scrubber.dm
@@ -17,23 +17,12 @@
var/overpressure_m = 80
///Should the machine use overlay in update_overlays() when open/close?
var/use_overlays = TRUE
- ///List of gases that can be scrubbed
- var/list/scrubbing = list(
- /datum/gas/plasma,
- /datum/gas/carbon_dioxide,
- /datum/gas/nitrous_oxide,
- /datum/gas/bz,
- /datum/gas/nitrium,
- /datum/gas/tritium,
- /datum/gas/hypernoblium,
- /datum/gas/water_vapor,
- /datum/gas/freon,
- /datum/gas/hydrogen,
- /datum/gas/healium,
- /datum/gas/proto_nitrate,
- /datum/gas/zauker,
- /datum/gas/halon,
- )
+ var/power_rating = 7500
+ ///List of gases that are being scrubbed.
+ var/list/scrubbing = list()
+
+/obj/machinery/portable_atmospherics/scrubber/Initialize(mapload)
+ . = ..()
/obj/machinery/portable_atmospherics/scrubber/Destroy()
var/turf/T = get_turf(src)
@@ -54,8 +43,8 @@
. += "scrubber-connector"
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
- var/pressure = air_contents.return_pressure()
- var/temperature = air_contents.return_temperature()
+ var/pressure = air_contents.returnPressure()
+ var/temperature = air_contents.get_temperature()
///function used to check the limit of the scrubbers and also set the amount of damage that the scrubber can receive, if the heat and pressure are way higher than the limit the more damage will be done
if(temperature > heat_limit || pressure > pressure_limit)
take_damage(clamp((temperature/heat_limit) * (pressure/pressure_limit), 5, 50), BURN, 0)
@@ -79,27 +68,14 @@
* * mixture: the gas mixture to be scrubbed
*/
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(datum/gas_mixture/mixture)
- if(air_contents.return_pressure() >= overpressure_m * ONE_ATMOSPHERE)
+ if(!mixture.total_moles || !length(scrubbing))
return
-
- var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles()
-
- var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter.
- var/datum/gas_mixture/filtered = new
- if(!filtering)
+ if(air_contents.returnPressure() >= overpressure_m * ONE_ATMOSPHERE)
return
- filtered.temperature = filtering.temperature
- for(var/gas in filtering.gases & scrubbing)
- filtered.add_gas(gas)
- filtered.gases[gas][MOLES] = filtering.gases[gas][MOLES] // Shuffle the "bad" gasses to the filtered mixture.
- filtering.gases[gas][MOLES] = 0
- filtering.garbage_collect() // Now that the gasses are set to 0, clean up the mixture.
+ var/transfer_moles = min(1, volume_rate/mixture.volume)*mixture.total_moles
- air_contents.merge(filtered) // Store filtered out gasses.
- mixture.merge(filtering) // Returned the cleaned gas.
- if(!holding)
- air_update_turf(FALSE, FALSE)
+ scrub_gas(scrubbing, mixture, air_contents, transfer_moles, power_rating)
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
. = ..()
@@ -109,7 +85,7 @@
if(prob(50 / severity))
on = !on
if(on)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
update_appearance()
/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, datum/tgui/ui)
@@ -122,19 +98,18 @@
var/data = list()
data["on"] = on
data["connected"] = connected_port ? 1 : 0
- data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
+ data["pressure"] = round(air_contents.returnPressure() ? air_contents.returnPressure() : 0)
data["id_tag"] = -1 //must be defined in order to reuse code between portable and vent scrubbers
data["filter_types"] = list()
- for(var/path in GLOB.meta_gas_info)
- var/list/gas = GLOB.meta_gas_info[path]
- data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in scrubbing)))
+ for(var/gas_id in ASSORTED_GASES)
+ data["filter_types"] += list(list("gas_id" = gas_id, "gas_name" = gas_id, "enabled" = (gas_id in scrubbing)))
if(holding)
data["holding"] = list()
data["holding"]["name"] = holding.name
var/datum/gas_mixture/holding_mix = holding.return_air()
- data["holding"]["pressure"] = round(holding_mix.return_pressure())
+ data["holding"]["pressure"] = round(holding_mix.returnPressure())
else
data["holding"] = null
return data
@@ -158,14 +133,14 @@
if("power")
on = !on
if(on)
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
. = TRUE
if("eject")
if(holding)
replace_tank(usr, FALSE)
. = TRUE
if("toggle_filter")
- scrubbing ^= gas_id2path(params["val"])
+ scrubbing ^= params["val"]
. = TRUE
update_appearance()
@@ -207,9 +182,8 @@
excited = TRUE
if(!holding)
- var/turf/T = get_turf(src)
- for(var/turf/AT in T.get_atmos_adjacent_turfs(alldir = TRUE))
- scrub(AT.return_air())
+ var/turf/muhturf = get_turf(src)
+ scrub(muhturf.return_air())
return ..()
diff --git a/code/modules/atmospherics/rust/fuel_rod.dm b/code/modules/atmospherics/rust/fuel_rod.dm
new file mode 100644
index 00000000000..b9f3470a350
--- /dev/null
+++ b/code/modules/atmospherics/rust/fuel_rod.dm
@@ -0,0 +1,94 @@
+/obj/item/fuel_rod
+ name = "fuel rod"
+ desc = "A heavy container filled with a reactive substance"
+ icon = 'icons/obj/machines/rust/fuel_rod.dmi'
+ flags_1 = CONDUCT_1
+ hitsound = 'sound/weapons/smash.ogg'
+ force = 5
+ throwforce = 10
+ throw_speed = 1
+ throw_range = 4
+ custom_materials = list(/datum/material/iron = 500)
+
+ var/obj/machinery/power/reactor_core/parent
+ ///Fuel, Control, Moderator
+ var/rod_type
+ ///The reactor slot this rod occupies
+ var/occupied_slot
+ var/max_volume
+ ///The amount of contents being exposed to the air, as a decimal
+ var/exposure_rate = 0
+
+/obj/item/fuel_rod/Destroy(force)
+ if(parent)
+ remove(parent)
+ return ..()
+
+/obj/item/fuel_rod/proc/return_volume()
+ return
+
+/obj/item/fuel_rod/proc/insert(obj/machinery/power/reactor_core/reactor, slot, mob/user) // No, you can't put two in one slot. Im sorry.
+ if(reactor.rods_by_slot[slot])
+ to_chat(user, span_notice("There is already a fuel rod in that slot."))
+ return
+
+ parent = reactor
+ parent.rods_by_slot[slot] = src
+ parent.all_rods += src
+ occupied_slot = slot
+
+ switch(rod_type)
+ if(ROD_FUEL)
+ parent.fuel_rods += src
+ if(ROD_CONTROL)
+ parent.control_rods += src
+ if(ROD_MODERATOR)
+ parent.moderator_rods += src
+
+
+/obj/item/fuel_rod/proc/remove(mob/user) // PULL OUT PULL OUT
+ if(!parent)
+ CRASH("Fuel rod remove() called with no parent")
+
+ if(user)
+ INVOKE_ASYNC(user, /mob.proc/put_in_hands, src)
+ else
+ forceMove(get_turf(parent))
+
+ parent.rods_by_slot[occupied_slot] = null
+ parent.all_rods -= src
+ occupied_slot = null
+ switch(rod_type)
+ if(ROD_FUEL)
+ parent.fuel_rods -= src
+ if(ROD_CONTROL)
+ parent.control_rods -= src
+ if(ROD_MODERATOR)
+ parent.moderator_rods -= src
+ parent = null
+
+/obj/item/fuel_rod/gas
+ name = "fuel rod (gas)"
+ desc = "A long and heavy container used for storing highly compressed gas."
+
+ max_volume = FUEL_ROD_GAS_VOLUME
+ var/datum/gas_mixture/air_contents = null
+
+/obj/item/fuel_rod/gas/Initialize(mapload)
+ . = ..()
+ air_contents = new(max_volume)
+
+/obj/item/fuel_rod/gas/return_volume()
+ return air_contents.removeVolume(exposure_rate * air_contents.volume)
+
+/obj/item/fuel_rod/reagent
+ name = "fuel rod (reagent)"
+
+ max_volume = FUEL_ROD_REAGENT_VOLUME
+
+/obj/item/fuel_rod/reagent/Initialize(mapload)
+ . = ..()
+ create_reagents(max_volume, TRANSPARENT)
+
+/obj/item/fuel_rod/reagent/return_volume()
+ return reagents.trans_to(parent, max_volume * exposure_rate, show_message = FALSE)
diff --git a/code/modules/atmospherics/rust/fusion_reactions.dm b/code/modules/atmospherics/rust/fusion_reactions.dm
new file mode 100644
index 00000000000..55ea238a82f
--- /dev/null
+++ b/code/modules/atmospherics/rust/fusion_reactions.dm
@@ -0,0 +1,29 @@
+GLOBAL_LIST_EMPTY(fusion_reactions)
+
+/datum/fusion_reaction
+ var/p_react = "" // Primary reactant.
+ var/s_react = "" // Secondary reactant.
+ var/minimum_energy_level = 1
+ var/energy_consumption = 0
+ var/energy_production = 0
+ var/radiation = 0
+ var/instability = 0
+ var/list/products = list()
+ var/minimum_reaction_temperature = 100
+ var/priority = 100
+
+/datum/fusion_reaction/proc/handle_reaction_special(obj/effect/reactor_em_field/holder)
+ return 0
+
+/proc/get_fusion_reaction(p_react, s_react)
+ return GLOB.fusion_reactions[p_react]?[s_react]
+
+/datum/fusion_reaction/deuterium_lithium
+ p_react = GAS_DEUTERIUM
+ //s_react = "lithium"
+ s_react = GAS_NEON //DEBUG PURPOSES
+ energy_consumption = 0
+ energy_production = 2
+ radiation = 3
+ products = list(GAS_TRITIUM= 1)
+ instability = 1
diff --git a/code/modules/atmospherics/rust/particle_catcher.dm b/code/modules/atmospherics/rust/particle_catcher.dm
new file mode 100644
index 00000000000..d0e214d83e6
--- /dev/null
+++ b/code/modules/atmospherics/rust/particle_catcher.dm
@@ -0,0 +1,42 @@
+/obj/effect/fusion_particle_catcher
+ density = TRUE
+ anchored = TRUE
+ invisibility = 101
+ light_color = COLOR_BLUE
+ ///Typecache of particles that can interact with this field.
+ var/static/list/particle_cache = typecacheof(/obj/projectile/energy/nuclear_particle)
+ var/obj/effect/reactor_em_field/parent
+ var/mysize = 0
+
+/obj/effect/fusion_particle_catcher/Destroy()
+ parent?.particle_catchers -= src //This should never actually exist outside of the R-UST, but, unit tests.
+ parent = null
+ return ..()
+
+/obj/effect/fusion_particle_catcher/proc/set_size(newsize)
+ name = "collector [newsize]"
+ mysize = newsize
+ update_size()
+
+/obj/effect/fusion_particle_catcher/proc/add_particles(name, quantity = 1)
+ if(parent && parent.size >= mysize)
+ parent.add_particles(name, quantity)
+ return 1
+ return 0
+
+/obj/effect/fusion_particle_catcher/proc/update_size()
+ if(parent.size >= mysize)
+ set_density(1)
+ name = "collector [mysize] ON"
+ else
+ set_density(0)
+ name = "collector [mysize] OFF"
+
+/obj/effect/fusion_particle_catcher/bullet_act(obj/projectile/Proj)
+ parent.add_energy(Proj.damage)
+ update_icon()
+ return 0
+
+/obj/effect/fusion_particle_catcher/CanAllowThrough(atom/movable/mover, border_dir)
+ ..()
+ return !particle_cache[mover.type]
diff --git a/code/modules/atmospherics/rust/reactor_core.dm b/code/modules/atmospherics/rust/reactor_core.dm
new file mode 100644
index 00000000000..e615e1a3831
--- /dev/null
+++ b/code/modules/atmospherics/rust/reactor_core.dm
@@ -0,0 +1,136 @@
+#define MAX_FIELD_STR 10000
+#define MIN_FIELD_STR 1
+
+/obj/machinery/power/reactor_core
+ name = "\improper R-UST Mk. 10 Tokamak Reactor"
+ desc = "An enormous solenoid for generating extremely high power electromagnetic fields."
+ icon = 'icons/obj/machines/rust/fusion_core.dmi'
+ icon_state = "core0"
+ layer = ABOVE_ALL_MOB_LAYER
+ density = TRUE
+ use_power = IDLE_POWER_USE
+ idle_power_usage = IDLE_POWER_USE
+ active_power_usage = 1000 //multiplied by field strength
+ anchored = FALSE
+
+ var/is_on = FALSE
+ var/obj/effect/reactor_em_field/owned_field
+ var/field_strength = 1//0.01
+ var/initial_id_tag
+
+ var/list/all_rods = list()
+ var/list/control_rods = list()
+ var/list/moderator_rods = list()
+ var/list/fuel_rods = list()
+
+ var/list/rods_by_slot = list(
+ REACTOR_SLOT_1 = null,
+ REACTOR_SLOT_2 = null,
+ REACTOR_SLOT_3 = null,
+ REACTOR_SLOT_4 = null,
+ REACTOR_SLOT_5 = null,
+ REACTOR_SLOT_6 = null,
+ REACTOR_SLOT_7 = null,
+ REACTOR_SLOT_8 = null,
+ REACTOR_SLOT_9 = null
+ )
+
+/obj/machinery/power/reactor_core/mapped
+ anchored = TRUE
+
+/obj/machinery/power/reactor_core/process()
+ if((machine_stat & BROKEN) || !use_power_from_net(use_power) || !owned_field)
+ if(is_on)
+ Shutdown()
+/*
+/obj/machinery/power/reactor_core/Topic(href, href_list)
+ if(..())
+ return 1
+ if(href_list["str"])
+ var/dif = text2num(href_list["str"])
+ field_strength = min(max(field_strength + dif, MIN_FIELD_STR), MAX_FIELD_STR)
+ change_power_consumption(500 * field_strength, POWER_USE_ACTIVE)
+ if(owned_field)
+ owned_field.ChangeFieldStrength(field_strength)
+*/
+
+/obj/machinery/power/reactor_core/proc/Startup()
+ if(owned_field)
+ return
+ owned_field = new(loc, src)
+ owned_field.set_field_strength(field_strength)
+ icon_state = "core1"
+ update_use_power(ACTIVE_POWER_USE)
+ is_on = TRUE
+ return TRUE
+
+/obj/machinery/power/reactor_core/proc/Shutdown(force_rupture)
+ if(owned_field)
+ icon_state = "core0"
+ if(force_rupture || owned_field.plasma_temperature > 1000)
+ owned_field.rupture()
+ else
+ owned_field.radiate_all()
+ qdel(owned_field)
+ owned_field = null
+ update_use_power(IDLE_POWER_USE)
+ is_on = FALSE
+
+/obj/machinery/power/reactor_core/proc/add_particles(name, quantity = 1)
+ if(owned_field)
+ owned_field.add_particles(name, quantity)
+ return TRUE
+
+/obj/machinery/power/reactor_core/bullet_act(obj/projectile/Proj)
+ if(owned_field)
+ . = owned_field.bullet_act(Proj)
+
+/obj/machinery/power/reactor_core/proc/set_strength(value)
+ value = clamp(value, MIN_FIELD_STR, MAX_FIELD_STR)
+ field_strength = value
+ active_power_usage = value*5
+ if(owned_field)
+ owned_field.set_field_strength(value)
+
+/obj/machinery/power/reactor_core/attack_hand(mob/user)
+ . = ..()
+ if(!.)
+ visible_message("\The [user] hugs \the [src] to make it feel better!")
+ if(owned_field)
+ Shutdown()
+ return TRUE
+
+/obj/machinery/power/reactor_core/attackby(obj/item/W, mob/user)
+ if(owned_field)
+ to_chat(user,"Shut \the [src] off first!")
+ return
+
+ if(W.tool_behaviour & TOOL_WRENCH)
+ anchored = !anchored
+ if(W.use_tool(user, 4 SECONDS))
+ if(anchored)
+ user.visible_message("[user.name] secures [src.name] to the floor.", \
+ "You secure the [src.name] to the floor.", \
+ "You hear a ratchet.")
+ else
+ user.visible_message("[user.name] unsecures [src.name] from the floor.", \
+ "You unsecure the [src.name] from the floor.", \
+ "You hear a ratchet.")
+ return
+
+ return ..()
+
+/obj/machinery/power/reactor_core/proc/Jumpstart(field_temperature)
+ field_strength = 501 // Generally a good size.
+ Startup()
+ if(!owned_field)
+ return FALSE
+ owned_field.plasma_temperature = field_temperature
+ return TRUE
+
+/obj/machinery/power/reactor_core/proc/check_core_status()
+ if(machine_stat & BROKEN)
+ return FALSE
+ /*if(idle_power_usage > avail())
+ return FALSE*/
+ return TRUE
diff --git a/code/modules/atmospherics/rust/reactor_em_field.dm b/code/modules/atmospherics/rust/reactor_em_field.dm
new file mode 100644
index 00000000000..da4c479508a
--- /dev/null
+++ b/code/modules/atmospherics/rust/reactor_em_field.dm
@@ -0,0 +1,517 @@
+//the em field is where the fun happens
+/*
+Deuterium-deuterium fusion : 40 x 10^7 K
+Deuterium-tritium fusion: 4.5 x 10^7 K
+*/
+
+//#DEFINE MAX_STORED_ENERGY (held_plasma[GAS_PLASMA] * held_plasma[GAS_PLASMA] * SPECIFIC_HEAT_TOXIN)
+//#define FUSIONDBG
+
+#define FUSION_ENERGY_PER_K 20
+#define FUSION_INSTABILITY_DIVISOR 50000
+#define FUSION_RUPTURE_THRESHOLD 10000
+#define FUSION_REACTANT_CAP 10000
+
+/obj/effect/reactor_em_field
+ name = "electromagnetic field"
+ desc = "A coruscating, barely visible field of energy. It is shaped like a slightly flattened torus."
+ icon = 'icons/obj/machines/rust/fusion.dmi'
+ icon_state = "emfield_s1"
+ alpha = 30
+ layer = RIPPLE_LAYER
+ light_color = COLOR_RED
+ color = COLOR_RED
+ anchored = TRUE //STOP FUCKING DRAGGING THE ELECTROMAGNETIC FIELD
+ var/size = 1
+ var/energy = 0
+ var/plasma_temperature = 0
+ var/radiation = 0
+ var/field_strength = 0.01
+ var/tick_instability = 0
+ var/percent_unstable = 0
+
+ var/obj/machinery/power/reactor_core/owned_core
+ var/list/reactants = list()
+ var/list/particle_catchers = list()
+
+ var/static/list/ignore_types
+
+ var/light_min_range = 2
+ var/light_min_power = 0.2
+ var/light_max_range = 18
+ var/light_max_power = 1
+
+ var/last_range
+ var/last_power
+
+/obj/effect/reactor_em_field/New(loc, obj/machinery/power/reactor_core/new_owned_core)
+ ..()
+ if(!ignore_types)
+ ignore_types = typecacheof(
+ list(
+ /obj/projectile,
+ /obj/effect,
+ /obj/structure/cable,
+ /obj/machinery/atmospherics
+ )
+ )
+
+ set_light(light_min_range, light_min_power, light_color, TRUE)
+ last_range = light_min_range
+ last_power = light_min_power
+
+ owned_core = new_owned_core
+ if(!owned_core)
+ qdel(src)
+ return
+
+ //create the gimmicky things to handle field collisions
+ var/obj/effect/fusion_particle_catcher/catcher
+
+ catcher = new (locate(src.x,src.y,src.z))
+ catcher.parent = src
+ catcher.set_size(1)
+ particle_catchers.Add(catcher)
+
+ for(var/iter in 1 to 6)
+ catcher = new (locate(src.x-iter,src.y,src.z))
+ catcher.parent = src
+ catcher.set_size((iter*2)+1)
+ particle_catchers.Add(catcher)
+
+ catcher = new (locate(src.x+iter,src.y,src.z))
+ catcher.parent = src
+ catcher.set_size((iter*2)+1)
+ particle_catchers.Add(catcher)
+
+ catcher = new (locate(src.x,src.y+iter,src.z))
+ catcher.parent = src
+ catcher.set_size((iter*2)+1)
+ particle_catchers.Add(catcher)
+
+ catcher = new (locate(src.x,src.y-iter,src.z))
+ catcher.parent = src
+ catcher.set_size((iter*2)+1)
+ particle_catchers.Add(catcher)
+
+ START_PROCESSING(SSobj, src)
+
+/obj/effect/reactor_em_field/Initialize()
+ . = ..()
+ addtimer(CALLBACK(src, .proc/update_light_colors), 10 SECONDS, TIMER_LOOP)
+ if(!GLOB.fusion_reactions.len)
+ GLOB.fusion_reactions = list()
+ for(var/rtype in subtypesof(/datum/fusion_reaction))
+ var/datum/fusion_reaction/cur_reaction = new rtype()
+ if(!GLOB.fusion_reactions[cur_reaction.p_react])
+ GLOB.fusion_reactions[cur_reaction.p_react] = list()
+ GLOB.fusion_reactions[cur_reaction.p_react][cur_reaction.s_react] = cur_reaction
+ if(!GLOB.fusion_reactions[cur_reaction.s_react])
+ GLOB.fusion_reactions[cur_reaction.s_react] = list()
+ GLOB.fusion_reactions[cur_reaction.s_react][cur_reaction.p_react] = cur_reaction
+
+/obj/effect/reactor_em_field/proc/update_light_colors()
+ var/use_range
+ var/use_power
+ switch (plasma_temperature)
+ if (-INFINITY to 1000)
+ light_color = COLOR_RED
+ use_range = light_min_range
+ use_power = light_min_power
+ alpha = 30
+ if (100000 to INFINITY)
+ light_color = COLOR_VIOLET
+ use_range = light_max_range
+ use_power = light_max_power
+ alpha = 230
+ else
+ var/temp_mod = ((plasma_temperature-5000)/20000)
+ use_range = light_min_range + Ceil((light_max_range-light_min_range)*temp_mod)
+ use_power = light_min_power + Ceil((light_max_power-light_min_power)*temp_mod)
+ switch (plasma_temperature)
+ if (1000 to 6000)
+ light_color = COLOR_ORANGE
+ alpha = 50
+ if (6000 to 20000)
+ light_color = COLOR_YELLOW
+ alpha = 80
+ if (20000 to 50000)
+ light_color = COLOR_GREEN
+ alpha = 120
+ if (50000 to 70000)
+ light_color = COLOR_CYAN
+ alpha = 160
+ if (70000 to 100000)
+ light_color = COLOR_BLUE
+ alpha = 200
+
+ if (last_range != use_range || last_power != use_power || color != light_color)
+ color = light_color
+ set_light(use_range, min(use_power, 1), light_color) //cap first arg at 1 to avoid breaking lighting stuff.
+ last_range = use_range
+ last_power = use_power
+
+/obj/effect/reactor_em_field/process()
+ //make sure the field generator is still intact
+ if(QDELETED(owned_core))
+ qdel(src)
+ return
+
+ // Take some gas up from our environment.
+ var/added_particles = FALSE
+ var/datum/gas_mixture/uptake_gas = owned_core.loc.return_air()
+ if(uptake_gas)
+ uptake_gas = uptake_gas.removeByFlag(XGM_GAS_FUSION_FUEL, rand(50,100))
+ if(uptake_gas && uptake_gas.total_moles)
+ for(var/gasname in uptake_gas.gas)
+ if(uptake_gas.gas[gasname]*10 > reactants[gasname])
+ add_particles(gasname, uptake_gas.gas[gasname]*10)
+ uptake_gas.adjustGas(gasname, -(uptake_gas.gas[gasname]), update=FALSE)
+ added_particles = TRUE
+ if(added_particles)
+ AIR_UPDATE_VALUES(uptake_gas)
+
+ //let the particles inside the field react
+ react()
+
+ // Dump power to our powernet.
+ owned_core.add_avail(FUSION_ENERGY_PER_K * plasma_temperature)
+
+ // Energy decay.
+ if(plasma_temperature >= 1)
+ var/lost = plasma_temperature*0.01
+ radiation += lost
+ plasma_temperature -= lost
+
+ //handle some reactants formatting
+ for(var/reactant in reactants)
+ var/amount = reactants[reactant]
+ if(amount < 1)
+ reactants.Remove(reactant)
+ else if(amount >= FUSION_REACTANT_CAP)
+ var/radiate = rand(3 * amount / 4, amount / 4)
+ reactants[reactant] -= radiate
+ radiation += radiate
+
+ check_instability()
+ radiate()
+ if(radiation)
+ radiation_pulse(src, src.size/2, RAD_FULL_INSULATION, 100)
+ return 1
+
+/obj/effect/reactor_em_field/proc/check_instability()
+ if(tick_instability > 0)
+ percent_unstable += (tick_instability*size)/FUSION_INSTABILITY_DIVISOR
+ tick_instability = 0
+ else
+ if(percent_unstable < 0)
+ percent_unstable = 0
+ else
+ if(percent_unstable > 1)
+ percent_unstable = 1
+ if(percent_unstable > 0)
+ percent_unstable = max(0, percent_unstable-rand(0.01,0.03))
+
+ if(percent_unstable >= 1)
+ owned_core.Shutdown(force_rupture=1)
+ else
+ if(percent_unstable > 0.5 && prob(percent_unstable*100))
+ if(plasma_temperature < FUSION_RUPTURE_THRESHOLD)
+ visible_message("\The [src] ripples uneasily, like a disturbed pond.")
+ else
+ var/flare
+ var/fuel_loss
+ var/rupture
+ if(percent_unstable < 0.7)
+ visible_message("\The [src] ripples uneasily, like a disturbed pond.")
+ fuel_loss = prob(5)
+ else if(percent_unstable < 0.9)
+ visible_message("\The [src] undulates violently, shedding plumes of plasma!")
+ flare = prob(50)
+ fuel_loss = prob(20)
+ rupture = prob(5)
+ else
+ visible_message("\The [src] is wracked by a series of horrendous distortions, buckling and twisting like a living thing!")
+ flare = 1
+ fuel_loss = prob(50)
+ rupture = prob(25)
+
+ if(rupture)
+ owned_core.Shutdown(force_rupture=1)
+ else
+ var/lost_plasma = (plasma_temperature*percent_unstable)
+ radiation += lost_plasma
+ if(flare)
+ radiation += plasma_temperature/2
+ plasma_temperature -= lost_plasma
+
+ if(fuel_loss)
+ for(var/particle in reactants)
+ var/lost_fuel = reactants[particle]*percent_unstable
+ radiation += lost_fuel
+ reactants[particle] -= lost_fuel
+ if(reactants[particle] <= 0)
+ reactants.Remove(particle)
+ radiate()
+ return
+
+/obj/effect/reactor_em_field/proc/is_shutdown_safe()
+ return plasma_temperature < 1000
+
+/obj/effect/reactor_em_field/proc/rupture()
+ visible_message(
+ span_danger("\The [src] shudders like a dying animal before flaring to eye-searing brightness and rupturing!"),
+ null,
+ span_hear("You hear a horrifying resonant crash. Oh no.")
+ )
+ set_light(15, 1, "#ccccff")
+ empulse(get_turf(src), Ceil(plasma_temperature/1000), Ceil(plasma_temperature/300))
+ addtimer(CALLBACK(src, .proc/kaboom), 5 SECONDS)
+
+/obj/effect/reactor_em_field/proc/kaboom()
+ radiate_all()
+ explosion(get_turf(owned_core),-1,-1,8,10) // Blow out all the windows.
+
+/obj/effect/reactor_em_field/proc/set_field_strength(new_strength)
+ var/calc_size = 1
+ if(new_strength <= 50)
+ calc_size = 1
+ else if(new_strength <= 200)
+ calc_size = 3
+ else if(new_strength <= 500)
+ calc_size = 5
+ else if(new_strength <= 1000)
+ calc_size = 7
+ else if(new_strength <= 2000)
+ calc_size = 9
+ else if(new_strength <= 5000)
+ calc_size = 11
+ else
+ calc_size = 13
+ field_strength = new_strength
+ change_size(calc_size)
+
+/obj/effect/reactor_em_field/proc/add_energy(added_energy, added_plasma_temperature)
+ energy += added_energy
+ plasma_temperature += added_plasma_temperature
+ if(added_energy && percent_unstable > 0)
+ percent_unstable -= added_energy/10000
+ if(percent_unstable < 0)
+ percent_unstable = 0
+ while(energy >= 100)
+ energy -= 100
+ plasma_temperature += 1
+
+/obj/effect/reactor_em_field/proc/add_particles(name, quantity = 1)
+ if(name in reactants)
+ reactants[name] += quantity
+ else if(name != "proton" && name != "electron" && name != "neutron")
+ reactants.Add(name)
+ reactants[name] = quantity
+
+/obj/effect/reactor_em_field/proc/radiate_all(ratio_lost = 1)
+ // Create our plasma field and dump it into our environment.
+ var/turf/T = get_turf(src)
+ if(istype(T))
+ var/datum/gas_mixture/plasma
+ for(var/reactant in reactants)
+ if(!xgm_gas_data.name[reactant])
+ continue
+ if(!plasma)
+ plasma = new
+ plasma.adjustGas(reactant, max(1,round(reactants[reactant]*0.1)), 0) // *0.1 to compensate for *10 when uptaking gas.
+ if(!plasma)
+ return
+ plasma.temperature = (plasma_temperature/2)
+ AIR_UPDATE_VALUES(plasma)
+ T.assume_air(plasma)
+ T.hotspot_expose(plasma_temperature)
+ plasma = null
+
+ // Radiate all our unspent fuel and energy.
+ for(var/particle in reactants)
+ radiation += reactants[particle]
+ reactants.Remove(particle)
+ radiation += plasma_temperature/2
+ plasma_temperature = 0
+
+ radiation_pulse(src, src.size/2, RAD_FULL_INSULATION, 100)
+ radiate()
+
+/obj/effect/reactor_em_field/proc/radiate()
+ if(isturf(loc))
+ var/list/cache4speed = ignore_types
+ var/empsev = max(1, min(3, Ceil(size/2)))
+ for(var/atom/movable/AM in range(max(1,Floor(size/2)), loc))
+ if(AM == src || AM == owned_core || !AM.simulated || cache4speed[AM.type])
+ continue
+
+ AM.visible_message(span_danger("The field buckles visibly around \the [AM]!"))
+ tick_instability += rand(30,50)
+ AM.emp_act(empsev)
+
+ if(owned_core && owned_core.loc)
+ var/datum/gas_mixture/environment = owned_core.loc.return_air()
+ if(environment && environment.temperature < (T0C+1000)) // Putting an upper bound on it to stop it being used in a TEG.
+ environment.addThermalEnergy(plasma_temperature*20000)
+ radiation = 0
+
+/obj/effect/reactor_em_field/proc/change_size(newsize = 1)
+ var/changed = 0
+ var/static/list/size_to_icon = list(
+ "3" = 'icons/obj/machines/rust/96x96.dmi',
+ "5" = 'icons/obj/machines/rust/160x160.dmi',
+ "7" = 'icons/obj/machines/rust/224x224.dmi',
+ "9" = 'icons/obj/machines/rust/288x288.dmi',
+ "11" = 'icons/obj/machines/rust/352x352.dmi',
+ "13" = 'icons/obj/machines/rust/416x416.dmi'
+ )
+
+ if( ((newsize-1)%2==0) && (newsize<=13) )
+ icon = 'icons/obj/machines/rust/fusion.dmi'
+ if(newsize>1)
+ icon = size_to_icon["[newsize]"]
+ icon_state = "emfield_s[newsize]"
+ pixel_x = ((newsize-1) * -16)
+ pixel_y = ((newsize-1) * -16)
+ size = newsize
+ changed = newsize
+
+ for(var/obj/effect/fusion_particle_catcher/catcher as anything in particle_catchers)
+ catcher.update_size()
+ return changed
+
+//the !!fun!! part
+/obj/effect/reactor_em_field/proc/react()
+ //loop through the reactants in random order
+ var/list/react_pool = reactants.Copy()
+
+ //cant have any reactions if there aren't any reactants present
+ if(react_pool.len)
+ //determine a random amount to actually react this cycle, and remove it from the standard pool
+ //this is a hack, and quite nonrealistic :(
+ for(var/reactant in react_pool)
+ react_pool[reactant] = rand(Floor(react_pool[reactant]/2),react_pool[reactant])
+ reactants[reactant] -= react_pool[reactant]
+ if(!react_pool[reactant])
+ react_pool -= reactant
+
+ //loop through all the reacting reagents, picking out random reactions for them
+ var/list/produced_reactants = new/list
+ var/list/p_react_pool = react_pool.Copy()
+ while(p_react_pool.len)
+ //for(var/i = 1; i <= p_react_pool.len; i++)
+ //pick one of the unprocessed reacting reagents randomly
+ var/cur_p_react = pick(p_react_pool)
+ p_react_pool.Remove(cur_p_react)
+
+ //grab all the possible reactants to have a reaction with
+ var/list/possible_s_reacts = react_pool.Copy()
+ //if there is only one of a particular reactant, then it can not react with itself so remove it
+ possible_s_reacts[cur_p_react] -= 1
+ if(possible_s_reacts[cur_p_react] < 1)
+ possible_s_reacts.Remove(cur_p_react)
+
+ //loop through and work out all the possible reactions
+ var/list/possible_reactions
+ for(var/cur_s_react in possible_s_reacts)
+ if(possible_s_reacts[cur_s_react] < 1)
+ continue
+ var/datum/fusion_reaction/cur_reaction = get_fusion_reaction(cur_p_react, cur_s_react)
+ if(cur_reaction && plasma_temperature >= cur_reaction.minimum_energy_level)
+ LAZYDISTINCTADD(possible_reactions, cur_reaction)
+
+ //if there are no possible reactions here, abandon this primary reactant and move on
+ if(!LAZYLEN(possible_reactions))
+ continue
+
+ /// Sort based on reaction priority to avoid deut-deut eating all the deut before deut-trit can run etc.
+ sortTim(possible_reactions, /proc/cmp_fusion_reaction_des)
+
+ //split up the reacting atoms between the possible reactions
+ while(possible_reactions.len)
+ var/datum/fusion_reaction/cur_reaction = possible_reactions[1]
+ possible_reactions.Remove(cur_reaction)
+
+ //set the randmax to be the lower of the two involved reactants
+ var/max_num_reactants = react_pool[cur_reaction.p_react] > react_pool[cur_reaction.s_react] ? \
+ react_pool[cur_reaction.s_react] : react_pool[cur_reaction.p_react]
+ if(max_num_reactants < 1)
+ continue
+
+ //make sure we have enough energy
+ if(plasma_temperature < cur_reaction.minimum_reaction_temperature)
+ continue
+
+ if(plasma_temperature < max_num_reactants * cur_reaction.energy_consumption)
+ max_num_reactants = round(plasma_temperature / cur_reaction.energy_consumption)
+ if(max_num_reactants < 1)
+ continue
+
+ //randomly determined amount to react
+ var/amount_reacting = rand(1, max_num_reactants)
+
+ //removing the reacting substances from the list of substances that are primed to react this cycle
+ //if there aren't enough of that substance (there should be) then modify the reactant amounts accordingly
+ if( react_pool[cur_reaction.p_react] - amount_reacting >= 0 )
+ react_pool[cur_reaction.p_react] -= amount_reacting
+ else
+ amount_reacting = react_pool[cur_reaction.p_react]
+ react_pool[cur_reaction.p_react] = 0
+ //same again for secondary reactant
+ if(react_pool[cur_reaction.s_react] - amount_reacting >= 0 )
+ react_pool[cur_reaction.s_react] -= amount_reacting
+ else
+ react_pool[cur_reaction.p_react] += amount_reacting - react_pool[cur_reaction.p_react]
+ amount_reacting = react_pool[cur_reaction.s_react]
+ react_pool[cur_reaction.s_react] = 0
+
+ plasma_temperature -= max_num_reactants * cur_reaction.energy_consumption // Remove the consumed energy.
+ plasma_temperature += max_num_reactants * cur_reaction.energy_production // Add any produced energy.
+ radiation += max_num_reactants * cur_reaction.radiation // Add any produced radiation.
+ tick_instability += max_num_reactants * cur_reaction.instability
+
+ // Create the reaction products.
+ for(var/reactant in cur_reaction.products)
+ var/success = 0
+ for(var/check_reactant in produced_reactants)
+ if(check_reactant == reactant)
+ produced_reactants[reactant] += cur_reaction.products[reactant] * amount_reacting
+ success = 1
+ break
+ if(!success)
+ produced_reactants[reactant] = cur_reaction.products[reactant] * amount_reacting
+
+ // Handle anything special. If this proc returns true, abort the current reaction.
+ if(cur_reaction.handle_reaction_special(src))
+ return
+
+ // This reaction is done, and can't be repeated this sub-cycle.
+ possible_reactions.Remove(cur_reaction.s_react)
+
+ // Loop through the newly produced reactants and add them to the pool.
+ for(var/reactant in produced_reactants)
+ add_particles(reactant, produced_reactants[reactant])
+
+ // Check whether there are reactants left, and add them back to the pool.
+ for(var/reactant in react_pool)
+ add_particles(reactant, react_pool[reactant])
+
+/obj/effect/reactor_em_field/Destroy()
+ set_light(0)
+ radiate_all()
+ QDEL_LIST(particle_catchers)
+ if(owned_core)
+ owned_core.owned_field = null
+ owned_core = null
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/effect/reactor_em_field/bullet_act(obj/projectile/proj)
+ add_energy(proj.damage)
+ update_icon()
+ return 0
+
+#undef FUSION_INSTABILITY_DIVISOR
+#undef FUSION_RUPTURE_THRESHOLD
+#undef FUSION_REACTANT_CAP
diff --git a/code/modules/awaymissions/away_props.dm b/code/modules/awaymissions/away_props.dm
index 71d04598086..077f8abd42a 100644
--- a/code/modules/awaymissions/away_props.dm
+++ b/code/modules/awaymissions/away_props.dm
@@ -10,24 +10,6 @@
. = ..()
return . && (REVERSE_DIR(border_dir) == dir || get_turf(mover) == get_turf(src))
-
-/obj/effect/wind
- name = "wind effect"
- desc = "Creates pressure effect in it's direction. Use sparingly."
- icon = 'icons/effects/mapping_helpers.dmi'
- icon_state = "field_dir"
- invisibility = INVISIBILITY_MAXIMUM
- var/strength = 30
-
-/obj/effect/wind/Initialize(mapload)
- . = ..()
- START_PROCESSING(SSobj,src)
-
-/obj/effect/wind/process()
- var/turf/open/T = get_turf(src)
- if(istype(T))
- T.consider_pressure_difference(get_step(T,dir),strength)
-
//Keep these rare due to cost of doing these checks
/obj/effect/path_blocker
name = "magic barrier"
diff --git a/code/modules/awaymissions/cordon.dm b/code/modules/awaymissions/cordon.dm
index e85a2e346e4..31a4ddc7447 100644
--- a/code/modules/awaymissions/cordon.dm
+++ b/code/modules/awaymissions/cordon.dm
@@ -16,7 +16,6 @@
/turf/cordon/AfterChange()
. = ..()
- SSair.high_pressure_delta -= src
/turf/cordon/attack_ghost(mob/dead/observer/user)
return FALSE
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index a7d07884a71..a83c6ce77a8 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -6,7 +6,7 @@
requires_power = FALSE
static_lighting = FALSE
base_lighting_alpha = 255
-
+
/area/awaymission/snowdin/outside
name = "Snowdin Tundra Plains"
icon_state = "awaycontent25"
@@ -157,15 +157,12 @@
//liquid plasma!!!!!!//
/turf/open/floor/iron/dark/snowdin
- initial_gas_mix = FROZEN_ATMOS
- planetary_atmos = 1
temperature = 180
/turf/open/lava/plasma
name = "liquid plasma"
desc = "A flowing stream of chilled liquid plasma. You probably shouldn't get in."
icon_state = "liquidplasma"
- initial_gas_mix = "n2=82;plasma=24;TEMP=120"
baseturfs = /turf/open/lava/plasma
light_range = 3
@@ -226,7 +223,7 @@
//mafia specific tame happy plasma (normal atmos, no slowdown)
/turf/open/lava/plasma/mafia
- initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ initial_gas = OPENTURF_DEFAULT_ATMOS
baseturfs = /turf/open/lava/plasma/mafia
slowdown = 0
diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm
index c3216543b63..29a349c598f 100644
--- a/code/modules/cargo/bounties/engineering.dm
+++ b/code/modules/cargo/bounties/engineering.dm
@@ -4,42 +4,42 @@
reward = CARGO_CRATE_VALUE * 15
wanted_types = list(/obj/item/tank = TRUE)
var/moles_required = 20 // A full tank is 28 moles, but CentCom ignores that fact.
- var/gas_type = /datum/gas/pluoxium
+ var/gas_type
/datum/bounty/item/engineering/gas/applies_to(obj/O)
if(!..())
return FALSE
var/obj/item/tank/T = O
var/datum/gas_mixture/our_mix = T.return_air()
- if(!our_mix.gases[gas_type])
+ if(!our_mix.getGroupGas(gas_type))
return FALSE
- return our_mix.gases[gas_type][MOLES] >= moles_required
+ return our_mix.getGroupGas(gas_type) >= moles_required
/datum/bounty/item/engineering/gas/nitrium_tank
name = "Full Tank of Nitrium"
description = "The non-human staff of Station 88 has been volunteered to test performance enhancing drugs. Ship them a tank full of Nitrium so they can get started. (20 Moles)"
- gas_type = /datum/gas/nitrium
+// gas_type = /datum/gas/nitrium
/datum/bounty/item/engineering/gas/freon_tank
name = "Full Tank of Freon"
description = "The Supermatter of station 33 has started the delamination process. Deliver a tank of Freon gas to help them stop it! (20 Moles)"
- gas_type = /datum/gas/freon
+ //gas_type = /datum/gas/freon
/datum/bounty/item/engineering/gas/tritium_tank
name = "Full Tank of Tritium"
description = "Station 49 is looking to kickstart their research program. Ship them a tank full of Tritium. (20 Moles)"
- gas_type = /datum/gas/tritium
+ //gas_type = /datum/gas/tritium
/datum/bounty/item/engineering/gas/hydrogen_tank
name = "Full Tank of Hydrogen"
description = "Our R&D department is working on the development of more efficient electrical batteries using hydrogen as a catalyst. Ship us a tank full of it. (20 Moles)"
- gas_type = /datum/gas/hydrogen
+ //gas_type = /datum/gas/hydrogen
/datum/bounty/item/engineering/gas/zauker_tank
name = "Full Tank of Zauker"
description = "The main planet of \[REDACTED] has been chosen as testing grounds for the new weapon that uses Zauker gas. Ship us a tank full of it. (20 Moles)"
reward = CARGO_CRATE_VALUE * 20
- gas_type = /datum/gas/zauker
+ //gas_type = /datum/gas/zauker
/datum/bounty/item/engineering/emitter
name = "Emitter"
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index 52eb1611bae..c2fd281e86f 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -301,7 +301,7 @@
temp_pod.explosionSize = list(0,0,0,0)
return
explosionChoice = 2
- temp_pod.explosionSize = list(GLOB.MAX_EX_DEVESTATION_RANGE, GLOB.MAX_EX_HEAVY_RANGE, GLOB.MAX_EX_LIGHT_RANGE,GLOB.MAX_EX_FLAME_RANGE) //Set explosion to max cap of server
+ temp_pod.explosionSize = list(zas_settings.maxex_devastation_range, zas_settings.maxex_heavy_range, zas_settings.maxex_light_range, zas_settings.maxex_fire_range) //Set explosion to max cap of server
. = TRUE
if("damageCustom") //Deals damage to whoevers under the pod when it lands
if (damageChoice == 1) //If already doing custom damage, set back to default (no damage)
diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm
index 422082a060f..10ad1c85695 100644
--- a/code/modules/cargo/exports/large_objects.dm
+++ b/code/modules/cargo/exports/large_objects.dm
@@ -79,7 +79,7 @@
/datum/export/large/supermatter
cost = CARGO_CRATE_VALUE * 16
unit_name = "supermatter shard"
- export_types = list(/obj/machinery/power/supermatter_crystal/shard)
+ //export_types = list(/obj/machinery/power/supermatter_crystal/shard)
/datum/export/large/grounding_rod
cost = CARGO_CRATE_VALUE * 1.2
@@ -106,32 +106,14 @@
var/obj/machinery/portable_atmospherics/canister/C = O
var/worth = cost
var/datum/gas_mixture/canister_mix = C.return_air()
- var/canister_gas = canister_mix.gases
- var/list/gases_to_check = list(
- /datum/gas/bz,
- /datum/gas/nitrium,
- /datum/gas/hypernoblium,
- /datum/gas/miasma,
- /datum/gas/tritium,
- /datum/gas/pluoxium,
- /datum/gas/freon,
- /datum/gas/hydrogen,
- /datum/gas/healium,
- /datum/gas/proto_nitrate,
- /datum/gas/zauker,
- /datum/gas/helium,
- /datum/gas/antinoblium,
- /datum/gas/halon,
- )
+ var/list/gases_to_check = xgm_gas_data.gases
for(var/gasID in gases_to_check)
- canister_mix.assert_gas(gasID)
- if(canister_gas[gasID][MOLES] > 0)
- worth += get_gas_value(gasID, canister_gas[gasID][MOLES])
+ if(canister_mix.getGroupGas(gasID) > 0)
+ worth += get_gas_value(gasID, canister_mix.getGroupGas(gasID))
- canister_mix.garbage_collect()
return worth
-/datum/export/large/gas_canister/proc/get_gas_value(datum/gas/gasType, moles)
- var/baseValue = initial(gasType.base_value)
+/datum/export/large/gas_canister/proc/get_gas_value(gastype, moles)
+ var/baseValue = xgm_gas_data.base_value[gastype]
return round((baseValue/k_elasticity) * (1 - NUM_E**(-1 * k_elasticity * moles)))
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index b0f6250098f..5a2fb8a381c 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -953,7 +953,7 @@
desc = "The power of the heavens condensed into a single crystal. Requires CE access to open."
cost = CARGO_CRATE_VALUE * 20
access = ACCESS_CE
- contains = list(/obj/machinery/power/supermatter_crystal/shard)
+ //contains = list(/obj/machinery/power/supermatter_crystal/shard)
crate_name = "supermatter shard crate"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
@@ -974,7 +974,7 @@
desc = "The new and improved fusion reactor. Requires CE access to open."
cost = CARGO_CRATE_VALUE * 23
access = ACCESS_CE
- contains = list(/obj/item/hfr_box/corner,
+ /*contains = list(/obj/item/hfr_box/corner,
/obj/item/hfr_box/corner,
/obj/item/hfr_box/corner,
/obj/item/hfr_box/corner,
@@ -982,7 +982,7 @@
/obj/item/hfr_box/body/moderator_input,
/obj/item/hfr_box/body/waste_output,
/obj/item/hfr_box/body/interface,
- /obj/item/hfr_box/core)
+ /obj/item/hfr_box/core)*/
crate_name = "HFR crate"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
@@ -1111,30 +1111,40 @@
// This is the amount of moles in a default canister
var/moleCount = (initial(fakeCanister.maximum_pressure) * initial(fakeCanister.filled)) * initial(fakeCanister.volume) / (R_IDEAL_GAS_EQUATION * T20C)
- for(var/gasType in GLOB.meta_gas_info)
- var/datum/gas/gas = gasType
- var/name = initial(gas.name)
- if(!initial(gas.purchaseable))
+ for(var/gasType in xgm_gas_data.gases)
+ var/name = xgm_gas_data.name[gasType]
+ if(!xgm_gas_data.purchaseable[gasType])
continue
var/datum/supply_pack/materials/pack = new
pack.name = "[name] Canister"
pack.desc = "Contains a canister of [name]."
- if(initial(gas.dangerous))
+ if(xgm_gas_data.flags[gasType] & XGM_GAS_FUEL)
pack.desc = "[pack.desc] Requires Atmospherics access to open."
pack.access = ACCESS_ATMOSPHERICS
pack.access_view = ACCESS_ATMOSPHERICS
pack.crate_name = "[name] canister crate"
pack.id = "[type]([name])"
- pack.cost = cost + moleCount * initial(gas.base_value) * 1.6
+ pack.cost = cost + moleCount * xgm_gas_data.base_value[gasType] * 1.6
pack.cost = CEILING(pack.cost, 10)
- pack.contains = list(GLOB.gas_id_to_canister[initial(gas.id)])
+ pack.contains = list(GLOB.gas_id_to_canister[gasType])
pack.crate_type = crate_type
canister_packs += pack
+ ////AIRMIX SPECIAL BABY
+ var/datum/supply_pack/materials/airpack = new
+ airpack.name = "Airmix Canister"
+ airpack.desc = "Contains a canister of breathable air."
+ airpack.crate_name = "airmix canister crate"
+ airpack.id = "[type](airmix)"
+ airpack.cost = 3000
+ airpack.contains = list(/obj/machinery/portable_atmospherics/canister/air)
+ airpack.crate_type = crate_type
+ canister_packs += airpack
+
return canister_packs
//////////////////////////////////////////////////////////////////////////////
diff --git a/code/modules/clothing/masks/gas_filter.dm b/code/modules/clothing/masks/gas_filter.dm
index 09dafd7e415..0f11dc967b0 100644
--- a/code/modules/clothing/masks/gas_filter.dm
+++ b/code/modules/clothing/masks/gas_filter.dm
@@ -29,25 +29,14 @@
///List of gases with high filter priority
var/list/high_filtering_gases = list(
- /datum/gas/plasma,
- /datum/gas/carbon_dioxide,
- /datum/gas/nitrous_oxide
- )
+ GAS_PLASMA,
+ GAS_CO2,
+ GAS_N2O
+ )
///List of gases with medium filter priority
- var/list/mid_filtering_gases = list(
- /datum/gas/nitrium,
- /datum/gas/freon,
- /datum/gas/hypernoblium,
- /datum/gas/bz
- )
+ var/list/mid_filtering_gases = list()
///List of gases with low filter priority
- var/list/low_filtering_gases = list(
- /datum/gas/healium,
- /datum/gas/proto_nitrate,
- /datum/gas/halon,
- /datum/gas/tritium,
- /datum/gas/zauker
- )
+ var/list/low_filtering_gases = list()
/obj/item/gas_filter/examine(mob/user)
. = ..()
@@ -62,38 +51,39 @@
*
*/
/obj/item/gas_filter/proc/reduce_filter_status(datum/gas_mixture/breath)
-
+ var/list/gases = breath.getGases()
var/danger_points = 0
- for(var/gas_id in breath.gases)
+ for(var/gas_id in gases)
if(gas_id in high_filtering_gases)
- if(breath.gases[gas_id][MOLES] > HIGH_FILTERING_MOLES)
- breath.gases[gas_id][MOLES] = max(breath.gases[gas_id][MOLES] - filter_strength_high * filter_efficiency * HIGH_FILTERING_RATIO, 0)
+ if(gases[gas_id] > HIGH_FILTERING_MOLES)
+ gases[gas_id] = max(gases[gas_id] - filter_strength_high * filter_efficiency * HIGH_FILTERING_RATIO, 0)
danger_points += 0.5
continue
- breath.gases[gas_id][MOLES] = max(breath.gases[gas_id][MOLES] - filter_strength_high * filter_efficiency * LOW_FILTERING_RATIO, 0)
+ gases[gas_id] = max(gases[gas_id] - filter_strength_high * filter_efficiency * LOW_FILTERING_RATIO, 0)
danger_points += 0.05
continue
if(gas_id in mid_filtering_gases)
- if(breath.gases[gas_id][MOLES] > MID_FILTERING_MOLES)
- breath.gases[gas_id][MOLES] = max(breath.gases[gas_id][MOLES] - filter_strength_mid * filter_efficiency * HIGH_FILTERING_RATIO, 0)
+ if(gases[gas_id] > MID_FILTERING_MOLES)
+ gases[gas_id] = max(gases[gas_id]- filter_strength_mid * filter_efficiency * HIGH_FILTERING_RATIO, 0)
danger_points += 0.75
continue
- breath.gases[gas_id][MOLES] = max(breath.gases[gas_id][MOLES] - filter_strength_mid * filter_efficiency * LOW_FILTERING_RATIO, 0)
+ gases[gas_id] = max(gases[gas_id] - filter_strength_mid * filter_efficiency * LOW_FILTERING_RATIO, 0)
danger_points += 0.15
continue
if(gas_id in low_filtering_gases)
- if(breath.gases[gas_id][MOLES] > LOW_FILTERING_MOLES)
- breath.gases[gas_id][MOLES] = max(breath.gases[gas_id][MOLES] - filter_strength_low * filter_efficiency * HIGH_FILTERING_RATIO, 0)
+ if(gases[gas_id] > LOW_FILTERING_MOLES)
+ gases[gas_id] = max(gases[gas_id] - filter_strength_low * filter_efficiency * HIGH_FILTERING_RATIO, 0)
danger_points += 1
continue
- breath.gases[gas_id][MOLES] = max(breath.gases[gas_id][MOLES] - filter_strength_low * filter_efficiency * LOW_FILTERING_RATIO, 0)
+ gases[gas_id] = max(gases[gas_id] - filter_strength_low * filter_efficiency * LOW_FILTERING_RATIO, 0)
danger_points += 0.5
continue
filter_status = max(filter_status - danger_points - FILTERS_CONSTANT_WEAR, 0)
return breath
+
/obj/item/gas_filter/damaged
name = "damaged gas filter"
desc = "A piece of filtering cloth to be used with atmospheric gas masks and emergency gas masks, it seems damaged."
@@ -106,7 +96,7 @@
/obj/item/gas_filter/plasmaman
name = "plasmaman atmospheric gas filter"
high_filtering_gases = list(
- /datum/gas/oxygen,
- /datum/gas/carbon_dioxide,
- /datum/gas/nitrous_oxide
+ GAS_OXYGEN,
+ GAS_CO2,
+ GAS_N2O
)
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index c90516ace11..aea17d2a37f 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -261,7 +261,7 @@
/obj/item/clothing/head/helmet/space/suicide_act(mob/living/carbon/user)
var/datum/gas_mixture/environment = user.loc.return_air()
- if(HAS_TRAIT(user, TRAIT_RESISTCOLD) || !environment || environment.return_temperature() >= user.get_body_temp_cold_damage_limit())
+ if(HAS_TRAIT(user, TRAIT_RESISTCOLD) || !environment || environment.get_temperature() >= user.get_body_temp_cold_damage_limit())
user.visible_message(span_suicide("[user] is beating [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
return BRUTELOSS
user.say("You want proof? I'll give you proof! Here's proof of what'll happen to you if you stay here with your stuff!", forced = "space helmet suicide")
diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm
index da8b23ac5a8..e787571f3f7 100755
--- a/code/modules/clothing/under/accessories.dm
+++ b/code/modules/clothing/under/accessories.dm
@@ -261,17 +261,12 @@
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = -10, ACID = 0) //It's made of plasma. Of course it's flammable.
custom_materials = list(/datum/material/plasma=1000)
-/obj/item/clothing/accessory/medal/plasma/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/atmos_sensitive, mapload)
-
-/obj/item/clothing/accessory/medal/plasma/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 300
-
/obj/item/clothing/accessory/medal/plasma/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- atmos_spawn_air("plasma=20;TEMP=[exposed_temperature]")
- visible_message(span_danger("\The [src] bursts into flame!"), span_userdanger("Your [src] bursts into flame!"))
- qdel(src)
+ if(exposed_temperature > 300)
+ var/turf/turfloc = get_turf(src)
+ turfloc.atmos_spawn_air(GAS_PLASMA, 20, exposed_temperature)
+ visible_message(span_danger("\The [src] bursts into flame!"), span_userdanger("Your [src] bursts into flame!"))
+ qdel(src)
/obj/item/clothing/accessory/medal/plasma/nobel_science
name = "nobel sciences award"
diff --git a/code/modules/error_handler/error_viewer.dm b/code/modules/error_handler/error_viewer.dm
index fbaa0ca3fae..56c5a082c09 100644
--- a/code/modules/error_handler/error_viewer.dm
+++ b/code/modules/error_handler/error_viewer.dm
@@ -116,7 +116,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache)
// from the same source hasn't been shown too recently
if (error_source.next_message_at <= world.time)
var/const/viewtext = "\[view]" // Nesting these in other brackets went poorly
- //log_debug("Runtime in [e.file], line [e.line]: [html_encode(e.name)] [error_entry.make_link(viewtext)]")
+ //log_admin("Runtime in [e.file], line [e.line]: [html_encode(e.name)] [error_entry.make_link(viewtext)]")
var/err_msg_delay
if(config?.loaded)
err_msg_delay = CONFIG_GET(number/error_msg_delay)
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index 91dd2ef8cb1..3fcaf759832 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -265,10 +265,9 @@
var/turf/open/floor/turf = holder.loc
if(istype(turf))
var/datum/gas_mixture/gas_mix = turf.air
- if(!gas_mix.gases[/datum/gas/oxygen])
+ if(!gas_mix.getGroupGas(GAS_OXYGEN))
return
- gas_mix.gases[/datum/gas/oxygen][MOLES] = max(gas_mix.gases[/datum/gas/oxygen][MOLES] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0)
- gas_mix.garbage_collect()
+ gas_mix.setGasMoles(GAS_OXYGEN, max(gas_mix.gas[GAS_OXYGEN] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0))
/datum/spacevine_mutation/nitro_eater
name = "Nitrogen consuming"
@@ -280,10 +279,9 @@
var/turf/open/floor/turf = holder.loc
if(istype(turf))
var/datum/gas_mixture/gas_mix = turf.air
- if(!gas_mix.gases[/datum/gas/nitrogen])
+ if(!gas_mix.getGroupGas(GAS_NITROGEN))
return
- gas_mix.gases[/datum/gas/nitrogen][MOLES] = max(gas_mix.gases[/datum/gas/nitrogen][MOLES] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0)
- gas_mix.garbage_collect()
+ gas_mix.setGasMoles(GAS_NITROGEN, max(gas_mix.gas[GAS_NITROGEN] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0))
/datum/spacevine_mutation/carbondioxide_eater
name = "CO2 consuming"
@@ -295,10 +293,9 @@
var/turf/open/floor/turf = holder.loc
if(istype(turf))
var/datum/gas_mixture/gas_mix = turf.air
- if(!gas_mix.gases[/datum/gas/carbon_dioxide])
+ if(!gas_mix.getGroupGas(GAS_OXYGEN))
return
- gas_mix.gases[/datum/gas/carbon_dioxide][MOLES] = max(gas_mix.gases[/datum/gas/carbon_dioxide][MOLES] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0)
- gas_mix.garbage_collect()
+ gas_mix.setGasMoles(GAS_CO2, max(gas_mix.gas[GAS_CO2] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0))
/datum/spacevine_mutation/plasma_eater
name = "Plasma consuming"
@@ -310,10 +307,9 @@
var/turf/open/floor/turf = holder.loc
if(istype(turf))
var/datum/gas_mixture/gas_mix = turf.air
- if(!gas_mix.gases[/datum/gas/plasma])
+ if(!gas_mix.getGroupGas(GAS_PLASMA))
return
- gas_mix.gases[/datum/gas/plasma][MOLES] = max(gas_mix.gases[/datum/gas/plasma][MOLES] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0)
- gas_mix.garbage_collect()
+ gas_mix.setGasMoles(GAS_PLASMA, max(gas_mix.gas[GAS_PLASMA] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.energy, 0))
/datum/spacevine_mutation/thorns
name = "Thorny"
@@ -393,7 +389,6 @@
COMSIG_ATOM_ENTERED = .proc/on_entered,
)
AddElement(/datum/element/connect_loc, loc_connections)
- AddElement(/datum/element/atmos_sensitive, mapload)
/obj/structure/spacevine/examine(mob/user)
. = ..()
@@ -663,16 +658,14 @@
if(!index && prob(34 * severity))
qdel(src)
-/obj/structure/spacevine/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD || exposed_temperature < VINE_FREEZING_POINT || !can_spread)//if you're room temperature you're safe
-
/obj/structure/spacevine/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- if(!can_spread && (exposed_temperature >= VINE_FREEZING_POINT || (trait_flags & SPACEVINE_COLD_RESISTANT)))
- can_spread = TRUE // not returning here just in case its now a plasmafire and the kudzu should be deleted
- if(exposed_temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD && !(trait_flags & SPACEVINE_HEAT_RESISTANT))
- qdel(src)
- else if (exposed_temperature < VINE_FREEZING_POINT && !(trait_flags & SPACEVINE_COLD_RESISTANT))
- can_spread = FALSE
+ if(exposed_temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD || exposed_temperature < VINE_FREEZING_POINT || !can_spread)
+ if(!can_spread && (exposed_temperature >= VINE_FREEZING_POINT || (trait_flags & SPACEVINE_COLD_RESISTANT)))
+ can_spread = TRUE // not returning here just in case its now a plasmafire and the kudzu should be deleted
+ if(exposed_temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD && !(trait_flags & SPACEVINE_HEAT_RESISTANT))
+ qdel(src)
+ else if (exposed_temperature < VINE_FREEZING_POINT && !(trait_flags & SPACEVINE_COLD_RESISTANT))
+ can_spread = FALSE
/obj/structure/spacevine/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
diff --git a/code/modules/experisci/experiment/experiments.dm b/code/modules/experisci/experiment/experiments.dm
index 2d2606f6fbb..8983a50080d 100644
--- a/code/modules/experisci/experiment/experiments.dm
+++ b/code/modules/experisci/experiment/experiments.dm
@@ -82,7 +82,7 @@
sanitized_misc = TRUE
sanitized_reactions = TRUE
require_all = FALSE
- required_reactions = list(/datum/gas_reaction/h2fire, /datum/gas_reaction/tritfire)
+ //required_reactions = list(/datum/gas_reaction/h2fire, /datum/gas_reaction/tritfire)
/datum/experiment/ordnance/explosive/nobliumbomb
name = "Noblium Explosives"
@@ -92,7 +92,7 @@
experiment_proper = TRUE
sanitized_misc = TRUE
sanitized_reactions = TRUE
- required_reactions = list(/datum/gas_reaction/nobliumformation)
+ //required_reactions = list(/datum/gas_reaction/nobliumformation)
/datum/experiment/ordnance/explosive/pressurebomb
name = "Reactionless Explosives"
@@ -109,7 +109,7 @@
gain = list(20,60,120)
target_amount = list(20,120,500)
experiment_proper = TRUE
- required_gas = /datum/gas/nitrium
+ //required_gas = /datum/gas/nitrium
/datum/experiment/ordnance/gaseous/bz
name = "BZ Gas Shells"
@@ -117,7 +117,7 @@
gain = list(25,50)
target_amount = list(200,600)
experiment_proper = TRUE
- required_gas = /datum/gas/bz
+ //required_gas = /datum/gas/bz
/datum/experiment/ordnance/gaseous/noblium
name = "Noblium Gas Shells"
@@ -125,7 +125,7 @@
gain = list(10,40,80)
target_amount = list(15,55,250)
experiment_proper = TRUE
- required_gas = /datum/gas/hypernoblium
+ //required_gas = /datum/gas/hypernoblium
/datum/experiment/ordnance/gaseous/halon
name = "Halon Gas Shells"
@@ -133,7 +133,7 @@
gain = list(10,30,60)
target_amount = list(15,55,250)
experiment_proper = TRUE
- required_gas = /datum/gas/halon
+ //required_gas = /datum/gas/halon
/datum/experiment/scanning/random/material/meat
name = "Biological Material Scanning Experiment"
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 204ed0792d2..c3706114a6e 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -223,7 +223,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
for(var/turf/FT in flood_turfs)
for(var/dir in GLOB.cardinals)
var/turf/T = get_step(FT, dir)
- if((T in flood_turfs) || !TURFS_CAN_SHARE(T, FT) || isspaceturf(T)) //If we've gottem already, or if they're not alright to spread with.
+ if((T in flood_turfs) /*|| !TURFS_CAN_SHARE(T, FT)*/ || isspaceturf(T)) //If we've gottem already, or if they're not alright to spread with.
continue
var/obj/effect/plasma_image_holder/pih = new(T)
var/image/new_plasma = image(image_icon, pih, image_state, FLY_LAYER)
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index 641f8eef4d0..fd969ee942d 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -661,7 +661,9 @@
break
if(firestarter && active)
hit_atom.fire_act()
- new /obj/effect/hotspot(get_turf(hit_atom))
+ //new /obj/effect/hotspot(get_turf(hit_atom))
+ var/turf/T = get_turf(hit_atom)
+ T.create_fire(1, 10)
..()
/obj/item/reagent_containers/food/drinks/bottle/molotov/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/griddle.dm b/code/modules/food_and_drinks/kitchen_machinery/griddle.dm
index 40421e50a35..d0cc81a683c 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/griddle.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/griddle.dm
@@ -137,7 +137,7 @@
var/obj/item/griddled_item = i
if(SEND_SIGNAL(griddled_item, COMSIG_ITEM_GRILLED, src, delta_time) & COMPONENT_HANDLED_GRILLING)
continue
- griddled_item.fire_act(1000) //Hot hot hot!
+ griddled_item.fire_act(null, 1000) //Hot hot hot!
if(prob(10))
visible_message(span_danger("[griddled_item] doesn't seem to be doing too great on the [src]!"))
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index a67c76511d2..1371008a8be 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -366,7 +366,8 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
- atmos_spawn_air("TEMP=1000")
+ var/turf/T = get_turf(src)
+ T.atmos_spawn_air(GAS_OXYGEN, 1, 1000)
// ----------------------------
diff --git a/code/modules/holodeck/area_copy.dm b/code/modules/holodeck/area_copy.dm
index 054f5d59abc..56232c8058f 100644
--- a/code/modules/holodeck/area_copy.dm
+++ b/code/modules/holodeck/area_copy.dm
@@ -135,13 +135,14 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
if(V == "air")
var/turf/open/O1 = B
var/turf/open/O2 = T
- O1.air.copy_from(O2.return_air())
+ O1.air.copyFrom(O2.return_air())
continue
B.vars[V] = T.vars[V]
toupdate += B
- if(toupdate.len)
+ /*if(toupdate.len)
for(var/turf/T1 in toupdate)
CALCULATE_ADJACENT_TURFS(T1, KILL_EXCITED)
+ */
return copiedobjs
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index 15f0f00e29f..78fce7e403d 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -51,7 +51,7 @@
/turf/open/floor/holofloor/plating/burnmix
name = "burn-mix floor"
- initial_gas_mix = BURNMIX_ATMOS
+ initial_gas = BURNMIX_ATMOS
/turf/open/floor/holofloor/grass
gender = PLURAL
@@ -171,7 +171,7 @@
tiled_dirt = FALSE
/turf/open/floor/holofloor/snow/cold
- initial_gas_mix = "nob=7500;TEMP=2.7"
+ temperature = 2.7
/turf/open/floor/holofloor/dark
icon_state = "darkfull"
diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm
index 7b523f31606..ffbeb476971 100644
--- a/code/modules/hydroponics/fermenting_barrel.dm
+++ b/code/modules/hydroponics/fermenting_barrel.dm
@@ -5,7 +5,7 @@
icon_state = "barrel"
density = TRUE
anchored = FALSE
- pressure_resistance = 2 * ONE_ATMOSPHERE
+ //pressure_resistance = 2 * ONE_ATMOSPHERE
max_integrity = 300
var/open = FALSE
var/can_open = TRUE
diff --git a/code/modules/hydroponics/unique_plant_genes.dm b/code/modules/hydroponics/unique_plant_genes.dm
index a53924cf2f3..c0f632cb62a 100644
--- a/code/modules/hydroponics/unique_plant_genes.dm
+++ b/code/modules/hydroponics/unique_plant_genes.dm
@@ -621,13 +621,12 @@
stop_gas()
return
- var/turf/open/tray_turf = get_turf(tray)
- if(abs(ONE_ATMOSPHERE - tray_turf.return_air().return_pressure()) > (seed.potency / 10 + 10)) // clouds can begin showing at around 50-60 potency in standard atmos
+ var/turf/tray_turf = get_turf(tray)
+ if(abs(ONE_ATMOSPHERE - tray_turf.return_air().returnPressure()) > (seed.potency / 10 + 10)) // clouds can begin showing at around 50-60 potency in standard atmos
return
var/datum/gas_mixture/stank = new
- ADD_GAS(/datum/gas/miasma, stank.gases)
- stank.gases[/datum/gas/miasma][MOLES] = (seed.yield + 6) * 3.5 * MIASMA_CORPSE_MOLES * delta_time // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses
+ stank.adjustGas(GAS_METHANE, (seed.yield + 6) * 3.5 * MIASMA_CORPSE_MOLES * delta_time) // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses
stank.temperature = T20C // without this the room would eventually freeze and miasma mining would be easier
tray_turf.assume_air(stank)
diff --git a/code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm b/code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm
index e396f872980..e56594df2d3 100644
--- a/code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm
+++ b/code/modules/mapfluff/ruins/icemoonruin_code/hotsprings.dm
@@ -12,8 +12,8 @@
/turf/open/water/cursed_spring
baseturfs = /turf/open/water/cursed_spring
- planetary_atmos = TRUE
- initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+
+ initial_gas = ICEMOON_DEFAULT_ATMOS
/turf/open/water/cursed_spring/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
index e0f2094e675..6ed7e46870e 100644
--- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
+++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
@@ -37,7 +37,7 @@
base_icon_state = "wasteland"
baseturfs = /turf/open/misc/asteroid/basalt/wasteland
digResult = /obj/item/stack/ore/glass/basalt
- initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ initial_gas = LAVALAND_DEFAULT_ATMOS
slowdown = 0.5
floor_variance = 30
diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm b/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm
index 1fd36f7a7d1..55c6bb5fc5d 100644
--- a/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm
+++ b/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm
@@ -45,7 +45,7 @@
new /obj/item/organ/tongue/tied(src)
new /obj/item/autosurgeon/organ/syndicate/commsagent(src)
new /obj/item/clothing/gloves/radio(src)
-
+/*
/obj/machinery/power/supermatter_crystal/shard/syndicate
name = "syndicate supermatter shard"
desc = "Your benefactors conveinently neglected to mention it's already assembled."
@@ -61,3 +61,4 @@
return
else
. = ..()
+*/
diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm
index 7574ddee5fd..aca8c8d2103 100644
--- a/code/modules/mapping/map_template.dm
+++ b/code/modules/mapping/map_template.dm
@@ -105,7 +105,7 @@
// NOTE, now that Initialize and LateInitialize run correctly, do we really
// need these two below?
SSmachines.setup_template_powernets(cables)
- SSair.setup_template_machinery(atmos_machines)
+ SSairmachines.setup_template_machinery(atmos_machines)
SSshuttle.setup_shuttles(ports)
//calculate all turfs inside the border
@@ -122,7 +122,7 @@
)
)
for(var/turf/affected_turf as anything in template_and_bordering_turfs)
- affected_turf.air_update_turf(TRUE, TRUE)
+ //affected_turf.air_update_turf(TRUE, TRUE)
affected_turf.levelupdate()
/datum/map_template/proc/load_new_z(secret = FALSE)
@@ -154,13 +154,7 @@
if(T.y+height > world.maxy)
return
- var/list/border = block(locate(max(T.x-1, 1), max(T.y-1, 1), T.z),
- locate(min(T.x+width+1, world.maxx), min(T.y+height+1, world.maxy), T.z))
- for(var/L in border)
- var/turf/turf_to_disable = L
- SSair.remove_from_active(turf_to_disable) //stop processing turfs along the border to prevent runtimes, we return it in initTemplateBounds()
- turf_to_disable.atmos_adjacent_turfs?.Cut()
-
+ SSzas.can_fire = FALSE
// Accept cached maps, but don't save them automatically - we don't want
// ruins clogging up memory for the whole round.
var/datum/parsed_map/parsed = cached_map || new(file(mappath))
@@ -187,6 +181,7 @@
generate_ceiling(affected_turfs)
log_game("[name] loaded at [T.x],[T.y],[T.z]")
+ SSzas.can_fire = TRUE
return bounds
/datum/map_template/proc/generate_ceiling(affected_turfs)
diff --git a/code/modules/mapping/space_management/traits.dm b/code/modules/mapping/space_management/traits.dm
index cd53a3632da..db9a517139b 100644
--- a/code/modules/mapping/space_management/traits.dm
+++ b/code/modules/mapping/space_management/traits.dm
@@ -5,14 +5,14 @@
if (z_list)
if (z > z_list.len)
stack_trace("Unmanaged z-level [z]! maxz = [world.maxz], z_list.len = [z_list.len]")
- return list()
+ return FALSE
var/datum/space_level/S = get_level(z)
return S.traits[trait]
else
var/list/default = DEFAULT_MAP_TRAITS
if (z > default.len)
stack_trace("Unmanaged z-level [z]! maxz = [world.maxz], default.len = [default.len]")
- return list()
+ return FALSE
return default[z][DL_TRAITS][trait]
/// Check if levels[z] has any of the specified traits
diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm
index a31ea2446f5..738bdf5526c 100644
--- a/code/modules/mining/aux_base.dm
+++ b/code/modules/mining/aux_base.dm
@@ -336,7 +336,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/auxiliary_base, 32)
icon = 'icons/obj/objects.dmi'
icon_state = "miningbeacon"
var/obj/docking_port/stationary/Mport //Linked docking port for the mining shuttle
- pressure_resistance = 200 //So it does not get blown into lava.
+ //pressure_resistance = 200 //So it does not get blown into lava.
var/anti_spam_cd = 0 //The linking process might be a bit intensive, so this here to prevent over use.
var/console_range = 15 //Wifi range of the beacon to find the aux base console
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index 0baefc9041b..510e942ac7a 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -233,7 +233,7 @@
density = TRUE
var/buildstacktype = /obj/item/stack/sheet/iron
var/buildstackamount = 5
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
/obj/structure/fans/deconstruct()
if(!(flags_1 & NODECONSTRUCT_1))
@@ -262,10 +262,10 @@
/obj/structure/fans/Initialize(mapload)
. = ..()
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
/obj/structure/fans/Destroy()
- air_update_turf(TRUE, FALSE)
+ //air_update_turf(TRUE, FALSE)
. = ..()
//Invisible, indestructible fans
/obj/structure/fans/tiny/invisible
@@ -290,7 +290,7 @@
/obj/item/ship_in_a_bottle,
/obj/item/gun/energy/pulse,
/obj/item/book/granter/martial/carp,
- /obj/item/melee/supermatter_sword,
+ //obj/item/melee/supermatter_sword,
/obj/item/shield/changeling,
/obj/item/lava_staff,
/obj/item/energy_katana,
diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm
index 67cef378df0..b18f588ca86 100644
--- a/code/modules/mining/satchel_ore_boxdm.dm
+++ b/code/modules/mining/satchel_ore_boxdm.dm
@@ -7,7 +7,7 @@
name = "ore box"
desc = "A heavy wooden box, which can be filled with a lot of ores."
density = TRUE
- pressure_resistance = 5*ONE_ATMOSPHERE
+ //pressure_resistance = 5*ONE_ATMOSPHERE
/obj/structure/ore_box/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/stack/ore))
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index 2d1ea422c7a..c68f68b2b2e 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -10,13 +10,15 @@
invisibility = INVISIBILITY_ABSTRACT // No one can see us
sight = SEE_SELF
move_on_shuttle = FALSE
+ simulated = FALSE
/mob/camera/Initialize(mapload)
. = ..()
SSpoints_of_interest.make_point_of_interest(src)
-
+/*
/mob/camera/experience_pressure_difference()
return
+*/
/mob/camera/canUseStorage()
return FALSE
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 5c7ff4b78de..0120b87134e 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -22,6 +22,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
light_power = 2
light_on = FALSE
shift_to_open_context_menu = FALSE
+ simulated = FALSE
var/can_reenter_corpse
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index 67b89bd6b4c..64917ada9af 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -66,7 +66,7 @@ GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list(
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
- if(breath && breath.total_moles() > 0 && !sneaking)
+ if(breath && breath.get_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, FALSE, -5)
..()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
index 30f8dbaebf2..b2b031b542b 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
@@ -10,7 +10,7 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //above most mobs, but below speechbubbles
plane = GAME_PLANE_UPPER_FOV_HIDDEN
- pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
+ //pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
butcher_results = list(/obj/item/food/meat/slab/xeno = 20, /obj/item/stack/sheet/animalhide/xeno = 3)
var/alt_inhands_file = 'icons/mob/alienqueen.dmi'
diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm
index 19e6a17ac30..f3c267e7102 100644
--- a/code/modules/mob/living/carbon/alien/life.dm
+++ b/code/modules/mob/living/carbon/alien/life.dm
@@ -6,7 +6,7 @@
if(status_flags & GODMODE)
return
- if(!breath || (breath.total_moles() == 0))
+ if(!breath || (breath.get_moles() == 0))
//Aliens breathe in vaccuum
return 0
@@ -15,29 +15,23 @@
var/plasma_used = 0
var/plas_detect_threshold = 0.02
- var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
- var/list/breath_gases = breath.gases
-
- breath.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
+ var/breath_pressure = (breath.get_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
//Partial pressure of the plasma in our breath
- var/Plasma_pp = (breath_gases[/datum/gas/plasma][MOLES]/breath.total_moles())*breath_pressure
+ var/Plasma_pp = (breath.getGroupGas(GAS_PLASMA)/breath.get_moles())*breath_pressure
if(Plasma_pp > plas_detect_threshold) // Detect plasma in air
- adjustPlasma(breath_gases[/datum/gas/plasma][MOLES]*250)
+ adjustPlasma(breath.getGroupGas(GAS_PLASMA)*250)
throw_alert(ALERT_XENO_PLASMA, /atom/movable/screen/alert/alien_plas)
- plasma_used = breath_gases[/datum/gas/plasma][MOLES]
+ plasma_used = breath.getGroupGas(GAS_PLASMA)
else
clear_alert(ALERT_XENO_PLASMA)
//Breathe in plasma and out oxygen
- breath_gases[/datum/gas/plasma][MOLES] -= plasma_used
- breath_gases[/datum/gas/oxygen][MOLES] += plasma_used
-
- breath.garbage_collect()
-
+ breath.adjustGas(GAS_PLASMA, -plasma_used)
+ breath.adjustGas(GAS_OXYGEN, plasma_used)
//BREATH TEMPERATURE
handle_breath_temperature(breath)
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index cae2ce811d0..e8ae7cf04cb 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -40,7 +40,6 @@
COMSIG_ATOM_ENTERED = .proc/on_entered,
)
AddElement(/datum/element/connect_loc, loc_connections)
- AddElement(/datum/element/atmos_sensitive, mapload)
/obj/item/clothing/mask/facehugger/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
..()
@@ -74,11 +73,9 @@
if (sterile)
. += span_boldannounce("It looks like the proboscis has been removed.")
-/obj/item/clothing/mask/facehugger/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature > 300)
-
/obj/item/clothing/mask/facehugger/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- Die()
+ if(exposed_temperature > 300)
+ Die()
/obj/item/clothing/mask/facehugger/equipped(mob/M)
. = ..()
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 85cb222c74b..eda8332c11b 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -1,7 +1,7 @@
/mob/living/carbon
blood_volume = BLOOD_VOLUME_NORMAL
gender = MALE
- pressure_resistance = 15
+ //pressure_resistance = 15
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,GLAND_HUD)
has_limbs = TRUE
held_items = list(null, null)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 04ce6c1e317..ff5e986c64a 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -82,7 +82,7 @@
else
. += ""
. += "Internal Atmosphere Info: [internal.name]"
- . += "Tank Pressure: [internal_air.return_pressure()]"
+ . += "Tank Pressure: [internal_air.returnPressure()]"
. += "Distribution Pressure: [internal.distribute_pressure]"
if(istype(wear_suit, /obj/item/clothing/suit/space))
var/obj/item/clothing/suit/space/S = wear_suit
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 4834b7f2a44..0e3799fcfe1 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -7,7 +7,7 @@
appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD,GLAND_HUD,SENTIENT_DISEASE_HUD,FAN_HUD)
hud_type = /datum/hud/human
- pressure_resistance = 25
+ //pressure_resistance = 25
can_buckle = TRUE
buckle_lying = 0
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 6f2e1281e8a..8711c7cfe74 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -96,13 +96,13 @@
var/datum/species/S = dna.species
- if(S.breathid == "o2")
+ if(S.breathid == GAS_OXYGEN)
throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
- else if(S.breathid == "plas")
+ else if(S.breathid == GAS_PLASMA)
throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas)
- else if(S.breathid == "co2")
+ else if(S.breathid == GAS_CO2)
throw_alert(ALERT_NOT_ENOUGH_CO2, /atom/movable/screen/alert/not_enough_co2)
- else if(S.breathid == "n2")
+ else if(S.breathid == GAS_NITROGEN)
throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro)
return FALSE
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 190a9742ba1..0e37e1635c6 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -185,7 +185,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/sound/miss_sound = 'sound/weapons/punchmiss.ogg'
///What gas does this species breathe? Used by suffocation screen alerts, most of actual gas breathing is handled by mutantlungs. See [life.dm][code/modules/mob/living/carbon/human/life.dm]
- var/breathid = "o2"
+ var/breathid = GAS_OXYGEN
///What anim to use for dusting
var/dust_anim = "dust-h"
@@ -1691,7 +1691,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
/// Handle the air pressure of the environment
/datum/species/proc/handle_environment_pressure(mob/living/carbon/human/H, datum/gas_mixture/environment, delta_time, times_fired)
- var/pressure = environment.return_pressure()
+ var/pressure = environment.returnPressure()
var/adjusted_pressure = H.calculate_affecting_pressure(pressure)
// Set alerts and apply damage based on the amount of pressure
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 58b72066d9e..f0e6b8052dc 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -26,7 +26,7 @@
heatmod = 1.5
brutemod = 1.5
payday_modifier = 0.75
- breathid = "plas"
+ breathid = GAS_PLASMA
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
disliked_food = FRUIT | CLOTH
liked_food = VEGETABLES
@@ -73,12 +73,12 @@
return
if(!atmos_sealed && (!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman) || !istype(H.gloves, /obj/item/clothing/gloves)))
var/datum/gas_mixture/environment = H.loc.return_air()
- if(environment?.total_moles())
- if(environment.gases[/datum/gas/hypernoblium] && (environment.gases[/datum/gas/hypernoblium][MOLES]) >= 5)
+ if(environment?.get_moles())
+ /*if(environment.gases[/datum/gas/hypernoblium] && (environment.gases[/datum/gas/hypernoblium][MOLES]) >= 5)
if(H.on_fire && H.fire_stacks > 0)
- H.adjust_fire_stacks(-10 * delta_time)
- else if(!HAS_TRAIT(H, TRAIT_NOFIRE) && !HAS_TRAIT(H, TRAIT_NOSELFIGNITION))
- if(environment.gases[/datum/gas/oxygen] && (environment.gases[/datum/gas/oxygen][MOLES]) >= 1) //Same threshhold that extinguishes fire
+ H.adjust_fire_stacks(-10 * delta_time)*/
+ if(!HAS_TRAIT(H, TRAIT_NOFIRE) && !HAS_TRAIT(H, TRAIT_NOSELFIGNITION))
+ if(environment.hasGas(GAS_OXYGEN, 1)) //Same threshhold that extinguishes fire
H.adjust_fire_stacks(0.25 * delta_time)
if(!H.on_fire && H.fire_stacks > 0)
H.visible_message(span_danger("[H]'s body reacts with the atmosphere and bursts into flames!"),span_userdanger("Your body reacts with the atmosphere and bursts into flame!"))
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 1dec6074d7e..9ca2e5c371f 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -108,7 +108,7 @@
else if(isturf(loc)) //Breathe from loc as turf
var/breath_moles = 0
if(environment)
- breath_moles = environment.total_moles()*BREATH_PERCENTAGE
+ breath_moles = environment.get_moles()*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
else //Breathe from loc as obj again
@@ -116,9 +116,23 @@
var/obj/loc_as_obj = loc
loc_as_obj.handle_internal_lifeform(src,0)
- check_breath(breath)
+ // Pass reagents from the gas into our body.
+ // Presumably if you breathe it you have a specialized metabolism for it, so we drop/ignore breath_type. Also avoids
+ // humans processing thousands of units of oxygen over the course of a round for the sole purpose of poisoning vox.
+ if(lungs && !isnull(breath))
+ var/breath_type = dna?.species?.breathid
+ for(var/gasname in breath.gas - breath_type)
+ var/breathed_product = xgm_gas_data.breathed_product[gasname]
+ if(breathed_product)
+ var/reagent_amount = breath.gas[gasname] * REAGENT_GAS_EXCHANGE_FACTOR
+ // Little bit of sanity so we aren't trying to add 0.0000000001 units of CO2, and so we don't end up with 99999 units of CO2.
+ if(reagent_amount >= 0.05)
+ reagents.add_reagent(breathed_product, reagent_amount)
+ breath.adjustGas(gasname, -breath.gas[gasname], update = 0) //update after
- if(breath)
+ check_breath(breath)
+ if(breath?.total_moles)
+ AIR_UPDATE_VALUES(breath)
loc.assume_air(breath)
/mob/living/carbon/proc/has_smoke_protection()
@@ -141,7 +155,7 @@
adjustOxyLoss(2)
//CRIT
- if(!breath || (breath.total_moles() == 0) || !lungs)
+ if(!breath || (breath.total_moles == 0) || !lungs)
if(reagents.has_reagent(/datum/reagent/medicine/epinephrine, needs_metabolizing = TRUE) && lungs)
return FALSE
adjustOxyLoss(1)
@@ -150,19 +164,18 @@
throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
return FALSE
+ var/list/breath_gases = breath.gas
var/safe_oxy_min = 16
var/safe_co2_max = 10
var/safe_plas_max = 0.05
var/SA_para_min = 1
var/SA_sleep_min = 5
var/oxygen_used = 0
- var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
+ var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
- var/list/breath_gases = breath.gases
- breath.assert_gases(/datum/gas/oxygen, /datum/gas/plasma, /datum/gas/carbon_dioxide, /datum/gas/nitrous_oxide, /datum/gas/bz)
- var/O2_partialpressure = (breath_gases[/datum/gas/oxygen][MOLES]/breath.total_moles())*breath_pressure
- var/Plasma_partialpressure = (breath_gases[/datum/gas/plasma][MOLES]/breath.total_moles())*breath_pressure
- var/CO2_partialpressure = (breath_gases[/datum/gas/carbon_dioxide][MOLES]/breath.total_moles())*breath_pressure
+ var/O2_partialpressure = (breath_gases[GAS_OXYGEN]/breath.total_moles)*breath_pressure
+ var/Plasma_partialpressure = (breath_gases[GAS_PLASMA]/breath.total_moles)*breath_pressure
+ var/CO2_partialpressure = (breath_gases[GAS_CO2]/breath.total_moles)*breath_pressure
//OXYGEN
@@ -173,7 +186,7 @@
var/ratio = 1 - O2_partialpressure/safe_oxy_min
adjustOxyLoss(min(5*ratio, 3))
failed_last_breath = TRUE
- oxygen_used = breath_gases[/datum/gas/oxygen][MOLES]*ratio
+ oxygen_used = breath_gases[GAS_OXYGEN]*ratio
else
adjustOxyLoss(3)
failed_last_breath = TRUE
@@ -183,11 +196,11 @@
failed_last_breath = FALSE
if(health >= crit_threshold)
adjustOxyLoss(-5)
- oxygen_used = breath_gases[/datum/gas/oxygen][MOLES]
+ oxygen_used = breath_gases[GAS_OXYGEN]
clear_alert(ALERT_NOT_ENOUGH_OXYGEN)
- breath_gases[/datum/gas/oxygen][MOLES] -= oxygen_used
- breath_gases[/datum/gas/carbon_dioxide][MOLES] += oxygen_used
+ breath.adjustGas(GAS_OXYGEN, -oxygen_used, update = 0)
+ breath.adjustGas(GAS_CO2, oxygen_used, update = 0)
//CARBON DIOXIDE
if(CO2_partialpressure > safe_co2_max)
@@ -206,15 +219,15 @@
//PLASMA
if(Plasma_partialpressure > safe_plas_max)
- var/ratio = (breath_gases[/datum/gas/plasma][MOLES]/safe_plas_max) * 10
+ var/ratio = breath.gas[GAS_PLASMA]/safe_plas_max * 10
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas)
else
clear_alert(ALERT_TOO_MUCH_PLASMA)
//NITROUS OXIDE
- if(breath_gases[/datum/gas/nitrous_oxide])
- var/SA_partialpressure = (breath_gases[/datum/gas/nitrous_oxide][MOLES]/breath.total_moles())*breath_pressure
+ if(breath_gases[GAS_N2O])
+ var/SA_partialpressure = (breath_gases[GAS_N2O]/breath.total_moles)*breath_pressure
if(SA_partialpressure > SA_para_min)
throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o)
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria")
@@ -234,16 +247,18 @@
clear_alert(ALERT_TOO_MUCH_N2O)
//BZ (Facepunch port of their Agent B)
+ /*
if(breath_gases[/datum/gas/bz])
- var/bz_partialpressure = (breath_gases[/datum/gas/bz][MOLES]/breath.total_moles())*breath_pressure
+ var/bz_partialpressure = (breath_gases[/datum/gas/bz][MOLES]/breath.get_moles())*breath_pressure
if(bz_partialpressure > 1)
hallucination += 10
else if(bz_partialpressure > 0.01)
hallucination += 5
-
+ */
//NITRIUM
+ /*
if(breath_gases[/datum/gas/nitrium])
- var/nitrium_partialpressure = (breath_gases[/datum/gas/nitrium][MOLES]/breath.total_moles())*breath_pressure
+ var/nitrium_partialpressure = (breath_gases[/datum/gas/nitrium][MOLES]/breath.get_moles())*breath_pressure
if(nitrium_partialpressure > 0.5)
adjustFireLoss(nitrium_partialpressure * 0.15)
if(nitrium_partialpressure > 5)
@@ -251,12 +266,12 @@
//FREON
if(breath_gases[/datum/gas/freon])
- var/freon_partialpressure = (breath_gases[/datum/gas/freon][MOLES]/breath.total_moles())*breath_pressure
+ var/freon_partialpressure = (breath_gases[/datum/gas/freon][MOLES]/breath.get_moles())*breath_pressure
adjustFireLoss(freon_partialpressure * 0.25)
//MIASMA
if(breath_gases[/datum/gas/miasma])
- var/miasma_partialpressure = (breath_gases[/datum/gas/miasma][MOLES]/breath.total_moles())*breath_pressure
+ var/miasma_partialpressure = (breath_gases[/datum/gas/miasma][MOLES]/breath.get_moles())*breath_pressure
if(prob(1 * miasma_partialpressure))
var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(2,3)
@@ -295,7 +310,7 @@
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
breath.garbage_collect()
-
+ */
//BREATH TEMPERATURE
handle_breath_temperature(breath)
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
index fd7c347c20c..66163e1de99 100644
--- a/code/modules/mob/living/init_signals.dm
+++ b/code/modules/mob/living/init_signals.dm
@@ -30,6 +30,9 @@
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_RESTRAINED), .proc/on_restrained_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_RESTRAINED), .proc/on_restrained_trait_loss)
+ RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_EXPERIENCING_AIRFLOW), .proc/on_airflow_trait_gain)
+ RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_EXPERIENCING_AIRFLOW), .proc/on_airflow_trait_loss)
+
RegisterSignal(src, list(
SIGNAL_ADDTRAIT(TRAIT_CRITICAL_CONDITION),
SIGNAL_REMOVETRAIT(TRAIT_CRITICAL_CONDITION),
@@ -213,3 +216,15 @@
/mob/living/proc/on_skittish_trait_loss(datum/source)
SIGNAL_HANDLER
RemoveElement(/datum/element/skittish)
+
+/// Called when [TRAIT_EXPERIENCING_AIRFLOW] is added to the mob.
+/mob/living/proc/on_airflow_trait_gain(datum/source)
+ SIGNAL_HANDLER
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/atmos_pressure, TRUE, zas_settings.airflow_mob_slowdown)
+
+/// Called when [TRAIT_EXPERIENCING_AIRFLOW] is removed from the mob.
+/mob/living/proc/on_airflow_trait_loss(datum/source)
+ SIGNAL_HANDLER
+ remove_movespeed_modifier(/datum/movespeed_modifier/atmos_pressure, TRUE)
+ if(!resting)
+ get_up(TRUE)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index fcfd8585513..cad4424b77f 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -121,7 +121,7 @@
extinguish_mob()
return TRUE //mob was put out, on_fire = FALSE via extinguish_mob(), no need to update everything down the chain.
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
- if(!G.gases[/datum/gas/oxygen] || G.gases[/datum/gas/oxygen][MOLES] < 1)
+ if(G && (G.gas[GAS_OXYGEN] <= 1))
extinguish_mob() //If there's no oxygen in the tile we're on, put out the fire
return TRUE
var/turf/location = get_turf(src)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 5b627f6a734..efad7e212ba 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -957,7 +957,7 @@
return pick("ltrails_1", "ltrails_2")
else
return pick("trails_1", "trails_2")
-
+/*
/mob/living/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
playsound(src, 'sound/effects/space_wind.ogg', 50, TRUE)
if(buckled || mob_negates_gravity())
@@ -987,7 +987,7 @@
pressure_resistance_prob_delta -= 20
break
..(pressure_difference, direction, pressure_resistance_prob_delta)
-
+*/
/mob/living/can_resist()
if(next_move > world.time)
return FALSE
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 48b9fdf8ca0..d79923f707c 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -39,7 +39,7 @@
/mob/living/proc/get_ear_protection()
var/turf/current_turf = get_turf(src)
var/datum/gas_mixture/environment = current_turf.return_air()
- var/pressure = environment ? environment.return_pressure() : 0
+ var/pressure = environment ? environment.returnPressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE) //space is empty
return 1
return 0
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index ff69a1e1d81..a0e625946aa 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -3,7 +3,7 @@
sight = 0
see_in_dark = 2
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD)
- pressure_resistance = 10
+ //pressure_resistance = 10
hud_type = /datum/hud/living
diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm
index a2b6f06d765..a6a219116b3 100644
--- a/code/modules/mob/living/living_say.dm
+++ b/code/modules/mob/living/living_say.dm
@@ -263,7 +263,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
//No screams in space, unless you're next to someone.
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.return_air()
- var/pressure = (environment)? environment.return_pressure() : 0
+ var/pressure = (environment)? environment.returnPressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE && !HAS_TRAIT(H, TRAIT_SIGN_LANG))
message_range = 1
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index f21ebabf39e..f34469e17e6 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -496,7 +496,7 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
var/turf/T = get_turf(src)
if(!T)
return
- var/list/adjacent = T.get_atmos_adjacent_turfs(1)
+ var/list/adjacent = get_adjacent_open_turfs(T)
if(shuffle) //If we were on the same tile as another bot, let's randomize our choices so we dont both go the same way
adjacent = shuffle(adjacent)
shuffle = FALSE
diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm
index 9ffc4680868..081676809d2 100644
--- a/code/modules/mob/living/simple_animal/bot/firebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/firebot.dm
@@ -47,7 +47,6 @@
prev_access = access_card.access.Copy()
create_extinguisher()
- AddElement(/datum/element/atmos_sensitive, mapload)
/mob/living/simple_animal/bot/firebot/bot_reset()
create_extinguisher()
@@ -153,7 +152,7 @@
else if(isturf(target))
var/turf/open/T = target
- if(T.active_hotspot)
+ if(T.fire)
return TRUE
return FALSE
@@ -261,14 +260,15 @@
result = scan_target
return result
-
/mob/living/simple_animal/bot/firebot/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature > T0C + 200 || exposed_temperature < BODYTEMP_COLD_DAMAGE_LIMIT)
+ if(exposed_temperature > T0C + 200 || exposed_temperature < BODYTEMP_COLD_DAMAGE_LIMIT)
+ return TRUE
/mob/living/simple_animal/bot/firebot/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- if(COOLDOWN_FINISHED(src, foam_cooldown))
- new /obj/effect/particle_effect/foam/firefighting(loc)
- COOLDOWN_START(src, foam_cooldown, FOAM_INTERVAL)
+ if(exposed_temperature > T0C + 200 || exposed_temperature < BODYTEMP_COLD_DAMAGE_LIMIT)
+ if(COOLDOWN_FINISHED(src, foam_cooldown))
+ new /obj/effect/particle_effect/foam/firefighting(loc)
+ COOLDOWN_START(src, foam_cooldown, FOAM_INTERVAL)
/mob/living/simple_animal/bot/firebot/proc/spray_water(atom/target, mob/user)
if(stationary_mode)
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index cde799f703c..fd72786d6e3 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -27,7 +27,7 @@
maxbodytemp = INFINITY
healable = 0
faction = list("cult")
- pressure_resistance = 100
+ //pressure_resistance = 100
unique_name = 1
AIStatus = AI_OFF //normal constructs don't have AI
loot = list(/obj/item/ectoplasm)
diff --git a/code/modules/mob/living/simple_animal/heretic_monsters.dm b/code/modules/mob/living/simple_animal/heretic_monsters.dm
index af19683a97f..83fd0b936a7 100644
--- a/code/modules/mob/living/simple_animal/heretic_monsters.dm
+++ b/code/modules/mob/living/simple_animal/heretic_monsters.dm
@@ -26,7 +26,7 @@
maxbodytemp = INFINITY
healable = FALSE
movement_type = GROUND
- pressure_resistance = 100
+ //pressure_resistance = 100
del_on_death = TRUE
deathmessage = "implodes into itself."
loot = list(/obj/effect/gibspawner/human)
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index 839af83ffea..92605a8db3e 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -39,7 +39,7 @@
minbodytemp = 0
maxbodytemp = 1500
faction = list("carp")
- pressure_resistance = 200
+ //pressure_resistance = 200
gold_core_spawnable = HOSTILE_SPAWN
/// If the carp uses random coloring
var/random_color = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 51d2a3a4736..89059e8828a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -183,8 +183,9 @@
for(var/turf/T in turfs)
if(istype(T, /turf/closed))
break
- var/obj/effect/hotspot/drake_fire_hotspot = new /obj/effect/hotspot(T)
- if(frozen)
+
+ var/obj/effect/hotspot/drake_fire_hotspot = T.create_fire(1, 10)
+ if(frozen && drake_fire_hotspot)
drake_fire_hotspot.add_atom_colour(COLOR_BLUE_LIGHT, FIXED_COLOUR_PRIORITY)
T.hotspot_expose(DRAKE_FIRE_TEMP,DRAKE_FIRE_EXPOSURE,1)
for(var/mob/living/L in T.contents)
@@ -285,7 +286,7 @@
anchored = TRUE
opacity = FALSE
density = TRUE
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
duration = 82
color = COLOR_DARK_ORANGE
@@ -332,7 +333,8 @@
var/turf/closed/mineral/M = T
M.gets_drilled()
playsound(T, SFX_EXPLOSION, 80, TRUE)
- new /obj/effect/hotspot(T)
+ //new /obj/effect/hotspot(T)
+ T.create_fire(1, 10)
T.hotspot_expose(DRAKE_FIRE_TEMP, DRAKE_FIRE_EXPOSURE, 1)
for(var/mob/living/L in T.contents)
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
diff --git a/code/modules/mob/living/simple_animal/hostile/regalrat.dm b/code/modules/mob/living/simple_animal/hostile/regalrat.dm
index da55ced5181..819ddf41558 100644
--- a/code/modules/mob/living/simple_animal/hostile/regalrat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/regalrat.dm
@@ -116,9 +116,9 @@
/mob/living/simple_animal/hostile/regalrat/handle_environment(datum/gas_mixture/environment)
. = ..()
- if(stat == DEAD || !environment || !environment.gases[/datum/gas/miasma])
+ if(stat == DEAD || !environment || !environment.getGroupGas(GAS_METHANE))
return
- var/miasma_percentage = environment.gases[/datum/gas/miasma][MOLES] / environment.total_moles()
+ var/miasma_percentage = environment.gas[GAS_METHANE] / environment.get_moles()
if(miasma_percentage>=0.25)
heal_bodypart_damage(1)
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
index 902ef3058c8..9aa10b1523a 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
@@ -28,7 +28,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
- pressure_resistance = 300
+ //pressure_resistance = 300
gold_core_spawnable = NO_SPAWN //too spooky for science
light_system = MOVABLE_LIGHT
light_range = 1 // same glowing as visible player ghosts
diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
index c7d17ea8c37..9d890df0041 100644
--- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
@@ -66,7 +66,7 @@
minbodytemp = 0
maxbodytemp = 1500
faction = list("carp")
- pressure_resistance = 200
+ //pressure_resistance = 200
/// Current time since the the last rift was activated. If set to -1, does not increment.
var/riftTimer = 0
/// Maximum amount of time which can pass without a rift before Space Dragon despawns.
@@ -334,7 +334,8 @@
/mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T)
var/list/hit_list = list()
hit_list += src
- new /obj/effect/hotspot(T)
+ //new /obj/effect/hotspot(T)
+ T.create_fire(1, 10)
T.hotspot_expose(700,50,1)
for(var/mob/living/L in T.contents)
if(L in hit_list)
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index e982b5bfc38..47e70ea99b7 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -56,14 +56,14 @@
if(!is_tree || !isopenturf(loc))
return
var/turf/open/T = src.loc
- if(!T.air || !T.air.gases[/datum/gas/carbon_dioxide])
+ if(!T.air || !T.air.hasGas(GAS_CO2))
return
- var/co2 = T.air.gases[/datum/gas/carbon_dioxide][MOLES]
+ var/co2 = T.air.gas[GAS_CO2]
if(co2 > 0 && DT_PROB(13, delta_time))
var/amt = min(co2, 9)
- T.air.gases[/datum/gas/carbon_dioxide][MOLES] -= amt
- T.atmos_spawn_air("o2=[amt]")
+ T.air.adjustGas(GAS_CO2, -amt)
+ T.atmos_spawn_air(GAS_OXYGEN, amt)
/mob/living/simple_animal/hostile/tree/AttackingTarget()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index c0772d21050..cce729db3b8 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -7,6 +7,7 @@
gender = PLURAL //placeholder
living_flags = MOVES_ON_ITS_OWN
status_flags = CANPUSH
+ simulated = FALSE
var/icon_living = ""
///Icon when the animal is dead. Don't use animated icons for this.
@@ -317,15 +318,12 @@
if(isturf(loc) && isopenturf(loc))
var/turf/open/ST = loc
if(ST.air)
- var/ST_gases = ST.air.gases
- ST.air.assert_gases(arglist(GLOB.hardcoded_gases))
+ var/datum/gas_mixture/muhair = ST.return_air().getGases()
- var/plas = ST_gases[/datum/gas/plasma][MOLES]
- var/oxy = ST_gases[/datum/gas/oxygen][MOLES]
- var/n2 = ST_gases[/datum/gas/nitrogen][MOLES]
- var/co2 = ST_gases[/datum/gas/carbon_dioxide][MOLES]
-
- ST.air.garbage_collect()
+ var/plas = muhair[GAS_PLASMA]
+ var/oxy = muhair[GAS_OXYGEN]
+ var/n2 = muhair[GAS_NITROGEN]
+ var/co2 = muhair[GAS_CO2]
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
. = FALSE
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index 5afb8ac74a0..fa762eae317 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -141,11 +141,11 @@
adjustBruteLoss(round(sqrt(bodytemperature)) * delta_time)
else
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, SLIME_COLD)
-
+ /*
if(stat != DEAD)
var/bz_percentage =0
if(environment.gases[/datum/gas/bz])
- bz_percentage = environment.gases[/datum/gas/bz][MOLES] / environment.total_moles()
+ bz_percentage = environment.gases[/datum/gas/bz][MOLES] / environment.get_moles()
var/stasis = (bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) || force_stasis
switch(stat)
@@ -161,7 +161,7 @@
to_chat(src, span_notice("You wake up from the stasis."))
set_stat(CONSCIOUS)
regenerate_icons()
-
+ */
updatehealth()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index f8fd20f372e..3c4dd839d26 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -126,10 +126,9 @@
var/t = "[span_notice("Coordinates: [x],[y] ")]\n"
t += "[span_danger("Temperature: [environment.temperature] ")]\n"
- for(var/id in environment.gases)
- var/gas = environment.gases[id]
- if(gas[MOLES])
- t+="[span_notice("[gas[GAS_META][META_GAS_NAME]]: [gas[MOLES]] ")]\n"
+ for(var/id in environment.gas)
+ if(!environment.getGroupGas(id))
+ t+="[span_notice("[xgm_gas_data.name[environment.gas]]: [environment.getGroupGas(id)] ")]\n"
to_chat(usr, t)
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index dfac35d7e58..a9264753690 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -13,11 +13,13 @@
plane = GAME_PLANE_FOV_HIDDEN
animate_movement = SLIDE_STEPS
hud_possible = list(ANTAG_HUD)
- pressure_resistance = 8
+ //pressure_resistance = 8
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
throwforce = 10
blocks_emissive = EMISSIVE_BLOCK_GENERIC
pass_flags_self = PASSMOB
+ flags_2 = NO_TEMP_CHANGE_2 //We're going to assume mobs handle their own temperature on life
+
/// The current client inhabiting this mob. Managed by login/logout
/// This exists so we can do cleanup in logout for occasions where a client was transfere rather then destroyed
/// We need to do this because the mob on logout never actually has a reference to client
diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm
index 3b9f075b585..a851581f33e 100644
--- a/code/modules/mod/modules/modules_maint.dm
+++ b/code/modules/mod/modules/modules_maint.dm
@@ -315,7 +315,7 @@
var/turf/open/openspace/turf_above = get_step_multiz(mod.wearer, UP)
if(current_turf && istype(turf_above))
current_turf.zFall(mod.wearer)
- else if(!turf_above && istype(current_turf) && current_turf.planetary_atmos) //nothing holding you down
+ else if(!turf_above && istype(current_turf) && !current_turf.simulated) //nothing holding you down
INVOKE_ASYNC(src, .proc/fly_away)
else if(!(step_count % 2))
playsound(current_turf, 'sound/items/modsuit/atrocinator_step.ogg', 50)
diff --git a/code/modules/mod/modules/modules_timeline.dm b/code/modules/mod/modules/modules_timeline.dm
index b52f2dfbfb0..801c9cbee37 100644
--- a/code/modules/mod/modules/modules_timeline.dm
+++ b/code/modules/mod/modules/modules_timeline.dm
@@ -412,9 +412,8 @@
/obj/structure/chrono_field/return_air() //we always have nominal air and temperature
var/datum/gas_mixture/fresh_air = new
- fresh_air.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
- fresh_air.gases[/datum/gas/oxygen][MOLES] = MOLES_O2STANDARD
- fresh_air.gases[/datum/gas/nitrogen][MOLES] = MOLES_N2STANDARD
+ fresh_air.gas[GAS_OXYGEN] = MOLES_O2STANDARD
+ fresh_air.gas[GAS_NITROGEN] = MOLES_N2STANDARD
fresh_air.temperature = T20C
return fresh_air
diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm
index fe09b4b971e..50c1e27aee5 100644
--- a/code/modules/modular_computers/file_system/programs/atmosscan.dm
+++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm
@@ -16,7 +16,7 @@
to_chat(user, span_warning("\The [computer] flashes an error: \"hardware\\sensorpackage\\startup.bin -- file not found\"."))
/datum/computer_file/program/atmosscan/ui_static_data(mob/user)
- return return_atmos_handbooks()
+ return
/datum/computer_file/program/atmosscan/ui_data(mob/user)
var/list/data = get_header_data()
@@ -27,7 +27,7 @@
if(!air_sensor)
data["gasmixes"] = list(gas_mixture_parser(null, "No Sensors Detected!"))
return data
-
+
data["gasmixes"] = list(gas_mixture_parser(air, "Sensor Reading")) //Null air wont cause errors, don't worry.
return data
diff --git a/code/modules/modular_computers/hardware/job_disk.dm b/code/modules/modular_computers/hardware/job_disk.dm
index 529fdab68d2..528ed67a02a 100644
--- a/code/modules/modular_computers/hardware/job_disk.dm
+++ b/code/modules/modular_computers/hardware/job_disk.dm
@@ -65,8 +65,8 @@
if(disk_flags & DISK_BUDGET)
progs_to_store += new /datum/computer_file/program/budgetorders(src)
- if(disk_flags & DISK_STATUS)
- progs_to_store += new /datum/computer_file/program/status(src)
+ /*if(disk_flags & DISK_STATUS)
+ progs_to_store += new /datum/computer_file/program/status(src)*/
if(disk_flags & DISK_SCI)
progs_to_store += new /datum/computer_file/program/science(src)
diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm
index 1c373b4de40..066b0235777 100644
--- a/code/modules/movespeed/modifiers/mobs.dm
+++ b/code/modules/movespeed/modifiers/mobs.dm
@@ -129,3 +129,8 @@
/datum/movespeed_modifier/auto_wash
multiplicative_slowdown = 3
+
+/datum/movespeed_modifier/atmos_pressure
+ multiplicative_slowdown = 3
+ id = MOVESPEED_ID_MOB_ATMOS_AFFLICTION
+ variable = TRUE
diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index ef22e798c6a..944f8201c2f 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "folder"
w_class = WEIGHT_CLASS_SMALL
- pressure_resistance = 2
+ //pressure_resistance = 2
resistance_flags = FLAMMABLE
/// The background color for tgui in hex (with a `#`)
var/bg_color = "#7f7f7f"
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 848653c5687..8c1fd29a1ed 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -26,7 +26,7 @@
w_class = WEIGHT_CLASS_TINY
throw_range = 1
throw_speed = 1
- pressure_resistance = 0
+ //pressure_resistance = 0
slot_flags = ITEM_SLOT_HEAD
body_parts_covered = HEAD
resistance_flags = FLAMMABLE
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index 720c4acd024..aa71b67c941 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -12,7 +12,7 @@
w_class = WEIGHT_CLASS_NORMAL
throw_speed = 3
throw_range = 7
- pressure_resistance = 8
+ //pressure_resistance = 8
var/papertype = /obj/item/paper
var/total_paper = 30
var/list/papers = list()
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 2d9d207ac4f..47f078e3c94 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -23,7 +23,7 @@
throw_speed = 3
throw_range = 7
custom_materials = list(/datum/material/iron=10)
- pressure_resistance = 2
+ //pressure_resistance = 2
grind_results = list(/datum/reagent/iron = 2, /datum/reagent/iodine = 1)
var/colour = "#000000" //what colour the ink is!
var/degrees = 0
@@ -309,7 +309,7 @@
force = 3
w_class = WEIGHT_CLASS_TINY
custom_materials = list(/datum/material/iron=10, /datum/material/diamond=100, /datum/material/titanium = 10)
- pressure_resistance = 2
+ //pressure_resistance = 2
grind_results = list(/datum/reagent/iron = 2, /datum/reagent/iodine = 1)
tool_behaviour = TOOL_MINING //For the classic "digging out of prison with a spoon but you're in space so this analogy doesn't work" situation.
toolspeed = 10 //You will never willingly choose to use one of these over a shovel.
diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm
index 2d61ca83c19..561aa52bb3d 100644
--- a/code/modules/paperwork/stamps.dm
+++ b/code/modules/paperwork/stamps.dm
@@ -9,7 +9,7 @@
throw_speed = 3
throw_range = 7
custom_materials = list(/datum/material/iron=60)
- pressure_resistance = 2
+ //pressure_resistance = 2
attack_verb_continuous = list("stamps")
attack_verb_simple = list("stamp")
diff --git a/code/modules/power/apc/apc_main.dm b/code/modules/power/apc/apc_main.dm
index 4c59bfb4ab2..914e03a4008 100644
--- a/code/modules/power/apc/apc_main.dm
+++ b/code/modules/power/apc/apc_main.dm
@@ -144,7 +144,6 @@
/obj/machinery/power/apc/Initialize(mapload)
. = ..()
- AddElement(/datum/element/atmos_sensitive, mapload)
alarm_manager = new(src)
if(!mapload)
@@ -558,12 +557,12 @@
breaked_light.on = TRUE
breaked_light.break_light_tube()
stoplag()
-
/obj/machinery/power/apc/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return (exposed_temperature > 2000)
+ return (exposed_temperature > 2000) ? TRUE : FALSE
/obj/machinery/power/apc/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- take_damage(min(exposed_temperature/100, 10), BURN)
+ if(exposed_temperature > 2000)
+ take_damage(min(exposed_temperature/100, 10), BURN)
/obj/machinery/power/apc/proc/report()
return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_total]) : [cell? cell.percent() : "N/C"] ([charging])"
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
index e3e84e04511..8cca877253d 100644
--- a/code/modules/power/generator.dm
+++ b/code/modules/power/generator.dm
@@ -20,12 +20,12 @@
AddComponent(/datum/component/simple_rotation)
find_circs()
connect_to_network()
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
update_appearance()
/obj/machinery/power/generator/Destroy()
kill_circs()
- SSair.stop_processing_machine(src)
+ SSairmachines.stop_processing_machine(src)
return ..()
/obj/machinery/power/generator/update_overlays()
@@ -53,8 +53,8 @@
if(cold_air && hot_air)
- var/cold_air_heat_capacity = cold_air.heat_capacity()
- var/hot_air_heat_capacity = hot_air.heat_capacity()
+ var/cold_air_heat_capacity = cold_air.getHeatCapacity()
+ var/hot_air_heat_capacity = hot_air.getHeatCapacity()
var/delta_temperature = hot_air.temperature - cold_air.temperature
@@ -116,11 +116,11 @@
t += "Cold loop "
t += "Temperature Inlet: [round(cold_circ_air2.temperature, 0.1)] K / Outlet: [round(cold_circ_air1.temperature, 0.1)] K "
- t += "Pressure Inlet: [round(cold_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(cold_circ_air1.return_pressure(), 0.1)] kPa "
+ t += "Pressure Inlet: [round(cold_circ_air2.returnPressure(), 0.1)] kPa / Outlet: [round(cold_circ_air1.returnPressure(), 0.1)] kPa "
t += "Hot loop "
t += "Temperature Inlet: [round(hot_circ_air2.temperature, 0.1)] K / Outlet: [round(hot_circ_air1.temperature, 0.1)] K "
- t += "Pressure Inlet: [round(hot_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(hot_circ_air1.return_pressure(), 0.1)] kPa "
+ t += "Pressure Inlet: [round(hot_circ_air2.returnPressure(), 0.1)] kPa / Outlet: [round(hot_circ_air1.returnPressure(), 0.1)] kPa "
t += ""
else if(!hot_circ && cold_circ)
diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm
index 8d67f45b9ec..64939dcc9b1 100644
--- a/code/modules/power/lighting/light.dm
+++ b/code/modules/power/lighting/light.dm
@@ -84,7 +84,6 @@
cell = new/obj/item/stock_parts/cell/emergency_light(src)
RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, .proc/on_light_eater)
- AddElement(/datum/element/atmos_sensitive, mapload)
return INITIALIZE_HINT_LATELOAD
/obj/machinery/light/LateInitialize()
@@ -600,11 +599,6 @@
var/area/local_area = get_area(src)
set_on(local_area.lightswitch && local_area.power_light)
-// called when heated
-
-/obj/machinery/light/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > 673
-
/obj/machinery/light/atmos_expose(datum/gas_mixture/air, exposed_temperature)
if(prob(max(0, exposed_temperature - 673))) //0% at <400C, 100% at >500C
break_light_tube()
diff --git a/code/modules/power/lighting/light_items.dm b/code/modules/power/lighting/light_items.dm
index c9a39ba40fc..58856a46ba9 100644
--- a/code/modules/power/lighting/light_items.dm
+++ b/code/modules/power/lighting/light_items.dm
@@ -135,5 +135,6 @@
force = 5
playsound(src.loc, 'sound/effects/glasshit.ogg', 75, TRUE)
if(rigged)
- atmos_spawn_air("plasma=5") //5u of plasma are required to rig a light bulb/tube
+ var/turf/T = get_turf(src)
+ T.atmos_spawn_air(GAS_PLASMA, 5) //5u of plasma are required to rig a light bulb/tube
update()
diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm
index f2772304f23..64f1527b1aa 100644
--- a/code/modules/power/rtg.dm
+++ b/code/modules/power/rtg.dm
@@ -107,6 +107,16 @@
SHOULD_CALL_PARENT(FALSE)
return
+/obj/machinery/power/rtg/debug/station
+ name = "Debug RTG"
+ power_gen = 400000
+
+/obj/machinery/power/rtg/debug/station/Initialize(mapload)
+ . = ..()
+ var/joke = pick("Singularity", "Supermatter Shard", "Tesla Coil")
+ name = "Totally a [joke]."
+ desc = "Yup. That's a [joke]."
+
/obj/machinery/power/rtg/lavaland
name = "Lava powered RTG"
desc = "This device only works when exposed to the toxic fumes of Lavaland"
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index fb9abb17a68..a0a004e1ad6 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -11,7 +11,7 @@
use_power = NO_POWER_USE
interaction_flags_atom = NONE
interaction_flags_machine = NONE
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
light_range = 4
layer = ABOVE_OBJ_LAYER
///First of the generators producing the containment field
@@ -21,7 +21,7 @@
/obj/machinery/field/containment/Initialize(mapload)
. = ..()
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
RegisterSignal(src, COMSIG_ATOM_SINGULARITY_TRY_MOVE, .proc/block_singularity)
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = .proc/on_entered,
@@ -35,8 +35,8 @@
if(field_gen_2)
field_gen_2.fields -= src
field_gen_2 = null
- can_atmos_pass = ATMOS_PASS_YES
- air_update_turf(TRUE, FALSE)
+ can_atmos_pass = CANPASS_ALWAYS
+ //air_update_turf(TRUE, FALSE)
return ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm
index b37775f6610..7e3a4b06481 100644
--- a/code/modules/power/singularity/field_generator.dm
+++ b/code/modules/power/singularity/field_generator.dm
@@ -32,7 +32,7 @@ no power level overlay is currently in the overlays list.
density = TRUE
use_power = NO_POWER_USE
max_integrity = 500
- can_atmos_pass = ATMOS_PASS_YES
+ can_atmos_pass = CANPASS_ALWAYS
//100% immune to lasers and energy projectiles since it absorbs their energy.
armor = list(MELEE = 25, BULLET = 10, LASER = 100, ENERGY = 100, BOMB = 0, BIO = 0, FIRE = 50, ACID = 70)
///Amount of energy stored, used for visual overlays (over 9000?)
@@ -199,8 +199,8 @@ no power level overlay is currently in the overlays list.
/obj/machinery/field/generator/proc/turn_off()
active = FG_OFFLINE
- can_atmos_pass = ATMOS_PASS_YES
- air_update_turf(TRUE, FALSE)
+ can_atmos_pass = CANPASS_ALWAYS
+ //air_update_turf(TRUE, FALSE)
INVOKE_ASYNC(src, .proc/cleanup)
addtimer(CALLBACK(src, .proc/cool_down), 5 SECONDS)
@@ -275,8 +275,8 @@ no power level overlay is currently in the overlays list.
turn_off()
return
move_resist = INFINITY
- can_atmos_pass = ATMOS_PASS_NO
- air_update_turf(TRUE, TRUE)
+ can_atmos_pass = CANPASS_NEVER
+ //air_update_turf(TRUE, TRUE)
addtimer(CALLBACK(src, .proc/setup_field, 1), 1)
addtimer(CALLBACK(src, .proc/setup_field, 2), 2)
addtimer(CALLBACK(src, .proc/setup_field, 4), 3)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 5636cac5203..76d358296e4 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -290,11 +290,12 @@
/obj/singularity/proc/consume(atom/thing)
var/gain = thing.singularity_act(current_size, src)
energy += gain
- if(istype(thing, /obj/machinery/power/supermatter_crystal) && !consumed_supermatter)
+ /*if(istype(thing, /obj/machinery/power/supermatter_crystal) && !consumed_supermatter)
desc = "[initial(desc)] It glows fiercely with inner fire."
name = "supermatter-charged [initial(name)]"
consumed_supermatter = TRUE
set_light(10)
+ */
/obj/singularity/proc/check_cardinals_range(steps, retry_with_move = FALSE)
. = length(GLOB.cardinals) //Should be 4.
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index dffba8c22a6..cbf48d67cf8 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -15,7 +15,7 @@
#define SMES_INPUT_ATTEMPT 9
/obj/machinery/power/smes
- name = "power storage unit"
+ name = "\improper SMES unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
icon_state = "smes"
density = TRUE
@@ -408,7 +408,7 @@
log_smes()
/obj/machinery/power/smes/engineering
- charge = 2e6 // Engineering starts with some charge for singulo //sorry little one, singulo as engine is gone
+ charge = 5e6 // Engineering starts with some charge for singulo //sorry little one, singulo as engine is gone //ZAS supermatter takes longer to set up so you get max.
output_level = 90000
/obj/machinery/power/smes/magical
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index f45a52590a7..45e07d5c08a 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -69,90 +69,58 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
var/gas_change_rate = 0.05
///The list of gases we will be interacting with in process_atoms()
var/list/gases_we_care_about = list(
- /datum/gas/oxygen,
- /datum/gas/water_vapor,
- /datum/gas/plasma,
- /datum/gas/carbon_dioxide,
- /datum/gas/nitrous_oxide,
- /datum/gas/nitrogen,
- /datum/gas/pluoxium,
- /datum/gas/tritium,
- /datum/gas/bz,
- /datum/gas/freon,
- /datum/gas/hydrogen,
- /datum/gas/healium,
- /datum/gas/proto_nitrate,
- /datum/gas/zauker,
- /datum/gas/miasma
+ GAS_OXYGEN,
+ GAS_PLASMA,
+ GAS_CO2,
+ GAS_N2O,
+ GAS_NITROGEN,
+ GAS_TRITIUM,
+ GAS_HYDROGEN,
+ GAS_STEAM,
)
///The list of gases mapped against their current comp. We use this to calculate different values the supermatter uses, like power or heat resistance. It doesn't perfectly match the air around the sm, instead moving up at a rate determined by gas_change_rate per call. Ranges from 0 to 1
var/list/gas_comp = list(
- /datum/gas/oxygen = 0,
- /datum/gas/water_vapor = 0,
- /datum/gas/plasma = 0,
- /datum/gas/carbon_dioxide = 0,
- /datum/gas/nitrous_oxide = 0,
- /datum/gas/nitrogen = 0,
- /datum/gas/pluoxium = 0,
- /datum/gas/tritium = 0,
- /datum/gas/bz = 0,
- /datum/gas/freon = 0,
- /datum/gas/hydrogen = 0,
- /datum/gas/healium = 0,
- /datum/gas/proto_nitrate = 0,
- /datum/gas/zauker = 0,
+ GAS_OXYGEN = 0,
+ GAS_PLASMA = 0,
+ GAS_CO2 = 0,
+ GAS_N2O = 0,
+ GAS_NITROGEN = 0,
+ GAS_TRITIUM = 0,
+ GAS_HYDROGEN = 0,
+ GAS_STEAM = 0,
)
///The list of gases mapped against their transmit values. We use it to determine the effect different gases have on the zaps
var/list/gas_trans = list(
- /datum/gas/oxygen = OXYGEN_TRANSMIT_MODIFIER,
- /datum/gas/water_vapor = H2O_TRANSMIT_MODIFIER,
- /datum/gas/plasma = PLASMA_TRANSMIT_MODIFIER,
- /datum/gas/pluoxium = PLUOXIUM_TRANSMIT_MODIFIER,
- /datum/gas/tritium = TRITIUM_TRANSMIT_MODIFIER,
- /datum/gas/bz = BZ_TRANSMIT_MODIFIER,
- /datum/gas/hydrogen = HYDROGEN_TRANSMIT_MODIFIER,
- /datum/gas/healium = HEALIUM_TRANSMIT_MODIFIER,
- /datum/gas/proto_nitrate = PROTO_NITRATE_TRANSMIT_MODIFIER,
- /datum/gas/zauker = ZAUKER_TRANSMIT_MODIFIER,
+ GAS_OXYGEN = OXYGEN_TRANSMIT_MODIFIER,
+ GAS_PLASMA = PLASMA_TRANSMIT_MODIFIER,
+ GAS_TRITIUM = TRITIUM_TRANSMIT_MODIFIER,
+ GAS_HYDROGEN = HYDROGEN_TRANSMIT_MODIFIER,
+ GAS_STEAM = H2O_TRANSMIT_MODIFIER,
)
///The list of gases mapped against their heat penaltys. We use it to determin molar and heat output
var/list/gas_heat = list(
- /datum/gas/oxygen = OXYGEN_HEAT_PENALTY,
- /datum/gas/water_vapor = H2O_HEAT_PENALTY,
- /datum/gas/plasma = PLASMA_HEAT_PENALTY,
- /datum/gas/carbon_dioxide = CO2_HEAT_PENALTY,
- /datum/gas/nitrogen = NITROGEN_HEAT_PENALTY,
- /datum/gas/pluoxium = PLUOXIUM_HEAT_PENALTY,
- /datum/gas/tritium = TRITIUM_HEAT_PENALTY,
- /datum/gas/bz = BZ_HEAT_PENALTY,
- /datum/gas/freon = FREON_HEAT_PENALTY,
- /datum/gas/hydrogen = HYDROGEN_HEAT_PENALTY,
- /datum/gas/healium = HEALIUM_HEAT_PENALTY,
- /datum/gas/proto_nitrate = PROTO_NITRATE_HEAT_PENALTY,
- /datum/gas/zauker = ZAUKER_HEAT_PENALTY,
+ GAS_OXYGEN = OXYGEN_HEAT_PENALTY,
+ GAS_PLASMA = PLASMA_HEAT_PENALTY,
+ GAS_CO2 = CO2_HEAT_PENALTY,
+ GAS_NITROGEN = NITROGEN_HEAT_PENALTY,
+ GAS_TRITIUM = TRITIUM_HEAT_PENALTY,
+ GAS_HYDROGEN = HYDROGEN_HEAT_PENALTY,
+ GAS_STEAM = H2O_HEAT_PENALTY,
)
///The list of gases mapped against their heat resistance. We use it to moderate heat damage.
var/list/gas_resist = list(
- /datum/gas/nitrous_oxide = N2O_HEAT_RESISTANCE,
- /datum/gas/hydrogen = HYDROGEN_HEAT_RESISTANCE,
- /datum/gas/proto_nitrate = PROTO_NITRATE_HEAT_RESISTANCE,
+ GAS_N2O = N2O_HEAT_RESISTANCE,
+ GAS_HYDROGEN = HYDROGEN_HEAT_RESISTANCE,
)
///The list of gases mapped against their powermix ratio
var/list/gas_powermix = list(
- /datum/gas/oxygen = 1,
- /datum/gas/water_vapor = 1,
- /datum/gas/plasma = 1,
- /datum/gas/carbon_dioxide = 1,
- /datum/gas/nitrogen = -1,
- /datum/gas/pluoxium = -1,
- /datum/gas/tritium = 1,
- /datum/gas/bz = 1,
- /datum/gas/freon = -1,
- /datum/gas/hydrogen = 1,
- /datum/gas/healium = 1,
- /datum/gas/proto_nitrate = 1,
- /datum/gas/zauker = 1,
- /datum/gas/miasma = 0.5,
+ GAS_OXYGEN = 1,
+ GAS_STEAM = 1,
+ GAS_PLASMA = 1,
+ GAS_CO2 = 1,
+ GAS_NITROGEN = -1,
+ GAS_TRITIUM = 1,
+ GAS_HYDROGEN = 1,
)
///The last air sample's total molar count, will always be above or equal to 0
var/combined_gas = 0
@@ -254,7 +222,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/Initialize(mapload)
. = ..()
uid = gl_uid++
- SSair.start_processing_machine(src)
+ SSairmachines.start_processing_machine(src)
countdown = new(src)
countdown.start()
SSpoints_of_interest.make_point_of_interest(src)
@@ -288,7 +256,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/Destroy()
investigate_log("has been destroyed.", INVESTIGATE_ENGINE)
- SSair.stop_processing_machine(src)
+ SSairmachines.stop_processing_machine(src)
QDEL_NULL(radio)
QDEL_NULL(countdown)
if(is_main_engine && GLOB.main_supermatter_engine == src)
@@ -331,7 +299,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
data["SM_integrity"] = get_integrity_percent()
data["SM_power"] = power
data["SM_ambienttemp"] = air.temperature
- data["SM_ambientpressure"] = air.return_pressure()
+ data["SM_ambientpressure"] = air.returnPressure()
data["SM_bad_moles_amount"] = MOLE_PENALTY_THRESHOLD / gasefficency
data["SM_moles"] = 0
data["SM_uid"] = uid
@@ -340,17 +308,17 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
var/list/gasdata = list()
- if(air.total_moles())
- data["SM_moles"] = air.total_moles()
- for(var/gasid in air.gases)
+ if(air.total_moles)
+ data["SM_moles"] = air.total_moles
+ for(var/gasid in air.gas)
gasdata.Add(list(list(
- "name"= air.gases[gasid][GAS_META][META_GAS_NAME],
- "amount" = round(100*air.gases[gasid][MOLES]/air.total_moles(),0.01))))
+ "name"= xgm_gas_data.name[gasid],
+ "amount" = round(100*air.gas[gasid]/air.total_moles,0.01))))
else
- for(var/gasid in air.gases)
+ for(var/gasid in air.gas)
gasdata.Add(list(list(
- "name"= air.gases[gasid][GAS_META][META_GAS_NAME],
+ "name"= xgm_gas_data.name[gasid],
"amount" = 0)))
data["gases"] = gasdata
@@ -653,7 +621,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
var/turf/target_turf = get_turf(target)
var/pressure = 1
if(target_turf?.return_air())
- pressure = max(1,target_turf.return_air().return_pressure())
+ pressure = max(1,target_turf.return_air().returnPressure())
//We get our range with the strength of the zap and the pressure, the higher the former and the lower the latter the better
var/new_range = clamp(zap_str / pressure * 10, 2, 7)
var/zap_count = 1
diff --git a/code/modules/power/supermatter/supermatter_process.dm b/code/modules/power/supermatter/supermatter_process.dm
index 3dfc5e0027f..857aa00dbd2 100644
--- a/code/modules/power/supermatter/supermatter_process.dm
+++ b/code/modules/power/supermatter/supermatter_process.dm
@@ -22,7 +22,7 @@
var/datum/gas_mixture/removed
if(produces_gas)
//Remove gas from surrounding area
- removed = env.remove(gasefficency * env.total_moles())
+ removed = env.remove(gasefficency * env.total_moles)
else
// Pass all the gas related code an empty gas container
removed = new()
@@ -35,23 +35,21 @@
else
psy_overlay = FALSE
damage_archived = damage
- if(!removed || !removed.total_moles() || isspaceturf(local_turf)) //we're in space or there is no gas to process
+ if(!removed || !removed.total_moles || isspaceturf(local_turf)) //we're in space or there is no gas to process
if(takes_damage)
damage += max((power / 1000) * DAMAGE_INCREASE_MULTIPLIER, 0.1) // always does at least some damage
- if(!istype(env, /datum/gas_mixture/immutable) && produces_gas && power) //There is no gas to process, but we are not in a space turf. Lets make them.
+ if(local_turf.simulated && produces_gas && power) //There is no gas to process, but we are not in a space turf. Lets make them.
//Power * 0.55 * a value between 1 and 0.8
var/device_energy = power * REACTION_POWER_MODIFIER * (1 - (psyCoeff * 0.2))
//Can't do stuff if it's null, so lets make a new gasmix.
removed = new()
//Since there is no gas to process, we will produce as if heat penalty is 1 and temperature at TCMB.
- removed.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
removed.temperature = ((device_energy) / THERMAL_RELEASE_MODIFIER)
removed.temperature = max(TCMB, min(removed.temperature, 2500))
- removed.gases[/datum/gas/plasma][MOLES] = max((device_energy) / PLASMA_RELEASE_MODIFIER, 0)
- removed.gases[/datum/gas/oxygen][MOLES] = max(((device_energy + TCMB) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)
- removed.garbage_collect()
+ removed.adjustGas(GAS_PLASMA, max((device_energy) / PLASMA_RELEASE_MODIFIER, 0), FALSE) //Don't update just yet
+ removed.adjustGas(GAS_OXYGEN, max(((device_energy + TCMB) - T0C) / OXYGEN_RELEASE_MODIFIER, 0), TRUE) //Now we update the mixture
env.merge(removed)
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
else
if(takes_damage)
//causing damage
@@ -59,14 +57,21 @@
//registers the current enviromental gases in the various lists and vars
setup_lists(removed)
+ AIR_UPDATE_VALUES(removed)
//some gases can have special interactions
special_gases_interactions(env, removed)
+ AIR_UPDATE_VALUES(removed)
+ AIR_UPDATE_VALUES(env)
//main power calculations proc
power_calculations(env, removed)
+ AIR_UPDATE_VALUES(removed)
+ AIR_UPDATE_VALUES(env)
//irradiate at this point
emit_radiation()
//handles temperature increase and gases made by the crystal
temperature_gas_production(env, removed)
+ AIR_UPDATE_VALUES(removed)
+ AIR_UPDATE_VALUES(env)
//handles hallucinations and the presence of a psychiatrist
psychological_examination()
@@ -113,7 +118,7 @@
//((((some value between 0.5 and 1 * temp - ((273.15 + 40) * some values between 1 and 10)) * some number between 0.25 and knock your socks off / 150) * 0.25
//Heat and mols account for each other, a lot of hot mols are more damaging then a few
//Mols start to have a positive effect on damage after 350
- damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
+ damage = max(damage + (max(clamp(removed.get_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Power only starts affecting damage when it is above 5000
damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Molar count only starts affecting damage when it is above 1800
@@ -127,7 +132,7 @@
//Check for holes in the SM inner chamber
for(var/turf/open/space/turf_to_check in RANGE_TURFS(1, loc))
- if(LAZYLEN(turf_to_check.atmos_adjacent_turfs))
+ if(LAZYLEN(turf_to_check.get_atmos_adjacent_turfs()))
var/integrity = get_integrity_percent()
if(integrity < 10)
damage += clamp((power * 0.0005) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
@@ -145,13 +150,9 @@
damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage)
/obj/machinery/power/supermatter_crystal/proc/setup_lists(datum/gas_mixture/removed)
-
- for(var/gas_id in gases_we_care_about)
- removed.assert_gas(gas_id)
-
//calculating gas related values
//Wanna know a secret? See that max() to zero? it's used for error checking. If we get a mol count in the negative, we'll get a divide by zero error //Old me, you're insane
- combined_gas = max(removed.total_moles(), 0)
+ combined_gas = max(removed.get_moles(), 0)
//This is more error prevention, according to all known laws of atmos, gas_mix.remove() should never make negative mol values.
//But this is tg
@@ -159,14 +160,14 @@
//Lets get the proportions of the gasses in the mix for scaling stuff later
//They range between 0 and 1
for(var/gas_id in gases_we_care_about)
- gas_comp[gas_id] = clamp(removed.gases[gas_id][MOLES] / combined_gas, 0, 1)
+ gas_comp[gas_id] = clamp(removed.gas[gas_id] / combined_gas, 0, 1)
var/list/heat_mod = gases_we_care_about.Copy()
var/list/transit_mod = gases_we_care_about.Copy()
var/list/resistance_mod = gases_we_care_about.Copy()
- var/h2obonus = 1 - (gas_comp[/datum/gas/water_vapor] * 0.25)//At max this value should be 0.75
- freonbonus = (gas_comp[/datum/gas/freon] <= 0.03) //Let's just yeet power output if this shit is high
+ var/h2obonus = 1 - (gas_comp[GAS_STEAM] * 0.25)//At max this value should be 0.75
+ //freonbonus = (gas_comp[/datum/gas/freon] <= 0.03) //Let's just yeet power output if this shit is high
//No less then zero, and no greater then one, we use this to do explosions and heat to power transfer
@@ -196,30 +197,33 @@
/obj/machinery/power/supermatter_crystal/proc/special_gases_interactions(datum/gas_mixture/env, datum/gas_mixture/removed)
//Miasma is really just microscopic particulate. It gets consumed like anything else that touches the crystal.
- if(gas_comp[/datum/gas/miasma])
- var/miasma_pp = env.return_pressure() * gas_comp[/datum/gas/miasma]
+ /*if(gas_comp[/datum/gas/miasma])
+ var/miasma_pp = env.returnPressure() * gas_comp[/datum/gas/miasma]
var/consumed_miasma = clamp(((miasma_pp - MIASMA_CONSUMPTION_PP) / (miasma_pp + MIASMA_PRESSURE_SCALING)) * (1 + (gasmix_power_ratio * MIASMA_GASMIX_SCALING)), MIASMA_CONSUMPTION_RATIO_MIN, MIASMA_CONSUMPTION_RATIO_MAX)
consumed_miasma *= gas_comp[/datum/gas/miasma] * combined_gas
if(consumed_miasma)
removed.gases[/datum/gas/miasma][MOLES] -= consumed_miasma
matter_power += consumed_miasma * MIASMA_POWER_GAIN
+ */
//Let's say that the CO2 touches the SM surface and the radiation turns it into Pluoxium.
- if(gas_comp[/datum/gas/carbon_dioxide] && gas_comp[/datum/gas/oxygen])
- var/carbon_dioxide_pp = env.return_pressure() * gas_comp[/datum/gas/carbon_dioxide]
+ if(gas_comp[GAS_CO2] && gas_comp[GAS_OXYGEN])
+ var/carbon_dioxide_pp = env.returnPressure() * gas_comp[GAS_CO2]
var/consumed_carbon_dioxide = clamp(((carbon_dioxide_pp - CO2_CONSUMPTION_PP) / (carbon_dioxide_pp + CO2_PRESSURE_SCALING)), CO2_CONSUMPTION_RATIO_MIN, CO2_CONSUMPTION_RATIO_MAX)
- consumed_carbon_dioxide = min(consumed_carbon_dioxide * gas_comp[/datum/gas/carbon_dioxide] * combined_gas, removed.gases[/datum/gas/carbon_dioxide][MOLES] * INVERSE(0.5), removed.gases[/datum/gas/oxygen][MOLES] * INVERSE(0.5))
+ consumed_carbon_dioxide = min(consumed_carbon_dioxide * gas_comp[GAS_CO2] * combined_gas, removed.gas[GAS_CO2] * INVERSE(0.5), removed.gas[GAS_OXYGEN] * INVERSE(0.5))
if(consumed_carbon_dioxide)
- removed.gases[/datum/gas/carbon_dioxide][MOLES] -= consumed_carbon_dioxide * 0.5
- removed.gases[/datum/gas/oxygen][MOLES] -= consumed_carbon_dioxide * 0.5
- removed.gases[/datum/gas/pluoxium][MOLES] += consumed_carbon_dioxide * 0.25
+ removed.adjustGas(GAS_CO2, -consumed_carbon_dioxide * 0.5, FALSE)
+ removed.adjustGas(GAS_OXYGEN, -consumed_carbon_dioxide * 0.5, FALSE)
+ removed.adjustGas(GAS_HYDROGEN, consumed_carbon_dioxide * 0.25, FALSE) //Pluoxium is hydrogen now, deal with it.
- if(prob(gas_comp[/datum/gas/zauker]))
+ /*if(prob(gas_comp[/datum/gas/zauker]))
playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10)
supermatter_zap(src, 6, clamp(power * 2, 4000, 20000), ZAP_MOB_STUN, zap_cutoff = src.zap_cutoff, power_level = power, zap_icon = src.zap_icon)
+ */
- if(gas_comp[/datum/gas/bz] >= 0.4 && prob(30 * gas_comp[/datum/gas/bz]))
+ /*if(gas_comp[/datum/gas/bz] >= 0.4 && prob(30 * gas_comp[/datum/gas/bz]))
fire_nuclear_particle() // Start to emit radballs at a maximum of 30% chance per tick
+ */
/obj/machinery/power/supermatter_crystal/proc/power_calculations(datum/gas_mixture/env, datum/gas_mixture/removed)
@@ -229,8 +233,8 @@
//Ramps up or down in increments of 0.02 up to the proportion of co2
//Given infinite time, powerloss_dynamic_scaling = co2comp
//Some value between 0 and 1
- if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && gas_comp[/datum/gas/carbon_dioxide] > POWERLOSS_INHIBITION_GAS_THRESHOLD) //If there are more then 20 mols, and more then 20% co2
- powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(gas_comp[/datum/gas/carbon_dioxide] - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1)
+ if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && gas_comp[GAS_CO2] > POWERLOSS_INHIBITION_GAS_THRESHOLD) //If there are more then 20 mols, and more then 20% co2
+ powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(gas_comp[GAS_CO2] - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1)
else
powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05, 0, 1)
//Ranges from 0 to 1(1-(value between 0 and 1 * ranges from 1 to 1.5(mol / 500)))
@@ -264,9 +268,10 @@
if(power && (last_power_zap + 4 SECONDS - (power * 0.001)) < world.time)
//(1 + (tritRad + pluoxDampen * bzDampen * o2Rad * plasmaRad / (10 - bzrads))) * freonbonus
playsound(src, 'sound/weapons/emitter2.ogg', 70, TRUE)
- var/power_multiplier = max(0, (1 + (power_transmission_bonus / (10 - (gas_comp[/datum/gas/bz] * BZ_RADIOACTIVITY_MODIFIER)))) * freonbonus)// RadModBZ(500%)
- var/pressure_multiplier = max((1 / ((env.return_pressure() ** pressure_bonus_curve_angle) + 1) * pressure_bonus_derived_steepness) + pressure_bonus_derived_constant, 1)
- var/co2_power_increase = max(gas_comp[/datum/gas/carbon_dioxide] * 2, 1)
+ //var/power_multiplier = max(0, (1 + (power_transmission_bonus / (10 - (gas_comp[/datum/gas/bz] * BZ_RADIOACTIVITY_MODIFIER)))) * freonbonus)// RadModBZ(500%)
+ var/power_multiplier = max(0, (1 + (power_transmission_bonus / 10)))
+ var/pressure_multiplier = max((1 / ((env.returnPressure() ** pressure_bonus_curve_angle) + 1) * pressure_bonus_derived_steepness) + pressure_bonus_derived_constant, 1)
+ var/co2_power_increase = max(gas_comp[GAS_CO2] * 2, 1)
supermatter_zap(
zapstart = src,
range = 3,
@@ -295,14 +300,14 @@
//Calculate how much gas to release
//Varies based on power and gas content
- removed.gases[/datum/gas/plasma][MOLES] += max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)
+ removed.adjustGas(GAS_PLASMA, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0), FALSE)
//Varies based on power, gas content, and heat
- removed.gases[/datum/gas/oxygen][MOLES] += max(((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)
+ removed.adjustGas(GAS_OXYGEN, max(((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0), FALSE)
if(produces_gas)
- removed.garbage_collect()
+ AIR_UPDATE_VALUES(removed) //This might be a waste
env.merge(removed)
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
/obj/machinery/power/supermatter_crystal/proc/psychological_examination()
// Defaults to a value less than 1. Over time the psyCoeff goes to 0 if
@@ -334,12 +339,12 @@
return
var/range = 4
zap_cutoff = 1500
- if(removed && removed.return_pressure() > 0 && removed.return_temperature() > 0)
+ if(removed && removed.returnPressure() > 0 && removed.temperature > 0)
//You may be able to freeze the zapstate of the engine with good planning, we'll see
- zap_cutoff = clamp(3000 - (power * (removed.total_moles()) / 10) / removed.return_temperature(), 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols
+ zap_cutoff = clamp(3000 - (power * (removed.total_moles) / 10) / removed.temperature, 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols
//We should always be able to zap our way out of the default enclosure
//See supermatter_zap() for more details
- range = clamp(power / removed.return_pressure() * 10, 2, 7)
+ range = clamp(power / removed.returnPressure() * 10, 2, 7)
var/flags = ZAP_SUPERMATTER_FLAGS
var/zap_count = 0
//Deal with power zaps
diff --git a/code/modules/power/turbine/turbine.dm b/code/modules/power/turbine/turbine.dm
index dd752ecef4a..a13ec413f22 100644
--- a/code/modules/power/turbine/turbine.dm
+++ b/code/modules/power/turbine/turbine.dm
@@ -1,7 +1,7 @@
/obj/machinery/power/turbine
density = TRUE
resistance_flags = FIRE_PROOF
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
///Theoretical volume of gas that's moving through the turbine, it expands the further it goes
var/gas_theoretical_volume = 0
@@ -514,8 +514,8 @@
//the compressor compresses down the gases from 2500 L to 1000 L
//the temperature and pressure rises up, you can regulate this to increase/decrease the amount of gas moved in.
var/compressor_work = do_calculations(input_turf_mixture, compressor.machine_gasmix, regulated = TRUE)
- input_turf.air_update_turf(TRUE)
- var/compressor_pressure = max(compressor.machine_gasmix.return_pressure(), 0.01)
+ input_turf.//air_update_turf(TRUE)
+ var/compressor_pressure = max(compressor.machine_gasmix.returnPressure(), 0.01)
//the rotor moves the gases that expands from 1000 L to 3000 L, they cool down and both temperature and pressure lowers
var/rotor_work = do_calculations(compressor.machine_gasmix, machine_gasmix, compressor_work)
@@ -523,10 +523,10 @@
//the turbine expands the gases more from 3000 L to 6000 L, cooling them down further.
var/turbine_work = do_calculations(machine_gasmix, turbine.machine_gasmix, abs(rotor_work))
- var/turbine_pressure = max(turbine.machine_gasmix.return_pressure(), 0.01)
+ var/turbine_pressure = max(turbine.machine_gasmix.returnPressure(), 0.01)
//the total work done by the gas
- var/work_done = turbine.machine_gasmix.total_moles() * R_IDEAL_GAS_EQUATION * turbine.machine_gasmix.temperature * log(compressor_pressure / turbine_pressure)
+ var/work_done = turbine.machine_gasmix.get_moles() * R_IDEAL_GAS_EQUATION * turbine.machine_gasmix.temperature * log(compressor_pressure / turbine_pressure)
//removing the work needed to move the compressor but adding back the turbine work that is the one generating most of the power.
work_done = max(work_done - compressor_work * TURBINE_COMPRESSOR_STATOR_INTERACTION_MULTIPLIER - turbine_work, 0)
@@ -538,14 +538,14 @@
add_avail(produced_energy)
- turbine.machine_gasmix.pump_gas_to(output_turf.air, turbine.machine_gasmix.return_pressure())
- output_turf.air_update_turf(TRUE)
+ turbine.machine_gasmix.pump_gas_to(output_turf.air, turbine.machine_gasmix.returnPressure())
+ output_turf.//air_update_turf(TRUE)
/**
* Handles all the calculations needed for the gases, work done, temperature increase/decrease
*/
/obj/machinery/power/turbine/core_rotor/proc/do_calculations(datum/gas_mixture/input_mix, datum/gas_mixture/output_mix, work_amount_to_remove, regulated = FALSE)
- var/work_done = input_mix.total_moles() * R_IDEAL_GAS_EQUATION * input_mix.temperature * log((input_mix.volume * max(input_mix.return_pressure(), 0.01)) / (output_mix.volume * max(output_mix.return_pressure(), 0.01))) * TURBINE_WORK_CONVERSION_MULTIPLIER
+ var/work_done = input_mix.get_moles() * R_IDEAL_GAS_EQUATION * input_mix.temperature * log((input_mix.volume * max(input_mix.returnPressure(), 0.01)) / (output_mix.volume * max(output_mix.returnPressure(), 0.01))) * TURBINE_WORK_CONVERSION_MULTIPLIER
if(work_amount_to_remove)
work_done = work_done - work_amount_to_remove
@@ -553,11 +553,11 @@
if(regulated)
intake_size = intake_regulator
- input_mix.pump_gas_to(output_mix, input_mix.return_pressure() * intake_size)
- var/output_mix_heat_capacity = output_mix.heat_capacity()
+ input_mix.pump_gas_to(output_mix, input_mix.returnPressure() * intake_size)
+ var/output_mix_heat_capacity = output_mix.getHeatCapacity()
if(!output_mix_heat_capacity)
return 0
- output_mix.temperature = max((output_mix.temperature * output_mix_heat_capacity + work_done * output_mix.total_moles() * TURBINE_HEAT_CONVERSION_MULTIPLIER) / output_mix_heat_capacity, TCMB)
+ output_mix.temperature = max((output_mix.temperature * output_mix_heat_capacity + work_done * output_mix.get_moles() * TURBINE_HEAT_CONVERSION_MULTIPLIER) / output_mix_heat_capacity, TCMB)
return work_done
/obj/item/paper/guides/jobs/atmos/turbine
diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
index 844b41c05c7..6f82e45a4bf 100644
--- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
+++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
@@ -9,6 +9,7 @@
/datum/map_generator_module/bottom_layer/repressurize/generate()
if(!mother)
return
+ /*
var/list/map = mother.map
for(var/turf/T in map)
SSair.remove_from_active(T)
@@ -16,7 +17,7 @@
if(T.air)
T.air.copy_from_turf(T)
SSair.add_to_active(T, TRUE)
-
+*/
/datum/map_generator_module/bottom_layer/massdelete
spawnableAtoms = list()
spawnableTurfs = list()
diff --git a/code/modules/procedural_mapping/mapGenerators/repair.dm b/code/modules/procedural_mapping/mapGenerators/repair.dm
index b305ac2c438..594d5f66e67 100644
--- a/code/modules/procedural_mapping/mapGenerators/repair.dm
+++ b/code/modules/procedural_mapping/mapGenerators/repair.dm
@@ -51,7 +51,7 @@
SSatoms.InitializeAtoms(atoms)
SSmachines.setup_template_powernets(cables)
- SSair.setup_template_machinery(atmos_machines)
+ SSairmachines.setup_template_machinery(atmos_machines)
GLOB.reloading_map = FALSE
/datum/map_generator/repair
diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm
index 01a2e87700d..1ae0ca8bd01 100644
--- a/code/modules/projectiles/guns/energy/beam_rifle.dm
+++ b/code/modules/projectiles/guns/energy/beam_rifle.dm
@@ -448,7 +448,8 @@
to_chat(L, span_userdanger("\The [src] sears you!"))
for(var/turf/T in RANGE_TURFS(aoe_fire_range, epicenter)) //handle aoe fire
if(prob(aoe_fire_chance))
- new /obj/effect/hotspot(T)
+ //new /obj/effect/hotspot(T)
+ T.create_fire(1, 10)
for(var/obj/O in range(aoe_structure_range, epicenter))
if(!isitem(O))
O.take_damage(aoe_structure_damage * get_damage_coeff(O), BURN, LASER, FALSE)
diff --git a/code/modules/projectiles/guns/special/blastcannon.dm b/code/modules/projectiles/guns/special/blastcannon.dm
index 3596105c4d3..3443d68b7f7 100644
--- a/code/modules/projectiles/guns/special/blastcannon.dm
+++ b/code/modules/projectiles/guns/special/blastcannon.dm
@@ -189,8 +189,8 @@
var/cap_multiplier = SSmapping.level_trait(start_turf.z, ZTRAIT_BOMBCAP_MULTIPLIER)
if(isnull(cap_multiplier))
cap_multiplier = 1
- var/capped_heavy = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, heavy)
- var/capped_medium = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, medium)
+ var/capped_heavy = min(zas_settings.maxex_devastation_range * cap_multiplier, heavy)
+ var/capped_medium = min(zas_settings.maxex_heavy_range * cap_multiplier, medium)
SSexplosions.shake_the_room(start_turf, max(heavy, medium, light, 0), (capped_heavy * 15) + (capped_medium * 20), capped_heavy, capped_medium)
var/obj/projectile/blastwave/blastwave = new(loc, heavy, medium, light)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index de6a269e464..58f6ad6b352 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -15,6 +15,8 @@
blocks_emissive = EMISSIVE_BLOCK_GENERIC
layer = MOB_LAYER
plane = GAME_PLANE_FOV_HIDDEN
+ simulated = FALSE
+
//The sound this plays on impact.
var/hitsound = 'sound/weapons/pierce.ogg'
var/hitsound_wall = ""
@@ -1018,9 +1020,6 @@
if(cleanup)
cleanup_beam_segments()
-/obj/projectile/experience_pressure_difference()
- return
-
///Like [/obj/item/proc/updateEmbedding] but for projectiles instead, call this when you want to add embedding or update the stats on the embedding element
/obj/projectile/proc/updateEmbedding()
if(!shrapnel_type || !LAZYLEN(embedding))
diff --git a/code/modules/projectiles/projectile/bullets/_incendiary.dm b/code/modules/projectiles/projectile/bullets/_incendiary.dm
index cb18fa00236..cbbe45861f4 100644
--- a/code/modules/projectiles/projectile/bullets/_incendiary.dm
+++ b/code/modules/projectiles/projectile/bullets/_incendiary.dm
@@ -13,7 +13,8 @@
. = ..()
var/turf/location = get_turf(src)
if(location)
- new /obj/effect/hotspot(location)
+ //.new /obj/effect/hotspot(location)
+ location.create_fire(1, 10)
location.hotspot_expose(700, 50, 1)
/// Used in [the backblast element][/datum/element/backblast]
@@ -50,7 +51,8 @@
. = ..()
var/turf/location = get_turf(target)
if(isopenturf(location))
- new /obj/effect/hotspot(location)
+ //new /obj/effect/hotspot(location)
+ location.create_fire(1, 10)
location.hotspot_expose(700, 50, 1)
/obj/projectile/bullet/incendiary/backblast/Move()
diff --git a/code/modules/projectiles/projectile/bullets/cannonball.dm b/code/modules/projectiles/projectile/bullets/cannonball.dm
index 587e1a2e99d..eadaf11564a 100644
--- a/code/modules/projectiles/projectile/bullets/cannonball.dm
+++ b/code/modules/projectiles/projectile/bullets/cannonball.dm
@@ -55,7 +55,7 @@
/obj/projectile/bullet/cannonball/biggest_one/on_hit(atom/target, blocked = FALSE)
if(projectile_piercing == NONE)
- explosion(target, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE, explosion_cause = src)
+ explosion(target,devastation_range = zas_settings.maxex_devastation_range, heavy_impact_range = zas_settings.maxex_heavy_range, light_impact_range = zas_settings.maxex_light_range, flash_range = zas_settings.maxex_flash_range, explosion_cause = src)
. = ..()
/obj/projectile/bullet/cannonball/trashball
diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm
index 8a0b0ca51a5..14bef9e7193 100644
--- a/code/modules/projectiles/projectile/bullets/revolver.dm
+++ b/code/modules/projectiles/projectile/bullets/revolver.dm
@@ -93,7 +93,7 @@
/obj/projectile/bullet/c38/iceblox //see /obj/projectile/temp for the original code
name = ".38 Iceblox bullet"
damage = 20
- var/temperature = 100
+ temperature = 100
ricochets_max = 0
/obj/projectile/bullet/c38/iceblox/on_hit(atom/target, blocked = FALSE)
diff --git a/code/modules/projectiles/projectile/energy/nuclear_particle.dm b/code/modules/projectiles/projectile/energy/nuclear_particle.dm
index f8e518bdb8b..2942350ea10 100644
--- a/code/modules/projectiles/projectile/energy/nuclear_particle.dm
+++ b/code/modules/projectiles/projectile/energy/nuclear_particle.dm
@@ -1,6 +1,7 @@
//Nuclear particle projectile - a deadly side effect of fusion
/obj/projectile/energy/nuclear_particle
name = "nuclear particle"
+ desc = "Wow, that's moving pretty fast!"
icon_state = "nuclear_particle"
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
armor_flag = ENERGY
@@ -9,6 +10,11 @@
speed = 0.4
hitsound = 'sound/weapons/emitter2.ogg'
impact_type = /obj/effect/projectile/impact/xray
+ var/energy = 10 //energy in eV
+ var/mega_energy = 0 //energy in MeV
+ var/particle_type
+ var/additional_particles = 0
+
var/static/list/particle_colors = list(
"red" = "#FF0000",
"blue" = "#00FF00",
diff --git a/code/modules/projectiles/projectile/special/temperature.dm b/code/modules/projectiles/projectile/special/temperature.dm
index 6f6e39004e5..a3db79507f4 100644
--- a/code/modules/projectiles/projectile/special/temperature.dm
+++ b/code/modules/projectiles/projectile/special/temperature.dm
@@ -5,22 +5,22 @@
damage_type = BURN
nodamage = FALSE
armor_flag = ENERGY
- var/temperature = -50 // reduce the body temperature by 50 points
+ var/adj_temperature = -50 // reduce the body temperature by 50 points
/obj/projectile/temp/on_hit(atom/target, blocked = 0)
. = ..()
if(iscarbon(target))
var/mob/living/carbon/hit_mob = target
- var/thermal_protection = 1 - hit_mob.get_insulation_protection(hit_mob.bodytemperature + temperature)
+ var/thermal_protection = 1 - hit_mob.get_insulation_protection(hit_mob.bodytemperature + adj_temperature)
// The new body temperature is adjusted by the bullet's effect temperature
// Reduce the amount of the effect temperature change based on the amount of insulation the mob is wearing
- hit_mob.adjust_bodytemperature((thermal_protection * temperature) + temperature)
+ hit_mob.adjust_bodytemperature((thermal_protection * adj_temperature) + adj_temperature)
else if(isliving(target))
var/mob/living/L = target
// the new body temperature is adjusted by the bullet's effect temperature
- L.adjust_bodytemperature((1 - blocked) * temperature)
+ L.adjust_bodytemperature((1 - blocked) * adj_temperature)
/obj/projectile/temp/hot
name = "heat beam"
diff --git a/code/modules/reagents/chem_splash.dm b/code/modules/reagents/chem_splash.dm
index 4b4a95809ab..9393c64761d 100644
--- a/code/modules/reagents/chem_splash.dm
+++ b/code/modules/reagents/chem_splash.dm
@@ -97,8 +97,8 @@
for(var/turf/T in turflist)
if(accessible[T])
continue
- for(var/thing in T.get_atmos_adjacent_turfs(alldir = TRUE))
- var/turf/NT = thing
+ //for(var/thing in T.get_atmos_adjacent_turfs(alldir = TRUE))
+ for(var/turf/NT as anything in get_adjacent_open_turfs(T))
if(!(NT in accessible))
continue
if(!(get_dir(T,NT) in GLOB.cardinals))
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 900a99bfcac..2137538ee78 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -223,7 +223,7 @@
iter_reagent.on_merge(data, amount)
if(reagtemp != cached_temp)
- var/new_heat_capacity = heat_capacity()
+ var/new_heat_capacity = getHeatCapacity()
if(new_heat_capacity)
set_temperature(((old_heat_capacity * cached_temp) + (iter_reagent.specific_heat * amount * reagtemp)) / new_heat_capacity)
else
@@ -252,7 +252,7 @@
update_total()
if(reagtemp != cached_temp)
- var/new_heat_capacity = heat_capacity()
+ var/new_heat_capacity = getHeatCapacity()
if(new_heat_capacity)
set_temperature(((old_heat_capacity * cached_temp) + (new_reagent.specific_heat * amount * reagtemp)) / new_heat_capacity)
else
@@ -1359,7 +1359,7 @@
/// Returns the total heat capacity for all of the reagents currently in this holder.
-/datum/reagents/proc/heat_capacity()
+/datum/reagents/proc/getHeatCapacity()
. = 0
var/list/cached_reagents = reagent_list //cache reagents
for(var/datum/reagent/reagent in cached_reagents)
@@ -1373,7 +1373,7 @@
* - max_temp: The maximum temperature that can be reached.
*/
/datum/reagents/proc/adjust_thermal_energy(delta_energy, min_temp = 2.7, max_temp = 1000)
- var/heat_capacity = heat_capacity()
+ var/heat_capacity = getHeatCapacity()
if(!heat_capacity)
return // no div/0 please
set_temperature(clamp(chem_temp + (delta_energy / heat_capacity), min_temp, max_temp))
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index db74f2a29f5..bdc3161c00a 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -332,7 +332,7 @@
var/turf/open/exposed_open_turf = exposed_turf
exposed_open_turf.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure.
var/temperature = exposed_open_turf.air.temperature
- var/heat_capacity = exposed_open_turf.air.heat_capacity()
+ var/heat_capacity = exposed_open_turf.air.getHeatCapacity()
exposed_open_turf.air.temperature = max(exposed_open_turf.air.temperature - ((temperature - TCMB) * (heat_capacity * reac_volume * specific_heat) / (heat_capacity + reac_volume * specific_heat)) / heat_capacity, TCMB) // Exchanges environment temperature with reagent. Reagent is at 2.7K with a heat capacity of 40J per unit.
if(reac_volume < 5)
return
@@ -478,7 +478,7 @@
exposed_turf.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume*2 SECONDS)
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in exposed_turf)
if(hotspot)
- var/datum/gas_mixture/lowertemp = exposed_turf.remove_air(exposed_turf.air.total_moles())
+ var/datum/gas_mixture/lowertemp = exposed_turf.remove_air(exposed_turf.air.get_moles())
lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0)
lowertemp.react(src)
exposed_turf.assume_air(lowertemp)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 3896f2a25c8..b4674bc6bbe 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -915,7 +915,7 @@
/datum/reagent/chlorine/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
- M.take_bodypart_damage(0.5*REM*delta_time, 0, 0, 0)
+ M.adjustToxLoss(3*REM*delta_time)
. = TRUE
..()
@@ -1393,7 +1393,7 @@
. = ..()
if(istype(exposed_turf))
var/temp = holder ? holder.chem_temp : T20C
- exposed_turf.atmos_spawn_air("n2o=[reac_volume/20];TEMP=[temp]")
+ exposed_turf.assume_gas(GAS_N2O, reac_volume / REAGENT_GAS_EXCHANGE_FACTOR, temp)
/datum/reagent/nitrous_oxide/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)
. = ..()
diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm
index bc6120804c9..31355b69b89 100644
--- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm
@@ -67,15 +67,18 @@
exposed_turf.burn_tile()
if(isfloorturf(exposed_turf))
for(var/turf/nearby_turf in RANGE_TURFS(1, exposed_turf))
- if(!locate(/obj/effect/hotspot) in nearby_turf)
- new /obj/effect/hotspot(nearby_turf)
+ /*if(!locate(/obj/effect/hotspot) in nearby_turf)
+ new /obj/effect/hotspot(nearby_turf)*/
+ nearby_turf.create_fire(1, 10)
/datum/reagent/clf3/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)
. = ..()
exposed_mob.adjust_fire_stacks(min(reac_volume/5, 10))
exposed_mob.IgniteMob()
- if(!locate(/obj/effect/hotspot) in exposed_mob.loc)
- new /obj/effect/hotspot(exposed_mob.loc)
+ //if(!locate(/obj/effect/hotspot) in exposed_mob.loc)
+ //new /obj/effect/hotspot(exposed_mob.loc)
+ var/turf/T = get_turf(exposed_mob)
+ T.create_fire(1, 10)
/datum/reagent/sorium
name = "Sorium"
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 2802580546f..441c285e531 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -107,8 +107,10 @@
if(!holder.my_atom)
return
- var/atom/A = holder.my_atom
- A.atmos_spawn_air("plasma=[volume];TEMP=[holder.chem_temp]")
+ var/turf/open/T = get_turf(holder.my_atom)
+ if(!istype(T))
+ return
+ T.assume_gas(GAS_PLASMA, volume, holder.chem_temp)
holder.del_reagent(type)
/datum/reagent/toxin/plasma/expose_turf(turf/open/exposed_turf, reac_volume)
@@ -116,13 +118,15 @@
return
var/temp = holder ? holder.chem_temp : T20C
if(temp >= LIQUID_PLASMA_BP)
- exposed_turf.atmos_spawn_air("plasma=[reac_volume];TEMP=[temp]")
+ exposed_turf.assume_gas(GAS_PLASMA, reac_volume / REAGENT_GAS_EXCHANGE_FACTOR, holder.chem_temp)
return ..()
/datum/reagent/toxin/plasma/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with plasma is stronger than fuel!
. = ..()
if(methods & (TOUCH|VAPOR))
exposed_mob.adjust_fire_stacks(reac_volume / 5)
+ if(prob(50 * reac_volume))
+ exposed_mob.expose_plasma()
return
/datum/reagent/toxin/hot_ice
diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm
index bc133b55a48..8594509568a 100644
--- a/code/modules/reagents/chemistry/recipes.dm
+++ b/code/modules/reagents/chemistry/recipes.dm
@@ -475,7 +475,8 @@
equilibrium.data["[id]_y"] += increment
var/turf/holder_turf = get_turf(holder.my_atom)
var/turf/target = locate(holder_turf.x + equilibrium.data["[id]_x"], holder_turf.y + equilibrium.data["[id]_y"], holder_turf.z)
- new /obj/effect/hotspot(target)
+ //new /obj/effect/hotspot(target)
+ target.create_fire(1, 10)
debug_world("X: [equilibrium.data["[id]_x"]], Y: [equilibrium.data["[id]_x"]]")
/*
@@ -487,10 +488,12 @@
/datum/chemical_reaction/proc/explode_fire_square(datum/reagents/holder, datum/equilibrium/equilibrium, fire_range = 1)
var/turf/location = get_turf(holder.my_atom)
if(fire_range == 0)
- new /obj/effect/hotspot(location)
+ //new /obj/effect/hotspot(location)
+ location.create_fire(1, 10)
return
for(var/turf/turf as anything in RANGE_TURFS(fire_range, location))
- new /obj/effect/hotspot(turf)
+ //new /obj/effect/hotspot(turf)
+ turf.create_fire(1, 10)
///////////END FIRE BASED EXPLOSIONS
diff --git a/code/modules/reagents/chemistry/recipes/cat2_medicines.dm b/code/modules/reagents/chemistry/recipes/cat2_medicines.dm
index a34603f4a6a..ecbf33d3fc1 100644
--- a/code/modules/reagents/chemistry/recipes/cat2_medicines.dm
+++ b/code/modules/reagents/chemistry/recipes/cat2_medicines.dm
@@ -30,7 +30,9 @@
return
if(helbital.purity <= 0.25)
if(prob(25))
- new /obj/effect/hotspot(holder.my_atom.loc)
+ //new /obj/effect/hotspot(holder.my_atom.loc)
+ var/turf/T = get_turf(holder.my_atom)
+ T.create_fire(1, 10)
holder.remove_reagent(/datum/reagent/medicine/c2/helbital, 2)
holder.chem_temp += 5
holder.my_atom.audible_message(span_notice("[icon2html(holder.my_atom, viewers(DEFAULT_MESSAGE_RANGE, src))] The impurity of the reacting helbital is too great causing [holder.my_atom] to let out a hearty burst of flame, evaporating part of the product!"))
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index 08385f6e134..6635fbca8b2 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -53,7 +53,8 @@
var/fire_range = round(created_volume/30)
var/turf/T = get_turf(holder.my_atom)
for(var/turf/target as anything in RANGE_TURFS(fire_range,T))
- new /obj/effect/hotspot(target)
+ //new /obj/effect/hotspot(target)
+ target.create_fire(1, 10)
holder.chem_temp = 500
..()
@@ -67,7 +68,8 @@
var/fire_range = round(created_volume/20)
var/turf/T = get_turf(holder.my_atom)
for(var/turf/turf as anything in RANGE_TURFS(fire_range,T))
- new /obj/effect/hotspot(turf)
+ //new /obj/effect/hotspot(turf)
+ turf.create_fire(1, 10)
holder.chem_temp = 750
..()
@@ -212,7 +214,8 @@
/datum/chemical_reaction/clf3/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume)
var/turf/T = get_turf(holder.my_atom)
for(var/turf/target as anything in RANGE_TURFS(1,T))
- new /obj/effect/hotspot(target)
+ //new /obj/effect/hotspot(target)
+ target.create_fire(1, 10)
holder.chem_temp = 1000 // hot as shit
/datum/chemical_reaction/reagent_explosion/methsplosion
@@ -225,7 +228,8 @@
/datum/chemical_reaction/reagent_explosion/methsplosion/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume)
var/turf/T = get_turf(holder.my_atom)
for(var/turf/target in RANGE_TURFS(1,T))
- new /obj/effect/hotspot(target)
+ //new /obj/effect/hotspot(target)
+ target.create_fire(1, 10)
holder.chem_temp = 1000 // hot as shit
..()
diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm
index 331a8431dac..9996cf5e216 100644
--- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm
+++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm
@@ -210,10 +210,9 @@
/datum/chemical_reaction/slime/slimefreeze/proc/freeze(datum/reagents/holder)
if(holder?.my_atom)
- var/turf/open/T = get_turf(holder.my_atom)
+ var/turf/T = get_turf(holder.my_atom)
if(istype(T))
- var/datum/gas/gastype = /datum/gas/nitrogen
- T.atmos_spawn_air("[initial(gastype.id)]=50;TEMP=2.7")
+ T.atmos_spawn_air(GAS_NITROGEN, 50, 2.7)
/datum/chemical_reaction/slime/slimefireproof
required_reagents = list(/datum/reagent/water = 1)
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 0980f89d9b5..f82a8c17eb3 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -207,8 +207,8 @@
reagents.expose_temperature(1000)
..()
-/obj/item/reagent_containers/fire_act(temperature, volume)
- reagents.expose_temperature(temperature)
+/obj/item/reagent_containers/fire_act(exposed_temperature, exposed_volume)
+ reagents.expose_temperature(exposed_temperature)
/// Updates the icon of the container when the reagents change. Eats signal args
/obj/item/reagent_containers/proc/on_reagent_change(datum/reagents/holder, ...)
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index 48d88b4654c..0bc8bc897a0 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -5,7 +5,7 @@
icon_state = "water"
density = TRUE
anchored = FALSE
- pressure_resistance = 2*ONE_ATMOSPHERE
+ //pressure_resistance = 2*ONE_ATMOSPHERE
max_integrity = 300
///In units, how much the dispenser can hold
var/tank_volume = 1000
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 69c8d5ebb16..94c4b71524e 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -76,9 +76,9 @@
/obj/machinery/disposal/LateInitialize()
//this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
- var/atom/L = loc
+ var/turf/L = loc
var/datum/gas_mixture/env = new
- env.copy_from(L.return_air())
+ env.copyFrom(L.return_air())
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
air_contents.merge(removed)
trunk_check()
@@ -314,7 +314,7 @@
data["full_pressure"] = full_pressure
data["pressure_charging"] = pressure_charging
data["panel_open"] = panel_open
- data["per"] = CLAMP01(air_contents.return_pressure() / (SEND_PRESSURE))
+ data["per"] = CLAMP01(air_contents.returnPressure() / (SEND_PRESSURE))
data["isai"] = isAI(user)
return data
@@ -416,7 +416,7 @@
do_flush()
flush_count = 0
- if(flush && air_contents.return_pressure() >= SEND_PRESSURE) // flush can happen even without power
+ if(flush && air_contents.returnPressure() >= SEND_PRESSURE) // flush can happen even without power
do_flush()
if(machine_stat & NOPOWER) // won't charge if no power
@@ -435,17 +435,17 @@
var/datum/gas_mixture/env = L.return_air()
if(!env.temperature)
return
- var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure()
+ var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.returnPressure()
var/transfer_moles = 0.05 * delta_time * (pressure_delta*air_contents.volume)/(env.temperature * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = env.remove(transfer_moles)
air_contents.merge(removed)
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
//if full enough, switch to ready mode
- if(air_contents.return_pressure() >= SEND_PRESSURE)
+ if(air_contents.returnPressure() >= SEND_PRESSURE)
full_pressure = TRUE
pressure_charging = FALSE
update_appearance()
diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm
index 5f24bc63241..56a14772878 100644
--- a/code/modules/recycling/disposal/construction.dm
+++ b/code/modules/recycling/disposal/construction.dm
@@ -8,7 +8,7 @@
icon_state = "conpipe"
anchored = FALSE
density = FALSE
- pressure_resistance = 5*ONE_ATMOSPHERE
+ //pressure_resistance = 5*ONE_ATMOSPHERE
max_integrity = 200
var/obj/pipe_type = /obj/structure/disposalpipe/segment
var/pipename
diff --git a/code/modules/research/anomaly/anomaly_refinery.dm b/code/modules/research/anomaly/anomaly_refinery.dm
index 5d70b73af31..a2de260fc3f 100644
--- a/code/modules/research/anomaly/anomaly_refinery.dm
+++ b/code/modules/research/anomaly/anomaly_refinery.dm
@@ -1,5 +1,5 @@
-#define MAX_RADIUS_REQUIRED 20 //maxcap
-#define MIN_RADIUS_REQUIRED 4 //1, 2, 4
+#define MAX_RADIUS_REQUIRED zas_settings.maxex_light_range //maxcap
+#define MIN_RADIUS_REQUIRED zas_settings.maxex_light_range/5 //1, 2, 4
/// How long the compression test can last before the machine just gives up and ejects the items.
#define COMPRESSION_TEST_TIME (SSOBJ_DT SECONDS * 5)
@@ -216,8 +216,8 @@
var/cap_multiplier = SSmapping.level_trait(location.z, ZTRAIT_BOMBCAP_MULTIPLIER)
if(isnull(cap_multiplier))
cap_multiplier = 1
- var/capped_heavy = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, heavy)
- var/capped_medium = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, medium)
+ var/capped_heavy = min(zas_settings.maxex_devastation_range * cap_multiplier, heavy)
+ var/capped_medium = min(zas_settings.maxex_heavy_range * cap_multiplier, medium)
SSexplosions.shake_the_room(location, explosion_range, (capped_heavy * 15) + (capped_medium * 20), capped_heavy, capped_medium)
if(explosion_range < required_range)
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 40c7d7b112f..0b070ddfa50 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -689,7 +689,7 @@
name = "Machine Design (HFR Core)"
desc = "The circuit board for an HFR Core."
id = "HFR_core"
- build_path = /obj/item/circuitboard/machine/HFR_core
+ //build_path = /obj/item/circuitboard/machine/HFR_core
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
@@ -697,7 +697,7 @@
name = "Machine Design (HFR fuel input)"
desc = "The circuit board for an HFR fuel input."
id = "HFR_fuel_input"
- build_path = /obj/item/circuitboard/machine/HFR_fuel_input
+ //build_path = /obj/item/circuitboard/machine/HFR_fuel_input
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
@@ -705,7 +705,7 @@
name = "Machine Design (HFR waste output)"
desc = "The circuit board for an HFR waste output."
id = "HFR_waste_output"
- build_path = /obj/item/circuitboard/machine/HFR_waste_output
+ //build_path = /obj/item/circuitboard/machine/HFR_waste_output
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
@@ -713,7 +713,7 @@
name = "Machine Design (HFR moderator input)"
desc = "The circuit board for an HFR moderator input."
id = "HFR_moderator_input"
- build_path = /obj/item/circuitboard/machine/HFR_moderator_input
+ //build_path = /obj/item/circuitboard/machine/HFR_moderator_input
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
@@ -721,7 +721,7 @@
name = "Machine Design (HFR corner)"
desc = "The circuit board for an HFR corner."
id = "HFR_corner"
- build_path = /obj/item/circuitboard/machine/HFR_corner
+ //build_path = /obj/item/circuitboard/machine/HFR_corner
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
@@ -729,7 +729,7 @@
name = "Machine Design (HFR interface)"
desc = "The circuit board for an HFR interface."
id = "HFR_interface"
- build_path = /obj/item/circuitboard/machine/HFR_interface
+ //build_path = /obj/item/circuitboard/machine/HFR_interface
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
@@ -737,7 +737,7 @@
name = "Machine Design (Crystallizer)"
desc = "The circuit board for a crystallizer."
id = "crystallizer"
- build_path = /obj/item/circuitboard/machine/crystallizer
+ //build_path = /obj/item/circuitboard/machine/crystallizer
category = list ("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
diff --git a/code/modules/research/designs/power_designs.dm b/code/modules/research/designs/power_designs.dm
index 8fb730f544a..aa1b0d9ee7f 100644
--- a/code/modules/research/designs/power_designs.dm
+++ b/code/modules/research/designs/power_designs.dm
@@ -88,7 +88,7 @@
build_type = PROTOLATHE | AUTOLATHE
materials = list(/datum/material/iron = 500)
construction_time = 100
- build_path = /obj/item/turbine_parts/compressor
+ //build_path = /obj/item/turbine_parts/compressor
category = list("Misc","Power Designs","Machinery","initial")
/datum/design/turbine_part_rotor
@@ -98,7 +98,7 @@
build_type = PROTOLATHE | AUTOLATHE
materials = list(/datum/material/iron = 500)
construction_time = 100
- build_path = /obj/item/turbine_parts/rotor
+ //build_path = /obj/item/turbine_parts/rotor
category = list("Misc","Power Designs","Machinery","initial")
/datum/design/turbine_part_stator
@@ -108,5 +108,5 @@
build_type = PROTOLATHE | AUTOLATHE
materials = list(/datum/material/iron = 500)
construction_time = 100
- build_path = /obj/item/turbine_parts/stator
+ //build_path = /obj/item/turbine_parts/stator
category = list("Misc","Power Designs","Machinery","initial")
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index 629333422dc..3f6c7257c71 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -368,15 +368,15 @@
else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
visible_message(span_warning("[src] malfunctions, melting [exp_on] and leaking hot air!"))
var/datum/gas_mixture/env = loc.return_air()
- var/transfer_moles = 0.25 * env.total_moles()
+ var/transfer_moles = 0.25 * env.get_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
- var/heat_capacity = removed.heat_capacity()
+ var/heat_capacity = removed.getHeatCapacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = min((removed.temperature*heat_capacity + 100000)/heat_capacity, 1000)
env.merge(removed)
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
investigate_log("Experimentor has released hot air.", INVESTIGATE_EXPERIMENTOR)
ejectItem(TRUE)
else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
@@ -414,15 +414,15 @@
else if(prob(EFFECT_PROB_LOW-badThingCoeff))
visible_message(span_warning("[src] malfunctions, shattering [exp_on] and leaking cold air!"))
var/datum/gas_mixture/env = loc.return_air()
- var/transfer_moles = 0.25 * env.total_moles()
+ var/transfer_moles = 0.25 * env.get_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
- var/heat_capacity = removed.heat_capacity()
+ var/heat_capacity = removed.getHeatCapacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = (removed.temperature*heat_capacity - 75000)/heat_capacity
env.merge(removed)
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
investigate_log("Experimentor has released cold air.", INVESTIGATE_EXPERIMENTOR)
ejectItem(TRUE)
else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
diff --git a/code/modules/research/ordnance/doppler_array.dm b/code/modules/research/ordnance/doppler_array.dm
index 56c93fbbe79..08103972c0e 100644
--- a/code/modules/research/ordnance/doppler_array.dm
+++ b/code/modules/research/ordnance/doppler_array.dm
@@ -284,8 +284,8 @@
// Make sure the list is indexed first.
if(reaction_data.len)
for (var/path in reaction_data[TANK_RESULTS_REACTION])
- var/datum/gas_reaction/reaction_path = path
- record_data["reaction_results"] += initial(reaction_path.name)
+ //var/datum/gas_reaction/reaction_path = path
+ record_data["reaction_results"] += "UNIMPLIMENTED - GAS REACTIONS"
if(TANK_MERGE_OVERPRESSURE in reaction_data[TANK_RESULTS_MISC])
record_data["reaction_results"] += "Tank overpressurized before reaction"
diff --git a/code/modules/research/ordnance/tank_compressor.dm b/code/modules/research/ordnance/tank_compressor.dm
index a94c28316a0..f66c66b725e 100644
--- a/code/modules/research/ordnance/tank_compressor.dm
+++ b/code/modules/research/ordnance/tank_compressor.dm
@@ -86,7 +86,7 @@
return FALSE
update_appearance()
return TRUE
-
+
/obj/machinery/atmospherics/components/binary/tank_compressor/crowbar_act(mob/living/user, obj/item/tool)
if(active || inserted_tank)
return FALSE
@@ -119,28 +119,28 @@
if(nodes[2])
nodes[2].atmos_init()
nodes[2].add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
update_appearance()
/// Glorified volume pump.
/obj/machinery/atmospherics/components/binary/tank_compressor/process_atmos()
var/datum/gas_mixture/input_air = airs[2]
- if(!input_air?.total_moles() || !active || !transfer_rate || !inserted_tank)
+ if(!input_air?.get_moles() || !active || !transfer_rate || !inserted_tank)
return
var/datum/gas_mixture/tank_air = inserted_tank.return_air()
if(!tank_air)
return
- if(input_air.return_pressure() < 0.01 || tank_air.return_pressure() > TANK_COMPRESSOR_PRESSURE_LIMIT)
+ if(input_air.returnPressure() < 0.01 || tank_air.returnPressure() > TANK_COMPRESSOR_PRESSURE_LIMIT)
return
/// Prevent pumping if tank is taking damage but still below pressure limit. Here to prevent exploiting the buffer system.
- if((inserted_tank.leaking) && (tank_air.return_pressure() <= TANK_LEAK_PRESSURE))
+ if((inserted_tank.leaking) && (tank_air.returnPressure() <= TANK_LEAK_PRESSURE))
active = FALSE
return
- var/datum/gas_mixture/removed = input_air.remove_ratio(transfer_rate / input_air.volume)
+ var/datum/gas_mixture/removed = input_air.removeRatio(transfer_rate / input_air.volume)
if(!removed)
return
@@ -160,7 +160,7 @@
return
flush_buffer()
var/datum/gas_mixture/tank_air = inserted_tank.return_air()
- last_recorded_pressure = tank_air.return_pressure()
+ last_recorded_pressure = tank_air.returnPressure()
active = FALSE
return
@@ -172,17 +172,17 @@
return COMSIG_CANCEL_EXPLOSION
/**
- * Everytime a tank is destroyed or a new tank is inserted, our buffer is flushed.
+ * Everytime a tank is destroyed or a new tank is inserted, our buffer is flushed.
* Mole requirements in experiments are tracked by buffer data.
*/
/obj/machinery/atmospherics/components/binary/tank_compressor/proc/flush_buffer()
- if(!leaked_gas_buffer.total_moles())
+ if(!leaked_gas_buffer.get_moles())
return
- if(leaked_gas_buffer.total_moles() > SIGNIFICANT_AMOUNT_OF_MOLES)
+ if(leaked_gas_buffer.get_moles() > SIGNIFICANT_AMOUNT_OF_MOLES)
record_data()
else
say("Buffer data discarded. Required moles for storage: [SIGNIFICANT_AMOUNT_OF_MOLES] moles.")
- var/datum/gas_mixture/removed = leaked_gas_buffer.remove_ratio(1)
+ var/datum/gas_mixture/removed = leaked_gas_buffer.removeRatio(1)
airs[1].merge(removed)
say("Gas stored in buffer flushed to output port. Compressor ready to start the next experiment.")
@@ -192,9 +192,9 @@
new_record.name = "Log Recording #[record_number]"
new_record.experiment_source = inserted_tank.name
new_record.timestamp = station_time_timestamp()
- for(var/gas_path in leaked_gas_buffer.gases)
- new_record.gas_data[gas_path] = leaked_gas_buffer.gases[gas_path][MOLES]
-
+ for(var/gas_path in leaked_gas_buffer.gas)
+ new_record.gas_data[gas_path] = leaked_gas_buffer.gas[gas_path]
+
compressor_record += new_record
record_number += 1
say("Buffer data stored.")
@@ -207,7 +207,7 @@
if(experiment.required_gas in gas_data)
if(gas_data[experiment.required_gas] > MINIMUM_MOLE_COUNT)
passed_experiments += list(experiment.type = gas_data[experiment.required_gas])
-
+
return passed_experiments
/obj/machinery/atmospherics/components/binary/tank_compressor/proc/print(mob/user, datum/data/compressor_record/record)
@@ -229,7 +229,7 @@
if(!inserted_tank)
return FALSE
var/datum/gas_mixture/tank_air = inserted_tank.return_air()
- if(!tank_air.return_pressure() >= PUMP_MAX_PRESSURE)
+ if(!tank_air.returnPressure() >= PUMP_MAX_PRESSURE)
return FALSE
flush_buffer()
if(user)
@@ -335,7 +335,7 @@
var/list/data = list()
data["tankPresent"] = inserted_tank ? TRUE : FALSE
var/datum/gas_mixture/tank_air = inserted_tank?.return_air()
- data["tankPressure"] = tank_air?.return_pressure()
+ data["tankPressure"] = tank_air?.returnPressure()
data["leaking"] = inserted_tank?.leaking
data["active"] = active
@@ -358,7 +358,6 @@
"gases" = list()
)
for (var/path in record.gas_data)
- var/datum/gas/gas_path = path
- single_record_data["gases"] += list(initial(gas_path.name) = record.gas_data[gas_path])
+ single_record_data["gases"] += list(path = record.gas_data[path])
data["records"] += list(single_record_data)
return data
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 5f7cf77a9d0..bac86d937f5 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -95,19 +95,19 @@
var/datum/gas_mixture/env = L.return_air()
if(env.temperature < (heat_amt+T0C))
- var/transfer_moles = 0.25 * env.total_moles()
+ var/transfer_moles = 0.25 * env.get_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
- var/heat_capacity = removed.heat_capacity()
+ var/heat_capacity = removed.getHeatCapacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000)
env.merge(removed)
- air_update_turf(FALSE, FALSE)
+ //air_update_turf(FALSE, FALSE)
/proc/fix_noid_research_servers()
var/list/no_id_servers = list()
diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm
index 8ca7afff9ba..a9a7c578af1 100644
--- a/code/modules/research/xenobiology/crossbreeding/_misc.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm
@@ -134,7 +134,7 @@ Slimecrossing Items
desc = "A mass of solidified slime gel - completely impenetrable, but it's melting away!"
icon = 'icons/obj/slimecrossing.dmi'
icon_state = "slimebarrier_thick"
- can_atmos_pass = ATMOS_PASS_NO
+ can_atmos_pass = CANPASS_NEVER
opacity = TRUE
timeleft = 100
diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm
index 9b4cfa25aa2..9e5beccb169 100644
--- a/code/modules/research/xenobiology/crossbreeding/charged.dm
+++ b/code/modules/research/xenobiology/crossbreeding/charged.dm
@@ -44,8 +44,9 @@ Charged extracts:
/obj/item/slimecross/charged/orange/do_effect(mob/user)
var/turf/targetturf = get_turf(user)
for(var/turf/turf as anything in RANGE_TURFS(5,targetturf))
- if(!locate(/obj/effect/hotspot) in turf)
- new /obj/effect/hotspot(turf)
+ /*if(!locate(/obj/effect/hotspot) in turf)
+ new /obj/effect/hotspot(turf)*/
+ turf.create_fire(1, 10)
..()
/obj/item/slimecross/charged/purple
diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm
index 3015bfd6a79..5f7b88442cb 100644
--- a/code/modules/research/xenobiology/crossbreeding/chilling.dm
+++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm
@@ -45,7 +45,8 @@ Chilling extracts:
user.visible_message(span_danger("[src] shatters, and lets out a jet of heat!"))
for(var/turf/T in orange(get_turf(user),2))
if(get_dist(get_turf(user), T) > 1)
- new /obj/effect/hotspot(T)
+ //new /obj/effect/hotspot(T)
+ T.create_fire(1, 10)
..()
/obj/item/slimecross/chilling/purple
@@ -104,14 +105,12 @@ Chilling extracts:
to_chat(user, span_warning("[src] can't affect such a large area."))
return
var/filtered = FALSE
- for(var/turf/open/T in A)
+ for(var/turf/T in A)
var/datum/gas_mixture/G = T.air
if(istype(G))
- G.assert_gas(/datum/gas/plasma)
- G.gases[/datum/gas/plasma][MOLES] = 0
+ G.setGasMoles(GAS_PLASMA, 0)
filtered = TRUE
- G.garbage_collect()
- T.air_update_turf(FALSE, FALSE)
+ //T.air_update_turf(FALSE, FALSE)
if(filtered)
user.visible_message(span_notice("Cracks spread throughout [src], and some air is sucked in!"))
else
diff --git a/code/modules/research/xenobiology/crossbreeding/regenerative.dm b/code/modules/research/xenobiology/crossbreeding/regenerative.dm
index 5e36207a44b..77ed699dc87 100644
--- a/code/modules/research/xenobiology/crossbreeding/regenerative.dm
+++ b/code/modules/research/xenobiology/crossbreeding/regenerative.dm
@@ -44,8 +44,9 @@ Regenerative extracts:
/obj/item/slimecross/regenerative/orange/core_effect_before(mob/living/target, mob/user)
target.visible_message(span_warning("The [src] boils over!"))
for(var/turf/targetturf in RANGE_TURFS(1,target))
- if(!locate(/obj/effect/hotspot) in targetturf)
- new /obj/effect/hotspot(targetturf)
+ /*if(!locate(/obj/effect/hotspot) in targetturf)
+ new /obj/effect/hotspot(targetturf)*/
+ targetturf.create_fire(1, 10)
/obj/item/slimecross/regenerative/purple
colour = "purple"
diff --git a/code/modules/shuttle/arrivals.dm b/code/modules/shuttle/arrivals.dm
index b2a0e3302db..9406fc579a9 100644
--- a/code/modules/shuttle/arrivals.dm
+++ b/code/modules/shuttle/arrivals.dm
@@ -107,7 +107,7 @@
/obj/docking_port/mobile/arrivals/proc/CheckTurfsPressure()
for(var/I in SSjob.latejoin_trackers)
var/turf/open/T = get_turf(I)
- var/pressure = T.air.return_pressure()
+ var/pressure = T.return_air().returnPressure()
if(pressure < HAZARD_LOW_PRESSURE || pressure > HAZARD_HIGH_PRESSURE) //simple safety check
return TRUE
return FALSE
diff --git a/code/modules/shuttle/docking.dm b/code/modules/shuttle/docking.dm
index 13c8fe5410b..c085cad12d7 100644
--- a/code/modules/shuttle/docking.dm
+++ b/code/modules/shuttle/docking.dm
@@ -216,3 +216,8 @@
continue
var/turf/oldT = moved_atoms[moved_object]
moved_object.lateShuttleMove(oldT, movement_force, movement_direction)
+
+
+ ///THIS IS PROBABLY NOT THE ANSWER. BUT IT WORKS AND ISN'T TERRIBLY EXPENSIVE.
+ for(var/turf/T as anything in new_turfs)
+ SSzas.mark_for_update(T)
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index 2ddc73e2527..4115beaa475 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -58,9 +58,9 @@ All ShuttleMove procs go here
var/depth = baseturfs.len - shuttle_boundary + 1
newT.CopyOnTop(src, 1, depth, TRUE)
newT.blocks_air = TRUE
- newT.air_update_turf(TRUE, FALSE)
+ //newT.air_update_turf(TRUE, FALSE)
blocks_air = TRUE
- air_update_turf(TRUE, TRUE)
+ //air_update_turf(TRUE, TRUE)
if(isopenturf(newT))
var/turf/open/new_open = newT
new_open.copy_air_with_tile(src)
@@ -86,9 +86,9 @@ All ShuttleMove procs go here
/turf/proc/lateShuttleMove(turf/oldT)
blocks_air = initial(blocks_air)
- air_update_turf(TRUE, blocks_air)
+ //air_update_turf(TRUE, blocks_air)
oldT.blocks_air = initial(oldT.blocks_air)
- oldT.air_update_turf(TRUE, oldT.blocks_air)
+ //oldT.air_update_turf(TRUE, oldT.blocks_air)
/////////////////////////////////////////////////////////////////////////////////////
@@ -254,7 +254,7 @@ All ShuttleMove procs go here
A.atmos_init()
if(A.return_pipenet())
A.add_member(src)
- SSair.add_to_rebuild_queue(src)
+ SSairmachines.add_to_rebuild_queue(src)
else
// atmos_init() calls update_appearance(), so we don't need to call it
update_appearance()
diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm
index 36afbd35010..a56a14fcd3a 100644
--- a/code/modules/surgery/organic_steps.dm
+++ b/code/modules/surgery/organic_steps.dm
@@ -141,7 +141,7 @@
/obj/item/hatchet = 'sound/surgery/scalpel1.ogg',
/obj/item/knife/butcher = 'sound/surgery/scalpel1.ogg',
/obj/item = 'sound/surgery/scalpel1.ogg',
- )
+ )
success_sound = 'sound/surgery/organ2.ogg'
/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index 7d3f569911a..47f0f73e13a 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -212,7 +212,7 @@
// Priority 1: use air from environment.
var/datum/gas_mixture/environment = owner_turf.return_air()
- if(environment && environment.return_pressure() > 30)
+ if(environment && environment.returnPressure() > 30)
ion_trail.generate_effect()
return TRUE
@@ -225,9 +225,9 @@
// Priority 3: use internals tank.
var/datum/gas_mixture/internal_mix = owner.internal.return_air()
- if(internal_mix && internal_mix.total_moles() > num)
+ if(internal_mix && internal_mix.get_moles() > num)
var/datum/gas_mixture/removed = internal_mix.remove(num)
- if(removed.total_moles() > 0.005)
+ if(removed.get_moles() > 0.005)
owner_turf.assume_air(removed)
ion_trail.generate_effect()
return TRUE
diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm
index 211a4555a2c..04489150731 100644
--- a/code/modules/surgery/organs/ears.dm
+++ b/code/modules/surgery/organs/ears.dm
@@ -10,7 +10,7 @@
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
- low_threshold_passed = "Your ears begin to resonate with an internal ring sometimes."
+ low_threshold_passed = "Your ears begin to resonate with an internal ring."
now_failing = "You are unable to hear at all!"
now_fixed = "Noise slowly begins filling your ears once more."
low_threshold_cleared = "The ringing in your ears has died down."
diff --git a/code/modules/surgery/organs/external/wings.dm b/code/modules/surgery/organs/external/wings.dm
index bca39659054..594e1cdde5a 100644
--- a/code/modules/surgery/organs/external/wings.dm
+++ b/code/modules/surgery/organs/external/wings.dm
@@ -78,7 +78,7 @@
return FALSE
var/datum/gas_mixture/environment = location.return_air()
- if(environment?.return_pressure() < HAZARD_LOW_PRESSURE + 10)
+ if(environment?.returnPressure() < HAZARD_LOW_PRESSURE + 10)
to_chat(human, span_warning("The atmosphere is too thin for you to fly!"))
return FALSE
else
@@ -202,7 +202,7 @@
if(!isspaceturf(owner.loc) && !burnt)
var/datum/gas_mixture/current = owner.loc.return_air()
- if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible
+ if(current && (current.returnPressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible
ADD_TRAIT(owner, TRAIT_FREE_FLOAT_MOVEMENT, src)
return
diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm
index aac1c76dcd0..22da13e7641 100644
--- a/code/modules/surgery/organs/lungs.dm
+++ b/code/modules/surgery/organs/lungs.dm
@@ -91,7 +91,7 @@
if(HAS_TRAIT(breather, TRAIT_NOBREATH))
return
- if(!breath || (breath.total_moles() == 0))
+ if(!breath || (breath.total_moles == 0))
if(breather.reagents.has_reagent(crit_stabilizing_reagent, needs_metabolizing = TRUE))
return
if(breather.health >= breather.crit_threshold)
@@ -110,34 +110,38 @@
breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro)
return FALSE
- for(var/gas_id in GLOB.meta_gas_info)
- breath.assert_gas(gas_id)
-
if(istype(breather.wear_mask) && (breather.wear_mask.clothing_flags & GAS_FILTERING) && breather.wear_mask.has_filter)
breath = breather.wear_mask.consume_filter(breath)
var/gas_breathed = 0
- var/list/breath_gases = breath.gases
+ var/list/breath_gases = breath.gas
+ //Handle subtypes' breath processing
+ handle_gas_override(breather, breath, gas_breathed)
+
+ //Molar count cache of our key gases
+ var/O2_moles = breath_gases[GAS_OXYGEN]
+ var/N2_moles = breath_gases[GAS_NITROGEN]
+ var/plasma_moles = breath_gases[GAS_PLASMA]
+ var/CO2_moles = breath_gases[GAS_CO2]
+ var/SA_moles = breath_gases[GAS_N2O]
//Partial pressures in our breath
- var/O2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen][MOLES])+(8*breath.get_breath_partial_pressure(breath_gases[/datum/gas/pluoxium][MOLES]))
- var/N2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrogen][MOLES])
- var/Plasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma][MOLES])
- var/CO2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide][MOLES])
+ var/O2_pp = breath.getBreathPartialPressure(O2_moles)
+ var/N2_pp = breath.getBreathPartialPressure(N2_moles)
+ var/Plasma_pp = breath.getBreathPartialPressure(plasma_moles)
+ var/CO2_pp = breath.getBreathPartialPressure(CO2_moles)
+ var/SA_pp = breath.getBreathPartialPressure(SA_moles)
//Vars for n2o and healium induced euphorias.
var/n2o_euphoria = EUPHORIA_LAST_FLAG
var/healium_euphoria = EUPHORIA_LAST_FLAG
- //Handle subtypes' breath processing
- handle_gas_override(breather,breath_gases, gas_breathed)
-
//-- OXY --//
//Too much oxygen! //Yes, some species may not like it.
if(safe_oxygen_max)
if(O2_pp > safe_oxygen_max)
- var/ratio = (breath_gases[/datum/gas/oxygen][MOLES]/safe_oxygen_max) * 10
+ var/ratio = (O2_moles/safe_oxygen_max) * 10
breather.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type)
breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy)
else
@@ -146,18 +150,18 @@
//Too little oxygen!
if(safe_oxygen_min)
if(O2_pp < safe_oxygen_min)
- gas_breathed = handle_too_little_breath(breather, O2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen][MOLES])
+ gas_breathed = handle_too_little_breath(breather, O2_pp, safe_oxygen_min, O2_moles)
breather.throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
else
breather.failed_last_breath = FALSE
if(breather.health >= breather.crit_threshold)
breather.adjustOxyLoss(-5)
- gas_breathed = breath_gases[/datum/gas/oxygen][MOLES]
+ gas_breathed = O2_moles
breather.clear_alert(ALERT_NOT_ENOUGH_OXYGEN)
//Exhale
- breath_gases[/datum/gas/oxygen][MOLES] -= gas_breathed
- breath_gases[/datum/gas/carbon_dioxide][MOLES] += gas_breathed
+ breath.adjustGas(GAS_OXYGEN, -gas_breathed, FALSE)
+ breath.adjustGas(GAS_CO2, gas_breathed, FALSE)
gas_breathed = 0
//-- Nitrogen --//
@@ -165,7 +169,7 @@
//Too much nitrogen!
if(safe_nitro_max)
if(N2_pp > safe_nitro_max)
- var/ratio = (breath_gases[/datum/gas/nitrogen][MOLES]/safe_nitro_max) * 10
+ var/ratio = (N2_moles/safe_nitro_max) * 10
breather.apply_damage_type(clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type)
breather.throw_alert(ALERT_TOO_MUCH_NITRO, /atom/movable/screen/alert/too_much_nitro)
else
@@ -174,18 +178,18 @@
//Too little nitrogen!
if(safe_nitro_min)
if(N2_pp < safe_nitro_min)
- gas_breathed = handle_too_little_breath(breather, N2_pp, safe_nitro_min, breath_gases[/datum/gas/nitrogen][MOLES])
+ gas_breathed = handle_too_little_breath(breather, N2_pp, safe_nitro_min, N2_moles)
breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro)
else
breather.failed_last_breath = FALSE
if(breather.health >= breather.crit_threshold)
breather.adjustOxyLoss(-5)
- gas_breathed = breath_gases[/datum/gas/nitrogen][MOLES]
+ gas_breathed = N2_moles
breather.clear_alert(ALERT_NOT_ENOUGH_NITRO)
//Exhale
- breath_gases[/datum/gas/nitrogen][MOLES] -= gas_breathed
- breath_gases[/datum/gas/carbon_dioxide][MOLES] += gas_breathed
+ breath.adjustGas(GAS_NITROGEN, -gas_breathed, FALSE)
+ breath.adjustGas(GAS_CO2, gas_breathed, FALSE)
gas_breathed = 0
//-- CO2 --//
@@ -211,18 +215,18 @@
//Too little CO2!
if(safe_co2_min)
if(CO2_pp < safe_co2_min)
- gas_breathed = handle_too_little_breath(breather, CO2_pp, safe_co2_min, breath_gases[/datum/gas/carbon_dioxide][MOLES])
+ gas_breathed = handle_too_little_breath(breather, CO2_pp, safe_co2_min, CO2_moles)
breather.throw_alert(ALERT_NOT_ENOUGH_CO2, /atom/movable/screen/alert/not_enough_co2)
else
breather.failed_last_breath = FALSE
if(breather.health >= breather.crit_threshold)
breather.adjustOxyLoss(-5)
- gas_breathed = breath_gases[/datum/gas/carbon_dioxide][MOLES]
+ gas_breathed = CO2_moles
breather.clear_alert(ALERT_NOT_ENOUGH_CO2)
//Exhale
- breath_gases[/datum/gas/carbon_dioxide][MOLES] -= gas_breathed
- breath_gases[/datum/gas/oxygen][MOLES] += gas_breathed
+ breath.adjustGas(GAS_CO2, -gas_breathed, FALSE)
+ breath.adjustGas(GAS_OXYGEN, gas_breathed, FALSE)
gas_breathed = 0
@@ -231,7 +235,7 @@
//Too much plasma!
if(safe_plasma_max)
if(Plasma_pp > safe_plasma_max)
- var/ratio = (breath_gases[/datum/gas/plasma][MOLES]/safe_plasma_max) * 10
+ var/ratio = (plasma_moles/safe_plasma_max) * 10
breather.apply_damage_type(clamp(ratio, plas_breath_dam_min, plas_breath_dam_max), plas_damage_type)
breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas)
else
@@ -241,28 +245,26 @@
//Too little plasma!
if(safe_plasma_min)
if(Plasma_pp < safe_plasma_min)
- gas_breathed = handle_too_little_breath(breather, Plasma_pp, safe_plasma_min, breath_gases[/datum/gas/plasma][MOLES])
+ gas_breathed = handle_too_little_breath(breather, Plasma_pp, safe_plasma_min, plasma_moles)
breather.throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas)
else
breather.failed_last_breath = FALSE
if(breather.health >= breather.crit_threshold)
breather.adjustOxyLoss(-5)
- gas_breathed = breath_gases[/datum/gas/plasma][MOLES]
+ gas_breathed = plasma_moles
breather.clear_alert(ALERT_NOT_ENOUGH_PLASMA)
//Exhale
- breath_gases[/datum/gas/plasma][MOLES] -= gas_breathed
- breath_gases[/datum/gas/carbon_dioxide][MOLES] += gas_breathed
+ breath.adjustGas(GAS_PLASMA, -gas_breathed, FALSE)
+ breath.adjustGas(GAS_CO2, gas_breathed, FALSE)
gas_breathed = 0
//-- TRACES --//
-
- if(breath) // If there's some other shit in the air lets deal with it here.
+ AIR_UPDATE_VALUES(breath)
+ if(breath.total_moles) // If there's some other shit in the air lets deal with it here.
// N2O
-
- var/SA_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrous_oxide][MOLES])
if(SA_pp > SA_para_min) // Enough to make us stunned for a bit
breather.throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o)
breather.Unconscious(60) // 60 gives them one second to wake up and run away a bit!
@@ -277,158 +279,6 @@
n2o_euphoria = EUPHORIA_INACTIVE
breather.clear_alert(ALERT_TOO_MUCH_N2O)
-
- // BZ
-
- var/bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz][MOLES])
- if(bz_pp > BZ_trip_balls_min)
- breather.hallucination += 10
- breather.reagents.add_reagent(/datum/reagent/bz_metabolites,5)
- if(bz_pp > BZ_brain_damage_min && prob(33))
- breather.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150)
-
- // Tritium
- var/trit_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/tritium][MOLES])
- // If you're breathing in half an atmosphere of radioactive gas, you fucked up.
- if (trit_pp > tritium_irradiation_moles_min && SSradiation.can_irradiate_basic(breather))
- var/lerp_scale = min(tritium_irradiation_moles_max, trit_pp - tritium_irradiation_moles_min) / (tritium_irradiation_moles_max - tritium_irradiation_moles_min)
- var/chance = LERP(tritium_irradiation_probability_min, tritium_irradiation_probability_max, lerp_scale)
- if (prob(chance))
- breather.AddComponent(/datum/component/irradiated)
-
- gas_breathed = breath_gases[/datum/gas/tritium][MOLES]
-
- if (trit_pp > 0)
- var/ratio = gas_breathed * 15
- breather.adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
-
- breath_gases[/datum/gas/tritium][MOLES] -= gas_breathed
-
- // Nitrium
- var/nitrium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrium][MOLES])
- if (prob(nitrium_pp) && nitrium_pp > 15)
- breather.adjustOrganLoss(ORGAN_SLOT_LUNGS, nitrium_pp * 0.1)
- to_chat(breather, "You feel a burning sensation in your chest")
- gas_breathed = breath_gases[/datum/gas/nitrium][MOLES]
- if (nitrium_pp > 5)
- var/existing = breather.reagents.get_reagent_amount(/datum/reagent/nitrium_low_metabolization)
- breather.reagents.add_reagent(/datum/reagent/nitrium_low_metabolization, max(0, 2 - existing))
- if (nitrium_pp > 10)
- var/existing = breather.reagents.get_reagent_amount(/datum/reagent/nitrium_high_metabolization)
- breather.reagents.add_reagent(/datum/reagent/nitrium_high_metabolization, max(0, 1 - existing))
-
- breath_gases[/datum/gas/nitrium][MOLES] -= gas_breathed
-
- // Freon
- var/freon_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/freon][MOLES])
- if (prob(freon_pp))
- to_chat(breather, span_alert("Your mouth feels like it's burning!"))
- if (freon_pp >40)
- breather.emote("gasp")
- breather.adjustFireLoss(15)
- if (prob(freon_pp/2))
- to_chat(breather, span_alert("Your throat closes up!"))
- breather.silent = max(breather.silent, 3)
- else
- breather.adjustFireLoss(freon_pp/4)
- gas_breathed = breath_gases[/datum/gas/freon][MOLES]
- if (gas_breathed > gas_stimulation_min)
- breather.reagents.add_reagent(/datum/reagent/freon,1)
-
- breath_gases[/datum/gas/freon][MOLES]-=gas_breathed
-
- // Healium
- var/healium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/healium][MOLES])
- if(healium_pp > gas_stimulation_min)
- if(prob(15))
- to_chat(breather, span_alert("Your head starts spinning and your lungs burn!"))
- healium_euphoria = EUPHORIA_ACTIVE
- breather.emote("gasp")
- else
- healium_euphoria = EUPHORIA_INACTIVE
-
- if(healium_pp > healium_para_min)
- breather.Unconscious(rand(30, 50))//not in seconds to have a much higher variation
- if(healium_pp > healium_sleep_min)
- var/existing = breather.reagents.get_reagent_amount(/datum/reagent/healium)
- breather.reagents.add_reagent(/datum/reagent/healium,max(0, 1 - existing))
- gas_breathed = breath_gases[/datum/gas/healium][MOLES]
- breath_gases[/datum/gas/healium][MOLES]-=gas_breathed
-
- // Proto Nitrate
- // Inert
- // Zauker
- var/zauker_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/zauker][MOLES])
- if(zauker_pp > gas_stimulation_min)
- var/existing = breather.reagents.get_reagent_amount(/datum/reagent/zauker)
- breather.reagents.add_reagent(/datum/reagent/zauker, max(0, 1 - existing))
- gas_breathed = breath_gases[/datum/gas/zauker][MOLES]
- breath_gases[/datum/gas/zauker][MOLES]-=gas_breathed
-
- // Halon
- var/halon_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/halon][MOLES])
- if(halon_pp > gas_stimulation_min)
- breather.adjustOxyLoss(5)
- var/existing = breather.reagents.get_reagent_amount(/datum/reagent/halon)
- breather.reagents.add_reagent(/datum/reagent/halon,max(0, 1 - existing))
- gas_breathed = breath_gases[/datum/gas/halon][MOLES]
- breath_gases[/datum/gas/halon][MOLES]-=gas_breathed
-
- // Hyper-Nob
- gas_breathed = breath_gases[/datum/gas/hypernoblium][MOLES]
- if (gas_breathed > gas_stimulation_min)
- var/existing = breather.reagents.get_reagent_amount(/datum/reagent/hypernoblium)
- breather.reagents.add_reagent(/datum/reagent/hypernoblium,max(0, 1 - existing))
- breath_gases[/datum/gas/hypernoblium][MOLES]-=gas_breathed
-
- // Miasma
- if (breath_gases[/datum/gas/miasma] && suffers_miasma)
- var/miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma][MOLES])
-
- //Miasma sickness
- if(prob(0.5 * miasma_pp))
- var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(min(round(max(miasma_pp/2, 1), 1), 6), min(round(max(miasma_pp, 1), 1), 8))
- //tl;dr the first argument chooses the smaller of miasma_pp/2 or 6(typical max virus symptoms), the second chooses the smaller of miasma_pp or 8(max virus symptom level) //
- miasma_disease.name = "Unknown"//^each argument has a minimum of 1 and rounds to the nearest value. Feel free to change the pp scaling I couldn't decide on good numbers for it.
- miasma_disease.try_infect(owner)
-
- // Miasma side effects
- switch(miasma_pp)
- if(0.25 to 5)
- // At lower pp, give out a little warning
- SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell")
- if(prob(5))
- to_chat(owner, span_notice("There is an unpleasant smell in the air."))
- if(5 to 15)
- //At somewhat higher pp, warning becomes more obvious
- if(prob(15))
- to_chat(owner, span_warning("You smell something horribly decayed inside this room."))
- SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/bad_smell)
- if(15 to 30)
- //Small chance to vomit. By now, people have internals on anyway
- if(prob(5))
- to_chat(owner, span_warning("The stench of rotting carcasses is unbearable!"))
- SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
- owner.vomit()
- if(30 to INFINITY)
- //Higher chance to vomit. Let the horror start
- if(prob(15))
- to_chat(owner, span_warning("The stench of rotting carcasses is unbearable!"))
- SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
- owner.vomit()
- else
- SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell")
-
- // In a full miasma atmosphere with 101.34 pKa, about 10 disgust per breath, is pretty low compared to threshholds
- // Then again, this is a purely hypothetical scenario and hardly reachable
- owner.adjust_disgust(0.1 * miasma_pp)
-
- breath_gases[/datum/gas/miasma][MOLES]-=gas_breathed
-
- // Clear out moods when no miasma at all
- else
- SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell")
-
if (n2o_euphoria == EUPHORIA_ACTIVE || healium_euphoria == EUPHORIA_ACTIVE)
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "chemical_euphoria", /datum/mood_event/chemical_euphoria)
else if (n2o_euphoria == EUPHORIA_INACTIVE && healium_euphoria == EUPHORIA_INACTIVE)
@@ -436,12 +286,11 @@
// Activate mood on first flag, remove on second, do nothing on third.
handle_breath_temperature(breath, breather)
- breath.garbage_collect()
return TRUE
///override this for breath handling unique to lung subtypes, breath_gas is the list of gas in the breath while gas breathed is just what is being added or removed from that list, just as they are when this is called in check_breath()
-/obj/item/organ/lungs/proc/handle_gas_override(mob/living/carbon/human/breather, list/breath_gas, gas_breathed)
+/obj/item/organ/lungs/proc/handle_gas_override(mob/living/carbon/human/breather, datum/gas_mixture/breath, gas_breathed)
return
/obj/item/organ/lungs/proc/handle_too_little_breath(mob/living/carbon/human/suffocator = null, breath_pp = 0, safe_breath_min = 0, true_pp = 0)
@@ -524,8 +373,8 @@
/obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather_slime)
. = ..()
- if (breath?.gases[/datum/gas/plasma])
- var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma][MOLES])
+ if (breath.getGroupGas(GAS_PLASMA))
+ var/plasma_pp = breath.getBreathPartialPressure(breath.getGroupGas(GAS_PLASMA))
owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you.
/obj/item/organ/lungs/skrell
@@ -612,51 +461,48 @@
/obj/item/organ/lungs/ashwalker/Initialize(mapload)
. = ..()
- var/datum/gas_mixture/immutable/planetary/mix = SSair.planetary[LAVALAND_DEFAULT_ATMOS]
+ var/datum/gas_mixture/mix = SSzas.lavaland_atmos
- if(!mix?.total_moles()) // this typically means we didn't load lavaland, like if we're using #define LOWMEMORYMODE
+ if(!mix?.get_moles()) // this typically means we didn't load lavaland, like if we're using #define LOWMEMORYMODE
return
// Take a "breath" of the air
- var/datum/gas_mixture/breath = mix.remove(mix.total_moles() * BREATH_PERCENTAGE)
-
- var/list/breath_gases = breath.gases
-
- breath.assert_gases(
- /datum/gas/oxygen,
- /datum/gas/plasma,
- /datum/gas/carbon_dioxide,
- /datum/gas/nitrogen,
- /datum/gas/bz,
- /datum/gas/miasma,
- )
-
- var/oxygen_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen][MOLES])
- var/nitrogen_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrogen][MOLES])
- var/plasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma][MOLES])
- var/carbon_dioxide_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide][MOLES])
- var/bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz][MOLES])
- var/miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma][MOLES])
-
- safe_oxygen_min = max(0, oxygen_pp - GAS_TOLERANCE)
- safe_nitro_min = max(0, nitrogen_pp - GAS_TOLERANCE)
- safe_plasma_min = max(0, plasma_pp - GAS_TOLERANCE)
+ var/datum/gas_mixture/breath = mix.remove(mix.get_moles() * BREATH_PERCENTAGE)
+
+ var/list/breath_gases = breath.gas
+ var/O2_moles = breath_gases[GAS_OXYGEN]
+ var/N2_moles = breath_gases[GAS_NITROGEN]
+ var/plasma_moles = breath_gases[GAS_PLASMA]
+ var/CO2_moles = breath_gases[GAS_CO2]
+
+ //Partial pressures in our breath
+ var/O2_pp = breath.getBreathPartialPressure(O2_moles)
+ var/N2_pp = breath.getBreathPartialPressure(N2_moles)
+ var/Plasma_pp = breath.getBreathPartialPressure(plasma_moles)
+ var/CO2_pp = breath.getBreathPartialPressure(CO2_moles)
+
+ safe_oxygen_min = max(0, O2_pp - GAS_TOLERANCE)
+ safe_nitro_min = max(0, N2_pp - GAS_TOLERANCE)
+ safe_plasma_min = max(0, Plasma_pp - GAS_TOLERANCE)
// Increase plasma tolerance based on amount in base air
- safe_plasma_max += plasma_pp
+ safe_plasma_max += Plasma_pp
// CO2 is always a waste gas, so none is required, but ashwalkers
// tolerate the base amount plus tolerance*2 (humans tolerate only 10 pp)
- safe_co2_max = carbon_dioxide_pp + GAS_TOLERANCE * 2
+ safe_co2_max = CO2_pp + GAS_TOLERANCE * 2
// The lung tolerance against BZ is also increased the amount of BZ in the base air
+ /*
BZ_trip_balls_min += bz_pp
BZ_brain_damage_min += bz_pp
+ */
// Lungs adapted to a high miasma atmosphere do not process it, and breathe it back out
- if(miasma_pp)
- suffers_miasma = FALSE
+
+ //if(miasma_pp)
+ //suffers_miasma = FALSE
#undef GAS_TOLERANCE
@@ -668,13 +514,14 @@
heat_level_2_threshold = 473
heat_level_3_threshold = 1073
-
+/*
/obj/item/organ/lungs/ethereal/handle_gas_override(mob/living/carbon/human/breather, list/breath_gases, gas_breathed)
// H2O electrolysis
gas_breathed = breath_gases[/datum/gas/water_vapor][MOLES]
breath_gases[/datum/gas/oxygen][MOLES] += gas_breathed
breath_gases[/datum/gas/hydrogen][MOLES] += gas_breathed*2
breath_gases[/datum/gas/water_vapor][MOLES] -= gas_breathed
+*/
/obj/item/organ/lungs/vox
name = "Vox lungs"
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 2d5b6a4eb85..5c4080947dd 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -69,6 +69,7 @@
#include "achievements.dm"
#include "anchored_mobs.dm"
#include "anonymous_themes.dm"
+#include "atmos_moles_tests.dm"
#include "autowiki.dm"
#include "bespoke_id.dm"
#include "binary_insert.dm"
diff --git a/code/modules/unit_tests/atmos_moles_tests.dm b/code/modules/unit_tests/atmos_moles_tests.dm
new file mode 100644
index 00000000000..927c3a68655
--- /dev/null
+++ b/code/modules/unit_tests/atmos_moles_tests.dm
@@ -0,0 +1,272 @@
+#define ALL_GASIDS xgm_gas_data.gases
+
+/datum/unit_test/atmos_machinery
+ //template = /datum/unit_test/atmos_machinery
+ var/list/test_cases = list()
+
+/datum/unit_test/atmos_machinery/Run()
+ return
+
+/datum/unit_test/atmos_machinery/proc/create_gas_mixes(gas_mix_data)
+ var/list/gas_mixes = list()
+ for(var/mix_name in gas_mix_data)
+ var/list/mix_data = gas_mix_data[mix_name]
+
+ var/datum/gas_mixture/gas_mix = new (CELL_VOLUME, mix_data["temperature"])
+
+ var/list/initial_gas = mix_data["initial_gas"]
+ if(initial_gas.len)
+ var/list/gas_args = list()
+ for(var/gasid in initial_gas)
+ gas_args += gasid
+ gas_args += initial_gas[gasid]
+ gas_mix.adjustMultipleGases(arglist(gas_args))
+
+ gas_mixes[mix_name] = gas_mix
+ return gas_mixes
+
+/datum/unit_test/atmos_machinery/proc/gas_amount_changes(list/before_gas_mixes, list/after_gas_mixes)
+ var/list/result = list()
+ for(var/mix_name in before_gas_mixes & after_gas_mixes)
+ var/change = list()
+
+ var/datum/gas_mixture/before = before_gas_mixes[mix_name]
+ var/datum/gas_mixture/after = after_gas_mixes[mix_name]
+
+ var/list/all_gases = before.gas | after.gas
+ for(var/gasid in all_gases)
+ change[gasid] = after.getGroupGas(gasid) - before.getGroupGas(gasid)
+
+ result[mix_name] = change
+
+ return result
+
+/datum/unit_test/atmos_machinery/proc/check_moles_conserved(case_name, list/before_gas_mixes, list/after_gas_mixes)
+ var/failed = FALSE
+ for(var/gasid in xgm_gas_data.gases)
+ var/before = 0
+ for(var/gasmix in before_gas_mixes)
+ var/datum/gas_mixture/G = before_gas_mixes[gasmix]
+ before += G.getGroupGas(gasid)
+
+ var/after = 0
+ for(var/gasmix in after_gas_mixes)
+ var/datum/gas_mixture/G = after_gas_mixes[gasmix]
+ after += G.getGroupGas(gasid)
+
+ if(abs(before - after) > ATMOS_PRECISION)
+ Fail("expected [before] moles of [gasid], found [after] moles.")
+ failed |= TRUE
+
+ if(!failed)
+ pass("conserved moles of each gas ID.")
+
+/datum/unit_test/atmos_machinery/conserve_moles
+ //template = /datum/unit_test/atmos_machinery/conserve_moles
+ test_cases = list(
+ uphill = list(
+ source = list(
+ initial_gas = list(
+ GAS_OXYGEN = 5,
+ GAS_NITROGEN = 10,
+ GAS_CO2 = 5,
+ GAS_PHORON = 10,
+ GAS_N2O = 5,
+ ),
+ temperature = T20C - 5,
+ ),
+ sink = list(
+ initial_gas = list(
+ GAS_OXYGEN = 10,
+ GAS_NITROGEN = 20,
+ GAS_CO2 = 10,
+ GAS_PHORON = 20,
+ GAS_N2O = 10,
+ ),
+ temperature = T20C + 5,
+ )
+ ),
+ downhill = list(
+ source = list(
+ initial_gas = list(
+ GAS_OXYGEN = 10,
+ GAS_NITROGEN = 20,
+ GAS_CO2 = 10,
+ GAS_PHORON = 20,
+ GAS_N2O = 10,
+ ),
+ temperature = T20C + 5,
+ ),
+ sink = list(
+ initial_gas = list(
+ GAS_OXYGEN = 5,
+ GAS_NITROGEN = 10,
+ GAS_CO2 = 5,
+ GAS_PHORON = 10,
+ GAS_N2O = 5,
+ ),
+ temperature = T20C - 5,
+ ),
+ ),
+ flat = list(
+ source = list(
+ initial_gas = list(
+ GAS_OXYGEN = 10,
+ GAS_NITROGEN = 20,
+ GAS_CO2 = 10,
+ GAS_PHORON = 20,
+ GAS_N2O = 10,
+ ),
+ temperature = T20C,
+ ),
+ sink = list(
+ initial_gas = list(
+ GAS_OXYGEN = 10,
+ GAS_NITROGEN = 20,
+ GAS_CO2 = 10,
+ GAS_PHORON = 20,
+ GAS_N2O = 10,
+ ),
+ temperature = T20C,
+ ),
+ ),
+ vacuum_sink = list(
+ source = list(
+ initial_gas = list(
+ GAS_OXYGEN = 10,
+ GAS_NITROGEN = 20,
+ GAS_CO2 = 10,
+ GAS_PHORON = 20,
+ GAS_N2O = 10,
+ ),
+ temperature = T20C,
+ ),
+ sink = list(
+ initial_gas = list(),
+ temperature = 0,
+ ),
+ ),
+ vacuum_source = list(
+ source = list(
+ initial_gas = list(),
+ temperature = 0,
+ ),
+ sink = list(
+ initial_gas = list(
+ GAS_OXYGEN = 10,
+ GAS_NITROGEN = 20,
+ GAS_CO2 = 10,
+ GAS_PHORON = 20,
+ GAS_N2O = 10,
+ ),
+ temperature = T20C,
+ ),
+ ),
+ )
+
+/datum/unit_test/atmos_machinery/conserve_moles/Run()
+ return
+
+/datum/unit_test/atmos_machinery/conserve_moles/pump_gas
+ //name = "ATMOS MACHINERY: pump_gas() Conserves Moles"
+
+/datum/unit_test/atmos_machinery/conserve_moles/pump_gas/Run()
+ for(var/case_name in test_cases)
+ var/gas_mix_data = test_cases[case_name]
+ var/list/before_gas_mixes = create_gas_mixes(gas_mix_data)
+ var/list/after_gas_mixes = create_gas_mixes(gas_mix_data)
+
+ pump_gas(after_gas_mixes["source"], after_gas_mixes["sink"], null, INFINITY)
+
+ check_moles_conserved(case_name, before_gas_mixes, after_gas_mixes)
+
+ return 1
+
+/datum/unit_test/atmos_machinery/conserve_moles/pump_gas_passive
+ //name = "ATMOS MACHINERY: pump_gas_passive() Conserves Moles"
+
+/datum/unit_test/atmos_machinery/conserve_moles/pump_gas_passive/Run()
+ for(var/case_name in test_cases)
+ var/gas_mix_data = test_cases[case_name]
+ var/list/before_gas_mixes = create_gas_mixes(gas_mix_data)
+ var/list/after_gas_mixes = create_gas_mixes(gas_mix_data)
+
+ pump_gas_passive(after_gas_mixes["source"], after_gas_mixes["sink"], null)
+
+ check_moles_conserved(case_name, before_gas_mixes, after_gas_mixes)
+
+ return 1
+
+/datum/unit_test/atmos_machinery/conserve_moles/scrub_gas
+ //name = "ATMOS MACHINERY: scrub_gas() Conserves Moles"
+
+/datum/unit_test/atmos_machinery/conserve_moles/scrub_gas/Run()
+ var/list/filtering = xgm_gas_data.gases
+
+ for(var/case_name in test_cases)
+ var/gas_mix_data = test_cases[case_name]
+ var/list/before_gas_mixes = create_gas_mixes(gas_mix_data)
+ var/list/after_gas_mixes = create_gas_mixes(gas_mix_data)
+
+ scrub_gas(filtering, after_gas_mixes["source"], after_gas_mixes["sink"], null, INFINITY)
+
+ check_moles_conserved(case_name, before_gas_mixes, after_gas_mixes)
+
+ return 1
+
+/datum/unit_test/atmos_machinery/conserve_moles/filter_gas
+// name = "ATMOS MACHINERY: filter_gas() Conserves Moles"
+
+/datum/unit_test/atmos_machinery/conserve_moles/filter_gas/Run()
+ var/list/filtering = xgm_gas_data.gases
+
+ for(var/case_name in test_cases)
+ var/gas_mix_data = test_cases[case_name]
+ var/list/before_gas_mixes = create_gas_mixes(gas_mix_data)
+ var/list/after_gas_mixes = create_gas_mixes(gas_mix_data)
+
+ filter_gas(filtering, after_gas_mixes["source"], after_gas_mixes["sink"], after_gas_mixes["source"], null, INFINITY)
+
+ check_moles_conserved(case_name, before_gas_mixes, after_gas_mixes)
+
+ return 1
+
+/datum/unit_test/atmos_machinery/conserve_moles/filter_gas_multi
+ //name = "ATMOS MACHINERY: filter_gas_multi() Conserves Moles"
+
+/datum/unit_test/atmos_machinery/conserve_moles/filter_gas_multi/Run()
+ for(var/case_name in test_cases)
+ var/gas_mix_data = test_cases[case_name]
+ var/list/before_gas_mixes = create_gas_mixes(gas_mix_data)
+ var/list/after_gas_mixes = create_gas_mixes(gas_mix_data)
+
+ var/list/filtering = list()
+ for(var/gasid in xgm_gas_data.gases)
+ filtering[gasid] = after_gas_mixes["sink"] //just filter everything to sink
+
+ filter_gas_multi(filtering, after_gas_mixes["source"], after_gas_mixes["sink"], null, INFINITY)
+
+ check_moles_conserved(case_name, before_gas_mixes, after_gas_mixes)
+
+ return 1
+
+/datum/unit_test/atmos_machinery/conserve_moles/mix_gas
+ //name = "ATMOS MACHINERY: mix_gas() Conserves Moles"
+
+/datum/unit_test/atmos_machinery/conserve_moles/mix_gas/Run()
+ for(var/case_name in test_cases)
+ var/gas_mix_data = test_cases[case_name]
+ var/list/before_gas_mixes = create_gas_mixes(gas_mix_data)
+ var/list/after_gas_mixes = create_gas_mixes(gas_mix_data)
+
+ var/list/mix_sources = list()
+ for(var/gasid in ALL_GASIDS)
+ var/datum/gas_mixture/mix_source = after_gas_mixes["sink"]
+ mix_sources[mix_source] = 1.0/xgm_gas_data.gases.len //doesn't work as a macro for some reason
+
+ mix_gas(mix_sources, after_gas_mixes["sink"], null, INFINITY)
+
+ check_moles_conserved(case_name, before_gas_mixes, after_gas_mixes)
+
+ return 1
+#undef ALL_GASIDS
diff --git a/code/modules/unit_tests/breath.dm b/code/modules/unit_tests/breath.dm
index d564b291a60..fa7994e43f1 100644
--- a/code/modules/unit_tests/breath.dm
+++ b/code/modules/unit_tests/breath.dm
@@ -24,13 +24,12 @@
var/turf/open/to_fill = run_loc_floor_bottom_left
//Prep the floor
- to_fill.initial_gas_mix = OPENTURF_DEFAULT_ATMOS
- to_fill.air = new
- to_fill.air.copy_from_turf(to_fill)
+ to_fill.initial_gas = OPENTURF_DEFAULT_ATMOS
+ to_fill.make_air()
lab_rat.breathe()
- TEST_ASSERT(!lab_rat.has_alert(ALERT_NOT_ENOUGH_OXYGEN), "Humans can't get a full breath from the standard initial_gas_mix on a turf")
+ TEST_ASSERT(!lab_rat.has_alert(ALERT_NOT_ENOUGH_OXYGEN), "Humans can't get a full breath from the standard initial_gas on a turf. Turf: [to_fill.type] | Air: [json_encode(to_fill.air.gas)] | Returned Air: [json_encode(to_fill.return_air().gas)]")
/// Tests to make sure plasmaman can breath from their internal tanks
/datum/unit_test/breath_sanity_plasmamen
@@ -64,16 +63,26 @@
var/turf/open/to_fill = run_loc_floor_bottom_left
//Prep the floor
- to_fill.initial_gas_mix = LAVALAND_DEFAULT_ATMOS
- to_fill.air = new
- to_fill.air.copy_from_turf(to_fill)
+ to_fill.initial_gas = SSzas.lavaland_atmos.gas
+ to_fill.make_air()
lab_rat.breathe()
+ var/list/reason
+ if(lab_rat.has_alert(ALERT_NOT_ENOUGH_OXYGEN))
+ if(!to_fill.return_air())
+ return Fail("Assertion Failed: Turf failed to return air. Type: [to_fill.type], Initial Gas: [json_encode(to_fill.initial_gas)]")
- TEST_ASSERT(!lab_rat.has_alert(ALERT_NOT_ENOUGH_OXYGEN), "Ashwalkers can't get a full breath from the Lavaland's initial_gas_mix on a turf")
+ var/datum/gas_mixture/turf_gas = to_fill.return_air()
+ LAZYADD(reason, "Turf mix: [json_encode(turf_gas.gas)] | T: [turf_gas.temperature] | P: [turf_gas.returnPressure()] | Initial Gas: [json_encode(to_fill.initial_gas)]")
+
+ if(lab_rat.loc != to_fill)
+ LAZYADD(reason, "Rat was not located on it's intended turf!")
+
+ if(reason)
+ return Fail("Assertion Failed: [reason.Join(";")]", __FILE__, __LINE__)
/datum/unit_test/breath_sanity_ashwalker/Destroy()
- //Reset initial_gas_mix to avoid future issues on other tests
+ //Reset initial_gas to avoid future issues on other tests
var/turf/open/to_fill = run_loc_floor_bottom_left
- to_fill.initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+ to_fill.initial_gas = OPENTURF_DEFAULT_ATMOS
return ..()
diff --git a/code/modules/unit_tests/gas_transfer.dm b/code/modules/unit_tests/gas_transfer.dm
index 32f973d7244..52634f090fe 100644
--- a/code/modules/unit_tests/gas_transfer.dm
+++ b/code/modules/unit_tests/gas_transfer.dm
@@ -2,31 +2,30 @@
/datum/unit_test/atmospheric_gas_transfer
/datum/unit_test/atmospheric_gas_transfer/Run()
+ /*
for (var/tempNmoles in list(1e4, 1e6, 1e8, 1e10, 1e12))
var/datum/gas_mixture/first_mix = allocate(/datum/gas_mixture)
var/datum/gas_mixture/second_mix = allocate(/datum/gas_mixture)
first_mix.volume = 200
second_mix.volume = 200
-
- ASSERT_GAS(/datum/gas/hypernoblium, first_mix)
- ASSERT_GAS(/datum/gas/tritium, second_mix)
- first_mix.gases[/datum/gas/hypernoblium][MOLES] = tempNmoles
- second_mix.gases[/datum/gas/tritium][MOLES] = 200
+ first_mix.adjustGas(GAS_OXYGEN, tempNmoles)
+ second_mix.adjustGas(GAS_NITROGEN, 200)
first_mix.temperature = tempNmoles
second_mix.temperature = T20C
- var/initial_pressure = second_mix.return_pressure()
+ var/initial_pressure = second_mix.returnPressure()
// A constant value would be nicer but there will be cases when even MOLAR_ACCURACY amounts would far exceed the pressure so we need to scale it somewhat.
var/additional_pressure = (tempNmoles / 1000) + 500
-
+
/* ERROR MARGIN CALCULATION
* We calculate how much would the pressure change if MOLAR_ACCURACY amount of hothotgas is imparted on the cold mix.
* This number gets really big for very high temperatures so it's somewhat meaningless, but our main goal is to ensure the code doesn't break.
- */
+ */
var/error_margin = first_mix.gas_pressure_minimum_transfer(second_mix) - initial_pressure
-
+
first_mix.pump_gas_to(second_mix, (initial_pressure + additional_pressure))
- var/margin = abs(second_mix.return_pressure() - (initial_pressure+additional_pressure))
+ var/margin = abs(second_mix.returnPressure() - (initial_pressure+additional_pressure))
- TEST_ASSERT(margin<=error_margin, "Gas pressure pumping test failed for [tempNmoles]. Expected pressure = [initial_pressure+additional_pressure] +/- [error_margin]. Got [second_mix.return_pressure()].")
+ TEST_ASSERT(margin<=error_margin, "Gas pressure pumping test failed for [tempNmoles]. Expected pressure = [initial_pressure+additional_pressure] +/- [error_margin]. Got [second_mix.returnPressure()].")
+ */
diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm
index 4359d2f1de0..71f5a2bf5a3 100644
--- a/code/modules/unit_tests/unit_test.dm
+++ b/code/modules/unit_tests/unit_test.dm
@@ -127,6 +127,8 @@ GLOBAL_LIST_EMPTY(unit_test_mapping_logs)
qdel(test)
/proc/RunUnitTests()
+ SSairflow.pause() //Look man, shit's whack. I don't trust airflow to not displace things when it shouldn't.
+
CHECK_TICK
var/list/tests_to_run = subtypesof(/datum/unit_test)
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 28ebd761d9f..e8c6da6b46e 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -215,9 +215,7 @@
cabin_air = new
cabin_air.volume = 200
cabin_air.temperature = T20C
- cabin_air.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
- cabin_air.gases[/datum/gas/oxygen][MOLES] = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
- cabin_air.gases[/datum/gas/nitrogen][MOLES] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
+ cabin_air.adjustMultipleGases(GAS_OXYGEN, (O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)), GAS_NITROGEN, (N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)))
add_cell()
add_scanmod()
@@ -234,7 +232,6 @@
diag_hud_set_mechstat()
update_appearance()
- AddElement(/datum/element/atmos_sensitive, mapload)
become_hearing_sensitive(trait_source = ROUNDSTART_TRAIT)
ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, ROUNDSTART_TRAIT) //protects pilots from ashstorms.
for(var/key in equip_by_category)
@@ -430,20 +427,20 @@
clear_internal_damage(MECHA_INT_FIRE)
if(internal_tank)
var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
- if(int_tank_air.return_pressure() > internal_tank.maximum_pressure && !(internal_damage & MECHA_INT_TANK_BREACH))
+ if(int_tank_air.returnPressure() > internal_tank.maximum_pressure && !(internal_damage & MECHA_INT_TANK_BREACH))
set_internal_damage(MECHA_INT_TANK_BREACH)
- if(int_tank_air && int_tank_air.return_volume() > 0) //heat the air_contents
+ if(int_tank_air && int_tank_air.get_volume() > 0) //heat the air_contents
int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(5,7.5)*delta_time)
- if(cabin_air && cabin_air.return_volume()>0)
- cabin_air.temperature = min(6000+T0C, cabin_air.return_temperature()+rand(5,7.5)*delta_time)
- if(cabin_air.return_temperature() > max_temperature/2)
- take_damage(delta_time*2/round(max_temperature/cabin_air.return_temperature(),0.1), BURN, 0, 0)
+ if(cabin_air && cabin_air.get_volume()>0)
+ cabin_air.temperature = min(6000+T0C, cabin_air.get_temperature()+rand(5,7.5)*delta_time)
+ if(cabin_air.get_temperature() > max_temperature/2)
+ take_damage(delta_time*2/round(max_temperature/cabin_air.get_temperature(),0.1), BURN, 0, 0)
if(internal_damage & MECHA_INT_TANK_BREACH) //remove some air from internal tank
if(internal_tank)
var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
- var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(DT_PROB_RATE(0.05, delta_time))
+ var/datum/gas_mixture/leaked_gas = int_tank_air.removeRatio(DT_PROB_RATE(0.05, delta_time))
if(loc)
loc.assume_air(leaked_gas)
else
@@ -456,7 +453,7 @@
cell.maxcharge -= min(10 * delta_time, cell.maxcharge)
if(!(internal_damage & MECHA_INT_TEMP_CONTROL))
- if(cabin_air && cabin_air.return_volume() > 0)
+ if(cabin_air && cabin_air.get_volume() > 0)
var/delta = cabin_air.temperature - T20C
cabin_air.temperature -= clamp(round(delta / 8, 0.1), -5, 5) * delta_time
@@ -464,21 +461,21 @@
var/datum/gas_mixture/tank_air = internal_tank.return_air()
var/release_pressure = internal_tank_valve
- var/cabin_pressure = cabin_air.return_pressure()
- var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2)
+ var/cabin_pressure = cabin_air.returnPressure()
+ var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.returnPressure() - cabin_pressure)/2)
var/transfer_moles = 0
if(pressure_delta > 0) //cabin pressure lower than release pressure
- if(tank_air.return_temperature() > 0)
- transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
+ if(tank_air.temperature > 0)
+ transfer_moles = pressure_delta*cabin_air.volume/(cabin_air.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
cabin_air.merge(removed)
else if(pressure_delta < 0) //cabin pressure higher than release pressure
var/datum/gas_mixture/t_air = return_air()
pressure_delta = cabin_pressure - release_pressure
if(t_air)
- pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta)
+ pressure_delta = min(cabin_pressure - t_air.returnPressure(), pressure_delta)
if(pressure_delta > 0) //if location pressure is lower than cabin pressure
- transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
+ transfer_moles = pressure_delta*cabin_air.volume/(cabin_air.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles)
if(t_air)
t_air.merge(removed)
@@ -1231,14 +1228,14 @@
return cabin_air
///fetches pressure of the gas mixture we are using
-/obj/vehicle/sealed/mecha/proc/return_pressure()
+/obj/vehicle/sealed/mecha/proc/returnPressure()
var/datum/gas_mixture/air = return_air()
- return air?.return_pressure()
+ return air?.returnPressure()
///fetches temp of the gas mixture we are using
/obj/vehicle/sealed/mecha/return_temperature()
var/datum/gas_mixture/air = return_air()
- return air?.return_temperature()
+ return air?.temperature
diff --git a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm
index 3b28c661952..827673abe33 100644
--- a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm
+++ b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm
@@ -123,7 +123,8 @@
shake_camera(shaken, 3, 3)
var/turf/launch_turf = get_turf(chassis)
- new /obj/effect/hotspot(launch_turf)
+ //new /obj/effect/hotspot(launch_turf)
+ launch_turf.create_fire(1, 10)
launch_turf.hotspot_expose(700, 50, 1)
new /obj/effect/skyfall_landingzone(launch_turf, chassis)
chassis.resistance_flags |= INDESTRUCTIBLE //not while jumping at least
diff --git a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
index 276138e8b2d..d1b9f463f5f 100644
--- a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
+++ b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
@@ -447,7 +447,7 @@
if(!chassis || !chassis.internal_tank)
return FALSE
var/datum/gas_mixture/our_mix = chassis.internal_tank.return_air()
- var/moles = our_mix.total_moles()
+ var/moles = our_mix.total_moles
if(moles < move_cost)
our_mix.remove(moles)
return FALSE
diff --git a/code/modules/vehicles/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm
index eef2a1de549..0f10ed65ae1 100644
--- a/code/modules/vehicles/mecha/mecha_control_console.dm
+++ b/code/modules/vehicles/mecha/mecha_control_console.dm
@@ -29,7 +29,7 @@
name = M.name,
integrity = round((M.get_integrity() / M.max_integrity) * 100),
charge = M.cell ? round(M.cell.percent()) : null,
- airtank = M.internal_tank ? M.return_pressure() : null,
+ airtank = M.internal_tank ? M.returnPressure() : null,
pilot = M.return_drivers(),
location = get_area_name(M, TRUE),
emp_recharging = MT.recharging,
@@ -96,7 +96,7 @@
var/answer = {"Name: [chassis.name] Integrity: [round((chassis.get_integrity()/chassis.max_integrity * 100), 0.01)]% Cell Charge: [isnull(cell_charge) ? "Not Found":"[chassis.cell.percent()]%"]
- Airtank: [chassis.internal_tank ? "[round(chassis.return_pressure(), 0.01)]" : "Not Equipped"] kPa
+ Airtank: [chassis.internal_tank ? "[round(chassis.returnPressure(), 0.01)]" : "Not Equipped"] kPa Pilot: [chassis.return_drivers() || "None"] Location: [get_area_name(chassis, TRUE) || "Unknown"]"}
if(istype(chassis, /obj/vehicle/sealed/mecha/working/ripley))
diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm
index 61411b077cd..ee3e99da778 100644
--- a/code/modules/vehicles/mecha/mecha_defense.dm
+++ b/code/modules/vehicles/mecha/mecha_defense.dm
@@ -192,11 +192,13 @@
equipment_disabled = TRUE
/obj/vehicle/sealed/mecha/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
- return exposed_temperature > max_temperature
+ if(exposed_temperature > max_temperature)
+ return TRUE
/obj/vehicle/sealed/mecha/atmos_expose(datum/gas_mixture/air, exposed_temperature)
- log_message("Exposed to dangerous temperature.", LOG_MECHA, color="red")
- take_damage(5, BURN, 0, 1)
+ if(exposed_temperature > max_temperature)
+ log_message("Exposed to dangerous temperature.", LOG_MECHA, color="red")
+ take_damage(5, BURN, 0, 1)
/obj/vehicle/sealed/mecha/attackby_secondary(obj/item/weapon, mob/user, params)
if(istype(weapon, /obj/item/mecha_parts))
diff --git a/code/modules/vehicles/mecha/mecha_ui.dm b/code/modules/vehicles/mecha/mecha_ui.dm
index 35fcc68a3a5..0182b5b8f69 100644
--- a/code/modules/vehicles/mecha/mecha_ui.dm
+++ b/code/modules/vehicles/mecha/mecha_ui.dm
@@ -116,10 +116,10 @@
data["mecha_flags"] = mecha_flags
data["internal_damage"] = internal_damage
data["air_source"] = use_internal_tank ? "Internal Airtank" : "Environment"
- data["airtank_pressure"] = int_tank_air ? round(int_tank_air.return_pressure(), 0.01) : null
+ data["airtank_pressure"] = int_tank_air ? round(int_tank_air.returnPressure(), 0.01) : null
data["airtank_temp"] = int_tank_air?.temperature
data["port_connected"] = internal_tank?.connected_port ? TRUE : FALSE
- data["cabin_pressure"] = round(return_pressure(), 0.01)
+ data["cabin_pressure"] = round(returnPressure(), 0.01)
data["cabin_temp"] = return_temperature()
data["dna_lock"] = dna_lock
data["mech_view"] = ui_view.assigned_map
diff --git a/code/modules/wiremod/components/sensors/pressuresensor.dm b/code/modules/wiremod/components/sensors/pressuresensor.dm
index 06e45cc688a..7d733f369d8 100644
--- a/code/modules/wiremod/components/sensors/pressuresensor.dm
+++ b/code/modules/wiremod/components/sensors/pressuresensor.dm
@@ -24,8 +24,8 @@
return
//Get environment info
var/datum/gas_mixture/environment = location.return_air()
- var/total_moles = environment.total_moles()
- var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles
+ var/pressure = environment.returnPressure()
if(total_moles)
//If there's atmos, return pressure
result.set_output(round(pressure,1))
diff --git a/code/modules/wiremod/components/sensors/tempsensor.dm b/code/modules/wiremod/components/sensors/tempsensor.dm
index e88d5dea1c3..c84282582cb 100644
--- a/code/modules/wiremod/components/sensors/tempsensor.dm
+++ b/code/modules/wiremod/components/sensors/tempsensor.dm
@@ -24,7 +24,7 @@
return
//Get environment info
var/datum/gas_mixture/environment = location.return_air()
- var/total_moles = environment.total_moles()
+ var/total_moles = environment.total_moles
if(total_moles)
//If there's atmos, return temperature
result.set_output(round(environment.temperature,1))
diff --git a/config/admins.txt b/config/admins.txt
index 9a6f0eb28a2..5f7377aa202 100644
--- a/config/admins.txt
+++ b/config/admins.txt
@@ -5,3 +5,5 @@
#If SQL-based admin loading is enabled, admins listed here will always be loaded first and will override any duplicate entries in the database.
Octus = Host
+Francinum = Host
+Gonenoculer5 = Host
\ No newline at end of file
diff --git a/config/game_options.txt b/config/game_options.txt
index 0d246725aec..5777c639830 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -403,7 +403,7 @@ REACTIONARY_EXPLOSIONS
## eg: If you give the number 20. The bomb cap will be 5,10,20.
## Can be any number above 4, some examples are provided below.
-## Small (3, 7, 14)
+## Small (4, 8, 16)
#BOMBCAP 14
## Default (5, 10, 20) (recommended if you enable REACTIONARY_EXPLOSIONS above)
BOMBCAP 20
diff --git a/config/maps.txt b/config/maps.txt
index 58cd6676cc3..bf2428dec61 100644
--- a/config/maps.txt
+++ b/config/maps.txt
@@ -42,6 +42,12 @@ endmap
map runtimestation
endmap
+map atmostest
+endmap
+
+map atmostest_multiz
+endmap
+
map multiz_debug
endmap
diff --git a/html/changelogs/archive/2020-03.yml b/html/changelogs/archive/2020-03.yml
index bae4ee0a1e0..8b9b02ab488 100644
--- a/html/changelogs/archive/2020-03.yml
+++ b/html/changelogs/archive/2020-03.yml
@@ -737,7 +737,7 @@
- bugfix: Fixed runtime on donutstation caused by mistype in dmm file
2020-03-26:
Dennok:
- - code_imp: now copy_from(target, partial) can copy part of target gas moles
+ - code_imp: now copyFrom(target, partial) can copy part of target gas moles
Detective-Google:
- code_imp: shotgun's weapon_weight variable being defined twice
Fikou:
diff --git a/icons/obj/atmospherics/components/idle2_cc_-_Copy.dmi b/icons/obj/atmospherics/components/idle2_cc_-_Copy.dmi
new file mode 100644
index 00000000000..6e3cd7c45a9
Binary files /dev/null and b/icons/obj/atmospherics/components/idle2_cc_-_Copy.dmi differ
diff --git a/icons/obj/atmospherics/components/unary_devices.dmi b/icons/obj/atmospherics/components/unary_devices.dmi
index 3350500fde9..e3215f57990 100644
Binary files a/icons/obj/atmospherics/components/unary_devices.dmi and b/icons/obj/atmospherics/components/unary_devices.dmi differ
diff --git a/icons/obj/machines/rust/160x160.dmi b/icons/obj/machines/rust/160x160.dmi
new file mode 100644
index 00000000000..4d1c433dc5d
Binary files /dev/null and b/icons/obj/machines/rust/160x160.dmi differ
diff --git a/icons/obj/machines/rust/224x224.dmi b/icons/obj/machines/rust/224x224.dmi
new file mode 100644
index 00000000000..14ac5100a9a
Binary files /dev/null and b/icons/obj/machines/rust/224x224.dmi differ
diff --git a/icons/obj/machines/rust/288x288.dmi b/icons/obj/machines/rust/288x288.dmi
new file mode 100644
index 00000000000..d2169ef032a
Binary files /dev/null and b/icons/obj/machines/rust/288x288.dmi differ
diff --git a/icons/obj/machines/rust/352x352.dmi b/icons/obj/machines/rust/352x352.dmi
new file mode 100644
index 00000000000..b5e369d91d3
Binary files /dev/null and b/icons/obj/machines/rust/352x352.dmi differ
diff --git a/icons/obj/machines/rust/416x416.dmi b/icons/obj/machines/rust/416x416.dmi
new file mode 100644
index 00000000000..93f4ba7d521
Binary files /dev/null and b/icons/obj/machines/rust/416x416.dmi differ
diff --git a/icons/obj/machines/rust/96x96.dmi b/icons/obj/machines/rust/96x96.dmi
new file mode 100644
index 00000000000..764f03c1916
Binary files /dev/null and b/icons/obj/machines/rust/96x96.dmi differ
diff --git a/icons/obj/machines/rust/fuel_rod.dmi b/icons/obj/machines/rust/fuel_rod.dmi
new file mode 100644
index 00000000000..7e48b39f9ca
Binary files /dev/null and b/icons/obj/machines/rust/fuel_rod.dmi differ
diff --git a/icons/obj/machines/rust/fusion.dmi b/icons/obj/machines/rust/fusion.dmi
new file mode 100644
index 00000000000..bd1131a1e6a
Binary files /dev/null and b/icons/obj/machines/rust/fusion.dmi differ
diff --git a/icons/obj/machines/rust/fusion_core.dmi b/icons/obj/machines/rust/fusion_core.dmi
new file mode 100644
index 00000000000..76904a1200d
Binary files /dev/null and b/icons/obj/machines/rust/fusion_core.dmi differ
diff --git a/modular_pariah/master_files/code/game/sound.dm b/modular_pariah/master_files/code/game/sound.dm
index fd542f6f946..7434392cd0c 100644
--- a/modular_pariah/master_files/code/game/sound.dm
+++ b/modular_pariah/master_files/code/game/sound.dm
@@ -9,4 +9,12 @@
'modular_pariah/modules/aesthetics/computer/sound/keypress4.ogg',
'modular_pariah/modules/aesthetics/computer/sound/keystroke4.ogg',
)
+ if(SFX_GLASS_CRACK)
+ soundin = pick(
+ 'modular_pariah/master_files/sound/effects/glass_crack1.ogg',
+ 'modular_pariah/master_files/sound/effects/glass_crack2.ogg',
+ 'modular_pariah/master_files/sound/effects/glass_crack3.ogg',
+ 'modular_pariah/master_files/sound/effects/glass_crack4.ogg',
+ )
+
return soundin
diff --git a/modular_pariah/master_files/icons/effects/contamination.dmi b/modular_pariah/master_files/icons/effects/contamination.dmi
new file mode 100644
index 00000000000..367394213be
Binary files /dev/null and b/modular_pariah/master_files/icons/effects/contamination.dmi differ
diff --git a/modular_pariah/master_files/icons/effects/fire.dmi b/modular_pariah/master_files/icons/effects/fire.dmi
new file mode 100644
index 00000000000..90e3bb41259
Binary files /dev/null and b/modular_pariah/master_files/icons/effects/fire.dmi differ
diff --git a/modular_pariah/master_files/icons/effects/gas_overlays.dmi b/modular_pariah/master_files/icons/effects/gas_overlays.dmi
new file mode 100644
index 00000000000..1e5684036df
Binary files /dev/null and b/modular_pariah/master_files/icons/effects/gas_overlays.dmi differ
diff --git a/modular_pariah/master_files/icons/obj/inflatable.dmi b/modular_pariah/master_files/icons/obj/inflatable.dmi
new file mode 100644
index 00000000000..403e39c6378
Binary files /dev/null and b/modular_pariah/master_files/icons/obj/inflatable.dmi differ
diff --git a/modular_pariah/master_files/icons/testing/Zone.dmi b/modular_pariah/master_files/icons/testing/Zone.dmi
new file mode 100644
index 00000000000..1d8ab851669
Binary files /dev/null and b/modular_pariah/master_files/icons/testing/Zone.dmi differ
diff --git a/modular_pariah/master_files/icons/testing/air_meter.dmi b/modular_pariah/master_files/icons/testing/air_meter.dmi
new file mode 100644
index 00000000000..56d1ff18a59
Binary files /dev/null and b/modular_pariah/master_files/icons/testing/air_meter.dmi differ
diff --git a/modular_pariah/master_files/icons/testing/atmos_testing.dmi b/modular_pariah/master_files/icons/testing/atmos_testing.dmi
new file mode 100644
index 00000000000..142bd4cbb1a
Binary files /dev/null and b/modular_pariah/master_files/icons/testing/atmos_testing.dmi differ
diff --git a/modular_pariah/master_files/icons/testing/turf_analysis.dmi b/modular_pariah/master_files/icons/testing/turf_analysis.dmi
new file mode 100644
index 00000000000..e3aac1ebd05
Binary files /dev/null and b/modular_pariah/master_files/icons/testing/turf_analysis.dmi differ
diff --git a/modular_pariah/master_files/sound/effects/glass_crack1.ogg b/modular_pariah/master_files/sound/effects/glass_crack1.ogg
new file mode 100644
index 00000000000..0221b238d7f
Binary files /dev/null and b/modular_pariah/master_files/sound/effects/glass_crack1.ogg differ
diff --git a/modular_pariah/master_files/sound/effects/glass_crack2.ogg b/modular_pariah/master_files/sound/effects/glass_crack2.ogg
new file mode 100644
index 00000000000..e5e37024588
Binary files /dev/null and b/modular_pariah/master_files/sound/effects/glass_crack2.ogg differ
diff --git a/modular_pariah/master_files/sound/effects/glass_crack3.ogg b/modular_pariah/master_files/sound/effects/glass_crack3.ogg
new file mode 100644
index 00000000000..631c584462e
Binary files /dev/null and b/modular_pariah/master_files/sound/effects/glass_crack3.ogg differ
diff --git a/modular_pariah/master_files/sound/effects/glass_crack4.ogg b/modular_pariah/master_files/sound/effects/glass_crack4.ogg
new file mode 100644
index 00000000000..5d6302e88b2
Binary files /dev/null and b/modular_pariah/master_files/sound/effects/glass_crack4.ogg differ
diff --git a/modular_pariah/master_files/sound/effects/space_wind.ogg b/modular_pariah/master_files/sound/effects/space_wind.ogg
new file mode 100644
index 00000000000..3709cdb0557
Binary files /dev/null and b/modular_pariah/master_files/sound/effects/space_wind.ogg differ
diff --git a/modular_pariah/master_files/sound/effects/space_wind_big.ogg b/modular_pariah/master_files/sound/effects/space_wind_big.ogg
new file mode 100644
index 00000000000..6e8934bb603
Binary files /dev/null and b/modular_pariah/master_files/sound/effects/space_wind_big.ogg differ
diff --git a/modular_pariah/modules/large_doors/code/large_doors.dm b/modular_pariah/modules/large_doors/code/large_doors.dm
index 7b161926250..f4ce1ee62a1 100644
--- a/modular_pariah/modules/large_doors/code/large_doors.dm
+++ b/modular_pariah/modules/large_doors/code/large_doors.dm
@@ -61,7 +61,7 @@
density = TRUE
opacity = TRUE
anchored = TRUE
- can_atmos_pass = ATMOS_PASS_DENSITY
+ can_atmos_pass = CANPASS_DENSITY
var/parent_airlock
/obj/airlock_filler_object/CanAllowThrough(atom/movable/mover, turf/target)
diff --git a/pariah.dme b/pariah.dme
index e3973417c76..3d727be9c61 100644
--- a/pariah.dme
+++ b/pariah.dme
@@ -199,6 +199,12 @@
#include "code\__DEFINES\atmospherics\atmos_mapping_helpers.dm"
#include "code\__DEFINES\atmospherics\atmos_mob_interaction.dm"
#include "code\__DEFINES\atmospherics\atmos_piping.dm"
+#include "code\__DEFINES\atmospherics\Connections.dm"
+#include "code\__DEFINES\atmospherics\reactor.dm"
+#include "code\__DEFINES\atmospherics\temperature.dm"
+#include "code\__DEFINES\atmospherics\XGM.dm"
+#include "code\__DEFINES\atmospherics\ZAS.dm"
+#include "code\__DEFINES\atmospherics\ZAS_math.dm"
#include "code\__DEFINES\dcs\flags.dm"
#include "code\__DEFINES\dcs\helpers.dm"
#include "code\__DEFINES\dcs\signals\signals_action.dm"
@@ -225,6 +231,7 @@
#include "code\__DEFINES\dcs\signals\signals_janitor.dm"
#include "code\__DEFINES\dcs\signals\signals_ladder.dm"
#include "code\__DEFINES\dcs\signals\signals_light_eater.dm"
+#include "code\__DEFINES\dcs\signals\signals_machinery.dm"
#include "code\__DEFINES\dcs\signals\signals_medical.dm"
#include "code\__DEFINES\dcs\signals\signals_mind.dm"
#include "code\__DEFINES\dcs\signals\signals_mod.dm"
@@ -356,6 +363,7 @@
#include "code\__HELPERS\verbs.dm"
#include "code\__HELPERS\view.dm"
#include "code\__HELPERS\weakref.dm"
+#include "code\__HELPERS\zas.dm"
#include "code\__HELPERS\sorts\__main.dm"
#include "code\__HELPERS\sorts\InsertSort.dm"
#include "code\__HELPERS\sorts\MergeSort.dm"
@@ -452,7 +460,9 @@
#include "code\controllers\subsystem\achievements.dm"
#include "code\controllers\subsystem\addiction.dm"
#include "code\controllers\subsystem\ai_controllers.dm"
-#include "code\controllers\subsystem\air.dm"
+#include "code\controllers\subsystem\airflow.dm"
+#include "code\controllers\subsystem\airmachines.dm"
+//#include "code\controllers\subsystem\air.dm"
#include "code\controllers\subsystem\ambience.dm"
#include "code\controllers\subsystem\assets.dm"
#include "code\controllers\subsystem\atoms.dm"
@@ -530,6 +540,7 @@
#include "code\controllers\subsystem\wardrobe.dm"
#include "code\controllers\subsystem\weather.dm"
#include "code\controllers\subsystem\wiremod_composite.dm"
+#include "code\controllers\subsystem\zas.dm"
#include "code\controllers\subsystem\movement\ai_movement.dm"
#include "code\controllers\subsystem\movement\move_handler.dm"
#include "code\controllers\subsystem\movement\movement.dm"
@@ -538,6 +549,7 @@
#include "code\controllers\subsystem\processing\acid.dm"
#include "code\controllers\subsystem\processing\ai_basic_avoidance.dm"
#include "code\controllers\subsystem\processing\ai_behaviors.dm"
+#include "code\controllers\subsystem\processing\airatoms.dm"
#include "code\controllers\subsystem\processing\antag_hud.dm"
#include "code\controllers\subsystem\processing\aura_healing.dm"
#include "code\controllers\subsystem\processing\clock_component.dm"
@@ -675,7 +687,7 @@
#include "code\datums\announcers\intern_announcer.dm"
#include "code\datums\announcers\medbot_announcer.dm"
#include "code\datums\atmosphere\_atmosphere.dm"
-#include "code\datums\atmosphere\planetary.dm"
+//#include "code\datums\atmosphere\planetary.dm"
#include "code\datums\brain_damage\brain_trauma.dm"
#include "code\datums\brain_damage\creepy_trauma.dm"
#include "code\datums\brain_damage\hypnosis.dm"
@@ -1404,7 +1416,7 @@
#include "code\game\objects\effects\effect_system\effects_smoke.dm"
#include "code\game\objects\effects\effect_system\effects_sparks.dm"
#include "code\game\objects\effects\effect_system\effects_water.dm"
-#include "code\game\objects\effects\spawners\bombspawner.dm"
+//#include "code\game\objects\effects\spawners\bombspawner.dm"
#include "code\game\objects\effects\spawners\costume.dm"
#include "code\game\objects\effects\spawners\gibspawner.dm"
#include "code\game\objects\effects\spawners\structure.dm"
@@ -2303,17 +2315,8 @@
#include "code\modules\asset_cache\assets\vv.dm"
#include "code\modules\asset_cache\transports\asset_transport.dm"
#include "code\modules\asset_cache\transports\webroot_transport.dm"
-#include "code\modules\atmospherics\environmental\LINDA_fire.dm"
-#include "code\modules\atmospherics\environmental\LINDA_system.dm"
-#include "code\modules\atmospherics\environmental\LINDA_turf_tile.dm"
-#include "code\modules\atmospherics\gasmixtures\gas_mixture.dm"
-#include "code\modules\atmospherics\gasmixtures\gas_types.dm"
-#include "code\modules\atmospherics\gasmixtures\immutable_mixtures.dm"
-#include "code\modules\atmospherics\gasmixtures\reaction_factors.dm"
-#include "code\modules\atmospherics\gasmixtures\reactions.dm"
#include "code\modules\atmospherics\machinery\airalarm.dm"
#include "code\modules\atmospherics\machinery\atmosmachinery.dm"
-#include "code\modules\atmospherics\machinery\bluespace_vendor.dm"
#include "code\modules\atmospherics\machinery\datum_pipeline.dm"
#include "code\modules\atmospherics\machinery\components\components_base.dm"
#include "code\modules\atmospherics\machinery\components\tank.dm"
@@ -2327,26 +2330,19 @@
#include "code\modules\atmospherics\machinery\components\binary_devices\temperature_pump.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\valve.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\volume_pump.dm"
-#include "code\modules\atmospherics\machinery\components\electrolyzer\electrolyzer.dm"
-#include "code\modules\atmospherics\machinery\components\electrolyzer\electrolyzer_reactions.dm"
-#include "code\modules\atmospherics\machinery\components\fusion\hfr_core.dm"
-#include "code\modules\atmospherics\machinery\components\fusion\hfr_defines.dm"
-#include "code\modules\atmospherics\machinery\components\fusion\hfr_fuel_datums.dm"
-#include "code\modules\atmospherics\machinery\components\fusion\hfr_main_processes.dm"
-#include "code\modules\atmospherics\machinery\components\fusion\hfr_parts.dm"
-#include "code\modules\atmospherics\machinery\components\fusion\hfr_procs.dm"
-#include "code\modules\atmospherics\machinery\components\gas_recipe_machines\atmos_machines_recipes.dm"
-#include "code\modules\atmospherics\machinery\components\gas_recipe_machines\crystallizer.dm"
-#include "code\modules\atmospherics\machinery\components\gas_recipe_machines\crystallizer_items.dm"
+#include "code\modules\atmospherics\rust\fusion_reactions.dm"
#include "code\modules\atmospherics\machinery\components\trinary_devices\filter.dm"
#include "code\modules\atmospherics\machinery\components\trinary_devices\mixer.dm"
#include "code\modules\atmospherics\machinery\components\trinary_devices\trinary_devices.dm"
-#include "code\modules\atmospherics\machinery\components\unary_devices\bluespace_sender.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\cryo.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\heat_exchanger.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\outlet_injector.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\passive_vent.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\portables_connector.dm"
+#include "code\modules\atmospherics\rust\reactor_core.dm"
+#include "code\modules\atmospherics\rust\reactor_em_field.dm"
+#include "code\modules\atmospherics\rust\particle_catcher.dm"
+#include "code\modules\atmospherics\rust\fuel_rod.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\thermomachine.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\unary_devices.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\vent_pump.dm"
@@ -2358,13 +2354,33 @@
#include "code\modules\atmospherics\machinery\pipes\layermanifold.dm"
#include "code\modules\atmospherics\machinery\pipes\mapping.dm"
#include "code\modules\atmospherics\machinery\pipes\multiz.dm"
+#include "code\modules\atmospherics\ZAS\Temperature.dm"
+#include "code\modules\atmospherics\ZAS\atmos_primitives.dm"
#include "code\modules\atmospherics\machinery\pipes\pipes.dm"
#include "code\modules\atmospherics\machinery\pipes\smart.dm"
#include "code\modules\atmospherics\machinery\pipes\heat_exchange\he_pipes.dm"
#include "code\modules\atmospherics\machinery\pipes\heat_exchange\junction.dm"
#include "code\modules\atmospherics\machinery\pipes\heat_exchange\manifold.dm"
#include "code\modules\atmospherics\machinery\pipes\heat_exchange\manifold4w.dm"
+#include "code\modules\atmospherics\ZAS\Connection.dm"
+#include "code\modules\atmospherics\ZAS\ConnectionGroup.dm"
+#include "code\modules\atmospherics\ZAS\zas_extras\gas_reagents.dm"
+#include "code\modules\atmospherics\ZAS\ConnectionManager.dm"
+#include "code\modules\atmospherics\ZAS\ZAS_Settings.dm"
+#include "code\modules\atmospherics\ZAS\Debug.dm"
+#include "code\modules\atmospherics\ZAS\Diagnostic.dm"
+#include "code\modules\atmospherics\ZAS\Fire.dm"
#include "code\modules\atmospherics\machinery\pipes\heat_exchange\simple.dm"
+#include "code\modules\atmospherics\ZAS\Turf.dm"
+#include "code\modules\atmospherics\ZAS\XGM\gases.dm"
+#include "code\modules\atmospherics\ZAS\Zone.dm"
+#include "code\modules\atmospherics\ZAS\zas_extras\inflatable.dm"
+#include "code\modules\atmospherics\ZAS\_docs.dm"
+#include "code\modules\atmospherics\ZAS\Airflow.dm"
+#include "code\modules\atmospherics\ZAS\Atom.dm"
+#include "code\modules\atmospherics\ZAS\Plasma.dm"
+#include "code\modules\atmospherics\ZAS\XGM\xgm_gas_mixture.dm"
+#include "code\modules\atmospherics\ZAS\XGM\gas_data.dm"
#include "code\modules\atmospherics\machinery\portable\canister.dm"
#include "code\modules\atmospherics\machinery\portable\portable_atmospherics.dm"
#include "code\modules\atmospherics\machinery\portable\pump.dm"
@@ -3781,9 +3797,9 @@
#include "code\modules\power\supermatter\supermatter_radiation.dm"
#include "code\modules\power\tesla\coil.dm"
#include "code\modules\power\tesla\energy_ball.dm"
-#include "code\modules\power\turbine\turbine.dm"
-#include "code\modules\power\turbine\turbine_computer.dm"
-#include "code\modules\power\turbine\turbine_parts.dm"
+// #include "code\modules\power\turbine\turbine.dm"
+// #include "code\modules\power\turbine\turbine_computer.dm"
+// #include "code\modules\power\turbine\turbine_parts.dm"
#include "code\modules\procedural_mapping\mapGenerator.dm"
#include "code\modules\procedural_mapping\mapGeneratorModule.dm"
#include "code\modules\procedural_mapping\mapGeneratorObj.dm"
diff --git a/sound/machines/atmosalarm.ogg b/sound/machines/atmosalarm.ogg
new file mode 100644
index 00000000000..fe44b7e4343
Binary files /dev/null and b/sound/machines/atmosalarm.ogg differ
diff --git a/tgui/packages/tgui/constants.js b/tgui/packages/tgui/constants.js
index 495c04d8a0e..5c396609495 100644
--- a/tgui/packages/tgui/constants.js
+++ b/tgui/packages/tgui/constants.js
@@ -140,19 +140,19 @@ export const RADIO_CHANNELS = [
const GASES = [
{
- 'id': 'o2',
+ 'id': 'oxygen',
'name': 'Oxygen',
'label': 'O₂',
'color': 'blue',
},
{
- 'id': 'n2',
+ 'id': 'nitrogen',
'name': 'Nitrogen',
'label': 'N₂',
'color': 'red',
},
{
- 'id': 'co2',
+ 'id': 'carbon_dioxide',
'name': 'Carbon Dioxide',
'label': 'CO₂',
'color': 'grey',
@@ -164,7 +164,7 @@ const GASES = [
'color': 'pink',
},
{
- 'id': 'water_vapor',
+ 'id': 'water',
'name': 'Water Vapor',
'label': 'H₂O',
'color': 'lightsteelblue',
@@ -176,23 +176,17 @@ const GASES = [
'color': 'teal',
},
{
- 'id': 'n2o',
+ 'id': 'sleeping_agent',
'name': 'Nitrous Oxide',
'label': 'N₂O',
'color': 'bisque',
},
{
- 'id': 'no2',
- 'name': 'Nitrium',
- 'label': 'Nitrium',
+ 'id': 'nitrodioxide',
+ 'name': 'Nitrogen Dioxide',
+ 'label': 'NO₂',
'color': 'brown',
},
- {
- 'id': 'tritium',
- 'name': 'Tritium',
- 'label': 'Tritium',
- 'color': 'limegreen',
- },
{
'id': 'bz',
'name': 'BZ',
@@ -202,7 +196,7 @@ const GASES = [
{
'id': 'pluox',
'name': 'Pluoxium',
- 'label': 'Pluoxium',
+ 'label': 'O₁₆',
'color': 'mediumslateblue',
},
{
@@ -259,6 +253,96 @@ const GASES = [
'label': 'Anti-Noblium',
'color': 'maroon',
},
+ {
+ 'id': 'carbon_monoxide',
+ 'name': 'Carbon Monoxide',
+ 'label': 'CO',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'methyl_bromide',
+ 'name': 'Methyl Bromide',
+ 'label': 'CH₃Br',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'methane',
+ 'name': 'Methane',
+ 'label': 'CH₄',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'methane',
+ 'name': 'Methane',
+ 'label': 'CH₄',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'argon',
+ 'name': 'Argon',
+ 'label': 'Ar',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'krypton',
+ 'name': 'Krypton',
+ 'label': 'Kr',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'xenon',
+ 'name': 'Xenon',
+ 'label': 'Xe',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'neon',
+ 'name': 'Neon',
+ 'label': 'Ne',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'ammonia',
+ 'name': 'Ammonia',
+ 'label': 'NH₃',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'chlorine',
+ 'name': 'Chlorine',
+ 'label': 'Cl',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'sulfurdioxide',
+ 'name': 'Chlorine',
+ 'label': 'SO₂',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'nitricoxide',
+ 'name': 'Nitric Oxide',
+ 'label': 'NO',
+ 'color': 'maroon',
+ },
+ {
+ 'id': 'deuterium',
+ 'name': 'Deuterium',
+ 'label': '²H',
+ 'color': 'lightgrey',
+ },
+ {
+ 'id': 'tritium',
+ 'name': 'Tritium',
+ 'label': '³H',
+ 'color': 'limegreen',
+ },
+ {
+ 'id': 'boron',
+ 'name': 'Boron',
+ 'label': 'B',
+ 'color': 'limegreen',
+ },
];
export const getGasLabel = (gasId, fallbackValue) => {
diff --git a/tgui/packages/tgui/interfaces/AirAlarm.js b/tgui/packages/tgui/interfaces/AirAlarm.js
index 402ced320eb..2639a0853a0 100644
--- a/tgui/packages/tgui/interfaces/AirAlarm.js
+++ b/tgui/packages/tgui/interfaces/AirAlarm.js
@@ -1,7 +1,7 @@
import { toFixed } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from '../backend';
-import { Box, Button, LabeledList, Section } from '../components';
+import { Box, Button, Flex, Knob, LabeledControls, LabeledList, RoundGauge, Section } from '../components';
import { Window } from '../layouts';
import { Scrubber, Vent } from './common/AtmosControls';
import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox';
@@ -15,6 +15,7 @@ export const AirAlarm = (props, context) => {
height={650}>
+
{!locked && (
@@ -91,6 +92,74 @@ const AirAlarmStatus = (props, context) => {
);
};
+const ThermostatControl = (props, context) => {
+ const { act, data } = useBackend(context);
+ const entries = (data.environment_data || [])
+ .filter(entry => entry.value >= 0.01);
+ return (
+
+
+
+
+
+
+ act('target', {
+ target: value,
+ })} />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
const AIR_ALARM_ROUTES = {
home: {
title: 'Air Controls',
@@ -142,9 +211,18 @@ const AirAlarmControlHome = (props, context) => {
const {
mode,
atmos_alarm,
+ fire_alarm,
} = data;
return (
<>
+