mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-17 13:12:37 +00:00
* hygeienbots basic bots (#80435) ## About The Pull Request turns hygenic bots into basic bots. also now PAIs and people can play as hygeinebots. and they can wear hats ## Why It's Good For The Game transforms hyginebots into basic bots. their old AI used to handle all the logic. i moved some of the logic to the mob itself so players can also clean (or burn) things. also this pr will add pathing limits to bots, in the case the jps movement thinks it can reach something, but actually cant, in which case the bot will give up the chase ## Changelog 🆑 refactor: hygeinebots are now basic bots. please report all the bugs fix: fixes hygenebots not being able to patrol add: hygeinebots can now be controlled by Players /🆑 * hygeienbots basic bots --------- Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
354 lines
12 KiB
Plaintext
354 lines
12 KiB
Plaintext
|
|
//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
|
|
possessed_message = "You are a cleanbot! Clean the station to the best of your ability!"
|
|
ai_controller = /datum/ai_controller/basic_controller/bot/cleanbot
|
|
path_image_color = "#993299"
|
|
///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,
|
|
))
|
|
///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,
|
|
/obj/effect/decal/remains,
|
|
))
|
|
///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 = 2 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/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
|
|
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)
|