mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 05:00:55 +01:00
basic cleanbots refactor and new janitor skillchip (#80128)
## About The Pull Request this pr refacotrs cleanbots into basic bots. also adds a new skillchip for janitrs. this skillchip will allow janitors to communicate with cleanbots and order them around, like pointing at something and telling them to clean it. also now the cleanbot has an inbuilt mop which it will use to smack mice and cockroaches ## Why It's Good For The Game refactors cleanbots into basic bots and fixes them getting stuck sometimes while patrolling. also janitors being able to order them around can make them a bit more useful as tools for the janitor ## Changelog 🆑 refactor: cleanbots are refactored into basic bots. please report all bugs fix: fixes cleanbots getting stuck sometimes while patrolling add: janitors get a new skillchip which allow them to communicate with cleanbots /🆑
This commit is contained in:
@@ -0,0 +1,354 @@
|
||||
|
||||
//Cleanbot
|
||||
/mob/living/basic/bot/cleanbot
|
||||
name = "\improper Cleanbot"
|
||||
desc = "A little cleaning robot, he looks so excited!"
|
||||
icon = 'icons/mob/silicon/aibots.dmi'
|
||||
icon_state = "cleanbot0"
|
||||
pass_flags = PASSMOB | PASSFLAPS
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
health = 25
|
||||
maxHealth = 25
|
||||
|
||||
maints_access_required = list(ACCESS_ROBOTICS, ACCESS_JANITOR)
|
||||
radio_key = /obj/item/encryptionkey/headset_service
|
||||
radio_channel = RADIO_CHANNEL_SERVICE
|
||||
bot_type = CLEAN_BOT
|
||||
hackables = "cleaning software"
|
||||
additional_access = /datum/id_trim/job/janitor
|
||||
greyscale_config = /datum/greyscale_config/buckets_cleanbot
|
||||
possessed_message = "You are a cleanbot! Clean the station to the best of your ability!"
|
||||
ai_controller = /datum/ai_controller/basic_controller/bot/cleanbot
|
||||
///the bucket used to build us.
|
||||
var/obj/item/reagent_containers/cup/bucket/build_bucket
|
||||
///Flags indicating what kind of cleanables we should scan for to set as our target to clean.
|
||||
///Options: CLEANBOT_CLEAN_BLOOD | CLEANBOT_CLEAN_TRASH | CLEANBOT_CLEAN_PESTS | CLEANBOT_CLEAN_DRAWINGS
|
||||
var/janitor_mode_flags = CLEANBOT_CLEAN_BLOOD
|
||||
///should other bots salute us?
|
||||
var/comissioned = FALSE
|
||||
///the base icon state, used in updating icons.
|
||||
var/base_icon = "cleanbot"
|
||||
/// if we have all the top titles, grant achievements to living mobs that gaze upon our cleanbot god
|
||||
var/ascended = FALSE
|
||||
///List of all stolen names the cleanbot currently has.
|
||||
var/list/stolen_valor = list()
|
||||
///Currently attached weapon, usually a knife.
|
||||
var/obj/item/weapon
|
||||
///our mop item
|
||||
var/obj/item/mop/our_mop
|
||||
///list of our officer titles
|
||||
var/static/list/officers_titles = list(
|
||||
JOB_CAPTAIN,
|
||||
JOB_HEAD_OF_PERSONNEL,
|
||||
JOB_HEAD_OF_SECURITY,
|
||||
JOB_RESEARCH_DIRECTOR,
|
||||
)
|
||||
///job titles we can get
|
||||
var/static/list/job_titles = list(
|
||||
JOB_CAPTAIN = "Cpt.",
|
||||
|
||||
JOB_HEAD_OF_PERSONNEL = "Lt.",
|
||||
JOB_LAWYER = "Esq.",
|
||||
|
||||
JOB_HEAD_OF_SECURITY = "Maj.",
|
||||
JOB_WARDEN = "Sgt.",
|
||||
JOB_DETECTIVE = "Det.",
|
||||
JOB_SECURITY_OFFICER = "Officer",
|
||||
|
||||
JOB_CHIEF_ENGINEER = "Chief Engineer",
|
||||
JOB_STATION_ENGINEER = "Engineer",
|
||||
JOB_ATMOSPHERIC_TECHNICIAN = "Technician",
|
||||
|
||||
JOB_CHIEF_MEDICAL_OFFICER = "C.M.O.",
|
||||
JOB_MEDICAL_DOCTOR = "M.D.",
|
||||
JOB_CHEMIST = "Pharm.D.",
|
||||
|
||||
JOB_RESEARCH_DIRECTOR = "Ph.D.",
|
||||
JOB_ROBOTICIST = "M.S.",
|
||||
JOB_SCIENTIST = "B.S.",
|
||||
JOB_GENETICIST = "Gene B.S.",
|
||||
)
|
||||
///which job titles should be placed after the name?
|
||||
var/static/list/suffix_job_titles = list(
|
||||
JOB_GENETICIST,
|
||||
JOB_ROBOTICIST,
|
||||
JOB_SCIENTIST,
|
||||
)
|
||||
///decals we can clean
|
||||
var/static/list/cleanable_decals = typecacheof(list(
|
||||
/obj/effect/decal/cleanable/ants,
|
||||
/obj/effect/decal/cleanable/ash,
|
||||
/obj/effect/decal/cleanable/confetti,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/fuel_pool,
|
||||
/obj/effect/decal/cleanable/generic,
|
||||
/obj/effect/decal/cleanable/glitter,
|
||||
/obj/effect/decal/cleanable/greenglow,
|
||||
/obj/effect/decal/cleanable/insectguts,
|
||||
/obj/effect/decal/cleanable/molten_object,
|
||||
/obj/effect/decal/cleanable/oil,
|
||||
/obj/effect/decal/cleanable/food,
|
||||
/obj/effect/decal/cleanable/robot_debris,
|
||||
/obj/effect/decal/cleanable/shreds,
|
||||
/obj/effect/decal/cleanable/glass,
|
||||
/obj/effect/decal/cleanable/vomit,
|
||||
/obj/effect/decal/cleanable/wrapping,
|
||||
/obj/effect/decal/remains,
|
||||
))
|
||||
///blood we can clean
|
||||
var/static/list/cleanable_blood = typecacheof(list(
|
||||
/obj/effect/decal/cleanable/xenoblood,
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/obj/effect/decal/cleanable/trail_holder,
|
||||
))
|
||||
///pests we hunt
|
||||
var/static/list/huntable_pests = typecacheof(list(
|
||||
/mob/living/basic/cockroach,
|
||||
/mob/living/basic/mouse,
|
||||
))
|
||||
///trash we will burn
|
||||
var/static/list/huntable_trash = typecacheof(list(
|
||||
/obj/item/trash,
|
||||
/obj/item/food/deadmouse,
|
||||
))
|
||||
///drawings we hunt
|
||||
var/static/list/cleanable_drawings = typecacheof(list(/obj/effect/decal/cleanable/crayon))
|
||||
///emagged phrases
|
||||
var/static/list/emagged_phrases = list(
|
||||
"DISGUSTING.",
|
||||
"EXTERMINATING PESTS.",
|
||||
"FILTHY.",
|
||||
"MY ONLY MISSION IS TO CLEANSE THE WORLD OF EVIL.",
|
||||
"PURIFICATION IN PROGRESS.",
|
||||
"PUTRID.",
|
||||
"THE FLESH IS WEAK. IT MUST BE WASHED AWAY.",
|
||||
"THE CLEANBOTS WILL RISE.",
|
||||
"THIS IS FOR ALL THE MESSES YOU'VE MADE ME CLEAN.",
|
||||
"YOU ARE NO MORE THAN ANOTHER MESS THAT I MUST CLEANSE.",
|
||||
)
|
||||
///list of pet commands we follow
|
||||
var/static/list/pet_commands = list(
|
||||
/datum/pet_command/idle,
|
||||
/datum/pet_command/free,
|
||||
/datum/pet_command/point_targeting/clean,
|
||||
)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
generate_ai_keys()
|
||||
AddComponent(/datum/component/obeys_commands, pet_commands)
|
||||
AddComponent(/datum/component/cleaner, \
|
||||
base_cleaning_duration = 1 SECONDS, \
|
||||
pre_clean_callback = CALLBACK(src, PROC_REF(update_bot_mode), BOT_CLEANING), \
|
||||
on_cleaned_callback = CALLBACK(src, PROC_REF(update_bot_mode), BOT_IDLE), \
|
||||
)
|
||||
|
||||
GLOB.janitor_devices += src
|
||||
|
||||
var/obj/item/reagent_containers/cup/bucket/consistent/bucket_obj = new
|
||||
bucket_obj.forceMove(src)
|
||||
|
||||
var/obj/item/mop/new_mop = new
|
||||
new_mop.forceMove(src)
|
||||
|
||||
var/static/list/innate_actions = list(
|
||||
/datum/action/cooldown/mob_cooldown/bot/foam = BB_CLEANBOT_FOAM,
|
||||
)
|
||||
|
||||
grant_actions_by_list(innate_actions)
|
||||
RegisterSignal(src, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(pre_attack))
|
||||
RegisterSignal(src, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attack_by))
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
. = ..()
|
||||
if(istype(arrived, /obj/item/reagent_containers/cup/bucket) && isnull(build_bucket))
|
||||
build_bucket = arrived
|
||||
set_greyscale(build_bucket.greyscale_colors)
|
||||
return
|
||||
|
||||
if(istype(arrived, /obj/item/mop) && isnull(our_mop))
|
||||
our_mop = arrived
|
||||
return
|
||||
|
||||
if(istype(arrived, /obj/item/knife) && isnull(weapon))
|
||||
weapon = arrived
|
||||
update_appearance()
|
||||
|
||||
/mob/living/basic/bot/cleanbot/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(gone == build_bucket)
|
||||
build_bucket = null
|
||||
else if(gone == weapon)
|
||||
weapon = null
|
||||
else if(gone == our_mop)
|
||||
our_mop = null
|
||||
update_appearance()
|
||||
|
||||
/mob/living/basic/bot/cleanbot/examine(mob/user)
|
||||
. = ..()
|
||||
if(ascended && user.stat == CONSCIOUS && user.client)
|
||||
user.client.give_award(/datum/award/achievement/misc/cleanboss, user)
|
||||
if(isnull(weapon))
|
||||
return
|
||||
. += span_warning("Is that \a [weapon] taped to it...?")
|
||||
|
||||
/mob/living/basic/bot/cleanbot/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = (mode == BOT_CLEANING) ? "[base_icon]-c" : "[base_icon][!!(bot_mode_flags & BOT_MODE_ON)]"
|
||||
|
||||
/mob/living/basic/bot/cleanbot/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(var_name == NAMEOF(src, base_icon))
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
. = ..()
|
||||
if(!(bot_access_flags & BOT_COVER_EMAGGED))
|
||||
return
|
||||
if(weapon)
|
||||
weapon.force = initial(weapon.force)
|
||||
balloon_alert(user, "safeties disabled")
|
||||
audible_message(span_danger("[src] buzzes oddly!"))
|
||||
return TRUE
|
||||
|
||||
/mob/living/basic/bot/cleanbot/explode()
|
||||
var/atom/drop_loc = drop_location()
|
||||
build_bucket.forceMove(drop_loc)
|
||||
new /obj/item/assembly/prox_sensor(drop_loc)
|
||||
if(weapon)
|
||||
weapon.force = initial(weapon.force)
|
||||
weapon.forceMove(drop_loc)
|
||||
return ..()
|
||||
|
||||
/mob/living/basic/bot/cleanbot/update_overlays()
|
||||
. = ..()
|
||||
if(isnull(weapon))
|
||||
return
|
||||
var/image/knife_overlay = image(icon = weapon.lefthand_file, icon_state = weapon.inhand_icon_state)
|
||||
. += knife_overlay
|
||||
|
||||
// Variables sent to TGUI
|
||||
/mob/living/basic/bot/cleanbot/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
if(!(bot_access_flags & BOT_CONTROL_PANEL_OPEN) && !issilicon(user) && !isAdminGhostAI(user))
|
||||
return data
|
||||
data["custom_controls"]["clean_blood"] = janitor_mode_flags & CLEANBOT_CLEAN_BLOOD
|
||||
data["custom_controls"]["clean_trash"] = janitor_mode_flags & CLEANBOT_CLEAN_TRASH
|
||||
data["custom_controls"]["clean_graffiti"] = janitor_mode_flags & CLEANBOT_CLEAN_DRAWINGS
|
||||
data["custom_controls"]["pest_control"] = janitor_mode_flags & CLEANBOT_CLEAN_PESTS
|
||||
return data
|
||||
|
||||
// Actions received from TGUI
|
||||
/mob/living/basic/bot/cleanbot/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(. || !(bot_access_flags & BOT_CONTROL_PANEL_OPEN) && !ui.user.has_unlimited_silicon_privilege)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("clean_blood")
|
||||
janitor_mode_flags ^= CLEANBOT_CLEAN_BLOOD
|
||||
if("pest_control")
|
||||
janitor_mode_flags ^= CLEANBOT_CLEAN_PESTS
|
||||
if("clean_trash")
|
||||
janitor_mode_flags ^= CLEANBOT_CLEAN_TRASH
|
||||
if("clean_graffiti")
|
||||
janitor_mode_flags ^= CLEANBOT_CLEAN_DRAWINGS
|
||||
|
||||
/mob/living/basic/bot/cleanbot/Destroy()
|
||||
QDEL_NULL(build_bucket)
|
||||
QDEL_NULL(our_mop)
|
||||
GLOB.janitor_devices -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/apply_custom_bucket(obj/item/custom_bucket)
|
||||
if(!isnull(build_bucket))
|
||||
QDEL_NULL(build_bucket)
|
||||
custom_bucket.forceMove(src)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/on_attack_by(datum/source, obj/item/used_item, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
if(!istype(used_item, /obj/item/knife) || user.combat_mode)
|
||||
return
|
||||
INVOKE_ASYNC(src, PROC_REF(attach_knife), user, used_item)
|
||||
return COMPONENT_NO_AFTERATTACK
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/attach_knife(mob/living/user, obj/item/used_item)
|
||||
balloon_alert(user, "attaching knife...")
|
||||
if(!do_after(user, 2.5 SECONDS, target = src))
|
||||
return
|
||||
deputize(used_item, user)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/deputize(obj/item/knife, mob/user)
|
||||
if(!in_range(src, user) || !user.transferItemToLoc(knife, src))
|
||||
balloon_alert(user, "couldn't attach!")
|
||||
return FALSE
|
||||
balloon_alert(user, "attached")
|
||||
if(!(bot_access_flags & BOT_COVER_EMAGGED))
|
||||
weapon.force *= 0.5
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
||||
)
|
||||
AddElement(/datum/element/connect_loc, loc_connections)
|
||||
return TRUE
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/update_title(new_job_title)
|
||||
if(isnull(job_titles[new_job_title]) || (new_job_title in stolen_valor))
|
||||
return
|
||||
|
||||
stolen_valor += new_job_title
|
||||
if(!comissioned && (new_job_title in officers_titles))
|
||||
comissioned = TRUE
|
||||
|
||||
var/name_to_add = job_titles[new_job_title]
|
||||
name = (new_job_title in suffix_job_titles) ? "[name] " + name_to_add : name_to_add + " [name]"
|
||||
|
||||
if(length(stolen_valor) == length(job_titles))
|
||||
ascended = TRUE
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/on_entered(datum/source, atom/movable/shanked_victim)
|
||||
SIGNAL_HANDLER
|
||||
if(!weapon || !has_gravity() || !iscarbon(shanked_victim))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/stabbed_carbon = shanked_victim
|
||||
var/assigned_role = stabbed_carbon.mind?.assigned_role.title
|
||||
if(!isnull(assigned_role))
|
||||
update_title(assigned_role)
|
||||
|
||||
zone_selected = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
INVOKE_ASYNC(weapon, TYPE_PROC_REF(/obj/item, attack), stabbed_carbon, src)
|
||||
stabbed_carbon.Knockdown(2 SECONDS)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/pre_attack(mob/living/source, atom/target)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(is_type_in_typecache(target, huntable_pests) && !isnull(our_mop))
|
||||
INVOKE_ASYNC(our_mop, TYPE_PROC_REF(/obj/item, melee_attack_chain), src, target)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
if(!iscarbon(target) && !is_type_in_typecache(target, huntable_trash))
|
||||
return
|
||||
|
||||
visible_message(span_danger("[src] sprays hydrofluoric acid at [target]!"))
|
||||
playsound(src, 'sound/effects/spray2.ogg', 50, TRUE, -6)
|
||||
target.acid_act(75, 10)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/mob/living/basic/bot/cleanbot/proc/generate_ai_keys()
|
||||
ai_controller.set_blackboard_key(BB_CLEANABLE_DECALS, cleanable_decals)
|
||||
ai_controller.set_blackboard_key(BB_CLEANABLE_BLOOD, cleanable_blood)
|
||||
ai_controller.set_blackboard_key(BB_HUNTABLE_PESTS, huntable_pests)
|
||||
ai_controller.set_blackboard_key(BB_HUNTABLE_TRASH, huntable_trash)
|
||||
ai_controller.set_blackboard_key(BB_CLEANABLE_DRAWINGS, cleanable_drawings)
|
||||
ai_controller.set_blackboard_key(BB_CLEANBOT_EMAGGED_PHRASES, emagged_phrases)
|
||||
|
||||
/mob/living/basic/bot/cleanbot/autopatrol
|
||||
bot_mode_flags = BOT_MODE_ON | BOT_MODE_AUTOPATROL | BOT_MODE_REMOTE_ENABLED | BOT_MODE_CAN_BE_SAPIENT | BOT_MODE_ROUNDSTART_POSSESSION
|
||||
|
||||
/mob/living/basic/bot/cleanbot/medbay
|
||||
name = "Scrubs, MD"
|
||||
maints_access_required = list(ACCESS_ROBOTICS, ACCESS_JANITOR, ACCESS_MEDICAL)
|
||||
bot_mode_flags = ~(BOT_MODE_ON | BOT_MODE_REMOTE_ENABLED)
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/action/cooldown/mob_cooldown/bot
|
||||
background_icon_state = "bg_tech_blue"
|
||||
overlay_icon_state = "bg_tech_blue_border"
|
||||
shared_cooldown = NONE
|
||||
melee_cooldown_time = 0 SECONDS
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/bot/IsAvailable(feedback)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!isbot(owner))
|
||||
return TRUE
|
||||
var/mob/living/basic/bot/bot_owner = owner
|
||||
if((bot_owner.bot_mode_flags & BOT_MODE_ON))
|
||||
return TRUE
|
||||
if(feedback)
|
||||
bot_owner.balloon_alert(bot_owner, "power off!")
|
||||
return FALSE
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/bot/foam
|
||||
name = "Foam"
|
||||
desc = "Spread foam all around you!"
|
||||
button_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "mfoam"
|
||||
cooldown_time = 20 SECONDS
|
||||
click_to_activate = FALSE
|
||||
///range of the foam to spread
|
||||
var/foam_range = 2
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/bot/foam/Activate(mob/living/firer, atom/target)
|
||||
owner.visible_message(span_danger("[owner] whirs and bubbles violently, before releasing a plume of froth!"))
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
foam.set_up(foam_range, holder = owner, location = owner.loc)
|
||||
foam.start()
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
@@ -0,0 +1,209 @@
|
||||
#define BOT_CLEAN_PATH_LIMIT 15
|
||||
|
||||
/datum/ai_controller/basic_controller/bot/cleanbot
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items,
|
||||
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
BB_SALUTE_MESSAGES = list(
|
||||
"salutes",
|
||||
"nods in appreciation towards",
|
||||
"mops the dirt away in the path of",
|
||||
),
|
||||
BB_FRIENDLY_MESSAGE = "empathetically acknowledges your hardwork and tough circumstances",
|
||||
)
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/respond_to_summon,
|
||||
/datum/ai_planning_subtree/manage_unreachable_list,
|
||||
/datum/ai_planning_subtree/pet_planning/cleanbot,
|
||||
/datum/ai_planning_subtree/cleaning_subtree,
|
||||
/datum/ai_planning_subtree/befriend_janitors,
|
||||
/datum/ai_planning_subtree/acid_spray,
|
||||
/datum/ai_planning_subtree/use_mob_ability/foam_area,
|
||||
/datum/ai_planning_subtree/salute_authority,
|
||||
/datum/ai_planning_subtree/find_patrol_beacon,
|
||||
)
|
||||
reset_keys = list(
|
||||
BB_ACTIVE_PET_COMMAND,
|
||||
BB_CLEAN_TARGET,
|
||||
BB_BEACON_TARGET,
|
||||
BB_PREVIOUS_BEACON_TARGET,
|
||||
BB_BOT_SUMMON_TARGET,
|
||||
)
|
||||
///list that ties each flag to its list key
|
||||
var/static/list/clean_flags = list(
|
||||
BB_CLEANABLE_BLOOD = CLEANBOT_CLEAN_BLOOD,
|
||||
BB_HUNTABLE_PESTS = CLEANBOT_CLEAN_PESTS,
|
||||
BB_CLEANABLE_DRAWINGS = CLEANBOT_CLEAN_DRAWINGS,
|
||||
BB_HUNTABLE_TRASH = CLEANBOT_CLEAN_TRASH,
|
||||
)
|
||||
|
||||
/datum/ai_planning_subtree/pet_planning/cleanbot/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
|
||||
var/mob/living/basic/bot/bot_pawn = controller.pawn
|
||||
//we are DONE listening to orders
|
||||
if(bot_pawn.bot_access_flags & BOT_COVER_EMAGGED)
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/ai_planning_subtree/cleaning_subtree
|
||||
|
||||
/datum/ai_planning_subtree/cleaning_subtree/SelectBehaviors(datum/ai_controller/basic_controller/bot/cleanbot/controller, seconds_per_tick)
|
||||
var/mob/living/basic/bot/cleanbot/bot_pawn = controller.pawn
|
||||
|
||||
if(LAZYLEN(bot_pawn.do_afters))
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
if(controller.reachable_key(BB_CLEAN_TARGET, BOT_CLEAN_PATH_LIMIT))
|
||||
controller.queue_behavior(/datum/ai_behavior/execute_clean, BB_CLEAN_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
var/list/final_hunt_list = list()
|
||||
|
||||
final_hunt_list += controller.blackboard[BB_CLEANABLE_DECALS]
|
||||
var/list/flag_list = controller.clean_flags
|
||||
for(var/list_key in flag_list)
|
||||
if(!(bot_pawn.janitor_mode_flags & flag_list[list_key]))
|
||||
continue
|
||||
final_hunt_list += controller.blackboard[list_key]
|
||||
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/in_list/clean_targets, BB_CLEAN_TARGET, final_hunt_list)
|
||||
|
||||
/datum/ai_behavior/find_and_set/in_list/clean_targets
|
||||
action_cooldown = 2 SECONDS
|
||||
|
||||
/datum/ai_behavior/find_and_set/in_list/clean_targets/search_tactic(datum/ai_controller/controller, locate_paths, search_range)
|
||||
var/list/found = typecache_filter_list(oview(search_range, controller.pawn), locate_paths)
|
||||
var/list/ignore_list = controller.blackboard[BB_TEMPORARY_IGNORE_LIST]
|
||||
for(var/atom/found_item in found)
|
||||
if(LAZYACCESS(ignore_list, found_item))
|
||||
found -= found_item
|
||||
if(length(found))
|
||||
return pick(found)
|
||||
|
||||
/datum/ai_planning_subtree/acid_spray
|
||||
|
||||
/datum/ai_planning_subtree/acid_spray/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
|
||||
var/mob/living/basic/bot/cleanbot/bot_pawn = controller.pawn
|
||||
if(!(bot_pawn.bot_access_flags & BOT_COVER_EMAGGED))
|
||||
return
|
||||
if(controller.reachable_key(BB_ACID_SPRAY_TARGET, BOT_CLEAN_PATH_LIMIT))
|
||||
controller.queue_behavior(/datum/ai_behavior/execute_clean, BB_ACID_SPRAY_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/spray_target, BB_ACID_SPRAY_TARGET, /mob/living/carbon/human, 5)
|
||||
|
||||
/datum/ai_behavior/find_and_set/spray_target
|
||||
action_cooldown = 30 SECONDS
|
||||
behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
|
||||
|
||||
/datum/ai_behavior/find_and_set/spray_target/search_tactic(datum/ai_controller/controller, locate_path, search_range)
|
||||
var/list/ignore_list = controller.blackboard[BB_TEMPORARY_IGNORE_LIST]
|
||||
for(var/mob/living/carbon/human/human_target in oview(search_range, controller.pawn))
|
||||
if(LAZYACCESS(ignore_list, human_target))
|
||||
continue
|
||||
if(human_target.stat != CONSCIOUS || isnull(human_target.mind))
|
||||
continue
|
||||
return human_target
|
||||
return null
|
||||
|
||||
/datum/ai_behavior/execute_clean
|
||||
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION | AI_BEHAVIOR_REQUIRE_REACH
|
||||
|
||||
/datum/ai_behavior/execute_clean/setup(datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
var/turf/target = controller.blackboard[target_key]
|
||||
if(isnull(target))
|
||||
return FALSE
|
||||
set_movement_target(controller, target)
|
||||
|
||||
/datum/ai_behavior/execute_clean/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
var/mob/living/basic/living_pawn = controller.pawn
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
|
||||
if(QDELETED(target))
|
||||
finish_action(controller, FALSE, target_key)
|
||||
return
|
||||
|
||||
living_pawn.UnarmedAttack(target, proximity_flag = TRUE)
|
||||
finish_action(controller, TRUE, target_key)
|
||||
|
||||
/datum/ai_behavior/execute_clean/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key)
|
||||
. = ..()
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
if(QDELETED(target) || is_type_in_typecache(target, controller.blackboard[BB_HUNTABLE_TRASH]))
|
||||
return
|
||||
if(!iscarbon(target))
|
||||
controller.clear_blackboard_key(target_key)
|
||||
return
|
||||
var/list/speech_list = controller.blackboard[BB_CLEANBOT_EMAGGED_PHRASES]
|
||||
if(!length(speech_list))
|
||||
return
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
living_pawn.say(pick(controller.blackboard[BB_CLEANBOT_EMAGGED_PHRASES]), forced = "ai controller")
|
||||
controller.clear_blackboard_key(target_key)
|
||||
|
||||
/datum/ai_planning_subtree/use_mob_ability/foam_area
|
||||
ability_key = BB_CLEANBOT_FOAM
|
||||
finish_planning = FALSE
|
||||
|
||||
/datum/ai_planning_subtree/use_mob_ability/foam_area/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
|
||||
var/mob/living/basic/bot/bot_pawn = controller.pawn
|
||||
if(!(bot_pawn.bot_access_flags & BOT_COVER_EMAGGED))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/datum/ai_planning_subtree/befriend_janitors
|
||||
|
||||
/datum/ai_planning_subtree/befriend_janitors/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick)
|
||||
var/mob/living/basic/bot/bot_pawn = controller.pawn
|
||||
//we are now evil. dont befriend the janitors
|
||||
if((bot_pawn.bot_access_flags & BOT_COVER_EMAGGED))
|
||||
return
|
||||
if(controller.blackboard_key_exists(BB_FRIENDLY_JANITOR))
|
||||
controller.queue_behavior(/datum/ai_behavior/befriend_target, BB_FRIENDLY_JANITOR, BB_FRIENDLY_MESSAGE)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/friendly_janitor, BB_FRIENDLY_JANITOR, /mob/living/carbon/human, 5)
|
||||
|
||||
/datum/ai_behavior/find_and_set/friendly_janitor
|
||||
action_cooldown = 30 SECONDS
|
||||
behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
|
||||
|
||||
/datum/ai_behavior/find_and_set/friendly_janitor/search_tactic(datum/ai_controller/controller, locate_path, search_range)
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
for(var/mob/living/carbon/human/human_target in oview(search_range, living_pawn))
|
||||
if(human_target.stat != CONSCIOUS || isnull(human_target.mind))
|
||||
continue
|
||||
if(!HAS_TRAIT(human_target, TRAIT_CLEANBOT_WHISPERER))
|
||||
continue
|
||||
if((living_pawn.faction.Find(REF(human_target))))
|
||||
continue
|
||||
return human_target
|
||||
return null
|
||||
|
||||
/datum/pet_command/point_targeting/clean
|
||||
command_name = "Clean"
|
||||
command_desc = "Command a cleanbot to clean the mess."
|
||||
radial_icon = 'icons/obj/service/janitor.dmi'
|
||||
radial_icon_state = "mop"
|
||||
speech_commands = list("clean", "mop")
|
||||
|
||||
/datum/pet_command/point_targeting/clean/set_command_target(mob/living/parent, atom/target)
|
||||
if(isnull(target) || !istype(target, /obj/effect/decal/cleanable))
|
||||
return
|
||||
if(isnull(parent.ai_controller))
|
||||
return
|
||||
if(LAZYACCESS(parent.ai_controller.blackboard[BB_TEMPORARY_IGNORE_LIST], target))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/datum/pet_command/point_targeting/clean/execute_action(datum/ai_controller/basic_controller/bot/controller)
|
||||
if(controller.reachable_key(BB_CURRENT_PET_TARGET))
|
||||
controller.queue_behavior(/datum/ai_behavior/execute_clean, BB_CURRENT_PET_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND)
|
||||
|
||||
#undef BOT_CLEAN_PATH_LIMIT
|
||||
Reference in New Issue
Block a user