From 9e1f3798fa3778309babc4d5fbc7658a4a5e6170 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:06:02 +0200 Subject: [PATCH] [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 :cl: 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. /:cl: * Ancient and recent mecha bug fixes --------- Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com> --- .../signals/signals_mob/signals_mob_main.dm | 2 +- code/datums/elements/relay_attackers.dm | 2 +- .../lavaland/watcher/watcher_overwatch.dm | 2 +- code/modules/vehicles/mecha/_mecha.dm | 14 ++++------ .../mecha/equipment/weapons/weapons.dm | 22 +++++++++++----- .../vehicles/mecha/mech_melee_attack.dm | 26 +++++++++++++++++-- code/modules/vehicles/mecha/mecha_movement.dm | 18 ++++++++----- 7 files changed, 59 insertions(+), 27 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 8ada1c30be3..39fa037a264 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -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" diff --git a/code/datums/elements/relay_attackers.dm b/code/datums/elements/relay_attackers.dm index 5f5bf7ed589..fd87cb3bc2c 100644 --- a/code/datums/elements/relay_attackers.dm +++ b/code/datums/elements/relay_attackers.dm @@ -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) diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm index 541a4ed9e1c..a61ea0743f9 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm @@ -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, ) diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index 1155e6293d2..ed1d7c1d94b 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -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) diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm index d13b90e5659..5b50ac93523 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm @@ -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. diff --git a/code/modules/vehicles/mecha/mech_melee_attack.dm b/code/modules/vehicles/mecha/mech_melee_attack.dm index 08669ebdd0c..e5c7b0aac72 100644 --- a/code/modules/vehicles/mecha/mech_melee_attack.dm +++ b/code/modules/vehicles/mecha/mech_melee_attack.dm @@ -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) diff --git a/code/modules/vehicles/mecha/mecha_movement.dm b/code/modules/vehicles/mecha/mecha_movement.dm index 53e61690aba..3c743bd7fb3 100644 --- a/code/modules/vehicles/mecha/mecha_movement.dm +++ b/code/modules/vehicles/mecha/mecha_movement.dm @@ -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)