Skip to content

Commit

Permalink
code cleanup, additional subtrees
Browse files Browse the repository at this point in the history
  • Loading branch information
crix870 committed Jan 3, 2025
1 parent 53f034d commit 95762b4
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 13 deletions.
5 changes: 0 additions & 5 deletions code/__DEFINES/ai/creatures.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,3 @@

#define BB_DRAGON_ADULTBREATH "BB"


//Chicken egglaying

#define BB_CHICKEN_LAYEGG

19 changes: 16 additions & 3 deletions code/__DEFINES/ai/hostile.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
//Hunting defines
#define SUCCESFUL_HUNT_COOLDOWN 5 SECONDS

///Hunting BB keys
#define BB_CURRENT_HUNTING_TARGET "BB_current_hunting_target"
#define BB_HUNTING_COOLDOWN "BB_HUNTING_COOLDOWN"

///Basic Mob Keys

Expand All @@ -59,3 +56,19 @@

///List of mobs who have damaged us
#define BB_BASIC_MOB_RETALIATE_LIST "BB_basic_mob_shitlist"

///Blackboard key for a whitelist typecache of "things we can target while trying to move"
#define BB_OBSTACLE_TARGETING_WHITELIST "BB_targeting_whitelist"

///Hunting BB keys
#define BB_CURRENT_HUNTING_TARGET "BB_current_hunting_target"
#define BB_HUNTING_COOLDOWN "BB_hunting_cooldown"

///Travel BB key
#define BB_TRAVEL_DESTINATION "BB_travel_destination"

///Reinforcements BB key
#define BB_BASIC_MOB_REINFORCEMENT_TARGET "BB_basic_mob_reinforcement_target"
#define BB_REINFORCEMENTS_SAY "BB_basic_mob_reinforcement_say"
#define BB_REINFORCEMENTS_EMOTE "BB_basic_mob_reinforcement_emote"
#define BB_BASIC_MOB_REINFORCEMENTS_COOLDOWN "BB_basic_mob_reinforcement_cooldown"
2 changes: 2 additions & 0 deletions code/__DEFINES/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define TEXT_EAST "[EAST]"
#define TEXT_WEST "[WEST]"

///Returns true if the dir is diagonal, false otherwise
#define ISDIAGONALDIR(d) (d&(d-1))

//Human Overlays Indexes/////////
#define MUTATIONS_LAYER 49 //mutations. Tk headglows, cold resistance glow, etc
Expand Down
52 changes: 52 additions & 0 deletions code/datums/ai/behaviors/travel_towards.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* # Travel Towards
* Moves towards the atom in the passed blackboard key.
* Planning continues during this action so it can be interrupted by higher priority actions.
*/
/datum/ai_behavior/travel_towards
required_distance = 0
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
/// If true we will get rid of our target on completion
var/clear_target = FALSE
///should we use a different movement type?
var/new_movement_type

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

/datum/ai_behavior/travel_towards/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
finish_action(controller, TRUE, target_key)

/datum/ai_behavior/travel_towards/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
if (clear_target)
controller.clear_blackboard_key(target_key)
if(new_movement_type)
controller.change_ai_movement_type(initial(controller.ai_movement))

/datum/ai_behavior/travel_towards/stop_on_arrival
clear_target = TRUE

/**
* # Travel Towards Atom
* Travel towards an atom you pass directly from the controller rather than a blackboard key.
* You might need to do this to avoid repeating some checks in both a controller and an action.
*/
/datum/ai_behavior/travel_towards_atom
required_distance = 0
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT

/datum/ai_behavior/travel_towards_atom/setup(datum/ai_controller/controller, atom/target_atom)
. = ..()
if(isnull(target_atom))
return FALSE
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)
6 changes: 4 additions & 2 deletions code/datums/ai/controllers/orc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
ai_movement = /datum/ai_movement/basic_avoidance

blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic()
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(),
BB_REINFORCEMENTS_SAY = "Intruders!"
)

planning_subtrees = list(
/datum/ai_planning_subtree/simple_find_target/closest,
/datum/ai_planning_subtree/basic_melee_attack_subtree,
/datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic
/datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic,
/datum/ai_planning_subtree/call_reinforcements
)

idle_behavior = /datum/idle_behavior/idle_random_walk
Expand Down
82 changes: 81 additions & 1 deletion code/datums/ai/subtrees/attack_obstacle_in_path.dm
Original file line number Diff line number Diff line change
@@ -1 +1,81 @@
//todo
/// If there's something between us and our target then we need to queue a behaviour to make it not be there
/datum/ai_planning_subtree/attack_obstacle_in_path
/// Blackboard key containing current target
var/target_key = BB_BASIC_MOB_CURRENT_TARGET
/// The action to execute, extend to add a different cooldown or something
var/attack_behaviour = /datum/ai_behavior/attack_obstructions

/datum/ai_planning_subtree/attack_obstacle_in_path/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
. = ..()
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
return

var/turf/next_step = get_step_towards(controller.pawn, target)
if (!next_step.is_blocked_turf(exclude_mobs = TRUE, source_atom = controller.pawn))
return

controller.queue_behavior(attack_behaviour, target_key)
// Don't cancel future planning, maybe we can move now

/// Something is in our way, get it outta here
/datum/ai_behavior/attack_obstructions
action_cooldown = 2 SECONDS
/// If we should attack walls, be prepared for complaints about breaches
var/can_attack_turfs = FALSE
/// For if you want your mob to be able to attack dense objects
var/can_attack_dense_objects = FALSE

/datum/ai_behavior/attack_obstructions/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
var/mob/living/simple_animal/basic_mob = controller.pawn
var/atom/target = controller.blackboard[target_key]

if (QDELETED(target))
finish_action(controller, succeeded = FALSE)
return

var/turf/next_step = get_step_towards(basic_mob, target)
var/dir_to_next_step = get_dir(basic_mob, next_step)
// If moving diagonally we need to punch both ways, or more accurately the one we are blocked in
var/list/dirs_to_move = list()
if (ISDIAGONALDIR(dir_to_next_step))
for(var/direction in GLOB.cardinals)
if(direction & dir_to_next_step)
dirs_to_move += direction
else
dirs_to_move += dir_to_next_step

for (var/direction in dirs_to_move)
if (attack_in_direction(controller, basic_mob, direction))
return
finish_action(controller, succeeded = TRUE)

/datum/ai_behavior/attack_obstructions/proc/attack_in_direction(datum/ai_controller/controller, mob/living/simple_animal/basic_mob, direction)
var/turf/next_step = get_step(basic_mob, direction)
if (!next_step.is_blocked_turf(exclude_mobs = TRUE, source_atom = controller.pawn))
return FALSE

for (var/obj/object as anything in next_step.contents)
if (!can_smash_object(basic_mob, object))
continue
basic_mob.ClickOn(object, list())
return TRUE

if (can_attack_turfs)
basic_mob.ClickOn(next_step)
return TRUE
return FALSE

/datum/ai_behavior/attack_obstructions/proc/can_smash_object(mob/living/simple_animal/basic_mob, obj/object)
if (!object.density && !can_attack_dense_objects)
return FALSE
if (object.IsObscured())
return FALSE
if (basic_mob.see_invisible < object.invisibility)
return FALSE
var/list/whitelist = basic_mob.ai_controller.blackboard[BB_OBSTACLE_TARGETING_WHITELIST]
if(whitelist && !is_type_in_typecache(object, whitelist))
return FALSE

return TRUE // It's in our way, let's get it out of our way
50 changes: 50 additions & 0 deletions code/datums/ai/subtrees/call_reinforcements.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#define REINFORCEMENTS_COOLDOWN (30 SECONDS)

/// Calls all nearby mobs that share a faction to give backup in combat
/datum/ai_planning_subtree/call_reinforcements
/// Blackboard key containing something to say when calling reinforcements (takes precedence over emotes)
var/say_key = BB_REINFORCEMENTS_SAY
/// Blackboard key containing an emote to perform when calling reinforcements
var/emote_key = BB_REINFORCEMENTS_EMOTE
/// Reinforcement-calling behavior to use
var/call_type = /datum/ai_behavior/call_reinforcements

/datum/ai_planning_subtree/call_reinforcements/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
. = ..()
if (!decide_to_call(controller) || controller.blackboard[BB_BASIC_MOB_REINFORCEMENTS_COOLDOWN] > world.time)
return

var/call_say = controller.blackboard[BB_REINFORCEMENTS_SAY]
var/call_emote = controller.blackboard[BB_REINFORCEMENTS_EMOTE]

if(!isnull(call_say))
controller.queue_behavior(/datum/ai_behavior/perform_speech, call_say)
else if(!isnull(call_emote))
controller.queue_behavior(/datum/ai_behavior/perform_emote, call_emote)
else
controller.queue_behavior(/datum/ai_behavior/perform_emote, "cries for help!")

controller.queue_behavior(call_type)

/// Decides when to call reinforcements, can be overridden for alternate behavior
/datum/ai_planning_subtree/call_reinforcements/proc/decide_to_call(datum/ai_controller/controller)
return controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET) && istype(controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET], /mob)

/// Call out to all mobs in the specified range for help
/datum/ai_behavior/call_reinforcements
/// Range to call reinforcements from
var/reinforcements_range = 12

/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(faction_check(pawn_mob, other_mob) && !isnull(other_mob.ai_controller))
// Add our current target to their retaliate list so that they'll attack our aggressor
other_mob.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET])
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)
finish_action(controller, TRUE)
return //AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED

#undef REINFORCEMENTS_COOLDOWN
21 changes: 21 additions & 0 deletions code/datums/ai/subtrees/travel_to_point.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// Simply walk to a location
/datum/ai_planning_subtree/travel_to_point
/// Blackboard key where we travel a place we walk to
var/location_key = BB_TRAVEL_DESTINATION
/// What do we do in order to travel
var/travel_behaviour = /datum/ai_behavior/travel_towards

/datum/ai_planning_subtree/travel_to_point/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
. = ..()
var/atom/target = controller.blackboard[location_key]
if (QDELETED(target))
return
controller.queue_behavior(travel_behaviour, location_key)
return SUBTREE_RETURN_FINISH_PLANNING


/datum/ai_planning_subtree/travel_to_point/and_clear_target
travel_behaviour = /datum/ai_behavior/travel_towards/stop_on_arrival

/datum/ai_planning_subtree/travel_to_point/and_clear_target/reinforce
location_key = BB_BASIC_MOB_REINFORCEMENT_TARGET
6 changes: 4 additions & 2 deletions roguetown.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1991,6 +1991,8 @@
#include "code\datums\ai\behaviors\resist.dm"
#include "code\datums\ai\behaviors\recuperate.dm"
#include "code\datums\ai\behaviors\run_from_target.dm"
#include "code\datums\ai\behaviors\travel_towards.dm"

#include "code\datums\ai\behaviors\use_in_hand.dm"
#include "code\datums\ai\behaviors\use_on_object.dm"
#include "code\datums\ai\behaviors\use_targeted_ability.dm"
Expand Down Expand Up @@ -2023,12 +2025,12 @@

#include "code\datums\ai\subtrees\attack_adjacent_target.dm"
#include "code\datums\ai\subtrees\attack_obstacle_in_path.dm"
#include "code\datums\ai\subtrees\call_reinforcements.dm"
#include "code\datums\ai\subtrees\find_food.dm"
#include "code\datums\ai\subtrees\flee_nearest_target.dm"
#include "code\datums\ai\subtrees\flee_target.dm"
#include "code\datums\ai\subtrees\eat_body.dm"
#include "code\datums\ai\subtrees\eat_food.dm"

#include "code\datums\ai\subtrees\move_to_cardinal.dm"
#include "code\datums\ai\subtrees\melee_spacing.dm"
#include "code\datums\ai\subtrees\random_speech.dm"
Expand All @@ -2037,7 +2039,7 @@
#include "code\datums\ai\subtrees\simple_find_target.dm"
#include "code\datums\ai\subtrees\simple_melee_subtree.dm"
#include "code\datums\ai\subtrees\targeted_ability_use.dm"

#include "code\datums\ai\subtrees\travel_to_point.dm"

#include "code\datums\ai\targetting_datum\simple_targetting_datum.dm"
#include "code\datums\ai\targetting_datum\simple_targetting_allow_item.dm"
Expand Down

0 comments on commit 95762b4

Please sign in to comment.