Assorted atmos performance improvements. (#27966)

This commit is contained in:
Charlie Nolan
2025-01-20 07:18:32 -08:00
committed by GitHub
parent 8954a8e401
commit fdbd2b2050
13 changed files with 271 additions and 230 deletions
@@ -173,9 +173,9 @@
/turf/proc/Initialize_Atmos(times_fired)
// This is one of two places expected to call this otherwise-unsafe method.
private_unsafe_recalculate_atmos_connectivity()
var/list/connectivity = private_unsafe_recalculate_atmos_connectivity()
var/list/air = list(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature)
milla_data = milla_atmos_airtight + list(atmos_mode, SSmapping.environments[atmos_environment]) + air + milla_superconductivity
milla_data = connectivity[1] + list(atmos_mode, SSmapping.environments[atmos_environment]) + air + connectivity[2]
/turf/proc/recalculate_atmos_connectivity()
var/datum/milla_safe/recalculate_atmos_connectivity/milla = new()
@@ -188,26 +188,26 @@
return
// This is one of two places expected to call this otherwise-unsafe method.
T.private_unsafe_recalculate_atmos_connectivity()
var/list/connectivity = T.private_unsafe_recalculate_atmos_connectivity()
set_tile_airtight(T, T.milla_atmos_airtight)
set_tile_airtight(T, connectivity[1])
reset_superconductivity(T)
reduce_superconductivity(T, T.milla_superconductivity)
reduce_superconductivity(T, connectivity[2])
/// This method is unsafe to use because it only updates milla_* properties, but does not write them to MILLA. Use recalculate_atmos_connectivity() instead.
/turf/proc/private_unsafe_recalculate_atmos_connectivity()
if(blocks_air)
milla_atmos_airtight = list(TRUE, TRUE, TRUE, TRUE)
milla_superconductivity = list(0, 0, 0, 0)
return
var/milla_atmos_airtight = list(TRUE, TRUE, TRUE, TRUE)
var/milla_superconductivity = list(0, 0, 0, 0)
return list(milla_atmos_airtight, milla_superconductivity)
milla_atmos_airtight = list(
var/milla_atmos_airtight = list(
!CanAtmosPass(NORTH, FALSE),
!CanAtmosPass(EAST, FALSE),
!CanAtmosPass(SOUTH, FALSE),
!CanAtmosPass(WEST, FALSE))
milla_superconductivity = list(
var/milla_superconductivity = list(
OPEN_HEAT_TRANSFER_COEFFICIENT,
OPEN_HEAT_TRANSFER_COEFFICIENT,
OPEN_HEAT_TRANSFER_COEFFICIENT,
@@ -230,6 +230,8 @@
milla_superconductivity[INDEX_SOUTH] = min(milla_superconductivity[INDEX_SOUTH], O.get_superconductivity(SOUTH))
milla_superconductivity[INDEX_WEST] = min(milla_superconductivity[INDEX_WEST], O.get_superconductivity(WEST))
return list(milla_atmos_airtight, milla_superconductivity)
/obj/effect/wind
anchored = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -114,12 +114,10 @@ What are the archived variables for?
/// Calculate moles
/datum/gas_mixture/proc/total_moles()
var/moles = private_oxygen + private_carbon_dioxide + private_nitrogen + private_toxins + private_sleeping_agent + private_agent_b
return moles
return private_oxygen + private_carbon_dioxide + private_nitrogen + private_toxins + private_sleeping_agent + private_agent_b
/datum/gas_mixture/proc/total_trace_moles()
var/moles = private_agent_b
return moles
return private_agent_b
/// Calculate pressure in kilopascals
/datum/gas_mixture/proc/return_pressure()
@@ -662,23 +660,26 @@ What are the archived variables for?
/proc/share_many_airs(list/mixtures)
var/total_volume = 0
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/total_oxygen = 0
var/total_nitrogen = 0
var/total_toxins = 0
var/total_carbon_dioxide = 0
var/total_sleeping_agent = 0
var/total_agent_b = 0
var/must_share = FALSE
// Collect all the cheap data and check if there's a significant temperature difference.
var/temperature = null
for(var/datum/gas_mixture/G as anything in mixtures)
if(!istype(G))
stack_trace("share_many_airs had [G] in mixtures ([json_encode(mixtures)])")
continue
total_volume += G.volume
var/heat_capacity = G.heat_capacity()
total_heat_capacity += heat_capacity
total_thermal_energy += G.private_temperature * heat_capacity
if(isnull(temperature))
temperature = G.private_temperature
else if(abs(temperature - G.private_temperature) >= 1)
must_share = TRUE
total_oxygen += G.private_oxygen
total_nitrogen += G.private_nitrogen
@@ -687,26 +688,65 @@ What are the archived variables for?
total_sleeping_agent += G.private_sleeping_agent
total_agent_b += G.private_agent_b
if(total_volume > 0)
//Calculate temperature
var/temperature = 0
if(total_volume <= 0)
return
if(total_heat_capacity > 0)
temperature = total_thermal_energy/total_heat_capacity
//Update individual gas_mixtures by volume ratio
// If we don't have a significant temperature difference, check for a significant gas amount difference.
if(!must_share)
for(var/datum/gas_mixture/G as anything in mixtures)
if(!istype(G))
continue
G.private_oxygen = total_oxygen * G.volume / total_volume
G.private_nitrogen = total_nitrogen * G.volume / total_volume
G.private_toxins = total_toxins * G.volume / total_volume
G.private_carbon_dioxide = total_carbon_dioxide * G.volume / total_volume
G.private_sleeping_agent = total_sleeping_agent * G.volume / total_volume
G.private_agent_b = total_agent_b * G.volume / total_volume
if(abs(G.private_oxygen - total_oxygen * G.volume / total_volume) > 0.1)
must_share = TRUE
break
if(abs(G.private_nitrogen - total_nitrogen * G.volume / total_volume) > 0.1)
must_share = TRUE
break
if(abs(G.private_toxins - total_toxins * G.volume / total_volume) > 0.1)
must_share = TRUE
break
if(abs(G.private_carbon_dioxide - total_carbon_dioxide * G.volume / total_volume) > 0.1)
must_share = TRUE
break
if(abs(G.private_sleeping_agent - total_sleeping_agent * G.volume / total_volume) > 0.1)
must_share = TRUE
break
if(abs(G.private_agent_b - total_agent_b * G.volume / total_volume) > 0.1)
must_share = TRUE
break
G.private_temperature = temperature
G.set_dirty()
if(!must_share)
// Nothing significant, don't do any more work.
return
// Collect the more expensive data.
var/total_thermal_energy = 0
var/total_heat_capacity = 0
for(var/datum/gas_mixture/G as anything in mixtures)
if(!istype(G))
continue
var/heat_capacity = G.heat_capacity()
total_heat_capacity += heat_capacity
total_thermal_energy += G.private_temperature * heat_capacity
// Calculate shared temperature.
temperature = TCMB
if(total_heat_capacity > 0)
temperature = total_thermal_energy/total_heat_capacity
// Update individual gas_mixtures by volume ratio.
for(var/datum/gas_mixture/G as anything in mixtures)
if(!istype(G))
continue
G.private_oxygen = total_oxygen * G.volume / total_volume
G.private_nitrogen = total_nitrogen * G.volume / total_volume
G.private_toxins = total_toxins * G.volume / total_volume
G.private_carbon_dioxide = total_carbon_dioxide * G.volume / total_volume
G.private_sleeping_agent = total_sleeping_agent * G.volume / total_volume
G.private_agent_b = total_agent_b * G.volume / total_volume
G.private_temperature = temperature
// In theory, we should G.set_dirty() here, but that's only useful for bound mixtures, and these can't be.
/datum/gas_mixture/proc/hotspot_expose(temperature, volume)
return
@@ -222,6 +222,7 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
set_pixel_offsets_from_dir(24, -24, 24, -24)
GLOB.air_alarms += src
alarm_area.air_alarms += src
if(!mapload)
GLOB.air_alarms = sortAtom(GLOB.air_alarms)
@@ -231,17 +232,12 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
if(!building)
first_run()
if(!master_is_operating())
elect_master()
/obj/machinery/alarm/Destroy()
SStgui.close_uis(wires)
GLOB.air_alarms -= src
alarm_area.air_alarms -= src
GLOB.air_alarm_repository.update_cache(src)
QDEL_NULL(wires)
if(alarm_area && alarm_area.master_air_alarm == src)
alarm_area.master_air_alarm = null
elect_master(exclude_self = 1)
alarm_area = null
return ..()
@@ -249,24 +245,6 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
apply_preset(AALARM_PRESET_HUMAN) // Don't cycle.
GLOB.air_alarm_repository.update_cache(src)
/obj/machinery/alarm/proc/master_is_operating()
if(!alarm_area)
alarm_area = get_area(src)
if(!alarm_area)
. = FALSE
CRASH("Air alarm /obj/machinery/alarm lacks alarm_area vars during proc/master_is_operating()")
return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN))
/obj/machinery/alarm/proc/elect_master(exclude_self = 0) //Why is this an alarm and not area proc?
for(var/obj/machinery/alarm/AA in alarm_area)
if(exclude_self && AA == src)
continue
if(!(AA.stat & (NOPOWER|BROKEN)))
alarm_area.master_air_alarm = AA
return 1
return 0
/obj/machinery/alarm/process()
if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2)
return
@@ -275,8 +253,9 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
if(!istype(location))
return 0
var/datum/milla_safe/airalarm_heat_cool/milla = new()
milla.invoke_async(src)
if(thermostat_state)
var/datum/milla_safe/airalarm_heat_cool/milla = new()
milla.invoke_async(src)
var/datum/gas_mixture/environment = location.get_readonly_air()
var/GET_PP = R_IDEAL_GAS_EQUATION * environment.temperature() / environment.volume
@@ -342,8 +321,6 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
var/turf/location = get_turf(alarm)
var/datum/gas_mixture/environment = get_turf_air(location)
if(!alarm.thermostat_state)
return
var/datum/tlv/cur_tlv = alarm.TLV["temperature"]
//Handle temperature adjustment here.
if(environment.temperature() < alarm.target_temperature - 2 || environment.temperature() > alarm.target_temperature + 2 || alarm.regulating_temperature)
@@ -94,21 +94,14 @@
if(Old == parent)
parent = New
/obj/machinery/atmospherics/unary/unsafe_pressure_release(mob/user, pressures)
/obj/machinery/atmospherics/unary/unsafe_pressure_release(mob/user, pressure)
..()
var/turf/T = get_turf(src)
if(T)
var/datum/milla_safe/unary_unsafe_pressure_release/milla = new()
milla.invoke_async(src, pressures)
if(!T)
return
/datum/milla_safe/unary_unsafe_pressure_release
var/lost = pressure * CELL_VOLUME / (air_contents.temperature() * R_IDEAL_GAS_EQUATION)
/datum/milla_safe/unary_unsafe_pressure_release/on_run(obj/machinery/atmospherics/unary/device, pressures)
//Remove the gas from air_contents and assume it
var/turf/T = get_turf(device)
var/datum/gas_mixture/environment = get_turf_air(T)
var/lost = pressures * environment.volume / (device.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/to_release = device.air_contents.remove(lost)
environment.merge(to_release)
var/datum/gas_mixture/to_release = air_contents.remove(lost)
T.blind_release_air(to_release)
@@ -108,69 +108,71 @@
update_underlays()
/obj/machinery/atmospherics/unary/vent_pump/process_atmos()
var/datum/milla_safe/vent_pump_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/vent_pump_process
/datum/milla_safe/vent_pump_process/on_run(obj/machinery/atmospherics/unary/vent_pump/vent_pump)
if(vent_pump.stat & (NOPOWER|BROKEN))
if(stat & (NOPOWER|BROKEN))
return FALSE
if(QDELETED(vent_pump.parent))
if(QDELETED(parent))
// We're orphaned!
return FALSE
var/turf/T = get_turf(vent_pump)
var/turf/T = get_turf(src)
if(T.density) //No, you should not be able to get free air from walls
return
if(!vent_pump.node)
vent_pump.on = FALSE
if(!vent_pump.on)
if(!node)
on = FALSE
if(!on)
return FALSE
if(vent_pump.welded)
if(vent_pump.air_contents.return_pressure() >= vent_pump.weld_burst_pressure && prob(5)) //the weld is on but the cover is welded shut, can it withstand the internal pressure?
vent_pump.visible_message("<span class='danger'>The welded cover of [vent_pump] bursts open!</span>")
if(welded)
if(air_contents.return_pressure() >= weld_burst_pressure && prob(5)) //the weld is on but the cover is welded shut, can it withstand the internal pressure?
visible_message("<span class='danger'>The welded cover of [src] bursts open!</span>")
for(var/mob/living/M in range(1))
vent_pump.unsafe_pressure_release(M, vent_pump.air_contents.return_pressure()) //let's send everyone flying
vent_pump.welded = FALSE
vent_pump.update_icon()
unsafe_pressure_release(M, air_contents.return_pressure()) //let's send everyone flying
welded = FALSE
update_icon()
return FALSE
var/datum/gas_mixture/environment = get_turf_air(T)
var/environment_pressure = environment.return_pressure()
if(vent_pump.releasing) //internal -> external
var/datum/gas_mixture/environment = T.get_readonly_air()
if(releasing) //internal -> external
var/pressure_delta = 10000
if(vent_pump.pressure_checks == ONLY_CHECK_EXT_PRESSURE)
if(pressure_checks == ONLY_CHECK_EXT_PRESSURE)
// Only checks difference between set pressure and environment pressure
pressure_delta = min(pressure_delta, (vent_pump.external_pressure_bound - environment_pressure))
if(vent_pump.pressure_checks == ONLY_CHECK_INT_PRESSURE)
pressure_delta = min(pressure_delta, (vent_pump.air_contents.return_pressure() - vent_pump.internal_pressure_bound))
pressure_delta = min(pressure_delta, (external_pressure_bound - environment.return_pressure()))
if(pressure_checks == ONLY_CHECK_INT_PRESSURE)
pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound))
if(pressure_delta > 0.5 && vent_pump.air_contents.temperature() > 0)
if(pressure_delta > 0.5 && air_contents.temperature() > 0)
// 1kPa * 1L = 1J
var/wanted_joules = pressure_delta * environment.volume
var/transfer_moles = min(vent_pump.max_transfer_joules, wanted_joules) / (vent_pump.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = vent_pump.air_contents.remove(transfer_moles)
environment.merge(removed)
vent_pump.parent.update = TRUE
var/transfer_moles = min(max_transfer_joules, wanted_joules) / (air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
// This isn't exactly "blind", but using the data from last tick is good enough for a vent.
T.blind_release_air(removed)
parent.update = TRUE
else //external -> internal
var/pressure_delta = 10000
if(vent_pump.pressure_checks == ONLY_CHECK_EXT_PRESSURE)
pressure_delta = min(pressure_delta, (environment_pressure - vent_pump.external_pressure_bound))
if(vent_pump.pressure_checks == ONLY_CHECK_INT_PRESSURE)
pressure_delta = min(pressure_delta, (vent_pump.internal_pressure_bound - vent_pump.air_contents.return_pressure()))
if(pressure_delta > 0.5 && environment.temperature() > 0)
// 1kPa * 1L = 1J
var/wanted_joules = pressure_delta * environment.volume
var/transfer_moles = min(vent_pump.max_transfer_joules, wanted_joules) / (environment.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
vent_pump.air_contents.merge(removed)
vent_pump.parent.update = TRUE
var/datum/milla_safe/vent_pump_siphon/milla = new()
milla.invoke_async(src)
return TRUE
/datum/milla_safe/vent_pump_siphon
/datum/milla_safe/vent_pump_siphon/on_run(obj/machinery/atmospherics/unary/vent_pump/vent_pump)
var/turf/T = get_turf(vent_pump)
var/datum/gas_mixture/environment = get_turf_air(T)
var/pressure_delta = 10000
if(vent_pump.pressure_checks == ONLY_CHECK_EXT_PRESSURE)
pressure_delta = min(pressure_delta, (environment.return_pressure() - vent_pump.external_pressure_bound))
if(vent_pump.pressure_checks == ONLY_CHECK_INT_PRESSURE)
pressure_delta = min(pressure_delta, (vent_pump.internal_pressure_bound - vent_pump.air_contents.return_pressure()))
if(pressure_delta > 0.5 && environment.temperature() > 0)
// 1kPa * 1L = 1J
var/wanted_joules = pressure_delta * environment.volume
var/transfer_moles = min(vent_pump.max_transfer_joules, wanted_joules) / (environment.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
vent_pump.air_contents.merge(removed)
vent_pump.parent.update = TRUE
/obj/machinery/atmospherics/unary/vent_pump/can_crawl_through()
return !welded
@@ -140,9 +140,31 @@
adjacent_turfs = T.GetAtmosAdjacentTurfs(alldir=1)
/obj/machinery/atmospherics/unary/vent_scrubber/proc/scrub(turf/simulated/tile)
if(!tile || !istype(tile))
return 0
if(scrubbing && !should_scrub(tile.get_readonly_air()))
return 0
var/datum/milla_safe/vent_scrubber_process/milla = new()
milla.invoke_async(src, tile)
/obj/machinery/atmospherics/unary/vent_scrubber/proc/should_scrub(datum/gas_mixture/environment)
if(scrub_O2 && environment.oxygen() > 0.001)
return TRUE
if(scrub_N2 && environment.nitrogen() > 0.001)
return TRUE
if(scrub_CO2 && environment.carbon_dioxide() > 0.001)
return TRUE
if(scrub_Toxins && environment.toxins() > 0.001)
return TRUE
if(environment.sleeping_agent() > 0.001)
return TRUE
if(environment.agent_b() > 0.001)
return TRUE
return FALSE
/datum/milla_safe/vent_scrubber_process
/datum/milla_safe/vent_scrubber_process/on_run(obj/machinery/atmospherics/unary/vent_scrubber/scrubber, turf/simulated/tile)
@@ -152,7 +174,7 @@
var/datum/gas_mixture/environment = get_turf_air(tile)
if(scrubber.scrubbing)
if((scrubber.scrub_O2 && environment.oxygen() > 0.001) || (scrubber.scrub_N2 && environment.nitrogen() > 0.001) || (scrubber.scrub_CO2 && environment.carbon_dioxide() > 0.001) || (scrubber.scrub_Toxins && environment.toxins() > 0.001) || (environment.sleeping_agent()) || (environment.agent_b()))
if(scrubber.should_scrub(environment))
var/transfer_moles = min(1, scrubber.volume_rate / environment.volume) * environment.total_moles()
//Take a gas sample
@@ -210,41 +210,41 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
/obj/machinery/atmospherics/portable/canister/process_atmos()
..()
sync_pressure_appearance()
var/datum/milla_safe/canister_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/canister_process
/datum/milla_safe/canister_process/on_run(obj/machinery/atmospherics/portable/canister/canister)
if(canister.stat & BROKEN)
if(stat & BROKEN)
return
if(canister.valve_open)
var/datum/gas_mixture/environment
if(canister.holding_tank)
environment = canister.holding_tank.air_contents
else
var/turf/T = get_turf(canister)
environment = get_turf_air(T)
if(valve_open)
var/datum/milla_safe/canister_release/milla = new()
milla.invoke_async(src)
var/env_pressure = environment.return_pressure()
var/pressure_delta = min(canister.release_pressure - env_pressure, (canister.air_contents.return_pressure() - env_pressure) / 2)
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if((canister.air_contents.temperature() > 0) && (pressure_delta > 0))
transfer_moles = pressure_delta * environment.volume / (canister.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = canister.air_contents.remove(transfer_moles)
environment.merge(removed)
canister.sync_pressure_appearance()
if(canister.air_contents.return_pressure() < 1)
canister.can_label = TRUE
if(air_contents.return_pressure() < 1)
can_label = TRUE
else
canister.can_label = FALSE
can_label = FALSE
/datum/milla_safe/canister_release
/datum/milla_safe/canister_release/on_run(obj/machinery/atmospherics/portable/canister/canister)
var/datum/gas_mixture/environment
if(canister.holding_tank)
environment = canister.holding_tank.air_contents
else
var/turf/T = get_turf(canister)
environment = get_turf_air(T)
var/env_pressure = environment.return_pressure()
var/pressure_delta = min(canister.release_pressure - env_pressure, (canister.air_contents.return_pressure() - env_pressure) / 2)
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if((canister.air_contents.temperature() > 0) && (pressure_delta > 0))
transfer_moles = pressure_delta * environment.volume / (canister.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = canister.air_contents.remove(transfer_moles)
environment.merge(removed)
canister.sync_pressure_appearance()
/obj/machinery/atmospherics/portable/canister/return_obj_air()
RETURN_TYPE(/datum/gas_mixture)
@@ -61,44 +61,44 @@
/obj/machinery/atmospherics/portable/pump/process_atmos()
..()
var/datum/milla_safe/portable_pump_process/milla = new()
milla.invoke_async(src)
if(on)
var/datum/milla_safe/portable_pump_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/portable_pump_process
/datum/milla_safe/portable_pump_process/on_run(obj/machinery/atmospherics/portable/pump/pump)
if(pump.on)
var/datum/gas_mixture/environment
if(pump.holding_tank)
environment = pump.holding_tank.air_contents
else
var/turf/T = get_turf(pump)
environment = get_turf_air(T)
if(pump.direction == DIRECTION_OUT)
var/pressure_delta = pump.target_pressure - environment.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/datum/gas_mixture/environment
if(pump.holding_tank)
environment = pump.holding_tank.air_contents
else
var/turf/T = get_turf(pump)
environment = get_turf_air(T)
if(pump.direction == DIRECTION_OUT)
var/pressure_delta = pump.target_pressure - environment.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if(pump.air_contents.temperature() > 0)
transfer_moles = pressure_delta*environment.volume/(pump.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/transfer_moles = 0
if(pump.air_contents.temperature() > 0)
transfer_moles = pressure_delta*environment.volume/(pump.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = pump.air_contents.remove(transfer_moles)
//Actually transfer the gas
var/datum/gas_mixture/removed = pump.air_contents.remove(transfer_moles)
environment.merge(removed)
else
var/pressure_delta = pump.target_pressure - pump.air_contents.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
environment.merge(removed)
else
var/pressure_delta = pump.target_pressure - pump.air_contents.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if(environment.temperature() > 0)
transfer_moles = pressure_delta*pump.air_contents.volume/(environment.temperature() * R_IDEAL_GAS_EQUATION)
var/transfer_moles = 0
if(environment.temperature() > 0)
transfer_moles = pressure_delta*pump.air_contents.volume/(environment.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed
removed = environment.remove(transfer_moles)
//Actually transfer the gas
var/datum/gas_mixture/removed
removed = environment.remove(transfer_moles)
pump.air_contents.merge(removed)
pump.air_contents.merge(removed)
/obj/machinery/atmospherics/portable/pump/return_obj_air()
RETURN_TYPE(/datum/gas_mixture)
@@ -46,18 +46,18 @@
/obj/machinery/atmospherics/portable/scrubber/process_atmos()
..()
var/datum/milla_safe/portable_scrubber_process/milla = new()
if(!on)
return
if(holding_tank)
scrub(holding_tank.air_contents)
return
var/datum/milla_safe/portable_scrubber_scrub/milla = new()
milla.invoke_async(src)
/datum/milla_safe/portable_scrubber_process
/datum/milla_safe/portable_scrubber_process/on_run(obj/machinery/atmospherics/portable/scrubber/scrubber)
if(!scrubber.on)
return
if(scrubber.holding_tank)
scrubber.scrub(scrubber.holding_tank.air_contents)
return
/datum/milla_safe/portable_scrubber_scrub
/datum/milla_safe/portable_scrubber_scrub/on_run(obj/machinery/atmospherics/portable/scrubber/scrubber)
var/turf/T = get_turf(scrubber)
scrubber.scrub(get_turf_air(T))
if(scrubber.widenet)