diff --git a/code/defines/obj/storage.dm b/code/defines/obj/storage.dm
index c52bd713cd6..7a543e3022b 100644
--- a/code/defines/obj/storage.dm
+++ b/code/defines/obj/storage.dm
@@ -180,11 +180,6 @@
icon_state = "satchel-cap"
item_state = "captainpack"
-/obj/item/weapon/storage/backpack/bandolier
- name = "bandolier"
- desc = "It's a very old bandolier to wear on your back."
- icon_state = "bandolier"
-
/obj/item/weapon/storage/backpack/industrial
name = "industrial backpack"
desc = "It's a tough backpack for the daily grind of station life."
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
new file mode 100644
index 00000000000..0b018d5187c
--- /dev/null
+++ b/code/game/objects/structures/safe.dm
@@ -0,0 +1,164 @@
+/obj/structure/safe
+ name = "safe"
+ desc = "A huge chunk of metal with a dial embedded in it. Fine print on the dial reads \"Scarborough Arms - 2 tumbler safe, guaranteed thermite resistant, explosion resistant, and assistant resistant.\""
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "safe"
+ anchored = 1
+ density = 1
+ var/open = 0 //is the safe open?
+ var/tumbler_1_pos //the tumbler position- from 0 to 72
+ var/tumbler_1_open //the tumbler position to open at- 0 to 72
+ var/tumbler_2_pos
+ var/tumbler_2_open
+ var/dial = 0 //where is the dial pointing?
+ var/space = 0 //the combined w_class of everything in the safe
+ var/maxspace = 24 //the maximum combined w_class of stuff in the safe
+
+
+/obj/structure/safe/New()
+ tumbler_1_pos = round(rand(0, 72))
+ tumbler_1_open = round(rand(0, 72))
+
+ tumbler_2_pos = round(rand(0, 72))
+ tumbler_2_open = round(rand(0, 72))
+
+
+/obj/structure/safe/initialize()
+ for(var/obj/item/I in loc)
+ if(space >= maxspace)
+ return
+ if(I.w_class + space <= maxspace)
+ space += I.w_class
+ I.loc = src
+
+
+/obj/structure/safe/proc/check_unlocked(mob/user as mob, canhear)
+ if(user && canhear)
+ if(tumbler_1_pos == tumbler_1_open)
+ user << "You hear a [pick("tonk", "krunk", "plunk")] from [src]."
+ if(tumbler_2_pos == tumbler_2_open)
+ user << "You hear a [pick("tink", "krink", "plink")] from [src]."
+ if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open)
+ if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!")
+ return 1
+ return 0
+
+
+/obj/structure/safe/proc/decrement(num)
+ num -= 1
+ if(num < 0)
+ num = 71
+ return num
+
+
+/obj/structure/safe/proc/increment(num)
+ num += 1
+ if(num > 71)
+ num = 0
+ return num
+
+
+/obj/structure/safe/update_icon()
+ if(open)
+ icon_state = "[initial(icon_state)]-open"
+ else
+ icon_state = initial(icon_state)
+
+
+/obj/structure/safe/attack_hand(mob/user as mob)
+ user.machine = src
+ var/dat = "
"
+ dat += "[open ? "Close" : "Open"] [src] | - [dial * 5] +"
+ if(open)
+ dat += ""
+ for(var/i = contents.len, i>=1, i--)
+ var/obj/item/P = contents[i]
+ dat += "| [P.name] |
"
+ dat += "
"
+ user << browse("[name][dat]", "window=safe;size=350x300")
+
+
+/obj/structure/safe/Topic(href, href_list)
+ if(!ishuman(usr)) return
+ var/mob/living/carbon/human/user = usr
+
+ var/canhear = 0
+ if(istype(user.l_hand, /obj/item/clothing/tie/stethoscope) || istype(user.r_hand, /obj/item/clothing/tie/stethoscope))
+ canhear = 1
+
+ if(href_list["open"])
+ if(check_unlocked())
+ user << "You [open ? "close" : "open"] [src]."
+ open = !open
+ update_icon()
+ updateUsrDialog()
+ return
+ else
+ user << "You can't [open ? "close" : "open"] [src], the lock is engaged!"
+ return
+
+ if(href_list["decrement"])
+ dial = decrement(dial)
+ if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71)
+ tumbler_1_pos = decrement(tumbler_1_pos)
+ if(canhear)
+ user << "You hear a [pick("clack", "scrape", "clank")] from [src]."
+ if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35)
+ tumbler_2_pos = decrement(tumbler_2_pos)
+ if(canhear)
+ user << "You hear a [pick("click", "chink", "clink")] from [src]."
+ check_unlocked(user, canhear)
+ updateUsrDialog()
+ return
+
+ if(href_list["increment"])
+ dial = increment(dial)
+ if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71)
+ tumbler_1_pos = increment(tumbler_1_pos)
+ if(canhear)
+ user << "You hear a [pick("clack", "scrape", "clank")] from [src]."
+ if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35)
+ tumbler_2_pos = increment(tumbler_2_pos)
+ if(canhear)
+ user << "You hear a [pick("click", "chink", "clink")] from [src]."
+ check_unlocked(user, canhear)
+ updateUsrDialog()
+ return
+
+ if(href_list["retrieve"])
+ user << browse("", "window=safe") // Close the menu
+
+ var/obj/item/P = locate(href_list["retrieve"])
+ if(P && in_range(src, user))
+ user.put_in_hands(P)
+ updateUsrDialog()
+
+
+/obj/structure/safe/attackby(obj/item/I as obj, mob/user as mob)
+ if(open)
+ if(I.w_class + space <= maxspace)
+ space += I.w_class
+ user.drop_item()
+ I.loc = src
+ user << "You put [I] in [src]."
+ updateUsrDialog()
+ return
+ else
+ user << "[I] won't fit in [src]."
+ return
+ else
+ if(istype(I, /obj/item/clothing/tie/stethoscope))
+ user << "Hold [I] in one of your hands while you manipulate the dial."
+ return
+
+
+obj/structure/safe/blob_act()
+ return
+
+
+obj/structure/safe/ex_act(severity)
+ return
+
+
+obj/structure/safe/meteorhit(obj/O as obj)
+ return
\ No newline at end of file
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 45da622f009..744ccdc28c9 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -861,7 +861,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/hgpirate(M), slot_wear_suit)
- M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/bandolier(M), slot_back)
+ M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back)
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(M), slot_belt)
M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform)
var/obj/item/weapon/card/id/W = new(M)
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index 4009b683b7d..f169e6e1393 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi
index 808cf775f64..37aab81a3d4 100644
Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 79a55391560..7d2360b7c95 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -746,6 +746,7 @@
#include "code\game\objects\structures\morgue.dm"
#include "code\game\objects\structures\musician.dm"
#include "code\game\objects\structures\noticeboard.dm"
+#include "code\game\objects\structures\safe.dm"
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\target_stake.dm"
#include "code\game\objects\structures\watercloset.dm"