From abe15dea7f9e4f737acedd04ce6091a3ee3624c5 Mon Sep 17 00:00:00 2001 From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Date: Thu, 29 Sep 2022 18:00:11 -0400 Subject: [PATCH] Bot Code Improvement - Cleanbots (#69925) About The Pull Request Removes a ton of unused vars Replaces blood/trash/pests/drawn vars with flags Adds docs to most remaining vars Registers cleanbot's on_entered when they get deputized instead of on initialize, removing calling procs uselessly. Also makes the title only update when they get a new one, also removing useless proc calls. Reworks how updating titles work so it isn't copy pasting its own code. Cleanbot stealing names now check for the mind's assigned job, rather than the living's job. Replaces single letter vars in many areas Removes two places of checking what targets to scan for, makes use of the generalized scanning proc instead. Slightly reworks process_scan to return null Replaces cleanbot's cleaning time with a define replaces 'initial' weapon force with just initial(weapon.force) Why It's Good For The Game Continuing my past work that since I haven't done a bot code improvement PR in a pretty long while, I thought I would try to get back into this with cleanbots, which used to be one of the worst bots but I fixed some major problems in the past already, so it wasn't too bad. Changelog cl refactor: Cleanbots have been entirely reworked, please report any bugs you might find. /cl --- code/__DEFINES/robots.dm | 27 ++ .../mob/living/simple_animal/bot/bot.dm | 24 +- .../mob/living/simple_animal/bot/cleanbot.dm | 313 ++++++++---------- .../mob/living/simple_animal/bot/firebot.dm | 20 +- .../mob/living/simple_animal/bot/floorbot.dm | 2 - .../mob/living/simple_animal/bot/medbot.dm | 24 +- .../mob/living/simple_animal/bot/secbot.dm | 6 + 7 files changed, 213 insertions(+), 203 deletions(-) diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index 433e3d9087d..4c172c14656 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -177,6 +177,14 @@ ///Whether we will stun & cuff or endlessly stun #define SECBOT_HANDCUFF_TARGET (1<<4) +DEFINE_BITFIELD(security_mode_flags, list( + "SECBOT_DECLARE_ARRESTS" = SECBOT_DECLARE_ARRESTS, + "SECBOT_CHECK_IDS" = SECBOT_CHECK_IDS, + "SECBOT_CHECK_WEAPONS" = SECBOT_CHECK_WEAPONS, + "SECBOT_CHECK_RECORDS" = SECBOT_CHECK_RECORDS, + "SECBOT_HANDCUFF_TARGET" = SECBOT_HANDCUFF_TARGET, +)) + //MedBOT defines ///Whether to declare if someone (we are healing) is in critical condition #define MEDBOT_DECLARE_CRIT (1<<0) @@ -184,3 +192,22 @@ #define MEDBOT_STATIONARY_MODE (1<<1) ///Whether the bot will randomly speak from time to time. This will not actually prevent all speech. #define MEDBOT_SPEAK_MODE (1<<2) + +DEFINE_BITFIELD(medical_mode_flags, list( + "MEDBOT_DECLARE_CRIT" = MEDBOT_DECLARE_CRIT, + "MEDBOT_STATIONARY_MODE" = MEDBOT_STATIONARY_MODE, + "MEDBOT_SPEAK_MODE" = MEDBOT_SPEAK_MODE, +)) + +//cleanBOT defines on what to clean +#define CLEANBOT_CLEAN_BLOOD (1<<0) +#define CLEANBOT_CLEAN_TRASH (1<<1) +#define CLEANBOT_CLEAN_PESTS (1<<2) +#define CLEANBOT_CLEAN_DRAWINGS (1<<3) + +DEFINE_BITFIELD(janitor_mode_flags, list( + "CLEANBOT_CLEAN_BLOOD" = CLEANBOT_CLEAN_BLOOD, + "CLEANBOT_CLEAN_TRASH" = CLEANBOT_CLEAN_TRASH, + "CLEANBOT_CLEAN_PESTS" = CLEANBOT_CLEAN_PESTS, + "CLEANBOT_CLEAN_DRAWINGS" = CLEANBOT_CLEAN_DRAWINGS, +)) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 5b2ad2a7359..223bc5a279a 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -37,8 +37,6 @@ var/maints_access_required = list(ACCESS_ROBOTICS) ///The Robot arm attached to this robot - has a 50% chance to drop on death. var/robot_arm = /obj/item/bodypart/r_arm/robot - ///People currently looking into a bot's UI panel. - var/list/users = list() ///The inserted (if any) pAI in this bot. var/obj/item/pai_card/paicard ///The type of bot it is, for radio control. @@ -231,7 +229,7 @@ /mob/living/simple_animal/bot/death(gibbed) explode() - ..() + return ..() /mob/living/simple_animal/bot/proc/explode() visible_message(span_boldnotice("[src] blows apart!")) @@ -257,7 +255,7 @@ if(user) log_combat(user, src, "emagged") return - else //Bot is unlocked, but the maint panel has not been opened with a screwdriver yet. + else //Bot is unlocked, but the maint panel has not been opened with a screwdriver (or through the UI) yet. to_chat(user, span_warning("You need to open maintenance panel first!")) /mob/living/simple_animal/bot/examine(mob/user) @@ -284,7 +282,7 @@ /mob/living/simple_animal/bot/adjustHealth(amount, updating_health = TRUE, forced = FALSE) if(amount > 0 && prob(10)) new /obj/effect/decal/cleanable/oil(loc) - . = ..() + return ..() /mob/living/simple_animal/bot/updatehealth() ..() @@ -525,7 +523,7 @@ continue var/scan_result = process_scan(scan) //Some bots may require additional processing when a result is selected. - if(scan_result) + if(!isnull(scan_result)) return scan_result //When the scan finds a target, run bot specific processing to select it for the next step. Empty by default. @@ -533,11 +531,14 @@ return scan_target /mob/living/simple_animal/bot/proc/check_bot(targ) - var/turf/T = get_turf(targ) - if(T) - for(var/C in T.contents) - if(istype(C,type) && (C != src)) //Is there another bot there already? If so, let's skip it so we dont all atack on top of eachother. - return TRUE //Let's abort if we find a bot so we dont have to keep rechecking + var/turf/target_turf = get_turf(targ) + if(!target_turf) + return FALSE + for(var/turf_contents in target_turf.contents) + //Is there another bot there already? If so, let's skip it so we dont all atack on top of eachother. + if(istype(turf_contents, type) && (turf_contents != src)) + return TRUE //Let's abort if we find a bot so we dont have to keep rechecking + return FALSE /mob/living/simple_animal/bot/proc/add_to_ignore(subject) if(ignore_list.len < 50) //This will help keep track of them, so the bot is always trying to reach a blocked spot. @@ -643,6 +644,7 @@ Pass a positive integer as an argument to override a bot's default speed. access_card.set_access(prev_access) tries = 0 mode = BOT_IDLE + ignore_list = list() diag_hud_set_botstat() diag_hud_set_botmode() diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index 49246c6fbb2..e4b7531ec8f 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -1,3 +1,5 @@ +#define CLEANBOT_CLEANING_TIME (1 SECONDS) + //Cleanbot /mob/living/simple_animal/bot/cleanbot name = "\improper Cleanbot" @@ -12,33 +14,28 @@ maints_access_required = list(ACCESS_ROBOTICS, ACCESS_JANITOR) radio_key = /obj/item/encryptionkey/headset_service - radio_channel = RADIO_CHANNEL_SERVICE //Service + radio_channel = RADIO_CHANNEL_SERVICE //Service //true bot_type = CLEAN_BOT hackables = "cleaning software" path_image_color = "#993299" - var/blood = 1 - var/trash = 0 - var/pests = 0 - var/drawn = 0 + ///Flags indicating what kind of cleanables we should scan for to set as our target to clean. + var/janitor_mode_flags = CLEANBOT_CLEAN_BLOOD +// Selections: CLEANBOT_CLEAN_BLOOD | CLEANBOT_CLEAN_TRASH | CLEANBOT_CLEAN_PESTS | CLEANBOT_CLEAN_DRAWINGS - var/base_icon = "cleanbot" /// icon_state to use in update_icon_state + ///the base icon state, used in updating icons. + var/base_icon = "cleanbot" + ///List of things cleanbots can target for cleaning. var/list/target_types + ///The current bot's target. var/atom/target - var/max_targets = 50 //Maximum number of targets a cleanbot can ignore. - var/closest_dist - var/closest_loc - var/failed_steps - var/next_dest - var/next_dest_loc + ///Currently attached weapon, usually a knife. var/obj/item/weapon - var/weapon_orig_force = 0 - var/chosen_name - - /// The time it takes for the cleanbot to clean something. - var/cleaning_time = 1 SECONDS + /// 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() var/static/list/officers_titles = list( @@ -77,19 +74,19 @@ JOB_LAWYER = "Esq.", ) + ///What ranks are prefixes to the name. var/static/list/prefixes = list( command_titles, security_titles, engineering_titles, ) + ///What ranks are suffixes to the name. var/static/list/suffixes = list( research_titles, medical_titles, legal_titles, ) - var/ascended = FALSE // if we have all the top titles, grant achievements to living mobs that gaze upon our cleanbot god - /mob/living/simple_animal/bot/cleanbot/autopatrol bot_mode_flags = BOT_MODE_ON | BOT_MODE_AUTOPATROL | BOT_MODE_REMOTE_ENABLED | BOT_MODE_PAI_CONTROLLABLE @@ -98,79 +95,38 @@ maints_access_required = list(ACCESS_ROBOTICS, ACCESS_JANITOR, ACCESS_MEDICAL) bot_mode_flags = ~(BOT_MODE_ON | BOT_MODE_REMOTE_ENABLED) -/mob/living/simple_animal/bot/cleanbot/proc/deputize(obj/item/W, mob/user) - if(in_range(src, user) && user.transferItemToLoc(W, src)) - balloon_alert(user, "attached") - weapon = W - weapon_orig_force = weapon.force - if(!(bot_cover_flags & BOT_COVER_EMAGGED)) - weapon.force = weapon.force / 2 - add_overlay(image(icon=weapon.lefthand_file,icon_state=weapon.inhand_icon_state)) - return TRUE - balloon_alert(user, "couldn't attach!") - return FALSE - -/mob/living/simple_animal/bot/cleanbot/proc/update_titles() - var/working_title = "" - - ascended = TRUE - - for(var/all_prefixes as anything in prefixes) - for(var/prefix_titles as anything in all_prefixes) - if(prefix_titles in stolen_valor) - working_title += all_prefixes[prefix_titles] + " " - if(prefix_titles in officers_titles) - commissioned = TRUE - else - ascended = FALSE // we didn't have the first entry in the list if we got here, so we're not achievement worthy yet - - working_title += chosen_name - - for(var/suf in suffixes) - for(var/title in suf) - if(title in stolen_valor) - working_title += " " + suf[title] - break - else - ascended = FALSE - - name = working_title - -/mob/living/simple_animal/bot/cleanbot/examine(mob/user) - . = ..() - if(weapon) - . += "[span_warning("Is that \a [weapon] taped to it...?")]" - - if(ascended && user.stat == CONSCIOUS && user.client) - user.client.give_award(/datum/award/achievement/misc/cleanboss, user) - /mob/living/simple_animal/bot/cleanbot/Initialize(mapload) . = ..() - AddComponent(/datum/component/cleaner, cleaning_time, on_cleaned_callback=CALLBACK(src, /atom/.proc/update_icon_state)) + AddComponent(/datum/component/cleaner, CLEANBOT_CLEANING_TIME, \ + on_cleaned_callback = CALLBACK(src, /atom/.proc/update_appearance, UPDATE_ICON)) - chosen_name = name get_targets() - update_icon_state() + update_appearance(UPDATE_ICON) // Doing this hurts my soul, but simplebot access reworks are for another day. var/datum/id_trim/job/jani_trim = SSid_access.trim_singletons_by_path[/datum/id_trim/job/janitor] access_card.add_access(jani_trim.access + jani_trim.wildcard_access) prev_access = access_card.access.Copy() - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = .proc/on_entered, - ) - AddElement(/datum/element/connect_loc, loc_connections) GLOB.janitor_devices += src /mob/living/simple_animal/bot/cleanbot/Destroy() GLOB.janitor_devices -= src if(weapon) - var/atom/Tsec = drop_location() - weapon.force = weapon_orig_force - drop_part(weapon, Tsec) + var/atom/drop_loc = drop_location() + weapon.force = initial(weapon.force) + drop_part(weapon, drop_loc) return ..() +/mob/living/simple_animal/bot/cleanbot/examine(mob/user) + . = ..() + if(!weapon) + return + . += "[span_warning("Is that \a [weapon] taped to it...?")]" + + if(ascended && user.stat == CONSCIOUS && user.client) + user.client.give_award(/datum/award/achievement/misc/cleanboss, user) + /mob/living/simple_animal/bot/cleanbot/update_icon_state() . = ..() switch(mode) @@ -179,101 +135,120 @@ else icon_state = "[base_icon][get_bot_flag(bot_mode_flags, BOT_MODE_ON)]" +/mob/living/simple_animal/bot/cleanbot/vv_edit_var(var_name, var_value) + . = ..() + if(var_name == NAMEOF(src, base_icon)) + update_appearance(UPDATE_ICON) + +/mob/living/simple_animal/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!") + weapon = knife + if(!(bot_cover_flags & BOT_COVER_EMAGGED)) + weapon.force = weapon.force / 2 + add_overlay(image(icon = weapon.lefthand_file, icon_state = weapon.inhand_icon_state)) + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = .proc/on_entered, + ) + AddElement(/datum/element/connect_loc, loc_connections) + return TRUE + +/mob/living/simple_animal/bot/cleanbot/proc/update_titles() + name = initial(name) //reset the name + ascended = TRUE + + for(var/title in (prefixes + suffixes)) + for(var/title_name in title) + if(!(title_name in stolen_valor)) + ascended = FALSE + continue + + if(title_name in officers_titles) + commissioned = TRUE + if(title in prefixes) + name = title[title_name] + " [name]" + if(title in suffixes) + name = "[name] " + title[title_name] + /mob/living/simple_animal/bot/cleanbot/bot_reset() - ..() - if(weapon && bot_cover_flags & BOT_COVER_EMAGGED) - weapon.force = weapon_orig_force - ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable. + . = ..() target = null /mob/living/simple_animal/bot/cleanbot/proc/on_entered(datum/source, atom/movable/AM) SIGNAL_HANDLER + if(!weapon || !has_gravity() || !iscarbon(AM)) + return - zone_selected = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - if(weapon && has_gravity() && ismob(AM)) - var/mob/living/carbon/C = AM - if(!istype(C)) - return - - if(!(C.job in stolen_valor)) - stolen_valor += C.job + var/mob/living/carbon/stabbed_carbon = AM + if(!(stabbed_carbon.mind.assigned_role.title in stolen_valor)) + stolen_valor += stabbed_carbon.mind.assigned_role.title update_titles() - INVOKE_ASYNC(weapon, /obj/item.proc/attack, C, src) - C.Knockdown(20) + zone_selected = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + INVOKE_ASYNC(weapon, /obj/item.proc/attack, stabbed_carbon, src) + stabbed_carbon.Knockdown(20) /mob/living/simple_animal/bot/cleanbot/attackby(obj/item/attacking_item, mob/living/user, params) if(istype(attacking_item, /obj/item/knife) && !user.combat_mode) - to_chat(user, span_notice("You start attaching \the [attacking_item] to \the [src]...")) + balloon_alert(user, "attaching knife...") if(!do_after(user, 2.5 SECONDS, target = src)) return deputize(attacking_item, user) return return ..() -/mob/living/simple_animal/bot/cleanbot/emag_act(mob/user) - ..() - +/mob/living/simple_animal/bot/cleanbot/emag_act(mob/user, obj/item/card/emag/emag_card) + . = ..() if(!(bot_cover_flags & BOT_COVER_EMAGGED)) return + if(weapon) - weapon.force = weapon_orig_force + weapon.force = initial(weapon.force) if(user) to_chat(user, span_danger("[src] buzzes and beeps.")) + get_targets() //recalibrate target list /mob/living/simple_animal/bot/cleanbot/process_scan(atom/scan_target) if(iscarbon(scan_target)) var/mob/living/carbon/scan_carbon = scan_target - if(scan_carbon.stat != DEAD && scan_carbon.body_position == LYING_DOWN) - return scan_carbon - else if(is_type_in_typecache(scan_target, target_types)) + if(!(scan_carbon in view(DEFAULT_SCAN_RANGE, src))) + return null + if(scan_carbon.stat == DEAD) + return null + if(scan_carbon.body_position != LYING_DOWN) + return null + return scan_carbon + if(is_type_in_typecache(scan_target, target_types)) return scan_target +/mob/living/simple_animal/bot/cleanbot/handle_atom_del(atom/deleting_atom) + if(deleting_atom == weapon) + weapon = null + update_appearance(UPDATE_ICON) + return ..() + /mob/living/simple_animal/bot/cleanbot/handle_automated_action() . = ..() if(!.) return - if(mode == BOT_CLEANING) return if(bot_cover_flags & BOT_COVER_EMAGGED) //Emag functions - var/mob/living/carbon/victim = locate(/mob/living/carbon) in loc if(victim && victim == target) UnarmedAttack(victim) // Acid spray - - if(isopenturf(loc)) - if(prob(15)) // Wets floors and spawns foam randomly - UnarmedAttack(src) - + if(isopenturf(loc) && prob(15)) // Wets floors and spawns foam randomly + UnarmedAttack(src) else if(prob(5)) audible_message("[src] makes an excited beeping booping sound!") - if(ismob(target)) - if(!(target in view(DEFAULT_SCAN_RANGE, src))) - target = null - if(!process_scan(target)) - target = null - + if(ismob(target) && isnull(process_scan(target))) + target = null if(!target) - var/list/scan_targets = list() - - if(bot_cover_flags & BOT_COVER_EMAGGED) // When emagged, ignore cleanables and scan humans first. - scan_targets += list(/mob/living/carbon) - if(pests) - scan_targets += list(/mob/living/simple_animal) - if(trash) - scan_targets += list( - /obj/item/trash, - /obj/item/food/deadmouse, - ) - scan_targets += list( - /obj/effect/decal/cleanable, - /obj/effect/decal/remains, - ) - - target = scan(scan_targets) + target = scan(target_types) if(!target && bot_mode_flags & BOT_MODE_AUTOPATROL) //Search for cleanables it can see. switch(mode) @@ -288,17 +263,17 @@ return if(loc == get_turf(target)) - if(!(check_bot(target))) + if(check_bot(target)) + shuffle = TRUE //Shuffle the list the next time we scan so we dont both go the same way. + path = list() + else UnarmedAttack(target) //Rather than check at every step of the way, let's check before we do an action, so we can rescan before the other bot. if(QDELETED(target)) //We done here. target = null mode = BOT_IDLE return - else - shuffle = TRUE //Shuffle the list the next time we scan so we dont both go the same way. - path = list() - if(!path || path.len == 0) //No path, need a new one + if(!length(path)) //No path, need a new one //Try to produce a path to the target, and ignore airlocks to which it has access. path = get_path_to(src, target, 30, id=access_card) if(!bot_move(target)) @@ -313,6 +288,11 @@ return /mob/living/simple_animal/bot/cleanbot/proc/get_targets() + if(bot_cover_flags & BOT_COVER_EMAGGED) // When emagged, ignore cleanables and scan humans first. + target_types = list(/mob/living/carbon) + return + + //main targets target_types = list( /obj/effect/decal/cleanable/oil, /obj/effect/decal/cleanable/vomit, @@ -326,23 +306,23 @@ /obj/effect/decal/remains, ) - if(blood) + if(janitor_mode_flags & CLEANBOT_CLEAN_BLOOD) target_types += list( /obj/effect/decal/cleanable/xenoblood, /obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/trail_holder, ) - if(pests) + if(janitor_mode_flags & CLEANBOT_CLEAN_PESTS) target_types += list( /mob/living/basic/cockroach, /mob/living/simple_animal/mouse, ) - if(drawn) + if(janitor_mode_flags & CLEANBOT_CLEAN_DRAWINGS) target_types += list(/obj/effect/decal/cleanable/crayon) - if(trash) + if(janitor_mode_flags & CLEANBOT_CLEAN_TRASH) target_types += list( /obj/item/trash, /obj/item/food/deadmouse, @@ -350,36 +330,40 @@ target_types = typecacheof(target_types) -/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A, proximity_flag, list/modifiers) +/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED)) return - if(ismopable(A)) + . = ..() + if(ismopable(attack_target)) mode = BOT_CLEANING update_icon_state() - var/turf/T = get_turf(A) - start_cleaning(src, T, src) + var/turf/turf_to_clean = get_turf(attack_target) + start_cleaning(src, turf_to_clean, src) target = null mode = BOT_IDLE - else if(isitem(A) || istype(A, /obj/effect/decal/remains)) - visible_message(span_danger("[src] sprays hydrofluoric acid at [A]!")) + else if(isitem(attack_target) || istype(attack_target, /obj/effect/decal)) + visible_message(span_danger("[src] sprays hydrofluoric acid at [attack_target]!")) playsound(src, 'sound/effects/spray2.ogg', 50, TRUE, -6) - A.acid_act(75, 10) + attack_target.acid_act(75, 10) target = null - else if(istype(A, /mob/living/basic/cockroach) || ismouse(A)) - var/mob/living/living_target = A + else if(istype(attack_target, /mob/living/basic/cockroach) || ismouse(attack_target)) + var/mob/living/living_target = attack_target if(!living_target.stat) visible_message(span_danger("[src] smashes [living_target] with its mop!")) living_target.death() target = null else if(bot_cover_flags & BOT_COVER_EMAGGED) //Emag functions - if(iscarbon(A)) - var/mob/living/carbon/victim = A + if(iscarbon(attack_target)) + var/mob/living/carbon/victim = attack_target if(victim.stat == DEAD)//cleanbots always finish the job + target = null return - victim.visible_message(span_danger("[src] sprays hydrofluoric acid at [victim]!"), span_userdanger("[src] sprays you with hydrofluoric acid!")) + victim.visible_message( + span_danger("[src] sprays hydrofluoric acid at [victim]!"), + span_userdanger("[src] sprays you with hydrofluoric acid!")) var/phrase = pick( "PURIFICATION IN PROGRESS.", "THIS IS FOR ALL THE MESSES YOU'VE MADE ME CLEAN.", @@ -396,22 +380,19 @@ victim.emote("scream") playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6) victim.acid_act(5, 100) - else if(A == src) // Wets floors and spawns foam randomly + else if(attack_target == src) // Wets floors and spawns foam randomly if(prob(75)) - var/turf/open/T = loc - if(istype(T)) - T.MakeSlippery(TURF_WET_WATER, min_wet_time = 20 SECONDS, wet_time_to_add = 15 SECONDS) + var/turf/open/current_floor = loc + if(istype(current_floor)) + current_floor.MakeSlippery(TURF_WET_WATER, min_wet_time = 20 SECONDS, wet_time_to_add = 15 SECONDS) else visible_message(span_danger("[src] whirs and bubbles violently, before releasing a plume of froth!")) new /obj/effect/particle_effect/fluid/foam(loc) - else - ..() - /mob/living/simple_animal/bot/cleanbot/explode() - var/atom/Tsec = drop_location() - new /obj/item/reagent_containers/cup/bucket(Tsec) - new /obj/item/assembly/prox_sensor(Tsec) + var/atom/drop_loc = drop_location() + new /obj/item/reagent_containers/cup/bucket(drop_loc) + new /obj/item/assembly/prox_sensor(drop_loc) return ..() // Variables sent to TGUI @@ -419,10 +400,10 @@ var/list/data = ..() if(!(bot_cover_flags & BOT_COVER_LOCKED) || issilicon(user)|| isAdminGhostAI(user)) - data["custom_controls"]["clean_blood"] = blood - data["custom_controls"]["clean_trash"] = trash - data["custom_controls"]["clean_graffiti"] = drawn - data["custom_controls"]["pest_control"] = pests + 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 @@ -433,11 +414,11 @@ switch(action) if("clean_blood") - blood = !blood + janitor_mode_flags ^= CLEANBOT_CLEAN_BLOOD if("pest_control") - pests = !pests + janitor_mode_flags ^= CLEANBOT_CLEAN_PESTS if("clean_trash") - trash = !trash + janitor_mode_flags ^= CLEANBOT_CLEAN_TRASH if("clean_graffiti") - drawn = !drawn + janitor_mode_flags ^= CLEANBOT_CLEAN_DRAWINGS get_targets() diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index e3cb673b642..03012317d71 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -89,7 +89,6 @@ ..() target_fire = null old_target_fire = null - ignore_list = list() set_anchored(FALSE) update_appearance() @@ -250,19 +249,16 @@ //Look for burning people or turfs around the bot /mob/living/simple_animal/bot/firebot/process_scan(atom/scan_target) - var/result - if(scan_target == src) - return result + return src + if(!is_burning(scan_target)) + return null - if(is_burning(scan_target)) - if((detected_cooldown + DETECTED_VOICE_INTERVAL) < world.time) - speak("Fire detected!") - playsound(src, 'sound/voice/firebot/detected.ogg', 50, FALSE) - detected_cooldown = world.time - result = scan_target - - return result + if((detected_cooldown + DETECTED_VOICE_INTERVAL) < world.time) + speak("Fire detected!") + playsound(src, 'sound/voice/firebot/detected.ogg', 50, FALSE) + detected_cooldown = world.time + return scan_target /mob/living/simple_animal/bot/firebot/should_atmos_process(datum/gas_mixture/air, exposed_temperature) return (exposed_temperature > T0C + 200 || exposed_temperature < BODYTEMP_COLD_DAMAGE_LIMIT) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 258ef5502f2..8288f039f65 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -23,7 +23,6 @@ var/obj/item/stack/tile/tilestack var/fixfloors = TRUE var/autotile = FALSE - var/max_targets = 50 var/turf/target var/toolbox = /obj/item/storage/toolbox/mechanical var/toolbox_color = "" @@ -73,7 +72,6 @@ /mob/living/simple_animal/bot/floorbot/bot_reset() ..() target = null - ignore_list = list() toggle_magnet(FALSE) /mob/living/simple_animal/bot/floorbot/attackby(obj/item/W , mob/user, params) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index af3ed8ad0b2..410d6d718e3 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -232,20 +232,20 @@ /mob/living/simple_animal/bot/medbot/process_scan(mob/living/carbon/human/H) if(H.stat == DEAD) - return - + return null if((H == oldpatient) && (world.time < last_found + 200)) - return + return null + if(!assess_patient(H)) + return null - if(assess_patient(H)) - last_found = world.time - if(COOLDOWN_FINISHED(src, last_newpatient_speak)) - COOLDOWN_START(src, last_newpatient_speak, MEDBOT_NEW_PATIENTSPEAK_DELAY) - var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg') - var/message = pick(messagevoice) - speak(message) - playsound(src, messagevoice[message], 50, FALSE) - return H + last_found = world.time + if(COOLDOWN_FINISHED(src, last_newpatient_speak)) + COOLDOWN_START(src, last_newpatient_speak, MEDBOT_NEW_PATIENTSPEAK_DELAY) + var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg') + var/message = pick(messagevoice) + speak(message) + playsound(src, messagevoice[message], 50, FALSE) + return H /* * Proc used in a callback for before this medibot is tipped by the tippable component. diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index bc27d056ecd..471f39c0651 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -149,6 +149,12 @@ playsound(src, 'sound/machines/defib_zap.ogg', 50) visible_message(span_warning("[src] shakes and speeds up!")) +/mob/living/simple_animal/bot/secbot/handle_atom_del(atom/deleting_atom) + if(deleting_atom == weapon) + weapon = null + update_appearance() + return ..() + // Variables sent to TGUI /mob/living/simple_animal/bot/secbot/ui_data(mob/user) var/list/data = ..()