Skip to content

Refactors some cleaning slimes behaviors to be subtypes of cleanbot behaviors #5657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4 changes: 4 additions & 0 deletions code/__DEFINES/ai/bot_keys.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
. = ..()
Expand All @@ -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
Expand Down
8 changes: 4 additions & 4 deletions code/datums/ai/generic/find_and_set.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion code/datums/ai/movement/ai_movement_jps.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
43 changes: 19 additions & 24 deletions code/modules/mob/living/basic/bots/bot_ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"salutes",
"nods in appreciation towards",
"fist bumps",
)
),
BB_UNREACHABLE_LIST_COOLDOWN = 45 SECONDS,
)

ai_movement = /datum/ai_movement/jps/bot
Expand Down Expand Up @@ -54,10 +55,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)
Expand All @@ -70,42 +73,30 @@
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)
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)
set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, 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)
. = ..()
if(!isnull(controller.blackboard[list_key]))
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
Expand All @@ -114,7 +105,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))
Expand All @@ -132,9 +123,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
Expand Down Expand Up @@ -170,6 +161,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]
Expand All @@ -188,9 +180,12 @@

/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
if(QDELETED(bot_pawn)) // pawn can be null at this point
return ..()
bot_pawn.calling_ai_ref = null
bot_pawn.update_bot_mode(new_mode = BOT_IDLE)
return ..()
Expand Down
33 changes: 21 additions & 12 deletions code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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

Expand All @@ -68,13 +69,17 @@
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 = 2 SECONDS //Monkestation edit
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)
var/list/ignore_list = controller.blackboard[BB_TEMPORARY_IGNORE_LIST]
for(var/atom/found_item in found)
if(LAZYACCESS(ignore_list, found_item))
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

Expand All @@ -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

Expand All @@ -97,7 +102,7 @@
/datum/ai_behavior/find_and_set/spray_target/search_tactic(datum/ai_controller/controller, locate_path, search_range)
var/list/ignore_list = controller.blackboard[BB_TEMPORARY_IGNORE_LIST]
for(var/mob/living/carbon/human/human_target in oview(search_range, controller.pawn))
if(LAZYACCESS(ignore_list, human_target))
if(LAZYACCESS(ignore_list, REF(human_target)))
continue
if(human_target.stat != CONSCIOUS || isnull(human_target.mind))
continue
Expand Down Expand Up @@ -128,16 +133,20 @@
. = ..()
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))
controller.clear_blackboard_key(target_key)
return
var/list/speech_list = controller.blackboard[BB_CLEANBOT_EMAGGED_PHRASES]
if(!length(speech_list))
return
var/mob/living/living_pawn = controller.pawn
living_pawn.say(pick(controller.blackboard[BB_CLEANBOT_EMAGGED_PHRASES]), forced = "ai controller")
if(length(speech_list))
var/mob/living/living_pawn = controller.pawn
if(!QDELETED(living_pawn)) // pawn can be null at this point
living_pawn.say(pick(speech_list), forced = "ai controller")
controller.clear_blackboard_key(target_key)

/datum/ai_planning_subtree/use_mob_ability/foam_area
Expand All @@ -155,7 +164,7 @@
/datum/ai_planning_subtree/befriend_janitors/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
var/mob/living/basic/bot/bot_pawn = controller.pawn
//we are now evil. dont befriend the janitors
if((bot_pawn.bot_access_flags & BOT_COVER_EMAGGED))
if(bot_pawn.bot_access_flags & BOT_COVER_EMAGGED)
return
if(controller.blackboard_key_exists(BB_FRIENDLY_JANITOR))
controller.queue_behavior(/datum/ai_behavior/befriend_target, BB_FRIENDLY_JANITOR, BB_FRIENDLY_MESSAGE)
Expand Down Expand Up @@ -198,12 +207,12 @@
return
if(isnull(parent.ai_controller))
return
if(LAZYACCESS(parent.ai_controller.blackboard[BB_TEMPORARY_IGNORE_LIST], target))
if(LAZYACCESS(parent.ai_controller.blackboard[BB_TEMPORARY_IGNORE_LIST], REF(target)))
return
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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#define BOT_FRUSTRATION_LIMIT 8
#define BOT_ANGER_THRESHOLD 5

/datum/ai_controller/basic_controller/bot/hygienebot
blackboard = list(
Expand Down Expand Up @@ -128,7 +129,7 @@
var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY]

if(succeeded)
if(controller.blackboard[BB_WASH_FRUSTRATION] > 0)
if(controller.blackboard[BB_WASH_FRUSTRATION] > BOT_ANGER_THRESHOLD)
announcement.announce(pick(controller.blackboard[BB_WASH_DONE]))
controller.clear_blackboard_key(target_key)
return
Expand All @@ -139,4 +140,5 @@
announcement.announce(pick(controller.blackboard[BB_WASH_THREATS]))
controller.set_blackboard_key(BB_WASH_FRUSTRATION, 0)

#undef BOT_ANGER_THRESHOLD
#undef BOT_FRUSTRATION_LIMIT
Loading
Loading