mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
Co-authored-by: AMonkeyThatCodes <20987591+AMonkeyThatCodes@users.noreply.github.com> Co-authored-by: Gandalf <jzo123@hotmail.com>
284 lines
9.4 KiB
Plaintext
284 lines
9.4 KiB
Plaintext
|
|
/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/give_up_distance = 10
|
|
|
|
/datum/ai_behavior/break_spine/setup(datum/ai_controller/controller, target_key)
|
|
. = ..()
|
|
controller.current_movement_target = controller.blackboard[target_key]
|
|
|
|
/datum/ai_behavior/break_spine/perform(delta_time, datum/ai_controller/controller, target_key)
|
|
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, target_key)
|
|
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/setup(datum/ai_controller/controller, target_key)
|
|
. = ..()
|
|
controller.current_movement_target = controller.blackboard[target_key]
|
|
|
|
/datum/ai_behavior/use_on_object/perform(delta_time, datum/ai_controller/controller, target_key)
|
|
. = ..()
|
|
var/mob/living/pawn = controller.pawn
|
|
var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand())
|
|
var/atom/target = controller.blackboard[BB_MONKEY_CURRENT_PRESS_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/setup(datum/ai_controller/controller, target_key)
|
|
. = ..()
|
|
controller.current_movement_target = controller.blackboard[target_key]
|
|
|
|
|
|
/datum/ai_behavior/give/perform(delta_time, datum/ai_controller/controller, target_key)
|
|
. = ..()
|
|
var/mob/living/pawn = controller.pawn
|
|
var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand())
|
|
var/atom/target = controller.blackboard[target_key]
|
|
|
|
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
|
|
|
|
|
|
|
|
/datum/ai_behavior/perform_emote
|
|
|
|
/datum/ai_behavior/perform_emote/perform(delta_time, datum/ai_controller/controller, emote)
|
|
var/mob/living/living_pawn = controller.pawn
|
|
if(!istype(living_pawn))
|
|
return
|
|
living_pawn.manual_emote(emote)
|
|
finish_action(controller, TRUE)
|
|
|
|
/datum/ai_behavior/perform_speech
|
|
|
|
/datum/ai_behavior/perform_speech/perform(delta_time, datum/ai_controller/controller, speech)
|
|
var/mob/living/living_pawn = controller.pawn
|
|
if(!istype(living_pawn))
|
|
return
|
|
living_pawn.say(speech, forced = "AI Controller")
|
|
finish_action(controller, TRUE)
|
|
|
|
|