diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index b464ea130c..97bf61779f 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -53,6 +53,9 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
// TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
#define TESLA_IGNORE_2 512
+// Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
+#define NO_MAT_REDEMPTION_2 1024
+
//turf-only flags
#define NOJAUNT_1 1
#define UNUSED_TRANSIT_TURF_1 2
diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm
index b82f02353c..1fcc54ac2a 100644
--- a/code/game/mecha/equipment/tools/work_tools.dm
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -196,6 +196,7 @@
equip_cooldown = 10
energy_drain = 250
range = MELEE|RANGED
+ flags_2 = NO_MAT_REDEMPTION_2
var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
/obj/item/mecha_parts/mecha_equipment/rcd/New()
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 6e094a5bbb..a2f80a94a9 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -123,6 +123,7 @@ obj/item/construction
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
max_matter = 160
+ flags_2 = NO_MAT_REDEMPTION_2
var/mode = 1
var/canRturf = 0
var/ranged = FALSE
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index 2cb6c5b93f..d0dc220d4d 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -1,70 +1,71 @@
-
-/obj/item/bodybag
- name = "body bag"
- desc = "A folded bag designed for the storage and transportation of cadavers."
- icon = 'icons/obj/bodybag.dmi'
- icon_state = "bodybag_folded"
- var/unfoldedbag_path = /obj/structure/closet/body_bag
- w_class = WEIGHT_CLASS_SMALL
-
-/obj/item/bodybag/attack_self(mob/user)
- deploy_bodybag(user, user.loc)
-
-/obj/item/bodybag/afterattack(atom/target, mob/user, proximity)
- if(proximity)
- if(isopenturf(target))
- deploy_bodybag(user, target)
-
-/obj/item/bodybag/proc/deploy_bodybag(mob/user, atom/location)
- var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
- R.open(user)
- R.add_fingerprint(user)
- qdel(src)
-
-
-// Bluespace bodybag
-
-/obj/item/bodybag/bluespace
- name = "bluespace body bag"
- desc = "A folded bluespace body bag designed for the storage and transportation of cadavers."
- icon = 'icons/obj/bodybag.dmi'
- icon_state = "bluebodybag_folded"
- unfoldedbag_path = /obj/structure/closet/body_bag/bluespace
- w_class = WEIGHT_CLASS_SMALL
- origin_tech = "bluespace=4;materials=4;plasmatech=4"
-
-/obj/item/bodybag/bluespace/examine(mob/user)
- ..()
- if(contents.len)
- to_chat(user, "You can make out the shapes of [contents.len] objects through the fabric.")
-
-/obj/item/bodybag/bluespace/Destroy()
- for(var/atom/movable/A in contents)
- A.forceMove(get_turf(src))
- if(isliving(A))
- to_chat(A, "You suddenly feel the space around you torn apart! You're free!")
- return ..()
-
-/obj/item/bodybag/bluespace/deploy_bodybag(mob/user, atom/location)
- var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
- for(var/atom/movable/A in contents)
- A.forceMove(R)
- if(isliving(A))
- to_chat(A, "You suddenly feel air around you! You're free!")
- R.open(user)
- R.add_fingerprint(user)
- qdel(src)
-
-/obj/item/bodybag/bluespace/container_resist(mob/living/user)
- if(user.incapacitated())
- to_chat(user, "You can't get out while you're restrained like this!")
- return
- user.changeNext_move(CLICK_CD_BREAKOUT)
- user.last_special = world.time + CLICK_CD_BREAKOUT
- to_chat(user, "You claw at the fabric of [src], trying to tear it open...")
- to_chat(loc, "Someone starts trying to break free of [src]!")
- if(!do_after(user, 200, target = src))
- to_chat(loc, "The pressure subsides. It seems that they've stopped resisting...")
- return
- loc.visible_message("[user] suddenly appears in front of [loc]!", "[user] breaks free of [src]!")
- qdel(src)
+/obj/item/bodybag
+ name = "body bag"
+ desc = "A folded bag designed for the storage and transportation of cadavers."
+ icon = 'icons/obj/bodybag.dmi'
+ icon_state = "bodybag_folded"
+ var/unfoldedbag_path = /obj/structure/closet/body_bag
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/bodybag/attack_self(mob/user)
+ deploy_bodybag(user, user.loc)
+
+/obj/item/bodybag/afterattack(atom/target, mob/user, proximity)
+ if(proximity)
+ if(isopenturf(target))
+ deploy_bodybag(user, target)
+
+/obj/item/bodybag/proc/deploy_bodybag(mob/user, atom/location)
+ var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
+ R.open(user)
+ R.add_fingerprint(user)
+ qdel(src)
+
+
+// Bluespace bodybag
+
+/obj/item/bodybag/bluespace
+ name = "bluespace body bag"
+ desc = "A folded bluespace body bag designed for the storage and transportation of cadavers."
+ icon = 'icons/obj/bodybag.dmi'
+ icon_state = "bluebodybag_folded"
+ unfoldedbag_path = /obj/structure/closet/body_bag/bluespace
+ w_class = WEIGHT_CLASS_SMALL
+ flags_2 = NO_MAT_REDEMPTION_2
+ origin_tech = "bluespace=4;materials=4;plasmatech=4"
+
+/obj/item/bodybag/bluespace/examine(mob/user)
+ ..()
+ if(contents.len)
+ to_chat(user, "You can make out the shapes of [contents.len] objects through the fabric.")
+
+/obj/item/bodybag/bluespace/Destroy()
+ for(var/atom/movable/A in contents)
+ A.forceMove(get_turf(src))
+ if(isliving(A))
+ to_chat(A, "You suddenly feel the space around you torn apart! You're free!")
+ return ..()
+
+/obj/item/bodybag/bluespace/deploy_bodybag(mob/user, atom/location)
+ var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location)
+ for(var/atom/movable/A in contents)
+ A.forceMove(R)
+ if(isliving(A))
+ to_chat(A, "You suddenly feel air around you! You're free!")
+ R.open(user)
+ R.add_fingerprint(user)
+ qdel(src)
+
+/obj/item/bodybag/bluespace/container_resist(mob/living/user)
+ if(user.incapacitated())
+ to_chat(user, "You can't get out while you're restrained like this!")
+ return
+ user.changeNext_move(CLICK_CD_BREAKOUT)
+ user.last_special = world.time + CLICK_CD_BREAKOUT
+ to_chat(user, "You claw at the fabric of [src], trying to tear it open...")
+ to_chat(loc, "Someone starts trying to break free of [src]!")
+ if(!do_after(user, 200, target = src))
+ to_chat(loc, "The pressure subsides. It seems that they've stopped resisting...")
+ return
+ loc.visible_message("[user] suddenly appears in front of [loc]!", "[user] breaks free of [src]!")
+ qdel(src)
+
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 2290ea91d3..3e9231f562 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -40,6 +40,7 @@
max_w_class = WEIGHT_CLASS_GIGANTIC
max_combined_w_class = 35
resistance_flags = FIRE_PROOF
+ flags_2 = NO_MAT_REDEMPTION_2
var/pshoom = 'sound/items/pshoom.ogg'
var/alt_sound = 'sound/items/pshoom_2.ogg'
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 60, acid = 50)
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 8615e1cf8c..638313386e 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -1,381 +1,382 @@
-/*
- * These absorb the functionality of the plant bag, ore satchel, etc.
- * They use the use_to_pickup, quick_gather, and quick_empty functions
- * that were already defined in weapon/storage, but which had been
- * re-implemented in other classes.
- *
- * Contains:
- * Trash Bag
- * Mining Satchel
- * Plant Bag
- * Sheet Snatcher
- * Book Bag
- * Biowaste Bag
- *
- * -Sayu
- */
-
-// Generic non-item
-/obj/item/storage/bag
- allow_quick_gather = 1
- allow_quick_empty = 1
- display_contents_with_number = 1 // should work fine now
- use_to_pickup = 1
- slot_flags = SLOT_BELT
-
-// -----------------------------
-// Trash bag
-// -----------------------------
-/obj/item/storage/bag/trash
- name = "trash bag"
- desc = "It's the heavy-duty black polymer kind. Time to take out the trash!"
- icon = 'icons/obj/janitor.dmi'
- icon_state = "trashbag"
- item_state = "trashbag"
- lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
-
- w_class = WEIGHT_CLASS_BULKY
- max_w_class = WEIGHT_CLASS_SMALL
- max_combined_w_class = 30
- storage_slots = 30
- can_hold = list() // any
- cant_hold = list(/obj/item/disk/nuclear)
-
-/obj/item/storage/bag/trash/suicide_act(mob/user)
- user.visible_message("[user] puts [src] over [user.p_their()] head and starts chomping at the insides! Disgusting!")
- playsound(loc, 'sound/items/eatfood.ogg', 50, 1, -1)
- return (TOXLOSS)
-
-/obj/item/storage/bag/trash/update_icon()
- if(contents.len == 0)
- icon_state = "[initial(icon_state)]"
- else if(contents.len < 12)
- icon_state = "[initial(icon_state)]1"
- else if(contents.len < 21)
- icon_state = "[initial(icon_state)]2"
- else icon_state = "[initial(icon_state)]3"
-
-/obj/item/storage/bag/trash/cyborg
-
-/obj/item/storage/bag/trash/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J)
- J.put_in_cart(src, user)
- J.mybag=src
- J.update_icon()
-
-/obj/item/storage/bag/trash/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
- return
-
-/obj/item/storage/bag/trash/bluespace
- name = "trash bag of holding"
- desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage."
- icon_state = "bluetrashbag"
- origin_tech = "materials=4;bluespace=4;engineering=4;plasmatech=3"
- max_combined_w_class = 60
- storage_slots = 60
-
-// -----------------------------
-// Mining Satchel
-// -----------------------------
-
-/obj/item/storage/bag/ore
- name = "mining satchel"
- desc = "This little bugger can be used to store and transport ores."
- icon = 'icons/obj/mining.dmi'
- icon_state = "satchel"
- origin_tech = "engineering=2"
- slot_flags = SLOT_BELT | SLOT_POCKET
- w_class = WEIGHT_CLASS_NORMAL
- storage_slots = 50
- max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
- max_w_class = WEIGHT_CLASS_NORMAL
- can_hold = list(/obj/item/ore)
- var/spam_protection = FALSE //If this is TRUE, the holder won't receive any messages when they fail to pick up ore through crossing it
-
-/obj/item/storage/bag/ore/cyborg
- name = "cyborg mining satchel"
-
-/obj/item/storage/bag/ore/holding //miners, your messiah has arrived
- name = "mining satchel of holding"
- desc = "A revolution in convenience, this satchel allows for huge amounts of ore storage. It's been outfitted with anti-malfunction safety measures."
- storage_slots = INFINITY
- max_combined_w_class = INFINITY
- origin_tech = "bluespace=4;materials=3;engineering=3"
- icon_state = "satchel_bspace"
-
-// -----------------------------
-// Plant bag
-// -----------------------------
-
-/obj/item/storage/bag/plants
- name = "plant bag"
- icon = 'icons/obj/hydroponics/equipment.dmi'
- icon_state = "plantbag"
- storage_slots = 100; //the number of plant pieces it can carry.
- max_combined_w_class = 100 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class
- max_w_class = WEIGHT_CLASS_NORMAL
- w_class = WEIGHT_CLASS_TINY
- can_hold = list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/seeds, /obj/item/grown, /obj/item/reagent_containers/honeycomb)
- resistance_flags = FLAMMABLE
-
-////////
-
-/obj/item/storage/bag/plants/portaseeder
- name = "portable seed extractor"
- desc = "For the enterprising botanist on the go. Less efficient than the stationary model, it creates one seed per plant."
- icon_state = "portaseeder"
- origin_tech = "biotech=3;engineering=2"
-
-/obj/item/storage/bag/plants/portaseeder/verb/dissolve_contents()
- set name = "Activate Seed Extraction"
- set category = "Object"
- set desc = "Activate to convert your plants into plantable seeds."
- if(usr.stat || !usr.canmove || usr.restrained())
- return
- for(var/obj/item/O in contents)
- seedify(O, 1)
- close_all()
-
-
-// -----------------------------
-// Sheet Snatcher
-// -----------------------------
-// Because it stacks stacks, this doesn't operate normally.
-// However, making it a storage/bag allows us to reuse existing code in some places. -Sayu
-
-/obj/item/storage/bag/sheetsnatcher
- name = "sheet snatcher"
- desc = "A patented Nanotrasen storage system designed for any kind of mineral sheet."
- icon = 'icons/obj/mining.dmi'
- icon_state = "sheetsnatcher"
-
- var/capacity = 300; //the number of sheets it can carry.
- w_class = WEIGHT_CLASS_NORMAL
-
- allow_quick_empty = 1 // this function is superceded
-
-/obj/item/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W, stop_messages = 0)
- if(!istype(W, /obj/item/stack/sheet) || istype(W, /obj/item/stack/sheet/mineral/sandstone) || istype(W, /obj/item/stack/sheet/mineral/wood))
- if(!stop_messages)
- to_chat(usr, "The snatcher does not accept [W].")
- return 0 //I don't care, but the existing code rejects them for not being "sheets" *shrug* -Sayu
- var/current = 0
- for(var/obj/item/stack/sheet/S in contents)
- current += S.amount
- if(capacity == current)//If it's full, you're done
- if(!stop_messages)
- to_chat(usr, "The snatcher is full.")
- return 0
- return 1
-
-
-// Modified handle_item_insertion. Would prefer not to, but...
-/obj/item/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W, prevent_warning = 0)
- var/obj/item/stack/sheet/S = W
- if(!istype(S)) return 0
-
- var/amount
- var/inserted = 0
- var/current = 0
- for(var/obj/item/stack/sheet/S2 in contents)
- current += S2.amount
- if(capacity < current + S.amount)//If the stack will fill it up
- amount = capacity - current
- else
- amount = S.amount
-
- for(var/obj/item/stack/sheet/sheet in contents)
- if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
- sheet.amount += amount // they should only be removed through procs in this file, which split them up.
- S.amount -= amount
- inserted = 1
- break
-
- if(!inserted || !S.amount)
- usr.dropItemToGround(S)
- if (usr.client && usr.s_active != src)
- usr.client.screen -= S
- S.dropped(usr)
- if(!S.amount)
- qdel(S)
- else
- if(S.pulledby)
- S.pulledby.stop_pulling()
- S.loc = src
-
- orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
- return 1
-
-
-// Sets up numbered display to show the stack size of each stored mineral
-// NOTE: numbered display is turned off currently because it's broken
-/obj/item/storage/bag/sheetsnatcher/orient2hud(mob/user)
- var/adjusted_contents = contents.len
-
- //Numbered contents display
- var/list/datum/numbered_display/numbered_contents
- if(display_contents_with_number)
- numbered_contents = list()
- adjusted_contents = 0
- for(var/obj/item/stack/sheet/I in contents)
- adjusted_contents++
- var/datum/numbered_display/D = new/datum/numbered_display(I)
- D.number = I.amount
- numbered_contents.Add( D )
-
- var/row_num = 0
- var/col_count = min(7,storage_slots) -1
- if (adjusted_contents > 7)
- row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
- src.standard_orient_objs(row_num, col_count, numbered_contents)
- return
-
-
-// Modified quick_empty verb drops appropriate sized stacks
-/obj/item/storage/bag/sheetsnatcher/quick_empty()
- var/location = get_turf(src)
- for(var/obj/item/stack/sheet/S in contents)
- while(S.amount)
- var/obj/item/stack/sheet/N = new S.type(location)
- var/stacksize = min(S.amount,N.max_amount)
- N.amount = stacksize
- S.amount -= stacksize
- if(!S.amount)
- qdel(S)// todo: there's probably something missing here
- orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
-
-// Instead of removing
-/obj/item/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W, atom/new_location)
- var/obj/item/stack/sheet/S = W
- if(!istype(S)) return 0
-
- //I would prefer to drop a new stack, but the item/attack_hand code
- // that calls this can't recieve a different object than you clicked on.
- //Therefore, make a new stack internally that has the remainder.
- // -Sayu
-
- if(S.amount > S.max_amount)
- var/obj/item/stack/sheet/temp = new S.type(src)
- temp.amount = S.amount - S.max_amount
- S.amount = S.max_amount
-
- return ..(S,new_location)
-
-// -----------------------------
-// Sheet Snatcher (Cyborg)
-// -----------------------------
-
-/obj/item/storage/bag/sheetsnatcher/borg
- name = "sheet snatcher 9000"
- desc = ""
- capacity = 500//Borgs get more because >specialization
-
-
-// -----------------------------
-// Book bag
-// -----------------------------
-
-/obj/item/storage/bag/books
- name = "book bag"
- desc = "A bag for books."
- icon = 'icons/obj/library.dmi'
- icon_state = "bookbag"
- display_contents_with_number = 0 //This would look really stupid otherwise
- storage_slots = 7
- max_combined_w_class = 21
- max_w_class = WEIGHT_CLASS_NORMAL
- w_class = WEIGHT_CLASS_BULKY //Bigger than a book because physics
- can_hold = list(/obj/item/book, /obj/item/storage/book, /obj/item/spellbook)
- resistance_flags = FLAMMABLE
-
-/*
- * Trays - Agouri
- */
-/obj/item/storage/bag/tray
- name = "tray"
- icon = 'icons/obj/food/containers.dmi'
- icon_state = "tray"
- desc = "A metal tray to lay food on."
- force = 5
- throwforce = 10
- throw_speed = 3
- throw_range = 5
- w_class = WEIGHT_CLASS_BULKY
- flags_1 = CONDUCT_1
- materials = list(MAT_METAL=3000)
- preposition = "on"
-
-/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
- ..()
- // Drop all the things. All of them.
- var/list/obj/item/oldContents = contents.Copy()
- quick_empty()
-
- // Make each item scatter a bit
- for(var/obj/item/I in oldContents)
- spawn()
- for(var/i = 1, i <= rand(1,2), i++)
- if(I)
- step(I, pick(NORTH,SOUTH,EAST,WEST))
- sleep(rand(2,4))
-
- if(prob(50))
- playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
- else
- playsound(M, 'sound/items/trayhit2.ogg', 50, 1)
-
- if(ishuman(M) || ismonkey(M))
- if(prob(10))
- M.Knockdown(40)
-
-/obj/item/storage/bag/tray/proc/rebuild_overlays()
- cut_overlays()
- for(var/obj/item/I in contents)
- add_overlay(mutable_appearance(I.icon, I.icon_state))
-
-/obj/item/storage/bag/tray/remove_from_storage(obj/item/W as obj, atom/new_location)
- ..()
- rebuild_overlays()
-
-/obj/item/storage/bag/tray/handle_item_insertion(obj/item/I, prevent_warning = 0)
- add_overlay(mutable_appearance(I.icon, I.icon_state))
- . = ..()
-
-
-/*
- * Chemistry bag
- */
-
-/obj/item/storage/bag/chemistry
- name = "chemistry bag"
- icon = 'icons/obj/chemical.dmi'
- icon_state = "bag"
- desc = "A bag for storing pills, patches, and bottles."
- storage_slots = 50
- max_combined_w_class = 200
- w_class = WEIGHT_CLASS_TINY
- preposition = "in"
- can_hold = list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle)
- resistance_flags = FLAMMABLE
-
-/*
- * Biowaste bag (mostly for xenobiologists)
- */
-
-/obj/item/storage/bag/bio
- name = "bio bag"
- icon = 'icons/obj/chemical.dmi'
- icon_state = "biobag"
- desc = "A bag for the safe transportation and disposal of biowaste and other biological materials."
- storage_slots = 25
- max_combined_w_class = 200
- w_class = WEIGHT_CLASS_TINY
- preposition = "in"
- can_hold = list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/monkeycube)
- resistance_flags = FLAMMABLE
+/*
+ * These absorb the functionality of the plant bag, ore satchel, etc.
+ * They use the use_to_pickup, quick_gather, and quick_empty functions
+ * that were already defined in weapon/storage, but which had been
+ * re-implemented in other classes.
+ *
+ * Contains:
+ * Trash Bag
+ * Mining Satchel
+ * Plant Bag
+ * Sheet Snatcher
+ * Book Bag
+ * Biowaste Bag
+ *
+ * -Sayu
+ */
+
+// Generic non-item
+/obj/item/storage/bag
+ allow_quick_gather = 1
+ allow_quick_empty = 1
+ display_contents_with_number = 1 // should work fine now
+ use_to_pickup = 1
+ slot_flags = SLOT_BELT
+
+// -----------------------------
+// Trash bag
+// -----------------------------
+/obj/item/storage/bag/trash
+ name = "trash bag"
+ desc = "It's the heavy-duty black polymer kind. Time to take out the trash!"
+ icon = 'icons/obj/janitor.dmi'
+ icon_state = "trashbag"
+ item_state = "trashbag"
+ lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
+
+ w_class = WEIGHT_CLASS_BULKY
+ max_w_class = WEIGHT_CLASS_SMALL
+ max_combined_w_class = 30
+ storage_slots = 30
+ can_hold = list() // any
+ cant_hold = list(/obj/item/disk/nuclear)
+
+/obj/item/storage/bag/trash/suicide_act(mob/user)
+ user.visible_message("[user] puts [src] over [user.p_their()] head and starts chomping at the insides! Disgusting!")
+ playsound(loc, 'sound/items/eatfood.ogg', 50, 1, -1)
+ return (TOXLOSS)
+
+/obj/item/storage/bag/trash/update_icon()
+ if(contents.len == 0)
+ icon_state = "[initial(icon_state)]"
+ else if(contents.len < 12)
+ icon_state = "[initial(icon_state)]1"
+ else if(contents.len < 21)
+ icon_state = "[initial(icon_state)]2"
+ else icon_state = "[initial(icon_state)]3"
+
+/obj/item/storage/bag/trash/cyborg
+
+/obj/item/storage/bag/trash/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J)
+ J.put_in_cart(src, user)
+ J.mybag=src
+ J.update_icon()
+
+/obj/item/storage/bag/trash/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
+ return
+
+/obj/item/storage/bag/trash/bluespace
+ name = "trash bag of holding"
+ desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage."
+ icon_state = "bluetrashbag"
+ origin_tech = "materials=4;bluespace=4;engineering=4;plasmatech=3"
+ max_combined_w_class = 60
+ storage_slots = 60
+ flags_2 = NO_MAT_REDEMPTION_2
+
+// -----------------------------
+// Mining Satchel
+// -----------------------------
+
+/obj/item/storage/bag/ore
+ name = "mining satchel"
+ desc = "This little bugger can be used to store and transport ores."
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "satchel"
+ origin_tech = "engineering=2"
+ slot_flags = SLOT_BELT | SLOT_POCKET
+ w_class = WEIGHT_CLASS_NORMAL
+ storage_slots = 50
+ max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
+ max_w_class = WEIGHT_CLASS_NORMAL
+ can_hold = list(/obj/item/ore)
+ var/spam_protection = FALSE //If this is TRUE, the holder won't receive any messages when they fail to pick up ore through crossing it
+
+/obj/item/storage/bag/ore/cyborg
+ name = "cyborg mining satchel"
+
+/obj/item/storage/bag/ore/holding //miners, your messiah has arrived
+ name = "mining satchel of holding"
+ desc = "A revolution in convenience, this satchel allows for huge amounts of ore storage. It's been outfitted with anti-malfunction safety measures."
+ storage_slots = INFINITY
+ max_combined_w_class = INFINITY
+ origin_tech = "bluespace=4;materials=3;engineering=3"
+ icon_state = "satchel_bspace"
+
+// -----------------------------
+// Plant bag
+// -----------------------------
+
+/obj/item/storage/bag/plants
+ name = "plant bag"
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "plantbag"
+ storage_slots = 100; //the number of plant pieces it can carry.
+ max_combined_w_class = 100 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class
+ max_w_class = WEIGHT_CLASS_NORMAL
+ w_class = WEIGHT_CLASS_TINY
+ can_hold = list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/seeds, /obj/item/grown, /obj/item/reagent_containers/honeycomb)
+ resistance_flags = FLAMMABLE
+
+////////
+
+/obj/item/storage/bag/plants/portaseeder
+ name = "portable seed extractor"
+ desc = "For the enterprising botanist on the go. Less efficient than the stationary model, it creates one seed per plant."
+ icon_state = "portaseeder"
+ origin_tech = "biotech=3;engineering=2"
+
+/obj/item/storage/bag/plants/portaseeder/verb/dissolve_contents()
+ set name = "Activate Seed Extraction"
+ set category = "Object"
+ set desc = "Activate to convert your plants into plantable seeds."
+ if(usr.stat || !usr.canmove || usr.restrained())
+ return
+ for(var/obj/item/O in contents)
+ seedify(O, 1)
+ close_all()
+
+
+// -----------------------------
+// Sheet Snatcher
+// -----------------------------
+// Because it stacks stacks, this doesn't operate normally.
+// However, making it a storage/bag allows us to reuse existing code in some places. -Sayu
+
+/obj/item/storage/bag/sheetsnatcher
+ name = "sheet snatcher"
+ desc = "A patented Nanotrasen storage system designed for any kind of mineral sheet."
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "sheetsnatcher"
+
+ var/capacity = 300; //the number of sheets it can carry.
+ w_class = WEIGHT_CLASS_NORMAL
+
+ allow_quick_empty = 1 // this function is superceded
+
+/obj/item/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W, stop_messages = 0)
+ if(!istype(W, /obj/item/stack/sheet) || istype(W, /obj/item/stack/sheet/mineral/sandstone) || istype(W, /obj/item/stack/sheet/mineral/wood))
+ if(!stop_messages)
+ to_chat(usr, "The snatcher does not accept [W].")
+ return 0 //I don't care, but the existing code rejects them for not being "sheets" *shrug* -Sayu
+ var/current = 0
+ for(var/obj/item/stack/sheet/S in contents)
+ current += S.amount
+ if(capacity == current)//If it's full, you're done
+ if(!stop_messages)
+ to_chat(usr, "The snatcher is full.")
+ return 0
+ return 1
+
+
+// Modified handle_item_insertion. Would prefer not to, but...
+/obj/item/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W, prevent_warning = 0)
+ var/obj/item/stack/sheet/S = W
+ if(!istype(S)) return 0
+
+ var/amount
+ var/inserted = 0
+ var/current = 0
+ for(var/obj/item/stack/sheet/S2 in contents)
+ current += S2.amount
+ if(capacity < current + S.amount)//If the stack will fill it up
+ amount = capacity - current
+ else
+ amount = S.amount
+
+ for(var/obj/item/stack/sheet/sheet in contents)
+ if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
+ sheet.amount += amount // they should only be removed through procs in this file, which split them up.
+ S.amount -= amount
+ inserted = 1
+ break
+
+ if(!inserted || !S.amount)
+ usr.dropItemToGround(S)
+ if (usr.client && usr.s_active != src)
+ usr.client.screen -= S
+ S.dropped(usr)
+ if(!S.amount)
+ qdel(S)
+ else
+ if(S.pulledby)
+ S.pulledby.stop_pulling()
+ S.loc = src
+
+ orient2hud(usr)
+ if(usr.s_active)
+ usr.s_active.show_to(usr)
+ update_icon()
+ return 1
+
+
+// Sets up numbered display to show the stack size of each stored mineral
+// NOTE: numbered display is turned off currently because it's broken
+/obj/item/storage/bag/sheetsnatcher/orient2hud(mob/user)
+ var/adjusted_contents = contents.len
+
+ //Numbered contents display
+ var/list/datum/numbered_display/numbered_contents
+ if(display_contents_with_number)
+ numbered_contents = list()
+ adjusted_contents = 0
+ for(var/obj/item/stack/sheet/I in contents)
+ adjusted_contents++
+ var/datum/numbered_display/D = new/datum/numbered_display(I)
+ D.number = I.amount
+ numbered_contents.Add( D )
+
+ var/row_num = 0
+ var/col_count = min(7,storage_slots) -1
+ if (adjusted_contents > 7)
+ row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
+ src.standard_orient_objs(row_num, col_count, numbered_contents)
+ return
+
+
+// Modified quick_empty verb drops appropriate sized stacks
+/obj/item/storage/bag/sheetsnatcher/quick_empty()
+ var/location = get_turf(src)
+ for(var/obj/item/stack/sheet/S in contents)
+ while(S.amount)
+ var/obj/item/stack/sheet/N = new S.type(location)
+ var/stacksize = min(S.amount,N.max_amount)
+ N.amount = stacksize
+ S.amount -= stacksize
+ if(!S.amount)
+ qdel(S)// todo: there's probably something missing here
+ orient2hud(usr)
+ if(usr.s_active)
+ usr.s_active.show_to(usr)
+ update_icon()
+
+// Instead of removing
+/obj/item/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W, atom/new_location)
+ var/obj/item/stack/sheet/S = W
+ if(!istype(S)) return 0
+
+ //I would prefer to drop a new stack, but the item/attack_hand code
+ // that calls this can't recieve a different object than you clicked on.
+ //Therefore, make a new stack internally that has the remainder.
+ // -Sayu
+
+ if(S.amount > S.max_amount)
+ var/obj/item/stack/sheet/temp = new S.type(src)
+ temp.amount = S.amount - S.max_amount
+ S.amount = S.max_amount
+
+ return ..(S,new_location)
+
+// -----------------------------
+// Sheet Snatcher (Cyborg)
+// -----------------------------
+
+/obj/item/storage/bag/sheetsnatcher/borg
+ name = "sheet snatcher 9000"
+ desc = ""
+ capacity = 500//Borgs get more because >specialization
+
+
+// -----------------------------
+// Book bag
+// -----------------------------
+
+/obj/item/storage/bag/books
+ name = "book bag"
+ desc = "A bag for books."
+ icon = 'icons/obj/library.dmi'
+ icon_state = "bookbag"
+ display_contents_with_number = 0 //This would look really stupid otherwise
+ storage_slots = 7
+ max_combined_w_class = 21
+ max_w_class = WEIGHT_CLASS_NORMAL
+ w_class = WEIGHT_CLASS_BULKY //Bigger than a book because physics
+ can_hold = list(/obj/item/book, /obj/item/storage/book, /obj/item/spellbook)
+ resistance_flags = FLAMMABLE
+
+/*
+ * Trays - Agouri
+ */
+/obj/item/storage/bag/tray
+ name = "tray"
+ icon = 'icons/obj/food/containers.dmi'
+ icon_state = "tray"
+ desc = "A metal tray to lay food on."
+ force = 5
+ throwforce = 10
+ throw_speed = 3
+ throw_range = 5
+ w_class = WEIGHT_CLASS_BULKY
+ flags_1 = CONDUCT_1
+ materials = list(MAT_METAL=3000)
+ preposition = "on"
+
+/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
+ ..()
+ // Drop all the things. All of them.
+ var/list/obj/item/oldContents = contents.Copy()
+ quick_empty()
+
+ // Make each item scatter a bit
+ for(var/obj/item/I in oldContents)
+ spawn()
+ for(var/i = 1, i <= rand(1,2), i++)
+ if(I)
+ step(I, pick(NORTH,SOUTH,EAST,WEST))
+ sleep(rand(2,4))
+
+ if(prob(50))
+ playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
+ else
+ playsound(M, 'sound/items/trayhit2.ogg', 50, 1)
+
+ if(ishuman(M) || ismonkey(M))
+ if(prob(10))
+ M.Knockdown(40)
+
+/obj/item/storage/bag/tray/proc/rebuild_overlays()
+ cut_overlays()
+ for(var/obj/item/I in contents)
+ add_overlay(mutable_appearance(I.icon, I.icon_state))
+
+/obj/item/storage/bag/tray/remove_from_storage(obj/item/W as obj, atom/new_location)
+ ..()
+ rebuild_overlays()
+
+/obj/item/storage/bag/tray/handle_item_insertion(obj/item/I, prevent_warning = 0)
+ add_overlay(mutable_appearance(I.icon, I.icon_state))
+ . = ..()
+
+
+/*
+ * Chemistry bag
+ */
+
+/obj/item/storage/bag/chemistry
+ name = "chemistry bag"
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "bag"
+ desc = "A bag for storing pills, patches, and bottles."
+ storage_slots = 50
+ max_combined_w_class = 200
+ w_class = WEIGHT_CLASS_TINY
+ preposition = "in"
+ can_hold = list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle)
+ resistance_flags = FLAMMABLE
+
+/*
+ * Biowaste bag (mostly for xenobiologists)
+ */
+
+/obj/item/storage/bag/bio
+ name = "bio bag"
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "biobag"
+ desc = "A bag for the safe transportation and disposal of biowaste and other biological materials."
+ storage_slots = 25
+ max_combined_w_class = 200
+ w_class = WEIGHT_CLASS_TINY
+ preposition = "in"
+ can_hold = list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/monkeycube)
+ resistance_flags = FLAMMABLE
diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm
index 1f2285cdf5..3c8460b57d 100644
--- a/code/modules/projectiles/guns/magic/staff.dm
+++ b/code/modules/projectiles/guns/magic/staff.dm
@@ -2,6 +2,7 @@
slot_flags = SLOT_BACK
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
+ flags_2 = NO_MAT_REDEMPTION_2
/obj/item/gun/magic/staff/change
name = "staff of change"