mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-15 20:22:07 +00:00
* Removes watcher overwatch ability (#78292) ## About The Pull Request Removes the "overwatch" ability from Watchers, allowing them to use their "look away" ability at any health threshold instead (but only if it's been fighting you for at least 5 seconds or if you attack it). Drops the cooldown on the gaze a little bit to compensate. Also fixes some weird behaviour I noticed while testing: - It won't cancel its own ability by trying to back away from you. - It will look at you when it shoots you. ## Why It's Good For The Game I was cooking too hard with this one. - Two abilities overcomplicates what are supposed to be a pretty simple mob you fight in packs. - It wasn't obvious what you were actually supposed to do when targetted. - Doing it wrong could be very punishing in groups. - Doing it _right_ was still kind of unexciting. This is an ability to give to an elite, not a random trash mob. ## Changelog 🆑 balance: Watchers will no longer put you at gunpoint. /🆑 * Removes watcher overwatch ability --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
89 lines
3.1 KiB
Plaintext
89 lines
3.1 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
|
|
/// how many shots we will fire
|
|
var/burst_shots
|
|
/// intervals between shots
|
|
var/burst_intervals
|
|
/// 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',
|
|
burst_shots,
|
|
burst_intervals = 0.2 SECONDS,
|
|
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?")
|
|
if(burst_shots <= 1)
|
|
return
|
|
src.burst_shots = burst_shots
|
|
src.burst_intervals = burst_intervals
|
|
|
|
/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)
|
|
if(isnull(burst_shots))
|
|
return
|
|
for(var/i in 1 to (burst_shots - 1))
|
|
addtimer(CALLBACK(src, PROC_REF(async_fire_ranged_attack), firer, target, modifiers), i * burst_intervals)
|
|
|
|
/// Actually fire the damn thing
|
|
/datum/component/ranged_attacks/proc/async_fire_ranged_attack(mob/living/basic/firer, atom/target, modifiers)
|
|
firer.face_atom(target)
|
|
if(projectile_type)
|
|
firer.fire_projectile(projectile_type, target, projectile_sound)
|
|
SEND_SIGNAL(parent, COMSIG_BASICMOB_POST_ATTACK_RANGED, target, modifiers)
|
|
return
|
|
playsound(firer, projectile_sound, 100, TRUE)
|
|
var/turf/startloc = get_turf(firer)
|
|
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.update_appearance()
|
|
casing.AddElement(/datum/element/temporary_atom, 30 SECONDS)
|
|
SEND_SIGNAL(parent, COMSIG_BASICMOB_POST_ATTACK_RANGED, target, modifiers)
|
|
return
|
|
|