From 3feb8c959b45bccb198d0645a5c9a9afa3236ff3 Mon Sep 17 00:00:00 2001
From: Ryll Ryll <3589655+Ryll-Ryll@users.noreply.github.com>
Date: Wed, 3 Mar 2021 19:27:36 -0500
Subject: [PATCH] Fixes runtimes from firing projectiles, adds unit test for
firing guns (#57345)
---
.../mining/equipment/kinetic_crusher.dm | 3 ++-
.../carbon/alien/humanoid/alien_powers.dm | 3 ++-
.../mob/living/simple_animal/hostile/ooze.dm | 3 ++-
.../modules/projectiles/ammunition/_firing.dm | 3 ++-
.../projectiles/guns/misc/beam_rifle.dm | 6 +++--
.../projectiles/guns/misc/blastcannon.dm | 3 ++-
code/modules/projectiles/projectile.dm | 3 +++
code/modules/unit_tests/projectiles.dm | 24 +++++++++++++++++++
.../mecha/equipment/weapons/weapons.dm | 3 ++-
9 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index d3f5e768a09..cde49333b12 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -96,6 +96,7 @@
/obj/item/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams)
. = ..()
+ var/modifiers = params2list(clickparams)
if(!wielded)
return
if(!proximity_flag && charged)//Mark a target, or mine a tile.
@@ -106,7 +107,7 @@
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
T.on_projectile_fire(D, user)
- D.preparePixelProjectile(target, user, clickparams)
+ D.preparePixelProjectile(target, user, modifiers)
D.firer = user
D.hammer_synced = src
playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, TRUE)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index 60b4a1f30f9..96286cf1b6e 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -227,9 +227,10 @@ Doesn't work on other aliens/AI.*/
if(!isturf(U) || !isturf(T))
return FALSE
+ var/modifiers = params2list(params)
user.visible_message("[user] spits neurotoxin!", "You spit neurotoxin.")
var/obj/projectile/neurotoxin/neurotoxin = new /obj/projectile/neurotoxin(user.loc)
- neurotoxin.preparePixelProjectile(target, user, params)
+ neurotoxin.preparePixelProjectile(target, user, modifiers)
neurotoxin.fire()
user.newtonian_move(get_dir(U, T))
user.adjustPlasma(-p_cost)
diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm
index 5df93518d4b..a7d49c4d2b1 100644
--- a/code/modules/mob/living/simple_animal/hostile/ooze.dm
+++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm
@@ -363,8 +363,9 @@
return
ooze.visible_message("You launch a mending globule.")
+ var/modifiers = params2list(params)
var/obj/projectile/globule/globule = new (ooze.loc)
- globule.preparePixelProjectile(target, ooze, params)
+ globule.preparePixelProjectile(target, ooze, modifiers)
globule.def_zone = ooze.zone_selected
globule.fire()
ooze.adjust_ooze_nutrition(-5)
diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm
index 0861a0fcdce..ddc37bcdcd9 100644
--- a/code/modules/projectiles/ammunition/_firing.dm
+++ b/code/modules/projectiles/ammunition/_firing.dm
@@ -61,7 +61,8 @@
if(target) //if the target is right on our location we'll skip the travelling code in the proj's fire()
direct_target = target
if(!direct_target)
- loaded_projectile.preparePixelProjectile(target, user, params, spread)
+ var/modifiers = params2list(params)
+ loaded_projectile.preparePixelProjectile(target, user, modifiers, spread)
loaded_projectile.fire(null, direct_target)
loaded_projectile = null
return TRUE
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index 4581d83a31b..eb70e5376bf 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -201,7 +201,8 @@
if(!istype(curloc))
return
targloc = get_turf_in_angle(lastangle, curloc, 10)
- P.preparePixelProjectile(targloc, current_user, current_user.client.mouseParams, 0)
+ var/mouse_modifiers = params2list(current_user.client.mouseParams)
+ P.preparePixelProjectile(targloc, current_user, mouse_modifiers, 0)
P.fire(lastangle)
/obj/item/gun/energy/beam_rifle/process()
@@ -394,7 +395,8 @@
firing_dir = loaded_projectile.firer.dir
if(!loaded_projectile.suppressed && firing_effect_type)
new firing_effect_type(get_turf(src), firing_dir)
- loaded_projectile.preparePixelProjectile(target, user, params, spread)
+ var/modifiers = params2list(params)
+ loaded_projectile.preparePixelProjectile(target, user, modifiers, spread)
loaded_projectile.fire(gun? gun.lastangle : null, null)
loaded_projectile = null
return TRUE
diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm
index 4455a12799d..673d793b812 100644
--- a/code/modules/projectiles/guns/misc/blastcannon.dm
+++ b/code/modules/projectiles/guns/misc/blastcannon.dm
@@ -123,7 +123,8 @@
message_admins("Blast wave fired from [ADMIN_VERBOSEJMP(starting)] at [ADMIN_VERBOSEJMP(targturf)] ([target.name]) by [ADMIN_LOOKUPFLW(user)] with power [heavy]/[medium]/[light].")
log_game("Blast wave fired from [AREACOORD(starting)] at [AREACOORD(targturf)] ([target.name]) by [key_name(user)] with power [heavy]/[medium]/[light].")
var/obj/projectile/blastwave/BW = new(loc, heavy, medium, light)
- BW.preparePixelProjectile(target, get_turf(src), params, 0)
+ var/modifiers = params2list(params)
+ BW.preparePixelProjectile(target, get_turf(src), modifiers, 0)
BW.fire()
name = initial(name)
desc = initial(desc)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 20e57e0f273..618c6a94871 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -850,6 +850,9 @@
//Spread is FORCED!
/obj/projectile/proc/preparePixelProjectile(atom/target, atom/source, modifiers, spread = 0)
+ if(!isnull(modifiers) && !islist(modifiers))
+ stack_trace("WARNING: Projectile [type] fired with non-list modifiers, likely was passed click params.")
+
var/turf/curloc = get_turf(source)
var/turf/targloc = get_turf(target)
trajectory_ignore_forcemove = TRUE
diff --git a/code/modules/unit_tests/projectiles.dm b/code/modules/unit_tests/projectiles.dm
index 06a8fb0780a..b42a2e54e5a 100644
--- a/code/modules/unit_tests/projectiles.dm
+++ b/code/modules/unit_tests/projectiles.dm
@@ -3,3 +3,27 @@
var/obj/projectile/projectile = path
if(initial(projectile.movement_type) & PHASING)
Fail("[path] has default movement type PHASING. Piercing projectiles should be done using the projectile piercing system, not movement_types!")
+
+/datum/unit_test/gun_go_bang/Run()
+ // test is for a ballistic gun that starts loaded + chambered
+ var/obj/item/gun/test_gun = allocate(/obj/item/gun/ballistic/automatic/pistol)
+ var/mob/living/carbon/human/victim = allocate(/mob/living/carbon/human)
+ var/mob/living/carbon/human/gunner = allocate(/mob/living/carbon/human)
+
+ ADD_TRAIT(victim, TRAIT_RESISTLOWPRESSURE, INNATE_TRAIT) // so pressure damage doesn't throw off our damage check
+
+ var/obj/item/ammo_casing/loaded_casing = test_gun.chambered
+ TEST_ASSERT(loaded_casing, "Gun started without round chambered, should be loaded")
+ var/obj/projectile/loaded_bullet = loaded_casing.loaded_projectile
+ TEST_ASSERT(loaded_bullet, "Ammo casing has no loaded bullet")
+
+ gunner.put_in_hands(test_gun, forced=TRUE)
+ gunner.set_combat_mode(FALSE) // just to make sure we know we're not trying to pistol-whip them
+ var/expected_damage = loaded_bullet.damage
+ loaded_bullet.def_zone = BODY_ZONE_CHEST
+ var/did_we_shoot = test_gun.afterattack(victim, gunner)
+ TEST_ASSERT(did_we_shoot, "Gun does not appeared to have successfully fired.")
+ TEST_ASSERT_EQUAL(victim.getBruteLoss(), expected_damage, "Victim took incorrect amount of damage, expected [expected_damage], got [victim.getBruteLoss()].")
+
+ var/obj/item/bodypart/expected_part = victim.get_bodypart(BODY_ZONE_CHEST)
+ TEST_ASSERT_EQUAL(expected_part.brute_dam, expected_damage, "Intended bodypart took incorrect amount of damage, either it hit another bodypart or armor was incorrectly applied. Expected [expected_damage], got [expected_part.brute_dam].")
diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
index 3e9751b1411..e36fefb04f2 100644
--- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
+++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
@@ -37,7 +37,8 @@
spread = round((i / projectiles_per_shot - 0.5) * variance)
var/obj/projectile/A = new projectile(get_turf(src))
- A.preparePixelProjectile(target, source, params, spread)
+ var/modifiers = params2list(params)
+ A.preparePixelProjectile(target, source, modifiers, spread)
A.fire()
if(!A.suppressed && firing_effect_type)