diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 2b25d0cfb31..24461464c3e 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -172,8 +172,26 @@ ///Text we display when we befriend someone #define BB_FRIENDLY_MESSAGE "friendly_message" +//fishing! + ///our fishing target -#define BB_FISHING_TARGET "fishing_target" +#define BB_FISHING_TARGET "BB_fishing_target" + +///key holding the list of things we are able to fish from +#define BB_FISHABLE_LIST "BB_fishable_list" + +///key holding our cooldown between fishing attempts +#define BB_FISHING_COOLDOWN "BB_fishing_cooldown" + +///key that holds the next time we will start fishing +#define BB_FISHING_TIMER "BB_fishing_timer" + +///are we ONLY allowed to fish when we're hungry? +#define BB_ONLY_FISH_WHILE_HUNGRY "BB_only_fish_while_hungry" + +///drillable ice we can make holes in +#define BB_DRILLABLE_ICE "BB_drillable_ice" + // Keys used by one and only one behavior // Used to hold state without making bigass lists diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index db012679363..de93661e169 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1334,6 +1334,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait which silences all chemical reactions in its container #define TRAIT_SILENT_REACTIONS "silent_reactions" +///Trait given to mobs that can dig +#define TRAIT_MOB_CAN_DIG "mob_can_dig" + /** * * This trait is used in some interactions very high in the interaction chain to allow diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 13cb39b7e78..9eef84860b5 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -335,6 +335,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_MINDSHIELD" = TRAIT_MINDSHIELD, "TRAIT_MIND_TEMPORARILY_GONE" = TRAIT_MIND_TEMPORARILY_GONE, "TRAIT_MOB_BREEDER" = TRAIT_MOB_BREEDER, + "TRAIT_MOB_CAN_DIG" = TRAIT_MOB_CAN_DIG, "TRAIT_MOB_EATER" = TRAIT_MOB_EATER, "TRAIT_MOB_HATCHED" = TRAIT_MOB_HATCHED, "TRAIT_MOB_HIDE_HAPPINESS" = TRAIT_MOB_HIDE_HAPPINESS, diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index d6230ec8d35..65e3acf5f6f 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -268,11 +268,6 @@ multiple modular subtrees with behaviors return AI_STATUS_IDLE return AI_STATUS_ON -/datum/ai_controller/proc/get_current_turf() - var/mob/living/mob_pawn = pawn - var/turf/pawn_turf = get_turf(mob_pawn) - to_chat(world, "[pawn_turf]") - ///Called when the AI controller pawn changes z levels, we check if there's any clients on the new one and wake up the AI if there is. /datum/ai_controller/proc/on_changed_z_level(atom/source, turf/old_turf, turf/new_turf, same_z_layer, notify_contents) SIGNAL_HANDLER @@ -380,6 +375,7 @@ multiple modular subtrees with behaviors if(isnull(current_movement_target)) fail_behavior(current_behavior) return + ///Stops pawns from performing such actions that should require the target to be adjacent. var/atom/movable/moving_pawn = pawn var/can_reach = !(current_behavior.behavior_flags & AI_BEHAVIOR_REQUIRE_REACH) || moving_pawn.CanReach(current_movement_target) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/interact_with_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/interact_with_target.dm index 3b0c4245656..e3b202c5e16 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/interact_with_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/interact_with_target.dm @@ -3,6 +3,8 @@ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH ///should we be clearing the target after the fact? var/clear_target = TRUE + ///should our combat mode be off during interaction? + var/combat_mode = TRUE /datum/ai_behavior/interact_with_target/setup(datum/ai_controller/controller, target_key) . = ..() @@ -15,7 +17,7 @@ var/atom/target = controller.blackboard[target_key] if(QDELETED(target) || !pre_interact(controller, target)) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED - controller.ai_interact(target) + controller.ai_interact(target, combat_mode) return AI_BEHAVIOR_SUCCEEDED | AI_BEHAVIOR_DELAY /datum/ai_behavior/interact_with_target/finish_action(datum/ai_controller/controller, succeeded, target_key) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/fishing.dm b/code/datums/ai/basic_mobs/basic_subtrees/fishing.dm new file mode 100644 index 00000000000..e17f50740fa --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/fishing.dm @@ -0,0 +1,44 @@ +#define FISHING_COOLDOWN 45 SECONDS + +///subtree for fishing and eating food! +/datum/ai_planning_subtree/fish + ///behavior we use to find fishable objects + var/datum/ai_behavior/find_fishable_behavior = /datum/ai_behavior/find_and_set/in_list + ///behavior we use to fish! + var/datum/ai_behavior/fishing_behavior = /datum/ai_behavior/interact_with_target/fishing + ///blackboard key storing things we can fish from + var/fishable_list_key = BB_FISHABLE_LIST + ///key where we store found fishable items + var/fishing_target_key = BB_FISHING_TARGET + ///key where we store our fishing cooldown + var/fishing_cooldown_key = BB_FISHING_COOLDOWN + ///our fishing range + var/fishing_range = 5 + +/datum/ai_planning_subtree/fish/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(controller.blackboard[BB_ONLY_FISH_WHILE_HUNGRY] && controller.blackboard[BB_NEXT_FOOD_EAT] > world.time) + return + if(controller.blackboard[BB_FISHING_TIMER] > world.time) + return + if(!controller.blackboard_key_exists(fishing_target_key)) + controller.queue_behavior(find_fishable_behavior, fishing_target_key, controller.blackboard[fishable_list_key], fishing_range) + return + controller.queue_behavior(/datum/ai_behavior/interact_with_target/fishing, fishing_target_key, fishing_cooldown_key) + return SUBTREE_RETURN_FINISH_PLANNING + +///less expensive fishing behavior! +/datum/ai_planning_subtree/fish/fish_from_turfs + find_fishable_behavior = /datum/ai_behavior/find_and_set/in_list/closest_turf + +/datum/ai_behavior/interact_with_target/fishing + clear_target = FALSE + combat_mode = FALSE + +/datum/ai_behavior/interact_with_target/fishing/finish_action(datum/ai_controller/controller, succeeded, fishing_target_key, fishing_cooldown_key) + . = ..() + if(!succeeded) + return + var/cooldown = controller.blackboard[fishing_cooldown_key] || FISHING_COOLDOWN + controller.set_blackboard_key(BB_FISHING_TIMER, world.time + cooldown) + +#undef FISHING_COOLDOWN diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index 5a424f304f2..0096ff0f2eb 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -181,7 +181,6 @@ /datum/ai_behavior/find_and_set/in_list/turf_types - /datum/ai_behavior/find_and_set/in_list/turf_types/search_tactic(datum/ai_controller/controller, locate_paths, search_range) var/list/found = RANGE_TURFS(search_range, controller.pawn) shuffle_inplace(found) @@ -191,3 +190,12 @@ if(can_see(controller.pawn, possible_turf, search_range)) return possible_turf return null + +/datum/ai_behavior/find_and_set/in_list/closest_turf + +/datum/ai_behavior/find_and_set/in_list/closest_turf/search_tactic(datum/ai_controller/controller, locate_paths, search_range) + var/list/found = RANGE_TURFS(search_range, controller.pawn) + for(var/turf/possible_turf as anything in found) + if(!is_type_in_typecache(possible_turf, locate_paths) || !can_see(controller.pawn, possible_turf, search_range)) + found -= possible_turf + return (length(found)) ? get_closest_atom(/turf, found, controller.pawn) : null diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index c202c4be6a7..0ab14ff0d32 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -50,11 +50,13 @@ /// Finds a specific atom type to hunt. /datum/ai_behavior/find_hunt_target + ///is this only meant to search for turf types? + var/search_turf_types = FALSE /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)) + var/list/interesting_objects = search_turf_types ? RANGE_TURFS(hunt_range, living_mob) : oview(hunt_range, living_mob) + for(var/atom/possible_dinner as anything in typecache_filter_list(interesting_objects, types_to_hunt)) if(!valid_dinner(living_mob, possible_dinner, hunt_range, controller, seconds_per_tick)) continue controller.set_blackboard_key(hunting_target_key, possible_dinner) @@ -69,6 +71,9 @@ return can_see(source, dinner, radius) +/datum/ai_behavior/find_hunt_target/search_turf_types + search_turf_types = TRUE + /// Hunts down a specific atom type. /datum/ai_behavior/hunt_target behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH diff --git a/code/game/turfs/open/ice.dm b/code/game/turfs/open/ice.dm index f28bc8dd4b0..39abe6ebfee 100644 --- a/code/game/turfs/open/ice.dm +++ b/code/game/turfs/open/ice.dm @@ -42,15 +42,23 @@ if(can_make_hole) . += span_info("You could use a [EXAMINE_HINT("shovel")] or a [EXAMINE_HINT("pick")] to dig a fishing hole here.") +/turf/open/misc/ice/attack_animal(mob/living/animal, list/modifiers) + . = ..() + if(HAS_TRAIT(animal, TRAIT_MOB_CAN_DIG)) + dig_hole(animal) + /turf/open/misc/ice/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if(!can_make_hole) - return NONE if(tool.tool_behaviour != TOOL_SHOVEL && tool.tool_behaviour != TOOL_MINING) return NONE + return dig_hole(user) ? ITEM_INTERACT_SUCCESS : NONE + +/turf/open/misc/ice/proc/dig_hole(mob/living/user) + if(!can_make_hole) + return FALSE balloon_alert(user, "digging...") playsound(src, 'sound/effects/shovel_dig.ogg', 50, TRUE) if(!do_after(user, 5 SECONDS, src)) - return NONE + return FALSE balloon_alert(user, "dug hole") AddComponent(/datum/component/fishing_spot, GLOB.preset_fish_sources[/datum/fish_source/ice_fishing]) ADD_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT) @@ -58,7 +66,7 @@ can_make_hole = FALSE RemoveElement(/datum/element/contextual_screentip_tools, tool_screentips) flags_1 &= ~HAS_CONTEXTUAL_SCREENTIPS_1 - return ITEM_INTERACT_SUCCESS + return TRUE /turf/open/misc/ice/smooth icon_state = "ice_turf-255" diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm index 625dc4af907..d7f5a024ace 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm @@ -55,6 +55,8 @@ charge = new charge_type(src) charge.Grant(src) ai_controller.set_blackboard_key(BB_TARGETED_ACTION, charge) + var/static/list/fishable_turfs = typecacheof(list(/turf/open/lava)) + ai_controller.set_blackboard_key(BB_FISHABLE_LIST, fishable_turfs) /mob/living/basic/mining/lobstrosity/Destroy() QDEL_NULL(charge) 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 de6ca4a0cc1..647aeac9474 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -14,6 +14,8 @@ BB_LOBSTROSITY_FINGER_LUST = 0, BB_LOBSTROSITY_NAIVE_HUNTER = FALSE, BB_BASIC_MOB_FLEE_DISTANCE = 8, + BB_EAT_FOOD_COOLDOWN = 3 MINUTES, + BB_ONLY_FISH_WHILE_HUNGRY = TRUE, BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, BB_OWNER_SELF_HARM_RESPONSES = SHRIMP_HARM_RESPONSES, ) @@ -31,7 +33,7 @@ /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster, /datum/ai_planning_subtree/find_food, - /datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing, + /datum/ai_planning_subtree/fish/fish_from_turfs, /datum/ai_planning_subtree/find_fingers, ) @@ -65,7 +67,7 @@ /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster, /datum/ai_planning_subtree/find_food, - /datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing, + /datum/ai_planning_subtree/fish/fish_from_turfs, /datum/ai_planning_subtree/find_fingers, ) @@ -81,7 +83,7 @@ /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster, /datum/ai_planning_subtree/find_food, - /datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing, + /datum/ai_planning_subtree/fish/fish_from_turfs, /datum/ai_planning_subtree/find_fingers, ) @@ -97,15 +99,10 @@ /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster, /datum/ai_planning_subtree/find_food, - /datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing, + /datum/ai_planning_subtree/fish/fish_from_turfs, /datum/ai_planning_subtree/find_fingers, ) -/datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing - target_key = BB_FISHING_TARGET - hunt_targets = list(/turf/open/lava) - hunting_behavior = /datum/ai_behavior/hunt_target/interact_with_target/reset_target_combat_mode_off - /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/lobster diff --git a/code/modules/mob/living/basic/pets/penguin.dm b/code/modules/mob/living/basic/pets/penguin/penguin.dm similarity index 72% rename from code/modules/mob/living/basic/pets/penguin.dm rename to code/modules/mob/living/basic/pets/penguin/penguin.dm index c1afe10187c..5a473203998 100644 --- a/code/modules/mob/living/basic/pets/penguin.dm +++ b/code/modules/mob/living/basic/pets/penguin/penguin.dm @@ -35,6 +35,7 @@ AddElement(/datum/element/ai_flee_while_injured) AddElement(/datum/element/pet_bonus, "honk") AddElementTrait(TRAIT_WADDLING, INNATE_TRAIT, /datum/element/waddling) + ADD_TRAIT(src, TRAIT_MOB_CAN_DIG, INNATE_TRAIT) if(!can_lay_eggs) return AddComponent(\ @@ -47,6 +48,11 @@ max_eggs_held = 1,\ egg_laid_callback = CALLBACK(src, PROC_REF(lay_penguin_egg)),\ ) + var/static/list/fishable_objects = typecacheof(list(/turf/open/misc/ice)) + ai_controller.set_blackboard_key(BB_FISHABLE_LIST, fishable_objects) + var/static/list/delicious_food = list(/obj/item/fish) + AddElement(/datum/element/basic_eating, heal_amt = 10, food_types = delicious_food) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(delicious_food)) /mob/living/basic/pet/penguin/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) . = ..() @@ -93,38 +99,6 @@ carried_egg = null cut_overlay("penguin_egg_overlay") -/datum/ai_controller/basic_controller/penguin - blackboard = list( - BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, - ) - - ai_traits = STOP_MOVING_WHEN_PULLED - ai_movement = /datum/ai_movement/basic_avoidance - idle_behavior = /datum/idle_behavior/idle_random_walk - - 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/find_and_hunt_target/penguin_egg, - /datum/ai_planning_subtree/random_speech/penguin, - ) - -/datum/ai_planning_subtree/find_and_hunt_target/penguin_egg - target_key = BB_LOW_PRIORITY_HUNTING_TARGET - hunting_behavior = /datum/ai_behavior/hunt_target/penguin_egg - finding_behavior = /datum/ai_behavior/find_hunt_target/penguin_egg - hunt_targets = list(/obj/item/food/egg/penguin_egg) - hunt_range = 7 - -/datum/ai_behavior/find_hunt_target/penguin_egg/valid_dinner(mob/living/source, atom/dinner, radius) - return can_see(source, dinner, radius) && !(dinner in source.contents) -/datum/ai_behavior/hunt_target/penguin_egg - hunt_cooldown = 15 SECONDS - always_reset_target = TRUE - -/datum/ai_behavior/hunt_target/penguin_egg/target_caught(mob/living/basic/hunter, obj/item/food/egg/target) - hunter.UnarmedAttack(target, TRUE) - /mob/living/basic/pet/penguin/emperor name = "emperor penguin" real_name = "penguin" @@ -163,7 +137,6 @@ ///will it grow up? var/can_grow_up = TRUE - /mob/living/basic/pet/penguin/baby/Initialize(mapload) . = ..() if(!can_grow_up) @@ -187,23 +160,6 @@ /mob/living/basic/pet/penguin/baby/proc/ready_to_grow() return (stat == CONSCIOUS) -/datum/ai_controller/basic_controller/penguin/baby - blackboard = list( - BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, - BB_FIND_MOM_TYPES = list(/mob/living/basic/pet/penguin), - BB_IGNORE_MOM_TYPES = list(/mob/living/basic/pet/penguin/baby), - ) - - ai_traits = STOP_MOVING_WHEN_PULLED - ai_movement = /datum/ai_movement/basic_avoidance - idle_behavior = /datum/idle_behavior/idle_random_walk - - 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/look_for_adult, - ) - /mob/living/basic/pet/penguin/baby/permanent can_grow_up = FALSE diff --git a/code/modules/mob/living/basic/pets/penguin/penguin_ai.dm b/code/modules/mob/living/basic/pets/penguin/penguin_ai.dm new file mode 100644 index 00000000000..90d12e87941 --- /dev/null +++ b/code/modules/mob/living/basic/pets/penguin/penguin_ai.dm @@ -0,0 +1,79 @@ + +/datum/ai_controller/basic_controller/penguin + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_ONLY_FISH_WHILE_HUNGRY = TRUE, + ) + + ai_traits = STOP_MOVING_WHEN_PULLED + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + + 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/find_food, + /datum/ai_planning_subtree/fish/drilled_ice, + /datum/ai_planning_subtree/find_and_hunt_target/drill_ice, + /datum/ai_planning_subtree/find_and_hunt_target/penguin_egg, + /datum/ai_planning_subtree/random_speech/penguin, + ) + +///subtree to find baby eggs! +/datum/ai_planning_subtree/find_and_hunt_target/penguin_egg + target_key = BB_LOW_PRIORITY_HUNTING_TARGET + hunting_behavior = /datum/ai_behavior/hunt_target/interact_with_target/reset_target + finding_behavior = /datum/ai_behavior/find_hunt_target/penguin_egg + hunt_targets = list(/obj/item/food/egg/penguin_egg) + hunt_range = 7 + +/datum/ai_behavior/find_hunt_target/penguin_egg/valid_dinner(mob/living/source, atom/dinner, radius) + return can_see(source, dinner, radius) && !(dinner in source.contents) + +///subtree to find diggable ice we can fish from! +/datum/ai_planning_subtree/find_and_hunt_target/drill_ice + target_key = BB_DRILLABLE_ICE + hunting_behavior = /datum/ai_behavior/hunt_target/interact_with_target/reset_target + finding_behavior = /datum/ai_behavior/find_hunt_target/search_turf_types/drillable_ice + hunt_targets = list(/turf/open/misc/ice) + hunt_range = 7 + +/datum/ai_behavior/find_hunt_target/search_turf_types/drillable_ice + +/datum/ai_behavior/find_hunt_target/search_turf_types/drillable_ice/valid_dinner(mob/living/source, turf/open/misc/ice/ice, radius) + return ice.can_make_hole && can_see(source, ice, radius) + +/datum/ai_planning_subtree/find_and_hunt_target/drill_ice/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(controller.blackboard_key_exists(BB_FISHING_TARGET)) + return + return ..() + +/datum/ai_planning_subtree/fish/drilled_ice + find_fishable_behavior = /datum/ai_behavior/find_and_set/in_list/drilled_ice + +/datum/ai_behavior/find_and_set/in_list/drilled_ice/search_tactic(datum/ai_controller/controller, locate_paths, search_range) + for(var/atom/possible_ice as anything in RANGE_TURFS(search_range, controller.pawn)) + if(!istype(possible_ice, /turf/open/misc/ice)) + continue + if(HAS_TRAIT(possible_ice, TRAIT_FISHING_SPOT)) + return possible_ice + return null + +///ai controller for the baby penguin +/datum/ai_controller/basic_controller/penguin/baby + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_FIND_MOM_TYPES = list(/mob/living/basic/pet/penguin), + BB_IGNORE_MOM_TYPES = list(/mob/living/basic/pet/penguin/baby), + ) + + ai_traits = STOP_MOVING_WHEN_PULLED + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + + 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/find_food, + /datum/ai_planning_subtree/look_for_adult, + ) diff --git a/tgstation.dme b/tgstation.dme index f6b649ee670..f2fc8af67b8 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -927,6 +927,7 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\find_paper_and_write.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_parent.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_targets_prioritize_traits.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\fishing.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\flee_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\go_for_swim.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\maintain_distance.dm" @@ -4971,7 +4972,6 @@ #include "code\modules\mob\living\basic\minebots\minebot_remote_control.dm" #include "code\modules\mob\living\basic\minebots\minebot_upgrades.dm" #include "code\modules\mob\living\basic\pets\fox.dm" -#include "code\modules\mob\living\basic\pets\penguin.dm" #include "code\modules\mob\living\basic\pets\pet.dm" #include "code\modules\mob\living\basic\pets\pet_designer.dm" #include "code\modules\mob\living\basic\pets\sloth.dm" @@ -5000,6 +5000,8 @@ #include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_hoarding.dm" #include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_perching.dm" #include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parroting_action.dm" +#include "code\modules\mob\living\basic\pets\penguin\penguin.dm" +#include "code\modules\mob\living\basic\pets\penguin\penguin_ai.dm" #include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_abilities.dm" #include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_ai.dm" #include "code\modules\mob\living\basic\ruin_defender\cybersun_aicore.dm"