diff --git a/_maps/RandomRuins/IceRuins/icemoon_hydroponics_lab.dmm b/_maps/RandomRuins/IceRuins/icemoon_hydroponics_lab.dmm index 67613238e83d..0a5f67672fb1 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_hydroponics_lab.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_hydroponics_lab.dmm @@ -281,9 +281,7 @@ /turf/open/floor/plasteel/tech, /area/ruin/powered/hydroponicslab) "gA" = ( -/turf/open/floor/plating/snowed/temperatre{ - initial_gas_mix = "ICEMOON_ATMOS" - }, +/turf/open/floor/plating/snowed, /area/overmap_encounter/planetoid/cave/explored) "gC" = ( /obj/structure/table, @@ -2173,9 +2171,7 @@ /area/ruin/powered/hydroponicslab) "Wi" = ( /obj/structure/marker_beacon, -/turf/open/floor/plating/snowed/temperatre{ - initial_gas_mix = "ICEMOON_ATMOS" - }, +/turf/open/floor/plating/snowed, /area/overmap_encounter/planetoid/cave/explored) "WK" = ( /obj/item/stack/cable_coil/yellow{ diff --git a/code/datums/atmosphere/_atmosphere.dm b/code/datums/atmosphere/_atmosphere.dm index 0652ef5560f6..f3b7fddf60e9 100644 --- a/code/datums/atmosphere/_atmosphere.dm +++ b/code/datums/atmosphere/_atmosphere.dm @@ -17,42 +17,44 @@ generate_gas_string() /datum/atmosphere/proc/generate_gas_string() + // Pure randomization var/target_pressure = rand(minimum_pressure, maximum_pressure) + var/temperature = rand(minimum_temp, maximum_temp) + + // This was used in the old method to keep ratios of gases "correct" even at different pressures. I'm not touching it var/pressure_scalar = target_pressure / maximum_pressure - // 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 - gasmix.set_temperature(rand(minimum_temp, maximum_temp)) - for(var/i in base_gases) - gasmix.set_moles(i, base_gases[i]) - - // Now let the random choices begin - var/datum/gas/gastype - var/amount - while(gasmix.return_pressure() < target_pressure) + // Get the total moles of gas in each turf, and then distribute the gases based on their weights + var/total_moles = target_pressure * CELL_VOLUME / (temperature * R_IDEAL_GAS_EQUATION) + + // The weight of each potential gas + var/list/gas_weights = list() + // The sum of all the weights, used to normalize them + var/sum = 0 + + for(var/gas in base_gases) + var/to_add = base_gases[gas] + gas_weights[gas] = to_add + sum += to_add + + for(var/gas in normal_gases) + // 0.5 to 2x the base amount + var/to_add = normal_gases[gas] * rand(50, 200) / 100 * pressure_scalar + gas_weights[gas] += to_add + sum += to_add + + for(var/gas in restricted_gases) if(!prob(restricted_chance)) - gastype = pick(normal_gases) - amount = normal_gases[gastype] - else - gastype = pick(restricted_gases) - amount = restricted_gases[gastype] - if(gasmix.get_moles(gastype)) - continue - - amount *= rand(50, 200) / 100 // Randomly modifes the amount from half to double the base for some variety - 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) - - gasmix.set_moles(gastype, gasmix.get_moles(gastype) + amount) - - // That last one put us over the limit, remove some of it - while(gasmix.return_pressure() > target_pressure) - gasmix.set_moles(gastype, gasmix.get_moles(gastype) - (gasmix.get_moles(gastype) * 0.1)) - gasmix.set_moles(gastype, FLOOR(gasmix.get_moles(gastype), 0.1)) - // Now finally lets make that string - var/list/gas_string_builder = list() - for(var/i in gasmix.get_gases()) - gas_string_builder += "[GLOB.gas_data.ids[i]]=[gasmix.get_moles(i)]" - gas_string_builder += "TEMP=[gasmix.return_temperature()]" - gas_string = gas_string_builder.Join(";") + continue + var/to_add = restricted_gases[gas] * rand(50, 200) / 100 * pressure_scalar + gas_weights[gas] += to_add + sum += to_add + + var/list/string_builder = list() + for(var/gas in gas_weights) + // CEIL will make it inaccurate, but prettier + var/real_weight = CEILING(gas_weights[gas] / sum * total_moles, 0.1) + string_builder += "[gas]=[real_weight]" + string_builder += "TEMP=[temperature]" + + gas_string = string_builder.Join(";") diff --git a/code/datums/atmosphere/planetary.dm b/code/datums/atmosphere/planetary.dm index 8a2d37ab2471..0b3a4776160f 100644 --- a/code/datums/atmosphere/planetary.dm +++ b/code/datums/atmosphere/planetary.dm @@ -186,7 +186,7 @@ ) normal_gases = list( GAS_O2=5, - GAS_H2O=7, + GAS_H2=7, GAS_N2=5, GAS_NITROUS=7, GAS_CO2=5, diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index 1d6020490840..fdd12d7c9dfa 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -15,7 +15,6 @@ opacity = TRUE density = TRUE layer = EDGED_TURF_LAYER - initial_temperature = TCMB base_icon_state = "smoothrocks" var/smooth_icon = 'icons/turf/walls/smoothrocks.dmi' var/environment_type = "asteroid" diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index e2c6caa8be7e..571d824f2d5f 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -155,7 +155,7 @@ baseturfs = /turf/open/indestructible/airblock /turf/open/Initalize_Atmos(times_fired) - if(!istype(air, /datum/gas_mixture)) + if(!air) air = new(2500, src) air.copy_from_turf(src) update_air_ref(planetary_atmos ? AIR_REF_PLANETARY_TURF : AIR_REF_OPEN_TURF) diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm index 2d043371a9bb..ffc233b755f1 100644 --- a/code/game/turfs/open/floor/fancy_floor.dm +++ b/code/game/turfs/open/floor/fancy_floor.dm @@ -84,9 +84,6 @@ to_chat(user, "You forcefully pry off the planks, destroying them in the process.") return make_plating() -/turf/open/floor/wood/cold - initial_temperature = 255.37 - /turf/open/floor/wood/airless initial_gas_mix = AIRLESS_ATMOS diff --git a/code/game/turfs/open/floor/hull.dm b/code/game/turfs/open/floor/hull.dm index 67be2d8436f5..d50d9b5cecce 100644 --- a/code/game/turfs/open/floor/hull.dm +++ b/code/game/turfs/open/floor/hull.dm @@ -4,7 +4,6 @@ desc = "Sturdy exterior hull plating that separates you from the uncaring vacuum of space." icon_state = "regular_hull" initial_gas_mix = AIRLESS_ATMOS - initial_temperature = TCMB /turf/open/floor/engine/hull/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) //no rcd destroying this flooring if(passed_mode == RCD_DECONSTRUCT) @@ -21,9 +20,7 @@ /turf/open/floor/engine/hull/interior name = "interior hull plating" initial_gas_mix = OPENTURF_DEFAULT_ATMOS - initial_temperature = T20C /turf/open/floor/engine/hull/reinforced/interior name = "interior reinforced hull plating" initial_gas_mix = OPENTURF_DEFAULT_ATMOS - initial_temperature = T20C diff --git a/code/game/turfs/open/floor/plating/misc_plating.dm b/code/game/turfs/open/floor/plating/misc_plating.dm index 684420c8eb89..d5087dc5f6f3 100644 --- a/code/game/turfs/open/floor/plating/misc_plating.dm +++ b/code/game/turfs/open/floor/plating/misc_plating.dm @@ -141,7 +141,6 @@ icon = 'icons/turf/snow.dmi' icon_state = "ice" initial_gas_mix = FROZEN_ATMOS - initial_temperature = 180 planetary_atmos = TRUE baseturfs = /turf/open/floor/plating/ice slowdown = 1 @@ -172,11 +171,8 @@ light_power = 1 light_color = LIGHT_COLOR_LIGHT_CYAN -/turf/open/floor/plating/ice/colder - initial_temperature = 140 - /turf/open/floor/plating/ice/temperate - initial_temperature = 255.37 + initial_gas_mix = OPENTURF_DEFAULT_ATMOS /turf/open/floor/plating/ice/break_tile() return @@ -208,7 +204,6 @@ icon = 'icons/turf/snow.dmi' icon_state = "snowplating" initial_gas_mix = FROZEN_ATMOS - initial_temperature = 180 attachment_holes = FALSE planetary_atmos = TRUE footstep = FOOTSTEP_SAND @@ -228,12 +223,6 @@ canSmoothWith = list(SMOOTH_GROUP_FLOOR_SNOWED) planetary_atmos = TRUE -/turf/open/floor/plating/snowed/colder - initial_temperature = 140 - -/turf/open/floor/plating/snowed/temperatre - initial_temperature = 255.37 - /turf/open/floor/plating/snowed/smoothed/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index 0784f2a140a7..7f007e64873c 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -7,7 +7,6 @@ name = "\proper space" intact = 0 - initial_temperature = TCMB thermal_conductivity = 0 heat_capacity = 700000 initial_gas_mix = AIRLESS_ATMOS diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 4da6e25703bb..84784d26e943 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -15,9 +15,6 @@ GLOBAL_LIST_EMPTY(created_baseturf_lists) // This shouldn't be modified directly; use the helper procs, as many baseturf lists are shared between turfs. var/list/baseturfs = /turf/baseturf_bottom - /// How hot the turf is, in kelvin - var/initial_temperature = T20C - /// Used for fire, if a melting temperature was reached, it will be destroyed var/to_be_destroyed = 0 var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 1aff4ddadb7f..928013601a10 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -187,7 +187,6 @@ GLOBAL_LIST_INIT(auxtools_atmos_initialized, FALSE) return copy /datum/gas_mixture/copy_from_turf(turf/model) - set_temperature(initial(model.initial_temperature)) parse_gas_string(model.initial_gas_mix) return 1 diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 10c4e9e417d0..d80be269eb00 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -292,7 +292,9 @@ /datum/gas_reaction/freonfire/init_reqs() min_requirements = list( GAS_O2 = MINIMUM_MOLE_COUNT, - GAS_FREON = MINIMUM_MOLE_COUNT + GAS_FREON = MINIMUM_MOLE_COUNT, + "TEMP" = FREON_LOWER_TEMPERATURE, + "MAX_TEMP" = FREON_MAXIMUM_BURN_TEMPERATURE ) /datum/gas_reaction/freonfire/react(datum/gas_mixture/air, datum/holder) @@ -533,7 +535,8 @@ GAS_O2 = 10, GAS_N2 = 20, GAS_BZ = 5, - "TEMP" = 200 + "TEMP" = 200, + "MAX_TEMP" = 250 ) /datum/gas_reaction/nitrousformation/react(datum/gas_mixture/air) @@ -543,8 +546,6 @@ var/energy_used = heat_efficency * NITROUS_FORMATION_ENERGY if ((air.get_moles(GAS_O2) - heat_efficency < 0)|| (air.get_moles(GAS_N2) - heat_efficency < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - if (temperature > 250) //maximum allowed temperature for the reaction - return NO_REACTION air.adjust_moles(GAS_O2, -heat_efficency) air.adjust_moles(GAS_N2, -heat_efficency * 2) air.adjust_moles(GAS_NITROUS, heat_efficency) diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index c205746b16f3..d3360c9a5dd9 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -3,7 +3,6 @@ /turf/open/floor/plasteel/dark/snowdin initial_gas_mix = FROZEN_ATMOS planetary_atmos = 1 - initial_temperature = 180 /turf/open/lava/plasma name = "liquid plasma" diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 3195d86e7fb7..7f49c7a39510 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -76,6 +76,7 @@ #include "icons/spritesheets.dm" #include "icons/worn_icons.dm" #include "anchored_mobs.dm" +#include "atmospheres.dm" #include "autowiki.dm" #include "bespoke_id.dm" #include "binary_insert.dm" diff --git a/code/modules/unit_tests/atmospheres.dm b/code/modules/unit_tests/atmospheres.dm new file mode 100644 index 000000000000..8c3febe737c5 --- /dev/null +++ b/code/modules/unit_tests/atmospheres.dm @@ -0,0 +1,99 @@ +/datum/unit_test/atmospheres + focus = TRUE + +/datum/unit_test/atmospheres/Run() + for(var/id in SSair.string_mixes) + var/datum/atmosphere/mix = SSair.string_mixes[id] + compare(mix) + +/datum/unit_test/atmospheres/proc/compare(datum/atmosphere/mix) + var/max_moles = mix.maximum_pressure * CELL_VOLUME / (mix.minimum_temp * R_IDEAL_GAS_EQUATION) + var/lowest_sum = get_min_sum(mix) + var/list/max_possible = list() + + for(var/gas_id in mix.base_gases) + var/value = mix.base_gases[gas_id] + + max_possible[gas_id] = value / (lowest_sum - value) * max_moles + + for(var/gas_id in mix.normal_gases) + var/value = mix.normal_gases[gas_id] + + max_possible[gas_id] = value * 2 / (lowest_sum - value * 2) * max_moles + + for(var/gas_id in mix.restricted_gases) + var/value = mix.restricted_gases[gas_id] * 2 + + max_possible[gas_id] += value / lowest_sum * max_moles + + for(var/datum/gas_reaction/reaction as anything in SSair.gas_reactions) + var/min_temp = reaction.min_requirements["TEMP"] || 0 + var/max_temp = reaction.min_requirements["MAX_TEMP"] || INFINITY + + if(max_temp < mix.minimum_temp) + continue + if(min_temp > mix.maximum_temp) + continue + + var/fire_reagents = reaction.min_requirements["FIRE_REAGENTS"] + if(fire_reagents) + var/oxidizer + var/fuel + + for(var/gas_id in max_possible) + var/datum/gas/gas = GLOB.gas_data.datums[gas_id] + if(gas.oxidation_rate > 0 && gas.oxidation_temperature && gas.oxidation_temperature < mix.maximum_temp && max_possible[gas_id] > fire_reagents) + oxidizer = gas + if(gas.fire_temperature && gas.fire_temperature < mix.maximum_temp) + fuel = gas + + if(!oxidizer || !fuel) + continue + + var/list/reqs = reaction.min_requirements - list("TEMP", "MAX_TEMP", "ENER", "FIRE_REAGENTS") + + //See if the reaction can be done in the worst case scenario mix + var/real_max_temp = max_temp + var/remaining_moles = max_moles + if(real_max_temp > mix.maximum_temp) + real_max_temp = mix.maximum_temp + remaining_moles = mix.maximum_pressure * CELL_VOLUME / (real_max_temp * R_IDEAL_GAS_EQUATION) + + var/reacted = TRUE + + var/gas_str = "TEMP=[real_max_temp];" + for(var/gas_id as anything in reqs) + if(!(gas_id in max_possible)) + reacted = FALSE + break + if(reqs[gas_id] > max_possible[gas_id]) + reacted = FALSE + break + if(reqs[gas_id] > remaining_moles) + reacted = FALSE + break + + remaining_moles -= reqs[gas_id] + gas_str += "[gas_id]=[reqs[gas_id]];" + + if(!reacted) + continue + + var/datum/gas_mixture/remaining = new /datum/gas_mixture + remaining.parse_gas_string(gas_str) + + if(reaction.react(remaining, src.run_loc_bottom_left) != NO_REACTION) + TEST_FAIL("Reaction \"[reaction]\" could happen in [mix]") + else + TEST_NOTICE(src, "Reaction \"[reaction]\"- could get constantly called in [mix]") + + +/datum/unit_test/atmospheres/proc/get_min_sum(datum/atmosphere/mix) + . = 0 + + for(var/gas_id in mix.base_gases) + . += mix.base_gases[gas_id] + for(var/gas_id in mix.normal_gases) + . += mix.normal_gases[gas_id] * 0.5 + + return .