Adds a priority targeting framework, and priority targeting to mining mobs (#95720)

## About The Pull Request

Introduces a new targeting priority strategy system for basicmob AIs,
which allows controllers to decide which mob to prioritize over others.

Mining mobs will now focus on the NODE drone unless hit, and will pursue
the attacker for 25 seconds before dropping the aggro. They also get
increased aggro if you've attacked other mobs in their view recently,
and after a few hits will have enough aggro to swap to you from the NODE
drone. Ashwalkers get a reduction in aggro because they live there.
Legion broods and brimdemons will immediately target anyone who attacks
their allies rather than waiting for multiple hits. Broods also now
inherit their parent's targets and retaliation/reinforcements lists.


https://github.com/user-attachments/assets/6baaba8a-8b3c-4b2f-ae8b-842f0b1f2b6d

#### This is a bounty for ArcaneMusic

## Why It's Good For The Game

Makes vent defense mob behavior more predictable and easier for players
to manipulate, allowing them to draw aggro from the NODE drone should
make vents more engaging and less of an AI rng fest

## Changelog
🆑
add: Mining mobs now use priority when choosing their target,
prioritizing NODE drones over miners who haven't attacked them or their
allies
/🆑
This commit is contained in:
SmArtKar
2026-05-08 21:40:01 +02:00
committed by GitHub
parent 7579ccc8c2
commit 119c1e9ccc
24 changed files with 216 additions and 38 deletions
+1 -1
View File
@@ -57,7 +57,7 @@
if (!istype(attacker))
return
for (var/mob/living/basic/clown/harbringer in oview(src, 7))
harbringer.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker)
harbringer.ai_controller.set_blackboard_key_assoc_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker, world.time)
/mob/living/basic/clown/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE)
if(!istype(target, /obj/item/food/grown/banana/bunch))
@@ -1,10 +1,12 @@
/datum/ai_controller/basic_controller/bileworm
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/bileworm,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining,
)
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity,
/datum/ai_planning_subtree/call_reinforcements/mining,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/bileworm_attack,
/datum/ai_planning_subtree/bileworm_execute,
@@ -4,6 +4,7 @@
/datum/ai_controller/basic_controller/brimdemon
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining/low_node_priority,
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
)
@@ -11,6 +12,7 @@
idle_behavior = /datum/idle_behavior/idle_random_walk/no_target
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity,
/datum/ai_planning_subtree/call_reinforcements/mining,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic,
/datum/ai_planning_subtree/move_to_cardinal/brimdemon,
@@ -4,6 +4,7 @@
/datum/ai_controller/basic_controller/goliath
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining,
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
)
@@ -11,6 +12,7 @@
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity,
/datum/ai_planning_subtree/call_reinforcements/mining,
/datum/ai_planning_subtree/target_retaliate/check_faction,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/find_food,
@@ -2,6 +2,7 @@
/datum/ai_controller/basic_controller/legion
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/legion,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining,
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
BB_AGGRO_RANGE = 5, // Unobservant
BB_BASIC_MOB_FLEE_DISTANCE = 6,
@@ -11,6 +12,7 @@
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity,
/datum/ai_planning_subtree/call_reinforcements/mining,
/datum/ai_planning_subtree/random_speech/legion,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/targeted_mob_ability,
@@ -21,6 +23,7 @@
/datum/ai_controller/basic_controller/legion_brood
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/legion,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining/low_node_priority,
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
)
@@ -103,8 +103,17 @@
else
add_ally(creator)
created_by = WEAKREF(creator)
ai_controller?.set_blackboard_key(BB_LEGION_BROOD_CREATOR, creator)
RegisterSignal(creator, COMSIG_QDELETING, PROC_REF(creator_destroyed))
if (!ai_controller)
return
ai_controller.set_blackboard_key(BB_LEGION_BROOD_CREATOR, creator)
if (!creator.ai_controller)
return
// Inherit our creator's target and reinforcement requests
ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, creator.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET])
ai_controller.set_blackboard_key(BB_MINING_MOB_REINFORCEMENTS_REQUESTS, creator.ai_controller.blackboard[BB_MINING_MOB_REINFORCEMENTS_REQUESTS])
/// Reference handling
/mob/living/basic/mining/legion_brood/proc/creator_destroyed()
@@ -8,6 +8,7 @@
/datum/ai_controller/basic_controller/lobstrosity
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining,
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
BB_LOBSTROSITY_EXPLOIT_TRAITS = list(TRAIT_INCAPACITATED, TRAIT_FLOORED, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT),
@@ -24,6 +25,7 @@
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity,
/datum/ai_planning_subtree/call_reinforcements/mining,
/datum/ai_planning_subtree/random_speech/insect,
/datum/ai_planning_subtree/hoard_fingers,
/datum/ai_planning_subtree/pet_planning,
@@ -187,7 +187,7 @@
if(istype(intruder, /mob/living/basic/mining/mook))
return
for(var/mob/living/basic/mining/mook/villager in oview(src, 9))
villager.ai_controller?.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, intruder)
villager.ai_controller?.set_blackboard_key_assoc(BB_BASIC_MOB_RETALIATE_LIST, intruder, world.time)
/mob/living/basic/mining/mook/worker
@@ -1,12 +1,14 @@
/datum/ai_controller/basic_controller/watcher
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining,
)
ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity,
/datum/ai_planning_subtree/call_reinforcements/mining,
/datum/ai_planning_subtree/target_retaliate/check_faction,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/maintain_distance,
@@ -320,4 +320,4 @@
/// If someone slaps one of the school, scatter
/mob/living/basic/carp/passive/proc/on_attacked(mob/living/attacker)
for(var/mob/living/basic/carp/passive/schoolmate in oview(src, 9))
schoolmate.ai_controller?.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker)
schoolmate.ai_controller?.set_blackboard_key_assoc_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker, world.time)
@@ -121,7 +121,7 @@
if (!istype(attacker))
return
for (var/mob/living/basic/garden_gnome/potential_gnome in oview(src, 7))
potential_gnome.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker)
potential_gnome.ai_controller.set_blackboard_key_assoc_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker, world.time)
/datum/ai_controller/basic_controller/garden_gnome
blackboard = list(
@@ -98,4 +98,4 @@
if (!istype(attacker))
return
for (var/mob/living/basic/trooper/nanotrasen/potential_trooper in oview(src, 7))
potential_trooper.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker)
potential_trooper.ai_controller.set_blackboard_key_assoc_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker, world.time)