Files
Bubberstation/code/datums/components/basic_mob_attack_telegraph.dm
Sealed101 297f7f88e8 Fixes things about goliaths: wallhacks/range hacks(no, really) and tentacles not spawning in mineral turfs; also fixes find_potential_targets wallhacks (#77393)
## About The Pull Request

Goliath's sand digging behaviour could potentially target a turf that's
actually unreachable by the goliath, e.g.
```
G#
#T
```
where G - goliath # - wall T - target turf. fixed that, but i think
there could be something easier here, maybe instead grabbing turfs in
goliath's `view()`? unsure

The component goliaths use to telegraph their attacks
(`basic_mob_attack_telegraph`) casts a `do_after()` to perform the
attack, but it was not actually checking for the target staying in melee
range, as it was using the source goliath as both `user` and `target`,
so it didn't actually care at all for the target. Implemented an
`extra_checks` to `Adjacent()` since that's the closest we get for melee
range shenanigans I suppose
This still allows the source basicmob to attack the target if the target
moves around the source basicmob.

`!`Goliaths were also able to summon tentacles on a target that moved
into cover and still stayed in the `find_potential_targets` target
range. Which meant more wallhacks. This was a thing for the base
`find_potential_targets`, meaning that every basic mob using it was a
dirty haxxor (or very vengeful). Fixed that by making
`find_potential_targets` also check for `can_see()` before proceeding
further down `find_potential_targets/perform()`. `!` The only exception
to this check currently are bileworms.

`!`Goliath tentacles were not spawning in mineral turfs as their
`Initialize()` checked for closed turfs before handling mineral turf
mining. Fixed that as well.

## Why It's Good For The Game

![Dr__Hax_by_Didgeridoo_Dealer](https://github.com/tgstation/tgstation/assets/75863639/fbcbfc1b-f489-435e-bb01-677f55398787)

## Changelog

🆑
fix: fixed goliaths digging sand that they can't actually reach (behind
windows or inbetween closed turfs)
fix: fixed goliaths melee attacking their target despite the target
running away from goliath melee range
fix: fixed goliath tentacles not spawning in mineral turfs
fix: fixed goliaths summoning tentacles on targets that moved behind
cover but stayed in their targeting range. this applies for most basic
mobs, really, so if any basic mob was targeting you despite you hauling
ass behind cover, they shouldn't anymore
/🆑
2023-08-07 13:02:09 +01:00

84 lines
3.3 KiB
Plaintext

/**
* Delays outgoing attacks which are directed at mobs to give players time to get out of the way
*/
/datum/component/basic_mob_attack_telegraph
/// Time to wait before attack can complete
var/telegraph_duration
/// Overlay which we display over targets
var/mutable_appearance/target_overlay
/// Our current target, if we have one
var/mob/living/current_target
/// Callback executed when we start aiming at something
var/datum/callback/on_began_forecast
/datum/component/basic_mob_attack_telegraph/Initialize(
telegraph_icon = 'icons/mob/telegraphing/telegraph.dmi',
telegraph_state = ATTACK_EFFECT_BITE,
telegraph_duration = 0.3 SECONDS,
datum/callback/on_began_forecast,
)
. = ..()
if (!isbasicmob(parent))
return ELEMENT_INCOMPATIBLE
target_overlay = mutable_appearance(telegraph_icon, telegraph_state)
src.telegraph_duration = telegraph_duration
src.on_began_forecast = on_began_forecast
/datum/component/basic_mob_attack_telegraph/RegisterWithParent()
. = ..()
RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_attack))
/datum/component/basic_mob_attack_telegraph/UnregisterFromParent()
if (current_target)
forget_target(current_target)
QDEL_NULL(target_overlay)
REMOVE_TRAIT(parent, TRAIT_BASIC_ATTACK_FORECAST, REF(src))
UnregisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)
return ..()
/// When we attempt to attack, check if it is allowed
/datum/component/basic_mob_attack_telegraph/proc/on_attack(mob/living/basic/source, atom/target)
SIGNAL_HANDLER
if (!isliving(target))
return
if (HAS_TRAIT_FROM(source, TRAIT_BASIC_ATTACK_FORECAST, REF(src)))
REMOVE_TRAIT(source, TRAIT_BASIC_ATTACK_FORECAST, REF(src))
return
if (!DOING_INTERACTION(source, INTERACTION_BASIC_ATTACK_FORCEAST))
INVOKE_ASYNC(src, PROC_REF(delayed_attack), source, target)
return COMPONENT_HOSTILE_NO_ATTACK
/// Perform an attack after a delay
/datum/component/basic_mob_attack_telegraph/proc/delayed_attack(mob/living/basic/source, mob/living/target)
current_target = target
target.add_overlay(target_overlay)
RegisterSignal(target, COMSIG_QDELETING, PROC_REF(forget_target))
RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(target_moved))
on_began_forecast?.Invoke(target)
//we stop the do_after if the target moves out of neighboring turfs but if they dance around us they get their face smashed
if (!do_after(source, delay = telegraph_duration, target = target, timed_action_flags = IGNORE_TARGET_LOC_CHANGE, extra_checks = CALLBACK(source, TYPE_PROC_REF(/atom/movable, Adjacent), target), interaction_key = INTERACTION_BASIC_ATTACK_FORCEAST))
forget_target(target)
return
if (isnull(target)) // They got out of the way :(
return
ADD_TRAIT(source, TRAIT_BASIC_ATTACK_FORECAST, REF(src))
forget_target(target)
source.melee_attack(target)
/// The guy we're trying to attack moved, is he still in range?
/datum/component/basic_mob_attack_telegraph/proc/target_moved(mob/living/target)
SIGNAL_HANDLER
if (in_range(parent, target))
return
forget_target(target)
/// The guy we're trying to attack isn't a valid target any more
/datum/component/basic_mob_attack_telegraph/proc/forget_target(atom/target)
SIGNAL_HANDLER
current_target = null
target.cut_overlay(target_overlay)
UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED))