Adds Water Vapor and the Electrolyzer (#30875)

* this will work first try (adds water vapor and the electrolyzer)

* naming fix

* removes a warn

* makes water vapor able to be seen and adds it to the tiny_test atmos map

* Build Rust library

* adds the electrolyzer to all maps, and linter fix

* linter fix part 2

* electrolyzer tweak and more work on the test_atmos map

* tgui rebuilding

* re
rebuilding tgui

* makes the electrolyzer consume power and some small test atmos touch ups

* im axing the test_tiny because i don't want to map it

* clarifies how much power the electrolyzer uses

* Build Rust library

* suggestionss

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Co-authored-by: JimKil3 <47290811+JimKil3@users.noreply.github.com>
Signed-off-by: Hayden Redacted <91229275+haydenredacted@users.noreply.github.com>

* updating the SM manual

* electrolyzer tweaks

* dg suggestions pt. 2

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Hayden Redacted <91229275+haydenredacted@users.noreply.github.com>

* removed unused code

---------

Signed-off-by: Hayden Redacted <91229275+haydenredacted@users.noreply.github.com>
Co-authored-by: paradisess13[bot] <165046124+paradisess13[bot]@users.noreply.github.com>
Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Co-authored-by: JimKil3 <47290811+JimKil3@users.noreply.github.com>
This commit is contained in:
Hayden Redacted
2025-12-10 00:04:11 +00:00
committed by GitHub
co-authored by DGamerL JimKil3 paradisess13[bot] <165046124+paradisess13[bot]@users.noreply.github.com> warriorstar-orion
parent be48d7598f
commit 5728e0c46f
54 changed files with 671 additions and 117 deletions
+142
View File
@@ -0,0 +1,142 @@
/obj/machinery/power/electrolyzer
name = "gas electrolyzer"
desc = "A nifty little machine that is able to produce hydrogen when supplied with water vapor and enough power, allowing for on-the-go hydrogen production! Nanotrasen is not responsible for any accidents that may occur from sudden hydrogen combustion or explosions. It seems it needs around 350 kW of power to funtion properly."
anchored = FALSE
icon = 'icons/obj/atmos.dmi'
icon_state = "electrolyzer_off"
density = TRUE
active_power_consumption = 350000
/// whether or not we're actively using power/seeking water vapor in the air
var/on = FALSE
var/datum/gas_mixture/gas
var/board_path = /obj/item/circuitboard/electrolyzer
/obj/machinery/power/electrolyzer/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/electrolyzer(src)
component_parts += new /obj/item/stock_parts/micro_laser(src)
component_parts += new /obj/item/stock_parts/micro_laser(src)
component_parts += new /obj/item/stock_parts/matter_bin(src)
component_parts += new /obj/item/stock_parts/matter_bin(src)
component_parts += new /obj/item/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
if(!powernet)
connect_to_network()
if(powernet)
RegisterSignal(powernet)
RefreshParts()
/obj/machinery/power/electrolyzer/wrench_act(mob/living/user, obj/item/I)
if(on)
return
. = TRUE
if(!I.use_tool(src, user, I.tool_volume))
return
if(!anchored)
connect_to_network()
to_chat(user, "<span class='notice'>You secure the generator to the floor.</span>")
else
disconnect_from_network()
to_chat(user, "<span class='notice'>You unsecure the generator from the floor.</span>")
anchored = !anchored
/obj/machinery/power/electrolyzer/screwdriver_act(mob/user, obj/item/I)
. = TRUE
if(!anchored)
to_chat(user, "<span class='warning'>[src] needs to be secured down first!</span>")
return
if(on)
to_chat(user, "<span class='warning'>[src] needs to be turned off first!</span>")
return
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
return
panel_open = !panel_open
if(panel_open)
SCREWDRIVER_OPEN_PANEL_MESSAGE
panel_open = TRUE
icon_state = "electrolyzer_open"
else
SCREWDRIVER_CLOSE_PANEL_MESSAGE
icon_state = "electrolyzer_off"
panel_open = FALSE
/obj/machinery/power/electrolyzer/crowbar_act(mob/living/user, obj/item/I)
if(panel_open)
deconstruct(TRUE)
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
I.play_tool_sound(user, I.tool_volume)
return TRUE
return FALSE
/obj/machinery/power/electrolyzer/AltClick(mob/user)
if(anchored)
to_chat(user, "<span class='warning'>[src] is anchored to the floor!</span>")
return
pixel_x = 0
pixel_y = 0
/obj/machinery/power/electrolyzer/Destroy()
if(powernet)
UnregisterSignal(powernet, COMSIG_POWERNET_POWER_CHANGE)
return ..()
/datum/milla_safe/electrolyzer_process
/obj/machinery/power/electrolyzer/process()
if(on && get_surplus() >= active_power_consumption)
consume_direct_power(active_power_consumption)
var/datum/milla_safe/electrolyzer_process/milla = new()
milla.invoke_async(src)
// Turns the electrolyzer on and off
/obj/machinery/power/electrolyzer/attack_hand(mob/user)
if(stat & BROKEN)
return
if(!anchored)
to_chat(user, "<span class='warning'>[src] must be anchored first!</span>")
return
if(panel_open)
to_chat(user, "<span class='warning'>Close the panel first!</span>")
return
var/area/A = get_area(src)
if(!istype(A) || !A.powernet.has_power(PW_CHANNEL_EQUIPMENT))
to_chat(user, "<span class='warning'>[src] must be powered!</span>")
return
. = ..()
if(on)
on = FALSE
to_chat(user, "<span class='notice'>[src] switches off.</span>")
icon_state = "electrolyzer_off"
else
on = TRUE
to_chat(user, "<span class='notice'>[src] begins to hum quietly.</span>")
icon_state = "electrolyzer_on"
add_fingerprint(usr)
/obj/machinery/power/electrolyzer/proc/process_atmos_safely(turf/T, datum/gas_mixture/env)
var/datum/gas_mixture/removed = new()
if(env.water_vapor() > 3)
removed.set_water_vapor(env.water_vapor())
env.set_water_vapor(0)
return removed
/obj/machinery/power/electrolyzer/proc/has_water_vapor(datum/gas_mixture/gas)
if(!gas)
return FALSE
return gas.water_vapor() > 3
/datum/milla_safe/electrolyzer_process/on_run(obj/machinery/power/electrolyzer/electrolyzer, datum/gas_mixture)
var/turf/T = get_turf(electrolyzer)
var/datum/gas_mixture/env = get_turf_air(T)
var/datum/gas_mixture/removed = electrolyzer.process_atmos_safely(T, env)
if(electrolyzer.on && electrolyzer.has_water_vapor(removed))
var/water_vapor_to_remove = removed.water_vapor()
var/hydrogen_produced = water_vapor_to_remove
var/oxygen_produced = water_vapor_to_remove / 2
removed.set_water_vapor(removed.water_vapor() - water_vapor_to_remove)
env.set_hydrogen(env.hydrogen() + hydrogen_produced)
env.set_oxygen(env.oxygen() + oxygen_produced)
@@ -16,10 +16,12 @@
#define CO2_HEAT_PENALTY 0.1
#define NITROGEN_HEAT_PENALTY -1.5
#define HYDROGEN_HEAT_PENALTY 20
#define H2O_HEAT_PENALTY 5
#define OXYGEN_TRANSMIT_MODIFIER 1.5 //Higher == Bigger bonus to power generation.
#define PLASMA_TRANSMIT_MODIFIER 4
#define HYDROGEN_TRANSMIT_MODIFIER 3
#define H2O_TRANSMIT_MODIFIER -10
#define N2O_HEAT_RESISTANCE 6 //Higher == Gas makes the crystal more resistant against heat damage.
@@ -33,6 +35,7 @@
#define N2O_CRUNCH 0.55
#define PLASMA_CRUNCH 4
#define HYDROGEN_CRUNCH 2
#define H2O_CRUNCH 0.75
#define MOLE_CRUNCH_THRESHOLD 1700 //Above this value we can get lord singulo and
#define MOLE_PENALTY_THRESHOLD 1800 //Above this value we can get lord singulo and independent mol damage, below it we can heal damage
@@ -156,6 +159,7 @@
var/co2comp = 0
var/n2ocomp = 0
var/h2comp = 0
var/h2ocomp = 0
///The last air sample's total molar count, will always be above or equal to 0
var/combined_gas = 0
@@ -522,13 +526,14 @@
n2ocomp = max(removed.sleeping_agent() / combined_gas, 0)
n2comp = max(removed.nitrogen() / combined_gas, 0)
h2comp = max(removed.hydrogen() / combined_gas, 0)
h2ocomp = max(removed.water_vapor() / combined_gas, 0)
gasmix_power_ratio = min(max(plasmacomp + o2comp + co2comp + h2comp - n2comp, 0), 1)
gasmix_power_ratio = min(max(plasmacomp + o2comp + co2comp + h2comp + h2ocomp - n2comp, 0), 1)
dynamic_heat_modifier = max((plasmacomp * PLASMA_HEAT_PENALTY) + (o2comp * OXYGEN_HEAT_PENALTY) + (co2comp * CO2_HEAT_PENALTY) + (n2comp * NITROGEN_HEAT_PENALTY) + (h2comp * HYDROGEN_HEAT_PENALTY), 0.5)
dynamic_heat_modifier = max((plasmacomp * PLASMA_HEAT_PENALTY) + (o2comp * OXYGEN_HEAT_PENALTY) + (co2comp * CO2_HEAT_PENALTY) + (n2comp * NITROGEN_HEAT_PENALTY) + (h2comp * HYDROGEN_HEAT_PENALTY) + (h2ocomp * H2O_HEAT_PENALTY), 0.5)
dynamic_heat_resistance = max(n2ocomp * N2O_HEAT_RESISTANCE, 1)
power_transmission_bonus = max((plasmacomp * PLASMA_TRANSMIT_MODIFIER) + (o2comp * OXYGEN_TRANSMIT_MODIFIER), 0)
power_transmission_bonus = max((plasmacomp * PLASMA_TRANSMIT_MODIFIER) + (o2comp * OXYGEN_TRANSMIT_MODIFIER) + (h2comp * HYDROGEN_TRANSMIT_MODIFIER) + (h2ocomp * H2O_TRANSMIT_MODIFIER), 0)
//more moles of gases are harder to heat than fewer, so let's scale heat damage around them
mole_heat_penalty = max(combined_gas / MOLE_HEAT_PENALTY, 1)
@@ -568,7 +573,7 @@
var/crush_ratio = combined_gas / MOLE_CRUNCH_THRESHOLD
gas_coefficient = 1 + (crush_ratio ** 2 * (crush_ratio <= 1) + (crush_ratio > 1) * 2 * crush_ratio / (crush_ratio + 1)) * (plasmacomp * PLASMA_CRUNCH + o2comp * O2_CRUNCH + co2comp * CO2_CRUNCH + n2comp * N2_CRUNCH + n2ocomp * N2O_CRUNCH + h2comp * HYDROGEN_CRUNCH)
gas_coefficient = 1 + (crush_ratio ** 2 * (crush_ratio <= 1) + (crush_ratio > 1) * 2 * crush_ratio / (crush_ratio + 1)) * (plasmacomp * PLASMA_CRUNCH + o2comp * O2_CRUNCH + co2comp * CO2_CRUNCH + n2comp * N2_CRUNCH + n2ocomp * N2O_CRUNCH + h2comp * HYDROGEN_CRUNCH + h2ocomp * H2O_CRUNCH)
radiation_pulse(src, 6 * power * (gas_coefficient + max(0, ((power_transmission_bonus / 10)))), GAMMA_RAD)
@@ -1282,9 +1287,11 @@
#undef CO2_HEAT_PENALTY
#undef NITROGEN_HEAT_PENALTY
#undef HYDROGEN_HEAT_PENALTY
#undef H2O_HEAT_PENALTY
#undef OXYGEN_TRANSMIT_MODIFIER
#undef PLASMA_TRANSMIT_MODIFIER
#undef HYDROGEN_TRANSMIT_MODIFIER
#undef H2O_TRANSMIT_MODIFIER
#undef N2O_HEAT_RESISTANCE
#undef POWERLOSS_INHIBITION_GAS_THRESHOLD
#undef POWERLOSS_INHIBITION_MOLE_THRESHOLD
@@ -1328,3 +1335,4 @@
#undef N2O_CRUNCH
#undef PLASMA_CRUNCH
#undef HYDROGEN_CRUNCH
#undef H2O_CRUNCH
@@ -120,6 +120,15 @@
air.set_hydrogen(2000)
supermatter_turf.blind_release_air(air)
//water vapor
/datum/engi_event/supermatter_event/charlie_tier/water_vapor
name = "C-5"
/datum/engi_event/supermatter_event/charlie_tier/water_vapor/on_start()
var/datum/gas_mixture/air = new()
air.set_water_vapor(2000)
supermatter_turf.blind_release_air(air)
//Class B events
/datum/engi_event/supermatter_event/bravo_tier
threat_level = SM_EVENT_THREAT_B