Increases performance significantly by turning garbage collection into a define
This commit is contained in:
@@ -5,8 +5,6 @@ What are the archived variables for?
|
||||
*/
|
||||
#define MINIMUM_HEAT_CAPACITY 0.0003
|
||||
#define MINIMUM_MOLE_COUNT 0.01
|
||||
#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
|
||||
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
|
||||
GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
|
||||
/datum/gas_mixture
|
||||
var/list/gases = list()
|
||||
@@ -22,23 +20,6 @@ GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
|
||||
if (!isnull(volume))
|
||||
src.volume = volume
|
||||
|
||||
//listmos procs
|
||||
//use the macros in performance intensive areas. for their definitions, refer to code/__DEFINES/atmospherics.dm
|
||||
|
||||
//UNOMOS - whoever originally wrote this is a sadist that just wants to see byond suffer.
|
||||
|
||||
//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.
|
||||
//UNOMOS - i have no idea exactly what the fuck or how the fuck it's the case, but removing this proc can and will completely nullify all of the performance gain from removing add_gas and assert_gas. so uh, dont remove it i guess. Why this shit isn't a define is beyond me.
|
||||
/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]) <= 0)
|
||||
cached_gases -= id
|
||||
|
||||
//PV = nRT
|
||||
|
||||
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
|
||||
@@ -152,7 +133,7 @@ GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
|
||||
for(var/id in cached_gases)
|
||||
removed_gases[id] = QUANTIZE((cached_gases[id] / sum) * amount)
|
||||
cached_gases[id] -= removed_gases[id]
|
||||
garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
|
||||
return removed
|
||||
|
||||
@@ -170,7 +151,7 @@ GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
|
||||
removed_gases[id] = QUANTIZE(cached_gases[id] * ratio)
|
||||
cached_gases[id] -= removed_gases[id]
|
||||
|
||||
garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
|
||||
return removed
|
||||
|
||||
@@ -282,11 +263,8 @@ GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
|
||||
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(cached_gases ^ sharer_gases)) //if all gases were present in both mixtures, we know that no gases are 0
|
||||
garbage_collect(cached_gases - sharer_gases) //any gases the sharer had, we are guaranteed to have. gases that it didn't have we are not.
|
||||
sharer.garbage_collect(sharer_gases - cached_gases) //the reverse is equally true
|
||||
if (initial(sharer.gc_share))
|
||||
sharer.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(sharer.gases)
|
||||
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
var/our_moles
|
||||
TOTAL_MOLES(cached_gases,our_moles)
|
||||
@@ -391,7 +369,7 @@ GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
|
||||
if (. & STOP_REACTIONS)
|
||||
break
|
||||
if(.)
|
||||
garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
if(temperature < TCMB) //just for safety
|
||||
temperature = TCMB
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
/datum/gas_mixture/immutable/New()
|
||||
..()
|
||||
garbage_collect()
|
||||
|
||||
/datum/gas_mixture/immutable/garbage_collect()
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
@@ -19,7 +16,9 @@
|
||||
|
||||
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
garbage_collect()
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
|
||||
/datum/gas_mixture/immutable/react()
|
||||
return 0 //we're immutable.
|
||||
@@ -59,9 +58,13 @@
|
||||
/datum/gas_mixture/immutable/cloner
|
||||
initial_temperature = T20C
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/garbage_collect()
|
||||
/datum/gas_mixture/immutable/cloner/New()
|
||||
..()
|
||||
gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD
|
||||
|
||||
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/heat_capacity()
|
||||
return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,237 +1,237 @@
|
||||
/obj/machinery/atmospherics/components/trinary/filter
|
||||
name = "gas filter"
|
||||
icon_state = "filter_off"
|
||||
desc = "Very useful for filtering gasses."
|
||||
density = FALSE
|
||||
can_unwrench = TRUE
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
var/filter_type = null
|
||||
var/frequency = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
construction_type = /obj/item/pipe/trinary/flippable
|
||||
pipe_state = "filter"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped
|
||||
icon_state = "filter_off_f"
|
||||
flipped = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
// 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.
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/critical
|
||||
critical_machine = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped/critical
|
||||
critical_machine = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos //Used for atmos waste loops
|
||||
on = TRUE
|
||||
icon_state = "filter_on"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/n2
|
||||
name = "nitrogen filter"
|
||||
filter_type = "n2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/o2
|
||||
name = "oxygen filter"
|
||||
filter_type = "o2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/co2
|
||||
name = "carbon dioxide filter"
|
||||
filter_type = "co2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o
|
||||
name = "nitrous oxide filter"
|
||||
filter_type = "n2o"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/plasma
|
||||
name = "plasma filter"
|
||||
filter_type = "plasma"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped //This feels wrong, I know
|
||||
icon_state = "filter_on_f"
|
||||
flipped = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2
|
||||
name = "nitrogen filter"
|
||||
filter_type = "n2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/o2
|
||||
name = "oxygen filter"
|
||||
filter_type = "o2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2
|
||||
name = "carbon dioxide filter"
|
||||
filter_type = "co2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2o
|
||||
name = "nitrous oxide filter"
|
||||
filter_type = "n2o"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/plasma
|
||||
name = "plasma filter"
|
||||
filter_type = "plasma"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/update_icon()
|
||||
cut_overlays()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
if(direction & initialize_directions)
|
||||
var/obj/machinery/atmospherics/node = findConnecting(direction)
|
||||
if(node)
|
||||
add_overlay(getpipeimage('icons/obj/atmospherics/components/trinary_devices.dmi', "cap", direction, node.pipe_color))
|
||||
continue
|
||||
add_overlay(getpipeimage('icons/obj/atmospherics/components/trinary_devices.dmi', "cap", direction))
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/update_icon_nopipes()
|
||||
if(on && nodes[1] && nodes[2] && nodes[3] && is_operational())
|
||||
icon_state = "filter_on[flipped?"_f":""]"
|
||||
return
|
||||
icon_state = "filter_off[flipped?"_f":""]"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(stat != old_stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/process_atmos()
|
||||
..()
|
||||
if(!on || !(nodes[1] && nodes[2] && nodes[3]) || !is_operational())
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
var/datum/gas_mixture/air2 = airs[2]
|
||||
var/datum/gas_mixture/air3 = airs[3]
|
||||
|
||||
var/output_starting_pressure = air3.return_pressure()
|
||||
|
||||
if(output_starting_pressure >= target_pressure)
|
||||
//No need to transfer if target is already full!
|
||||
return
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles
|
||||
|
||||
if(air1.temperature > 0)
|
||||
transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
|
||||
if(transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
|
||||
if(!removed)
|
||||
return
|
||||
|
||||
var/filtering = TRUE
|
||||
if(!ispath(filter_type))
|
||||
if(filter_type)
|
||||
filter_type = gas_id2path(filter_type) //support for mappers so they don't need to type out paths
|
||||
else
|
||||
filtering = FALSE
|
||||
|
||||
if(filtering && removed.gases[filter_type])
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
|
||||
filtered_out.temperature = removed.temperature
|
||||
filtered_out.gases[filter_type] = removed.gases[filter_type]
|
||||
|
||||
removed.gases[filter_type] = 0
|
||||
removed.garbage_collect()
|
||||
|
||||
var/datum/gas_mixture/target = (air2.return_pressure() < target_pressure ? air2 : air1) //if there's no room for the filtered gas; just leave it in air1
|
||||
target.merge(filtered_out)
|
||||
|
||||
air3.merge(removed)
|
||||
|
||||
update_parents()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmosinit()
|
||||
set_frequency(frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_filter", name, 475, 195, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
|
||||
var/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
|
||||
data["filter_types"] = list()
|
||||
data["filter_types"] += list(list("name" = "Nothing", "path" = "", "selected" = !filter_type))
|
||||
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], "id" = gas[META_GAS_ID], "selected" = (path == gas_id2path(filter_type))))
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/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("pressure")
|
||||
var/pressure = params["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure) && !..())
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
if("filter")
|
||||
filter_type = null
|
||||
var/filter_name = "nothing"
|
||||
var/gas = gas_id2path(params["mode"])
|
||||
if(gas in GLOB.meta_gas_info)
|
||||
filter_type = gas
|
||||
filter_name = GLOB.meta_gas_info[gas][META_GAS_NAME]
|
||||
investigate_log("was set to filter [filter_name] by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/can_unwrench(mob/user)
|
||||
. = ..()
|
||||
if(. && on && is_operational())
|
||||
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
|
||||
return FALSE
|
||||
/obj/machinery/atmospherics/components/trinary/filter
|
||||
name = "gas filter"
|
||||
icon_state = "filter_off"
|
||||
desc = "Very useful for filtering gasses."
|
||||
density = FALSE
|
||||
can_unwrench = TRUE
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
var/filter_type = null
|
||||
var/frequency = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
construction_type = /obj/item/pipe/trinary/flippable
|
||||
pipe_state = "filter"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped
|
||||
icon_state = "filter_off_f"
|
||||
flipped = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
// 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.
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/critical
|
||||
critical_machine = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/flipped/critical
|
||||
critical_machine = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos //Used for atmos waste loops
|
||||
on = TRUE
|
||||
icon_state = "filter_on"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/n2
|
||||
name = "nitrogen filter"
|
||||
filter_type = "n2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/o2
|
||||
name = "oxygen filter"
|
||||
filter_type = "o2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/co2
|
||||
name = "carbon dioxide filter"
|
||||
filter_type = "co2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o
|
||||
name = "nitrous oxide filter"
|
||||
filter_type = "n2o"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/plasma
|
||||
name = "plasma filter"
|
||||
filter_type = "plasma"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped //This feels wrong, I know
|
||||
icon_state = "filter_on_f"
|
||||
flipped = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2
|
||||
name = "nitrogen filter"
|
||||
filter_type = "n2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/o2
|
||||
name = "oxygen filter"
|
||||
filter_type = "o2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2
|
||||
name = "carbon dioxide filter"
|
||||
filter_type = "co2"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2o
|
||||
name = "nitrous oxide filter"
|
||||
filter_type = "n2o"
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/plasma
|
||||
name = "plasma filter"
|
||||
filter_type = "plasma"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/update_icon()
|
||||
cut_overlays()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
if(direction & initialize_directions)
|
||||
var/obj/machinery/atmospherics/node = findConnecting(direction)
|
||||
if(node)
|
||||
add_overlay(getpipeimage('icons/obj/atmospherics/components/trinary_devices.dmi', "cap", direction, node.pipe_color))
|
||||
continue
|
||||
add_overlay(getpipeimage('icons/obj/atmospherics/components/trinary_devices.dmi', "cap", direction))
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/update_icon_nopipes()
|
||||
if(on && nodes[1] && nodes[2] && nodes[3] && is_operational())
|
||||
icon_state = "filter_on[flipped?"_f":""]"
|
||||
return
|
||||
icon_state = "filter_off[flipped?"_f":""]"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(stat != old_stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/process_atmos()
|
||||
..()
|
||||
if(!on || !(nodes[1] && nodes[2] && nodes[3]) || !is_operational())
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
var/datum/gas_mixture/air2 = airs[2]
|
||||
var/datum/gas_mixture/air3 = airs[3]
|
||||
|
||||
var/output_starting_pressure = air3.return_pressure()
|
||||
|
||||
if(output_starting_pressure >= target_pressure)
|
||||
//No need to transfer if target is already full!
|
||||
return
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles
|
||||
|
||||
if(air1.temperature > 0)
|
||||
transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
|
||||
if(transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
|
||||
if(!removed)
|
||||
return
|
||||
|
||||
var/filtering = TRUE
|
||||
if(!ispath(filter_type))
|
||||
if(filter_type)
|
||||
filter_type = gas_id2path(filter_type) //support for mappers so they don't need to type out paths
|
||||
else
|
||||
filtering = FALSE
|
||||
|
||||
if(filtering && removed.gases[filter_type])
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
|
||||
filtered_out.temperature = removed.temperature
|
||||
filtered_out.gases[filter_type] = removed.gases[filter_type]
|
||||
|
||||
removed.gases[filter_type] = 0
|
||||
GAS_GARBAGE_COLLECT(removed.gases)
|
||||
|
||||
var/datum/gas_mixture/target = (air2.return_pressure() < target_pressure ? air2 : air1) //if there's no room for the filtered gas; just leave it in air1
|
||||
target.merge(filtered_out)
|
||||
|
||||
air3.merge(removed)
|
||||
|
||||
update_parents()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/atmosinit()
|
||||
set_frequency(frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_filter", name, 475, 195, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
|
||||
var/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
|
||||
data["filter_types"] = list()
|
||||
data["filter_types"] += list(list("name" = "Nothing", "path" = "", "selected" = !filter_type))
|
||||
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], "id" = gas[META_GAS_ID], "selected" = (path == gas_id2path(filter_type))))
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/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("pressure")
|
||||
var/pressure = params["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure) && !..())
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
if("filter")
|
||||
filter_type = null
|
||||
var/filter_name = "nothing"
|
||||
var/gas = gas_id2path(params["mode"])
|
||||
if(gas in GLOB.meta_gas_info)
|
||||
filter_type = gas
|
||||
filter_name = GLOB.meta_gas_info[gas][META_GAS_NAME]
|
||||
investigate_log("was set to filter [filter_name] by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/can_unwrench(mob/user)
|
||||
. = ..()
|
||||
if(. && on && is_operational())
|
||||
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents.
|
||||
beaker.reagents.reaction(occupant, VAPOR)
|
||||
air1.gases[/datum/gas/oxygen] -= max(0,air1.gases[/datum/gas/oxygen] - 2 / efficiency) //Let's use gas for this
|
||||
air1.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(air1.gases)
|
||||
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
|
||||
reagent_transfer = 0
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
mob_occupant.adjust_bodytemperature(heat / heat_capacity, TCMB)
|
||||
|
||||
air1.gases[/datum/gas/oxygen] = max(0,air1.gases[/datum/gas/oxygen] - 0.5 / efficiency) // Magically consume gas? Why not, we run on cryo magic.
|
||||
air1.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(air1.gases)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
|
||||
..()
|
||||
|
||||
@@ -1,329 +1,329 @@
|
||||
#define SIPHONING 0
|
||||
#define SCRUBBING 1
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber
|
||||
name = "air scrubber"
|
||||
desc = "Has a valve and pump attached to it."
|
||||
icon_state = "scrub_map"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 60
|
||||
can_unwrench = TRUE
|
||||
welded = FALSE
|
||||
level = 1
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
|
||||
var/id_tag = null
|
||||
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
|
||||
|
||||
var/filter_types = list(/datum/gas/carbon_dioxide)
|
||||
var/volume_rate = 200
|
||||
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
|
||||
var/list/turf/adjacent_turfs = list()
|
||||
|
||||
var/frequency = FREQ_ATMOS_CONTROL
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/radio_filter_out
|
||||
var/radio_filter_in
|
||||
|
||||
pipe_state = "scrubber"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
|
||||
..()
|
||||
if(!id_tag)
|
||||
id_tag = assign_uid_vents()
|
||||
|
||||
for(var/f in filter_types)
|
||||
if(istext(f))
|
||||
filter_types -= f
|
||||
filter_types += gas_id2path(f)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on
|
||||
on = TRUE
|
||||
icon_state = "scrub_map_on"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
|
||||
var/area/A = get_area(src)
|
||||
if (A)
|
||||
A.air_scrub_names -= id_tag
|
||||
A.air_scrub_info -= id_tag
|
||||
|
||||
SSradio.remove_object(src,frequency)
|
||||
radio_connection = null
|
||||
adjacent_turfs.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power()
|
||||
if(!on || welded || !is_operational() || !powered(power_channel))
|
||||
return FALSE
|
||||
|
||||
var/amount = idle_power_usage
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
amount += idle_power_usage * length(filter_types)
|
||||
else //scrubbing == SIPHONING
|
||||
amount = active_power_usage
|
||||
|
||||
if(widenet)
|
||||
amount += amount * (adjacent_turfs.len * (adjacent_turfs.len / 2))
|
||||
use_power(amount, power_channel)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes()
|
||||
cut_overlays()
|
||||
if(showpipe)
|
||||
add_overlay(getpipeimage(icon, "scrub_cap", initialize_directions))
|
||||
|
||||
if(welded)
|
||||
icon_state = "scrub_welded"
|
||||
return
|
||||
|
||||
if(!nodes[1] || !on || !is_operational())
|
||||
icon_state = "scrub_off"
|
||||
return
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
if(widenet)
|
||||
icon_state = "scrub_wide"
|
||||
else
|
||||
icon_state = "scrub_on"
|
||||
else //scrubbing == SIPHONING
|
||||
icon_state = "scrub_purge"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
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)))
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
"frequency" = frequency,
|
||||
"device" = "VS",
|
||||
"timestamp" = world.time,
|
||||
"power" = on,
|
||||
"scrubbing" = scrubbing,
|
||||
"widenet" = widenet,
|
||||
"filter_types" = f_types,
|
||||
"sigtype" = "status"
|
||||
))
|
||||
|
||||
var/area/A = get_area(src)
|
||||
if(!A.air_scrub_names[id_tag])
|
||||
name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]"
|
||||
A.air_scrub_names[id_tag] = name
|
||||
|
||||
A.air_scrub_info[id_tag] = signal.data
|
||||
radio_connection.post_signal(src, signal, radio_filter_out)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit()
|
||||
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
|
||||
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
broadcast_status()
|
||||
check_turfs()
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos()
|
||||
..()
|
||||
if(welded || !is_operational())
|
||||
return FALSE
|
||||
if(!nodes[1] || !on)
|
||||
on = FALSE
|
||||
return FALSE
|
||||
scrub(loc)
|
||||
if(widenet)
|
||||
for(var/turf/tile in adjacent_turfs)
|
||||
scrub(tile)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/tile)
|
||||
if(!istype(tile))
|
||||
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)
|
||||
return FALSE
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
if(length(env_gases & filter_types))
|
||||
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
|
||||
|
||||
//Take a gas sample
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
//Nothing left to remove from the tile
|
||||
if(isnull(removed))
|
||||
return FALSE
|
||||
|
||||
var/list/removed_gases = removed.gases
|
||||
|
||||
//Filter it
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
var/list/filtered_gases = filtered_out.gases
|
||||
filtered_out.temperature = removed.temperature
|
||||
|
||||
for(var/gas in filter_types & removed_gases)
|
||||
filtered_gases[gas] = removed_gases[gas]
|
||||
removed_gases[gas] = 0
|
||||
|
||||
removed.garbage_collect()
|
||||
|
||||
//Remix the resulting gases
|
||||
air_contents.merge(filtered_out)
|
||||
tile.assume_air(removed)
|
||||
tile.air_update_turf()
|
||||
|
||||
else //Just siphoning all air
|
||||
|
||||
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
|
||||
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
air_contents.merge(removed)
|
||||
tile.air_update_turf()
|
||||
|
||||
update_parents()
|
||||
|
||||
return TRUE
|
||||
|
||||
//There is no easy way for an object to be notified of changes to atmos can pass flags
|
||||
// So we check every machinery process (2 seconds)
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/process()
|
||||
if(widenet)
|
||||
check_turfs()
|
||||
|
||||
//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/T = get_turf(src)
|
||||
if(istype(T))
|
||||
adjacent_turfs = T.GetAtmosAdjacentTurfs(alldir = 1)
|
||||
|
||||
/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 0
|
||||
|
||||
var/mob/signal_sender = signal.data["user"]
|
||||
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
if("widenet" in signal.data)
|
||||
widenet = text2num(signal.data["widenet"])
|
||||
if("toggle_widenet" in signal.data)
|
||||
widenet = !widenet
|
||||
|
||||
var/old_scrubbing = scrubbing
|
||||
if("scrubbing" in signal.data)
|
||||
scrubbing = text2num(signal.data["scrubbing"])
|
||||
if("toggle_scrubbing" in signal.data)
|
||||
scrubbing = !scrubbing
|
||||
if(scrubbing != old_scrubbing)
|
||||
investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
|
||||
|
||||
if("toggle_filter" in signal.data)
|
||||
filter_types ^= gas_id2path(signal.data["toggle_filter"])
|
||||
|
||||
if("set_filters" in signal.data)
|
||||
filter_types = list()
|
||||
for(var/gas in signal.data["set_filters"])
|
||||
filter_types += gas_id2path(gas)
|
||||
|
||||
if("init" in signal.data)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
|
||||
if("status" in signal.data)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/power_change()
|
||||
..()
|
||||
update_icon_nopipes()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/welder_act(mob/living/user, obj/item/I)
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>Now welding the scrubber.</span>")
|
||||
if(I.use_tool(src, user, 20, volume=50))
|
||||
if(!welded)
|
||||
user.visible_message("[user] welds the scrubber shut.","You weld the scrubber shut.", "You hear welding.")
|
||||
welded = TRUE
|
||||
else
|
||||
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
|
||||
welded = FALSE
|
||||
update_icon()
|
||||
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
|
||||
pipe_vision_img.plane = ABOVE_HUD_PLANE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user)
|
||||
. = ..()
|
||||
if(. && on && is_operational())
|
||||
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/examine(mob/user)
|
||||
..()
|
||||
if(welded)
|
||||
to_chat(user, "It seems welded shut.")
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
|
||||
return !welded
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user)
|
||||
if(!welded || !(do_after(user, 20, target = src)))
|
||||
return
|
||||
user.visible_message("[user] furiously claws at [src]!", "You manage to clear away the stuff blocking the scrubber.", "You hear loud scraping noises.")
|
||||
welded = FALSE
|
||||
update_icon()
|
||||
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
|
||||
pipe_vision_img.plane = ABOVE_HUD_PLANE
|
||||
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
|
||||
|
||||
|
||||
|
||||
#undef SIPHONING
|
||||
#undef SCRUBBING
|
||||
#define SIPHONING 0
|
||||
#define SCRUBBING 1
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber
|
||||
name = "air scrubber"
|
||||
desc = "Has a valve and pump attached to it."
|
||||
icon_state = "scrub_map"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 60
|
||||
can_unwrench = TRUE
|
||||
welded = FALSE
|
||||
level = 1
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
|
||||
var/id_tag = null
|
||||
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
|
||||
|
||||
var/filter_types = list(/datum/gas/carbon_dioxide)
|
||||
var/volume_rate = 200
|
||||
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
|
||||
var/list/turf/adjacent_turfs = list()
|
||||
|
||||
var/frequency = FREQ_ATMOS_CONTROL
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/radio_filter_out
|
||||
var/radio_filter_in
|
||||
|
||||
pipe_state = "scrubber"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
|
||||
..()
|
||||
if(!id_tag)
|
||||
id_tag = assign_uid_vents()
|
||||
|
||||
for(var/f in filter_types)
|
||||
if(istext(f))
|
||||
filter_types -= f
|
||||
filter_types += gas_id2path(f)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on
|
||||
on = TRUE
|
||||
icon_state = "scrub_map_on"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
pixel_y = -PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3
|
||||
piping_layer = PIPING_LAYER_MAX
|
||||
pixel_x = PIPING_LAYER_P_X
|
||||
pixel_y = PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
|
||||
var/area/A = get_area(src)
|
||||
if (A)
|
||||
A.air_scrub_names -= id_tag
|
||||
A.air_scrub_info -= id_tag
|
||||
|
||||
SSradio.remove_object(src,frequency)
|
||||
radio_connection = null
|
||||
adjacent_turfs.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power()
|
||||
if(!on || welded || !is_operational() || !powered(power_channel))
|
||||
return FALSE
|
||||
|
||||
var/amount = idle_power_usage
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
amount += idle_power_usage * length(filter_types)
|
||||
else //scrubbing == SIPHONING
|
||||
amount = active_power_usage
|
||||
|
||||
if(widenet)
|
||||
amount += amount * (adjacent_turfs.len * (adjacent_turfs.len / 2))
|
||||
use_power(amount, power_channel)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes()
|
||||
cut_overlays()
|
||||
if(showpipe)
|
||||
add_overlay(getpipeimage(icon, "scrub_cap", initialize_directions))
|
||||
|
||||
if(welded)
|
||||
icon_state = "scrub_welded"
|
||||
return
|
||||
|
||||
if(!nodes[1] || !on || !is_operational())
|
||||
icon_state = "scrub_off"
|
||||
return
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
if(widenet)
|
||||
icon_state = "scrub_wide"
|
||||
else
|
||||
icon_state = "scrub_on"
|
||||
else //scrubbing == SIPHONING
|
||||
icon_state = "scrub_purge"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
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)))
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
"frequency" = frequency,
|
||||
"device" = "VS",
|
||||
"timestamp" = world.time,
|
||||
"power" = on,
|
||||
"scrubbing" = scrubbing,
|
||||
"widenet" = widenet,
|
||||
"filter_types" = f_types,
|
||||
"sigtype" = "status"
|
||||
))
|
||||
|
||||
var/area/A = get_area(src)
|
||||
if(!A.air_scrub_names[id_tag])
|
||||
name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]"
|
||||
A.air_scrub_names[id_tag] = name
|
||||
|
||||
A.air_scrub_info[id_tag] = signal.data
|
||||
radio_connection.post_signal(src, signal, radio_filter_out)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit()
|
||||
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
|
||||
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
broadcast_status()
|
||||
check_turfs()
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos()
|
||||
..()
|
||||
if(welded || !is_operational())
|
||||
return FALSE
|
||||
if(!nodes[1] || !on)
|
||||
on = FALSE
|
||||
return FALSE
|
||||
scrub(loc)
|
||||
if(widenet)
|
||||
for(var/turf/tile in adjacent_turfs)
|
||||
scrub(tile)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/tile)
|
||||
if(!istype(tile))
|
||||
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)
|
||||
return FALSE
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
if(length(env_gases & filter_types))
|
||||
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
|
||||
|
||||
//Take a gas sample
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
//Nothing left to remove from the tile
|
||||
if(isnull(removed))
|
||||
return FALSE
|
||||
|
||||
var/list/removed_gases = removed.gases
|
||||
|
||||
//Filter it
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
var/list/filtered_gases = filtered_out.gases
|
||||
filtered_out.temperature = removed.temperature
|
||||
|
||||
for(var/gas in filter_types & removed_gases)
|
||||
filtered_gases[gas] = removed_gases[gas]
|
||||
removed_gases[gas] = 0
|
||||
|
||||
GAS_GARBAGE_COLLECT(removed.gases)
|
||||
|
||||
//Remix the resulting gases
|
||||
air_contents.merge(filtered_out)
|
||||
tile.assume_air(removed)
|
||||
tile.air_update_turf()
|
||||
|
||||
else //Just siphoning all air
|
||||
|
||||
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
|
||||
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
air_contents.merge(removed)
|
||||
tile.air_update_turf()
|
||||
|
||||
update_parents()
|
||||
|
||||
return TRUE
|
||||
|
||||
//There is no easy way for an object to be notified of changes to atmos can pass flags
|
||||
// So we check every machinery process (2 seconds)
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/process()
|
||||
if(widenet)
|
||||
check_turfs()
|
||||
|
||||
//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/T = get_turf(src)
|
||||
if(istype(T))
|
||||
adjacent_turfs = T.GetAtmosAdjacentTurfs(alldir = 1)
|
||||
|
||||
/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 0
|
||||
|
||||
var/mob/signal_sender = signal.data["user"]
|
||||
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
if("widenet" in signal.data)
|
||||
widenet = text2num(signal.data["widenet"])
|
||||
if("toggle_widenet" in signal.data)
|
||||
widenet = !widenet
|
||||
|
||||
var/old_scrubbing = scrubbing
|
||||
if("scrubbing" in signal.data)
|
||||
scrubbing = text2num(signal.data["scrubbing"])
|
||||
if("toggle_scrubbing" in signal.data)
|
||||
scrubbing = !scrubbing
|
||||
if(scrubbing != old_scrubbing)
|
||||
investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
|
||||
|
||||
if("toggle_filter" in signal.data)
|
||||
filter_types ^= gas_id2path(signal.data["toggle_filter"])
|
||||
|
||||
if("set_filters" in signal.data)
|
||||
filter_types = list()
|
||||
for(var/gas in signal.data["set_filters"])
|
||||
filter_types += gas_id2path(gas)
|
||||
|
||||
if("init" in signal.data)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
|
||||
if("status" in signal.data)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/power_change()
|
||||
..()
|
||||
update_icon_nopipes()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/welder_act(mob/living/user, obj/item/I)
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>Now welding the scrubber.</span>")
|
||||
if(I.use_tool(src, user, 20, volume=50))
|
||||
if(!welded)
|
||||
user.visible_message("[user] welds the scrubber shut.","You weld the scrubber shut.", "You hear welding.")
|
||||
welded = TRUE
|
||||
else
|
||||
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
|
||||
welded = FALSE
|
||||
update_icon()
|
||||
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
|
||||
pipe_vision_img.plane = ABOVE_HUD_PLANE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user)
|
||||
. = ..()
|
||||
if(. && on && is_operational())
|
||||
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/examine(mob/user)
|
||||
..()
|
||||
if(welded)
|
||||
to_chat(user, "It seems welded shut.")
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
|
||||
return !welded
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user)
|
||||
if(!welded || !(do_after(user, 20, target = src)))
|
||||
return
|
||||
user.visible_message("[user] furiously claws at [src]!", "You manage to clear away the stuff blocking the scrubber.", "You hear loud scraping noises.")
|
||||
welded = FALSE
|
||||
update_icon()
|
||||
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
|
||||
pipe_vision_img.plane = ABOVE_HUD_PLANE
|
||||
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
|
||||
|
||||
|
||||
|
||||
#undef SIPHONING
|
||||
#undef SCRUBBING
|
||||
|
||||
@@ -1,145 +1,145 @@
|
||||
/obj/machinery/portable_atmospherics/scrubber
|
||||
name = "portable air scrubber"
|
||||
icon_state = "pscrubber:0"
|
||||
density = TRUE
|
||||
|
||||
var/on = FALSE
|
||||
var/volume_rate = 1000
|
||||
volume = 1000
|
||||
|
||||
var/list/scrubbing = list(/datum/gas/plasma, /datum/gas/carbon_dioxide, /datum/gas/nitrous_oxide, /datum/gas/bz, /datum/gas/nitryl, /datum/gas/tritium, /datum/gas/hypernoblium, /datum/gas/water_vapor)
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
T.assume_air(air_contents)
|
||||
air_update_turf()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/update_icon()
|
||||
icon_state = "pscrubber:[on]"
|
||||
|
||||
cut_overlays()
|
||||
if(holding)
|
||||
add_overlay("scrubber-open")
|
||||
if(connected_port)
|
||||
add_overlay("scrubber-connector")
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(holding)
|
||||
scrub(holding.air_contents)
|
||||
else
|
||||
var/turf/T = get_turf(src)
|
||||
scrub(T.return_air())
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
|
||||
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)
|
||||
return
|
||||
|
||||
filtered.temperature = filtering.temperature
|
||||
for(var/gas in filtering.gases & scrubbing)
|
||||
filtered.gases[gas] = filtering.gases[gas] // Shuffle the "bad" gasses to the filtered mixture.
|
||||
filtering.gases[gas] = 0
|
||||
filtering.garbage_collect() // Now that the gasses are set to 0, clean up the mixture.
|
||||
|
||||
air_contents.merge(filtered) // Store filtered out gasses.
|
||||
mixture.merge(filtering) // Returned the cleaned gas.
|
||||
if(!holding)
|
||||
air_update_turf()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(is_operational())
|
||||
if(prob(50 / severity))
|
||||
on = !on
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "portable_scrubber", name, 420, 435, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_data()
|
||||
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["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)))
|
||||
|
||||
if(holding)
|
||||
data["holding"] = list()
|
||||
data["holding"]["name"] = holding.name
|
||||
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
|
||||
return data
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
. = TRUE
|
||||
if("eject")
|
||||
if(holding)
|
||||
holding.forceMove(drop_location())
|
||||
holding = null
|
||||
. = TRUE
|
||||
if("toggle_filter")
|
||||
scrubbing ^= gas_id2path(params["val"])
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge
|
||||
name = "huge air scrubber"
|
||||
icon_state = "scrubber:0"
|
||||
anchored = TRUE
|
||||
active_power_usage = 500
|
||||
idle_power_usage = 10
|
||||
|
||||
volume_rate = 1500
|
||||
volume = 50000
|
||||
|
||||
var/movable = FALSE
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/movable
|
||||
movable = TRUE
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/update_icon()
|
||||
icon_state = "scrubber:[on]"
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/process_atmos()
|
||||
if((!anchored && !movable) || !is_operational())
|
||||
on = FALSE
|
||||
update_icon()
|
||||
use_power = on ? ACTIVE_POWER_USE : IDLE_POWER_USE
|
||||
if(!on)
|
||||
return
|
||||
|
||||
..()
|
||||
if(!holding)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/turf/AT in T.GetAtmosAdjacentTurfs(alldir = TRUE))
|
||||
scrub(AT.return_air())
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/attackby(obj/item/W, mob/user)
|
||||
if(default_unfasten_wrench(user, W))
|
||||
if(!movable)
|
||||
on = FALSE
|
||||
else
|
||||
return ..()
|
||||
/obj/machinery/portable_atmospherics/scrubber
|
||||
name = "portable air scrubber"
|
||||
icon_state = "pscrubber:0"
|
||||
density = TRUE
|
||||
|
||||
var/on = FALSE
|
||||
var/volume_rate = 1000
|
||||
volume = 1000
|
||||
|
||||
var/list/scrubbing = list(/datum/gas/plasma, /datum/gas/carbon_dioxide, /datum/gas/nitrous_oxide, /datum/gas/bz, /datum/gas/nitryl, /datum/gas/tritium, /datum/gas/hypernoblium, /datum/gas/water_vapor)
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
T.assume_air(air_contents)
|
||||
air_update_turf()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/update_icon()
|
||||
icon_state = "pscrubber:[on]"
|
||||
|
||||
cut_overlays()
|
||||
if(holding)
|
||||
add_overlay("scrubber-open")
|
||||
if(connected_port)
|
||||
add_overlay("scrubber-connector")
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(holding)
|
||||
scrub(holding.air_contents)
|
||||
else
|
||||
var/turf/T = get_turf(src)
|
||||
scrub(T.return_air())
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
|
||||
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)
|
||||
return
|
||||
|
||||
filtered.temperature = filtering.temperature
|
||||
for(var/gas in filtering.gases & scrubbing)
|
||||
filtered.gases[gas] = filtering.gases[gas] // Shuffle the "bad" gasses to the filtered mixture.
|
||||
filtering.gases[gas] = 0
|
||||
GAS_GARBAGE_COLLECT(filtering.gases)
|
||||
|
||||
air_contents.merge(filtered) // Store filtered out gasses.
|
||||
mixture.merge(filtering) // Returned the cleaned gas.
|
||||
if(!holding)
|
||||
air_update_turf()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(is_operational())
|
||||
if(prob(50 / severity))
|
||||
on = !on
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "portable_scrubber", name, 420, 435, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_data()
|
||||
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["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)))
|
||||
|
||||
if(holding)
|
||||
data["holding"] = list()
|
||||
data["holding"]["name"] = holding.name
|
||||
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
|
||||
return data
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
. = TRUE
|
||||
if("eject")
|
||||
if(holding)
|
||||
holding.forceMove(drop_location())
|
||||
holding = null
|
||||
. = TRUE
|
||||
if("toggle_filter")
|
||||
scrubbing ^= gas_id2path(params["val"])
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge
|
||||
name = "huge air scrubber"
|
||||
icon_state = "scrubber:0"
|
||||
anchored = TRUE
|
||||
active_power_usage = 500
|
||||
idle_power_usage = 10
|
||||
|
||||
volume_rate = 1500
|
||||
volume = 50000
|
||||
|
||||
var/movable = FALSE
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/movable
|
||||
movable = TRUE
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/update_icon()
|
||||
icon_state = "scrubber:[on]"
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/process_atmos()
|
||||
if((!anchored && !movable) || !is_operational())
|
||||
on = FALSE
|
||||
update_icon()
|
||||
use_power = on ? ACTIVE_POWER_USE : IDLE_POWER_USE
|
||||
if(!on)
|
||||
return
|
||||
|
||||
..()
|
||||
if(!holding)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/turf/AT in T.GetAtmosAdjacentTurfs(alldir = TRUE))
|
||||
scrub(AT.return_air())
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/huge/attackby(obj/item/W, mob/user)
|
||||
if(default_unfasten_wrench(user, W))
|
||||
if(!movable)
|
||||
on = FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
Reference in New Issue
Block a user