Files
Bubberstation/code/datums/components/ai_has_target_timer.dm
SkyratBot b73b8b7d0a [MIRROR] Mining mob tweaks [MDB IGNORE] (#23242)
* Mining mob tweaks (#77763)

## About The Pull Request

~~I wanted to do this after #77700 (wow cool numbers) but nobody has
merged it yet despite how simple it is so i'll just hope they don't
conflict.~~ Thanks san

I'm fucking about with mining mobs with the intention of making them
more interesting but not necessarily towards making mining _harder_, but
some of these changes unquestionably have done so.

These changes are mostly in response to feedback about Watchers who are
definitely significantly more threatening than previously, although some
of this is user error.

- Watchers are annoying when traversing lavaland because they use their
ability on you instantly upon acquiring a target, if you are trying to
escape other fauna this quickly becomes deadly.
- A lot of players don't really realise what the overwatch ability is
actually doing and so just complain about getting machine gunned.
- If you _do_ react properly to the ability it still makes fighting them
take a lot longer than it used to.
- The "look away" icon is hard to see in the dark sometimes

To ammeliorate these factors I have:

- Reduced watcher health by ~20%
- Display an alerted graphic over the head of the watcher every time you
trigger the overwatch.
- Multiple watchers now won't overwatch you at the same time (this made
the "penalty" volley essentially become instant death)
- The "look away" icon is rendered above the lighting plane so you can
always see it
- Added a new component which tracks how long a mob has had a specific
target.
- - Watchers will now only Overwatch you if they've seen you for at
least 5 seconds (usually they'll try and shoot at you twice before
this).
- - Goliaths will only tentacle you if they've seen you for at least 3
seconds.

If overwatch is still problematic after this I guess I can just nerf it
to not track movement at all and only respond to attacks.

## Why It's Good For The Game

I don't want to discourage miners from "actually mining" by having them
get sniped just for walking around and the added time-to-kill on these
guys could make clearing tendrils more tedious too.

## Changelog

🆑
balance: Watchers have less health
balance: You can't be overwatched by several watchers at a time
balance: Watchers won't overwatch you instantly upon seeing you
balance: Goliaths won't launch tentacles at you instantly upon seeing
you
/🆑

* Mining mob tweaks

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
2023-08-21 14:32:45 -04:00

80 lines
3.1 KiB
Plaintext

/// Increments a blackboard key while the attached mob is engaged with a particular target, does nothing else on its own
/datum/component/ai_target_timer
/// Blackboard key to store data inside
var/increment_key
/// Blackboard key to watch to indicate whether we are 'in combat'
var/target_key
/// Amount of time we have spent focused on one target
var/time_on_target = 0
/// The last target we had
var/atom/last_target
/// Timer used to see if you
var/reset_clock_timer
/datum/component/ai_target_timer/Initialize(increment_key = BB_BASIC_MOB_HAS_TARGET_TIME, target_key = BB_BASIC_MOB_CURRENT_TARGET)
. = ..()
if (!isliving(parent))
return COMPONENT_INCOMPATIBLE
var/mob/living/mob_parent = parent
if (isnull(mob_parent.ai_controller))
return COMPONENT_INCOMPATIBLE
src.increment_key = increment_key
src.target_key = target_key
/datum/component/ai_target_timer/RegisterWithParent()
. = ..()
RegisterSignal(parent, COMSIG_AI_BLACKBOARD_KEY_SET(target_key), PROC_REF(changed_target))
RegisterSignal(parent, COMSIG_AI_BLACKBOARD_KEY_CLEARED(target_key), PROC_REF(lost_target))
ADD_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type)
/datum/component/ai_target_timer/UnregisterFromParent()
finalise_losing_target()
UnregisterSignal(parent, list(COMSIG_AI_BLACKBOARD_KEY_SET(target_key), COMSIG_AI_BLACKBOARD_KEY_CLEARED(target_key)))
REMOVE_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type)
return ..()
/datum/component/ai_target_timer/Destroy(force, silent)
finalise_losing_target()
return ..()
/// When we get a new target, reset the timer and start processing
/datum/component/ai_target_timer/proc/changed_target(mob/living/source)
SIGNAL_HANDLER
var/mob/living/living_parent = parent
var/atom/new_target = living_parent.ai_controller.blackboard[target_key]
deltimer(reset_clock_timer)
if (new_target == last_target)
return
time_on_target = 0
store_current_time()
START_PROCESSING(SSdcs, src)
if (!isnull(last_target))
UnregisterSignal(last_target, COMSIG_QDELETING)
RegisterSignal(new_target, COMSIG_QDELETING, PROC_REF(finalise_losing_target))
last_target = new_target
/// When we lose our target, start a short timer in case we reacquire it very quickly
/datum/component/ai_target_timer/proc/lost_target()
SIGNAL_HANDLER
reset_clock_timer = addtimer(CALLBACK(src, PROC_REF(finalise_losing_target)), 3 SECONDS, TIMER_STOPPABLE | TIMER_DELETE_ME)
/// Called if we have had no target for long enough
/datum/component/ai_target_timer/proc/finalise_losing_target()
deltimer(reset_clock_timer)
STOP_PROCESSING(SSdcs, src)
if (!isnull(last_target))
UnregisterSignal(last_target, COMSIG_QDELETING)
last_target = null
time_on_target = 0
if (!QDELETED(parent))
store_current_time()
/// Store the current time on our timer in our blackboard key
/datum/component/ai_target_timer/proc/store_current_time()
var/mob/living/living_parent = parent
living_parent.ai_controller.set_blackboard_key(increment_key, time_on_target)
/datum/component/ai_target_timer/process(seconds_per_tick)
time_on_target += seconds_per_tick SECONDS
store_current_time()