diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm
index f2798b2aac..4ac13ac651 100644
--- a/code/game/objects/random/misc.dm
+++ b/code/game/objects/random/misc.dm
@@ -1105,3 +1105,32 @@
/obj/item/weapon/storage/box/donkpockets/honk,
/obj/item/weapon/storage/box/donkpockets/gondola,
/obj/item/weapon/storage/box/donkpockets/berry)
+
+/obj/random/bluespace
+ name = "Random Bluespace Item"
+ desc = "This is a random Bluespace item."
+ icon_state = "bluespace"
+
+/obj/random/bluespace/item_to_spawn()
+ return pick(
+ prob(20);/obj/item/weapon/gun/energy/sizegun,
+ prob(20);/obj/item/device/slow_sizegun,
+ prob(20);/obj/item/clothing/accessory/collar/shock/bluespace,
+ prob(4);/obj/item/weapon/reagent_containers/glass/beaker/bluespace,
+ prob(4);/obj/item/device/bodysnatcher,
+ prob(10);/obj/item/clothing/under/hyperfiber,
+ prob(10);/obj/item/clothing/under/hyperfiber/bluespace,
+ prob(20);/obj/item/weapon/implant/sizecontrol,
+ prob(2);/obj/item/weapon/storage/bag/ore/holding,
+ prob(2);/obj/item/weapon/storage/backpack/holding,
+ prob(2);/obj/item/weapon/storage/backpack/holding/duffle,
+ prob(2);/obj/item/weapon/storage/bag/trash/holding,
+ prob(2);/obj/item/weapon/storage/pouch/holding,
+ prob(2);/obj/item/weapon/storage/belt/medical/holding,
+ prob(2);/obj/item/weapon/storage/belt/utility/holding,
+ prob(2);/obj/item/device/perfect_tele,
+ prob(8);/obj/item/capture_crystal/random,
+ prob(10);/obj/item/weapon/bluespace_harpoon,
+ prob(10);/obj/item/weapon/bluespace_crystal,
+ prob(1);/obj/item/clothing/glasses/graviton
+ )
\ No newline at end of file
diff --git a/code/game/objects/structures/trash_pile_vr.dm b/code/game/objects/structures/trash_pile_vr.dm
index 1da8e0a159..4fcfc0619a 100644
--- a/code/game/objects/structures/trash_pile_vr.dm
+++ b/code/game/objects/structures/trash_pile_vr.dm
@@ -280,6 +280,7 @@
prob(4);/obj/item/seeds/ambrosiavulgarisseed,
prob(4);/obj/item/weapon/gun/energy/sizegun,
prob(4);/obj/item/device/slow_sizegun,
+ prob(4);/obj/item/clothing/accessory/collar/shock/bluespace,
prob(3);/obj/item/weapon/material/butterfly,
prob(3);/obj/item/weapon/material/butterfly/switchblade,
prob(3);/obj/item/clothing/gloves/knuckledusters,
@@ -311,7 +312,8 @@
prob(1);/obj/item/capture_crystal,
prob(1);/obj/item/device/perfect_tele/one_beacon,
prob(1);/obj/item/clothing/gloves/bluespace,
- prob(1);/obj/item/weapon/gun/energy/mouseray)
+ prob(1);/obj/item/weapon/gun/energy/mouseray,
+ prob(1);/obj/item/clothing/accessory/collar/shock/bluespace/modified)
var/obj/item/I = new path()
return I
diff --git a/code/modules/casino/casino_prize_vendor.dm b/code/modules/casino/casino_prize_vendor.dm
index 6bf70bb763..115e51ed48 100644
--- a/code/modules/casino/casino_prize_vendor.dm
+++ b/code/modules/casino/casino_prize_vendor.dm
@@ -99,6 +99,7 @@
CASINO_PRIZE("Cowboy costume", /obj/item/weapon/storage/box/casino/costume_cowboy, 1, 500, "clothing"),
CASINO_PRIZE("Golden Collar", /obj/item/clothing/accessory/collar/gold, 1, 250, "clothing"),
CASINO_PRIZE("Decorative Casino Sentient Prize Collar", /obj/item/clothing/accessory/collar/casinosentientprize_fake, 1, 100, "clothing"),
+ CASINO_PRIZE("Bluespace Collar", /obj/item/clothing/accessory/collar/shock/bluespace, 1, 1000, "clothing"),
)
item_list["Donk Soft"] = list(
CASINO_PRIZE("Donk-Soft shotgun", /obj/item/weapon/gun/projectile/shotgun/pump/toy, 1, 1000, "misc"),
diff --git a/code/modules/clothing/under/accessories/accessory_vr.dm b/code/modules/clothing/under/accessories/accessory_vr.dm
index 4aaff66354..fec423c436 100644
--- a/code/modules/clothing/under/accessories/accessory_vr.dm
+++ b/code/modules/clothing/under/accessories/accessory_vr.dm
@@ -357,6 +357,274 @@
name = initial(name) + " ([str])"
desc = initial(desc) + " Something has been [erasemethod] on the tag, and it now has \"[str]\" [writemethod] on it."
+//Size collar remote
+
+/obj/item/clothing/accessory/collar/shock/bluespace
+ name = "Bluespace collar"
+ desc = "A collar that can manipulate the size of the wearer, and can be modified when unequiped."
+ icon_state = "collar_size"
+ item_state = "collar_size"
+ overlay_state = "collar_size"
+ var/original_size
+ var/last_activated
+ var/target_size = 1
+ on = 1
+
+/obj/item/clothing/accessory/collar/shock/bluespace/Topic(href, href_list)
+ if(usr.stat || usr.restrained())
+ return
+ if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf)))))
+ usr.set_machine(src)
+ if(href_list["freq"])
+ var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
+ set_frequency(new_frequency)
+ if(href_list["tag"])
+ var/str = copytext(reject_bad_text(tgui_input_text(usr,"Tag text?","Set tag","",MAX_NAME_LEN)),1,MAX_NAME_LEN)
+ if(!str || !length(str))
+ to_chat(usr,"[name]'s tag set to be blank.")
+ name = initial(name)
+ desc = initial(desc)
+ else
+ to_chat(usr,"You set the [name]'s tag to '[str]'.")
+ name = initial(name) + " ([str])"
+ desc = initial(desc) + " The tag says \"[str]\"."
+ else
+ if(href_list["code"])
+ code += text2num(href_list["code"])
+ code = round(code)
+ code = min(100, code)
+ code = max(1, code)
+ else
+ if(href_list["size"])
+ var/size_select = tgui_input_number(usr, "Put the desired size (25-200%), (1-600%) in dormitory areas.", "Set Size", target_size * 100, 200, 25)
+ if(!size_select)
+ return //cancelled
+ target_size = clamp((size_select/100), RESIZE_MINIMUM_DORMS, RESIZE_MAXIMUM_DORMS)
+ to_chat(usr, "You set the size to [size_select]%")
+ if(target_size < RESIZE_MINIMUM || target_size > RESIZE_MAXIMUM)
+ to_chat(usr, "Note: Resizing limited to 25-200% automatically while outside dormatory areas.") //hint that we clamp it in resize
+ if(!( master ))
+ if(istype(loc, /mob))
+ attack_self(loc)
+ else
+ for(var/mob/M in viewers(1, src))
+ if(M.client)
+ attack_self(M)
+ else
+ if(istype(master.loc, /mob))
+ attack_self(master.loc)
+ else
+ for(var/mob/M in viewers(1, master))
+ if(M.client)
+ attack_self(M)
+ else
+ usr << browse(null, "window=radio")
+ return
+ return
+
+/obj/item/clothing/accessory/collar/shock/bluespace/attack_self(mob/user as mob, flag1)
+ if(!istype(user, /mob/living/carbon/human))
+ return
+ user.set_machine(src)
+ var/dat = {"
+ Frequency/Code for collar:
+ Frequency:
+ -
+ - [format_frequency(frequency)]
+ +
+ +
+
+ Code:
+ -
+ - [code]
+ +
+ +
+
+ Tag:
+ Set tag
+
+ Size:
+ Set size
+ "}
+ user << browse(dat, "window=radio")
+ onclose(user, "radio")
+ return
+
+/obj/item/clothing/accessory/collar/shock/bluespace/receive_signal(datum/signal/signal)
+ if(!signal || signal.encryption != code)
+ return
+
+ if(on)
+ var/mob/M = null
+ if(ismob(loc))
+ M = loc
+ if(ismob(loc.loc))
+ M = loc.loc // This is about as terse as I can make my solution to the whole 'collar won't work when attached as accessory' thing.
+ var/mob/living/carbon/human/H = M
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ if(!H.resizable)
+ H.visible_message("The space around [H] compresses for a moment but then nothing happens.","The space around you distorts but nothing happens to you.")
+ return
+ if(H.size_multiplier != target_size)
+ if(!(world.time - last_activated > 10 SECONDS))
+ to_chat(M, "\The [src] flickers. It seems to be recharging.")
+ return
+ last_activated = world.time
+ original_size = H.size_multiplier
+ H.resize(target_size, ignore_prefs = FALSE) //In case someone else tries to put it on you.
+ H.visible_message("The space around [H] distorts as they change size!","The space around you distorts as you change size!")
+ log_admin("Admin [key_name(M)]'s size was altered by a bluespace collar.")
+ s.set_up(3, 1, M)
+ s.start()
+ else if(H.size_multiplier == target_size)
+ if(original_size == null)
+ H.visible_message("The space around [H] twists and turns for a moment but then nothing happens.","The space around you distorts but stay the same size.")
+ return
+ last_activated = world.time
+ H.resize(original_size, ignore_prefs = FALSE)
+ original_size = null
+ H.visible_message("The space around [H] distorts as they return to their original size!","The space around you distorts as you return to your original size!")
+ log_admin("Admin [key_name(M)]'s size was altered by a bluespace collar.")
+ to_chat(M, "\The [src] flickers. It is now recharging and will be ready again in ten seconds.")
+ s.set_up(3, 1, M)
+ s.start()
+ return
+
+/obj/item/clothing/accessory/collar/shock/bluespace/relaymove(var/mob/living/user,var/direction)
+ return //For some reason equipping this item was triggering this proc, putting the wearer inside of the collars belly for some reason.
+
+/obj/item/clothing/accessory/collar/shock/bluespace/attackby(var/obj/item/device/assembly/signaler/component, mob/user as mob)
+ if (!istype(component,/obj/item/device/assembly/signaler))
+ ..()
+ return
+ to_chat(user, "You wire the signaler into the [src].")
+ user.drop_item()
+ qdel(component)
+ var/turf/T = get_turf(src)
+ new /obj/item/clothing/accessory/collar/shock/bluespace/modified(T)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+
+// modified bluespace collar where the size is controlled by the signaller.
+
+/obj/item/clothing/accessory/collar/shock/bluespace/modified
+ name = "Bluespace collar"
+ desc = "A collar that can manipulate the size of the wearer, and can be modified when unequiped. It has a little reciever attached."
+ icon_state = "collar_size_mod"
+ item_state = "collar_size"
+ overlay_state = "collar_size"
+ target_size = 1
+ on = 1
+
+/obj/item/clothing/accessory/collar/shock/bluespace/modified/attackby(var/obj/item/device/assembly/signaler/component, mob/user as mob)
+ if (!istype(component,/obj/item/device/assembly/signaler))
+ ..()
+ return
+ to_chat(user, "There is already a signaler wired to the [src].")
+ return
+
+/obj/item/clothing/accessory/collar/shock/bluespace/modified/attack_self(mob/user as mob, flag1)
+ if(!istype(user, /mob/living/carbon/human))
+ return
+ user.set_machine(src) //Doesn't need code or size options as the code now just defines the size.
+ var/dat = {"
+ Frequency/Code for collar:
+ Frequency:
+ -
+ - [format_frequency(frequency)]
+ +
+ +
+
+ Tag:
+ Set tag
+
+ The size control of the collar is determined by two times the value of the code it recieves, to a minimum of 26 (code 13).
+ "}
+ user << browse(dat, "window=radio")
+ onclose(user, "radio")
+ return
+
+/obj/item/clothing/accessory/collar/shock/bluespace/modified/Topic(href, href_list)
+ if(usr.stat || usr.restrained())
+ return
+ if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf)))))
+ usr.set_machine(src)
+ if(href_list["freq"])
+ var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
+ set_frequency(new_frequency)
+ if(href_list["tag"])
+ var/str = copytext(reject_bad_text(tgui_input_text(usr,"Tag text?","Set tag","",MAX_NAME_LEN)),1,MAX_NAME_LEN)
+ if(!str || !length(str))
+ to_chat(usr,"[name]'s tag set to be blank.")
+ name = initial(name)
+ desc = initial(desc)
+ else
+ to_chat(usr,"You set the [name]'s tag to '[str]'.")
+ name = initial(name) + " ([str])"
+ desc = initial(desc) + " The tag says \"[str]\"."
+ if(!( master ))
+ if(istype(loc, /mob))
+ attack_self(loc)
+ else
+ for(var/mob/M in viewers(1, src))
+ if(M.client)
+ attack_self(M)
+ else
+ if(istype(master.loc, /mob))
+ attack_self(master.loc)
+ else
+ for(var/mob/M in viewers(1, master))
+ if(M.client)
+ attack_self(M)
+ else
+ usr << browse(null, "window=radio")
+ return
+ return
+
+/obj/item/clothing/accessory/collar/shock/bluespace/modified/receive_signal(datum/signal/signal)
+ if(!signal)
+ return
+ target_size = (signal.encryption * 2)/100
+ if(on)
+ var/mob/M = null
+ if(ismob(loc))
+ M = loc
+ if(ismob(loc.loc))
+ M = loc.loc // This is about as terse as I can make my solution to the whole 'collar won't work when attached as accessory' thing.
+ var/mob/living/carbon/human/H = M
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ if(!H.resizable)
+ H.visible_message("The space around [H] compresses for a moment but then nothing happens.","The space around you distorts but nothing happens to you.")
+ return
+ if (target_size < 0.26)
+ H.visible_message("The collar on [H] flickers, but fizzles out.","Your collar flickers, but is not powerful enough to shrink you that small.")
+ return
+ if(H.size_multiplier != target_size)
+ if(!(world.time - last_activated > 10 SECONDS))
+ to_chat(M, "\The [src] flickers. It seems to be recharging.")
+ return
+ last_activated = world.time
+ original_size = H.size_multiplier
+ H.resize(target_size, ignore_prefs = FALSE) //In case someone else tries to put it on you.
+ H.visible_message("The space around [H] distorts as they change size!","The space around you distorts as you change size!")
+ log_admin("Admin [key_name(M)]'s size was altered by a bluespace collar.")
+ s.set_up(3, 1, M)
+ s.start()
+ else if(H.size_multiplier == target_size)
+ if(original_size == null)
+ H.visible_message("The space around [H] twists and turns for a moment but then nothing happens.","The space around you distorts but stay the same size.")
+ return
+ last_activated = world.time
+ H.resize(original_size, ignore_prefs = FALSE)
+ original_size = null
+ H.visible_message("The space around [H] distorts as they return to their original size!","The space around you distorts as you return to your original size!")
+ log_admin("Admin [key_name(M)]'s size was altered by a bluespace collar.")
+ to_chat(M, "\The [src] flickers. It is now recharging and will be ready again in ten seconds.")
+ s.set_up(3, 1, M)
+ s.start()
+ return
+
//Machete Holsters
/obj/item/clothing/accessory/holster/machete
name = "machete sheath"
diff --git a/code/modules/economy/trader.dm b/code/modules/economy/trader.dm
index 0491c17eea..d0acd04bae 100644
--- a/code/modules/economy/trader.dm
+++ b/code/modules/economy/trader.dm
@@ -326,6 +326,7 @@
/obj/item/device/chameleon = 25,
/obj/item/weapon/gun/energy/sizegun = 25,
/obj/item/device/slow_sizegun = 25,
+ /obj/item/clothing/accessory/collar/shock/bluespace = 25,
/obj/item/weapon/implant/sizecontrol = 25,
/obj/item/clothing/under/hyperfiber/bluespace = 25,
/obj/item/device/nif/authentic = 1,
@@ -352,6 +353,7 @@
/obj/item/device/chameleon = 20,
/obj/item/weapon/gun/energy/sizegun = 10,
/obj/item/device/slow_sizegun = 10,
+ /obj/item/clothing/accessory/collar/shock/bluespace = 10,
/obj/item/weapon/implant/sizecontrol = 10,
/obj/item/clothing/under/hyperfiber/bluespace = 10,
/obj/item/device/nif/authentic = 100,
@@ -376,6 +378,7 @@
/obj/item/capture_crystal/random = 2,
/obj/item/weapon/gun/energy/sizegun = 2,
/obj/item/device/slow_sizegun = 2,
+ /obj/item/clothing/accessory/collar/shock/bluespace = 2,
/obj/item/weapon/implant/sizecontrol = 2,
/obj/item/clothing/under/hyperfiber/bluespace = 2,
/obj/item/weapon/reagent_containers/food/snacks/jellyfishcore = 10
diff --git a/code/modules/research/designs/misc_vr.dm b/code/modules/research/designs/misc_vr.dm
index 1756d12493..12121fea11 100644
--- a/code/modules/research/designs/misc_vr.dm
+++ b/code/modules/research/designs/misc_vr.dm
@@ -30,6 +30,14 @@
build_path = /obj/item/device/slow_sizegun
sort_string = "TAVBB"
+/datum/design/item/general/bluespace_collar
+ name = "Bluespace collar"
+ id = "bluespacecollar"
+ req_tech = list(TECH_BLUESPACE = 3, TECH_MATERIAL = 3, TECH_POWER = 2)
+ materials = list(MAT_STEEL = 2000, MAT_GLASS = 2000)
+ build_path = /obj/item/clothing/accessory/collar/shock/bluespace
+ sort_string = "TAVBC"
+
/datum/design/item/general/bodysnatcher
name = "Body Snatcher"
id = "bodysnatcher"
diff --git a/icons/inventory/accessory/item_vr.dmi b/icons/inventory/accessory/item_vr.dmi
index 6f84a0e538..67c951fb06 100644
Binary files a/icons/inventory/accessory/item_vr.dmi and b/icons/inventory/accessory/item_vr.dmi differ
diff --git a/icons/inventory/accessory/mob_vr.dmi b/icons/inventory/accessory/mob_vr.dmi
index 3ddbd06479..f3509128a7 100644
Binary files a/icons/inventory/accessory/mob_vr.dmi and b/icons/inventory/accessory/mob_vr.dmi differ
diff --git a/icons/misc/random_spawners.dmi b/icons/misc/random_spawners.dmi
index 27e55fc9ec..851218e6e3 100644
Binary files a/icons/misc/random_spawners.dmi and b/icons/misc/random_spawners.dmi differ