diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index 8a62039228e..58f83c91d2c 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -226,6 +226,8 @@ #define BB_TARGETTING_DATUM "targetting_datum" ///some behaviors that check current_target also set this on deep crit mobs #define BB_BASIC_MOB_EXECUTION_TARGET "BB_basic_execution_target" +///Blackboard key for a whitelist typecache of "things we can target while trying to move" +#define BB_OBSTACLE_TARGETTING_WHITELIST "BB_targetting_whitelist" ///Targetting keys for something to run away from, if you need to store this separately from current target #define BB_BASIC_MOB_FLEE_TARGET "BB_basic_flee_target" 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 ccc58d9f0a9..7f152e43ce0 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 @@ -30,10 +30,9 @@ finish_action(controller, succeeded = FALSE, target_key = target_key, hiding_location_key = hiding_location_key) /datum/ai_behavior/run_away_from_target/proc/plot_path_away_from(datum/ai_controller/controller, atom/target) - var/run_direction = get_dir(controller.pawn, get_step_away(controller.pawn, target)) var/turf/target_destination = get_turf(controller.pawn) for (var/i in 1 to run_distance) - var/turf/test_destination = get_ranged_target_turf(controller.pawn, run_direction, i) + var/turf/test_destination = get_ranged_target_turf_direct(controller.pawn, target, range = i, offset = 180) if (test_destination.is_blocked_turf(exclude_mobs = TRUE, source_atom = controller.pawn, ignore_atoms = GLOB.airlocks)) break target_destination = test_destination 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 32809ba652b..941063558e2 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 @@ -77,6 +77,10 @@ return FALSE if (basic_mob.see_invisible < object.invisibility) return FALSE + var/list/whitelist = basic_mob.ai_controller.blackboard[BB_OBSTACLE_TARGETTING_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 /datum/ai_planning_subtree/attack_obstacle_in_path/low_priority_target diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index b297a89e9de..d25a93b76a2 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -63,6 +63,21 @@ var/static/list/desired_food = list(/obj/item/food/meat/slab, /obj/item/food/meat/rawcutlet) /// Carp want to eat delicious six pack plastic rings var/static/list/desired_trash = list(/obj/item/storage/cans) + /// Structures that AI carp are willing to attack. This prevents them from deconstructing supermatter cooling equipment. + var/static/list/allowed_obstacle_targets = typecacheof(list( + /obj/structure/closet, + /obj/machinery/door, + /obj/structure/door_assembly, + /obj/structure/filingcabinet, + /obj/structure/frame, + /obj/structure/grille, + /obj/structure/plasticflaps, + /obj/structure/rack, + /obj/structure/reagent_dispensers, // Carp can have a little welding fuel, as a treat + /obj/structure/table, + /obj/machinery/vending, + /obj/structure/window, + )) /// Weighted list of colours a carp can be /// Weighted list of usual carp colors var/static/list/carp_colors = list( @@ -104,6 +119,7 @@ teleport = new(src) teleport.Grant(src) ai_controller.blackboard[BB_CARP_RIFT] = WEAKREF(teleport) + ai_controller.blackboard[BB_OBSTACLE_TARGETTING_WHITELIST] = allowed_obstacle_targets /mob/living/basic/carp/Destroy() QDEL_NULL(teleport) diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_abilities.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_abilities.dm index 94fc89ca9da..9a6aea8eff1 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_abilities.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_abilities.dm @@ -37,12 +37,14 @@ button_icon = 'icons/effects/effects.dmi' button_icon_state = "rift" desc = "Open a rift through the carp stream, allowing passage to somewhere close by." - cooldown_time = 1 MINUTES - melee_cooldown_time = 2 SECONDS + cooldown_time = 15 SECONDS + melee_cooldown_time = 0 SECONDS // Handled by rift /// How far away can you place a rift? - var/max_range = 6 + var/max_range = 3 /datum/action/cooldown/mob_cooldown/lesser_carp_rift/Activate(atom/target_atom) + if (get_dist(get_turf(owner), target_atom) > max_range) + target_atom = get_ranged_target_turf_direct(owner, target_atom, range = max_range) if (!make_rift(target_atom)) return FALSE StartCooldown() @@ -58,10 +60,6 @@ if (!target_turf) return FALSE - if (get_dist(owner_turf, target_turf) > max_range) - owner.balloon_alert(owner, "too far!") - return FALSE - if (!target_turf) return FALSE @@ -107,6 +105,8 @@ /obj/effect/temp_visual/lesser_carp_rift/entrance /// Where you get teleported to var/list/exit_locs + /// Click CD to apply after teleporting + var/disorient_time = CLICK_CD_MELEE /obj/effect/temp_visual/lesser_carp_rift/entrance/Initialize(mapload) . = ..() @@ -129,6 +129,10 @@ if (isobserver(entered_atom)) return + if (isliving(entered_atom)) + var/mob/living/teleported_mob = entered_atom + teleported_mob.changeNext_move(disorient_time) + var/turf/destination = pick(exit_locs) do_teleport(entered_atom, destination, channel = TELEPORT_CHANNEL_MAGIC) playsound(src, 'sound/magic/wand_teleport.ogg', 50) 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 71be65aadd7..9083467a8a0 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 @@ -99,8 +99,7 @@ /datum/ai_behavior/make_carp_rift/away /datum/ai_behavior/make_carp_rift/away/find_target_turf(datum/ai_controller/controller, atom/target, datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability) - var/run_direction = get_dir(controller.pawn, get_step_away(controller.pawn, target)) - return get_ranged_target_turf(controller.pawn, run_direction, ability.max_range) + return get_ranged_target_turf_direct(controller.pawn, target, range = ability.max_range, offset = 180) /** * # Make carp rift forwards @@ -161,7 +160,7 @@ * Make a rift towards your target if you are blocked from moving or if it is far away */ /datum/ai_behavior/make_carp_rift/towards/aggressive - teleport_buffer_distance = 2 // Don't aggressively drop carps directly on top of a target mob + teleport_buffer_distance = 1 // Don't aggressively drop carps directly on top of a target mob /** * # Make carp rift forwards (unvalidated) @@ -183,9 +182,9 @@ */ /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift /// How far away do we look for rifts? - var/search_distance = 2 + var/search_distance = 3 /// Minimum distance we should be from the target before we bother performing this action - var/minimum_distance = 3 + var/minimum_distance = 2 /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift/SelectBehaviors(datum/ai_controller/controller, delta_time) var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]