Pneumatic Cannons can now be placed on tables and some cleanup/QOL. (#95571)

## About The Pull Request

The Pneumatic Cannon: ~~god's greatest mistake~~

On live there's current a bug, almost certainly attack chain-based
causing the cannon to be unable to be placed on tables. This most often
occurs with the clown's pie cannon, as it will always try and fire at
the table instead of putting it down. This PR corrects this by adding a
small intermediary proc similar to the ones guns use in order to verify
some of the conditions that could prevent you from firing the pneumatic
cannon, while still letting you fire point blank at another mob.

Additionally, Autodocs some variables, as well as axing a variable that
was doing quite literally nothing that another variable was already
doing.

Finally, cleans up some of the logic on `examine()` for the cannon, such
as not looping through 50 pies that an automatic pie cannon can hold,
and cleaning up some magic numbers a bit with some self explanatory
logic regarding combined weight on self-charging pneumatic cannons.

## Why It's Good For The Game

Cleans up some attack chain code, and allows for everyone favorite
non-gun gun to behave in a similar way to a gun that we'd all expect.

Also, makes the examine text a bit more useful, such as displaying the
contents of the cannon in a way that doesn't require a CHECK_TICK for
something that can only hold pies.

Lastly, cleans up most of the var documentation because it's my pet
peeve

## Changelog

🆑
qol: The pneumatic cannon's examine will now show the contents of the
cannon loaded.
fix: You may now place a pneumatic cannon (and the clown's pie cannon!)
onto tables.
/🆑
This commit is contained in:
ArcaneMusic
2026-04-03 15:33:26 +01:00
committed by GitHub
parent 8040eb3aae
commit 57e46b4c9c
@@ -1,7 +1,11 @@
/// Fire all loaded contents at once.
#define PCANNON_FIREALL 1
/// First in, Last out.
#define PCANNON_FILO 2
/// First in, first out. Default value.
#define PCANNON_FIFO 3
///Defines for the pressure strength of the cannon
#define LOW_PRESSURE 1
#define MID_PRESSURE 2
@@ -21,27 +25,40 @@
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
armor_type = /datum/armor/item_pneumatic_cannon
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6)
var/maxWeightClass = 20 //The max weight of items that can fit into the cannon
var/loadedWeightClass = 0 //The weight of items currently in the cannon
var/obj/item/tank/internals/tank = null //The gas tank that is drawn from to fire things
var/gasPerThrow = 3 //How much gas is drawn from a tank's pressure to fire
var/list/loadedItems = list() //The items loaded into the cannon that will be fired out
var/pressure_setting = LOW_PRESSURE //How powerful the cannon is - higher pressure = more gas but more powerful throws
var/checktank = TRUE
/// The max weight of items that can fit into the cannon
var/maxWeightClass = 20
/// The weight of items currently in the cannon
var/loadedWeightClass = 0
/// The gas tank that is drawn from to fire things
var/obj/item/tank/internals/tank = null
/// How much gas is drawn from a tank's pressure to fire
var/gasPerThrow = 3
/// The items loaded into the cannon that will be fired out
var/list/loadedItems = list()
/// How powerful the cannon is - higher pressure = more gas but more powerful throws
var/pressure_setting = LOW_PRESSURE
/// Additional multiplier that adjusts how much farther thrown objects can travel.
var/range_multiplier = 1
var/throw_amount = 1 //How many items to throw per fire
/// How many items to throw per fire
var/throw_amount = 1
/// What methodology should be used when firing? See #defines at top of file.
var/fire_mode = PCANNON_FIFO
/// Allows you to hold down LMB to continuously fire.
var/automatic = FALSE
/// Determines if a pneumatic cannon needs an air tank to fire. False for things like the pie cannons.
var/needs_air = TRUE
/// If true, has side effects if fired with the clumsy trait (read: clowns)
var/clumsyCheck = TRUE
var/list/allowed_typecache //Leave as null to allow all.
///Leave as null to allow all. Otherwise whitelists what can be inserted into the cannon.
var/list/allowed_typecache
var/charge_amount = 1
var/charge_ticks = 1
var/charge_tick = 0
var/charge_type
var/atom/charge_type
var/selfcharge = FALSE
var/fire_sound = 'sound/items/weapons/sonic_jackhammer.ogg'
var/spin_item = TRUE //Do the projectiles spin when launched?
///Do the projectiles spin when launched?
var/spin_item = TRUE
trigger_guard = TRIGGER_GUARD_NORMAL
@@ -86,9 +103,15 @@
if(!in_range(user, src))
out += span_notice("You'll need to get closer to see any more.")
return
for(var/obj/item/I in loadedItems)
out += span_info("[icon2html(I, user)] It has \a [I] loaded.")
CHECK_TICK
if(selfcharge)
if(length(loadedItems))
out += span_info("[icon2html(pick(loadedItems), user)] It has [length(loadedItems)] [charge_type::name] loaded.")
else
for(var/obj/item/I in loadedItems)
out += span_info("[icon2html(I, user)] It has \a [I] loaded.")
CHECK_TICK
if(!length(loadedItems))
out += span_info("The chamber has nothing loaded.")
if(tank)
out += span_notice("[icon2html(tank, user)] It has \a [tank] mounted onto it. It could be removed with a <b>screwdriver</b>.")
if(needs_air == TRUE)
@@ -165,6 +188,8 @@
/obj/item/pneumatic_cannon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(user.combat_mode)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!pre_fire(user, interacting_with))
return NONE
Fire(user, interacting_with)
return ITEM_INTERACT_SUCCESS
@@ -172,6 +197,15 @@
Fire(user, interacting_with)
return ITEM_INTERACT_SUCCESS
/** Checks */
/obj/item/pneumatic_cannon/proc/pre_fire(mob/living/user, atom/target)
if(user.Adjacent(target))
if(target in user.contents)
return FALSE
if(!ismob(target))
return FALSE
return TRUE
/obj/item/pneumatic_cannon/proc/Fire(mob/living/user, atom/target)
if(!istype(user) && !target)
return
@@ -181,7 +215,7 @@
if(!loadedItems || !loadedWeightClass)
to_chat(user, span_warning("\The [src] has nothing loaded."))
return
if(!tank && checktank)
if(!tank && needs_air)
to_chat(user, span_warning("\The [src] can't fire without a source of gas."))
return
if(HAS_TRAIT(user, TRAIT_PACIFISM))
@@ -313,11 +347,9 @@
force = 10
icon_state = "piecannon"
gasPerThrow = 0
checktank = FALSE
range_multiplier = 3
fire_mode = PCANNON_FIFO
throw_amount = 1
maxWeightClass = 150 //50 pies. :^)
maxWeightClass = (/obj/item/food/pie::w_class * 50) //50 pies. :^)
needs_air = FALSE
clumsyCheck = FALSE
var/static/list/pie_typecache = typecacheof(/obj/item/food/pie)
@@ -330,13 +362,13 @@
automatic = TRUE
selfcharge = TRUE
charge_type = /obj/item/food/pie/cream
maxWeightClass = 60 //20 pies.
maxWeightClass = (/obj/item/food/pie::w_class * 20) //20 pies.
/obj/item/pneumatic_cannon/pie/selfcharge/cyborg
name = "low velocity pie cannon"
automatic = FALSE
charge_type = /obj/item/food/pie/cream/nostun
maxWeightClass = 6 //2 pies
maxWeightClass = (/obj/item/food/pie::w_class * 2) //2 pies
charge_ticks = 2 //4 second/pie
#undef PCANNON_FIREALL