Files
Aurora.3/code/modules/reagents/Chemistry-Temperature.dm
81c4eb2b79 Fix reagent temperature mismatch crash (#23063)
* Please describe the intent of your changes in a clear fashion.
This PR addresses a crash (`SERVER-PROD-2R6`) caused by a temperature
mismatch when adding new reagents, particularly in low-volume metabolism
holders.

The root cause was identified as a combination of:
1. A coarse rounding guard in `set_thermal_energy` that discarded
small-but-valid thermal energy changes.
2. A temperature assertion in `add_reagent` that was too sensitive to
floating-point inaccuracies.
3. The `nicotine` reagent lacking an explicit `fallback_specific_heat`.

Changes implemented:
- **`code/modules/reagents/Chemistry-Temperature.dm`**: Modified
`set_thermal_energy` to remove the `round(delta, 1)` guard. Now,
`if(!delta)` is used, allowing small, non-zero energy changes to be
processed.
- **`code/modules/reagents/Chemistry-Holder.dm`**: Updated the
temperature assertion in `add_reagent` from `round(temperature, 1) !=
round(get_temperature(), 1)` to `abs(temperature - get_temperature()) >
0.1`. This provides a more robust, tolerance-based comparison.
-
**`code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm`**:
Added `fallback_specific_heat = 1.67` to
`/singleton/reagent/mental/nicotine` to ensure it has a proper specific
heat value.

* Please make sure that, in the case of mapping changes, you include
images of these changes in the PR's description.
* Please make sure to mark your PR as wip or review required by making a
comment with !wip or !review required
* If you include sprites/sounds/... (assets) that you have not created
yourself specify the license and original author below.
* Ensure that you also credit them in the appropriate location /
changelog as specified in the contributor guidelines

### Asset Licenses
The following assets that **have not** been created by myself are
included in this PR:

| Path | Original Author | License |
| --- | --- | --- |
| icons/example.dmi | ExamplePerson (Example Station) | CC0 |


Fixes
[SERVER-PROD-2R6](https://aurorastation.sentry.io/issues/7661064998/?seerDrawer=true)

---------

Co-authored-by: VMSolidus <evilexecutive@gmail.com>
2026-08-19 18:09:57 +00:00

65 lines
2.8 KiB
Plaintext

//Everything to do with reagents having temperature. Override reagent procs to make your own snowflake special reagent with mystical properties.
// https://www.aqua-calc.com/calculate/volume-to-weight/substance/
// https://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html USE THE TABLE ON THE LEFT
// https://www.engineeringtoolbox.com/specific-heat-solids-d_154.html USE THE TABLE ON THE RIGHT
// http://www2.ucdsb.on.ca/tiss/stretton/database/specific_heat_capacity_table.html
// https://www.nuclear-power.net/radium-specific-heat-latent-heat-vaporization-fusion/
/singleton/reagent/proc/get_thermal_fraction(var/datum/reagents/holder)
return get_heat_capacity(holder)/holder.get_heat_capacity()
/singleton/reagent/proc/get_thermal_energy(var/datum/reagents/holder)
return (holder.thermal_energy * get_thermal_fraction(holder))
/singleton/reagent/proc/set_thermal_energy(amount, var/datum/reagents/holder, safety = FALSE)
var/delta = amount / get_thermal_fraction(holder) - holder.thermal_energy
if(!delta)
return
holder.add_thermal_energy(delta, safety) // this handles on_heat_change for us
/singleton/reagent/proc/add_thermal_energy(amount, var/datum/reagents/holder, safety = FALSE)
holder.add_thermal_energy(amount, safety)
/singleton/reagent/proc/set_temperature(temperature, var/datum/reagents/holder, safety = FALSE)
set_thermal_energy(temperature * get_heat_capacity(holder), holder, safety = safety)
/datum/reagents/proc/get_heat_capacity()
. = 0
for(var/_R in reagent_volumes)
var/singleton/reagent/R = GET_SINGLETON(_R)
. += R.get_heat_capacity(src)
/singleton/reagent/proc/get_heat_capacity(var/datum/reagents/holder)
return src.specific_heat * REAGENT_VOLUME(holder, src.type)
/datum/reagents/proc/get_temperature()
var/HC = get_heat_capacity()
var/TE = thermal_energy
if(HC && TE)
return TE / HC
else
return T20C
/datum/reagents/proc/get_thermal_energy_change(old_temperature, new_temperature)
return get_heat_capacity()*(max(new_temperature, TCMB) - old_temperature)
/datum/reagents/proc/set_thermal_energy(set_energy, safety = FALSE)
return add_thermal_energy(-thermal_energy + set_energy, safety)
/datum/reagents/proc/set_temperature(new_temperature, safety = FALSE)
return set_thermal_energy(get_thermal_energy_change(0,new_temperature), safety)
/datum/reagents/proc/add_thermal_energy(thermal_energy_to_add, safety = FALSE)
thermal_energy_to_add = max(-thermal_energy, thermal_energy_to_add)
var/total_heat_capacity = get_heat_capacity()
for(var/_R in reagent_volumes)
var/singleton/reagent/R = GET_SINGLETON(_R)
var/energy_per_reagent = thermal_energy_to_add * (R.get_heat_capacity(src)/total_heat_capacity)
if(!safety)
R.on_heat_change(energy_per_reagent, src)
thermal_energy += thermal_energy_to_add
/singleton/reagent/proc/on_heat_change(energy_change, var/datum/reagents/holder)
return // stub for heat effects