diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 95e609ee524..e392b468557 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -371,7 +371,15 @@ update_flag
SSnanoui.update_uis(src) // Update all NanoUIs attached to src
-
+/obj/machinery/portable_atmospherics/canister/replace_tank(mob/living/user, close_valve)
+ . = ..()
+ if(.)
+ if(close_valve)
+ valve_open = FALSE
+ update_icon()
+ investigate_log("Valve was closed by [key_name(user)].
", "atmos")
+ else if(valve_open && holding)
+ investigate_log("[key_name(user)] started a transfer into [holding].
", "atmos")
/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob)
src.add_hiddenprint(user)
diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm
index dfecc3a4409..71e1310f96b 100644
--- a/code/game/machinery/atmoalter/portable_atmospherics.dm
+++ b/code/game/machinery/atmoalter/portable_atmospherics.dm
@@ -82,16 +82,49 @@
/obj/machinery/portable_atmospherics/portableConnectorReturnAir()
return air_contents
-/obj/machinery/portable_atmospherics/attackby(var/obj/item/W as obj, var/mob/user as mob, params)
- if((istype(W, /obj/item/tank) && !( src.destroyed )))
- if(src.holding)
- return
- var/obj/item/tank/T = W
- user.drop_item()
- T.loc = src
- src.holding = T
- update_icon()
+/obj/machinery/portable_atmospherics/AltClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
return
+ if(!in_range(src, user))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ if(holding)
+ to_chat(user, "You remove [holding] from [src].")
+ replace_tank(user, TRUE)
+
+/obj/machinery/portable_atmospherics/examine(mob/user)
+ ..()
+ if(holding)
+ to_chat(user, "\The [src] contains [holding]. Alt-click [src] to remove it.")
+
+/obj/machinery/portable_atmospherics/proc/replace_tank(mob/living/user, close_valve, obj/item/tank/new_tank)
+ if(holding)
+ holding.forceMove(drop_location())
+ if(Adjacent(user) && !issilicon(user))
+ user.put_in_hands(holding)
+ if(new_tank)
+ holding = new_tank
+ else
+ holding = null
+ update_icon()
+ return TRUE
+
+/obj/machinery/portable_atmospherics/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/tank))
+ if(!(stat & BROKEN))
+ if(!user.drop_item())
+ return
+ var/obj/item/tank/T = W
+ user.drop_item()
+ if(src.holding)
+ to_chat(user, "[holding ? "In one smooth motion you pop [holding] out of [src]'s connector and replace it with [T]" : "You insert [T] into [src]"].")
+ replace_tank(user, FALSE)
+ T.loc = src
+ src.holding = T
+ update_icon()
+ return
else if(istype(W, /obj/item/wrench))
if(connected_port)
diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm
index a7680e815ff..5bd441f6748 100644
--- a/code/game/machinery/atmoalter/pump.dm
+++ b/code/game/machinery/atmoalter/pump.dm
@@ -95,6 +95,16 @@
/obj/machinery/portable_atmospherics/pump/return_air()
return air_contents
+/obj/machinery/portable_atmospherics/pump/replace_tank(mob/living/user, close_valve)
+ . = ..()
+ if(.)
+ if(close_valve)
+ if(on)
+ on = FALSE
+ update_icon()
+ else if(on && holding && direction_out)
+ investigate_log("[key_name(user)] started a transfer into [holding].
", "atmos")
+
/obj/machinery/portable_atmospherics/pump/attack_ai(var/mob/user as mob)
src.add_hiddenprint(user)
return src.attack_hand(user)
@@ -139,10 +149,14 @@
if(href_list["power"])
on = !on
+ if(on && direction_out)
+ investigate_log("[key_name(usr)] started a transfer into [holding].
", "atmos")
update_icon()
if(href_list["direction"])
direction_out = !direction_out
+ if(on && holding)
+ investigate_log("[key_name(usr)] started a transfer into [holding].
", "atmos")
if(href_list["remove_tank"])
if(holding)