diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 7ed8518e66f..079b052853f 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -85,6 +85,11 @@ ///List of mobs who have damaged us #define BB_BASIC_MOB_RETALIATE_LIST "BB_basic_mob_shitlist" +/// Chance to randomly acquire a new target +#define BB_RANDOM_AGGRO_CHANCE "BB_random_aggro_chance" +/// Chance to randomly drop all of our targets +#define BB_RANDOM_DEAGGRO_CHANCE "BB_random_deaggro_chance" + /// Flag to set on if you want your mob to STOP running away #define BB_BASIC_MOB_STOP_FLEEING "BB_basic_stop_fleeing" @@ -102,7 +107,9 @@ #define MOD_AI_RANGE 200 ///should we skip the faction check for the targetting datum? -#define BB_BASIC_MOB_SKIP_FACTION_CHECK "BB_basic_mob_skip_faction_check" +#define BB_ALWAYS_IGNORE_FACTION "BB_always_ignore_factions" +///are we in some kind of temporary state of ignoring factions when targetting? can result in volatile results if multiple behaviours touch this +#define BB_TEMPORARILY_IGNORE_FACTION "BB_temporarily_ignore_factions" ///currently only used by clowns, a list of what can the mob speak randomly #define BB_BASIC_MOB_SPEAK_LINES "BB_speech_lines" diff --git a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm new file mode 100644 index 00000000000..47f4155ac45 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm @@ -0,0 +1,69 @@ +/// Add or remove people to our retaliation shitlist just on an arbitrary whim +/datum/ai_planning_subtree/capricious_retaliate + /// Blackboard key which tells us how to select valid targets + var/targetting_datum_key = BB_TARGETTING_DATUM + /// Whether we should skip checking faction for our decision + var/ignore_faction = TRUE + +/datum/ai_planning_subtree/capricious_retaliate/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + controller.queue_behavior(/datum/ai_behavior/capricious_retaliate, targetting_datum_key, ignore_faction) + +/// Add or remove people to our retaliation shitlist just on an arbitrary whim +/datum/ai_behavior/capricious_retaliate + action_cooldown = 1 SECONDS + +/datum/ai_behavior/capricious_retaliate/perform(seconds_per_tick, datum/ai_controller/controller, targetting_datum_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 + 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 + + 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 + + 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_targetting(controller, pawn, ignore_faction) + return + + var/datum/targetting_datum/target_helper = controller.blackboard[targetting_datum_key] + + var/mob/living/final_target = null + if (ignore_faction) + controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, TRUE) + while (isnull(final_target) && length(potential_targets)) + var/mob/living/test_target = pick_n_take(potential_targets) + if (target_helper.can_attack(pawn, test_target, vision_range = aggro_range)) + final_target = test_target + + if (isnull(final_target)) + failed_targetting(controller, pawn, ignore_faction) + return + + 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) + +/// Called if we try but fail to target something +/datum/ai_behavior/capricious_retaliate/proc/failed_targetting(datum/ai_controller/controller, atom/pawn, ignore_faction) + finish_action(controller, FALSE, ignore_faction) + 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) + . = ..() + if (succeeded || !ignore_faction) + return + var/usually_ignores_faction = controller.blackboard[BB_ALWAYS_IGNORE_FACTION] || FALSE + controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, usually_ignores_faction) 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 6133759183d..701f911d273 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -41,23 +41,27 @@ if(!targetting_datum) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") + var/list/shitlist = controller.blackboard[shitlist_key] + var/atom/existing_target = controller.blackboard[target_key] + + if (!check_faction) + controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, TRUE) + + if (!QDELETED(existing_target) && (locate(existing_target) in shitlist) && targetting_datum.can_attack(living_mob, existing_target, vision_range)) + finish_action(controller, succeeded = TRUE, check_faction = check_faction) + return var/list/enemies_list = list() - - for(var/mob/living/potential_target as anything in controller.blackboard[shitlist_key]) - if(!targetting_datum.can_attack(living_mob, potential_target, vision_range, check_faction)) + for(var/mob/living/potential_target as anything in shitlist) + if(!targetting_datum.can_attack(living_mob, potential_target, vision_range)) continue enemies_list += potential_target - if(!length(enemies_list)) + controller.clear_blackboard_key(target_key) finish_action(controller, succeeded = FALSE, check_faction = check_faction) return - if (controller.blackboard[target_key] in enemies_list) // Don't bother changing - finish_action(controller, succeeded = TRUE, check_faction = check_faction) - return - var/atom/new_target = pick_final_target(controller, enemies_list) controller.set_blackboard_key(target_key, new_target) @@ -72,9 +76,9 @@ /datum/ai_behavior/target_from_retaliate_list/proc/pick_final_target(datum/ai_controller/controller, list/enemies_list) return pick(enemies_list) - -/datum/ai_behavior/target_from_retaliate_list/finish_action(datum/ai_controller/controller, succeeded, target_key, check_faction) +/datum/ai_behavior/target_from_retaliate_list/finish_action(datum/ai_controller/controller, succeeded, check_faction) . = ..() - if(check_faction) + if (succeeded || check_faction) return - controller.set_blackboard_key(BB_BASIC_MOB_SKIP_FACTION_CHECK, succeeded) + var/usually_ignores_faction = controller.blackboard[BB_ALWAYS_IGNORE_FACTION] || FALSE + controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, usually_ignores_faction) diff --git a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm index 978d7b7f8a7..bc4a554bc02 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm @@ -20,7 +20,7 @@ ///Whether we care for seeing the target or not var/ignore_sight = FALSE -/datum/targetting_datum/basic/can_attack(mob/living/living_mob, atom/the_target, vision_range, check_faction = TRUE) +/datum/targetting_datum/basic/can_attack(mob/living/living_mob, atom/the_target, vision_range) var/datum/ai_controller/basic_controller/our_controller = living_mob.ai_controller if(isnull(our_controller)) @@ -52,8 +52,7 @@ if(isliving(the_target)) //Targeting vs living mobs var/mob/living/living_target = the_target - var/bypass_faction_check = !check_faction || our_controller.blackboard[BB_BASIC_MOB_SKIP_FACTION_CHECK] - if(faction_check(living_mob, living_target) && !bypass_faction_check) + if(faction_check(our_controller, living_mob, living_target)) return FALSE if(living_target.stat > stat_attack) return FALSE @@ -79,26 +78,21 @@ return FALSE /// Returns true if the mob and target share factions -/datum/targetting_datum/basic/proc/faction_check(mob/living/living_mob, mob/living/the_target) +/datum/targetting_datum/basic/proc/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) + if (controller.blackboard[BB_ALWAYS_IGNORE_FACTION] || controller.blackboard[BB_TEMPORARILY_IGNORE_FACTION]) + return FALSE return living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly) /// Subtype more forgiving for items. /// Careful, this can go wrong and keep a mob hyper-focused on an item it can't lose aggro on /datum/targetting_datum/basic/allow_items -/datum/targetting_datum/basic/allow_items/can_attack(mob/living/living_mob, atom/the_target) +/datum/targetting_datum/basic/allow_items/can_attack(mob/living/living_mob, atom/the_target, vision_range) . = ..() if(isitem(the_target)) // trust fall exercise return TRUE -/// Subtype which doesn't care about faction -/// Mobs which retaliate but don't otherwise target seek should just attack anything which annoys them -/datum/targetting_datum/basic/ignore_faction - -/datum/targetting_datum/basic/ignore_faction/faction_check(mob/living/living_mob, mob/living/the_target) - return FALSE - /// Subtype which searches for mobs of a size relative to ours /datum/targetting_datum/basic/of_size /// If true, we will return mobs which are smaller than us. If false, larger. @@ -106,7 +100,7 @@ /// If true, we will return mobs which are the same size as us. var/inclusive = TRUE -/datum/targetting_datum/basic/of_size/can_attack(mob/living/owner, atom/target) +/datum/targetting_datum/basic/of_size/can_attack(mob/living/owner, atom/target, vision_range) if(!isliving(target)) return FALSE . = ..() diff --git a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm b/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm index 3556e11900f..f1bd411fd29 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm @@ -6,7 +6,7 @@ var/attack_closed_turf = FALSE ///Returns true or false depending on if the target can be attacked by the mob -/datum/targetting_datum/not_friends/can_attack(mob/living/living_mob, atom/target) +/datum/targetting_datum/not_friends/can_attack(mob/living/living_mob, atom/target, vision_range) if (!target) return FALSE if (attack_closed_turf) @@ -43,7 +43,7 @@ /// Subtype that allows us to target items while deftly avoiding attacking our allies. Be careful when it comes to targetting items as an AI could get trapped targetting something it can't destroy. /datum/targetting_datum/basic/not_friends/allow_items -/datum/targetting_datum/basic/not_friends/allow_items/can_attack(mob/living/living_mob, atom/the_target) +/datum/targetting_datum/basic/not_friends/allow_items/can_attack(mob/living/living_mob, atom/the_target, vision_range) . = ..() if(isitem(the_target)) // trust fall exercise diff --git a/code/datums/ai/basic_mobs/targetting_datums/with_object.dm b/code/datums/ai/basic_mobs/targetting_datums/with_object.dm index 039027b6aa5..91e99bb4a22 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/with_object.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/with_object.dm @@ -23,7 +23,7 @@ src.object_type_path = object_type_path ///Returns true or false depending on if the target can be attacked by the mob -/datum/targetting_datum/basic/holding_object/can_attack(mob/living/living_mob, atom/target, vision_range, check_faction = FALSE) +/datum/targetting_datum/basic/holding_object/can_attack(mob/living/living_mob, atom/target, vision_range) if (object_type_path == null) return FALSE // no op if(!ismob(target)) diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index eb09506a282..dc941ec33fa 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -9,6 +9,7 @@ /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 var/find_this_thing = search_tactic(controller, locate_path, search_range) if(find_this_thing) diff --git a/code/datums/elements/ai_flee_while_injured.dm b/code/datums/elements/ai_flee_while_injured.dm index 0bbc08eb88b..eca709dbee5 100644 --- a/code/datums/elements/ai_flee_while_injured.dm +++ b/code/datums/elements/ai_flee_while_injured.dm @@ -19,6 +19,7 @@ src.stop_fleeing_at = stop_fleeing_at src.start_fleeing_below = start_fleeing_below RegisterSignal(target, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_health_changed)) + on_health_changed(target) /datum/element/ai_flee_while_injured/Detach(datum/source) . = ..() @@ -28,7 +29,7 @@ /datum/element/ai_flee_while_injured/proc/on_health_changed(mob/living/source) SIGNAL_HANDLER - if (!source.ai_controller) + if (isnull(source.ai_controller)) return var/current_health_percentage = source.health / source.maxHealth 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 017eac3cb51..3c8b018cc93 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 @@ -85,7 +85,7 @@ /datum/targetting_datum/basic/bee -/datum/targetting_datum/basic/bee/can_attack(mob/living/owner, atom/target) +/datum/targetting_datum/basic/bee/can_attack(mob/living/owner, atom/target, vision_range) if(!isliving(target)) return FALSE . = ..() diff --git a/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm b/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm index 89f5174f15e..99ff6b52748 100644 --- a/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm +++ b/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm @@ -88,8 +88,6 @@ GLOBAL_VAR_INIT(chicken_count, 0) planning_subtrees = list( /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, /datum/ai_planning_subtree/flee_target, - /datum/ai_planning_subtree/target_retaliate, - /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/random_speech/chicken, ) diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm index cdfb0868f9e..7db589334ff 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm @@ -62,7 +62,7 @@ ///moonicorns will not attack people holding something that could tame them. /datum/targetting_datum/basic/allow_items/moonicorn -/datum/targetting_datum/basic/allow_items/moonicorn/can_attack(mob/living/living_mob, atom/the_target) +/datum/targetting_datum/basic/allow_items/moonicorn/can_attack(mob/living/living_mob, atom/the_target, vision_range) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/basic/farm_animals/deer.dm b/code/modules/mob/living/basic/farm_animals/deer.dm index a948ec4d7a6..7907e668443 100644 --- a/code/modules/mob/living/basic/farm_animals/deer.dm +++ b/code/modules/mob/living/basic/farm_animals/deer.dm @@ -35,7 +35,7 @@ /datum/ai_controller/basic_controller/deer blackboard = list( BB_STATIONARY_MOVE_TO_TARGET = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm index f698e5015e8..db49ae8df9f 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm @@ -34,7 +34,10 @@ blood_volume = BLOOD_VOLUME_NORMAL ai_controller = /datum/ai_controller/basic_controller/goat - + /// How often will we develop an evil gleam in our eye? + var/gleam_delay = 20 SECONDS + /// Time until we can next gleam evilly + COOLDOWN_DECLARE(gleam_cooldown) /// List of stuff (flora) that we want to eat var/static/list/edibles = list( /obj/structure/alien/resin/flower_bud, @@ -85,15 +88,14 @@ return COMPONENT_HOSTILE_NO_ATTACK -/// If we are being attacked by someone who we are already retaliating against, give a nice fluff message. +/// If we are being attacked by someone, give a nice fluff message. But only once in a while. /mob/living/basic/goat/proc/on_attacked(datum/source, atom/attacker, attack_flags) - var/is_attacker_shitlisted = locate(attacker) in ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] - if(!is_attacker_shitlisted) + if (!COOLDOWN_FINISHED(src, gleam_cooldown)) return - visible_message( span_danger("[src] gets an evil-looking gleam in [p_their()] eye."), ) + COOLDOWN_START(src, gleam_cooldown, gleam_delay) /// Handles automagically eating a plant when we move into a turf that has one. /mob/living/basic/goat/proc/on_move(datum/source, atom/entering_loc) diff --git a/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm b/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm index 41fc448a3b6..f8463b19675 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm @@ -9,6 +9,7 @@ idle_behavior = /datum/idle_behavior/idle_random_walk planning_subtrees = list( + /datum/ai_planning_subtree/capricious_retaliate, // Capricious like Capra, get it? /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/find_food, /datum/ai_planning_subtree/basic_melee_attack_subtree, diff --git a/code/modules/mob/living/basic/farm_animals/pig.dm b/code/modules/mob/living/basic/farm_animals/pig.dm index 46655e50341..c0ad3f6b349 100644 --- a/code/modules/mob/living/basic/farm_animals/pig.dm +++ b/code/modules/mob/living/basic/farm_animals/pig.dm @@ -29,11 +29,11 @@ ai_controller = /datum/ai_controller/basic_controller/pig /mob/living/basic/pig/Initialize(mapload) + . = ..() AddElement(/datum/element/pet_bonus, "oinks!") AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/ai_flee_while_injured) make_tameable() - . = ..() ///wrapper for the tameable component addition so you can have non tamable cow subtypes /mob/living/basic/pig/proc/make_tameable() @@ -47,7 +47,7 @@ /datum/ai_controller/basic_controller/pig blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/pony.dm b/code/modules/mob/living/basic/farm_animals/pony.dm index 7649068458d..e1765f0fdba 100644 --- a/code/modules/mob/living/basic/farm_animals/pony.dm +++ b/code/modules/mob/living/basic/farm_animals/pony.dm @@ -106,7 +106,7 @@ /datum/ai_controller/basic_controller/pony blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/rabbit.dm b/code/modules/mob/living/basic/farm_animals/rabbit.dm index e837fc3bf83..19fd0120ba7 100644 --- a/code/modules/mob/living/basic/farm_animals/rabbit.dm +++ b/code/modules/mob/living/basic/farm_animals/rabbit.dm @@ -49,7 +49,7 @@ /datum/ai_controller/basic_controller/rabbit blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/farm_animals/sheep.dm b/code/modules/mob/living/basic/farm_animals/sheep.dm index 4452c5ae77c..ac320d80804 100644 --- a/code/modules/mob/living/basic/farm_animals/sheep.dm +++ b/code/modules/mob/living/basic/farm_animals/sheep.dm @@ -81,7 +81,7 @@ /datum/ai_controller/basic_controller/sheep blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance 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 b17d5c1a30d..28ddd38324a 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 @@ -5,7 +5,6 @@ /obj/item/weldingtool, /obj/item/flashlight/flare, ), - BB_BASIC_MOB_FLEEING = TRUE, BB_MINIMUM_DISTANCE_RANGE = 3, ) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm index cbadd709047..310bbeb708e 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -31,7 +31,7 @@ /// Target nearby friendlies if they are hurt (and are not themselves Legions) /datum/targetting_datum/basic/attack_until_dead/legion -/datum/targetting_datum/basic/attack_until_dead/legion/faction_check(mob/living/living_mob, mob/living/the_target) +/datum/targetting_datum/basic/attack_until_dead/legion/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if (!living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly)) return FALSE if (istype(the_target, living_mob.type)) 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 14ed9eb2982..6a04742d471 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm @@ -28,7 +28,7 @@ GLOBAL_LIST_INIT(mook_commands, list( ) ///check for faction if not a ash walker, otherwise just attack -/datum/targetting_datum/basic/mook/faction_check(mob/living/living_mob, mob/living/the_target) +/datum/targetting_datum/basic/mook/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if(FACTION_ASHWALKER in living_mob.faction) return FALSE diff --git a/code/modules/mob/living/basic/pets/fox.dm b/code/modules/mob/living/basic/pets/fox.dm index f7a86be1e5c..150abdc676b 100644 --- a/code/modules/mob/living/basic/pets/fox.dm +++ b/code/modules/mob/living/basic/pets/fox.dm @@ -38,8 +38,9 @@ /datum/ai_controller/basic_controller/fox blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller/ignore_faction, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction + BB_ALWAYS_IGNORE_FACTION = TRUE, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller, + BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -60,12 +61,6 @@ /datum/ai_planning_subtree/random_speech/fox, ) -// Foxes will attack other station pets regardless of faction. -/datum/targetting_datum/basic/of_size/ours_or_smaller/ignore_faction - -/datum/targetting_datum/basic/of_size/ours_or_smaller/ignore_faction/faction_check(mob/living/living_mob, mob/living/the_target) - return FALSE - // The captain's fox, Renault /mob/living/basic/pet/fox/renault name = "Renault" diff --git a/code/modules/mob/living/basic/pets/sloth.dm b/code/modules/mob/living/basic/pets/sloth.dm index 5058e7d5334..aaeeb218b2c 100644 --- a/code/modules/mob/living/basic/pets/sloth.dm +++ b/code/modules/mob/living/basic/pets/sloth.dm @@ -75,9 +75,8 @@ GLOBAL_DATUM(cargo_sloth, /mob/living/basic/sloth) /// They're really passive in game, so they just wanna get away if you start smacking them. No trees in space from them to use for clawing your eyes out, but they will try if desperate. /datum/ai_controller/basic_controller/sloth blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, - BB_BASIC_MOB_FLEEING = TRUE, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm index 503264c3dc2..9d967c5a8b0 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm @@ -9,9 +9,8 @@ */ /datum/ai_controller/basic_controller/carp blackboard = list( - BB_BASIC_MOB_STOP_FLEEING = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items(), - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends() + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -36,9 +35,9 @@ */ /datum/ai_controller/basic_controller/carp/pet blackboard = list( - BB_BASIC_MOB_STOP_FLEEING = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends() + BB_ALWAYS_IGNORE_FACTION = TRUE, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends, ) ai_traits = STOP_MOVING_WHEN_PULLED planning_subtrees = list( @@ -80,9 +79,8 @@ */ /datum/ai_controller/basic_controller/carp/passive blackboard = list( - BB_BASIC_MOB_STOP_FLEEING = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends() + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends, ) ai_traits = STOP_MOVING_WHEN_PULLED planning_subtrees = list( diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm index a3c8e22071d..b3033b27a4b 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm @@ -22,7 +22,7 @@ return SUBTREE_RETURN_FINISH_PLANNING controller.queue_behavior(/datum/ai_behavior/find_the_blind, BB_BLIND_TARGET, BB_EYE_DAMAGE_THRESHOLD) -/datum/targetting_datum/basic/eyeball/can_attack(mob/living/owner, atom/target) +/datum/targetting_datum/basic/eyeball/can_attack(mob/living/owner, atom/target, vision_range) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/basic/space_fauna/ghost.dm b/code/modules/mob/living/basic/space_fauna/ghost.dm index 058c2d2cd3f..35afaade990 100644 --- a/code/modules/mob/living/basic/space_fauna/ghost.dm +++ b/code/modules/mob/living/basic/space_fauna/ghost.dm @@ -93,7 +93,7 @@ /datum/ai_controller/basic_controller/ghost blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/lightgeist.dm b/code/modules/mob/living/basic/space_fauna/lightgeist.dm index c70588f4502..9ab6ffe6778 100644 --- a/code/modules/mob/living/basic/space_fauna/lightgeist.dm +++ b/code/modules/mob/living/basic/space_fauna/lightgeist.dm @@ -97,7 +97,7 @@ /// Type of limb we can heal var/required_bodytype = BODYTYPE_ORGANIC -/datum/targetting_datum/lightgeist/can_attack(mob/living/living_mob, mob/living/target) +/datum/targetting_datum/lightgeist/can_attack(mob/living/living_mob, mob/living/target, vision_range) if (!isliving(target) || target.stat == DEAD) return FALSE if (!(heal_biotypes & target.mob_biotypes)) diff --git a/code/modules/mob/living/basic/space_fauna/mushroom.dm b/code/modules/mob/living/basic/space_fauna/mushroom.dm index e6d47e2db5c..96280db2923 100644 --- a/code/modules/mob/living/basic/space_fauna/mushroom.dm +++ b/code/modules/mob/living/basic/space_fauna/mushroom.dm @@ -73,7 +73,7 @@ stat_attack = DEAD ///we only attacked another mushrooms -/datum/targetting_datum/basic/mushroom/faction_check(mob/living/living_mob, mob/living/the_target) +/datum/targetting_datum/basic/mushroom/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) return !living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly) /datum/ai_planning_subtree/find_and_hunt_target/mushroom_food diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm index 97dbdbd0a7d..8a7013b9623 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/regal_rat blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/spaceman.dm b/code/modules/mob/living/basic/space_fauna/spaceman.dm index 0ad2c4cfb8c..5851bfa531b 100644 --- a/code/modules/mob/living/basic/space_fauna/spaceman.dm +++ b/code/modules/mob/living/basic/space_fauna/spaceman.dm @@ -32,7 +32,7 @@ /datum/ai_controller/basic_controller/spaceman blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_movement = /datum/ai_movement/basic_avoidance 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 9894d15fdfb..7dd61b72070 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 @@ -30,7 +30,7 @@ /// Used by Araneus, who only attacks those who attack first. He is house-trained and will not web up the HoS office. /datum/ai_controller/basic_controller/giant_spider/retaliate blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) planning_subtrees = list( diff --git a/code/modules/mob/living/basic/vermin/crab.dm b/code/modules/mob/living/basic/vermin/crab.dm index 4843c6e6f7b..bb81fd29c4d 100644 --- a/code/modules/mob/living/basic/vermin/crab.dm +++ b/code/modules/mob/living/basic/vermin/crab.dm @@ -77,9 +77,9 @@ ///The basic ai controller for crabs /datum/ai_controller/basic_controller/crab blackboard = list( - BB_BASIC_MOB_STOP_FLEEING = TRUE, + BB_ALWAYS_IGNORE_FACTION = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/vermin/space_bat.dm b/code/modules/mob/living/basic/vermin/space_bat.dm index 3ce1b41173d..232febf0f97 100644 --- a/code/modules/mob/living/basic/vermin/space_bat.dm +++ b/code/modules/mob/living/basic/vermin/space_bat.dm @@ -42,7 +42,7 @@ ///Controller for space bats, has nothing unique, just retaliation. /datum/ai_controller/basic_controller/space_bat blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/tgstation.dme b/tgstation.dme index c64acfa67d1..7daabadeaf6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -910,6 +910,7 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\write_on_paper.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\attack_adjacent_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\attack_obstacle_in_path.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\capricious_retaliate.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\climb_tree.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_food.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_paper_and_write.dm"