mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
basic firebots refactor (#83861)
## About The Pull Request this refactors firebots into basic bots. also this adds a small addition of emagged firebots giving out (extremely dubious) fire safety hazard tips!  ## Why It's Good For The Game refactors firebots into basic bots and makes them alot more responsive and helpful ## Changelog 🆑 refactor: firebots are now basic bots /🆑 Fixes #83568 --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Afevis <ShizCalev@users.noreply.github.com>
This commit is contained in:
co-authored by
MrMelbert
Afevis
parent
4165d8a3ba
commit
13d759b1a8
@@ -0,0 +1,169 @@
|
||||
#define FOAM_INTERVAL 5 SECONDS
|
||||
|
||||
/mob/living/basic/bot/firebot
|
||||
name = "\improper Firebot"
|
||||
desc = "A little fire extinguishing bot. He looks rather anxious."
|
||||
icon = 'icons/mob/silicon/aibots.dmi'
|
||||
icon_state = "firebot1"
|
||||
light_color = "#8cffc9"
|
||||
light_power = 0.8
|
||||
|
||||
req_access = list(ACCESS_ROBOTICS, ACCESS_CONSTRUCTION)
|
||||
radio_key = /obj/item/encryptionkey/headset_eng
|
||||
radio_channel = RADIO_CHANNEL_ENGINEERING
|
||||
bot_type = FIRE_BOT
|
||||
additional_access = /datum/id_trim/job/station_engineer
|
||||
hackables = "fire safety protocols"
|
||||
path_image_color = "#FFA500"
|
||||
possessed_message = "You are a firebot! Protect the station from fires to the best of your ability!"
|
||||
ai_controller = /datum/ai_controller/basic_controller/bot/firebot
|
||||
///our inbuilt fire extinguisher
|
||||
var/obj/item/extinguisher/internal_ext
|
||||
|
||||
///Flags firebots use to decide how they function.
|
||||
var/firebot_mode_flags = FIREBOT_EXTINGUISH_PEOPLE | FIREBOT_EXTINGUISH_FLAMES
|
||||
//Selections: FIREBOT_STATIONARY_MODE | FIREBOT_EXTINGUISH_PEOPLE | FIREBOT_EXTINGUISH_FLAMES
|
||||
///cooldown before we release foam all over
|
||||
COOLDOWN_DECLARE(foam_cooldown)
|
||||
|
||||
|
||||
/mob/living/basic/bot/firebot/generate_speak_list()
|
||||
var/static/list/idle_lines = list(
|
||||
FIREBOT_VOICED_NO_FIRES = 'sound/voice/firebot/nofires.ogg',
|
||||
FIREBOT_VOICED_ONLY_YOU = 'sound/voice/firebot/onlyyou.ogg',
|
||||
FIREBOT_VOICED_TEMPERATURE_NOMINAL = 'sound/voice/firebot/tempnominal.ogg',
|
||||
FIREBOT_VOICED_KEEP_COOL = 'sound/voice/firebot/keepitcool.ogg',
|
||||
)
|
||||
var/static/list/fire_detected_lines = list(
|
||||
FIREBOT_VOICED_FIRE_DETECTED = 'sound/voice/firebot/detected.ogg',
|
||||
FIREBOT_VOICED_STOP_DROP = 'sound/voice/firebot/stopdropnroll.ogg',
|
||||
FIREBOT_VOICED_EXTINGUISHING = 'sound/voice/firebot/extinguishing.ogg',
|
||||
)
|
||||
var/static/list/emagged_lines = list(
|
||||
FIREBOT_VOICED_CANDLE_TIP = 'sound/voice/firebot/candle_tip.ogg',
|
||||
FIREBOT_VOICED_ELECTRIC_FIRE = 'sound/voice/firebot/electric_fire_tip.ogg',
|
||||
FIREBOT_VOICED_FUEL_TIP = 'sound/voice/firebot/gasoline_tip.ogg'
|
||||
)
|
||||
ai_controller.set_blackboard_key(BB_FIREBOT_EMAGGED_LINES, emagged_lines)
|
||||
ai_controller.set_blackboard_key(BB_FIREBOT_IDLE_LINES, idle_lines)
|
||||
ai_controller.set_blackboard_key(BB_FIREBOT_FIRE_DETECTED_LINES, fire_detected_lines)
|
||||
return idle_lines + fire_detected_lines
|
||||
|
||||
/mob/living/basic/bot/firebot/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
|
||||
update_appearance(UPDATE_ICON)
|
||||
var/static/list/things_to_extinguish = typecacheof(list(/mob/living/carbon))
|
||||
ai_controller.set_blackboard_key(BB_FIREBOT_CAN_EXTINGUISH, things_to_extinguish)
|
||||
create_extinguisher()
|
||||
AddElement(/datum/element/atmos_sensitive, mapload)
|
||||
|
||||
/mob/living/basic/bot/firebot/Destroy()
|
||||
QDEL_NULL(internal_ext)
|
||||
return ..()
|
||||
|
||||
/mob/living/basic/bot/firebot/bot_reset(bypass_ai_reset)
|
||||
. = ..()
|
||||
create_extinguisher()
|
||||
|
||||
/mob/living/basic/bot/firebot/proc/create_extinguisher()
|
||||
internal_ext = new /obj/item/extinguisher(src)
|
||||
internal_ext.safety = FALSE
|
||||
internal_ext.precision = TRUE
|
||||
internal_ext.max_water = INFINITY
|
||||
internal_ext.refill()
|
||||
|
||||
/mob/living/basic/bot/firebot/melee_attack(atom/attacked_atom, list/modifiers, ignore_cooldown = FALSE)
|
||||
use_extinguisher(attacked_atom)
|
||||
|
||||
/mob/living/basic/bot/firebot/RangedAttack(atom/attacked_atom, list/modifiers)
|
||||
use_extinguisher(attacked_atom)
|
||||
|
||||
/mob/living/basic/bot/firebot/proc/use_extinguisher(atom/attacked_atom)
|
||||
if(!(bot_mode_flags & BOT_MODE_ON))
|
||||
return
|
||||
spray_water(attacked_atom)
|
||||
|
||||
/mob/living/basic/bot/firebot/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
. = ..()
|
||||
if(!(bot_access_flags & BOT_COVER_EMAGGED))
|
||||
return
|
||||
|
||||
to_chat(user, span_warning("You enable the very ironically named \"fighting with fire\" mode, and disable the targeting safeties.")) // heheehe. funny
|
||||
|
||||
audible_message(span_danger("[src] buzzes oddly!"))
|
||||
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
|
||||
internal_ext.chem = /datum/reagent/clf3 //Refill the internal extinguisher with liquid fire
|
||||
internal_ext.power = 3
|
||||
internal_ext.safety = FALSE
|
||||
internal_ext.precision = FALSE
|
||||
internal_ext.max_water = INFINITY
|
||||
internal_ext.refill()
|
||||
return TRUE
|
||||
|
||||
// Variables sent to TGUI
|
||||
/mob/living/basic/bot/firebot/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
if(!(bot_access_flags & BOT_COVER_LOCKED) || HAS_SILICON_ACCESS(user))
|
||||
data["custom_controls"]["extinguish_fires"] = firebot_mode_flags & FIREBOT_EXTINGUISH_FLAMES
|
||||
data["custom_controls"]["extinguish_people"] = firebot_mode_flags & FIREBOT_EXTINGUISH_PEOPLE
|
||||
data["custom_controls"]["stationary_mode"] = firebot_mode_flags & FIREBOT_STATIONARY_MODE
|
||||
return data
|
||||
|
||||
// Actions received from TGUI
|
||||
/mob/living/basic/bot/firebot/ui_act(action, params)
|
||||
. = ..()
|
||||
if(. || (bot_access_flags & BOT_COVER_LOCKED && !HAS_SILICON_ACCESS(usr)))
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("extinguish_fires")
|
||||
firebot_mode_flags ^= FIREBOT_EXTINGUISH_FLAMES
|
||||
if("extinguish_people")
|
||||
firebot_mode_flags ^= FIREBOT_EXTINGUISH_PEOPLE
|
||||
if("stationary_mode")
|
||||
firebot_mode_flags ^= FIREBOT_STATIONARY_MODE
|
||||
update_appearance()
|
||||
|
||||
/mob/living/basic/bot/firebot/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
|
||||
return (exposed_temperature > T0C + 200 || exposed_temperature < BODYTEMP_COLD_DAMAGE_LIMIT)
|
||||
|
||||
/mob/living/basic/bot/firebot/atmos_expose(datum/gas_mixture/air, exposed_temperature)
|
||||
if(!COOLDOWN_FINISHED(src, foam_cooldown))
|
||||
return
|
||||
var/datum/effect_system/fluid_spread/foam/firefighting/foam = new
|
||||
foam.set_up(3, holder = src, location = loc)
|
||||
foam.start()
|
||||
COOLDOWN_START(src, foam_cooldown, FOAM_INTERVAL)
|
||||
|
||||
/mob/living/basic/bot/firebot/proc/spray_water(atom/attacked_atom)
|
||||
if(firebot_mode_flags & FIREBOT_STATIONARY_MODE)
|
||||
flick("firebots_use", src)
|
||||
else
|
||||
flick("firebot1_use", src)
|
||||
internal_ext?.melee_attack_chain(src, attacked_atom)
|
||||
|
||||
/mob/living/basic/bot/firebot/update_icon_state()
|
||||
. = ..()
|
||||
if(!(bot_mode_flags & BOT_MODE_ON))
|
||||
icon_state = "firebot0"
|
||||
return
|
||||
if(IsStun() || IsParalyzed() || (firebot_mode_flags & FIREBOT_STATIONARY_MODE)) //Bot has yellow light to indicate stationary mode.
|
||||
icon_state = "firebots1"
|
||||
return
|
||||
icon_state = "firebot1"
|
||||
|
||||
/mob/living/basic/bot/firebot/explode()
|
||||
var/turf/my_turf = drop_location()
|
||||
|
||||
new /obj/item/assembly/prox_sensor(my_turf)
|
||||
new /obj/item/clothing/head/utility/hardhat/red(my_turf)
|
||||
|
||||
if(isopenturf(my_turf))
|
||||
var/turf/open/open_turf = my_turf
|
||||
open_turf.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
|
||||
|
||||
return ..()
|
||||
|
||||
#undef FOAM_INTERVAL
|
||||
@@ -0,0 +1,132 @@
|
||||
#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 = 45 SECONDS,
|
||||
)
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/respond_to_summon,
|
||||
/datum/ai_planning_subtree/manage_unreachable_list,
|
||||
/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(target_key, 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.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, target, TRUE)
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user