[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>
This commit is contained in:
SkyratBot
2023-08-21 20:32:45 +02:00
committed by GitHub
parent b657de9a70
commit b73b8b7d0a
11 changed files with 116 additions and 9 deletions
@@ -53,6 +53,7 @@
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_HEAVY)
AddElement(/datum/element/basic_eating, heal_amt = 10, food_types = goliath_foods)
AddComponent(/datum/component/ai_target_timer)
AddComponent(/datum/component/basic_mob_attack_telegraph)
AddComponentFrom(INNATE_TRAIT, /datum/component/shovel_hands)
if (tameable)
@@ -1,3 +1,6 @@
/// We won't use tentacles unless we have had the same target for this long
#define MIN_TIME_TO_TENTACLE 3 SECONDS
/datum/ai_controller/basic_controller/goliath
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items/goliath,
@@ -20,12 +23,16 @@
stat_attack = HARD_CRIT
/datum/ai_planning_subtree/basic_melee_attack_subtree/goliath
operational_datums = list(/datum/component/ai_target_timer)
melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/goliath
/// Go for the tentacles if they're available
/datum/ai_behavior/basic_melee_attack/goliath
/datum/ai_behavior/basic_melee_attack/goliath/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, health_ratio_key)
var/time_on_target = controller.blackboard[BB_BASIC_MOB_HAS_TARGET_TIME] || 0
if (time_on_target < MIN_TIME_TO_TENTACLE)
return ..()
var/mob/living/target = controller.blackboard[target_key]
// Interrupt attack chain to use tentacles, unless the target is already tentacled
if (ismecha(target) || (isliving(target) && !target.has_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled)))
@@ -37,11 +44,15 @@
/datum/ai_planning_subtree/targeted_mob_ability/goliath_tentacles
ability_key = BB_GOLIATH_TENTACLES
operational_datums = list(/datum/component/ai_target_timer)
/datum/ai_planning_subtree/targeted_mob_ability/goliath_tentacles/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
var/mob/living/target = controller.blackboard[target_key]
if (!(isliving(target) || ismecha(target)) || (isliving(target) && target.has_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled)))
return // Target can be an item or already grabbed, we don't want to tentacle those
var/time_on_target = controller.blackboard[BB_BASIC_MOB_HAS_TARGET_TIME] || 0
if (time_on_target < MIN_TIME_TO_TENTACLE)
return // We need to spend some time acquiring our target first
return ..()
/// If we got nothing better to do, find a turf we can search for tasty roots and such
@@ -115,3 +126,5 @@
/datum/ai_behavior/goliath_dig/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
controller.clear_blackboard_key(target_key)
#undef MIN_TIME_TO_TENTACLE
@@ -11,8 +11,8 @@
base_pixel_x = -12
speak_emote = list("chimes")
speed = 3
maxHealth = 200
health = 200
maxHealth = 160
health = 160
attack_verb_continuous = "buffets"
attack_verb_simple = "buffet"
crusher_loot = /obj/item/crusher_trophy/watcher_wing
@@ -44,6 +44,7 @@
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/simple_flying)
AddElement(/datum/element/content_barfer)
AddComponent(/datum/component/ai_target_timer)
AddComponent(/datum/component/basic_ranged_ready_overlay, overlay_state = eye_glow)
AddComponent(\
/datum/component/ranged_attacks,\
@@ -84,8 +85,8 @@
icon_living = "watcher_magmawing"
icon_dead = "watcher_magmawing_dead"
eye_glow = "fire_glow"
maxHealth = 215 //Compensate for the lack of slowdown on projectiles with a bit of extra health
health = 215
maxHealth = 175 //Compensate for the lack of slowdown on projectiles with a bit of extra health
health = 175
projectile_type = /obj/projectile/temp/watcher/magma_wing
gaze_attack = /datum/action/cooldown/mob_cooldown/watcher_gaze/fire
crusher_loot = /obj/item/crusher_trophy/blaster_tubes/magma_wing
@@ -98,8 +99,8 @@
icon_state = "watcher_icewing"
icon_living = "watcher_icewing"
icon_dead = "watcher_icewing_dead"
maxHealth = 170
health = 170
maxHealth = 130
health = 130
projectile_type = /obj/projectile/temp/watcher/ice_wing
gaze_attack = /datum/action/cooldown/mob_cooldown/watcher_gaze/ice
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/bone = 1)
@@ -16,6 +16,7 @@
/datum/ai_planning_subtree/targeted_mob_ability/overwatch
ability_key = BB_WATCHER_OVERWATCH
operational_datums = list(/datum/component/ai_target_timer)
/datum/ai_planning_subtree/targeted_mob_ability/overwatch/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
var/mob/living/living_pawn = controller.pawn
@@ -24,6 +25,9 @@
var/atom/target = controller.blackboard[target_key]
if (QDELETED(target) || HAS_TRAIT(target, TRAIT_OVERWATCH_IMMUNE))
return // We should probably let miners move sometimes
var/time_on_target = controller.blackboard[BB_BASIC_MOB_HAS_TARGET_TIME] || 0
if (time_on_target < 5 SECONDS)
return // We need to spend some time acquiring our target first
return ..()
/datum/ai_planning_subtree/use_mob_ability/gaze
@@ -84,7 +84,8 @@
/// Display an animated overlay over our head to indicate what's going on
/datum/action/cooldown/mob_cooldown/watcher_gaze/proc/show_indicator_overlay(overlay_state)
clear_current_overlay()
current_overlay = image(icon = 'icons/effects/eldritch.dmi', loc = owner, icon_state = overlay_state, pixel_x = -owner.pixel_x, pixel_y = 28)
current_overlay = image(icon = 'icons/effects/eldritch.dmi', loc = owner, icon_state = overlay_state, pixel_x = -owner.pixel_x, pixel_y = 28, layer = ABOVE_ALL_MOB_LAYER)
SET_PLANE_EXPLICIT(current_overlay, ABOVE_LIGHTING_PLANE, owner)
for(var/client/add_to in GLOB.clients)
add_to.images += current_overlay
@@ -96,7 +96,7 @@
. = ..()
if (!.)
return FALSE
ADD_TRAIT(owner, TRAIT_OVERWATCHED, TRAIT_STATUS_EFFECT(id))
owner.add_traits(list(TRAIT_OVERWATCHED, TRAIT_OVERWATCH_IMMUNE), TRAIT_STATUS_EFFECT(id))
owner.do_alert_animation()
owner.Immobilize(0.25 SECONDS) // Just long enough that they don't trigger it by mistake
owner.playsound_local(owner, 'sound/machines/chime.ogg', 50, TRUE)
@@ -109,7 +109,7 @@
/datum/status_effect/overwatch/on_remove()
UnregisterSignal(owner, forbidden_actions + list(COMSIG_QDELETING, COMSIG_LIVING_DEATH))
QDEL_NULL(link)
REMOVE_TRAIT(owner, TRAIT_OVERWATCHED, TRAIT_STATUS_EFFECT(id))
owner.remove_traits(list(TRAIT_OVERWATCHED, TRAIT_OVERWATCH_IMMUNE), TRAIT_STATUS_EFFECT(id))
if (!QDELETED(owner))
owner.apply_status_effect(/datum/status_effect/overwatch_immune)
return ..()
@@ -135,6 +135,7 @@
qdel(src)
return
overwatch_triggered = TRUE
watcher.do_alert_animation()
INVOKE_ASYNC(watcher, TYPE_PROC_REF(/atom/, fire_projectile), projectile_type, owner, projectile_sound)
/// Can't overwatch you if I don't exist