Skip to content
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

#82643 Refactor of basic AI sucess/failure #4958

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions code/__DEFINES/ai/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@
///Flags for ai_behavior new()
#define AI_CONTROLLER_INCOMPATIBLE (1<<0)

//Return flags for ai_behavior/perform()
///Update this behavior's cooldown
#define AI_BEHAVIOR_DELAY (1<<0)
///Finish the behavior successfully
#define AI_BEHAVIOR_SUCCEEDED (1<<1)
///Finish the behavior unsuccessfully
#define AI_BEHAVIOR_FAILED (1<<1)

#define AI_BEHAVIOR_INSTANT (NONE)

///Does this task require movement from the AI before it can be performed?
#define AI_BEHAVIOR_REQUIRE_MOVEMENT (1<<0)
///Does this require the current_movement_target to be adjacent and in reach?
Expand Down
2 changes: 1 addition & 1 deletion code/datums/ai/_ai_behavior.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
return TRUE

///Called by the AI controller when this action is performed
///Returns a set of flags defined in [code/__DEFINES/ai/ai.dm]
/datum/ai_behavior/proc/perform(seconds_per_tick, datum/ai_controller/controller, ...)
controller.behavior_cooldowns[src] = world.time + get_cooldown(controller)
return

///Called when the action is finished. This needs the same args as perform besides the default ones
Expand Down
24 changes: 16 additions & 8 deletions code/datums/ai/_ai_controller.dm
Original file line number Diff line number Diff line change
Expand Up @@ -358,14 +358,12 @@ multiple modular subtrees with behaviors
break

SEND_SIGNAL(src, COMSIG_AI_CONTROLLER_PICKED_BEHAVIORS, current_behaviors, planned_behaviors)
for(var/datum/ai_behavior/current_behavior as anything in current_behaviors)
if(LAZYACCESS(planned_behaviors, current_behavior))
continue
for(var/datum/ai_behavior/forgotten_behavior as anything in current_behaviors - planned_behaviors)
var/list/arguments = list(src, FALSE)
var/list/stored_arguments = behavior_args[type]
if(stored_arguments)
arguments += stored_arguments
current_behavior.finish_action(arglist(arguments))
forgotten_behavior.finish_action(arglist(arguments))

///This proc handles changing ai status, and starts/stops processing if required.
/datum/ai_controller/proc/set_ai_status(new_ai_status)
Expand All @@ -391,7 +389,7 @@ multiple modular subtrees with behaviors
paused_until = world.time + time

/datum/ai_controller/proc/modify_cooldown(datum/ai_behavior/behavior, new_cooldown)
behavior_cooldowns[behavior.type] = new_cooldown
behavior_cooldowns[behavior] = new_cooldown

///Call this to add a behavior to the stack.
/datum/ai_controller/proc/queue_behavior(behavior_type, ...)
Expand Down Expand Up @@ -421,13 +419,23 @@ multiple modular subtrees with behaviors
var/list/stored_arguments = behavior_args[behavior.type]
if(stored_arguments)
arguments += stored_arguments
behavior.perform(arglist(arguments))

var/process_flags = behavior.perform(arglist(arguments))
if(process_flags & AI_BEHAVIOR_DELAY)
behavior_cooldowns[behavior] = world.time + behavior.get_cooldown(src)
if(process_flags & AI_BEHAVIOR_FAILED)
arguments[1] = src
arguments[2] = FALSE
behavior.finish_action(arglist(arguments))
else if (process_flags & AI_BEHAVIOR_SUCCEEDED)
arguments[1] = src
arguments[2] = TRUE
behavior.finish_action(arglist(arguments))

/datum/ai_controller/proc/CancelActions()
if(!LAZYLEN(current_behaviors))
return
for(var/i in current_behaviors)
var/datum/ai_behavior/current_behavior = i
for(var/datum/ai_behavior/current_behavior as anything in current_behaviors)
var/list/arguments = list(src, FALSE)
var/list/stored_arguments = behavior_args[current_behavior.type]
if(stored_arguments)
Expand Down
10 changes: 5 additions & 5 deletions code/datums/ai/_item_behaviors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
/datum/ai_behavior/item_escape_grasp

/datum/ai_behavior/item_escape_grasp/perform(seconds_per_tick, datum/ai_controller/controller)
. = ..()
var/obj/item/item_pawn = controller.pawn
var/mob/item_holder = item_pawn.loc
if(!istype(item_holder))
finish_action(controller, FALSE) //We're no longer being held. abort abort!!
//We're no longer being held. abort abort!!
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
item_pawn.visible_message(span_warning("[item_pawn] slips out of the hands of [item_holder]!"))
item_holder.dropItemToGround(item_pawn, TRUE)
finish_action(controller, TRUE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED


///This behavior is for obj/items, it is used to move closer to a target and throw themselves towards them.
Expand All @@ -30,7 +30,6 @@
set_movement_target(controller, target)

/datum/ai_behavior/item_move_close_and_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, throw_count_key)
. = ..()
var/obj/item/item_pawn = controller.pawn
var/atom/throw_target = controller.blackboard[target_key]

Expand All @@ -39,7 +38,8 @@
playsound(item_pawn.loc, attack_sound, 100, TRUE)
controller.add_blackboard_key(throw_count_key, 1)
if(controller.blackboard[throw_count_key] >= max_attempts)
finish_action(controller, TRUE, target_key, throw_count_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_DELAY

/datum/ai_behavior/item_move_close_and_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, throw_count_key)
. = ..()
Expand Down
17 changes: 6 additions & 11 deletions code/datums/ai/babies/babies_behaviors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
var/max_children = 3

/datum/ai_behavior/find_partner/perform(seconds_per_tick, datum/ai_controller/controller, target_key, partner_types_key, child_types_key)
. = ..()
max_children = controller.blackboard[BB_MAX_CHILDREN] || max_children
var/mob/pawn_mob = controller.pawn
var/list/partner_types = controller.blackboard[partner_types_key]
Expand All @@ -18,12 +17,10 @@
var/children = 0
for(var/mob/living/other in oview(range, pawn_mob))
if(!pawn_mob.faction_check_atom(other))
finish_action(controller, FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

if(children >= max_children)
finish_action(controller, FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

if(other.stat != CONSCIOUS) //Check if it's conscious FIRST.
continue
Expand All @@ -40,9 +37,9 @@

if(other.gender != living_pawn.gender && !(other.flags_1 & HOLOGRAM_1)) //Better safe than sorry ;_;
controller.set_blackboard_key(target_key, other)
finish_action(controller, TRUE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

finish_action(controller, FALSE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED


/**
Expand All @@ -59,16 +56,14 @@
set_movement_target(controller, target)

/datum/ai_behavior/make_babies/perform(seconds_per_tick, datum/ai_controller/controller, target_key, child_types_key)
. = ..()
var/mob/target = controller.blackboard[target_key]
if(QDELETED(target) || target.stat != CONSCIOUS)
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/mob/living/basic/living_pawn = controller.pawn
//living_pawn.set_combat_mode(FALSE)
living_pawn.istate &= ~ISTATE_HARM
living_pawn.melee_attack(target)
finish_action(controller, TRUE, target_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

/datum/ai_behavior/make_babies/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
Expand Down
17 changes: 8 additions & 9 deletions code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
if (isliving(controller.pawn))
var/mob/living/pawn = controller.pawn
if (world.time < pawn.next_move)
return
return AI_BEHAVIOR_INSTANT

. = ..()
var/mob/living/basic/basic_mob = controller.pawn
Expand All @@ -30,8 +30,7 @@
var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key])

if(!targeting_strategy.can_attack(basic_mob, target))
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

var/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something!

Expand All @@ -44,7 +43,8 @@
basic_mob.melee_attack(target)

if(terminate_after_action)
finish_action(controller, TRUE, target_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_DELAY

/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key)
. = ..()
Expand Down Expand Up @@ -81,22 +81,21 @@
var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key])

if(!targeting_strategy.can_attack(basic_mob, target, chase_range))
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED

var/atom/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something!
var/atom/final_target = hiding_target ? hiding_target : target

if(!can_see(basic_mob, final_target, required_distance))
return
return AI_BEHAVIOR_INSTANT

if(avoid_friendly_fire && check_friendly_in_path(basic_mob, target, targeting_strategy))
adjust_position(basic_mob, target)
return ..()
return AI_BEHAVIOR_DELAY

controller.set_blackboard_key(hiding_location_key, hiding_target)
basic_mob.RangedAttack(final_target)
return ..() //only start the cooldown when the shot is shot
return AI_BEHAVIOR_DELAY //only start the cooldown when the shot is shot

/datum/ai_behavior/basic_ranged_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key)
. = ..()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
/datum/ai_behavior/befriend_target

/datum/ai_behavior/befriend_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, befriend_message)
. = ..()
var/mob/living/living_pawn = controller.pawn
var/mob/living/living_target = controller.blackboard[target_key]
if(QDELETED(living_target))
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

living_pawn.befriend(living_target)
var/befriend_text = controller.blackboard[befriend_message]
if(befriend_text)
to_chat(living_target, span_nicegreen("[living_pawn] [befriend_text]"))

finish_action(controller, TRUE, target_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

/datum/ai_behavior/befriend_target/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
Expand Down
3 changes: 1 addition & 2 deletions code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@
set_movement_target(controller, target)

/datum/ai_behavior/climb_tree/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
var/obj/structure/flora/target_tree = controller.blackboard[target_key]
var/mob/living/basic/living_pawn = controller.pawn
if(QDELETED(living_pawn)) // pawn can be null at this point
return
SEND_SIGNAL(living_pawn, COMSIG_LIVING_CLIMB_TREE, target_tree)
finish_action(controller, TRUE, target_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

/datum/ai_behavior/climb_tree/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
Expand Down
10 changes: 3 additions & 7 deletions code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@
var/look_range = 7

/datum/ai_behavior/find_mom/perform(seconds_per_tick, datum/ai_controller/controller, mom_key, ignore_mom_key, found_mom)
. = ..()

var/mob/living_pawn = controller.pawn
var/list/mom_types = controller.blackboard[mom_key]
var/list/all_moms = list()
var/list/ignore_types = controller.blackboard[ignore_mom_key]

if(!length(mom_types))
finish_action(controller, FALSE)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

for(var/mob/mother in oview(look_range, living_pawn))
if(!is_type_in_list(mother, mom_types))
Expand All @@ -26,6 +23,5 @@
controller.set_blackboard_key(found_mom, mom)
if(isbasicmob(mom))
controller.set_blackboard_key(BB_FRIENDS_LIST, mom.ai_controller.blackboard[BB_FRIENDS_LIST])
finish_action(controller, TRUE)
return
finish_action(controller, FALSE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
9 changes: 3 additions & 6 deletions code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,13 @@
return isitem(target) && isturf(target.loc) && !target.anchored

/datum/ai_behavior/pick_up_item/perform(seconds_per_tick, datum/ai_controller/controller, target_key, storage_key)
. = ..()
var/obj/item/target = controller.blackboard[target_key]
if(QDELETED(target) || !isturf(target.loc)) // Someone picked it up or it got deleted
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
if(!controller.pawn.Adjacent(target)) // It teleported
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
pickup_item(controller, target, storage_key)
finish_action(controller, TRUE, target_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

/datum/ai_behavior/pick_up_item/finish_action(datum/ai_controller/controller, success, target_key, storage_key)
. = ..()
Expand Down
22 changes: 22 additions & 0 deletions code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/datum/ai_behavior/pull_target
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION | AI_BEHAVIOR_REQUIRE_REACH

/datum/ai_behavior/pull_target/setup(datum/ai_controller/controller, target_key)
. = ..()
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
return FALSE
set_movement_target(controller, target)

/datum/ai_behavior/pull_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
var/atom/movable/target = controller.blackboard[target_key]
if(QDELETED(target) || target.anchored || target.pulledby)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/mob/living/our_mob = controller.pawn
our_mob.start_pulling(target)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

/datum/ai_behavior/pull_target/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
if(!succeeded)
controller.clear_blackboard_key(target_key)
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,16 @@
return ..()

/datum/ai_behavior/run_away_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key)
. = ..()
if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING])
finish_action(controller, succeeded = FALSE, target_key = target_key, hiding_location_key = hiding_location_key)
return
return AI_BEHAVIOR_DELAY
var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key]
if (QDELETED(target) || !can_see(controller.pawn, target, run_distance))
finish_action(controller, succeeded = TRUE, target_key = target_key, hiding_location_key = hiding_location_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
if (get_dist(controller.pawn, controller.current_movement_target) > required_distance)
return // Still heading over
return AI_BEHAVIOR_DELAY // Still heading over
if (plot_path_away_from(controller, target))
return
finish_action(controller, succeeded = FALSE, target_key = target_key, hiding_location_key = hiding_location_key)
return AI_BEHAVIOR_DELAY
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

/datum/ai_behavior/run_away_from_target/proc/plot_path_away_from(datum/ai_controller/controller, atom/target)
var/turf/target_destination = get_turf(controller.pawn)
Expand All @@ -47,3 +44,14 @@
/datum/ai_behavior/run_away_from_target/finish_action(datum/ai_controller/controller, succeeded, target_key, hiding_location_key)
. = ..()
controller.clear_blackboard_key(target_key)

/datum/ai_behavior/run_away_from_target/run_and_shoot
clear_failed_targets = FALSE

/datum/ai_behavior/run_away_from_target/run_and_shoot/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key)
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/mob/living/living_pawn = controller.pawn
living_pawn.RangedAttack(target)
return ..()
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
/datum/ai_behavior/set_travel_destination

/datum/ai_behavior/set_travel_destination/perform(seconds_per_tick, datum/ai_controller/controller, target_key, location_key)
. = ..()
var/atom/target = controller.blackboard[target_key]

if(QDELETED(target))
finish_action(controller, FALSE, target_key)
return
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED

controller.set_blackboard_key(location_key, target)

finish_action(controller, TRUE, target_key)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@

// We actually only wanted the movement so if we've arrived we're done
/datum/ai_behavior/step_towards_turf/perform(seconds_per_tick, datum/ai_controller/controller, area_key, turf_key)
. = ..()
finish_action(controller, succeeded = TRUE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

/**
* # Step towards turf in area
Expand Down
Loading
Loading