diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm
index 320fdbd900a..bd40f60001f 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 Pump", /obj/machinery/atmospherics/components/binary/temperature_pump, TRUE),
new /datum/pipe_info/meter("Meter"),
),
"Heat Exchange" = list(
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
new file mode 100644
index 00000000000..9fbc082ab29
--- /dev/null
+++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
@@ -0,0 +1,82 @@
+/obj/machinery/atmospherics/components/binary/temperature_pump
+ icon_state = "tpump_map-3"
+ name = "temperature pump"
+ desc = "A pump that moves heat only."
+
+ can_unwrench = TRUE
+ shift_underlay_only = FALSE
+
+ ///Value of the amount of rate of heat exchange
+ var/heat_transfer_rate = 0
+ ///Maximum allowed amount for the heat exchange
+ var/max_heat_transfer_rate = 4500
+
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "tpump"
+
+/obj/machinery/atmospherics/components/binary/temperature_pump/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_pump/AltClick(mob/user)
+ if(can_interact(user) && !(heat_transfer_rate == max_heat_transfer_rate))
+ heat_transfer_rate = max_heat_transfer_rate
+ investigate_log("was set to [heat_transfer_rate] K/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ update_icon()
+ return ..()
+
+/obj/machinery/atmospherics/components/binary/temperature_pump/update_icon_nopipes()
+ icon_state = "tpump_[on && is_operational ? "on" : "off"]-[set_overlay_offset(piping_layer)]"
+
+/obj/machinery/atmospherics/components/binary/temperature_pump/process_atmos()
+
+ if(!on || !is_operational)
+ return
+
+ var/datum/gas_mixture/air_input = airs[1]
+ var/datum/gas_mixture/air_output = airs[2]
+
+ if((air_output.temperature + heat_transfer_rate) >= air_input.temperature || (air_input.temperature - heat_transfer_rate) <= TCRYO)
+ return
+
+ air_input.temperature -= heat_transfer_rate
+ air_output.temperature += heat_transfer_rate
+ update_parents()
+
+/obj/machinery/atmospherics/components/binary/temperature_pump/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "AtmosTempPump", name)
+ ui.open()
+
+/obj/machinery/atmospherics/components/binary/temperature_pump/ui_data()
+ var/data = list()
+ data["on"] = on
+ data["rate"] = round(heat_transfer_rate)
+ data["max_transfer_rate"] = round(max_heat_transfer_rate)
+ return data
+
+/obj/machinery/atmospherics/components/binary/temperature_pump/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("rate")
+ var/rate = params["rate"]
+ if(rate == "max")
+ rate = max_heat_transfer_rate
+ . = TRUE
+ else if(text2num(rate) != null)
+ rate = text2num(rate)
+ . = TRUE
+ if(.)
+ heat_transfer_rate = clamp(rate, 0, max_heat_transfer_rate)
+ investigate_log("was set to [heat_transfer_rate] K/s by [key_name(usr)]", INVESTIGATE_ATMOS)
+ update_icon()
+
diff --git a/icons/obj/atmospherics/components/binary_devices.dmi b/icons/obj/atmospherics/components/binary_devices.dmi
index f7c9c33901f..a4a382423a0 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 eaa3255455e..a2e611b702c 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 b2f0cf8015e..d2f834ed710 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1609,6 +1609,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_pump.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\valve.dm"
#include "code\modules\atmospherics\machinery\components\binary_devices\volume_pump.dm"
#include "code\modules\atmospherics\machinery\components\trinary_devices\filter.dm"
diff --git a/tgui/packages/tgui/interfaces/AtmosTempPump.js b/tgui/packages/tgui/interfaces/AtmosTempPump.js
new file mode 100644
index 00000000000..345fe817f1f
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/AtmosTempPump.js
@@ -0,0 +1,47 @@
+import { useBackend } from '../backend';
+import { Button, LabeledList, NumberInput, Section } from '../components';
+import { Window } from '../layouts';
+
+export const AtmosTempPump = (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