From 4c092db88f6a6066bc874cc3a8e3e70401b17af2 Mon Sep 17 00:00:00 2001 From: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com> Date: Wed, 21 May 2025 22:41:48 +0100 Subject: [PATCH] Antinoblium converts every other gas into antinoblium. (#91016) ## About The Pull Request Recommended for #91048 to be merged first to limit availability of the gas. Adds a gas reaction that requires antinoblium. Causes other gases to get converted into antinoblium when above 20 Kelvin. Irradiates people upon skin contact. ## Why It's Good For The Game Hypernoblium halts entropy from increasing. To make antinoblium the opposite, it accelerates entropy as fast as it can by converting every other gas into antinoblium. This brings a unique way for antinoblium to interact with the atmospherics system. Due to the grey goo nature of the gas, people will panic if this gets leaked for whatever reason, which can bring some good quality roleplay moments as people desparately try to prevent the spread of the gas or prevent the gas spreading into their departments. ## Changelog :cl: add: Antinoblium converts other gases into antinoblium when above 20 Kelvin. balance: Firelocks close when they detect antinoblium. balance: Antinoblium irradiates people upon skin contact. /:cl: --- code/__DEFINES/reactions.dm | 6 +++ code/game/machinery/doors/firedoor.dm | 2 + .../atmospherics/gasmixtures/gas_mixture.dm | 2 +- .../gasmixtures/reaction_factors.dm | 7 +++ .../atmospherics/gasmixtures/reactions.dm | 44 +++++++++++++++++++ .../mob/living/carbon/human/_species.dm | 15 +++++++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/code/__DEFINES/reactions.dm b/code/__DEFINES/reactions.dm index 1989ca0eaa3..85aabaed830 100644 --- a/code/__DEFINES/reactions.dm +++ b/code/__DEFINES/reactions.dm @@ -174,6 +174,8 @@ /// The number of moles of hyper-noblium required to prevent reactions. #define REACTION_OPPRESSION_THRESHOLD 5 +/// Minimum temperature required for hypernoblium to prevent reactions. +#define REACTION_OPPRESSION_MIN_TEMP 20 // Halon: /// Energy released per mole of BZ consumed during halon formation. @@ -262,6 +264,10 @@ /// How much radiation in consumed amount does a nuclear particle take from radiation when proto-nitrate breaks down BZ. #define PN_BZASE_NUCLEAR_PARTICLE_RADIATION_ENERGY_CONVERSION 2.5 +// Antinoblium: +/// The divisor for the maximum antinoblium conversion rate. (1/90 of the antinoblium converts other gases to antinoblium in one reaction tick.) +#define ANTINOBLIUM_CONVERSION_DIVISOR 90 + // Electrolysis: // Electrolysis arguments: /// Supermatter power argument. diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 5766cc40ab5..52495186602 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -285,6 +285,8 @@ 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) + return FIRELOCK_ALARM_TYPE_HOT if(environment.temperature <= BODYTEMP_COLD_DAMAGE_LIMIT) return FIRELOCK_ALARM_TYPE_COLD return diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index cddd5c24125..ac3dab1503c 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -508,7 +508,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 > 20) + if(cached_gases[/datum/gas/hypernoblium] && cached_gases[/datum/gas/hypernoblium][MOLES] >= REACTION_OPPRESSION_THRESHOLD && temperature > REACTION_OPPRESSION_MIN_TEMP) return STOP_REACTIONS reaction_results = new diff --git a/code/modules/atmospherics/gasmixtures/reaction_factors.dm b/code/modules/atmospherics/gasmixtures/reaction_factors.dm index af058dc7787..329cb1b733b 100644 --- a/code/modules/atmospherics/gasmixtures/reaction_factors.dm +++ b/code/modules/atmospherics/gasmixtures/reaction_factors.dm @@ -207,3 +207,10 @@ "Nuclear Particles" = "This reaction emits extremely high energy nuclear particles, up to [2 * PN_BZASE_NUCLEAR_PARTICLE_MAXIMUM] per second per unique gas mixture.", "Temperature" = "Can only occur between [PN_BZASE_MIN_TEMP] - [PN_BZASE_MAX_TEMP] kelvin.", ) + +/datum/gas_reaction/antinoblium_replication/init_factors() + factor = list( + /datum/gas/antinoblium = "[MOLES_GAS_VISIBLE] moles of antinoblium is needed to replicate itself. Requires other gases to be converted to antinoblium.", + "Temperature" = "Can only occur above [REACTION_OPPRESSION_MIN_TEMP] Kelvin." + ) + diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 56655a4806e..47e00340703 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -1162,4 +1162,48 @@ air.temperature = max((temperature * old_heat_capacity + energy_released) / new_heat_capacity, TCMB) return REACTING +/datum/gas_reaction/antinoblium_replication + priority_group = PRIORITY_FORMATION + name = "Antinoblium Replication" + id = "antinoblium_replication" + desc = "Antinoblium breaks down all gases into more of itself." + +/datum/gas_reaction/antinoblium_replication/init_reqs() + requirements = list( + /datum/gas/antinoblium = MOLES_GAS_VISIBLE, + "MIN_TEMP" = REACTION_OPPRESSION_MIN_TEMP, + ) + +/** + * Antinoblium Recplication + * + * Converts all gases into antinoblium. + */ +/datum/gas_reaction/antinoblium_replication/react(datum/gas_mixture/air, datum/holder) + . = REACTING + var/list/cached_gases = air.gases + 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/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 in cached_gases) + if(id == /datum/gas/antinoblium) + continue + var/list/gas = cached_gases[id] + if(. == NO_REACTION) // Let the gases get properly cleared while avoiding potential division by 0. + gas[MOLES] = 0 + continue + gas[MOLES] -= reaction_rate * gas[MOLES] / total_not_antinoblium_moles + antinoblium[MOLES] += reaction_rate + SET_REACTION_RESULTS(reaction_rate) + var/new_heat_capacity = air.heat_capacity() + if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) + air.temperature = max(air.temperature * heat_capacity / new_heat_capacity, TCMB) + + #undef SET_REACTION_RESULTS diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index cd5f6c9fe9c..0d9cc2dd908 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1074,6 +1074,7 @@ GLOBAL_LIST_EMPTY(features_by_species) */ /datum/species/proc/handle_environment(mob/living/carbon/human/humi, datum/gas_mixture/environment, seconds_per_tick, times_fired) handle_environment_pressure(humi, environment, seconds_per_tick, times_fired) + handle_gas_interaction(humi, environment, seconds_per_tick, times_fired) /** * Body temperature handler for species @@ -1377,6 +1378,20 @@ GLOBAL_LIST_EMPTY(features_by_species) H.adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 2) +/** + * Handles exposure to the skin of various gases. + */ +/datum/species/proc/handle_gas_interaction(mob/living/carbon/human/human, datum/gas_mixture/environment, seconds_per_tick, times_fired) + if((human?.wear_suit?.clothing_flags & STOPSPRESSUREDAMAGE) && (human?.head?.clothing_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) + //////////// // Stun // ////////////