mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-26 00:51:23 +00:00
* Give basic mob ranged attacks a cooldown (#77575) ## About The Pull Request Atomised change from a different PR I am working on. This changes the basic mob ranged attacks element into a component so that it can also track an attack cooldown on the mob, preventing it from firing until the cooldown is complete. This was possible with simple mobs but wasn't kept going forwards when converting things to basic ones. ## Why It's Good For The Game Ideally player and mob behaviour should be unified as much as is realistically possible. Currently mobs which are designed to fire a powerful weapon slowly can blast as rapidly as the click cooldown if placed under control of a player, which is not ideal. This isn't currently aligned for melee attacks either but I will look at that later. ## Changelog 🆑 fix: Player-controlled basic mobs with ranged attacks can now only fire about as fast as AI-controlled ones. /🆑 * Give basic mob ranged attacks a cooldown * Modular update --------- Co-authored-by: Jacquerel <hnevard@gmail.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
79 lines
2.7 KiB
Plaintext
79 lines
2.7 KiB
Plaintext
/**
|
|
* Configurable ranged attack for basic mobs.
|
|
*/
|
|
/datum/component/ranged_attacks
|
|
/// What kind of casing do we use to fire?
|
|
var/casing_type
|
|
/// What kind of projectile to we fire? Use only one of this or casing_type
|
|
var/projectile_type
|
|
/// Sound to play when we fire our projectile
|
|
var/projectile_sound
|
|
/// Time to wait between shots
|
|
var/cooldown_time
|
|
/// Tracks time between shots
|
|
COOLDOWN_DECLARE(fire_cooldown)
|
|
|
|
/datum/component/ranged_attacks/Initialize(
|
|
casing_type,
|
|
projectile_type,
|
|
projectile_sound = 'sound/weapons/gun/pistol/shot.ogg',
|
|
cooldown_time = 3 SECONDS,
|
|
)
|
|
. = ..()
|
|
if(!isbasicmob(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.casing_type = casing_type
|
|
src.projectile_sound = projectile_sound
|
|
src.projectile_type = projectile_type
|
|
src.cooldown_time = cooldown_time
|
|
|
|
if (casing_type && projectile_type)
|
|
CRASH("Set both casing type and projectile type in [parent]'s ranged attacks component! uhoh! stinky!")
|
|
if (!casing_type && !projectile_type)
|
|
CRASH("Set neither casing type nor projectile type in [parent]'s ranged attacks component! What are they supposed to be attacking with, air?")
|
|
|
|
/datum/component/ranged_attacks/RegisterWithParent()
|
|
. = ..()
|
|
RegisterSignal(parent, COMSIG_MOB_ATTACK_RANGED, PROC_REF(fire_ranged_attack))
|
|
ADD_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type)
|
|
|
|
/datum/component/ranged_attacks/UnregisterFromParent()
|
|
. = ..()
|
|
UnregisterSignal(parent, COMSIG_MOB_ATTACK_RANGED)
|
|
REMOVE_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type)
|
|
|
|
/datum/component/ranged_attacks/proc/fire_ranged_attack(mob/living/basic/firer, atom/target, modifiers)
|
|
SIGNAL_HANDLER
|
|
if (!COOLDOWN_FINISHED(src, fire_cooldown))
|
|
return
|
|
COOLDOWN_START(src, fire_cooldown, cooldown_time)
|
|
INVOKE_ASYNC(src, PROC_REF(async_fire_ranged_attack), firer, target, modifiers)
|
|
|
|
/// Actually fire the damn thing
|
|
/datum/component/ranged_attacks/proc/async_fire_ranged_attack(mob/living/basic/firer, atom/target, modifiers)
|
|
playsound(firer, projectile_sound, 100, TRUE)
|
|
var/turf/startloc = get_turf(firer)
|
|
|
|
if(casing_type)
|
|
var/obj/item/ammo_casing/casing = new casing_type(startloc)
|
|
var/target_zone
|
|
if(ismob(target))
|
|
var/mob/target_mob = target
|
|
target_zone = target_mob.get_random_valid_zone()
|
|
else
|
|
target_zone = ran_zone()
|
|
casing.fire_casing(target, firer, null, null, null, target_zone, 0, firer)
|
|
casing.AddElement(/datum/element/temporary_atom, 30 SECONDS)
|
|
return
|
|
|
|
var/obj/projectile/bullet = new projectile_type(startloc)
|
|
bullet.starting = startloc
|
|
bullet.firer = firer
|
|
bullet.fired_from = firer
|
|
bullet.yo = target.y - startloc.y
|
|
bullet.xo = target.x - startloc.x
|
|
bullet.original = target
|
|
bullet.preparePixelProjectile(target, firer)
|
|
bullet.fire()
|