mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 14:08:31 +01:00
Bigger Booms: Adds Pipe-Organ Gun and Canister Gatling, two emplaced weapons, along with Mounted Gun code. (#86390)
## About The Pull Request  So, as you may know, I really like the bootleg weaponry this game has, but after dealing with gun code for the crossbow, I wasnt inclined to make more of it. However, when I'm playing ss13 I often have background noise on, and one day I was listening to an age of empires game, which, if you aren't aware, is basically a medival rts, featuring a weapon called an "organ gun". Said organ gun is basically 8 or so muskets stuck together firing at once. And well, given SS13 has pipeguns, also called muskets, I couldnt pass up the pun of "pipe organ gun." And thats why this pr exists. However, as I am noticing I have a habit of doing, I tend to end up coding more than I ever initially planned. So what does it add? Well, lets start with the pipe organ gun. <img width="428" alt="image" src="https://github.com/user-attachments/assets/0cb93fb9-6ed3-4cb1-a340-0b54832ac577"> The pipe organ gun is made from wood, pipes, iron, typical maints weapon stuff. Where it differs is it isn't a handheld object - it's a machine you push and pull around akin to say, the pirate cannons. It can hold up to 8 pipegun shells, and launches them all at once when lit with anything that ignites stuff, like a welder, match, torch, etc. It does a lot of damage, but requires time to reload, and a smart enemy can just lie down and ignore it. Or maybe it'll just roll 8 of the really bad ammo types and do nothing, who knows. https://github.com/user-attachments/assets/5ee1353b-c965-4f47-aa22-4f5cfeb04c51 Initially I planned to use the cannon code as a base, but that presented a lot of issues, as they need to use cannonballs (which arent ammo in the traditonal sense), along with only being single shot among other things. So I made an entire new type of structure called Mounted guns, which are like cannons that can use conventional ballistic ammo, and dont have any of the restrictions, and made to be customizable. You want a gun that takes plasma bars as ammo and launches fireballs? it can do that. You want to have a rebar ballista, that can shoot up to 3 rods at once, but only needs to be loaded once? It can do that too. Hell, you could probably just make full-on gun emplacements with some code changes. If it's a projectile, it can shoot it, and if its an object, it can use it as ammo. A list of the current stuff you can change is below. <img width="510" alt="image" src="https://github.com/user-attachments/assets/107abbc1-a004-4724-9627-a3388f92cd63"> Which leads me to the second gun I added, which is more of an example of what can be done with the mounted_gun class. The canister gatling spawns on the flying dutchman pirate ship, with enough ammo for five shots. <img width="453" alt="image" src="https://github.com/user-attachments/assets/46fdc16e-813a-4e14-b25a-9cf49d245ca6"> Five shots may not sound like much at first - but thats because each shot is a burst of 50 individual shrapnel bullets. It's unable to break any walls or doors except for windows, but against anything that isnt a structure... well, as shown below, they'll have a very bad day. https://github.com/user-attachments/assets/3519c49d-97e6-4095-99cf-ee8039adbaba If people like these concepts, I genuinely might add that engineering rebar ballista. ## Why It's Good For The Game As said above, I'm a big fan of the whole improvised armory concept ss13 has, and the fact the only "big" gun featured is the trash cannon (which is locked behind maint loot) is a shame. I felt the pipe-organ gun was a good compromise - as stated, its just eight pipeguns stuck together, with all the strengths (high damage output) and weaknesses (slow reload, needs to be dragged around, cant hit people on the floor, cant damage walls) that it lacks. As for the canister gatling, I dont forsee it being a massive problem, as it cant breach walls or doors, so it isn't just a better cannon. ## Changelog 🆑 WebcomicArtist add: Added pipe-organ gun: a buildable object akin to trash cannon that takes pipegun rounds, and shoots up to 8 off at once. add: Added The Canister Gatling, a rapid fire but non-destructive cannon for skeleton pirates. Also Canister shot ammo. sound: Added sounds for the above guns. image: Added sprites for the guns as well. code: Added a whole "mounted_gun" class that is basically cannons but you aren't forced to use cannonballs as ammo and load them with gunpowder. /🆑
This commit is contained in:
@@ -17,4 +17,10 @@ REGULAR CANNONBALL: A fine choice for killing landlubbers! Will take off any lim
|
||||
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!<br>
|
||||
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!<br>
|
||||
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!
|
||||
|
||||
<br><center><b>FIRING THAR CANISTER GATLING</b><br></center>
|
||||
|
||||
THE CANISTER GATLING AIN'T LIKE OTHER CANNONS, AND DOESN'T REQUIRE GUNPOWDER, INSTEAD RELYING ON SPECIAL CANISTER SHOT SHELLS.
|
||||
ALL YOU HAVE TO DO IS CRAM A SHELL IN THE BREACH, LIGHT HER UP AND YOU'LL BE BLOWING THOSE CORPORATE SODS TO KINGDOM COME!
|
||||
SHE LACKS THE SHEER WALL-BREAKING PUNCH OF THE HOLEMAKERS, BUT CHEWS THROUGH SOFT TARGETS LIKE A SHARK THROUGH A GROUP OF BEACH THROUGH A GROUP OF BEACHGOERS, YAHAR.
|
||||
"}
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
//Mounted guns are basically a smaller equivalent to cannons, designed to use pre-existing ammo rather than cannonballs.
|
||||
//Due to using pre-existing ammo, they dont require to be loaded with gunpowder or an equivalent.
|
||||
|
||||
/obj/structure/mounted_gun
|
||||
name = "Mounted Gun"
|
||||
desc = "Default mounted gun for inheritance purposes."
|
||||
density = TRUE
|
||||
anchored = FALSE
|
||||
icon = 'icons/obj/weapons/cannons.dmi'
|
||||
icon_state = "falconet_patina"
|
||||
var/icon_state_base = "falconet_patina"
|
||||
var/icon_state_fire = "falconet_patina_fire"
|
||||
max_integrity = 300
|
||||
///whether the cannon can be unwrenched from the ground. Anchorable_cannon equivalent.
|
||||
var/anchorable_gun = TRUE
|
||||
///Max shots per firing of the gun.
|
||||
var/max_shots_per_fire = 1
|
||||
///Shots currently loaded. Should never be more than max_shots_per_fire.
|
||||
var/shots_in_gun = 1
|
||||
///shots added to gun, per piece of ammo loaded.
|
||||
var/shots_per_load = 1
|
||||
///Accepted "ammo" type
|
||||
var/obj/item/ammo_type = /obj/item/ammo_casing/strilka310
|
||||
///Projectile from said gun. Doesnt automatically inherit said ammo's projectile in case you wanted to make a gun that shoots floor tiles or something.
|
||||
var/obj/item/projectile_type = /obj/projectile/bullet/strilka310
|
||||
///If the gun has anything in it.
|
||||
var/loaded_gun = TRUE
|
||||
///If the gun is currently loaded with its maximum capacity.
|
||||
var/fully_loaded_gun = TRUE
|
||||
///delay in firing the gun after lighting
|
||||
var/fire_delay = 5
|
||||
///Delay between shots
|
||||
var/shot_delay = 3
|
||||
///If the gun shakes the camera when firing
|
||||
var/firing_shakes_camera = TRUE
|
||||
///sound of firing for all but last shot
|
||||
var/fire_sound = 'sound/weapons/gun/general/mountedgun.ogg'
|
||||
///sound of firing for last shot
|
||||
var/last_fire_sound = 'sound/weapons/gun/general/mountedgunend.ogg'
|
||||
|
||||
/obj/structure/mounted_gun/wrench_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(!anchorable_gun) /// Can't anchor an unanchorable gun.
|
||||
return FALSE
|
||||
default_unfasten_wrench(user, tool)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
///Covers Reloading and lighting of the gun
|
||||
/obj/structure/mounted_gun/attackby(obj/item/ammo_casing/used_item, mob/user, params)
|
||||
var/ignition_message = used_item.ignition_effect(src, user) // Checks if item used can ignite stuff.
|
||||
if(istype(used_item, ammo_type))
|
||||
if(fully_loaded_gun)
|
||||
balloon_alert(user, "already fully loaded!")
|
||||
return
|
||||
else
|
||||
shots_in_gun = shots_in_gun + shots_per_load //Add one to the shots in the gun
|
||||
|
||||
loaded_gun = TRUE // Make sure it registers theres ammo in there, so it can fire.
|
||||
QDEL_NULL(used_item)
|
||||
if(shots_in_gun >= max_shots_per_fire)
|
||||
shots_in_gun = max_shots_per_fire // in case of somehow firing only some of a guns shots, and reloading, you still cant get above the maximum ammo size.
|
||||
fully_loaded_gun = TRUE //So you cant load extra.
|
||||
return
|
||||
|
||||
else if(ignition_message) // if item the player used ignites, light the gun!
|
||||
visible_message(ignition_message)
|
||||
user.log_message("fired a cannon", LOG_ATTACK)
|
||||
log_game("[key_name(user)] fired a cannon in [AREACOORD(src)]")
|
||||
addtimer(CALLBACK(src, PROC_REF(fire)), fire_delay) //uses fire proc as shown below to shoot the gun
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/structure/mounted_gun/proc/fire()
|
||||
if (!loaded_gun)
|
||||
balloon_alert_to_viewers("gun is not loaded!","",2)
|
||||
return
|
||||
for(var/times_fired = 1, times_fired <= shots_in_gun, times_fired++) //The normal DM for loop structure since the times it has fired is changing in the loop itself.
|
||||
for(var/mob/shaken_mob in urange(10, src))
|
||||
if(shaken_mob.stat == CONSCIOUS && firing_shakes_camera == TRUE)
|
||||
shake_camera(shaken_mob, 3, 1)
|
||||
icon_state = icon_state_fire
|
||||
if(loaded_gun)
|
||||
|
||||
if (times_fired < shots_in_gun)
|
||||
playsound(src, fire_sound, 50, FALSE, 5)
|
||||
else
|
||||
playsound(src, last_fire_sound, 50, TRUE, 5)
|
||||
var/obj/projectile/fired_projectile = new projectile_type(get_turf(src))
|
||||
fired_projectile.firer = src
|
||||
fired_projectile.fired_from = src
|
||||
fired_projectile.fire(dir2angle(dir))
|
||||
sleep(shot_delay)
|
||||
loaded_gun = FALSE
|
||||
shots_in_gun = 0
|
||||
fully_loaded_gun = FALSE
|
||||
icon_state = icon_state_base
|
||||
|
||||
/obj/structure/mounted_gun/pipe
|
||||
|
||||
name = "Pipe Organ Gun"
|
||||
desc = "To become master over one who has killed, one must become a better killer. This engine of destruction is one of many things made to that end."
|
||||
icon_state = "pipeorgangun"
|
||||
icon_state_base = "pipeorgangun"
|
||||
icon_state_fire = "pipeorgangun_fire"
|
||||
anchored = FALSE
|
||||
anchorable_gun = TRUE
|
||||
max_shots_per_fire = 8
|
||||
shots_in_gun = 8
|
||||
shots_per_load = 2
|
||||
ammo_type = /obj/item/ammo_casing/junk
|
||||
projectile_type = /obj/projectile/bullet/junk
|
||||
loaded_gun = TRUE
|
||||
fully_loaded_gun = TRUE
|
||||
fire_delay = 3
|
||||
shot_delay = 2
|
||||
firing_shakes_camera = FALSE
|
||||
|
||||
/obj/structure/mounted_gun/pipe/examine_more(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("<b><i>Looking down at the [name], you recall a tale told to you in some distant memory...</i></b>")
|
||||
|
||||
. += span_info("To commit an act of vengeance is not unlike to enter a blood pact with a devil, ending the life of another, at the cost of your own.")
|
||||
. += span_info("When humanity first spilled the blood of its own kind, with likely nothing more than a rock, the seal was broken. Vengeance was borne unto the world.")
|
||||
. += span_info("However, vengeance alone is not enough to carry through the grim deed of murder. One must an gain advantage over their adversary.")
|
||||
. += span_info("As such, the man who ended another's life with a stone, was in turn smote himself by another wielding a spear. After spears, bows. Swords. Guns. Tanks. Missiles. And on and on Vengeance fed. Growing stronger. Growing Worse.")
|
||||
. += span_info("Vengeance persists to this day. It sometimes may slumber, seemingly content with having gorged itself, but in the end, its ceaseless hunger can be neither numbed nor sated.")
|
||||
|
||||
/obj/structure/mounted_gun/pipe/fire()
|
||||
if (!loaded_gun)
|
||||
balloon_alert_to_viewers("Gun is not loaded!","",2)
|
||||
return
|
||||
for(var/times_fired = 1, times_fired <= shots_in_gun, times_fired++) //The normal DM for loop structure since the times it has fired is changing in the loop itself.
|
||||
for(var/mob/shaken_mob in urange(10, src))
|
||||
if((shaken_mob.stat == CONSCIOUS)&&(firing_shakes_camera == TRUE))
|
||||
shake_camera(shaken_mob, 3, 1)
|
||||
icon_state = icon_state_fire
|
||||
if(loaded_gun)
|
||||
playsound(src, fire_sound, 50, TRUE, 5)
|
||||
|
||||
var/list_of_projectiles = list(
|
||||
/obj/projectile/bullet/junk = 40,
|
||||
/obj/projectile/bullet/incendiary/fire/junk = 25,
|
||||
/obj/projectile/bullet/junk/shock = 25,
|
||||
/obj/projectile/bullet/junk/hunter = 20,
|
||||
/obj/projectile/bullet/junk/phasic = 8,
|
||||
/obj/projectile/bullet/junk/ripper = 8,
|
||||
/obj/projectile/bullet/junk/reaper = 3,
|
||||
)
|
||||
projectile_type = pick_weight(list_of_projectiles)
|
||||
|
||||
var/obj/projectile/fired_projectile = new projectile_type(get_turf(src))
|
||||
fired_projectile.firer = src
|
||||
fired_projectile.fired_from = src
|
||||
fired_projectile.fire(dir2angle(dir))
|
||||
sleep(shot_delay)
|
||||
loaded_gun = FALSE
|
||||
shots_in_gun = 0
|
||||
fully_loaded_gun = FALSE
|
||||
icon_state = icon_state_base
|
||||
|
||||
/obj/structure/mounted_gun/canister_gatling //for the funny skeleton pirates!
|
||||
|
||||
name = "Canister Gatling Gun"
|
||||
desc = "''Quantity has a quality of its own.''"
|
||||
icon_state = "canister_gatling"
|
||||
icon_state_base = "canister_gatling"
|
||||
icon_state_fire = "canister_gatling_fire"
|
||||
anchored = FALSE
|
||||
anchorable_gun = TRUE
|
||||
max_shots_per_fire = 50
|
||||
shots_per_load = 50
|
||||
shots_in_gun = 50
|
||||
ammo_type = /obj/item/ammo_casing/canister_shot
|
||||
projectile_type = /obj/projectile/bullet/shrapnel
|
||||
loaded_gun = TRUE
|
||||
fully_loaded_gun = TRUE
|
||||
fire_delay = 3
|
||||
shot_delay = 1
|
||||
firing_shakes_camera = FALSE
|
||||
|
||||
/obj/item/ammo_casing/canister_shot
|
||||
name = "Canister Shot"
|
||||
desc = "A gigantic... well, canister of canister shot. Used for reloading the Canister Gatling Gun."
|
||||
icon_state = "canister_shot"
|
||||
obj_flags = CONDUCTS_ELECTRICITY
|
||||
throwforce = 0
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
Reference in New Issue
Block a user