diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index d583084791..3454b1ea7f 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -44,6 +44,8 @@ avoid code duplication. This includes items that may sometimes act as a standard
/mob/living/attackby(obj/item/I, mob/user)
if(!ismob(user))
return 0
+ if(src.Airattackby(I,user))
+ return 0
if(can_operate(src) && I.do_surgery(src,user)) //Surgery
return 1
if(attempt_vr(src,"vore_attackby",args)) return //VOREStation Code
diff --git a/code/modules/mob/airhack.dm b/code/modules/mob/airhack.dm
new file mode 100644
index 0000000000..3d01892f9a
--- /dev/null
+++ b/code/modules/mob/airhack.dm
@@ -0,0 +1,123 @@
+/mob
+ var/datum/gas_mixture/air_contents = new
+
+ var/obj/machinery/atmospherics/portables_connector/connected_port
+ var/obj/item/weapon/tank/holding
+
+ var/volume = 1000
+ var/destroyed = 0
+
+ var/start_pressure = ONE_ATMOSPHERE
+ var/maximum_pressure = 90 * ONE_ATMOSPHERE
+ var/inflatable = 1
+/mob/living
+ inflatable= 0
+/mob/New()
+ ..()
+
+ air_contents.volume = volume
+ air_contents.temperature = T20C
+
+ return 1
+/mob/Destroy()
+ qdel_null(air_contents)
+ qdel_null(holding)
+ . = ..()
+/mob/Life()
+ if(!connected_port) //only react when pipe_network will ont it do it for you
+ //Allow for reactions
+ air_contents.react()
+ . = ..()
+/mob/proc/StandardAirMix()
+ return list(
+ "oxygen" = O2STANDARD * MolesForPressure(),
+ "nitrogen" = N2STANDARD * MolesForPressure())
+/mob/proc/MolesForPressure(var/target_pressure = start_pressure)
+ return (target_pressure * air_contents.volume) / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
+
+/mob/proc/connect(obj/machinery/atmospherics/portables_connector/new_port)
+ //Make sure not already connected to something else
+ if(connected_port || !new_port || new_port.connected_device)
+ return 0
+
+ //Make sure are close enough for a valid connection
+ if(new_port.loc != loc)
+ return 0
+
+ //Perform the connection
+ connected_port = new_port
+ connected_port.connected_device = src
+ connected_port.on = 1 //Activate port updates
+
+ anchored = 1 //Prevent movement
+
+ //Actually enforce the air sharing
+ var/datum/pipe_network/network = connected_port.return_network(src)
+ if(network && !network.gases.Find(air_contents))
+ network.gases += air_contents
+ network.update = 1
+
+ return 1
+
+/mob/proc/disconnect()
+ if(!connected_port)
+ return 0
+
+ var/datum/pipe_network/network = connected_port.return_network(src)
+ if(network)
+ network.gases -= air_contents
+
+ anchored = 0
+
+ connected_port.connected_device = null
+ connected_port = null
+
+ return 1
+
+/mob/proc/update_connected_network()
+ if(!connected_port)
+ return
+
+ var/datum/pipe_network/network = connected_port.return_network(src)
+ if (network)
+ network.update = 1
+
+/mob/proc/Airattackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ if(src.inflatable == 0)
+ return 0
+ if (istype(W, /obj/item/weapon/wrench))
+ if(connected_port)
+ disconnect()
+ user << "You disconnect \the [src] from the port."
+ update_icon()
+ playsound(src, W.usesound, 50, 1)
+ return 1
+ else
+ var/obj/machinery/atmospherics/portables_connector/possible_port = locate(/obj/machinery/atmospherics/portables_connector/) in loc
+ if(possible_port)
+ if(connect(possible_port))
+ user << "You connect \the [src] to the port."
+ update_icon()
+ playsound(src, W.usesound, 50, 1)
+ return 1
+ else
+ user << "\The [src] failed to connect to the port."
+ return 0
+ else
+ return 0
+ else if ((istype(W, /obj/item/device/analyzer)) && Adjacent(user))
+ var/obj/item/device/analyzer/A = W
+ A.analyze_gases(src, user)
+ return 1
+ return 0
+
+/mob/proc/atmosanalyze(var/mob/user)
+ return atmosanalyzer_scan(src, src.air_contents, user)
+
+/datum/trait/inflatable
+ name = "Inflatable"
+ desc = "You were born with an unusual ability to store air like a portable canister"
+ cost = 0
+/datum/trait/inflatable/apply(var/datum/species/S,var/mob/living/carbon/human/H)
+ H.inflatable = 1
+ ..(S,H)
\ No newline at end of file
diff --git a/vorestation.dme b/vorestation.dme
index 69073f19f0..6f3a5716e5 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1898,6 +1898,7 @@
#include "code\modules\mining\orm_vr\construction.dm"
#include "code\modules\mining\orm_vr\equipment_vendor.dm"
#include "code\modules\mining\orm_vr\mine_point_items.dm"
+#include "code\modules\mob\airhack.dm"
#include "code\modules\mob\animations.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\emote.dm"