LINDA -> MILLA (#25328)

* LINDA -> MILLA

* Tiles now change their atmos mode properly.

* Fixed a bug that made walls generate supercold air when deconstructed/destroyed.

* Apply suggestions from code review

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

* Begone, var!

* MILLA -> milla

* Lint.

* More lint.

* Prevent negative/NaN atmos from spreading.

* Made fires start more reliably.

* Undef what the rest should not see.

* Enums are nice.

* Match LINDA better.

* Debugging verbs.

* Debug verb fixes.

* Labelled more lavaland stuff with ATMOS_MODE_LAVALAND

* Block superconductivity on a couple more things for Lavaland.

* Updated milla.dll

* Lavaland map fixes.

* Missed a spot.

* Begone, var! (again)

* Add libmilla_ci.so for continuous integration tests.

* Install/contributing instructions for MILLA.

* Directional plasmaglass windows on shuttles shouldn't stop protecting from heat after moving.

* Banish bad naming.

* Better naming and debug stats for SSair.

* Apply suggestions from code review

Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

* Magic numbers and formatting.

* Don't screw up the temperature during reactions.

* Efficiency and readability.

* Fix hotspots.

* Removed redundant safety (MILLA will already output an error)

* Optimizations.

* oops

* TGS build script update.

* Change API of gas_mixture and how you get one from a turf.

* Get in there.

* so many vars

* MILLA binary updates.

* Lint

* Made MT cost more honest.

* Gave MILLA a read-only mode.

* More read-only vs synchronized mode work.

* Even more.

* Synchronize disposals.

* Updated a bunch of stuff to use SSair.synchronize or GM.synchronize.

* MILLA <3 Tracy

* lint

* cargo fmt

* more lint

* Test needed MILLA sync.

* Silence atmos machinery that's behaving as intended, but continue objecting to other potential failures to synchronize.

* Push new MILLA DLL

* Build MILLA

* Update PR instructions for MILLA.

* Add some fancy plasmaglass windows to the Lifebringers' ship.

* The golems remembered that they should insulate *all* their engines.

* First round of TM bugfixes.

* Build MILLA

* fix two lavaland ruin turf types

* bunch more maps

* fixes milla ci and makes the interesting turf verb better

* Solid turfs can no longer conduct heat (for now...)

* Made indoor tiles in beach and winter biodomes not lavaland air.

* Re-added random IT teleport, adjusted warning message

* Fixed a tinted window on Lavaland to be a plasglass window instead.

* Made firelocks and holofans heatproof

* Made RPD auto-wrench pipes if you have a wrench in your offhand.

* Runtime fixes.

* Made visuals update more reliably.

* Lint

* Update .github/CONTRIBUTING.md

Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

* Build MILLA

* The Syndicate have installed tiny fans on their research base.

* The syndicate have figured out how to make plastitanium windows heatproof.

* This is getting out of hand. Now there are two of them.

* Un-break the auto-wrenching that I broke before committing.

* Build MILLA

* Build MILLA

* Massive MILLA refactor, assorted bugfixes.

* Build MILLA

* Explicit typing.

* Less sleeping/blocking.

* Build MILLA

* Yes, yes, this part can sleep.

* Build MILLA

* SSair reporting improvements.

* Build MILLA

* Please do not dock twice and splat yourself.

* Build MILLA

* Pls to not make SM go nuts.

* Build MILLA

* Build MILLA

* Added stricter lower bounds on plasmafire, fixing perpetually-burning SM.

* Build MILLA

* Lint

* Temporary logging, begone.

* Build MILLA

* Prevent hotspot strobing.

* Add in radiate_to_spess behavior.

* Build MILLA

* progress

* Compiling is good.

* bugfixes

* Progress.

* Ruins update.

* This one exists.

* Fixup temporary hotspots to last longer than one tick.

* Add/fix comments.

* Cut the slash.

* Fix test.

* No sleep for you.

* Build MILLA

* Prevent nested MILLA safety from runtiming.

* Build MILLA

* Runtime fix.

* Build MILLA

* Fix canisters not updating icon when gas contents change.

* Build MILLA

* Build MILLA

* Fixed an issue that made mechs very cold on environment air.

* Build MILLA

* oops

* Build MILLA

* Walls can make loud noises again.

* Build MILLA

* Fixes a rare runtime.

* Build MILLA

* Update .github/DOWNLOADING.md

Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

* Review suggestions

* Lint

* Build MILLA

* bound_mixtures now only contains mixtures that can be written

* Build MILLA

* Apply suggestions from code review

Co-authored-by: Matt <116982774+Burzah@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

* Build MILLA

* Restore the original async behavior of pyro anomalies.

* Build MILLA

* Build MILLA

* Make the safety assertion in /datum/milla_safe safer.

* Build MILLA

---------

Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>
Co-authored-by: FunnyMan3595 (Charlie Nolan) <funnyman@google.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com>
Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Co-authored-by: paradisess13[bot] <165046124+paradisess13[bot]@users.noreply.github.com>
Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Co-authored-by: GDN <Roanrichards1@Gmail.com>
This commit is contained in:
Charlie Nolan
2024-06-09 00:18:11 -07:00
committed by GitHub
parent 56b4da8ffc
commit d3584b1d1c
200 changed files with 7244 additions and 3918 deletions
+110 -2
View File
@@ -157,7 +157,6 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/view_runtimes,
/client/proc/admin_serialize,
/client/proc/uid_log,
/client/proc/visualise_active_turfs,
/client/proc/reestablish_db_connection,
/client/proc/ss_breakdown,
#ifdef REFERENCE_TRACKING
@@ -172,6 +171,9 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/force_verb_bypass,
/client/proc/show_gc_queues,
/client/proc/debug_global_variables,
/client/proc/raw_gas_scan,
/client/proc/teleport_interesting_turf,
/client/proc/visualize_interesting_turfs,
/client/proc/profile_code,
/client/proc/debug_atom_init
))
@@ -242,9 +244,11 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
/client/proc/ss_breakdown,
/client/proc/show_gc_queues,
/client/proc/debug_global_variables,
/client/proc/visualise_active_turfs,
/client/proc/debug_timers,
/client/proc/timer_log,
/client/proc/raw_gas_scan,
/client/proc/teleport_interesting_turf,
/client/proc/visualize_interesting_turfs,
/client/proc/profile_code
))
@@ -1117,3 +1121,107 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
if(ishuman(mob))
var/mob/living/carbon/human/H = mob
H.export_dmi_json()
/client/proc/raw_gas_scan()
set name = "Raw Gas Scan"
set category = "Debug"
set desc = "Scans your current tile, including LINDA data not normally displayed."
if(!check_rights(R_DEBUG | R_VIEWRUNTIMES))
return
atmos_scan(mob, get_turf(mob), silent = TRUE, milla_turf_details = TRUE)
/client/proc/teleport_interesting_turf()
set name = "Interesting Turf"
set category = "Debug"
set desc = "Teleports you to a random Interesting Turf from MILLA"
if(!check_rights(R_DEBUG | R_VIEWRUNTIMES))
return
if(!isobserver(mob))
to_chat(mob, "<span class='warning'>You must be an observer to do this!</span>")
return
var/list/interesting_tile = get_random_interesting_tile()
if(!length(interesting_tile))
to_chat(mob, "<span class='notice'>There are no interesting turfs. How interesting!</span>")
return
var/turf/T = interesting_tile[MILLA_INDEX_TURF]
var/mob/dead/observer/O = mob
admin_forcemove(O, T)
O.ManualFollow(T)
/client/proc/visualize_interesting_turfs()
set name = "Visualize Interesting Turfs"
set category = "Debug"
set desc = "Shows all the Interesting Turfs from MILLA"
if(!check_rights(R_DEBUG | R_VIEWRUNTIMES))
return
if(SSair.interesting_tile_count > 500)
// This can potentially iterate through a list thats 20k things long. Give ample warning to the user
var/confirm = alert(usr, "WARNING: There are [SSair.interesting_tile_count] Interesting Turfs. This process will be lag intensive and should only be used if the atmos controller is screaming bloody murder. Are you sure you with to continue", "WARNING", "I am sure", "Nope")
if(confirm != "I am sure")
return
var/display_turfs_overlay = FALSE
var/do_display_turf_overlay = alert(usr, "Would you like to have all interesting turfs have a client side overlay applied as well?", "Optional", "Yep", "Nope")
if(do_display_turf_overlay == "Yep")
display_turfs_overlay = TRUE
message_admins("[key_name_admin(usr)] is visualising interesting atmos turfs. Server may lag.")
var/list/zlevel_turf_indexes = list()
var/list/coords = get_interesting_atmos_tiles()
if(!length(coords))
to_chat(mob, "<span class='notice'>There are no interesting turfs. How interesting!</span>")
return
while(length(coords))
var/offset = length(coords) - MILLA_INTERESTING_TILE_SIZE
var/turf/T = coords[offset + MILLA_INDEX_TURF]
coords.len -= MILLA_INTERESTING_TILE_SIZE
// ENSURE YOU USE STRING NUMBERS HERE, THIS IS A DICTIONARY KEY NOT AN INDEX!!!
if(!zlevel_turf_indexes["[T.z]"])
zlevel_turf_indexes["[T.z]"] = list()
zlevel_turf_indexes["[T.z]"] |= T
if(display_turfs_overlay)
usr.client.images += image('icons/effects/alphacolors.dmi', T, "red")
CHECK_TICK
// Sort the keys
zlevel_turf_indexes = sortAssoc(zlevel_turf_indexes)
for(var/key in zlevel_turf_indexes)
to_chat(usr, "<span class='notice'>Z[key]: <b>[length(zlevel_turf_indexes["[key]"])] Interesting Turfs</b></span>")
var/z_to_view = input(usr, "A list of z-levels their ITs has appeared in chat. Please enter a Z to visualise. Enter 0 to cancel.", "Selection", 0) as num
if(!z_to_view)
return
// Do not combine these
var/list/ui_dat = list()
var/list/turf_markers = list()
var/datum/browser/vis = new(usr, "atvis", "Interesting Turfs (Z[z_to_view])", 300, 315)
ui_dat += "<center><canvas width=\"255px\" height=\"255px\" id=\"atmos\"></canvas></center>"
ui_dat += "<script>e=document.getElementById(\"atmos\");c=e.getContext('2d');c.fillStyle='#ffffff';c.fillRect(0,0,255,255);function s(x,y){var p=c.createImageData(1,1);p.data\[0]=255;p.data\[1]=0;p.data\[2]=0;p.data\[3]=255;c.putImageData(p,(x-1),255-Math.abs(y-1));}</script>"
// Now generate the other list
for(var/x in zlevel_turf_indexes["[z_to_view]"])
var/turf/T = x
turf_markers += "s([T.x],[T.y]);"
CHECK_TICK
ui_dat += "<script>[turf_markers.Join("")]</script>"
vis.set_content(ui_dat.Join(""))
vis.open(FALSE)
+3 -1
View File
@@ -2091,7 +2091,9 @@
if("Fire Death")
to_chat(M,"<span class='userdanger'>You feel hotter than usual. Maybe you should lowe-wait, is that your hand melting?</span>")
var/turf/simulated/T = get_turf(M)
new /obj/effect/hotspot(T)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(T)
hotspot.temperature = 1000
hotspot.recolor()
M.adjustFireLoss(150)
logmsg = "a firey death."
if("Gib")
+6 -66
View File
@@ -262,13 +262,13 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!isturf(T))
return
var/datum/gas_mixture/env = T.return_air()
var/datum/gas_mixture/env = T.get_readonly_air()
var/t = ""
t+= "Nitrogen : [env.nitrogen]\n"
t+= "Oxygen : [env.oxygen]\n"
t+= "Plasma : [env.toxins]\n"
t+= "CO2: [env.carbon_dioxide]\n"
t+= "Nitrogen : [env.nitrogen()]\n"
t+= "Oxygen : [env.oxygen()]\n"
t+= "Plasma : [env.toxins()]\n"
t+= "CO2: [env.carbon_dioxide()]\n"
usr.show_message(t, 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Air Status (Location)") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -736,7 +736,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(Rad.anchored)
if(!Rad.loaded_tank)
var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad)
Plasma.air_contents.toxins = 70
Plasma.air_contents.set_toxins(70)
Rad.drainratio = 0
Rad.loaded_tank = Plasma
Plasma.loc = Rad
@@ -930,66 +930,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
to_chat(src, "<span class='info'>You can now right click to use inspect on browsers.</span>")
winset(src, "", "browser-options=byondstorage,find,devtools")
/client/proc/visualise_active_turfs()
set category = "Debug"
set name = "Visualise Active Turfs"
if(!check_rights(R_DEBUG | R_VIEWRUNTIMES))
return
// This can potentially iterate through a list thats 20k things long. Give ample warning to the user
var/confirm = alert(usr, "WARNING: This process is lag intensive and should only be used if the atmos controller is screaming bloody murder. Are you sure you with to continue", "WARNING", "Im sure", "Nope")
if(confirm != "Im sure")
return
var/display_turfs_overlay = FALSE
var/do_display_turf_overlay = alert(usr, "Would you like to have all active turfs have a client side overlay applied as well?", "Optional", "Yep", "Nope")
if(do_display_turf_overlay == "Yep")
display_turfs_overlay = TRUE
message_admins("[key_name_admin(usr)] is visualising active atmos turfs. Server may lag.")
var/list/zlevel_turf_indexes = list()
for(var/i in SSair.active_turfs)
var/turf/T = i
// ENSURE YOU USE STRING NUMBERS HERE, THIS IS A DICTIONARY KEY NOT AN INDEX!!!
if(!zlevel_turf_indexes["[T.z]"])
zlevel_turf_indexes["[T.z]"] = list()
zlevel_turf_indexes["[T.z]"] |= T
if(display_turfs_overlay)
usr.client.images += image('icons/effects/alphacolors.dmi', T, "red")
CHECK_TICK
// Sort the keys
zlevel_turf_indexes = sortAssoc(zlevel_turf_indexes)
for(var/key in zlevel_turf_indexes)
to_chat(usr, "<span class='notice'>Z[key]: <b>[length(zlevel_turf_indexes["[key]"])] ATs</b></span>")
var/z_to_view = input(usr, "A list of z-levels their ATs has appeared in chat. Please enter a Z to visualise. Enter 0 to cancel.", "Selection", 0) as num
if(!z_to_view)
return
// Do not combine these
var/list/ui_dat = list()
var/list/turf_markers = list()
var/datum/browser/vis = new(usr, "atvis", "Active Turfs (Z[z_to_view])", 300, 315)
ui_dat += "<center><canvas width=\"255px\" height=\"255px\" id=\"atmos\"></canvas></center>"
ui_dat += "<script>e=document.getElementById(\"atmos\");c=e.getContext('2d');c.fillStyle='#ffffff';c.fillRect(0,0,255,255);function s(x,y){var p=c.createImageData(1,1);p.data\[0]=255;p.data\[1]=0;p.data\[2]=0;p.data\[3]=255;c.putImageData(p,(x-1),255-Math.abs(y-1));}</script>"
// Now generate the other list
for(var/x in zlevel_turf_indexes["[z_to_view]"])
var/turf/T = x
turf_markers += "s([T.x],[T.y]);"
CHECK_TICK
ui_dat += "<script>[turf_markers.Join("")]</script>"
vis.set_content(ui_dat.Join(""))
vis.open(FALSE)
/client/proc/cmd_clean_radiation()
set name = "Remove All Radiation"
set desc = "Remove all radiation in the world."
+2 -2
View File
@@ -8,14 +8,14 @@
if(!isturf(target))
return
var/datum/gas_mixture/GM = target.return_air()
var/datum/gas_mixture/GM = target.get_readonly_air()
var/burning = 0
if(issimulatedturf(target))
var/turf/simulated/T = target
if(T.active_hotspot)
burning = 1
to_chat(usr, "<span class='notice'>@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] N2O: [GM.sleeping_agent] Agent B: [GM.agent_b] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("<span class='warning'>BURNING</span>"):(null)]</span>")
to_chat(usr, "<span class='notice'>@[target.x],[target.y]: O:[GM.oxygen()] T:[GM.toxins()] N:[GM.nitrogen()] C:[GM.carbon_dioxide()] N2O: [GM.sleeping_agent()] Agent B: [GM.agent_b()] w [GM.temperature()] Kelvin, [GM.return_pressure()] kPa [(burning)?("<span class='warning'>BURNING</span>"):(null)]</span>")
message_admins("[key_name_admin(usr)] has checked the air status of [target]")
log_admin("[key_name(usr)] has checked the air status of [target]")
+19 -21
View File
@@ -54,14 +54,14 @@
return
if(!status)
status = TRUE
investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]")
investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", INVESTIGATE_BOMB)
log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]")
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.</span>")
add_attack_logs(user, src, "welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW)
add_attack_logs(user, src, "welded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", ATKLOG_FEW)
else
status = FALSE
investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
add_attack_logs(user, src, "unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_ALMOSTALL)
investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", INVESTIGATE_BOMB)
add_attack_logs(user, src, "unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", ATKLOG_ALMOSTALL)
to_chat(user, "<span class='notice'>The hole has been closed.</span>")
@@ -117,14 +117,14 @@
return
/obj/item/tank/proc/detonate() //This happens when a bomb is told to explode
var/fuel_moles = air_contents.toxins + air_contents.oxygen / 6
var/fuel_moles = air_contents.toxins() + air_contents.oxygen() / 6
var/strength = 1
var/turf/ground_zero = get_turf(loc)
loc = null
if(air_contents.temperature > (T0C + 400))
strength = (fuel_moles/15)
if(air_contents.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))
@@ -133,34 +133,33 @@
else if(strength >=0.2)
explosion(ground_zero, -1, 0, 1, 2)
else
ground_zero.assume_air(air_contents)
ground_zero.blind_release_air(air_contents)
ground_zero.hotspot_expose(1000, 125)
else if(air_contents.temperature > (T0C + 250))
else if(air_contents.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))
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(air_contents)
ground_zero.blind_release_air(air_contents)
ground_zero.hotspot_expose(1000, 125)
else if(air_contents.temperature > (T0C + 100))
strength = (fuel_moles/25)
else if(air_contents.temperature() > (T0C + 100))
strength = (fuel_moles / 25)
if(strength >=1)
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
if(strength >= 1)
explosion(ground_zero, -1, 0, round(strength, 1), round(strength * 3, 1))
else
ground_zero.assume_air(air_contents)
ground_zero.blind_release_air(air_contents)
ground_zero.hotspot_expose(1000, 125)
else
ground_zero.assume_air(air_contents)
ground_zero.blind_release_air(air_contents)
ground_zero.hotspot_expose(1000, 125)
air_update_turf()
if(master)
qdel(master)
qdel(src)
@@ -170,5 +169,4 @@
var/turf/simulated/T = get_turf(src)
if(!T)
return
T.assume_air(removed)
air_update_turf()
T.blind_release_air(removed)
@@ -4,44 +4,37 @@
reagents.temperature_reagents(exposed_temperature)
return null
/turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
return
return FALSE
/turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
var/datum/gas_mixture/air_contents = return_air()
if(reagents)
reagents.temperature_reagents(exposed_temperature, 10, 300)
if(!air_contents)
return 0
if(!issimulatedturf(src))
return FALSE
var/datum/gas_mixture/air = get_readonly_air()
if(!air)
return FALSE
if(active_hotspot)
if(soh)
if(air_contents.toxins > 0.5 && air_contents.oxygen > 0.5)
if(air.toxins() > 0.5 && air.oxygen() > 0.5)
if(active_hotspot.temperature < exposed_temperature)
active_hotspot.temperature = exposed_temperature
if(active_hotspot.volume < exposed_volume)
active_hotspot.volume = exposed_volume
return 1
var/igniting = 0
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && air_contents.toxins > 0.5)
igniting = 1
if(igniting)
if(air_contents.oxygen < 0.5 || air_contents.toxins < 0.5)
return 0
return TRUE
if(exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE && air.oxygen() > 0.5 && air.toxins() > 0.5)
var/total = air.total_moles()
if(air.toxins() < 0.01 * total || air.oxygen() < 0.01 * total)
// The rest of the gas is snuffing out the reaction.
return FALSE
active_hotspot = new /obj/effect/hotspot(src)
active_hotspot.temperature = exposed_temperature
active_hotspot.volume = exposed_volume
return TRUE
active_hotspot.just_spawned = (current_cycle < SSair.times_fired)
//remove just_spawned protection if no longer processing this cell
SSair.add_to_active(src, 0)
return igniting
return FALSE
//This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile
/obj/effect/hotspot
@@ -56,8 +49,6 @@
var/volume = 125
var/temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
var/just_spawned = 1
var/bypassing = 0
var/fake = FALSE
var/burn_time = 0
@@ -65,76 +56,119 @@
..()
if(!fake)
SSair.hotspots += src
perform_exposure()
var/datum/milla_safe/hotspot_burn_plasma/milla = new()
milla.invoke_async(src)
dir = pick(GLOB.cardinal)
air_update_turf()
/obj/effect/hotspot/proc/perform_exposure()
/datum/milla_safe/hotspot_burn_plasma
/// Burns the air affected by this hotspot. A hotspot is effectively a gas fire that might not cover the entire tile yet. This proc makes that "partial fire" burn, altering the tile as a whole, and potentially setting the entire tile on fire.
/datum/milla_safe/hotspot_burn_plasma/on_run(obj/effect/hotspot/hotspot)
var/turf/simulated/location = get_turf(hotspot)
if(!istype(location) || location.blocks_air)
// We're in the wrong neighborhood.
qdel(hotspot)
return
var/datum/gas_mixture/location_air = get_turf_air(location)
if(location_air.temperature() >= min(hotspot.temperature, PLASMA_UPPER_TEMPERATURE))
// The cell is already hot enough, no need to do more.
hotspot.temperature = location_air.temperature()
hotspot.volume = CELL_VOLUME
hotspot.recolor()
return
if(location_air.toxins() < 0.5 || location_air.oxygen() < 0.5)
// Burn what, exactly?
qdel(hotspot)
return
var/total = location_air.total_moles()
if(location_air.toxins() < 0.01 * total || location_air.oxygen() < 0.01 * total)
// The rest of the gas is snuffing out the reaction.
qdel(hotspot)
return
// Get some of the surrounding air for the hotspot to burn.
var/datum/gas_mixture/burning = location_air.remove_ratio(hotspot.volume / location_air.volume)
// Temporarily boost the temperature of this air to the hotspot temperature.
var/old_temperature = burning.temperature()
burning.set_temperature(hotspot.temperature)
// Record how much plasma we had initially.
var/old_toxins = burning.toxins()
// Burn it.
burning.react()
// Calculate how much thermal energy was produced.
// (Yes, gas_mixture has its own .fuel_burnt, but I dont' trust that code.)
var/fuel_burnt = old_toxins - burning.toxins()
var/thermal_energy = FIRE_PLASMA_ENERGY_RELEASED * fuel_burnt
// Update the hotspot based on the reaction.
hotspot.temperature = burning.temperature()
hotspot.volume = min(CELL_VOLUME, fuel_burnt * FIRE_GROWTH_RATE)
hotspot.recolor()
// Revert the air's temperature to where it started.
burning.set_temperature(old_temperature)
var/heat_capacity = burning.heat_capacity()
if(heat_capacity)
// Add in the produced thermal energy.
burning.set_temperature(burning.temperature() + thermal_energy / burning.heat_capacity())
// And add it back to the tile.
location_air.merge(burning)
/obj/effect/hotspot/process()
var/turf/simulated/location = loc
if(!istype(location) || !(location.air))
return FALSE
if(!istype(location))
qdel(src)
return
if(volume > CELL_VOLUME * 0.95)
bypassing = TRUE
else
bypassing = FALSE
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
qdel(src)
return
if(bypassing)
if(!just_spawned)
volume = location.air.fuel_burnt * FIRE_GROWTH_RATE
temperature = location.air.temperature
else
var/datum/gas_mixture/affected = location.air.remove_ratio(volume / location.air.volume)
affected.temperature = temperature
affected.react()
temperature = affected.temperature
volume = affected.fuel_burnt * FIRE_GROWTH_RATE
location.assume_air(affected)
var/datum/gas_mixture/location_air = location.get_readonly_air()
if(location.blocks_air || location_air.toxins() < 0.5 || location_air.oxygen() < 0.5)
qdel(src)
return
var/datum/milla_safe/hotspot_burn_plasma/milla = new()
milla.invoke_async(src)
if(QDELETED(src))
return
for(var/A in loc)
var/atom/item = A
if(!QDELETED(item) && item != src) // It's possible that the item is deleted in temperature_expose
item.fire_act(null, temperature, volume)
color = heat2color(temperature)
set_light(l_color = color)
return FALSE
/obj/effect/hotspot/process()
if(just_spawned)
just_spawned = 0
return 0
var/turf/simulated/location = loc
if(!istype(location))
qdel(src)
// We are now space. No need to do anything else.
return
if(location.excited_group)
location.excited_group.reset_cooldowns()
if(location.wet)
location.wet = TURF_DRY
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
qdel(src)
return
if(!(location.air) || location.air.toxins < 0.5 || location.air.oxygen < 0.5)
qdel(src)
return
perform_exposure()
if(location.wet) location.wet = TURF_DRY
if(bypassing)
if(volume >= CELL_VOLUME * 0.95)
icon_state = "3"
location.burn_tile()
//Possible spread due to radiated heat
if(location.air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD)
var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE
for(var/turf/simulated/T in location.atmos_adjacent_turfs)
if(!T.active_hotspot)
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD)
var/radiated_temperature = temperature * FIRE_SPREAD_RADIOSITY_SCALE
for(var/direction in GLOB.cardinal)
var/turf/simulated/T = get_step(location, direction)
if(!istype(T))
continue
if(T.active_hotspot)
continue
if(src.CanAtmosPass(direction) && T.CanAtmosPass(turn(direction, 180)))
T.hotspot_expose(radiated_temperature, CELL_VOLUME / 4)
else
@@ -147,7 +181,7 @@
location.max_fire_temperature_sustained = temperature
if(location.heat_capacity && temperature > location.heat_capacity)
location.to_be_destroyed = 1
location.to_be_destroyed = TRUE
/*if(prob(25))
location.ReplaceWithSpace()
return 0*/
@@ -165,6 +199,10 @@
DestroyTurf()
return ..()
/obj/effect/hotspot/proc/recolor()
color = heat2color(temperature)
set_light(l_color = color)
/obj/effect/hotspot/proc/DestroyTurf()
if(issimulatedturf(loc))
var/turf/simulated/T = loc
@@ -212,8 +250,7 @@
var/obj/effect/hotspot/fake/H = new(T)
H.temperature = temp
H.volume = 400
H.color = heat2color(H.temperature)
H.set_light(l_color = H.color)
H.recolor()
T.hotspot_expose(H.temperature, H.volume)
for(var/atom/A in T)
@@ -270,8 +307,7 @@
H.temperature = temp - dist * falloff
expose_temp = H.temperature
H.volume = 400
H.color = heat2color(H.temperature)
H.set_light(l_color = H.color)
H.recolor()
existing_hotspot = H
else if(existing_hotspot.temperature < temp - dist * falloff)
@@ -280,8 +316,7 @@
if(expose_temp > prev_temp * 3)
need_expose = TRUE
existing_hotspot.temperature = temp - dist * falloff
existing_hotspot.color = heat2color(existing_hotspot.temperature)
existing_hotspot.set_light(l_color = existing_hotspot.color)
existing_hotspot.recolor()
affected[T] = existing_hotspot.temperature
if(need_expose && expose_temp)
@@ -310,12 +345,12 @@
if(dist == max_dist)
continue
for(var/dir in GLOB.cardinal)
var/turf/link = get_step(T, dir)
for(var/direction in GLOB.cardinal)
var/turf/link = get_step(T, direction)
if(!link)
continue
// Check if it wasn't already visited and if you can get to that turf
if(!closed[link] && T.CanAtmosPass(link))
if(!closed[link] && T.CanAtmosPass(direction) && link.CanAtmosPass(turn(direction, 180)))
var/dx = link.x - Ce.x
var/dy = link.y - Ce.y
var/target_dist = max((dist + 1 + sqrt(dx * dx + dy * dy)) / 2, dist)
@@ -1,39 +1,22 @@
/turf/proc/CanAtmosPass(turf/T)
if(!istype(T)) return 0
var/R
if(blocks_air || T.blocks_air)
R = 1
/turf/proc/CanAtmosPass(direction, consider_objects = TRUE)
if(blocks_air)
return FALSE
if(!consider_objects)
return TRUE
for(var/obj/O in contents)
if(!O.CanAtmosPass(T))
R = 1
if(O.BlockSuperconductivity()) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments
var/D = get_dir(src, T)
atmos_superconductivity |= D
D = get_dir(T, src)
T.atmos_superconductivity |= D
return 0 //no need to keep going, we got all we asked
if(istype(O, /obj/item))
// Items can't block atmos.
continue
for(var/obj/O in T.contents)
if(!O.CanAtmosPass(src))
R = 1
if(O.BlockSuperconductivity())
var/D = get_dir(src, T)
atmos_superconductivity |= D
D = get_dir(T, src)
T.atmos_superconductivity |= D
return 0
if(!O.CanAtmosPass(direction))
return FALSE
var/D = get_dir(src, T)
atmos_superconductivity &= ~D
D = get_dir(T, src)
T.atmos_superconductivity &= ~D
if(!R)
return 1
return TRUE
/atom/movable/proc/CanAtmosPass()
return 1
return TRUE
/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
return (!density || !height)
@@ -57,20 +40,17 @@
return 1
/atom/movable/proc/BlockSuperconductivity() // objects that block air and don't let superconductivity act. Only firelocks atm.
return 0
/atom/movable/proc/get_superconductivity(direction)
return OPEN_HEAT_TRANSFER_COEFFICIENT
/turf/proc/CalculateAdjacentTurfs()
for(var/direction in GLOB.cardinal)
var/turf/T = get_step(src, direction)
if(!istype(T))
continue
if(CanAtmosPass(T))
atmos_adjacent_turfs |= T
T.atmos_adjacent_turfs |= src
else
atmos_adjacent_turfs -= T
T.atmos_adjacent_turfs -= src
/atom/movable/proc/recalculate_atmos_connectivity()
for(var/turf/T in locs) // used by double wide doors and other nonexistant multitile structures
T.recalculate_atmos_connectivity()
/atom/movable/proc/move_update_air(turf/T)
if(isturf(T))
T.recalculate_atmos_connectivity()
recalculate_atmos_connectivity()
//returns a list of adjacent turfs that can share air with this one.
//alldir includes adjacent diagonal tiles that can share
@@ -79,89 +59,87 @@
if(!issimulatedturf(src))
return list()
var/adjacent_turfs = atmos_adjacent_turfs.Copy()
var/adjacent_turfs = list()
for(var/turf/T in RANGE_EDGE_TURFS(1, src))
var/direction = get_dir(src, T)
if(!CanAtmosPass(direction))
continue
if(!T.CanAtmosPass(turn(direction, 180)))
continue
adjacent_turfs += T
if(!alldir)
return adjacent_turfs
var/turf/simulated/curloc = src
for(var/direction in GLOB.diagonals)
var/matchingDirections = 0
var/turf/simulated/S = get_step(curloc, direction)
for(var/checkDirection in GLOB.cardinal)
var/turf/simulated/checkTurf = get_step(S, checkDirection)
if(!(checkTurf in S.atmos_adjacent_turfs))
for(var/turf/T in RANGE_TURFS(1, src))
var/direction = get_dir(src, T)
if(IS_DIR_CARDINAL(direction))
continue
// check_direction is the first way we move, from src
for(var/check_direction in GLOB.cardinal)
if(!(check_direction & direction))
// Wrong way.
continue
if(checkTurf in adjacent_turfs)
matchingDirections++
var/turf/intermediate = get_step(src, check_direction)
if(!(intermediate in adjacent_turfs))
continue
if(matchingDirections >= 2)
adjacent_turfs += S
break
// other_direction is the second way we move, from intermediate.
var/other_direction = direction & ~check_direction
// We already know we can reach intermediate, so now we just need to check the second step.
if(!intermediate.CanAtmosPass(other_direction))
continue
if(!T.CanAtmosPass(turn(other_direction, 180)))
continue
adjacent_turfs += T
break
return adjacent_turfs
/atom/movable/proc/air_update_turf(command = 0)
if(!isturf(loc) && command)
return
for(var/turf/T in locs) // used by double wide doors and other nonexistant multitile structures
T.air_update_turf(command)
/turf/proc/air_update_turf(command = 0)
if(command)
CalculateAdjacentTurfs()
if(SSair)
SSair.add_to_active(src,command)
/atom/movable/proc/move_update_air(turf/T)
if(isturf(T))
T.air_update_turf(1)
air_update_turf(1)
/atom/movable/proc/atmos_spawn_air(text, amount) //because a lot of people loves to copy paste awful code lets just make a easy proc to spawn your plasma fires
/atom/movable/proc/atmos_spawn_air(flag, amount) //because a lot of people loves to copy paste awful code lets just make a easy proc to spawn your plasma fires
var/turf/simulated/T = get_turf(src)
if(!istype(T))
return
T.atmos_spawn_air(text, amount)
T.atmos_spawn_air(flag, amount)
/turf/simulated/proc/atmos_spawn_air(flag, amount)
if(!text || !amount || !air)
if(!flag || !amount || blocks_air)
return
var/datum/gas_mixture/G = new
var/datum/gas_mixture/G = new()
if(flag & LINDA_SPAWN_20C)
G.temperature = T20C
G.set_temperature(T20C)
if(flag & LINDA_SPAWN_HEAT)
G.temperature += 1000
G.set_temperature(G.temperature() + 1000)
if(flag & LINDA_SPAWN_COLD)
G.temperature = TCMB
G.set_temperature(TCMB)
if(flag & LINDA_SPAWN_TOXINS)
G.toxins += amount
G.set_toxins(G.toxins() + amount)
if(flag & LINDA_SPAWN_OXYGEN)
G.oxygen += amount
G.set_oxygen(G.oxygen() + amount)
if(flag & LINDA_SPAWN_CO2)
G.carbon_dioxide += amount
G.set_carbon_dioxide(G.carbon_dioxide() + amount)
if(flag & LINDA_SPAWN_NITROGEN)
G.nitrogen += amount
G.set_nitrogen(G.nitrogen() + amount)
if(flag & LINDA_SPAWN_N2O)
G.sleeping_agent += amount
G.set_sleeping_agent(G.sleeping_agent() + amount)
if(flag & LINDA_SPAWN_AGENT_B)
G.agent_b += amount
G.set_agent_b(G.agent_b() + amount)
if(flag & LINDA_SPAWN_AIR)
G.oxygen += MOLES_O2STANDARD * amount
G.nitrogen += MOLES_N2STANDARD * amount
G.set_oxygen(G.oxygen() + MOLES_O2STANDARD * amount)
G.set_nitrogen(G.nitrogen() + MOLES_N2STANDARD * amount)
air.merge(G)
SSair.add_to_active(src, 0)
blind_release_air(G)
@@ -1,103 +1,33 @@
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
qdel(giver)
return 0
/turf/return_air()
RETURN_TYPE(/datum/gas_mixture)
//Create gas mixture to hold data for passing
var/datum/gas_mixture/GM = new
GM.oxygen = oxygen
GM.carbon_dioxide = carbon_dioxide
GM.nitrogen = nitrogen
GM.toxins = toxins
GM.sleeping_agent = sleeping_agent
GM.agent_b = agent_b
GM.temperature = temperature
return GM
/turf/return_analyzable_air()
return return_air()
/turf/remove_air(amount)
var/datum/gas_mixture/GM = new
var/sum = oxygen + carbon_dioxide + nitrogen + toxins + sleeping_agent + agent_b
if(sum > 0)
GM.oxygen = (oxygen / sum) * amount
GM.carbon_dioxide = (carbon_dioxide / sum) * amount
GM.nitrogen = (nitrogen / sum) * amount
GM.toxins = (toxins / sum) * amount
GM.sleeping_agent = (sleeping_agent / sum) * amount
GM.agent_b = (agent_b / sum) * amount
GM.temperature = temperature
return GM
/turf/simulated/Initialize(mapload)
. = ..()
if(!blocks_air)
air = new
blind_set_air(get_initial_air())
air.oxygen = oxygen
air.carbon_dioxide = carbon_dioxide
air.nitrogen = nitrogen
air.toxins = toxins
air.sleeping_agent = sleeping_agent
air.agent_b = agent_b
air.temperature = temperature
/turf/simulated/proc/get_initial_air()
var/datum/gas_mixture/air = new()
if(!blocks_air)
air.set_oxygen(oxygen)
air.set_carbon_dioxide(carbon_dioxide)
air.set_nitrogen(nitrogen)
air.set_toxins(toxins)
air.set_sleeping_agent(sleeping_agent)
air.set_agent_b(agent_b)
air.set_temperature(temperature)
else
air.set_oxygen(0)
air.set_carbon_dioxide(0)
air.set_nitrogen(0)
air.set_toxins(0)
air.set_sleeping_agent(0)
air.set_agent_b(0)
air.set_temperature(0)
return air
/turf/simulated/Destroy()
QDEL_NULL(active_hotspot)
QDEL_NULL(wet_overlay)
return ..()
/turf/simulated/assume_air(datum/gas_mixture/giver)
if(!giver) return 0
var/datum/gas_mixture/receiver = air
if(istype(receiver))
air.merge(giver)
update_visuals()
return 1
else return ..()
/turf/simulated/proc/copy_air_with_tile(turf/simulated/T)
if(istype(T) && T.air && air)
air.copy_from(T.air)
/turf/simulated/proc/copy_air(datum/gas_mixture/copy)
if(air && copy)
air.copy_from(copy)
/turf/simulated/return_air()
RETURN_TYPE(/datum/gas_mixture)
if(air)
return air
else
return ..()
/turf/simulated/remove_air(amount)
if(air)
var/datum/gas_mixture/removed = null
removed = air.remove(amount)
update_visuals()
return removed
else
return ..()
/turf/simulated/proc/mimic_temperature_solid(turf/model, conduction_coefficient)
var/delta_temperature = (temperature_archived - model.temperature)
if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER))
@@ -116,131 +46,9 @@
temperature -= heat/heat_capacity
sharer.temperature += heat/sharer.heat_capacity
/turf/proc/process_cell(fire_count)
SSair.remove_from_active(src)
/turf/simulated/process_cell(fire_count)
if(archived_cycle < fire_count) //archive self if not already done
archive()
current_cycle = fire_count
var/remove = 1 //set by non simulated turfs who are sharing with this turf
//cache for sanic speed
var/list/adjacent_turfs = atmos_adjacent_turfs
var/datum/excited_group/our_excited_group = excited_group
var/adjacent_turfs_length = length(adjacent_turfs)
if(planetary_atmos)
adjacent_turfs_length++
for(var/t in adjacent_turfs)
var/turf/enemy_tile = t
if(issimulatedturf(enemy_tile))
var/turf/simulated/enemy_simulated = enemy_tile
if(fire_count > enemy_simulated.current_cycle)
enemy_simulated.archive()
/******************* GROUP HANDLING START *****************************************************************/
if(enemy_simulated.excited)
//cache for sanic speed
var/datum/excited_group/enemy_excited_group = enemy_simulated.excited_group
if(our_excited_group)
if(enemy_excited_group)
if(our_excited_group != enemy_excited_group)
//combine groups (this also handles updating the excited_group var of all involved turfs)
our_excited_group.merge_groups(enemy_excited_group)
our_excited_group = excited_group //update our cache
share_air(enemy_simulated, fire_count, adjacent_turfs_length) //share
else
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
our_excited_group.add_turf(enemy_simulated) //add enemy to our group
share_air(enemy_simulated, fire_count, adjacent_turfs_length) //share
else
if(enemy_excited_group)
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
enemy_excited_group.add_turf(src) //join self to enemy group
our_excited_group = excited_group //update our cache
share_air(enemy_simulated, fire_count, adjacent_turfs_length) //share
else
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
var/datum/excited_group/EG = new //generate new group
EG.add_turf(src)
EG.add_turf(enemy_simulated)
our_excited_group = excited_group //update our cache
share_air(enemy_simulated, fire_count, adjacent_turfs_length) //share
else
if(!air.compare(enemy_simulated.air)) //compare if
SSair.add_to_active(enemy_simulated) //excite enemy
if(our_excited_group)
excited_group.add_turf(enemy_simulated) //add enemy to group
else
var/datum/excited_group/EG = new //generate new group
EG.add_turf(src)
EG.add_turf(enemy_simulated)
our_excited_group = excited_group //update our cache
share_air(enemy_simulated, fire_count, adjacent_turfs_length) //share
/******************* GROUP HANDLING FINISH *********************************************************************/
else
if(!air.check_turf(enemy_tile, adjacent_turfs_length))
var/difference = air.mimic(enemy_tile, adjacent_turfs_length)
if(difference)
if(difference > 0)
consider_pressure_difference(enemy_tile, difference)
else
enemy_tile.consider_pressure_difference(src, difference)
remove = 0
if(our_excited_group)
last_share_check()
if(planetary_atmos) //share our air with the "atmosphere" "above" the turf
var/datum/gas_mixture/G = new
G.oxygen = oxygen
G.carbon_dioxide = carbon_dioxide
G.nitrogen = nitrogen
G.toxins = toxins
G.sleeping_agent = sleeping_agent
G.agent_b = agent_b
G.temperature = initial(temperature) // Temperature is modified at runtime; we only care about the turf's initial temperature
G.archive()
if(!air.compare(G))
if(!our_excited_group)
var/datum/excited_group/EG = new
EG.add_turf(src)
our_excited_group = excited_group
air.share(G, adjacent_turfs_length)
last_share_check()
air.react()
update_visuals()
if(air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
hotspot_expose(air.temperature, CELL_VOLUME)
for(var/atom/movable/item in src)
item.temperature_expose(air, air.temperature, CELL_VOLUME)
temperature_expose(air, air.temperature, CELL_VOLUME)
if(air.temperature > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION)
if(consider_superconductivity(starting = 1))
remove = 0
if(!our_excited_group && remove == 1)
SSair.remove_from_active(src)
/turf/simulated/proc/archive()
if(air) //For open space like floors
air.archive()
temperature_archived = temperature
archived_cycle = SSair.times_fired
/turf/simulated/proc/update_visuals()
var/new_overlay_type = tile_graphic()
var/datum/gas_mixture/air = get_readonly_air()
var/new_overlay_type = tile_graphic(air)
if(new_overlay_type == atmos_overlay_type)
return
var/atmos_overlay = get_atmos_overlay_by_name(atmos_overlay_type)
@@ -261,38 +69,19 @@
return GLOB.slmaster
return null
/turf/simulated/proc/tile_graphic()
if(!air)
/turf/simulated/proc/tile_graphic(datum/gas_mixture/air)
if(blocks_air)
return
if(air.toxins > MOLES_PLASMA_VISIBLE)
if(!istype(air))
air = get_readonly_air()
if(air.toxins() > MOLES_PLASMA_VISIBLE)
return "plasma"
if(air.sleeping_agent > 1)
if(air.sleeping_agent() > 1)
return "sleeping_agent"
return null
/turf/simulated/proc/share_air(turf/simulated/T, fire_count, adjacent_turfs_length)
if(T.current_cycle < fire_count)
var/difference
difference = air.share(T.air, adjacent_turfs_length)
if(difference)
if(difference > 0)
consider_pressure_difference(T, difference)
else
T.consider_pressure_difference(src, difference)
last_share_check()
/turf/proc/consider_pressure_difference(turf/simulated/T, difference)
SSair.high_pressure_delta |= src
if(difference > pressure_difference)
pressure_direction = get_dir(src, T)
pressure_difference = difference
/turf/simulated/proc/last_share_check()
if(air.last_share > MINIMUM_AIR_TO_SUSPEND)
excited_group.reset_cooldowns()
/turf/proc/high_pressure_movements()
/turf/proc/high_pressure_movements(flow_x, flow_y)
var/atom/movable/M
for(var/thing in src)
M = thing
@@ -303,11 +92,13 @@
if(M.pulledby)
continue
if(M.last_high_pressure_movement_air_cycle < SSair.times_fired)
M.experience_pressure_difference(pressure_difference, pressure_direction)
M.experience_pressure_difference(flow_x, flow_y)
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
/atom/movable/proc/experience_pressure_difference(flow_x, flow_y, pressure_resistance_prob_delta = 0)
var/const/PROBABILITY_OFFSET = 25
var/const/PROBABILITY_BASE_PRECENT = 75
var/pressure_difference = sqrt(flow_x ** 2 + flow_y ** 2)
var/max_force = sqrt(pressure_difference) * (MOVE_FORCE_DEFAULT / 5)
set waitfor = 0
var/move_prob = 100
@@ -315,165 +106,19 @@
move_prob = (pressure_difference / pressure_resistance * PROBABILITY_BASE_PRECENT) - PROBABILITY_OFFSET
move_prob += pressure_resistance_prob_delta
if(move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO))))
var/direction = 0
if(flow_x > 0.5)
direction |= EAST
if(flow_x < -0.5)
direction |= WEST
if(flow_y > 0.5)
direction |= NORTH
if(flow_y < -0.5)
direction |= SOUTH
step(src, direction)
last_high_pressure_movement_air_cycle = SSair.times_fired
/datum/excited_group
var/list/turf_list = list()
var/breakdown_cooldown = 0
/datum/excited_group/New()
if(SSair)
SSair.excited_groups += src
/datum/excited_group/proc/add_turf(turf/simulated/T)
turf_list += T
T.excited_group = src
T.recently_active = 1
reset_cooldowns()
/datum/excited_group/proc/merge_groups(datum/excited_group/E)
if(length(turf_list) > length(E.turf_list))
SSair.excited_groups -= E
for(var/turf/simulated/T in E.turf_list)
T.excited_group = src
turf_list += T
reset_cooldowns()
else
SSair.excited_groups -= src
for(var/turf/simulated/T in turf_list)
T.excited_group = E
E.turf_list += T
E.reset_cooldowns()
/datum/excited_group/proc/reset_cooldowns()
breakdown_cooldown = 0
/datum/excited_group/proc/self_breakdown()
var/datum/gas_mixture/A = new
var/list/cached_turf_list = turf_list // cache for super speed
for(var/turf/simulated/T in cached_turf_list)
A.oxygen += T.air.oxygen
A.carbon_dioxide += T.air.carbon_dioxide
A.nitrogen += T.air.nitrogen
A.toxins += T.air.toxins
A.sleeping_agent += T.air.sleeping_agent
A.agent_b += T.air.agent_b
var/turflen = length(cached_turf_list)
for(var/turf/simulated/T in cached_turf_list)
T.air.oxygen = A.oxygen / turflen
T.air.carbon_dioxide = A.carbon_dioxide / turflen
T.air.nitrogen = A.nitrogen / turflen
T.air.toxins = A.toxins / turflen
T.air.sleeping_agent = A.sleeping_agent / turflen
T.air.agent_b = A.agent_b / turflen
T.update_visuals()
/datum/excited_group/proc/dismantle()
for(var/turf/simulated/T in turf_list)
T.excited = 0
T.recently_active = 0
T.excited_group = null
SSair.active_turfs -= T
garbage_collect()
/datum/excited_group/proc/garbage_collect()
for(var/turf/simulated/T in turf_list)
T.excited_group = null
turf_list.Cut()
SSair.excited_groups -= src
/turf/simulated/proc/super_conduct()
var/conductivity_directions = 0
if(blocks_air)
//Does not participate in air exchange, so will conduct heat across all four borders at this time
conductivity_directions = NORTH|SOUTH|EAST|WEST
if(archived_cycle < SSair.times_fired)
archive()
else
//Does particate in air exchange so only consider directions not considered during process_cell()
for(var/direction in GLOB.cardinal)
var/turf/T = get_step(src, direction)
if(!(T in atmos_adjacent_turfs) && !(atmos_superconductivity & direction))
conductivity_directions += direction
if(conductivity_directions > 0)
//Conduct with tiles around me
for(var/direction in GLOB.cardinal)
if(conductivity_directions & direction)
var/turf/neighbor = get_step(src,direction)
if(!neighbor?.thermal_conductivity)
continue
if(issimulatedturf(neighbor)) //anything under this subtype will share in the exchange
var/turf/simulated/T = neighbor
if(T.archived_cycle < SSair.times_fired)
T.archive()
if(T.air)
if(air) //Both tiles are open
air.temperature_share(T.air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
else //Solid but neighbor is open
T.air.temperature_turf_share(src, T.thermal_conductivity)
SSair.add_to_active(T, 0)
else
if(air) //Open but neighbor is solid
air.temperature_turf_share(T, T.thermal_conductivity)
else //Both tiles are solid
share_temperature_mutual_solid(T, T.thermal_conductivity)
T.temperature_expose(null, T.temperature, null)
T.consider_superconductivity()
else
if(air) //Open
air.temperature_mimic(neighbor, neighbor.thermal_conductivity)
else
mimic_temperature_solid(neighbor, neighbor.thermal_conductivity)
if(!planetary_atmos)
radiate_to_spess()
//Conduct with air on my tile if I have it
if(air)
air.temperature_turf_share(src, thermal_conductivity)
//Make sure still hot enough to continue conducting heat
if(air.temperature < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)
SSair.active_super_conductivity -= src
return 0
else
if(temperature < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)
SSair.active_super_conductivity -= src
return 0
/turf/simulated/proc/consider_superconductivity(starting)
if(!thermal_conductivity)
return 0
if(air)
if(air.temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
return 0
if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant.
return 0
else
if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
return 0
SSair.active_super_conductivity |= src
return 1
return pressure_difference
/turf/simulated/proc/radiate_to_spess() //Radiate excess tile heat to space
if(temperature > T0C) //Considering 0 degC as te break even point for radiation in and out
@@ -484,21 +129,76 @@
(heat_capacity*HEAT_CAPACITY_VACUUM/(heat_capacity+HEAT_CAPACITY_VACUUM)) //700000 is the heat_capacity from a space turf, hardcoded here
temperature -= heat/heat_capacity
/turf/proc/Initialize_Atmos(times_fired)
CalculateAdjacentTurfs()
#define INDEX_NORTH 1
#define INDEX_EAST 2
#define INDEX_SOUTH 3
#define INDEX_WEST 4
/turf/simulated/Initialize_Atmos(times_fired)
..()
update_visuals()
for(var/tile in atmos_adjacent_turfs)
var/turf/enemy_tile = tile
if(issimulatedturf(enemy_tile))
var/turf/simulated/enemy_simulated = enemy_tile
if(!air.compare(enemy_simulated.air))
excited = 1
SSair.active_turfs |= src
break
else
if(!air.check_turf_total(enemy_tile))
excited = 1
SSair.active_turfs |= src
/turf/proc/Initialize_Atmos(times_fired)
recalculate_atmos_connectivity()
if(!blocks_air)
var/datum/gas_mixture/air = new()
air.set_oxygen(oxygen)
air.set_carbon_dioxide(carbon_dioxide)
air.set_nitrogen(nitrogen)
air.set_toxins(toxins)
air.set_sleeping_agent(sleeping_agent)
air.set_agent_b(agent_b)
air.set_temperature(temperature)
blind_set_air(air)
/turf/proc/recalculate_atmos_connectivity()
var/datum/milla_safe/recalculate_atmos_connectivity/milla = new()
milla.invoke_async(src)
/datum/milla_safe/recalculate_atmos_connectivity
/datum/milla_safe/recalculate_atmos_connectivity/on_run(turf/T)
if(isnull(T))
return
if(T.blocks_air)
set_tile_airtight(T, list(TRUE, TRUE, TRUE, TRUE))
// Will be needed when we go back to having solid tile conductivity.
//reset_superconductivity(src)
reduce_superconductivity(T, list(0, 0, 0, 0))
return
var/list/atmos_airtight = list(
!T.CanAtmosPass(NORTH, FALSE),
!T.CanAtmosPass(EAST, FALSE),
!T.CanAtmosPass(SOUTH, FALSE),
!T.CanAtmosPass(WEST, FALSE))
var/list/superconductivity = list(
OPEN_HEAT_TRANSFER_COEFFICIENT,
OPEN_HEAT_TRANSFER_COEFFICIENT,
OPEN_HEAT_TRANSFER_COEFFICIENT,
OPEN_HEAT_TRANSFER_COEFFICIENT)
for(var/obj/O in T)
if(istype(O, /obj/item))
// Items can't block atmos.
continue
if(!O.CanAtmosPass(NORTH))
atmos_airtight[INDEX_NORTH] = TRUE
if(!O.CanAtmosPass(EAST))
atmos_airtight[INDEX_EAST] = TRUE
if(!O.CanAtmosPass(SOUTH))
atmos_airtight[INDEX_SOUTH] = TRUE
if(!O.CanAtmosPass(WEST))
atmos_airtight[INDEX_WEST] = TRUE
superconductivity[INDEX_NORTH] = min(superconductivity[INDEX_NORTH], O.get_superconductivity(NORTH))
superconductivity[INDEX_EAST] = min(superconductivity[INDEX_EAST], O.get_superconductivity(EAST))
superconductivity[INDEX_SOUTH] = min(superconductivity[INDEX_SOUTH], O.get_superconductivity(SOUTH))
superconductivity[INDEX_WEST] = min(superconductivity[INDEX_WEST], O.get_superconductivity(WEST))
set_tile_airtight(T, atmos_airtight)
reset_superconductivity(T)
reduce_superconductivity(T, superconductivity)
#undef INDEX_NORTH
#undef INDEX_EAST
#undef INDEX_SOUTH
#undef INDEX_WEST
@@ -9,84 +9,137 @@ What are the archived variables for?
#define SPECIFIC_HEAT_N2O 40
#define SPECIFIC_HEAT_AGENT_B 300
#define HEAT_CAPACITY_CALCULATION(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b) \
(carbon_dioxide * SPECIFIC_HEAT_CDO + (oxygen + nitrogen) * SPECIFIC_HEAT_AIR + toxins * SPECIFIC_HEAT_TOXIN + sleeping_agent * SPECIFIC_HEAT_N2O + agent_b * SPECIFIC_HEAT_AGENT_B)
#define HEAT_CAPACITY_CALCULATION(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, innate_heat_capacity) \
(carbon_dioxide * SPECIFIC_HEAT_CDO + (oxygen + nitrogen) * SPECIFIC_HEAT_AIR + toxins * SPECIFIC_HEAT_TOXIN + sleeping_agent * SPECIFIC_HEAT_N2O + agent_b * SPECIFIC_HEAT_AGENT_B + innate_heat_capacity)
#define MINIMUM_HEAT_CAPACITY 0.0003
#define MINIMUM_MOLE_COUNT 0.01
#define QUANTIZE(variable) (round(variable, 0.0001))
/datum/gas_mixture
var/oxygen = 0
var/carbon_dioxide = 0
var/nitrogen = 0
var/toxins = 0
var/sleeping_agent = 0
var/agent_b = 0
/// The volume this gas mixture fills.
var/volume = CELL_VOLUME
/// Heat capacity intrinsic to the container of this gas mixture.
var/innate_heat_capacity = 0
/// How much fuel this gas mixture burnt last reaction.
var/fuel_burnt = 0
var/temperature = 0 //in Kelvin
// Private fields. Use the matching procs to get and set them.
// e.g. GM.oxygen(), GM.set_oxygen()
var/private_oxygen = 0
var/private_carbon_dioxide = 0
var/private_nitrogen = 0
var/private_toxins = 0
var/private_sleeping_agent = 0
var/private_agent_b = 0
var/private_temperature = 0 //in Kelvin
var/last_share
// Archived versions of the private fields.
// Only gas_mixture should use these.
var/private_oxygen_archived = 0
var/private_carbon_dioxide_archived = 0
var/private_nitrogen_archived = 0
var/private_toxins_archived = 0
var/private_sleeping_agent_archived = 0
var/private_agent_b_archived = 0
var/private_temperature_archived = 0
var/tmp/oxygen_archived
var/tmp/carbon_dioxide_archived
var/tmp/nitrogen_archived
var/tmp/toxins_archived
var/tmp/sleeping_agent_archived
var/tmp/agent_b_archived
/// Is this mixture currently synchronized with MILLA? Always true for non-bound mixtures.
var/synchronized = TRUE
var/tmp/temperature_archived
/// Tracks the callbacks from synchronize() that haven't run yet.
var/list/waiting_for_sync = list()
var/tmp/fuel_burnt = 0
/datum/gas_mixture/Destroy()
waiting_for_sync.Cut()
return ..()
//PV = nRT
/// Marks this gas mixture as changed from MILLA. Does nothing on non-bound mixtures.
/datum/gas_mixture/proc/set_dirty()
return
/datum/gas_mixture/proc/oxygen()
return private_oxygen
/datum/gas_mixture/proc/set_oxygen(value)
private_oxygen = value
/datum/gas_mixture/proc/carbon_dioxide()
return private_carbon_dioxide
/datum/gas_mixture/proc/set_carbon_dioxide(value)
private_carbon_dioxide = value
/datum/gas_mixture/proc/nitrogen()
return private_nitrogen
/datum/gas_mixture/proc/set_nitrogen(value)
private_nitrogen = value
/datum/gas_mixture/proc/toxins()
return private_toxins
/datum/gas_mixture/proc/set_toxins(value)
private_toxins = value
/datum/gas_mixture/proc/sleeping_agent()
return private_sleeping_agent
/datum/gas_mixture/proc/set_sleeping_agent(value)
private_sleeping_agent = value
/datum/gas_mixture/proc/agent_b()
return private_agent_b
/datum/gas_mixture/proc/set_agent_b(value)
private_agent_b = value
/datum/gas_mixture/proc/temperature()
return private_temperature
/datum/gas_mixture/proc/set_temperature(value)
private_temperature = value
///joules per kelvin
/datum/gas_mixture/proc/heat_capacity()
return HEAT_CAPACITY_CALCULATION(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b)
return HEAT_CAPACITY_CALCULATION(private_oxygen, private_carbon_dioxide, private_nitrogen, private_toxins, private_sleeping_agent, private_agent_b, innate_heat_capacity)
/datum/gas_mixture/proc/heat_capacity_archived()
return HEAT_CAPACITY_CALCULATION(oxygen_archived, carbon_dioxide_archived, nitrogen_archived, toxins_archived, sleeping_agent_archived, agent_b_archived)
return HEAT_CAPACITY_CALCULATION(private_oxygen_archived, private_carbon_dioxide_archived, private_nitrogen_archived, private_toxins_archived, private_sleeping_agent_archived, private_agent_b_archived, innate_heat_capacity)
/// Calculate moles
/datum/gas_mixture/proc/total_moles()
var/moles = oxygen + carbon_dioxide + nitrogen + toxins + sleeping_agent + agent_b
var/moles = private_oxygen + private_carbon_dioxide + private_nitrogen + private_toxins + private_sleeping_agent + private_agent_b
return moles
/datum/gas_mixture/proc/total_trace_moles()
var/moles = agent_b
var/moles = private_agent_b
return moles
/// Calculate pressure in kilopascals
/datum/gas_mixture/proc/return_pressure()
if(volume > 0)
return total_moles() * R_IDEAL_GAS_EQUATION * temperature / volume
return total_moles() * R_IDEAL_GAS_EQUATION * private_temperature / volume
return 0
/// Calculate temperature in kelvins
/datum/gas_mixture/proc/return_temperature()
return temperature
/// Calculate volume in liters
/datum/gas_mixture/proc/return_volume()
return max(0, volume)
/// Calculate thermal energy in joules
/datum/gas_mixture/proc/thermal_energy()
return temperature * heat_capacity()
return private_temperature * heat_capacity()
///Update archived versions of variables. Returns: TRUE in all cases
/datum/gas_mixture/proc/archive()
oxygen_archived = oxygen
carbon_dioxide_archived = carbon_dioxide
nitrogen_archived = nitrogen
toxins_archived = toxins
sleeping_agent_archived = sleeping_agent
agent_b_archived = agent_b
private_oxygen_archived = private_oxygen
private_carbon_dioxide_archived = private_carbon_dioxide
private_nitrogen_archived = private_nitrogen
private_toxins_archived = private_toxins
private_sleeping_agent_archived = private_sleeping_agent
private_agent_b_archived = private_agent_b
temperature_archived = temperature
private_temperature_archived = private_temperature
return TRUE
@@ -95,20 +148,22 @@ What are the archived variables for?
if(!giver)
return FALSE
if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
if(abs(private_temperature - giver.private_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity != 0)
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
private_temperature = (giver.private_temperature * giver_heat_capacity + private_temperature * self_heat_capacity) / combined_heat_capacity
oxygen += giver.oxygen
carbon_dioxide += giver.carbon_dioxide
nitrogen += giver.nitrogen
toxins += giver.toxins
sleeping_agent += giver.sleeping_agent
agent_b += giver.agent_b
private_oxygen += giver.private_oxygen
private_carbon_dioxide += giver.private_carbon_dioxide
private_nitrogen += giver.private_nitrogen
private_toxins += giver.private_toxins
private_sleeping_agent += giver.private_sleeping_agent
private_agent_b += giver.private_agent_b
set_dirty()
return TRUE
/// Only removes the gas if we have more than the amount
@@ -129,22 +184,23 @@ What are the archived variables for?
var/datum/gas_mixture/removed = new
removed.oxygen = QUANTIZE((oxygen / sum) * amount)
removed.nitrogen = QUANTIZE((nitrogen/ sum) * amount)
removed.carbon_dioxide = QUANTIZE((carbon_dioxide / sum) * amount)
removed.toxins = QUANTIZE((toxins / sum) * amount)
removed.sleeping_agent = QUANTIZE((sleeping_agent / sum) * amount)
removed.agent_b = QUANTIZE((agent_b / sum) * amount)
removed.private_oxygen = QUANTIZE((private_oxygen / sum) * amount)
removed.private_nitrogen = QUANTIZE((private_nitrogen/ sum) * amount)
removed.private_carbon_dioxide = QUANTIZE((private_carbon_dioxide / sum) * amount)
removed.private_toxins = QUANTIZE((private_toxins / sum) * amount)
removed.private_sleeping_agent = QUANTIZE((private_sleeping_agent / sum) * amount)
removed.private_agent_b = QUANTIZE((private_agent_b / sum) * amount)
oxygen = max(oxygen - removed.oxygen, 0)
nitrogen = max(nitrogen - removed.nitrogen, 0)
carbon_dioxide = max(carbon_dioxide - removed.carbon_dioxide, 0)
toxins = max(toxins - removed.toxins, 0)
sleeping_agent = max(sleeping_agent - removed.sleeping_agent, 0)
agent_b = max(agent_b - removed.agent_b, 0)
private_oxygen = max(private_oxygen - removed.private_oxygen, 0)
private_nitrogen = max(private_nitrogen - removed.private_nitrogen, 0)
private_carbon_dioxide = max(private_carbon_dioxide - removed.private_carbon_dioxide, 0)
private_toxins = max(private_toxins - removed.private_toxins, 0)
private_sleeping_agent = max(private_sleeping_agent - removed.private_sleeping_agent, 0)
private_agent_b = max(private_agent_b - removed.private_agent_b, 0)
removed.temperature = temperature
removed.private_temperature = private_temperature
set_dirty()
return removed
///Proportionally removes amount of gas from the gas_mixture.
@@ -158,51 +214,54 @@ What are the archived variables for?
var/datum/gas_mixture/removed = new
removed.oxygen = QUANTIZE(oxygen * ratio)
removed.nitrogen = QUANTIZE(nitrogen * ratio)
removed.carbon_dioxide = QUANTIZE(carbon_dioxide * ratio)
removed.toxins = QUANTIZE(toxins * ratio)
removed.sleeping_agent = QUANTIZE(sleeping_agent * ratio)
removed.agent_b = QUANTIZE(agent_b * ratio)
removed.private_oxygen = QUANTIZE(private_oxygen * ratio)
removed.private_nitrogen = QUANTIZE(private_nitrogen * ratio)
removed.private_carbon_dioxide = QUANTIZE(private_carbon_dioxide * ratio)
removed.private_toxins = QUANTIZE(private_toxins * ratio)
removed.private_sleeping_agent = QUANTIZE(private_sleeping_agent * ratio)
removed.private_agent_b = QUANTIZE(private_agent_b * ratio)
oxygen = max(oxygen - removed.oxygen, 0)
nitrogen = max(nitrogen - removed.nitrogen, 0)
carbon_dioxide = max(carbon_dioxide - removed.carbon_dioxide, 0)
toxins = max(toxins - removed.toxins, 0)
sleeping_agent = max(sleeping_agent - removed.sleeping_agent, 0)
agent_b = max(agent_b - removed.agent_b, 0)
private_oxygen = max(private_oxygen - removed.private_oxygen, 0)
private_nitrogen = max(private_nitrogen - removed.private_nitrogen, 0)
private_carbon_dioxide = max(private_carbon_dioxide - removed.private_carbon_dioxide, 0)
private_toxins = max(private_toxins - removed.private_toxins, 0)
private_sleeping_agent = max(private_sleeping_agent - removed.private_sleeping_agent, 0)
private_agent_b = max(private_agent_b - removed.private_agent_b, 0)
removed.temperature = temperature
removed.private_temperature = private_temperature
set_dirty()
return removed
//Copies variables from sample
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
oxygen = sample.oxygen
carbon_dioxide = sample.carbon_dioxide
nitrogen = sample.nitrogen
toxins = sample.toxins
sleeping_agent = sample.sleeping_agent
agent_b = sample.agent_b
private_oxygen = sample.private_oxygen
private_carbon_dioxide = sample.private_carbon_dioxide
private_nitrogen = sample.private_nitrogen
private_toxins = sample.private_toxins
private_sleeping_agent = sample.private_sleeping_agent
private_agent_b = sample.private_agent_b
temperature = sample.temperature
private_temperature = sample.private_temperature
set_dirty()
return TRUE
///Copies all gas info from the turf into the gas list along with temperature
///Returns: TRUE if we are mutable, FALSE otherwise
/datum/gas_mixture/proc/copy_from_turf(turf/model)
oxygen = model.oxygen
carbon_dioxide = model.carbon_dioxide
nitrogen = model.nitrogen
toxins = model.toxins
sleeping_agent = model.sleeping_agent
agent_b = model.agent_b
private_oxygen = model.oxygen
private_carbon_dioxide = model.carbon_dioxide
private_nitrogen = model.nitrogen
private_toxins = model.toxins
private_sleeping_agent = model.sleeping_agent
private_agent_b = model.agent_b
//acounts for changes in temperature
var/turf/model_parent = model.parent_type
if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
temperature = model.temperature
private_temperature = model.temperature
set_dirty()
return TRUE
@@ -212,17 +271,17 @@ What are the archived variables for?
if(!sharer)
return 0
/// Don't make calculations if there is no difference.
if(oxygen_archived == sharer.oxygen_archived && carbon_dioxide_archived == sharer.carbon_dioxide_archived && nitrogen_archived == sharer.nitrogen_archived &&\
toxins_archived == sharer.toxins_archived && sleeping_agent_archived == sharer.sleeping_agent_archived && agent_b_archived == sharer.agent_b_archived && temperature_archived == sharer.temperature_archived)
if(private_oxygen_archived == sharer.private_oxygen_archived && private_carbon_dioxide_archived == sharer.private_carbon_dioxide_archived && private_nitrogen_archived == sharer.private_nitrogen_archived &&\
private_toxins_archived == sharer.private_toxins_archived && private_sleeping_agent_archived == sharer.private_sleeping_agent_archived && private_agent_b_archived == sharer.private_agent_b_archived && private_temperature_archived == sharer.private_temperature_archived)
return 0
var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived) / (atmos_adjacent_turfs + 1)
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived) / (atmos_adjacent_turfs + 1)
var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived) / (atmos_adjacent_turfs + 1)
var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived) / (atmos_adjacent_turfs + 1)
var/delta_sleeping_agent = QUANTIZE(sleeping_agent_archived - sharer.sleeping_agent_archived) / (atmos_adjacent_turfs + 1)
var/delta_agent_b = QUANTIZE(agent_b_archived - sharer.agent_b_archived) / (atmos_adjacent_turfs + 1)
var/delta_oxygen = QUANTIZE(private_oxygen_archived - sharer.private_oxygen_archived) / (atmos_adjacent_turfs + 1)
var/delta_carbon_dioxide = QUANTIZE(private_carbon_dioxide_archived - sharer.private_carbon_dioxide_archived) / (atmos_adjacent_turfs + 1)
var/delta_nitrogen = QUANTIZE(private_nitrogen_archived - sharer.private_nitrogen_archived) / (atmos_adjacent_turfs + 1)
var/delta_toxins = QUANTIZE(private_toxins_archived - sharer.private_toxins_archived) / (atmos_adjacent_turfs + 1)
var/delta_sleeping_agent = QUANTIZE(private_sleeping_agent_archived - sharer.private_sleeping_agent_archived) / (atmos_adjacent_turfs + 1)
var/delta_agent_b = QUANTIZE(private_agent_b_archived - sharer.private_agent_b_archived) / (atmos_adjacent_turfs + 1)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/delta_temperature = (private_temperature_archived - sharer.private_temperature_archived)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
@@ -271,56 +330,56 @@ What are the archived variables for?
old_self_heat_capacity = heat_capacity()
old_sharer_heat_capacity = sharer.heat_capacity()
oxygen -= delta_oxygen
sharer.oxygen += delta_oxygen
private_oxygen -= delta_oxygen
sharer.private_oxygen += delta_oxygen
carbon_dioxide -= delta_carbon_dioxide
sharer.carbon_dioxide += delta_carbon_dioxide
private_carbon_dioxide -= delta_carbon_dioxide
sharer.private_carbon_dioxide += delta_carbon_dioxide
nitrogen -= delta_nitrogen
sharer.nitrogen += delta_nitrogen
private_nitrogen -= delta_nitrogen
sharer.private_nitrogen += delta_nitrogen
toxins -= delta_toxins
sharer.toxins += delta_toxins
private_toxins -= delta_toxins
sharer.private_toxins += delta_toxins
sleeping_agent -= delta_sleeping_agent
sharer.sleeping_agent += delta_sleeping_agent
private_sleeping_agent -= delta_sleeping_agent
sharer.private_sleeping_agent += delta_sleeping_agent
agent_b -= delta_agent_b
sharer.agent_b += delta_agent_b
private_agent_b -= delta_agent_b
sharer.private_agent_b += delta_agent_b
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins + delta_sleeping_agent + delta_agent_b)
last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins) + abs(delta_sleeping_agent) + abs(delta_agent_b)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity * temperature - heat_capacity_self_to_sharer * temperature_archived + heat_capacity_sharer_to_self * sharer.temperature_archived) / new_self_heat_capacity
private_temperature = (old_self_heat_capacity * private_temperature - heat_capacity_self_to_sharer * private_temperature_archived + heat_capacity_sharer_to_self * sharer.private_temperature_archived) / new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
sharer.temperature = (old_sharer_heat_capacity * sharer.temperature - heat_capacity_sharer_to_self * sharer.temperature_archived + heat_capacity_self_to_sharer * temperature_archived) / new_sharer_heat_capacity
sharer.private_temperature = (old_sharer_heat_capacity * sharer.private_temperature - heat_capacity_sharer_to_self * sharer.private_temperature_archived + heat_capacity_self_to_sharer * private_temperature_archived) / new_sharer_heat_capacity
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
if(abs(new_sharer_heat_capacity / old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
set_dirty()
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived * (total_moles() + moved_moles) - sharer.temperature_archived * (sharer.total_moles() - moved_moles)
var/delta_pressure = private_temperature_archived * (total_moles() + moved_moles) - sharer.private_temperature_archived * (sharer.total_moles() - moved_moles)
return delta_pressure * R_IDEAL_GAS_EQUATION / volume
//Similar to share(...), except the model is not modified
//Return: amount of gas exchanged
/datum/gas_mixture/proc/mimic(turf/model, atmos_adjacent_turfs = 4) //I want this proc to die a painful death
var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen) / (atmos_adjacent_turfs + 1)
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide) / (atmos_adjacent_turfs + 1)
var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen) / (atmos_adjacent_turfs + 1)
var/delta_toxins = QUANTIZE(toxins_archived - model.toxins) / (atmos_adjacent_turfs + 1)
var/delta_sleeping_agent = QUANTIZE(sleeping_agent_archived - model.sleeping_agent) / (atmos_adjacent_turfs + 1)
var/delta_agent_b = QUANTIZE(agent_b_archived - model.agent_b) / (atmos_adjacent_turfs + 1)
var/delta_oxygen = QUANTIZE(private_oxygen_archived - model.oxygen) / (atmos_adjacent_turfs + 1)
var/delta_carbon_dioxide = QUANTIZE(private_carbon_dioxide_archived - model.carbon_dioxide) / (atmos_adjacent_turfs + 1)
var/delta_nitrogen = QUANTIZE(private_nitrogen_archived - model.nitrogen) / (atmos_adjacent_turfs + 1)
var/delta_toxins = QUANTIZE(private_toxins_archived - model.toxins) / (atmos_adjacent_turfs + 1)
var/delta_sleeping_agent = QUANTIZE(private_sleeping_agent_archived - model.sleeping_agent) / (atmos_adjacent_turfs + 1)
var/delta_agent_b = QUANTIZE(private_agent_b_archived - model.agent_b) / (atmos_adjacent_turfs + 1)
var/delta_temperature = (temperature_archived - model.temperature)
var/delta_temperature = (private_temperature_archived - model.temperature)
var/heat_transferred = 0
var/old_self_heat_capacity = 0
@@ -356,46 +415,46 @@ What are the archived variables for?
old_self_heat_capacity = heat_capacity()
oxygen -= delta_oxygen
carbon_dioxide -= delta_carbon_dioxide
nitrogen -= delta_nitrogen
toxins -= delta_toxins
sleeping_agent -= delta_sleeping_agent
agent_b -= delta_agent_b
private_oxygen -= delta_oxygen
private_carbon_dioxide -= delta_carbon_dioxide
private_nitrogen -= delta_nitrogen
private_toxins -= delta_toxins
private_sleeping_agent -= delta_sleeping_agent
private_agent_b -= delta_agent_b
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins + delta_sleeping_agent + delta_agent_b)
last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins) + abs(delta_sleeping_agent) + abs(delta_agent_b)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity * temperature - heat_capacity_transferred * temperature_archived) / new_self_heat_capacity
private_temperature = (old_self_heat_capacity * private_temperature - heat_capacity_transferred * private_temperature_archived) / new_self_heat_capacity
temperature_mimic(model, model.thermal_conductivity)
set_dirty()
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived * (total_moles() + moved_moles) - model.temperature * (model.oxygen + model.carbon_dioxide + model.nitrogen + model.toxins + model.sleeping_agent + model.agent_b)
var/delta_pressure = private_temperature_archived * (total_moles() + moved_moles) - model.temperature * (model.oxygen + model.carbon_dioxide + model.nitrogen + model.toxins + model.sleeping_agent + model.agent_b)
return delta_pressure * R_IDEAL_GAS_EQUATION / volume
else
return 0
//Returns: FALSE if self-check failed or TRUE if check passes
/datum/gas_mixture/proc/check_turf(turf/model, atmos_adjacent_turfs = 4) //I want this proc to die a painful death
var/delta_oxygen = (oxygen_archived - model.oxygen) / (atmos_adjacent_turfs + 1)
var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide) / (atmos_adjacent_turfs + 1)
var/delta_nitrogen = (nitrogen_archived - model.nitrogen) / (atmos_adjacent_turfs + 1)
var/delta_toxins = (toxins_archived - model.toxins) / (atmos_adjacent_turfs + 1)
var/delta_sleeping_agent = (sleeping_agent_archived - model.sleeping_agent) / (atmos_adjacent_turfs + 1)
var/delta_agent_b = (agent_b_archived - model.agent_b) / (atmos_adjacent_turfs + 1)
var/delta_oxygen = (private_oxygen_archived - model.oxygen) / (atmos_adjacent_turfs + 1)
var/delta_carbon_dioxide = (private_carbon_dioxide_archived - model.carbon_dioxide) / (atmos_adjacent_turfs + 1)
var/delta_nitrogen = (private_nitrogen_archived - model.nitrogen) / (atmos_adjacent_turfs + 1)
var/delta_toxins = (private_toxins_archived - model.toxins) / (atmos_adjacent_turfs + 1)
var/delta_sleeping_agent = (private_sleeping_agent_archived - model.sleeping_agent) / (atmos_adjacent_turfs + 1)
var/delta_agent_b = (private_agent_b_archived - model.agent_b) / (atmos_adjacent_turfs + 1)
var/delta_temperature = (temperature_archived - model.temperature)
var/delta_temperature = (private_temperature_archived - model.temperature)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_sleeping_agent) >= sleeping_agent_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_agent_b) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_agent_b) >= agent_b_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)))
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= private_oxygen_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= private_carbon_dioxide_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= private_nitrogen_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= private_toxins_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_sleeping_agent) >= private_sleeping_agent_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_agent_b) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_agent_b) >= private_agent_b_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)))
return FALSE
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return FALSE
@@ -403,7 +462,8 @@ What are the archived variables for?
return TRUE
/datum/gas_mixture/proc/temperature_mimic(turf/model, conduction_coefficient) //I want this proc to die a painful death
var/delta_temperature = (temperature - model.temperature)
set_dirty()
var/delta_temperature = (private_temperature - model.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
@@ -411,14 +471,15 @@ What are the archived variables for?
var/heat = conduction_coefficient * delta_temperature * \
(self_heat_capacity * model.heat_capacity / (self_heat_capacity + model.heat_capacity))
temperature -= heat / self_heat_capacity
private_temperature -= heat / self_heat_capacity
///Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length
///Returns: new temperature of the sharer
/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/delta_temperature = (private_temperature_archived - sharer.private_temperature_archived)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
set_dirty()
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
@@ -426,64 +487,65 @@ What are the archived variables for?
var/heat = conduction_coefficient*delta_temperature * \
(self_heat_capacity * sharer_heat_capacity / (self_heat_capacity + sharer_heat_capacity))
temperature -= heat / self_heat_capacity
sharer.temperature += heat / sharer_heat_capacity
private_temperature -= heat / self_heat_capacity
sharer.private_temperature += heat / sharer_heat_capacity
/datum/gas_mixture/proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient) //I want this proc to die a painful death
var/delta_temperature = (temperature_archived - sharer.temperature)
var/delta_temperature = (private_temperature_archived - sharer.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
set_dirty()
var/self_heat_capacity = heat_capacity()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient * delta_temperature * \
(self_heat_capacity * sharer.heat_capacity / (self_heat_capacity + sharer.heat_capacity))
temperature -= heat / self_heat_capacity
private_temperature -= heat / self_heat_capacity
sharer.temperature += heat / sharer.heat_capacity
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
if((abs(oxygen - sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
((oxygen < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.oxygen) || (oxygen > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.oxygen)))
if((abs(private_oxygen - sample.private_oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
((private_oxygen < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_oxygen) || (private_oxygen > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_oxygen)))
return FALSE
if((abs(nitrogen - sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
((nitrogen < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.nitrogen) || (nitrogen > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.nitrogen)))
if((abs(private_nitrogen - sample.private_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
((private_nitrogen < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_nitrogen) || (private_nitrogen > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_nitrogen)))
return FALSE
if((abs(carbon_dioxide - sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
((carbon_dioxide < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.carbon_dioxide) || (carbon_dioxide > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.carbon_dioxide)))
if((abs(private_carbon_dioxide - sample.private_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
((private_carbon_dioxide < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_carbon_dioxide) || (private_carbon_dioxide > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_carbon_dioxide)))
return FALSE
if((abs(toxins - sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
((toxins < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.toxins) || (toxins > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.toxins)))
if((abs(private_toxins - sample.private_toxins) > MINIMUM_AIR_TO_SUSPEND) && \
((private_toxins < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_toxins) || (private_toxins > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_toxins)))
return FALSE
if((abs(sleeping_agent - sample.sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && \
((sleeping_agent < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.sleeping_agent) || (sleeping_agent > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.sleeping_agent)))
if((abs(private_sleeping_agent - sample.private_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && \
((private_sleeping_agent < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_sleeping_agent) || (private_sleeping_agent > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_sleeping_agent)))
return FALSE
if((abs(agent_b - sample.agent_b) > MINIMUM_AIR_TO_SUSPEND) && \
((agent_b < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.agent_b) || (agent_b > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.agent_b)))
if((abs(private_agent_b - sample.private_agent_b) > MINIMUM_AIR_TO_SUSPEND) && \
((private_agent_b < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_agent_b) || (private_agent_b > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.private_agent_b)))
return FALSE
if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
if((abs(temperature - sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
((temperature < (1 - MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND) * sample.temperature) || (temperature > (1 + MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND) * sample.temperature)))
if((abs(private_temperature - sample.private_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
((private_temperature < (1 - MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND) * sample.private_temperature) || (private_temperature > (1 + MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND) * sample.private_temperature)))
return FALSE
return TRUE
/datum/gas_mixture/proc/check_turf_total(turf/model) //I want this proc to die a painful death
var/delta_oxygen = (oxygen - model.oxygen)
var/delta_carbon_dioxide = (carbon_dioxide - model.carbon_dioxide)
var/delta_nitrogen = (nitrogen - model.nitrogen)
var/delta_toxins = (toxins - model.toxins)
var/delta_sleeping_agent = (sleeping_agent - model.sleeping_agent)
var/delta_agent_b = (agent_b - model.agent_b)
var/delta_oxygen = (private_oxygen - model.oxygen)
var/delta_carbon_dioxide = (private_carbon_dioxide - model.carbon_dioxide)
var/delta_nitrogen = (private_nitrogen - model.nitrogen)
var/delta_toxins = (private_toxins - model.toxins)
var/delta_sleeping_agent = (private_sleeping_agent - model.sleeping_agent)
var/delta_agent_b = (private_agent_b - model.agent_b)
var/delta_temperature = (temperature - model.temperature)
var/delta_temperature = (private_temperature - model.temperature)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_sleeping_agent) >= sleeping_agent * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_agent_b) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_agent_b) >= agent_b * MINIMUM_AIR_RATIO_TO_SUSPEND)))
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= private_oxygen * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= private_carbon_dioxide * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= private_nitrogen * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= private_toxins * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_sleeping_agent) >= private_sleeping_agent * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_agent_b) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_agent_b) >= private_agent_b * MINIMUM_AIR_RATIO_TO_SUSPEND)))
return FALSE
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return FALSE
@@ -495,77 +557,78 @@ What are the archived variables for?
/datum/gas_mixture/proc/react(atom/dump_location)
var/reacting = FALSE //set to TRUE if a notable reaction occured (used by pipe_network)
if((agent_b > MINIMUM_MOLE_COUNT) && temperature > 900)
if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY)
var/reaction_rate = min(carbon_dioxide * 0.75, toxins * 0.25, agent_b * 0.05)
if((private_agent_b > MINIMUM_MOLE_COUNT) && private_temperature > 900)
if(private_toxins > MINIMUM_HEAT_CAPACITY && private_carbon_dioxide > MINIMUM_HEAT_CAPACITY)
var/reaction_rate = min(private_carbon_dioxide * 0.75, private_toxins * 0.25, private_agent_b * 0.05)
carbon_dioxide -= reaction_rate
oxygen += reaction_rate
private_carbon_dioxide -= reaction_rate
private_oxygen += reaction_rate
agent_b -= reaction_rate * 0.05
private_agent_b -= reaction_rate * 0.05
temperature += (reaction_rate * 20000) / heat_capacity()
private_temperature += (reaction_rate * 20000) / heat_capacity()
reacting = TRUE
if((sleeping_agent > MINIMUM_MOLE_COUNT) && temperature > N2O_DECOMPOSITION_MIN_ENERGY)
if((private_sleeping_agent > MINIMUM_MOLE_COUNT) && private_temperature > N2O_DECOMPOSITION_MIN_ENERGY)
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
var/burned_fuel = 0
burned_fuel = max(0, 0.00002 * (temperature - (0.00001 * (temperature ** 2)))) * sleeping_agent
if(sleeping_agent - burned_fuel > 0)
sleeping_agent -= burned_fuel
burned_fuel = max(0, 0.00002 * (private_temperature - (0.00001 * (private_temperature ** 2)))) * private_sleeping_agent
if(private_sleeping_agent - burned_fuel > 0)
private_sleeping_agent -= burned_fuel
if(burned_fuel)
energy_released += (N2O_DECOMPOSITION_ENERGY_RELEASED * burned_fuel)
oxygen += burned_fuel * 0.5
nitrogen += burned_fuel
private_oxygen += burned_fuel * 0.5
private_nitrogen += burned_fuel
var/new_heat_capacity = heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
private_temperature = (private_temperature * old_heat_capacity + energy_released) / new_heat_capacity
reacting = TRUE
fuel_burnt = 0
//Handle plasma burning
if((toxins > MINIMUM_MOLE_COUNT) && (oxygen > MINIMUM_MOLE_COUNT) && temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
if((private_toxins > MINIMUM_MOLE_COUNT) && (private_oxygen > MINIMUM_MOLE_COUNT) && private_temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
var/plasma_burn_rate = 0
var/oxygen_burn_rate = 0
var/private_oxygen_burn_rate = 0
//more plasma released at higher temperatures
var/temperature_scale = 0
var/private_temperature_scale = 0
if(temperature > PLASMA_UPPER_TEMPERATURE)
temperature_scale = 1
if(private_temperature > PLASMA_UPPER_TEMPERATURE)
private_temperature_scale = 1
else
temperature_scale = (temperature - PLASMA_MINIMUM_BURN_TEMPERATURE) / (PLASMA_UPPER_TEMPERATURE - PLASMA_MINIMUM_BURN_TEMPERATURE)
if(temperature_scale > 0)
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
if(oxygen > toxins * PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (toxins * temperature_scale) / PLASMA_BURN_RATE_DELTA
private_temperature_scale = (private_temperature - PLASMA_MINIMUM_BURN_TEMPERATURE) / (PLASMA_UPPER_TEMPERATURE - PLASMA_MINIMUM_BURN_TEMPERATURE)
if(private_temperature_scale > 0)
private_oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - private_temperature_scale
if(private_oxygen > private_toxins * PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (private_toxins * private_temperature_scale) / PLASMA_BURN_RATE_DELTA
else
plasma_burn_rate = (temperature_scale * (oxygen / PLASMA_OXYGEN_FULLBURN)) / PLASMA_BURN_RATE_DELTA
plasma_burn_rate = (private_temperature_scale * (private_oxygen / PLASMA_OXYGEN_FULLBURN)) / PLASMA_BURN_RATE_DELTA
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
plasma_burn_rate = min(plasma_burn_rate, toxins, oxygen / oxygen_burn_rate) //Ensures matter is conserved properly
toxins = QUANTIZE(toxins - plasma_burn_rate)
oxygen = QUANTIZE(oxygen - (plasma_burn_rate * oxygen_burn_rate))
carbon_dioxide += plasma_burn_rate
plasma_burn_rate = min(plasma_burn_rate, private_toxins, private_oxygen / private_oxygen_burn_rate) //Ensures matter is conserved properly
private_toxins = QUANTIZE(private_toxins - plasma_burn_rate)
private_oxygen = QUANTIZE(private_oxygen - (plasma_burn_rate * private_oxygen_burn_rate))
private_carbon_dioxide += plasma_burn_rate
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
fuel_burnt += (plasma_burn_rate) * (1 + oxygen_burn_rate)
fuel_burnt += (plasma_burn_rate) * (1 + private_oxygen_burn_rate)
if(energy_released > 0)
var/new_heat_capacity = heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
private_temperature = (private_temperature * old_heat_capacity + energy_released) / new_heat_capacity
if(fuel_burnt)
reacting = TRUE
set_dirty()
return reacting
///Takes the amount of the gas you want to PP as an argument
@@ -575,11 +638,66 @@ What are the archived variables for?
///O2_PP = get_partial_pressure(gas_mixture.oxygen)
/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
return (gas_pressure * R_IDEAL_GAS_EQUATION * private_temperature) / BREATH_VOLUME
///inverse
/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure)
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * private_temperature)
/datum/gas_mixture/proc/copy_from_milla(list/milla)
private_oxygen = milla[MILLA_INDEX_OXYGEN]
private_carbon_dioxide = milla[MILLA_INDEX_CARBON_DIOXIDE]
private_nitrogen = milla[MILLA_INDEX_NITROGEN]
private_toxins = milla[MILLA_INDEX_TOXINS]
private_sleeping_agent = milla[MILLA_INDEX_SLEEPING_AGENT]
private_agent_b = milla[MILLA_INDEX_AGENT_B]
innate_heat_capacity = milla[MILLA_INDEX_INNATE_HEAT_CAPACITY]
private_temperature = milla[MILLA_INDEX_TEMPERATURE]
/proc/share_many_airs(list/mixtures)
var/total_volume = 0
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/total_oxygen = 0
var/total_nitrogen = 0
var/total_toxins = 0
var/total_carbon_dioxide = 0
var/total_sleeping_agent = 0
var/total_agent_b = 0
for(var/datum/gas_mixture/G as anything in mixtures)
total_volume += G.volume
var/heat_capacity = G.heat_capacity()
total_heat_capacity += heat_capacity
total_thermal_energy += G.private_temperature * heat_capacity
total_oxygen += G.private_oxygen
total_nitrogen += G.private_nitrogen
total_toxins += G.private_toxins
total_carbon_dioxide += G.private_carbon_dioxide
total_sleeping_agent += G.private_sleeping_agent
total_agent_b += G.private_agent_b
if(total_volume > 0)
//Calculate temperature
var/temperature = 0
if(total_heat_capacity > 0)
temperature = total_thermal_energy/total_heat_capacity
//Update individual gas_mixtures by volume ratio
for(var/datum/gas_mixture/G as anything in mixtures)
G.private_oxygen = total_oxygen * G.volume / total_volume
G.private_nitrogen = total_nitrogen * G.volume / total_volume
G.private_toxins = total_toxins * G.volume / total_volume
G.private_carbon_dioxide = total_carbon_dioxide * G.volume / total_volume
G.private_sleeping_agent = total_sleeping_agent * G.volume / total_volume
G.private_agent_b = total_agent_b * G.volume / total_volume
G.private_temperature = temperature
G.set_dirty()
///Mathematical proofs:
/**
@@ -599,3 +717,103 @@ get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
#undef MINIMUM_HEAT_CAPACITY
#undef MINIMUM_MOLE_COUNT
#undef QUANTIZE
/datum/gas_mixture/bound_to_turf
var/dirty = FALSE
var/lastread = 0
var/turf/bound_turf = null
var/datum/gas_mixture/readonly/readonly = null
/datum/gas_mixture/bound_to_turf/Destroy()
bound_turf = null
return ..()
/datum/gas_mixture/bound_to_turf/set_dirty()
dirty = TRUE
if(!isnull(readonly))
readonly.private_oxygen = private_oxygen
readonly.private_carbon_dioxide = private_carbon_dioxide
readonly.private_nitrogen = private_nitrogen
readonly.private_toxins = private_toxins
readonly.private_sleeping_agent = private_sleeping_agent
readonly.private_agent_b = private_agent_b
readonly.private_temperature = private_temperature
if(istype(bound_turf, /turf/simulated))
var/turf/simulated/S = bound_turf
S.update_visuals()
ASSERT(SSair.is_in_milla_safe_code())
/datum/gas_mixture/bound_to_turf/set_oxygen(value)
private_oxygen = value
set_dirty()
/datum/gas_mixture/bound_to_turf/set_carbon_dioxide(value)
private_carbon_dioxide = value
set_dirty()
/datum/gas_mixture/bound_to_turf/set_nitrogen(value)
private_nitrogen = value
set_dirty()
/datum/gas_mixture/bound_to_turf/set_toxins(value)
private_toxins = value
set_dirty()
/datum/gas_mixture/bound_to_turf/set_sleeping_agent(value)
private_sleeping_agent = value
set_dirty()
/datum/gas_mixture/bound_to_turf/set_agent_b(value)
private_agent_b = value
set_dirty()
/datum/gas_mixture/bound_to_turf/set_temperature(value)
private_temperature = value
set_dirty()
/datum/gas_mixture/bound_to_turf/proc/private_unsafe_write()
set_tile_atmos(bound_turf, oxygen = private_oxygen, carbon_dioxide = private_carbon_dioxide, nitrogen = private_nitrogen, toxins = private_toxins, sleeping_agent = private_sleeping_agent, agent_b = private_agent_b, temperature = private_temperature)
/datum/gas_mixture/bound_to_turf/proc/get_readonly()
if(isnull(readonly))
readonly = new(src)
return readonly
/// A gas mixture that should not be modified after creation.
/datum/gas_mixture/readonly
/datum/gas_mixture/readonly/New(datum/gas_mixture/parent)
private_oxygen = parent.private_oxygen
private_carbon_dioxide = parent.private_carbon_dioxide
private_nitrogen = parent.private_nitrogen
private_toxins = parent.private_toxins
private_sleeping_agent = parent.private_sleeping_agent
private_agent_b = parent.private_agent_b
private_temperature = parent.private_temperature
/datum/gas_mixture/readonly/set_dirty()
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_oxygen(value)
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_carbon_dioxide(value)
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_nitrogen(value)
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_toxins(value)
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_sleeping_agent(value)
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_agent_b(value)
CRASH("Attempted to modify a readonly gas_mixture.")
/datum/gas_mixture/readonly/set_temperature(value)
CRASH("Attempted to modify a readonly gas_mixture.")
+58 -53
View File
@@ -262,37 +262,37 @@
if(!istype(location))
return 0
var/datum/gas_mixture/environment = location.return_air()
var/datum/milla_safe/airalarm_heat_cool/milla = new()
milla.invoke_async(src)
var/datum/gas_mixture/environment = location.get_readonly_air()
var/GET_PP = R_IDEAL_GAS_EQUATION * environment.temperature() / environment.volume
var/datum/tlv/cur_tlv
handle_heating_cooling(environment, cur_tlv, location)
var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
cur_tlv = TLV["pressure"]
var/environment_pressure = environment.return_pressure()
var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
cur_tlv = TLV["oxygen"]
var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP)
var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen() * GET_PP)
cur_tlv = TLV["nitrogen"]
var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen*GET_PP)
var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen() * GET_PP)
cur_tlv = TLV["carbon dioxide"]
var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP)
var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide() * GET_PP)
cur_tlv = TLV["plasma"]
var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins() * GET_PP)
cur_tlv = TLV["nitrous oxide"]
var/sleeping_agent_dangerlevel = cur_tlv.get_danger_level(environment.sleeping_agent*GET_PP)
var/sleeping_agent_dangerlevel = cur_tlv.get_danger_level(environment.sleeping_agent() * GET_PP)
cur_tlv = TLV["other"]
var/other_dangerlevel = cur_tlv.get_danger_level(environment.total_trace_moles() * GET_PP)
cur_tlv = TLV["temperature"]
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature())
var/old_danger_level = danger_level
danger_level = max(
@@ -313,43 +313,48 @@
mode = AALARM_MODE_SCRUBBING
apply_mode()
/datum/milla_safe/airalarm_heat_cool
/obj/machinery/alarm/proc/handle_heating_cooling(datum/gas_mixture/environment, datum/tlv/cur_tlv, turf/simulated/location)
cur_tlv = TLV["temperature"]
/datum/milla_safe/airalarm_heat_cool/on_run(obj/machinery/alarm/alarm)
var/turf/location = get_turf(alarm)
var/datum/gas_mixture/environment = get_turf_air(location)
if(!alarm.thermostat_state)
return
var/datum/tlv/cur_tlv = alarm.TLV["temperature"]
//Handle temperature adjustment here.
if(environment.temperature < target_temperature - 2 || environment.temperature > target_temperature + 2 || regulating_temperature)
if(environment.temperature() < alarm.target_temperature - 2 || environment.temperature() > alarm.target_temperature + 2 || alarm.regulating_temperature)
//If it goes too far, we should adjust ourselves back before stopping.
if(!cur_tlv.get_danger_level(target_temperature))
var/datum/gas_mixture/gas = location.remove_air(0.25 * environment.total_moles())
if(!cur_tlv.get_danger_level(alarm.target_temperature))
var/datum/gas_mixture/gas = environment.remove(0.25 * environment.total_moles())
if(!gas)
return
if(!regulating_temperature && thermostat_state)
regulating_temperature = TRUE
visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click and a faint electronic hum.")
if(!alarm.regulating_temperature && alarm.thermostat_state)
alarm.regulating_temperature = TRUE
alarm.visible_message("\The [alarm] clicks as it starts [environment.temperature() > alarm.target_temperature ? "cooling" : "heating"] the room.", "You hear a click and a faint electronic hum.")
if(target_temperature > MAX_TEMPERATURE)
target_temperature = MAX_TEMPERATURE
if(alarm.target_temperature > MAX_TEMPERATURE)
alarm.target_temperature = MAX_TEMPERATURE
if(target_temperature < MIN_TEMPERATURE)
target_temperature = MIN_TEMPERATURE
if(alarm.target_temperature < MIN_TEMPERATURE)
alarm.target_temperature = MIN_TEMPERATURE
if(thermostat_state)
var/heat_capacity = gas.heat_capacity()
var/energy_used = max(abs(heat_capacity * (gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
var/heat_capacity = gas.heat_capacity()
var/energy_used = max(abs(heat_capacity * (gas.temperature() - alarm.target_temperature) ), MAX_ENERGY_CHANGE)
//Use power. Assuming that each power unit represents 1000 watts....
use_power(energy_used / 1000, PW_CHANNEL_ENVIRONMENT)
//Use power. Assuming that each power unit represents 1000 watts....
alarm.use_power(energy_used / 1000, PW_CHANNEL_ENVIRONMENT)
//We need to cool ourselves.
if(heat_capacity)
if(environment.temperature > target_temperature)
gas.temperature -= energy_used / heat_capacity
else
gas.temperature += energy_used / heat_capacity
//We need to cool ourselves.
if(heat_capacity)
if(environment.temperature() > alarm.target_temperature)
gas.set_temperature(gas.temperature() - energy_used / heat_capacity)
else
gas.set_temperature(gas.temperature() + energy_used / heat_capacity)
if(abs(environment.temperature - target_temperature) <= 0.5)
regulating_temperature = FALSE
visible_message("[src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click as a faint electronic humming stops.")
if(abs(environment.temperature() - alarm.target_temperature) <= 0.5)
alarm.regulating_temperature = FALSE
alarm.visible_message("[alarm] clicks quietly as it stops [environment.temperature() > alarm.target_temperature ? "cooling" : "heating"] the room.", "You hear a click as a faint electronic humming stops.")
environment.merge(gas)
@@ -577,36 +582,36 @@
if(!istype(location))
return
var/datum/gas_mixture/environment = location.return_air()
var/known_total = environment.oxygen + environment.nitrogen + environment.carbon_dioxide + environment.toxins + environment.sleeping_agent
var/datum/gas_mixture/environment = location.get_readonly_air()
var/known_total = environment.oxygen() + environment.nitrogen() + environment.carbon_dioxide() + environment.toxins() + environment.sleeping_agent()
var/total = environment.total_moles()
var/datum/tlv/cur_tlv
var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
var/GET_PP = R_IDEAL_GAS_EQUATION * environment.temperature() / environment.volume
cur_tlv = TLV["pressure"]
var/environment_pressure = environment.return_pressure()
var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
cur_tlv = TLV["oxygen"]
var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP)
var/oxygen_percent = total ? environment.oxygen / total * 100 : 0
var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen() * GET_PP)
var/oxygen_percent = total ? environment.oxygen() / total * 100 : 0
cur_tlv = TLV["nitrogen"]
var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen*GET_PP)
var/nitrogen_percent = total ? environment.nitrogen / total * 100 : 0
var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen() * GET_PP)
var/nitrogen_percent = total ? environment.nitrogen() / total * 100 : 0
cur_tlv = TLV["carbon dioxide"]
var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP)
var/co2_percent = total ? environment.carbon_dioxide / total * 100 : 0
var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide() * GET_PP)
var/co2_percent = total ? environment.carbon_dioxide() / total * 100 : 0
cur_tlv = TLV["plasma"]
var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
var/plasma_percent = total ? environment.toxins / total * 100 : 0
var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins() * GET_PP)
var/plasma_percent = total ? environment.toxins() / total * 100 : 0
cur_tlv = TLV["nitrous oxide"]
var/sleeping_agent_dangerlevel = cur_tlv.get_danger_level(environment.sleeping_agent*GET_PP)
var/sleeping_agent_percent = total ? environment.sleeping_agent / total * 100 : 0
var/sleeping_agent_dangerlevel = cur_tlv.get_danger_level(environment.sleeping_agent() * GET_PP)
var/sleeping_agent_percent = total ? environment.sleeping_agent() / total * 100 : 0
cur_tlv = TLV["other"]
var/other_moles = total - known_total
@@ -614,12 +619,12 @@
var/other_percent = total ? other_moles / total * 100 : 0
cur_tlv = TLV["temperature"]
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature())
var/list/data = list()
data["pressure"] = environment_pressure
data["temperature"] = environment.temperature
data["temperature_c"] = round(environment.temperature - T0C, 0.1)
data["temperature"] = environment.temperature()
data["temperature_c"] = round(environment.temperature() - T0C, 0.1)
data["thermostat_state"] = thermostat_state
var/list/percentages = list()
@@ -65,6 +65,8 @@ Pipelines + Other Objects -> Pipe network
pipe_color = null
/obj/machinery/atmospherics/proc/process_atmos() //If you dont use process why are you here
// Any proc that wants MILLA to be synchronous should not sleep.
SHOULD_NOT_SLEEP(TRUE)
return PROCESS_KILL
/obj/machinery/atmospherics/proc/atmos_init()
@@ -73,7 +75,7 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/Destroy()
SSair.atmos_machinery -= src
SSair.deferred_pipenet_rebuilds -= src
SSair.pipenets_to_build -= src
for(var/mob/living/L in src) //ventcrawling is serious business
L.remove_ventcrawl()
L.forceMove(get_turf(src))
@@ -175,10 +177,10 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/build_network(remove_deferral = FALSE)
// Called to build a network from this node
if(remove_deferral)
SSair.deferred_pipenet_rebuilds -= src
SSair.pipenets_to_build -= src
/obj/machinery/atmospherics/proc/defer_build_network()
SSair.deferred_pipenet_rebuilds += src
SSair.pipenets_to_build += src
/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
return
@@ -197,8 +199,8 @@ Pipelines + Other Objects -> Pipe network
if(level == 1 && isturf(T) && T.intact)
to_chat(user, "<span class='danger'>You must remove the plating first.</span>")
return
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
var/datum/gas_mixture/int_air = return_obj_air()
var/datum/gas_mixture/env_air = T.get_readonly_air()
add_fingerprint(user)
var/unsafe_wrenching = FALSE
@@ -252,8 +254,9 @@ Pipelines + Other Objects -> Pipe network
return
if(!pressures)
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
var/datum/gas_mixture/int_air = return_obj_air()
var/turf/T = get_turf(src)
var/datum/gas_mixture/env_air = T.get_readonly_air()
pressures = int_air.return_pressure() - env_air.return_pressure()
var/fuck_you_dir = get_dir(src, user)
@@ -144,12 +144,10 @@
var/turf/T = get_turf(src)
if(T)
//Remove the gas from air1+air2 and assume it
var/datum/gas_mixture/environment = T.return_air()
var/lost = pressures*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
lost += pressures*environment.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
var/shared_loss = lost/2
var/lost = pressures * CELL_VOLUME / (air1.temperature() * R_IDEAL_GAS_EQUATION)
lost += pressures * CELL_VOLUME / (air2.temperature() * R_IDEAL_GAS_EQUATION)
var/shared_loss = lost / 2
var/datum/gas_mixture/to_release = air1.remove(shared_loss)
to_release.merge(air2.remove(shared_loss))
T.assume_air(to_release)
air_update_turf(1)
T.blind_release_air(to_release)
@@ -53,9 +53,9 @@
return
//Calculate necessary moles to transfer using PV = nRT
if(inlet.temperature > 0)
if(inlet.temperature() > 0)
var/pressure_delta = (input_starting_pressure - output_starting_pressure) / 2
var/transfer_moles = pressure_delta * outlet.volume/(inlet.temperature * R_IDEAL_GAS_EQUATION)
var/transfer_moles = pressure_delta * outlet.volume/(inlet.temperature() * R_IDEAL_GAS_EQUATION)
if(last_pressure_delta != pressure_delta)
last_pressure_delta = pressure_delta
@@ -55,11 +55,11 @@
return 1
//Calculate necessary moles to transfer using PV = nRT
if((air1.total_moles() > 0) && (air1.temperature > 0))
if((air1.total_moles() > 0) && (air1.temperature() > 0))
var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure) / 2)
//Can not have a pressure delta that would cause output_pressure > input_pressure
var/transfer_moles = pressure_delta * air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/transfer_moles = pressure_delta * air2.volume / (air1.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
@@ -82,9 +82,9 @@ Thus, the two variables affect pump operation are set in New():
return 1
//Calculate necessary moles to transfer using PV=nRT
if((air1.total_moles() > 0) && (air1.temperature>0))
if((air1.total_moles() > 0) && (air1.temperature() > 0))
var/pressure_delta = target_pressure - output_starting_pressure
var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/transfer_moles = pressure_delta * air2.volume / (air1.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
@@ -108,8 +108,8 @@
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)
if(air1.temperature() > 0)
transfer_moles = pressure_delta * air3.volume / (air1.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
@@ -119,31 +119,31 @@
if(!removed)
return
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
filtered_out.set_temperature(removed.temperature())
switch(filter_type)
if(FILTER_TOXINS)
filtered_out.toxins = removed.toxins
removed.toxins = 0
filtered_out.set_toxins(removed.toxins())
removed.set_toxins(0)
filtered_out.agent_b = removed.agent_b
removed.agent_b = 0
filtered_out.set_agent_b(removed.agent_b())
removed.set_agent_b(0)
if(FILTER_OXYGEN)
filtered_out.oxygen = removed.oxygen
removed.oxygen = 0
filtered_out.set_oxygen(removed.oxygen())
removed.set_oxygen(0)
if(FILTER_NITROGEN)
filtered_out.nitrogen = removed.nitrogen
removed.nitrogen = 0
filtered_out.set_nitrogen(removed.nitrogen())
removed.set_nitrogen(0)
if(FILTER_CO2)
filtered_out.carbon_dioxide = removed.carbon_dioxide
removed.carbon_dioxide = 0
filtered_out.set_carbon_dioxide(removed.carbon_dioxide())
removed.set_carbon_dioxide(0)
if(FILTER_N2O)
filtered_out.sleeping_agent = removed.sleeping_agent
removed.sleeping_agent = 0
filtered_out.set_sleeping_agent(removed.sleeping_agent())
removed.set_sleeping_agent(0)
else
filtered_out = null
@@ -151,11 +151,14 @@
air2.merge(filtered_out)
air3.merge(removed)
parent2.update = 1
if(!QDELETED(parent1))
parent1.update = 1
parent3.update = 1
if(!QDELETED(parent2))
parent2.update = 1
parent1.update = 1
if(!QDELETED(parent3))
parent3.update = 1
return TRUE
@@ -94,11 +94,11 @@
var/transfer_moles1 = 0
var/transfer_moles2 = 0
if(air1.temperature > 0)
transfer_moles1 = (node1_concentration*pressure_delta)*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
if(air1.temperature() > 0)
transfer_moles1 = (node1_concentration*pressure_delta)*air3.volume/(air1.temperature() * R_IDEAL_GAS_EQUATION)
if(air2.temperature > 0)
transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
if(air2.temperature() > 0)
transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature() * R_IDEAL_GAS_EQUATION)
var/air1_moles = air1.total_moles()
var/air2_moles = air2.total_moles()
@@ -199,14 +199,12 @@
var/turf/T = get_turf(src)
if(T)
//Remove the gas from air1+air2+air3 and assume it
var/datum/gas_mixture/environment = T.return_air()
var/lost = pressures*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
lost += pressures*environment.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
lost += pressures*environment.volume/(air3.temperature * R_IDEAL_GAS_EQUATION)
var/lost = pressures * CELL_VOLUME / (air1.temperature() * R_IDEAL_GAS_EQUATION)
lost += pressures * CELL_VOLUME / (air2.temperature() * R_IDEAL_GAS_EQUATION)
lost += pressures * CELL_VOLUME / (air3.temperature() * R_IDEAL_GAS_EQUATION)
var/shared_loss = lost/3
var/datum/gas_mixture/to_release = air1.remove(shared_loss)
to_release.merge(air2.remove(shared_loss))
to_release.merge(air3.remove(shared_loss))
T.assume_air(to_release)
air_update_turf(1)
T.blind_release_air(to_release)
@@ -182,10 +182,10 @@
return
if(air_contents)
temperature_archived = air_contents.temperature
temperature_archived = air_contents.temperature()
heat_gas_contents()
if(abs(temperature_archived-air_contents.temperature) > 1)
if(abs(temperature_archived-air_contents.temperature()) > 1)
parent.update = 1
@@ -240,11 +240,11 @@
occupantData["bodyTemperature"] = occupant.bodytemperature
data["occupant"] = occupantData
data["cellTemperature"] = round(air_contents.temperature)
data["cellTemperature"] = round(air_contents.temperature())
data["cellTemperatureStatus"] = "good"
if(air_contents.temperature > T0C) // if greater than 273.15 kelvin (0 celcius)
if(air_contents.temperature() > T0C) // if greater than 273.15 kelvin (0 celcius)
data["cellTemperatureStatus"] = "bad"
else if(air_contents.temperature > TCRYO)
else if(air_contents.temperature() > TCRYO)
data["cellTemperatureStatus"] = "average"
data["isBeakerLoaded"] = beaker ? TRUE : FALSE
@@ -379,14 +379,14 @@
occupant.bodytemperature = T0C
return
occupant.bodytemperature += 2 * (air_contents.temperature - occupant.bodytemperature) * current_heat_capacity / (current_heat_capacity + air_contents.heat_capacity())
occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise
occupant.bodytemperature += 2 * (air_contents.temperature() - occupant.bodytemperature) * current_heat_capacity / (current_heat_capacity + air_contents.heat_capacity())
occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature()) // this is so ugly i'm sorry for doing it i'll fix it later i promise
if(occupant.bodytemperature < T0C)
var/stun_time = (max(5 / efficiency, (1 / occupant.bodytemperature) * 2000 / efficiency)) STATUS_EFFECT_CONSTANT
occupant.Sleeping(stun_time)
var/heal_mod = air_contents.oxygen < 2 ? 0.2 : 1
var/heal_mod = air_contents.oxygen() < 2 ? 0.2 : 1
occupant.adjustOxyLoss(-6 * heal_mod)
if(beaker && world.time >= last_injection + injection_cooldown)
@@ -403,8 +403,8 @@
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
if(combined_heat_capacity > 0)
var/combined_energy = T20C*current_heat_capacity + air_heat_capacity*air_contents.temperature
air_contents.temperature = combined_energy/combined_heat_capacity
var/combined_energy = T20C * current_heat_capacity + air_heat_capacity * air_contents.temperature()
air_contents.set_temperature(combined_energy / combined_heat_capacity)
/obj/machinery/atmospherics/unary/cryo_cell/proc/go_out()
if(!occupant)
@@ -42,20 +42,20 @@
var/other_air_heat_capacity = partner.air_contents.heat_capacity()
var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity
var/old_temperature = air_contents.temperature
var/other_old_temperature = partner.air_contents.temperature
var/old_temperature = air_contents.temperature()
var/other_old_temperature = partner.air_contents.temperature()
if(combined_heat_capacity > 0)
var/combined_energy = partner.air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature
var/combined_energy = partner.air_contents.temperature() * other_air_heat_capacity + air_heat_capacity * air_contents.temperature()
var/new_temperature = combined_energy/combined_heat_capacity
air_contents.temperature = new_temperature
partner.air_contents.temperature = new_temperature
air_contents.set_temperature(new_temperature)
partner.air_contents.set_temperature(new_temperature)
if(abs(old_temperature-air_contents.temperature) > 1)
if(abs(old_temperature-air_contents.temperature()) > 1)
parent.update = 1
if(abs(other_old_temperature-partner.air_contents.temperature) > 1)
if(abs(other_old_temperature-partner.air_contents.temperature()) > 1)
partner.parent.update = 1
@@ -59,13 +59,13 @@ GLOBAL_LIST_EMPTY(air_injectors)
if(!on || stat & NOPOWER)
return 0
if(air_contents.temperature > 0)
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
if(air_contents.temperature() > 0)
var/transfer_moles = (air_contents.return_pressure()) * volume_rate / (air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
loc.assume_air(removed)
air_update_turf()
var/turf/T = get_turf(src)
T.blind_release_air(removed)
parent.update = TRUE
@@ -35,8 +35,8 @@
var/added_oxygen = oxygen_content - total_moles
air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
air_contents.oxygen += added_oxygen
air_contents.set_temperature((current_heat_capacity * air_contents.temperature() + 20 * added_oxygen * T0C) / (current_heat_capacity + 20 * added_oxygen))
air_contents.set_oxygen(air_contents.oxygen() + added_oxygen)
parent.update = 1
@@ -20,16 +20,21 @@
air_contents.volume = volume
/obj/machinery/atmospherics/unary/passive_vent/process_atmos()
if(!node)
return 0
var/datum/milla_safe/passive_vent_processing/milla = new()
milla.invoke_async(src)
var/turf/T = loc
/datum/milla_safe/passive_vent_processing
/datum/milla_safe/passive_vent_processing/on_run(obj/machinery/atmospherics/unary/passive_vent/vent)
if(!vent.node)
return FALSE
var/turf/T = get_turf(vent)
if(T.density) //No, you should not be able to get free air from walls
return
var/datum/gas_mixture/environment = get_turf_air(T)
var/datum/gas_mixture/environment = loc.return_air()
var/pressure_delta = air_contents.return_pressure() - environment.return_pressure()
var/pressure_delta = vent.air_contents.return_pressure() - environment.return_pressure()
// based on pressure_pump to equalize pressure
// already equalized
@@ -38,25 +43,23 @@
if(pressure_delta > 0)
// transfer from pipe air to environment
if((air_contents.total_moles() > 0) && (air_contents.temperature > 0))
var/transfer_moles = pressure_delta * environment.volume / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
transfer_moles = min(transfer_moles, volume)
if((vent.air_contents.total_moles() > 0) && (vent.air_contents.temperature() > 0))
var/transfer_moles = pressure_delta * environment.volume / (vent.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
transfer_moles = min(transfer_moles, vent.volume)
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
loc.assume_air(removed)
air_update_turf()
var/datum/gas_mixture/removed = vent.air_contents.remove(transfer_moles)
environment.merge(removed)
else
// transfer from environment to pipe air
pressure_delta = -pressure_delta
if((environment.total_moles() > 0) && (environment.temperature > 0))
var/transfer_moles = pressure_delta * air_contents.volume / (environment.temperature * R_IDEAL_GAS_EQUATION)
transfer_moles = min(transfer_moles, volume)
if((environment.total_moles() > 0) && (environment.temperature() > 0))
var/transfer_moles = pressure_delta * vent.air_contents.volume / (environment.temperature() * R_IDEAL_GAS_EQUATION)
transfer_moles = min(transfer_moles, vent.volume)
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
air_contents.merge(removed)
air_update_turf()
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
vent.air_contents.merge(removed)
parent.update = 1
vent.parent.update = 1
return 1
/obj/machinery/atmospherics/unary/passive_vent/update_underlays()
@@ -28,9 +28,9 @@
. = ..()
icon_state = "air"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.oxygen = (25*ONE_ATMOSPHERE*O2STANDARD)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
air_contents.nitrogen = (25*ONE_ATMOSPHERE*N2STANDARD)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
air_contents.set_temperature(T20C)
air_contents.set_oxygen((25 * ONE_ATMOSPHERE * O2STANDARD) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
air_contents.set_nitrogen((25 * ONE_ATMOSPHERE * N2STANDARD) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
/obj/machinery/atmospherics/unary/tank/oxygen
name = "Pressure Tank (Oxygen)"
@@ -40,8 +40,8 @@
. = ..()
icon_state = "o2"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.oxygen = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
air_contents.set_temperature(T20C)
air_contents.set_oxygen((25 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
/obj/machinery/atmospherics/unary/tank/nitrogen
name = "Pressure Tank (Nitrogen)"
@@ -51,8 +51,8 @@
. = ..()
icon_state = "n2"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.nitrogen = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
air_contents.set_temperature(T20C)
air_contents.set_nitrogen((25 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
/obj/machinery/atmospherics/unary/tank/carbon_dioxide
name = "Pressure Tank (Carbon Dioxide)"
@@ -62,8 +62,8 @@
. = ..()
icon_state = "co2"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.carbon_dioxide = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
air_contents.set_temperature(T20C)
air_contents.set_carbon_dioxide((25 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
/obj/machinery/atmospherics/unary/tank/toxins
name = "Pressure Tank (Toxins)"
@@ -73,8 +73,8 @@
. = ..()
icon_state = "toxins"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.toxins = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
air_contents.set_temperature(T20C)
air_contents.set_toxins((25 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
/obj/machinery/atmospherics/unary/tank/nitrous_oxide
name = "Pressure Tank (Nitrous Oxide)"
@@ -84,9 +84,9 @@
. = ..()
icon_state = "n2o"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.set_temperature(T20C)
air_contents.sleeping_agent = (25 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_sleeping_agent((25 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
/obj/machinery/atmospherics/unary/tank/oxygen_agent_b
name = "Unidentified Gas Tank"
@@ -97,6 +97,6 @@
. = ..()
icon_state = "agent_b"
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.set_temperature(T20C)
air_contents.agent_b = (50 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_agent_b((50 * ONE_ATMOSPHERE) * (air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
@@ -18,7 +18,14 @@
icon_state = "[prefix]off"
/obj/machinery/atmospherics/unary/thermal_plate/process_atmos()
var/datum/gas_mixture/environment = loc.return_air()
var/datum/milla_safe/thermal_plate_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/thermal_plate_process
/datum/milla_safe/thermal_plate_process/on_run(obj/machinery/atmospherics/unary/thermal_plate/plate)
var/turf/T = get_turf(plate)
var/datum/gas_mixture/environment = get_turf_air(T)
//Get processable air sample and thermal info from environment
@@ -26,33 +33,33 @@
var/datum/gas_mixture/external_removed = environment.remove(transfer_moles)
if(!external_removed)
return radiate()
return plate.radiate()
if(external_removed.total_moles() < 10)
return radiate()
return plate.radiate()
//Get same info from connected gas
var/internal_transfer_moles = 0.25 * air_contents.total_moles()
var/datum/gas_mixture/internal_removed = air_contents.remove(internal_transfer_moles)
var/internal_transfer_moles = 0.25 * plate.air_contents.total_moles()
var/datum/gas_mixture/internal_removed = plate.air_contents.remove(internal_transfer_moles)
if(!internal_removed)
environment.merge(external_removed)
return 1
var/combined_heat_capacity = internal_removed.heat_capacity() + external_removed.heat_capacity()
var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + external_removed.heat_capacity() * external_removed.temperature
var/combined_energy = internal_removed.temperature() * internal_removed.heat_capacity() + external_removed.heat_capacity() * external_removed.temperature()
if(!combined_heat_capacity) combined_heat_capacity = 1
var/final_temperature = combined_energy / combined_heat_capacity
external_removed.temperature = final_temperature
external_removed.set_temperature(final_temperature)
environment.merge(external_removed)
internal_removed.temperature = final_temperature
air_contents.merge(internal_removed)
internal_removed.set_temperature(final_temperature)
plate.air_contents.merge(internal_removed)
parent.update = 1
plate.parent.update = 1
return 1
@@ -64,11 +71,11 @@
return 1
var/combined_heat_capacity = internal_removed.heat_capacity() + RADIATION_CAPACITY
var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + (RADIATION_CAPACITY * 6.4)
var/combined_energy = internal_removed.temperature() * internal_removed.heat_capacity() + (RADIATION_CAPACITY * 6.4)
var/final_temperature = combined_energy / combined_heat_capacity
internal_removed.temperature = final_temperature
internal_removed.set_temperature(final_temperature)
air_contents.merge(internal_removed)
parent.update = 1
@@ -97,25 +97,25 @@
return
// Coolers don't heat.
if(air_contents.temperature <= target_temperature && cooling)
if(air_contents.temperature() <= target_temperature && cooling)
return
// Heaters don't cool.
if(air_contents.temperature >= target_temperature && !cooling)
if(air_contents.temperature() >= target_temperature && !cooling)
return
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = heat_capacity + air_heat_capacity
var/old_temperature = air_contents.temperature
var/old_temperature = air_contents.temperature()
if(combined_heat_capacity > 0)
var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.temperature
air_contents.temperature = combined_energy / combined_heat_capacity
var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.temperature()
air_contents.set_temperature(combined_energy / combined_heat_capacity)
//todo: have current temperature affected. require power to bring down current temperature again
var/temperature_delta = abs(old_temperature - air_contents.temperature)
var/temperature_delta = abs(old_temperature - air_contents.temperature())
if(temperature_delta > 1)
var/new_active_consumption = (temperature_delta * 25) * min(log(10, air_contents.temperature) - 1, 1)
var/new_active_consumption = (temperature_delta * 25) * min(log(10, air_contents.temperature()) - 1, 1)
update_active_power_consumption(power_channel, new_active_consumption + idle_power_consumption)
change_power_mode(ACTIVE_POWER_USE)
parent.update = TRUE
@@ -190,7 +190,7 @@
data["target"] = target_temperature
data["initial"] = initial(target_temperature)
data["temperature"] = air_contents.temperature
data["temperature"] = air_contents.temperature()
data["pressure"] = air_contents.return_pressure()
return data
@@ -92,10 +92,16 @@
var/turf/T = get_turf(src)
if(T)
//Remove the gas from air_contents and assume it
var/datum/gas_mixture/environment = T.return_air()
var/lost = pressures*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
var/datum/milla_safe/unary_unsafe_pressure_release/milla = new()
milla.invoke_async(src, pressures)
var/datum/gas_mixture/to_release = air_contents.remove(lost)
T.assume_air(to_release)
air_update_turf(1)
/datum/milla_safe/unary_unsafe_pressure_release
/datum/milla_safe/unary_unsafe_pressure_release/on_run(obj/machinery/atmospherics/unary/device, pressures)
//Remove the gas from air_contents and assume it
var/turf/T = get_turf(device)
var/datum/gas_mixture/environment = get_turf_air(T)
var/lost = pressures * environment.volume / (device.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/to_release = device.air_contents.remove(lost)
environment.merge(to_release)
@@ -110,57 +110,61 @@
update_underlays()
/obj/machinery/atmospherics/unary/vent_pump/process_atmos()
if(stat & (NOPOWER|BROKEN))
var/datum/milla_safe/vent_pump_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/vent_pump_process
/datum/milla_safe/vent_pump_process/on_run(obj/machinery/atmospherics/unary/vent_pump/vent_pump)
if(vent_pump.stat & (NOPOWER|BROKEN))
return FALSE
var/turf/T = loc
if(QDELETED(vent_pump.parent))
// We're orphaned!
return FALSE
var/turf/T = get_turf(vent_pump)
if(T.density) //No, you should not be able to get free air from walls
return
if(!node)
on = FALSE
//broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0
if(!on)
if(!vent_pump.node)
vent_pump.on = FALSE
if(!vent_pump.on)
return FALSE
if(welded)
if(air_contents.return_pressure() >= weld_burst_pressure && prob(5)) //the weld is on but the cover is welded shut, can it withstand the internal pressure?
visible_message("<span class='danger'>The welded cover of [src] bursts open!</span>")
if(vent_pump.welded)
if(vent_pump.air_contents.return_pressure() >= vent_pump.weld_burst_pressure && prob(5)) //the weld is on but the cover is welded shut, can it withstand the internal pressure?
vent_pump.visible_message("<span class='danger'>The welded cover of [vent_pump] bursts open!</span>")
for(var/mob/living/M in range(1))
unsafe_pressure_release(M, air_contents.return_pressure()) //let's send everyone flying
welded = FALSE
update_icon()
vent_pump.unsafe_pressure_release(M, vent_pump.air_contents.return_pressure()) //let's send everyone flying
vent_pump.welded = FALSE
vent_pump.update_icon()
return FALSE
var/datum/gas_mixture/environment = loc.return_air()
var/datum/gas_mixture/environment = get_turf_air(T)
var/environment_pressure = environment.return_pressure()
if(releasing) //internal -> external
if(vent_pump.releasing) //internal -> external
var/pressure_delta = 10000
if(pressure_checks & 1)
pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
if(pressure_checks & 2)
pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound))
if(vent_pump.pressure_checks & 1)
pressure_delta = min(pressure_delta, (vent_pump.external_pressure_bound - environment_pressure))
if(vent_pump.pressure_checks & 2)
pressure_delta = min(pressure_delta, (vent_pump.air_contents.return_pressure() - vent_pump.internal_pressure_bound))
if(pressure_delta > 0.5 && air_contents.temperature > 0)
var/transfer_moles = pressure_delta * environment.volume / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
loc.assume_air(removed)
air_update_turf()
parent.update = TRUE
if(pressure_delta > 0.5 && vent_pump.air_contents.temperature() > 0)
var/transfer_moles = pressure_delta * environment.volume / (vent_pump.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = vent_pump.air_contents.remove(transfer_moles)
environment.merge(removed)
vent_pump.parent.update = TRUE
else //external -> internal
var/pressure_delta = 10000
if(pressure_checks & 1)
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
if(pressure_checks & 2)
pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure()))
if(vent_pump.pressure_checks & 1)
pressure_delta = min(pressure_delta, (environment_pressure - vent_pump.external_pressure_bound))
if(vent_pump.pressure_checks & 2)
pressure_delta = min(pressure_delta, (vent_pump.internal_pressure_bound - vent_pump.air_contents.return_pressure()))
if(pressure_delta > 0.5 && environment.temperature > 0)
var/transfer_moles = pressure_delta * air_contents.volume / (environment.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
if(isnull(removed)) //in space
return
air_contents.merge(removed)
air_update_turf()
parent.update = TRUE
if(pressure_delta > 0.5 && environment.temperature() > 0)
var/transfer_moles = pressure_delta * vent_pump.air_contents.volume / (environment.temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
vent_pump.air_contents.merge(removed)
vent_pump.parent.update = TRUE
return TRUE
@@ -133,62 +133,67 @@
adjacent_turfs = T.GetAtmosAdjacentTurfs(alldir=1)
/obj/machinery/atmospherics/unary/vent_scrubber/proc/scrub(turf/simulated/tile)
var/datum/milla_safe/vent_scrubber_process/milla = new()
milla.invoke_async(src, tile)
/datum/milla_safe/vent_scrubber_process
/datum/milla_safe/vent_scrubber_process/on_run(obj/machinery/atmospherics/unary/vent_scrubber/scrubber, turf/simulated/tile)
if(!tile || !istype(tile))
return 0
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/environment = get_turf_air(tile)
if(scrubbing)
if((scrub_O2 && environment.oxygen>0.001) || (scrub_N2 && environment.nitrogen>0.001) || (scrub_CO2 && environment.carbon_dioxide>0.001) || (scrub_Toxins && environment.toxins>0.001) || (environment.sleeping_agent) || (environment.agent_b))
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
if(scrubber.scrubbing)
if((scrubber.scrub_O2 && environment.oxygen() > 0.001) || (scrubber.scrub_N2 && environment.nitrogen() > 0.001) || (scrubber.scrub_CO2 && environment.carbon_dioxide() > 0.001) || (scrubber.scrub_Toxins && environment.toxins() > 0.001) || (environment.sleeping_agent()) || (environment.agent_b()))
var/transfer_moles = min(1, scrubber.volume_rate / environment.volume) * environment.total_moles()
//Take a gas sample
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
if(isnull(removed)) //in space
return
//Filter it
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
if(scrub_O2)
filtered_out.oxygen = removed.oxygen
removed.oxygen = 0
if(scrub_N2)
filtered_out.nitrogen = removed.nitrogen
removed.nitrogen = 0
if(scrub_Toxins)
filtered_out.toxins = removed.toxins
removed.toxins = 0
if(scrub_CO2)
filtered_out.carbon_dioxide = removed.carbon_dioxide
removed.carbon_dioxide = 0
filtered_out.set_temperature(removed.temperature())
if(scrubber.scrub_O2)
filtered_out.set_oxygen(removed.oxygen())
removed.set_oxygen(0)
if(scrubber.scrub_N2)
filtered_out.set_nitrogen(removed.nitrogen())
removed.set_nitrogen(0)
if(scrubber.scrub_Toxins)
filtered_out.set_toxins(removed.toxins())
removed.set_toxins(0)
if(scrubber.scrub_CO2)
filtered_out.set_carbon_dioxide(removed.carbon_dioxide())
removed.set_carbon_dioxide(0)
if(removed.agent_b)
filtered_out.agent_b = removed.agent_b
removed.agent_b = 0
if(removed.agent_b())
filtered_out.set_agent_b(removed.agent_b())
removed.set_agent_b(0)
if(scrub_N2O)
filtered_out.sleeping_agent = removed.sleeping_agent
removed.sleeping_agent = 0
if(scrubber.scrub_N2O)
filtered_out.set_sleeping_agent(removed.sleeping_agent())
removed.set_sleeping_agent(0)
//Remix the resulting gases
air_contents.merge(filtered_out)
scrubber.air_contents.merge(filtered_out)
tile.assume_air(removed)
tile.air_update_turf()
environment.merge(removed)
else //Just siphoning all air
if(air_contents.return_pressure() >= (50 * ONE_ATMOSPHERE))
if(scrubber.air_contents.return_pressure() >= (50 * ONE_ATMOSPHERE))
return
var/transfer_moles = environment.total_moles() * (volume_rate/environment.volume)
var/transfer_moles = environment.total_moles() * (scrubber.volume_rate / environment.volume)
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
air_contents.merge(removed)
tile.air_update_turf()
scrubber.air_contents.merge(removed)
parent.update = 1
if(!QDELETED(scrubber.parent))
scrubber.parent.update = 1
return 1
@@ -8,10 +8,10 @@
var/update = TRUE
/datum/pipeline/New()
SSair.networks += src
SSair.pipenets += src
/datum/pipeline/Destroy()
SSair.networks -= src
SSair.pipenets -= src
if(air && air.volume)
temporarily_store_air()
for(var/obj/machinery/atmospherics/pipe/P in members)
@@ -121,18 +121,26 @@
member.air_temporary = new
member.air_temporary.volume = member.volume
member.air_temporary.oxygen = air.oxygen * member.volume / air.volume
member.air_temporary.nitrogen = air.nitrogen * member.volume / air.volume
member.air_temporary.toxins = air.toxins * member.volume / air.volume
member.air_temporary.carbon_dioxide = air.carbon_dioxide * member.volume / air.volume
member.air_temporary.sleeping_agent = air.sleeping_agent * member.volume / air.volume
member.air_temporary.agent_b = air.agent_b * member.volume / air.volume
member.air_temporary.set_oxygen(air.oxygen() * member.volume / air.volume)
member.air_temporary.set_nitrogen(air.nitrogen() * member.volume / air.volume)
member.air_temporary.set_toxins(air.toxins() * member.volume / air.volume)
member.air_temporary.set_carbon_dioxide(air.carbon_dioxide() * member.volume / air.volume)
member.air_temporary.set_sleeping_agent(air.sleeping_agent() * member.volume / air.volume)
member.air_temporary.set_agent_b(air.agent_b() * member.volume / air.volume)
member.air_temporary.temperature = air.temperature
member.air_temporary.set_temperature(air.temperature())
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
var/total_heat_capacity = air.heat_capacity()
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
var/datum/milla_safe/pipeline_temperature_interact/milla = new()
milla.invoke_async(src, target, share_volume, thermal_conductivity)
/datum/milla_safe/pipeline_temperature_interact
/datum/milla_safe/pipeline_temperature_interact/on_run(datum/pipeline/pipeline, turf/target, share_volume, thermal_conductivity)
var/datum/gas_mixture/environment = get_turf_air(target)
var/total_heat_capacity = pipeline.air.heat_capacity()
var/partial_heat_capacity = total_heat_capacity*(share_volume/pipeline.air.volume)
if(issimulatedturf(target))
var/turf/simulated/modeled_location = target
@@ -140,20 +148,20 @@
if(modeled_location.blocks_air)
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.temperature - modeled_location.temperature
var/delta_temperature = pipeline.air.temperature() - modeled_location.temperature
var/heat = thermal_conductivity*delta_temperature* \
(partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity))
air.temperature -= heat/total_heat_capacity
pipeline.air.set_temperature(pipeline.air.temperature() - heat / total_heat_capacity)
modeled_location.temperature += heat/modeled_location.heat_capacity
else
var/delta_temperature = 0
var/sharer_heat_capacity = 0
delta_temperature = (air.temperature - modeled_location.air.temperature)
sharer_heat_capacity = modeled_location.air.heat_capacity()
delta_temperature = (pipeline.air.temperature() - environment.temperature())
sharer_heat_capacity = environment.heat_capacity()
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
@@ -167,20 +175,20 @@
else
return 1
air.temperature += self_temperature_delta
pipeline.air.set_temperature(pipeline.air.temperature() + self_temperature_delta)
modeled_location.air.temperature += sharer_temperature_delta
environment.set_temperature(environment.temperature() + sharer_temperature_delta)
else
if((target.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.temperature - target.temperature
var/delta_temperature = pipeline.air.temperature() - target.temperature
var/heat = thermal_conductivity*delta_temperature* \
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
var/heat = thermal_conductivity * delta_temperature * \
(partial_heat_capacity * target.heat_capacity / (partial_heat_capacity + target.heat_capacity))
air.temperature -= heat/total_heat_capacity
update = TRUE
pipeline.air.set_temperature(pipeline.air.temperature() - heat / total_heat_capacity)
pipeline.update = TRUE
/datum/pipeline/proc/reconcile_air()
var/list/datum/gas_mixture/GL = list()
@@ -210,43 +218,4 @@
if(C.connected_device)
GL += C.portableConnectorReturnAir()
var/total_volume = 0
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/total_oxygen = 0
var/total_nitrogen = 0
var/total_toxins = 0
var/total_carbon_dioxide = 0
var/total_sleeping_agent = 0
var/total_agent_b = 0
for(var/datum/gas_mixture/G in GL)
total_volume += G.volume
total_thermal_energy += G.thermal_energy()
total_heat_capacity += G.heat_capacity()
total_oxygen += G.oxygen
total_nitrogen += G.nitrogen
total_toxins += G.toxins
total_carbon_dioxide += G.carbon_dioxide
total_sleeping_agent += G.sleeping_agent
total_agent_b += G.agent_b
if(total_volume > 0)
//Calculate temperature
var/temperature = 0
if(total_heat_capacity > 0)
temperature = total_thermal_energy/total_heat_capacity
//Update individual gas_mixtures by volume ratio
for(var/datum/gas_mixture/G in GL)
G.oxygen = total_oxygen * G.volume / total_volume
G.nitrogen = total_nitrogen * G.volume / total_volume
G.toxins = total_toxins * G.volume / total_volume
G.carbon_dioxide = total_carbon_dioxide * G.volume / total_volume
G.sleeping_agent = total_sleeping_agent * G.volume / total_volume
G.agent_b = total_agent_b * G.volume / total_volume
G.temperature = temperature
share_many_airs(GL)
@@ -38,7 +38,7 @@ GLOBAL_LIST_EMPTY(gas_meters)
icon_state = "meter0"
return
var/datum/gas_mixture/environment = target.return_air()
var/datum/gas_mixture/environment = target.return_obj_air()
if(!environment)
icon_state = "meterX"
return
@@ -68,9 +68,9 @@ GLOBAL_LIST_EMPTY(gas_meters)
. += "<span class='danger'>The display is off.</span>"
else if(target)
var/datum/gas_mixture/environment = target.return_air()
var/datum/gas_mixture/environment = target.return_obj_air()
if(environment)
. += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]&deg;C)"
. += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature(), 0.01)]K ([round(environment.temperature() - T0C, 0.01)]&deg;C)"
else
. += "The sensor error light is blinking."
else
@@ -22,10 +22,9 @@
level = 1
/obj/machinery/atmospherics/pipe/Destroy()
releaseAirToTurf()
QDEL_NULL(air_temporary)
var/turf/T = get_turf(src)
T.blind_release_air(air_temporary)
var/turf/T = loc
for(var/obj/machinery/atmospherics/meter/meter in T)
if(meter.target == src)
var/obj/item/pipe_meter/PM = new (T)
@@ -49,13 +48,7 @@
/obj/machinery/atmospherics/proc/pipeline_expansion()
return null
/obj/machinery/atmospherics/pipe/proc/releaseAirToTurf()
if(air_temporary)
var/turf/T = loc
T.assume_air(air_temporary)
air_update_turf()
/obj/machinery/atmospherics/pipe/return_air()
/obj/machinery/atmospherics/pipe/return_obj_air()
RETURN_TYPE(/datum/gas_mixture)
if(!parent)
return 0
@@ -22,27 +22,24 @@
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process_atmos()
var/environment_temperature = 0
var/datum/gas_mixture/pipe_air = return_air()
var/datum/gas_mixture/pipe_air = return_obj_air()
if(!pipe_air)
return
var/turf/simulated/T = loc
if(istype(T))
if(T.blocks_air)
environment_temperature = T.temperature
else
var/datum/gas_mixture/environment = T.return_air()
environment_temperature = environment.temperature
else
var/turf/T = get_turf(src)
if(T.blocks_air)
environment_temperature = T.temperature
else
var/datum/gas_mixture/environment = T.get_readonly_air()
environment_temperature = environment.temperature()
if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
if(abs(environment_temperature-pipe_air.temperature()) > minimum_temperature_difference)
parent.temperature_interact(T, volume, thermal_conductivity)
//Heat causes pipe to glow
if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //glow starts at 500K
if(abs(pipe_air.temperature - icon_temperature) > 10)
icon_temperature = pipe_air.temperature
if(pipe_air.temperature() && (icon_temperature > 500 || pipe_air.temperature() > 500)) //glow starts at 500K
if(abs(pipe_air.temperature() - icon_temperature) > 10)
icon_temperature = pipe_air.temperature()
var/h_r = heat2color_r(icon_temperature)
var/h_g = heat2color_g(icon_temperature)
@@ -59,10 +56,10 @@
//burn any mobs buckled based on temperature
if(has_buckled_mobs())
var/heat_limit = 1000
if(pipe_air.temperature > heat_limit + 1)
if(pipe_air.temperature() > heat_limit + 1)
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, "chest")
buckled_mob.apply_damage(4 * log(pipe_air.temperature() - heat_limit), BURN, "chest")
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New()
@@ -219,68 +219,69 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
/obj/machinery/atmospherics/portable/canister/proc/canister_break()
disconnect()
var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
var/turf/T = get_turf(src)
T.assume_air(expelled_gas)
air_update_turf()
stat |= BROKEN
density = FALSE
playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
update_icon()
var/turf/T = get_turf(src)
if(holding_tank)
holding_tank.forceMove(T)
holding_tank = null
T.blind_release_air(expelled_gas)
/obj/machinery/atmospherics/portable/canister/process_atmos()
if(stat & BROKEN)
..()
var/datum/milla_safe/canister_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/canister_process
/datum/milla_safe/canister_process/on_run(obj/machinery/atmospherics/portable/canister/canister)
if(canister.stat & BROKEN)
return
..()
if(valve_open)
if(canister.valve_open)
var/datum/gas_mixture/environment
if(holding_tank)
environment = holding_tank.air_contents
if(canister.holding_tank)
environment = canister.holding_tank.air_contents
else
environment = loc.return_air()
var/turf/T = get_turf(canister)
environment = get_turf_air(T)
var/env_pressure = environment.return_pressure()
var/pressure_delta = min(release_pressure - env_pressure, (air_contents.return_pressure() - env_pressure)/2)
var/pressure_delta = min(canister.release_pressure - env_pressure, (canister.air_contents.return_pressure() - env_pressure) / 2)
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if((air_contents.temperature > 0) && (pressure_delta > 0))
transfer_moles = pressure_delta * environment.volume / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
if((canister.air_contents.temperature() > 0) && (pressure_delta > 0))
transfer_moles = pressure_delta * environment.volume / (canister.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
var/datum/gas_mixture/removed = canister.air_contents.remove(transfer_moles)
if(holding_tank)
environment.merge(removed)
else
loc.assume_air(removed)
air_update_turf()
update_icon()
environment.merge(removed)
canister.update_icon()
if(air_contents.return_pressure() < 1)
can_label = TRUE
if(canister.air_contents.return_pressure() < 1)
canister.can_label = TRUE
else
can_label = FALSE
canister.can_label = FALSE
/obj/machinery/atmospherics/portable/canister/return_air()
/obj/machinery/atmospherics/portable/canister/return_obj_air()
RETURN_TYPE(/datum/gas_mixture)
return air_contents
/obj/machinery/atmospherics/portable/canister/proc/return_temperature()
var/datum/gas_mixture/GM = return_air()
if(GM && GM.volume>0)
return GM.temperature
var/datum/gas_mixture/GM = return_obj_air()
if(GM && GM.volume > 0)
return GM.temperature()
return
/obj/machinery/atmospherics/portable/canister/proc/return_pressure()
var/datum/gas_mixture/GM = return_air()
var/datum/gas_mixture/GM = return_obj_air()
if(GM && GM.volume>0)
return GM.return_pressure()
return
@@ -384,12 +385,12 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
if(!holding_tank)
logmsg = "Valve was <b>opened</b> by [key_name(ui.user)], starting a transfer into the air.<br>"
if(air_contents.toxins > 0)
if(air_contents.toxins() > 0)
message_admins("[key_name_admin(ui.user)] opened a canister that contains plasma in [get_area(src)]! (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_admin("[key_name(ui.user)] opened a canister that contains plasma at [get_area(src)]: [x], [y], [z]")
ui.user.create_log(MISC_LOG, "has opened a canister of plasma")
if(air_contents.sleeping_agent > 0)
if(air_contents.sleeping_agent() > 0)
message_admins("[key_name_admin(ui.user)] opened a canister that contains N2O in [get_area(src)]! (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_admin("[key_name(ui.user)] opened a canister that contains N2O at [get_area(src)]: [x], [y], [z]")
ui.user.create_log(MISC_LOG, "has opened a canister of N2O")
@@ -462,7 +463,7 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
. = ..()
canister_color["prim"] = "orange"
air_contents.toxins = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_toxins((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
update_icon()
@@ -470,7 +471,7 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
. = ..()
canister_color["prim"] = "blue"
air_contents.oxygen = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_oxygen((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
update_icon()
@@ -478,7 +479,7 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
. = ..()
canister_color["prim"] = "redws"
air_contents.sleeping_agent = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_sleeping_agent((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
update_icon()
@@ -486,7 +487,7 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
. = ..()
canister_color["prim"] = "red"
air_contents.nitrogen = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_nitrogen((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
update_icon()
@@ -495,7 +496,7 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
. = ..()
canister_color["prim"] = "black"
air_contents.carbon_dioxide = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_carbon_dioxide((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
update_icon()
@@ -503,8 +504,8 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
. = ..()
canister_color["prim"] = "grey"
air_contents.oxygen = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.nitrogen = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.set_oxygen((O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
air_contents.set_nitrogen((N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature()))
update_icon()
@@ -19,7 +19,7 @@
SSair.atmos_machinery += src
air_contents.volume = volume
air_contents.temperature = T20C
air_contents.set_temperature(T20C)
if(mapload)
return INITIALIZE_HINT_LATELOAD
@@ -53,49 +53,46 @@
/obj/machinery/atmospherics/portable/pump/process_atmos()
..()
if(on)
var/datum/milla_safe/portable_pump_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/portable_pump_process
/datum/milla_safe/portable_pump_process/on_run(obj/machinery/atmospherics/portable/pump/pump)
if(pump.on)
var/datum/gas_mixture/environment
if(holding_tank)
environment = holding_tank.air_contents
if(pump.holding_tank)
environment = pump.holding_tank.air_contents
else
environment = loc.return_air()
if(direction == DIRECTION_OUT)
var/pressure_delta = target_pressure - environment.return_pressure()
var/turf/T = get_turf(pump)
environment = get_turf_air(T)
if(pump.direction == DIRECTION_OUT)
var/pressure_delta = pump.target_pressure - environment.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if(air_contents.temperature > 0)
transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
if(pump.air_contents.temperature() > 0)
transfer_moles = pressure_delta*environment.volume/(pump.air_contents.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
var/datum/gas_mixture/removed = pump.air_contents.remove(transfer_moles)
if(holding_tank)
environment.merge(removed)
else
loc.assume_air(removed)
air_update_turf()
environment.merge(removed)
else
var/pressure_delta = target_pressure - air_contents.return_pressure()
var/pressure_delta = pump.target_pressure - pump.air_contents.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if(environment.temperature > 0)
transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
if(environment.temperature() > 0)
transfer_moles = pressure_delta*pump.air_contents.volume/(environment.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed
if(holding_tank)
removed = environment.remove(transfer_moles)
else
removed = loc.remove_air(transfer_moles)
air_update_turf()
removed = environment.remove(transfer_moles)
air_contents.merge(removed)
pump.air_contents.merge(removed)
return
/obj/machinery/atmospherics/portable/pump/return_air()
/obj/machinery/atmospherics/portable/pump/return_obj_air()
RETURN_TYPE(/datum/gas_mixture)
return air_contents
@@ -46,60 +46,56 @@
/obj/machinery/atmospherics/portable/scrubber/process_atmos()
..()
var/datum/milla_safe/portable_scrubber_process/milla = new()
milla.invoke_async(src)
if(!on)
/datum/milla_safe/portable_scrubber_process
/datum/milla_safe/portable_scrubber_process/on_run(obj/machinery/atmospherics/portable/scrubber/scrubber)
if(!scrubber.on)
return
if(scrubber.holding_tank)
scrubber.scrub(scrubber.holding_tank.air_contents)
return
scrub(loc)
if(widenet)
var/turf/T = loc
if(istype(T))
for(var/turf/simulated/tile in T.GetAtmosAdjacentTurfs(alldir=1))
scrub(tile)
/obj/machinery/atmospherics/portable/scrubber/proc/scrub(turf/simulated/tile)
var/datum/gas_mixture/environment
if(holding_tank)
environment = holding_tank.air_contents
else
environment = tile.return_air()
var/transfer_moles = min(1,volume_rate/environment.volume)*environment.total_moles()
var/turf/T = get_turf(scrubber)
scrubber.scrub(get_turf_air(T))
if(scrubber.widenet)
for(var/turf/simulated/tile in T.GetAtmosAdjacentTurfs(alldir=1))
scrubber.scrub(get_turf_air(tile))
/obj/machinery/atmospherics/portable/scrubber/proc/scrub(datum/gas_mixture/environment)
var/transfer_moles = min(1, volume_rate / environment.volume) * environment.total_moles()
//Take a gas sample
var/datum/gas_mixture/removed
if(holding_tank)
removed = environment.remove(transfer_moles)
else
removed = loc.remove_air(transfer_moles)
removed = environment.remove(transfer_moles)
//Filter it
if(removed)
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
filtered_out.set_temperature(removed.temperature())
filtered_out.toxins = removed.toxins
removed.toxins = 0
filtered_out.set_toxins(removed.toxins())
removed.set_toxins(0)
filtered_out.carbon_dioxide = removed.carbon_dioxide
removed.carbon_dioxide = 0
filtered_out.set_carbon_dioxide(removed.carbon_dioxide())
removed.set_carbon_dioxide(0)
filtered_out.sleeping_agent = removed.sleeping_agent
removed.sleeping_agent = 0
filtered_out.set_sleeping_agent(removed.sleeping_agent())
removed.set_sleeping_agent(0)
filtered_out.agent_b = removed.agent_b
removed.agent_b = 0
filtered_out.set_agent_b(removed.agent_b())
removed.set_agent_b(0)
//Remix the resulting gases
//Remix the resulting gases
air_contents.merge(filtered_out)
if(holding_tank)
environment.merge(removed)
else
tile.assume_air(removed)
tile.air_update_turf()
environment.merge(removed)
/obj/machinery/atmospherics/portable/scrubber/return_air()
/obj/machinery/atmospherics/portable/scrubber/return_obj_air()
RETURN_TYPE(/datum/gas_mixture)
return air_contents
@@ -32,7 +32,8 @@
icon = 'icons/misc/beach.dmi'
var/water_overlay_image = null
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
planetary_atmos = TRUE
atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
atmos_environment = ENVIRONMENT_TEMPERATE
/turf/simulated/floor/beach/away/Initialize(mapload)
. = ..()
@@ -114,10 +115,11 @@
linkedcontroller.decalinpool += A
/turf/simulated/floor/beach/away/water/lavaland_air
nitrogen = LAVALAND_NITROGEN
oxygen = LAVALAND_OXYGEN
nitrogen = LAVALAND_NITROGEN
temperature = LAVALAND_TEMPERATURE
planetary_atmos = TRUE
atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
atmos_environment = ENVIRONMENT_LAVALAND
/// for boundary "walls"
/turf/simulated/floor/beach/away/water/dense
+5 -4
View File
@@ -1,6 +1,7 @@
// Call this before you remove the last dirt on a z level - that way, all objects
// will have proper atmos and other important enviro things
/proc/late_setup_level(turfs, smoothTurfs)
/datum/milla_safe/late_setup_level
// Ensures that atmos and environment are set up.
/datum/milla_safe/late_setup_level/on_run(turfs, smoothTurfs)
var/total_timer = start_watch()
var/subtimer = start_watch()
if(!smoothTurfs)
@@ -11,7 +12,7 @@
* air subsystem will call subsequently call setup_allturfs with _every_
* turf in the world */
if(SSair && SSair.initialized)
SSair.setup_allturfs(turfs)
SSair.setup_allturfs_sleepless(turfs)
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
+17 -18
View File
@@ -43,30 +43,29 @@
var/left_click = pa.Find("left")
var/ctrl_click = pa.Find("ctrl")
if(left_click) //rectangular
var/datum/gas_mixture/air = new()
air.set_temperature(temperature)
air.set_oxygen(ppratio_to_moles(oxygen))
air.set_nitrogen(ppratio_to_moles(nitrogen))
air.set_toxins(ppratio_to_moles(plasma))
air.set_carbon_dioxide(ppratio_to_moles(cdiox))
air.set_sleeping_agent(ppratio_to_moles(nitrox))
air.set_agent_b(ppratio_to_moles(agentbx))
for(var/turf/T in block(cornerA,cornerB))
if(issimulatedturf(T))
// fill the turf with the appropriate gasses
// this feels slightly icky
var/turf/simulated/S = T
if(S.air)
S.air.temperature = temperature
S.air.oxygen = ppratio_to_moles(oxygen)
S.air.nitrogen = ppratio_to_moles(nitrogen)
S.air.toxins = ppratio_to_moles(plasma)
S.air.carbon_dioxide = ppratio_to_moles(cdiox)
S.air.sleeping_agent = ppratio_to_moles(nitrox)
S.air.agent_b = ppratio_to_moles(agentbx)
S.update_visuals()
S.air_update_turf()
if(!S.blocks_air)
T.blind_set_air(air)
else if(ctrl_click) // overwrite "default" space air
T.temperature = temperature
T.oxygen = ppratio_to_moles(oxygen)
T.nitrogen = ppratio_to_moles(nitrogen)
T.toxins = ppratio_to_moles(plasma)
T.carbon_dioxide = ppratio_to_moles(cdiox)
T.sleeping_agent = ppratio_to_moles(nitrox)
T.agent_b = ppratio_to_moles(agentbx)
T.air_update_turf()
T.oxygen = air.oxygen()
T.nitrogen = air.nitrogen()
T.toxins = air.toxins()
T.carbon_dioxide = air.carbon_dioxide()
T.sleeping_agent = air.sleeping_agent()
T.agent_b = air.agent_b()
// admin log
log_admin("Build Mode: [key_name(user)] changed the atmos of region [COORD(cornerA)] to [COORD(cornerB)]. T: [temperature], P: [pressure], Ox: [oxygen]%, N2: [nitrogen]%, Plsma: [plasma]%, CO2: [cdiox]%, N2O: [nitrox]%. [ctrl_click ? "Overwrote base space turf gases." : ""]")
@@ -27,7 +27,7 @@
atmosblock = FALSE
else
atmosblock = TRUE
air_update_turf(1)
recalculate_atmos_connectivity()
/obj/structure/blob/shield/update_name()
. = ..()
+7 -5
View File
@@ -31,21 +31,23 @@ GLOBAL_LIST_EMPTY(blob_minions)
setDir(pick(GLOB.cardinal))
check_integrity()
if(atmosblock)
air_update_turf(TRUE)
recalculate_atmos_connectivity()
ConsumeTile()
/obj/structure/blob/Destroy()
if(atmosblock)
atmosblock = FALSE
air_update_turf(1)
recalculate_atmos_connectivity()
GLOB.blobs -= src
overmind = null // let us not have gc issues
if(isturf(loc)) //Necessary because Expand() is screwed up and spawns a blob and then deletes it
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
return ..()
/obj/structure/blob/BlockSuperconductivity()
return atmosblock
/obj/structure/blob/get_superconductivity(direction)
if(atmosblock)
return FALSE
return ..()
/obj/structure/blob/CanPass(atom/movable/mover, turf/target, height=0)
if(height==0)
@@ -54,7 +56,7 @@ GLOBAL_LIST_EMPTY(blob_minions)
return 1
return 0
/obj/structure/blob/CanAtmosPass(turf/T)
/obj/structure/blob/CanAtmosPass(direction)
return !atmosblock
/obj/structure/blob/CanPathfindPass(obj/item/card/id/ID, dir, caller, no_id = FALSE)
+1 -1
View File
@@ -161,7 +161,7 @@
//////////////////////////////
//Stops atmos from passing wall tanks, since they are effectively full-windows.
/obj/machinery/fishtank/wall/CanAtmosPass(turf/T)
/obj/machinery/fishtank/wall/CanAtmosPass(direction)
return FALSE
/obj/machinery/fishtank/process()
@@ -374,7 +374,9 @@
..()
if(firestarter && active)
target.fire_act()
new /obj/effect/hotspot(get_turf(target))
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(target)
hotspot.temperature = 1000
hotspot.recolor()
/obj/item/reagent_containers/drinks/bottle/molotov/attackby(obj/item/I, mob/user, params)
if(I.get_heat() && !active)
@@ -284,9 +284,9 @@
var/turf/source_turf = t
expand_queue -= source_turf
// Expand to each dir
for(var/dir in GLOB.cardinal)
var/turf/target_turf = get_step(source_turf, dir)
if(processed[target_turf] || !source_turf.CanAtmosPass(target_turf))
for(var/direction in GLOB.cardinal)
var/turf/target_turf = get_step(source_turf, direction)
if(processed[target_turf] || !source_turf.CanAtmosPass(direction) || !target_turf.CanAtmosPass(turn(direction, 180)))
continue
create_plasma(target_turf)
expand_queue += target_turf
+4 -2
View File
@@ -180,9 +180,11 @@
..()
/// Check if we're standing in an oxygenless environment
/obj/structure/bonfire/proc/CheckOxygen()
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(G.oxygen > 13)
var/turf/T = get_turf(src)
var/datum/gas_mixture/G = T.get_readonly_air()
if(G.oxygen() > 13)
return 1
return 0
+21 -3
View File
@@ -111,11 +111,25 @@
icon_regular_floor = "podfloor_light"
floor_tile = /obj/item/stack/tile/pod/light
/turf/simulated/floor/pod/light/lavaland_air
oxygen = LAVALAND_OXYGEN
nitrogen = LAVALAND_NITROGEN
temperature = LAVALAND_TEMPERATURE
atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
atmos_environment = ENVIRONMENT_LAVALAND
/turf/simulated/floor/pod/dark
icon_state = "podfloor_dark"
icon_regular_floor = "podfloor_dark"
floor_tile = /obj/item/stack/tile/pod/dark
/turf/simulated/floor/pod/dark/lavaland_air
oxygen = LAVALAND_OXYGEN
nitrogen = LAVALAND_NITROGEN
temperature = LAVALAND_TEMPERATURE
atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
atmos_environment = ENVIRONMENT_LAVALAND
//Door
/obj/machinery/door/airlock/survival_pod
icon = 'icons/obj/doors/airlocks/survival/survival.dmi'
@@ -264,14 +278,14 @@
/obj/structure/fans/Initialize(loc)
. = ..()
air_update_turf(1)
recalculate_atmos_connectivity()
/obj/structure/fans/Destroy()
arbitraryatmosblockingvar = 0
air_update_turf(1)
recalculate_atmos_connectivity()
return ..()
/obj/structure/fans/CanAtmosPass(turf/T)
/obj/structure/fans/CanAtmosPass(direction)
return !arbitraryatmosblockingvar
/obj/structure/fans/deconstruct()
@@ -297,6 +311,10 @@
icon_state = "fan_tiny"
buildstackamount = 2
/obj/structure/fans/tiny/get_superconductivity(direction)
// Mostly for stuff on Lavaland.
return ZERO_HEAT_TRANSFER_COEFFICIENT
/obj/structure/fans/tiny/invisible
name = "air flow blocker"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
@@ -136,9 +136,6 @@
var/turf/T = Stuff
if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors)
var/turf/simulated/O = T.ChangeTurf(NewTerrainFloors)
if(O.air)
var/datum/gas_mixture/G = O.air
G.copy_from(O.air)
if(prob(florachance) && length(NewFlora) && !is_blocked_turf(O))
var/atom/Picked = pick(NewFlora)
new Picked(O)
+2 -2
View File
@@ -13,8 +13,8 @@
move_on_shuttle = FALSE
flags_2 = IMMUNE_TO_SHUTTLECRUSH_2
/mob/camera/experience_pressure_difference()
return
/mob/camera/experience_pressure_difference(flow_x, flow_y)
return // Immune to gas flow.
/mob/camera/forceMove(atom/destination)
var/oldloc = loc
+1 -1
View File
@@ -68,7 +68,7 @@
//make sure the air can transmit speech - hearer's side
var/turf/T = get_turf(src)
if(T && !isobserver(src))
var/datum/gas_mixture/environment = T.return_air()
var/datum/gas_mixture/environment = T.get_readonly_air()
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
return FALSE
@@ -72,11 +72,11 @@
/mob/living/carbon/alien/check_eye_prot()
return 2
/mob/living/carbon/alien/handle_environment(datum/gas_mixture/environment)
if(!environment)
/mob/living/carbon/alien/handle_environment(datum/gas_mixture/readonly_environment)
if(!readonly_environment)
return
var/loc_temp = get_temperature(environment)
var/loc_temp = get_temperature(readonly_environment)
if(!on_fire) // If you're on fire, ignore local air temperature
if(loc_temp > bodytemperature)
@@ -8,23 +8,23 @@
var/toxins_used = 0
var/tox_detect_threshold = 0.02
var/breath_pressure = (breath.total_moles() * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME
var/breath_pressure = (breath.total_moles() * R_IDEAL_GAS_EQUATION * breath.temperature()) / BREATH_VOLUME
//Partial pressure of the toxins in our breath
var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath_pressure
var/Toxins_pp = (breath.toxins() / breath.total_moles()) * breath_pressure
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
add_plasma(breath.toxins * 250)
add_plasma(breath.toxins() * 250)
throw_alert("alien_tox", /atom/movable/screen/alert/alien_tox)
toxins_used = breath.toxins
toxins_used = breath.toxins()
else
clear_alert("alien_tox")
//Breathe in toxins and out oxygen
breath.toxins -= toxins_used
breath.oxygen += toxins_used
breath.set_toxins(breath.toxins() - toxins_used)
breath.set_oxygen(breath.oxygen() + toxins_used)
/mob/living/carbon/alien/handle_status_effects()
..()
+24 -22
View File
@@ -42,21 +42,24 @@
//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing(times_fired)
if(times_fired % 2 == 1)
breathe() //Breathe every other tick, unless suffocating
var/datum/milla_safe/carbon_breathe/milla = new()
milla.invoke_async(src)
else
if(isobj(loc))
var/obj/location_as_object = loc
location_as_object.handle_internal_lifeform(src, 0)
/datum/milla_safe/carbon_breathe
/datum/milla_safe/carbon_breathe/on_run(mob/living/carbon/carbon)
var/turf/T = get_turf(carbon)
carbon.breathe(get_turf_air(T))
//Second link in a breath chain, calls check_breath()
/mob/living/carbon/proc/breathe()
/mob/living/carbon/proc/breathe(datum/gas_mixture/environment)
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
return
var/datum/gas_mixture/environment
if(loc)
environment = loc.return_air()
var/datum/gas_mixture/breath
if(health <= HEALTH_THRESHOLD_CRIT && check_death_method())
@@ -77,14 +80,14 @@
if(isobj(loc)) //Breathe from loc as object
var/obj/loc_as_obj = loc
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME)
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME, environment)
else if(isturf(loc)) //Breathe from loc as turf
var/breath_moles = 0
if(environment)
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
breath = environment.remove(breath_moles)
else //Breathe from loc as obj again
if(isobj(loc))
var/obj/loc_as_obj = loc
@@ -93,9 +96,8 @@
check_breath(breath)
if(breath)
loc.assume_air(breath)
air_update_turf()
if(ishuman(src) && !internal && environment.temperature < 273 && environment.return_pressure() > 20) //foggy breath :^)
environment.merge(breath)
if(ishuman(src) && !internal && environment.temperature() < 273 && environment.return_pressure() > 20) //foggy breath :^)
new /obj/effect/frosty_breath(loc, src)
//Third and last link in a breath chain
@@ -119,12 +121,12 @@
var/SA_para_min = 1
var/SA_sleep_min = 1
var/oxygen_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature())/BREATH_VOLUME
var/O2_partialpressure = (breath.oxygen/breath.total_moles())*breath_pressure
var/Toxins_partialpressure = (breath.toxins/breath.total_moles())*breath_pressure
var/CO2_partialpressure = (breath.carbon_dioxide/breath.total_moles())*breath_pressure
var/SA_partialpressure = (breath.sleeping_agent/breath.total_moles())*breath_pressure
var/O2_partialpressure = (breath.oxygen() / breath.total_moles()) * breath_pressure
var/Toxins_partialpressure = (breath.toxins() / breath.total_moles()) * breath_pressure
var/CO2_partialpressure = (breath.carbon_dioxide() / breath.total_moles()) * breath_pressure
var/SA_partialpressure = (breath.sleeping_agent() / breath.total_moles()) * breath_pressure
//OXYGEN
if(O2_partialpressure < safe_oxy_min) //Not enough oxygen
@@ -133,18 +135,18 @@
if(O2_partialpressure > 0)
var/ratio = 1 - O2_partialpressure/safe_oxy_min
adjustOxyLoss(min(5*ratio, 3))
oxygen_used = breath.oxygen*ratio
oxygen_used = breath.oxygen() * ratio
else
adjustOxyLoss(3)
throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
else //Enough oxygen
adjustOxyLoss(-5)
oxygen_used = breath.oxygen
oxygen_used = breath.oxygen()
clear_alert("not_enough_oxy")
breath.oxygen -= oxygen_used
breath.carbon_dioxide += oxygen_used
breath.set_oxygen(breath.oxygen() - oxygen_used)
breath.set_carbon_dioxide(breath.carbon_dioxide() + oxygen_used)
//CARBON DIOXIDE
if(CO2_partialpressure > safe_co2_max)
@@ -163,14 +165,14 @@
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath.toxins/safe_tox_max) * 10
var/ratio = (breath.toxins() / safe_tox_max) * 10
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
//TRACE GASES
if(breath.sleeping_agent)
if(breath.sleeping_agent())
if(SA_partialpressure > SA_para_min)
Paralyse(6 SECONDS)
if(SA_partialpressure > SA_sleep_min)
@@ -772,10 +772,10 @@ emp_act
else
..()
/mob/living/carbon/human/experience_pressure_difference(pressure_difference, direction)
/mob/living/carbon/human/experience_pressure_difference(flow_x, flow_y)
playsound(src, 'sound/effects/space_wind.ogg', 50, TRUE)
if(HAS_TRAIT(src, TRAIT_NOSLIP))
return FALSE
return // Immune to gas flow.
return ..()
/mob/living/carbon/human/water_act(volume, temperature, source, method = REAGENT_TOUCH)
@@ -185,12 +185,11 @@
return null
/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
if(!environment)
/mob/living/carbon/human/handle_environment(datum/gas_mixture/readonly_environment)
if(!readonly_environment)
return
var/loc_temp = get_temperature(environment)
// to_chat(world, "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Thermal protection: [get_thermal_protection()] - Fire protection: [thermal_protection + add_fire_protection(loc_temp)] - Heat capacity: [environment_heat_capacity] - Location: [loc] - src: [src]")
var/loc_temp = get_temperature(readonly_environment)
//Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit.
if(stat != DEAD)
@@ -254,7 +253,7 @@
// Account for massive pressure differences. Done by Polymorph
// Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense!
var/pressure = environment.return_pressure()
var/pressure = readonly_environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
if(status_flags & GODMODE) return 1 //godmode
@@ -117,8 +117,12 @@
return FALSE
if(H.has_status_effect(STATUS_EFFECT_BURNT_WINGS))
return FALSE
var/datum/gas_mixture/current = A.return_air()
if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible
if(isobj(H.loc))
// Can't fly if you're in a box/mech/whatever.
return FALSE
var/turf/T = get_turf(H)
var/datum/gas_mixture/current = T.get_readonly_air()
if(current && (current.return_pressure() >= ONE_ATMOSPHERE * 0.85)) //as long as there's reasonable pressure and no gravity, flight is possible
return TRUE
/datum/species/moth/spec_thunk(mob/living/carbon/human/H)
@@ -153,11 +153,17 @@
/datum/species/plasmaman/handle_life(mob/living/carbon/human/H)
var/atmos_sealed = !HAS_TRAIT(H, TRAIT_NOFIRE) && (isclothing(H.wear_suit) && H.wear_suit.flags & STOPSPRESSUREDMAGE) && (isclothing(H.head) && H.head.flags & STOPSPRESSUREDMAGE)
if(!atmos_sealed && (!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman) && !HAS_TRAIT(H, TRAIT_NOSELFIGNITION_HEAD_ONLY)))
var/datum/gas_mixture/environment = H.loc.return_air()
var/datum/gas_mixture/environment = null
if(isobj(H.loc))
var/obj/O = H.loc
environment = O.return_obj_air()
if(isnull(environment))
var/turf/T = get_turf(H)
environment = T.get_readonly_air()
if(environment)
if(environment.total_moles())
if(!HAS_TRAIT(H, TRAIT_NOFIRE))
if(environment.oxygen && environment.oxygen >= OXYCONCEN_PLASMEN_IGNITION) //Same threshhold that extinguishes fire
if(environment.oxygen() && environment.oxygen() >= OXYCONCEN_PLASMEN_IGNITION) //Same threshhold that extinguishes fire
H.adjust_fire_stacks(0.5)
if(!H.on_fire && H.fire_stacks > 0)
H.visible_message("<span class='danger'>[H]'s body reacts with the atmosphere and bursts into flames!</span>","<span class='userdanger'>Your body reacts with the atmosphere and bursts into flame!</span>")
+21 -7
View File
@@ -671,7 +671,7 @@
else
return pick("trails_1", "trails_2")
/mob/living/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
/mob/living/experience_pressure_difference(flow_x, flow_y, pressure_resistance_prob_delta = 0)
if(buckled)
return
if(client && client.move_delay >= world.time + world.tick_lag * 2)
@@ -680,6 +680,16 @@
var/list/turfs_to_check = list()
if(has_limbs)
var/direction = 0
if(flow_x > 100)
direction |= EAST
if(flow_x < -100)
direction |= WEST
if(flow_y > 100)
direction |= NORTH
if(flow_y < -100)
direction |= SOUTH
var/turf/T = get_step(src, angle2dir(dir2angle(direction) + 90))
if(T)
turfs_to_check += T
@@ -698,7 +708,7 @@
pressure_resistance_prob_delta -= 20
break
..(pressure_difference, direction, pressure_resistance_prob_delta)
..(flow_x, flow_y, pressure_resistance_prob_delta)
/*//////////////////////
START RESIST PROCS
@@ -885,10 +895,14 @@
var/loc_temp = T0C
if(ismecha(loc))
var/obj/mecha/M = loc
loc_temp = M.return_temperature()
var/datum/gas_mixture/cabin = M.return_obj_air()
if(cabin)
loc_temp = cabin.temperature()
else
loc_temp = environment.temperature()
else if(istype(loc, /obj/structure/transit_tube_pod))
loc_temp = environment.temperature
loc_temp = environment.temperature()
else if(isspaceturf(get_turf(src)))
var/turf/heat_turf = get_turf(src)
@@ -898,12 +912,12 @@
var/obj/machinery/atmospherics/unary/cryo_cell/C = loc
if(C.air_contents.total_moles() < 10)
loc_temp = environment.temperature
loc_temp = environment.temperature()
else
loc_temp = C.air_contents.temperature
loc_temp = C.air_contents.temperature()
else
loc_temp = environment.temperature
loc_temp = environment.temperature()
return loc_temp
+4 -4
View File
@@ -223,12 +223,12 @@
else
ExtinguishMob()
return FALSE
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(G.oxygen < 1)
var/turf/T = get_turf(src)
var/datum/gas_mixture/G = T?.get_readonly_air() // Check if we're standing in an oxygenless environment
if(!G || G.oxygen() < 1)
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return FALSE
var/turf/location = get_turf(src)
location.hotspot_expose(700, 50, 1)
T.hotspot_expose(700, 50, 1)
SEND_SIGNAL(src, COMSIG_LIVING_FIRE_TICK)
return TRUE
+9 -3
View File
@@ -51,9 +51,15 @@
handle_heartattack()
//Handle temperature/pressure differences between body and environment
var/datum/gas_mixture/environment = loc.return_air()
if(environment)
handle_environment(environment)
var/datum/gas_mixture/readonly_environment = null
if(isobj(loc))
var/obj/O = loc
readonly_environment = O.return_obj_air()
if(isnull(readonly_environment))
var/turf/T = get_turf(src)
if(!isnull(T))
readonly_environment = T.get_readonly_air()
handle_environment(readonly_environment)
handle_fire()
+1 -1
View File
@@ -239,7 +239,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
if(T)
//make sure the air can transmit speech - speaker's side
var/datum/gas_mixture/environment = T.return_air()
var/datum/gas_mixture/environment = T.get_readonly_air()
var/pressure = environment ? environment.return_pressure() : 0
if(!ignore_atmospherics)
if(pressure < SOUND_MINIMUM_PRESSURE)
@@ -22,6 +22,6 @@
/mob/living/silicon/robot/mob_has_gravity()
return ..() || mob_negates_gravity()
/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
/mob/living/silicon/robot/experience_pressure_difference(flow_x, flow_y)
if(!HAS_TRAIT(src, TRAIT_MAGPULSE))
return ..()
@@ -864,12 +864,6 @@
new /obj/effect/decal/cleanable/blood/oil(loc)
..()
/mob/living/simple_animal/bot/mulebot/remove_air(amount) //To prevent riders suffocating
if(loc)
return loc.remove_air(amount)
else
return null
/mob/living/simple_animal/bot/mulebot/run_resist()
. = ..()
if(load)
@@ -593,7 +593,9 @@ Difficulty: Hard
var/turf/C = get_turf(src)
new /obj/effect/temp_visual/lava_warning(C, enraged ? 18 SECONDS : 6 SECONDS)
for(var/turf/T in range (1,src))
new /obj/effect/hotspot(T)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(T)
hotspot.temperature = 1000
hotspot.recolor()
T.hotspot_expose(700,50,1)
if(mode == VORTEX)
var/turf/T = get_turf(src)
@@ -279,7 +279,9 @@ Difficulty: Medium
for(var/turf/T in turfs)
if(T.density)
break
new /obj/effect/hotspot(T)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(T)
hotspot.temperature = 1000
hotspot.recolor()
T.hotspot_expose(700,50,1)
for(var/mob/living/L in T.contents)
if(L in hit_list || L == source)
@@ -473,7 +475,7 @@ Difficulty: Medium
duration = 82
color = COLOR_DARK_ORANGE
/obj/effect/temp_visual/drakewall/CanAtmosPass()
/obj/effect/temp_visual/drakewall/CanAtmosPass(direction)
return !density
/obj/effect/temp_visual/lava_safe
@@ -567,7 +569,9 @@ Difficulty: Medium
var/turf/simulated/mineral/M = T
M.gets_drilled()
playsound(T, "explosion", 80, TRUE)
new /obj/effect/hotspot(T)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(T)
hotspot.temperature = 1000
hotspot.recolor()
T.hotspot_expose(700, 50, 1)
for(var/mob/living/L in T.contents)
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
@@ -366,12 +366,12 @@
/obj/structure/spider/terrorweb/queen/Initialize(mapload)
. = ..()
air_update_turf(TRUE)
recalculate_atmos_connectivity()
/obj/structure/spider/terrorweb/queen/CanAtmosPass(turf/T)
/obj/structure/spider/terrorweb/queen/CanAtmosPass(direction)
return FALSE
/obj/structure/spider/terrorweb/queen/Destroy()
var/turf/T = get_turf(src)
. = ..()
T.air_update_turf(TRUE)
T.recalculate_atmos_connectivity()
@@ -289,20 +289,22 @@
custom_emote(EMOTE_AUDIBLE, pick(emote_hear))
/mob/living/simple_animal/handle_environment(datum/gas_mixture/environment)
/mob/living/simple_animal/handle_environment(datum/gas_mixture/readonly_environment)
if(!readonly_environment)
return
var/atmos_suitable = 1
var/areatemp = get_temperature(environment)
var/areatemp = get_temperature(readonly_environment)
if(abs(areatemp - bodytemperature) > 5 && !HAS_TRAIT(src, TRAIT_NOBREATH))
var/diff = areatemp - bodytemperature
diff = diff / 5
bodytemperature += diff
var/tox = environment.toxins
var/oxy = environment.oxygen
var/n2 = environment.nitrogen
var/co2 = environment.carbon_dioxide
var/tox = readonly_environment.toxins()
var/oxy = readonly_environment.oxygen()
var/n2 = readonly_environment.nitrogen()
var/co2 = readonly_environment.carbon_dioxide()
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
atmos_suitable = 0
@@ -101,11 +101,11 @@
AIproc = FALSE
/mob/living/simple_animal/slime/handle_environment(datum/gas_mixture/environment)
if(!environment)
/mob/living/simple_animal/slime/handle_environment(datum/gas_mixture/readonly_environment)
if(!readonly_environment)
return
var/loc_temp = get_temperature(environment)
var/loc_temp = get_temperature(readonly_environment)
adjust_bodytemperature(adjust_body_temperature(bodytemperature, loc_temp, 1))
+11 -9
View File
@@ -95,18 +95,20 @@
set category = "Admin"
set hidden = 1
if(!loc) return 0
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.get_readonly_air()
var/datum/gas_mixture/environment = loc.return_air()
if(!environment)
return
var/t = "<span class='notice'>Coordinates: [x],[y] \n</span>"
t+= "<span class='warning'>Temperature: [environment.temperature] \n</span>"
t+= "<span class='notice'>Nitrogen: [environment.nitrogen] \n</span>"
t+= "<span class='notice'>Oxygen: [environment.oxygen] \n</span>"
t+= "<span class='notice'>Plasma : [environment.toxins] \n</span>"
t+= "<span class='notice'>Carbon Dioxide: [environment.carbon_dioxide] \n</span>"
t+= "<span class='notice'>N2O: [environment.sleeping_agent] \n</span>"
t+= "<span class='notice'>Agent B: [environment.agent_b] \n</span>"
t+= "<span class='warning'>Temperature: [environment.temperature()] \n</span>"
t+= "<span class='notice'>Nitrogen: [environment.nitrogen()] \n</span>"
t+= "<span class='notice'>Oxygen: [environment.oxygen()] \n</span>"
t+= "<span class='notice'>Plasma : [environment.toxins()] \n</span>"
t+= "<span class='notice'>Carbon Dioxide: [environment.carbon_dioxide()] \n</span>"
t+= "<span class='notice'>N2O: [environment.sleeping_agent()] \n</span>"
t+= "<span class='notice'>Agent B: [environment.agent_b()] \n</span>"
usr.show_message(t, EMOTE_VISIBLE)
+3 -1
View File
@@ -832,7 +832,9 @@
else if(myeffect == "Death By Fire")
to_chat(target,"<span class='userdanger'>You feel hotter than usual. Maybe you should lowe-wait, is that your hand melting?</span>")
var/turf/simulated/T = get_turf(target)
new /obj/effect/hotspot(T)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(T)
hotspot.temperature = 1000
hotspot.recolor()
target.adjustFireLoss(150) // hard crit, the burning takes care of the rest.
else if(myeffect == "Total Brain Death")
to_chat(target,"<span class='userdanger'>You see a message appear in front of you in bright red letters: <b>YHWH-3 ACTIVATED. TERMINATION IN 3 SECONDS</b></span>")
+8 -8
View File
@@ -103,21 +103,21 @@
var/list/results = list()
var/turf/T = get_turf(user.loc)
if(!isnull(T))
var/datum/gas_mixture/environment = T.return_air()
var/datum/gas_mixture/environment = T.get_readonly_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
if(total_moles)
var/o2_level = environment.oxygen/total_moles
var/n2_level = environment.nitrogen/total_moles
var/co2_level = environment.carbon_dioxide/total_moles
var/plasma_level = environment.toxins/total_moles
var/n2o_level = environment.sleeping_agent/total_moles
var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level+n2o_level)
var/o2_level = environment.oxygen()/total_moles
var/n2_level = environment.nitrogen() / total_moles
var/co2_level = environment.carbon_dioxide() / total_moles
var/plasma_level = environment.toxins() / total_moles
var/n2o_level = environment.sleeping_agent() / total_moles
var/unknown_level = 1 - (o2_level + n2_level + co2_level + plasma_level + n2o_level)
results = list(
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
list("entry" = "Temperature", "units" = "C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
list("entry" = "Temperature", "units" = "C", "val" = "[round(environment.temperature()-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
list("entry" = "Oxygen", "units" = "%", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
list("entry" = "Nitrogen", "units" = "%", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
list("entry" = "Carbon Dioxide", "units" = "%", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
@@ -25,13 +25,13 @@
/obj/machinery/power/rad_collector/process()
if(!loaded_tank)
return
if(!loaded_tank.air_contents.toxins)
if(!loaded_tank.air_contents.toxins())
investigate_log("<font color='red'>out of fuel</font>.", "singulo")
playsound(src, 'sound/machines/ding.ogg', 50, TRUE)
eject()
else
var/gasdrained = min(powerproduction_drain * drainratio, loaded_tank.air_contents.toxins)
loaded_tank.air_contents.toxins -= gasdrained
var/gasdrained = min(powerproduction_drain * drainratio, loaded_tank.air_contents.toxins())
loaded_tank.air_contents.set_toxins(loaded_tank.air_contents.toxins() - gasdrained)
var/power_produced = RAD_COLLECTOR_OUTPUT
produce_direct_power(power_produced)
@@ -43,7 +43,7 @@
if(!locked)
toggle_power()
user.visible_message("[user.name] turns the [name] [active ? "on" : "off"].", "You turn the [name] [active ? "on" : "off"].")
investigate_log("turned [active ? "<font color='green'>on</font>" : "<font color='red'>off</font>"] by [user.key]. [loaded_tank ? "Fuel: [round(loaded_tank.air_contents.toxins / 0.29)]%" : "<font color='red'>It is empty</font>"].", "singulo")
investigate_log("turned [active ? "<font color='green'>on</font>" : "<font color='red'>off</font>"] by [user.key]. [loaded_tank ? "Fuel: [round(loaded_tank.air_contents.toxins() / 0.29)]%" : "<font color='red'>It is empty</font>"].", "singulo")
else
to_chat(user, "<span class='warning'>The controls are locked!</span>")
@@ -272,7 +272,7 @@
var/turf/T = get_turf(src)
if(!T)
return SUPERMATTER_ERROR
var/datum/gas_mixture/air = T.return_air()
var/datum/gas_mixture/air = T.get_readonly_air()
if(!air)
return SUPERMATTER_ERROR
@@ -286,10 +286,10 @@
if(integrity < SUPERMATTER_DANGER_PERCENT)
return SUPERMATTER_DANGER
if((integrity < SUPERMATTER_WARNING_PERCENT) || (air.temperature > CRITICAL_TEMPERATURE))
if((integrity < SUPERMATTER_WARNING_PERCENT) || (air.temperature() > CRITICAL_TEMPERATURE))
return SUPERMATTER_WARNING
if(air.temperature > (CRITICAL_TEMPERATURE * 0.8))
if(air.temperature() > (CRITICAL_TEMPERATURE * 0.8))
return SUPERMATTER_NOTIFY
if(power > 5)
@@ -402,9 +402,19 @@
qdel(src)
/obj/machinery/atmospherics/supermatter_crystal/process_atmos()
var/datum/milla_safe/supermatter_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/supermatter_process
/datum/milla_safe/supermatter_process/on_run(obj/machinery/atmospherics/supermatter_crystal/supermatter)
var/turf/T = get_turf(supermatter)
var/datum/gas_mixture/env = get_turf_air(T)
supermatter.process_atmos_safely(T, env)
/obj/machinery/atmospherics/supermatter_crystal/proc/process_atmos_safely(turf/T, datum/gas_mixture/env)
if(!processes) //Just fuck me up bro
return
var/turf/T = loc
if(isnull(T)) // We have a null turf...something is wrong, stop processing this entity.
return PROCESS_KILL
@@ -440,9 +450,6 @@
var/next_sound = round((100 - aggression) * 5)
last_accent_sound = world.time + max(SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN, next_sound)
//Ok, get the air from the turf
var/datum/gas_mixture/env = T.return_air()
var/datum/gas_mixture/removed
if(produces_gas)
//Remove gas from surrounding area
@@ -462,7 +469,7 @@
//((((some value between 0.5 and 1 * temp - ((273.15 + 40) * some values between 1 and 10)) * some number between 0.25 and knock your socks off / 150) * 0.25
//Heat and mols account for each other, a lot of hot mols are more damaging then a few
//Mols start to have a positive effect on damage after 350
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + heat_penalty_threshold)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature() - ((T0C + heat_penalty_threshold)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Power only starts affecting damage when it is above 5000
damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Molar count only starts affecting damage when it is above 1800
@@ -472,24 +479,23 @@
//healing damage
if(combined_gas < MOLE_PENALTY_THRESHOLD)
//Only has a net positive effect when the temp is below 313.15, heals up to 2 damage. Psycologists increase this temp min by up to 45
damage = max(damage + (min(removed.temperature - (T0C + heat_penalty_threshold), 0) / 150 ), 0)
damage = max(damage + (min(removed.temperature() - (T0C + heat_penalty_threshold), 0) / 150 ), 0)
//Check for holes in the SM inner chamber
for(var/t in RANGE_TURFS(1, loc))
if(!isspaceturf(t))
var/turf/here = get_turf(src)
for(var/turf/neighbor in here.GetAtmosAdjacentTurfs(alldir = TRUE))
if(!isspaceturf(neighbor))
continue
var/turf/turf_to_check = t
if(length(turf_to_check.atmos_adjacent_turfs))
var/integrity = get_integrity()
if(integrity < 10)
damage += clamp((power * 0.0005) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
else if(integrity < 25)
damage += clamp((power * 0.0009) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
else if(integrity < 45)
damage += clamp((power * 0.005) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
else if(integrity < 75)
damage += clamp((power * 0.002) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
break
var/integrity = get_integrity()
if(integrity < 10)
damage += clamp((power * 0.0005) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
else if(integrity < 25)
damage += clamp((power * 0.0009) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
else if(integrity < 45)
damage += clamp((power * 0.005) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
else if(integrity < 75)
damage += clamp((power * 0.002) * DAMAGE_INCREASE_MULTIPLIER, 0, MAX_SPACE_EXPOSURE_DAMAGE)
break
//caps damage rate
//Takes the lower number between archived damage + (1.8) and damage
@@ -499,11 +505,11 @@
//calculating gas related values
combined_gas = max(removed.total_moles(), 0)
plasmacomp = max(removed.toxins / combined_gas, 0)
o2comp = max(removed.oxygen / combined_gas, 0)
co2comp = max(removed.carbon_dioxide / combined_gas, 0)
n2ocomp = max(removed.sleeping_agent / combined_gas, 0)
n2comp = max(removed.nitrogen / combined_gas, 0)
plasmacomp = max(removed.toxins() / combined_gas, 0)
o2comp = max(removed.oxygen() / combined_gas, 0)
co2comp = max(removed.carbon_dioxide() / combined_gas, 0)
n2ocomp = max(removed.sleeping_agent() / combined_gas, 0)
n2comp = max(removed.nitrogen() / combined_gas, 0)
gasmix_power_ratio = min(max(plasmacomp + o2comp + co2comp - n2comp, 0), 1)
@@ -544,7 +550,7 @@
if(power_changes)
power = max((removed.temperature * temp_factor / T0C) * gasmix_power_ratio + power, 0)
power = max((removed.temperature() * temp_factor / T0C) * gasmix_power_ratio + power, 0)
if(prob(50))
var/mole_crunch_bonus = 0
@@ -563,19 +569,18 @@
//Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock
//is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall.
//Power * 0.55 * (some value between 1.5 and 23) / 5
removed.temperature += (((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER) * heat_multiplier)
removed.set_temperature(removed.temperature() + (((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER) * heat_multiplier))
//We can only emit so much heat, that being 57500
removed.temperature = max(0, min(removed.temperature, 2500 * dynamic_heat_modifier))
removed.set_temperature(max(0, min(removed.temperature(), 2500 * dynamic_heat_modifier)))
//Calculate how much gas to release
//Varies based on power and gas content
removed.toxins += max(((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER) * gas_multiplier, 0)
removed.set_toxins(removed.toxins() + max(((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER) * gas_multiplier, 0))
//Varies based on power, gas content, and heat
removed.oxygen += max((((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER) * gas_multiplier, 0)
removed.set_oxygen(removed.oxygen() + max((((device_energy + removed.temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER) * gas_multiplier, 0))
if(produces_gas)
env.merge(removed)
air_update_turf()
//Makes em go mad and accumulate rads.
for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them.
@@ -597,9 +602,9 @@
if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point) //If the power is above 5000 or if the damage is above 550
var/range = 4
zap_cutoff = 1500
if(removed && removed.return_pressure() > 0 && removed.return_temperature() > 0)
if(removed && removed.return_pressure() > 0 && removed.temperature() > 0)
//You may be able to freeze the zapstate of the engine with good planning, we'll see
zap_cutoff = clamp(3000 - (power * (removed.total_moles()) / 10) / removed.return_temperature(), 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols
zap_cutoff = clamp(3000 - (power * (removed.total_moles()) / 10) / removed.temperature(), 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols
//We should always be able to zap our way out of the default enclosure
//See supermatter_zap() for more details
range = clamp(power / removed.return_pressure() * 10, 2, 7)
@@ -1182,8 +1187,8 @@
//This gotdamn variable is a boomer and keeps giving me problems
var/turf/T = get_turf(target)
var/pressure = 1
if(T?.return_air())
var/datum/gas_mixture/G = T.return_air()
var/datum/gas_mixture/G = T?.get_readonly_air()
if(G)
pressure = max(1, G.return_pressure())
//We get our range with the strength of the zap and the pressure, the higher the former and the lower the latter the better
var/new_range = clamp(zap_str / pressure * 10, 2, 7)
@@ -1,22 +1,21 @@
/datum/supermatter_event
var/name = "Unknown X-K (Report this to coders)"
var/obj/machinery/atmospherics/supermatter_crystal/supermatter
var/datum/gas_mixture/environment
/// Probability of the event not running, higher tiers being rarer
var/threat_level
var/duration
var/turf/supermatter_turf
/datum/supermatter_event/New(obj/machinery/atmospherics/supermatter_crystal/_supermatter)
. = ..()
supermatter = _supermatter
supermatter_turf = get_turf(supermatter)
if(!supermatter)
stack_trace("a /datum/supermatter_event was called without an involved supermatter.")
return
if(!istype(supermatter))
stack_trace("a /datum/supermatter_event was called with (name: [supermatter], type: [supermatter.type]) instead of a supermatter!")
return
var/turf/T = get_turf(supermatter)
environment = T.return_air()
/datum/supermatter_event/proc/start_event()
supermatter.event_active = src
@@ -66,21 +65,27 @@
name = "D-1"
/datum/supermatter_event/delta_tier/sleeping_gas/on_start()
environment.sleeping_agent += 200
var/datum/gas_mixture/air = new()
air.set_sleeping_agent(200)
supermatter_turf.blind_release_air(air)
// nitrogen
/datum/supermatter_event/delta_tier/nitrogen
name = "D-2"
/datum/supermatter_event/delta_tier/nitrogen/on_start()
environment.nitrogen += 200
var/datum/gas_mixture/air = new()
air.set_nitrogen(200)
supermatter_turf.blind_release_air(air)
// carbon dioxide
/datum/supermatter_event/delta_tier/carbon_dioxide
name = "D-3"
/datum/supermatter_event/delta_tier/carbon_dioxide/on_start()
environment.carbon_dioxide += 250
var/datum/gas_mixture/air = new()
air.set_carbon_dioxide(250)
supermatter_turf.blind_release_air(air)
// C class events
@@ -97,14 +102,18 @@
name = "C-1"
/datum/supermatter_event/charlie_tier/oxygen/on_start()
environment.oxygen += 250
var/datum/gas_mixture/air = new()
air.set_oxygen(250)
supermatter_turf.blind_release_air(air)
// plasma
/datum/supermatter_event/charlie_tier/plasma
name = "C-2"
/datum/supermatter_event/charlie_tier/plasma/on_start()
environment.toxins += 200
var/datum/gas_mixture/air = new()
air.set_toxins(200)
supermatter_turf.blind_release_air(air)
// lowers the temp required for the SM to take damage.
/datum/supermatter_event/charlie_tier/heat_penalty_threshold
@@ -125,10 +125,11 @@
Gives traitors more opportunities to sabotage the generator or allows enterprising engineers to build additional
cooling in order to get more power out.
*/
var/datum/gas_mixture/environment = loc.return_air()
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.get_readonly_air()
if(environment)
var/ratio = min(environment.return_pressure() / ONE_ATMOSPHERE, 1)
var/ambient = environment.temperature - T20C
var/ambient = environment.temperature() - T20C
lower_limit += ambient * ratio
upper_limit += ambient * ratio
@@ -154,10 +155,11 @@
/obj/machinery/power/port_gen/pacman/handle_inactive()
var/cooling_temperature = 20
var/datum/gas_mixture/environment = loc.return_air()
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.get_readonly_air()
if(environment)
var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
var/ambient = environment.temperature - T20C
var/ambient = environment.temperature() - T20C
cooling_temperature += ambient*ratio
if(temperature > cooling_temperature)
@@ -110,13 +110,13 @@
if(cold_air && hot_air)
//log_debug("hot_air = [hot_air] temperature = [hot_air.temperature]; cold_air = [cold_air] temperature = [hot_air.temperature];")
//log_debug("hot_air = [hot_air] temperature = [hot_air.temperature()]; cold_air = [cold_air] temperature = [hot_air.temperature()];")
//log_debug("coldair and hotair pass")
var/cold_air_heat_capacity = cold_air.heat_capacity()
var/hot_air_heat_capacity = hot_air.heat_capacity()
var/delta_temperature = hot_air.temperature - cold_air.temperature
var/delta_temperature = hot_air.temperature() - cold_air.temperature()
//log_debug("delta_temperature = [delta_temperature]; cold_air_heat_capacity = [cold_air_heat_capacity]; hot_air_heat_capacity = [hot_air_heat_capacity]")
@@ -130,8 +130,8 @@
//log_debug("lastgen = [lastgen]; heat = [heat]; delta_temperature = [delta_temperature]; hot_air_heat_capacity = [hot_air_heat_capacity]; cold_air_heat_capacity = [cold_air_heat_capacity];")
hot_air.temperature = hot_air.temperature - energy_transfer / hot_air_heat_capacity
cold_air.temperature = cold_air.temperature + heat / cold_air_heat_capacity
hot_air.set_temperature(hot_air.temperature() - energy_transfer / hot_air_heat_capacity)
cold_air.set_temperature(cold_air.temperature() + heat / cold_air_heat_capacity)
//log_debug("POWER: [lastgen] W generated at [efficiency * 100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]")
@@ -221,10 +221,10 @@
data["hot_dir"] = dir2text(hot_dir)
data["output_power"] = round(lastgen)
// Temps are K, pressures are kPa, power is W
data["cold_inlet_temp"] = round(cold_circ_air2.temperature, 0.1)
data["hot_inlet_temp"] = round(hot_circ_air2.temperature, 0.1)
data["cold_outlet_temp"] = round(cold_circ_air1.temperature, 0.1)
data["hot_outlet_temp"] = round(hot_circ_air1.temperature, 0.1)
data["cold_inlet_temp"] = round(cold_circ_air2.temperature(), 0.1)
data["hot_inlet_temp"] = round(hot_circ_air2.temperature(), 0.1)
data["cold_outlet_temp"] = round(cold_circ_air1.temperature(), 0.1)
data["hot_outlet_temp"] = round(hot_circ_air1.temperature(), 0.1)
data["cold_delta_temp"] = data["cold_outlet_temp"] - data["cold_inlet_temp"]
data["cold_inlet_pressure"] = round(cold_circ_air2.return_pressure(), 0.1)
data["hot_inlet_pressure"] = round(hot_circ_air2.return_pressure(), 0.1)
+58 -53
View File
@@ -167,7 +167,7 @@
M.set_multitool_buffer(user, src)
/obj/machinery/power/compressor/CanAtmosPass(turf/T)
/obj/machinery/power/compressor/CanAtmosPass(direction)
return !density
/obj/machinery/power/compressor/proc/trigger_overheat()
@@ -181,46 +181,46 @@
return max(last_overheat + OVERHEAT_TIME - world.time, 0)
/obj/machinery/power/compressor/process()
if(!turbine)
stat = BROKEN
if(stat & BROKEN || panel_open)
var/datum/milla_safe/compressor_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/compressor_process
/datum/milla_safe/compressor_process/on_run(obj/machinery/power/compressor/compressor)
if(!compressor.turbine)
compressor.stat = BROKEN
if(compressor.stat & BROKEN || compressor.panel_open)
return
if(!starter)
if(!compressor.starter)
return
if(rpm_threshold == OVERDRIVE)
//UI update here
overheat += 2
if(overheat >= OVERHEAT_THRESHOLD)
trigger_overheat()
else if(overheat > 0)
overheat -= 2
rpm = 0.9* rpm + 0.1 * rpmtarget
var/datum/gas_mixture/environment = inturf.return_air()
// It's a simplified version taking only 1/10 of the moles from the turf nearby. It should be later changed into a better version
//2023 note: It works, im not touc
if(compressor.rpm_threshold == OVERDRIVE)
compressor.overheat += 2
if(compressor.overheat >= OVERHEAT_THRESHOLD)
compressor.trigger_overheat()
else if(compressor.overheat > 0)
compressor.overheat -= 2
compressor.rpm = 0.9 * compressor.rpm + 0.1 * compressor.rpmtarget
var/datum/gas_mixture/environment = get_turf_air(compressor.inturf)
var/transfer_moles = environment.total_moles()/10
//var/transfer_moles = rpm/10000*capacity
var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles)
gas_contained.merge(removed)
var/datum/gas_mixture/removed = environment.remove(transfer_moles)
compressor.gas_contained.merge(removed)
// RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy
rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION*efficiency))
compressor.rpm = max(0, compressor.rpm - (compressor.rpm*compressor.rpm)/(COMPFRICTION*compressor.efficiency))
if(starter && !(stat & NOPOWER))
use_power(2800)
if(rpm<1000)
rpmtarget = 1000
if(!(compressor.stat & NOPOWER))
compressor.use_power(2800)
if(compressor.rpm < 1000)
compressor.rpmtarget = 1000
else
if(rpm<1000)
rpmtarget = 0
if(compressor.rpm < 1000)
compressor.rpmtarget = 0
var/new_rpm_threshold
switch(rpm)
switch(compressor.rpm)
if(50001 to INFINITY)
new_rpm_threshold = OVERDRIVE
if(10001 to 50000)
@@ -232,9 +232,9 @@
else
new_rpm_threshold = NONE
if(rpm_threshold != new_rpm_threshold)
rpm_threshold = new_rpm_threshold
update_icon(UPDATE_OVERLAYS)
if(compressor.rpm_threshold != new_rpm_threshold)
compressor.rpm_threshold = new_rpm_threshold
compressor.update_icon(UPDATE_OVERLAYS)
/obj/machinery/power/compressor/update_overlays()
. = ..()
@@ -286,44 +286,49 @@
return !density
/obj/machinery/power/turbine/process()
var/datum/milla_safe/turbine_process/milla = new()
milla.invoke_async(src)
if(!compressor)
stat = BROKEN
/datum/milla_safe/turbine_process
if((stat & BROKEN) || panel_open)
/datum/milla_safe/turbine_process/on_run(obj/machinery/power/turbine/turbine)
if(!turbine.compressor)
turbine.stat = BROKEN
if((turbine.stat & BROKEN) || turbine.panel_open)
return
if(!compressor.starter)
if(!turbine.compressor.starter)
return
// This is the power generation function. If anything is needed it's good to plot it in EXCEL before modifying
// the TURBPOWER and TURBCURVESHAPE values
if(compressor.gas_contained.temperature < 500)
lastgen = 0
if(turbine.compressor.gas_contained.temperature() < 500)
turbine.lastgen = 0
else
lastgen = ((compressor.rpm / TURBPOWER) ** TURBCURVESHAPE) * TURBPOWER * productivity * POWER_CURVE_MOD
turbine.lastgen = ((turbine.compressor.rpm / TURBPOWER) ** TURBCURVESHAPE) * TURBPOWER * turbine.productivity * POWER_CURVE_MOD
produce_direct_power(lastgen)
turbine.produce_direct_power(turbine.lastgen)
// Weird function but it works. Should be something else...
var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4
var/newrpm = ((turbine.compressor.gas_contained.temperature()) * turbine.compressor.gas_contained.total_moles()) / 4
newrpm = max(0, newrpm)
if(!compressor.starter || newrpm > 1000)
compressor.rpmtarget = newrpm
if(!turbine.compressor.starter || newrpm > 1000)
turbine.compressor.rpmtarget = newrpm
if(compressor.gas_contained.total_moles()>0)
var/oamount = min(compressor.gas_contained.total_moles(), (compressor.rpm+100)/35000*compressor.capacity)
var/datum/gas_mixture/removed = compressor.gas_contained.remove(oamount)
outturf.assume_air(removed)
if(turbine.compressor.gas_contained.total_moles()>0)
var/oamount = min(turbine.compressor.gas_contained.total_moles(), (turbine.compressor.rpm + 100) / 35000 * turbine.compressor.capacity)
var/datum/gas_mixture/removed = turbine.compressor.gas_contained.remove(oamount)
turbine.outturf.blind_release_air(removed)
if((lastgen > 100) != generator_threshold)
generator_threshold = !generator_threshold
update_icon(UPDATE_OVERLAYS)
if((turbine.lastgen > 100) != turbine.generator_threshold)
turbine.generator_threshold = !turbine.generator_threshold
turbine.update_icon(UPDATE_OVERLAYS)
updateDialog()
turbine.updateDialog()
/obj/machinery/power/turbine/update_overlays()
. = ..()
@@ -378,7 +383,7 @@
data["online"] = compressor.starter
data["power"] = compressor.turbine.lastgen
data["rpm"] = compressor.rpm
data["temperature"] = compressor.gas_contained.return_temperature()
data["temperature"] = compressor.gas_contained.temperature()
return data
/obj/machinery/power/turbine/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
@@ -446,7 +451,7 @@
data["online"] = compressor.starter
data["power"] = compressor.turbine.lastgen
data["rpm"] = compressor.rpm
data["temperature"] = compressor.gas_contained.return_temperature()
data["temperature"] = compressor.gas_contained.temperature()
data["bearing_heat"] = clamp((compressor.overheat / OVERHEAT_THRESHOLD) * 100, 0, 100)
return data
@@ -11,17 +11,15 @@
return
var/list/map = mother.map
for(var/turf/simulated/T in map)
SSair.remove_from_active(T)
for(var/turf/simulated/T in map)
if(T.air)
T.air.oxygen = T.oxygen
T.air.nitrogen = T.nitrogen
T.air.carbon_dioxide = T.carbon_dioxide
T.air.toxins = T.toxins
T.air.sleeping_agent = T.sleeping_agent
T.air.agent_b = T.agent_b
T.air.temperature = T.temperature
SSair.add_to_active(T)
var/datum/gas_mixture/air = new()
air.set_oxygen(T.oxygen)
air.set_nitrogen(T.nitrogen)
air.set_carbon_dioxide(T.carbon_dioxide)
air.set_toxins(T.toxins)
air.set_sleeping_agent(T.sleeping_agent)
air.set_agent_b(T.agent_b)
air.set_temperature(T.temperature)
T.blind_set_air(air)
//Only places atoms/turfs on area borders
/datum/mapGeneratorModule/border
@@ -588,7 +588,11 @@
visible_message("<span class='danger'>[src] vents heated plasma!</span>")
var/turf/simulated/T = get_turf(src)
if(istype(T))
T.atmos_spawn_air(LINDA_SPAWN_HEAT | LINDA_SPAWN_TOXINS|LINDA_SPAWN_20C, 20)
var/datum/gas_mixture/air = new()
air.set_temperature(1000)
air.set_toxins(20)
air.set_oxygen(20)
T.blind_release_air(air)
#undef PLASMA_CHARGE_USE_PER_SECOND
#undef PLASMA_DISCHARGE_LIMIT
@@ -98,7 +98,9 @@
..()
var/turf/location = get_turf(src)
if(location)
new /obj/effect/hotspot(location)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(location)
hotspot.temperature = 1000
hotspot.recolor()
location.hotspot_expose(700, 50, 1)
//magazines//
@@ -164,7 +164,9 @@
..()
var/turf/location = get_turf(src)
if(location)
new /obj/effect/hotspot(location)
var/obj/effect/hotspot/hotspot = new /obj/effect/hotspot/fake(location)
hotspot.temperature = 1000
hotspot.recolor()
location.hotspot_expose(700, 50, 1)
/obj/item/projectile/bullet/incendiary/shell/dragonsbreath
+1 -1
View File
@@ -463,7 +463,7 @@
return TRUE
/obj/item/projectile/experience_pressure_difference()
return
return // Immune to gas flow.
/obj/item/projectile/forceMove(atom/target)
. = ..()
@@ -384,13 +384,7 @@
return
if(volume >= 3)
T.MakeSlippery()
var/hotspot = (locate(/obj/effect/hotspot) in T)
if(hotspot)
var/datum/gas_mixture/lowertemp = T.remove_air( T.air.total_moles())
lowertemp.temperature = max(min(lowertemp.temperature-2000, lowertemp.temperature / 2), 0)
lowertemp.react()
T.assume_air(lowertemp)
qdel(hotspot)
T.quench(1000, 2)
/datum/reagent/consumable/enzyme
name = "Universal Enzyme"
@@ -424,15 +424,8 @@
/datum/reagent/firefighting_foam/reaction_turf(turf/simulated/T, volume)
if(!istype(T))
return
var/CT = cooling_temperature
new /obj/effect/decal/cleanable/flour/foam(T) //foam mess; clears up quickly.
var/hotspot = (locate(/obj/effect/hotspot) in T)
if(hotspot)
var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles())
lowertemp.temperature = max(min(lowertemp.temperature-(CT*1000), lowertemp.temperature / CT), 0)
lowertemp.react()
T.assume_air(lowertemp)
qdel(hotspot)
T.quench(1000, cooling_temperature)
/datum/reagent/plasma_dust
name = "Plasma Dust"
@@ -338,7 +338,10 @@
if(holder && holder.my_atom)
var/turf/simulated/T = get_turf(holder.my_atom)
if(istype(T))
T.atmos_spawn_air(LINDA_SPAWN_HEAT | LINDA_SPAWN_TOXINS, 50)
var/datum/gas_mixture/air = new()
air.set_temperature(1000)
air.set_toxins(20)
T.blind_release_air(air)
//Yellow
+28 -29
View File
@@ -77,15 +77,32 @@
/obj/machinery/disposal/Initialize(mapload)
// this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
. = ..()
var/atom/L = loc
var/datum/gas_mixture/env = new
env.copy_from(L.return_air())
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
air_contents = new
air_contents.merge(removed)
air_contents = new()
var/datum/milla_safe/disposal_suck_air/milla = new()
milla.invoke_async(src)
trunk_check()
update()
/datum/milla_safe/disposal_suck_air
/datum/milla_safe/disposal_suck_air/on_run(obj/machinery/disposal/disposal)
var/turf/T = get_turf(disposal)
var/datum/gas_mixture/env = get_turf_air(T)
var/pressure_delta = (SEND_PRESSURE + 1) - disposal.air_contents.return_pressure()
if(env.temperature() > 0)
var/transfer_moles = 0.1 * pressure_delta*disposal.air_contents.volume / (env.temperature() * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = env.remove(transfer_moles)
disposal.air_contents.merge(removed)
// if full enough, switch to ready mode
if(disposal.air_contents.return_pressure() >= SEND_PRESSURE)
disposal.mode = 2
disposal.update()
// attack by item places it in to disposal
/obj/machinery/disposal/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN || !user || I.flags & ABSTRACT)
@@ -425,25 +442,9 @@
// otherwise charge
change_power_mode(ACTIVE_POWER_USE)
var/atom/L = loc // recharging from loc turf
var/datum/milla_safe/disposal_suck_air/milla = new()
milla.invoke_async(src)
var/datum/gas_mixture/env = L.return_air()
var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure()
if(env.temperature > 0)
var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = env.remove(transfer_moles)
air_contents.merge(removed)
air_update_turf()
// if full enough, switch to ready mode
if(air_contents.return_pressure() >= SEND_PRESSURE)
mode = 2
update()
return
// perform a flush
/obj/machinery/disposal/proc/flush()
@@ -714,11 +715,9 @@
playsound(loc, 'sound/effects/clang.ogg', 50, 0, 0)
// called to vent all gas in holder to a location
/obj/structure/disposalholder/proc/vent_gas(atom/location)
if(location)
location.assume_air(gas) // vent all gas to turf
air_update_turf()
return
/obj/structure/disposalholder/proc/vent_gas(turf/location)
if(istype(location))
location.blind_release_air(gas)
// Disposal pipes
+19 -20
View File
@@ -367,16 +367,8 @@
ejectItem(TRUE)
if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
visible_message("<span class='warning'>[src] malfunctions, melting [exp_on] and leaking hot air!</span>")
var/datum/gas_mixture/env = loc.return_air()
var/transfer_moles = 0.25 * env.total_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
var/heat_capacity = removed.heat_capacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = min((removed.temperature*heat_capacity + 100000)/heat_capacity, 1000)
env.merge(removed)
air_update_turf()
var/datum/milla_safe/experimentor_temperature/milla = new()
milla.invoke_async(src, 100000, 1000)
investigate_log("Experimentor has released hot air.", "experimentor")
ejectItem(TRUE)
if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
@@ -413,16 +405,8 @@
ejectItem(TRUE)
if(prob(EFFECT_PROB_LOW-badThingCoeff))
visible_message("<span class='warning'>[src] malfunctions, shattering [exp_on] and leaking cold air!</span>")
var/datum/gas_mixture/env = loc.return_air()
var/transfer_moles = 0.25 * env.total_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
var/heat_capacity = removed.heat_capacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = (removed.temperature*heat_capacity - 75000)/heat_capacity
env.merge(removed)
air_update_turf()
var/datum/milla_safe/experimentor_temperature/milla = new()
milla.invoke_async(src, -75000, 1000, TCMB)
investigate_log("Experimentor has released cold air.", "experimentor")
ejectItem(TRUE)
if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
@@ -529,6 +513,21 @@
icon_state = "h_lathe"
recentlyExperimented = 0
/datum/milla_safe/experimentor_temperature
/datum/milla_safe/experimentor_temperature/on_run(obj/machinery/r_n_d/experimentor/experimentor, delta, min_new_temp)
var/turf/T = get_turf(experimentor)
var/datum/gas_mixture/env = get_turf_air(T)
var/transfer_moles = 0.25 * env.total_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
var/heat_capacity = removed.heat_capacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.set_temperature(max(min_new_temp, (removed.temperature() * heat_capacity + delta) / heat_capacity))
env.merge(removed)
/obj/machinery/r_n_d/experimentor/Topic(href, href_list)
if(..())
return
+25 -18
View File
@@ -74,8 +74,9 @@
if(prob(3) && plays_sound)
playsound(loc, "computer_ambience", 10, TRUE, ignore_walls = FALSE)
var/datum/gas_mixture/environment = loc.return_air()
switch(environment.temperature)
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.get_readonly_air()
switch(environment.temperature())
if(0 to T0C)
health = min(100, health + 1)
if(T0C to (T20C + 20))
@@ -88,11 +89,11 @@
var/updateRD = 0
files.known_designs = list()
for(var/v in files.known_tech)
var/datum/tech/T = files.known_tech[v]
var/datum/tech/tech = files.known_tech[v]
// Slowly decrease research if health drops below 0
if(prob(1))
updateRD++
T.level--
tech.level--
if(updateRD)
files.RefreshResearch()
if(delay)
@@ -120,25 +121,31 @@
files.push_data(C.files)
/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt)
if(!(stat & (NOPOWER|BROKEN))) // Blatantly stolen from space heater.
var/turf/simulated/L = loc
if(istype(L))
var/datum/gas_mixture/env = L.return_air()
if(env.temperature < (heat_amt+T0C))
var/datum/milla_safe/rnd_server_heat/milla = new()
milla.invoke_async(src, heat_amt)
var/transfer_moles = 0.25 * env.total_moles()
/datum/milla_safe/rnd_server_heat
var/datum/gas_mixture/removed = env.remove(transfer_moles)
/datum/milla_safe/rnd_server_heat/on_run(obj/machinery/r_n_d/server/server, heat)
var/turf/T = get_turf(server)
var/datum/gas_mixture/env = get_turf_air(T)
if(removed)
if(server.stat & (NOPOWER|BROKEN))
return
if(env.temperature() >= (heat + T0C))
return
var/heat_capacity = removed.heat_capacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000)
var/transfer_moles = 0.25 * env.total_moles()
env.merge(removed)
air_update_turf()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(!removed)
return
var/heat_capacity = removed.heat_capacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.set_temperature(min((removed.temperature() * heat_capacity + server.heating_power) / heat_capacity, 1000))
env.merge(removed)
/obj/machinery/r_n_d/server/attackby(obj/item/O as obj, mob/user as mob, params)
if(exchange_parts(user, O))
+38 -29
View File
@@ -448,7 +448,23 @@
if(!canMove())
return -1
var/obj/docking_port/stationary/S0 = get_docked()
var/datum/milla_safe/docking_port_dock/milla = new()
milla.invoke_async(src, S1, force, transit)
/datum/milla_safe/docking_port_dock
/datum/milla_safe/docking_port_dock/on_run(obj/docking_port/mobile/mobile_port, obj/docking_port/stationary/S1, force, transit)
// Re-check that it's OK to dock.
if(S1.get_docked() == mobile_port)
mobile_port.remove_ripples()
return
if(!force)
if(!mobile_port.check_dock(S1))
return
if(!mobile_port.canMove())
return
var/obj/docking_port/stationary/S0 = mobile_port.get_docked()
var/turf_type = /turf/space
var/area_type = /area/space
if(S0)
@@ -458,18 +474,18 @@
area_type = S0.area_type
//close and lock the dock's airlocks
closePortDoors(S0)
mobile_port.closePortDoors(S0)
var/list/L0 = return_ordered_turfs(x, y, z, dir, areaInstance)
var/list/L1 = return_ordered_turfs(S1.x, S1.y, S1.z, S1.dir)
var/list/L0 = mobile_port.return_ordered_turfs(mobile_port.x, mobile_port.y, mobile_port.z, mobile_port.dir, mobile_port.areaInstance)
var/list/L1 = mobile_port.return_ordered_turfs(S1.x, S1.y, S1.z, S1.dir)
var/rotation = dir2angle(S1.dir)-dir2angle(dir)
var/rotation = dir2angle(S1.dir) - dir2angle(mobile_port.dir)
if((rotation % 90) != 0)
rotation += (rotation % 90) //diagonal rotations not allowed, round up
rotation = SIMPLIFY_DEGREES(rotation)
//remove area surrounding docking port
if(length(areaInstance.contents))
if(length(mobile_port.areaInstance.contents))
var/area/A0 = locate("[area_type]")
if(!A0)
A0 = new area_type(null)
@@ -477,10 +493,10 @@
A0.contents += T0
// Removes ripples
remove_ripples()
mobile_port.remove_ripples()
//move or squish anything in the way ship at destination
if(lance_docking && is_station_level(S1.z))
if(mobile_port.lance_docking && is_station_level(S1.z))
var/list/L2 = list()
switch(S1.dir)
if(NORTH)
@@ -491,8 +507,8 @@
L2 = block(locate(S1.x+36, S1.y-9, S1.z), locate(255, S1.y+9, S1.z))
if(WEST)
L2 = block(locate(1, S1.y-9, S1.z), locate(S1.x-36, S1.y+9, S1.z))
shuttle_smash(L2, S1)
roadkill(L0, L1, S1.dir)
mobile_port.shuttle_smash(L2, S1)
mobile_port.roadkill(L0, L1, S1.dir)
for(var/i in 1 to length(L0))
var/turf/T0 = L0[i]
@@ -502,61 +518,54 @@
if(!T1)
continue
areaInstance.contents += T1
mobile_port.areaInstance.contents += T1
var/should_transit = !is_turf_blacklisted_for_transit(T0)
var/should_transit = !mobile_port.is_turf_blacklisted_for_transit(T0)
if(should_transit) // Only move over stuff if the transfer actually happened
T0.copyTurf(T1)
//copy over air
if(issimulatedturf(T1))
var/turf/simulated/Ts1 = T1
Ts1.copy_air_with_tile(T0)
get_turf_air(T1).copy_from(get_turf_air(T0))
//move mobile to new location
for(var/atom/movable/AM in T0)
if(AM.loc != T0) //fix for multi-tile objects
continue
AM.onShuttleMove(T0, T1, rotation, last_caller)
AM.onShuttleMove(T0, T1, rotation, mobile_port.last_caller)
if(rotation)
T1.shuttleRotate(rotation)
// Always do this stuff as it ensures that the destination turfs still behave properly with the rest of the shuttle transit
//atmos and lighting stuff
SSair.remove_from_active(T1)
T1.CalculateAdjacentTurfs()
SSair.add_to_active(T1,1)
//lighting stuff
T1.lighting_build_overlay()
T1.recalculate_atmos_connectivity()
if(!should_transit)
continue // Don't want to actually change the skipped turf
T0.ChangeTurf(turf_type, keep_icon = FALSE)
T0.recalculate_atmos_connectivity()
SSair.remove_from_active(T0)
T0.CalculateAdjacentTurfs()
SSair.add_to_active(T0,1)
areaInstance.moving = transit
mobile_port.areaInstance.moving = transit
for(var/A1 in L1)
var/turf/T1 = A1
T1.postDock(S1)
for(var/atom/movable/M in T1)
M.postDock(S1)
loc = S1.loc
dir = S1.dir
mobile_port.loc = S1.loc
mobile_port.dir = S1.dir
//update mining and labor shuttle ash storm audio
if(id in list("mining", "laborcamp"))
if(mobile_port.id in list("mining", "laborcamp"))
var/mining_zlevel = level_name_to_num(MINING)
var/datum/weather/ash_storm/W = SSweather.get_weather(mining_zlevel, /area/lavaland/surface/outdoors)
if(W)
W.update_eligible_areas()
W.update_audio()
unlockPortDoors(S1)
mobile_port.unlockPortDoors(S1)
/obj/docking_port/mobile/proc/is_turf_blacklisted_for_transit(turf/T)
var/static/list/blacklisted_turf_types = typecacheof(list(/turf/space, /turf/simulated/floor/chasm, /turf/simulated/floor/lava, /turf/simulated/floor/plating/asteroid))
@@ -29,6 +29,7 @@ GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new())
var/list/attributes = features["attributes"]
attributes = attributes.Copy() // Clone the list so it can't be changed on accident
milla_init_z(k)
var/datum/space_level/S = new /datum/space_level(k, name, transition_type = linking, traits = attributes)
z_list["[k]"] = S
levels_by_name[name] = S
@@ -37,6 +38,7 @@ GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new())
// Then, we take care of unmanaged z levels
// They get the default linkage of SELFLOOPING
for(var/i = k, i <= world.maxz, i++)
milla_init_z(k)
z_list["[i]"] = new /datum/space_level(i)
initialized = 1
@@ -112,6 +114,7 @@ GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new())
throw EXCEPTION("Name already in use: [name]")
world.maxz++
var/our_z = world.maxz
milla_init_z(our_z)
var/datum/space_level/S = new /datum/space_level(our_z, name, transition_type = linkage, traits = traits)
levels_by_name[name] = S
z_list["[our_z]"] = S
@@ -81,11 +81,11 @@
var/gas_breathed = 0
//Partial pressures in our breath
var/O2_pp = breath.get_breath_partial_pressure(breath.oxygen)
var/N2_pp = breath.get_breath_partial_pressure(breath.nitrogen)
var/Toxins_pp = breath.get_breath_partial_pressure(breath.toxins)
var/CO2_pp = breath.get_breath_partial_pressure(breath.carbon_dioxide)
var/SA_pp = breath.get_breath_partial_pressure(breath.sleeping_agent)
var/O2_pp = breath.get_breath_partial_pressure(breath.oxygen())
var/N2_pp = breath.get_breath_partial_pressure(breath.nitrogen())
var/Toxins_pp = breath.get_breath_partial_pressure(breath.toxins())
var/CO2_pp = breath.get_breath_partial_pressure(breath.carbon_dioxide())
var/SA_pp = breath.get_breath_partial_pressure(breath.sleeping_agent())
//-- OXY --//
@@ -93,7 +93,7 @@
//Too much oxygen! //Yes, some species may not like it.
if(safe_oxygen_max)
if(O2_pp > safe_oxygen_max)
var/ratio = (breath.oxygen / safe_oxygen_max / safe_oxygen_max) * 10
var/ratio = (breath.oxygen() / safe_oxygen_max / safe_oxygen_max) * 10
H.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type)
H.throw_alert("too_much_oxy", /atom/movable/screen/alert/too_much_oxy)
else
@@ -102,16 +102,16 @@
//Too little oxygen!
if(safe_oxygen_min)
if(O2_pp < safe_oxygen_min)
gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath.oxygen)
gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath.oxygen())
H.throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
else
H.adjustOxyLoss(-HUMAN_MAX_OXYLOSS)
gas_breathed = breath.oxygen
gas_breathed = breath.oxygen()
H.clear_alert("not_enough_oxy")
//Exhale
breath.oxygen -= gas_breathed
breath.carbon_dioxide += gas_breathed
breath.set_oxygen(breath.oxygen() - gas_breathed)
breath.set_carbon_dioxide(breath.carbon_dioxide() + gas_breathed)
gas_breathed = 0
//-- Nitrogen --//
@@ -119,7 +119,7 @@
//Too much nitrogen!
if(safe_nitro_max)
if(N2_pp > safe_nitro_max)
var/ratio = (breath.nitrogen / safe_nitro_max) * 10
var/ratio = (breath.nitrogen() / safe_nitro_max) * 10
H.apply_damage_type(clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type)
H.throw_alert("too_much_nitro", /atom/movable/screen/alert/too_much_nitro)
else
@@ -128,16 +128,16 @@
//Too little nitrogen!
if(safe_nitro_min)
if(N2_pp < safe_nitro_min)
gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.nitrogen)
gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.nitrogen())
H.throw_alert("not_enough_nitro", /atom/movable/screen/alert/not_enough_nitro)
else
H.adjustOxyLoss(-HUMAN_MAX_OXYLOSS)
gas_breathed = breath.nitrogen
gas_breathed = breath.nitrogen()
H.clear_alert("not_enough_nitro")
//Exhale
breath.nitrogen -= gas_breathed
breath.carbon_dioxide += gas_breathed
breath.set_nitrogen(breath.nitrogen() - gas_breathed)
breath.set_carbon_dioxide(breath.carbon_dioxide() + gas_breathed)
gas_breathed = 0
//-- CO2 --//
@@ -163,16 +163,16 @@
//Too little CO2!
if(safe_co2_min)
if(CO2_pp < safe_co2_min)
gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath.carbon_dioxide)
gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath.carbon_dioxide())
H.throw_alert("not_enough_co2", /atom/movable/screen/alert/not_enough_co2)
else
H.adjustOxyLoss(-HUMAN_MAX_OXYLOSS)
gas_breathed = breath.carbon_dioxide
gas_breathed = breath.carbon_dioxide()
H.clear_alert("not_enough_co2")
//Exhale
breath.carbon_dioxide -= gas_breathed
breath.oxygen += gas_breathed
breath.set_carbon_dioxide(breath.carbon_dioxide() - gas_breathed)
breath.set_oxygen(breath.oxygen() + gas_breathed)
gas_breathed = 0
@@ -181,7 +181,7 @@
//Too much toxins!
if(safe_toxins_max)
if(Toxins_pp > safe_toxins_max)
var/ratio = (breath.toxins / safe_toxins_max) * 10
var/ratio = (breath.toxins() / safe_toxins_max) * 10
H.apply_damage_type(clamp(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type)
H.throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox)
else
@@ -191,22 +191,22 @@
//Too little toxins!
if(safe_toxins_min)
if(Toxins_pp < safe_toxins_min)
gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath.toxins)
gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath.toxins())
H.throw_alert("not_enough_tox", /atom/movable/screen/alert/not_enough_tox)
else
H.adjustOxyLoss(-HUMAN_MAX_OXYLOSS)
gas_breathed = breath.toxins
gas_breathed = breath.toxins()
H.clear_alert("not_enough_tox")
//Exhale
breath.toxins -= gas_breathed
breath.carbon_dioxide += gas_breathed
breath.set_toxins(breath.toxins() - gas_breathed)
breath.set_carbon_dioxide(breath.carbon_dioxide() + gas_breathed)
gas_breathed = 0
//-- TRACES --//
if(breath.sleeping_agent) // If there's some other shit in the air lets deal with it here.
if(breath.sleeping_agent()) // If there's some other shit in the air lets deal with it here.
if(SA_pp > SA_para_min)
H.Paralyse(6 SECONDS) // 6 seconds gives them one second to wake up and run away a bit!
if(SA_pp > SA_sleep_min) // Enough to make us sleep as well
@@ -236,7 +236,7 @@
/datum/organ/lungs/proc/handle_breath_temperature(datum/gas_mixture/breath, mob/living/carbon/human/H) // called by human/life, handles temperatures
var/breath_temperature = breath.temperature
var/breath_temperature = breath.temperature()
if(!HAS_TRAIT(H, TRAIT_RESISTCOLD)) // COLD DAMAGE
var/CM = abs(H.dna.species.coldmod)
@@ -2,15 +2,20 @@
var/mob/living/simple_animal/slime = null
var/obj/machinery/vent = null
var/obj/structure/table/table = null
var/setup_complete = FALSE
/datum/unit_test/ventcrawl/proc/setup_test_area()
/datum/milla_safe/ventcrawl_test_setup
/datum/milla_safe/ventcrawl_test_setup/on_run(datum/unit_test/ventcrawl/test)
// This setup creates turfs that initialize themselves in MILLA on creation, which is why we need to be MILLA-safe.
var/datum/map_template/template = GLOB.map_templates["test_ventcrawl.dmm"]
if(!template.load(run_loc_bottom_left))
Fail("Failed to load 'test_ventcrawl.dmm'")
if(!template.load(test.run_loc_bottom_left))
test.Fail("Failed to load 'test_ventcrawl.dmm'")
slime = new /mob/living/simple_animal/slime/unit_test_dummy(run_loc_bottom_left)
vent = find_spawned_test_object(run_loc_bottom_left, /obj/machinery/atmospherics/unary/vent_pump)
table = find_spawned_test_object(get_step(run_loc_bottom_left, EAST), /obj/structure/table)
test.slime = new /mob/living/simple_animal/slime/unit_test_dummy(test.run_loc_bottom_left)
test.vent = test.find_spawned_test_object(test.run_loc_bottom_left, /obj/machinery/atmospherics/unary/vent_pump)
test.table = test.find_spawned_test_object(get_step(test.run_loc_bottom_left, EAST), /obj/structure/table)
test.setup_complete = TRUE
/datum/unit_test/ventcrawl/proc/find_spawned_test_object(turf/location as turf, test_object_type)
for(var/content in location.contents)
@@ -19,7 +24,10 @@
Fail("Couldn't find spawned test object of type: [test_object_type].")
/datum/unit_test/ventcrawl/Run()
setup_test_area()
var/datum/milla_safe/ventcrawl_test_setup/milla = new()
milla.invoke_async(src)
while(!setup_complete)
sleep(world.tick_lag)
// Enter vent
vent.AltClick(slime)