[NO GBP] Some more reaction patches (#95660)

## About The Pull Request
- Fixes #95651. Catalysts no longer get consumed
- Removed `REACTION_CLEAR_IMPURE` flag as it is now redundant with
`REACTION_CLEAR_INVERSE`
- Removed `REACTION_CLEAR_INSTANT` flag as it was never used
- Other minor nitpicks
This commit is contained in:
SyncIt21
2026-04-08 14:56:59 -05:00
committed by GitHub
parent a345fd36fa
commit 63bd540663
6 changed files with 37 additions and 72 deletions
+6 -10
View File
@@ -137,22 +137,18 @@
#define REAGENT_SPAWN_ALL_RANDOM_SPAWNS ALL
//Chemical reaction flags, for determining reaction specialties
///Convert into impure/pure on reaction completion
#define REACTION_CLEAR_IMPURE (1<<0)
///Convert into inverse on reaction completion when purity is low enough
#define REACTION_CLEAR_INVERSE (1<<1)
///Clear converted chems retain their purities/inverted purities. Requires 1 or both of the above.
#define REACTION_CLEAR_RETAIN (1<<2)
#define REACTION_CLEAR_INVERSE (1<<0)
///Used to create instant reactions
#define REACTION_INSTANT (1<<3)
#define REACTION_INSTANT (1<<1)
///Used to force reactions to create a specific amount of heat per 1u created. So if thermic_constant = 5, for 1u of reagent produced, the heat will be forced up arbitarily by 5 irresepective of other reagents. If you use this, keep in mind standard thermic_constant values are 100x what it should be with this enabled.
#define REACTION_HEAT_ARBITARY (1<<4)
#define REACTION_HEAT_ARBITARY (1<<2)
///Used to bypass the chem_master transfer block (This is needed for competitive reactions unless you have an end state programmed). More stuff might be added later. When defining this, please add in the comments the associated reactions that it competes with
#define REACTION_COMPETITIVE (1<<5)
#define REACTION_COMPETITIVE (1<<3)
///Used to force pH changes to be constant regardless of volume
#define REACTION_PH_VOL_CONSTANT (1<<6)
#define REACTION_PH_VOL_CONSTANT (1<<4)
///If a reaction will generate its impure/inverse reagents in the middle of a reaction, as apposed to being determined on ingestion/on reaction completion
#define REACTION_REAL_TIME_SPLIT (1<<7)
#define REACTION_REAL_TIME_SPLIT (1<<5)
///Used for overheat_temp - This sets the overheat so high it effectively has no overheat temperature.
#define NO_OVERHEAT 99999
-2
View File
@@ -494,9 +494,7 @@ DEFINE_BITFIELD(chemical_flags, list(
))
DEFINE_BITFIELD(reaction_flags, list(
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE,
"REACTION_CLEAR_RETAIN" = REACTION_CLEAR_RETAIN,
"REACTION_INSTANT" = REACTION_INSTANT,
"REACTION_HEAT_ARBITARY" = REACTION_HEAT_ARBITARY,
"REACTION_COMPETITIVE" = REACTION_COMPETITIVE,
@@ -67,7 +67,7 @@ Lets go over the reaction vars below. These can be edited and set on a per chemi
var/H_ion_release = 0.01 // pH change per 1u reaction
var/rate_up_lim = 20 // Optimal/max rate possible if all conditions are perfect
var/purity_min = 0.15 // If purity is below 0.15, it calls OverlyImpure() too. Set to 0 to disable this.
var/reaction_flags // bitflags for clear conversions; REACTION_CLEAR_IMPURE, REACTION_CLEAR_INVERSE, REACTION_CLEAR_RETAIN, REACTION_INSTANT
var/reaction_flags // bitflags for clear conversions;
```
### How temperature ranges are set and how reaction rate is determined
@@ -129,9 +129,7 @@ The thermic_constant is how much the temperature changes per u created, so for 1
Reaction_flags can be used to set these defines:
```dm
#define REACTION_CLEAR_IMPURE //Convert into impure/pure on reaction completion in the datum/reagents holder instead of on consumption
#define REACTION_CLEAR_INVERSE //Convert into inverse on reaction completion when purity is low enough in the datum/reagents holder instead of on consumption
#define REACTION_CLEAR_RETAIN //Clear converted chems retain their purities/inverted purities. Requires 1 or both of the above. This is so that it can split again after splitting from a reaction (i.e. if your impure_chem or inverse_chem has its own impure_chem/inverse_chem and you want it to split again on consumption).
#define REACTION_INSTANT //Used to create instant reactions
/datum/chemical_reaction
@@ -176,10 +174,9 @@ The new vars that are introduced are below:
- `pH` is the innate pH of the reagent and is used to calculate the pH of a reagents datum on addition/removal. This does not change and is a reference value. The reagents datum pH changes.
- `purity` is the INTERNAL value for splitting. This is set to 1 after splitting so that it doesn't infinite split
- `creation_purity` is the purity of the reagent on creation. This won't change. If you want to write code that checks the purity in any of the methods, use this.
- `impure_chem` is the datum type that is created provided that its `creation_purity` is above the `inverse_chem_val`. When the reagent is consumed it will split into this OR if the associated `datum/chemical_recipe` has a REACTION_CLEAR_IMPURE flag it will split at the end of the reaction in the `datum/reagents` holder
- `impure_chem` is the datum type that is created provided that its `creation_purity` is above the `inverse_chem_val`. When the reagent is consumed it will split into this OR if the associated `datum/chemical_recipe` has a REACTION_CLEAR_INVERSE flag it will split at the end of the reaction in the `datum/reagents` holder
- `inverse_chem_val` if a reagent's purity is below this value it will 100% convert into `inverse_chem`. If above it will split into `impure_chem`. See the note on purity effects above
- `inverse_chem` is the datum type that is created provided that its `creation_purity` is below the `inverse_chem_val`. When the reagent is consumed it will 100% convert into this OR if the associated `datum/chemical_recipe` has a REACTION_CLEAR_INVERSE flag it will 100% convert at the end of the reaction in the `datum/reagents` holder
- `failed_chem` is the chem that the product is 100% converted into if the purity is below the associated `datum/chemical_recipies`' `PurityMin` AT THE END OF A REACTION.
When writing any reagent code ALWAYS use creation_purity. Purity is kept for internal mechanics only and wont reflect the purity on creation.
@@ -14,10 +14,6 @@
force_stop_reacting() //Force anything that is trying to to stop
return FALSE //Yup, no reactions here. No siree.
if(is_reacting)//Prevent wasteful calculations
if(!(datum_flags & DF_ISPROCESSING))//If we're reacting - but not processing (i.e. we've transferred)
START_PROCESSING(SSreagents, src)
#ifndef UNIT_TESTS
// We assert that reagents will not need to react before the map is fully loaded
// This is the best I can do, sorry :(
@@ -37,7 +33,7 @@
//is this reaction already going on?
var/next_reaction = FALSE
for(var/datum/equilibrium/E_exist as anything in reaction_list)
if(ispath(E_exist.reaction.type, reaction.type)) //Don't add duplicates
if(E_exist.reaction == reaction) //Don't add duplicates
next_reaction = TRUE
break
if(next_reaction)
@@ -48,9 +44,7 @@
if(!(reaction.reaction_flags & REACTION_INSTANT))
granularity = CHEMICAL_QUANTISATION_LEVEL
var/present_volume = 0
var/list/datum/reagent/requirements = reaction.required_reagents
if(length(reaction.required_catalysts))
requirements |= reaction.required_catalysts
var/list/datum/reagent/requirements = reaction.required_reagents | reaction.required_catalysts
for(var/datum/reagent/requirement as anything in requirements)
present_volume = cached_reagents[requirement]
if(!present_volume)
@@ -101,7 +95,7 @@
else
//Adding is done in new(), deletion is in qdel
is_reacting = TRUE//Prevent any on_reaction() procs from infinite looping
equilibrium.reaction.on_reaction(src, equilibrium, equilibrium.multiplier)
reaction.on_reaction(src, equilibrium, equilibrium.multiplier)
equilibrium.react_timestep(1)//Get an initial
if(LAZYLEN(reaction_list))
+24 -44
View File
@@ -7,11 +7,11 @@
*/
/datum/chemical_reaction
///Results of the chemical reactions
var/list/results = new/list()
var/list/results = list()
///Required chemicals that are USED in the reaction
var/list/required_reagents = new/list()
var/list/required_reagents = list()
///Required chemicals that must be present in the container but are not USED.
var/list/required_catalysts = new/list()
var/list/required_catalysts = list()
/// If required_container will check for the exact type, or will also accept subtypes
var/required_container_accepts_subtypes = FALSE
@@ -52,7 +52,7 @@
var/rate_up_lim = 30
/// If purity is below 0.15, it calls OverlyImpure() too. Set to 0 to disable this.
var/purity_min = 0.15
/// bitflags for clear conversions; REACTION_CLEAR_IMPURE, REACTION_CLEAR_INVERSE, REACTION_CLEAR_RETAIN, REACTION_INSTANT
/// bitflags for clear conversions; see code/__DEFINES/reagents.dm
var/reaction_flags = NONE
///Tagging vars
///A bitflag var for tagging reagents for the reagent loopup functon
@@ -102,11 +102,7 @@
return
/**
* Stuff that occurs at the end of a reaction. This will proc if the beaker is forced to stop and start again (say for sudden temperature changes).
* Only procs at the END of reaction
* If reaction_flags & REACTION_INSTANT then this isn't called
* if reaction_flags REACTION_CLEAR_IMPURE then the impurity chem is handled here, producing the result in the beaker instead of in a mob
* Likewise for REACTION_CLEAR_INVERSE the inverse chem is produced at the end of the reaction in the beaker
* Stuff that should happen at the end of the reaction. Presently only REACTION_CLEAR_INVERSE is respected here
* You should be calling ..() if you're writing a child function of this proc otherwise purity methods won't work correctly
*
* Proc where the additional magic happens.
@@ -116,39 +112,24 @@
* * react_volume - volume created across the whole reaction
*/
/datum/chemical_reaction/proc/reaction_finish(datum/reagents/holder, datum/equilibrium/reaction, react_vol)
//failed_chem handler
var/cached_temp = holder.chem_temp
for(var/id in results)
var/datum/reagent/reagent = holder.has_reagent(id)
if(!reagent)
continue
//Split like this so it's easier for people to edit this function in a child
reaction_clear_check(reagent, holder)
holder.chem_temp = cached_temp
/**
* REACTION_CLEAR handler
* If the reaction has the REACTION_CLEAR flag, then it will split using purity methods in the beaker instead
*
* Arguments:
* * reagent - the target reagent to convert
*/
/datum/chemical_reaction/proc/reaction_clear_check(datum/reagent/reagent, datum/reagents/holder)
if(!reagent)//Failures can delete R
if(!(reaction_flags & REACTION_CLEAR_INVERSE))
return
if(reaction_flags & (REACTION_CLEAR_IMPURE | REACTION_CLEAR_INVERSE))
if(reagent.purity == 1)
return
if((reaction_flags & REACTION_CLEAR_INVERSE) && reagent.inverse_chem)
if(reagent.inverse_chem_val > reagent.purity)
var/inverse_chem = reagent.inverse_chem
var/cached_volume = reagent.volume
var/cached_purity = reagent.get_inverse_purity(reagent.purity)
reagent.volume = 0
holder.update_total()
holder.add_reagent(inverse_chem, cached_volume, FALSE, added_purity = cached_purity)
return
var/list/inverse_data = list()
for(var/datum/reagent/reagent as anything in holder.reagent_list)
if(!results[reagent.type] || !reagent.inverse_chem || reagent.purity == 1 || reagent.purity > reagent.inverse_chem_val)
continue
inverse_data += reagent.inverse_chem
inverse_data += reagent.volume
inverse_data += reagent.get_inverse_purity(reagent.purity)
reagent.volume = 0
holder.update_total()
var/cached_temp = holder.chem_temp
while(inverse_data.len)
holder.add_reagent(popleft(inverse_data), popleft(inverse_data), reagtemp = cached_temp, added_purity = popleft(inverse_data))
/**
* Occurs when a reation is overheated (i.e. past its overheatTemp)
@@ -163,10 +144,9 @@
* * step_volume_added - how much product (across all products) was added for this single step
*/
/datum/chemical_reaction/proc/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, step_volume_added)
for(var/id in results)
var/datum/reagent/reagent = holder.has_reagent(id)
if(!reagent)
return
for(var/datum/reagent/reagent as anything in holder.reagent_list)
if(!results[reagent.type])
continue
reagent.volume *= 0.98 //Slowly lower yield per tick
holder.update_total()
@@ -263,7 +263,7 @@
H_ion_release = -0.25
rate_up_lim = 15
purity_min = 0.3
reaction_flags = REACTION_CLEAR_IMPURE
reaction_flags = REACTION_CLEAR_INVERSE
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DAMAGING | REACTION_TAG_OTHER
/datum/chemical_reaction/ghoulpowder
@@ -303,7 +303,7 @@
H_ion_release = -0.06
rate_up_lim = 15
purity_min = 0.4
reaction_flags = REACTION_CLEAR_IMPURE
reaction_flags = REACTION_CLEAR_INVERSE
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DAMAGING | REACTION_TAG_OTHER
/datum/chemical_reaction/heparin