Files
Bubberstation/code/modules/mob/living/basic/bots/firebot/firebot_ai.dm

133 lines
5.7 KiB
Plaintext

#define ANNOUNCEMENT_TIMER 10 SECONDS
/datum/ai_controller/basic_controller/bot/firebot
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_turfs,
BB_UNREACHABLE_LIST_COOLDOWN = 3 MINUTES,
)
planning_subtrees = list(
/datum/ai_planning_subtree/escape_captivity/pacifist,
/datum/ai_planning_subtree/respond_to_summon,
/datum/ai_planning_subtree/extinguishing_people,
/datum/ai_planning_subtree/extinguishing_turfs,
/datum/ai_planning_subtree/salute_authority,
/datum/ai_planning_subtree/firebot_speech,
/datum/ai_planning_subtree/find_patrol_beacon,
)
reset_keys = list(
BB_FIREBOT_EXTINGUISH_TARGET,
BB_BEACON_TARGET,
BB_PREVIOUS_BEACON_TARGET,
BB_BOT_SUMMON_TARGET,
)
///cooldown until we announce a fire again
COOLDOWN_DECLARE(announcement_cooldown)
/datum/ai_controller/basic_controller/bot/firebot/TryPossessPawn(atom/new_pawn)
. = ..()
if(. & AI_CONTROLLER_INCOMPATIBLE)
return
RegisterSignal(new_pawn, COMSIG_AI_BLACKBOARD_KEY_SET(BB_FIREBOT_EXTINGUISH_TARGET), PROC_REF(on_target_found))
///say a silly line whenever we find someone on fire
/datum/ai_controller/basic_controller/bot/firebot/proc/on_target_found()
SIGNAL_HANDLER
if(!COOLDOWN_FINISHED(src, announcement_cooldown))
return
var/datum/action/cooldown/bot_announcement/announcement = blackboard[BB_ANNOUNCE_ABILITY]
if(isnull(announcement))
return
var/list/lines = blackboard[BB_FIREBOT_FIRE_DETECTED_LINES]
if(!length(lines))
return
INVOKE_ASYNC(announcement, TYPE_PROC_REF(/datum/action/cooldown/bot_announcement, announce), pick(lines))
COOLDOWN_START(src, announcement_cooldown, ANNOUNCEMENT_TIMER)
///subtree for extinguishing people
/datum/ai_planning_subtree/extinguishing_people
/datum/ai_planning_subtree/extinguishing_people/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
if(controller.blackboard_key_exists(BB_FIREBOT_EXTINGUISH_TARGET))
controller.queue_behavior(/datum/ai_behavior/basic_melee_attack/interact_once/extinguish, BB_FIREBOT_EXTINGUISH_TARGET, BB_TARGETING_STRATEGY)
return SUBTREE_RETURN_FINISH_PLANNING
var/mob/living/basic/bot/firebot/living_bot = controller.pawn
var/range = living_bot.firebot_mode_flags & FIREBOT_STATIONARY_MODE ? 1 : 5
if(living_bot.firebot_mode_flags & FIREBOT_EXTINGUISH_PEOPLE)
controller.queue_behavior(/datum/ai_behavior/bot_search/people_on_fire, BB_FIREBOT_EXTINGUISH_TARGET, controller.blackboard[BB_FIREBOT_CAN_EXTINGUISH], range)
///behavior for finding people on fire
/datum/ai_behavior/bot_search/people_on_fire
/datum/ai_behavior/bot_search/people_on_fire/valid_target(datum/ai_controller/basic_controller/bot/controller, mob/living/my_target)
var/mob/living/basic/bot/living_bot = controller.pawn
return (my_target.on_fire || (living_bot.bot_access_flags & BOT_COVER_EMAGGED))
///subtree for finding turfs to extinguish
/datum/ai_planning_subtree/extinguishing_turfs
/datum/ai_planning_subtree/extinguishing_turfs/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
if(controller.blackboard_key_exists(BB_FIREBOT_EXTINGUISH_TARGET))
return
var/mob/living/basic/bot/firebot/living_bot = controller.pawn
var/should_bypass_blacklist = living_bot.firebot_mode_flags & FIREBOT_STATIONARY_MODE
if(living_bot.firebot_mode_flags & FIREBOT_EXTINGUISH_FLAMES)
controller.queue_behavior(/datum/ai_behavior/search_burning_turfs, BB_FIREBOT_EXTINGUISH_TARGET, should_bypass_blacklist)
///behavior to find burning turfs
/datum/ai_behavior/search_burning_turfs
action_cooldown = 2 SECONDS
behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
/datum/ai_behavior/search_burning_turfs/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, bypass_add_blacklist = FALSE)
var/mob/living/living_pawn = controller.pawn
var/list/ignore_list = controller.blackboard[BB_TEMPORARY_IGNORE_LIST]
for(var/turf/possible_turf as anything in RANGE_TURFS(5, living_pawn))
if(QDELETED(living_pawn))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
if(!isopenturf(possible_turf))
continue
var/turf/open/open_turf = possible_turf
if(!open_turf.active_hotspot)
continue
if(LAZYACCESS(ignore_list, possible_turf))
continue
if(controller.set_if_can_reach(key = target_key, target = possible_turf, bypass_add_to_blacklist = bypass_add_blacklist))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
///behavior to extinguish mobs or turfs
/datum/ai_behavior/basic_melee_attack/interact_once/extinguish
/datum/ai_behavior/basic_melee_attack/interact_once/extinguish/finish_action(datum/ai_controller/basic_controller/bot/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key)
var/atom/target = controller.blackboard[BB_FIREBOT_EXTINGUISH_TARGET]
var/mob/living/basic/bot/living_bot = controller.pawn
//if we couldnt path, or we successfully burnt someone, ignore them for a bit!
if(!succeeded || (isliving(target) && (living_bot.bot_access_flags & BOT_COVER_EMAGGED)))
controller.add_to_blacklist(target)
return ..()
///subtree to make us say funny idle lines
/datum/ai_planning_subtree/firebot_speech
///chance we spout lines
var/speech_prob = 3
/datum/ai_planning_subtree/firebot_speech/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
if(controller.blackboard[BB_FIREBOT_EXTINGUISH_TARGET] || !SPT_PROB(speech_prob, seconds_per_tick))
return
var/mob/living/basic/bot/living_bot = controller.pawn
var/list/idle_lines = (living_bot.bot_access_flags & BOT_COVER_EMAGGED) ? controller.blackboard[BB_FIREBOT_EMAGGED_LINES] : controller.blackboard[BB_FIREBOT_IDLE_LINES]
controller.queue_behavior(/datum/ai_behavior/bot_speech, idle_lines, BB_ANNOUNCE_ABILITY)
#undef ANNOUNCEMENT_TIMER