From 9b7b4ae6565f514eef90a58707fe24c6d857c048 Mon Sep 17 00:00:00 2001 From: Tigercat2000 Date: Tue, 28 Apr 2015 11:57:44 -0700 Subject: [PATCH] Apply most/all of LINDA's updates This commit ports most, if not all of LINDA's updates on -tg-, and fixes a few bugs that appear to be unique to paradise's codebase. --- code/FEA/FEA_gas_mixture.dm | 33 +- code/LINDA/LINDA_fire.dm | 10 +- code/LINDA/LINDA_system.dm | 95 +- code/LINDA/LINDA_turf_tile.dm | 36 +- code/datums/gas_mixture.dm | 961 ++++++++++++++++++ code/game/machinery/doors/airlock.dm | 2 +- code/game/machinery/doors/door.dm | 4 +- code/game/machinery/shieldgen.dm | 4 +- code/game/objects/effects/aliens.dm | 2 + code/game/objects/effects/anomalies.dm | 5 +- code/game/objects/effects/effect_system.dm | 4 +- code/game/objects/effects/mines.dm | 4 +- code/game/objects/structures/mineral_doors.dm | 6 +- .../objects/structures/windoor_assembly.dm | 4 +- code/game/objects/structures/window.dm | 4 +- code/game/turfs/simulated.dm | 3 + code/game/turfs/simulated/floor.dm | 2 +- code/game/turfs/simulated/walls_mineral.dm | 2 +- code/modules/assembly/bomb.dm | 4 +- code/modules/reagents/Chemistry-Recipes.dm | 4 +- paradise.dme | 2 +- 21 files changed, 1112 insertions(+), 79 deletions(-) create mode 100644 code/datums/gas_mixture.dm diff --git a/code/FEA/FEA_gas_mixture.dm b/code/FEA/FEA_gas_mixture.dm index e3f0d62e8f6..a9538fba883 100644 --- a/code/FEA/FEA_gas_mixture.dm +++ b/code/FEA/FEA_gas_mixture.dm @@ -512,11 +512,11 @@ What are the archived variables for? return 1 - check_turf(turf/model) - var/delta_oxygen = (oxygen_archived - model.oxygen)/5 - var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/5 - var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/5 - var/delta_toxins = (toxins_archived - model.toxins)/5 + check_turf(turf/model, atmos_adjacent_turfs = 4) + 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_temperature = (temperature_archived - model.temperature) @@ -535,6 +535,29 @@ What are the archived variables for? return 1 + proc/check_turf_total(turf/model) + 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_temperature = (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))) + return 0 + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND*4) + return 0 + + return 1 + share(datum/gas_mixture/sharer, var/atmos_adjacent_turfs = 4) if(!sharer) return 0 var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/(atmos_adjacent_turfs+1) diff --git a/code/LINDA/LINDA_fire.dm b/code/LINDA/LINDA_fire.dm index 318239ec94f..0f173f97fda 100644 --- a/code/LINDA/LINDA_fire.dm +++ b/code/LINDA/LINDA_fire.dm @@ -60,7 +60,7 @@ /obj/effect/hotspot/proc/perform_exposure() var/turf/simulated/floor/location = loc - if(!istype(location)) return 0 + if(!istype(location) || !(location.air)) return 0 if(volume > CELL_VOLUME*0.95) bypassing = 1 else bypassing = 0 @@ -95,13 +95,13 @@ return if(location.excited_group) - location.excited_group.breakdown = 0 + location.excited_group.reset_cooldowns() if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1)) Kill() return - if(location.air.toxins < 0.5 || location.air.oxygen < 0.5) + if((!(location.air) || location.air.toxins < 0.5 || location.air.oxygen < 0.5)) Kill() return @@ -144,9 +144,9 @@ /obj/effect/hotspot/proc/Kill() air_master.hotspots -= src DestroyTurf() - garbage_collect() + qdel(src) -/obj/effect/hotspot/proc/garbage_collect() +/obj/effect/hotspot/Destroy() if(istype(loc, /turf/simulated)) var/turf/simulated/T = loc if(T.active_hotspot == src) diff --git a/code/LINDA/LINDA_system.dm b/code/LINDA/LINDA_system.dm index 2fe76785781..faa86e46754 100644 --- a/code/LINDA/LINDA_system.dm +++ b/code/LINDA/LINDA_system.dm @@ -27,6 +27,8 @@ datum/controller/air_system setup_allturfs() + setup_overlays() + world << "\red \b Geometry processed in [(world.timeofday-start_time)/10] seconds!" /datum/controller/air_system/proc/process() @@ -99,25 +101,31 @@ datum/controller/air_system active_turfs |= T break else - if(!T.air.check_turf(enemy_tile)) + if(!T.air.check_turf_total(enemy_tile)) T.excited = 1 active_turfs |= T /datum/controller/air_system/proc/process_excited_groups() for(var/datum/excited_group/EG in excited_groups) - if(EG.breakdown) - EG.breakdown_cooldown ++ - else - EG.breakdown_cooldown = 0 - - if(EG.breakdown_cooldown > 10) - if(EG.self_compare()) - EG.dismantle() + EG.breakdown_cooldown ++ if(EG.breakdown_cooldown == 10) - if(!EG.self_compare()) - EG.reset_cooldowns() EG.self_breakdown() - EG.breakdown = 1 + return + if(EG.breakdown_cooldown > 20) + EG.dismantle() + +/datum/controller/air_system/proc/setup_overlays() + plmaster = new /obj/effect/overlay() + plmaster.icon = 'icons/effects/tile_effects.dmi' + plmaster.icon_state = "plasma" + plmaster.layer = FLY_LAYER + plmaster.mouse_opacity = 0 + + slmaster = new /obj/effect/overlay() + slmaster.icon = 'icons/effects/tile_effects.dmi' + slmaster.icon_state = "sleeping_agent" + slmaster.layer = FLY_LAYER + slmaster.mouse_opacity = 0 /turf/proc/CanAtmosPass(var/turf/T) if(!istype(T)) return 0 @@ -201,12 +209,21 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0) T.atmos_adjacent_turfs &= ~counterdir /atom/movable/proc/air_update_turf(var/command = 0) - if(istype(loc,/turf)) - var/turf/T = loc - if(command) - T.CalculateAdjacentTurfs() - if(air_master) - air_master.add_to_active(T,command) + if(!istype(loc,/turf) && 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(var/command = 0) + if(command) + CalculateAdjacentTurfs() + if(air_master) + air_master.add_to_active(src,command) + +/atom/movable/proc/move_update_air(var/turf/T) + if(istype(T,/turf)) + T.air_update_turf(1) + air_update_turf(1) @@ -216,23 +233,43 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0) return T.atmos_spawn_air(text, amount) -/turf/simulated/proc/atmos_spawn_air(var/text, var/amount) +var/const/SPAWN_HEAT = 1 + +var/const/SPAWN_TOXINS = 4 +var/const/SPAWN_OXYGEN = 8 +var/const/SPAWN_CO2 = 16 +var/const/SPAWN_NITROGEN = 32 + +var/const/SPAWN_N2O = 64 + +var/const/SPAWN_AIR = 256 + +/turf/simulated/proc/atmos_spawn_air(var/flag, var/amount) if(!text || !amount || !air) return var/datum/gas_mixture/G = new - if(text == "fire") - G.toxins = amount - G.temperature = 1000 - else if(text == "n2o") + if(flag & SPAWN_HEAT) + G.temperature += 1000 + + if(flag & SPAWN_TOXINS) + G.toxins += amount + if(flag & SPAWN_OXYGEN) + G.oxygen += amount + if(flag & SPAWN_CO2) + G.carbon_dioxide += amount + if(flag & SPAWN_NITROGEN) + G.nitrogen += amount + + if(flag & SPAWN_N2O) var/datum/gas/sleeping_agent/T = new - T.moles = amount - G += T - else if(text == "fuel") - var/datum/gas/volatile_fuel/T - T.moles = amount - G += T + T.moles += amount + G.trace_gases += T + + if(flag & SPAWN_AIR) + G.oxygen += MOLES_O2STANDARD * amount + G.nitrogen += MOLES_N2STANDARD * amount air.merge(G) air_master.add_to_active(src, 0) \ No newline at end of file diff --git a/code/LINDA/LINDA_turf_tile.dm b/code/LINDA/LINDA_turf_tile.dm index 8007348a68a..c91d16e05f8 100644 --- a/code/LINDA/LINDA_turf_tile.dm +++ b/code/LINDA/LINDA_turf_tile.dm @@ -66,7 +66,7 @@ turf/simulated/New() turf/simulated/Destroy() if(active_hotspot) - active_hotspot.garbage_collect() + qdel(active_hotspot) ..() turf/simulated/assume_air(datum/gas_mixture/giver) @@ -193,7 +193,7 @@ turf/simulated/proc/share_temperature_mutual_solid(turf/simulated/sharer, conduc /******************* GROUP HANDLING FINISH *********************************************************************/ else - if(!air.check_turf(enemy_tile)) + if(!air.check_turf(enemy_tile, atmos_adjacent_turfs_amount)) var/difference = air.mimic(enemy_tile,,atmos_adjacent_turfs_amount) if(difference) if(difference > 0) @@ -259,7 +259,7 @@ turf/simulated/proc/share_temperature_mutual_solid(turf/simulated/sharer, conduc /turf/simulated/proc/last_share_check() if(air.last_share > MINIMUM_AIR_TO_SUSPEND) - excited_group.breakdown = 0 + excited_group.reset_cooldowns() /turf/proc/high_pressure_movements() for(var/atom/movable/M in src) @@ -285,7 +285,6 @@ atom/movable/proc/experience_pressure_difference(pressure_difference, direction) /datum/excited_group var/list/turf_list = list() - var/breakdown = 0 var/breakdown_cooldown = 0 /datum/excited_group/New() @@ -315,29 +314,38 @@ atom/movable/proc/experience_pressure_difference(pressure_difference, direction) /datum/excited_group/proc/reset_cooldowns() breakdown_cooldown = 0 -/datum/excited_group/proc/self_compare() - var/restore = 1 - var/turf/simulated/sample = pick(turf_list) - for(var/turf/simulated/T in turf_list) - if(!T.air.compare(sample.air)) - restore = 0 - break - if(restore) - return 1 - /datum/excited_group/proc/self_breakdown() var/datum/gas_mixture/A = new + var/datum/gas/sleeping_agent/S = new + A.trace_gases += S for(var/turf/simulated/T in turf_list) A.oxygen += T.air.oxygen A.carbon_dioxide+= T.air.carbon_dioxide A.nitrogen += T.air.nitrogen A.toxins += T.air.toxins + + if(T.air.trace_gases.len) + for(var/datum/gas/N in T.air.trace_gases) + S.moles += N.moles + for(var/turf/simulated/T in turf_list) T.air.oxygen = A.oxygen/turf_list.len T.air.carbon_dioxide= A.carbon_dioxide/turf_list.len T.air.nitrogen = A.nitrogen/turf_list.len T.air.toxins = A.toxins/turf_list.len + if(S.moles > 0) + if(T.air.trace_gases.len) + for(var/datum/gas/G in T.air.trace_gases) + G.moles = S.moles/turf_list.len + else + var/datum/gas/sleeping_agent/G = new + G.moles = S.moles/turf_list.len + T.air.trace_gases += G + + if(T.air.check_tile_graphic()) + T.update_visuals(T.air) + /datum/excited_group/proc/dismantle() for(var/turf/simulated/T in turf_list) diff --git a/code/datums/gas_mixture.dm b/code/datums/gas_mixture.dm new file mode 100644 index 00000000000..7bdd0cf0abc --- /dev/null +++ b/code/datums/gas_mixture.dm @@ -0,0 +1,961 @@ + /* +What are the archived variables for? + Calculations are done using the archived variables with the results merged into the regular variables. + This prevents race conditions that arise based on the order of tile processing. +*/ + +#define SPECIFIC_HEAT_TOXIN 200 +#define SPECIFIC_HEAT_AIR 20 +#define SPECIFIC_HEAT_CDO 30 +#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \ + (carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN) + +#define MINIMUM_HEAT_CAPACITY 0.0003 +#define QUANTIZE(variable) (round(variable,0.0001)) + +/datum/gas + sleeping_agent + specific_heat = 40 + + oxygen_agent_b + specific_heat = 300 + + volatile_fuel + specific_heat = 30 + + var/moles = 0 + var/specific_heat = 0 + + var/moles_archived = 0 + + +/datum/gas_mixture + var/oxygen = 0 + var/carbon_dioxide = 0 + var/nitrogen = 0 + var/toxins = 0 + + var/volume = CELL_VOLUME + + var/temperature = 0 //in Kelvin, use calculate_temperature() to modify + + var/last_share + + var/group_multiplier = 1 + //Size of the group this gas_mixture is representing. + //=1 for singletons + + var/graphic + + var/list/datum/gas/trace_gases = list() + + + var/tmp/oxygen_archived + var/tmp/carbon_dioxide_archived + var/tmp/nitrogen_archived + var/tmp/toxins_archived + + var/tmp/temperature_archived + + var/tmp/graphic_archived + var/tmp/fuel_burnt = 0 + + //PV=nRT - related procedures + proc/heat_capacity() + var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + heat_capacity += trace_gas.moles*trace_gas.specific_heat + return heat_capacity + + + proc/heat_capacity_archived() + var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived) + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat + return heat_capacity_archived + + + proc/total_moles() + var/moles = oxygen + carbon_dioxide + nitrogen + toxins + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + moles += trace_gas.moles + return moles + + + proc/return_pressure() + if(volume>0) + return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume + return 0 + + + proc/return_temperature() + return temperature + + + proc/return_volume() + return max(0, volume) + + + proc/thermal_energy() + return temperature*heat_capacity() + + + //Procedures used for very specific events + proc/check_tile_graphic() + //returns 1 if graphic changed + graphic = null + if(toxins > MOLES_PLASMA_VISIBLE) + graphic = "plasma" + else + var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases + if(sleeping_agent && (sleeping_agent.moles > 1)) + graphic = "sleeping_agent" + else + graphic = null + + return graphic != graphic_archived + + proc/react(atom/dump_location) + var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) + + if(trace_gases.len > 0) + if(temperature > 900) + if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY) + var/datum/gas/oxygen_agent_b/trace_gas = locate(/datum/gas/oxygen_agent_b/) in trace_gases + if(trace_gas) + var/reaction_rate = min(carbon_dioxide*0.75, toxins*0.25, trace_gas.moles*0.05) + + carbon_dioxide -= reaction_rate + oxygen += reaction_rate + + trace_gas.moles -= reaction_rate*0.05 + + temperature -= (reaction_rate*20000)/heat_capacity() + + reacting = 1 + + fuel_burnt = 0 + if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) + //world << "pre [temperature], [oxygen], [toxins]" + if(fire() > 0) + reacting = 1 + //world << "post [temperature], [oxygen], [toxins]" + + return reacting + + proc/fire() + var/energy_released = 0 + var/old_heat_capacity = heat_capacity() + + var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel/) in trace_gases + if(fuel_store) //General volatile gas burn + var/burned_fuel = 0 + + if(oxygen < fuel_store.moles) + burned_fuel = oxygen + fuel_store.moles -= burned_fuel + oxygen = 0 + else + burned_fuel = fuel_store.moles + oxygen -= fuel_store.moles + trace_gases -= fuel_store + fuel_store = null + + energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel + carbon_dioxide += burned_fuel + fuel_burnt += burned_fuel + + //Handle plasma burning + if(toxins > MINIMUM_HEAT_CAPACITY) + var/plasma_burn_rate = 0 + var/oxygen_burn_rate = 0 + //more plasma released at higher temperatures + var/temperature_scale + if(temperature > PLASMA_UPPER_TEMPERATURE) + temperature_scale = 1 + else + temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) + if(temperature_scale > 0) + oxygen_burn_rate = 1.4 - temperature_scale + if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN) + plasma_burn_rate = (toxins*temperature_scale)/4 + else + plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/4 + if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) + toxins -= plasma_burn_rate + oxygen -= plasma_burn_rate*oxygen_burn_rate + carbon_dioxide += plasma_burn_rate + + energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) + + fuel_burnt += (plasma_burn_rate)*(1+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 + + return fuel_burnt + + proc/archive() + //Update archived versions of variables + //Returns: 1 in all cases + + proc/merge(datum/gas_mixture/giver) + //Merges all air from giver into self. Deletes giver. + //Returns: 1 on success (no failure cases yet) + + proc/check_then_merge(datum/gas_mixture/giver) + //Similar to merge(...) but first checks to see if the amount of air assumed is small enough + // that group processing is still accurate for source (aborts if not) + //Returns: 1 on successful merge, 0 if the check failed + + proc/remove(amount) + //Proportionally removes amount of gas from the gas_mixture + //Returns: gas_mixture with the gases removed + + proc/remove_ratio(ratio) + //Proportionally removes amount of gas from the gas_mixture + //Returns: gas_mixture with the gases removed + + proc/subtract(datum/gas_mixture/right_side) + //Subtracts right_side from air_mixture. Used to help turfs mingle + + proc/check_then_remove(amount) + //Similar to remove(...) but first checks to see if the amount of air removed is small enough + // that group processing is still accurate for source (aborts if not) + //Returns: gas_mixture with the gases removed or null + + proc/copy_from(datum/gas_mixture/sample) + //Copies variables from sample + + proc/share(datum/gas_mixture/sharer) + //Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length + //Return: amount of gas exchanged (+ if sharer received) + + proc/mimic(turf/model) + //Similar to share(...), except the model is not modified + //Return: amount of gas exchanged + + proc/check_gas_mixture(datum/gas_mixture/sharer) + //Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if both checks pass + + proc/check_turf(turf/model) + //Returns: 0 if self-check failed or 1 if check passes + + // check_me_then_share(datum/gas_mixture/sharer) + //Similar to share(...) but first checks to see if amount of air moved is small enough + // that group processing is still accurate for source (aborts if not) + //Returns: 1 on successful share, 0 if the check failed + + // check_me_then_mimic(turf/model) + //Similar to mimic(...) but first checks to see if amount of air moved is small enough + // that group processing is still accurate (aborts if not) + //Returns: 1 on successful mimic, 0 if the check failed + + // check_both_then_share(datum/gas_mixture/sharer) + //Similar to check_me_then_share(...) but also checks to see if amount of air moved is small enough + // that group processing is still accurate for the sharer (aborts if not) + //Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if successful share + + + proc/temperature_mimic(turf/model, conduction_coefficient) + + proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + + proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + + + proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient) + + proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + + proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + + proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + + proc/compare(datum/gas_mixture/sample) + //Compares sample to self to see if within acceptable ranges that group processing may be enabled + + archive() + oxygen_archived = oxygen + carbon_dioxide_archived = carbon_dioxide + nitrogen_archived = nitrogen + toxins_archived = toxins + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles_archived = trace_gas.moles + + temperature_archived = temperature + + graphic_archived = graphic + + return 1 + + check_then_merge(datum/gas_mixture/giver) + if(!giver) + return 0 + if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(giver.trace_gases.len) + for(var/datum/gas/trace_gas in giver.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + + return merge(giver) + + merge(datum/gas_mixture/giver) + if(!giver) + return 0 + + if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity()*group_multiplier + var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier + var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity + if(combined_heat_capacity != 0) + temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity + + if((group_multiplier>1)||(giver.group_multiplier>1)) + oxygen += giver.oxygen*giver.group_multiplier/group_multiplier + carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier + nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier + toxins += giver.toxins*giver.group_multiplier/group_multiplier + else + oxygen += giver.oxygen + carbon_dioxide += giver.carbon_dioxide + nitrogen += giver.nitrogen + toxins += giver.toxins + + if(giver.trace_gases.len) + for(var/datum/gas/trace_gas in giver.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier + + // del(giver) + return 1 + + remove(amount) + + var/sum = total_moles() + amount = min(amount,sum) //Can not take more air than tile has! + if(amount <= 0) + return null + + 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) + + oxygen -= removed.oxygen/group_multiplier + nitrogen -= removed.nitrogen/group_multiplier + carbon_dioxide -= removed.carbon_dioxide/group_multiplier + toxins -= removed.toxins/group_multiplier + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + removed.trace_gases += corresponding + + corresponding.moles = (trace_gas.moles/sum)*amount + trace_gas.moles -= corresponding.moles/group_multiplier + + removed.temperature = temperature + + return removed + + remove_ratio(ratio) + + if(ratio <= 0) + return null + + ratio = min(ratio, 1) + + 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) + + oxygen -= removed.oxygen/group_multiplier + nitrogen -= removed.nitrogen/group_multiplier + carbon_dioxide -= removed.carbon_dioxide/group_multiplier + toxins -= removed.toxins/group_multiplier + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + removed.trace_gases += corresponding + + corresponding.moles = trace_gas.moles*ratio + trace_gas.moles -= corresponding.moles/group_multiplier + + removed.temperature = temperature + + return removed + + check_then_remove(amount) + + //Since it is all proportional, the check may be done on the gas as a whole + var/sum = total_moles() + amount = min(amount,sum) //Can not take more air than tile has! + + if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > sum*MINIMUM_AIR_RATIO_TO_SUSPEND)) + return 0 + + return remove(amount) + + copy_from(datum/gas_mixture/sample) + oxygen = sample.oxygen + carbon_dioxide = sample.carbon_dioxide + nitrogen = sample.nitrogen + toxins = sample.toxins + + trace_gases.len=null + if(sample.trace_gases.len > 0) + for(var/datum/gas/trace_gas in sample.trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + trace_gases += corresponding + + corresponding.moles = trace_gas.moles + + temperature = sample.temperature + + return 1 + + subtract(datum/gas_mixture/right_side) + oxygen -= right_side.oxygen + carbon_dioxide -= right_side.carbon_dioxide + nitrogen -= right_side.nitrogen + toxins -= right_side.toxins + + if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) + for(var/datum/gas/trace_gas in right_side.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + + corresponding.moles -= trace_gas.moles + + return 1 + + check_gas_mixture(datum/gas_mixture/sharer) + if(!sharer) return 0 + var/delta_oxygen = (oxygen_archived - sharer.oxygen_archived)/5 + var/delta_carbon_dioxide = (carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5 + var/delta_nitrogen = (nitrogen_archived - sharer.nitrogen_archived)/5 + var/delta_toxins = (toxins_archived - sharer.toxins_archived)/5 + + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + 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))) + return 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(sharer.trace_gases.len) + for(var/datum/gas/trace_gas in sharer.trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) + return 0 + else + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + if(!locate(trace_gas.type) in sharer.trace_gases) + return 0 + + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return -1 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases + if(corresponding) + if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) + return -1 + else + return -1 + + return 1 + + check_turf(turf/model, atmos_adjacent_turfs = 4) + 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_temperature = (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))) + return 0 + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + return 0 + + return 1 + + proc/check_turf_total(turf/model) + 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_temperature = (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))) + return 0 + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND*4) + return 0 + + return 1 + + share(datum/gas_mixture/sharer, var/atmos_adjacent_turfs = 4) + if(!sharer) 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_temperature = (temperature_archived - sharer.temperature_archived) + + var/old_self_heat_capacity = 0 + var/old_sharer_heat_capacity = 0 + + var/heat_capacity_self_to_sharer = 0 + var/heat_capacity_sharer_to_self = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + + var/delta_air = delta_oxygen+delta_nitrogen + if(delta_air) + var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air + if(delta_air > 0) + heat_capacity_self_to_sharer += air_heat_capacity + else + heat_capacity_sharer_to_self -= air_heat_capacity + + if(delta_carbon_dioxide) + var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide + if(delta_carbon_dioxide > 0) + heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity + else + heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity + + if(delta_toxins) + var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins + if(delta_toxins > 0) + heat_capacity_self_to_sharer += toxins_heat_capacity + else + heat_capacity_sharer_to_self -= toxins_heat_capacity + + old_self_heat_capacity = heat_capacity()*group_multiplier + old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier + + oxygen -= delta_oxygen/group_multiplier + sharer.oxygen += delta_oxygen/sharer.group_multiplier + + carbon_dioxide -= delta_carbon_dioxide/group_multiplier + sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier + + nitrogen -= delta_nitrogen/group_multiplier + sharer.nitrogen += delta_nitrogen/sharer.group_multiplier + + toxins -= delta_toxins/group_multiplier + sharer.toxins += delta_toxins/sharer.group_multiplier + + var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) + last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins) + + var/list/trace_types_considered = list() + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + + var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases + var/delta = 0 + + if(corresponding) + delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/(atmos_adjacent_turfs+1) + else + corresponding = new trace_gas.type() + sharer.trace_gases += corresponding + + delta = trace_gas.moles_archived/(atmos_adjacent_turfs+1) + + trace_gas.moles -= delta/group_multiplier + corresponding.moles += delta/sharer.group_multiplier + + if(delta) + var/individual_heat_capacity = trace_gas.specific_heat*delta + if(delta > 0) + heat_capacity_self_to_sharer += individual_heat_capacity + else + heat_capacity_sharer_to_self -= individual_heat_capacity + + moved_moles += delta + last_share += abs(delta) + + trace_types_considered += trace_gas.type + + + if(sharer.trace_gases.len) + for(var/datum/gas/trace_gas in sharer.trace_gases) + if(trace_gas.type in trace_types_considered) continue + else + var/datum/gas/corresponding + var/delta = 0 + + corresponding = new trace_gas.type() + trace_gases += corresponding + + delta = trace_gas.moles_archived/5 + + trace_gas.moles -= delta/sharer.group_multiplier + corresponding.moles += delta/group_multiplier + + //Guaranteed transfer from sharer to self + var/individual_heat_capacity = trace_gas.specific_heat*delta + heat_capacity_sharer_to_self += individual_heat_capacity + + moved_moles += -delta + last_share += abs(delta) + + 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 + + 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 + + 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) + + 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) + return delta_pressure*R_IDEAL_GAS_EQUATION/volume + + mimic(turf/model, border_multiplier, var/atmos_adjacent_turfs = 4) + 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_temperature = (temperature_archived - model.temperature) + + var/heat_transferred = 0 + var/old_self_heat_capacity = 0 + var/heat_capacity_transferred = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + + var/delta_air = delta_oxygen+delta_nitrogen + if(delta_air) + var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air + heat_transferred -= air_heat_capacity*model.temperature + heat_capacity_transferred -= air_heat_capacity + + if(delta_carbon_dioxide) + var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide + heat_transferred -= carbon_dioxide_heat_capacity*model.temperature + heat_capacity_transferred -= carbon_dioxide_heat_capacity + + if(delta_toxins) + var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins + heat_transferred -= toxins_heat_capacity*model.temperature + heat_capacity_transferred -= toxins_heat_capacity + + old_self_heat_capacity = heat_capacity()*group_multiplier + + if(border_multiplier) + oxygen -= delta_oxygen*border_multiplier/group_multiplier + carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier + nitrogen -= delta_nitrogen*border_multiplier/group_multiplier + toxins -= delta_toxins*border_multiplier/group_multiplier + else + oxygen -= delta_oxygen/group_multiplier + carbon_dioxide -= delta_carbon_dioxide/group_multiplier + nitrogen -= delta_nitrogen/group_multiplier + toxins -= delta_toxins/group_multiplier + + var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) + last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins) + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/delta = 0 + + delta = trace_gas.moles_archived/(atmos_adjacent_turfs+1) + + if(border_multiplier) + trace_gas.moles -= delta*border_multiplier/group_multiplier + else + trace_gas.moles -= delta/group_multiplier + + var/heat_cap_transferred = delta*trace_gas.specific_heat + heat_transferred += heat_cap_transferred*temperature_archived + heat_capacity_transferred += heat_cap_transferred + moved_moles += delta + moved_moles += abs(delta) + + 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) + if(border_multiplier) + temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity + else + temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity + + temperature_mimic(model, model.thermal_conductivity, border_multiplier) + + 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) + return delta_pressure*R_IDEAL_GAS_EQUATION/volume + else + return 0 + + check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + 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)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived)) + return -1 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency + + check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + 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)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency + + check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature) + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + + 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)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/sharer.heat_capacity + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency + + check_me_then_temperature_mimic(turf/model, conduction_coefficient) + var/delta_temperature = (temperature_archived - model.temperature) + var/self_temperature_delta = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + + if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + + return 1 + //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency + + temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + 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*group_multiplier) + sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier) + + temperature_mimic(turf/model, conduction_coefficient, border_multiplier) + var/delta_temperature = (temperature - model.temperature) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity()//_archived() + + if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) + + if(border_multiplier) + temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier) + else + temperature -= heat/(self_heat_capacity*group_multiplier) + + temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + 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*group_multiplier) + sharer.temperature += heat/sharer.heat_capacity + + compare(datum/gas_mixture/sample) + if(!istype(sample)) return //fix for this.. randomly runtiming + 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))) + return 0 + 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))) + return 0 + if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ + ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) + return 0 + 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))) + return 0 + + if(total_moles() > MINIMUM_AIR_TO_SUSPEND) + if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ + ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) + //world << "temp fail [temperature] & [sample.temperature]" + return 0 + + if(sample.trace_gases.len) + for(var/datum/gas/trace_gas in sample.trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) + return 0 + else + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) + var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases + if(corresponding) + if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) + return 0 + else + return 0 + return 1 \ No newline at end of file diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index b55fe25cfb9..24758c657fc 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -246,7 +246,7 @@ PlasmaBurn(exposed_temperature) /obj/machinery/door/airlock/plasma/proc/PlasmaBurn(temperature) - atmos_spawn_air("fire", 500) + atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 500) new/obj/structure/door_assembly( src.loc ) del (src) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 926b338b5bd..7adac024aca 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -308,7 +308,7 @@ return /obj/machinery/door/Move(new_loc, new_dir) - air_update_turf(1) + var/turf/T = loc . = ..() if(width > 1) if(dir in list(EAST, WEST)) @@ -318,7 +318,7 @@ bound_width = world.icon_size bound_height = width * world.icon_size - air_update_turf(1) + move_update_air(T) /obj/machinery/door/BlockSuperconductivity() if(opacity || heat_proof) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index cef0cce978c..d6a6a970acf 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -22,9 +22,9 @@ ..() /obj/machinery/shield/Move() - air_update_turf(1) + var/turf/T = loc ..() - air_update_turf(1) + move_update_air(T) /obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height, air_group) if(!height || air_group) return 0 diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 985b3bca9ba..2b0aa6a79f7 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -35,7 +35,9 @@ ..() /obj/structure/alien/resin/Move() + var/turf/T = loc ..() + move_update_air(T) /obj/structure/alien/resin/wall name = "resin wall" diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index a5ae1cf5f97..c66706a18b3 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -118,10 +118,7 @@ ..() var/turf/simulated/T = get_turf(src) if(istype(T)) - var/datum/gas_mixture/payload = new - payload.toxins = 60 - T.air.merge(payload) - T.hotspot_expose(1000, CELL_VOLUME) + T.atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 3) ///////////////////// diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 51419fd785c..d1fb5e583d1 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -1048,9 +1048,9 @@ steam.start() -- spawns the effect ..() Move() - air_update_turf(1) + var/turf/T = loc ..() - air_update_turf(1) + move_update_air(T) proc/updateicon() if(metal == 1) diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 58ae5b3d56f..9ca78dd7f30 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -46,12 +46,12 @@ del(src) /obj/effect/mine/proc/triggern2o(obj) - atmos_spawn_air("n2o", 360) + atmos_spawn_air(SPAWN_N2O, 360) spawn(0) del(src) /obj/effect/mine/proc/triggerplasma(obj) - atmos_spawn_air("fire", 360) + atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 360) spawn(0) del(src) diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 5d35988c2b8..d4d3dc787c0 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -27,9 +27,9 @@ ..() Move() - air_update_turf(1) + var/turf/T = loc ..() - air_update_turf(1) + move_update_air(T) Bumped(atom/user) ..() @@ -207,7 +207,7 @@ TemperatureAct(exposed_temperature) proc/TemperatureAct(temperature) - atmos_spawn_air("fire", 500) + atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 500) hardness = 0 CheckHardness() diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 5a57731b15b..a9ef0455066 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -38,9 +38,9 @@ obj/structure/windoor_assembly/Destroy() ..() /obj/structure/windoor_assembly/Move() - air_update_turf(1) + var/turf/T = loc ..() - air_update_turf(1) + move_update_air(T) /obj/structure/windoor_assembly/update_icon() icon_state = "[facing]_[secure ? "secure_" : ""]windoor_assembly[state]" diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 608c8266573..51f95e36b07 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -352,10 +352,10 @@ var/global/wcColored /obj/structure/window/Move() - air_update_turf(1) + var/turf/T = loc ..() dir = ini_dir - air_update_turf(1) + move_update_air(T) //checks if this window is full-tile one /obj/structure/window/proc/is_fulltile() diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 94623909eb8..fecdf392d51 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -15,6 +15,9 @@ ..() levelupdate() +/turf/simulated/proc/burn_tile() + return + /turf/simulated/proc/MakeSlippery(var/wet_setting = 1) // 1 = Water, 2 = Lube if(wet >= wet_setting) return diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 3ae57c57000..55954dc957f 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -293,7 +293,7 @@ turf/simulated/floor/proc/update_icon() src.icon_state = "sand[pick("1","2","3")]" broken = 1 -/turf/simulated/floor/proc/burn_tile() +/turf/simulated/floor/burn_tile() if(istype(src,/turf/simulated/floor/engine)) return if(istype(src,/turf/simulated/floor/plating/airless/asteroid)) return//Asteroid tiles don't burn if(broken || burnt) return diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index f7d36acbf33..393ff4beb8e 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -94,7 +94,7 @@ spawn(2) new /obj/structure/girder(src) src.ChangeTurf(/turf/simulated/floor) - atmos_spawn_air("fire", 400) + atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 400) /turf/simulated/wall/mineral/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)//Doesn't fucking work because walls don't interact with air :( if(exposed_temperature > 300) diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index be39f1be89a..48acf97242f 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -156,6 +156,7 @@ ground_zero.assume_air(air_contents) ground_zero.hotspot_expose(1000, 125) + air_update_turf() if(master) del(master) del(src) @@ -165,4 +166,5 @@ var/turf/simulated/T = get_turf(src) if(!T) return - T.assume_air(removed) \ No newline at end of file + T.assume_air(removed) + air_update_turf() \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 1e4ec3c79a5..00f9a662b91 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -648,9 +648,9 @@ datum for(var/mob/O in viewers(get_turf(holder.my_atom), null)) O.show_message(text("\red The slime extract begins to vibrate violently !"), 1) sleep(50) - var/turf/simulated/T = get_turf(src) + var/turf/simulated/T = get_turf(holder.my_atom) if(istype(T)) - T.atmos_spawn_air("fire", 50) + T.atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 50) //Yellow slimeoverload diff --git a/paradise.dme b/paradise.dme index 8dbbe48f7a7..c67c19c9dac 100644 --- a/paradise.dme +++ b/paradise.dme @@ -135,6 +135,7 @@ #include "code\datums\computerfiles.dm" #include "code\datums\datacore.dm" #include "code\datums\datumvars.dm" +#include "code\datums\gas_mixture.dm" #include "code\datums\martial.dm" #include "code\datums\medical_effects.dm" #include "code\datums\mind.dm" @@ -198,7 +199,6 @@ #include "code\defines\procs\records.dm" #include "code\defines\procs\sd_Alert.dm" #include "code\defines\procs\statistics.dm" -#include "code\FEA\FEA_gas_mixture.dm" #include "code\game\asteroid.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm"