diff --git a/auxmos.dll b/auxmos.dll index 04522e9d44..294ba83294 100644 Binary files a/auxmos.dll and b/auxmos.dll differ diff --git a/auxmos.pdb b/auxmos.pdb index 78725799be..11c009d548 100644 Binary files a/auxmos.pdb and b/auxmos.pdb differ diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 8fc2dc116b..6895a8cb54 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -264,6 +264,8 @@ #define GAS_MIASMA "miasma" #define GAS_METHANE "methane" #define GAS_METHYL_BROMIDE "methyl_bromide" +#define GAS_AMMONIA "ammonia" +#define GAS_FLUORINE "fluorine" #define GAS_FLAG_DANGEROUS (1<<0) #define GAS_FLAG_BREATH_PROC (1<<1) diff --git a/code/modules/atmospherics/gasmixtures/auxgm.dm b/code/modules/atmospherics/gasmixtures/auxgm.dm index 6c7bc0cc49..dfd9a2d866 100644 --- a/code/modules/atmospherics/gasmixtures/auxgm.dm +++ b/code/modules/atmospherics/gasmixtures/auxgm.dm @@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA /proc/_auxtools_register_gas(datum/gas/gas) // makes sure auxtools knows stuff about this gas /datum/auxgm + var/done_initializing = FALSE var/list/datums = list() var/list/specific_heats = list() var/list/names = list() @@ -24,6 +25,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA var/list/ids = list() var/list/typepaths = list() var/list/fusion_powers = list() + var/list/turf_reagents = list() var/list/breathing_classes = list() var/list/breath_results = list() var/list/breath_reagents = list() @@ -36,18 +38,19 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA var/list/fire_products = list() var/list/fire_burn_rates = list() - /datum/gas var/id = "" var/specific_heat = 0 var/name = "" var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi + var/color = "#ffff" var/moles_visible = null var/flags = NONE //currently used by canisters var/fusion_power = 0 // How much the gas destabilizes a fusion reaction var/breath_results = GAS_CO2 // what breathing this breathes out - var/breath_reagent = null // what breathing this adds to your reagents - var/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold + var/datum/reagent/turf_reagent = null + var/datum/reagent/breath_reagent = null // what breathing this adds to your reagents + var/datum/reagent/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold var/list/breath_alert_info = null // list for alerts that pop up when you have too much/not enough of something var/oxidation_temperature = null // temperature above which this gas is an oxidizer; null for none var/oxidation_rate = 1 // how many moles of this can oxidize how many moles of material @@ -87,7 +90,8 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA breath_reagents[g] = gas.breath_reagent if(gas.breath_reagent_dangerous) breath_reagents_dangerous[g] = gas.breath_reagent_dangerous - + if(gas.turf_reagent) + turf_reagents[g] = gas.turf_reagent if(gas.oxidation_temperature) oxidation_temperatures[g] = gas.oxidation_temperature oxidation_rates[g] = gas.oxidation_rate @@ -102,6 +106,11 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA fire_enthalpies[g] = gas.fire_energy_released _auxtools_register_gas(gas) + if(done_initializing) + for(var/r in SSair.gas_reactions) + var/datum/gas_reaction/R = r + R.init_reqs() + SSair.auxtools_update_reactions() /proc/finalize_gas_refs() @@ -112,6 +121,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA for(var/breathing_class_path in subtypesof(/datum/breathing_class)) var/datum/breathing_class/class = new breathing_class_path breathing_classes[breathing_class_path] = class + done_initializing = TRUE finalize_gas_refs() diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index b523d333df..755c22595a 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -56,17 +56,62 @@ min_requirements = list(GAS_H2O = MOLES_GAS_VISIBLE) /datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder) - var/turf/open/location = isturf(holder) ? holder : null - . = NO_REACTION + var/turf/open/location = holder + if(!istype(location)) + return NO_REACTION if (air.return_temperature() <= WATER_VAPOR_FREEZE) if(location && location.freon_gas_act()) - . = REACTING + return REACTING else if(location && location.water_vapor_gas_act()) air.adjust_moles(GAS_H2O,-MOLES_GAS_VISIBLE) - . = REACTING + return REACTING // no test cause it's entirely based on location +/datum/gas_reaction/reagent_stuff + priority = 0 + name = "Condensation" + id = "condense" + +/datum/gas_reaction/condensation/init_reqs() + var/highest_condensation_temp = -INFINITY + var/list/reagents = GLOB.gas_data.turf_reagents + for(var/gas in reagents) + var/datum/reagent/R = reagents[gas] + highest_condensation_temp = max(highest_condensation_temp, initial(R.boiling_point)) + min_requirements = list( + "MAX_TEMP" = highest_condensation_temp, + "ANY_REAGENT" = 1 + ) + +/datum/gas_reaction/condensation/react(datum/gas_mixture/air, datum/holder) + var/turf/open/location = holder + if(!istype(location)) + return NO_REACTION + var/list/gas_reagents = GLOB.gas_data.turf_reagents + var/temperature = air.return_temperature() + . = NO_REACTION + var/static/datum/reagents/reagents_holder = new + reagents_holder.clear_reagents() + reagents_holder.chem_temp = temperature + for(var/G in air.get_gases()) + if(G in gas_reagents) + var/datum/reagent/R = gas_reagents[G] + if(temperature < initial(R.boiling_point)) + var/amt = air.get_moles(G) + air.adjust_moles(G, -min(initial(R.condensation_amount), amt)) + reagents_holder.add_reagent(R, amt) + . = REACTING + if(. == REACTING) + for(var/atom/movable/AM in location) + if(location.intact && AM.level == 1) //hidden under the floor + continue + reagents_holder.reaction(AM, TOUCH) + + reagents_holder.reaction(location, TOUCH) + + + //tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic /datum/gas_reaction/tritfire priority = -1 //fire should ALWAYS be last, but tritium fires happen before plasma fires diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index fd6204a8e3..6c31edf840 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -794,7 +794,7 @@ pH = REAGENT_NORMAL_PH return 0 -/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1) +/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1, from_gas = 0) var/react_type if(isliving(A)) react_type = "LIVING" @@ -818,7 +818,7 @@ touch_protection = L.get_permeability_protection() R.reaction_mob(A, method, R.volume * volume_modifier, show_message, touch_protection) if("TURF") - R.reaction_turf(A, R.volume * volume_modifier, show_message) + R.reaction_turf(A, R.volume * volume_modifier, show_message, from_gas) if("OBJ") R.reaction_obj(A, R.volume * volume_modifier, show_message) @@ -828,17 +828,16 @@ return FALSE //Returns the average specific heat for all reagents currently in this holder. -/datum/reagents/proc/specific_heat() +/datum/reagents/proc/heat_capacity() . = 0 - var/cached_amount = total_volume //cache amount var/list/cached_reagents = reagent_list //cache reagents for(var/I in cached_reagents) var/datum/reagent/R = I - . += R.specific_heat * (R.volume / cached_amount) + . += R.specific_heat * R.volume /datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000) - var/S = specific_heat() - chem_temp = clamp(chem_temp + (J / (S * total_volume)), min_temp, max_temp) + var/S = heat_capacity() + chem_temp = clamp(chem_temp + (J / S), min_temp, max_temp) if(istype(my_atom, /obj/item/reagent_containers)) var/obj/item/reagent_containers/RC = my_atom RC.temp_check() diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 285ef70433..eb4a8f265b 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -390,11 +390,11 @@ var/datum/reagent/R = GLOB.chemical_reagents_list[reagent] if(R) var/state = "Unknown" - if(initial(R.reagent_state) == 1) + if(initial(R.reagent_state) == SOLID) state = "Solid" - else if(initial(R.reagent_state) == 2) + else if(initial(R.reagent_state) == LIQUID) state = "Liquid" - else if(initial(R.reagent_state) == 3) + else if(initial(R.reagent_state) == GAS) state = "Gas" var/const/P = 3 //The number of seconds between life ticks var/T = initial(R.metabolization_rate) * (60 / P) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index d6b7201ef9..2439f0caba 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -54,6 +54,9 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/chemical_flags // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME var/value = REAGENT_VALUE_NONE //How much does it sell for in cargo? var/datum/material/material //are we made of material? + var/gas //do we have an associated gas? + var/boiling_point = null // point at which this gas boils; if null, will never boil (and thus not become a gas) + var/condensation_amount = 1 /datum/reagent/New() . = ..() @@ -80,8 +83,18 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) /datum/reagent/proc/reaction_obj(obj/O, volume) return -/datum/reagent/proc/reaction_turf(turf/T, volume) - return +/datum/reagent/proc/reaction_turf(turf/T, volume, show_message, from_gas) + if(!from_gas && boiling_point) + var/temp = holder?.chem_temp + if(!temp) + if(isopenturf(T)) + var/turf/open/O = T + var/datum/gas_mixture/air = O.return_air() + temp = air.return_temperature() + else + temp = T20C + if(temp > boiling_point) + T.atmos_spawn_air("[get_gas()]=[volume/2];TEMP=[temp]") /datum/reagent/proc/on_mob_life(mob/living/carbon/M) current_cycle++ @@ -231,6 +244,46 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) return rs.Join(" | ") +/datum/reagent/proc/define_gas() + if(reagent_state == SOLID) + return null // doesn't make that much sense + var/list/cached_reactions = GLOB.chemical_reactions_list + for(var/reaction in cached_reactions[src.type]) + var/datum/chemical_reaction/C = reaction + if(!istype(C)) + continue + if(C.required_reagents.len < 2) // no reagents that react on their own + return null + var/datum/gas/G = new + G.id = "[src.type]" + G.name = name + G.specific_heat = specific_heat / 10 + G.color = color + G.breath_reagent = src.type + G.turf_reagent = src.type + return G + +/datum/reagent/proc/create_gas() + var/datum/gas/G = define_gas() + if(istype(G)) // if this reagent should never be a gas, define_gas may return null + GLOB.gas_data.add_gas(G) + +/datum/reagent/proc/get_gas() + if(gas) + return gas + else + var/datum/auxgm/cached_gas_data = GLOB.gas_data + . = "[src.type]" + if(!(. in cached_gas_data.ids)) + var/datum/gas/G = define_gas() + if(istype(G)) + cached_gas_data.add_gas(G) + else // this codepath should probably not happen at all, since we never use get_gas() on anything with no boiling point + return null + + + + //For easy bloodsucker disgusting and blood removal /datum/reagent/proc/disgust_bloodsucker(mob/living/carbon/C, disgust, blood_change, blood_puke = TRUE, force) if(AmBloodsucker(C)) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 177b1c70bc..851cc79af9 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -14,6 +14,7 @@ taste_description = "alcohol" var/boozepwr = 65 //Higher numbers equal higher hardness, higher hardness equals more intense alcohol poisoning pH = 7.33 + boiling_point = 351.38 value = REAGENT_VALUE_VERY_COMMON //don't bother tweaking all drinks values, way too many can easily be done roundstart or with an upgraded dispenser. /* diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 96985514b5..97088b4351 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -2,6 +2,7 @@ name = "Drug" metabolization_rate = 0.5 * REAGENTS_METABOLISM taste_description = "bitterness" + boiling_point = T0C + 100 var/trippy = TRUE //Does this drug make you trip? /datum/reagent/drug/on_mob_end_metabolize(mob/living/M) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 65443b65c7..4563dc3b1d 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -8,6 +8,7 @@ /datum/reagent/medicine name = "Medicine" taste_description = "bitterness" + boiling_point = T0C + 100 value = REAGENT_VALUE_VERY_COMMON //Low prices, spess medical companies are cheapstakes and products are taxed honk... /datum/reagent/medicine/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 593d77f959..ee00960d4f 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1006,6 +1006,7 @@ color = "#808080" // rgb: 128, 128, 128 taste_description = "chlorine" pH = 7.4 + boiling_point = 239.11 // You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial /datum/reagent/chlorine/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user) @@ -1272,7 +1273,14 @@ glass_name = "glass of welder fuel" glass_desc = "Unless you're an industrial tool, this is probably not safe for consumption." pH = 4 + boiling_point = 189 +/datum/reagent/fuel/define_gas() + var/datum/gas/G = ..() + G.fire_energy_released = 200000 + G.fire_products = list(GAS_CO2 = 1) + G.fire_temperature = T20C+30 + return G /datum/reagent/fuel/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with welding fuel to make them easy to ignite! if(method == TOUCH || method == VAPOR) @@ -1290,6 +1298,7 @@ description = "A compound used to clean things. Now with 50% more sodium hypochlorite!" color = "#A5F0EE" // rgb: 165, 240, 238 taste_description = "sourness" + boiling_point = T0C+50 pH = 5.5 /datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume) @@ -1302,6 +1311,7 @@ O.clean_blood() /datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume) + ..() if(reac_volume >= 1) T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK) @@ -2454,6 +2464,7 @@ var/decal_path = /obj/effect/decal/cleanable/semen /datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) + ..() if(!istype(T)) return if(reac_volume < 10) diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 2e05f66cf8..32c564a071 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -45,6 +45,8 @@ color = "#FFC8C8" metabolization_rate = 4 taste_description = "burning" + boiling_point = 289.4 + condensation_amount = 2 value = REAGENT_VALUE_COMMON /datum/reagent/clf3/on_mob_life(mob/living/carbon/M) @@ -82,6 +84,14 @@ if(!locate(/obj/effect/hotspot) in M.loc) new /obj/effect/hotspot(M.loc) +/datum/reagent/clf3/define_gas() + var/datum/gas/G = ..() + G.fire_energy_released = 123000 + G.oxidation_rate = 4 + G.oxidation_temperature = T0C - 50 + G.turf_reagent = src.type + return G + /datum/reagent/sorium name = "Sorium" description = "Sends everything flying from the detonation point." @@ -149,8 +159,16 @@ reagent_state = LIQUID color = "#FA00AF" taste_description = "burning" + boiling_point = T20C-10 value = REAGENT_VALUE_UNCOMMON +/datum/reagent/phlogiston/define_gas() + var/datum/gas/G = ..() + G.fire_energy_released = FIRE_PLASMA_ENERGY_RELEASED / 100 + G.fire_burn_rate = 1 + G.fire_temperature = T20C+1 + return G + /datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, reac_volume) M.adjust_fire_stacks(1) var/burndmg = max(0.3*M.fire_stacks, 0.3) @@ -281,6 +299,9 @@ taste_description = "the inside of a fire extinguisher" value = REAGENT_VALUE_UNCOMMON +/datum/reagent/firefighting_foam/define_gas() + return null + /datum/reagent/firefighting_foam/reaction_turf(turf/open/T, reac_volume) if (!istype(T)) return diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 0655faa1e8..71d29018f1 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -8,6 +8,7 @@ taste_description = "bitterness" taste_mult = 1.2 value = REAGENT_VALUE_COMMON //Encouraging people to mix toxins for reasons beyond harming each other or mixing reagents such as pen acid. + boiling_point = T0C + 100 var/toxpwr = 1.5 // Are you a bad enough dude to poison your own plants?