diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm
index bd40f60001f..37e2cdaa85a 100644
--- a/code/game/objects/items/RPD.dm
+++ b/code/game/objects/items/RPD.dm
@@ -34,6 +34,7 @@ GLOBAL_LIST_INIT(atmos_pipe_recipes, list(
new /datum/pipe_info/pipe("Manual Valve", /obj/machinery/atmospherics/components/binary/valve, TRUE),
new /datum/pipe_info/pipe("Digital Valve", /obj/machinery/atmospherics/components/binary/valve/digital, TRUE),
new /datum/pipe_info/pipe("Pressure Valve", /obj/machinery/atmospherics/components/binary/pressure_valve, TRUE),
+ new /datum/pipe_info/pipe("Temperature Gate", /obj/machinery/atmospherics/components/binary/temperature_gate, TRUE),
new /datum/pipe_info/pipe("Temperature Pump", /obj/machinery/atmospherics/components/binary/temperature_pump, TRUE),
new /datum/pipe_info/meter("Meter"),
),
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
new file mode 100644
index 00000000000..9b408a2d02a
--- /dev/null
+++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
@@ -0,0 +1,127 @@
+/obj/machinery/atmospherics/components/binary/temperature_gate
+ icon_state = "tgate_map-3"
+ name = "temperature gate"
+ desc = "An activable gate that compares the input temperature with the interface set temperature to check if the gas can flow or not."
+
+ can_unwrench = TRUE
+ shift_underlay_only = FALSE
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "tgate"
+
+ ///If the temperature of the mix before the gate is lower than this, the gas will flow (if inverted, if the temperature of the mix before the gate is higher than this)
+ var/target_temperature = T0C
+ ///Minimum allowed temperature
+ var/minimum_temperature = TCMB
+ ///Maximum allowed temperature to be set
+ var/max_temperature = 4500
+ ///Check if the sensor should let gas pass if temperature in the mix is less/higher than the target one
+ var/inverted = FALSE
+ ///Check if the gas is moving from one pipenet to the other
+ var/is_gas_flowing = FALSE
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/CtrlClick(mob/user)
+ if(can_interact(user))
+ on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_icon()
+ return ..()
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/AltClick(mob/user)
+ if(can_interact(user))
+ target_temperature = max_temperature
+ investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS)
+ to_chat(user, "You set the target temperature on [src] to [target_temperature] K.")
+ update_icon()
+ return ..()
+
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/examine(mob/user)
+ . = ..()
+ . += "This device will let gas flow if the temperature of the gas in the input is [inverted ? "higher" : "lower"] than the temperature set in the interface."
+ if(inverted)
+ . += "The device settings can be restored if a multitool is used on it."
+ else
+ . += "The sensor's settings can be changed by using a multitool on the device."
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/update_icon_nopipes()
+ if(on && is_operational && is_gas_flowing)
+ icon_state = "tgate_flow-[set_overlay_offset(piping_layer)]"
+ else if(on && is_operational && !is_gas_flowing)
+ icon_state = "tgate_on-[set_overlay_offset(piping_layer)]"
+ else
+ icon_state = "tgate_off-[set_overlay_offset(piping_layer)]"
+
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/process_atmos()
+
+ if(!on || !is_operational)
+ return
+
+ var/datum/gas_mixture/air1 = airs[1]
+ var/datum/gas_mixture/air2 = airs[2]
+
+ if(!inverted)
+ if(air1.temperature < target_temperature)
+ if(air1.release_gas_to(air2, air1.return_pressure()))
+ update_parents()
+ is_gas_flowing = TRUE
+ else
+ is_gas_flowing = FALSE
+ else
+ if(air1.temperature > target_temperature)
+ if(air1.release_gas_to(air2, air1.return_pressure()))
+ update_parents()
+ is_gas_flowing = TRUE
+ else
+ is_gas_flowing = FALSE
+ update_icon_nopipes()
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "AtmosTempGate", name)
+ ui.open()
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/ui_data()
+ var/data = list()
+ data["on"] = on
+ data["temperature"] = round(target_temperature)
+ data["max_temperature"] = round(max_temperature*100)
+ return data
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/ui_act(action, params)
+ if(..())
+ return
+ switch(action)
+ if("power")
+ on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", INVESTIGATE_ATMOS)
+ . = TRUE
+ if("temperature")
+ var/temperature = params["temperature"]
+ if(temperature == "max")
+ temperature = max_temperature
+ . = TRUE
+ else if(text2num(temperature) != null)
+ temperature = text2num(temperature)
+ . = TRUE
+ if(.)
+ target_temperature = clamp(minimum_temperature, temperature, max_temperature)
+ investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
+ update_icon()
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/can_unwrench(mob/user)
+ . = ..()
+ if(. && on && is_operational)
+ to_chat(user, "You cannot unwrench [src], turn it off first!")
+ return FALSE
+
+/obj/machinery/atmospherics/components/binary/temperature_gate/multitool_act(mob/living/user, obj/item/multitool/I)
+ . = ..()
+ if (istype(I))
+ inverted = !inverted
+ if(inverted)
+ to_chat(user, "You set the [src]'s sensors to release gases when the temperature is higher than the setted one.")
+ else
+ to_chat(user, "You set the [src]'s sensors to the default settings.")
+ return TRUE
diff --git a/icons/obj/atmospherics/components/binary_devices.dmi b/icons/obj/atmospherics/components/binary_devices.dmi
index a4a382423a0..00d98a33ee9 100644
Binary files a/icons/obj/atmospherics/components/binary_devices.dmi and b/icons/obj/atmospherics/components/binary_devices.dmi differ
diff --git a/icons/obj/atmospherics/pipes/pipe_item.dmi b/icons/obj/atmospherics/pipes/pipe_item.dmi
index a2e611b702c..66184882f0a 100644
Binary files a/icons/obj/atmospherics/pipes/pipe_item.dmi and b/icons/obj/atmospherics/pipes/pipe_item.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index d206a1ee25a..2bd37083d55 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1608,6 +1608,7 @@
#include "code\modules\atmospherics\machinery\components\binary_devices\passive_gate.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\pressure_valve.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\pump.dm"
+#include "code\modules\atmospherics\machinery\components\binary_devices\temperature_gate.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\temperature_pump.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\valve.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\volume_pump.dm"
diff --git a/tgui/packages/tgui/interfaces/AtmosTempGate.js b/tgui/packages/tgui/interfaces/AtmosTempGate.js
new file mode 100644
index 00000000000..8efb2da5706
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/AtmosTempGate.js
@@ -0,0 +1,47 @@
+import { useBackend } from '../backend';
+import { Button, LabeledList, NumberInput, Section } from '../components';
+import { Window } from '../layouts';
+
+export const AtmosTempGate = (props, context) => {
+ const { act, data } = useBackend(context);
+ return (
+ "+e+"
/gi,"\n").replace(/<\/?[a-z0-9-_]+[^>]*>/gi,"").replace(/&(nbsp|amp|quot|lt|gt|apos);/g,(function(e,n){return t[n]})).replace(/?([0-9]+);/gi,(function(e,t){var n=parseInt(t,10);return String.fromCharCode(n)})).replace(/?([0-9a-f]+);/gi,(function(e,t){var n=parseInt(t,16);return String.fromCharCode(n)}))};t.buildQueryString=function(e){return Object.keys(e).map((function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])})).join("&")}},function(e,t,n){"use strict";var r={}.hasOwnProperty;e.exports=function(e,t){return r.call(e,t)}},function(e,t,n){"use strict";var r=n(53),o=n(66),i=n(18),a=n(12),u=n(72),c=[].push,s=function(e){var t=1==e,n=2==e,s=3==e,l=4==e,f=6==e,d=5==e||f;return function(p,h,g,v){for(var m,y,b=i(p),x=o(b),w=r(h,g,3),_=a(x.length),E=0,k=v||u,S=t?k(p,_):n?k(p,0):undefined;_>E;E++)if((d||E in x)&&(y=w(m=x[E],E,b),e))if(t)S[E]=y;else if(y)switch(e){case 3:return!0;case 5:return m;case 6:return E;case 2:c.call(S,m)}else if(l)return!1;return f?-1:s||l?l:S}};e.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6)}},function(e,t,n){"use strict";t.__esModule=!0,t.useSelector=t.useDispatch=t.createAction=t.combineReducers=t.applyMiddleware=t.createStore=void 0;var r=n(30);function o(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return i(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return i(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0;return function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(n=e[Symbol.iterator]()).next.bind(n)}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);nc||n!=n?l*Infinity:l*n}},function(e,t,n){"use strict";var r=n(4),o=Math.hypot,i=Math.abs,a=Math.sqrt;r({target:"Math",stat:!0,forced:!!o&&o(Infinity,NaN)!==Infinity},{hypot:function(e,t){for(var n,r,o=0,u=0,c=arguments.length,s=0;u
\n":"'+(n?e:ee(e,!0))+"
\n"}return e}(),t.blockquote=function(){function e(e){return""+(n?e:ee(e,!0))+"\n"+e+"
\n"}return e}(),t.html=function(){function e(e){return e}return e}(),t.heading=function(){function e(e,t,n,r){return this.options.headerIds?"
\n":"
\n"}return e}(),t.list=function(){function e(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+""+r+">\n"}return e}(),t.listitem=function(){function e(e){return"\n\n"+e+"\n"+t+"
\n"}return e}(),t.tablerow=function(){function e(e){return"\n"+e+" \n"}return e}(),t.tablecell=function(){function e(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+""+n+">\n"}return e}(),t.strong=function(){function e(e){return""+e+""}return e}(),t.em=function(){function e(e){return""+e+""}return e}(),t.codespan=function(){function e(e){return""+e+""}return e}(),t.br=function(){function e(){return this.options.xhtml?"
":"
"}return e}(),t.del=function(){function e(e){return""+e+""}return e}(),t.link=function(){function e(e,t,n){if(null===(e=J(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"+n+""}return e}(),t.image=function(){function e(e,t,n){if(null===(e=J(this.options.sanitize,this.options.baseUrl,e)))return n;var r='":">"}return e}(),t.text=function(){function e(e){return e}return e}(),e}(),ne=function(){function e(){}var t=e.prototype;return t.strong=function(){function e(e){return e}return e}(),t.em=function(){function e(e){return e}return e}(),t.codespan=function(){function e(e){return e}return e}(),t.del=function(){function e(e){return e}return e}(),t.html=function(){function e(e){return e}return e}(),t.text=function(){function e(e){return e}return e}(),t.link=function(){function e(e,t,n){return""+n}return e}(),t.image=function(){function e(e,t,n){return""+n}return e}(),t.br=function(){function e(){return""}return e}(),e}(),re=function(){function e(){this.seen={}}return e.prototype.slug=function(){function e(e){var t=e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t)){var n=t;do{this.seen[n]++,t=n+"-"+this.seen[n]}while(this.seen.hasOwnProperty(t))}return this.seen[t]=0,t}return e}(),e}(),oe=a.defaults,ie=I.unescape,ae=function(){function e(e){this.options=e||oe,this.options.renderer=this.options.renderer||new te,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new ne,this.slugger=new re}e.parse=function(){function t(t,n){return new e(n).parse(t)}return t}();var t=e.prototype;return t.parse=function(){function e(e,t){void 0===t&&(t=!0);var n,r,o,i,a,u,c,s,l,f,d,p,h,g,v,m,y,b,x="",w=e.length;for(n=0;n
"+se(c.message+"",!0)+"";throw c}}return pe.options=pe.setOptions=function(e){return ue(pe.defaults,e),fe(pe.defaults),pe},pe.getDefaults=le,pe.defaults=de,pe.use=function(e){var t=ue({},e);if(e.renderer&&function(){var n=pe.defaults.renderer||new te,r=function(){function t(t){var r=n[t];n[t]=function(){for(var o=arguments.length,i=new Array(o),a=0;a
'+(n?e:ee(e,!0))+"\n":""+(n?e:ee(e,!0))+"\n"}return e}(),t.blockquote=function(){function e(e){return"\n"+e+"\n"}return e}(),t.html=function(){function e(e){return e}return e}(),t.heading=function(){function e(e,t,n,r){return this.options.headerIds?"
"+e+"
\n"}return e}(),t.table=function(){function e(e,t){return t&&(t=""+t+""),""+e+""}return e}(),t.br=function(){function e(){return this.options.xhtml?""+se(c.message+"",!0)+"";throw c}}return pe.options=pe.setOptions=function(e){return ue(pe.defaults,e),fe(pe.defaults),pe},pe.getDefaults=le,pe.defaults=de,pe.use=function(e){var t=ue({},e);if(e.renderer&&function(){var n=pe.defaults.renderer||new te,r=function(){function t(t){var r=n[t];n[t]=function(){for(var o=arguments.length,i=new Array(o),a=0;a