[MIRROR] Ancient and recent mecha bug fixes (#28522)

* Ancient and recent mecha bug fixes (#84171)

## About The Pull Request

Mecha guns actually utilize random spread while firing if ``randomspread
= TRUE``. Currently every weapon that isn't the shotguns are always
pinpoint even if they would have variance.

Makes bumpsmash and melee attacks in a mech use the same cooldown. The
actual speed between bumpsmash melees are the same as before (once every
0.3 seconds) and click melee is the same as well (once every second).
However, if you do one or the other, it will put you on cooldown for
both. The reason for this is that they're literally just calling the
same proc but not respecting each others cooldowns. So we've
consolidated this into one cooldown with varying cooldown timers. I
don't even think this is the most elegant solution, but I'm not going to
make any radical changes of the structure of the code. Fuck that.

**Edit** I forgot to mention this but you have to be in combat mode to
bumpsmash as a consequence of the above changes. You're fucking welcome.

Separates out mecha_melee_attack proc on the ``/obj/`` level to instead
only ``/obj/structure`` and ``/obj/machinery``, which is the only things
we should be attacking in the /obj/ list. I don't even want to know what
mechs have been able to punch while this wasn't the case. Probably
nothing they should have.

## Why It's Good For The Game

Mechs are a fucking diabolical nightmare of procs and some truly ancient
code. Over time, things have gotten worse, as we have no one really
actively maintaining some of this consistently. One of these bugs is
literally day of mech implementation. I shit you not.

## Changelog
🆑
fix: Mecha weaponry is capable, for the first time ever, of experiencing
recoil. This was an intended mechanic, I promise. The code just
literally never worked.
fix: Mecha bump melee attacks and click melee attacks are now on the
same cooldown, but have varying cooldown timers. You will always bump
attack faster than you will click.
fix: You must be in combat mode to punch objects and to bumpsmash into
objects.
fix: Stops mecha being able to punch literally any object and damage
them.
code: Tidies up some of the autodoc comments for mech weapons.
/🆑

* Ancient and recent mecha bug fixes

---------

Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-07-01 19:36:02 +05:30
committed by GitHub
co-authored by necromanceranne
parent 3a780a4c8c
commit 9e1f3798fa
7 changed files with 59 additions and 27 deletions
@@ -205,7 +205,7 @@
///Sent by pilot of mech in /obj/vehicle/sealed/mecha/on_mouseclick when using mech equipment : (/obj/vehicle/sealed/mecha/mech)
#define COMSIG_MOB_USED_MECH_EQUIPMENT "mob_used_mech_equipment"
///Sent by pilot of mech in /obj/vehicle/sealed/mecha/on_mouseclick when triggering mech punch : (/obj/vehicle/sealed/mecha/mech)
#define COMSIG_MOB_USED_MECH_MELEE "mob_used_mech_melee"
#define COMSIG_MOB_USED_CLICK_MECH_MELEE "mob_used_click_mech_melee"
///from living/flash_act(), when a mob is successfully flashed.
#define COMSIG_MOB_FLASHED "mob_flashed"
+1 -1
View File
@@ -85,7 +85,7 @@
SIGNAL_HANDLER
relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK)
/datum/element/relay_attackers/proc/on_attack_mech(atom/target, obj/vehicle/sealed/mecha/mecha_attacker, mob/living/pilot)
/datum/element/relay_attackers/proc/on_attack_mech(atom/target, obj/vehicle/sealed/mecha/mecha_attacker, mob/living/pilot, mecha_attack_cooldown)
SIGNAL_HANDLER
relay_attacker(target, mecha_attacker, ATTACKER_DAMAGING_ATTACK)
@@ -76,7 +76,7 @@
COMSIG_MOB_ITEM_ATTACK,
COMSIG_MOB_THROW,
COMSIG_MOB_USED_MECH_EQUIPMENT,
COMSIG_MOB_USED_MECH_MELEE,
COMSIG_MOB_USED_CLICK_MECH_MELEE,
COMSIG_MOVABLE_MOVED,
)
+5 -9
View File
@@ -16,6 +16,7 @@
* Clicks are wither translated into mech_melee_attack (see mech_melee_attack.dm)
* Or are used to call action() on equipped gear
* Cooldown for gear is on the mech because exploits
* Cooldown for melee is on mech_melee_attack also because exploits
*/
/obj/vehicle/sealed/mecha
name = "exosuit"
@@ -28,7 +29,6 @@
movedelay = 1 SECONDS
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_EXTREMELY_STRONG
COOLDOWN_DECLARE(mecha_bump_smash)
light_system = OVERLAY_LIGHT_DIRECTIONAL
light_on = FALSE
light_range = 6
@@ -139,7 +139,7 @@
var/turnsound = 'sound/mecha/mechturn.ogg'
///Cooldown duration between melee punches
var/melee_cooldown = 10
var/melee_cooldown = CLICK_CD_SLOW
///TIme taken to leave the mech
var/exit_delay = 2 SECONDS
@@ -194,9 +194,6 @@
///Wether we are strafing
var/strafe = FALSE
///Cooldown length between bumpsmashes
var/smashcooldown = 3
///Bool for whether this mech can only be used on lavaland
var/lavaland_only = FALSE
@@ -703,10 +700,9 @@
return
use_energy(melee_energy_drain)
SEND_SIGNAL(user, COMSIG_MOB_USED_MECH_MELEE, src)
target.mech_melee_attack(src, user)
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown)
SEND_SIGNAL(user, COMSIG_MOB_USED_CLICK_MECH_MELEE, src)
if(target.mech_melee_attack(src, user))
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown)
/// Driver alt clicks anything while in mech
/obj/vehicle/sealed/mecha/proc/on_click_alt(mob/user, atom/target, params)
@@ -4,14 +4,22 @@
equipment_slot = MECHA_WEAPON
destroy_sound = 'sound/mecha/weapdestr.ogg'
mech_flags = EXOSUIT_MODULE_COMBAT
/// The type of bullet generated by the mecha weapon.
var/projectile
/// The sound of the mecha weapon firing.
var/fire_sound
/// How many shots are fired per action.
var/projectiles_per_shot = 1
/// The degrees by which each individual bullet fans out from a central point. A predictable spray of bullets.
var/variance = 0
var/randomspread = FALSE //use random spread for machineguns, instead of shotgun scatter
/// Whether our bullets go off trajectory while firing randomly. Used to replicate recoil and not a structured, predictable spray.
var/randomspread = FALSE
/// The amount in deciseconds that the weapon sleeps between shots to simulate a 'burst fire'. The delay stops another bullet from being fired while sleeping.
var/projectile_delay = 0
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired.
var/kickback = TRUE //Will using this weapon in no grav push mecha back.
//the visual effect appearing when the weapon is fired.
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect
/// Will using this weapon in no grav push mecha back.
var/kickback = TRUE
/obj/item/mecha_parts/mecha_equipment/weapon/special_attaching_interaction(attach_right = FALSE, obj/vehicle/sealed/mecha/mech, mob/user, checkonly = FALSE)
var/obj/item/mecha_parts/mecha_equipment/concealed_weapon_bay/bay
@@ -43,17 +51,19 @@
/obj/item/mecha_parts/mecha_equipment/weapon/action(mob/source, atom/target, list/modifiers)
if(!action_checks(target))
return FALSE
/// Find our mecha, find the opposite direction. Used for kickback while the mecha is drifting in zero-g to launch us in this direction.
var/newtonian_target = REVERSE_DIR(chassis.dir)
. = ..()//start the cooldown early because of sleeps
for(var/i in 1 to projectiles_per_shot)
for(var/projectiles_to_shoot in 1 to projectiles_per_shot)
if(energy_drain && !chassis.has_charge(energy_drain))//in case we run out of energy mid-burst, such as emp
break
var/spread = 0
if(variance)
if(randomspread)
spread = round((rand() - 0.5) * variance)
spread = round((rand(0 , 1) - 0.5) * variance, 1)
else
spread = round((i / projectiles_per_shot - 0.5) * variance)
spread = round((projectiles_to_shoot / projectiles_per_shot - 0.5) * variance, 1)
var/obj/projectile/projectile_obj = new projectile(get_turf(src))
projectile_obj.log_override = TRUE //we log being fired ourselves a little further down.
@@ -2,7 +2,7 @@
* ## Mech melee attack
* Called when a mech melees a target with fists
* Handles damaging the target & associated effects
* return value is number of damage dealt
* return value is number of damage dealt. returning a value puts our mech onto attack cooldown.
* Arguments:
* * mecha_attacker: Mech attacking this target
* * user: mob that initiated the attack from inside the mech as a controller
@@ -14,6 +14,9 @@
return 0
/turf/closed/wall/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user)
if(!user.combat_mode)
return 0
mecha_attacker.do_attack_animation(src)
switch(mecha_attacker.damtype)
if(BRUTE)
@@ -31,7 +34,26 @@
..()
return 100 //this is an arbitrary "damage" number since the actual damage is rng dismantle
/obj/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user)
/obj/structure/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user)
if(!user.combat_mode)
return 0
mecha_attacker.do_attack_animation(src)
switch(mecha_attacker.damtype)
if(BRUTE)
playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
if(BURN)
playsound(src, 'sound/items/welder.ogg', 50, TRUE)
else
return 0
mecha_attacker.visible_message(span_danger("[mecha_attacker] hits [src]!"), span_danger("You hit [src]!"), null, COMBAT_MESSAGE_RANGE)
..()
return take_damage(mecha_attacker.force * 3, mecha_attacker.damtype, "melee", FALSE, get_dir(src, mecha_attacker)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
/obj/machinery/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user)
if(!user.combat_mode)
return 0
mecha_attacker.do_attack_animation(src)
switch(mecha_attacker.damtype)
if(BRUTE)
+11 -7
View File
@@ -154,13 +154,17 @@
return
if(.) //mech was thrown/door/whatever
return
if(bumpsmash) //Need a pilot to push the PUNCH button.
if(COOLDOWN_FINISHED(src, mecha_bump_smash))
var/list/mob/mobster = return_drivers()
obstacle.mech_melee_attack(src, mobster[1])
COOLDOWN_START(src, mecha_bump_smash, smashcooldown)
if(!obstacle || obstacle.CanPass(src, get_dir(obstacle, src) || dir)) // The else is in case the obstacle is in the same turf.
step(src,dir)
// Whether or not we're on our mecha melee cooldown
var/on_cooldown = TIMER_COOLDOWN_RUNNING(src, COOLDOWN_MECHA_MELEE_ATTACK)
if(bumpsmash && !on_cooldown)
// Our pilot for this evening
var/list/mob/mobster = return_drivers()
if(obstacle.mech_melee_attack(src, mobster[1]))
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown * 0.3)
if(!obstacle || obstacle.CanPass(src, get_dir(obstacle, src) || dir)) // The else is in case the obstacle is in the same turf.
step(src,dir)
if(isobj(obstacle))
var/obj/obj_obstacle = obstacle
if(!obj_obstacle.anchored && obj_obstacle.move_resist <= move_force)