diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index 14ba43ef0e8..530542d6581 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -314,6 +314,7 @@ GLOBAL_LIST_INIT(rarity_loot, list(//rare: really good items
list(//misc
/obj/item/disk/nuclear/fake = 1,
/obj/item/book/granter/crafting_recipe/pipegun_prime = 1,
+ /obj/item/book/granter/crafting_recipe/trash_cannon = 1,
) = 1,
))
diff --git a/code/datums/components/crafting/recipes.dm b/code/datums/components/crafting/recipes.dm
index ae175a8af4e..5a26c5ac75b 100644
--- a/code/datums/components/crafting/recipes.dm
+++ b/code/datums/components/crafting/recipes.dm
@@ -544,6 +544,32 @@
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
+/datum/crafting_recipe/trash_cannon
+ name = "Trash Cannon"
+ always_available = FALSE
+ tool_behaviors = list(TOOL_WELDER, TOOL_SCREWDRIVER)
+ result = /obj/structure/cannon/trash
+ reqs = list(
+ /obj/item/melee/skateboard/improvised = 1,
+ /obj/item/tank/internals/oxygen/red = 1,
+ /datum/reagent/drug/maint/tar = 15,
+ /obj/item/restraints/handcuffs/cable = 1,
+ /obj/item/storage/toolbox = 1,
+ )
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
+
+/datum/crafting_recipe/trashball
+ name = "Trashball"
+ always_available = FALSE
+ result = /obj/item/stack/cannonball/trashball
+ reqs = list(
+ /obj/item/stack/sheet = 5,
+ /datum/reagent/consumable/space_cola = 10,
+ )
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
/datum/crafting_recipe/chainsaw
name = "Chainsaw"
result = /obj/item/chainsaw
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index 48d4e4005f6..5e8976e58df 100644
--- a/code/game/objects/items/granters.dm
+++ b/code/game/objects/items/granters.dm
@@ -444,3 +444,18 @@
/obj/item/book/granter/crafting_recipe/pipegun_prime/recoil(mob/living/carbon/user)
to_chat(user, span_warning("The book turns to dust in your hands."))
qdel(src)
+
+/obj/item/book/granter/crafting_recipe/trash_cannon
+ name = "diary of a demoted engineer"
+ desc = "A lost journal. The engineer seems very deranged about their demotion."
+ crafting_recipe_types = list(
+ /datum/crafting_recipe/trash_cannon,
+ /datum/crafting_recipe/trashball,
+ )
+ icon_state = "book1"
+ oneuse = TRUE
+ remarks = list("\"I'll show them! I'll build a CANNON!\"", "\"Gunpowder is ideal, but i'll have to improvise...\"", "\"I savor the look on the CE's face when I BLOW down the walls to engineering!\"", "\"If the supermatter gets loose from my rampage, so be it!\"", "\"I'VE GONE COMPLETELY MENTAL!\"")
+
+/obj/item/book/granter/crafting_recipe/trash_cannon/recoil(mob/living/carbon/user)
+ to_chat(user, span_warning("The book turns to dust in your hands."))
+ qdel(src)
diff --git a/code/game/objects/structures/cannon.dm b/code/game/objects/structures/cannon.dm
deleted file mode 100644
index ce8b1807b82..00000000000
--- a/code/game/objects/structures/cannon.dm
+++ /dev/null
@@ -1,103 +0,0 @@
-/obj/structure/cannon
- name = "cannon"
- desc = "Holemaker Deluxe: A sporty model with a good stop power. Any cannon enthusiast should be expected to start here."
- density = TRUE
- anchored = TRUE
- icon_state = "falconet_patina"
- max_integrity = 300
- var/obj/item/stack/cannonball/loaded_cannonball = null
- var/charge_ignited = FALSE
- var/fire_delay = 15
- var/charge_size = 15
- var/fire_sound = 'sound/weapons/gun/general/cannon.ogg'
-
-/obj/structure/cannon/Initialize()
- . = ..()
- create_reagents(charge_size)
-
-/obj/structure/cannon/proc/fire()
- for(var/mob/shaken_mob in urange(10, src))
- if(shaken_mob.stat == CONSCIOUS)
- shake_camera(shaken_mob, 3, 1)
-
- playsound(src, fire_sound, 50, TRUE)
- if(loaded_cannonball)
- var/obj/projectile/fired_projectile = new loaded_cannonball.projectile_type(get_turf(src))
- QDEL_NULL(loaded_cannonball)
- fired_projectile.firer = src
- fired_projectile.fired_from = src
- fired_projectile.fire(dir2angle(dir))
- reagents.remove_all()
- charge_ignited = FALSE
-
-/obj/structure/cannon/attackby(obj/item/W, mob/user, params)
- if(charge_ignited)
- to_chat(user, span_danger("[src] is about to fire!"))
- return
- var/ignition_message = W.ignition_effect(src, user)
-
- if(istype(W, /obj/item/stack/cannonball))
- if(loaded_cannonball)
- to_chat(user, span_warning("[src] is already loaded!"))
- else
- var/obj/item/stack/cannonball/cannoneers_balls = W
- loaded_cannonball = new cannoneers_balls.type(src, 1)
- loaded_cannonball.copy_evidences(cannoneers_balls)
- to_chat(user, span_notice("You load a [cannoneers_balls.singular_name] into [src]."))
- cannoneers_balls.use(1, transfer = TRUE)
- return
-
- else if(ignition_message)
- if(!reagents.has_reagent(/datum/reagent/gunpowder,15))
- to_chat(user, span_warning("[src] needs at least 15u of gunpowder to fire!"))
- return
- visible_message(ignition_message)
- log_game("Cannon fired by [key_name(user)] in [AREACOORD(src)]")
- addtimer(CALLBACK(src, .proc/fire), fire_delay)
- charge_ignited = TRUE
- return
-
- else if(istype(W, /obj/item/reagent_containers))
- var/obj/item/reagent_containers/powder_keg = W
- if(!(powder_keg.reagent_flags & OPENCONTAINER))
- return ..()
- if(istype(powder_keg, /obj/item/reagent_containers/glass/rag))
- return ..()
-
- if(!powder_keg.reagents.total_volume)
- to_chat(user, span_warning("[powder_keg] is empty!"))
- return
- else if(!powder_keg.reagents.has_reagent(/datum/reagent/gunpowder, charge_size))
- to_chat(user, span_warning("[powder_keg] doesn't have at least 15u of gunpowder to fill [src]!"))
- return
- if(reagents.has_reagent(/datum/reagent/gunpowder, charge_size))
- to_chat(user, span_warning("[src] already contains a full charge of powder! It would be unwise to add more."))
- return
- powder_keg.reagents.trans_id_to(src, /datum/reagent/gunpowder, amount = charge_size)
- to_chat(user, span_notice("You load [src] with a charge of powder from [powder_keg]."))
- return
- if(W.tool_behaviour == TOOL_WRENCH)
- if(default_unfasten_wrench(user, W, time = 2 SECONDS))
- return
- ..()
-
-/obj/item/paper/crumpled/muddy/fluff/cannon_instructions
- name = "Mast of Cannon's Past's Cannon Instructions"
- desc = "A quickly written note detailing the basics of firing a cannon. Who wrote this?"
- info = @{"
-
-Ye don't know how to load cannon, and ye call yerself a fearsome pirate? I think ye be more alike a space sailor under the space monarchy's flag! Alas, everyone must learn how to blast holes in enemy ships. And thus:
-
-
HOW YE FIRES A CANNON:
-
-BE STEP ONE: LOAD THE LEAD BALL O' YE CHOICE!
-BE STEP TWO: LOAD 15U PIRATE STANDARD CHARGE O' GUNPOWDER!
-BE STEP THREE: LIGHT THE FUSE WITH SOMETHING, AND LET ER' RIP!
-
-
CANNONBALL TYPES:
-
-REGULAR CANNONBALL: A fine choice for killing landlubbers! Will take off any limb it hits, and most certainly down anyone hit in the chest! If they are not directly hit, they will be at least hurt by the shrapnel!
-EXPLOSIVE SHELLBALL: The most elegant in breaching (er killin', if you're good at aimin') tools, ye be packing this shell with many scuppering chemicals! Just make sure to not fire it when ye be close to target!
-MALFUNCTION SHOT: A very gentle "cannonball" dart at first glance, but make no mistake: This is their worst nightmare! Enjoy an easy boarding process while all their machines are broken and all their weapons unloaded from an EMP!
-THE BIGGEST ONE: A shellball, but much bigger. Ye won't be seein' much of these as they were discontinued for sinkin' the firer's ship as often as it sunk the scallywag's ship. Very big boom! If ye have one, ye have been warned!
- "}
diff --git a/code/game/objects/structures/cannons/cannon.dm b/code/game/objects/structures/cannons/cannon.dm
new file mode 100644
index 00000000000..395fb3b3147
--- /dev/null
+++ b/code/game/objects/structures/cannons/cannon.dm
@@ -0,0 +1,138 @@
+///how much projectile damage is lost when using a bad fuel
+#define BAD_FUEL_DAMAGE_TAX 20
+///extra chance it explodes upon firing
+#define BAD_FUEL_EXPLODE_PROBABILTY 10
+
+/obj/structure/cannon
+ name = "cannon"
+ desc = "Holemaker Deluxe: A sporty model with a good stop power. Any cannon enthusiast should be expected to start here."
+ density = TRUE
+ anchored = TRUE
+ icon_state = "falconet_patina"
+ max_integrity = 300
+ ///whether the cannon can be unwrenched from the ground.
+ var/anchorable_cannon = TRUE
+ var/obj/item/stack/cannonball/loaded_cannonball = null
+ var/charge_ignited = FALSE
+ var/fire_delay = 15
+ var/charge_size = 15
+ var/fire_sound = 'sound/weapons/gun/general/cannon.ogg'
+
+/obj/structure/cannon/Initialize()
+ . = ..()
+ create_reagents(charge_size)
+
+/obj/structure/cannon/examine(mob/user)
+ . = ..()
+ . += span_notice("[src] accepts gunpowder or welding fuel.")
+ . += span_warning("Using welding fuel will weaken the force of the projectile fired.")
+
+/obj/structure/cannon/proc/fire()
+ for(var/mob/shaken_mob in urange(10, src))
+ if(shaken_mob.stat == CONSCIOUS)
+ shake_camera(shaken_mob, 3, 1)
+
+ playsound(src, fire_sound, 50, TRUE)
+ flick(icon_state+"_fire", src)
+ if(loaded_cannonball)
+ var/obj/projectile/fired_projectile = new loaded_cannonball.projectile_type(get_turf(src))
+ if(reagents.has_reagent(/datum/reagent/fuel, charge_size))
+ fired_projectile.damage = max(2, fired_projectile.damage - BAD_FUEL_DAMAGE_TAX)
+ QDEL_NULL(loaded_cannonball)
+ fired_projectile.firer = src
+ fired_projectile.fired_from = src
+ fired_projectile.fire(dir2angle(dir))
+ reagents.remove_all()
+ charge_ignited = FALSE
+
+/obj/structure/cannon/attackby(obj/item/used_item, mob/user, params)
+ if(charge_ignited)
+ balloon_alert(user, "it's gonna fire!")
+ return
+ var/ignition_message = used_item.ignition_effect(src, user)
+
+ if(istype(used_item, /obj/item/stack/cannonball))
+ if(loaded_cannonball)
+ balloon_alert(user, "already loaded!")
+ else
+ var/obj/item/stack/cannonball/cannoneers_balls = used_item
+ loaded_cannonball = new cannoneers_balls.type(src, 1)
+ loaded_cannonball.copy_evidences(cannoneers_balls)
+ balloon_alert(user, "loaded a [cannoneers_balls.singular_name]")
+ cannoneers_balls.use(1, transfer = TRUE)
+ return
+
+ else if(ignition_message)
+ if(!reagents.has_reagent(/datum/reagent/gunpowder,charge_size) || !reagents.has_reagent(/datum/reagent/fuel,charge_size))
+ balloon_alert(user, "needs [reagents.maximum_volume]u of charge!")
+ return
+ visible_message(ignition_message)
+ log_game("Cannon fired by [key_name(user)] in [AREACOORD(src)]")
+ addtimer(CALLBACK(src, .proc/fire), fire_delay)
+ charge_ignited = TRUE
+ return
+
+ else if(istype(used_item, /obj/item/reagent_containers))
+ var/obj/item/reagent_containers/powder_keg = used_item
+ if(!(powder_keg.reagent_flags & OPENCONTAINER))
+ return ..()
+ if(istype(powder_keg, /obj/item/reagent_containers/glass/rag))
+ return ..()
+
+ if(!powder_keg.reagents.total_volume)
+ balloon_alert(user, "[powder_keg] is empty!")
+ return
+ if(reagents.total_volume == reagents.maximum_volume)
+ balloon_alert(user, "[src] is full!")
+ return
+ var/has_enough_gunpowder = powder_keg.reagents.has_reagent(/datum/reagent/gunpowder, charge_size)
+ var/has_enough_alt_fuel = powder_keg.reagents.has_reagent(/datum/reagent/fuel, charge_size)
+ if(!has_enough_gunpowder && !has_enough_alt_fuel)
+ balloon_alert(user, "[powder_keg] needs 15u of charge to load!")
+ to_chat(user, span_warning("[powder_keg] doesn't have at least 15u of gunpowder to fill [src]!"))
+ return
+ if(has_enough_gunpowder)
+ powder_keg.reagents.trans_id_to(src, /datum/reagent/gunpowder, amount = charge_size)
+ balloon_alert(user, "[src] loaded with gunpowder")
+ return
+ if(has_enough_alt_fuel)
+ powder_keg.reagents.trans_id_to(src, /datum/reagent/fuel, amount = charge_size)
+ balloon_alert(user, "[src] loaded with welding fuel")
+ return
+ if(anchorable_cannon && used_item.tool_behaviour == TOOL_WRENCH)
+ if(default_unfasten_wrench(user, used_item, time = 2 SECONDS))
+ return
+ ..()
+
+/obj/structure/cannon/trash
+ name = "trash cannon"
+ desc = "Okay, sure, you could call it a toolbox welded to an opened oxygen tank cabled to a skateboard, but it's a TRASH CANNON to us."
+ icon_state = "garbagegun"
+ anchored = FALSE
+ anchorable_cannon = FALSE
+ var/fires_before_deconstruction = 5
+
+/obj/structure/cannon/trash/fire()
+ var/explode_chance = 10
+ var/used_alt_fuel = reagents.has_reagent(/datum/reagent/fuel, charge_size)
+ if(used_alt_fuel)
+ explode_chance += BAD_FUEL_EXPLODE_PROBABILTY
+ . = ..()
+ fires_before_deconstruction--
+ if(used_alt_fuel)
+ fires_before_deconstruction--
+ if(prob(explode_chance))
+ visible_message(span_userdanger("[src] explodes!"))
+ explosion(src, heavy_impact_range = 1, light_impact_range = 5, flame_range = 5)
+ return
+ if(fires_before_deconstruction <= 0)
+ visible_message(span_warning("[src] falls apart from operation!"))
+ qdel(src)
+
+/obj/structure/cannon/trash/Destroy()
+ new /obj/item/stack/sheet/iron/five(src.loc)
+ new /obj/item/stack/rods(src.loc)
+ . = ..()
+
+#undef BAD_FUEL_DAMAGE_TAX
+#undef BAD_FUEL_EXPLODE_PROBABILTY
diff --git a/code/game/objects/structures/cannons/cannon_instructions.dm b/code/game/objects/structures/cannons/cannon_instructions.dm
new file mode 100644
index 00000000000..1ae484598d0
--- /dev/null
+++ b/code/game/objects/structures/cannons/cannon_instructions.dm
@@ -0,0 +1,20 @@
+/obj/item/paper/crumpled/muddy/fluff/cannon_instructions
+ name = "Mast of Cannon's Past's Cannon Instructions"
+ desc = "A quickly written note detailing the basics of firing a cannon. Who wrote this?"
+ info = @{"
+
+Ye don't know how to load cannon, and ye call yerself a fearsome pirate? I think ye be more alike a space sailor under the space monarchy's flag! Alas, everyone must learn how to blast holes in enemy ships. And thus:
+
+
HOW YE FIRES A CANNON:
+
+BE STEP ONE: LOAD THE LEAD BALL O' YE CHOICE!
+BE STEP TWO: LOAD 15U PIRATE STANDARD CHARGE O' GUNPOWDER!
+BE STEP THREE: LIGHT THE FUSE WITH SOMETHING, AND LET ER' RIP!
+
+
CANNONBALL TYPES:
+
+REGULAR CANNONBALL: A fine choice for killing landlubbers! Will take off any limb it hits, and most certainly down anyone hit in the chest! If they are not directly hit, they will be at least hurt by the shrapnel!
+EXPLOSIVE SHELLBALL: The most elegant in breaching (er killin', if you're good at aimin') tools, ye be packing this shell with many scuppering chemicals! Just make sure to not fire it when ye be close to target!
+MALFUNCTION SHOT: A very gentle "cannonball" dart at first glance, but make no mistake: This is their worst nightmare! Enjoy an easy boarding process while all their machines are broken and all their weapons unloaded from an EMP!
+THE BIGGEST ONE: A shellball, but much bigger. Ye won't be seein' much of these as they were discontinued for sinkin' the firer's ship as often as it sunk the scallywag's ship. Very big boom! If ye have one, ye have been warned!
+ "}
diff --git a/code/game/objects/items/stacks/cannonballs.dm b/code/game/objects/structures/cannons/cannonballs.dm
similarity index 83%
rename from code/game/objects/items/stacks/cannonballs.dm
rename to code/game/objects/structures/cannons/cannonballs.dm
index 4f66129932f..62a05a270aa 100644
--- a/code/game/objects/items/stacks/cannonballs.dm
+++ b/code/game/objects/structures/cannons/cannonballs.dm
@@ -56,3 +56,15 @@
/obj/item/stack/cannonball/the_big_one/five
amount = 5
+
+/obj/item/stack/cannonball/trashball
+ name = "trashballs"
+ singular_name = "trashball"
+ desc = "A clump of tightly packed garbage. It'll work as a cannonball, but it may be unhealthy to actually put this in a real cannon."
+ max_amount = 4
+ icon_state = "trashballs"
+ merge_type = /obj/item/stack/cannonball/trashball
+ projectile_type = /obj/projectile/bullet/cannonball/trashball
+
+/obj/item/stack/cannonball/trashball/four
+ amount = 4
diff --git a/code/modules/projectiles/projectile/bullets/cannon.dm b/code/modules/projectiles/projectile/bullets/cannonball.dm
similarity index 91%
rename from code/modules/projectiles/projectile/bullets/cannon.dm
rename to code/modules/projectiles/projectile/bullets/cannonball.dm
index b879e80bf97..9ee931e7f1f 100644
--- a/code/modules/projectiles/projectile/bullets/cannon.dm
+++ b/code/modules/projectiles/projectile/bullets/cannonball.dm
@@ -57,3 +57,8 @@
if(projectile_piercing == NONE)
explosion(target, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE)
. = ..()
+
+/obj/projectile/bullet/cannonball/trashball
+ name = "trashball"
+ icon_state = "trashball"
+ damage = 90 //better than the biggest one but no explosion, so kinda just a worse normal cannonball
diff --git a/icons/obj/cannons.dmi b/icons/obj/cannons.dmi
new file mode 100644
index 00000000000..f0e37c5310a
Binary files /dev/null and b/icons/obj/cannons.dmi differ
diff --git a/icons/obj/guns/projectiles.dmi b/icons/obj/guns/projectiles.dmi
index bb3c2ad2d9c..28546c5576f 100644
Binary files a/icons/obj/guns/projectiles.dmi and b/icons/obj/guns/projectiles.dmi differ
diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi
index 18788980284..e739ad63c7b 100644
Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 06d0043836d..f1232291af1 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1343,7 +1343,6 @@
#include "code\game\objects\items\robot\robot_upgrades.dm"
#include "code\game\objects\items\stacks\ammonia_crystals.dm"
#include "code\game\objects\items\stacks\bscrystal.dm"
-#include "code\game\objects\items\stacks\cannonballs.dm"
#include "code\game\objects\items\stacks\cash.dm"
#include "code\game\objects\items\stacks\license_plates.dm"
#include "code\game\objects\items\stacks\medical.dm"
@@ -1398,7 +1397,6 @@
#include "code\game\objects\structures\artstuff.dm"
#include "code\game\objects\structures\barsigns.dm"
#include "code\game\objects\structures\bedsheet_bin.dm"
-#include "code\game\objects\structures\cannon.dm"
#include "code\game\objects\structures\chess.dm"
#include "code\game\objects\structures\destructible_structures.dm"
#include "code\game\objects\structures\displaycase.dm"
@@ -1464,6 +1462,9 @@
#include "code\game\objects\structures\beds_chairs\chair.dm"
#include "code\game\objects\structures\beds_chairs\pew.dm"
#include "code\game\objects\structures\beds_chairs\sofa.dm"
+#include "code\game\objects\structures\cannons\cannon.dm"
+#include "code\game\objects\structures\cannons\cannon_instructions.dm"
+#include "code\game\objects\structures\cannons\cannonballs.dm"
#include "code\game\objects\structures\construction_console\construction_actions.dm"
#include "code\game\objects\structures\construction_console\construction_console.dm"
#include "code\game\objects\structures\construction_console\construction_console_aux.dm"
@@ -3159,7 +3160,7 @@
#include "code\modules\projectiles\projectile\bullets.dm"
#include "code\modules\projectiles\projectile\magic.dm"
#include "code\modules\projectiles\projectile\bullets\_incendiary.dm"
-#include "code\modules\projectiles\projectile\bullets\cannon.dm"
+#include "code\modules\projectiles\projectile\bullets\cannonball.dm"
#include "code\modules\projectiles\projectile\bullets\dart_syringe.dm"
#include "code\modules\projectiles\projectile\bullets\dnainjector.dm"
#include "code\modules\projectiles\projectile\bullets\grenade.dm"