diff --git a/_maps/RandomRuins/StationRuins/BoxStation/engine_rbmk.dmm b/_maps/RandomRuins/StationRuins/BoxStation/engine_rbmk.dmm new file mode 100644 index 000000000000..92ada37af472 --- /dev/null +++ b/_maps/RandomRuins/StationRuins/BoxStation/engine_rbmk.dmm @@ -0,0 +1,2268 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ae" = ( +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/turf/closed/wall, +/area/engine/engineering) +"bl" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"bp" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"bZ" = ( +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/orange/visible{ + dir = 1 + }, +/turf/open/floor/carpet/royalblack, +/area/engine/engineering) +"cp" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/door/airlock/engineering{ + name = "AI Satellite Access"; + req_one_access_txt = "10;17;32" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"cz" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plasteel, +/area/engine/engineering) +"dH" = ( +/turf/closed/wall/r_wall, +/area/engine/engineering) +"dV" = ( +/obj/structure/lattice, +/turf/closed/wall/r_wall, +/area/space/nearstation) +"ej" = ( +/obj/machinery/portable_atmospherics/canister/nitrogen, +/obj/machinery/atmospherics/components/unary/portables_connector, +/turf/open/floor/engine, +/area/engine/engineering) +"et" = ( +/obj/machinery/button/door{ + id = "au_nuclear_vent"; + name = "RBMK Compartment Flush"; + pixel_x = 27 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 10 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"ez" = ( +/obj/machinery/atmospherics/components/binary/pump{ + name = "Reactor to Cooling Loop" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"eG" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"eT" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"fE" = ( +/obj/effect/spawner/structure/window/plasma/reinforced/shutter, +/turf/open/floor/plating, +/area/engine/engineering) +"gI" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/spawner/structure/window/plasma/reinforced, +/turf/open/floor/plating, +/area/engine/engineering) +"hw" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/door/airlock/engineering/glass{ + name = "Reactor Clean Room"; + req_access_txt = "10" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"hV" = ( +/obj/machinery/shower{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = 25 + }, +/turf/open/floor/noslip, +/area/engine/engineering) +"is" = ( +/obj/effect/spawner/structure/window/plasma/reinforced, +/obj/structure/cable/yellow{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/engine/engineering) +"iu" = ( +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"iB" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/airlock/external{ + name = "Engineering External Access"; + req_access_txt = "10;13" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/engine/engineering) +"iV" = ( +/obj/machinery/door/poddoor{ + id = "au_nuclear_vent" + }, +/turf/open/floor/plating, +/area/engine/engineering) +"iZ" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/obj/machinery/computer/atmos_control/tank/oxygen_tank{ + dir = 8; + input_tag = null; + output_tag = "o2_out2"; + sensors = list("o2_sensor2" = "Tank") + }, +/turf/open/floor/engine, +/area/engine/engineering) +"jb" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 10 + }, +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"jx" = ( +/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"jz" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"jF" = ( +/obj/effect/spawner/structure/window/plasma/reinforced, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/turf/open/floor/plating, +/area/engine/engineering) +"jV" = ( +/obj/structure/rack, +/obj/item/clothing/mask/gas{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/clothing/mask/gas, +/obj/item/clothing/mask/gas{ + pixel_x = -3; + pixel_y = -3 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"jY" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8; + external_pressure_bound = 0; + frequency = 1441; + id_tag = "o2_out2"; + initialize_directions = 1; + internal_pressure_bound = 4000; + pressure_checks = 2; + pressure_resistance = 10; + pump_direction = 0 + }, +/turf/open/floor/engine/o2, +/area/engine/engineering) +"kq" = ( +/obj/item/fuel_rod, +/turf/open/indestructible/sound/pool{ + id = 1 + }, +/area/engine/engineering) +"kM" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, +/turf/open/floor/plasteel, +/area/engine/engineering) +"le" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/item/fuel_rod, +/turf/open/indestructible/sound/pool{ + id = 1 + }, +/area/engine/engineering) +"md" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"nf" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/closet/emcloset/anchored, +/obj/machinery/advanced_airlock_controller{ + dir = 1; + pixel_y = -24 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plating, +/area/engine/engineering) +"np" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"nH" = ( +/obj/machinery/computer/atmos_control/tank/toxin_tank{ + dir = 8; + input_tag = null; + output_tag = "tox_out2"; + sensors = list("tox_sensor2" = "Tank") + }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"nL" = ( +/obj/machinery/light/small, +/obj/machinery/firealarm{ + dir = 8; + pixel_y = -28 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/turf/open/floor/noslip, +/area/engine/engineering) +"nP" = ( +/obj/machinery/shower{ + dir = 8 + }, +/obj/item/radio/intercom{ + pixel_x = 27 + }, +/turf/open/floor/noslip, +/area/engine/engineering) +"nR" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 1 + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/turf/open/floor/carpet/royalblack, +/area/engine/engineering) +"oz" = ( +/obj/machinery/atmospherics/pipe/simple/purple/visible, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"oF" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"oT" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/obj/effect/spawner/structure/window/plasma/reinforced/shutter, +/turf/open/floor/plating, +/area/engine/engineering) +"pd" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 6 + }, +/turf/open/floor/carpet/royalblack, +/area/engine/engineering) +"pk" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"py" = ( +/obj/machinery/light/small, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/turf/open/floor/noslip, +/area/engine/engineering) +"pU" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"pZ" = ( +/obj/structure/table, +/obj/item/storage/toolbox/mechanical{ + pixel_y = 5 + }, +/obj/item/flashlight{ + pixel_x = 1; + pixel_y = 5 + }, +/obj/item/flashlight{ + pixel_x = 1; + pixel_y = 5 + }, +/obj/structure/sign/warning/vacuum/external{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"qk" = ( +/obj/machinery/shower{ + dir = 4 + }, +/turf/open/floor/noslip, +/area/engine/engineering) +"ql" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"qH" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"qV" = ( +/turf/closed/wall, +/area/engine/engineering) +"qY" = ( +/obj/effect/spawner/structure/window/plasma/reinforced/shutter, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/turf/open/floor/plating, +/area/engine/engineering) +"ra" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/engine, +/area/engine/engineering) +"rd" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 10 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"rm" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/structure/closet/firecloset, +/obj/machinery/firealarm{ + pixel_y = 24 + }, +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/camera{ + c_tag = "Reactor Control Room"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"rK" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"rN" = ( +/obj/machinery/atmospherics/components/binary/valve/digital{ + name = "Filter to Waste" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"rW" = ( +/obj/structure/cable/yellow, +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/preset, +/turf/open/floor/engine, +/area/engine/engineering) +"sb" = ( +/obj/machinery/light, +/turf/open/floor/engine, +/area/engine/engineering) +"sK" = ( +/obj/structure/closet/radiation, +/obj/item/clothing/glasses/meson/engine, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/sign/warning/radiation{ + pixel_y = 32 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4, +/obj/item/sealant, +/obj/machinery/camera{ + c_tag = "East Clean Room" + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"tc" = ( +/obj/effect/spawner/structure/window/plasma/reinforced, +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/turf/open/floor/plating, +/area/engine/engineering) +"tZ" = ( +/obj/machinery/computer/station_alert, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/obj/machinery/light{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"ug" = ( +/obj/structure/lattice, +/obj/structure/grille, +/turf/template_noop, +/area/space/nearstation) +"ul" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1; + name = "Filter Line Connector" + }, +/obj/machinery/portable_atmospherics/canister, +/turf/open/floor/engine, +/area/engine/engineering) +"uu" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"uK" = ( +/obj/machinery/atmospherics/components/trinary/mixer/t_mixer{ + dir = 8 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"vb" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/door/airlock/engineering/glass{ + name = "Reactor Clean Room"; + req_access_txt = "10" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"vl" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 5 + }, +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"vm" = ( +/obj/machinery/atmospherics/pipe/simple/brown/visible{ + dir = 5 + }, +/obj/machinery/meter, +/turf/open/floor/engine, +/area/engine/engineering) +"vp" = ( +/obj/item/radio/intercom{ + pixel_x = 26 + }, +/obj/structure/closet/radiation, +/obj/item/clothing/glasses/meson/engine, +/obj/item/sealant, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"vs" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"wg" = ( +/obj/structure/closet/radiation, +/obj/item/clothing/glasses/meson/engine, +/obj/structure/sign/warning/radiation{ + pixel_y = 32 + }, +/obj/item/clothing/glasses/meson/engine, +/obj/item/sealant, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"wo" = ( +/obj/machinery/atmospherics/pipe/simple/brown/visible{ + dir = 8 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"wr" = ( +/obj/machinery/shower{ + dir = 4 + }, +/obj/machinery/firealarm{ + dir = 8; + pixel_y = -28 + }, +/turf/open/floor/noslip, +/area/engine/engineering) +"ws" = ( +/obj/effect/spawner/structure/window/plasma/reinforced, +/turf/open/floor/plating, +/area/engine/engineering) +"wV" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Atmospherics to Moderator" + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"xm" = ( +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ + dir = 8 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"xA" = ( +/obj/structure/cable/yellow{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 5 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"xE" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"yt" = ( +/obj/structure/table, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/computer/reactor/stats, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"yw" = ( +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"zS" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 6 + }, +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"zY" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 8 + }, +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"Ah" = ( +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Az" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"AH" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"AK" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 10 + }, +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/space/nearstation) +"Bn" = ( +/obj/structure/closet/firecloset, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Bq" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/turf/template_noop, +/area/space/nearstation) +"Bu" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible, +/obj/effect/turf_decal/box, +/turf/open/floor/engine, +/area/engine/engineering) +"BT" = ( +/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/engine_waste{ + dir = 4 + }, +/obj/structure/grille/broken, +/turf/open/floor/plating/airless, +/area/engine/engineering) +"Cd" = ( +/obj/effect/turf_decal/delivery, +/turf/closed/wall/r_wall, +/area/engine/engineering) +"Ck" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/junction, +/obj/effect/spawner/structure/window/plasma/reinforced/shutter, +/turf/open/floor/plating, +/area/engine/engineering) +"CA" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external{ + name = "Engineering External Access"; + req_access_txt = "10;13" + }, +/obj/machinery/atmospherics/pipe/layer_manifold, +/turf/open/floor/plating, +/area/engine/engineering) +"CL" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/item/sealant{ + pixel_x = 4 + }, +/obj/item/reagent_containers/food/snacks/pizzaslice/meat{ + pixel_x = -3; + pixel_y = 5 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"CT" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"CV" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "Coolent to Reactor" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Fd" = ( +/obj/structure/grille, +/turf/template_noop, +/area/space/nearstation) +"Fl" = ( +/obj/machinery/atmospherics/components/binary/pump{ + name = "Moderators to Reactor" + }, +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/yellow{ + icon_state = "2-8" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"FF" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/machinery/meter, +/turf/open/floor/engine, +/area/engine/engineering) +"FG" = ( +/obj/machinery/air_sensor{ + id_tag = "tox_sensor2" + }, +/turf/open/floor/engine/plasma, +/area/engine/engineering) +"FM" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/engine, +/area/engine/engineering) +"FU" = ( +/obj/machinery/door/airlock/engineering{ + name = "Reactor Core"; + req_one_access_txt = "10;24" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Gc" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Gz" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/turf/open/indestructible/sound/pool{ + id = 1 + }, +/area/engine/engineering) +"GY" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/meter, +/turf/open/floor/carpet/royalblack, +/area/engine/engineering) +"Hd" = ( +/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"Hi" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 9 + }, +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"Hj" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = -25 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"HI" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"HQ" = ( +/obj/effect/turf_decal/stripes/corner, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"HV" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 1 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Im" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 8 + }, +/obj/machinery/meter, +/turf/open/floor/engine, +/area/engine/engineering) +"IH" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 6 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Jb" = ( +/obj/machinery/modular_computer/console/preset/engineering, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Je" = ( +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/door/airlock/engineering/glass{ + name = "Control Room"; + req_access_txt = "10" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Jj" = ( +/obj/effect/turf_decal/stripes/line, +/obj/item/fuel_rod, +/turf/open/indestructible/sound/pool{ + id = 1 + }, +/area/engine/engineering) +"Jx" = ( +/obj/machinery/camera{ + c_tag = "Reactor Core East"; + dir = 8 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"JW" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/machinery/atmospherics/components/trinary/filter{ + name = "Filter to Waste" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Kt" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Kx" = ( +/turf/open/floor/engine/plasma, +/area/engine/engineering) +"KP" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/door/airlock/engineering/glass{ + name = "Control Room"; + req_access_txt = "10" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"KS" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/item/fuel_rod, +/turf/open/indestructible/sound/pool{ + id = 1 + }, +/area/engine/engineering) +"Lw" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Mc" = ( +/obj/machinery/air_sensor{ + id_tag = "o2_sensor2" + }, +/turf/open/floor/engine/o2, +/area/engine/engineering) +"ME" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 6 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"MQ" = ( +/obj/structure/pool_ladder, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/open/indestructible/sound/pool/end{ + id = 1 + }, +/area/engine/engineering) +"Ng" = ( +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"Nm" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "2-8" + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 1 + }, +/turf/open/floor/carpet/royalblack, +/area/engine/engineering) +"NO" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 6 + }, +/obj/machinery/camera{ + c_tag = "Reactor Core West"; + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Om" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/item/fuel_rod, +/turf/open/indestructible/sound/pool/end{ + id = 1 + }, +/area/engine/engineering) +"Oq" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Or" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 5 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"OI" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 5 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"OM" = ( +/obj/structure/table, +/obj/item/clothing/gloves/color/yellow, +/obj/item/storage/toolbox/electrical{ + pixel_y = 5 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) +"Pg" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/table, +/obj/item/paper_bin, +/obj/item/pen, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"PR" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Qk" = ( +/obj/structure/cable/yellow{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Qp" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Qt" = ( +/obj/machinery/atmospherics/components/binary/pump{ + name = "Moderators to Reactor" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"QR" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 9 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"RI" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Sa" = ( +/obj/structure/table, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/computer/reactor/control_rods, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Sb" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/indestructible/sound/pool{ + id = 1 + }, +/area/engine/engineering) +"Sg" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/closet/radiation, +/obj/item/clothing/glasses/meson/engine, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4, +/obj/item/sealant, +/obj/machinery/camera{ + c_tag = "West Clean Room" + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"Sr" = ( +/turf/template_noop, +/area/template_noop) +"Sz" = ( +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/engine, +/area/engine/engineering) +"SX" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 1 + }, +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"Tn" = ( +/turf/open/floor/engine/o2, +/area/engine/engineering) +"Uc" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Ue" = ( +/turf/open/floor/plasteel, +/area/engine/engineering) +"Um" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 10 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"UF" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8; + external_pressure_bound = 0; + frequency = 1441; + id_tag = "tox_out"; + initialize_directions = 1; + internal_pressure_bound = 4000; + pressure_checks = 2; + pressure_resistance = 10; + pump_direction = 0 + }, +/turf/open/floor/engine/plasma, +/area/engine/engineering) +"VG" = ( +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/space/nearstation) +"Wm" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, +/turf/open/floor/engine, +/area/engine/engineering) +"Wp" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_x = 32 + }, +/obj/machinery/atmospherics/components/binary/dp_vent_pump/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/engine/engineering) +"Wq" = ( +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/obj/structure/closet/secure_closet/engineering_welding, +/turf/open/floor/engine, +/area/engine/engineering) +"Wt" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Atmospherics to Reactor" + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"WU" = ( +/obj/machinery/door/poddoor{ + id = "au_nuclear_vent" + }, +/turf/open/floor/plating/airless, +/area/engine/engineering) +"Xk" = ( +/turf/open/floor/engine, +/area/engine/engineering) +"XN" = ( +/turf/closed/wall/r_wall, +/area/space/nearstation) +"XR" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/pool_filter{ + id = 1 + }, +/obj/item/fuel_rod, +/turf/open/indestructible/sound/pool/end{ + id = 1 + }, +/area/engine/engineering) +"Ym" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"YD" = ( +/obj/machinery/atmospherics/pipe/manifold4w/brown/visible, +/turf/open/floor/engine, +/area/engine/engineering) +"YG" = ( +/obj/item/twohanded/required/pool/rubber_ring, +/obj/item/twohanded/required/pool/pool_noodle, +/obj/item/twohanded/required/pool/pool_noodle, +/obj/item/twohanded/required/pool/pool_noodle, +/obj/item/twohanded/required/pool/rubber_ring, +/obj/item/twohanded/required/pool/rubber_ring, +/obj/structure/closet/crate, +/turf/open/floor/engine, +/area/engine/engineering) +"Zm" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "Cooling Loop to Reactor" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"ZB" = ( +/obj/structure/table, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/computer/reactor/fuel_rods, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) +"ZI" = ( +/obj/machinery/atmospherics/components/binary/valve/digital{ + dir = 4; + name = "Emergency Coolant Purge" + }, +/turf/open/floor/engine, +/area/engine/engineering) +"ZM" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/space/nearstation) +"ZS" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 1 + }, +/obj/machinery/meter, +/turf/open/floor/engine, +/area/engine/engineering) +"ZT" = ( +/turf/template_noop, +/area/space) + +(1,1,1) = {" +Sr +Sr +Sr +Sr +Sr +Sr +Sr +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +Sr +Sr +Sr +Sr +Sr +"} +(2,1,1) = {" +Sr +Sr +Sr +Sr +Sr +Sr +Sr +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +Sr +Sr +Sr +Sr +Sr +"} +(3,1,1) = {" +Sr +Sr +Sr +Sr +Sr +Sr +Sr +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +Sr +Sr +Sr +Sr +Sr +"} +(4,1,1) = {" +Sr +Sr +Sr +Sr +Sr +Sr +Sr +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +Sr +Sr +Sr +Sr +Sr +"} +(5,1,1) = {" +Sr +Sr +Sr +Sr +Sr +Sr +Sr +ZT +ZT +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +ZT +ZT +ZT +ZT +Sr +Sr +Sr +Sr +Sr +"} +(6,1,1) = {" +Sr +Sr +Sr +Sr +Sr +Sr +Sr +ZT +ZT +Fd +XN +XN +XN +XN +XN +XN +Fd +ZT +ZT +ZT +ZT +Sr +Sr +Sr +Sr +Sr +"} +(7,1,1) = {" +Sr +Sr +Sr +Sr +qV +qV +dH +ZT +ZT +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +ZT +"} +(8,1,1) = {" +Sr +Sr +OM +pZ +qV +nf +dH +ZT +ZT +ZT +yw +ZT +ZT +ZT +yw +yw +ZT +ZT +ZT +ZT +ZT +ZT +ZT +yw +ZT +ZT +"} +(9,1,1) = {" +Sr +Sr +vs +cz +iB +Wp +CA +ZT +ZT +ZT +yw +ZT +ZT +ZT +yw +yw +ZT +ZT +ZT +ZT +ZT +yw +yw +yw +yw +ZT +"} +(10,1,1) = {" +Sr +gI +hw +ws +dH +dH +dH +ZT +ZT +ZT +yw +ZT +ZT +ZT +yw +yw +yw +yw +ZT +ZT +ZT +yw +ZT +ZT +ZT +ZT +"} +(11,1,1) = {" +ws +is +Qk +wr +dH +ZT +ZT +ZT +ZT +ZT +yw +ZT +ZT +ZT +yw +yw +zS +vl +zS +vl +yw +ug +ug +ZT +ZT +ZT +"} +(12,1,1) = {" +dH +Sg +Lw +py +dH +yw +ug +ug +BT +ug +ug +ug +ug +ug +yw +yw +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(13,1,1) = {" +dH +wg +RI +nP +dH +dH +dH +dH +oT +dH +fE +fE +dH +dH +dH +dH +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(14,1,1) = {" +dH +dH +Je +dH +dH +CL +Xk +Xk +HV +NO +jz +ul +Xk +Xk +YG +dH +zY +ZM +zY +ZM +yw +dV +ug +ZT +ZT +ZT +"} +(15,1,1) = {" +dH +rm +bp +Hj +dH +Wq +Xk +Xk +ZI +rd +rN +Oq +md +Or +sb +dH +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(16,1,1) = {" +ws +Pg +pd +Wt +jF +eG +md +FF +xE +rK +MQ +Sb +Gz +pk +Xk +fE +zY +Bq +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(17,1,1) = {" +ws +yt +Nm +iu +FU +Gc +bl +Sz +ra +xA +XR +kq +Jj +pk +Xk +fE +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(18,1,1) = {" +ws +ZB +bZ +wV +tc +Ah +Ng +vm +pk +Az +Om +le +KS +pk +Xk +dH +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(19,1,1) = {" +ws +Sa +GY +ql +ws +Xk +Xk +wo +Um +HQ +eT +Im +eT +JW +ez +Ck +Hi +ZM +zY +Bq +yw +XN +ug +ZT +ZT +ZT +"} +(20,1,1) = {" +ws +Jb +nR +AH +ws +Xk +Xk +wo +Xk +xm +Xk +pk +Xk +ME +Zm +Ck +vl +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(21,1,1) = {" +dH +tZ +PR +Qp +ws +Bu +Qt +YD +Hd +Fl +oz +rW +Xk +Uc +sb +dH +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(22,1,1) = {" +dH +dH +KP +dH +dH +Xk +Xk +wo +Xk +FM +Xk +Wm +Xk +Uc +Xk +fE +zY +ZM +zY +ZM +yw +dV +ug +ZT +ZT +ZT +"} +(23,1,1) = {" +dH +Bn +HI +qk +dH +Xk +IH +uK +OI +Kt +CT +ZS +np +QR +Xk +fE +zY +ZM +zY +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(24,1,1) = {" +dH +sK +oF +nL +dH +qH +nH +Xk +iZ +Jx +pU +et +CV +ej +Xk +dH +zY +AK +Hi +ZM +yw +XN +ug +ZT +ZT +ZT +"} +(25,1,1) = {" +dH +vp +Ym +hV +dH +dH +qY +dH +qY +dH +dH +dH +iV +iV +WU +dH +jb +SX +SX +Hi +yw +ug +ug +ZT +ZT +ZT +"} +(26,1,1) = {" +Cd +dH +vb +dH +dH +Kx +UF +dH +jY +Tn +dH +ZT +ZT +ZT +ZT +ZT +VG +yw +yw +Fd +Fd +ZT +ZT +yw +ZT +ZT +"} +(27,1,1) = {" +Sr +uu +kM +Ue +dH +Kx +FG +dH +Mc +Tn +dH +ZT +ZT +ZT +ZT +ZT +VG +yw +yw +XN +Fd +yw +yw +yw +yw +yw +"} +(28,1,1) = {" +Sr +Ue +jx +jV +dH +Kx +Kx +dH +Tn +Tn +dH +ZT +ZT +ZT +ZT +ZT +VG +VG +yw +XN +ug +ZT +ZT +yw +ZT +ZT +"} +(29,1,1) = {" +Sr +ae +cp +qV +dH +dH +dH +dH +dH +dH +dH +dH +dH +dH +dH +dH +VG +yw +yw +XN +ug +ZT +ZT +yw +ZT +ZT +"} diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index a6ee1c3f4f69..00bf3427e7c5 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -9,11 +9,12 @@ #define CHANNEL_BUZZ 1017 #define CHANNEL_BICYCLE 1016 #define CHANNEL_VOICE_ANNOUNCE 1015 +#define CHANNEL_REACTOR_ALERT 1014 //THIS SHOULD ALWAYS BE THE LOWEST ONE! //KEEP IT UPDATED -#define CHANNEL_HIGHEST_AVAILABLE 1014 +#define CHANNEL_HIGHEST_AVAILABLE 1013 #define MAX_INSTRUMENT_CHANNELS (128 * 6) diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index 4c38e4a05c40..3a5c88798b1c 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -205,3 +205,47 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro for(x in 1 to 4) output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y==5?B[x+16]:0), 0.001) return output + +/atom/proc/shake_animation(var/intensity = 8) //Makes the object visibly shake + var/initial_transform = new/matrix(transform) + var/init_px = pixel_x + var/shake_dir = pick(-1, 1) + var/rotation = 2+soft_cap(intensity, 1, 1, 0.94) + var/offset = 1+soft_cap(intensity*0.3, 1, 1, 0.8) + var/time = 2+soft_cap(intensity*0.3, 2, 1, 0.92) + animate(src, transform=turn(transform, rotation*shake_dir), pixel_x=init_px + offset*shake_dir, time=1) + animate(transform=initial_transform, pixel_x=init_px, time=time, easing=ELASTIC_EASING) + +/* + This proc makes the input taper off above cap. But there's no absolute cutoff. + Chunks of the input value above cap, are reduced more and more with each successive one and added to the output + A higher input value always makes a higher output value. but the rate of growth slows +*/ +/proc/soft_cap(var/input, var/cap = 0, var/groupsize = 1, var/groupmult = 0.9) + + //The cap is a ringfenced amount. If we're below that, just return the input + if (input <= cap) + return input + + var/output = 0 + var/buffer = 0 + var/power = 1//We increment this after each group, then apply it to the groupmult as a power + + //Ok its above, so the cap is a safe amount, we move that to the output + input -= cap + output += cap + + //Now we start moving groups from input to buffer + + + while (input > 0) + buffer = min(input, groupsize) //We take the groupsize, or all the input has left if its less + input -= buffer + + buffer *= groupmult**power //This reduces the group by the groupmult to the power of which index we're on. + //This ensures that each successive group is reduced more than the previous one + + output += buffer + power++ //Transfer to output, increment power, repeat until the input pile is all used + + return output diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm index 593bdf8c5a18..873faec201ca 100644 --- a/code/__HELPERS/radiation.dm +++ b/code/__HELPERS/radiation.dm @@ -27,8 +27,11 @@ /proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE) if(!SSradiation.can_fire) return - for(var/dir in GLOB.cardinals) - new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate) + if(istype(get_turf(source), /turf/open/indestructible/sound/pool)) //Nsv13 - Pools heavily block rads. Spent fuel pool! + intensity *= 0.10 + if(intensity >= 10) // Don't bother to spawn rad waves if they're just going to immediately go out + for(var/dir in GLOB.cardinals) + new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate) var/list/things = get_rad_contents(source) //copypasta because I don't want to put special code in waves to handle their origin for(var/k in 1 to things.len) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f857064f2f04..0e2329bfdf05 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -689,6 +689,8 @@ * Default behaviour is to send COMSIG_ATOM_RAD_ACT and return */ /atom/proc/rad_act(strength) + if(istype(get_turf(src), /turf/open/indestructible/sound/pool)) //Nsv13 - Pools protect you from rads. + strength *= 0.25 SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength) /** diff --git a/code/modules/power/reactor/fuel_rods.dm b/code/modules/power/reactor/fuel_rods.dm new file mode 100644 index 000000000000..7f99beb0325d --- /dev/null +++ b/code/modules/power/reactor/fuel_rods.dm @@ -0,0 +1,241 @@ +/obj/item/fuel_rod + name = "Uranium-235 Fuel Rod" + desc = "A titanium sheathed rod containing a measure of enriched uranium-dioxide powder inside, and a breeding blanket of uranium-238 around it, used to kick off a fission reaction and breed plutonium fuel respectivly." + icon = 'icons/obj/control_rod.dmi' + icon_state = "irradiated" + w_class = WEIGHT_CLASS_BULKY + var/depletion = 0 //Each fuel rod will deplete in around 30 minutes. + var/fuel_power = 0.10 + var/rad_strength = 500 + var/half_life = 2000 // how many depletion ticks are needed to half the fuel_power (1 tick = 1 second) + var/time_created = 0 + var/og_fuel_power = 0.20 //the original fuel power value + var/process = FALSE + // The depletion where depletion_final() will be called (and does something) + var/depletion_threshold = 100 + // How fast this rod will deplete + var/depletion_speed_modifier = 1 + var/depleted_final = FALSE // depletion_final should run only once + var/depletion_conversion_type = "plutonium" + +/obj/item/fuel_rod/Initialize() + . = ..() + time_created = world.time + AddComponent(/datum/component/radioactive, rad_strength, src) // This should be temporary for it won't make rads go lower than 350 + if(process) + START_PROCESSING(SSobj, src) + +/obj/item/fuel_rod/Destroy() + if(process) + STOP_PROCESSING(SSobj, src) + var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/N = loc + if(istype(N)) + N.fuel_rods -= src + . = ..() + +// This proc will try to convert your fuel rod if you don't override this proc +// So, ideally, you should write an override of this for every fuel rod you want to create +/obj/item/fuel_rod/proc/depletion_final(result_rod) + if(!result_rod) + return + var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/N = loc + // Rod conversion is moot when you can't find the reactor + if(istype(N)) + var/obj/item/fuel_rod/R + + // You can add your own depletion scheme and not override this proc if you are going to convert a fuel rod into another type + switch(result_rod) + if("plutonium") + R = new /obj/item/fuel_rod/plutonium(loc) + R.depletion = depletion + if("depleted") + if(fuel_power < 10) + fuel_power = 0 + playsound(loc, 'sound/effects/supermatter.ogg', 100, TRUE) + R = new /obj/item/fuel_rod/depleted(loc) + R.depletion = depletion + + // Finalization of conversion + if(istype(R)) + N.fuel_rods += R + qdel(src) + else + depleted_final = FALSE // Maybe try again later? + +/obj/item/fuel_rod/proc/deplete(amount=0.035) + depletion += amount * depletion_speed_modifier + if(depletion >= depletion_threshold && !depleted_final) + depleted_final = TRUE + depletion_final(depletion_conversion_type) + +/obj/item/fuel_rod/plutonium + fuel_power = 0.20 + name = "Plutonium-239 Fuel Rod" + desc = "A highly energetic titanium sheathed rod containing a sizeable measure of weapons grade plutonium, it's highly efficient as nuclear fuel, but will cause the reaction to get out of control if not properly utilised." + icon_state = "inferior" + rad_strength = 1500 + process = TRUE // for half life code + depletion_threshold = 300 + depletion_conversion_type = "depleted" + +/obj/item/fuel_rod/process() + fuel_power = og_fuel_power * 0.5**((world.time - time_created) / half_life SECONDS) // halves the fuel power every half life (33 minutes) + +/obj/item/fuel_rod/depleted + fuel_power = 0.05 + name = "Depleted Fuel Rod" + desc = "A highly radioactive fuel rod which has expended most of it's useful energy." + icon_state = "normal" + rad_strength = 6000 // smelly + depletion_conversion_type = null // It means that it won't turn into anything + process = TRUE + +// Master type for material optional (or requiring, wyci) and/or producing rods +/obj/item/fuel_rod/material + // Whether the rod has been harvested. Should be set in expend(). + var/expended = FALSE + // The material that will be inserted and then multiplied (or not). Should be some sort of /obj/item/stack + var/material_type + // The name of material that'll be used for texts + var/material_name + var/material_name_singular + var/initial_amount = 0 + // The maximum amount of material the rod can hold + var/max_initial_amount = 10 + var/grown_amount = 0 + // The multiplier for growth. 1 for the same 2 for double etc etc + var/multiplier = 2 + // After this depletion, you won't be able to add new materials + var/material_input_deadline = 25 + // Material fuel rods generally don't get converted into another fuel object + depletion_conversion_type = null + +// Called when the rod is fully harvested +/obj/item/fuel_rod/material/proc/expend() + expended = TRUE + +// Basic checks for material rods +/obj/item/fuel_rod/material/proc/check_material_input(mob/user) + if(depletion >= material_input_deadline) + to_chat(user, "The sample slots have sealed themselves shut, it's too late to add [material_name] now!") // no cheesing in crystals at 100% + return FALSE + if(expended) + to_chat(user, "\The [src]'s material slots have already been used.") + return FALSE + return TRUE + +// The actual growth +/obj/item/fuel_rod/material/depletion_final(result_rod) + if(result_rod) + ..() // So if you put anything into depletion_conversion_type then your fuel rod will be converted (or not) and *won't grow* + else + grown_amount = initial_amount * multiplier + +/obj/item/fuel_rod/material/attackby(obj/item/W, mob/user, params) + var/obj/item/stack/M = W + if(istype(M, material_type)) + if(!check_material_input(user)) + return + if(initial_amount < max_initial_amount) + var/adding = min((max_initial_amount - initial_amount), M.amount) + M.amount -= adding + initial_amount += adding + if (adding == 1) + to_chat(user, "You insert [adding] [material_name_singular] into \the [src].") + else + to_chat(user, "You insert [adding] [material_name] into \the [src].") + M.zero_amount() + else + to_chat(user, "\The [src]'s material slots are full!") + return + else + return ..() + +/obj/item/fuel_rod/material/attack_self(mob/user) + if(expended) + to_chat(user, "You have already removed [material_name] from \the [src].") + return + + if(depleted_final) + new material_type(user.loc, grown_amount) + if (grown_amount == 1) + to_chat(user, "You harvest [grown_amount] [material_name_singular] from \the [src].") // Unlikely + else + to_chat(user, "You harvest [grown_amount] [material_name] from \the [src].") + playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) + grown_amount = 0 + expend() + else if(depletion) + to_chat(user, "\The [src] has not fissiled enough to fully grow the sample. The progress bar shows it is [min(depletion/depletion_threshold*100,100)]% complete.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + else if(initial_amount) + new material_type(user.loc, initial_amount) + if (initial_amount == 1) + to_chat(user, "You remove [initial_amount] [material_name_singular] from \the [src].") + else + to_chat(user, "You remove [initial_amount] [material_name] from \the [src].") + playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) + initial_amount = 0 + +/obj/item/fuel_rod/material/examine(mob/user) + . = ..() + if(expended) + . += "The material slots have been slagged by the extreme heat, you can't grow [material_name] in this rod again..." + return + else if(depleted_final) + . += "This fuel rod's [material_name] are now fully grown, and it currently bears [grown_amount] harvestable [material_name_singular]\s." + return + if(depletion) + . += "The sample is [min(depletion/depletion_threshold*100,100)]% fissiled." + . += "[initial_amount]/[max_initial_amount] of the slots for [material_name] are full." + +/obj/item/fuel_rod/material/telecrystal + name = "Telecrystal Fuel Rod" + desc = "A disguised titanium sheathed rod containing several small slots infused with uranium dioxide. Permits the insertion of telecrystals to grow more. Fissiles much faster than its standard counterpart" + icon_state = "telecrystal" + fuel_power = 0.30 // twice as powerful as a normal rod, you're going to need some engineering autism if you plan to mass produce TC + depletion_speed_modifier = 3 // headstart, otherwise it takes two hours + rad_strength = 1500 + max_initial_amount = 8 + multiplier = 3 + material_type = /obj/item/stack/telecrystal + material_name = "telecrystals" + material_name_singular = "telecrystal" + +/obj/item/fuel_rod/material/telecrystal/depletion_final(result_rod) + ..() + if(result_rod) + return + fuel_power = 0.60 // thrice as powerful as plutonium, you'll want to get this one out quick! + name = "Exhausted Telecrystal Fuel Rod" + desc = "A highly energetic, disguised titanium sheathed rod containing a number of slots filled with greatly expanded telecrystals which can be removed by hand. It's extremely efficient as nuclear fuel, but will cause the reaction to get out of control if not properly utilised." + icon_state = "telecrystal_used" + AddComponent(/datum/component/radioactive, 3000, src) + +/obj/item/fuel_rod/material/bananium + name = "Bananium Fuel Rod" + desc = "A hilarious heavy-duty fuel rod which fissiles a bit slower than its cowardly counterparts. However, its cutting-edge cosmic clown technology allows rooms for extraordinarily exhilarating extraterrestrial element called bananium to menacingly multiply." + icon_state = "bananium" + fuel_power = 0.15 + depletion_speed_modifier = 3 + rad_strength = 350 + max_initial_amount = 10 + multiplier = 3 + material_type = /obj/item/stack/sheet/mineral/bananium + material_name = "sheets of bananium" + material_name_singular = "sheet of bananium" + +/obj/item/fuel_rod/material/bananium/deplete(amount=0.035) + ..() + if(initial_amount == max_initial_amount && prob(10)) + playsound(src, pick('sound/items/bikehorn.ogg'), 50) // HONK + +/obj/item/fuel_rod/material/bananium/depletion_final(result_rod) + ..() + if(result_rod) + return + fuel_power = 0.3 // Be warned + name = "Fully Grown Bananium Fuel Rod" + desc = "A hilarious heavy-duty fuel rod which fissiles a bit slower than it cowardly counterparts. Its greatly grimacing grwoth stage is now over, and bananium outgrowth hums as if it's blatantly honking bike horns." + icon_state = "bananium_used" + AddComponent(/datum/component/radioactive, 1250, src) diff --git a/code/modules/power/reactor/rbmk.dm b/code/modules/power/reactor/rbmk.dm new file mode 100644 index 000000000000..7f99e216026b --- /dev/null +++ b/code/modules/power/reactor/rbmk.dm @@ -0,0 +1,1013 @@ +//For my sanity :)) + +#define COOLANT_INPUT_GATE airs[1] +#define MODERATOR_INPUT_GATE airs[2] +#define COOLANT_OUTPUT_GATE airs[3] + +#define RBMK_TEMPERATURE_OPERATING 640 //Celsius +#define RBMK_TEMPERATURE_CRITICAL 800 //At this point the entire ship is alerted to a meltdown. This may need altering +#define RBMK_TEMPERATURE_MELTDOWN 900 + +#define RBMK_NO_COOLANT_TOLERANCE 5 //How many process()ing ticks the reactor can sustain without coolant before slowly taking damage + +#define RBMK_PRESSURE_OPERATING 1000 //PSI +#define RBMK_PRESSURE_CRITICAL 1469.59 //PSI + +#define RBMK_MAX_CRITICALITY 3 //No more criticality than N for now. + +#define RBMK_POWER_FLAVOURISER 8000 //To turn those KWs into something usable + +//Math. Lame. +#define KPA_TO_PSI(A) (A/6.895) +#define PSI_TO_KPA(A) (A*6.895) +#define KELVIN_TO_CELSIUS(A) (A-273.15) +#define MEGAWATTS /1e+6 +#define CELSIUS_TO_KELVIN(T_K) ((T_K) + T0C) + +//Reference: Heaters go up to 500K. +//Hot plasmaburn: 14164.95 C. + +/** + +What is this? + +Moderators list (Not gonna keep this accurate forever): +Fuel Type: +Oxygen: Power production multiplier. Allows you to run a low plasma, high oxy mix, and still get a lot of power. +Plasma: Power production gas. More plasma -> more power, but it enriches your fuel and makes the reactor much, much harder to control. +Tritium: Extremely efficient power production gas. Will cause chernobyl if used improperly. + +Moderation Type: +N2: Helps you regain control of the reaction by increasing control rod effectiveness, will massively boost the rad production of the reactor. +CO2: Super effective shutdown gas for runaway reactions. MASSIVE RADIATION PENALTY! +Pluoxium: Same as N2, but no cancer-rads! + +Permeability Type: +BZ: Increases your reactor's ability to transfer its heat to the coolant, thus letting you cool it down faster (but your output will get hotter) +Water Vapour: More efficient permeability modifier +Hyper Noblium: Extremely efficient permeability increase. (10x as efficient as bz) + +Depletion type: +Nitryl: When you need weapons grade plutonium yesterday. Causes your fuel to deplete much, much faster. Not a huge amount of use outside of sabotage. + +Sabotage: + +Meltdown: +Flood reactor moderator with plasma, they won't be able to mitigate the reaction with control rods. +Shut off coolant entirely. Raise control rods. +Swap all fuel out with spent fuel, as it's way stronger. + +Blowout: +Shut off exit valve for quick overpressure. +Cause a pipefire in the coolant line (LETHAL). +Tack heater onto coolant line (can also cause straight meltdown) + +Tips: +Be careful to not exhaust your plasma supply. I recommend you DON'T max out the moderator input when youre running plasma + o2, or you're at a tangible risk of running out of those gasses from atmos. +The reactor CHEWS through moderator. It does not do this slowly. Be very careful with that! + +*/ + +//Remember kids. If the reactor itself is not physically powered by an APC, it cannot shove coolant in! + +//Helper proc to set a new looping ambience, and play it to any mobs already inside of that area. + + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor + name = "\improper Advanced Gas-Cooled Nuclear Reactor" + desc = "A tried and tested design which can output stable power at an acceptably low risk. The moderator can be changed to provide different effects." + icon = 'icons/obj/machines/rbmk.dmi' + icon_state = "reactor_map" + pixel_x = -32 + pixel_y = -32 + density = FALSE //It burns you if you're stupid enough to walk over it. + anchored = TRUE + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF + light_color = LIGHT_COLOR_CYAN + dir = 8 //Less headache inducing :)) + var/id = null //Change me mappers + //Variables essential to operation + var/temperature = 0 //Lose control of this -> Meltdown + var/vessel_integrity = 400 //How long can the reactor withstand overpressure / meltdown? This gives you a fair chance to react to even a massive pipe fire + var/pressure = 0 //Lose control of this -> Blowout + var/K = 0 //Rate of reaction. + var/desired_k = 0 + var/control_rod_effectiveness = 0.65 //Starts off with a lot of control over K. If you flood this thing with plasma, you lose your ability to control K as easily. + var/power = 0 //0-100%. A function of the maximum heat you can achieve within operating temperature + var/power_modifier = 1 //Upgrade me with parts, science! Flat out increase to physical power output when loaded with plasma. + var/list/fuel_rods = list() + //Secondary variables. + var/next_slowprocess = 0 + var/gas_absorption_effectiveness = 0.5 + var/gas_absorption_constant = 0.5 //We refer to this one as it's set on init, randomized. + var/minimum_coolant_level = 5 + var/warning = FALSE //Have we begun warning the crew of their impending death? + var/next_warning = 0 //To avoid spam. + var/last_power_produced = 0 //For logging purposes + var/next_flicker = 0 //Light flicker timer + var/base_power_modifier = RBMK_POWER_FLAVOURISER + var/slagged = FALSE //Is this reactor even usable any more? + //Console statistics. + var/last_coolant_temperature = 0 + var/last_output_temperature = 0 + var/last_heat_delta = 0 //For administrative cheating only. Knowing the delta lets you know EXACTLY what to set K at. + var/no_coolant_ticks = 0 //How many times in succession did we not have enough coolant? Decays twice as fast as it accumulates. + var/last_user = null + var/current_desired_k = null + var/datum/powernet/powernet = null + +//Use this in your maps if you want everything to be preset. +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/preset + id = "default_reactor_for_lazy_mappers" + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/examine(mob/user) + . = ..() + if(Adjacent(src, user)) + if(do_after(user, 1 SECONDS, target=src)) + var/percent = vessel_integrity / initial(vessel_integrity) * 100 + var/msg = "The reactor looks operational." + switch(percent) + if(0 to 10) + msg = "[src]'s seals are dangerously warped and you can see cracks all over the reactor vessel! " + if(10 to 40) + msg = "[src]'s seals are heavily warped and cracked! " + if(40 to 60) + msg = "[src]'s seals are holding, but barely. You can see some micro-fractures forming in the reactor vessel." + if(60 to 80) + msg = "[src]'s seals are in-tact, but slightly worn. There are no visible cracks in the reactor vessel." + if(80 to 90) + msg = "[src]'s seals are in good shape, and there are no visible cracks in the reactor vessel." + if(95 to 100) + msg = "[src]'s seals look factory new, and the reactor's in excellent shape." + . += msg + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/fuel_rod)) + if(power >= 20) + to_chat(user, "You cannot insert fuel into [src] when it has been raised above 20% power.") + return FALSE + if(fuel_rods.len >= 5) + to_chat(user, "[src] is already at maximum fuel load.") + return FALSE + to_chat(user, "You start to insert [W] into [src]...") + radiation_pulse(src, temperature) + if(do_after(user, 5 SECONDS, target=src)) + if(!fuel_rods.len) + start_up() //That was the first fuel rod. Let's heat it up. + message_admins("Reactor first started up by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]") + investigate_log("Reactor first started by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_SINGULO) + fuel_rods += W + W.forceMove(src) + radiation_pulse(src, temperature) //Wear protective equipment when even breathing near a reactor! + investigate_log("Rod added to reactor by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_SINGULO) + return TRUE + if(istype(W, /obj/item/sealant)) + if(power >= 20) + to_chat(user, "You cannot repair [src] while it is running at above 20% power.") + return FALSE + if(vessel_integrity >= 350) + to_chat(user, "[src]'s seals are already in-tact, repairing them further would require a new set of seals.") + return FALSE + if(vessel_integrity <= 0.5 * initial(vessel_integrity)) //Heavily damaged. + to_chat(user, "[src]'s reactor vessel is cracked and worn, you need to repair the cracks with a welder before you can repair the seals.") + return FALSE + if(do_after(user, 5 SECONDS, target=src)) + if(vessel_integrity >= 350) //They might've stacked doafters + to_chat(user, "[src]'s seals are already in-tact, repairing them further would require a new set of seals.") + return FALSE + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) + user.visible_message("[user] applies sealant to some of [src]'s worn out seals.", "You apply sealant to some of [src]'s worn out seals.") + vessel_integrity += 10 + vessel_integrity = clamp(vessel_integrity, 0, initial(vessel_integrity)) + return TRUE + return ..() + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/welder_act(mob/living/user, obj/item/I) + if(power >= 20) + to_chat(user, "You can't repair [src] while it is running at above 20% power.") + return FALSE + if(vessel_integrity > 0.5 * initial(vessel_integrity)) + to_chat(user, "[src] is free from cracks. Further repairs must be carried out with flexi-seal sealant.") + return FALSE + if(I.use_tool(src, user, 0, volume=40)) + if(vessel_integrity > 0.5 * initial(vessel_integrity)) + to_chat(user, "[src] is free from cracks. Further repairs must be carried out with flexi-seal sealant.") + return FALSE + vessel_integrity += 20 + to_chat(user, "You weld together some of [src]'s cracks. This'll do for now.") + return TRUE + +//Admin procs to mess with the reaction environment. + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/lazy_startup() + for(var/I=0;I<5;I++) + fuel_rods += new /obj/item/fuel_rod(src) + message_admins("Reactor started up by admins in [ADMIN_VERBOSEJMP(src)]") + start_up() + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/deplete() + for(var/obj/item/fuel_rod/FR in fuel_rods) + FR.depletion = 100 + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/Initialize() + . = ..() + connect_to_network() + icon_state = "reactor_off" + gas_absorption_effectiveness = rand(5, 6)/10 //All reactors are slightly different. This will result in you having to figure out what the balance is for K. + gas_absorption_constant = gas_absorption_effectiveness //And set this up for the rest of the round. + STOP_PROCESSING(SSmachines, src) //We'll handle this one ourselves. + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/Crossed(atom/movable/AM, oldloc) + . = ..() + if(isliving(AM) && temperature > 0) + var/mob/living/L = AM + L.adjust_bodytemperature(clamp(temperature, BODYTEMP_COOLING_MAX, BODYTEMP_HEATING_MAX)) //If you're on fire, you heat up! + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/process() + update_parents() //Update the pipenet to register new gas mixes + if(next_slowprocess < world.time) + slowprocess() + next_slowprocess = world.time + 1 SECONDS //Set to wait for another second before processing again, we don't need to process more than once a second + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/has_fuel() + return length(fuel_rods) + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/slowprocess() + //Let's get our gasses sorted out. + var/datum/gas_mixture/coolant_input = COOLANT_INPUT_GATE + var/datum/gas_mixture/moderator_input = MODERATOR_INPUT_GATE + var/datum/gas_mixture/coolant_output = COOLANT_OUTPUT_GATE + + //Firstly, heat up the reactor based off of K. + var/input_moles = coolant_input.total_moles() //Firstly. Do we have enough moles of coolant? + if(input_moles >= minimum_coolant_level) + last_coolant_temperature = KELVIN_TO_CELSIUS(coolant_input.return_temperature()) + //Important thing to remember, once you slot in the fuel rods, this thing will not stop making heat, at least, not unless you can live to be thousands of years old which is when the spent fuel finally depletes fully. + var/heat_delta = (KELVIN_TO_CELSIUS(coolant_input.return_temperature()) / 100) * gas_absorption_effectiveness //Take in the gas as a cooled input, cool the reactor a bit. The optimum, 100% balanced reaction sits at K=1, coolant input temp of 200K / -73 celsius. + last_heat_delta = heat_delta + temperature += heat_delta + coolant_output.merge(coolant_input) //And now, shove the input into the output. + coolant_input.clear() //Clear out anything left in the input gate. + color = null + no_coolant_ticks = max(0, no_coolant_ticks-2) //Needs half as much time to recover the ticks than to acquire them + else + if(has_fuel()) + no_coolant_ticks++ + if(no_coolant_ticks > RBMK_NO_COOLANT_TOLERANCE) + temperature += temperature / 500 //This isn't really harmful early game, but when your reactor is up to full power, this can get out of hand quite quickly. + vessel_integrity -= temperature / 200 //Think fast loser. + take_damage(10) //Just for the sound effect, to let you know you've fucked up. + color = "[COLOR_RED]" + investigate_log("Reactor taking damage from the lack of coolant", INVESTIGATE_SINGULO) + //Now, heat up the output and set our pressure. + coolant_output.set_temperature(CELSIUS_TO_KELVIN(temperature)) //Heat the coolant output gas that we just had pass through us. + last_output_temperature = KELVIN_TO_CELSIUS(coolant_output.return_temperature()) + pressure = KPA_TO_PSI(coolant_output.return_pressure()) + power = (temperature / RBMK_TEMPERATURE_CRITICAL) * 100 + var/radioactivity_spice_multiplier = 1 //Some gasses make the reactor a bit spicy. + var/depletion_modifier = 0.035 //How rapidly do your rods decay + gas_absorption_effectiveness = gas_absorption_constant + //Next up, handle moderators! + if(moderator_input.total_moles() >= minimum_coolant_level) + var/total_fuel_moles = moderator_input.get_moles(/datum/gas/plasma) + (moderator_input.get_moles(/datum/gas/tritium)*10) //Constricted plasma is 50% more efficient as fuel than plasma, but we dont have it :) + var/power_modifier = max((moderator_input.get_moles(/datum/gas/oxygen) / moderator_input.total_moles() * 10), 1) //You can never have negative IPM. For now. + if(total_fuel_moles >= minimum_coolant_level) //You at least need SOME fuel. + var/power_produced = max((total_fuel_moles / moderator_input.total_moles() * 10), 1) + last_power_produced = max(0,((power_produced*power_modifier)*moderator_input.total_moles())) + last_power_produced *= (max(0,power)/100) //Aaaand here comes the cap. Hotter reactor => more power. + last_power_produced *= base_power_modifier //Finally, we turn it into actual usable numbers. + radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/tritium) / 5 //Chernobyl 2. + var/turf/T = get_turf(src) + if(power >= 20) + coolant_output.adjust_moles(/datum/gas/nitryl, total_fuel_moles/20) //Shove out nitryl into the air when it's fuelled. You need to filter this off, or you're gonna have a bad time. + var/obj/structure/cable/C = T.get_cable_node() + if(!C?.powernet) + return + else + add_avail(last_power_produced) + var/total_control_moles = moderator_input.get_moles(/datum/gas/nitrogen) + (moderator_input.get_moles(/datum/gas/carbon_dioxide)*2) + (moderator_input.get_moles(/datum/gas/pluoxium)*3) //N2 helps you control the reaction at the cost of making it absolutely blast you with rads. Pluoxium has the same effect but without the rads! + if(total_control_moles >= minimum_coolant_level) + var/control_bonus = total_control_moles / 250 //1 mol of n2 -> 0.002 bonus control rod effectiveness, if you want a super controlled reaction, you'll have to sacrifice some power. + control_rod_effectiveness = initial(control_rod_effectiveness) + control_bonus + radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/nitrogen) / 25 //An example setup of 50 moles of n2 (for dealing with spent fuel) leaves us with a radioactivity spice multiplier of 3. + radioactivity_spice_multiplier += moderator_input.get_moles(/datum/gas/carbon_dioxide) / 12.5 + var/total_permeability_moles = moderator_input.get_moles(/datum/gas/bz) + (moderator_input.get_moles(/datum/gas/water_vapor)*2) + (moderator_input.get_moles(/datum/gas/hypernoblium)*10) + if(total_permeability_moles >= minimum_coolant_level) + var/permeability_bonus = total_permeability_moles / 500 + gas_absorption_effectiveness = gas_absorption_constant + permeability_bonus + var/total_degradation_moles = moderator_input.get_moles(/datum/gas/nitryl) //Because it's quite hard to get. + if(total_degradation_moles >= minimum_coolant_level*0.5) //I'll be nice. + depletion_modifier += total_degradation_moles / 15 //Oops! All depletion. This causes your fuel rods to get SPICY. + playsound(src, pick('sound/machines/sm/accent/normal/1.ogg','sound/machines/sm/accent/normal/2.ogg','sound/machines/sm/accent/normal/3.ogg','sound/machines/sm/accent/normal/4.ogg','sound/machines/sm/accent/normal/5.ogg'), 100, TRUE) + //From this point onwards, we clear out the remaining gasses. + moderator_input.clear() //Woosh. And the soul is gone. + K += total_fuel_moles / 1000 + var/fuel_power = 0 //So that you can't magically generate K with your control rods. + if(!has_fuel()) //Reactor must be fuelled and ready to go before we can heat it up boys. + K = 0 + else + for(var/obj/item/fuel_rod/FR in fuel_rods) + K += FR.fuel_power + fuel_power += FR.fuel_power + FR.deplete(depletion_modifier) + //Firstly, find the difference between the two numbers. + var/difference = abs(K - desired_k) + //Then, hit as much of that goal with our cooling per tick as we possibly can. + difference = clamp(difference, 0, control_rod_effectiveness) //And we can't instantly zap the K to what we want, so let's zap as much of it as we can manage.... + if(difference > fuel_power && desired_k > K) + message_admins("Not enough fuel to get [difference]. We have fuel [fuel_power]") + investigate_log("Reactor has not enough fuel to get [difference]. We have fuel [fuel_power]", INVESTIGATE_SINGULO) + difference = fuel_power //Again, to stop you being able to run off of 1 fuel rod. + if(K != desired_k) + if(desired_k > K) + K += difference + else if(desired_k < K) + K -= difference + if(K == desired_k && last_user && current_desired_k != desired_k) + current_desired_k = desired_k + message_admins("Reactor desired criticality set to [desired_k] by [ADMIN_LOOKUPFLW(last_user)] in [ADMIN_VERBOSEJMP(src)]") + investigate_log("reactor desired criticality set to [desired_k] by [key_name(last_user)] at [AREACOORD(src)]", INVESTIGATE_SINGULO) + K = clamp(K, 0, RBMK_MAX_CRITICALITY) + if(has_fuel()) + temperature += K + else + temperature -= 10 //Nothing to heat us up, so. + handle_alerts() //Let's check if they're about to die, and let them know. + update_icon() + radiation_pulse(src, temperature*radioactivity_spice_multiplier) + if(power >= 90 && world.time >= next_flicker) //You're overloading the reactor. Give a more subtle warning that power is getting out of control. + next_flicker = world.time + 1.5 MINUTES + for(var/obj/machinery/light/L in GLOB.machines) + if(prob(25) && L.z == z) //If youre running the reactor cold though, no need to flicker the lights. + L.flicker() + investigate_log("Reactor overloading at [power]% power", INVESTIGATE_SINGULO) + for(var/atom/movable/I in get_turf(src)) + if(isliving(I)) + var/mob/living/L = I + if(temperature > 0) + L.adjust_bodytemperature(clamp(temperature, BODYTEMP_COOLING_MAX, BODYTEMP_HEATING_MAX)) //If you're on fire, you heat up! + if(istype(I, /obj/item/reagent_containers/food) && !istype(I, /obj/item/reagent_containers/food/drinks)) + playsound(src, pick('sound/machines/fryer/deep_fryer_1.ogg', 'sound/machines/fryer/deep_fryer_2.ogg'), 100, TRUE) + var/obj/item/reagent_containers/food/grilled_item = I + if(prob(80)) + return //To give the illusion that it's actually cooking omegalul. + switch(power) + if(20 to 39) + grilled_item.name = "grilled [initial(grilled_item.name)]" + grilled_item.desc = "[initial(I.desc)] It's been grilled over a nuclear reactor." + if(!(grilled_item.foodtype & FRIED)) + grilled_item.foodtype |= FRIED + if(40 to 70) + grilled_item.name = "heavily grilled [initial(grilled_item.name)]" + grilled_item.desc = "[initial(I.desc)] It's been heavily grilled through the magic of nuclear fission." + if(!(grilled_item.foodtype & FRIED)) + grilled_item.foodtype |= FRIED + if(70 to 95) + grilled_item.name = "Three-Mile Nuclear-Grilled [initial(grilled_item.name)]" + grilled_item.desc = "A [initial(grilled_item.name)]. It's been put on top of a nuclear reactor running at extreme power by some badass engineer." + if(!(grilled_item.foodtype & FRIED)) + grilled_item.foodtype |= FRIED + if(95 to INFINITY) + grilled_item.name = "Ultimate Meltdown Grilled [initial(grilled_item.name)]" + grilled_item.desc = "A [initial(grilled_item.name)]. A grill this perfect is a rare technique only known by a few engineers who know how to perform a 'controlled' meltdown whilst also having the time to throw food on a reactor. I'll bet it tastes amazing." + if(!(grilled_item.foodtype & FRIED)) + grilled_item.foodtype |= FRIED + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/relay(var/sound, var/message=null, loop = FALSE, channel = null) //Sends a sound + text message to the crew of a ship + for(var/mob/M in GLOB.player_list) + if(M.z == z) + if(!isinspace(M)) + if(sound) + if(channel) //Doing this forbids overlapping of sounds + SEND_SOUND(M, sound(sound, repeat = loop, wait = 0, volume = 70, channel = channel)) + else + SEND_SOUND(M, sound(sound, repeat = loop, wait = 0, volume = 70)) + if(message) + to_chat(M, message) + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/stop_relay(channel) //Stops all playing sounds for crewmen on N channel. + for(var/mob/M in GLOB.player_list) + if(M.z == z) + M.stop_sound_channel(channel) + +//Method to handle sound effects, reactor warnings, all that jazz. +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/handle_alerts() + var/alert = FALSE //If we have an alert condition, we'd best let people know. + if(K <= 0 && temperature <= 0) + shut_down() + //First alert condition: Overheat + if(temperature >= RBMK_TEMPERATURE_CRITICAL) + alert = TRUE + investigate_log("Reactor reaching critical temperature at [temperature] C with desired criticality at [desired_k]", INVESTIGATE_SINGULO) + message_admins("Reactor reaching critical temperature at [ADMIN_VERBOSEJMP(src)]") + if(temperature >= RBMK_TEMPERATURE_MELTDOWN) + var/temp_damage = min(temperature/100, initial(vessel_integrity)/40) //40 seconds to meltdown from full integrity, worst-case. Bit less than blowout since it's harder to spike heat that much. + vessel_integrity -= temp_damage + if(vessel_integrity <= temp_damage) + investigate_log("Reactor melted down at [temperature] C with desired criticality at [desired_k]", INVESTIGATE_SINGULO) //It wouldn't be able to tank another hit. + meltdown() //Oops! All meltdown + return + else + alert = FALSE + if(temperature < -200) //That's as cold as I'm letting you get it, engineering. + color = COLOR_CYAN + temperature = -200 + else + color = null + //Second alert condition: Overpressurized (the more lethal one) + if(pressure >= RBMK_PRESSURE_CRITICAL) + alert = TRUE + investigate_log("Reactor reaching critical pressure at [pressure] PSI with desired criticality at [desired_k]", INVESTIGATE_SINGULO) + message_admins("Reactor reaching critical pressure at [ADMIN_VERBOSEJMP(src)]") + shake_animation(0.5) + playsound(loc, 'sound/machines/clockcult/steam_whoosh.ogg', 100, TRUE) + var/turf/T = get_turf(src) + T.atmos_spawn_air("water_vapor=[pressure/100];TEMP=[CELSIUS_TO_KELVIN(temperature)]") + var/pressure_damage = min(pressure/100, initial(vessel_integrity)/45) //You get 45 seconds (if you had full integrity), worst-case. But hey, at least it can't be instantly nuked with a pipe-fire.. though it's still very difficult to save. + vessel_integrity -= pressure_damage + if(vessel_integrity <= pressure_damage) //It wouldn't be able to tank another hit. + investigate_log("Reactor blowout at [pressure] PSI with desired criticality at [desired_k]", INVESTIGATE_SINGULO) + blowout() + return + if(warning) + if(!alert) //Congrats! You stopped the meltdown / blowout. + stop_relay(CHANNEL_REACTOR_ALERT) + warning = FALSE + set_light(0) + light_color = LIGHT_COLOR_CYAN + set_light(10) + else + if(!alert) + return + if(world.time < next_warning) + return + next_warning = world.time + 30 SECONDS //To avoid engis pissing people off when reaaaally trying to stop the meltdown or whatever. + warning = TRUE //Start warning the crew of the imminent danger. + relay('sound/effects/reactor/alarm.ogg', null, loop=TRUE, channel = CHANNEL_REACTOR_ALERT) + set_light(0) + light_color = LIGHT_COLOR_RED + set_light(10) + +//Failure condition 1: Meltdown. Achieved by having heat go over tolerances. This is less devastating because it's easier to achieve. +//Results: Engineering becomes unusable and your engine irreparable +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/meltdown() + set waitfor = FALSE + SSair.atmos_machinery -= src //Annd we're now just a useless brick. + slagged = TRUE + color = null + update_icon() + STOP_PROCESSING(SSmachines, src) + icon_state = "reactor_slagged" + AddComponent(/datum/component/radioactive, 15000 , src, 0) + var/obj/effect/landmark/nuclear_waste_spawner/NSW = new /obj/effect/landmark/nuclear_waste_spawner/strong(get_turf(src)) + relay('sound/effects/reactor/meltdown.ogg', "You hear a horrible metallic hissing.") + stop_relay(CHANNEL_REACTOR_ALERT) + NSW.fire() //This will take out engineering for a decent amount of time as they have to clean up the sludge. + for(var/obj/machinery/power/apc/apc in GLOB.apcs_list) + if((apc.z == z) && prob(70)) + apc.overload_lighting() + var/datum/gas_mixture/coolant_input = COOLANT_INPUT_GATE + var/datum/gas_mixture/moderator_input = MODERATOR_INPUT_GATE + var/datum/gas_mixture/coolant_output = COOLANT_OUTPUT_GATE + var/turf/T = get_turf(src) + coolant_input.set_temperature(CELSIUS_TO_KELVIN(temperature)*2) + moderator_input.set_temperature(CELSIUS_TO_KELVIN(temperature)*2) + coolant_output.set_temperature(CELSIUS_TO_KELVIN(temperature)*2) + T.assume_air(coolant_input) + T.assume_air(moderator_input) + T.assume_air(coolant_output) + explosion(get_turf(src), 0, 5, 10, 20, TRUE, TRUE) + empulse(get_turf(src), 25, 15) + +//Failure condition 2: Blowout. Achieved by reactor going over-pressured. This is a round-ender because it requires more fuckery to achieve. +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/blowout() + explosion(get_turf(src), GLOB.MAX_EX_DEVESTATION_RANGE, GLOB.MAX_EX_HEAVY_RANGE, GLOB.MAX_EX_LIGHT_RANGE, GLOB.MAX_EX_FLASH_RANGE) + meltdown() //Double kill. + relay('sound/effects/reactor/explode.ogg') + SSweather.run_weather("nuclear fallout") + for(var/X in GLOB.landmarks_list) + if(istype(X, /obj/effect/landmark/nuclear_waste_spawner)) + var/obj/effect/landmark/nuclear_waste_spawner/WS = X + if(is_station_level(WS.z)) //Begin the SLUDGING + WS.fire() + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/update_icon() + icon_state = "reactor_off" + switch(temperature) + if(0 to 200) + icon_state = "reactor_on" + if(200 to RBMK_TEMPERATURE_OPERATING) + icon_state = "reactor_hot" + if(RBMK_TEMPERATURE_OPERATING to 750) + icon_state = "reactor_veryhot" + if(750 to RBMK_TEMPERATURE_CRITICAL) //Point of no return. + icon_state = "reactor_overheat" + if(RBMK_TEMPERATURE_CRITICAL to INFINITY) + icon_state = "reactor_meltdown" + if(!has_fuel()) + icon_state = "reactor_off" + if(slagged) + icon_state = "reactor_slagged" + + +//Startup, shutdown + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/start_up() + START_PROCESSING(SSmachines, src) + desired_k = 1 + set_light(10) + var/startup_sound = pick('sound/effects/reactor/startup.ogg', 'sound/effects/reactor/startup2.ogg') + playsound(loc, startup_sound, 100) + if(!powernet) + message_admins("No powernet for the Nuclear Reactor! Trying to add.") + connect_to_network() + if(!powernet) + message_admins("Powernet add fail. This reactor will never produce power.") + +//Shuts off the fuel rods, ambience, etc. Keep in mind that your temperature may still go up! +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/shut_down() + STOP_PROCESSING(SSmachines, src) + set_light(0) + K = 0 + desired_k = 0 + temperature = 0 + update_icon() + +/obj/item/fuel_rod/Initialize() + .=..() + AddComponent(/datum/component/radioactive, 350 , src) + +//Controlling the reactor. + +/obj/machinery/computer/reactor + name = "Reactor control console" + desc = "Scream" + light_color = "#55BA55" + light_power = 1 + light_range = 3 + icon_state = "oldcomp" + icon_screen = "library" + icon_keyboard = null + var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/reactor = null + var/id = "default_reactor_for_lazy_mappers" + +/obj/machinery/computer/reactor/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + addtimer(CALLBACK(src, .proc/link_to_reactor), 10 SECONDS) + +/obj/machinery/computer/reactor/wrench_act(mob/living/user, obj/item/I) + to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") + if(I.use_tool(src, user, 40, volume=75)) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + setAnchored(!anchored) + return TRUE + return FALSE + +/obj/machinery/computer/reactor/proc/link_to_reactor() + for(var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/asdf in GLOB.machines) + if(asdf.id && asdf.id == id) + reactor = asdf + return TRUE + return FALSE + +#define FREQ_RBMK_CONTROL 1439.69 + +/obj/machinery/computer/reactor/control_rods + name = "Control rod management computer" + desc = "A computer which can remotely raise / lower the control rods of a reactor." + icon_screen = "rbmk_rods" + +/obj/machinery/computer/reactor/control_rods/attack_hand(mob/living/user) + . = ..() + ui_interact(user) + +/obj/machinery/computer/reactor/control_rods/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "RbmkControlRods") + ui.open() + ui.set_autoupdate(TRUE) + +/obj/machinery/computer/reactor/control_rods/ui_act(action, params) + if(..()) + return + if(!reactor) + return + if(action == "input") + var/input = text2num(params["target"]) + reactor.last_user = usr + reactor.desired_k = clamp(input, 0, 3) + +/obj/machinery/computer/reactor/control_rods/ui_data(mob/user) + var/list/data = list() + data["control_rods"] = 0 + data["k"] = 0 + data["desiredK"] = 0 + if(reactor) + data["k"] = reactor.K + data["desiredK"] = reactor.desired_k + data["control_rods"] = 100 - (reactor.desired_k / 3 * 100) //Rod insertion is extrapolated as a function of the percentage of K + return data + +/obj/machinery/computer/reactor/stats + name = "Reactor Statistics Console" + desc = "A console for monitoring the statistics of a nuclear reactor." + icon_screen = "rbmk_stats" + var/next_stat_interval = 0 + var/list/psiData = list() + var/list/powerData = list() + var/list/tempInputData = list() + var/list/tempOutputdata = list() + +/obj/machinery/computer/reactor/stats/attack_hand(mob/living/user) + . = ..() + ui_interact(user) + +/obj/machinery/computer/reactor/stats/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "RbmkStats") + ui.open() + ui.set_autoupdate(TRUE) + +/obj/machinery/computer/reactor/stats/process() + if(world.time >= next_stat_interval) + next_stat_interval = world.time + 1 SECONDS //You only get a slow tick. + psiData += (reactor) ? reactor.pressure : 0 + if(psiData.len > 100) //Only lets you track over a certain timeframe. + psiData.Cut(1, 2) + powerData += (reactor) ? reactor.power*10 : 0 //We scale up the figure for a consistent:tm: scale + if(powerData.len > 100) //Only lets you track over a certain timeframe. + powerData.Cut(1, 2) + tempInputData += (reactor) ? reactor.last_coolant_temperature : 0 //We scale up the figure for a consistent:tm: scale + if(tempInputData.len > 100) //Only lets you track over a certain timeframe. + tempInputData.Cut(1, 2) + tempOutputdata += (reactor) ? reactor.last_output_temperature : 0 //We scale up the figure for a consistent:tm: scale + if(tempOutputdata.len > 100) //Only lets you track over a certain timeframe. + tempOutputdata.Cut(1, 2) + +/obj/machinery/computer/reactor/stats/ui_data(mob/user) + var/list/data = list() + data["powerData"] = powerData + data["psiData"] = psiData + data["tempInputData"] = tempInputData + data["tempOutputdata"] = tempOutputdata + data["coolantInput"] = reactor ? reactor.last_coolant_temperature : 0 + data["coolantOutput"] = reactor ? reactor.last_output_temperature : 0 + data["power"] = reactor ? reactor.power : 0 + data ["psi"] = reactor ? reactor.pressure : 0 + return data + +/obj/machinery/computer/reactor/fuel_rods + name = "Reactor Fuel Management Console" + desc = "A console which can remotely raise fuel rods out of nuclear reactors." + icon_screen = "rbmk_fuel" + +/obj/machinery/computer/reactor/fuel_rods/attack_hand(mob/living/user) + . = ..() + if(!reactor) + return FALSE + if(reactor.power > 20) + to_chat(user, "You cannot remove fuel from [reactor] when it is above 20% power.") + return FALSE + if(!reactor.fuel_rods.len) + to_chat(user, "[reactor] does not have any fuel rods loaded.") + return FALSE + var/atom/movable/fuel_rod = input(usr, "Select a fuel rod to remove", "[src]", null) as null|anything in reactor.fuel_rods + if(!fuel_rod) + return + playsound(src, pick('sound/effects/reactor/switch.ogg','sound/effects/reactor/switch2.ogg','sound/effects/reactor/switch3.ogg'), 100, FALSE) + playsound(reactor, 'sound/effects/reactor/crane_1.wav', 100, FALSE) + fuel_rod.forceMove(get_turf(reactor)) + reactor.fuel_rods -= fuel_rod + +//Preset pumps for mappers. You can also set the id tags yourself. +/obj/machinery/atmospherics/components/binary/pump/rbmk_input + id = "rbmk_input" + frequency = FREQ_RBMK_CONTROL + +/obj/machinery/atmospherics/components/binary/pump/rbmk_output + id = "rbmk_output" + frequency = FREQ_RBMK_CONTROL + +/obj/machinery/atmospherics/components/binary/pump/rbmk_moderator + id = "rbmk_moderator" + frequency = FREQ_RBMK_CONTROL + +/obj/machinery/computer/reactor/pump + name = "Reactor inlet valve computer" + desc = "A computer which controls valve settings on an advanced gas cooled reactor. Alt click it to remotely set pump pressure." + icon_screen = "rbmk_input" + id = "rbmk_input" + var/datum/radio_frequency/radio_connection + var/on = FALSE + +/obj/machinery/computer/reactor/pump/AltClick(mob/user) + . = ..() + var/newPressure = input(user, "Set new output pressure (kPa)", "Remote pump control", null) as num + if(!newPressure) + return + newPressure = clamp(newPressure, 0, MAX_OUTPUT_PRESSURE) //Number sanitization is not handled in the pumps themselves, only during their ui_act which this doesn't use. + signal(on, newPressure) + +/obj/machinery/computer/reactor/attack_robot(mob/user) + . = ..() + attack_hand(user) + +/obj/machinery/computer/reactor/attack_ai(mob/user) + . = ..() + attack_hand(user) + +/obj/machinery/computer/reactor/pump/attack_hand(mob/living/user) + . = ..() + if(!is_operational()) + return FALSE + playsound(loc, pick('sound/effects/reactor/switch.ogg','sound/effects/reactor/switch2.ogg','sound/effects/reactor/switch3.ogg'), 100, FALSE) + visible_message("[src]'s switch flips [on ? "off" : "on"].") + on = !on + signal(on) + +/obj/machinery/computer/reactor/pump/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + radio_connection = SSradio.add_object(src, FREQ_RBMK_CONTROL,filter=RADIO_ATMOSIA) + +/obj/machinery/computer/reactor/pump/proc/signal(power, set_output_pressure=null) + var/datum/signal/signal + if(!set_output_pressure) //Yes this is stupid, but technically if you pass through "set_output_pressure" onto the signal, it'll always try and set its output pressure and yeahhh... + signal = new(list( + "tag" = id, + "frequency" = FREQ_RBMK_CONTROL, + "timestamp" = world.time, + "power" = power, + "sigtype" = "command" + )) + else + signal = new(list( + "tag" = id, + "frequency" = FREQ_RBMK_CONTROL, + "timestamp" = world.time, + "power" = power, + "set_output_pressure" = set_output_pressure, + "sigtype" = "command" + )) + radio_connection.post_signal(src, signal, filter=RADIO_ATMOSIA) + +//Preset subtypes for mappers +/obj/machinery/computer/reactor/pump/rbmk_input + name = "Reactor inlet valve computer" + icon_screen = "rbmk_input" + id = "rbmk_input" + +/obj/machinery/computer/reactor/pump/rbmk_output + name = "Reactor output valve computer" + icon_screen = "rbmk_output" + id = "rbmk_output" + +/obj/machinery/computer/reactor/pump/rbmk_moderator + name = "Reactor moderator valve computer" + icon_screen = "rbmk_moderator" + id = "rbmk_moderator" + +//Monitoring program. +/datum/computer_file/program/nuclear_monitor + filename = "rbmkmonitor" + filedesc = "Nuclear Reactor Monitoring" + ui_header = "smmon_0.gif" + program_icon_state = "smmon_0" + extended_desc = "This program connects to specially calibrated sensors to provide information on the status of nuclear reactors." + requires_ntnet = TRUE + transfer_access = ACCESS_CONSTRUCTION + //network_destination = "rbmk monitoring system" dont need anymore? + size = 2 + tgui_id = "NtosRbmkStats" + var/active = TRUE //Easy process throttle + var/next_stat_interval = 0 + var/list/psiData = list() + var/list/powerData = list() + var/list/tempInputData = list() + var/list/tempOutputdata = list() + var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/reactor //Our reactor. + +/datum/computer_file/program/nuclear_monitor/process_tick() + ..() + if(!reactor || !active) + return FALSE + var/stage = 0 + //This is dirty but i'm lazy wahoo! + if(reactor.power > 0) + stage = 1 + if(reactor.power >= 40) + stage = 2 + if(reactor.temperature >= RBMK_TEMPERATURE_OPERATING) + stage = 3 + if(reactor.temperature >= RBMK_TEMPERATURE_CRITICAL) + stage = 4 + if(reactor.temperature >= RBMK_TEMPERATURE_MELTDOWN) + stage = 5 + if(reactor.vessel_integrity <= 100) //Bye bye! GET OUT! + stage = 6 + ui_header = "smmon_[stage].gif" + program_icon_state = "smmon_[stage]" + if(istype(computer)) + computer.update_icon() + if(world.time >= next_stat_interval) + next_stat_interval = world.time + 1 SECONDS //You only get a slow tick. + psiData += (reactor) ? reactor.pressure : 0 + if(psiData.len > 100) //Only lets you track over a certain timeframe. + psiData.Cut(1, 2) + powerData += (reactor) ? reactor.power*10 : 0 //We scale up the figure for a consistent:tm: scale + if(powerData.len > 100) //Only lets you track over a certain timeframe. + powerData.Cut(1, 2) + tempInputData += (reactor) ? reactor.last_coolant_temperature : 0 //We scale up the figure for a consistent:tm: scale + if(tempInputData.len > 100) //Only lets you track over a certain timeframe. + tempInputData.Cut(1, 2) + tempOutputdata += (reactor) ? reactor.last_output_temperature : 0 //We scale up the figure for a consistent:tm: scale + if(tempOutputdata.len > 100) //Only lets you track over a certain timeframe. + tempOutputdata.Cut(1, 2) + +/datum/computer_file/program/nuclear_monitor/run_program(mob/living/user) + . = ..(user) + //No reactor? Go find one then. + if(!reactor) + for(var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/R in GLOB.machines) + if(R.z == usr.z) + reactor = R + break + active = TRUE + +/datum/computer_file/program/nuclear_monitor/kill_program(forced = FALSE) + active = FALSE + ..() + +/datum/computer_file/program/nuclear_monitor/ui_data() + var/list/data = get_header_data() + data["powerData"] = powerData + data["psiData"] = psiData + data["tempInputData"] = tempInputData + data["tempOutputdata"] = tempOutputdata + data["coolantInput"] = reactor ? reactor.last_coolant_temperature : 0 + data["coolantOutput"] = reactor ? reactor.last_output_temperature : 0 + data["power"] = reactor ? reactor.power : 0 + data ["psi"] = reactor ? reactor.pressure : 0 + return data + +/datum/computer_file/program/nuclear_monitor/ui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("swap_reactor") + var/list/choices = list() + for(var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/R in GLOB.machines) + if(R.z != usr.z) + continue + choices += R + reactor = input(usr, "What reactor do you wish to monitor?", "[src]", null) as null|anything in choices + powerData = list() + psiData = list() + tempInputData = list() + tempOutputdata = list() + return TRUE + +/obj/effect/decal/nuclear_waste + name = "Plutonium sludge" + desc = "A writhing pool of heavily irradiated, spent reactor fuel. You probably shouldn't step through this..." + icon = 'icons/obj/machines/reactor_parts.dmi' + icon_state = "nuclearwaste" + alpha = 150 + light_color = LIGHT_COLOR_CYAN + color = "#ff9eff" + +/obj/effect/decal/nuclear_waste/Initialize() + . = ..() + for(var/obj/A in get_turf(src)) + if(istype(A, /obj/structure)) + qdel(src) //It is more processing efficient to do this here rather than when searching for available turfs. + set_light(3) + AddComponent(/datum/component/radioactive, 1000, src, 0) + +/obj/effect/decal/nuclear_waste/epicenter //The one that actually does the irradiating. This is to avoid every bit of sludge PROCESSING + name = "Dense nuclear sludge" + +/obj/effect/landmark/nuclear_waste_spawner //Clean way of spawning nuclear gunk after a reactor core meltdown. + name = "Nuclear waste spawner" + var/range = 5 //5 tile radius to spawn goop + +/obj/effect/landmark/nuclear_waste_spawner/strong + range = 10 + +/obj/effect/landmark/nuclear_waste_spawner/proc/fire() + playsound(loc, 'sound/effects/gib_step.ogg', 100) + new /obj/effect/decal/nuclear_waste/epicenter(get_turf(src)) + for(var/turf/open/floor in orange(range, get_turf(src))) + if(prob(35)) //Scatter the sludge, don't smear it everywhere + new /obj/effect/decal/nuclear_waste (floor) + qdel(src) + +/obj/effect/decal/nuclear_waste/epicenter/Initialize() + . = ..() + +/obj/effect/decal/nuclear_waste/Crossed(atom/movable/AM) + . = ..() + if(isliving(AM)) + var/mob/living/L = AM + playsound(loc, 'sound/effects/gib_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 20 : 50, 1) + radiation_pulse(src, 500, 5) //MORE RADS + +/obj/effect/decal/nuclear_waste/attackby(obj/item/tool, mob/user) + if(tool.tool_behaviour == TOOL_SHOVEL) + radiation_pulse(src, 1000, 5) //MORE RADS + to_chat(user, "You start to clear [src]...") + if(tool.use_tool(src, user, 50, volume=100)) + to_chat(user, "You clear [src]. ") + qdel(src) + return + . = ..() + +/datum/weather/nuclear_fallout + name = "nuclear fallout" + desc = "Irradiated dust falls down everywhere." + telegraph_duration = 50 + telegraph_message = "The air suddenly becomes dusty.." + weather_message = "You feel a wave of hot ash fall down on you." + weather_overlay = "light_ash" + telegraph_overlay = "light_snow" + weather_duration_lower = 600 + weather_duration_upper = 1500 + weather_color = "green" + telegraph_sound = null + weather_sound = 'sound/effects/reactor/falloutwind.ogg' + end_duration = 100 + area_type = /area + protected_areas = list(/area/maintenance, /area/ai_monitored/turret_protected/ai_upload, /area/ai_monitored/turret_protected/ai_upload_foyer, + /area/ai_monitored/turret_protected/ai, /area/shuttle) + target_trait = ZTRAIT_STATION + end_message = "The ash stops falling." + immunity_type = "rad" + +/datum/weather/nuclear_fallout/weather_act(mob/living/L) + L.rad_act(100) + +/datum/weather/nuclear_fallout/telegraph() + ..() + status_alarm(TRUE) + +/datum/weather/nuclear_fallout/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement. + var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) + if(!frequency) + return + + var/datum/signal/signal = new + if (active) + signal.data["command"] = "alert" + signal.data["picture_state"] = "radiation" + else + signal.data["command"] = "shuttle" + + var/atom/movable/virtualspeaker/virt = new(null) + frequency.post_signal(virt, signal) + +/datum/weather/nuclear_fallout/end() + if(..()) + return + status_alarm(FALSE) + +/obj/item/sealant + name = "Flexi seal" + desc = "A neat spray can that can repair torn inflatable segments, and more!" + icon = 'icons/obj/inflatable.dmi' + icon_state = "sealant" + w_class = 1 + +/area/engineering/main/reactor_core + name = "Nuclear Reactor Core" + +/area/engineering/main/reactor_control + name = "Reactor Control Room" + + +//Procs shamelessly taken from machinery/power +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/connect_to_network() + var/turf/T = src.loc + if(!T || !istype(T)) + return FALSE + + var/obj/structure/cable/C = T.get_cable_node() //check if we have a node cable on the machine turf, the first found is picked + if(!C || !C.powernet) + return FALSE + + C.powernet.add_machine(src) + return TRUE + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/disconnect_from_network() + if(!powernet) + return FALSE + powernet.remove_machine(src) + return TRUE + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/proc/add_avail(amount) + if(powernet) + powernet.newavail += amount + return TRUE + else + return FALSE diff --git a/code/modules/power/reactor/reactor_cargo.dm b/code/modules/power/reactor/reactor_cargo.dm new file mode 100644 index 000000000000..20a770d2b74d --- /dev/null +++ b/code/modules/power/reactor/reactor_cargo.dm @@ -0,0 +1,31 @@ +// modular shitcode but it works:tm: + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/multitool_act(mob/living/user, obj/item/multitool/I) + if(istype(I)) + to_chat(user, "You add \the [src]'s ID into the multitool's buffer.") + I.buffer = src.id + return TRUE +/obj/machinery/computer/reactor/multitool_act(mob/living/user, obj/item/multitool/I) + if(istype(I)) + to_chat(user, "You add the reactor's ID to \the [src]>") + src.id = I.buffer + return TRUE + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/cargo // easier on the brain + +/obj/machinery/atmospherics/components/trinary/nuclear_reactor/cargo/New() + id = rand(1, 1000000) // cmon, what are the chances? + +// Cargo varients can be wrenched down and don't start linked to the default RMBK reactor + +/obj/machinery/computer/reactor/control_rods/cargo + anchored = FALSE + id = null + +/obj/machinery/computer/reactor/stats/cargo + anchored = FALSE + id = null + +/obj/machinery/computer/reactor/fuel_rods/cargo + anchored = FALSE + id = null diff --git a/config/game_options.txt b/config/game_options.txt index 3bb0063eda13..ae22d828464b 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -663,5 +663,5 @@ ECONOMY ## Uncomment to enable dynamic ruleset config file. DYNAMIC_CONFIG_ENABLED -## Force Engine - 1 for SM, 2 for Sing/Tesla, 3 for any, 4 for TEG -ENGINE_TYPE 3 +## Force Engine - 1 for SM, 2 for Sing/Tesla, 3 for any, 4 for TEG, 5 for RBMK +ENGINE_TYPE 5 diff --git a/icons/obj/control_rod.dmi b/icons/obj/control_rod.dmi new file mode 100644 index 000000000000..bef59ebf2ecd Binary files /dev/null and b/icons/obj/control_rod.dmi differ diff --git a/icons/obj/inflatable.dmi b/icons/obj/inflatable.dmi new file mode 100644 index 000000000000..65888be4adf4 Binary files /dev/null and b/icons/obj/inflatable.dmi differ diff --git a/icons/obj/machines/rbmk.dmi b/icons/obj/machines/rbmk.dmi new file mode 100644 index 000000000000..1c52ddac12f1 Binary files /dev/null and b/icons/obj/machines/rbmk.dmi differ diff --git a/icons/obj/machines/reactor_parts.dmi b/icons/obj/machines/reactor_parts.dmi new file mode 100644 index 000000000000..7fd5cfccb07a Binary files /dev/null and b/icons/obj/machines/reactor_parts.dmi differ diff --git a/icons/obj/rbmk_computer.dmi b/icons/obj/rbmk_computer.dmi new file mode 100644 index 000000000000..66bbcb40ac22 Binary files /dev/null and b/icons/obj/rbmk_computer.dmi differ diff --git a/sound/effects/reactor/alarm.ogg b/sound/effects/reactor/alarm.ogg new file mode 100644 index 000000000000..8e698a69f1a5 Binary files /dev/null and b/sound/effects/reactor/alarm.ogg differ diff --git a/sound/effects/reactor/crane_1.wav b/sound/effects/reactor/crane_1.wav new file mode 100644 index 000000000000..394bd658cb83 Binary files /dev/null and b/sound/effects/reactor/crane_1.wav differ diff --git a/sound/effects/reactor/explode.ogg b/sound/effects/reactor/explode.ogg new file mode 100644 index 000000000000..a16a0634b93d Binary files /dev/null and b/sound/effects/reactor/explode.ogg differ diff --git a/sound/effects/reactor/falloutwind.ogg b/sound/effects/reactor/falloutwind.ogg new file mode 100644 index 000000000000..4119371517e8 Binary files /dev/null and b/sound/effects/reactor/falloutwind.ogg differ diff --git a/sound/effects/reactor/meltdown.ogg b/sound/effects/reactor/meltdown.ogg new file mode 100644 index 000000000000..9c0a1a991791 Binary files /dev/null and b/sound/effects/reactor/meltdown.ogg differ diff --git a/sound/effects/reactor/startup.ogg b/sound/effects/reactor/startup.ogg new file mode 100644 index 000000000000..4df6e736c50d Binary files /dev/null and b/sound/effects/reactor/startup.ogg differ diff --git a/sound/effects/reactor/startup2.ogg b/sound/effects/reactor/startup2.ogg new file mode 100644 index 000000000000..4df6e736c50d Binary files /dev/null and b/sound/effects/reactor/startup2.ogg differ diff --git a/sound/effects/reactor/switch.ogg b/sound/effects/reactor/switch.ogg new file mode 100644 index 000000000000..b9cd7d154021 Binary files /dev/null and b/sound/effects/reactor/switch.ogg differ diff --git a/sound/effects/reactor/switch2.ogg b/sound/effects/reactor/switch2.ogg new file mode 100644 index 000000000000..668d3b031056 Binary files /dev/null and b/sound/effects/reactor/switch2.ogg differ diff --git a/sound/effects/reactor/switch3.ogg b/sound/effects/reactor/switch3.ogg new file mode 100644 index 000000000000..b89cbab4cc82 Binary files /dev/null and b/sound/effects/reactor/switch3.ogg differ diff --git a/tgui/packages/tgui/interfaces/NtosRbmkStats.js b/tgui/packages/tgui/interfaces/NtosRbmkStats.js new file mode 100644 index 000000000000..9d44e0b9e9dc --- /dev/null +++ b/tgui/packages/tgui/interfaces/NtosRbmkStats.js @@ -0,0 +1,94 @@ +import { map, sortBy } from 'common/collections'; +import { flow } from 'common/fp'; +import { toFixed } from 'common/math'; +import { pureComponentHooks } from 'common/react'; +import { Component, Fragment } from 'inferno'; +import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components'; +import { NtosWindow } from '../layouts'; +import { useBackend, useLocalState } from '../backend'; + +export const NtosRbmkStats = (props, context) => { + const { act, data } = useBackend(context); + const powerData = data.powerData.map((value, i) => [i, value]); + const psiData = data.psiData.map((value, i) => [i, value]); + const tempInputData = data.tempInputData.map((value, i) => [i, value]); + const tempOutputdata = data.tempOutputdata.map((value, i) => [i, value]); + return ( + + + +
act('swap_reactor')} + content="Change Reactor" /> + }> + Reactor Power (%): + +
+ Reactor Pressure (PSI): + + {data.psi} PSI + + Coolant temperature (°C): + + {data.coolantInput} °C + + Outlet temperature (°C): + + {data.coolantOutput} °C + +
+
+ + + + +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/RbmkControlRods.js b/tgui/packages/tgui/interfaces/RbmkControlRods.js new file mode 100644 index 000000000000..13b4a95ca985 --- /dev/null +++ b/tgui/packages/tgui/interfaces/RbmkControlRods.js @@ -0,0 +1,56 @@ +import { Fragment } from 'inferno'; +import { useBackend, useLocalState } from '../backend'; +import { Section, ProgressBar, Slider } from '../components'; +import { Window } from '../layouts'; + +export const RbmkControlRods = (props, context) => { + const { act, data } = useBackend(context); + const control_rods = data.control_rods; + const k = data.k; + const desiredK = data.desiredK; + return ( + + +
+ Control Rod Insertion: + +
+ Neutrons per generation (K): +
+ + {k} + +
+ Target criticality: +
+ act('input', { + target: value, + })} /> +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/RbmkStats.js b/tgui/packages/tgui/interfaces/RbmkStats.js new file mode 100644 index 000000000000..c168023db541 --- /dev/null +++ b/tgui/packages/tgui/interfaces/RbmkStats.js @@ -0,0 +1,89 @@ +import { map, sortBy } from 'common/collections'; +import { flow } from 'common/fp'; +import { toFixed } from 'common/math'; +import { pureComponentHooks } from 'common/react'; +import { Component, Fragment } from 'inferno'; +import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components'; +import { Window } from '../layouts'; +import { useBackend, useLocalState } from '../backend'; + +export const RbmkStats = (props, context) => { + const { act, data } = useBackend(context); + const powerData = data.powerData.map((value, i) => [i, value]); + const psiData = data.psiData.map((value, i) => [i, value]); + const tempInputData = data.tempInputData.map((value, i) => [i, value]); + const tempOutputdata = data.tempOutputdata.map((value, i) => [i, value]); + return ( + + +
+ Reactor Power (%): + +
+ Reactor Pressure (PSI): + + {data.psi} PSI + + Coolant temperature (°C): + + {data.coolantInput} °C + + Outlet temperature (°C): + + {data.coolantOutput} °C + +
+
+ + + + +
+
+
+ ); +}; diff --git a/yogstation.dme b/yogstation.dme index 552ac26a3ee8..efc266b30e15 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -2670,6 +2670,9 @@ #include "code\modules\power\terminal.dm" #include "code\modules\power\tracker.dm" #include "code\modules\power\turbine.dm" +#include "code\modules\power\reactor\fuel_rods.dm" +#include "code\modules\power\reactor\rbmk.dm" +#include "code\modules\power\reactor\reactor_cargo.dm" #include "code\modules\power\singularity\collector.dm" #include "code\modules\power\singularity\containment_field.dm" #include "code\modules\power\singularity\emitter.dm" diff --git a/yogstation/code/datums/ruins/station.dm b/yogstation/code/datums/ruins/station.dm index 4c2676e31382..516d98cc7626 100644 --- a/yogstation/code/datums/ruins/station.dm +++ b/yogstation/code/datums/ruins/station.dm @@ -85,6 +85,11 @@ suffix = "engine_teg.dmm" name = "Engine TEG" +/datum/map_template/ruin/station/box/engine/rbmk + id = "engine_rbmk" + suffix = "engine_rbmk.dmm" + name = "Engine RBMK" + /datum/map_template/ruin/station/box/testingsite/bunker id = "testing_site_1" suffix = "testingsite_range1.dmm" diff --git a/yogstation/code/game/objects/effects/landmarks.dm b/yogstation/code/game/objects/effects/landmarks.dm index 7512f79e9a5d..c62b4f2212e3 100644 --- a/yogstation/code/game/objects/effects/landmarks.dm +++ b/yogstation/code/game/objects/effects/landmarks.dm @@ -94,7 +94,7 @@ GLOBAL_LIST_EMPTY(chosen_station_templates) return TRUE /obj/effect/landmark/stationroom/box/engine - template_names = list("Engine SM" = 50, "Engine Singulo And Tesla" = 30, "Engine TEG" = 20) + template_names = list("Engine SM" = 50, "Engine Singulo And Tesla" = 30, "Engine TEG" = 10, "Engine RBMK" = 10) icon = 'yogstation/icons/rooms/box/engine.dmi' /obj/effect/landmark/stationroom/box/engine/choose() @@ -109,6 +109,8 @@ GLOBAL_LIST_EMPTY(chosen_station_templates) return . //We let the normal choose() do the work if we want to have all of them in play if(4) return "Engine TEG" + if(5) + return "Engine RBMK" /obj/effect/landmark/stationroom/box/testingsite