diff --git a/code/__DEFINES/atmospherics/atmos_core.dm b/code/__DEFINES/atmospherics/atmos_core.dm index 0b5742d24a5..e2c66a83095 100644 --- a/code/__DEFINES/atmospherics/atmos_core.dm +++ b/code/__DEFINES/atmospherics/atmos_core.dm @@ -1,11 +1,4 @@ //LISTMOS -//indices of values in gas lists. -///Amount of total moles in said gas mixture -#define MOLES 1 -///Archived version of MOLES -#define ARCHIVE 2 -///All gas related variables -#define GAS_META 3 ///Gas specific heat per mole #define META_GAS_SPECIFIC_HEAT 1 ///Name of the gas @@ -22,6 +15,8 @@ #define META_GAS_FUSION_POWER 7 ///Short description of the gas. #define META_GAS_DESC 8 +///Length of gas meta array +#define META_GAS_LENGTH 8 //ATMOS //stuff you should probably leave well alone! /// kPa*L/(K*mol) @@ -54,7 +49,7 @@ /// Molar accuracy to round to #define MOLAR_ACCURACY 1E-4 /// Types of gases (based on gaslist_cache) -#define GAS_TYPE_COUNT GLOB.gaslist_cache.len +#define GAS_TYPE_COUNT 20 /// Maximum error caused by QUANTIZE when removing gas (roughly, in reality around 2 * MOLAR_ACCURACY less) #define MAXIMUM_ERROR_GAS_REMOVAL (MOLAR_ACCURACY * GAS_TYPE_COUNT) @@ -182,3 +177,5 @@ #define ATMOS_PRESSURE_APPROXIMATION_ITERATIONS 20 /// We deal with big numbers and a lot of math, things are bound to get imprecise. Take this traveller. #define ATMOS_PRESSURE_ERROR_TOLERANCE 0.01 +/// Helper function for retrieving gas meta info for use in performace critical places +#define GAS_META /datum/gas_mixture::gas_meta diff --git a/code/__DEFINES/atmospherics/atmos_helpers.dm b/code/__DEFINES/atmospherics/atmos_helpers.dm index ce3e2f40a68..cd6ca3aa0dd 100644 --- a/code/__DEFINES/atmospherics/atmos_helpers.dm +++ b/code/__DEFINES/atmospherics/atmos_helpers.dm @@ -53,41 +53,24 @@ ///Calculate the thermal energy of the selected gas (J) #define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity()) -///Directly adds a gas to a gas mixture without checking for its presence beforehand, use only if is certain the absence of said gas -#define ADD_GAS(gas_id, out_list)\ - var/list/tmp_gaslist = GLOB.gaslist_cache[gas_id]; out_list[gas_id] = tmp_gaslist.Copy(); - -///Adds a gas to a gas mixture but checks if is already present, faster than the same proc -#define ASSERT_GAS(gas_id, gas_mixture) ASSERT_GAS_IN_LIST(gas_id, gas_mixture.gases) - -///Adds a gas to a gas LIST but checks if is already present, accepts a list instead of a datum, so faster if the list is locally cached -#define ASSERT_GAS_IN_LIST(gas_id, gases) if (!gases[gas_id]) { ADD_GAS(gas_id, gases) }; - -//prefer this to gas_mixture/total_moles in performance critical areas -///Calculate the total moles of the gas mixture, faster than the proc, good for performance critical areas -#define TOTAL_MOLES(cached_gases, out_var)\ - out_var = 0;\ - for(var/total_moles_id in cached_gases){\ - out_var += cached_gases[total_moles_id][MOLES];\ - } - GLOBAL_LIST_INIT(nonoverlaying_gases, typecache_of_gases_with_no_overlays()) ///Returns a list of overlays of every gas in the mixture -#define GAS_OVERLAYS(gases, out_var, z_layer_turf)\ +#define GAS_OVERLAYS(moles, out_var, z_layer_turf)\ do { \ out_var = list();\ var/offset = GET_TURF_PLANE_OFFSET(z_layer_turf) + 1;\ - for(var/_ID in gases){\ - if(GLOB.nonoverlaying_gases[_ID]) continue;\ - var/_GAS = gases[_ID];\ - var/_GAS_META = _GAS[GAS_META];\ - if(_GAS[MOLES] <= _GAS_META[META_GAS_MOLES_VISIBLE]) continue;\ - var/_GAS_OVERLAY = _GAS_META[META_GAS_OVERLAY][offset];\ - out_var += _GAS_OVERLAY[min(TOTAL_VISIBLE_STATES, CEILING(_GAS[MOLES] / MOLES_GAS_VISIBLE_STEP, 1))];\ - } \ + var/list/_META_MOLES_VISIBLE = GAS_META[META_GAS_MOLES_VISIBLE];\ + var/list/_META_GAS_OVERLAY = GAS_META[META_GAS_OVERLAY];\ + for(var/gas_id, amount in moles){\ + if(GLOB.nonoverlaying_gases[gas_id]) continue;\ + if(amount <= _META_MOLES_VISIBLE[gas_id]) continue;\ + var/_GAS_OVERLAY = _META_GAS_OVERLAY[gas_id][offset];\ + out_var += _GAS_OVERLAY[min(TOTAL_VISIBLE_STATES, CEILING(amount / MOLES_GAS_VISIBLE_STEP, 1))];\ + }\ }\ while (FALSE) + #ifdef TESTING GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) #define CALCULATE_ADJACENT_TURFS(T, state) if (SSair.adjacent_rebuild[T]) { GLOB.atmos_adjacent_savings[1] += 1 } else { GLOB.atmos_adjacent_savings[2] += 1; SSair.adjacent_rebuild[T] = state} diff --git a/code/__HELPERS/atmospherics.dm b/code/__HELPERS/atmospherics.dm index 6264823b7f2..d3f1522dbf8 100644 --- a/code/__HELPERS/atmospherics.dm +++ b/code/__HELPERS/atmospherics.dm @@ -41,11 +41,13 @@ ) if(!gasmix) return - for(var/gas_path in gasmix.gases) + var/list/cached_gas_id = GAS_META[META_GAS_ID] + var/list/cached_gas_name = GAS_META[META_GAS_NAME] + for(var/gas_path, amount in gasmix.moles) .["gases"] += list(list( - gasmix.gases[gas_path][GAS_META][META_GAS_ID], - gasmix.gases[gas_path][GAS_META][META_GAS_NAME], - gasmix.gases[gas_path][MOLES], + cached_gas_id[gas_path], + cached_gas_name[gas_path], + amount, )) for(var/datum/gas_reaction/reaction_result as anything in gasmix.reaction_results) .["reactions"] += list(list( @@ -75,13 +77,13 @@ GLOBAL_LIST_EMPTY(gas_handbook) for (var/datum/gas/gas_path as anything in subtypesof(/datum/gas)) var/list/gas_info = list() - var/list/meta_information = GLOB.meta_gas_info[gas_path] - if(!meta_information) + var/list/meta_information = GLOB.meta_gas_info + if(!meta_information[META_GAS_ID]) continue - gas_info["id"] = meta_information[META_GAS_ID] - gas_info["name"] = meta_information[META_GAS_NAME] - gas_info["description"] = meta_information[META_GAS_DESC] - gas_info["specific_heat"] = meta_information[META_GAS_SPECIFIC_HEAT] + gas_info["id"] = meta_information[META_GAS_ID][gas_path] + gas_info["name"] = meta_information[META_GAS_NAME][gas_path] + gas_info["description"] = meta_information[META_GAS_DESC][gas_path] + gas_info["specific_heat"] = meta_information[META_GAS_SPECIFIC_HEAT][gas_path] gas_info["reactions"] = list() momentary_gas_list[gas_path] = gas_info @@ -172,41 +174,9 @@ GLOBAL_LIST_EMPTY(gas_handbook) return null -/** - * A simple helper proc that checks if the contents of a list of gases are within acceptable terms. - * - * Arguments: - * * gases: The list of gases which contents are being checked - * * acceptable_gas_bounds: An associated list of gas types and acceptable boundaries in moles. e.g. /datum/gas/oxygen = list(16, 30) - * * * if the assoc list is null, then it'll be considered a safe gas and won't return FALSE. - * * extraneous_gas_limit: If a gas not in gases is found, this is the limit above which the proc will return FALSE. - * - * Returns TRUE if the list of gases is acceptable, FALSE otherwise. - */ -/proc/check_gases(list/gases, list/acceptable_gas_bounds, extraneous_gas_limit = 0.1) - SHOULD_BE_PURE(TRUE) - - var/list/gases_to_check = acceptable_gas_bounds.Copy() // thank you spaceman - for(var/id in gases) - var/gas_moles = gases[id][MOLES] - if(!(id in gases_to_check)) - if(gas_moles > extraneous_gas_limit) - return FALSE - continue - var/list/boundaries = gases_to_check[id] - if(boundaries && !ISINRANGE(gas_moles, boundaries[1], boundaries[2])) - return FALSE - gases_to_check -= id - ///Check that gases absent from the turf have a lower boundary of zero or none at all, otherwise return FALSE - for(var/id in gases_to_check) - var/list/boundaries = gases_to_check[id] - if(boundaries && boundaries[1] > 0) - return FALSE - return TRUE - /proc/print_gas_mixture(datum/gas_mixture/gas_mixture) var/message = "TEMPERATURE: [gas_mixture.temperature]K, QUANTITY: [gas_mixture.total_moles()] mols, VOLUME: [gas_mixture.volume]L; " - for(var/key in gas_mixture.gases) - var/list/gaslist = gas_mixture.gases[key] - message += "[gaslist[GAS_META][META_GAS_ID]]=[gaslist[MOLES]] mols;" + var/list/cached_gas_id = GAS_META[META_GAS_ID] + for(var/gas_id, amount in gas_mixture.moles) + message += "[cached_gas_id[gas_id]]=[amount] mols;" return message diff --git a/code/__HELPERS/logging/atmos.dm b/code/__HELPERS/logging/atmos.dm index 644c9e65625..9e2a76f648a 100644 --- a/code/__HELPERS/logging/atmos.dm +++ b/code/__HELPERS/logging/atmos.dm @@ -2,26 +2,27 @@ /proc/log_atmos(text, datum/gas_mixture/gas_mixture) var/message = "[text]\"[print_gas_mixture(gas_mixture)]\"" //Cache commonly accessed information. - var/list/gases = gas_mixture.gases //List of gas datum paths that are associated with a list of information related to the gases. + var/list/cached_moles = gas_mixture.moles var/heat_capacity = gas_mixture.heat_capacity() var/temperature = gas_mixture.return_temperature() var/thermal_energy = temperature * heat_capacity var/volume = gas_mixture.return_volume() var/pressure = gas_mixture.return_pressure() var/total_moles = gas_mixture.total_moles() + var/list/cached_specific_heat = GAS_META[META_GAS_SPECIFIC_HEAT] + var/list/cached_gas_name = GAS_META[META_GAS_NAME] ///The total value of the gas mixture in credits. var/total_value = 0 var/list/specific_gas_data = list() //Gas specific information assigned to each gas. - for(var/datum/gas/gas_path as anything in gases) - var/list/gas = gases[gas_path] - var/moles = gas[MOLES] + for(var/datum/gas/gas_path as anything in cached_moles) + var/moles = cached_moles[gas_path] var/composition = moles / total_moles - var/energy = temperature * moles * gas[GAS_META][META_GAS_SPECIFIC_HEAT] + var/energy = temperature * moles * cached_specific_heat[gas_path] var/value = initial(gas_path.base_value) * moles total_value += value - specific_gas_data[gas[GAS_META][META_GAS_NAME]] = list( + specific_gas_data[cached_gas_name[gas_path]] = list( "moles" = moles, "composition" = composition, "molar concentration" = moles / volume, diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index b75d9e813e3..730c7386ea9 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -564,8 +564,7 @@ SUBSYSTEM_DEF(air) if(enemy_tile.current_cycle == -INFINITY) continue // .air instead of .return_air() because we can guarantee that the proc won't do anything - if(potential_diff.air.compare(enemy_tile.air, MOLES)) - //testing("Active turf found. Return value of compare(): [T.air.compare(enemy_tile.air, MOLES)]") + if(potential_diff.air.compare(enemy_tile.air, FALSE)) if(!potential_diff.excited) potential_diff.excited = TRUE SSair.active_turfs += potential_diff @@ -785,7 +784,6 @@ GLOBAL_LIST_EMPTY(colored_images) strings_to_mix["[gas_string]-[gastype]"] = canonical_mix gas_string = preprocess_gas_string(gas_string) - var/list/gases = canonical_mix.gases var/list/gas = params2list(gas_string) if(gas["TEMP"]) canonical_mix.temperature = text2num(gas["TEMP"]) @@ -793,12 +791,12 @@ GLOBAL_LIST_EMPTY(colored_images) gas -= "TEMP" else // if we do not have a temp in the new gas mix lets assume room temp. canonical_mix.temperature = T20C + var/list/cached_moles = canonical_mix.moles for(var/id in gas) var/path = id if(!ispath(path)) path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around - ADD_GAS(path, gases) - gases[path][MOLES] = text2num(gas[id]) + cached_moles[path] = text2num(gas[id]) if(istype(canonical_mix, /datum/gas_mixture/immutable)) return canonical_mix diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 274325956a4..39061b3e0dc 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -802,10 +802,9 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away GLOB.starlight_objects += starlight_object(offset) GLOB.starlight_overlays += starlight_overlay(offset) - for(var/datum/gas/gas_type as anything in GLOB.meta_gas_info) - var/list/gas_info = GLOB.meta_gas_info[gas_type] + for(var/datum/gas/gas_type as anything in GLOB.meta_gas_info[META_GAS_ID]) if(initial(gas_type.moles_visible) != null) - gas_info[META_GAS_OVERLAY] += generate_gas_overlays(gen_from, new_offset, gas_type) + GLOB.meta_gas_info[META_GAS_OVERLAY][gas_type] += generate_gas_overlays(gen_from, new_offset, gas_type) /datum/controller/subsystem/mapping/proc/create_plane_offsets(gen_from, new_offset) for(var/plane_offset in gen_from to new_offset) diff --git a/code/datums/atmosphere/_atmosphere.dm b/code/datums/atmosphere/_atmosphere.dm index 702a42e7ab0..37bdb954fa1 100644 --- a/code/datums/atmosphere/_atmosphere.dm +++ b/code/datums/atmosphere/_atmosphere.dm @@ -27,11 +27,10 @@ // First let's set up the gasmix and base gases for this template // We make the string from a gasmix in this proc because gases need to calculate their pressure var/datum/gas_mixture/gasmix = new - var/list/gaslist = gasmix.gases gasmix.temperature = rand(minimum_temp, maximum_temp) + var/list/cached_moles = gasmix.moles for(var/i in base_gases) - ADD_GAS(i, gaslist) - gaslist[i][MOLES] = base_gases[i] + cached_moles[i] = base_gases[i] // Now let the random choices begin var/datum/gas/gastype @@ -49,22 +48,21 @@ amount *= pressure_scalar // If we pick a really small target pressure we want roughly the same mix but less of it all amount = CEILING(amount, 0.1) - ASSERT_GAS_IN_LIST(gastype, gaslist) - gaslist[gastype][MOLES] += amount + cached_moles[gastype] += amount // Ensure that minimum_pressure is actually a hard lower limit - target_pressure = clamp(target_pressure, minimum_pressure + (gaslist[gastype][MOLES] * 0.1), maximum_pressure) + target_pressure = clamp(target_pressure, minimum_pressure + (cached_moles[gastype] * 0.1), maximum_pressure) // That last one put us over the limit, remove some of it while(gasmix.return_pressure() > target_pressure) - gaslist[gastype][MOLES] -= gaslist[gastype][MOLES] * 0.1 - gaslist[gastype][MOLES] = FLOOR(gaslist[gastype][MOLES], 0.1) + cached_moles[gastype] -= cached_moles[gastype] * 0.1 + cached_moles[gastype] = FLOOR(cached_moles[gastype], 0.1) gasmix.garbage_collect() // Now finally lets make that string var/list/gas_string_builder = list() - for(var/i in gaslist) - var/list/gas = gaslist[i] - gas_string_builder += "[gas[GAS_META][META_GAS_ID]]=[gas[MOLES]]" + var/list/cached_gas_id = GAS_META[META_GAS_ID] + for(var/gas_id, gas_amount in cached_moles) + gas_string_builder += "[cached_gas_id[gas_id]]=[gas_amount]" gas_string_builder += "TEMP=[gasmix.temperature]" gas_string = gas_string_builder.Join(";") diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 3caa3d0fe49..48bcacf938a 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -513,8 +513,6 @@ /datum/symptom/heal/plasma/CanHeal(datum/disease/advance/our_disease) var/mob/living/carbon/carbon_host = our_disease.affected_mob var/datum/gas_mixture/environment - var/list/gases - . = 0 // Check internals @@ -525,16 +523,14 @@ if(internals_tank) var/datum/gas_mixture/tank_contents = internals_tank.return_air() if(tank_contents && round(tank_contents.return_pressure())) // make sure the tank is not empty or 0 pressure - if(tank_contents.gases[/datum/gas/plasma]) + if(tank_contents.moles[/datum/gas/plasma]) // higher tank distribution pressure leads to more healing, but once you get to about 15kpa you reach the max . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, internals_tank.distribute_pressure * HEALING_PER_BREATH_PRESSURE) else // Check environment if(carbon_host.loc) environment = carbon_host.loc.return_air() - if(environment) - gases = environment.gases - if(gases[/datum/gas/plasma]) - . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, gases[/datum/gas/plasma][MOLES] * HEALING_PER_MOL) + if(environment && environment.moles[/datum/gas/plasma]) + . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, environment.moles[/datum/gas/plasma] * HEALING_PER_MOL) // Check for reagents in bloodstream if(carbon_host.reagents.has_reagent(/datum/reagent/toxin/plasma, needs_metabolizing = TRUE)) diff --git a/code/datums/elements/atmos_requirements.dm b/code/datums/elements/atmos_requirements.dm index 1e7b5ba9368..39f06dbd6be 100644 --- a/code/datums/elements/atmos_requirements.dm +++ b/code/datums/elements/atmos_requirements.dm @@ -77,14 +77,14 @@ return TRUE /datum/element/atmos_requirements/proc/get_atmos_req_list(turf/open/open_turf) - var/open_turf_gases = open_turf.air.gases + var/open_turf_moles = open_turf.air.moles open_turf.air.assert_gases(/datum/gas/oxygen, /datum/gas/pluoxium, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma) var/list/return_gases = list() - return_gases["plas"] = open_turf_gases[/datum/gas/plasma][MOLES] - return_gases["oxy"] = open_turf_gases[/datum/gas/oxygen][MOLES] + (open_turf_gases[/datum/gas/pluoxium][MOLES] * PLUOXIUM_PROPORTION) - return_gases["n2"] = open_turf_gases[/datum/gas/nitrogen][MOLES] - return_gases["co2"] = open_turf_gases[/datum/gas/carbon_dioxide][MOLES] + return_gases["plas"] = open_turf_moles[/datum/gas/plasma] + return_gases["oxy"] = open_turf_moles[/datum/gas/oxygen] + (open_turf_moles[/datum/gas/pluoxium] * PLUOXIUM_PROPORTION) + return_gases["n2"] = open_turf_moles[/datum/gas/nitrogen] + return_gases["co2"] = open_turf_moles[/datum/gas/carbon_dioxide] open_turf.air.garbage_collect() diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 77e21e5a928..b234481babc 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -187,13 +187,12 @@ if(!floor_gas_mixture) return - var/list/floor_gases = floor_gas_mixture.gases var/static/list/gases_to_check = list( /datum/gas/oxygen = list(/obj/item/organ/lungs::safe_oxygen_min, 100), /datum/gas/nitrogen, /datum/gas/carbon_dioxide = list(0, /obj/item/organ/lungs::safe_co2_max) ) - if(!check_gases(floor_gases, gases_to_check)) + if(!floor_gas_mixture.check_gases(gases_to_check)) return FALSE // Aim for goldilocks temperatures and pressure diff --git a/code/datums/mutations/olfaction.dm b/code/datums/mutations/olfaction.dm index c9b6043872b..fda296fe0e1 100644 --- a/code/datums/mutations/olfaction.dm +++ b/code/datums/mutations/olfaction.dm @@ -50,9 +50,8 @@ . = ..() // Can we sniff? is there miasma in the air? var/datum/gas_mixture/air = cast_on.loc.return_air() - var/list/cached_gases = air.gases - if(cached_gases[/datum/gas/miasma]) + if(air.moles[/datum/gas/miasma]) cast_on.adjust_disgust(sensitivity * 45) to_chat(cast_on, span_warning("With your overly sensitive nose, \ you get a whiff of stench and feel sick! Try moving to a cleaner area!")) diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index 28796766cdf..07df99eeb2b 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -183,7 +183,7 @@ return TRUE var/datum/gas_mixture/air = owner.loc.return_air() - if(!air.gases[/datum/gas/oxygen] || air.gases[/datum/gas/oxygen][MOLES] < 1) + if(air.moles[/datum/gas/oxygen] < 1) qdel(src) return TRUE diff --git a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm index db7eff67cc4..6101c3f69a9 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm @@ -369,7 +369,7 @@ /// Called when there isn't enough water to breath /obj/item/organ/lungs/fish/proc/on_low_water(mob/living/carbon/breather, datum/gas_mixture/breath, water_pp) breather.throw_alert(ALERT_NOT_ENOUGH_WATER, /atom/movable/screen/alert/not_enough_water) - var/gas_breathed = handle_suffocation(breather, water_pp, safe_water_level, breath.gases[/datum/gas/water_vapor][MOLES]) + var/gas_breathed = handle_suffocation(breather, water_pp, safe_water_level, breath.moles[/datum/gas/water_vapor]) if(water_pp) breathe_gas_volume(breath, /datum/gas/water_vapor, /datum/gas/carbon_dioxide, volume = gas_breathed) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 6fa67ce9af5..b5228803e61 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -286,7 +286,7 @@ if(environment.temperature >= FIRE_MINIMUM_TEMPERATURE_TO_EXIST) return FIRELOCK_ALARM_TYPE_HOT - if(environment.gases[/datum/gas/antinoblium] && environment.gases[/datum/gas/antinoblium][MOLES] > MINIMUM_MOLE_COUNT) + if(environment.moles[/datum/gas/antinoblium] > MINIMUM_MOLE_COUNT) return FIRELOCK_ALARM_TYPE_HOT if(environment.temperature <= BODYTEMP_COLD_DAMAGE_LIMIT) return FIRELOCK_ALARM_TYPE_COLD diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm index cea1190aa66..5c5d108eeb3 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm @@ -296,8 +296,8 @@ QDEL_NULL(hotspot) var/datum/gas_mixture/air = location.air - if (air.gases[/datum/gas/plasma]) - var/scrub_amt = min(30, air.gases[/datum/gas/plasma][MOLES]) //Absorb some plasma + if (air.moles[/datum/gas/plasma]) + var/scrub_amt = min(30, air.moles[/datum/gas/plasma]) //Absorb some plasma air.adjust_gas(/datum/gas/plasma, -scrub_amt) absorbed_plasma += scrub_amt if (air.temperature > T20C) @@ -452,10 +452,10 @@ for(var/obj/effect/hotspot/fire in location) qdel(fire) - var/list/gases = air.gases - for(var/gas_type in gases) - if(!(ignored_gases[gas_type])) - gases[gas_type][MOLES] = 0 + var/list/cached_moles = air.moles + for(var/gas_id in cached_moles) + if(!(ignored_gases[gas_id])) + cached_moles[gas_id] = 0 air.garbage_collect() for(var/obj/machinery/atmospherics/components/unary/comp in location) diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm index cca69643fb3..1f7c671555e 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm @@ -297,8 +297,8 @@ if(!distcheck || get_dist(location, chilly) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air air.temperature = temperature - if(air.gases[/datum/gas/plasma]) - var/mole_count = air.gases[/datum/gas/plasma][MOLES] + if(air.moles[/datum/gas/plasma]) + var/mole_count = air.moles[/datum/gas/plasma] air.adjust_gas(/datum/gas/nitrogen, mole_count) air.adjust_gas(/datum/gas/plasma, -mole_count) air.garbage_collect() diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 20904faff4e..acdf14f57aa 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -212,10 +212,10 @@ if(total_moles > 0) message += span_notice("Moles: [round(total_moles, 0.01)] mol") - var/list/cached_gases = air.gases - for(var/id in cached_gases) - var/gas_concentration = cached_gases[id][MOLES]/total_moles - message += span_notice("[cached_gases[id][GAS_META][META_GAS_NAME]]: [round(cached_gases[id][MOLES], 0.01)] mol ([round(gas_concentration*100, 0.01)] %)") + var/list/cached_gas_name = GAS_META[META_GAS_NAME] + for(var/id, amount in air.moles) + var/gas_concentration = amount / total_moles + message += span_notice("[cached_gas_name[id]]: [round(amount, 0.01)] mol ([round(gas_concentration*100, 0.01)] %)") message += span_notice("Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)") message += span_notice("Volume: [volume] L") message += span_notice("Pressure: [round(pressure, 0.01)] kPa") diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 80d68c1beb5..724d3cb37db 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -509,7 +509,7 @@ var/datum/gas_mixture/our_mix = return_air() our_mix.assert_gases(/datum/gas/plasma, /datum/gas/oxygen) - var/fuel_moles = our_mix.gases[/datum/gas/plasma][MOLES] + our_mix.gases[/datum/gas/oxygen][MOLES]/6 + var/fuel_moles = our_mix.moles[/datum/gas/plasma] + our_mix.moles[/datum/gas/oxygen]/6 our_mix.garbage_collect() var/datum/gas_mixture/bomb_mixture = our_mix.copy() var/strength = 1 diff --git a/code/game/objects/items/weaponry/ranged/flamethrower.dm b/code/game/objects/items/weaponry/ranged/flamethrower.dm index ae9cb7dd809..7300a342693 100644 --- a/code/game/objects/items/weaponry/ranged/flamethrower.dm +++ b/code/game/objects/items/weaponry/ranged/flamethrower.dm @@ -230,8 +230,8 @@ var/datum/gas_mixture/tank_mix = ptank.return_air() var/datum/gas_mixture/air_transfer = tank_mix.remove_ratio(release_amount) - if(air_transfer.gases[/datum/gas/plasma]) - var/moles = air_transfer.gases[/datum/gas/plasma][MOLES] * 5 //Suffering + if(air_transfer.moles[/datum/gas/plasma]) + var/moles = air_transfer.moles[/datum/gas/plasma] * 5 //Suffering air_transfer.set_gas(/datum/gas/plasma, moles) target.assume_air(air_transfer) //Burn it based on transferred gas diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm index f56ac10b79e..701d1d4e58c 100644 --- a/code/game/objects/structures/bonfire.dm +++ b/code/game/objects/structures/bonfire.dm @@ -98,10 +98,8 @@ /obj/structure/bonfire/proc/check_oxygen() if(isopenturf(loc)) var/turf/open/bonfire_turf = loc - if(bonfire_turf.air) - var/loc_gases = bonfire_turf.air.gases - if(loc_gases[/datum/gas/oxygen] && loc_gases[/datum/gas/oxygen][MOLES] >= 5) - return TRUE + if(bonfire_turf.air?.moles[/datum/gas/oxygen] >= 5) + return TRUE return FALSE /obj/structure/bonfire/proc/start_burning() diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index dfd4998b7ad..944899bc669 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -268,7 +268,6 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( return var/datum/gas_mixture/total = new//Holders to assimilate air from nearby turfs - var/list/total_gases = total.gases //Stolen blatently from self_breakdown var/list/turf_list = atmos_adjacent_turfs + src var/turflen = turf_list.len @@ -284,14 +283,13 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( energy += mix.temperature * capacity heat_cap += capacity - var/list/giver_gases = mix.gases - for(var/giver_id in giver_gases) - ASSERT_GAS_IN_LIST(giver_id, total_gases) - total.adjust_gas(giver_id, giver_gases[giver_id][MOLES]) + for(var/giver_id, amount in mix.moles) + total.adjust_gas(giver_id, amount) total.temperature = energy / heat_cap - for(var/id in total_gases) - total_gases[id][MOLES] /= turflen + var/list/cached_total_moles = total.moles + for(var/id in cached_total_moles) + cached_total_moles[id] /= turflen for(var/turf/open/turf in turf_list) turf.air.copy_from(total) diff --git a/code/modules/atmospherics/Atmospherics.md b/code/modules/atmospherics/Atmospherics.md index 99679e13325..4401379f0ae 100644 --- a/code/modules/atmospherics/Atmospherics.md +++ b/code/modules/atmospherics/Atmospherics.md @@ -114,21 +114,28 @@ Each gas mixture has an associative list, gases, which maps according to a key t Each type of gas is defined by defining a new subtype of /datum/gas. These datums do not get instantiated; they merely serve as a convenient and familiar means for a coder unfamiliar with the inner workings of listmos to define a new gas. Additionally, the type paths serve a second use as the keys used to access a particular gas within the gases list. It is easiest to demonstrate the manipulation of gas, including these list accesses, with an example. +### Vectorized xgm-like system +Current system uses two associative arrays: `moles` and `moles_archived` with the key being `/datum/gas`. The gas metadata array is stored in a static variable `gas_mixture::gas_meta`. The layout of keys in the array is `gas_meta[META_INDEX][gas_path]`. This allows us to use vector functions like `values_sum` and `values_dot` (introduced in BYOND v516). This approach showed improvement of ~20% on process_cell and memory footprint stayed the same. + +While these vector functions are extremely fast, they can only work with associative arrays of number. To calculate total moles you would write `values_sum(moles)` and to calculate heat capacity, it would be `values_dot(moles, gas_meta[META_GAS_SPECIFIC_HEAT])`. This does not seem like a lot, but when a subsytem is doing 1000 updates each simulation tick every microsecond matters. + +Another benefit of using one-dimensional associative arrays is that for any arithmetic or logic operation a missing key acts like a 0. For example you could write `moles[/datum/gas/oxygen] += 10` even if `/datum/gas/oxygen` is not in the list. + ### Interfacing with a Gas Mixture ```DM var/datum/gas_mixture/air = new air.assert_gas(/datum/gas/oxygen) -air.gases[/datum/gas/oxygen][MOLES] = 100 -world << air.gases[/datum/gas/oxygen][GAS_META][META_GAS_NAME] //outputs "Oxygen" -world << air.gases.heat_capacity() //outputs 2000 (100 mol * 20 J/K/mol) -air.gases[/datum/gas/oxygen][MOLES] -= 110 +air.moles[/datum/gas/oxygen] = 100 +world << air.gas_meta[META_GAS_NAME][/datum/gas/oxygen] //outputs "Oxygen" +world << air.heat_capacity() //outputs 2000 (100 mol * 20 J/K/mol) +air.moles[/datum/gas/oxygen] -= 110 air.garbage_collect() //oxygen is now removed from the gases list, since it was empty ``` _Snippet 4.2: gas mixture usage examples_ -Of particular note in this snippet are the two procs assert_gas() and garbage_collect(). These procs are very important while interfacing with gas mixtures. If you are uncertain about whether a given mixture has a particular gas, you must use assert_gas() before any reads or writes from the gas. If you fail to use assert_gas() then there will be runtime errors when you try to access the inner lists. When you remove any number of moles from a given gas, be sure to call garbage_collect(). This proc removes all gases which have mole counts less than or equal to 0. This is a memory and performance enhancement for list accesses achieved by reducing the size of the list, and also saves us from having to do sanity checks for negative moles whenever gas is removed. As a quick reference, here is a list of common procs/vars/list indices which the average coder may wish to use when interfacing with a gas mixture. +Of particular note in this snippet are the two procs assert_gas() and garbage_collect(). These procs are very important while interfacing with gas mixtures. If you are uncertain about whether a given mixture has a particular gas, you must use assert_gas() before any reads or writes from the gas. When you remove any number of moles from a given gas, be sure to call garbage_collect(). This proc removes all gases which have mole counts less than or equal to 0. This is a memory and performance enhancement for list accesses achieved by reducing the size of the list, and also saves us from having to do sanity checks for negative moles whenever gas is removed. As a quick reference, here is a list of common procs/vars/list indices which the average coder may wish to use when interfacing with a gas mixture. ##### Gas Mixture Datum @@ -149,9 +156,13 @@ It's also implemented by `/datum/gas_mixture/immutable/planetary`, which is used ##### Gas List -- _`gases[path][MOLES]`_ - Quantity of a particular gas within a mixture. -- _`gases[path][GAS_META][META_GAS_NAME]`_ - The long name of a gas, ex. "Oxygen" or "Hyper-noblium" -- _`gases[path][GAS_META][META_GAS_ID]`_ - The internal ID of a given gas, ex. "o2" or "nob" +- _`moles[path]`_ - Quantity of a particular gas within a mixture. +- _`gas_meta[META_GAS_NAME][path]`_ - The long name of a gas, ex. "Oxygen" or "Hyper-noblium" +- _`gas_meta[META_GAS_ID][path]`_ - The internal ID of a given gas, ex. "o2" or "nob" + +##### Gas Meta +As was said previously gas metadata is stored in a static variable `gas_mixture.gas_meta`. This is done so you can easily access this variable from within gas_mixture, but if you are outside of gas_mixture code and you need gas metadata you can use convenience macro `GAS_META`. There is also third name for that list and it is `GLOB.meta_gas_info`. All of those variables point to the same list and you can use either. As the rule of thumb, in the performance critical code use `GAS_META` or `gas_meta`, otherwise `GLOB.meta_gas_info`. + ### Reactions diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm index 6a82fe99ed5..a0ab9be883f 100644 --- a/code/modules/atmospherics/environmental/LINDA_fire.dm +++ b/code/modules/atmospherics/environmental/LINDA_fire.dm @@ -25,38 +25,34 @@ exposed_temperature = TCMB CRASH("[src].hotspot_expose() called with exposed_temperature < [TCMB]") //If the air doesn't exist we just return false - var/list/air_gases = air?.gases - if(!air_gases) + var/cached_moles = air?.moles + if(!cached_moles) return - . = air_gases[/datum/gas/oxygen] - var/oxy = . ? .[MOLES] : 0 - if (oxy < 0.5) + if (cached_moles[/datum/gas/oxygen] < 0.5) return - . = air_gases[/datum/gas/plasma] - var/plas = . ? .[MOLES] : 0 - . = air_gases[/datum/gas/tritium] - var/trit = . ? .[MOLES] : 0 - . = air_gases[/datum/gas/hydrogen] - var/h2 = . ? .[MOLES] : 0 - . = air_gases[/datum/gas/freon] - var/freon = . ? .[MOLES] : 0 + + var/plas_trit_h2_threshold = (\ + cached_moles[/datum/gas/plasma] > 0.5\ + || cached_moles[/datum/gas/tritium] > 0.5\ + || cached_moles[/datum/gas/hydrogen] > 0.5) + var/freon_threshold = (cached_moles[/datum/gas/freon] > 0.5) if(active_hotspot) if(soh) - if(plas > 0.5 || trit > 0.5 || h2 > 0.5) + if(plas_trit_h2_threshold) if(active_hotspot.temperature < exposed_temperature) active_hotspot.temperature = exposed_temperature if(active_hotspot.volume < exposed_volume) active_hotspot.volume = exposed_volume - else if(freon > 0.5) + else if(freon_threshold) if(active_hotspot.temperature > exposed_temperature) active_hotspot.temperature = exposed_temperature if(active_hotspot.volume < exposed_volume) active_hotspot.volume = exposed_volume return - if(((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (plas > 0.5 || trit > 0.5 || h2 > 0.5)) || \ - ((exposed_temperature < FREON_MAXIMUM_BURN_TEMPERATURE) && (freon > 0.5))) + if (((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && plas_trit_h2_threshold) || \ + ((exposed_temperature < FREON_MAXIMUM_BURN_TEMPERATURE) && freon_threshold)) new /obj/effect/hotspot(src, exposed_volume * 25, exposed_temperature) SSair.add_to_active(src) @@ -282,7 +278,7 @@ color = list(LERP(0.3, 1, 1-greyscale_fire) * heat_r,0.3 * heat_g * greyscale_fire,0.3 * heat_b * greyscale_fire, 0.59 * heat_r * greyscale_fire,LERP(0.59, 1, 1-greyscale_fire) * heat_g,0.59 * heat_b * greyscale_fire, 0.11 * heat_r * greyscale_fire,0.11 * heat_g * greyscale_fire,LERP(0.11, 1, 1-greyscale_fire) * heat_b, 0,0,0) alpha = heat_a -#define INSUFFICIENT(path) (!location.air.gases[path] || location.air.gases[path][MOLES] < 0.5) +#define INSUFFICIENT(path) (!location.air.moles[path] || location.air.moles[path] < 0.5) /** * Regular process proc for hotspots governed by the controller. diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 827510313e2..4407402b8b6 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -173,10 +173,9 @@ src.atmos_overlay_types = null return - var/list/gases = air.gases - + var/list/moles = air.moles var/list/new_overlay_types - GAS_OVERLAYS(gases, new_overlay_types, src) + GAS_OVERLAYS(moles, new_overlay_types, src) if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added @@ -306,7 +305,7 @@ our_excited_group = excited_group //update our cache if(our_excited_group && enemy_excited_group && enemy_tile.excited) //If you're both excited, no need to compare right? should_share_air = TRUE - else if(our_air.compare(enemy_air, ARCHIVE)) //Lets see if you're up for it + else if(our_air.compare(enemy_air, /*cmp_archive = */ TRUE)) //Lets see if you're up for it SSair.add_to_active(enemy_tile) //Add yourself young man var/datum/excited_group/existing_group = our_excited_group || enemy_excited_group || new if(!our_excited_group) @@ -334,7 +333,7 @@ var/datum/gas_mixture/planetary_mix = SSair.planetary[initial_gas_mix] // archive ourself again so we don't accidentally share more gas than we currently have LINDA_CYCLE_ARCHIVE(src) - if(our_air.compare(planetary_mix, ARCHIVE)) + if(our_air.compare(planetary_mix, /*cmp_archive = */ TRUE)) if(!our_excited_group) var/datum/excited_group/new_group = new new_group.add_turf(src) @@ -471,7 +470,7 @@ var/datum/gas_mixture/shared_mix = new //make local for sanic speed - var/list/shared_gases = shared_mix.gases + var/list/shared_cached_moles = shared_mix.moles var/list/turf_list = src.turf_list var/turflen = turf_list.len var/imumutable_in_group = FALSE @@ -485,14 +484,14 @@ if(istype(group_member.air, /datum/gas_mixture/immutable)) imumutable_in_group = TRUE shared_mix.copy_from(group_member.air) //This had better be immutable young man - shared_gases = shared_mix.gases //update the cache + shared_cached_moles = shared_mix.moles //update the cache break // If we're planetary use THAT mix, and stop here if(group_member.planetary_atmos) imumutable_in_group = TRUE var/datum/gas_mixture/planetary_mix = SSair.planetary[group_member.initial_gas_mix] shared_mix.copy_from(planetary_mix) - shared_gases = shared_mix.gases // Cache update + shared_cached_moles = shared_mix.moles // Cache update break //"borrowing" this code from merge(), I need to play with the temp portion. Lets expand it out //temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity @@ -500,15 +499,13 @@ energy += mix.temperature * capacity heat_cap += capacity - var/list/giver_gases = mix.gases - for(var/giver_id in giver_gases) - ASSERT_GAS_IN_LIST(giver_id, shared_gases) - shared_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES] + for(var/gas_id, amount in mix.moles) + shared_cached_moles[gas_id] += amount if(!imumutable_in_group) shared_mix.temperature = energy / heat_cap - for(var/id in shared_gases) - shared_gases[id][MOLES] /= turflen + for(var/gas_id in shared_cached_moles) + shared_cached_moles[gas_id] /= turflen shared_mix.garbage_collect() for(var/turf/open/group_member as anything in turf_list) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 2324824426a..053ba55bb73 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -5,22 +5,14 @@ This prevents race conditions that arise based on the order of tile processing. */ GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm -GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) - -/proc/init_gaslist_cache() - var/list/gases = list() - for(var/id in GLOB.meta_gas_info) - var/list/cached_gas = new(3) - - gases[id] = cached_gas - - cached_gas[MOLES] = 0 - cached_gas[ARCHIVE] = 0 - cached_gas[GAS_META] = GLOB.meta_gas_info[id] - return gases /datum/gas_mixture - var/list/gases + /// Associative list of moles for each gas. List key is /datum/gas/, value is amount in moles + var/list/moles + /// Archived version of moles + var/list/moles_archive + /// Static list of gas meta data like heat capacity (initialized globally) + var/static/list/gas_meta /// The temperature of the gas mix in kelvin. Should never be lower then TCMB var/temperature = TCMB /// Used, like all archived variables, to ensure turf sharing is consistent inside a tick, no matter @@ -39,7 +31,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) var/pipeline_cycle = -1 /datum/gas_mixture/New(volume) - gases = new + moles = list() + moles_archive = list() if(!isnull(volume)) src.volume = volume if(src.volume <= 0) @@ -52,73 +45,74 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ///assert_gas(gas_id) - used to guarantee that the gas list for this id exists in gas_mixture.gases. ///Must be used before adding to a gas. May be used before reading from a gas. /datum/gas_mixture/proc/assert_gas(gas_id) - ASSERT_GAS(gas_id, src) + moles[gas_id] += 0 + moles_archive[gas_id] += 0 -///assert_gases(args) - shorthand for calling ASSERT_GAS() once for each gas type. +///assert_gases(args) - shorthand for calling assert_gas(gas_id) once for each gas type. /datum/gas_mixture/proc/assert_gases(...) - for(var/id in args) - ASSERT_GAS(id, src) + var/cached_moles = moles + var/cached_moles_archive = moles_archive + for(var/gas_id in args) + cached_moles[gas_id] += 0 + cached_moles_archive[gas_id] += 0 ///add_gas(gas_id) - similar to assert_gas(), but does not check for an existing gas list for this id. This can clobber existing gases. ///Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas(). /datum/gas_mixture/proc/add_gas(gas_id) - ADD_GAS(gas_id, gases) + moles[gas_id] = 0 + moles_archive[gas_id] = 0 ///add_gases(args) - shorthand for calling add_gas() once for each gas_type. /datum/gas_mixture/proc/add_gases(...) - var/cached_gases = gases - for(var/id in args) - ADD_GAS(id, cached_gases) + var/cached_moles = moles + var/cached_moles_archive = moles_archive + for(var/gas_id in args) + cached_moles[gas_id] = 0 + cached_moles_archive[gas_id] = 0 ///garbage_collect() - removes any gas list which is empty. ///If called with a list as an argument, only removes gas lists with IDs from that list. ///Must be used after subtracting from a gas. Must be used after assert_gas() ///if assert_gas() was called only to read from the gas. ///By removing empty gases, processing speed is increased. -/datum/gas_mixture/proc/garbage_collect(list/tocheck) - var/list/cached_gases = gases - for(var/id in (tocheck || cached_gases)) - if(QUANTIZE(cached_gases[id][MOLES]) <= 0) - cached_gases -= id +/datum/gas_mixture/proc/garbage_collect() + values_cut_under(moles, MOLAR_ACCURACY, TRUE) + values_cut_under(moles_archive, MOLAR_ACCURACY, TRUE) //PV = nRT ///joules per kelvin -/datum/gas_mixture/proc/heat_capacity(data = MOLES) - var/list/cached_gases = gases - . = 0 - for(var/_id, gas_data in cached_gases) - . += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] +/datum/gas_mixture/proc/heat_capacity() + return values_dot(moles, GAS_META[META_GAS_SPECIFIC_HEAT]) + +///joules per kelvin. Same as heat_capacity() for moles_archive. +// Separate function to reduce branches in a hot function +/datum/gas_mixture/proc/heat_capacity_archive() + return values_dot(moles_archive, GAS_META[META_GAS_SPECIFIC_HEAT]) /// Same as above except vacuums return HEAT_CAPACITY_VACUUM -/datum/gas_mixture/turf/heat_capacity(data = MOLES) - var/list/cached_gases = gases - . = 0 - for(var/_id, gas_data in cached_gases) - . += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] - if(!.) - . += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space +/datum/gas_mixture/turf/heat_capacity() + return values_dot(moles, GAS_META[META_GAS_SPECIFIC_HEAT]) || HEAT_CAPACITY_VACUUM + +/// Same as above except vacuums return HEAT_CAPACITY_VACUUM +// Separate function to reduce branches in a hot function +/datum/gas_mixture/turf/heat_capacity_archive() + return values_dot(moles_archive, GAS_META[META_GAS_SPECIFIC_HEAT]) || HEAT_CAPACITY_VACUUM /// Calculate moles /datum/gas_mixture/proc/total_moles() - var/cached_gases = gases - TOTAL_MOLES(cached_gases, .) + return values_sum(moles) /// Checks to see if gas amount exists in mixture. /// Do NOT use this in code where performance matters! /// It's better to batch calls to garbage_collect(), especially in places where you're checking many gastypes /datum/gas_mixture/proc/has_gas(gas_id, amount=0) - ASSERT_GAS(gas_id, src) - var/is_there_gas = amount < gases[gas_id][MOLES] - garbage_collect() - return is_there_gas + return amount < moles[gas_id] /// Calculate pressure in kilopascals /datum/gas_mixture/proc/return_pressure() if(volume) // to prevent division by zero - var/cached_gases = gases - TOTAL_MOLES(cached_gases, .) - return . * R_IDEAL_GAS_EQUATION * temperature / volume + return values_sum(moles) * R_IDEAL_GAS_EQUATION * temperature / volume return 0 /// Calculate temperature in kelvins @@ -132,7 +126,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /// Gets the gas visuals for everything in this mixture /datum/gas_mixture/proc/return_visuals(turf/z_context) var/list/output - GAS_OVERLAYS(gases, output, z_context) + GAS_OVERLAYS(moles, output, z_context) return output /// Calculate thermal energy in joules @@ -141,11 +135,12 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ///Update archived versions of variables. Returns: 1 in all cases /datum/gas_mixture/proc/archive() - var/list/cached_gases = gases + var/list/cached_moles = moles + var/list/cached_moles_archive = moles_archive temperature_archived = temperature - for(var/id in cached_gases) - cached_gases[id][ARCHIVE] = cached_gases[id][MOLES] + for(var/gas_id in cached_moles) + cached_moles_archive[gas_id] = cached_moles[gas_id] return TRUE @@ -162,20 +157,18 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) if(combined_heat_capacity) temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity - var/list/cached_gases = gases //accessing datum vars is slower than proc vars - var/list/giver_gases = giver.gases + var/list/cached_moles = moles //accessing datum vars is slower than proc vars + var/list/cached_giver_moles = giver.moles //gas transfer - for(var/giver_id in giver_gases) - ASSERT_GAS_IN_LIST(giver_id, cached_gases) - cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES] + for(var/gas_id in cached_giver_moles) + cached_moles[gas_id] += cached_giver_moles[gas_id] SEND_SIGNAL(src, COMSIG_GASMIX_MERGED) return TRUE // Set the gas specie within the gas mix to a set amount, if there is none it will be created at the target temp /datum/gas_mixture/proc/set_gas(gas_specie, amount) - ASSERT_GAS(gas_specie, src) - gases[gas_specie][MOLES] = amount + moles[gas_specie] = amount garbage_collect() /datum/gas_mixture/proc/set_temperature(target_temp) @@ -184,46 +177,46 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /// Add a specific amount of moles to specified gas or add a new gas to the mix /// amount is added so make it negative to remove /datum/gas_mixture/proc/adjust_gas(gas, amount) - ASSERT_GAS(gas, src) - gases[gas][MOLES] += QUANTIZE(amount) + moles[gas] += QUANTIZE(amount) garbage_collect() /// Add a specific amount of moles to all the gasses present or add a new gas to the mix ///gases_moles is an associative list of gas species to their amount to be added /datum/gas_mixture/proc/adjust_multiple_gases(list/gases_moles) - for(var/gas_specie in gases_moles) - ASSERT_GAS(gas_specie, src) - gases[gas_specie][MOLES] += gases_moles[gas_specie] + var/cached_moles = moles + for(var/gas_id in gases_moles) + cached_moles[gas_id] += gases_moles[gas_id] garbage_collect() /// Modify the gas list as to convert moles of gas species A to gas species B /// reactant and product are the gas species to convert and conversion_amount is the amount to be converted /datum/gas_mixture/proc/convert_gas(datum/gas/reactant, datum/gas/product, conversion_amount) - var/list/cached_gases = gases + var/list/cached_moles = moles assert_gases(reactant, product) - cached_gases[reactant][MOLES] -= QUANTIZE(conversion_amount) - cached_gases[product][MOLES] += QUANTIZE(conversion_amount) + cached_moles[reactant] -= QUANTIZE(conversion_amount) + cached_moles[product] += QUANTIZE(conversion_amount) garbage_collect() ///Proportionally removes amount of gas from the gas_mixture. ///Returns: gas_mixture with the gases removed /datum/gas_mixture/proc/remove(amount) - var/sum - var/list/cached_gases = gases - TOTAL_MOLES(cached_gases, sum) - amount = min(amount, sum) //Can not take more air than tile has! + + var/list/cached_moles = moles + var/total_moles = values_sum(cached_moles) + amount = min(amount, total_moles) //Can not take more air than tile has! if(amount <= 0) return null - var/ratio = amount / sum + var/ratio = amount / total_moles + var/datum/gas_mixture/removed = new type(volume) - var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars + var/list/cached_removed_moles = removed.moles //accessing datum vars is slower than proc vars removed.temperature = temperature - for(var/id in cached_gases) - ADD_GAS(id, removed.gases) - removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio) - cached_gases[id][MOLES] -= removed_gases[id][MOLES] + for(var/id in cached_moles) + cached_removed_moles[id] = QUANTIZE(cached_moles[id] * ratio) + cached_moles[id] -= cached_removed_moles[id] + garbage_collect() SEND_SIGNAL(src, COMSIG_GASMIX_REMOVED) @@ -237,15 +230,14 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) return removed ratio = min(ratio, 1) - var/list/cached_gases = gases + var/list/cached_moles = moles var/datum/gas_mixture/removed = new type(volume) - var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars + var/list/cached_removed_moles = removed.moles //accessing datum vars is slower than proc vars removed.temperature = temperature - for(var/id in cached_gases) - ADD_GAS(id, removed.gases) - removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio) - cached_gases[id][MOLES] -= removed_gases[id][MOLES] + for(var/id in cached_moles) + cached_removed_moles[id] = QUANTIZE(cached_moles[id] * ratio) + cached_moles[id] -= cached_removed_moles[id] garbage_collect() @@ -255,18 +247,17 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ///Removes an amount of a specific gas from the gas_mixture. ///Returns: gas_mixture with the gas removed /datum/gas_mixture/proc/remove_specific(gas_id, amount) - var/list/cached_gases = gases - amount = min(amount, cached_gases[gas_id][MOLES]) + var/list/cached_moles = moles + amount = min(amount, cached_moles[gas_id]) if(amount <= 0) return null var/datum/gas_mixture/removed = new type - var/list/removed_gases = removed.gases removed.temperature = temperature - ADD_GAS(gas_id, removed.gases) - removed_gases[gas_id][MOLES] = amount - cached_gases[gas_id][MOLES] -= amount + removed.moles[gas_id] = amount + cached_moles[gas_id] -= amount - garbage_collect(list(gas_id)) + // TODO(antropod): maybe use if (cached_moles[gas_id] < MOLAR_ACCURACY) cached_moles -= gas_id? + garbage_collect() return removed /datum/gas_mixture/proc/remove_specific_ratio(gas_id, ratio) @@ -274,16 +265,15 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) return null ratio = min(ratio, 1) - var/list/cached_gases = gases + var/list/cached_moles = moles var/datum/gas_mixture/removed = new type - var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars + var/list/cached_removed_moles = removed.moles //accessing datum vars is slower than proc vars removed.temperature = temperature - ADD_GAS(gas_id, removed.gases) - removed_gases[gas_id][MOLES] = QUANTIZE(cached_gases[gas_id][MOLES] * ratio) - cached_gases[gas_id][MOLES] -= removed_gases[gas_id][MOLES] + cached_removed_moles[gas_id] = QUANTIZE(cached_moles[gas_id] * ratio) + cached_moles[gas_id] -= cached_removed_moles[gas_id] - garbage_collect(list(gas_id)) + garbage_collect() return removed @@ -301,33 +291,33 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) var/min_p_delta = 0.1 var/total_volume = volume + other.volume - var/list/gas_list = gases | other.gases + var/list/cached_moles = moles + var/list/cached_other_moles = other.moles + var/list/gas_list = cached_moles | cached_other_moles for(var/gas_id in gas_list) assert_gas(gas_id) other.assert_gas(gas_id) //math is under the assumption temperatures are equal - if(abs(gases[gas_id][MOLES] / volume - other.gases[gas_id][MOLES] / other.volume) > min_p_delta / (R_IDEAL_GAS_EQUATION * temperature)) + if(abs(cached_moles[gas_id] / volume - cached_other_moles[gas_id] / other.volume) > min_p_delta / (R_IDEAL_GAS_EQUATION * temperature)) . = TRUE - var/total_moles = gases[gas_id][MOLES] + other.gases[gas_id][MOLES] - gases[gas_id][MOLES] = total_moles * (volume/total_volume) - other.gases[gas_id][MOLES] = total_moles * (other.volume/total_volume) + var/total_moles = cached_moles[gas_id] + cached_other_moles[gas_id] + cached_moles[gas_id] = total_moles * (volume/total_volume) + cached_other_moles[gas_id] = total_moles * (other.volume/total_volume) garbage_collect() other.garbage_collect() ///Creates new, identical gas mixture ///Returns: duplicate gas mixture /datum/gas_mixture/proc/copy() - // Type as /list/list to make spacemandmm happy with the inlined access we do down there - var/list/list/cached_gases = gases + var/list/cached_moles = moles var/datum/gas_mixture/copy = new type - var/list/copy_gases = copy.gases + var/list/copy_cached_moles = copy.moles + var/list/copy_cached_moles_archive = copy.moles_archive copy.temperature = temperature - for(var/id in cached_gases) - // Sort of a sideways way of doing ADD_GAS() - // Faster tho, gotta save those cpu cycles - copy_gases[id] = cached_gases[id].Copy() - copy_gases[id][ARCHIVE] = 0 + for(var/gas_id in cached_moles) + copy_cached_moles[gas_id] = cached_moles[gas_id] + copy_cached_moles_archive[gas_id] = 0 return copy @@ -335,33 +325,33 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ///Copies variables from sample ///Returns: TRUE if we are mutable, FALSE otherwise /datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample) - var/list/cached_gases = gases //accessing datum vars is slower than proc vars - // Type as /list/list to make spacemandmm happy with the inlined access we do down there - var/list/list/sample_gases = sample.gases + var/list/cached_moles = moles //accessing datum vars is slower than proc vars + var/list/cached_moles_archive = moles_archive + var/list/sample_cached_moles = sample.moles //remove all gases - cached_gases.Cut() + cached_moles.Cut() + cached_moles_archive.Cut() temperature = sample.temperature - for(var/id in sample_gases) - cached_gases[id] = sample_gases[id].Copy() - cached_gases[id][ARCHIVE] = 0 + for(var/gas_id in sample_cached_moles) + cached_moles[gas_id] = sample_cached_moles[gas_id] + cached_moles_archive[gas_id] = 0 return TRUE ///Copies variables from sample, moles multiplicated by partial ///Returns: TRUE if we are mutable, FALSE otherwise /datum/gas_mixture/proc/copy_from_ratio(datum/gas_mixture/sample, partial = 1) - var/list/cached_gases = gases //accessing datum vars is slower than proc vars - var/list/sample_gases = sample.gases + var/list/cached_moles = moles //accessing datum vars is slower than proc vars + var/list/sample_cached_moles = sample.moles //remove all gases not in the sample - cached_gases &= sample_gases + cached_moles &= sample_cached_moles temperature = sample.temperature - for(var/id in sample_gases) - ASSERT_GAS_IN_LIST(id, cached_gases) - cached_gases[id][MOLES] = sample_gases[id][MOLES] * partial + for(var/gas_id in sample_cached_moles) + cached_moles[gas_id] = sample_cached_moles[gas_id] * partial return TRUE @@ -370,18 +360,20 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /// If we don't retain this, we will get negative moles. Don't do it /// Returns: amount of gas exchanged (+ if sharer received) /datum/gas_mixture/proc/share(datum/gas_mixture/sharer, our_coeff, sharer_coeff) - var/list/cached_gases = gases - var/list/sharer_gases = sharer.gases + var/list/cached_moles = moles + var/list/cached_moles_archive = moles_archive + var/list/sharer_cached_moles = sharer.moles + var/list/sharer_cached_moles_archive = sharer.moles_archive - var/list/only_in_sharer = sharer_gases - cached_gases - var/list/only_in_cached = cached_gases - sharer_gases + var/list/only_in_sharer = sharer_cached_moles - cached_moles + var/list/only_in_cached = cached_moles - sharer_cached_moles var/temperature_delta = temperature_archived - sharer.temperature_archived - var/abs_temperature_delta = abs(temperature_delta) + var/temp_delta_threshold = abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER var/old_self_heat_capacity = 0 var/old_sharer_heat_capacity = 0 - if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + if(temp_delta_threshold) old_self_heat_capacity = heat_capacity() old_sharer_heat_capacity = sharer.heat_capacity() @@ -394,15 +386,16 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) //GAS TRANSFER //Prep - for(var/id in only_in_sharer) //create gases not in our cache - ADD_GAS(id, cached_gases) - for(var/id in only_in_cached) //create gases not in the sharing mix - ADD_GAS(id, sharer_gases) + for(var/gas_id in only_in_sharer) //create gases not in our cache + cached_moles[gas_id] = 0 + cached_moles_archive[gas_id] = 0 + for(var/gas_id in only_in_cached) //create gases not in the sharing mix + sharer_cached_moles[gas_id] = 0 + sharer_cached_moles_archive[gas_id] = 0 - for(var/id in cached_gases) //transfer gases - var/gas = cached_gases[id] - var/sharergas = sharer_gases[id] - var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE]) //the amount of gas that gets moved between the mixtures + var/list/cached_specific_heat = GAS_META[META_GAS_SPECIFIC_HEAT] + for(var/gas_id in cached_moles) //transfer gases + var/delta = QUANTIZE(cached_moles_archive[gas_id] - sharer_cached_moles_archive[gas_id]) //the amount of gas that gets moved between the mixtures if(!delta) continue @@ -414,22 +407,22 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) else delta = delta * sharer_coeff - if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/gas_heat_capacity = delta * gas[GAS_META][META_GAS_SPECIFIC_HEAT] + if(temp_delta_threshold) + var/gas_heat_capacity = delta * cached_specific_heat[gas_id] if(delta > 0) heat_capacity_self_to_sharer += gas_heat_capacity else heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative. - gas[MOLES] -= delta - sharergas[MOLES] += delta + cached_moles[gas_id] -= delta + sharer_cached_moles[gas_id] += delta moved_moles += delta abs_moved_moles += abs(delta) last_share = abs_moved_moles //THERMAL ENERGY TRANSFER - if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + if(temp_delta_threshold) 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 @@ -452,10 +445,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) sharer.garbage_collect() if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - var/our_moles - TOTAL_MOLES(cached_gases,our_moles) - var/their_moles - TOTAL_MOLES(sharer_gases,their_moles) + var/our_moles = values_sum(cached_moles) + var/their_moles = values_sum(sharer_cached_moles) return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume ///Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length @@ -466,8 +457,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) sharer_temperature = sharer.temperature_archived var/temperature_delta = temperature_archived - sharer_temperature if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity(ARCHIVE) - sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity(ARCHIVE) + var/self_heat_capacity = heat_capacity_archive() + sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity_archive() if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) // coefficient applied first because some turfs have very big heat caps. @@ -483,27 +474,21 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) //thermal energy of the system (self and sharer) is unchanged ///Compares sample to self to see if within acceptable ranges that group processing may be enabled -///Takes the gas index to read from as a second arg (either MOLES or ARCHIVE) +///Takes the bool as a second arg to read to read archived values for moles and temperature ///Returns: a string indicating what check failed, or "" if check passes -/datum/gas_mixture/proc/compare(datum/gas_mixture/sample, index) - var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars - var/list/cached_gases = gases - var/moles_sum = 0 +/datum/gas_mixture/proc/compare(datum/gas_mixture/sample, cmp_archive) + var/list/cached_moles = (cmp_archive) ? moles_archive : moles + var/list/sample_cached_moles = (cmp_archive) ? sample.moles_archive : sample.moles //accessing datum vars is slower than proc vars - for(var/id in cached_gases | sample_gases) // compare gases from either mixture - // Yes this is actually fast. I too hate it here - var/gas_moles = cached_gases[id]?[index] || 0 - var/sample_moles = sample_gases[id]?[index] || 0 - // Brief explanation. We are much more likely to not pass this first check then pass the first and fail the second - // Because of this, double calculating the delta is FASTER then inserting it into a var - if(abs(gas_moles - sample_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - if(abs(gas_moles - sample_moles) > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE) - return id - // similarly, we will rarely get cut off, so this is cheaper then doing it later - moles_sum += gas_moles + for(var/gas_id in cached_moles | sample_cached_moles) // compare gases from either mixture + var/gas_moles = cached_moles[gas_id] // it can be null, but everything coerce to 0 after, so we save JMP and Tst + var/sample_moles = sample_cached_moles[gas_id] + var/abs_delta = abs(gas_moles - sample_moles) + if((abs_delta > MINIMUM_MOLES_DELTA_TO_MOVE) && (abs_delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)) + return gas_id - if(moles_sum > MINIMUM_MOLES_DELTA_TO_MOVE) //Don't consider temp if there's not enough mols - if(index == ARCHIVE) + if(values_sum(cached_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) //Don't consider temp if there's not enough mols + if(cmp_archive) if(abs(temperature_archived - sample.temperature_archived) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) return "temp" else @@ -516,8 +501,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ///Returns: 1 if any reaction took place; 0 otherwise /datum/gas_mixture/proc/react(datum/holder) . = NO_REACTION - var/list/cached_gases = gases - if(!length(cached_gases)) + var/list/cached_moles = moles + if(!length(cached_moles)) return var/list/pre_formation = list() @@ -525,7 +510,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) var/list/post_formation = list() var/list/fires = list() var/list/gas_reactions = SSair.gas_reactions - for(var/gas_id in cached_gases) + for(var/gas_id in cached_moles) var/list/reaction_set = gas_reactions[gas_id] if(!reaction_set) continue @@ -540,7 +525,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) return //Fuck you - if(cached_gases[/datum/gas/hypernoblium] && cached_gases[/datum/gas/hypernoblium][MOLES] >= REACTION_OPPRESSION_THRESHOLD && temperature > REACTION_OPPRESSION_MIN_TEMP) + if(cached_moles[/datum/gas/hypernoblium] >= REACTION_OPPRESSION_THRESHOLD && temperature > REACTION_OPPRESSION_MIN_TEMP) return STOP_REACTIONS reaction_results = new @@ -556,7 +541,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) for(var/id in reqs) if (id == "MIN_TEMP" || id == "MAX_TEMP") continue - if(!cached_gases[id] || cached_gases[id][MOLES] < reqs[id]) + if(cached_moles[id] < reqs[id]) continue reaction_loop //at this point, all requirements for the reaction are satisfied. we can now react() @@ -571,8 +556,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /** * Returns the partial pressure of the gas in the breath based on BREATH_VOLUME * eg: - * Plas_PP = get_breath_partial_pressure(gas_mixture.gases[/datum/gas/plasma][MOLES]) - * O2_PP = get_breath_partial_pressure(gas_mixture.gases[/datum/gas/oxygen][MOLES]) + * Plas_PP = get_breath_partial_pressure(gas_mixture.moles[/datum/gas/plasma]) + * O2_PP = get_breath_partial_pressure(gas_mixture.moles[/datum/gas/oxygen]) * get_breath_partial_pressure(gas_mole_count) --> PV = nRT, P = nRT/V * * 10/20*5 = 2.5 @@ -779,23 +764,52 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /// Convert a gas mixture to a string (ie. "o2=22;n2=82;TEMP=180") /// Rounds all temperature and gases to 0.01 and skips any gases less than that amount /datum/gas_mixture/proc/to_string() - var/list/cached_gases = gases + var/list/cached_moles = moles var/rounded_temp = round(temperature, 0.01) var/list/atmos_contents = list() var/temperature_str = "TEMP=[num2text(rounded_temp)]" - if(!length(cached_gases) || total_moles() < 0.01) + if(!length(cached_moles) || total_moles() < 0.01) return temperature_str - for(var/gas_path in cached_gases) - var/gas_moles = cached_gases[gas_path][MOLES] - var/gas_id = cached_gases[gas_path][GAS_META][META_GAS_ID] - + var/list/cached_gas_id = GAS_META[META_GAS_ID] + for(var/gas_id, gas_moles in cached_moles) gas_moles = round(gas_moles, 0.01) if(gas_moles >= 0.01) - atmos_contents += "[gas_id]=[num2text(gas_moles)]" + atmos_contents += "[cached_gas_id[gas_id]]=[num2text(gas_moles)]" atmos_contents += temperature_str return atmos_contents.Join(";") +/** + * A simple helper proc that checks if the contents of a list of gases are within acceptable terms. + * + * Arguments: + * * acceptable_gas_bounds: An associated list of gas types and acceptable boundaries in moles. e.g. /datum/gas/oxygen = list(16, 30) + * * * if the assoc list is null, then it'll be considered a safe gas and won't return FALSE. + * * extraneous_gas_limit: If a gas not in gases is found, this is the limit above which the proc will return FALSE. + * + * Returns TRUE if the list of gases is acceptable, FALSE otherwise. + */ +/datum/gas_mixture/proc/check_gases(list/acceptable_gas_bounds, extraneous_gas_limit = 0.1) + SHOULD_BE_PURE(TRUE) + + var/list/gases_to_check = acceptable_gas_bounds.Copy() // thank you spaceman + var/list/cached_moles = moles + for(var/id in cached_moles) + var/gas_moles = cached_moles[id] + if(!(id in gases_to_check)) + if(gas_moles > extraneous_gas_limit) + return FALSE + continue + var/list/boundaries = gases_to_check[id] + if(boundaries && !ISINRANGE(gas_moles, boundaries[1], boundaries[2])) + return FALSE + gases_to_check -= id + ///Check that gases absent from the turf have a lower boundary of zero or none at all, otherwise return FALSE + for(var/id in gases_to_check) + var/list/boundaries = gases_to_check[id] + if(boundaries && boundaries[1] > 0) + return FALSE + return TRUE diff --git a/code/modules/atmospherics/gasmixtures/gas_types.dm b/code/modules/atmospherics/gasmixtures/gas_types.dm index ae81c16def1..49e57b08d44 100644 --- a/code/modules/atmospherics/gasmixtures/gas_types.dm +++ b/code/modules/atmospherics/gasmixtures/gas_types.dm @@ -1,21 +1,25 @@ /proc/meta_gas_list() - . = subtypesof(/datum/gas) - for(var/gas_path in .) - var/list/gas_info = new(8) + var/list/gas_info = new (META_GAS_LENGTH) + for (var/array_idx in 1 to gas_info.len) + gas_info[array_idx] = list() + + var/list/gas_types = subtypesof(/datum/gas) + ASSERT(GAS_TYPE_COUNT == length(gas_types),\ + "GAS_TYPE_COUNT != length(subtypesof(gas_types)), if you added new gas please increment GAS_TYPE_COUNT") + for(var/gas_path in gas_types) var/datum/gas/gas = gas_path + gas_info[META_GAS_SPECIFIC_HEAT][gas_path] = initial(gas.specific_heat) + gas_info[META_GAS_NAME][gas_path] = initial(gas.name) + gas_info[META_GAS_MOLES_VISIBLE][gas_path] = initial(gas.moles_visible) + if (gas_info[META_GAS_MOLES_VISIBLE][gas_path]) + gas_info[META_GAS_OVERLAY][gas_path] += generate_gas_overlays(0, SSmapping.max_plane_offset, gas) + gas_info[META_GAS_FUSION_POWER][gas_path] = initial(gas.fusion_power) + gas_info[META_GAS_DANGER][gas_path] = initial(gas.dangerous) + gas_info[META_GAS_ID][gas_path] = initial(gas.id) + gas_info[META_GAS_DESC][gas_path] = initial(gas.desc) - gas_info[META_GAS_SPECIFIC_HEAT] = initial(gas.specific_heat) - gas_info[META_GAS_NAME] = initial(gas.name) - - gas_info[META_GAS_MOLES_VISIBLE] = initial(gas.moles_visible) - if(initial(gas.moles_visible) != null) - gas_info[META_GAS_OVERLAY] = generate_gas_overlays(0, SSmapping.max_plane_offset, gas) - - gas_info[META_GAS_FUSION_POWER] = initial(gas.fusion_power) - gas_info[META_GAS_DANGER] = initial(gas.dangerous) - gas_info[META_GAS_ID] = initial(gas.id) - gas_info[META_GAS_DESC] = initial(gas.desc) - .[gas_path] = gas_info + /datum/gas_mixture::gas_meta = gas_info // save the reference to the list + return gas_info /proc/generate_gas_overlays(old_offset, new_offset, datum/gas/gas_type) var/list/to_return = list() @@ -28,11 +32,11 @@ return to_return /proc/gas_id2path(id) - var/list/meta_gas = GLOB.meta_gas_info - if(id in meta_gas) + var/list/meta_gas_id = GLOB.meta_gas_info[META_GAS_ID] + if(id in meta_gas_id) return id - for(var/path in meta_gas) - if(meta_gas[path][META_GAS_ID] == id) + for(var/path in meta_gas_id) + if(meta_gas_id[path] == id) return path return "" diff --git a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm index ab0517f9d02..dce8ab87ed5 100644 --- a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm +++ b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm @@ -10,9 +10,9 @@ garbage_collect() /datum/gas_mixture/immutable/garbage_collect() - temperature = initial_temperature - temperature_archived = initial_temperature - gases.Cut() + temperature = temperature_archived = initial_temperature + moles.Cut() + moles_archive.Cut() /datum/gas_mixture/immutable/archive() return TRUE //nothing changes, so we do nothing and the archive is successful @@ -58,13 +58,11 @@ /datum/gas_mixture/immutable/planetary var/list/initial_gas = list() +// Intentionally duplicate code to save microseconds on a call to parent /datum/gas_mixture/immutable/planetary/garbage_collect() - ..() - gases.Cut() - for(var/id in initial_gas) - ADD_GAS(id, gases) - gases[id][MOLES] = initial_gas[id][MOLES] - gases[id][ARCHIVE] = initial_gas[id][ARCHIVE] + temperature = temperature_archived = initial_temperature + moles = initial_gas.Copy() + moles_archive = initial_gas.Copy() /datum/gas_mixture/immutable/planetary/proc/parse_string_immutable(gas_string) //I know I know, I need this tho gas_string = SSair.preprocess_gas_string(gas_string) @@ -81,13 +79,11 @@ var/path = id if(!ispath(path)) path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around - ADD_GAS(path, mix) - mix[path][MOLES] = text2num(gas[id]) - mix[path][ARCHIVE] = mix[path][MOLES] + mix[path] = text2num(gas[id]) - for(var/id in mix) - ADD_GAS(id, gases) - gases[id][MOLES] = mix[id][MOLES] - gases[id][ARCHIVE] = mix[id][MOLES] + var/list/cached_moles = moles + var/list/cached_moles_archive = moles_archive + for(var/gas_id in mix) + cached_moles[gas_id] = cached_moles_archive[gas_id] = mix[gas_id] diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 4f5c643d05c..060b394872e 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -5,7 +5,7 @@ var/list/priority_reactions = list() //Builds a list of gas id to reaction group - for(var/gas_id in GLOB.meta_gas_info) + for(var/gas_id in GLOB.meta_gas_info[META_GAS_ID]) priority_reactions[gas_id] = list( /* PRIORITY_PRE_FORMATION = */ list(), /* PRIORITY_FORMATION = */ list(), @@ -27,7 +27,7 @@ priority_reactions[reaction_key][reaction.priority_group] += reaction //Culls empty gases - for(var/gas_id in GLOB.meta_gas_info) + for(var/gas_id in GLOB.meta_gas_info[META_GAS_ID]) var/passed = FALSE for(var/list/priority_grouping in priority_reactions[gas_id]) if(length(priority_grouping)) @@ -120,7 +120,7 @@ consumed = MOLES_GAS_VISIBLE if(consumed) - air.gases[/datum/gas/water_vapor][MOLES] -= consumed + air.moles[/datum/gas/water_vapor] -= consumed SET_REACTION_RESULTS(consumed) . |= REACTING @@ -143,18 +143,17 @@ ) /datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases - var/list/water_vapor = cached_gases[/datum/gas/water_vapor] - var/list/miasma = cached_gases[/datum/gas/miasma] + var/list/cached_moles = air.moles + var/water_vapor_moles = cached_moles[/datum/gas/water_vapor] + var/miasma_moles = cached_moles[/datum/gas/miasma] // As the name says it, it needs to be dry - if(water_vapor && water_vapor[MOLES] / air.total_moles() > MIASTER_STERILIZATION_MAX_HUMIDITY) + if(water_vapor_moles && water_vapor_moles / air.total_moles() > MIASTER_STERILIZATION_MAX_HUMIDITY) return NO_REACTION //Replace miasma with oxygen - var/cleaned_air = min(miasma[MOLES], MIASTER_STERILIZATION_RATE_BASE + (air.temperature - MIASTER_STERILIZATION_TEMP) / MIASTER_STERILIZATION_RATE_SCALE) - miasma[MOLES] -= cleaned_air - ASSERT_GAS(/datum/gas/oxygen, air) - cached_gases[/datum/gas/oxygen][MOLES] += cleaned_air + var/cleaned_air = min(miasma_moles, MIASTER_STERILIZATION_RATE_BASE + (air.temperature - MIASTER_STERILIZATION_TEMP) / MIASTER_STERILIZATION_RATE_SCALE) + cached_moles[/datum/gas/miasma] -= cleaned_air + cached_moles[/datum/gas/oxygen] += cleaned_air //Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable air.temperature += cleaned_air * MIASTER_STERILIZATION_ENERGY @@ -201,33 +200,30 @@ var/oxygen_burn_ratio = OXYGEN_BURN_RATIO_BASE - temperature_scale var/plasma_burn_rate = 0 var/super_saturation = FALSE // Whether we should make tritium. - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/list/oxygen = cached_gases[/datum/gas/oxygen] - var/list/plasma = cached_gases[/datum/gas/plasma] - switch(oxygen[MOLES] / plasma[MOLES]) + var/list/cached_moles = air.moles //this speeds things up because accessing datum vars is slow + var/oxygen_moles = cached_moles[/datum/gas/oxygen] || 0 + var/plasma_moles = cached_moles[/datum/gas/plasma] || 0 + switch(oxygen_moles / plasma_moles) if(SUPER_SATURATION_THRESHOLD to INFINITY) - plasma_burn_rate = (plasma[MOLES] / PLASMA_BURN_RATE_DELTA) * temperature_scale + plasma_burn_rate = (plasma_moles / PLASMA_BURN_RATE_DELTA) * temperature_scale super_saturation = TRUE // Begin to form tritium if(PLASMA_OXYGEN_FULLBURN to SUPER_SATURATION_THRESHOLD) - plasma_burn_rate = (plasma[MOLES] / PLASMA_BURN_RATE_DELTA) * temperature_scale + plasma_burn_rate = (plasma_moles / PLASMA_BURN_RATE_DELTA) * temperature_scale else - plasma_burn_rate = ((oxygen[MOLES] / PLASMA_OXYGEN_FULLBURN) / PLASMA_BURN_RATE_DELTA) * temperature_scale + plasma_burn_rate = ((oxygen_moles / PLASMA_OXYGEN_FULLBURN) / PLASMA_BURN_RATE_DELTA) * temperature_scale if(plasma_burn_rate < MINIMUM_HEAT_CAPACITY) return var/old_heat_capacity = air.heat_capacity() - plasma_burn_rate = min(plasma_burn_rate, plasma[MOLES], oxygen[MOLES] * INVERSE(oxygen_burn_ratio)) //Ensures matter is conserved properly - plasma[MOLES] = QUANTIZE(plasma[MOLES] - plasma_burn_rate) - oxygen[MOLES] = QUANTIZE(oxygen[MOLES] - (plasma_burn_rate * oxygen_burn_ratio)) + plasma_burn_rate = min(plasma_burn_rate, plasma_moles, oxygen_moles * INVERSE(oxygen_burn_ratio)) //Ensures matter is conserved properly + cached_moles[/datum/gas/plasma] = QUANTIZE(plasma_moles - plasma_burn_rate) + cached_moles[/datum/gas/oxygen] = QUANTIZE(oxygen_moles - (plasma_burn_rate * oxygen_burn_ratio)) if(super_saturation) - ASSERT_GAS(/datum/gas/tritium, air) - cached_gases[/datum/gas/tritium][MOLES] += plasma_burn_rate + cached_moles[/datum/gas/tritium] += plasma_burn_rate else - ASSERT_GAS(/datum/gas/carbon_dioxide, air) - ASSERT_GAS(/datum/gas/water_vapor, air) - cached_gases[/datum/gas/carbon_dioxide][MOLES] += plasma_burn_rate * 0.75 - cached_gases[/datum/gas/water_vapor][MOLES] += plasma_burn_rate * 0.25 + cached_moles[/datum/gas/carbon_dioxide] += plasma_burn_rate * 0.75 + cached_moles[/datum/gas/water_vapor] += plasma_burn_rate * 0.25 SET_REACTION_RESULTS((plasma_burn_rate) * (1 + oxygen_burn_ratio)) @@ -269,20 +265,19 @@ /datum/gas_reaction/h2fire/react(datum/gas_mixture/air, datum/holder) . = NO_REACTION - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/hydrogen = cached_gases[/datum/gas/hydrogen] - var/oxygen = cached_gases[/datum/gas/oxygen] + var/list/cached_moles = air.moles //this speeds things up because accessing datum vars is slow + var/hydrogen_moles = cached_moles[/datum/gas/hydrogen] + var/oxygen_moles = cached_moles[/datum/gas/oxygen] var/old_heat_capacity = air.heat_capacity() var/temperature = air.temperature - var/burned_fuel = min(hydrogen[MOLES] / FIRE_HYDROGEN_BURN_RATE_DELTA, oxygen[MOLES] / (FIRE_HYDROGEN_BURN_RATE_DELTA * HYDROGEN_OXYGEN_FULLBURN), hydrogen[MOLES], oxygen[MOLES] * INVERSE(0.5)) - if(burned_fuel <= 0 || hydrogen[MOLES] - burned_fuel < 0 || oxygen[MOLES] - burned_fuel * 0.5 < 0) //Shouldn't produce gas from nothing. + var/burned_fuel = min(hydrogen_moles / FIRE_HYDROGEN_BURN_RATE_DELTA, oxygen_moles / (FIRE_HYDROGEN_BURN_RATE_DELTA * HYDROGEN_OXYGEN_FULLBURN), hydrogen_moles, oxygen_moles * INVERSE(0.5)) + if(burned_fuel <= 0 || hydrogen_moles - burned_fuel < 0 || oxygen_moles - burned_fuel * 0.5 < 0) //Shouldn't produce gas from nothing. return - hydrogen[MOLES] -= burned_fuel - oxygen[MOLES] -= burned_fuel * 0.5 - ASSERT_GAS(/datum/gas/water_vapor, air) - cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel + cached_moles[/datum/gas/hydrogen] -= burned_fuel + cached_moles[/datum/gas/oxygen] -= burned_fuel * 0.5 + cached_moles[/datum/gas/water_vapor] += burned_fuel SET_REACTION_RESULTS(burned_fuel) @@ -326,20 +321,19 @@ /datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder) . = NO_REACTION - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/tritium = cached_gases[/datum/gas/tritium] - var/oxygen = cached_gases[/datum/gas/oxygen] + var/list/cached_moles = air.moles //this speeds things up because accessing datum vars is slow + var/tritium_moles = cached_moles[/datum/gas/tritium] + var/oxygen_moles = cached_moles[/datum/gas/oxygen] var/old_heat_capacity = air.heat_capacity() var/temperature = air.temperature - var/burned_fuel = min(tritium[MOLES] / FIRE_TRITIUM_BURN_RATE_DELTA, oxygen[MOLES] / (FIRE_TRITIUM_BURN_RATE_DELTA * TRITIUM_OXYGEN_FULLBURN), tritium[MOLES], oxygen[MOLES] * INVERSE(0.5)) - if(burned_fuel <= 0 || tritium[MOLES] - burned_fuel < 0 || oxygen[MOLES] - burned_fuel * 0.5 < 0) //Shouldn't produce gas from nothing. + var/burned_fuel = min(tritium_moles / FIRE_TRITIUM_BURN_RATE_DELTA, oxygen_moles / (FIRE_TRITIUM_BURN_RATE_DELTA * TRITIUM_OXYGEN_FULLBURN), tritium_moles, oxygen_moles * INVERSE(0.5)) + if(burned_fuel <= 0 || tritium_moles - burned_fuel < 0 || oxygen_moles - burned_fuel * 0.5 < 0) //Shouldn't produce gas from nothing. return - tritium[MOLES] -= burned_fuel - oxygen[MOLES] -= burned_fuel * 0.5 - ASSERT_GAS(/datum/gas/water_vapor, air) - cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel + cached_moles[/datum/gas/tritium] -= burned_fuel + cached_moles[/datum/gas/oxygen] -= burned_fuel * 0.5 + cached_moles[/datum/gas/water_vapor] += burned_fuel SET_REACTION_RESULTS(burned_fuel) @@ -405,23 +399,22 @@ var/oxygen_burn_ratio = OXYGEN_BURN_RATIO_BASE - temperature_scale var/freon_burn_rate - var/list/cached_gases = air.gases - var/freon = cached_gases[/datum/gas/freon] - var/oxygen = cached_gases[/datum/gas/oxygen] - if(oxygen[MOLES] < freon[MOLES] * FREON_OXYGEN_FULLBURN) - freon_burn_rate = ((oxygen[MOLES] / FREON_OXYGEN_FULLBURN) / FREON_BURN_RATE_DELTA) * temperature_scale + var/list/cached_moles = air.moles + var/freon_moles = cached_moles[/datum/gas/freon] + var/oxygen_moles = cached_moles[/datum/gas/oxygen] + if(oxygen_moles < freon_moles * FREON_OXYGEN_FULLBURN) + freon_burn_rate = ((oxygen_moles / FREON_OXYGEN_FULLBURN) / FREON_BURN_RATE_DELTA) * temperature_scale else - freon_burn_rate = (cached_gases[/datum/gas/freon][MOLES] / FREON_BURN_RATE_DELTA) * temperature_scale + freon_burn_rate = (freon_moles / FREON_BURN_RATE_DELTA) * temperature_scale if (freon_burn_rate < MINIMUM_HEAT_CAPACITY) return var/old_heat_capacity = air.heat_capacity() - freon_burn_rate = min(freon_burn_rate, freon[MOLES], oxygen[MOLES] * INVERSE(oxygen_burn_ratio)) //Ensures matter is conserved properly - freon[MOLES] = QUANTIZE(freon[MOLES] - freon_burn_rate) - oxygen[MOLES] = QUANTIZE(oxygen[MOLES] - (freon_burn_rate * oxygen_burn_ratio)) - ASSERT_GAS(/datum/gas/carbon_dioxide, air) - cached_gases[/datum/gas/carbon_dioxide][MOLES] += freon_burn_rate + freon_burn_rate = min(freon_burn_rate, freon_moles, oxygen_moles * INVERSE(oxygen_burn_ratio)) //Ensures matter is conserved properly + cached_moles[/datum/gas/freon] = QUANTIZE(freon_moles - freon_burn_rate) + cached_moles[/datum/gas/oxygen] = QUANTIZE(oxygen_moles - (freon_burn_rate * oxygen_burn_ratio)) + cached_moles[/datum/gas/carbon_dioxide] += freon_burn_rate if(temperature < HOT_ICE_FORMATION_MAXIMUM_TEMPERATURE && temperature > HOT_ICE_FORMATION_MINIMUM_TEMPERATURE && prob(HOT_ICE_FORMATION_PROB) && isturf(holder)) new /obj/item/stack/sheet/hot_ice(holder) @@ -466,18 +459,17 @@ ) /datum/gas_reaction/nitrousformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/oxygen = cached_gases[/datum/gas/oxygen] - var/nitrogen = cached_gases[/datum/gas/nitrogen] - var/heat_efficiency = min(oxygen[MOLES] * INVERSE(0.5), nitrogen[MOLES]) - if ((oxygen[MOLES] - heat_efficiency * 0.5 < 0 ) || (nitrogen[MOLES] - heat_efficiency < 0)) + var/list/cached_moles = air.moles + var/oxygen_moles = cached_moles[/datum/gas/oxygen] + var/nitrogen_moles = cached_moles[/datum/gas/nitrogen] + var/heat_efficiency = min(oxygen_moles * INVERSE(0.5), nitrogen_moles) + if ((oxygen_moles - heat_efficiency * 0.5 < 0 ) || (nitrogen_moles - heat_efficiency < 0)) return NO_REACTION // Shouldn't produce gas from nothing. var/old_heat_capacity = air.heat_capacity() - oxygen[MOLES] -= heat_efficiency * 0.5 - nitrogen[MOLES] -= heat_efficiency - ASSERT_GAS(/datum/gas/nitrous_oxide, air) - cached_gases[/datum/gas/nitrous_oxide][MOLES] += heat_efficiency + cached_moles[/datum/gas/oxygen] -= heat_efficiency * 0.5 + cached_moles[/datum/gas/nitrogen] -= heat_efficiency + cached_moles[/datum/gas/nitrous_oxide] += heat_efficiency SET_REACTION_RESULTS(heat_efficiency) var/energy_released = heat_efficiency * N2O_FORMATION_ENERGY @@ -507,19 +499,17 @@ ) /datum/gas_reaction/nitrous_decomp/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/nitrous_oxide = cached_gases[/datum/gas/nitrous_oxide] + var/list/cached_moles = air.moles //this speeds things up because accessing datum vars is slow + var/nitrous_oxide_moles = cached_moles[/datum/gas/nitrous_oxide] var/temperature = air.temperature - var/burned_fuel = (nitrous_oxide[MOLES] / N2O_DECOMPOSITION_RATE_DIVISOR) * ((temperature - N2O_DECOMPOSITION_MIN_SCALE_TEMP) * (temperature - N2O_DECOMPOSITION_MAX_SCALE_TEMP) / (N2O_DECOMPOSITION_SCALE_DIVISOR)) - if(burned_fuel <= 0 || nitrous_oxide[MOLES] - burned_fuel < 0) + var/burned_fuel = (nitrous_oxide_moles / N2O_DECOMPOSITION_RATE_DIVISOR) * ((temperature - N2O_DECOMPOSITION_MIN_SCALE_TEMP) * (temperature - N2O_DECOMPOSITION_MAX_SCALE_TEMP) / (N2O_DECOMPOSITION_SCALE_DIVISOR)) + if(burned_fuel <= 0 || nitrous_oxide_moles - burned_fuel < 0) return NO_REACTION var/old_heat_capacity = air.heat_capacity() - nitrous_oxide[MOLES] -= burned_fuel - ASSERT_GAS(/datum/gas/nitrogen, air) - cached_gases[/datum/gas/nitrogen][MOLES] += burned_fuel - ASSERT_GAS(/datum/gas/oxygen, air) - cached_gases[/datum/gas/oxygen][MOLES] += burned_fuel / 2 + cached_moles[/datum/gas/nitrous_oxide] -= burned_fuel + cached_moles[/datum/gas/nitrogen] += burned_fuel + cached_moles[/datum/gas/oxygen] += burned_fuel / 2 SET_REACTION_RESULTS(burned_fuel) var/energy_released = N2O_DECOMPOSITION_ENERGY * burned_fuel @@ -551,17 +541,17 @@ ) /datum/gas_reaction/bzformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/nitrous_oxide = cached_gases[/datum/gas/nitrous_oxide] - var/plasma = cached_gases[/datum/gas/plasma] + var/list/cached_moles = air.moles + var/nitrous_oxide_moles = cached_moles[/datum/gas/nitrous_oxide] + var/plasma_moles = cached_moles[/datum/gas/plasma] var/pressure = air.return_pressure() var/volume = air.return_volume() var/environment_effciency = volume/pressure //More volume and less pressure gives better rates - var/ratio_efficency = min(nitrous_oxide[MOLES]/plasma[MOLES], 1) //Less n2o than plasma give lower rates - var/nitrous_oxide_decomposed_factor = max(4 * (plasma[MOLES] / (nitrous_oxide[MOLES] + plasma[MOLES]) - 0.75), 0) // Nitrous oxide decomposes when there are more than 3 parts plasma per n2o. - var/bz_formed = min(0.01 * ratio_efficency * environment_effciency, nitrous_oxide[MOLES] * INVERSE(0.4), plasma[MOLES] * INVERSE(0.8 * (1 - nitrous_oxide_decomposed_factor))) + var/ratio_efficency = min(nitrous_oxide_moles/plasma_moles, 1) //Less n2o than plasma give lower rates + var/nitrous_oxide_decomposed_factor = max(4 * (plasma_moles / (nitrous_oxide_moles + plasma_moles) - 0.75), 0) // Nitrous oxide decomposes when there are more than 3 parts plasma per n2o. + var/bz_formed = min(0.01 * ratio_efficency * environment_effciency, nitrous_oxide_moles * INVERSE(0.4), plasma_moles * INVERSE(0.8 * (1 - nitrous_oxide_decomposed_factor))) - if (nitrous_oxide[MOLES] - bz_formed * 0.4 < 0 || plasma[MOLES] - 0.8 * bz_formed * (1 - nitrous_oxide_decomposed_factor) < 0 || bz_formed <= 0) + if (nitrous_oxide_moles - bz_formed * 0.4 < 0 || plasma_moles - 0.8 * bz_formed * (1 - nitrous_oxide_decomposed_factor) < 0 || bz_formed <= 0) return NO_REACTION var/old_heat_capacity = air.heat_capacity() @@ -573,18 +563,13 @@ *N2O decomposes with its normal decomposition energy */ if (nitrous_oxide_decomposed_factor>0) - ASSERT_GAS(/datum/gas/nitrogen, air) - ASSERT_GAS(/datum/gas/oxygen, air) var/amount_decomposed = 0.4 * bz_formed * nitrous_oxide_decomposed_factor - cached_gases[/datum/gas/nitrogen][MOLES] += amount_decomposed - cached_gases[/datum/gas/oxygen][MOLES] += 0.5 * amount_decomposed - - ASSERT_GAS(/datum/gas/bz, air) - cached_gases[/datum/gas/bz][MOLES] += bz_formed * (1-nitrous_oxide_decomposed_factor) - nitrous_oxide[MOLES] -= 0.4 * bz_formed - plasma[MOLES] -= 0.8 * bz_formed * (1-nitrous_oxide_decomposed_factor) - + cached_moles[/datum/gas/nitrogen] += amount_decomposed + cached_moles[/datum/gas/oxygen] += 0.5 * amount_decomposed + cached_moles[/datum/gas/bz] += bz_formed * (1-nitrous_oxide_decomposed_factor) + cached_moles[/datum/gas/nitrous_oxide] -= 0.4 * bz_formed + cached_moles[/datum/gas/plasma] -= 0.8 * bz_formed * (1-nitrous_oxide_decomposed_factor) SET_REACTION_RESULTS(bz_formed) var/energy_released = bz_formed * (BZ_FORMATION_ENERGY + nitrous_oxide_decomposed_factor * (N2O_DECOMPOSITION_ENERGY - BZ_FORMATION_ENERGY)) @@ -618,22 +603,20 @@ ) /datum/gas_reaction/pluox_formation/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases - var/list/carbon_dioxide = cached_gases[/datum/gas/carbon_dioxide] - var/list/oxygen = cached_gases[/datum/gas/oxygen] - var/list/tritium = cached_gases[/datum/gas/tritium] - var/produced_amount = min(PLUOXIUM_FORMATION_MAX_RATE, carbon_dioxide[MOLES], oxygen[MOLES] * INVERSE(0.5), tritium[MOLES] * INVERSE(0.01)) - if (produced_amount <= 0 || carbon_dioxide[MOLES] - produced_amount < 0 || oxygen[MOLES] - produced_amount * 0.5 < 0 || tritium[MOLES] - produced_amount * 0.01 < 0) + var/list/cached_moles = air.moles + var/carbon_dioxide_moles = cached_moles[/datum/gas/carbon_dioxide] + var/oxygen_moles = cached_moles[/datum/gas/oxygen] + var/tritium_moles = cached_moles[/datum/gas/tritium] + var/produced_amount = min(PLUOXIUM_FORMATION_MAX_RATE, carbon_dioxide_moles, oxygen_moles * INVERSE(0.5), tritium_moles * INVERSE(0.01)) + if (produced_amount <= 0 || carbon_dioxide_moles - produced_amount < 0 || oxygen_moles - produced_amount * 0.5 < 0 || tritium_moles - produced_amount * 0.01 < 0) return NO_REACTION var/old_heat_capacity = air.heat_capacity() - carbon_dioxide[MOLES] -= produced_amount - oxygen[MOLES] -= produced_amount * 0.5 - tritium[MOLES] -= produced_amount * 0.01 - ASSERT_GAS(/datum/gas/pluoxium, air) - cached_gases[/datum/gas/pluoxium][MOLES] += produced_amount - ASSERT_GAS(/datum/gas/hydrogen, air) - cached_gases[/datum/gas/hydrogen][MOLES] += produced_amount * 0.01 + cached_moles[/datum/gas/carbon_dioxide] -= produced_amount + cached_moles[/datum/gas/oxygen] -= produced_amount * 0.5 + cached_moles[/datum/gas/tritium] -= produced_amount * 0.01 + cached_moles[/datum/gas/pluoxium] += produced_amount + cached_moles[/datum/gas/hydrogen] += produced_amount * 0.01 SET_REACTION_RESULTS(produced_amount) var/energy_released = produced_amount * PLUOXIUM_FORMATION_ENERGY @@ -667,22 +650,21 @@ ) /datum/gas_reaction/nitrium_formation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/list/tritium = cached_gases[/datum/gas/tritium] - var/list/nitrogen = cached_gases[/datum/gas/nitrogen] - var/list/bz = cached_gases[/datum/gas/bz] + var/list/cached_moles = air.moles + var/tritium_moles = cached_moles[/datum/gas/tritium] + var/nitrogen_moles = cached_moles[/datum/gas/nitrogen] + var/bz_moles = cached_moles[/datum/gas/bz] var/temperature = air.temperature - var/heat_efficiency = min(temperature / NITRIUM_FORMATION_TEMP_DIVISOR, tritium[MOLES], nitrogen[MOLES], bz[MOLES] * INVERSE(0.05)) + var/heat_efficiency = min(temperature / NITRIUM_FORMATION_TEMP_DIVISOR, tritium_moles, nitrogen_moles, bz_moles * INVERSE(0.05)) - if( heat_efficiency <= 0 || (tritium[MOLES] - heat_efficiency < 0 ) || (nitrogen[MOLES] - heat_efficiency < 0) || (bz[MOLES] - heat_efficiency * 0.05 < 0)) //Shouldn't produce gas from nothing. + if( heat_efficiency <= 0 || (tritium_moles - heat_efficiency < 0 ) || (nitrogen_moles - heat_efficiency < 0) || (bz_moles - heat_efficiency * 0.05 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION var/old_heat_capacity = air.heat_capacity() - ASSERT_GAS(/datum/gas/nitrium, air) - tritium[MOLES] -= heat_efficiency - nitrogen[MOLES] -= heat_efficiency - bz[MOLES] -= heat_efficiency * 0.05 //bz gets consumed to balance the nitrium production and not make it too common and/or easy - cached_gases[/datum/gas/nitrium][MOLES] += heat_efficiency + cached_moles[/datum/gas/tritium] -= heat_efficiency + cached_moles[/datum/gas/nitrogen] -= heat_efficiency + cached_moles[/datum/gas/bz] -= heat_efficiency * 0.05 //bz gets consumed to balance the nitrium production and not make it too common and/or easy + cached_moles[/datum/gas/nitrium] += heat_efficiency SET_REACTION_RESULTS(heat_efficiency) @@ -714,21 +696,21 @@ ) /datum/gas_reaction/nitrium_decomposition/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/list/nitrium = cached_gases[/datum/gas/nitrium] + var/list/cached_moles = air.moles + var/nitrium_moles = cached_moles[/datum/gas/nitrium] var/temperature = air.temperature //This reaction is aggressively slow. like, a tenth of a mole per fire slow. Keep that in mind - var/heat_efficiency = min(temperature / NITRIUM_DECOMPOSITION_TEMP_DIVISOR, nitrium[MOLES]) + var/heat_efficiency = min(temperature / NITRIUM_DECOMPOSITION_TEMP_DIVISOR, nitrium_moles) - if (heat_efficiency <= 0 || (nitrium[MOLES] - heat_efficiency < 0)) //Shouldn't produce gas from nothing. + if (heat_efficiency <= 0 || (nitrium_moles - heat_efficiency < 0)) //Shouldn't produce gas from nothing. return NO_REACTION var/old_heat_capacity = air.heat_capacity() air.assert_gases(/datum/gas/nitrogen, /datum/gas/hydrogen) - nitrium[MOLES] -= heat_efficiency - cached_gases[/datum/gas/hydrogen][MOLES] += heat_efficiency - cached_gases[/datum/gas/nitrogen][MOLES] += heat_efficiency + cached_moles[/datum/gas/nitrium] -= heat_efficiency + cached_moles[/datum/gas/hydrogen] += heat_efficiency + cached_moles[/datum/gas/nitrogen] += heat_efficiency SET_REACTION_RESULTS(heat_efficiency) var/energy_released = heat_efficiency * NITRIUM_DECOMPOSITION_ENERGY @@ -759,27 +741,26 @@ ) /datum/gas_reaction/freonformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/list/plasma = cached_gases[/datum/gas/plasma] - var/list/carbon_dioxide = cached_gases[/datum/gas/carbon_dioxide] - var/list/bz = cached_gases[/datum/gas/bz] + var/list/cached_moles = air.moles + var/plasma_moles = cached_moles[/datum/gas/plasma] + var/carbon_dioxide_moles = cached_moles[/datum/gas/carbon_dioxide] + var/bz_moles = cached_moles[/datum/gas/bz] var/temperature = air.temperature - var/minimal_mole_factor = min(plasma[MOLES] * INVERSE(0.6), bz[MOLES] * INVERSE(0.1), carbon_dioxide[MOLES] * INVERSE(0.3)) + var/minimal_mole_factor = min(plasma_moles * INVERSE(0.6), bz_moles * INVERSE(0.1), carbon_dioxide_moles * INVERSE(0.3)) var/equation_first_part = NUM_E ** (-(((temperature - 800) / 200) ** 2)) var/equation_second_part = 3 / (1 + NUM_E ** (-0.001 * (temperature - 6000))) var/heat_factor = equation_first_part + equation_second_part - var/freon_formed = min(heat_factor * minimal_mole_factor * 0.05, plasma[MOLES] * INVERSE(0.6), carbon_dioxide[MOLES] * INVERSE(0.3), bz[MOLES] * INVERSE(0.1)) - if (freon_formed <= 0 || (plasma[MOLES] - freon_formed * 0.6 < 0 ) || (carbon_dioxide[MOLES] - freon_formed * 0.3 < 0) || (bz[MOLES] - freon_formed * 0.1 < 0)) //Shouldn't produce gas from nothing. + var/freon_formed = min(heat_factor * minimal_mole_factor * 0.05, plasma_moles * INVERSE(0.6), carbon_dioxide_moles * INVERSE(0.3), bz_moles * INVERSE(0.1)) + if (freon_formed <= 0 || (plasma_moles - freon_formed * 0.6 < 0 ) || (carbon_dioxide_moles - freon_formed * 0.3 < 0) || (bz_moles - freon_formed * 0.1 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION var/old_heat_capacity = air.heat_capacity() - ASSERT_GAS(/datum/gas/freon, air) - plasma[MOLES] -= freon_formed * 0.6 - carbon_dioxide[MOLES] -= freon_formed * 0.3 - bz[MOLES] -= freon_formed * 0.1 - cached_gases[/datum/gas/freon][MOLES] += freon_formed + cached_moles[/datum/gas/plasma] -= freon_formed * 0.6 + cached_moles[/datum/gas/carbon_dioxide] -= freon_formed * 0.3 + cached_moles[/datum/gas/bz] -= freon_formed * 0.1 + cached_moles[/datum/gas/freon] += freon_formed SET_REACTION_RESULTS(freon_formed) @@ -814,28 +795,28 @@ /datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air) . = NO_REACTION - var/list/cached_gases = air.gases - var/list/nitrogen = cached_gases[/datum/gas/nitrogen] - var/list/tritium = cached_gases[/datum/gas/tritium] + var/list/cached_moles = air.moles + var/nitrogen_moles = cached_moles[/datum/gas/nitrogen] + var/tritium_moles = cached_moles[/datum/gas/tritium] /// List of gases we will assert, and possibly garbage collect. var/list/asserted_gases = list(/datum/gas/hypernoblium, /datum/gas/bz) air.assert_gases(arglist(asserted_gases)) - var/list/bz = cached_gases[/datum/gas/bz] - var/reduction_factor = clamp(tritium[MOLES] / (tritium[MOLES] + bz[MOLES]), 0.001 , 1) //reduces trit consumption in presence of bz upward to 0.1% reduction - var/nob_formed = min((nitrogen[MOLES] + tritium[MOLES]) * 0.01, tritium[MOLES] * INVERSE(5 * reduction_factor), nitrogen[MOLES] * INVERSE(10)) + var/bz_moles = cached_moles[/datum/gas/bz] + var/reduction_factor = clamp(tritium_moles / (tritium_moles + bz_moles), 0.001 , 1) //reduces trit consumption in presence of bz upward to 0.1% reduction + var/nob_formed = min((nitrogen_moles + tritium_moles) * 0.01, tritium_moles * INVERSE(5 * reduction_factor), nitrogen_moles * INVERSE(10)) //calling QUANTIZE on results to round very small floating point values. - if (QUANTIZE(nob_formed) <= 0 || (QUANTIZE(tritium[MOLES] - 5 * nob_formed * reduction_factor) < 0) || (QUANTIZE(nitrogen[MOLES] - 10 * nob_formed) < 0)) - air.garbage_collect(arglist(asserted_gases)) + if (QUANTIZE(nob_formed) <= 0 || (QUANTIZE(tritium_moles - 5 * nob_formed * reduction_factor) < 0) || (QUANTIZE(nitrogen_moles - 10 * nob_formed) < 0)) + air.garbage_collect() return var/old_heat_capacity = air.heat_capacity() - tritium[MOLES] -= 5 * nob_formed * reduction_factor - nitrogen[MOLES] -= 10 * nob_formed - cached_gases[/datum/gas/hypernoblium][MOLES] += nob_formed // I'm not going to nitpick, but N20H10 feels like it should be an explosive more than anything. + cached_moles[/datum/gas/tritium] -= 5 * nob_formed * reduction_factor + cached_moles[/datum/gas/nitrogen] -= 10 * nob_formed + cached_moles[/datum/gas/hypernoblium] += nob_formed // I'm not going to nitpick, but N20H10 feels like it should be an explosive more than anything. SET_REACTION_RESULTS(nob_formed) - var/energy_released = nob_formed * NOBLIUM_FORMATION_ENERGY / max(bz[MOLES], 1) + var/energy_released = nob_formed * NOBLIUM_FORMATION_ENERGY / max(bz_moles, 1) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.temperature = max(((air.temperature * old_heat_capacity + energy_released) / new_heat_capacity), TCMB) @@ -866,20 +847,19 @@ /datum/gas_reaction/halon_o2removal/react(datum/gas_mixture/air, datum/holder) . = NO_REACTION - var/list/cached_gases = air.gases - var/list/halon = cached_gases[/datum/gas/halon] - var/list/oxygen = cached_gases[/datum/gas/oxygen] + var/list/cached_moles = air.moles + var/halon_moles = cached_moles[/datum/gas/halon] + var/oxygen_moles = cached_moles[/datum/gas/oxygen] var/temperature = air.temperature - var/heat_efficiency = min(temperature / HALON_COMBUSTION_TEMPERATURE_SCALE, halon[MOLES], oxygen[MOLES] * INVERSE(20)) - if (heat_efficiency <= 0 || (halon[MOLES] - heat_efficiency < 0 ) || (oxygen[MOLES] - heat_efficiency * 20 < 0)) //Shouldn't produce gas from nothing. + var/heat_efficiency = min(temperature / HALON_COMBUSTION_TEMPERATURE_SCALE, halon_moles, oxygen_moles * INVERSE(20)) + if (heat_efficiency <= 0 || (halon_moles - heat_efficiency < 0 ) || (oxygen_moles - heat_efficiency * 20 < 0)) //Shouldn't produce gas from nothing. return var/old_heat_capacity = air.heat_capacity() - ASSERT_GAS(/datum/gas/pluoxium, air) - halon[MOLES] -= heat_efficiency - oxygen[MOLES] -= heat_efficiency * 20 - cached_gases[/datum/gas/pluoxium][MOLES] += heat_efficiency * 2.5 + cached_moles[/datum/gas/halon] -= heat_efficiency + cached_moles[/datum/gas/oxygen] -= heat_efficiency * 20 + cached_moles[/datum/gas/pluoxium] += heat_efficiency * 2.5 SET_REACTION_RESULTS(heat_efficiency * 5) var/energy_used = heat_efficiency * HALON_COMBUSTION_ENERGY @@ -920,19 +900,18 @@ ) /datum/gas_reaction/healium_formation/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases - var/list/bz = cached_gases[/datum/gas/bz] - var/list/freon = cached_gases[/datum/gas/freon] + var/list/cached_moles = air.moles + var/bz_moles = cached_moles[/datum/gas/bz] + var/freon_moles = cached_moles[/datum/gas/freon] var/temperature = air.temperature - var/heat_efficiency = min(temperature * 0.3, freon[MOLES] * INVERSE(2.75), bz[MOLES] * INVERSE(0.25)) - if (heat_efficiency <= 0 || (freon[MOLES] - heat_efficiency * 2.75 < 0 ) || (bz[MOLES] - heat_efficiency * 0.25 < 0)) //Shouldn't produce gas from nothing. + var/heat_efficiency = min(temperature * 0.3, freon_moles * INVERSE(2.75), bz_moles * INVERSE(0.25)) + if (heat_efficiency <= 0 || (freon_moles - heat_efficiency * 2.75 < 0 ) || (bz_moles - heat_efficiency * 0.25 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION var/old_heat_capacity = air.heat_capacity() - ASSERT_GAS(/datum/gas/healium, air) - freon[MOLES] -= heat_efficiency * 2.75 - bz[MOLES] -= heat_efficiency * 0.25 - cached_gases[/datum/gas/healium][MOLES] += heat_efficiency * 3 + cached_moles[/datum/gas/freon] -= heat_efficiency * 2.75 + cached_moles[/datum/gas/bz] -= heat_efficiency * 0.25 + cached_moles[/datum/gas/healium] += heat_efficiency * 3 SET_REACTION_RESULTS(heat_efficiency * 3) var/energy_released = heat_efficiency * HEALIUM_FORMATION_ENERGY @@ -962,20 +941,19 @@ ) /datum/gas_reaction/zauker_formation/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases - var/list/hypernoblium = cached_gases[/datum/gas/hypernoblium] - var/list/nitrium = cached_gases[/datum/gas/nitrium] + var/list/cached_moles = air.moles + var/hypernoblium_moles = cached_moles[/datum/gas/hypernoblium] + var/nitrium_moles = cached_moles[/datum/gas/nitrium] var/temperature = air.temperature - var/heat_efficiency = min(temperature * ZAUKER_FORMATION_TEMPERATURE_SCALE, hypernoblium[MOLES] * INVERSE(0.01), nitrium[MOLES] * INVERSE(0.5)) - if (heat_efficiency <= 0 || (hypernoblium[MOLES] - heat_efficiency * 0.01 < 0 ) || (nitrium[MOLES] - heat_efficiency * 0.5 < 0)) //Shouldn't produce gas from nothing. + var/heat_efficiency = min(temperature * ZAUKER_FORMATION_TEMPERATURE_SCALE, hypernoblium_moles * INVERSE(0.01), nitrium_moles * INVERSE(0.5)) + if (heat_efficiency <= 0 || (hypernoblium_moles - heat_efficiency * 0.01 < 0 ) || (nitrium_moles - heat_efficiency * 0.5 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION var/old_heat_capacity = air.heat_capacity() - ASSERT_GAS(/datum/gas/zauker, air) - hypernoblium[MOLES] -= heat_efficiency * 0.01 - nitrium[MOLES] -= heat_efficiency * 0.5 - cached_gases[/datum/gas/zauker][MOLES] += heat_efficiency * 0.5 + cached_moles[/datum/gas/hypernoblium] -= heat_efficiency * 0.01 + cached_moles[/datum/gas/nitrium] -= heat_efficiency * 0.5 + cached_moles[/datum/gas/zauker] += heat_efficiency * 0.5 SET_REACTION_RESULTS(heat_efficiency * 0.5) var/energy_used = heat_efficiency * ZAUKER_FORMATION_ENERGY @@ -1004,18 +982,17 @@ ) /datum/gas_reaction/zauker_decomp/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/list/nitrogen = cached_gases[/datum/gas/nitrogen] - var/list/zauker = cached_gases[/datum/gas/zauker] - var/burned_fuel = min(ZAUKER_DECOMPOSITION_MAX_RATE, nitrogen[MOLES], zauker[MOLES]) - if (burned_fuel <= 0 || zauker[MOLES] - burned_fuel < 0) + var/list/cached_moles = air.moles //this speeds things up because accessing datum vars is slow + var/nitrogen_moles = cached_moles[/datum/gas/nitrogen] + var/zauker_moles = cached_moles[/datum/gas/zauker] + var/burned_fuel = min(ZAUKER_DECOMPOSITION_MAX_RATE, nitrogen_moles, zauker_moles) + if (burned_fuel <= 0 || zauker_moles - burned_fuel < 0) return NO_REACTION var/old_heat_capacity = air.heat_capacity() - zauker[MOLES] -= burned_fuel - ASSERT_GAS(/datum/gas/oxygen, air) - cached_gases[/datum/gas/oxygen][MOLES] += burned_fuel * 0.3 - nitrogen[MOLES] += burned_fuel * 0.7 + cached_moles[/datum/gas/zauker] -= burned_fuel + cached_moles[/datum/gas/oxygen] += burned_fuel * 0.3 + cached_moles[/datum/gas/nitrogen] += burned_fuel * 0.7 SET_REACTION_RESULTS(burned_fuel) var/energy_released = ZAUKER_DECOMPOSITION_ENERGY * burned_fuel @@ -1047,20 +1024,19 @@ ) /datum/gas_reaction/proto_nitrate_formation/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases - var/list/pluoxium = cached_gases[/datum/gas/pluoxium] - var/list/hydrogen = cached_gases[/datum/gas/hydrogen] + var/list/cached_moles = air.moles + var/pluoxium_moles = cached_moles[/datum/gas/pluoxium] + var/hydrogen_moles = cached_moles[/datum/gas/hydrogen] var/temperature = air.temperature - var/heat_efficiency = min(temperature * 0.005, pluoxium[MOLES] * INVERSE(0.2), hydrogen[MOLES] * INVERSE(2)) - if (heat_efficiency <= 0 || (pluoxium[MOLES] - heat_efficiency * 0.2 < 0 ) || (hydrogen[MOLES] - heat_efficiency * 2 < 0)) //Shouldn't produce gas from nothing. + var/heat_efficiency = min(temperature * 0.005, pluoxium_moles * INVERSE(0.2), hydrogen_moles * INVERSE(2)) + if (heat_efficiency <= 0 || (pluoxium_moles - heat_efficiency * 0.2 < 0 ) || (hydrogen_moles - heat_efficiency * 2 < 0)) //Shouldn't produce gas from nothing. return NO_REACTION var/old_heat_capacity = air.heat_capacity() - ASSERT_GAS(/datum/gas/proto_nitrate, air) - hydrogen[MOLES] -= heat_efficiency * 2 - pluoxium[MOLES] -= heat_efficiency * 0.2 - cached_gases[/datum/gas/proto_nitrate][MOLES] += heat_efficiency * 2.2 + cached_moles[/datum/gas/hydrogen] -= heat_efficiency * 2 + cached_moles[/datum/gas/pluoxium] -= heat_efficiency * 0.2 + cached_moles[/datum/gas/proto_nitrate] += heat_efficiency * 2.2 SET_REACTION_RESULTS(heat_efficiency * 2.2) var/energy_released = heat_efficiency * PN_FORMATION_ENERGY @@ -1088,16 +1064,16 @@ ) /datum/gas_reaction/proto_nitrate_hydrogen_response/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases - var/list/proto_nitrate = cached_gases[/datum/gas/proto_nitrate] - var/list/hydrogen = cached_gases[/datum/gas/hydrogen] - var/produced_amount = min(PN_HYDROGEN_CONVERSION_MAX_RATE, hydrogen[MOLES], proto_nitrate[MOLES]) - if (produced_amount <= 0 || hydrogen[MOLES] - produced_amount < 0) + var/list/cached_moles = air.moles + var/proto_nitrate_moles = cached_moles[/datum/gas/proto_nitrate] + var/hydrogen_moles = cached_moles[/datum/gas/hydrogen] + var/produced_amount = min(PN_HYDROGEN_CONVERSION_MAX_RATE, hydrogen_moles, proto_nitrate_moles) + if (produced_amount <= 0 || hydrogen_moles - produced_amount < 0) return NO_REACTION var/old_heat_capacity = air.heat_capacity() - hydrogen[MOLES] -= produced_amount - proto_nitrate[MOLES] += produced_amount * 0.5 + cached_moles[/datum/gas/hydrogen] -= produced_amount + cached_moles[/datum/gas/proto_nitrate] += produced_amount * 0.5 SET_REACTION_RESULTS(produced_amount * 0.5) var/energy_used = produced_amount * PN_HYDROGEN_CONVERSION_ENERGY @@ -1129,19 +1105,18 @@ /datum/gas_reaction/proto_nitrate_tritium_response/react(datum/gas_mixture/air, datum/holder) . = NO_REACTION - var/list/cached_gases = air.gases - var/list/proto_nitrate = cached_gases[/datum/gas/proto_nitrate] - var/list/tritium = cached_gases[/datum/gas/tritium] + var/list/cached_moles = air.moles + var/proto_nitrate_moles = cached_moles[/datum/gas/proto_nitrate] + var/tritium_moles = cached_moles[/datum/gas/tritium] var/temperature = air.temperature - var/produced_amount = min(air.temperature / 34 * (tritium[MOLES] * proto_nitrate[MOLES]) / (tritium[MOLES] + 10 * proto_nitrate[MOLES]), tritium[MOLES], proto_nitrate[MOLES] * INVERSE(0.01)) - if(tritium[MOLES] - produced_amount < 0 || proto_nitrate[MOLES] - produced_amount * 0.01 < 0) + var/produced_amount = min(temperature / 34 * (tritium_moles * proto_nitrate_moles) / (tritium_moles + 10 * proto_nitrate_moles), tritium_moles, proto_nitrate_moles * INVERSE(0.01)) + if(tritium_moles - produced_amount < 0 || proto_nitrate_moles - produced_amount * 0.01 < 0) return var/old_heat_capacity = air.heat_capacity() - proto_nitrate[MOLES] -= produced_amount * 0.01 - tritium[MOLES] -= produced_amount - ASSERT_GAS(/datum/gas/hydrogen, air) - cached_gases[/datum/gas/hydrogen][MOLES] += produced_amount + cached_moles[/datum/gas/proto_nitrate] -= produced_amount * 0.01 + cached_moles[/datum/gas/tritium] -= produced_amount + cached_moles[/datum/gas/hydrogen] += produced_amount SET_REACTION_RESULTS(produced_amount) var/turf/open/location @@ -1183,22 +1158,19 @@ /datum/gas_reaction/proto_nitrate_bz_response/react(datum/gas_mixture/air, datum/holder) . = NO_REACTION - var/list/cached_gases = air.gases - var/list/proto_nitrate = cached_gases[/datum/gas/proto_nitrate] - var/list/bz = cached_gases[/datum/gas/bz] + var/list/cached_moles = air.moles + var/proto_nitrate_moles = cached_moles[/datum/gas/proto_nitrate] + var/bz_moles = cached_moles[/datum/gas/bz] var/temperature = air.temperature - var/consumed_amount = min(air.temperature / 2240 * bz[MOLES] * proto_nitrate[MOLES] / (bz[MOLES] + proto_nitrate[MOLES]), bz[MOLES], proto_nitrate[MOLES]) - if (consumed_amount <= 0 || bz[MOLES] - consumed_amount < 0) + var/consumed_amount = min(temperature / 2240 * bz_moles * proto_nitrate_moles / (bz_moles + proto_nitrate_moles), bz_moles, proto_nitrate_moles) + if (consumed_amount <= 0 || bz_moles - consumed_amount < 0) return var/old_heat_capacity = air.heat_capacity() - bz[MOLES] -= consumed_amount - ASSERT_GAS(/datum/gas/nitrogen, air) - cached_gases[/datum/gas/nitrogen][MOLES] += consumed_amount * 0.4 - ASSERT_GAS(/datum/gas/helium, air) - cached_gases[/datum/gas/helium][MOLES] += consumed_amount * 1.6 - ASSERT_GAS(/datum/gas/plasma, air) - cached_gases[/datum/gas/plasma][MOLES] += consumed_amount * 0.8 + cached_moles[/datum/gas/bz] -= consumed_amount + cached_moles[/datum/gas/nitrogen] += consumed_amount * 0.4 + cached_moles[/datum/gas/helium] += consumed_amount * 1.6 + cached_moles[/datum/gas/plasma] += consumed_amount * 0.8 SET_REACTION_RESULTS(consumed_amount) var/turf/open/location @@ -1241,24 +1213,23 @@ */ /datum/gas_reaction/antinoblium_replication/react(datum/gas_mixture/air, datum/holder) . = REACTING | VOLATILE_REACTION - var/list/cached_gases = air.gases + var/list/cached_moles = air.moles var/heat_capacity = air.heat_capacity() var/total_moles = air.total_moles() - var/antinoblium = cached_gases[/datum/gas/antinoblium] - var/antinoblium_moles = antinoblium[MOLES] + var/antinoblium_moles = cached_moles[/datum/gas/antinoblium] var/total_not_antinoblium_moles = total_moles - antinoblium_moles var/reaction_rate = min(antinoblium_moles / ANTINOBLIUM_CONVERSION_DIVISOR, total_not_antinoblium_moles) if(total_not_antinoblium_moles < MINIMUM_MOLE_COUNT) // Clear up the remaining gases if this condition is met. . = NO_REACTION reaction_rate = total_not_antinoblium_moles - for(var/id,gas in cached_gases) - if(id == /datum/gas/antinoblium) + for(var/gas_id in cached_moles) + if(gas_id == /datum/gas/antinoblium) continue if(. == NO_REACTION) // Let the gases get properly cleared while avoiding potential division by 0. - gas[MOLES] = 0 + cached_moles[gas_id] = 0 continue - gas[MOLES] -= reaction_rate * gas[MOLES] / total_not_antinoblium_moles - antinoblium[MOLES] += reaction_rate + cached_moles[gas_id] -= reaction_rate * cached_moles[gas_id] / total_not_antinoblium_moles + cached_moles[/datum/gas/antinoblium] += reaction_rate SET_REACTION_RESULTS(reaction_rate) var/new_heat_capacity = air.heat_capacity() diff --git a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm index 4392a804d96..fa7bed31fb3 100644 --- a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm +++ b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm @@ -106,12 +106,12 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) tlv_collection["temperature"] = new /datum/tlv/temperature var/list/cached_gas_info = GLOB.meta_gas_info - for(var/datum/gas/gas_path as anything in cached_gas_info) + for(var/datum/gas/gas_path as anything in cached_gas_info[META_GAS_ID]) if(ispath(gas_path, /datum/gas/oxygen)) tlv_collection[gas_path] = new /datum/tlv/oxygen else if(ispath(gas_path, /datum/gas/carbon_dioxide)) tlv_collection[gas_path] = new /datum/tlv/carbon_dioxide - else if(cached_gas_info[gas_path][META_GAS_DANGER]) + else if(cached_gas_info[META_GAS_DANGER][gas_path]) tlv_collection[gas_path] = new /datum/tlv/dangerous else tlv_collection[gas_path] = new /datum/tlv/no_checks @@ -282,11 +282,10 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) "danger" = tlv_collection["temperature"].check_value(temp), )) if(total_moles) - for(var/gas_path in environment.gases) - var/moles = environment.gases[gas_path][MOLES] + for(var/gas_path, moles in environment.moles) var/portion = moles / total_moles data["envData"] += list(list( - "name" = GLOB.meta_gas_info[gas_path][META_GAS_NAME], + "name" = GLOB.meta_gas_info[META_GAS_NAME][gas_path], "value" = "[round(moles, 0.01)] moles / [round(100 * portion, 0.01)] % / [round(portion * pressure, 0.01)] kPa", "danger" = tlv_collection[gas_path].check_value(portion * pressure), )) @@ -302,7 +301,7 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) singular_tlv["name"] = "Temperature" singular_tlv["unit"] = "K" else - singular_tlv["name"] = GLOB.meta_gas_info[threshold][META_GAS_NAME] + singular_tlv["name"] = GLOB.meta_gas_info[META_GAS_NAME][threshold] singular_tlv["unit"] = "kPa" singular_tlv["id"] = threshold singular_tlv["warning_min"] = tlv.warning_min @@ -332,9 +331,9 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) data["scrubbers"] = list() for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/scrubber as anything in my_area.air_scrubbers) var/list/filter_types = list() - for (var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - filter_types += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in scrubber.filter_types))) + var/cached_gas_info = GLOB.meta_gas_info + for (var/path in cached_gas_info[META_GAS_ID]) + filter_types += list(list("gas_id" = cached_gas_info[META_GAS_ID][path], "gas_name" = cached_gas_info[META_GAS_NAME][path], "enabled" = (path in scrubber.filter_types))) data["scrubbers"] += list(list( "refID" = REF(scrubber), "long_name" = sanitize(scrubber.name), @@ -592,8 +591,8 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) danger_level = max(danger_level, tlv_collection["temperature"].check_value(temp)) if(total_moles) var/list/cached_gas_info = GLOB.meta_gas_info - for(var/datum/gas/gas_path as anything in cached_gas_info) - var/moles = environment.gases[gas_path] ? environment.gases[gas_path][MOLES] : 0 + for(var/datum/gas/gas_path as anything in cached_gas_info[META_GAS_ID]) + var/moles = environment.moles[gas_path] || 0 danger_level = max(danger_level, tlv_collection[gas_path].check_value(pressure * moles / total_moles)) if(danger_level) @@ -710,7 +709,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 27) tlv_collection["temperature"] = new /datum/tlv/no_checks tlv_collection["pressure"] = new /datum/tlv/no_checks - for(var/gas_path in GLOB.meta_gas_info) + for(var/gas_path in GLOB.meta_gas_info[META_GAS_ID]) tlv_collection[gas_path] = new /datum/tlv/no_checks ///Used for air alarm link helper, which connects air alarm to a sensor with corresponding chamber_id diff --git a/code/modules/atmospherics/machinery/air_alarm/air_alarm_circuit.dm b/code/modules/atmospherics/machinery/air_alarm/air_alarm_circuit.dm index a653522b9ca..685ce6eec11 100644 --- a/code/modules/atmospherics/machinery/air_alarm/air_alarm_circuit.dm +++ b/code/modules/atmospherics/machinery/air_alarm/air_alarm_circuit.dm @@ -164,8 +164,9 @@ "Temperature" = "temperature" ) - for(var/gas_id in GLOB.meta_gas_info) - component_options[GLOB.meta_gas_info[gas_id][META_GAS_NAME]] = gas_id2path(gas_id) + var/cached_gas_info = GLOB.meta_gas_info + for(var/gas_id in cached_gas_info[META_GAS_ID]) + component_options[cached_gas_info[META_GAS_NAME][gas_id]] = gas_id2path(gas_id) air_alarm_options = add_option_port("Air Alarm Options", component_options) options_map = component_options @@ -230,7 +231,7 @@ pressure.set_output(round(environment.return_pressure())) temperature.set_output(round(environment.temperature)) if(ispath(options_map[current_option])) - gas_amount.set_output(round(environment.gases[options_map[current_option]][MOLES])) + gas_amount.set_output(round(environment.moles[options_map[current_option]])) update_received.set_output(COMPONENT_SIGNAL) @@ -351,8 +352,9 @@ . = ..() var/static/list/meta_data = list() if(length(meta_data) == 0) - for(var/typepath in GLOB.meta_gas_info) - meta_data += GLOB.meta_gas_info[typepath][META_GAS_ID] + var/cached_gas_info = GLOB.meta_gas_info + for(var/typepath in cached_gas_info[META_GAS_ID]) + meta_data += cached_gas_info[META_GAS_ID][typepath] . += create_table_notices(meta_data, column_name = "Gas", column_name_plural = "Gases") /obj/item/circuit_component/air_alarm_scrubbers/proc/set_gas_to_filter(datum/port/input/port) diff --git a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm index 6ff94177190..b41b7ce0e76 100644 --- a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm +++ b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer_reactions.dm @@ -37,13 +37,13 @@ GLOBAL_LIST_INIT(electrolyzer_reactions, electrolyzer_reactions_list()) */ /datum/electrolyzer_reaction/proc/reaction_check(datum/gas_mixture/air_mixture, list/electrolyzer_args = list()) var/temp = air_mixture.temperature - var/list/cached_gases = air_mixture.gases + var/list/cached_moles = air_mixture.moles if((requirements["MIN_TEMP"] && temp < requirements["MIN_TEMP"]) || (requirements["MAX_TEMP"] && temp > requirements["MAX_TEMP"])) return FALSE for(var/id in requirements) if (id == "MIN_TEMP" || id == "MAX_TEMP") continue - if(!cached_gases[id] || cached_gases[id][MOLES] < requirements[id]) + if(cached_moles[id] < requirements[id]) return FALSE return TRUE @@ -65,7 +65,7 @@ GLOBAL_LIST_INIT(electrolyzer_reactions, electrolyzer_reactions_list()) var/old_heat_capacity = air_mixture.heat_capacity() - var/proportion = min(air_mixture.gases[/datum/gas/water_vapor][MOLES] * INVERSE(2), (2.5 * (working_power ** 2))) + var/proportion = min(air_mixture.moles[/datum/gas/water_vapor] * INVERSE(2), (2.5 * (working_power ** 2))) air_mixture.adjust_gas(/datum/gas/water_vapor, -proportion * 2) air_mixture.adjust_gas(/datum/gas/oxygen, proportion) air_mixture.adjust_gas(/datum/gas/hydrogen, proportion * 2) @@ -94,17 +94,16 @@ GLOBAL_LIST_INIT(electrolyzer_reactions, electrolyzer_reactions_list()) /datum/electrolyzer_reaction/nob_conversion/react(datum/gas_mixture/air_mixture, working_power, list/electrolyzer_args = list()) /// The supermatter zap power_level. var/supermatter_power = electrolyzer_args[ELECTROLYSIS_ARGUMENT_SUPERMATTER_POWER] - var/list/cached_gases = air_mixture.gases + var/list/cached_moles = air_mixture.moles var/old_heat_capacity = air_mixture.heat_capacity() air_mixture.assert_gases(/datum/gas/hypernoblium, /datum/gas/antinoblium) - var/list/hypernoblium = cached_gases[/datum/gas/hypernoblium] - var/list/antinoblium = cached_gases[/datum/gas/antinoblium] - var/electrolysed = hypernoblium[MOLES] * clamp(supermatter_power - POWER_PENALTY_THRESHOLD, 0, CRITICAL_POWER_PENALTY_THRESHOLD - POWER_PENALTY_THRESHOLD) / (CRITICAL_POWER_PENALTY_THRESHOLD - POWER_PENALTY_THRESHOLD) + var/electrolysed = cached_moles[/datum/gas/hypernoblium] * clamp(supermatter_power - POWER_PENALTY_THRESHOLD, 0, CRITICAL_POWER_PENALTY_THRESHOLD - POWER_PENALTY_THRESHOLD) / (CRITICAL_POWER_PENALTY_THRESHOLD - POWER_PENALTY_THRESHOLD) air_mixture.adjust_gas(/datum/gas/hypernoblium, -electrolysed) air_mixture.adjust_gas(/datum/gas/antinoblium, electrolysed) - var/new_heat_capacity = old_heat_capacity + electrolysed * (antinoblium[GAS_META][META_GAS_SPECIFIC_HEAT] - hypernoblium[GAS_META][META_GAS_SPECIFIC_HEAT]) + var/list/cached_specific_heat = GAS_META[META_GAS_SPECIFIC_HEAT] + var/new_heat_capacity = old_heat_capacity + electrolysed * (cached_specific_heat[/datum/gas/antinoblium] - cached_specific_heat[/datum/gas/hypernoblium]) if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air_mixture.temperature = max(air_mixture.temperature * old_heat_capacity / new_heat_capacity, TCMB) @@ -127,7 +126,8 @@ GLOBAL_LIST_INIT(electrolyzer_reactions, electrolyzer_reactions_list()) /datum/electrolyzer_reaction/halon_generation/react(datum/gas_mixture/air_mixture, working_power, list/electrolyzer_args = list()) var/old_heat_capacity = air_mixture.heat_capacity() air_mixture.assert_gases(/datum/gas/bz, /datum/gas/oxygen, /datum/gas/halon) - var/reaction_efficency = min(air_mixture.gases[/datum/gas/bz][MOLES] * (1 - NUM_E ** (-0.5 * air_mixture.temperature * working_power / FIRE_MINIMUM_TEMPERATURE_TO_EXIST)), air_mixture.gases[/datum/gas/bz][MOLES]) + var/bz_moles = air_mixture.moles[/datum/gas/bz] + var/reaction_efficency = min(bz_moles * (1 - NUM_E ** (-0.5 * air_mixture.temperature * working_power / FIRE_MINIMUM_TEMPERATURE_TO_EXIST)), bz_moles) air_mixture.adjust_gas(/datum/gas/bz, -reaction_efficency) air_mixture.adjust_gas(/datum/gas/oxygen, reaction_efficency * 0.2) diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm index 0dbf0cfaa54..0fbe0f01898 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm @@ -86,7 +86,7 @@ negative_temperature_multiplier = selected_fuel.negative_temperature_multiplier for(var/gas_id in selected_fuel.requirements | selected_fuel.primary_products) - var/amount = internal_fusion.gases[gas_id][MOLES] + var/amount = internal_fusion.moles[gas_id] fuel_list[gas_id] = amount scaled_fuel_list[gas_id] = max((amount - FUSION_MOLE_THRESHOLD) / scale_factor, 0) @@ -94,8 +94,7 @@ var/list/moderator_list = list() /// Scaled down moles of gases, no less than 0 var/list/scaled_moderator_list = list() - for(var/gas_id in moderator_internal.gases) - var/amount = moderator_internal.gases[gas_id][MOLES] + for(var/gas_id, amount in moderator_internal.moles) moderator_list[gas_id] = amount scaled_moderator_list[gas_id] = max((amount - FUSION_MOLE_THRESHOLD) / scale_factor, 0) @@ -106,11 +105,9 @@ //The size of the phase space hypertorus var/toroidal_size = (2 * PI) + TORADIANS(arctan((volume - TOROID_VOLUME_BREAKEVEN) / TOROID_VOLUME_BREAKEVEN)) //Calculation of the gas power, only for theoretical instability calculations - var/gas_power = 0 - for (var/gas_id in internal_fusion.gases) - gas_power += (internal_fusion.gases[gas_id][GAS_META][META_GAS_FUSION_POWER] * internal_fusion.gases[gas_id][MOLES]) - for (var/gas_id in moderator_internal.gases) - gas_power += (moderator_internal.gases[gas_id][GAS_META][META_GAS_FUSION_POWER] * moderator_internal.gases[gas_id][MOLES] * 0.75) + var/list/cached_fusion_power = GAS_META[META_GAS_FUSION_POWER] + var/gas_power = values_dot(cached_fusion_power, internal_fusion.moles) + gas_power += 0.75 * values_dot(cached_fusion_power, moderator_internal.moles) instability = MODULUS((gas_power * INSTABILITY_GAS_POWER_FACTOR)**2, toroidal_size) + (current_damper * 0.01) - iron_content * 0.05 //Effective reaction instability (determines if the energy is used/released) @@ -294,31 +291,31 @@ if(1) if(moderator_list[/datum/gas/plasma] > 100) internal_output.adjust_gas(/datum/gas/nitrous_oxide, scaled_production * 0.5) - moderator_internal.adjust_gas(/datum/gas/plasma, min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 0.85)) + moderator_internal.adjust_gas(/datum/gas/plasma, min(moderator_internal.moles[/datum/gas/plasma], scaled_production * 0.85)) if(moderator_list[/datum/gas/bz] > 150) internal_output.adjust_gas(/datum/gas/halon, scaled_production * 0.55) - moderator_internal.adjust_gas(/datum/gas/bz, min(moderator_internal.gases[/datum/gas/bz][MOLES], scaled_production * 0.95)) + moderator_internal.adjust_gas(/datum/gas/bz, min(moderator_internal.moles[/datum/gas/bz], scaled_production * 0.95)) if(2) if(moderator_list[/datum/gas/plasma] > 50) internal_output.adjust_gas(/datum/gas/bz, scaled_production * 1.8) - moderator_internal.adjust_gas(/datum/gas/plasma, min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 1.75)) + moderator_internal.adjust_gas(/datum/gas/plasma, min(moderator_internal.moles[/datum/gas/plasma], scaled_production * 1.75)) if(moderator_list[/datum/gas/proto_nitrate] > 20) radiation *= 1.55 heat_output *= 1.025 internal_output.adjust_gas(/datum/gas/nitrium, scaled_production * 1.05) - moderator_internal.adjust_gas(/datum/gas/proto_nitrate, min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 1.35)) + moderator_internal.adjust_gas(/datum/gas/proto_nitrate, min(moderator_internal.moles[/datum/gas/proto_nitrate], scaled_production * 1.35)) if(3, 4) if(moderator_list[/datum/gas/plasma] > 10) var/list/new_gases = list(/datum/gas/freon = scaled_production * 0.15, /datum/gas/nitrium = scaled_production * 1.05) internal_output.adjust_multiple_gases(new_gases) - moderator_internal.adjust_gas(/datum/gas/plasma, min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 0.45)) + moderator_internal.adjust_gas(/datum/gas/plasma, min(moderator_internal.moles[/datum/gas/plasma], scaled_production * 0.45)) if(moderator_list[/datum/gas/freon] > 50) heat_output *= 0.9 radiation *= 0.8 if(moderator_list[/datum/gas/proto_nitrate]> 15) var/list/new_gases = list(/datum/gas/nitrium = scaled_production * 1.25, /datum/gas/halon = scaled_production * 1.15) internal_output.adjust_multiple_gases(new_gases) - moderator_internal.adjust_gas(/datum/gas/proto_nitrate, min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 1.55)) + moderator_internal.adjust_gas(/datum/gas/proto_nitrate, min(moderator_internal.moles[/datum/gas/proto_nitrate], scaled_production * 1.55)) radiation *= 1.95 heat_output *= 1.25 if(moderator_list[/datum/gas/bz] > 100) @@ -329,14 +326,14 @@ if(5) if(moderator_list[/datum/gas/plasma] > 15) internal_output.adjust_gas(/datum/gas/freon, scaled_production *0.25) - moderator_internal.adjust_gas(/datum/gas/plasma,min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 1.45)) + moderator_internal.adjust_gas(/datum/gas/plasma,min(moderator_internal.moles[/datum/gas/plasma], scaled_production * 1.45)) if(moderator_list[/datum/gas/freon] > 500) heat_output *= 0.5 radiation *= 0.2 if(moderator_list[/datum/gas/proto_nitrate] > 50) var/list/new_gases = list(/datum/gas/nitrium = scaled_production * 1.95, /datum/gas/pluoxium = scaled_production) internal_output.adjust_multiple_gases(new_gases) - moderator_internal.adjust_gas(/datum/gas/proto_nitrate, min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 1.35)) + moderator_internal.adjust_gas(/datum/gas/proto_nitrate, min(moderator_internal.moles[/datum/gas/proto_nitrate], scaled_production * 1.35)) radiation *= 1.95 heat_output *= 1.25 if(moderator_list[/datum/gas/bz] > 100) @@ -346,18 +343,18 @@ if(moderator_list[/datum/gas/healium] > 100) if(critical_threshold_proximity > 400) critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[/datum/gas/healium] / 100 * seconds_per_tick ), 0) - moderator_internal.adjust_gas(/datum/gas/healium, -min(moderator_internal.gases[/datum/gas/healium][MOLES], scaled_production * 20)) + moderator_internal.adjust_gas(/datum/gas/healium, -min(moderator_internal.moles[/datum/gas/healium], scaled_production * 20)) if(moderator_internal.temperature < 1e7 || (moderator_list[/datum/gas/plasma] > 100 && moderator_list[/datum/gas/bz] > 50)) internal_output.adjust_gas(/datum/gas/antinoblium, dirty_production_rate * 0.9 / 0.065 * seconds_per_tick) if(6) internal_output.assert_gases(/datum/gas/antinoblium) if(moderator_list[/datum/gas/plasma] > 30) internal_output.adjust_gas(/datum/gas/bz, scaled_production * 1.15) - moderator_internal.adjust_gas(/datum/gas/plasma, -min(moderator_internal.gases[/datum/gas/plasma][MOLES], scaled_production * 1.45)) + moderator_internal.adjust_gas(/datum/gas/plasma, -min(moderator_internal.moles[/datum/gas/plasma], scaled_production * 1.45)) if(moderator_list[/datum/gas/proto_nitrate]) var/list/new_gases = list(/datum/gas/zauker = scaled_production * 5.35, /datum/gas/nitrium = scaled_production * 2.15) internal_output.adjust_multiple_gases(new_gases) - moderator_internal.adjust_gas(/datum/gas/proto_nitrate, -min(moderator_internal.gases[/datum/gas/proto_nitrate][MOLES], scaled_production * 3.35)) + moderator_internal.adjust_gas(/datum/gas/proto_nitrate, -min(moderator_internal.moles[/datum/gas/proto_nitrate], scaled_production * 3.35)) radiation *= 2 heat_output *= 2.25 if(moderator_list[/datum/gas/bz]) @@ -366,7 +363,7 @@ if(moderator_list[/datum/gas/healium] > 100) if(critical_threshold_proximity > 400) critical_threshold_proximity = max(critical_threshold_proximity - (moderator_list[/datum/gas/healium] / 100 * seconds_per_tick ), 0) - moderator_internal.adjust_gas(/datum/gas/healium, -min(moderator_internal.gases[/datum/gas/healium][MOLES], scaled_production * 20)) + moderator_internal.adjust_gas(/datum/gas/healium, -min(moderator_internal.moles[/datum/gas/healium], scaled_production * 20)) internal_fusion.adjust_gas(/datum/gas/antinoblium, dirty_production_rate * 0.01 / 0.095 * seconds_per_tick) //Modifies the internal_fusion temperature with the amount of heat output @@ -510,7 +507,7 @@ if(!waste_remove) return var/filtering_amount = moderator_scrubbing.len - for(var/gas in moderator_internal.gases & moderator_scrubbing) + for(var/gas in moderator_internal.moles & moderator_scrubbing) var/datum/gas_mixture/removed = moderator_internal.remove_specific(gas, (moderator_filtering_rate / filtering_amount) * seconds_per_tick) if(removed) linked_output.airs[1].merge(removed) @@ -518,8 +515,8 @@ if (selected_fuel) var/datum/gas_mixture/internal_remove for(var/gas_id in selected_fuel.primary_products) - if(internal_fusion.gases[gas_id][MOLES] > 0) - internal_remove = internal_fusion.remove_specific(gas_id, internal_fusion.gases[gas_id][MOLES] * (1 - (1 - 0.25) ** seconds_per_tick)) + if(internal_fusion.moles[gas_id] > 0) + internal_remove = internal_fusion.remove_specific(gas_id, internal_fusion.moles[gas_id] * (1 - (1 - 0.25) ** seconds_per_tick)) linked_output.airs[1].merge(internal_remove) internal_fusion.garbage_collect() moderator_internal.garbage_collect() diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm index a1878159900..13cde0056e5 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm @@ -219,14 +219,14 @@ //Internal Fusion gases var/list/fusion_gasdata = list() if(connected_core.internal_fusion.total_moles()) - for(var/gas_type in connected_core.internal_fusion.gases) + for(var/gas_type in connected_core.internal_fusion.moles) var/datum/gas/gas = gas_type fusion_gasdata.Add(list(list( "id"= initial(gas.id), - "amount" = round(connected_core.internal_fusion.gases[gas][MOLES], 0.01), + "amount" = round(connected_core.internal_fusion.moles[gas], 0.01), ))) else - for(var/gas_type in connected_core.internal_fusion.gases) + for(var/gas_type in connected_core.internal_fusion.moles) var/datum/gas/gas = gas_type fusion_gasdata.Add(list(list( "id"= initial(gas.id), @@ -235,14 +235,14 @@ //Moderator gases var/list/moderator_gasdata = list() if(connected_core.moderator_internal.total_moles()) - for(var/gas_type in connected_core.moderator_internal.gases) + for(var/gas_type in connected_core.moderator_internal.moles) var/datum/gas/gas = gas_type moderator_gasdata.Add(list(list( "id"= initial(gas.id), - "amount" = round(connected_core.moderator_internal.gases[gas][MOLES], 0.01), + "amount" = round(connected_core.moderator_internal.moles[gas], 0.01), ))) else - for(var/gas_type in connected_core.moderator_internal.gases) + for(var/gas_type in connected_core.moderator_internal.moles) var/datum/gas/gas = gas_type moderator_gasdata.Add(list(list( "id"= initial(gas.id), @@ -288,9 +288,13 @@ data["waste_remove"] = connected_core.waste_remove data["filter_types"] = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in connected_core.moderator_scrubbing))) + var/cached_gas_info = GLOB.meta_gas_info + for(var/path in cached_gas_info[META_GAS_ID]) + data["filter_types"] += list(list( + "gas_id" = cached_gas_info[META_GAS_ID][path], + "gas_name" = cached_gas_info[META_GAS_NAME][path], + "enabled" = (path in connected_core.moderator_scrubbing) + )) data["cooling_volume"] = connected_core.airs[1].volume data["mod_filtering_rate"] = connected_core.moderator_filtering_rate diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm index ddf8f950aa1..457db380e2f 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm @@ -167,7 +167,7 @@ internal_fusion.assert_gas(/datum/gas/antinoblium) - moderator_internal.assert_gases(arglist(GLOB.meta_gas_info)) + moderator_internal.assert_gases(arglist(GLOB.meta_gas_info[META_GAS_ID])) if (!selected_fuel) return @@ -241,7 +241,7 @@ return FALSE for(var/gas_type in selected_fuel.requirements) internal_fusion.assert_gas(gas_type) - if(internal_fusion.gases[gas_type][MOLES] < FUSION_MOLE_THRESHOLD) + if(internal_fusion.moles[gas_type] < FUSION_MOLE_THRESHOLD) return FALSE return TRUE @@ -261,7 +261,7 @@ /obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_gas_requirements() var/datum/gas_mixture/contents = linked_input.airs[1] for(var/gas_type in selected_fuel.requirements) - if(!contents.gases[gas_type] || !contents.gases[gas_type][MOLES]) + if(!contents.moles[gas_type]) return FALSE return TRUE diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm index 5f24e939746..91da68f1c7e 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm @@ -106,19 +106,19 @@ /obj/machinery/atmospherics/components/binary/crystallizer/proc/inject_gases() var/datum/gas_mixture/contents = airs[2] for(var/gas_type in selected_recipe.requirements) - if(!contents.gases[gas_type] || !contents.gases[gas_type][MOLES]) + if(!contents.moles[gas_type]) continue - if(internal.gases[gas_type] && internal.gases[gas_type][MOLES] >= selected_recipe.requirements[gas_type] * 2) + if(internal.moles[gas_type] >= selected_recipe.requirements[gas_type] * 2) continue - internal.merge(contents.remove_specific(gas_type, contents.gases[gas_type][MOLES] * gas_input)) + internal.merge(contents.remove_specific(gas_type, contents.moles[gas_type] * gas_input)) ///Checks if the gases required are all inside /obj/machinery/atmospherics/components/binary/crystallizer/proc/internal_check() var/gas_check = 0 for(var/gas_type in selected_recipe.requirements) - if(!internal.gases[gas_type] || !internal.gases[gas_type][MOLES]) + if(!internal.moles[gas_type]) return FALSE - if(internal.gases[gas_type][MOLES] >= selected_recipe.requirements[gas_type]) + if(internal.moles[gas_type] >= selected_recipe.requirements[gas_type]) gas_check++ if(gas_check == selected_recipe.requirements.len) return TRUE @@ -190,7 +190,7 @@ for(var/gas_type in selected_recipe.requirements) var/required_gas_moles = selected_recipe.requirements[gas_type] var/amount_consumed = required_gas_moles + (required_gas_moles * (quality_loss * 0.01)) - if(internal.gases[gas_type][MOLES] < amount_consumed) + if(internal.moles[gas_type] < amount_consumed) quality_loss = min(quality_loss + 10, 100) internal.remove_specific(gas_type, amount_consumed) @@ -257,18 +257,20 @@ data["selected"] = "" var/list/internal_gas_data = list() + var/list/cached_gas_name = GAS_META[META_GAS_NAME] + var/list/cached_gas_id = GAS_META[META_GAS_ID] if(internal.total_moles()) - for(var/gasid in internal.gases) + for(var/gasid, amount in internal.moles) internal_gas_data.Add(list(list( - "name"= internal.gases[gasid][GAS_META][META_GAS_NAME], - "id" = internal.gases[gasid][GAS_META][META_GAS_ID], - "amount" = round(internal.gases[gasid][MOLES], 0.01), + "name"= cached_gas_name[gasid], + "id" = cached_gas_id[gasid], + "amount" = round(amount, 0.01), ))) else - for(var/gasid in internal.gases) + for(var/gasid in internal.moles) internal_gas_data.Add(list(list( - "name"= internal.gases[gasid][GAS_META][META_GAS_NAME], - "id" = internal.gases[gasid][GAS_META][META_GAS_ID], + "name"= cached_gas_name[gasid], + "id" = cached_gas_id[gasid], "amount" = 0, ))) data["internal_gas_data"] = internal_gas_data diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm index e5b32b695c4..76a78ab1cac 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm @@ -98,7 +98,7 @@ if(filtering) var/datum/gas_mixture/filtered_out = new - for(var/gas in removed.gases & filter_type) + for(var/gas in removed.moles & filter_type) var/datum/gas_mixture/removing = removed.remove_specific_ratio(gas, 1) if(removing) filtered_out.merge(removing) @@ -133,9 +133,9 @@ data["max_rate"] = round(MAX_TRANSFER_RATE) data["filter_types"] = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "enabled" = (path in filter_type))) + var/cached_gas_info = GLOB.meta_gas_info + for(var/path in cached_gas_info[META_GAS_ID]) + data["filter_types"] += list(list("gas_id" = cached_gas_info[META_GAS_ID][path], "enabled" = (path in filter_type))) return data @@ -168,7 +168,7 @@ change = "added" else change = "removed" - var/gas_name = GLOB.meta_gas_info[gas_id2path(params["val"])][META_GAS_NAME] + var/gas_name = GLOB.meta_gas_info[META_GAS_NAME][gas_id2path(params["val"])] usr.investigate_log("[change] [gas_name] from the filter type.", INVESTIGATE_ATMOS) . = TRUE update_appearance(UPDATE_ICON) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index c265073dd2c..ba6680979fb 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -445,7 +445,7 @@ var/datum/gas_mixture/air1 = internal_connector.gas_connector.airs[1] //check for workable conditions - if(!internal_connector.gas_connector.nodes[1] || !air1 || !air1.gases.len || air1.total_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work. + if(!internal_connector.gas_connector.nodes[1] || !air1 || !air1.moles.len || air1.total_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work. set_on(FALSE) aas_config_announce(/datum/aas_config_entry/medical_cryo_announcements, list("EJECTING" = autoeject), src, list(broadcast_channel), "Insufficient Gas") if(autoeject) // Eject if configured. diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 29060150cd6..9200d94dbe3 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -186,12 +186,10 @@ set_on(FALSE) return FALSE - var/list/changed_gas = air.gases - - if(!changed_gas) + if(!air.moles) return FALSE - if(scrubbing == ATMOS_DIRECTION_SIPHONING || length(filter_types & changed_gas)) + if(scrubbing == ATMOS_DIRECTION_SIPHONING || length(filter_types & air.moles)) return TRUE return FALSE @@ -223,36 +221,36 @@ return FALSE var/datum/gas_mixture/environment = tile.return_air() var/datum/gas_mixture/air_contents = airs[1] - var/list/env_gases = environment.gases + var/list/env_cached_moles = environment.moles if(air_contents.return_pressure() >= 50 * ONE_ATMOSPHERE) return FALSE if(scrubbing == ATMOS_DIRECTION_SCRUBBING) - if(length(env_gases & filter_types)) + if(length(env_cached_moles & filter_types)) ///contains all of the gas we're sucking out of the tile, gets put into our parent pipenet var/datum/gas_mixture/filtered_out = new - var/list/filtered_gases = filtered_out.gases + var/list/filtered_out_cached_moles = filtered_out.moles filtered_out.temperature = environment.temperature ///maximum percentage of the turfs gas we can filter var/removal_ratio = min(1, volume_rate / environment.volume) var/total_moles_to_remove = 0 - for(var/gas in filter_types & env_gases) - total_moles_to_remove += env_gases[gas][MOLES] + for(var/gas_id in filter_types & env_cached_moles) + total_moles_to_remove += env_cached_moles[gas_id] if(total_moles_to_remove == 0)//sometimes this gets non gc'd values environment.garbage_collect() return FALSE - for(var/gas in filter_types & env_gases) - filtered_out.add_gas(gas) - //take this gases portion of removal_ratio of the turfs air, or all of that gas if less than or equal to MINIMUM_MOLES_TO_SCRUB - var/transferred_moles = max(QUANTIZE(env_gases[gas][MOLES] * removal_ratio * (env_gases[gas][MOLES] / total_moles_to_remove)), min(MINIMUM_MOLES_TO_SCRUB, env_gases[gas][MOLES])) + for(var/gas_id in filter_types & env_cached_moles) + filtered_out.add_gas(gas_id) + //take this gases portion of removal_ratio of the turfs air, or all of that gas_id if less than or equal to MINIMUM_MOLES_TO_SCRUB + var/transferred_moles = max(QUANTIZE(env_cached_moles[gas_id] * removal_ratio * (env_cached_moles[gas_id] / total_moles_to_remove)), min(MINIMUM_MOLES_TO_SCRUB, env_cached_moles[gas_id])) - filtered_gases[gas][MOLES] = transferred_moles - env_gases[gas][MOLES] -= transferred_moles + filtered_out_cached_moles[gas_id] = transferred_moles + env_cached_moles[gas_id] -= transferred_moles environment.garbage_collect() diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 3b39241f6fd..c229453b61d 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -254,12 +254,13 @@ var/total_thermal_energy = 0 var/total_heat_capacity = 0 - var/list/total_gases = list() - var/volume_sum = 0 var/static/process_id = 0 process_id = WRAP_UID(process_id + 1) + var/datum/gas_mixture/total_gas_mixture = new + var/list/total_cached_moles = total_gas_mixture.moles + var/list/cached_specific_heat = GAS_META[META_GAS_SPECIFIC_HEAT] for(var/datum/gas_mixture/gas_mixture as anything in gas_mixture_list) // Ensure we never walk the same mix twice @@ -271,14 +272,11 @@ // This is sort of a combined merge + heat_capacity calculation - var/list/giver_gases = gas_mixture.gases - var/heat_capacity = 0 + var/list/giver_cached_moles = gas_mixture.moles + var/heat_capacity = values_dot(giver_cached_moles, cached_specific_heat) //gas transfer - for(var/giver_id in giver_gases) - var/giver_gas_data = giver_gases[giver_id] - ASSERT_GAS_IN_LIST(giver_id, total_gases) - total_gases[giver_id][MOLES] += giver_gas_data[MOLES] - heat_capacity += giver_gas_data[MOLES] * giver_gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] + for(var/gas_id, amount in giver_cached_moles) + total_cached_moles[gas_id] += amount total_heat_capacity += heat_capacity total_thermal_energy += gas_mixture.temperature * heat_capacity @@ -286,9 +284,8 @@ if(volume_sum == 0) return - var/datum/gas_mixture/total_gas_mixture = new(volume_sum) + total_gas_mixture.volume = volume_sum total_gas_mixture.temperature = total_heat_capacity ? (total_thermal_energy / total_heat_capacity) : 0 - total_gas_mixture.gases = total_gases total_gas_mixture.garbage_collect() //Update individual gas_mixtures by volume ratio @@ -330,8 +327,8 @@ var/current_weight = 0 var/current_color - for(var/datum/gas/gas_path as anything in air.gases) - var/gas_weight = air.gases[gas_path][MOLES] + for(var/datum/gas/gas_path as anything in air.moles) + var/gas_weight = air.moles[gas_path] if(!gas_weight) continue var/gas_color = initial(gas_path.primary_color) diff --git a/code/modules/atmospherics/machinery/other/miner.dm b/code/modules/atmospherics/machinery/other/miner.dm index f61ebf3766b..d588bd88628 100644 --- a/code/modules/atmospherics/machinery/other/miner.dm +++ b/code/modules/atmospherics/machinery/other/miner.dm @@ -136,7 +136,7 @@ return FALSE var/datum/gas_mixture/merger = new merger.assert_gas(spawn_id) - merger.gases[spawn_id][MOLES] = spawn_mol * seconds_per_tick + merger.moles[spawn_id] = spawn_mol * seconds_per_tick merger.temperature = spawn_temp O.assume_air(merger) diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index 4a669154580..11401bb3f55 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -66,7 +66,7 @@ create_gas() if(ispath(gas_type, /datum/gas)) - desc = "[GLOB.meta_gas_info[gas_type][META_GAS_NAME]]. [GLOB.meta_gas_info[gas_type][META_GAS_DESC]]" + desc = "[GLOB.meta_gas_info[META_GAS_NAME][gas_type]]. [GLOB.meta_gas_info[META_GAS_DESC][gas_type]]" update_window() @@ -707,13 +707,15 @@ output += "[key_name(user)] opened a canister[wire_pulsed ? " via wire pulse" : ""] that contains the following:" var/list/admin_output = list() admin_output += "[ADMIN_LOOKUPFLW(user)] opened a canister[wire_pulsed ? " via wire pulse" : ""] that contains the following at [ADMIN_VERBOSEJMP(src)]:" - var/list/gases = air_contents.gases + var/list/cached_moles = air_contents.moles + var/list/cached_gas_name = GAS_META[META_GAS_NAME] + var/list/cached_gas_danger = GAS_META[META_GAS_DANGER] + var/list/cached_gas_visible = GAS_META[META_GAS_MOLES_VISIBLE] var/danger = FALSE - for(var/gas_index in 1 to length(gases)) - var/list/gas_info = gases[gases[gas_index]] - var/list/meta = gas_info[GAS_META] - var/name = meta[META_GAS_NAME] - var/moles = gas_info[MOLES] + for(var/gas_index in 1 to length(cached_moles)) + var/gas_id = cached_moles[gas_index] + var/name = cached_gas_name[gas_id] + var/moles = cached_moles[gas_id] output += "[name]: [moles] moles." if(gas_index <= 5) //the first five gases added @@ -721,7 +723,7 @@ else if(gas_index == 6) // anddd the warning admin_output += "Too many gases to log. Check investigate log." //if moles_visible is undefined, default to default visibility - if(meta[META_GAS_DANGER] && moles > (meta[META_GAS_MOLES_VISIBLE] || MOLES_GAS_VISIBLE)) + if(cached_gas_danger[gas_id] && moles > (cached_gas_visible[gas_id] || MOLES_GAS_VISIBLE)) danger = TRUE if(danger) //sent to admin's chat if contains dangerous gases diff --git a/code/modules/atmospherics/machinery/portable/pipe_scrubber.dm b/code/modules/atmospherics/machinery/portable/pipe_scrubber.dm index 6ab73e5b2e1..93c6ba513e5 100644 --- a/code/modules/atmospherics/machinery/portable/pipe_scrubber.dm +++ b/code/modules/atmospherics/machinery/portable/pipe_scrubber.dm @@ -91,11 +91,11 @@ return filtered.temperature = filtering.temperature - for(var/gas in filtering.gases & scrubbing) + for(var/gas in filtering.moles & scrubbing) filtered.add_gas(gas) - filtered.gases[gas][MOLES] = filtering.gases[gas][MOLES] // Shuffle the "bad" gasses to the filtered mixture. - filtering.gases[gas][MOLES] = 0 + filtered.moles[gas] = filtering.moles[gas] // Shuffle the "bad" gasses to the filtered mixture. + filtering.moles[gas] = 0 filtering.garbage_collect() // Now that the gasses are set to 0, clean up the mixture. internal_tank.air_contents.merge(filtered) // Store filtered out gasses. @@ -118,9 +118,13 @@ data["reactionSuppressionEnabled"] = suppress_reactions data["filterTypes"] = list() - for(var/gas_path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[gas_path] - data["filterTypes"] += list(list("gasId" = gas[META_GAS_ID], "gasName" = gas[META_GAS_NAME], "enabled" = (gas_path in scrubbing))) + var/cached_gas_info = GLOB.meta_gas_info + for(var/gas_path in cached_gas_info[META_GAS_ID]) + data["filterTypes"] += list(list( + "gasId" = cached_gas_info[META_GAS_ID][gas_path], + "gasName" = cached_gas_info[META_GAS_NAME][gas_path], + "enabled" = (gas_path in scrubbing) + )) return data diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm index 99b75afa0f6..3996c402d61 100644 --- a/code/modules/atmospherics/machinery/portable/pump.dm +++ b/code/modules/atmospherics/machinery/portable/pump.dm @@ -119,11 +119,11 @@ if(on) SSair.start_processing_machine(src) if(on && !holding) - var/plasma = air_contents.gases[/datum/gas/plasma] - var/n2o = air_contents.gases[/datum/gas/nitrous_oxide] - if(n2o || plasma) - message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]") - log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]") + var/plasma_moles = air_contents.moles[/datum/gas/plasma] + var/n2o_moles = air_contents.moles[/datum/gas/nitrous_oxide] + if(n2o_moles || plasma_moles) + message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o_moles ? "N2O" : ""][n2o_moles && plasma_moles ? " & " : ""][plasma_moles ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]") + log_admin("[key_name(usr)] turned on a pump that contains [n2o_moles ? "N2O" : ""][n2o_moles && plasma_moles ? " & " : ""][plasma_moles ? "Plasma" : ""] at [AREACOORD(src)]") else if(on && direction == PUMP_OUT) usr.investigate_log("started a transfer into [holding].", INVESTIGATE_ATMOS) . = TRUE diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm index 516aa657971..9330d6c2351 100644 --- a/code/modules/atmospherics/machinery/portable/scrubber.dm +++ b/code/modules/atmospherics/machinery/portable/scrubber.dm @@ -80,7 +80,7 @@ if(air_contents.return_pressure() >= overpressure_m * ONE_ATMOSPHERE) return - var/list/env_gases = environment.gases + var/list/cached_moles = environment.moles //contains all of the gas we're sucking out of the tile, gets put into our parent pipenet var/datum/gas_mixture/filtered_out = new @@ -91,24 +91,17 @@ var/removal_ratio = min(1, volume_rate / environment.volume) var/total_moles_to_remove = 0 - for(var/gas in env_gases & scrubbing) - total_moles_to_remove += env_gases[gas][MOLES] + for(var/gas_id in cached_moles & scrubbing) + total_moles_to_remove += cached_moles[gas_id] if(!total_moles_to_remove)//no gases to remove return FALSE - for(var/gas in env_gases & scrubbing) - var/transferred_moles = env_gases[gas] - // somehow gases with 0 moles can creep into our list which gets removed with `adjust_gas()` - // that compounded with the fact our for loop copies our list means it never gets updated so we may - // end up with an GC'd gas and that's bad so let's not - if(!transferred_moles) - continue - transferred_moles = transferred_moles[MOLES] - transferred_moles = max(QUANTIZE(transferred_moles * removal_ratio * (transferred_moles / total_moles_to_remove)), min(MOLAR_ACCURACY * 1000, transferred_moles)) + for(var/gas_id in cached_moles & scrubbing) + var/transferred_moles = max(QUANTIZE(cached_moles[gas_id] * removal_ratio * (cached_moles[gas_id] / total_moles_to_remove)), min(MOLAR_ACCURACY*1000, cached_moles[gas_id])) - filtered_out.adjust_gas(gas, transferred_moles) - environment.adjust_gas(gas, -transferred_moles) + filtered_out.moles[gas_id] += transferred_moles + cached_moles[gas_id] -= transferred_moles //Remix the resulting gases air_contents.merge(filtered_out) @@ -140,9 +133,13 @@ data["reactionSuppressionEnabled"] = !!suppress_reactions data["filterTypes"] = list() - for(var/path in GLOB.meta_gas_info) - var/list/gas = GLOB.meta_gas_info[path] - data["filterTypes"] += list(list("gasId" = gas[META_GAS_ID], "gasName" = gas[META_GAS_NAME], "enabled" = (path in scrubbing))) + var/cached_gas_info = GLOB.meta_gas_info + for(var/path in cached_gas_info[META_GAS_ID]) + data["filterTypes"] += list(list( + "gasId" = cached_gas_info[META_GAS_ID][path], + "gasName" = cached_gas_info[META_GAS_NAME][path], + "enabled" = (path in scrubbing) + )) if(holding) data["holding"] = list() diff --git a/code/modules/cargo/bounties/atmos.dm b/code/modules/cargo/bounties/atmos.dm index 3edc4f9665f..a24a45341e0 100644 --- a/code/modules/cargo/bounties/atmos.dm +++ b/code/modules/cargo/bounties/atmos.dm @@ -13,14 +13,14 @@ return FALSE var/obj/item/tank/applied_tank = applied_obj var/datum/gas_mixture/our_mix = applied_tank.return_air() - if(!our_mix.gases[gas_type]) + if(!our_mix.moles[gas_type]) return FALSE - return our_mix.gases[gas_type][MOLES] >= moles_required + return our_mix.moles[gas_type] >= moles_required /datum/bounty/item/atmospherics/contribution_amount(obj/shipped) var/obj/item/tank/shipped_tank = shipped var/datum/gas_mixture/our_mix = shipped_tank.return_air() - return our_mix.gases[gas_type][MOLES] + return our_mix.moles[gas_type] /datum/bounty/item/atmospherics/pluox_tank name = "Full Tank of Pluoxium" diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index 267dd2e54a5..9c4754c64ee 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -126,7 +126,7 @@ var/datum/gas_mixture/canister_mix = canister.return_air() if(!canister_mix.total_moles()) return 0 - var/canister_gas = canister_mix.gases + var/cached_moles = canister_mix.moles var/static/list/gases_to_check = list( /datum/gas/bz, @@ -146,10 +146,10 @@ ) var/worth = cost - for(var/gasID in gases_to_check) - canister_mix.assert_gas(gasID) - if(canister_gas[gasID][MOLES] > 0) - worth += get_gas_value(gasID, canister_gas[gasID][MOLES]) + for(var/gas_id in gases_to_check) + canister_mix.assert_gas(gas_id) + if(cached_moles[gas_id] > 0) + worth += get_gas_value(gas_id, cached_moles[gas_id]) if(worth > MAX_GAS_CREDITS) worth = MAX_GAS_CREDITS break diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm index 127fb54d4b5..cdfb7138de9 100644 --- a/code/modules/cargo/packs/materials.dm +++ b/code/modules/cargo/packs/materials.dm @@ -84,7 +84,7 @@ // This is the amount of moles in a default canister var/moleCount = (initial(fakeCanister.maximum_pressure) * initial(fakeCanister.filled)) * initial(fakeCanister.volume) / (R_IDEAL_GAS_EQUATION * T20C) - for(var/gasType in GLOB.meta_gas_info) + for(var/gasType in GLOB.meta_gas_info[META_GAS_ID]) var/datum/gas/gas = gasType var/name = initial(gas.name) if(!initial(gas.purchaseable)) diff --git a/code/modules/clothing/masks/gas_filter.dm b/code/modules/clothing/masks/gas_filter.dm index 49ce45f1b1d..b9d8f786483 100644 --- a/code/modules/clothing/masks/gas_filter.dm +++ b/code/modules/clothing/masks/gas_filter.dm @@ -68,32 +68,29 @@ var/danger_points = 0 - for(var/gas_id in breath.gases) - var/iterating_gas = breath.gases[gas_id] - if(!iterating_gas) - continue + for(var/gas_id, amount in breath.moles) if(gas_id in high_filtering_gases) - if(iterating_gas[MOLES] > HIGH_FILTERING_MOLES) - breath.set_gas(gas_id, max(iterating_gas[MOLES] - filter_strength_high * filter_efficiency * HIGH_FILTERING_RATIO, 0)) + if(amount > HIGH_FILTERING_MOLES) + breath.set_gas(gas_id, max(amount - filter_strength_high * filter_efficiency * HIGH_FILTERING_RATIO, 0)) danger_points += 1 continue - breath.set_gas(gas_id, max(iterating_gas[MOLES] - filter_strength_high * filter_efficiency * LOW_FILTERING_RATIO, 0)) + breath.set_gas(gas_id, max(amount - filter_strength_high * filter_efficiency * LOW_FILTERING_RATIO, 0)) danger_points += 0.2 continue if(gas_id in mid_filtering_gases) - if(iterating_gas[MOLES] > MID_FILTERING_MOLES) - breath.set_gas(gas_id, max(iterating_gas[MOLES] - filter_strength_mid * filter_efficiency * HIGH_FILTERING_RATIO, 0)) + if(amount > MID_FILTERING_MOLES) + breath.set_gas(gas_id, max(amount - filter_strength_mid * filter_efficiency * HIGH_FILTERING_RATIO, 0)) danger_points += 1.25 continue - breath.set_gas(gas_id, max(iterating_gas[MOLES] - filter_strength_mid * filter_efficiency * LOW_FILTERING_RATIO, 0)) + breath.set_gas(gas_id, max(amount - filter_strength_mid * filter_efficiency * LOW_FILTERING_RATIO, 0)) danger_points += 0.25 continue if(gas_id in low_filtering_gases) - if(iterating_gas[MOLES] > LOW_FILTERING_MOLES) - breath.set_gas(gas_id, max(iterating_gas[MOLES] - filter_strength_low * filter_efficiency * HIGH_FILTERING_RATIO, 0)) + if(amount > LOW_FILTERING_MOLES) + breath.set_gas(gas_id, max(amount - filter_strength_low * filter_efficiency * HIGH_FILTERING_RATIO, 0)) danger_points += 1.5 continue - breath.set_gas(gas_id, max(iterating_gas[MOLES] - filter_strength_low * filter_efficiency * LOW_FILTERING_RATIO, 0)) + breath.set_gas(gas_id, max(amount - filter_strength_low * filter_efficiency * LOW_FILTERING_RATIO, 0)) danger_points += 0.5 continue diff --git a/code/modules/events/space_vines/vine_mutations.dm b/code/modules/events/space_vines/vine_mutations.dm index 542e8f092c9..bfe185657a2 100644 --- a/code/modules/events/space_vines/vine_mutations.dm +++ b/code/modules/events/space_vines/vine_mutations.dm @@ -285,10 +285,10 @@ return var/datum/gas_mixture/gas_mix = turf.air - if(!gas_mix.gases[gas_type]) + if(!gas_mix.moles[gas_type]) return - gas_mix.set_gas(gas_type, max(gas_mix.gases[gas_type][MOLES] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.growth_stage, 0)) + gas_mix.set_gas(gas_type, max(gas_mix.moles[gas_type] - GAS_MUTATION_REMOVAL_MULTIPLIER * holder.growth_stage, 0)) gas_mix.garbage_collect() /datum/spacevine_mutation/gas_eater/oxy_eater diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 195e34f734b..605e88323e3 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -1230,7 +1230,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( var/datum/gas_mixture/mixture = loc.return_air() if(!mixture) return FALSE - if(safe_air_limits && !check_gases(mixture.gases, safe_air_limits)) + if(safe_air_limits && !mixture.check_gases(safe_air_limits)) return FALSE if(!ISINRANGE(mixture.temperature, required_temperature_min, required_temperature_max)) return FALSE diff --git a/code/modules/fishing/fish/types/rift.dm b/code/modules/fishing/fish/types/rift.dm index ca1b17e6910..2e2da5bfd61 100644 --- a/code/modules/fishing/fish/types/rift.dm +++ b/code/modules/fishing/fish/types/rift.dm @@ -202,11 +202,11 @@ //gas check var/datum/gas_mixture/turf_gasmix = onturf.return_air() // likes water, gets sleepy, gets very sleepy - if(turf_gasmix.gases[/datum/gas/water_vapor] && turf_gasmix.gases[/datum/gas/water_vapor][MOLES] >= 5) + if(turf_gasmix.moles[/datum/gas/water_vapor] >= 5) patience_reduction *= 0.5 - if(turf_gasmix.gases[/datum/gas/nitrous_oxide] && turf_gasmix.gases[/datum/gas/nitrous_oxide][MOLES] >= 5) + if(turf_gasmix.moles[/datum/gas/nitrous_oxide] >= 5) patience_reduction *= 0.25 - if(turf_gasmix.gases[/datum/gas/healium] && turf_gasmix.gases[/datum/gas/healium][MOLES] >= 5) + if(turf_gasmix.moles[/datum/gas/healium] >= 5) patience_reduction *= 0.1 if(!ismob(loc)) @@ -396,7 +396,7 @@ visible_message(span_suicide("[user] swallows [src] whole! It looks like they're trying to commit suicide!")) forceMove(user) var/datum/gas_mixture/environment = user.loc.return_air() - var/oxygen_in_air = locate(/datum/gas/oxygen) in environment.gases + var/oxygen_in_air = locate(/datum/gas/oxygen) in environment.moles if(!oxygen_in_air || (status == FISH_DEAD)) visible_message(span_suicide("[user] chokes and dies! (Wait, from the fish or from lack of air?)")) return OXYLOSS diff --git a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm index 7db7107e109..2547b8509d2 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm @@ -159,7 +159,7 @@ var/datum/gas_mixture/mix_to_spawn = new() mix_to_spawn.add_gas(active_gas) - mix_to_spawn.gases[active_gas][MOLES] = possible_gases[active_gas] * seconds_per_tick + mix_to_spawn.moles[active_gas] = possible_gases[active_gas] * seconds_per_tick mix_to_spawn.temperature = T20C var/turf/open/our_turf = get_turf(owner) our_turf.assume_air(mix_to_spawn) diff --git a/code/modules/mob/living/basic/slime/life.dm b/code/modules/mob/living/basic/slime/life.dm index 8d2b0a074df..68f1eb1646d 100644 --- a/code/modules/mob/living/basic/slime/life.dm +++ b/code/modules/mob/living/basic/slime/life.dm @@ -20,10 +20,7 @@ /mob/living/basic/slime/proc/handle_slime_stasis() var/datum/gas_mixture/environment = loc.return_air() - var/bz_percentage = 0 - - if(environment.gases[/datum/gas/bz]) - bz_percentage = environment.gases[/datum/gas/bz][MOLES] / environment.total_moles() + var/bz_percentage = environment.moles[/datum/gas/bz] / environment.total_moles() if(bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) //Check if we should be in stasis if(!has_status_effect(/datum/status_effect/grouped/stasis)) //Check if we don't have the status effect yet diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm index f0e370c668e..bf64860cb54 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm @@ -99,9 +99,9 @@ /mob/living/basic/regal_rat/handle_environment(datum/gas_mixture/environment) . = ..() - if(stat == DEAD || isnull(environment) || isnull(environment.gases[/datum/gas/miasma])) + if(stat == DEAD || isnull(environment) || isnull(environment.moles[/datum/gas/miasma])) return - var/miasma_percentage = environment.gases[/datum/gas/miasma][MOLES] / environment.total_moles() + var/miasma_percentage = environment.moles[/datum/gas/miasma] / environment.total_moles() if(miasma_percentage >= 0.25) heal_bodypart_damage(1) diff --git a/code/modules/mob/living/basic/tree.dm b/code/modules/mob/living/basic/tree.dm index 5d370cf7cfb..5cf9c1bf27a 100644 --- a/code/modules/mob/living/basic/tree.dm +++ b/code/modules/mob/living/basic/tree.dm @@ -66,10 +66,10 @@ if(!isopenturf(loc)) return var/turf/open/our_turf = src.loc - if(!our_turf.air || !our_turf.air.gases[/datum/gas/carbon_dioxide]) + if(!our_turf.air || !our_turf.air.moles[/datum/gas/carbon_dioxide]) return var/datum/gas_mixture/our_air = our_turf.air - var/co2 = our_air.gases[/datum/gas/carbon_dioxide][MOLES] + var/co2 = our_air.moles[/datum/gas/carbon_dioxide] if(co2 > 0 && SPT_PROB(13, seconds_per_tick)) var/amt = min(co2, 9) our_air.adjust_gas(/datum/gas/carbon_dioxide, -amt) diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index e7b45585511..33918c16741 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -18,25 +18,25 @@ var/plasma_used = 0 var/plas_detect_threshold = 0.02 var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - var/list/breath_gases = breath.gases + var/list/breath_moles = breath.moles breath.assert_gases(/datum/gas/plasma, /datum/gas/oxygen) //Partial pressure of the plasma in our breath - var/Plasma_pp = (breath_gases[/datum/gas/plasma][MOLES]/breath.total_moles())*breath_pressure + var/plasma_pp = (breath_moles[/datum/gas/plasma] / breath.total_moles()) * breath_pressure - if(Plasma_pp > plas_detect_threshold) // Detect plasma in air - adjustPlasma(breath_gases[/datum/gas/plasma][MOLES]*250) + if(plasma_pp > plas_detect_threshold) // Detect plasma in air + adjustPlasma(breath_moles[/datum/gas/plasma] * 250) throw_alert(ALERT_XENO_PLASMA, /atom/movable/screen/alert/alien_plas) - plasma_used = breath_gases[/datum/gas/plasma][MOLES] + plasma_used = breath_moles[/datum/gas/plasma] else clear_alert(ALERT_XENO_PLASMA) //Breathe in plasma and out oxygen - breath_gases[/datum/gas/plasma][MOLES] -= plasma_used - breath_gases[/datum/gas/oxygen][MOLES] += plasma_used + breath_moles[/datum/gas/plasma] -= plasma_used + breath_moles[/datum/gas/oxygen] += plasma_used breath.garbage_collect() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 8316c13f27f..28d95bd3626 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1340,12 +1340,9 @@ GLOBAL_LIST_EMPTY(features_by_species) if((suit_flags & STOPSPRESSUREDAMAGE) && (head_flags & STOPSPRESSUREDAMAGE)) return - for(var/gas_id in environment.gases) - var/gas_amount = environment.gases[gas_id][MOLES] - switch(gas_id) - if(/datum/gas/antinoblium) // Antinoblium - irradiates the target. - if(gas_amount >= MOLES_GAS_VISIBLE && SPT_PROB(1, gas_amount * seconds_per_tick)) - SSradiation.irradiate(human) + var/antinoblium_moles = environment.moles[/datum/gas/antinoblium] + if (antinoblium_moles >= MOLES_GAS_VISIBLE && SPT_PROB(1, antinoblium_moles * seconds_per_tick)) + SSradiation.irradiate(human) //////////// // Stun // diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index ab2b0ca061d..404086be71c 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -163,7 +163,7 @@ breath.assert_gases(/datum/gas/bz, /datum/gas/carbon_dioxide, /datum/gas/freon, /datum/gas/plasma, /datum/gas/pluoxium, /datum/gas/miasma, /datum/gas/nitrous_oxide, /datum/gas/nitrium, /datum/gas/oxygen) /// The list of gases in the breath. - var/list/breath_gases = breath.gases + var/list/breath_moles = breath.moles /// Indicates if there are moles of gas in the breath. var/has_moles = breath.total_moles() != 0 @@ -208,16 +208,16 @@ if(has_moles) // Breath has more than 0 moles of gas. // Partial pressures of "main gases". - pluoxium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/pluoxium][MOLES]) - o2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen][MOLES] + (PLUOXIUM_PROPORTION * pluoxium_pp)) - plasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma][MOLES]) - co2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide][MOLES]) + pluoxium_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/pluoxium]) + o2_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/oxygen] + (PLUOXIUM_PROPORTION * pluoxium_pp)) + plasma_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/plasma]) + co2_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/carbon_dioxide]) // Partial pressures of "trace" gases. - bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz][MOLES]) - freon_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/freon][MOLES]) - miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma][MOLES]) - n2o_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrous_oxide][MOLES]) - nitrium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrium][MOLES]) + bz_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/bz]) + freon_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/freon]) + miasma_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/miasma]) + n2o_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/nitrous_oxide]) + nitrium_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/nitrium]) // Breath has 0 moles of gas. else if(can_breathe_vacuum) @@ -235,7 +235,7 @@ // Behaves like Oxygen with 8X efficacy, but metabolizes into a reagent. if(pluoxium_pp) // Inhale Pluoxium. Exhale nothing. - breath_gases[/datum/gas/pluoxium][MOLES] = 0 + breath_moles[/datum/gas/pluoxium] = 0 // Metabolize to reagent. if(pluoxium_pp > gas_stimulation_min) var/existing = reagents.get_reagent_amount(/datum/reagent/pluoxium) @@ -247,7 +247,7 @@ // Minimum Oxygen effects. "Too little oxygen!" if(!can_breathe_vacuum && (o2_pp < safe_oxygen_min)) // Breathe insufficient amount of O2. - oxygen_used = handle_suffocation(o2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen][MOLES]) + oxygen_used = handle_suffocation(o2_pp, safe_oxygen_min, breath_moles[/datum/gas/oxygen]) if(!HAS_TRAIT(src, TRAIT_ANOSMIA)) throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy) else @@ -256,14 +256,14 @@ clear_alert(ALERT_NOT_ENOUGH_OXYGEN) if(o2_pp) // Inhale O2. - oxygen_used = breath_gases[/datum/gas/oxygen][MOLES] + oxygen_used = breath_moles[/datum/gas/oxygen] // Heal mob if not in crit. if(health >= crit_threshold) adjust_oxy_loss(-5) // Exhale equivalent amount of CO2. if(o2_pp) - breath_gases[/datum/gas/oxygen][MOLES] -= oxygen_used - breath_gases[/datum/gas/carbon_dioxide][MOLES] += oxygen_used + breath_moles[/datum/gas/oxygen] -= oxygen_used + breath_moles[/datum/gas/carbon_dioxide] += oxygen_used //-- CARBON DIOXIDE --// // Maximum CO2 effects. "Too much CO2!" @@ -293,7 +293,7 @@ // Maximum Plasma effects. "Too much Plasma!" if(plasma_pp > safe_plas_max) // Plasma side-effects. - var/ratio = (breath_gases[/datum/gas/plasma][MOLES] / safe_plas_max) * 10 + var/ratio = (breath_moles[/datum/gas/plasma] / safe_plas_max) * 10 adjust_tox_loss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE)) if(!HAS_TRAIT(src, TRAIT_ANOSMIA)) throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 434275a1333..b98f552add8 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -208,10 +208,10 @@ GAME_VERB_PROC(/mob, Cell, "Cell", "Admin") var/t = "[span_notice("Coordinates: [x],[y] ")]\n" t += "[span_danger("Temperature: [environment.temperature] ")]\n" - for(var/id in environment.gases) - var/gas = environment.gases[id] - if(gas[MOLES]) - t+="[span_notice("[gas[GAS_META][META_GAS_NAME]]: [gas[MOLES]] ")]\n" + var/list/cached_gas_name = GAS_META[META_GAS_NAME] + for(var/gas_id, gas_moles in environment.moles) + if(gas_moles) + t += "[span_notice("[cached_gas_name[gas_id]]: [gas_moles] ")]\n" to_chat(usr, t) diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm index 015d949f941..eaa5f5176b2 100644 --- a/code/modules/mod/modules/modules_maint.dm +++ b/code/modules/mod/modules/modules_maint.dm @@ -67,7 +67,7 @@ var/turf/wearer_turf = get_turf(src) var/datum/gas_mixture/air = wearer_turf.return_air() - if(!(air.gases[/datum/gas/water_vapor] && (air.gases[/datum/gas/water_vapor][MOLES]) >= 5)) + if(air.moles[/datum/gas/water_vapor] < 5) return //return if there aren't more than 5 Moles of Water Vapor in the air snap_signal() diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index ce521b09752..44482353208 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -292,7 +292,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) // Extra effects should always fire after the compositions are all finished // Some extra effects like [/datum/sm_gas/carbon_dioxide/extra_effects] // needs more than one gas and rely on a fully parsed gas_percentage. - for (var/gas_path in absorbed_gasmix.gases) + for (var/gas_path in absorbed_gasmix.moles) var/datum/sm_gas/sm_gas = current_gas_behavior[gas_path] sm_gas?.extra_effects(src) @@ -340,8 +340,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) merged_gasmix.temperature += device_energy * waste_multiplier / THERMAL_RELEASE_MODIFIER merged_gasmix.temperature = clamp(merged_gasmix.temperature, TCMB, 2500 * waste_multiplier) merged_gasmix.assert_gases(/datum/gas/plasma, /datum/gas/oxygen) - merged_gasmix.gases[/datum/gas/plasma][MOLES] += max(device_energy * waste_multiplier / PLASMA_RELEASE_MODIFIER, 0) - merged_gasmix.gases[/datum/gas/oxygen][MOLES] += max(((device_energy + merged_gasmix.temperature * waste_multiplier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0) + merged_gasmix.moles[/datum/gas/plasma] += max(device_energy * waste_multiplier / PLASMA_RELEASE_MODIFIER, 0) + merged_gasmix.moles[/datum/gas/oxygen] += max(((device_energy + merged_gasmix.temperature * waste_multiplier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0) merged_gasmix.garbage_collect() env.merge(merged_gasmix) air_update_turf(FALSE, FALSE) @@ -659,8 +659,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/total_moles = absorbed_gasmix.total_moles() if(total_moles < MINIMUM_MOLE_COUNT) //it's not worth processing small amounts like these, total_moles can also be 0 in vacuume return - for (var/gas_path in absorbed_gasmix.gases) - var/mole_count = absorbed_gasmix.gases[gas_path][MOLES] + for (var/gas_path, mole_count in absorbed_gasmix.moles) if(mole_count < MINIMUM_MOLE_COUNT) //save processing power from small amounts like these continue gas_percentage[gas_path] = mole_count / total_moles diff --git a/code/modules/power/supermatter/supermatter_gas.dm b/code/modules/power/supermatter/supermatter_gas.dm index 01eb977325e..057cb608679 100644 --- a/code/modules/power/supermatter/supermatter_gas.dm +++ b/code/modules/power/supermatter/supermatter_gas.dm @@ -105,11 +105,11 @@ GLOBAL_LIST_INIT(sm_gas_behavior, init_sm_gas()) return var/co2_pp = sm.absorbed_gasmix.return_pressure() * sm.gas_percentage[/datum/gas/carbon_dioxide] var/co2_ratio = clamp((1/2 * (co2_pp - CO2_CONSUMPTION_PP) / (co2_pp + CO2_PRESSURE_SCALING)), 0, 1) - var/consumed_co2 = sm.absorbed_gasmix.gases[/datum/gas/carbon_dioxide][MOLES] * co2_ratio + var/consumed_co2 = sm.absorbed_gasmix.moles[/datum/gas/carbon_dioxide] * co2_ratio consumed_co2 = min( consumed_co2, - sm.absorbed_gasmix.gases[/datum/gas/carbon_dioxide][MOLES], - sm.absorbed_gasmix.gases[/datum/gas/oxygen][MOLES] + sm.absorbed_gasmix.moles[/datum/gas/carbon_dioxide], + sm.absorbed_gasmix.moles[/datum/gas/oxygen] ) if(!consumed_co2) return @@ -175,7 +175,7 @@ GLOBAL_LIST_INIT(sm_gas_behavior, init_sm_gas()) return var/miasma_pp = sm.absorbed_gasmix.return_pressure() * sm.gas_percentage[/datum/gas/miasma] var/miasma_ratio = clamp(((miasma_pp - MIASMA_CONSUMPTION_PP) / (miasma_pp + MIASMA_PRESSURE_SCALING)) * (1 + (sm.gas_heat_power_generation * MIASMA_GASMIX_SCALING)), 0, 1) - var/consumed_miasma = sm.absorbed_gasmix.gases[/datum/gas/miasma][MOLES] * miasma_ratio + var/consumed_miasma = sm.absorbed_gasmix.moles[/datum/gas/miasma] * miasma_ratio if(!consumed_miasma) return sm.absorbed_gasmix.adjust_gas(/datum/gas/miasma, -consumed_miasma) diff --git a/code/modules/research/ordnance/tank_compressor.dm b/code/modules/research/ordnance/tank_compressor.dm index 0631a7ed0aa..fa6b288d883 100644 --- a/code/modules/research/ordnance/tank_compressor.dm +++ b/code/modules/research/ordnance/tank_compressor.dm @@ -170,8 +170,8 @@ new_record.name = "Log Recording #[record_number]" new_record.experiment_source = inserted_tank.name new_record.timestamp = "[server_timestamp(ic_time = TRUE)] (PT: [round_timestamp()])" - for(var/gas_path in leaked_gas_buffer.gases) - new_record.gas_data[gas_path] = leaked_gas_buffer.gases[gas_path][MOLES] + for(var/gas_path, amount in leaked_gas_buffer.moles) + new_record.gas_data[gas_path] = amount compressor_record += new_record record_number += 1 diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index bfc0f0b6dc9..f24108a4a05 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -113,7 +113,7 @@ Chilling extracts: var/datum/gas_mixture/G = T.air if(istype(G)) G.assert_gas(/datum/gas/plasma) - G.gases[/datum/gas/plasma][MOLES] = 0 + G.moles[/datum/gas/plasma] = 0 filtered = TRUE G.garbage_collect() T.air_update_turf(FALSE, FALSE) diff --git a/code/modules/surgery/bodyparts/bodypart_effects.dm b/code/modules/surgery/bodyparts/bodypart_effects.dm index 7ebfd813c05..d8fea22b95a 100644 --- a/code/modules/surgery/bodyparts/bodypart_effects.dm +++ b/code/modules/surgery/bodyparts/bodypart_effects.dm @@ -165,7 +165,7 @@ REMOVE_TRAIT(owner, TRAIT_IGNORE_FIRE_PROTECTION, type) return - if(environment.gases[/datum/gas/hypernoblium] && environment.gases[/datum/gas/hypernoblium][MOLES] >= 5) + if(environment.moles[/datum/gas/hypernoblium] >= 5) if(owner.on_fire && owner.fire_stacks > 0) owner.adjust_fire_stacks(-fire_stacks_loss * seconds_between_ticks * length(bodyparts)) else @@ -178,7 +178,7 @@ ADD_TRAIT(owner, TRAIT_IGNORE_FIRE_PROTECTION, type) - if(!environment.gases[/datum/gas/oxygen] || environment.gases[/datum/gas/oxygen][MOLES] < 1) //Same threshhold that extinguishes fire + if(environment.moles[/datum/gas/oxygen] < 1) //Same threshhold that extinguishes fire return owner.adjust_fire_stacks(fire_stacks_per_second * seconds_between_ticks * length(bodyparts)) diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index d1a95d8f014..33b4e6b3fcb 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -239,7 +239,7 @@ // Not safe to check the old pp because of can_breath_vacuum breather.throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy) - var/gas_breathed = handle_suffocation(breather, o2_pp, safe_oxygen_min, breath.gases[/datum/gas/oxygen][MOLES]) + var/gas_breathed = handle_suffocation(breather, o2_pp, safe_oxygen_min, breath.moles[/datum/gas/oxygen]) if(o2_pp) breathe_gas_volume(breath, /datum/gas/oxygen, /datum/gas/carbon_dioxide, volume = gas_breathed) return @@ -263,7 +263,7 @@ return BREATH_LOST return - var/ratio = (breath.gases[/datum/gas/oxygen][MOLES] / safe_oxygen_max) * 10 + var/ratio = (breath.moles[/datum/gas/oxygen] / safe_oxygen_max) * 10 breather.apply_damage(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type, spread_damage = TRUE) if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy) @@ -287,7 +287,7 @@ // Not safe to check the old pp because of can_breath_vacuum if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro) - var/gas_breathed = handle_suffocation(breather, nitro_pp, safe_nitro_min, breath.gases[/datum/gas/nitrogen][MOLES]) + var/gas_breathed = handle_suffocation(breather, nitro_pp, safe_nitro_min, breath.moles[/datum/gas/nitrogen]) if(nitro_pp) breathe_gas_volume(breath, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, volume = gas_breathed) return @@ -342,7 +342,7 @@ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) breather.throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas) // Breathe insufficient amount of Plasma, exhale CO2. - var/gas_breathed = handle_suffocation(breather, plasma_pp, safe_plasma_min, breath.gases[/datum/gas/plasma][MOLES]) + var/gas_breathed = handle_suffocation(breather, plasma_pp, safe_plasma_min, breath.moles[/datum/gas/plasma]) if(plasma_pp) breathe_gas_volume(breath, /datum/gas/plasma, /datum/gas/carbon_dioxide, volume = gas_breathed) return @@ -368,7 +368,7 @@ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) - var/ratio = (breath.gases[/datum/gas/plasma][MOLES] / safe_plasma_max) * 10 + var/ratio = (breath.moles[/datum/gas/plasma] / safe_plasma_max) * 10 breather.apply_damage(clamp(ratio, plas_breath_dam_min, plas_breath_dam_max), plas_damage_type, spread_damage = TRUE) /// Resets plasma side effects @@ -558,7 +558,7 @@ /// Radioactive, green gas. Toxin damage, and a radiation chance /obj/item/organ/lungs/proc/too_much_tritium(mob/living/carbon/breather, datum/gas_mixture/breath, trit_pp, old_trit_pp) var/gas_breathed = breathe_gas_volume(breath, /datum/gas/tritium) - var/moles_visible = GLOB.meta_gas_info[/datum/gas/tritium][META_GAS_MOLES_VISIBLE] * BREATH_PERCENTAGE + var/moles_visible = GLOB.meta_gas_info[META_GAS_MOLES_VISIBLE][/datum/gas/tritium] * BREATH_PERCENTAGE // Tritium side-effects. if(gas_breathed > moles_visible) var/ratio = gas_breathed * 15 @@ -625,7 +625,7 @@ breather.failed_last_breath = TRUE // The list of gases in the breath. - var/list/breath_gases = breath.gases + var/list/breath_moles = breath.moles // Copy the breath's temperature into breath_out to avoid cooling the output breath down unfairly breath_out.temperature = breath.temperature @@ -639,8 +639,8 @@ // Build out our partial pressures, for use as we go var/list/partial_pressures = list() - for(var/gas_id in breath_gases) - partial_pressures[gas_id] = breath.get_breath_partial_pressure(breath_gases[gas_id][MOLES] * received_pressure_mult) + for(var/gas_id, amount in breath_moles) + partial_pressures[gas_id] = breath.get_breath_partial_pressure(amount * received_pressure_mult) // Treat gas as other types of gas for(var/list/conversion_packet in treat_as) @@ -658,32 +658,31 @@ var/partial_pressure = partial_pressures[breath_id] || 0 var/old_partial_pressure = last_partial_pressures[breath_id] || 0 // Ensures the gas will always be instanciated, so people can interact with it safely - ASSERT_GAS(breath_id, breath) var/inhale = breathe_always[breath_id] call(src, inhale)(breather, breath, partial_pressure, old_partial_pressure) // Now we'll handle the callbacks that want to be run conditionally off our current breath - for(var/breath_id in breath_gases) - var/when_present = breath_present[breath_id] + for(var/gas_id in breath_moles) + var/when_present = breath_present[gas_id] if(!when_present) continue - var/reaction = call(src, when_present)(breather, breath, partial_pressures[breath_id], last_partial_pressures[breath_id]) + var/reaction = call(src, when_present)(breather, breath, partial_pressures[gas_id], last_partial_pressures[gas_id]) if(reaction == BREATH_LOST) - var/on_lose = breath_lost[breath_id] + var/on_lose = breath_lost[gas_id] if(on_lose) - call(src, on_lose)(breather, breath, partial_pressures[breath_id], last_partial_pressures[breath_id]) + call(src, on_lose)(breather, breath, partial_pressures[gas_id], last_partial_pressures[gas_id]) // Finally, we'll run the callbacks that aren't in breath_gases, but WERE in our last breath - for(var/gas_lost in last_partial_pressures) + for(var/gas_id in last_partial_pressures) // If we still have it, go away - if(breath_gases[gas_lost]) + if(breath_moles[gas_id]) continue - var/on_loss = breath_lost[gas_lost] + var/on_loss = breath_lost[gas_id] if(!on_loss) continue - call(src, on_loss)(breather, breath, last_partial_pressures[gas_lost]) + call(src, on_loss)(breather, breath, last_partial_pressures[gas_id]) src.last_partial_pressures = partial_pressures @@ -711,12 +710,11 @@ /// Removes 100% of the given gas type unless given a volume argument. /// Returns the amount of gas theoretically removed. /obj/item/organ/lungs/proc/breathe_gas_volume(datum/gas_mixture/breath, remove_id, exchange_id = null, volume = INFINITY) - var/list/breath_gases = breath.gases - volume = min(volume, breath_gases[remove_id][MOLES]) - breath_gases[remove_id][MOLES] -= volume + var/list/breath_moles = breath.moles + volume = min(volume, breath_moles[remove_id]) + breath_moles[remove_id] -= volume if(exchange_id) - ASSERT_GAS(exchange_id, breath_out) - breath_out.gases[exchange_id][MOLES] += volume + breath_out.moles[exchange_id] += volume return volume /// Applies suffocation side-effects to a given Human, scaling based on ratio of required pressure VS "true" pressure. @@ -924,8 +922,8 @@ /obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather_slime) . = ..() - if (breath?.gases[/datum/gas/plasma]) - var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma][MOLES]) + if (breath?.moles[/datum/gas/plasma]) + var/plasma_pp = breath.get_breath_partial_pressure(breath.moles[/datum/gas/plasma]) breather_slime.adjust_blood_volume(0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you. /obj/item/organ/lungs/smoker_lungs @@ -1023,7 +1021,7 @@ // Take a "breath" of the air var/datum/gas_mixture/breath = volumed_mix.remove(volumed_mix.total_moles() * BREATH_PERCENTAGE) - var/list/breath_gases = breath.gases + var/list/breath_moles = breath.moles breath.assert_gases( /datum/gas/oxygen, @@ -1034,12 +1032,12 @@ /datum/gas/miasma, ) - var/oxygen_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen][MOLES]) - var/nitrogen_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrogen][MOLES]) - var/plasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma][MOLES]) - var/carbon_dioxide_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide][MOLES]) - var/bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz][MOLES]) - var/miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma][MOLES]) + var/oxygen_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/oxygen]) + var/nitrogen_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/nitrogen]) + var/plasma_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/plasma]) + var/carbon_dioxide_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/carbon_dioxide]) + var/bz_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/bz]) + var/miasma_pp = breath.get_breath_partial_pressure(breath_moles[/datum/gas/miasma]) safe_oxygen_min = max(0, oxygen_pp - GAS_TOLERANCE) safe_nitro_min = max(0, nitrogen_pp - GAS_TOLERANCE) @@ -1120,7 +1118,7 @@ /// H2O electrolysis /obj/item/organ/lungs/ethereal/proc/consume_water(mob/living/carbon/breather, datum/gas_mixture/breath, h2o_pp, old_h2o_pp) - var/gas_breathed = breath.gases[/datum/gas/water_vapor][MOLES] + var/gas_breathed = breath.moles[/datum/gas/water_vapor] breath.adjust_gas(/datum/gas/water_vapor, -gas_breathed) var/list/new_gases = list(/datum/gas/oxygen = gas_breathed, /datum/gas/hydrogen = gas_breathed * 2) breath_out.adjust_multiple_gases(new_gases) diff --git a/code/modules/unit_tests/breath.dm b/code/modules/unit_tests/breath.dm index 2746ea6f461..7de6a67c226 100644 --- a/code/modules/unit_tests/breath.dm +++ b/code/modules/unit_tests/breath.dm @@ -43,7 +43,7 @@ lab_rat = allocate(/mob/living/carbon/human/consistent) source = equip_labrat_internals(lab_rat, /obj/item/tank/internals/emergency_oxygen/empty) source.air_contents.assert_gas(/datum/gas/nitrogen) - source.air_contents.gases[/datum/gas/nitrogen][MOLES] = (10 * ONE_ATMOSPHERE) * source.volume / (R_IDEAL_GAS_EQUATION * T20C) + source.air_contents.moles[/datum/gas/nitrogen] = (10 * ONE_ATMOSPHERE) * source.volume / (R_IDEAL_GAS_EQUATION * T20C) TEST_ASSERT(source.toggle_internals(lab_rat) && !isnull(lab_rat.internal), "Plasmaman toggle_internals() failed to toggle internals") lab_rat.breathe() TEST_ASSERT(lab_rat.failed_last_breath && lab_rat.has_alert(ALERT_NOT_ENOUGH_OXYGEN), "Humans should suffocate from pure n2 tanks") @@ -77,7 +77,7 @@ lab_rat = allocate(/mob/living/carbon/human/species/plasma) source = equip_labrat_internals(lab_rat, /obj/item/tank/internals/emergency_oxygen/empty) source.air_contents.assert_gas(/datum/gas/nitrogen) - source.air_contents.gases[/datum/gas/nitrogen][MOLES] = (10 * ONE_ATMOSPHERE) * source.volume / (R_IDEAL_GAS_EQUATION * T20C) + source.air_contents.moles[/datum/gas/nitrogen] = (10 * ONE_ATMOSPHERE) * source.volume / (R_IDEAL_GAS_EQUATION * T20C) TEST_ASSERT(source.toggle_internals(lab_rat) && !isnull(lab_rat.internal), "Plasmaman toggle_internals() failed to toggle internals") lab_rat.breathe() TEST_ASSERT(lab_rat.failed_last_breath && lab_rat.has_alert(ALERT_NOT_ENOUGH_PLASMA), "Humans should suffocate from pure n2 tanks") diff --git a/code/modules/unit_tests/gas_transfer.dm b/code/modules/unit_tests/gas_transfer.dm index 2b174ad8c62..06f4afd587c 100644 --- a/code/modules/unit_tests/gas_transfer.dm +++ b/code/modules/unit_tests/gas_transfer.dm @@ -25,13 +25,10 @@ first_mix.volume = 200 second_mix.volume = 200 - ASSERT_GAS(/datum/gas/hypernoblium, first_mix) - ASSERT_GAS(/datum/gas/tritium, second_mix) - - first_mix.gases[/datum/gas/hypernoblium][MOLES] = nob_moles + first_mix.moles[/datum/gas/hypernoblium] = nob_moles first_mix.temperature = nob_temp - second_mix.gases[/datum/gas/tritium][MOLES] = trit_moles + second_mix.moles[/datum/gas/tritium] = trit_moles second_mix.temperature = trit_temp var/initial_pressure = second_mix.return_pressure() diff --git a/code/modules/unit_tests/lungs.dm b/code/modules/unit_tests/lungs.dm index 446873d6aa1..4dae873a8e5 100644 --- a/code/modules/unit_tests/lungs.dm +++ b/code/modules/unit_tests/lungs.dm @@ -1,7 +1,7 @@ #define TEST_CHECK_BREATH_MESSAGE(lungs_organ, message) "[lungs_organ.type]/check_breath() [message]" #define TEST_ALERT_THROW_MESSAGE(lungs_organ, alert_name) TEST_CHECK_BREATH_MESSAGE(lungs_organ, "failed to throw alert [alert_name] when expected.") #define TEST_ALERT_INHIBIT_MESSAGE(lungs_organ, alert_name) TEST_CHECK_BREATH_MESSAGE(lungs_organ, "threw alert [alert_name] when it wasn't expected.") -#define GET_MOLES(gas_mixture, gas_type) (gas_mixture.gases[gas_type] ? gas_mixture.gases[gas_type][MOLES] : 0) +#define GET_MOLES(gas_mixture, gas_type) (gas_mixture.moles[gas_type] || 0) /// Tests the standard, plasmaman, and lavaland lungs organ to ensure breathing and suffocation behave as expected. /// Performs a check on each main (can be life-sustaining) gas, and ensures gas alerts are only thrown when expected. @@ -174,7 +174,7 @@ test_mix.temperature = T20C for(var/datum/gas/gas_type as anything in gas_to_percent) test_mix.add_gas(gas_type) - test_mix.gases[gas_type][MOLES] = (ONE_ATMOSPHERE * 2500 / (R_IDEAL_GAS_EQUATION * T20C) * gas_to_percent[gas_type]) + test_mix.moles[gas_type] = (ONE_ATMOSPHERE * 2500 / (R_IDEAL_GAS_EQUATION * T20C) * gas_to_percent[gas_type]) return test_mix /// Set up an O2/N2 gas mix which is "ideal" for organic life.