Refactors how basic ais do their success/failures (#82643)

This commit is contained in:
LemonInTheDark
2024-04-22 05:23:04 -07:00
committed by GitHub
parent 89b0dc1d3b
commit 1e78db8471
76 changed files with 453 additions and 664 deletions
@@ -27,7 +27,6 @@
/datum/ai_behavior/basic_melee_attack/opportunistic/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key)
var/atom/movable/atom_pawn = controller.pawn
if(!atom_pawn.CanReach(controller.blackboard[target_key]))
finish_action(controller, TRUE, target_key) // Don't clear target
return FALSE
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
. = ..()
finish_action(controller, TRUE, target_key) // Try doing something else
return . | AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
@@ -27,13 +27,11 @@
var/can_attack_dense_objects = FALSE
/datum/ai_behavior/attack_obstructions/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
var/mob/living/basic/basic_mob = controller.pawn
var/atom/target = controller.blackboard[target_key]
if (QDELETED(target))
finish_action(controller, succeeded = FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/turf/next_step = get_step_towards(basic_mob, target)
var/dir_to_next_step = get_dir(basic_mob, next_step)
@@ -48,8 +46,8 @@
for (var/direction in dirs_to_move)
if (attack_in_direction(controller, basic_mob, direction))
return
finish_action(controller, succeeded = TRUE)
return AI_BEHAVIOR_DELAY
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/datum/ai_behavior/attack_obstructions/proc/attack_in_direction(datum/ai_controller/controller, mob/living/basic/basic_mob, direction)
var/turf/next_step = get_step(basic_mob, direction)
@@ -36,8 +36,6 @@
var/reinforcements_range = 15
/datum/ai_behavior/call_reinforcements/perform(seconds_per_tick, datum/ai_controller/controller)
. = ..()
var/mob/pawn_mob = controller.pawn
for(var/mob/other_mob in oview(reinforcements_range, pawn_mob))
if(pawn_mob.faction_check_atom(other_mob) && !isnull(other_mob.ai_controller))
@@ -46,5 +44,6 @@
other_mob.ai_controller.set_blackboard_key(BB_BASIC_MOB_REINFORCEMENT_TARGET, pawn_mob)
controller.set_blackboard_key(BB_BASIC_MOB_REINFORCEMENTS_COOLDOWN, world.time + REINFORCEMENTS_COOLDOWN)
return AI_BEHAVIOR_DELAY
#undef REINFORCEMENTS_COOLDOWN
@@ -14,29 +14,25 @@
action_cooldown = 1 SECONDS
/datum/ai_behavior/capricious_retaliate/perform(seconds_per_tick, datum/ai_controller/controller, targeting_strategy_key, ignore_faction)
. = ..()
var/atom/pawn = controller.pawn
if (controller.blackboard_key_exists(BB_BASIC_MOB_RETALIATE_LIST))
var/deaggro_chance = controller.blackboard[BB_RANDOM_DEAGGRO_CHANCE] || 10
if (!SPT_PROB(deaggro_chance, seconds_per_tick))
finish_action(controller, TRUE, ignore_faction) // "true" here means "don't clear our ignoring factions status"
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
pawn.visible_message(span_notice("[pawn] calms down.")) // We can blackboard key this if anyone else actually wants to customise it
controller.clear_blackboard_key(BB_BASIC_MOB_RETALIATE_LIST)
finish_action(controller, FALSE, ignore_faction)
controller.CancelActions() // Otherwise they will try and get one last kick in
return
return AI_BEHAVIOR_DELAY
var/aggro_chance = controller.blackboard[BB_RANDOM_AGGRO_CHANCE] || 0.5
if (!SPT_PROB(aggro_chance, seconds_per_tick))
finish_action(controller, FALSE, ignore_faction)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/aggro_range = controller.blackboard[BB_AGGRO_RANGE] || 9
var/list/potential_targets = hearers(aggro_range, get_turf(pawn)) - pawn
if (!length(potential_targets))
failed_targeting(controller, pawn, ignore_faction)
return
failed_targeting(pawn)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/datum/targeting_strategy/target_helper = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key])
@@ -49,16 +45,15 @@
final_target = test_target
if (isnull(final_target))
failed_targeting(controller, pawn, ignore_faction)
return
failed_targeting(pawn)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, final_target)
pawn.visible_message(span_warning("[pawn] glares grumpily at [final_target]!"))
finish_action(controller, TRUE, ignore_faction)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/// Called if we try but fail to target something
/datum/ai_behavior/capricious_retaliate/proc/failed_targeting(datum/ai_controller/controller, atom/pawn, ignore_faction)
finish_action(controller, FALSE, ignore_faction)
/datum/ai_behavior/capricious_retaliate/proc/failed_targeting(atom/pawn)
pawn.visible_message(span_notice("[pawn] grumbles.")) // We're pissed off but with no outlet to vent our frustration upon
/datum/ai_behavior/capricious_retaliate/finish_action(datum/ai_controller/controller, succeeded, ignore_faction)
@@ -60,8 +60,7 @@
return FALSE
/datum/ai_behavior/step_away/perform(seconds_per_tick, datum/ai_controller/controller)
. = ..()
finish_action(controller, succeeded = TRUE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/datum/ai_behavior/step_away/finish_action(datum/ai_controller/controller, succeeded)
. = ..()
@@ -83,8 +82,8 @@
/datum/ai_behavior/pursue_to_range/perform(seconds_per_tick, datum/ai_controller/controller, target_key, range)
var/atom/current_target = controller.blackboard[target_key]
if (!QDELETED(current_target) && get_dist(controller.pawn, current_target) > range)
return
finish_action(controller, succeeded = TRUE)
return AI_BEHAVIOR_INSTANT
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
///instead of taking a single step, we cover the entire distance
/datum/ai_behavior/cover_minimum_distance
@@ -112,5 +111,4 @@
set_movement_target(controller, target = chosen_turf)
/datum/ai_behavior/cover_minimum_distance/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
finish_action(controller, succeeded = TRUE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
@@ -21,19 +21,16 @@
set_movement_target(controller, target)
/datum/ai_behavior/mine_wall/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
var/mob/living/basic/living_pawn = controller.pawn
var/turf/closed/mineral/target = controller.blackboard[target_key]
var/is_gibtonite_turf = istype(target, /turf/closed/mineral/gibtonite)
if(QDELETED(target))
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
living_pawn.melee_attack(target)
if(is_gibtonite_turf)
living_pawn.manual_emote("sighs...") //accept whats about to happen to us
finish_action(controller, TRUE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/datum/ai_behavior/mine_wall/finish_action(datum/ai_controller/controller, success, target_key)
. = ..()
@@ -42,17 +39,15 @@
/datum/ai_behavior/find_mineral_wall
/datum/ai_behavior/find_mineral_wall/perform(seconds_per_tick, datum/ai_controller/controller, found_wall_key)
. = ..()
var/mob/living_pawn = controller.pawn
for(var/turf/closed/mineral/potential_wall in oview(9, living_pawn))
if(!check_if_mineable(controller, potential_wall)) //check if its surrounded by walls
continue
controller.set_blackboard_key(found_wall_key, potential_wall) //closest wall first!
finish_action(controller, TRUE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
finish_action(controller, FALSE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
/datum/ai_behavior/find_mineral_wall/proc/check_if_mineable(datum/ai_controller/controller, turf/target_wall)
var/mob/living/source = controller.pawn
@@ -51,19 +51,17 @@
/datum/ai_behavior/move_to_cardinal/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
var/atom/target = controller.blackboard[target_key]
if (QDELETED(target))
finish_action(controller = controller, succeeded = FALSE, target_key = target_key)
return
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED
if (!(get_dir(controller.pawn, target) in GLOB.cardinals))
target_nearest_cardinal(controller, target)
return
return AI_BEHAVIOR_INSTANT
var/distance_to_target = get_dist(controller.pawn, target)
if (distance_to_target < minimum_distance)
target_nearest_cardinal(controller, target)
return
return AI_BEHAVIOR_INSTANT
if (distance_to_target > maximum_distance)
return
finish_action(controller = controller, succeeded = TRUE, target_key = target_key)
return
return AI_BEHAVIOR_INSTANT
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
/datum/ai_behavior/move_to_cardinal/finish_action(datum/ai_controller/controller, succeeded, target_key)
if (!succeeded)
@@ -26,16 +26,13 @@
return !QDELETED(target)
/datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range)
. = ..()
var/atom/target = controller.blackboard[target_key]
if (QDELETED(target))
finish_action(controller, succeeded = FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key])
if(!targeting_strategy.can_attack(controller.pawn, target))
finish_action(controller, succeeded = FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/hiding_target = targeting_strategy.find_hidden_mobs(controller.pawn, target)
controller.set_blackboard_key(hiding_location_key, hiding_target)
@@ -44,9 +41,8 @@
var/distance = get_dist(controller.pawn, target)
if (distance > max_range || distance < min_range)
finish_action(controller, succeeded = FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/mob/living/basic/gunman = controller.pawn
gunman.RangedAttack(target)
finish_action(controller, succeeded = TRUE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
@@ -15,8 +15,7 @@
/datum/ai_behavior/run_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote_key)
var/mob/living/living_pawn = controller.pawn
if (!isliving(living_pawn))
finish_action(controller, FALSE)
return
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED
var/list/emote_list = controller.blackboard[emote_key]
var/emote
@@ -26,8 +25,7 @@
emote = emote_list
if(isnull(emote))
finish_action(controller, FALSE)
return
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED
living_pawn.emote(emote)
finish_action(controller, TRUE)
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
@@ -16,7 +16,9 @@
/datum/ai_behavior/sleep_after_targetless_time/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
var/atom/target = controller.blackboard[target_key]
finish_action(controller, succeeded = QDELETED(target), seconds_per_tick = seconds_per_tick)
if(QDELETED(target))
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED
/datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, seconds_per_tick)
. = ..()
@@ -39,6 +39,7 @@
var/mob/living/living_mob = controller.pawn
var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key])
if(!targeting_strategy)
. = AI_BEHAVIOR_DELAY
CRASH("No target datum was supplied in the blackboard for [controller.pawn]")
var/list/shitlist = controller.blackboard[shitlist_key]
@@ -48,8 +49,7 @@
controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, TRUE)
if (!QDELETED(existing_target) && (locate(existing_target) in shitlist) && targeting_strategy.can_attack(living_mob, existing_target, vision_range))
finish_action(controller, succeeded = TRUE, check_faction = check_faction)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
var/list/enemies_list = list()
for(var/mob/living/potential_target as anything in shitlist)
@@ -59,8 +59,7 @@
if(!length(enemies_list))
controller.clear_blackboard_key(target_key)
finish_action(controller, succeeded = FALSE, check_faction = check_faction)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/atom/new_target = pick_final_target(controller, enemies_list)
controller.set_blackboard_key(target_key, new_target)
@@ -70,7 +69,7 @@
if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially.
controller.set_blackboard_key(hiding_location_key, potential_hiding_location)
finish_action(controller, succeeded = TRUE, check_faction = check_faction)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/// Returns the desired final target from the filtered list of enemies
/datum/ai_behavior/target_from_retaliate_list/proc/pick_final_target(datum/ai_controller/controller, list/enemies_list)
@@ -34,7 +34,7 @@
/datum/ai_behavior/find_furthest_turf_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, set_key, range)
var/mob/living/living_target = controller.blackboard[target_key]
if(QDELETED(living_target))
return
return AI_BEHAVIOR_INSTANT
var/distance = 0
var/turf/chosen_turf
@@ -49,8 +49,7 @@
break //we have already found the max distance
if(isnull(chosen_turf))
finish_action(controller, FALSE)
return
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED
controller.set_blackboard_key(set_key, chosen_turf)
finish_action(controller, TRUE)
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
@@ -27,7 +27,7 @@
/datum/ai_behavior/use_mob_ability/perform(seconds_per_tick, datum/ai_controller/controller, ability_key)
var/datum/action/using_action = controller.blackboard[ability_key]
if (QDELETED(using_action))
finish_action(controller, FALSE, ability_key)
return
var/result = using_action.Trigger()
finish_action(controller, result, ability_key)
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED
if(using_action.Trigger())
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED