diff --git a/code/game/objects/items/weapons/storage/bags_vr.dm b/code/game/objects/items/weapons/storage/bags_vr.dm
index 6f9d0a0b15..ccafe5fa63 100644
--- a/code/game/objects/items/weapons/storage/bags_vr.dm
+++ b/code/game/objects/items/weapons/storage/bags_vr.dm
@@ -1,2 +1,15 @@
/obj/item/weapon/storage/bag/chemistry
slot_flags = null
+
+/obj/item/weapon/storage/bag/xeno
+ name = "xenobiology bag"
+ icon = 'icons/obj/storage.dmi'
+ icon_state = "chembag"
+ max_storage_space = ITEMSIZE_COST_SMALL * 12
+ max_w_class = ITEMSIZE_NORMAL
+ w_class = ITEMSIZE_SMALL
+ can_hold = list(
+ /obj/item/slime_extract,
+ /obj/item/slimepotion,
+ /obj/item/weapon/reagent_containers/food/snacks/monkeycube
+ )
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/l3closet.dm b/code/game/objects/structures/crates_lockers/closets/l3closet.dm
index d9692abdc3..c592c3e69f 100644
--- a/code/game/objects/structures/crates_lockers/closets/l3closet.dm
+++ b/code/game/objects/structures/crates_lockers/closets/l3closet.dm
@@ -49,7 +49,8 @@
/obj/structure/closet/l3closet/scientist/double
starts_with = list(
/obj/item/clothing/suit/bio_suit/scientist = 2,
- /obj/item/clothing/head/bio_hood/scientist = 2)
+ /obj/item/clothing/head/bio_hood/scientist = 2,
+ /obj/item/weapon/storage/bag/xeno = 2) // VOREEdit, adding the xenobag to xenobio.
/obj/structure/closet/l3closet/medical
diff --git a/code/modules/projectiles/guns/projectile/dartgun_vr.dm b/code/modules/projectiles/guns/projectile/dartgun_vr.dm
index dda197ccc6..a802c17327 100644
--- a/code/modules/projectiles/guns/projectile/dartgun_vr.dm
+++ b/code/modules/projectiles/guns/projectile/dartgun_vr.dm
@@ -27,3 +27,10 @@
else
icon_state = "tranqgun"
return 1
+
+// This is to allow xenobio to activate slime cores via remote.
+/obj/item/projectile/bullet/chemdart/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
+ ..()
+ if(blocked < 2)
+ if(istype(target, /obj/item/weapon/reagent_containers/food) || istype(target, /obj/item/slime_extract))
+ reagents.trans_to_obj(target, reagent_amount)
\ No newline at end of file
diff --git a/code/modules/research/designs/xenobio_toys_vr.dm b/code/modules/research/designs/xenobio_toys_vr.dm
new file mode 100644
index 0000000000..39491c1b0c
--- /dev/null
+++ b/code/modules/research/designs/xenobio_toys_vr.dm
@@ -0,0 +1,17 @@
+/datum/design/item/weapon/xenobio/monkey_gun
+ name = "bluespace monkey deployment system"
+ desc = "An Advanced monkey teleportation and rehydration system. For serious monkey business."
+ id = "monkey_gun"
+ req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 3, TECH_POWER = 4, TECH_COMBAT = 4, TECH_BLUESPACE = 6)
+ materials = list(MAT_PLASTEEL = 5000, MAT_GLASS = 5000, MAT_DIAMOND = 500, MAT_MORPHIUM = 350)
+ build_path = /obj/item/weapon/xenobio/monkey_gun
+ sort_string = "HBBA"
+
+/datum/design/item/weapon/xenobio/grinder
+ name = "portable slime processor"
+ desc = "This high tech device combines the slime processor with the latest in woodcutting technology."
+ id = "slime_grinder"
+ req_tech = list(TECH_MAGNET = 4, TECH_BIO = 7)
+ materials = list(MAT_STEEL = 500, MAT_GLASS = 500, MAT_DIAMOND = 500, MAT_MORPHIUM = 100)
+ build_path = /obj/item/weapon/slime_grinder
+ sort_string = "HBBB"
\ No newline at end of file
diff --git a/code/modules/xenobio/items/weapons_vr.dm b/code/modules/xenobio/items/weapons_vr.dm
new file mode 100644
index 0000000000..24a91715a4
--- /dev/null
+++ b/code/modules/xenobio/items/weapons_vr.dm
@@ -0,0 +1,159 @@
+/obj/item/weapon/xenobio
+ name = "xenobio gun"
+ desc = "You shouldn't see this!"
+ icon = 'icons/obj/gun_vr.dmi'
+ icon_state = "harpoon-2"
+ var/loadable_item = null
+ var/loaded_item = null
+ var/loadable_name = null
+ var/firable = TRUE
+/obj/item/weapon/xenobio/examine(var/mob/user)
+ . = ..()
+ if(loaded_item)
+ .+= "A [loaded_item] is slotted into the side."
+ else
+ .+= "There appears to be an empty slot for attaching a [loadable_name]."
+
+/obj/item/weapon/xenobio/attack_hand(mob/user as mob)
+ if(user.get_inactive_hand() == src && loaded_item)
+ user.put_in_hands(loaded_item)
+ user.visible_message("[user] removes [loaded_item] from [src].", "You remove [loaded_item] from [src].")
+ loaded_item = null
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+ else
+ return ..()
+
+/obj/item/weapon/xenobio/attackby(obj/item/I as obj, mob/user as mob)
+ if(istype(I, loadable_item))
+ if(loaded_item)
+ to_chat(user, "[I] doesn't seem to fit into [src].")
+ return
+ //var/obj/item/weapon/reagent_containers/glass/beaker/B = I
+ user.drop_item()
+ I.loc = src
+ loaded_item = I
+ user.visible_message("[user] inserts [I] into [src].", "You slot [I] into [src].")
+ return 1
+ ..()
+
+/obj/item/weapon/xenobio/attack_self(mob/living/user as mob)
+ if(loaded_item)
+ user.put_in_hands(loaded_item)
+ user.visible_message("[user] removes [loaded_item] from [src].", "You remove [loaded_item] from [src].")
+ loaded_item = null
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+
+/obj/item/weapon/xenobio/afterattack(atom/A, mob/user as mob)
+ if(!loaded_item)
+ to_chat(user,"\The [src] shot fizzles, it appears you need to load something!")
+ //playsound(src, 'sound/weapons/wave.ogg', 60, 1)
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+ return
+ if(!firable)
+ return
+
+ playsound(src, 'sound/weapons/wave.ogg', 60, 1)
+
+ user.visible_message("[user] fires \the [src]!","You fire \the [src]!")
+
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(4, 1, A)
+ s.start()
+ s = new /datum/effect/effect/system/spark_spread
+ s.set_up(4, 1, user)
+ s.start()
+
+/obj/item/weapon/xenobio/monkey_gun
+ name = "Bluespace Cube Rehydrator"
+ desc = "Based on the technology of the 'Bluespace Harpoon' this device can teleport a loaded cube to a given target and rehydrate it."
+ loadable_item = /obj/item/weapon/reagent_containers/food/snacks/monkeycube
+ loadable_name = "Monkey Cube"
+ origin_tech = list(TECH_BLUESPACE = 5, TECH_BIO = 6)
+ //projectile_type = /obj/item/projectile/beam/xenobio/monkey
+
+/obj/item/weapon/xenobio/monkey_gun/afterattack(atom/A, mob/user as mob)
+ ..()
+
+ if(!firable)
+ return
+
+ var/turf/T = get_turf(A)
+ if(!T || (T.check_density(ignore_mobs = TRUE)))
+ to_chat(user,"Your rehydrator flashes an error as it attempts to process your target.")
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+ return
+ if(istype(A, /mob/living))
+ to_chat(user,"The rehydrator's saftey systems prevent firing into living creatures!")
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+ return
+ if(loaded_item)
+ var/obj/item/weapon/reagent_containers/food/snacks/monkeycube/cube = loaded_item
+ cube.loc = A
+ cube.Expand()
+ loaded_item = null
+ firable = FALSE
+ VARSET_IN(src, firable, TRUE, 2 SECONDS)
+
+// Instead of bringing the slime to the grinder, lets bring the grinder to the slime! This will process slimes and monkies one at a time.
+/obj/item/weapon/slime_grinder
+ name = "portable slime processor"
+ desc = "An industrial grinder used to automate the process of slime core extraction. It can also recycle biomatter. This one appears miniturized"
+ //icon = 'icons/obj/weapons_vr.dmi'
+ icon_state = "chainsaw0"
+ var/processing = FALSE // So I heard you like processing.
+ var/list/to_be_processed = list()
+ var/monkeys_recycled = 0
+ description_info = "Click a monkey or slime to begin processing."
+
+/obj/item/weapon/slime_grinder/proc/extract(var/atom/movable/AM, var/mob/living/user)
+ processing = TRUE
+ if(istype(AM, /mob/living/simple_mob/slime))
+ var/mob/living/simple_mob/slime/S = AM
+ while(S.cores)
+ playsound(src, 'sound/machines/juicer.ogg', 25, 1)
+ if(do_after(user, 15))
+ new S.coretype(get_turf(AM))
+ playsound(src, 'sound/effects/splat.ogg', 50, 1)
+ S.cores--
+ qdel(S)
+
+ if(istype(AM, /mob/living/carbon/human/monkey))
+ playsound(src, 'sound/machines/juicer.ogg', 25, 1)
+ if(do_after(user, 15))
+ var/mob/living/carbon/human/M = AM
+ playsound(src, 'sound/effects/splat.ogg', 50, 1)
+ qdel(M)
+ monkeys_recycled++
+ sleep(1 SECOND)
+ while(monkeys_recycled >= 4)
+ new /obj/item/weapon/reagent_containers/food/snacks/monkeycube(get_turf(src))
+ playsound(src, 'sound/effects/splat.ogg', 50, 1)
+ monkeys_recycled -= 4
+ sleep(1 SECOND)
+ processing = FALSE
+
+/obj/item/weapon/slime_grinder/proc/can_insert(var/atom/movable/AM)
+ if(istype(AM, /mob/living/simple_mob/slime))
+ var/mob/living/simple_mob/slime/S = AM
+ if(S.stat != DEAD)
+ return FALSE
+ return TRUE
+ if(istype(AM, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = AM
+ if(!istype(H.species, /datum/species/monkey))
+ return FALSE
+ if(H.stat != DEAD)
+ return FALSE
+ return TRUE
+ return FALSE
+
+/obj/item/weapon/slime_grinder/attack(mob/M as mob, mob/living/user as mob)
+ if(processing)
+ return
+ if(!can_insert(M))
+ to_chat(user, "\The [src] cannot process \the [M] at this time.")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
+ return
+
+ extract(M, user)
+ return ..()
\ No newline at end of file
diff --git a/vorestation.dme b/vorestation.dme
index fbe50d4df3..0cda4b083a 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -3723,6 +3723,7 @@
#include "code\modules\research\designs\weapons_vr.dm"
#include "code\modules\research\designs\xenoarch_toys.dm"
#include "code\modules\research\designs\xenobio_toys.dm"
+#include "code\modules\research\designs\xenobio_toys_vr.dm"
#include "code\modules\research\designs\circuits\ai_modules.dm"
#include "code\modules\research\designs\circuits\ai_modules_vr.dm"
#include "code\modules\research\designs\circuits\circuits.dm"
@@ -4063,6 +4064,7 @@
#include "code\modules\xenobio\items\slimepotions.dm"
#include "code\modules\xenobio\items\slimepotions_vr.dm"
#include "code\modules\xenobio\items\weapons.dm"
+#include "code\modules\xenobio\items\weapons_vr.dm"
#include "code\modules\xenobio\machinery\processor.dm"
#include "code\modules\xgm\xgm_gas_data.dm"
#include "code\modules\xgm\xgm_gas_mixture.dm"