mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 22:50:26 +01:00
[MIRROR] [no gbp] fixes ai controller runtime (#26278)
* [no gbp] fixes ai controller runtime (#81134) ## About The Pull Request fixes the flaky error that would happen in cleanbot controllers. i discovered thru the profiler that a proc i was using to stop tracking unreachable targets and caching them to a blacklist in selectbehavior had a bit of a high real time cost, so if the mob got deleted midway through for any reason would cause a runtime error. ive moved this proc off selectbehavior and im instead letting the move loop cache this target into the blacklist if it reaches the max pathing attempts ## Why It's Good For The Game fixes a runtime that sometimes happens in ai controllers ## Changelog 🆑 fix: fixes a runtime that sometimes happens in ai controllers /🆑 * [no gbp] fixes ai controller runtime --------- Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
This commit is contained in:
co-authored by
Ben10Omintrix
parent
5922f34a2a
commit
7f252e6e94
@@ -35,6 +35,10 @@
|
||||
#define BB_NEAR_DEATH_SPEECH "near_death_speech"
|
||||
///in crit patient we must alert medbay about
|
||||
#define BB_PATIENT_IN_CRIT "patient_in_crit"
|
||||
///how much time interval before we clear list
|
||||
#define BB_UNREACHABLE_LIST_COOLDOWN "unreachable_list_cooldown"
|
||||
///can we clear the list now
|
||||
#define BB_CLEAR_LIST_READY "clear_list_ready"
|
||||
|
||||
// cleanbots
|
||||
///key that holds the foaming ability
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
|
||||
/// If true we will get rid of our target on completion
|
||||
var/clear_target = FALSE
|
||||
///should we use a different movement type?
|
||||
var/new_movement_type
|
||||
|
||||
/datum/ai_behavior/travel_towards/setup(datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
if(QDELETED(target))
|
||||
return FALSE
|
||||
set_movement_target(controller, target)
|
||||
set_movement_target(controller, target, new_movement_type)
|
||||
|
||||
/datum/ai_behavior/travel_towards/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
@@ -24,6 +26,8 @@
|
||||
. = ..()
|
||||
if (clear_target)
|
||||
controller.clear_blackboard_key(target_key)
|
||||
if(new_movement_type)
|
||||
controller.change_ai_movement_type(initial(controller.ai_movement))
|
||||
|
||||
/datum/ai_behavior/travel_towards/stop_on_arrival
|
||||
clear_target = TRUE
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
finish_action(controller, TRUE)
|
||||
return
|
||||
var/find_this_thing = search_tactic(controller, locate_path, search_range)
|
||||
if(find_this_thing)
|
||||
controller.set_blackboard_key(set_key, find_this_thing)
|
||||
finish_action(controller, TRUE)
|
||||
else
|
||||
if(QDELETED(controller.pawn) || isnull(find_this_thing))
|
||||
finish_action(controller, FALSE)
|
||||
return
|
||||
controller.set_blackboard_key(set_key, find_this_thing)
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
/datum/ai_behavior/find_and_set/proc/search_tactic(datum/ai_controller/controller, locate_path, search_range)
|
||||
return locate(locate_path) in oview(search_range, controller.pawn)
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
/datum/ai_movement/jps/bot
|
||||
max_pathing_attempts = 25
|
||||
maximum_length = AI_BOT_PATH_LENGTH
|
||||
maximum_length = 25
|
||||
diagonal_flags = DIAGONAL_REMOVE_ALL
|
||||
|
||||
/datum/ai_movement/jps/bot/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target, min_distance)
|
||||
@@ -48,3 +48,6 @@
|
||||
if(isnull(our_pawn))
|
||||
return
|
||||
our_pawn.RegisterSignal(loop, COMSIG_MOVELOOP_JPS_FINISHED_PATHING, TYPE_PROC_REF(/mob/living/basic/bot, generate_bot_path))
|
||||
|
||||
/datum/ai_movement/jps/bot/travel_to_beacon
|
||||
maximum_length = AI_BOT_PATH_LENGTH
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"salutes",
|
||||
"nods in appreciation towards",
|
||||
"fist bumps",
|
||||
)
|
||||
),
|
||||
BB_UNREACHABLE_LIST_COOLDOWN = 45 SECONDS,
|
||||
)
|
||||
|
||||
ai_movement = /datum/ai_movement/jps/bot
|
||||
@@ -53,10 +54,12 @@
|
||||
clear_blackboard_key(key)
|
||||
|
||||
///set the target if we can reach them
|
||||
/datum/ai_controller/basic_controller/bot/proc/set_if_can_reach(key, target, distance = 10)
|
||||
/datum/ai_controller/basic_controller/bot/proc/set_if_can_reach(key, target, distance = 10, bypass_add_to_blacklist = FALSE)
|
||||
if(can_reach_target(target, distance))
|
||||
set_blackboard_key(key, target)
|
||||
return TRUE
|
||||
if(!bypass_add_to_blacklist)
|
||||
set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, REF(target), TRUE)
|
||||
return FALSE
|
||||
|
||||
/datum/ai_controller/basic_controller/bot/proc/can_reach_target(target, distance = 10)
|
||||
@@ -69,34 +72,16 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
///check if the target is too far away, and delete them if so and add them to the unreachables list
|
||||
/datum/ai_controller/basic_controller/bot/proc/reachable_key(key, distance = 10, bypass_add_to_blacklist = FALSE)
|
||||
var/datum/target = blackboard[key]
|
||||
if(QDELETED(target))
|
||||
return FALSE
|
||||
var/datum/last_attempt = blackboard[BB_LAST_ATTEMPTED_PATHING]
|
||||
if(last_attempt != target)
|
||||
current_pathing_attempts = 0
|
||||
set_blackboard_key(BB_LAST_ATTEMPTED_PATHING, target)
|
||||
else
|
||||
current_pathing_attempts++
|
||||
if(current_pathing_attempts >= max_pathing_attempts || !can_reach_target(target, distance))
|
||||
clear_blackboard_key(key)
|
||||
clear_blackboard_key(BB_LAST_ATTEMPTED_PATHING)
|
||||
if(!bypass_add_to_blacklist)
|
||||
set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, REF(target), TRUE)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/// subtree to manage our list of unreachables, we reset it every 15 seconds
|
||||
/datum/ai_planning_subtree/manage_unreachable_list
|
||||
|
||||
/datum/ai_planning_subtree/manage_unreachable_list/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
|
||||
if(isnull(controller.blackboard[BB_UNREACHABLE_LIST_COOLDOWN]) || controller.blackboard[BB_CLEAR_LIST_READY] > world.time)
|
||||
return
|
||||
controller.queue_behavior(/datum/ai_behavior/manage_unreachable_list, BB_TEMPORARY_IGNORE_LIST)
|
||||
|
||||
/datum/ai_behavior/manage_unreachable_list
|
||||
behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
|
||||
action_cooldown = 45 SECONDS
|
||||
|
||||
/datum/ai_behavior/manage_unreachable_list/perform(seconds_per_tick, datum/ai_controller/controller, list_key)
|
||||
. = ..()
|
||||
@@ -104,8 +89,13 @@
|
||||
controller.clear_blackboard_key(list_key)
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
/datum/ai_behavior/manage_unreachable_list/finish_action(datum/ai_controller/controller, succeeded)
|
||||
. = ..()
|
||||
controller.set_blackboard_key(BB_CLEAR_LIST_READY, controller.blackboard[BB_UNREACHABLE_LIST_COOLDOWN] + world.time)
|
||||
|
||||
/datum/ai_planning_subtree/find_patrol_beacon
|
||||
///travel towards beacon behavior
|
||||
var/travel_behavior = /datum/ai_behavior/travel_towards/beacon
|
||||
|
||||
/datum/ai_planning_subtree/find_patrol_beacon/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
|
||||
var/mob/living/basic/bot/bot_pawn = controller.pawn
|
||||
@@ -114,7 +104,7 @@
|
||||
|
||||
if(controller.blackboard_key_exists(BB_BEACON_TARGET))
|
||||
bot_pawn.update_bot_mode(new_mode = BOT_PATROL)
|
||||
controller.queue_behavior(/datum/ai_behavior/travel_towards/beacon, BB_BEACON_TARGET)
|
||||
controller.queue_behavior(travel_behavior, BB_BEACON_TARGET)
|
||||
return
|
||||
|
||||
if(controller.blackboard_key_exists(BB_PREVIOUS_BEACON_TARGET))
|
||||
@@ -132,9 +122,9 @@
|
||||
var/atom/final_target
|
||||
var/atom/previous_target = controller.blackboard[BB_PREVIOUS_BEACON_TARGET]
|
||||
for(var/obj/machinery/navbeacon/beacon as anything in GLOB.navbeacons["[bot_pawn.z]"])
|
||||
if(beacon == previous_target)
|
||||
continue
|
||||
var/dist = get_dist(bot_pawn, beacon)
|
||||
if(beacon == previous_target || dist <= 1)
|
||||
continue
|
||||
if(dist > closest_distance)
|
||||
continue
|
||||
closest_distance = dist
|
||||
@@ -170,6 +160,7 @@
|
||||
|
||||
/datum/ai_behavior/travel_towards/beacon
|
||||
clear_target = TRUE
|
||||
new_movement_type = /datum/ai_movement/jps/bot/travel_to_beacon
|
||||
|
||||
/datum/ai_behavior/travel_towards/beacon/finish_action(datum/ai_controller/controller, succeeded, target_key)
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
@@ -188,6 +179,7 @@
|
||||
|
||||
/datum/ai_behavior/travel_towards/bot_summon
|
||||
clear_target = TRUE
|
||||
new_movement_type = /datum/ai_movement/jps/bot/travel_to_beacon
|
||||
|
||||
/datum/ai_behavior/travel_towards/bot_summon/finish_action(datum/ai_controller/controller, succeeded, target_key)
|
||||
var/mob/living/basic/bot/bot_pawn = controller.pawn
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items,
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
BB_UNREACHABLE_LIST_COOLDOWN = 3 MINUTES,
|
||||
BB_SALUTE_MESSAGES = list(
|
||||
"salutes",
|
||||
"nods in appreciation towards",
|
||||
@@ -51,7 +52,7 @@
|
||||
/datum/ai_planning_subtree/cleaning_subtree
|
||||
|
||||
/datum/ai_planning_subtree/cleaning_subtree/SelectBehaviors(datum/ai_controller/basic_controller/bot/cleanbot/controller, seconds_per_tick)
|
||||
if(controller.reachable_key(BB_CLEAN_TARGET, BOT_CLEAN_PATH_LIMIT))
|
||||
if(controller.blackboard_key_exists(BB_CLEAN_TARGET))
|
||||
controller.queue_behavior(/datum/ai_behavior/execute_clean, BB_CLEAN_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
@@ -68,7 +69,7 @@
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/in_list/clean_targets, BB_CLEAN_TARGET, final_hunt_list)
|
||||
|
||||
/datum/ai_behavior/find_and_set/in_list/clean_targets
|
||||
action_cooldown = 1 SECONDS
|
||||
action_cooldown = 3 SECONDS
|
||||
|
||||
/datum/ai_behavior/find_and_set/in_list/clean_targets/search_tactic(datum/ai_controller/controller, locate_paths, search_range)
|
||||
var/list/found = typecache_filter_list(oview(search_range, controller.pawn), locate_paths)
|
||||
@@ -76,6 +77,10 @@
|
||||
for(var/atom/found_item in found)
|
||||
if(LAZYACCESS(ignore_list, REF(found_item)))
|
||||
continue
|
||||
var/list/path = get_path_to(controller.pawn, found_item, max_distance = BOT_CLEAN_PATH_LIMIT, access = controller.get_access())
|
||||
if(!length(path))
|
||||
controller.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, REF(found_item), TRUE)
|
||||
continue
|
||||
return found_item
|
||||
|
||||
/datum/ai_planning_subtree/acid_spray
|
||||
@@ -84,7 +89,7 @@
|
||||
var/mob/living/basic/bot/cleanbot/bot_pawn = controller.pawn
|
||||
if(!(bot_pawn.bot_access_flags & BOT_COVER_EMAGGED))
|
||||
return
|
||||
if(controller.reachable_key(BB_ACID_SPRAY_TARGET, BOT_CLEAN_PATH_LIMIT))
|
||||
if(controller.blackboard_key_exists(BB_ACID_SPRAY_TARGET))
|
||||
controller.queue_behavior(/datum/ai_behavior/execute_clean, BB_ACID_SPRAY_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
@@ -130,6 +135,10 @@
|
||||
. = ..()
|
||||
controller.set_blackboard_key(BB_POST_CLEAN_COOLDOWN, POST_CLEAN_COOLDOWN + world.time)
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
if(!succeeded && !isnull(target))
|
||||
controller.clear_blackboard_key(target_key)
|
||||
controller.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, REF(target), TRUE)
|
||||
return
|
||||
if(QDELETED(target) || is_type_in_typecache(target, controller.blackboard[BB_HUNTABLE_TRASH]))
|
||||
return
|
||||
if(!iscarbon(target))
|
||||
@@ -208,7 +217,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/pet_command/point_targeting/clean/execute_action(datum/ai_controller/basic_controller/bot/controller)
|
||||
if(controller.reachable_key(BB_CURRENT_PET_TARGET))
|
||||
if(controller.blackboard_key_exists(BB_CURRENT_PET_TARGET))
|
||||
controller.queue_behavior(/datum/ai_behavior/execute_clean, BB_CURRENT_PET_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/datum/ai_planning_subtree/find_and_hunt_target/patients_in_crit,
|
||||
/datum/ai_planning_subtree/treat_wounded_target,
|
||||
/datum/ai_planning_subtree/salute_authority,
|
||||
/datum/ai_planning_subtree/find_patrol_beacon,
|
||||
/datum/ai_planning_subtree/find_patrol_beacon/medbot,
|
||||
)
|
||||
ai_movement = /datum/ai_movement/jps/bot/medbot
|
||||
reset_keys = list(
|
||||
@@ -19,6 +19,8 @@
|
||||
ai_traits = PAUSE_DURING_DO_AFTER
|
||||
|
||||
/datum/ai_movement/jps/bot/medbot
|
||||
maximum_length = BOT_PATIENT_PATH_LIMIT
|
||||
max_pathing_attempts = 20
|
||||
|
||||
// only AI isnt allowed to move when this flag is set, sentient players can
|
||||
/datum/ai_movement/jps/bot/medbot/allowed_to_move(datum/move_loop/source)
|
||||
@@ -28,6 +30,9 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/ai_movement/jps/bot/medbot/travel_to_beacon
|
||||
maximum_length = AI_BOT_PATH_LENGTH
|
||||
|
||||
|
||||
/datum/ai_planning_subtree/treat_wounded_target
|
||||
|
||||
@@ -37,9 +42,8 @@
|
||||
controller.clear_blackboard_key(BB_PATIENT_TARGET)
|
||||
return
|
||||
var/is_stationary = bot_pawn.medical_mode_flags & MEDBOT_STATIONARY_MODE
|
||||
var/reach_distance = (is_stationary) ? 1 : BOT_PATIENT_PATH_LIMIT
|
||||
if(controller.reachable_key(BB_PATIENT_TARGET, distance = reach_distance, bypass_add_to_blacklist = is_stationary))
|
||||
controller.queue_behavior(/datum/ai_behavior/tend_to_patient, BB_PATIENT_TARGET, bot_pawn.heal_threshold, bot_pawn.damage_type_healer, bot_pawn.bot_access_flags)
|
||||
if(controller.blackboard_key_exists(BB_PATIENT_TARGET))
|
||||
controller.queue_behavior(/datum/ai_behavior/tend_to_patient, BB_PATIENT_TARGET, bot_pawn.heal_threshold, bot_pawn.damage_type_healer, bot_pawn.bot_access_flags, is_stationary)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
controller.queue_behavior(/datum/ai_behavior/find_suitable_patient, BB_PATIENT_TARGET, bot_pawn.heal_threshold, bot_pawn.damage_type_healer, bot_pawn.medical_mode_flags, bot_pawn.bot_access_flags)
|
||||
@@ -56,15 +60,15 @@
|
||||
if(LAZYACCESS(ignore_keys, REF(treatable_target)) || treatable_target.stat == DEAD)
|
||||
continue
|
||||
if((access_flags & BOT_COVER_EMAGGED) && treatable_target.stat == CONSCIOUS)
|
||||
controller.set_blackboard_key(BB_PATIENT_TARGET, treatable_target)
|
||||
controller.set_if_can_reach(BB_PATIENT_TARGET, treatable_target, distance =BOT_PATIENT_PATH_LIMIT, bypass_add_to_blacklist = (search_range == 1))
|
||||
break
|
||||
if((heal_type == HEAL_ALL_DAMAGE))
|
||||
if(treatable_target.get_total_damage() > threshold)
|
||||
controller.set_blackboard_key(BB_PATIENT_TARGET, treatable_target)
|
||||
controller.set_if_can_reach(BB_PATIENT_TARGET, treatable_target, distance = BOT_PATIENT_PATH_LIMIT, bypass_add_to_blacklist = (search_range == 1))
|
||||
break
|
||||
continue
|
||||
if(treatable_target.get_current_damage_of_type(damagetype = heal_type) > threshold)
|
||||
controller.set_blackboard_key(BB_PATIENT_TARGET, treatable_target)
|
||||
controller.set_if_can_reach(BB_PATIENT_TARGET, treatable_target, distance = BOT_PATIENT_PATH_LIMIT, bypass_add_to_blacklist = (search_range == 1))
|
||||
break
|
||||
|
||||
finish_action(controller, controller.blackboard_key_exists(BB_PATIENT_TARGET))
|
||||
@@ -86,14 +90,14 @@
|
||||
return FALSE
|
||||
set_movement_target(controller, target)
|
||||
|
||||
/datum/ai_behavior/tend_to_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, threshold, damage_type_healer, access_flags)
|
||||
/datum/ai_behavior/tend_to_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, threshold, damage_type_healer, access_flags, is_stationary)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/patient = controller.blackboard[target_key]
|
||||
if(QDELETED(patient) || patient.stat == DEAD)
|
||||
finish_action(controller, FALSE, target_key)
|
||||
finish_action(controller, FALSE, target_key, is_stationary)
|
||||
return
|
||||
if(check_if_healed(patient, threshold, damage_type_healer, access_flags))
|
||||
finish_action(controller, TRUE, target_key, healed_target = TRUE)
|
||||
finish_action(controller, TRUE, target_key, is_stationary, healed_target = TRUE)
|
||||
return
|
||||
|
||||
var/mob/living/basic/bot/bot_pawn = controller.pawn
|
||||
@@ -101,16 +105,23 @@
|
||||
var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY]
|
||||
announcement?.announce(pick(controller.blackboard[BB_NEAR_DEATH_SPEECH]))
|
||||
bot_pawn.melee_attack(patient)
|
||||
finish_action(controller, TRUE, target_key)
|
||||
finish_action(controller, TRUE, target_key, is_stationary)
|
||||
|
||||
// only clear the target if they get healed
|
||||
/datum/ai_behavior/tend_to_patient/finish_action(datum/ai_controller/controller, succeeded, target_key, healed_target = FALSE)
|
||||
/datum/ai_behavior/tend_to_patient/finish_action(datum/ai_controller/controller, succeeded, target_key, is_stationary, healed_target = FALSE)
|
||||
. = ..()
|
||||
if(!succeeded)
|
||||
return
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
if(!succeeded)
|
||||
|
||||
if(!isnull(target) && !is_stationary)
|
||||
controller.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, REF(target), TRUE)
|
||||
|
||||
controller.clear_blackboard_key(target_key)
|
||||
return
|
||||
|
||||
if(QDELETED(target) || !healed_target)
|
||||
return
|
||||
|
||||
var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY]
|
||||
announcement?.announce(pick(controller.blackboard[BB_AFTERHEAL_SPEECH]))
|
||||
controller.clear_blackboard_key(target_key)
|
||||
@@ -208,4 +219,11 @@
|
||||
. = ..()
|
||||
controller.clear_blackboard_key(target_key)
|
||||
|
||||
/datum/ai_planning_subtree/find_patrol_beacon/medbot
|
||||
///travel towards beacon behavior
|
||||
travel_behavior = /datum/ai_behavior/travel_towards/beacon/medbot
|
||||
|
||||
/datum/ai_behavior/travel_towards/beacon/medbot
|
||||
new_movement_type = /datum/ai_movement/jps/bot/medbot/travel_to_beacon
|
||||
|
||||
#undef BOT_PATIENT_PATH_LIMIT
|
||||
|
||||
Reference in New Issue
Block a user