diff --git a/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm b/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm
index 86ea8c855cc..71074aa4451 100644
--- a/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm
+++ b/_maps/RandomRuins/SpaceRuins/shuttlerelic.dmm
@@ -74,7 +74,7 @@
/turf/open/floor/oldshuttle,
/area/ruin/space/has_grav/powered)
"t" = (
-/obj/machinery/power/generator,
+/obj/machinery/power/thermoelectric_generator,
/turf/open/floor/oldshuttle,
/area/ruin/space/has_grav/powered)
"u" = (
diff --git a/_maps/templates/medium_shuttle4.dmm b/_maps/templates/medium_shuttle4.dmm
index 0071a71a1e9..67a5617da6b 100644
--- a/_maps/templates/medium_shuttle4.dmm
+++ b/_maps/templates/medium_shuttle4.dmm
@@ -54,7 +54,7 @@
/turf/open/floor/oldshuttle,
/area/ruin/powered/shuttle/medium_4)
"r" = (
-/obj/machinery/power/generator,
+/obj/machinery/power/thermoelectric_generator,
/turf/open/floor/oldshuttle,
/area/ruin/powered/shuttle/medium_4)
"s" = (
diff --git a/code/__DEFINES/atmospherics/atmos_piping.dm b/code/__DEFINES/atmospherics/atmos_piping.dm
index 5e501a83983..1993f102225 100644
--- a/code/__DEFINES/atmospherics/atmos_piping.dm
+++ b/code/__DEFINES/atmospherics/atmos_piping.dm
@@ -92,8 +92,14 @@
// Ventcrawling bitflags, handled in var/vent_movement
///Allows for ventcrawling to occur. All atmospheric machines have this flag on by default. Cryo is the exception
-#define VENTCRAWL_ALLOWED (1<<0)
+#define VENTCRAWL_ALLOWED (1<<0)
///Allows mobs to enter or leave from atmospheric machines. On for passive, unary, and scrubber vents.
#define VENTCRAWL_ENTRANCE_ALLOWED (1<<1)
///Used to check if a machinery is visible. Called by update_pipe_vision(). On by default for all except cryo.
-#define VENTCRAWL_CAN_SEE (1<<2)
+#define VENTCRAWL_CAN_SEE (1<<2)
+
+DEFINE_BITFIELD(vent_movement, list(
+ "Ventcrawl Allowed" = VENTCRAWL_ALLOWED,
+ "Ventcrawl Entrance Allowed" = VENTCRAWL_ENTRANCE_ALLOWED,
+ "Ventcrawl Can See" = VENTCRAWL_CAN_SEE,
+))
diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
index f232e1b9375..d5c9c8349d4 100644
--- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
@@ -243,10 +243,10 @@
/datum/stock_part/servo = 1)
needs_anchored = FALSE
-/obj/item/circuitboard/machine/generator
+/obj/item/circuitboard/machine/thermoelectric_generator
name = "Thermo-Electric Generator"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
- build_path = /obj/machinery/power/generator
+ build_path = /obj/machinery/power/thermoelectric_generator
req_components = list()
/obj/item/circuitboard/machine/ntnet_relay
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
index 9a4623ef49a..819f9d0f565 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
@@ -5,27 +5,23 @@
name = "circulator/heat exchanger"
desc = "A gas circulator pump and heat exchanger."
icon_state = "circ-off-0"
-
- var/active = FALSE
-
- var/last_pressure_delta = 0
pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
-
+ vent_movement = VENTCRAWL_CAN_SEE
density = TRUE
-
circuit = /obj/item/circuitboard/machine/circulator
+ var/active = FALSE
+ var/last_pressure_delta = 0
var/flipped = 0
+ ///Which circulator mode we are on, the generator requires one of each to work.
var/mode = CIRCULATOR_HOT
- var/obj/machinery/power/generator/generator
+ ///The generator we are connected to.
+ var/obj/machinery/power/thermoelectric_generator/generator
/obj/machinery/atmospherics/components/binary/circulator/Initialize(mapload)
. = ..()
AddComponent(/datum/component/simple_rotation)
-/obj/machinery/atmospherics/components/binary/circulator/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
-
//default cold circ for mappers
/obj/machinery/atmospherics/components/binary/circulator/cold
mode = CIRCULATOR_COLD
@@ -49,25 +45,18 @@
return null
//Calculate necessary moles to transfer using PV = nRT
- if(air2.temperature>0)
- var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2
-
- var/transfer_moles = (pressure_delta*air1.volume)/(air2.temperature * R_IDEAL_GAS_EQUATION)
-
- last_pressure_delta = pressure_delta
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = air2.remove(transfer_moles)
-
- update_parents()
-
- return removed
-
- else
+ if(air2.temperature <= 0)
last_pressure_delta = 0
+ return
+ var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2
+ var/transfer_moles = (pressure_delta*air1.volume)/(air2.temperature * R_IDEAL_GAS_EQUATION)
+ last_pressure_delta = pressure_delta
+ //Actually transfer the gas
+ var/datum/gas_mixture/removed = air2.remove(transfer_moles)
+ update_parents()
+ return removed
/obj/machinery/atmospherics/components/binary/circulator/process_atmos()
- ..()
update_appearance()
/obj/machinery/atmospherics/components/binary/circulator/update_icon_state()
@@ -86,13 +75,13 @@
/obj/machinery/atmospherics/components/binary/circulator/wrench_act(mob/living/user, obj/item/I)
if(!panel_open)
+ balloon_alert(user, "open the panel!")
return
set_anchored(!anchored)
I.play_tool_sound(src)
if(generator)
disconnectFromGenerator()
- to_chat(user, span_notice("You [anchored?"secure":"unsecure"] [src]."))
-
+ balloon_alert(user, "[anchored ? "secure" : "unsecure"]")
var/obj/machinery/atmospherics/node1 = nodes[1]
var/obj/machinery/atmospherics/node2 = nodes[2]
@@ -145,20 +134,22 @@
if(generator)
disconnectFromGenerator()
mode = !mode
- to_chat(user, span_notice("You set [src] to [mode ? "cold" : "hot"] mode."))
+ balloon_alert(user, "set to [mode ? "cold" : "hot"]")
return TRUE
/obj/machinery/atmospherics/components/binary/circulator/screwdriver_act(mob/user, obj/item/I)
- if(..())
- return TRUE
+ if(!anchored)
+ balloon_alert(user, "anchor it down!")
+ return
toggle_panel_open()
I.play_tool_sound(src)
- to_chat(user, span_notice("You [panel_open ? "open" : "close"] the panel on [src]."))
+ balloon_alert(user, "panel [panel_open ? "open" : "closed"]")
return TRUE
/obj/machinery/atmospherics/components/binary/circulator/crowbar_act(mob/user, obj/item/I)
- default_deconstruction_crowbar(I)
- return TRUE
+ if(default_deconstruction_crowbar(I))
+ return TRUE
+ return ..()
/obj/machinery/atmospherics/components/binary/circulator/on_deconstruction()
if(generator)
@@ -176,19 +167,3 @@
..()
pixel_x = 0
pixel_y = 0
-
-/obj/machinery/atmospherics/components/binary/circulator/verb/circulator_flip()
- set name = "Flip"
- set category = "Object"
- set src in oview(1)
-
- if(!ishuman(usr))
- return
-
- if(anchored)
- to_chat(usr, span_danger("[src] is anchored!"))
- return
-
- flipped = !flipped
- to_chat(usr, span_notice("You flip [src]."))
- update_appearance()
diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
index 09c8a3a9367..730e193671d 100644
--- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm
+++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
@@ -99,7 +99,7 @@
normalize_cardinal_directions()
find_all_connections()
-/obj/machinery/atmospherics/pipe/layer_manifold/set_piping_layer()
+/obj/machinery/atmospherics/pipe/layer_manifold/set_piping_layer(new_layer)
piping_layer = PIPING_LAYER_DEFAULT
/obj/machinery/atmospherics/pipe/layer_manifold/pipeline_expansion()
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
deleted file mode 100644
index d86b178ea0c..00000000000
--- a/code/modules/power/generator.dm
+++ /dev/null
@@ -1,231 +0,0 @@
-/obj/machinery/power/generator
- name = "thermoelectric generator"
- desc = "It's a high efficiency thermoelectric generator."
- icon_state = "teg"
- density = TRUE
- use_power = NO_POWER_USE
-
- circuit = /obj/item/circuitboard/machine/generator
-
- var/obj/machinery/atmospherics/components/binary/circulator/cold_circ
- var/obj/machinery/atmospherics/components/binary/circulator/hot_circ
-
- var/lastgen = 0
- var/lastgenlev = -1
- var/lastcirc = "00"
-
-
-/obj/machinery/power/generator/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/simple_rotation)
- find_circs()
- connect_to_network()
- SSair.start_processing_machine(src)
- update_appearance()
-
-/obj/machinery/power/generator/Destroy()
- kill_circs()
- SSair.stop_processing_machine(src)
- return ..()
-
-/obj/machinery/power/generator/update_overlays()
- . = ..()
- if(machine_stat & (NOPOWER|BROKEN))
- return
-
- var/L = min(round(lastgenlev / 100000), 11)
- if(L != 0)
- . += mutable_appearance('icons/obj/machines/engine/other.dmi', "teg-op[L]")
- if(hot_circ && cold_circ)
- . += "teg-oc[lastcirc]"
-
-
-#define GENRATE 800 // generator output coefficient from Q
-
-/obj/machinery/power/generator/process_atmos()
-
- if(!cold_circ || !hot_circ)
- return
-
- if(powernet)
- var/datum/gas_mixture/cold_air = cold_circ.return_transfer_air()
- var/datum/gas_mixture/hot_air = hot_circ.return_transfer_air()
-
- if(cold_air && hot_air)
-
- var/cold_air_heat_capacity = cold_air.heat_capacity()
- var/hot_air_heat_capacity = hot_air.heat_capacity()
-
- var/delta_temperature = hot_air.temperature - cold_air.temperature
-
-
- if(delta_temperature > 0 && cold_air_heat_capacity > 0 && hot_air_heat_capacity > 0)
- var/efficiency = 0.65
-
- var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity)
-
- var/heat = energy_transfer*(1-efficiency)
- lastgen += energy_transfer*efficiency
-
- hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity
- cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity
-
- //add_avail(lastgen) This is done in process now
- // update icon overlays only if displayed level has changed
-
- if(hot_air)
- var/datum/gas_mixture/hot_circ_air1 = hot_circ.airs[1]
- hot_circ_air1.merge(hot_air)
-
- if(cold_air)
- var/datum/gas_mixture/cold_circ_air1 = cold_circ.airs[1]
- cold_circ_air1.merge(cold_air)
-
- update_appearance()
-
- var/circ = "[cold_circ?.last_pressure_delta > 0 ? "1" : "0"][hot_circ?.last_pressure_delta > 0 ? "1" : "0"]"
- if(circ != lastcirc)
- lastcirc = circ
- update_appearance()
-
- src.updateDialog()
-
-/obj/machinery/power/generator/process()
- //Setting this number higher just makes the change in power output slower, it doesnt actualy reduce power output cause **math**
- var/power_output = round(lastgen / 10)
- add_avail(power_output)
- lastgenlev = power_output
- lastgen -= power_output
-
-/obj/machinery/power/generator/proc/get_menu(include_link = TRUE)
- var/t = ""
- if(!powernet)
- t += "Unable to connect to the power network!"
- else if(cold_circ && hot_circ)
- var/datum/gas_mixture/cold_circ_air1 = cold_circ.airs[1]
- var/datum/gas_mixture/cold_circ_air2 = cold_circ.airs[2]
- var/datum/gas_mixture/hot_circ_air1 = hot_circ.airs[1]
- var/datum/gas_mixture/hot_circ_air2 = hot_circ.airs[2]
-
- t += "
"
-
- t += "Output: [display_power(lastgenlev)]"
-
- t += "
"
-
- t += "Cold loop
"
- t += "Temperature Inlet: [round(cold_circ_air2.temperature, 0.1)] K / Outlet: [round(cold_circ_air1.temperature, 0.1)] K
"
- t += "Pressure Inlet: [round(cold_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(cold_circ_air1.return_pressure(), 0.1)] kPa
"
-
- t += "Hot loop
"
- t += "Temperature Inlet: [round(hot_circ_air2.temperature, 0.1)] K / Outlet: [round(hot_circ_air1.temperature, 0.1)] K
"
- t += "Pressure Inlet: [round(hot_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(hot_circ_air1.return_pressure(), 0.1)] kPa
"
-
- t += "
"
- else if(!hot_circ && cold_circ)
- t += "Unable to locate hot circulator!"
- else if(hot_circ && !cold_circ)
- t += "Unable to locate cold circulator!"
- else
- t += "Unable to locate any parts!"
- if(include_link)
- t += "
Close"
-
- return t
-
-/obj/machinery/power/generator/ui_interact(mob/user)
- . = ..()
- var/datum/browser/popup = new(user, "teg", "Thermo-Electric Generator", 460, 300)
- popup.set_content(get_menu())
- popup.open()
-
-/obj/machinery/power/generator/Topic(href, href_list)
- if(..())
- return
- if( href_list["close"] )
- usr << browse(null, "window=teg")
- usr.unset_machine()
- return FALSE
- return TRUE
-
-
-
-/obj/machinery/power/generator/proc/find_circs()
- kill_circs()
- var/list/circs = list()
- var/obj/machinery/atmospherics/components/binary/circulator/C
- var/circpath = /obj/machinery/atmospherics/components/binary/circulator
- if(dir == NORTH || dir == SOUTH)
- C = locate(circpath) in get_step(src, EAST)
- if(C && C.dir == WEST)
- circs += C
-
- C = locate(circpath) in get_step(src, WEST)
- if(C && C.dir == EAST)
- circs += C
-
- else
- C = locate(circpath) in get_step(src, NORTH)
- if(C && C.dir == SOUTH)
- circs += C
-
- C = locate(circpath) in get_step(src, SOUTH)
- if(C && C.dir == NORTH)
- circs += C
-
- if(circs.len)
- for(C in circs)
- if(C.mode == CIRCULATOR_COLD && !cold_circ)
- cold_circ = C
- C.generator = src
- else if(C.mode == CIRCULATOR_HOT && !hot_circ)
- hot_circ = C
- C.generator = src
-
-/obj/machinery/power/generator/wrench_act(mob/living/user, obj/item/I)
- . = ..()
- if(!panel_open)
- return
- set_anchored(!anchored)
- I.play_tool_sound(src)
- if(!anchored)
- kill_circs()
- connect_to_network()
- to_chat(user, span_notice("You [anchored?"secure":"unsecure"] [src]."))
- return TRUE
-
-/obj/machinery/power/generator/multitool_act(mob/living/user, obj/item/I)
- . = ..()
- if(!anchored)
- return
- find_circs()
- to_chat(user, span_notice("You update [src]'s circulator links."))
- return TRUE
-
-/obj/machinery/power/generator/screwdriver_act(mob/user, obj/item/I)
- if(..())
- return TRUE
- toggle_panel_open()
- I.play_tool_sound(src)
- to_chat(user, span_notice("You [panel_open?"open":"close"] the panel on [src]."))
- return TRUE
-
-/obj/machinery/power/generator/crowbar_act(mob/user, obj/item/I)
- default_deconstruction_crowbar(I)
- return TRUE
-
-/obj/machinery/power/generator/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
-
-/obj/machinery/power/generator/on_deconstruction()
- kill_circs()
-
-/obj/machinery/power/generator/proc/kill_circs()
- if(hot_circ)
- hot_circ.generator = null
- hot_circ = null
- if(cold_circ)
- cold_circ.generator = null
- cold_circ = null
-
-#undef GENRATE
diff --git a/code/modules/power/thermoelectric_generator.dm b/code/modules/power/thermoelectric_generator.dm
new file mode 100644
index 00000000000..1f8319ad51d
--- /dev/null
+++ b/code/modules/power/thermoelectric_generator.dm
@@ -0,0 +1,222 @@
+#define TEG_EFFICIENCY 0.65
+
+/obj/machinery/power/thermoelectric_generator
+ name = "thermoelectric generator"
+ desc = "It's a high efficiency thermoelectric generator."
+ icon_state = "teg"
+ base_icon_state = "teg"
+ density = TRUE
+ use_power = NO_POWER_USE
+ circuit = /obj/item/circuitboard/machine/thermoelectric_generator
+
+ ///The cold circulator machine, containing cold gas for the mix.
+ var/obj/machinery/atmospherics/components/binary/circulator/cold_circ
+ ///The hot circulator machine, containing very hot gas for the mix.
+ var/obj/machinery/atmospherics/components/binary/circulator/hot_circ
+ ///The amount of power the generator is currently producing.
+ var/lastgen = 0
+ ///The amount of power the generator has last produced.
+ var/lastgenlev = -1
+ /**
+ * Used in overlays for the TEG, basically;
+ * one number is for the cold mix, one is for the hot mix
+ * If the cold mix has pressure in it, then the first number is 1, else 0
+ * If the hot mix has pressure in it, then the second number is 1, else 0
+ * Neither has pressure: 00
+ * Only cold has pressure: 10
+ * Only hot has pressure: 01
+ * Both has pressure: 11
+ */
+ var/last_pressure_overlay = "00"
+
+/obj/machinery/power/thermoelectric_generator/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/simple_rotation)
+ find_circulators()
+ connect_to_network()
+ SSair.start_processing_machine(src)
+ update_appearance()
+
+/obj/machinery/power/thermoelectric_generator/Destroy()
+ null_circulators()
+ SSair.stop_processing_machine(src)
+ return ..()
+
+/obj/machinery/power/thermoelectric_generator/on_deconstruction()
+ null_circulators()
+
+/obj/machinery/power/thermoelectric_generator/update_overlays()
+ . = ..()
+ if(machine_stat & (NOPOWER|BROKEN))
+ return
+
+ var/level = min(round(lastgenlev / 100000), 11)
+ if(level)
+ . += mutable_appearance('icons/obj/machines/engine/other.dmi', "[base_icon_state]-op[level]")
+ if(hot_circ && cold_circ)
+ . += "[base_icon_state]-oc[last_pressure_overlay]"
+
+/obj/machinery/power/thermoelectric_generator/wrench_act(mob/living/user, obj/item/tool)
+ if(!panel_open)
+ balloon_alert(user, "open the panel!")
+ return
+ set_anchored(!anchored)
+ tool.play_tool_sound(src)
+ if(anchored)
+ connect_to_network()
+ else
+ null_circulators()
+ balloon_alert(user, "[anchored ? "secure" : "unsecure"]")
+ return TRUE
+
+/obj/machinery/power/thermoelectric_generator/multitool_act(mob/living/user, obj/item/tool)
+ . = ..()
+ if(!anchored)
+ return
+ find_circulators()
+ balloon_alert(user, "circulators updated")
+ return TRUE
+
+/obj/machinery/power/thermoelectric_generator/screwdriver_act(mob/user, obj/item/tool)
+ if(!anchored)
+ balloon_alert(user, "anchor it down!")
+ return
+ toggle_panel_open()
+ tool.play_tool_sound(src)
+ balloon_alert(user, "panel [panel_open ? "open" : "closed"]")
+ return TRUE
+
+/obj/machinery/power/thermoelectric_generator/crowbar_act(mob/living/user, obj/item/tool)
+ default_deconstruction_crowbar(tool)
+ return TRUE
+
+/obj/machinery/power/thermoelectric_generator/process()
+ //Setting this number higher just makes the change in power output slower, it doesnt actualy reduce power output cause **math**
+ var/power_output = round(lastgen / 10)
+ add_avail(power_output)
+ lastgenlev = power_output
+ lastgen -= power_output
+
+/obj/machinery/power/thermoelectric_generator/process_atmos()
+ if(!cold_circ || !hot_circ)
+ return
+ if(!powernet)
+ return
+
+ var/datum/gas_mixture/cold_air = cold_circ.return_transfer_air()
+ var/datum/gas_mixture/hot_air = hot_circ.return_transfer_air()
+ if(cold_air && hot_air)
+ var/cold_air_heat_capacity = cold_air.heat_capacity()
+ var/hot_air_heat_capacity = hot_air.heat_capacity()
+ var/delta_temperature = hot_air.temperature - cold_air.temperature
+ if(delta_temperature > 0 && cold_air_heat_capacity > 0 && hot_air_heat_capacity > 0)
+ var/efficiency = TEG_EFFICIENCY
+ var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity)
+ var/heat = energy_transfer*(1-efficiency)
+ lastgen += energy_transfer*efficiency
+ hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity
+ cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity
+
+ if(hot_air)
+ var/datum/gas_mixture/hot_circ_air1 = hot_circ.airs[1]
+ hot_circ_air1.merge(hot_air)
+
+ if(cold_air)
+ var/datum/gas_mixture/cold_circ_air1 = cold_circ.airs[1]
+ cold_circ_air1.merge(cold_air)
+
+ var/current_pressure = "[cold_circ?.last_pressure_delta > 0 ? "1" : "0"][hot_circ?.last_pressure_delta > 0 ? "1" : "0"]"
+ if(current_pressure != last_pressure_overlay)
+ //this requires an update to overlays.
+ last_pressure_overlay = current_pressure
+
+ update_appearance(UPDATE_ICON)
+
+/obj/machinery/power/thermoelectric_generator/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ThermoElectricGenerator", name)
+ ui.open()
+
+/obj/machinery/power/thermoelectric_generator/ui_data(mob/user)
+ var/list/data = list()
+ data["error_message"] = null
+ if(!powernet)
+ data["error_message"] = "Unable to connect to the power network!"
+ return data
+ if(!cold_circ && !hot_circ)
+ data["error_message"] = "Unable to locate any parts! Multitool the machine to sync to nearby parts."
+ return data
+ if(!cold_circ)
+ data["error_message"] = "Unable to locate cold circulator!"
+ return data
+ if(!hot_circ)
+ data["error_message"] = "Unable to locate hot circulator!"
+ return data
+
+ var/datum/gas_mixture/cold_circ_air1 = cold_circ.airs[1]
+ var/datum/gas_mixture/cold_circ_air2 = cold_circ.airs[2]
+
+ var/datum/gas_mixture/hot_circ_air1 = hot_circ.airs[1]
+ var/datum/gas_mixture/hot_circ_air2 = hot_circ.airs[2]
+
+ data["last_power_output"] = display_power(lastgenlev)
+
+ var/list/cold_data = list()
+ cold_data["temperature_inlet"] = round(cold_circ_air2.temperature, 0.1)
+ cold_data["temperature_outlet"] = round(cold_circ_air1.temperature, 0.1)
+ cold_data["pressure_inlet"] = round(cold_circ_air2.return_pressure(), 0.1)
+ cold_data["pressure_outlet"] = round(cold_circ_air1.return_pressure(), 0.1)
+ data["cold_data"] = list(cold_data)
+
+ var/list/hot_data = list()
+ hot_data["temperature_inlet"] = round(hot_circ_air2.temperature, 0.1)
+ hot_data["temperature_outlet"] = round(hot_circ_air1.temperature, 0.1)
+ hot_data["pressure_inlet"] = round(hot_circ_air2.return_pressure(), 0.1)
+ hot_data["pressure_outlet"] = round(hot_circ_air1.return_pressure(), 0.1)
+ data["hot_data"] = list(hot_data)
+
+ return data
+
+///Finds and connects nearby valid circulators to the machine, nulling out previous ones.
+/obj/machinery/power/thermoelectric_generator/proc/find_circulators()
+ null_circulators()
+ var/list/valid_circulators = list()
+
+ if(dir & (NORTH|SOUTH))
+ var/obj/machinery/atmospherics/components/binary/circulator/east_circulator = locate() in get_step(src, EAST)
+ if(east_circulator && east_circulator.dir == WEST)
+ valid_circulators += east_circulator
+ var/obj/machinery/atmospherics/components/binary/circulator/west_circulator = locate() in get_step(src, WEST)
+ if(west_circulator && west_circulator.dir == EAST)
+ valid_circulators += west_circulator
+ else
+ var/obj/machinery/atmospherics/components/binary/circulator/north_circulator = locate() in get_step(src, NORTH)
+ if(north_circulator && north_circulator.dir == SOUTH)
+ valid_circulators += north_circulator
+ var/obj/machinery/atmospherics/components/binary/circulator/south_circulator = locate() in get_step(src, SOUTH)
+ if(south_circulator && south_circulator.dir == NORTH)
+ valid_circulators += south_circulator
+
+ if(!valid_circulators.len)
+ return
+
+ for(var/obj/machinery/atmospherics/components/binary/circulator/circulators as anything in valid_circulators)
+ if(circulators.mode == CIRCULATOR_COLD && !cold_circ)
+ cold_circ = circulators
+ circulators.generator = src
+ continue
+ if(circulators.mode == CIRCULATOR_HOT && !hot_circ)
+ hot_circ = circulators
+ circulators.generator = src
+
+///Removes hot and cold circulators from the generator, nulling them.
+/obj/machinery/power/thermoelectric_generator/proc/null_circulators()
+ if(hot_circ)
+ hot_circ.generator = null
+ hot_circ = null
+ if(cold_circ)
+ cold_circ.generator = null
+ cold_circ = null
+
+#undef TEG_EFFICIENCY
diff --git a/code/modules/research/ordnance/tank_compressor.dm b/code/modules/research/ordnance/tank_compressor.dm
index 85a2cf44836..ff03b368291 100644
--- a/code/modules/research/ordnance/tank_compressor.dm
+++ b/code/modules/research/ordnance/tank_compressor.dm
@@ -85,9 +85,6 @@
update_appearance()
return TRUE
-/obj/machinery/atmospherics/components/binary/circulator/get_node_connects()
- return list(REVERSE_DIR(dir), dir) // airs[2] is input which is facing dir, airs[1] is output which is facing the other side of dir
-
/obj/machinery/atmospherics/components/binary/tank_compressor/screwdriver_act(mob/living/user, obj/item/tool)
if(active || inserted_tank)
return FALSE
diff --git a/tgstation.dme b/tgstation.dme
index 88028de4d91..579840aa66f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -5267,7 +5267,6 @@
#include "code\modules\power\cell.dm"
#include "code\modules\power\energy_accumulator.dm"
#include "code\modules\power\floodlight.dm"
-#include "code\modules\power\generator.dm"
#include "code\modules\power\gravitygenerator.dm"
#include "code\modules\power\monitor.dm"
#include "code\modules\power\multiz.dm"
@@ -5279,6 +5278,7 @@
#include "code\modules\power\smes.dm"
#include "code\modules\power\solar.dm"
#include "code\modules\power\terminal.dm"
+#include "code\modules\power\thermoelectric_generator.dm"
#include "code\modules\power\tracker.dm"
#include "code\modules\power\apc\apc_appearance.dm"
#include "code\modules\power\apc\apc_attack.dm"
diff --git a/tgui/packages/tgui/interfaces/ThermoElectricGenerator.tsx b/tgui/packages/tgui/interfaces/ThermoElectricGenerator.tsx
new file mode 100644
index 00000000000..1d9a1802461
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/ThermoElectricGenerator.tsx
@@ -0,0 +1,80 @@
+import { useBackend } from '../backend';
+import { Box, Divider, Section } from '../components';
+import { Window } from '../layouts';
+
+type Data = {
+ error_message: string | null;
+ last_power_output: string | null;
+ cold_data: CirculatorData[];
+ hot_data: CirculatorData[];
+};
+
+type CirculatorData = {
+ temperature_inlet: number | null;
+ temperature_outlet: number | null;
+ pressure_inlet: number | null;
+ pressure_outlet: number | null;
+};
+
+export const ThermoElectricGenerator = (props) => {
+ const { act, data } = useBackend();
+ const {
+ error_message,
+ last_power_output,
+ cold_data = [],
+ hot_data = [],
+ } = data;
+ if (error_message) {
+ return (
+
+
+
+
+
+ );
+ }
+ return (
+
+
+
+
+ Last Output: {last_power_output}
+
+
+ Cold Loop
+
+ {cold_data.map((data, index) => (
+
+
+ Temperature Inlet: {data.temperature_inlet} K / Outlet:{' '}
+ {data.temperature_outlet} K
+
+
+ Pressure Inlet: {data.pressure_inlet} kPa / Outlet:{' '}
+ {data.pressure_outlet} kPa
+
+
+ ))}
+
+
+
+ Hot loop{' '}
+
+ {hot_data.map((data, index) => (
+
+
+ Temperature Inlet: {data.temperature_inlet} K / Outlet:{' '}
+ {data.temperature_outlet} K
+
+
+ Pressure Inlet: {data.pressure_inlet} kPa / Outlet:{' '}
+ {data.pressure_outlet} kPa
+
+
+ ))}
+
+
+
+
+ );
+};