Increases performance significantly by turning garbage collection into a define
This commit is contained in:
+202
-202
@@ -1,202 +1,202 @@
|
||||
/obj/item/onetankbomb
|
||||
name = "bomb"
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
item_state = "assembly"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
throwforce = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 4
|
||||
flags_1 = CONDUCT_1
|
||||
var/status = FALSE //0 - not readied //1 - bomb finished with welder
|
||||
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
|
||||
/obj/item/onetankbomb/IsSpecialAssembly()
|
||||
return TRUE
|
||||
|
||||
/obj/item/onetankbomb/examine(mob/user)
|
||||
bombtank.examine(user)
|
||||
|
||||
/obj/item/onetankbomb/update_icon()
|
||||
cut_overlays()
|
||||
if(bombtank)
|
||||
icon = bombtank.icon
|
||||
icon_state = bombtank.icon_state
|
||||
if(bombassembly)
|
||||
add_overlay(bombassembly.icon_state)
|
||||
copy_overlays(bombassembly)
|
||||
add_overlay("bomb_assembly")
|
||||
|
||||
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
|
||||
if(bombassembly)
|
||||
bombassembly.forceMove(drop_location())
|
||||
bombassembly.master = null
|
||||
bombassembly = null
|
||||
if(bombtank)
|
||||
bombtank.forceMove(drop_location())
|
||||
bombtank.master = null
|
||||
bombtank = null
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
|
||||
. = FALSE
|
||||
if(status)
|
||||
to_chat(user, "<span class='notice'>[bombtank] already has a pressure hole!</span>")
|
||||
return
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return
|
||||
if(I.use_tool(src, user, 0, volume=40))
|
||||
status = TRUE
|
||||
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
|
||||
add_fingerprint(user)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I)
|
||||
bombtank.analyzer_act(user, I)
|
||||
|
||||
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
|
||||
bombassembly.attack_self(user, TRUE)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
|
||||
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
sleep(10)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(status)
|
||||
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
|
||||
else
|
||||
bombtank.release()
|
||||
|
||||
//Assembly / attached device memes
|
||||
|
||||
/obj/item/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.Crossed(AM)
|
||||
|
||||
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
|
||||
if(bombassembly)
|
||||
bombassembly.on_found(finder)
|
||||
|
||||
/obj/item/onetankbomb/attack_hand() //also for mousetraps
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(bombassembly)
|
||||
bombassembly.attack_hand()
|
||||
|
||||
/obj/item/onetankbomb/Move()
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.setDir(dir)
|
||||
bombassembly.Move()
|
||||
|
||||
/obj/item/onetankbomb/dropped()
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.dropped()
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
|
||||
|
||||
//Bomb assembly proc. This turns assembly+tank into a bomb
|
||||
/obj/item/tank/proc/bomb_assemble(obj/item/assembly_holder/assembly, mob/living/user)
|
||||
//Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
|
||||
if(isigniter(assembly.a_left) == isigniter(assembly.a_right))
|
||||
return
|
||||
|
||||
if((src in user.get_equipped_items(TRUE)) && !user.canUnEquip(src))
|
||||
to_chat(user, "<span class='warning'>[src] is stuck to you!</span>")
|
||||
return
|
||||
|
||||
if(!user.canUnEquip(assembly))
|
||||
to_chat(user, "<span class='warning'>[assembly] is stuck to your hand!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/onetankbomb/bomb = new
|
||||
user.transferItemToLoc(src, bomb)
|
||||
user.transferItemToLoc(assembly, bomb)
|
||||
|
||||
bomb.bombassembly = assembly //Tell the bomb about its assembly part
|
||||
assembly.master = bomb //Tell the assembly about its new owner
|
||||
|
||||
bomb.bombtank = src //Same for tank
|
||||
master = bomb
|
||||
|
||||
forceMove(bomb)
|
||||
bomb.update_icon()
|
||||
|
||||
user.put_in_hands(bomb) //Equips the bomb if possible, or puts it on the floor.
|
||||
to_chat(user, "<span class='notice'>You attach [assembly] to [src].</span>")
|
||||
return
|
||||
|
||||
/obj/item/tank/proc/ignite() //This happens when a bomb is told to explode
|
||||
var/fuel_moles = air_contents.gases[/datum/gas/plasma] + air_contents.gases[/datum/gas/oxygen]/6
|
||||
air_contents.garbage_collect()
|
||||
var/datum/gas_mixture/bomb_mixture = air_contents.copy()
|
||||
var/strength = 1
|
||||
|
||||
var/turf/ground_zero = get_turf(loc)
|
||||
|
||||
if(master)
|
||||
qdel(master)
|
||||
qdel(src)
|
||||
|
||||
if(bomb_mixture.temperature > (T0C + 400))
|
||||
strength = (fuel_moles/15)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1))
|
||||
else if(strength >=0.5)
|
||||
explosion(ground_zero, 0, 1, 2, 4)
|
||||
else if(strength >=0.2)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(bomb_mixture.temperature > (T0C + 250))
|
||||
strength = (fuel_moles/20)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1))
|
||||
else if (strength >=0.5)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(bomb_mixture.temperature > (T0C + 100))
|
||||
strength = (fuel_moles/25)
|
||||
|
||||
if (strength >=1)
|
||||
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
ground_zero.air_update_turf()
|
||||
|
||||
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
|
||||
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(removed)
|
||||
air_update_turf()
|
||||
/obj/item/onetankbomb
|
||||
name = "bomb"
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
item_state = "assembly"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
throwforce = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 4
|
||||
flags_1 = CONDUCT_1
|
||||
var/status = FALSE //0 - not readied //1 - bomb finished with welder
|
||||
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
|
||||
/obj/item/onetankbomb/IsSpecialAssembly()
|
||||
return TRUE
|
||||
|
||||
/obj/item/onetankbomb/examine(mob/user)
|
||||
bombtank.examine(user)
|
||||
|
||||
/obj/item/onetankbomb/update_icon()
|
||||
cut_overlays()
|
||||
if(bombtank)
|
||||
icon = bombtank.icon
|
||||
icon_state = bombtank.icon_state
|
||||
if(bombassembly)
|
||||
add_overlay(bombassembly.icon_state)
|
||||
copy_overlays(bombassembly)
|
||||
add_overlay("bomb_assembly")
|
||||
|
||||
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
|
||||
if(bombassembly)
|
||||
bombassembly.forceMove(drop_location())
|
||||
bombassembly.master = null
|
||||
bombassembly = null
|
||||
if(bombtank)
|
||||
bombtank.forceMove(drop_location())
|
||||
bombtank.master = null
|
||||
bombtank = null
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
|
||||
. = FALSE
|
||||
if(status)
|
||||
to_chat(user, "<span class='notice'>[bombtank] already has a pressure hole!</span>")
|
||||
return
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return
|
||||
if(I.use_tool(src, user, 0, volume=40))
|
||||
status = TRUE
|
||||
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
|
||||
add_fingerprint(user)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I)
|
||||
bombtank.analyzer_act(user, I)
|
||||
|
||||
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
|
||||
bombassembly.attack_self(user, TRUE)
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
|
||||
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
sleep(10)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(status)
|
||||
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
|
||||
else
|
||||
bombtank.release()
|
||||
|
||||
//Assembly / attached device memes
|
||||
|
||||
/obj/item/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.Crossed(AM)
|
||||
|
||||
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
|
||||
if(bombassembly)
|
||||
bombassembly.on_found(finder)
|
||||
|
||||
/obj/item/onetankbomb/attack_hand() //also for mousetraps
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(bombassembly)
|
||||
bombassembly.attack_hand()
|
||||
|
||||
/obj/item/onetankbomb/Move()
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.setDir(dir)
|
||||
bombassembly.Move()
|
||||
|
||||
/obj/item/onetankbomb/dropped()
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.dropped()
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
|
||||
|
||||
//Bomb assembly proc. This turns assembly+tank into a bomb
|
||||
/obj/item/tank/proc/bomb_assemble(obj/item/assembly_holder/assembly, mob/living/user)
|
||||
//Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
|
||||
if(isigniter(assembly.a_left) == isigniter(assembly.a_right))
|
||||
return
|
||||
|
||||
if((src in user.get_equipped_items(TRUE)) && !user.canUnEquip(src))
|
||||
to_chat(user, "<span class='warning'>[src] is stuck to you!</span>")
|
||||
return
|
||||
|
||||
if(!user.canUnEquip(assembly))
|
||||
to_chat(user, "<span class='warning'>[assembly] is stuck to your hand!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/onetankbomb/bomb = new
|
||||
user.transferItemToLoc(src, bomb)
|
||||
user.transferItemToLoc(assembly, bomb)
|
||||
|
||||
bomb.bombassembly = assembly //Tell the bomb about its assembly part
|
||||
assembly.master = bomb //Tell the assembly about its new owner
|
||||
|
||||
bomb.bombtank = src //Same for tank
|
||||
master = bomb
|
||||
|
||||
forceMove(bomb)
|
||||
bomb.update_icon()
|
||||
|
||||
user.put_in_hands(bomb) //Equips the bomb if possible, or puts it on the floor.
|
||||
to_chat(user, "<span class='notice'>You attach [assembly] to [src].</span>")
|
||||
return
|
||||
|
||||
/obj/item/tank/proc/ignite() //This happens when a bomb is told to explode
|
||||
var/fuel_moles = air_contents.gases[/datum/gas/plasma] + air_contents.gases[/datum/gas/oxygen]/6
|
||||
GAS_GARBAGE_COLLECT(air_contents.gases)
|
||||
var/datum/gas_mixture/bomb_mixture = air_contents.copy()
|
||||
var/strength = 1
|
||||
|
||||
var/turf/ground_zero = get_turf(loc)
|
||||
|
||||
if(master)
|
||||
qdel(master)
|
||||
qdel(src)
|
||||
|
||||
if(bomb_mixture.temperature > (T0C + 400))
|
||||
strength = (fuel_moles/15)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1))
|
||||
else if(strength >=0.5)
|
||||
explosion(ground_zero, 0, 1, 2, 4)
|
||||
else if(strength >=0.2)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(bomb_mixture.temperature > (T0C + 250))
|
||||
strength = (fuel_moles/20)
|
||||
|
||||
if(strength >=1)
|
||||
explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1))
|
||||
else if (strength >=0.5)
|
||||
explosion(ground_zero, -1, 0, 1, 2)
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(bomb_mixture.temperature > (T0C + 100))
|
||||
strength = (fuel_moles/25)
|
||||
|
||||
if (strength >=1)
|
||||
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
ground_zero.air_update_turf()
|
||||
|
||||
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
|
||||
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(removed)
|
||||
air_update_turf()
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
+548
-548
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@
|
||||
breath_gases[/datum/gas/plasma] -= toxins_used
|
||||
breath_gases[/datum/gas/oxygen] += toxins_used
|
||||
|
||||
breath.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(breath.gases)
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
@@ -291,7 +291,7 @@
|
||||
|
||||
|
||||
|
||||
breath.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(breath.gases)
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,7 +46,7 @@
|
||||
var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.gases[/datum/gas/plasma])
|
||||
loaded_tank.air_contents.gases[/datum/gas/plasma] -= gasdrained
|
||||
loaded_tank.air_contents.gases[/datum/gas/tritium] += gasdrained
|
||||
loaded_tank.air_contents.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
|
||||
|
||||
var/power_produced = RAD_COLLECTOR_OUTPUT
|
||||
add_avail(power_produced)
|
||||
@@ -60,7 +60,7 @@
|
||||
loaded_tank.air_contents.gases[/datum/gas/tritium] -= gasdrained
|
||||
loaded_tank.air_contents.gases[/datum/gas/oxygen] -= gasdrained
|
||||
loaded_tank.air_contents.gases[/datum/gas/carbon_dioxide] += gasdrained*2
|
||||
loaded_tank.air_contents.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
|
||||
var/bitcoins_mined = RAD_COLLECTOR_OUTPUT
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, bitcoins_mined*RAD_COLLECTOR_MINING_CONVERSION_RATE)
|
||||
stored_power-=bitcoins_mined
|
||||
|
||||
@@ -103,7 +103,7 @@ Chilling extracts:
|
||||
if(istype(G))
|
||||
G.gases[/datum/gas/plasma] = 0
|
||||
filtered = TRUE
|
||||
G.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(G.gases)
|
||||
T.air_update_turf()
|
||||
if(filtered)
|
||||
user.visible_message("<span class='notice'>Cracks spread throughout [src], and some air is sucked in!</span>")
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
|
||||
handle_breath_temperature(breath, H)
|
||||
breath.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(breath.gases)
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user