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 // ////////////