diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 3b5ca3a4ae9..83ce719e71b 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -1243,3 +1243,24 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/obj/item/weapon/lipstick/random)
cost = 30 //Lots of very expensive items. You gotta pay up to look good!
containername = "formal-wear crate"
+
+/datum/supply_packs/misc/foamforce
+ name = "Foam Force Crate"
+ contains = list(/obj/item/weapon/gun/projectile/shotgun/toy,
+ /obj/item/weapon/gun/projectile/shotgun/toy,
+ /obj/item/weapon/gun/projectile/shotgun/toy,
+ /obj/item/weapon/gun/projectile/shotgun/toy,
+ /obj/item/weapon/gun/projectile/shotgun/toy,
+ /obj/item/weapon/gun/projectile/shotgun/toy)
+ cost = 10
+ containername = "foam force crate"
+
+/datum/supply_packs/misc/foamforce/bonus
+ name = "Foam Force Pistol Crate"
+ contains = list(/obj/item/weapon/gun/projectile/automatic/toy/pistol,
+ /obj/item/weapon/gun/projectile/automatic/toy/pistol,
+ /obj/item/ammo_box/magazine/toy/pistol,
+ /obj/item/ammo_box/magazine/toy/pistol)
+ cost = 40
+ containername = "foam force Pistols crate"
+ contraband = 1
\ No newline at end of file
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 1bcc4decc8e..5a95966fbb1 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -3,35 +3,35 @@
desc = "random arcade machine"
icon = 'icons/obj/computer.dmi'
icon_state = "arcade"
- var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2,
- /obj/item/toy/AI = 2,
- /obj/item/clothing/under/syndicate/tacticool = 2,
- /obj/item/toy/sword = 2,
- /obj/item/toy/gun = 2,
- /obj/item/toy/crossbow = 2,
- /obj/item/weapon/storage/box/fakesyndiesuit = 2,
- /obj/item/weapon/storage/fancy/crayons = 2,
- /obj/item/toy/spinningtoy = 2,
- /obj/item/toy/prize/ripley = 1,
- /obj/item/toy/prize/fireripley = 1,
- /obj/item/toy/prize/deathripley = 1,
- /obj/item/toy/prize/gygax = 1,
- /obj/item/toy/prize/durand = 1,
- /obj/item/toy/prize/honk = 1,
- /obj/item/toy/prize/marauder = 1,
- /obj/item/toy/prize/seraph = 1,
- /obj/item/toy/prize/mauler = 1,
- /obj/item/toy/prize/odysseus = 1,
- /obj/item/toy/prize/phazon = 1,
- /obj/item/toy/prize/reticence = 1,
- /obj/item/toy/cards/deck = 2,
- /obj/item/toy/nuke = 2,
- /obj/item/toy/minimeteor = 2,
- /obj/item/toy/carpplushie = 2,
- /obj/item/toy/foamblade = 2,
- /obj/item/toy/redbutton = 2,
- /obj/item/toy/owl = 2,
- /obj/item/toy/griffin = 2
+ var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2,
+ /obj/item/toy/AI = 2,
+ /obj/item/clothing/under/syndicate/tacticool = 2,
+ /obj/item/toy/sword = 2,
+ /obj/item/toy/gun = 2,
+ /obj/item/weapon/gun/projectile/shotgun/toy/crossbow = 2,
+ /obj/item/weapon/storage/box/fakesyndiesuit = 2,
+ /obj/item/weapon/storage/fancy/crayons = 2,
+ /obj/item/toy/spinningtoy = 2,
+ /obj/item/toy/prize/ripley = 1,
+ /obj/item/toy/prize/fireripley = 1,
+ /obj/item/toy/prize/deathripley = 1,
+ /obj/item/toy/prize/gygax = 1,
+ /obj/item/toy/prize/durand = 1,
+ /obj/item/toy/prize/honk = 1,
+ /obj/item/toy/prize/marauder = 1,
+ /obj/item/toy/prize/seraph = 1,
+ /obj/item/toy/prize/mauler = 1,
+ /obj/item/toy/prize/odysseus = 1,
+ /obj/item/toy/prize/phazon = 1,
+ /obj/item/toy/prize/reticence = 1,
+ /obj/item/toy/cards/deck = 2,
+ /obj/item/toy/nuke = 2,
+ /obj/item/toy/minimeteor = 2,
+ /obj/item/toy/carpplushie = 2,
+ /obj/item/toy/foamblade = 2,
+ /obj/item/toy/redbutton = 2,
+ /obj/item/toy/owl = 2,
+ /obj/item/toy/griffin = 2
)
/obj/machinery/computer/arcade/New()
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index f21f71a1fa0..6d9d994f85e 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -186,120 +186,6 @@
..()
user << "There [amount_left == 1 ? "is" : "are"] [amount_left] cap\s left."
-/*
- * Toy crossbow
- */
-
-/obj/item/toy/crossbow
- name = "foam dart crossbow"
- desc = "A weapon favored by many overactive children. Ages 8 and up."
- icon = 'icons/obj/guns/energy.dmi'
- icon_state = "crossbow100"
- item_state = "crossbow"
- lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/guns_righthand.dmi'
- w_class = 2.0
- attack_verb = list("attacked", "struck", "hit")
- var/bullets = 5
-
-/obj/item/toy/crossbow/examine(mob/user)
- ..()
- if (bullets)
- user << "It is loaded with [bullets] foam dart\s."
-
-/obj/item/toy/crossbow/attackby(obj/item/I as obj, mob/user as mob, params)
- if(istype(I, /obj/item/toy/ammo/crossbow))
- if(bullets <= 4)
- user.drop_item()
- qdel(I)
- bullets++
- user << "You load the foam dart into the crossbow."
- else
- usr << "It's already fully loaded."
-
-
-/obj/item/toy/crossbow/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag)
- if(!isturf(target.loc) || target == user) return
- if(flag) return
-
- if (locate (/obj/structure/table, src.loc))
- return
- else if (bullets)
- var/turf/trg = get_turf(target)
- var/obj/effect/foam_dart_dummy/D = new/obj/effect/foam_dart_dummy(get_turf(src))
- bullets--
- D.icon_state = "foamdart"
- D.name = "foam dart"
- playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1)
-
- for(var/i=0, i<6, i++)
- if (D)
- if(D.loc == trg) break
- step_towards(D,trg)
-
- for(var/mob/living/M in D.loc)
- if(!istype(M,/mob/living)) continue
- if(M == user) continue
- D.visible_message("[M] was hit by the foam dart!")
- new /obj/item/toy/ammo/crossbow(M.loc)
- qdel(D)
- return
-
- for(var/atom/A in D.loc)
- if(A == user) continue
- if(A.density)
- new /obj/item/toy/ammo/crossbow(A.loc)
- qdel(D)
-
- sleep(1)
-
- spawn(10)
- if(D)
- new /obj/item/toy/ammo/crossbow(D.loc)
- qdel(D)
-
- return
- else if (bullets == 0)
- user.Weaken(5)
- user.visible_message("[user] realized they were out of ammo and starting scrounging for some!")
-
-
-/obj/item/toy/crossbow/attack(mob/M as mob, mob/user as mob)
- src.add_fingerprint(user)
-
-// ******* Check
-
- if (src.bullets > 0 && M.lying)
-
- M.visible_message("[user] casually lines up a shot with [M]'s head and pulls the trigger!")
- M.visible_message("[M] was hit in the head by the foam dart!", \
- "You're hit in the head by the foam dart!", \
- "You hear the sound of foam against skull.")
-
- playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1)
- new /obj/item/toy/ammo/crossbow(M.loc)
- src.bullets--
- else if (M.lying && src.bullets == 0)
- M.visible_message("[user] casually lines up a shot with [M]'s head, pulls the trigger, then realizes they are out of ammo and drops to the floor in search of some!")
- user.Weaken(5)
- return
-
-/obj/item/toy/ammo/crossbow
- name = "foam dart"
- desc = "Its nerf or nothing! Ages 8 and up."
- icon = 'icons/obj/toy.dmi'
- icon_state = "foamdart"
- w_class = 1.0
-
-/obj/effect/foam_dart_dummy
- name = ""
- desc = ""
- icon = 'icons/obj/toy.dmi'
- icon_state = "null"
- anchored = 1
- density = 0
-
-
/*
* Toy swords
*/
diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm
index 32e30d6e6f1..06d545def21 100644
--- a/code/modules/projectiles/ammunition/ammo_casings.dm
+++ b/code/modules/projectiles/ammunition/ammo_casings.dm
@@ -199,8 +199,26 @@
/obj/item/ammo_casing/caseless/magspear
name = "magnetic spear"
desc = "A reusable spear that is typically loaded into kinetic spearguns."
- projectile_type = /obj/item/projectile/bullet/magspear
+ projectile_type = /obj/item/projectile/bullet/reusable/magspear
caliber = "speargun"
icon_state = "magspear"
throwforce = 15 //still deadly when thrown
throw_speed = 3
+
+/obj/item/ammo_casing/caseless/foam_dart
+ name = "foam dart"
+ desc = "Its nerf or nothing! Ages 8 and up."
+ projectile_type = /obj/item/projectile/bullet/reusable/foam_dart
+ caliber = "foam_force"
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "foamdart"
+
+/obj/item/ammo_casing/update_icon()
+ ..()
+ icon_state = "[initial(icon_state)]"
+
+/obj/item/ammo_casing/caseless/foam_dart/riot
+ name = "riot foam dart"
+ desc = "Who's smart idea was it to use toys as crowd control? Ages 18 and up."
+ projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/riot
+ icon_state = "foamdart_riot"
diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm
index 6addb24a524..bb06ad9a480 100644
--- a/code/modules/projectiles/ammunition/magazines.dm
+++ b/code/modules/projectiles/ammunition/magazines.dm
@@ -104,6 +104,18 @@
max_ammo = 5
multiload = 1
+/obj/item/ammo_box/magazine/internal/shot/toy
+ ammo_type = /obj/item/ammo_casing/caseless/foam_dart
+ caliber = "foam_force"
+ max_ammo = 4
+
+/obj/item/ammo_box/magazine/internal/cylinder/toy
+ name = "crossbow cylinder"
+ desc = "Oh god, this shouldn't be here"
+ ammo_type = /obj/item/ammo_casing/caseless/foam_dart
+ caliber = "foam_force"
+ max_ammo = 5
+
///////////EXTERNAL MAGAZINES////////////////
/obj/item/ammo_box/magazine/m10mm
@@ -216,3 +228,20 @@ obj/item/ammo_box/magazine/tommygunm45
name = "shotgun magazine (12g dragon's breath)"
icon_state = "m12gf"
ammo_type = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath
+
+/obj/item/ammo_box/magazine/toy
+ name = "foam force SMG magazine"
+ icon_state = "c20r45"
+ ammo_type = /obj/item/ammo_casing/caseless/foam_dart
+ caliber = "foam_force"
+ max_ammo = 18
+ multiple_sprites = 2
+
+/obj/item/ammo_box/magazine/toy/pistol
+ name = "foam force pistol magazine"
+ icon_state = "9x19p"
+ max_ammo = 8
+ multiple_sprites = 2
+
+/obj/item/ammo_box/magazine/toy/pistol/riot
+ ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/projectile/toy.dm b/code/modules/projectiles/guns/projectile/toy.dm
new file mode 100644
index 00000000000..a848fc2bb39
--- /dev/null
+++ b/code/modules/projectiles/guns/projectile/toy.dm
@@ -0,0 +1,58 @@
+/obj/item/weapon/gun/projectile/automatic/toy
+ name = "foam force SMG"
+ desc = "A bullpup three-round burst toy SMG. Ages 8 and up."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "saber"
+ item_state = "c20r"
+ mag_type = /obj/item/ammo_box/magazine/toy
+ fire_sound = 'sound/weapons/Gunshot_smg.ogg'
+ fire_delay = 2
+ force = 0
+ throwforce = 0
+ burst_size = 3
+ can_suppress = 0
+ clumsy_check = 0
+
+/obj/item/weapon/gun/projectile/automatic/toy/process_chamber(var/eject_casing = 0, var/empty_chamber = 1)
+ ..()
+
+/obj/item/weapon/gun/projectile/automatic/toy/pistol
+ name = "foam force pistol"
+ desc = "A small, easily concealable toy handgun. Ages 8 and up."
+ icon_state = "pistol"
+ item_state = "gun"
+ w_class = 2
+ mag_type = /obj/item/ammo_box/magazine/toy/pistol
+ fire_sound = 'sound/weapons/Gunshot.ogg'
+ can_suppress = 0
+ burst_size = 1
+ fire_delay = 0
+ action_button_name = null
+
+/obj/item/weapon/gun/projectile/automatic/toy/pistol/update_icon()
+ ..()
+ icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
+
+/obj/item/weapon/gun/projectile/shotgun/toy
+ name = "foam force shotgun"
+ desc = "A toy shotgun with wood furniture and a four-shell capacity underneath. Ages 8 and up."
+ icon = 'icons/obj/toy.dmi'
+ force = 0
+ throwforce = 0
+ origin_tech = null
+ mag_type = /obj/item/ammo_box/magazine/internal/shot/toy
+ clumsy_check = 0
+
+/obj/item/weapon/gun/projectile/shotgun/toy/process_chamber()
+ ..()
+ if(chambered && !chambered.BB)
+ qdel(chambered)
+
+/obj/item/weapon/gun/projectile/shotgun/toy/crossbow
+ name = "foam force crossbow"
+ desc = "A weapon favored by many overactive children. Ages 8 and up."
+ icon_state = "foamcrossbow"
+ item_state = "crossbow"
+ fire_sound = 'sound/items/syringeproj.ogg'
+ slot_flags = SLOT_BELT
+ w_class = 2
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm
new file mode 100644
index 00000000000..5fc838b4478
--- /dev/null
+++ b/code/modules/projectiles/projectile/reusable.dm
@@ -0,0 +1,37 @@
+/obj/item/projectile/bullet/reusable
+ name = "reusable bullet"
+ desc = "How do you even reuse a bullet?"
+ var/obj/item/ammo_casing/caseless/ammo_type = /obj/item/ammo_casing/caseless/
+
+/obj/item/projectile/bullet/reusable/on_hit(var/atom/target, var/blocked = 0)
+ if(!proj_hit)
+ proj_hit = 1
+ new ammo_type(src.loc)
+ ..()
+
+/obj/item/projectile/bullet/reusable/on_range()
+ if(!proj_hit)
+ new ammo_type(src.loc)
+ ..()
+
+/obj/item/projectile/bullet/reusable/magspear
+ name = "magnetic spear"
+ desc = "WHITE WHALE, HOLY GRAIL"
+ damage = 30 //takes 3 spears to kill a mega carp, one to kill a normal carp
+ icon_state = "magspear"
+ ammo_type = /obj/item/ammo_casing/caseless/magspear
+
+/obj/item/projectile/bullet/reusable/foam_dart
+ name = "foam dart"
+ desc = "I hope you're wearing eye protection."
+ damage = 0 // It's a damn toy.
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "foamdart"
+ ammo_type = /obj/item/ammo_casing/caseless/foam_dart
+ range = 10
+
+/obj/item/projectile/bullet/reusable/foam_dart/riot
+ name = "riot foam dart"
+ icon_state = "foamdart_riot"
+ ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
+ stamina = 24
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index cdcb03031af..d866f286ecb 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -197,21 +197,4 @@ obj/item/projectile/kinetic/New()
/obj/item/projectile/bullet/frag12/on_hit(atom/target, blocked = 0)
explosion(target, -1, 0, 1)
- return 1
-
-/obj/item/projectile/bullet/magspear
- name = "magnetic spear"
- desc = "WHITE WHALE, HOLY GRAIL"
- damage = 30 //takes 3 spears to kill a mega carp, one to kill a normal carp
- icon_state = "magspear"
-
-/obj/item/projectile/bullet/magspear/on_hit(var/atom/target, var/blocked = 0)
- if(!proj_hit)
- proj_hit = 1
- new /obj/item/ammo_casing/caseless/magspear(src.loc)
- ..()
-
-/obj/item/projectile/bullet/magspear/on_range()
- if(!proj_hit)
- new /obj/item/ammo_casing/caseless/magspear(src.loc)
- ..()
+ return 1
\ No newline at end of file
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index c6c852b409a..1cf5dc99795 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -386,6 +386,14 @@
build_path = /obj/item/device/assembly/prox_sensor
category = list("initial", "Misc")
+/datum/design/foam_dart
+ name = "Box of Foam Darts"
+ id = "foam_dart"
+ build_type = AUTOLATHE
+ materials = list("$metal" = 500)
+ build_path = /obj/item/ammo_box/foambox
+ category = list("initial", "Misc")
+
//hacked autolathe recipes
/datum/design/flamethrower
name = "Flamethrower"
diff --git a/html/changelogs/Fayrik-FoamForceFuckYeah.yml b/html/changelogs/Fayrik-FoamForceFuckYeah.yml
new file mode 100644
index 00000000000..acab5161486
--- /dev/null
+++ b/html/changelogs/Fayrik-FoamForceFuckYeah.yml
@@ -0,0 +1,10 @@
+author: Fayrik
+
+delete-after: True
+
+changes:
+ - rscdel: "Deleted the toy crossbow that wasn't a gun, but flung projectiles like a gun. Why was that even a thing?"
+ - rscadd: "Added an abstract new type of reusable ammo."
+ - rscadd: "Added three new foam force guns and a foam force crossbow, all of which take the new foam dart ammo."
+ - rscadd: "Added foam force darts to the autolathe, and a crate orderable from cargo containing the new guns."
+ - rscadd: "New crossbow can be won as an arcade prize."
\ No newline at end of file
diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi
index 5c62c63a925..8e76f75029b 100644
Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ