[MIRROR] Fixes dog AI lockups when fetching things, adds growling noises for dog attack mode [MDB IGNORE] (#12105)

* Improves dog AI resilience (#65384)

About The Pull Request

AI dogs currently have a nasty habit of getting stuck when trying to fetch items sometimes, rendering their AI behavior basically dead as they're stuck in a state where they're unable to accept any commands/inputs from their environment. This PR fixes that by adding some more robust checks to make sure a failed fetch attempt doesn't softlock the pups.

This PR also adds some growling sounds for dogs in harass mode who are guarding against someone not within biting distance.
Why It's Good For The Game

Fixes some edge cases where dog AI would stop working entirely. Makes dog AI's in attack mode more conspicuous, and less reliant on text spam to show that.
Changelog

cl Ryll/Shaps
fix: Dog AI's should no longer lock up and become unresponsive after failed fetch attempts
soundadd: Dogs in harass mode that are guarding against someone will now make growling sounds
/cl

* Fixes dog AI lockups when fetching things, adds growling noises for dog attack mode

Co-authored-by: Ryll Ryll <3589655+Ryll-Ryll@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-03-16 00:16:05 +01:00
committed by GitHub
parent f09f4e5771
commit 31eaeb64bf
7 changed files with 29 additions and 6 deletions

View File

@@ -161,6 +161,7 @@
#define BB_DOG_ORDER_MODE "BB_DOG_ORDER_MODE"
#define BB_DOG_PLAYING_DEAD "BB_DOG_PLAYING_DEAD"
#define BB_DOG_HARASS_TARGET "BB_DOG_HARASS_TARGET"
#define BB_DOG_HARASS_FRUSTRATION "BB_DOG_HARASS_FRUSTRATION"
/// Basically, what is our vision/hearing range for picking up on things to fetch/
#define AI_DOG_VISION_RANGE 10
@@ -171,7 +172,9 @@
/// After being ordered to heel, we spend this long chilling out
#define AI_DOG_HEEL_DURATION 20 SECONDS
/// After either being given a verbal order or a pointing order, ignore further of each for this duration
#define AI_DOG_COMMAND_COOLDOWN 2 SECONDS
#define AI_DOG_COMMAND_COOLDOWN 2 SECONDS
/// If the dog is set to harass someone but doesn't bite them for this long, give up
#define AI_DOG_HARASS_FRUSTRATE_TIME 50 SECONDS
// dog command modes (what pointing at something/someone does depending on the last order the dog heard)
/// Don't do anything (will still react to stuff around them though)

View File

@@ -45,6 +45,8 @@
/datum/ai_behavior/simple_equip/finish_action(datum/ai_controller/controller, success)
. = ..()
controller.blackboard[BB_FETCH_TARGET] = null
if(!success)
controller.blackboard[BB_FETCH_DELIVER_TO] = null
/datum/ai_behavior/simple_equip/proc/pickup_item(datum/ai_controller/controller, obj/item/target)
var/atom/pawn = controller.pawn
@@ -82,6 +84,7 @@
/datum/ai_behavior/deliver_item/finish_action(datum/ai_controller/controller, success)
. = ..()
controller.blackboard[BB_FETCH_TARGET] = null
controller.blackboard[BB_FETCH_DELIVER_TO] = null
/// Actually drop the fetched item to the target
@@ -98,7 +101,7 @@
controller.pawn.visible_message(span_notice("[controller.pawn] delivers [carried_item] to [return_target]."))
carried_item.forceMove(get_turf(return_target))
controller.blackboard -= BB_SIMPLE_CARRY_ITEM
controller.blackboard[BB_SIMPLE_CARRY_ITEM] = null
return TRUE
/// This behavior involves either eating a snack we can reach, or begging someone holding a snack
@@ -184,21 +187,34 @@
finish_action(controller, TRUE)
return
if(!controller.blackboard[BB_DOG_HARASS_FRUSTRATION])
controller.blackboard[BB_DOG_HARASS_FRUSTRATION] = world.time
else if(controller.blackboard[BB_DOG_HARASS_FRUSTRATION] + AI_DOG_HARASS_FRUSTRATE_TIME < world.time) // if we haven't actually bit them in a while, give up
living_pawn.visible_message(span_danger("[living_pawn] yawns and seems to lose interest in harassing [harass_target]."))
finish_action(controller, FALSE)
return
// subtypes of this behavior can change behavior for how eager/averse the pawn is to attack the target as opposed to falling back/making noise/getting help
if(in_range(living_pawn, living_target))
attack(controller, living_target)
else if(DT_PROB(50, delta_time))
else if(DT_PROB(15, delta_time))
living_pawn.manual_emote("[pick("barks", "growls", "stares")] menacingly at [harass_target]!")
if(DT_PROB(40, delta_time))
playsound(living_pawn, pick('sound/creatures/dog/growl1.ogg', 'sound/creatures/dog/growl2.ogg'), 50, TRUE, -1)
/datum/ai_behavior/harass/finish_action(datum/ai_controller/controller, succeeded)
. = ..()
controller.blackboard[BB_DOG_HARASS_TARGET] = null
controller.blackboard[BB_DOG_HARASS_FRUSTRATION] = 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/harass/proc/attack(datum/ai_controller/controller, mob/living/living_target)
var/mob/living/living_pawn = controller.pawn
if(!istype(living_pawn))
return
controller.blackboard[BB_DOG_HARASS_FRUSTRATION] = world.time
// make sure the pawn gets some temporary strength boost to actually attack the target instead of pathetically nuzzling them.
var/old_melee_lower = living_pawn.melee_damage_lower
var/old_melee_upper = living_pawn.melee_damage_upper

View File

@@ -7,7 +7,9 @@
BB_FETCH_IGNORE_LIST = list(),\
BB_DOG_ORDER_MODE = DOG_COMMAND_NONE,\
BB_DOG_PLAYING_DEAD = FALSE,\
BB_DOG_HARASS_TARGET = null)
BB_DOG_HARASS_TARGET = null,\
BB_DOG_HARASS_FRUSTRATION = null,\
BB_VISION_RANGE = AI_DOG_VISION_RANGE)
ai_movement = /datum/ai_movement/jps
planning_subtrees = list(/datum/ai_planning_subtree/dog)
@@ -202,7 +204,7 @@
var/command
if(findtext(spoken_text, "heel") || findtext(spoken_text, "sit") || findtext(spoken_text, "stay"))
command = COMMAND_HEEL
else if(findtext(spoken_text, "fetch") || findtext(spoken_text, "get it"))
else if(findtext(spoken_text, "fetch"))
command = COMMAND_FETCH
else if(findtext(spoken_text, "attack") || findtext(spoken_text, "sic"))
command = COMMAND_ATTACK

View File

@@ -174,7 +174,7 @@
pawn.visible_message(span_notice("[pawn] [blackboard[BB_HOSTILE_ATTACK_WORD]] at [commander]'s command, and [pawn.p_they()] stop[pawn.p_s()] obediently, awaiting further orders."))
blackboard[BB_HOSTILE_ORDER_MODE] = HOSTILE_COMMAND_NONE
CancelActions()
// fetch: whatever the commander points to, try and bring it back
// follow: whatever the commander points to, try and bring it back
if(COMMAND_FOLLOW)
pawn.visible_message(span_notice("[pawn] [blackboard[BB_HOSTILE_ATTACK_WORD]] at [commander]'s command, and [pawn.p_they()] follow[pawn.p_s()] slightly in anticipation."))
CancelActions()

View File

@@ -27,3 +27,5 @@ can_shake.ogg adapted from https://freesound.org/people/mcmast/sounds/456703/
splatter.ogg adapted from https://freesound.org/people/Rocktopus/sounds/233418/
hohoho.ogg and hehe.ogg are cut from a recording by Nanakisan on freesound: https://freesound.org/people/Nanakisan/sounds/253534/
mbox_full.ogg and mbox_end.ogg make use of The Ragtime Drummer by James Lent, in the public domain
growl1.ogg and growl2.ogg in /sound/creatures/dog are adapted from Glitchedtones's Freesound shih-tzu uploads https://freesound.org/people/Glitchedtones/

Binary file not shown.

Binary file not shown.