/datum/ai_behavior/resist/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/living_pawn = controller.pawn living_pawn.resist() finish_action(controller, TRUE) /datum/ai_behavior/battle_screech ///List of possible screeches the behavior has var/list/screeches /datum/ai_behavior/battle_screech/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/living_pawn = controller.pawn INVOKE_ASYNC(living_pawn, /mob.proc/emote, pick(screeches)) finish_action(controller, TRUE) ///Moves to target then finishes /datum/ai_behavior/move_to_target behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT /datum/ai_behavior/move_to_target/perform(delta_time, datum/ai_controller/controller) . = ..() finish_action(controller, TRUE) /datum/ai_behavior/break_spine behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT action_cooldown = 0.7 SECONDS var/target_key var/give_up_distance = 10 /datum/ai_behavior/break_spine/perform(delta_time, datum/ai_controller/controller) var/mob/living/batman = controller.blackboard[target_key] var/mob/living/big_guy = controller.pawn //he was molded by the darkness if(batman.stat) finish_action(controller, TRUE) if(get_dist(batman, big_guy) >= give_up_distance) finish_action(controller, FALSE) big_guy.start_pulling(batman) big_guy.setDir(get_dir(big_guy, batman)) batman.visible_message(span_warning("[batman] gets a slightly too tight hug from [big_guy]!"), span_userdanger("You feel your body break as [big_guy] embraces you!")) if(iscarbon(batman)) var/mob/living/carbon/carbon_batman = batman for(var/obj/item/bodypart/bodypart_to_break in carbon_batman.bodyparts) if(bodypart_to_break.body_zone == BODY_ZONE_HEAD) continue bodypart_to_break.receive_damage(brute = 15, wound_bonus = 35) else batman.adjustBruteLoss(150) finish_action(controller, TRUE) /datum/ai_behavior/break_spine/finish_action(datum/ai_controller/controller, succeeded) if(succeeded) controller.blackboard[target_key] = null return ..() /// Use in hand the currently held item /datum/ai_behavior/use_in_hand behavior_flags = AI_BEHAVIOR_MOVE_AND_PERFORM /datum/ai_behavior/use_in_hand/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held = pawn.get_item_by_slot(pawn.get_active_hand()) if(!held) finish_action(controller, FALSE) return pawn.activate_hand(pawn.get_active_hand()) finish_action(controller, TRUE) /// Use the currently held item, or unarmed, on an object in the world /datum/ai_behavior/use_on_object required_distance = 1 behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT /datum/ai_behavior/use_on_object/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand()) var/atom/target = controller.current_movement_target if(!target || !pawn.CanReach(target)) finish_action(controller, FALSE) return pawn.set_combat_mode(FALSE) if(held_item) held_item.melee_attack_chain(pawn, target) else pawn.UnarmedAttack(target, TRUE) finish_action(controller, TRUE) /datum/ai_behavior/give required_distance = 1 behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT /datum/ai_behavior/give/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand()) var/atom/target = controller.current_movement_target if(!target || !pawn.CanReach(target) || !isliving(target)) finish_action(controller, FALSE) return var/mob/living/living_target = target 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_mob(pawn, living_target, 1 SECONDS)) return if(QDELETED(held_item) || QDELETED(living_target)) finish_action(controller, FALSE) return var/pocket_choice = prob(50) ? ITEM_SLOT_RPOCKET : ITEM_SLOT_LPOCKET if(prob(50) && living_target.can_put_in_hand(held_item)) living_target.put_in_hand(held_item) else if(held_item.mob_can_equip(living_target, pawn, pocket_choice, TRUE)) living_target.equip_to_slot(held_item, pocket_choice) finish_action(controller, TRUE) /datum/ai_behavior/consume required_distance = 1 behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT action_cooldown = 2 SECONDS /datum/ai_behavior/consume/setup(datum/ai_controller/controller, obj/item/target) . = ..() controller.current_movement_target = target /datum/ai_behavior/consume/perform(delta_time, datum/ai_controller/controller, obj/item/target) . = ..() var/mob/living/pawn = controller.pawn if(!(target in pawn.held_items)) if(!pawn.put_in_hand_check(target)) finish_action(controller, FALSE) return pawn.put_in_hands(target) target.melee_attack_chain(pawn, 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) /**find and set * Finds an item near themselves, sets a blackboard key as it. Very useful for ais that need to use machines or something. * if you want to do something more complicated than find a single atom, change the search_tactic() proc * cool tip: search_tactic() can set lists */ /datum/ai_behavior/find_and_set action_cooldown = 5 SECONDS ///search range in how many tiles around the pawn to look for the path var/search_range = 7 //optional, don't use if you're changing search_tactic() var/locate_path var/bb_key_to_set /datum/ai_behavior/find_and_set/perform(delta_time, datum/ai_controller/controller) . = ..() var/find_this_thing = search_tactic(controller) if(find_this_thing) controller.blackboard[bb_key_to_set] = find_this_thing finish_action(controller, TRUE) else finish_action(controller, FALSE) /datum/ai_behavior/find_and_set/proc/search_tactic(datum/ai_controller/controller) return locate(locate_path) in oview(search_range, controller.pawn) /// This behavior involves attacking a target. /datum/ai_behavior/attack behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM required_distance = 1 /datum/ai_behavior/attack/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !isturf(living_pawn.loc)) return var/datum/weakref/attack_ref = controller.blackboard[BB_ATTACK_TARGET] var/atom/movable/attack_target = attack_ref?.resolve() if(!attack_target || !can_see(living_pawn, attack_target, length=controller.blackboard[BB_VISION_RANGE])) finish_action(controller, FALSE) return var/mob/living/living_target = attack_target if(istype(living_target) && (living_target.stat == DEAD)) finish_action(controller, TRUE) return controller.current_movement_target = living_target attack(controller, living_target) /datum/ai_behavior/attack/finish_action(datum/ai_controller/controller, succeeded) . = ..() controller.blackboard[BB_ATTACK_TARGET] = null /// A proc representing when the mob is pushed to actually attack the target. Again, subtypes can be used to represent different attacks from different animals, or it can be some other generic behavior /datum/ai_behavior/attack/proc/attack(datum/ai_controller/controller, mob/living/living_target) var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn)) return living_pawn.ClickOn(living_target, list()) /// This behavior involves attacking a target. /datum/ai_behavior/follow behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM required_distance = 1 /datum/ai_behavior/follow/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !isturf(living_pawn.loc)) return var/datum/weakref/follow_ref = controller.blackboard[BB_FOLLOW_TARGET] var/atom/movable/follow_target = follow_ref?.resolve() if(!follow_target || get_dist(living_pawn, follow_target) > controller.blackboard[BB_VISION_RANGE]) finish_action(controller, FALSE) return var/mob/living/living_target = follow_target if(istype(living_target) && (living_target.stat == DEAD)) finish_action(controller, TRUE) return controller.current_movement_target = living_target /datum/ai_behavior/follow/finish_action(datum/ai_controller/controller, succeeded) . = ..() controller.blackboard[BB_FOLLOW_TARGET] = null