diff --git a/code/__DEFINES/ai/ai.dm b/code/__DEFINES/ai/ai.dm index 8bcb27351573..d58dda3dbbac 100644 --- a/code/__DEFINES/ai/ai.dm +++ b/code/__DEFINES/ai/ai.dm @@ -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? diff --git a/code/datums/ai/_ai_behavior.dm b/code/datums/ai/_ai_behavior.dm index 233b57b15772..eb8f7370dc29 100644 --- a/code/datums/ai/_ai_behavior.dm +++ b/code/datums/ai/_ai_behavior.dm @@ -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 diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index 48b0f1a9db46..d74aa09c5b8d 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -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) @@ -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, ...) @@ -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) diff --git a/code/datums/ai/_item_behaviors.dm b/code/datums/ai/_item_behaviors.dm index 6cfb539f7a0b..c9f3441fdd68 100644 --- a/code/datums/ai/_item_behaviors.dm +++ b/code/datums/ai/_item_behaviors.dm @@ -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. @@ -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] @@ -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) . = ..() diff --git a/code/datums/ai/babies/babies_behaviors.dm b/code/datums/ai/babies/babies_behaviors.dm index e58d99a3ed63..eadd77fa3f54 100644 --- a/code/datums/ai/babies/babies_behaviors.dm +++ b/code/datums/ai/babies/babies_behaviors.dm @@ -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] @@ -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 @@ -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 /** @@ -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) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 6c264e32de71..425b54edb225 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -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 @@ -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! @@ -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) . = ..() @@ -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) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm index e1fd8bed640d..865b028e156c 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm @@ -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) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm index c8c18072a4aa..5046baa7e0f1 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm @@ -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) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm index c012a9f43162..0adc0c5cfc7a 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm @@ -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)) @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm index e81c9f957515..1b65eaa507c9 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm @@ -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) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm new file mode 100644 index 000000000000..900b122dcb3f --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm @@ -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) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm index 23b3a69c4d38..30256cb540d3 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm @@ -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) @@ -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 ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm index 207df4424577..3813b0c843e1 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm index 70a557ccc436..0c6211f49d5f 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm index 377420021a5c..4b2971ae1eaa 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm @@ -12,11 +12,10 @@ return cooldown_for.blackboard[BB_STATIONARY_COOLDOWN] /datum/ai_behavior/stop_and_stare/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/datum/weakref/weak_target = controller.blackboard[target_key] var/atom/movable/target = weak_target?.resolve() if(!ismovable(target) || !isturf(target.loc)) // just to make sure that nothing funky happened between setup and perform - return + return AI_BEHAVIOR_DELAY var/mob/pawn_mob = controller.pawn var/turf/pawn_turf = get_turf(pawn_mob) @@ -27,3 +26,4 @@ if(controller.blackboard[BB_STATIONARY_MOVE_TO_TARGET]) addtimer(CALLBACK(src, PROC_REF(set_movement_target), controller, target, initial(controller.ai_movement)), (controller.blackboard[BB_STATIONARY_SECONDS] + 1 SECONDS)) + return AI_BEHAVIOR_DELAY diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm index a39200d0cc16..be1c6e932a13 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm @@ -8,12 +8,13 @@ var/datum/action/cooldown/ability = controller.blackboard[ability_key] var/mob/living/target = controller.blackboard[target_key] if(QDELETED(ability) || QDELETED(target)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/pawn = controller.pawn pawn.face_atom(target) var/result = ability.Trigger(target = target) - finish_action(controller, result, ability_key, target_key) + if(result) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED /datum/ai_behavior/targeted_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm index 8ad59ba2bf15..799b66095b78 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm @@ -28,8 +28,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ var/atom/current_target = controller.blackboard[target_key] if (targeting_strategy.can_attack(living_mob, current_target, vision_range)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/aggro_range = controller.blackboard[aggro_range_key] || vision_range @@ -46,8 +45,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ if(!potential_targets.len) failed_to_find_anyone(controller, target_key, targeting_strategy_key, hiding_location_key) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/list/filtered_targets = list() @@ -60,8 +58,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ if(!filtered_targets.len) failed_to_find_anyone(controller, target_key, targeting_strategy_key, hiding_location_key) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/atom/target = pick_final_target(controller, filtered_targets) controller.set_blackboard_key(target_key, target) @@ -71,7 +68,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ 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) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_potential_targets/proc/failed_to_find_anyone(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/aggro_range = controller.blackboard[aggro_range_key] || vision_range diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm index 643bb9ced5ad..c734d961b5ef 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm @@ -3,8 +3,6 @@ /datum/ai_behavior/tipped_reaction /datum/ai_behavior/tipped_reaction/perform(seconds_per_tick, datum/ai_controller/controller, tipper_key, reacting_key) - . = ..() - var/mob/living/carbon/tipper = controller.blackboard[tipper_key] // visible part of the visible message @@ -28,7 +26,7 @@ seen_message = "[controller.pawn] seems resigned to its fate." self_message = "You resign yourself to your fate." controller.pawn.visible_message(span_notice("[seen_message]"), span_notice("[self_message]")) - finish_action(controller, TRUE, tipper_key, reacting_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/tipped_reaction/finish_action(datum/ai_controller/controller, succeeded, tipper_key, reacting_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm index 55f6ef4c4c00..c0ae765d54c5 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm @@ -17,8 +17,7 @@ set_movement_target(controller, target) /datum/ai_behavior/travel_towards/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/travel_towards/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -44,5 +43,4 @@ set_movement_target(controller, target_atom) /datum/ai_behavior/travel_towards_atom/perform(seconds_per_tick, datum/ai_controller/controller, atom/target_atom) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm index 655b335d3b63..34e651f8e528 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm @@ -1,14 +1,11 @@ /datum/ai_behavior/unbuckle_mob /datum/ai_behavior/unbuckle_mob/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - var/mob/living/living_pawn = controller.pawn var/atom/movable/buckled_to = living_pawn.buckled if(isnull(buckled_to)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED buckled_to.unbuckle_mob(living_pawn) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm index 889b474ad038..5586425c37c5 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm @@ -17,26 +17,23 @@ return istype(target) && isliving(controller.pawn) // only mobs can vent crawl in the current framework /datum/ai_behavior/crawl_through_vents/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent = controller.blackboard[target_key] || controller.blackboard[BB_ENTRY_VENT_TARGET] var/mob/living/cached_pawn = controller.pawn if(HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING) || !controller.blackboard[BB_CURRENTLY_TARGETING_VENT] || !is_vent_valid(entry_vent)) - return + return AI_BEHAVIOR_DELAY if(!cached_pawn.can_enter_vent(entry_vent, provide_feedback = FALSE)) // we're an AI we scoff at feedback - finish_action(controller, FALSE, target_key) // "never enter a hole you can't get out of" - return + // "never enter a hole you can't get out of" + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/vent_we_exit_out_of = calculate_exit_vent(controller, target_key) if(isnull(vent_we_exit_out_of)) // don't get into the vents if we can't get out of them, that's SILLY. - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_CURRENTLY_TARGETING_VENT, FALSE) // must be done here because we have a do_after sleep in handle_ventcrawl unfortunately and double dipping could lead to erroneous suicide pill calls. cached_pawn.handle_ventcrawl(entry_vent) if(!HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING)) //something failed and we ARE NOT IN THE VENT even though the earlier check said we were good to go! odd. - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_EXIT_VENT_TARGET, vent_we_exit_out_of) @@ -50,7 +47,8 @@ var/upper_vent_time_limit = controller.blackboard[BB_UPPER_VENT_TIME_LIMIT] // the most amount of time we spend in the vents addtimer(CALLBACK(src, PROC_REF(exit_the_vents), controller), rand(lower_vent_time_limit, upper_vent_time_limit)) - controller.set_blackboard_key(BB_GIVE_UP_ON_VENT_PATHING_TIMER_ID, addtimer(CALLBACK(src, PROC_REF(suicide_pill), controller), controller.blackboard[BB_TIME_TO_GIVE_UP_ON_VENT_PATHING], TIMER_STOPPABLE)) + controller.set_blackboard_key(BB_GIVE_UP_ON_VENT_PATHING_TIMER_ID, addtimer(CALLBACK(src, PROC_REF(delayed_suicide_pill), controller, target_key), controller.blackboard[BB_TIME_TO_GIVE_UP_ON_VENT_PATHING], TIMER_STOPPABLE)) + return AI_BEHAVIOR_DELAY /// Figure out an exit vent that we should head towards. If we don't have one, default to the entry vent. If they're all kaput, we die. /datum/ai_behavior/crawl_through_vents/proc/calculate_exit_vent(datum/ai_controller/controller, target_key) @@ -83,8 +81,8 @@ var/mob/living/living_pawn = controller.pawn if(!HAS_TRAIT(living_pawn, TRAIT_MOVE_VENTCRAWLING) && isturf(get_turf(living_pawn))) // we're out of the vents, so no need to do an exit - finish_action(controller, TRUE, target_key) // assume that we got yeeted out somehow and call this so we can halt the suicide pill timer. - return + // assume that we got yeeted out somehow and return this so we can halt the suicide pill timer. + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED living_pawn.forceMove(exit_vent) if(!living_pawn.can_enter_vent(exit_vent, provide_feedback = FALSE)) @@ -92,8 +90,7 @@ emergency_vent = calculate_exit_vent(controller) if(isnull(emergency_vent)) // it's joever. we cooked too hard. - suicide_pill(controller, target_key) - return + return suicide_pill(controller) | AI_BEHAVIOR_DELAY controller.set_blackboard_key(BB_EXIT_VENT_TARGET, emergency_vent) // assign and go again addtimer(CALLBACK(src, PROC_REF(exit_the_vents), controller), (rand(controller.blackboard[BB_LOWER_VENT_TIME_LIMIT], controller.blackboard[BB_UPPER_VENT_TIME_LIMIT]) / 2)) // we're in danger mode, so scurry out at half the time it would normally take. @@ -105,29 +102,32 @@ suicide_pill() // all of the prior checks say we should have definitely made it through, but we didn't. dammit. return - finish_action(controller, TRUE, target_key) // we did it! we went into the vents and out of the vents. poggers. + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED // we did it! we went into the vents and out of the vents. poggers. /// Incredibly stripped down version of the overarching `can_enter_vent` proc on `/mob, just meant for rapid rechecking of a vent. Will be TRUE if not blocked, FALSE otherwise. /datum/ai_behavior/crawl_through_vents/proc/is_vent_valid(obj/machinery/atmospherics/components/unary/vent_pump/checkable) return !QDELETED(checkable) && !checkable.welded +/// Wraps a delayed defeat, so we gotta handle the return value properly ya feel? +/datum/ai_behavior/crawl_through_vents/proc/delayed_suicide_pill(datum/ai_controller/controller, target_key) + if(suicide_pill(controller) & AI_BEHAVIOR_FAILED) + finish_action(controller, FALSE, target_key) + /// Aw fuck, we may have been bested somehow. Regardless of what we do, we can't exit through a vent! Let's end our misery and prevent useless endless calculations. -/datum/ai_behavior/crawl_through_vents/proc/suicide_pill(datum/ai_controller/controller, target_key) +/datum/ai_behavior/crawl_through_vents/proc/suicide_pill(datum/ai_controller/controller) var/mob/living/living_pawn = controller.pawn if(istype(living_pawn)) - finish_action(controller, FALSE, target_key) - if(isnull(living_pawn.client)) // only call death if we don't have a client because maybe their natural intelligence can pick up where our AI calculations have failed living_pawn.death(TRUE) // call gibbed as true because we are never coming back it is so fucking joever - return + return AI_BEHAVIOR_FAILED if(QDELETED(living_pawn)) // we got deleted by some other means, just presume the action is a wash and get outta here - return + return NONE qdel(living_pawn) // failover, we really should've been caught in the istype() but lets just bow out of existing at this point - + return NONE /datum/ai_behavior/crawl_through_vents/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm index f5dba58416d2..51826676e9e8 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm @@ -1,7 +1,6 @@ /datum/ai_behavior/write_on_paper /datum/ai_behavior/write_on_paper/perform(seconds_per_tick, datum/ai_controller/controller, found_paper, list_of_writings) - . = ..() var/mob/living/wizard = controller.pawn var/list/writing_list = controller.blackboard[list_of_writings] var/obj/item/paper/target = controller.blackboard[found_paper] @@ -9,7 +8,7 @@ target.add_raw_text(pick(writing_list)) target.update_appearance() wizard.dropItemToGround(target) - finish_action(controller, TRUE, found_paper) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/write_on_paper/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm index 411690043546..2558fadcc0af 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm index 7059bec93fe2..bc8efdeb4ff5 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm @@ -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) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm b/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm index 59ff88b4879b..44d7cb4fe480 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm index 4d5319bca86e..a4fc49facc00 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm @@ -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) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm index 991f9962f2c7..fc1bbc6f28cf 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm @@ -63,8 +63,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) . = ..() @@ -86,8 +85,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 @@ -115,5 +114,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 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm b/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm index 3c03702b6994..da371224aecc 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm @@ -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 //poor creature, if you weren't explosion proof you would be dead. /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 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm b/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm index c98878e0fd71..bcf5c8290251 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm @@ -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) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm index 95a125eea5ce..3640a2052b55 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm b/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm index 6f2f5cdc2035..90e1de324959 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm @@ -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_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm index 93499cf673c4..5d9841a52473 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm @@ -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) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm index 55ec73876131..d327b1047cf5 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -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) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm index dadba992e9f1..25f0e4a42496 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm @@ -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 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm index 5ceef67bedb2..410c611ae43a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm @@ -27,7 +27,7 @@ /datum/ai_behavior/use_mob_ability/perform(seconds_per_tick, datum/ai_controller/controller, ability_key) var/datum/action/cooldown/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 diff --git a/code/datums/ai/basic_mobs/pet_commands/fetch.dm b/code/datums/ai/basic_mobs/pet_commands/fetch.dm index ce018b55f7ec..fe5bbb155664 100644 --- a/code/datums/ai/basic_mobs/pet_commands/fetch.dm +++ b/code/datums/ai/basic_mobs/pet_commands/fetch.dm @@ -19,15 +19,12 @@ // It stopped existing if (QDELETED(fetch_thing)) - finish_action(controller, FALSE, target_key, delivery_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn // We can't pick this up if (fetch_thing.anchored || !isturf(fetch_thing.loc) || !living_pawn.CanReach(fetch_thing)) - finish_action(controller, FALSE, target_key, delivery_key) - return - - finish_action(controller, TRUE, target_key, delivery_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/fetch_seek/finish_action(datum/ai_controller/controller, success, target_key, delivery_key) . = ..() @@ -54,14 +51,13 @@ set_movement_target(controller, return_target) /datum/ai_behavior/deliver_fetched_item/perform(seconds_per_tick, datum/ai_controller/controller, delivery_key, storage_key) - . = ..() var/mob/living/return_target = controller.blackboard[delivery_key] if(QDELETED(return_target)) - finish_action(controller, FALSE, delivery_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED - deliver_item(controller, return_target, storage_key) - finish_action(controller, TRUE, delivery_key) + if(!deliver_item(controller, return_target, storage_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/deliver_fetched_item/finish_action(datum/ai_controller/controller, success, delivery_key) . = ..() @@ -69,13 +65,13 @@ controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) /// Actually deliver the fetched item to the target, if we still have it +/// Returns TRUE if we succeeded, FALSE if we failed /datum/ai_behavior/deliver_fetched_item/proc/deliver_item(datum/ai_controller/controller, return_target, storage_key) var/mob/pawn = controller.pawn var/obj/item/carried_item = controller.blackboard[storage_key] if(QDELETED(carried_item) || carried_item.loc != pawn) pawn.visible_message(span_notice("[pawn] looks around as if [pawn.p_they()] [pawn.p_have()] lost something.")) - finish_action(controller, FALSE) - return + return FALSE pawn.visible_message(span_notice("[pawn] delivers [carried_item] to [return_target].")) carried_item.forceMove(get_turf(return_target)) @@ -100,14 +96,14 @@ set_movement_target(controller, snack) /datum/ai_behavior/eat_fetched_snack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, delivery_key) - . = ..() var/obj/item/snack = controller.blackboard[target_key] if(QDELETED(snack) || !isturf(snack.loc) || ishuman(snack.loc)) - finish_action(controller, FALSE) // Where did it go? + // Where did it go? + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/basic_pawn = controller.pawn if(!in_range(basic_pawn, snack)) - return + return AI_BEHAVIOR_DELAY if(isturf(snack.loc)) basic_pawn.melee_attack(snack) // snack attack! @@ -115,7 +111,8 @@ basic_pawn.manual_emote("Stares at [snack.loc]'s [snack.name] intently.") if(QDELETED(snack)) // we ate it! - finish_action(controller, TRUE, target_key, delivery_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/eat_fetched_snack/finish_action(datum/ai_controller/controller, succeeded, target_key, delivery_key) . = ..() @@ -140,7 +137,6 @@ return /datum/ai_behavior/forget_failed_fetches/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() COOLDOWN_START(src, reset_ignore_cooldown, cooldown_duration) controller.clear_blackboard_key(BB_FETCH_IGNORE_LIST) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm b/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm index 397021818aa8..38a6939c9018 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm @@ -10,8 +10,7 @@ set_movement_target(controller, target) /datum/ai_behavior/pet_follow_friend/perform(seconds_per_tick, datum/ai_controller/controller, target_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 + return AI_BEHAVIOR_DELAY diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm b/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm index c7153b0c12f7..3c8c06b00996 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm @@ -13,11 +13,11 @@ var/datum/action/cooldown/mob_cooldown/ability = controller.blackboard[ability_key] var/mob/living/target = controller.blackboard[target_key] if (QDELETED(ability) || QDELETED(target)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/pawn = controller.pawn if(QDELETED(pawn) || ability.InterceptClickOn(pawn, null, target)) - finish_action(controller, TRUE, ability_key, target_key) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT /datum/ai_behavior/pet_use_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/pet_commands/play_dead.dm b/code/datums/ai/basic_mobs/pet_commands/play_dead.dm index 3aed57fb35c2..de7f052a367c 100644 --- a/code/datums/ai/basic_mobs/pet_commands/play_dead.dm +++ b/code/datums/ai/basic_mobs/pet_commands/play_dead.dm @@ -13,7 +13,8 @@ /datum/ai_behavior/play_dead/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() if(SPT_PROB(10, seconds_per_tick)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/play_dead/finish_action(datum/ai_controller/controller, succeeded) . = ..() diff --git a/code/datums/ai/dog/dog_behaviors.dm b/code/datums/ai/dog/dog_behaviors.dm index d0c55a347cff..884161c2f82f 100644 --- a/code/datums/ai/dog/dog_behaviors.dm +++ b/code/datums/ai/dog/dog_behaviors.dm @@ -11,23 +11,21 @@ controller.behavior_cooldowns[src] = world.time + get_cooldown(controller) var/mob/living/living_pawn = controller.pawn if(!(isturf(living_pawn.loc) || HAS_TRAIT(living_pawn, TRAIT_AI_BAGATTACK))) // Void puppies can attack from inside bags - finish_action(controller, FALSE, target_key, targeting_strategy_key, hiding_location_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED // Unfortunately going to repeat this check in parent call but what can you do var/atom/target = controller.blackboard[target_key] var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if (!targeting_strategy.can_attack(living_pawn, target)) - finish_action(controller, FALSE, target_key, targeting_strategy_key, hiding_location_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED if (!in_range(living_pawn, target)) growl_at(living_pawn, target, seconds_per_tick) - return + return AI_BEHAVIOR_INSTANT if(!controller.blackboard[BB_DOG_HARASS_HARM]) paw_harmlessly(living_pawn, target, seconds_per_tick) - return + return AI_BEHAVIOR_INSTANT // Give Ian some teeth var/old_melee_lower = living_pawn.melee_damage_lower @@ -39,6 +37,7 @@ living_pawn.melee_damage_lower = old_melee_lower living_pawn.melee_damage_upper = old_melee_upper + return AI_BEHAVIOR_DELAY /// Swat at someone we don't like but won't hurt /datum/ai_behavior/basic_melee_attack/dog/proc/paw_harmlessly(mob/living/living_pawn, atom/target, seconds_per_tick) diff --git a/code/datums/ai/dog/dog_subtrees.dm b/code/datums/ai/dog/dog_subtrees.dm index 62f63da54bdd..ef2f1a1f37aa 100644 --- a/code/datums/ai/dog/dog_subtrees.dm +++ b/code/datums/ai/dog/dog_subtrees.dm @@ -36,4 +36,4 @@ /datum/ai_behavior/find_hated_dog_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index b0d34f68c224..1e9be0a6b960 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -7,16 +7,15 @@ action_cooldown = 2 SECONDS /datum/ai_behavior/find_and_set/perform(seconds_per_tick, datum/ai_controller/controller, set_key, locate_path, search_range) - . = ..() if (controller.blackboard_key_exists(set_key)) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + if(QDELETED(controller.pawn)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED 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 - finish_action(controller, FALSE) + if(isnull(find_this_thing)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + controller.set_blackboard_key(set_key, find_this_thing) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /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) diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index 9a4cba2da6c5..2dd58e945722 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -1,27 +1,25 @@ /datum/ai_behavior/resist/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn + living_pawn.ai_controller.set_blackboard_key(BB_RESISTING, TRUE) living_pawn.execute_resist() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/battle_screech ///List of possible screeches the behavior has var/list/screeches /datum/ai_behavior/battle_screech/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn INVOKE_ASYNC(living_pawn, TYPE_PROC_REF(/mob, emote), pick(screeches)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///Moves to target then finishes /datum/ai_behavior/move_to_target behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT /datum/ai_behavior/move_to_target/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/break_spine @@ -41,12 +39,10 @@ var/mob/living/big_guy = controller.pawn //he was molded by the darkness if(QDELETED(batman) || get_dist(batman, big_guy) >= give_up_distance) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED if(batman.stat != CONSCIOUS) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED big_guy.start_pulling(batman) big_guy.face_atom(batman) @@ -62,7 +58,7 @@ else batman.adjustBruteLoss(150) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/break_spine/finish_action(datum/ai_controller/controller, succeeded, target_key) if(succeeded) @@ -79,14 +75,12 @@ /datum/ai_behavior/use_in_hand/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held = pawn.get_active_held_item() if(!held) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED pawn.activate_hand() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// Use the currently held item, or unarmed, on a weakref to an object in the world /datum/ai_behavior/use_on_object @@ -101,13 +95,11 @@ set_movement_target(controller, target) /datum/ai_behavior/use_on_object/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand()) var/atom/target = controller.blackboard[target_key] if(QDELETED(target) || !pawn.CanReach(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED pawn.set_combat_mode(FALSE) if(held_item) @@ -115,7 +107,7 @@ else pawn.UnarmedAttack(target, TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/give required_distance = 1 @@ -127,37 +119,34 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/give/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_active_held_item() var/atom/target = controller.blackboard[target_key] if(!held_item) //if held_item is null, we pretend that action was succesful - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED - if(!target || !pawn.CanReach(target) || !isliving(target)) - finish_action(controller, FALSE) - return + if(!target || !isliving(target)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_target = target - - if(!try_to_give_item(controller, living_target, held_item)) - return + var/perform_flags = try_to_give_item(controller, living_target, held_item) + if(perform_flags & AI_BEHAVIOR_FAILED) + return perform_flags controller.PauseAi(1.5 SECONDS) living_target.visible_message( span_info("[pawn] starts trying to give [held_item] to [living_target]!"), span_warning("[pawn] tries to give you [held_item]!") ) if(!do_after(pawn, 1 SECONDS, living_target)) - return + return AI_BEHAVIOR_DELAY | perform_flags - try_to_give_item(controller, living_target, held_item, actually_give = TRUE) + perform_flags |= try_to_give_item(controller, living_target, held_item, actually_give = TRUE) + return AI_BEHAVIOR_DELAY | perform_flags /datum/ai_behavior/give/proc/try_to_give_item(datum/ai_controller/controller, mob/living/target, obj/item/held_item, actually_give) if(QDELETED(held_item) || QDELETED(target)) - finish_action(controller, FALSE) - return FALSE + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/has_left_pocket = target.can_equip(held_item, ITEM_SLOT_LPOCKET) var/has_right_pocket = target.can_equip(held_item, ITEM_SLOT_RPOCKET) @@ -169,17 +158,16 @@ break if(!has_left_pocket && !has_right_pocket && !has_valid_hand) - finish_action(controller, FALSE) - return FALSE + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(!actually_give) - return TRUE + return AI_BEHAVIOR_DELAY if(!has_valid_hand || prob(50)) target.equip_to_slot_if_possible(held_item, (!has_left_pocket ? ITEM_SLOT_RPOCKET : (prob(50) ? ITEM_SLOT_LPOCKET : ITEM_SLOT_RPOCKET))) else target.put_in_hands(held_item) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/consume @@ -192,21 +180,20 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/consume/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hunger_timer_key) - . = ..() var/mob/living/living_pawn = controller.pawn var/obj/item/target = controller.blackboard[target_key] if(QDELETED(target)) - return + return AI_BEHAVIOR_DELAY if(!(target in living_pawn.held_items)) if(!living_pawn.get_empty_held_indexes() || !living_pawn.put_in_hands(target)) - finish_action(controller, FALSE, target, hunger_timer_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED target.melee_attack_chain(living_pawn, living_pawn) if(QDELETED(target) || prob(10)) // Even if we don't finish it all we can randomly decide to be done - finish_action(controller, TRUE, null, hunger_timer_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/consume/finish_action(datum/ai_controller/controller, succeeded, target_key, hunger_timer_key) . = ..() @@ -219,13 +206,13 @@ /datum/ai_behavior/drop_item /datum/ai_behavior/drop_item/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn var/obj/item/best_held = GetBestWeapon(controller, null, living_pawn.held_items) for(var/obj/item/held as anything in living_pawn.held_items) if(!held || held == best_held) continue living_pawn.dropItemToGround(held) + return AI_BEHAVIOR_DELAY /// This behavior involves attacking a target. /datum/ai_behavior/attack @@ -233,23 +220,21 @@ required_distance = 1 /datum/ai_behavior/attack/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !isturf(living_pawn.loc)) - return + return AI_BEHAVIOR_DELAY var/atom/movable/attack_target = controller.blackboard[BB_ATTACK_TARGET] if(!attack_target || !can_see(living_pawn, attack_target, length = controller.blackboard[BB_VISION_RANGE])) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_target = attack_target if(istype(living_target) && (living_target.stat == DEAD)) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED set_movement_target(controller, living_target) attack(controller, living_target) + return AI_BEHAVIOR_DELAY /datum/ai_behavior/attack/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -268,22 +253,20 @@ required_distance = 1 /datum/ai_behavior/follow/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !isturf(living_pawn.loc)) - return + return AI_BEHAVIOR_DELAY var/atom/movable/follow_target = controller.blackboard[BB_FOLLOW_TARGET] if(!follow_target || get_dist(living_pawn, follow_target) > controller.blackboard[BB_VISION_RANGE]) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_target = follow_target if(istype(living_target) && (living_target.stat == DEAD)) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED set_movement_target(controller, living_target) + return AI_BEHAVIOR_DELAY /datum/ai_behavior/follow/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -294,9 +277,11 @@ /datum/ai_behavior/perform_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote) var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn)) - return + return AI_BEHAVIOR_INSTANT living_pawn.manual_emote(emote) - finish_action(controller, TRUE) + if(speech_sound) // Only audible emotes will pass in a sound + playsound(living_pawn, speech_sound, 80, vary = TRUE + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/perform_speech @@ -305,29 +290,26 @@ var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn)) - return + return AI_BEHAVIOR_INSTANT living_pawn.say(speech, forced = "AI Controller") if(speech_sound) playsound(living_pawn, speech_sound, 80, vary = TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/perform_speech_radio /datum/ai_behavior/perform_speech_radio/perform(seconds_per_tick, datum/ai_controller/controller, speech, obj/item/radio/speech_radio, list/try_channels = list(RADIO_CHANNEL_COMMON)) var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !istype(speech_radio) || QDELETED(speech_radio) || !length(try_channels)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED speech_radio.talk_into(living_pawn, speech, pick(try_channels)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED //song behaviors /datum/ai_behavior/setup_instrument /datum/ai_behavior/setup_instrument/perform(seconds_per_tick, datum/ai_controller/controller, song_instrument_key, song_lines_key) - . = ..() - var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key] var/datum/song/song = song_instrument.song var/song_lines = controller.blackboard[song_lines_key] @@ -337,24 +319,20 @@ song.ParseSong(song_lines) song.repeat = 10 song.volume = song.max_volume - 10 - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/play_instrument /datum/ai_behavior/play_instrument/perform(seconds_per_tick, datum/ai_controller/controller, song_instrument_key) - . = ..() - var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key] var/datum/song/song = song_instrument.song song.start_playing(controller.pawn) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_nearby /datum/ai_behavior/find_nearby/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/list/possible_targets = list() for(var/atom/thing in view(2, controller.pawn)) if(!thing.mouse_opacity) @@ -363,6 +341,6 @@ continue possible_targets += thing if(!possible_targets.len) - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, pick(possible_targets)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index 9bd8c60f28a4..c0deaf512792 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -52,18 +52,14 @@ /datum/ai_behavior/find_hunt_target /datum/ai_behavior/find_hunt_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range) - . = ..() - var/mob/living/living_mob = controller.pawn for(var/atom/possible_dinner as anything in typecache_filter_list(range(hunt_range, living_mob), types_to_hunt)) if(!valid_dinner(living_mob, possible_dinner, hunt_range)) continue controller.set_blackboard_key(hunting_target_key, possible_dinner) - finish_action(controller, TRUE) - return - - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/find_hunt_target/proc/valid_dinner(mob/living/source, atom/dinner, radius) if(isliving(dinner)) @@ -90,15 +86,13 @@ set_movement_target(controller, hunt_target) /datum/ai_behavior/hunt_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) - . = ..() var/mob/living/hunter = controller.pawn var/atom/hunted = controller.blackboard[hunting_target_key] if(QDELETED(hunted)) - finish_action(controller, FALSE, hunting_target_key) - else - target_caught(hunter, hunted) - finish_action(controller, TRUE, hunting_target_key, hunting_cooldown_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + target_caught(hunter, hunted) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/hunt_target/proc/target_caught(mob/living/hunter, atom/hunted) if(isliving(hunted)) // Are we hunting a living mob? @@ -151,7 +145,7 @@ /datum/ai_behavior/hunt_target/use_ability_on_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) var/datum/action/cooldown/ability = controller.blackboard[ability_key] if(!ability?.IsAvailable()) - finish_action(controller, FALSE, hunting_target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED return ..() /datum/ai_behavior/hunt_target/use_ability_on_target/target_caught(mob/living/hunter, atom/hunted) diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index 77aa49dd6c55..ffd574d0ab08 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -12,55 +12,51 @@ controller.clear_blackboard_key(BB_MONKEY_PICKUPTARGET) +/// Equips an item on the monkey +/// Returns TRUE if it works out, FALSE otherwise /datum/ai_behavior/monkey_equip/proc/equip_item(datum/ai_controller/controller) var/mob/living/living_pawn = controller.pawn var/obj/item/target = controller.blackboard[BB_MONKEY_PICKUPTARGET] var/best_force = controller.blackboard[BB_MONKEY_BEST_FORCE_FOUND] - if(!isturf(living_pawn.loc)) - finish_action(controller, FALSE) - return + return FALSE if(!target) - finish_action(controller, FALSE) - return + return FALSE if(target.anchored) //Can't pick it up, so stop trying. - finish_action(controller, FALSE) - return + return FALSE // Strong weapon else if(target.force > best_force) living_pawn.drop_all_held_items() living_pawn.put_in_hands(target) controller.set_blackboard_key(BB_MONKEY_BEST_FORCE_FOUND, target.force) - finish_action(controller, TRUE) - return + return TRUE else if(target.slot_flags) //Clothing == top priority living_pawn.dropItemToGround(target, TRUE) living_pawn.update_icons() if(!living_pawn.equip_to_appropriate_slot(target)) - finish_action(controller, FALSE) - return //Already wearing something, in the future this should probably replace the current item but the code didn't actually do that, and I dont want to support it right now. - finish_action(controller, TRUE) - return + return FALSE //Already wearing something, in the future this should probably replace the current item but the code didn't actually do that, and I dont want to support it right now. + return TRUE // EVERYTHING ELSE else if(living_pawn.get_empty_held_indexes()) living_pawn.put_in_hands(target) - finish_action(controller, TRUE) - return + return TRUE - finish_action(controller, FALSE) + return FALSE /datum/ai_behavior/monkey_equip/ground required_distance = 0 /datum/ai_behavior/monkey_equip/ground/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() - equip_item(controller) + if(equip_item(controller)) + return . | AI_BEHAVIOR_SUCCEEDED + return . | AI_BEHAVIOR_FAILED /datum/ai_behavior/monkey_equip/pickpocket @@ -110,13 +106,10 @@ /datum/ai_behavior/monkey_flee /datum/ai_behavior/monkey_flee/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - var/mob/living/living_pawn = controller.pawn - if(living_pawn.health >= MONKEY_FLEE_HEALTH) - finish_action(controller, TRUE) //we're back in bussiness - return + if(living_pawn.health >= MONKEY_FLEE_HEALTH) //we're back in bussiness + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/mob/living/target = null @@ -128,8 +121,8 @@ if(target) SSmove_manager.move_away(living_pawn, target, max_dist=MONKEY_ENEMY_VISION, delay=5) - else - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/monkey_attack_mob behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM //performs to increase frustration @@ -139,29 +132,28 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/monkey_attack_mob/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/mob/living/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn - if(!target || target.stat != CONSCIOUS) - finish_action(controller, TRUE) //Target == owned - return + if(!target || target.stat != CONSCIOUS) //Target == owned + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED - if(isturf(target.loc) && !IS_DEAD_OR_INCAP(living_pawn)) // Check if they're a valid target - // check if target has a weapon - var/obj/item/W - for(var/obj/item/I in target.held_items) - if(!(I.item_flags & ABSTRACT)) - W = I - break - - // if the target has a weapon, chance to disarm them - if(W && SPT_PROB(MONKEY_ATTACK_DISARM_PROB, seconds_per_tick)) - monkey_attack(controller, target, seconds_per_tick, TRUE) - else - monkey_attack(controller, target, seconds_per_tick, FALSE) + if(!isturf(target.loc) || IS_DEAD_OR_INCAP(living_pawn)) // Check if they're a valid target + return AI_BEHAVIOR_DELAY + // check if target has a weapon + var/obj/item/W + for(var/obj/item/I in target.held_items) + if(!(I.item_flags & ABSTRACT)) + W = I + break +// if the target has a weapon, chance to disarm them + var/perform_flags = NONE + if(W && SPT_PROB(MONKEY_ATTACK_DISARM_PROB, seconds_per_tick)) + perform_flags = monkey_attack(controller, target, seconds_per_tick, TRUE) + else + perform_flags = monkey_attack(controller, target, seconds_per_tick, FALSE) + return AI_BEHAVIOR_DELAY | perform_flags /datum/ai_behavior/monkey_attack_mob/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -176,7 +168,7 @@ var/mob/living/living_pawn = controller.pawn if(living_pawn.next_move > world.time) - return + return NONE living_pawn.changeNext_move(CLICK_CD_MELEE) //We play fair @@ -218,7 +210,7 @@ // no de-aggro if(controller.blackboard[BB_MONKEY_AGGRESSIVE] && !(HAS_TRAIT(target, TRAIT_MONKEYFRIEND))) - return + return NONE // we've queued up a monkey attack on a mob which isn't already an enemy, so give them 1 threat to start // note they might immediately reduce threat and drop from the list. @@ -242,7 +234,8 @@ controller.remove_thing_from_blackboard_key(BB_MONKEY_ENEMIES, target) living_pawn.set_combat_mode(FALSE) if(controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] == target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_SUCCEEDED + return NONE /datum/ai_behavior/disposal_mob behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM //performs to increase frustration @@ -258,10 +251,8 @@ controller.clear_blackboard_key(disposal_target_key) //No target disposal /datum/ai_behavior/disposal_mob/perform(seconds_per_tick, datum/ai_controller/controller, attack_target_key, disposal_target_key) - . = ..() - if(controller.blackboard[BB_MONKEY_DISPOSING]) //We are disposing, don't do ANYTHING!!!! - return + return AI_BEHAVIOR_DELAY var/mob/living/target = controller.blackboard[attack_target_key] var/mob/living/living_pawn = controller.pawn @@ -269,25 +260,24 @@ set_movement_target(controller, target) if(!target) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(target.pulledby != living_pawn && !HAS_AI_CONTROLLER_TYPE(target.pulledby, /datum/ai_controller/monkey)) //Dont steal from my fellow monkeys. if(living_pawn.Adjacent(target) && isturf(target.loc)) target.grabbedby(living_pawn) - return //Do the rest next turn + return AI_BEHAVIOR_DELAY //Do the rest next turn var/obj/machinery/disposal/disposal = controller.blackboard[disposal_target_key] set_movement_target(controller, disposal) if(!disposal) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(living_pawn.Adjacent(disposal)) INVOKE_ASYNC(src, PROC_REF(try_disposal_mob), controller, attack_target_key, disposal_target_key) //put him in! - else //This means we might be getting pissed! - return + return AI_BEHAVIOR_DELAY + //This means we might be getting pissed! + return AI_BEHAVIOR_DELAY /datum/ai_behavior/disposal_mob/proc/try_disposal_mob(datum/ai_controller/controller, attack_target_key, disposal_target_key) var/mob/living/living_pawn = controller.pawn @@ -302,8 +292,6 @@ /datum/ai_behavior/recruit_monkeys/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - controller.set_blackboard_key(BB_MONKEY_RECRUIT_COOLDOWN, world.time + MONKEY_RECRUIT_COOLDOWN) var/mob/living/living_pawn = controller.pawn @@ -317,7 +305,7 @@ // Other monkeys now also hate the guy we're currently targeting nearby_monkey.ai_controller.add_blackboard_key_assoc(BB_MONKEY_ENEMIES, controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET], MONKEY_RECRUIT_HATED_AMOUNT) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/monkey_set_combat_target/perform(seconds_per_tick, datum/ai_controller/controller, set_key, enemies_key) var/list/enemies = controller.blackboard[enemies_key] @@ -334,8 +322,7 @@ valids[possible_enemy] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1) if(!length(valids)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED controller.set_blackboard_key(set_key, pick_weight(valids)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/objects/mod.dm b/code/datums/ai/objects/mod.dm index 84f5678addbf..478c517be8d8 100644 --- a/code/datums/ai/objects/mod.dm +++ b/code/datums/ai/objects/mod.dm @@ -37,10 +37,10 @@ /datum/ai_behavior/mod_attach/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() if(!controller.pawn.Adjacent(controller.blackboard[BB_MOD_TARGET])) - return + return AI_BEHAVIOR_DELAY var/obj/item/implant/mod/implant = controller.blackboard[BB_MOD_IMPLANT] implant.module.attach(controller.blackboard[BB_MOD_TARGET]) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/mod_attach/finish_action(datum/ai_controller/controller, succeeded) . = ..() diff --git a/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm b/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm index b4e5609531c1..d6310bfc9f3b 100644 --- a/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm +++ b/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm @@ -10,15 +10,15 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/vendor_crush/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() if(controller.blackboard[BB_VENDING_BUSY_TILTING]) - return + return AI_BEHAVIOR_DELAY controller.ai_movement.stop_moving_towards(controller) controller.set_blackboard_key(BB_VENDING_BUSY_TILTING, TRUE) var/turf/target_turf = get_turf(controller.blackboard[BB_VENDING_CURRENT_TARGET]) new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(target_turf) addtimer(CALLBACK(src, PROC_REF(tiltonmob), controller, target_turf), time_to_tilt) + return AI_BEHAVIOR_DELAY /datum/ai_behavior/vendor_crush/proc/tiltonmob(datum/ai_controller/controller, turf/target_turf) var/obj/machinery/vending/vendor_pawn = controller.pawn @@ -40,10 +40,9 @@ var/succes_tilt_cooldown = 5 SECONDS /datum/ai_behavior/vendor_rise_up/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/obj/machinery/vending/vendor_pawn = controller.pawn vendor_pawn.visible_message(span_warning("[vendor_pawn] untilts itself!")) if(controller.blackboard[BB_VENDING_LAST_HIT_SUCCESFUL]) controller.set_blackboard_key(BB_VENDING_TILT_COOLDOWN, world.time + succes_tilt_cooldown) vendor_pawn.untilt() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/robot_customer/robot_customer_behaviors.dm b/code/datums/ai/robot_customer/robot_customer_behaviors.dm index 735b795e6066..03ca31e72902 100644 --- a/code/datums/ai/robot_customer/robot_customer_behaviors.dm +++ b/code/datums/ai/robot_customer/robot_customer_behaviors.dm @@ -2,7 +2,6 @@ action_cooldown = 8 SECONDS /datum/ai_behavior/find_seat/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] @@ -28,22 +27,20 @@ customer_pawn.say(pick(customer_data.found_seat_lines)) controller.set_blackboard_key(BB_CUSTOMER_MY_SEAT, found_seat) attending_venue.linked_seats[found_seat] = customer_pawn - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED // SPT_PROB 1.5 is about a 60% chance that the tourist will have vocalised at least once every minute. if(!controller.blackboard[BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE] || SPT_PROB(1.5, seconds_per_tick)) customer_pawn.say(pick(customer_data.cant_find_seat_lines)) controller.set_blackboard_key(BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE, TRUE) - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/order_food behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT required_distance = 0 /datum/ai_behavior/order_food/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/obj/structure/holosign/robot_seat/seat_marker = controller.blackboard[BB_CUSTOMER_MY_SEAT] @@ -55,23 +52,19 @@ var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] controller.set_blackboard_key(BB_CUSTOMER_CURRENT_ORDER, attending_venue.order_food(customer_pawn, customer_data)) - - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/wait_for_food behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM required_distance = 0 /datum/ai_behavior/wait_for_food/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() if(controller.blackboard[BB_CUSTOMER_EATING]) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED controller.add_blackboard_key(BB_CUSTOMER_PATIENCE, seconds_per_tick * -1 SECONDS) // Convert seconds_per_tick to a SECONDS equivalent. if(controller.blackboard[BB_CUSTOMER_PATIENCE] < 0 || controller.blackboard[BB_CUSTOMER_LEAVING]) // Check if we're leaving because sometthing mightve forced us to - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED // SPT_PROB 1.5 is about a 40% chance that the tourist will have vocalised at least once every minute. if(SPT_PROB(0.85, seconds_per_tick)) @@ -95,6 +88,7 @@ customer.eat_order(I, attending_venue) break + return AI_BEHAVIOR_DELAY /datum/ai_behavior/wait_for_food/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -122,6 +116,5 @@ set_movement_target(controller, attending_venue.restaurant_portal) /datum/ai_behavior/leave_venue/perform(seconds_per_tick, datum/ai_controller/controller, venue_key) - . = ..() qdel(controller.pawn) //save the world, my final message, goodbye. - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/modules/mob/living/basic/bots/bot_ai.dm b/code/modules/mob/living/basic/bots/bot_ai.dm index d07d4e13f71d..d350f6b9e2db 100644 --- a/code/modules/mob/living/basic/bots/bot_ai.dm +++ b/code/modules/mob/living/basic/bots/bot_ai.dm @@ -99,10 +99,9 @@ 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) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_planning_subtree/find_patrol_beacon @@ -126,7 +125,6 @@ /datum/ai_behavior/find_first_beacon_target /datum/ai_behavior/find_first_beacon_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/closest_distance = INFINITY var/mob/living/basic/bot/bot_pawn = controller.pawn var/atom/final_target @@ -141,19 +139,16 @@ final_target = beacon if(isnull(final_target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_BEACON_TARGET, final_target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_next_beacon_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/bot/bot_pawn = controller.pawn var/atom/final_target var/obj/machinery/navbeacon/prev_beacon = controller.blackboard[BB_PREVIOUS_BEACON_TARGET] if(QDELETED(prev_beacon)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/obj/machinery/navbeacon/beacon as anything in GLOB.navbeacons["[bot_pawn.z]"]) if(beacon.location == prev_beacon.codes[NAVBEACON_PATROL_NEXT]) @@ -162,10 +157,10 @@ if(isnull(final_target)) controller.clear_blackboard_key(BB_PREVIOUS_BEACON_TARGET) - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_BEACON_TARGET, final_target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/travel_towards/beacon @@ -227,14 +222,11 @@ /datum/ai_behavior/salute_authority /datum/ai_behavior/salute_authority/perform(seconds_per_tick, datum/ai_controller/controller, target_key, salute_keys) - . = ..() if(!controller.blackboard_key_exists(target_key)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/list/salute_list = controller.blackboard[salute_keys] if(!length(salute_list)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/bot/bot_pawn = controller.pawn //special interaction if we are wearing a fedora var/obj/item/our_hat = (locate(/obj/item/clothing/head) in bot_pawn) @@ -242,8 +234,7 @@ salute_list += "tips [our_hat] at " bot_pawn.manual_emote(pick(salute_list) + " [controller.blackboard[target_key]]") - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/salute_authority/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm b/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm index 2f16f88799db..6e6a3da8323f 100644 --- a/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm +++ b/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm @@ -115,14 +115,12 @@ set_movement_target(controller, target) /datum/ai_behavior/execute_clean/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.UnarmedAttack(target, proximity_flag = TRUE) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/execute_clean/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() diff --git a/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm b/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm index 2d2bc27079fd..a913df74c6bb 100644 --- a/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm +++ b/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm @@ -79,11 +79,10 @@ break if(isnull(found_target)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, found_target) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED @@ -111,17 +110,15 @@ var/mob/living/carbon/human/unclean_target = controller.blackboard[target_key] var/mob/living/basic/living_pawn = controller.pawn if(QDELETED(unclean_target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(living_pawn.loc == get_turf(unclean_target)) living_pawn.melee_attack(unclean_target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/frustration_count = controller.blackboard[BB_WASH_FRUSTRATION] controller.set_blackboard_key(BB_WASH_FRUSTRATION, frustration_count + 1) - finish_action(controller, FALSE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/wash_target/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm b/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm index 100366e0b12c..868ebe2a0f45 100644 --- a/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm +++ b/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm @@ -48,7 +48,6 @@ action_cooldown = 2 SECONDS /datum/ai_behavior/find_suitable_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, threshold, heal_type, mode_flags, access_flags) - . = ..() search_range = (mode_flags & MEDBOT_STATIONARY_MODE) ? 1 : initial(search_range) var/list/ignore_keys = controller.blackboard[BB_TEMPORARY_IGNORE_LIST] for(var/mob/living/carbon/human/treatable_target in oview(search_range, controller.pawn)) @@ -66,7 +65,10 @@ controller.set_blackboard_key(BB_PATIENT_TARGET, treatable_target) break - finish_action(controller, controller.blackboard_key_exists(BB_PATIENT_TARGET)) + if(controller.blackboard_key_exists(BB_PATIENT_TARGET)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + else + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/find_suitable_patient/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -86,21 +88,18 @@ 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) - . = ..() var/mob/living/carbon/human/patient = controller.blackboard[target_key] if(QDELETED(patient) || patient.stat == DEAD) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(check_if_healed(patient, threshold, damage_type_healer, access_flags)) - finish_action(controller, TRUE, target_key, healed_target = TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/mob/living/basic/bot/bot_pawn = controller.pawn if(patient.stat >= HARD_CRIT && prob(5)) 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) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED // 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) @@ -159,11 +158,10 @@ speech_to_pick_from += MEDIBOT_VOICED_CHICKEN if(!length(speech_to_pick_from)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED announcement.announce(pick(speech_to_pick_from)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_planning_subtree/find_and_hunt_target/patients_in_crit target_key = BB_PATIENT_IN_CRIT @@ -190,18 +188,15 @@ behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/announce_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key) - . = ..() 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 var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY] if(QDELETED(announcement)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/text_to_announce = "Medical emergency! [living_target] is in critical condition at [get_area(living_target)]!" announcement.announce(text_to_announce, controller.blackboard[BB_RADIO_CHANNEL]) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/announce_patient/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm index 9d2a9760470b..97a8e69473c8 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm @@ -23,13 +23,12 @@ set_movement_target(controller, target) /datum/ai_behavior/enter_exit_hive/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/structure/beebox/current_home = controller.blackboard[target_key] var/mob/living/bee_pawn = controller.pawn var/datum/callback/callback = CALLBACK(bee_pawn, TYPE_PROC_REF(/mob/living/basic/bee, handle_habitation), current_home) callback.Invoke() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/inhabit_hive behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH @@ -42,17 +41,15 @@ set_movement_target(controller, target) /datum/ai_behavior/inhabit_hive/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/structure/beebox/potential_home = controller.blackboard[target_key] var/mob/living/bee_pawn = controller.pawn if(!potential_home.habitable(bee_pawn)) //the house become full before we get to it - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/callback/callback = CALLBACK(bee_pawn, TYPE_PROC_REF(/mob/living/basic/bee, handle_habitation), potential_home) callback.Invoke() - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/inhabit_hive/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm index 20bcd8a69a13..8a900b0308a9 100644 --- a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm @@ -48,13 +48,11 @@ /datum/ai_behavior/find_valid_teleport_location /datum/ai_behavior/find_valid_teleport_location/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range) - . = ..() var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] var/list/possible_turfs = list() if(QDELETED(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/turf/open/potential_turf in oview(hunt_range, target)) //we check for turfs around the target if(potential_turf.is_blocked_turf()) @@ -64,11 +62,10 @@ possible_turfs += potential_turf if(!length(possible_turfs)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(hunting_target_key, pick(possible_turfs)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/hunt_target/use_ability_on_target/demon_teleport hunt_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm index 725dcc09b5ec..53d7e7191ef0 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm @@ -38,8 +38,7 @@ /datum/ai_behavior/hunt_target/unarmed_attack_target/dragon_cannibalise/perform(seconds_per_tick, datum/ai_controller/controller, target_key, attack_key) var/mob/living/target = controller.blackboard[target_key] if(QDELETED(target) || target.stat != DEAD || target.pulledby) //we were too slow - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() /datum/ai_behavior/cannibalize/finish_action(datum/ai_controller/controller, succeeded, target_key) @@ -67,17 +66,14 @@ set_movement_target(controller, target) /datum/ai_behavior/sculpt_statue/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/atom/target = controller.blackboard[target_key] var/mob/living/basic/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.melee_attack(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/sculpt_statue/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -123,8 +119,6 @@ /datum/ai_behavior/set_target_tree /datum/ai_behavior/set_target_tree/perform(seconds_per_tick, datum/ai_controller/controller, tree_key) - . = ..() - var/mob/living_pawn = controller.pawn var/list/possible_trees = list() @@ -134,11 +128,10 @@ possible_trees += possible_tree if(!length(possible_trees)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(tree_key, pick(possible_trees)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/targeted_mob_ability/and_clear_target/burn_trees behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm index 3e0558f89af0..79dae52242a4 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm @@ -43,6 +43,5 @@ /datum/ai_behavior/targeted_mob_ability/brimbeam/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) var/mob/living/target = controller.blackboard[target_key] if (QDELETED(target) || !(get_dir(controller.pawn, target) in GLOB.cardinals) || get_dist(controller.pawn, target) > max_target_distance) - finish_action(controller, succeeded = FALSE, ability_key = ability_key, target_key = target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm index 7509544cfa73..80cd4f3f2a48 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm @@ -37,8 +37,7 @@ if (isliving(target) && !target.has_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled)) var/datum/action/cooldown/using_action = controller.blackboard[BB_GOLIATH_TENTACLES] if (using_action?.IsAvailable()) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() /datum/ai_planning_subtree/targeted_mob_ability/goliath_tentacles @@ -68,20 +67,18 @@ var/scan_range = 3 /datum/ai_behavior/goliath_find_diggable_turf/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/turf/target_turf = controller.blackboard[target_key] if (is_valid_turf(target_turf)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/pawn = controller.pawn var/list/nearby_turfs = RANGE_TURFS(scan_range, pawn) var/turf/check_turf = pick(nearby_turfs) // This isn't an efficient search algorithm but we don't need it to be if (!is_valid_turf(check_turf)) - finish_action(controller, succeeded = FALSE) // Otherwise they won't perform idle wanderin - return + // Otherwise they won't perform idle wanderin + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, check_turf) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// Return true if this is a turf we can dig /datum/ai_behavior/goliath_find_diggable_turf/proc/is_valid_turf(turf/check_turf) @@ -113,13 +110,12 @@ set_movement_target(controller, target_turf) /datum/ai_behavior/goliath_dig/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/turf/target_turf = controller.blackboard[target_key] var/mob/living/basic/basic_mob = controller.pawn if(!basic_mob.CanReach(target_turf)) - return + return AI_BEHAVIOR_DELAY basic_mob.melee_attack(target_turf) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/goliath_dig/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm index faf7a58b65fa..0f6b3574a992 100644 --- a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm @@ -44,11 +44,9 @@ continue living_pawn.befriend(potential_friend) to_chat(potential_friend, span_nicegreen("[living_pawn] looks at you with endearing eyes!")) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index b80d5d6b9f79..c8e294f3e064 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -47,8 +47,8 @@ if (!is_vulnerable) controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, FALSE) if (!controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) - finish_action(controller = controller, succeeded = TRUE, target_key = target_key) // We don't want to clear our target - return + // We don't want to clear our target + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED return ..() /datum/ai_planning_subtree/flee_target/lobster @@ -72,8 +72,7 @@ if (!HAS_TRAIT(target, trait)) continue controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/living/us = controller.pawn if (us.pulling == target) @@ -132,14 +131,12 @@ set_movement_target(controller, current_target) /datum/ai_behavior/grab_fingers/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/atom/current_target = controller.blackboard[target_key] if (QDELETED(current_target)) - return + return AI_BEHAVIOR_DELAY var/mob/living/living_pawn = controller.pawn living_pawn.start_pulling(current_target) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// How far we'll try to go before eating an arm #define FLEE_TO_RANGE 9 @@ -159,14 +156,18 @@ if (QDELETED(current_target)) set_movement_target(controller, get_turf(controller.pawn)) return - target_step_away(controller, current_target, target_key) + var/perform_flags = target_step_away(controller, current_target, target_key) + if (perform_flags & AI_BEHAVIOR_SUCCEEDED) + finish_action(controller, TRUE, target_key) + else if(perform_flags & AI_BEHAVIOR_FAILED) + finish_action(controller, FALSE, target_key) /// Find the next step to take away from the current target /datum/ai_behavior/hoard_fingers/proc/target_step_away(datum/ai_controller/controller, atom/current_target, target_key) var/turf/next_step = get_step_away(controller.pawn, current_target) if (!isnull(next_step) && !next_step.is_blocked_turf(exclude_mobs = TRUE)) set_movement_target(controller, next_step) - return + return NONE var/list/all_dirs = GLOB.alldirs.Copy() all_dirs -= get_dir(controller.pawn, next_step) all_dirs -= get_dir(controller.pawn, current_target) @@ -175,37 +176,37 @@ next_step = get_step(controller.pawn, dir) if (!isnull(next_step) && !next_step.is_blocked_turf(exclude_mobs = TRUE)) set_movement_target(controller, next_step) - return - finish_action(controller, succeeded = FALSE, target_key = target_key) - return + return NONE + return AI_BEHAVIOR_FAILED /datum/ai_behavior/hoard_fingers/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/current_patience = controller.blackboard[patience_key] + 1 if (current_patience >= MAX_LOBSTROSITY_PATIENCE) - eat_fingers(controller, target_key) - return + if(eat_fingers(controller, target_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(patience_key, current_patience) var/mob/living/living_pawn = controller.pawn if (isnull(living_pawn.pulling)) - finish_action(controller, succeeded = FALSE, target_key = target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/atom/current_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] if (QDELETED(current_target) || !can_see(controller.pawn, current_target, FLEE_TO_RANGE)) - eat_fingers(controller, target_key) - return - target_step_away(controller, current_target, target_key) + if(eat_fingers(controller, target_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + if(target_step_away(controller, current_target, target_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /// Finally consume those delicious digits /datum/ai_behavior/hoard_fingers/proc/eat_fingers(datum/ai_controller/controller, target_key) var/mob/living/basic/living_pawn = controller.pawn var/atom/fingers = controller.blackboard[target_key] if (QDELETED(fingers) || living_pawn.pulling != fingers) - finish_action(controller, succeeded = FALSE, target_key = target_key) - return + return AI_BEHAVIOR_FAILED living_pawn.melee_attack(fingers) - finish_action(controller, succeeded = TRUE, target_key = target_key) + return AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/hoard_fingers/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm index 504166930614..eeefc7a8b5c7 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm @@ -117,15 +117,13 @@ GLOBAL_LIST_INIT(mook_commands, list( /datum/ai_behavior/find_village /datum/ai_behavior/find_village/perform(seconds_per_tick, datum/ai_controller/controller, village_key) - . = ..() var/obj/effect/landmark/home_marker = locate(/obj/effect/landmark/mook_village) in GLOB.landmarks_list if(isnull(home_marker)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(village_key, home_marker) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///explore the lands away from the village to look for ore /datum/ai_planning_subtree/wander_away_from_village @@ -190,8 +188,7 @@ GLOBAL_LIST_INIT(mook_commands, list( return return_turf /datum/ai_behavior/wander/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_planning_subtree/mine_walls/mook find_wall_behavior = /datum/ai_behavior/find_mineral_wall/mook @@ -367,23 +364,20 @@ GLOBAL_LIST_INIT(mook_commands, list( action_cooldown = 5 SECONDS /datum/ai_behavior/issue_commands/perform(seconds_per_tick, datum/ai_controller/controller, target_key, command_path) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/atom/target = controller.blackboard[target_key] if(isnull(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/pet_command/to_command = locate(command_path) in GLOB.mook_commands if(isnull(to_command)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/issue_command = pick(to_command.speech_commands) living_pawn.say(issue_command, forced = "controller") living_pawn._pointed(target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///find an ore, only pick it up when a mook brings it close to us diff --git a/code/modules/mob/living/basic/minebots/minebot_ai.dm b/code/modules/mob/living/basic/minebots/minebot_ai.dm index 91b8500300ac..42b284d9d92b 100644 --- a/code/modules/mob/living/basic/minebots/minebot_ai.dm +++ b/code/modules/mob/living/basic/minebots/minebot_ai.dm @@ -34,20 +34,17 @@ action_cooldown = 2 MINUTES /datum/ai_behavior/send_sos_message/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/carbon/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(QDELETED(target) || is_station_level(target.z)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/turf/target_turf = get_turf(target) var/obj/item/implant/radio/radio_implant = locate(/obj/item/implant/radio) in living_pawn.contents if(!radio_implant) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/message = "ALERT, [target] in need of help at coordinates: [target_turf.x], [target_turf.y], [target_turf.z]!" radio_implant.radio.talk_into(living_pawn, message, RADIO_CHANNEL_SUPPLY) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/send_sos_message/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -58,16 +55,50 @@ operational_datums = null ranged_attack_behavior = /datum/ai_behavior/basic_ranged_attack/minebot -/datum/ai_behavior/basic_ranged_attack/minebot - behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT - avoid_friendly_fire = TRUE - /datum/ai_planning_subtree/basic_ranged_attack_subtree/minebot/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target)) + return var/mob/living/living_pawn = controller.pawn - if(!(living_pawn.istate & ISTATE_HARM)) //we are not on attack mode + if(!living_pawn.combat_mode) //we are not on attack mode return + controller.queue_behavior(ranged_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_planning_subtree/minebot_maintain_distance/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target)) + return + var/mob/living/living_pawn = controller.pawn + if(get_dist(living_pawn, target) <= controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE]) + controller.queue_behavior(/datum/ai_behavior/run_away_from_target/run_and_shoot/minebot, BB_BASIC_MOB_CURRENT_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_behavior/run_away_from_target/run_and_shoot/minebot + +/datum/ai_behavior/run_away_from_target/run_and_shoot/minebot/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) + if(!controller.blackboard[BB_MINEBOT_PLANT_MINES]) + return ..() + var/datum/action/cooldown/mine_ability = controller.blackboard[BB_MINEBOT_LANDMINE_ABILITY] + mine_ability?.Trigger() return ..() +/datum/ai_behavior/basic_ranged_attack/minebot + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + avoid_friendly_fire = TRUE + ///if our target is closer than this distance, finish action + var/minimum_distance = 3 + +/datum/ai_behavior/basic_ranged_attack/minebot/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) + . = ..() + minimum_distance = controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE] ? controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE] : initial(minimum_distance) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + var/mob/living/living_pawn = controller.pawn + if(get_dist(living_pawn, target) <= minimum_distance) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + ///mine walls if we are on automated mining mode /datum/ai_planning_subtree/minebot_mining/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) if(!controller.blackboard[BB_AUTOMATED_MINING]) @@ -100,24 +131,20 @@ set_movement_target(controller, target) /datum/ai_behavior/minebot_mine_turf/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/turf/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(check_obstacles_in_path(controller, target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(!(living_pawn.istate & ISTATE_HARM)) living_pawn.set_combat_mode(TRUE) living_pawn.RangedAttack(target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/minebot_mine_turf/proc/check_obstacles_in_path(datum/ai_controller/controller, turf/target) var/mob/living/source = controller.pawn diff --git a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm index ccc3ef92f6ea..b5b34e30cad5 100644 --- a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm +++ b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm @@ -47,25 +47,21 @@ set_movement_target(controller, target) /datum/ai_behavior/perch_on_target/perform(seconds_per_tick, datum/ai_controller/controller, target_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 var/mob/living/basic/parrot/living_pawn = controller.pawn if(!ishuman(target)) living_pawn.start_perching(target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED if(!check_human_conditions(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.start_perching(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/perch_on_target/proc/check_human_conditions(mob/living/living_human) if(living_human.stat == DEAD || LAZYLEN(living_human.buckled_mobs) >= living_human.max_buckled_mobs) diff --git a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm index d1488a60b3bb..493d67cbca8c 100644 --- a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm +++ b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm @@ -45,6 +45,6 @@ speaking_pawn.say(modified_speech, forced = "AI Controller") if(speech_sound) playsound(speaking_pawn, speech_sound, 80, vary = TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED #undef HAS_CHANNEL_PREFIX diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm index 9e767bab3af1..71017bd2207a 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm @@ -21,8 +21,7 @@ if (QDELETED(using_action)) return ..() if (!controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETING] && using_action.IsAvailable()) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() /** diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm index 27fdb25ee22b..9458877af7fe 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm @@ -47,10 +47,8 @@ blackboard_points -= migration_point if(get_dist(controller.pawn, migration_point) > CARP_DESTINATION_SEARCH_RANGE) controller.set_blackboard_key(target_key, migration_point) - finish_action(controller, succeeded = TRUE) - return - - finish_action(controller, succeeded = FALSE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED #undef CARP_DESTINATION_SEARCH_RANGE #undef CARP_PORTAL_SEARCH_RANGE diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm index fc6997896b0d..84b96ae3ce40 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm @@ -52,21 +52,19 @@ return controller.blackboard[ability_key] && controller.blackboard[target_key] /datum/ai_behavior/make_carp_rift/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) - . = ..() var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = controller.blackboard[ability_key] var/atom/target = controller.blackboard[target_key] if (!validate_target(controller, target, ability)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/turf/target_destination = find_target_turf(controller, target, ability) if (!target_destination) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED - var/result = ability.InterceptClickOn(controller.pawn, null, target_destination) - finish_action(controller, result, ability_key, target_key) + if(ability.InterceptClickOn(controller.pawn, null, target_destination)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /// Return true if your target is valid for the action /datum/ai_behavior/make_carp_rift/proc/validate_target(datum/ai_controller/controller, atom/target, datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability) diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm index 57ea39c94dd5..d8cd8686d393 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm @@ -1,14 +1,11 @@ /datum/ai_behavior/find_the_blind /datum/ai_behavior/find_the_blind/perform(seconds_per_tick, datum/ai_controller/controller, blind_key, threshold_key) - . = ..() - var/mob/living_pawn = controller.pawn var/list/blind_list = list() var/eye_damage_threshold = controller.blackboard[threshold_key] if(!eye_damage_threshold) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/mob/living/carbon/blind in oview(9, living_pawn)) var/obj/item/organ/internal/eyes/eyes = blind.get_organ_slot(ORGAN_SLOT_EYES) if(isnull(eyes)) @@ -18,11 +15,10 @@ blind_list += blind if(!length(blind_list)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(blind_key, pick(blind_list)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/heal_eye_damage behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH @@ -41,13 +37,12 @@ var/mob/living/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/obj/item/organ/internal/eyes/eyes = target.get_organ_slot(ORGAN_SLOT_EYES) var/datum/callback/callback = CALLBACK(living_pawn, TYPE_PROC_REF(/mob/living/basic/eyeball, heal_eye_damage), target, eyes) callback.Invoke() - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/heal_eye_damage/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -77,17 +72,18 @@ var/mob/living/target = controller.blackboard[target_key] if(QDELETED(ability) || QDELETED(target)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/direction_to_compare = get_dir(target, controller.pawn) var/target_direction = target.dir if(direction_to_compare != target_direction) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/result = ability.InterceptClickOn(controller.pawn, null, target) - finish_action(controller, result, ability_key, target_key) + if(result == TRUE) + return AI_BEHAVIOR_INSTANT + else + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED /datum/ai_behavior/hunt_target/unarmed_attack_target/carrot hunt_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm index 28cffa4ed8e3..7db7a8913fa3 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm @@ -30,19 +30,16 @@ /datum/ai_behavior/relay_message/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/mob/living/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/message_relayed = "" for(var/i in 1 to length_of_message) message_relayed += prob(50) ? "1" : "0" living_pawn.say(message_relayed, forced = "AI Controller") - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/relay_message/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm index 25fcb3b7a4cf..8993df452e3a 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm @@ -73,19 +73,17 @@ var/scan_range = 3 /datum/ai_behavior/find_unwebbed_turf/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/spider = controller.pawn var/atom/current_target = controller.blackboard[target_key] if (current_target && !(locate(/obj/structure/spider/stickyweb) in current_target)) - finish_action(controller, succeeded = FALSE) // Already got a target - return + // Already got a target + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.clear_blackboard_key(target_key) var/turf/our_turf = get_turf(spider) if (is_valid_web_turf(our_turf)) controller.set_blackboard_key(target_key, our_turf) - finish_action(controller, succeeded = TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/list/turfs_by_range = list() for (var/i in 1 to scan_range) @@ -101,11 +99,10 @@ final_turfs = turfs_by_range[turf_list] break if (!length(final_turfs)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, pick(final_turfs)) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_unwebbed_turf/proc/is_valid_web_turf(turf/target_turf, mob/living/spider) if (locate(/obj/structure/spider/stickyweb) in target_turf) @@ -145,9 +142,10 @@ return ..() /datum/ai_behavior/spin_web/perform(seconds_per_tick, datum/ai_controller/controller, action_key, target_key) - . = ..() var/datum/action/cooldown/web_action = controller.blackboard[action_key] - finish_action(controller, succeeded = web_action?.Trigger(), action_key = action_key, target_key = target_key) + if(web_action?.Trigger()) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/spin_web/finish_action(datum/ai_controller/controller, succeeded, action_key, target_key) controller.clear_blackboard_key(target_key) diff --git a/code/modules/mob/living/basic/trader/trader_ai.dm b/code/modules/mob/living/basic/trader/trader_ai.dm index 5f447ab3229a..83a298a22935 100644 --- a/code/modules/mob/living/basic/trader/trader_ai.dm +++ b/code/modules/mob/living/basic/trader/trader_ai.dm @@ -61,19 +61,16 @@ return !QDELETED(target) /datum/ai_behavior/setup_shop/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - //We lost track of our costumer or our ability, abort if(!controller.blackboard_key_exists(target_key) || !controller.blackboard_key_exists(BB_SETUP_SHOP)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/action/setup_shop/shop = controller.blackboard[BB_SETUP_SHOP] shop.Trigger() controller.clear_blackboard_key(BB_FIRST_CUSTOMER) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/idle_behavior/idle_random_walk/not_while_on_target/trader target_key = BB_SHOP_SPOT diff --git a/tgstation.dme b/tgstation.dme index 3e0ad3749d93..d77e333a6610 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -955,6 +955,7 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\find_parent.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\nearest_targeting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\pick_up_item.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\pull_target.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\run_away_from_target.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\set_travel_destination.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\step_towards_turf.dm"