diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 83fbc6b41c8..009858118ae 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -324,6 +324,7 @@
/obj/machinery/light{
dir = 1
},
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/wood,
/area/library)
"aaL" = (
@@ -62724,6 +62725,7 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{
dir = 4
},
+/obj/structure/tank_holder/oxygen/red,
/turf/open/floor/plasteel,
/area/tcommsat/server)
"cpJ" = (
@@ -68256,12 +68258,6 @@
/area/maintenance/port)
"cAX" = (
/obj/structure/table/reinforced,
-/obj/item/tank/internals/emergency_oxygen{
- pixel_x = 6
- },
-/obj/item/tank/internals/emergency_oxygen{
- pixel_x = -6
- },
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/structure/sign/warning/nosmoking{
@@ -69166,6 +69162,7 @@
/area/maintenance/port)
"cCF" = (
/obj/effect/turf_decal/bot,
+/obj/structure/tank_holder/emergency_oxygen,
/turf/open/floor/plasteel,
/area/maintenance/port)
"cCG" = (
@@ -74448,8 +74445,6 @@
/area/science/xenobiology)
"cMZ" = (
/obj/structure/reagent_dispensers/watertank,
-/obj/item/extinguisher,
-/obj/item/extinguisher,
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/science/xenobiology)
@@ -75269,6 +75264,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 9
},
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/plasteel,
/area/science/xenobiology)
"cOM" = (
@@ -80263,6 +80259,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
+/obj/structure/tank_holder/oxygen,
/turf/open/floor/plasteel,
/area/medical/medbay/central)
"cYd" = (
@@ -84930,6 +84927,7 @@
/obj/effect/turf_decal/tile/blue{
dir = 1
},
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/plasteel/white,
/area/medical/psychology)
"dhw" = (
@@ -106153,8 +106151,8 @@
/area/hallway/secondary/exit/departure_lounge)
"edf" = (
/obj/effect/decal/cleanable/dirt,
-/obj/structure/closet/firecloset,
/obj/effect/turf_decal/delivery,
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/plasteel,
/area/maintenance/port/aft)
"edg" = (
@@ -109022,6 +109020,11 @@
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
+"hBB" = (
+/obj/effect/turf_decal/bot,
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plasteel,
+/area/science/xenobiology)
"hFL" = (
/obj/machinery/stasis,
/obj/effect/turf_decal/tile/blue{
@@ -112133,10 +112136,10 @@
/area/medical/chemistry)
"pND" = (
/obj/effect/decal/cleanable/dirt,
-/obj/item/extinguisher,
/obj/machinery/light/small{
dir = 8
},
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/plating,
/area/maintenance/port)
"pQm" = (
@@ -112899,6 +112902,14 @@
},
/turf/open/floor/plasteel/white,
/area/medical/surgery/room_b)
+"rLP" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/structure/tank_holder/emergency_oxygen,
+/turf/open/floor/plasteel,
+/area/maintenance/starboard)
"rMk" = (
/obj/machinery/newscaster{
pixel_y = -32
@@ -112996,6 +113007,20 @@
/obj/machinery/telecomms/broadcaster/preset_left,
/turf/open/floor/circuit/telecomms/mainframe,
/area/tcommsat/server)
+"rXu" = (
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/obj/structure/tank_holder/oxygen,
+/turf/open/floor/plasteel/dark/telecomms,
+/area/tcommsat/server)
"rYU" = (
/obj/structure/disposalpipe/segment,
/obj/structure/cable,
@@ -113068,6 +113093,20 @@
/obj/effect/decal/remains/xeno,
/turf/open/floor/engine/vacuum,
/area/science/mixing/chamber)
+"sfH" = (
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plasteel/dark/telecomms,
+/area/tcommsat/server)
"sfN" = (
/obj/structure/cable,
/obj/effect/turf_decal/tile/neutral{
@@ -114175,6 +114214,11 @@
},
/turf/open/floor/plasteel/white,
/area/science/research)
+"vec" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/tank_holder/emergency_oxygen,
+/turf/open/floor/plating,
+/area/maintenance/port)
"vjn" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/hydroponics/constructable,
@@ -144473,7 +144517,7 @@ caE
cAZ
cCF
cEm
-ceb
+vec
cHy
caE
cKo
@@ -147315,7 +147359,7 @@ cXk
cYZ
cXk
dcs
-ddT
+hBB
dfd
dgz
cQM
@@ -152674,7 +152718,7 @@ bMw
bOF
bQG
bIH
-bUF
+rXu
bWW
kxh
bUF
@@ -155758,7 +155802,7 @@ bMG
bOP
bQP
bIV
-bUF
+sfH
bXb
bUF
bUF
@@ -165790,7 +165834,7 @@ cff
cgT
ciE
bgZ
-clz
+rLP
cnj
cuE
cqf
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index 592c9665e2c..68a9a6cd11b 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -15884,8 +15884,6 @@
pixel_x = -2;
pixel_y = -1
},
-/obj/item/extinguisher,
-/obj/item/extinguisher,
/obj/machinery/light{
dir = 8
},
@@ -22396,13 +22394,9 @@
"aZJ" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer2,
/obj/structure/table,
-/obj/item/clothing/suit/hooded/wintercoat/security,
-/obj/item/clothing/suit/hooded/wintercoat/security,
-/obj/item/clothing/suit/hooded/wintercoat/security{
- pixel_x = 5
- },
-/obj/item/clothing/suit/hooded/wintercoat{
- pixel_x = -5
+/obj/item/flashlight{
+ pixel_x = 1;
+ pixel_y = 5
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
@@ -22410,6 +22404,18 @@
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
+/obj/item/clothing/suit/hooded/wintercoat{
+ pixel_x = -5
+ },
+/obj/item/clothing/suit/hooded/wintercoat/security{
+ pixel_x = 5
+ },
+/obj/item/clothing/suit/hooded/wintercoat/security{
+ pixel_x = 5
+ },
+/obj/item/clothing/suit/hooded/wintercoat/security{
+ pixel_x = 5
+ },
/turf/open/floor/plasteel/dark,
/area/security/execution/transfer)
"aZK" = (
@@ -22429,6 +22435,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
+/obj/structure/tank_holder/anesthetic,
/turf/open/floor/plasteel/dark,
/area/security/execution/transfer)
"aZO" = (
@@ -23189,18 +23196,6 @@
/turf/open/floor/plating,
/area/maintenance/port)
"bbJ" = (
-/obj/structure/rack,
-/obj/item/flashlight{
- pixel_x = 1;
- pixel_y = 5
- },
-/obj/item/tank/internals/anesthetic{
- pixel_x = -3;
- pixel_y = 1
- },
-/obj/item/tank/internals/oxygen/red{
- pixel_x = 3
- },
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
@@ -23208,6 +23203,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/tank_holder/oxygen/red,
/turf/open/floor/plasteel/dark,
/area/security/execution/transfer)
"bbK" = (
@@ -23581,7 +23577,7 @@
/turf/open/floor/plasteel,
/area/vacant_room/commissary)
"bcI" = (
-/obj/structure/closet/emcloset,
+/obj/structure/tank_holder/oxygen,
/turf/open/floor/plating,
/area/maintenance/port)
"bcK" = (
@@ -36156,6 +36152,7 @@
pixel_y = 27;
receive_ore_updates = 1
},
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/plasteel,
/area/science/xenobiology)
"bIv" = (
@@ -39073,12 +39070,12 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"bSt" = (
-/obj/structure/closet/emcloset,
/obj/machinery/camera{
c_tag = "Telecomms Monitoring";
dir = 8;
network = list("tcomms")
},
+/obj/structure/tank_holder/oxygen,
/turf/open/floor/plasteel,
/area/tcommsat/computer)
"bSv" = (
@@ -39901,10 +39898,10 @@
/obj/structure/disposalpipe/segment{
dir = 4
},
-/obj/structure/closet/emcloset,
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
dir = 4
},
+/obj/structure/tank_holder/oxygen,
/turf/open/floor/plating,
/area/maintenance/port/aft)
"bVC" = (
@@ -43497,7 +43494,7 @@
/turf/open/floor/plasteel/dark,
/area/crew_quarters/heads/chief)
"cjV" = (
-/obj/structure/closet/emcloset,
+/obj/structure/tank_holder/oxygen,
/turf/open/floor/plasteel,
/area/engine/engineering)
"cjX" = (
@@ -49617,6 +49614,10 @@
},
/turf/open/floor/plating,
/area/maintenance/aft)
+"ffa" = (
+/obj/structure/tank_holder/oxygen/red,
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
"fie" = (
/obj/structure/closet/bombcloset,
/obj/structure/extinguisher_cabinet{
@@ -50339,6 +50340,10 @@
/obj/structure/disposalpipe/segment,
/turf/open/floor/plating,
/area/maintenance/fore)
+"hhu" = (
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
"hjZ" = (
/turf/open/floor/plasteel/white,
/area/medical/medbay)
@@ -50381,6 +50386,12 @@
},
/turf/open/floor/plating,
/area/maintenance/aft)
+"hyy" = (
+/obj/structure/tank_holder/extinguisher{
+ pixel_y = 8
+ },
+/turf/open/floor/plasteel,
+/area/ai_monitored/storage/eva)
"hzQ" = (
/obj/structure/grille,
/turf/open/floor/plating,
@@ -50848,6 +50859,11 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
/turf/open/floor/plasteel/dark,
/area/crew_quarters/heads/cmo)
+"jbq" = (
+/obj/structure/cable,
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
"jcM" = (
/obj/structure/cable,
/turf/open/floor/plating,
@@ -53911,6 +53927,10 @@
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/medical/medbay)
+"pYU" = (
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plating,
+/area/maintenance/port)
"pZN" = (
/obj/effect/turf_decal/tile/blue{
dir = 1
@@ -54613,6 +54633,10 @@
/obj/structure/cable,
/turf/open/floor/plating,
/area/maintenance/port)
+"srU" = (
+/obj/structure/tank_holder,
+/turf/open/floor/plating,
+/area/maintenance/aft)
"stP" = (
/obj/machinery/atmospherics/pipe/multiz/layer2{
color = "#ff0000";
@@ -55640,6 +55664,10 @@
/obj/machinery/door/firedoor,
/turf/open/floor/plasteel/dark,
/area/medical/medbay/aft)
+"vhE" = (
+/obj/structure/tank_holder/emergency_oxygen,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"vjZ" = (
/obj/effect/turf_decal/trimline/blue/filled/line,
/obj/machinery/power/apc{
@@ -55831,6 +55859,10 @@
},
/turf/open/floor/grass,
/area/hydroponics/garden)
+"vKc" = (
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plating,
+/area/maintenance/aft)
"vLr" = (
/obj/effect/turf_decal/trimline/blue/filled/warning{
dir = 8
@@ -56492,6 +56524,10 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/port)
+"xpA" = (
+/obj/structure/tank_holder/extinguisher,
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"xqe" = (
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
@@ -72492,7 +72528,7 @@ aPz
aPz
aPz
aPz
-aSg
+pYU
aWj
aXP
aZr
@@ -82504,7 +82540,7 @@ aAW
aCa
aDB
aDI
-azW
+hyy
azW
azW
ayW
@@ -83532,7 +83568,7 @@ aBq
apX
aDE
aFc
-azW
+hyy
azW
aJf
ayW
@@ -96962,7 +96998,7 @@ bzs
bAw
bzs
bAw
-bAw
+vKc
bzs
bAw
bAw
@@ -98950,7 +98986,7 @@ alP
anf
vvP
alP
-anf
+ffa
aFm
aGF
aIp
@@ -100480,7 +100516,7 @@ boP
boP
boP
alO
-anf
+hhu
anf
asy
anf
@@ -102028,7 +102064,7 @@ anf
anf
anf
alP
-arr
+jbq
arr
arr
arr
@@ -102610,7 +102646,7 @@ pTj
nyR
bQZ
kKU
-bAw
+srU
stP
xMA
caK
@@ -103650,7 +103686,7 @@ hBY
cmr
tkC
bYs
-cOe
+vhE
kZR
cNW
cOe
@@ -108011,7 +108047,7 @@ cOe
cOe
cfv
cBL
-cOe
+xpA
cNW
boP
boP
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index fccf1aaeccd..844f70d43bb 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -822,3 +822,7 @@
#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt"
///from monkey CtrlClickOn(): (/mob)
#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl"
+
+// /datum/component/container_item
+/// (atom/container, mob/user) - returns bool
+#define COMSIG_CONTAINER_TRY_ATTACH "container_try_attach"
diff --git a/code/datums/components/container_item/container_item.dm b/code/datums/components/container_item/container_item.dm
new file mode 100644
index 00000000000..fda012cb0ea
--- /dev/null
+++ b/code/datums/components/container_item/container_item.dm
@@ -0,0 +1,10 @@
+/// Container item, an item which can be stored by specialized containers.
+/datum/component/container_item
+
+/datum/component/container_item/Initialize()
+ . = ..()
+ RegisterSignal(parent, COMSIG_CONTAINER_TRY_ATTACH, .proc/try_attach)
+
+/// Called when parent is added to the container.
+/datum/component/container_item/proc/try_attach(datum/source, atom/container, mob/user)
+ return FALSE
diff --git a/code/datums/components/container_item/tank_holder.dm b/code/datums/components/container_item/tank_holder.dm
new file mode 100644
index 00000000000..b68c413519c
--- /dev/null
+++ b/code/datums/components/container_item/tank_holder.dm
@@ -0,0 +1,31 @@
+/// Tank holder item - Added to an object which can be added to a tank holder.
+/datum/component/container_item/tank_holder
+ var/tank_holder_icon_state
+ var/make_density
+
+/datum/component/container_item/tank_holder/Initialize(state, density = TRUE)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ tank_holder_icon_state = state
+ make_density = density
+ return ..()
+
+/datum/component/container_item/tank_holder/try_attach(datum/source, obj/structure/tank_holder/container, mob/user)
+ if(!container || !istype(container))
+ return FALSE
+ var/obj/item/I = parent
+ if(container.contents.len)
+ if(user)
+ to_chat(user, "There's already something in [container].")
+ return TRUE
+ if(user)
+ if(!user.transferItemToLoc(I, container))
+ return TRUE
+ to_chat(user, "You put [I] into [container].")
+ else
+ I.forceMove(container)
+ container.tank = I
+ container.density = make_density
+ container.icon_state = tank_holder_icon_state
+ return TRUE
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index cb8a93e7e08..aaaed813409 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -187,7 +187,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
var/canMouseDown = FALSE
-
/obj/item/Initialize()
if(attack_verb_continuous)
diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm
index f25eb0a9206..f4902e9cd90 100644
--- a/code/game/objects/items/extinguisher.dm
+++ b/code/game/objects/items/extinguisher.dm
@@ -26,6 +26,8 @@
var/power = 5 //Maximum distance launched water will travel
var/precision = FALSE //By default, turfs picked from a spray are random, set to 1 to make it always have at least one water effect per row
var/cooling_power = 2 //Sets the cooling_temperature of the water reagent datum inside of the extinguisher when it is refilled
+ /// Icon state when inside a tank holder
+ var/tank_holder_icon_state = "holder_extinguisher"
/obj/item/extinguisher/mini
name = "pocket fire extinguisher"
@@ -52,11 +54,17 @@
. = ..()
refill()
+/obj/item/extinguisher/ComponentInitialize()
+ . = ..()
+ if(tank_holder_icon_state)
+ AddComponent(/datum/component/container_item/tank_holder, tank_holder_icon_state)
+
/obj/item/extinguisher/advanced
name = "advanced fire extinguisher"
desc = "Used to stop thermonuclear fires from spreading inside your engine."
icon_state = "foam_extinguisher0"
inhand_icon_state = "foam_extinguisher"
+ tank_holder_icon_state = "holder_foam_extinguisher"
dog_fashion = null
chem = /datum/reagent/firefighting_foam
tanktype = /obj/structure/reagent_dispensers/foamtank
diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm
index b88a8be22df..78f18e0a3d7 100644
--- a/code/game/objects/items/miscellaneous.dm
+++ b/code/game/objects/items/miscellaneous.dm
@@ -323,6 +323,10 @@
attack_verb_continuous = list("skubs")
attack_verb_simple = list("skub")
+/obj/item/skub/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/container_item/tank_holder, "holder_skub", FALSE)
+
/obj/item/skub/suicide_act(mob/living/user)
user.visible_message("[user] has declared themself as anti-skub! The skub tears them apart!")
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index dbc19cf3e5c..ed060e0be29 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -4,6 +4,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
new/datum/stack_recipe("scooter frame", /obj/item/scooter_frame, 10, time = 25, one_per_turf = FALSE), \
new/datum/stack_recipe("linen bin", /obj/structure/bedsheetbin/empty, 2, time = 5, one_per_turf = FALSE), \
new/datum/stack_recipe("railing", /obj/structure/railing, 3, time = 18, window_checks = TRUE), \
+ new/datum/stack_recipe("tank holder", /obj/structure/tank_holder, 2, time = 5, one_per_turf = TRUE, on_floor = FALSE), \
))
/obj/item/stack/rods
diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm
index 0a29033691e..c998e10af1e 100644
--- a/code/game/objects/items/tanks/tank_types.dm
+++ b/code/game/objects/items/tanks/tank_types.dm
@@ -15,6 +15,7 @@
name = "oxygen tank"
desc = "A tank of oxygen, this one is blue."
icon_state = "oxygen"
+ tank_holder_icon_state = "holder_oxygen"
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
force = 10
dog_fashion = /datum/dog_fashion/back
@@ -28,11 +29,13 @@
/obj/item/tank/internals/oxygen/yellow
desc = "A tank of oxygen, this one is yellow."
icon_state = "oxygen_f"
+ tank_holder_icon_state = "holder_oxygen_f"
dog_fashion = null
/obj/item/tank/internals/oxygen/red
desc = "A tank of oxygen, this one is red."
icon_state = "oxygen_fr"
+ tank_holder_icon_state = "holder_oxygen_fr"
dog_fashion = null
/obj/item/tank/internals/oxygen/empty/populate_gas()
@@ -46,6 +49,7 @@
desc = "A tank with an N2O/O2 gas mix."
icon_state = "anesthetic"
inhand_icon_state = "an_tank"
+ tank_holder_icon_state = "holder_oxygen_anesthetic"
force = 10
/obj/item/tank/internals/anesthetic/populate_gas()
@@ -61,6 +65,7 @@
desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable."
icon_state = "plasma"
worn_icon_state = "plasmatank"
+ tank_holder_icon_state = null
flags_1 = CONDUCT_1
slot_flags = null //they have no straps!
force = 8
@@ -99,6 +104,7 @@
desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this."
icon_state = "plasmaman_tank"
inhand_icon_state = "plasmaman_tank"
+ tank_holder_icon_state = null
force = 10
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
@@ -115,6 +121,7 @@
icon_state = "plasmaman_tank_belt"
inhand_icon_state = "plasmaman_tank_belt"
worn_icon_state = "plasmaman_tank_belt"
+ tank_holder_icon_state = null
worn_icon = null
slot_flags = ITEM_SLOT_BELT
force = 5
@@ -138,6 +145,7 @@
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
icon_state = "emergency"
worn_icon_state = "emergency"
+ tank_holder_icon_state = "holder_emergency"
worn_icon = null
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
@@ -159,6 +167,7 @@
name = "extended-capacity emergency oxygen tank"
icon_state = "emergency_engi"
worn_icon_state = "emergency_engi"
+ tank_holder_icon_state = "holder_emergency_engi"
worn_icon = null
volume = 6 // should last 24 minutes if full
@@ -168,6 +177,7 @@
/obj/item/tank/internals/emergency_oxygen/double
name = "double emergency oxygen tank"
icon_state = "emergency_double"
+ tank_holder_icon_state = null
volume = 24
/obj/item/tank/internals/emergency_oxygen/double/empty/populate_gas()
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index 0fcf25f03ee..3aba2a129bf 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -20,6 +20,8 @@
var/distribute_pressure = ONE_ATMOSPHERE
var/integrity = 3
var/volume = 70
+ /// Icon state when in a tank holder. Null makes it incompatible with tank holder.
+ var/tank_holder_icon_state = "holder_generic"
/obj/item/tank/ui_action_click(mob/user)
toggle_internals(user)
@@ -74,6 +76,11 @@
STOP_PROCESSING(SSobj, src)
. = ..()
+/obj/item/tank/ComponentInitialize()
+ . = ..()
+ if(tank_holder_icon_state)
+ AddComponent(/datum/component/container_item/tank_holder, tank_holder_icon_state)
+
/obj/item/tank/examine(mob/user)
var/obj/icon = src
. = ..()
diff --git a/code/game/objects/structures/tank_holder.dm b/code/game/objects/structures/tank_holder.dm
new file mode 100644
index 00000000000..3e9d0cbd4c5
--- /dev/null
+++ b/code/game/objects/structures/tank_holder.dm
@@ -0,0 +1,127 @@
+///?
+/obj/structure/tank_holder
+ name = "tank holder"
+ desc = "A metallic frame that can hold tanks and extinguishers."
+ icon = 'icons/obj/tank.dmi'
+ icon_state = "holder"
+
+ custom_materials = list(/datum/material/iron = 2000)
+
+ density = FALSE
+ anchored = FALSE
+ pass_flags = LETPASSTHROW
+ max_integrity = 20
+
+ resistance_flags = FIRE_PROOF
+
+ /// The stored tank. If this is a path, it gets created into contents at Initialize.
+ var/obj/item/tank
+
+/obj/structure/tank_holder/Initialize()
+ . = ..()
+ if(tank)
+ var/obj/item/tank_ = new tank(null)
+ tank = null
+ SEND_SIGNAL(tank_, COMSIG_CONTAINER_TRY_ATTACH, src, null)
+
+/obj/structure/tank_holder/Destroy()
+ QDEL_NULL(tank)
+ return ..()
+
+/obj/structure/tank_holder/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(istype(mover) && mover.throwing)
+ return TRUE
+
+/obj/structure/tank_holder/examine(mob/user)
+ . = ..()
+ . += "It is held together by some screws."
+
+/obj/structure/tank_holder/attackby(obj/item/W, mob/user, params)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+ if(!SEND_SIGNAL(W, COMSIG_CONTAINER_TRY_ATTACH, src, user))
+ to_chat(user, "[W] does not fit in [src].")
+
+/obj/structure/tank_holder/screwdriver_act(mob/living/user, obj/item/I)
+ if(..())
+ return TRUE
+ if(tank)
+ return FALSE
+ I.play_tool_sound(src)
+ deconstruct(TRUE)
+ return TRUE
+
+/obj/structure/tank_holder/deconstruct(disassembled = TRUE)
+ var/atom/Tsec = drop_location()
+ new /obj/item/stack/rods(Tsec, 2)
+ if(tank)
+ tank.forceMove(Tsec)
+ after_detach_tank()
+ qdel(src)
+
+/obj/structure/tank_holder/attack_paw(mob/user)
+ return attack_hand(user)
+
+/obj/structure/tank_holder/attack_hand(mob/user)
+ if(!tank)
+ return ..()
+ if(!Adjacent(user) || issilicon(user))
+ return ..()
+ to_chat(user, "You take [tank] from [src].")
+ add_fingerprint(user)
+ tank.add_fingerprint(user)
+ user.put_in_hands(tank)
+ after_detach_tank()
+
+/obj/structure/tank_holder/handle_atom_del(atom/A)
+ if(A == tank)
+ after_detach_tank()
+ return ..()
+
+/obj/structure/tank_holder/contents_explosion(severity, target)
+ if(tank)
+ tank.ex_act(severity, target)
+
+/// Call this after taking the tank from contents in order to update references, icon
+/// and density.
+/obj/structure/tank_holder/proc/after_detach_tank()
+ tank = null
+ density = FALSE
+ icon_state = "holder"
+
+/obj/structure/tank_holder/oxygen
+ icon_state = "holder_oxygen"
+ tank = /obj/item/tank/internals/oxygen
+
+/obj/structure/tank_holder/anesthetic
+ icon_state = "holder_anesthetic"
+ tank = /obj/item/tank/internals/anesthetic
+
+/obj/structure/tank_holder/oxygen/yellow
+ icon_state = "holder_oxygen_f"
+ tank = /obj/item/tank/internals/oxygen/yellow
+
+/obj/structure/tank_holder/oxygen/red
+ icon_state = "holder_oxygen_fr"
+ tank = /obj/item/tank/internals/oxygen/red
+
+/obj/structure/tank_holder/emergency_oxygen
+ icon_state = "holder_emergency"
+ tank = /obj/item/tank/internals/emergency_oxygen
+
+/obj/structure/tank_holder/emergency_oxygen/engi
+ icon_state = "holder_emergency_engi"
+ tank = /obj/item/tank/internals/emergency_oxygen/engi
+
+/obj/structure/tank_holder/generic
+ icon_state = "holder_generic"
+ tank = /obj/item/tank/internals/generic
+
+/obj/structure/tank_holder/extinguisher
+ icon_state = "holder_extinguisher"
+ tank = /obj/item/extinguisher
+
+/obj/structure/tank_holder/extinguisher/advanced
+ icon_state = "holder_foam_extinguisher"
+ tank = /obj/item/extinguisher/advanced
diff --git a/icons/obj/tank.dmi b/icons/obj/tank.dmi
index 15855e8610e..e6945ac7b9a 100644
Binary files a/icons/obj/tank.dmi and b/icons/obj/tank.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index f58136cfb99..cd76edd91d4 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -494,6 +494,8 @@
#include "code\datums\components\uplink.dm"
#include "code\datums\components\wearertargeting.dm"
#include "code\datums\components\wet_floor.dm"
+#include "code\datums\components\container_item\container_item.dm"
+#include "code\datums\components\container_item\tank_holder.dm"
#include "code\datums\components\crafting\crafting.dm"
#include "code\datums\components\crafting\guncrafting.dm"
#include "code\datums\components\crafting\recipes.dm"
@@ -1250,6 +1252,7 @@
#include "code\game\objects\structures\table_frames.dm"
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
+#include "code\game\objects\structures\tank_holder.dm"
#include "code\game\objects\structures\target_stake.dm"
#include "code\game\objects\structures\traps.dm"
#include "code\game\objects\structures\votingbox.dm"