mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-21 12:08:55 +01:00
Refactors how bots scan for stuff (#66681)
Refactors how bots scan for stuff and also improves Cleanbots' code. This started off as a Cleanbot refactor but I got too-deep into how it scans for stuff, so I decided to instead focus my PR on that first since it's something I want to tread carefully with. removes oldloc var from Cleanbot, Medibot and Floorbot, because it was all unused. I didn't even notice how bad this was before, because Secbots use their own snowflake thing instead of scanning like all the other bots do, which sounds like a good future PR.
This commit is contained in:
@@ -487,53 +487,50 @@
|
||||
|
||||
//Generalized behavior code, override where needed!
|
||||
|
||||
/*
|
||||
scan() will search for a given type (such as turfs, human mobs, or objects) in the bot's view range, and return a single result.
|
||||
Arguments: The object type to be searched (such as "/mob/living/carbon/human"), the old scan result to be ignored, if one exists,
|
||||
and the view range, which defaults to 7 (full screen) if an override is not passed.
|
||||
If the bot maintains an ignore list, it is also checked here.
|
||||
|
||||
Example usage: patient = scan(/mob/living/carbon/human, oldpatient, 1)
|
||||
The proc would return a human next to the bot to be set to the patient var.
|
||||
Pass the desired type path itself, declaring a temporary var beforehand is not required.
|
||||
*/
|
||||
/mob/living/simple_animal/bot/proc/scan(scan_type, old_target, scan_range = DEFAULT_SCAN_RANGE)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
/**
|
||||
* Attempt to scan tiles near [src], first by checking adjacent, then if a target is still not found, nearby.
|
||||
*
|
||||
* scan_types - list (of typepaths) that nearby tiles are being scanned for.
|
||||
* old_target - what has already been scanned, and will early return at checkscan.
|
||||
* scan_range - how far away from [src] will be scanned, if nothing is found directly adjacent.
|
||||
*/
|
||||
/mob/living/simple_animal/bot/proc/scan(list/scan_types, old_target, scan_range = DEFAULT_SCAN_RANGE)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return
|
||||
var/list/adjacent = T.get_atmos_adjacent_turfs(1)
|
||||
var/list/adjacent = current_turf.get_atmos_adjacent_turfs(1)
|
||||
if(shuffle) //If we were on the same tile as another bot, let's randomize our choices so we dont both go the same way
|
||||
adjacent = shuffle(adjacent)
|
||||
shuffle = FALSE
|
||||
for(var/scan in adjacent)//Let's see if there's something right next to us first!
|
||||
|
||||
for(var/turf/scan as anything in adjacent) //Let's see if there's something right next to us first!
|
||||
if(check_bot(scan)) //Is there another bot there? Then let's just skip it
|
||||
continue
|
||||
if(isturf(scan_type)) //If we're lookeing for a turf we can just run the checks directly!
|
||||
var/final_result = checkscan(scan,scan_type,old_target)
|
||||
if(final_result)
|
||||
return final_result
|
||||
else
|
||||
var/turf/turfy = scan
|
||||
for(var/deepscan in turfy.contents)//Check the contents since adjacent is turfs
|
||||
var/final_result = checkscan(deepscan,scan_type,old_target)
|
||||
if(final_result)
|
||||
return final_result
|
||||
for (var/scan in shuffle(view(scan_range, src))-adjacent) //Search for something in range!
|
||||
var/final_result = checkscan(scan,scan_type,old_target)
|
||||
var/final_result = checkscan(scan, scan_types, old_target)
|
||||
if(final_result)
|
||||
return final_result
|
||||
|
||||
/mob/living/simple_animal/bot/proc/checkscan(scan, scan_type, old_target)
|
||||
if(!istype(scan, scan_type)) //Check that the thing we found is the type we want!
|
||||
return FALSE //If not, keep searching!
|
||||
if((REF(scan) in ignore_list) || (scan == old_target)) //Filter for blacklisted elements, usually unreachable or previously processed oness
|
||||
return FALSE
|
||||
for(var/turf/scanned_turfs as anything in shuffle(view(scan_range, src)) - adjacent) //Search for something in range, minus what we already checked.
|
||||
if(check_bot(scanned_turfs)) //Is there another bot there? Then let's just skip it
|
||||
continue
|
||||
var/final_result = checkscan(scanned_turfs, scan_types, old_target)
|
||||
if(final_result)
|
||||
return final_result
|
||||
|
||||
var/scan_result = process_scan(scan) //Some bots may require additional processing when a result is selected.
|
||||
if(scan_result)
|
||||
return scan_result
|
||||
else
|
||||
return FALSE //The current element failed assessment, move on to the next.
|
||||
/mob/living/simple_animal/bot/proc/checkscan(atom/scan, list/scan_types, old_target)
|
||||
for(var/scan_type in scan_types)
|
||||
if(!istype(scan, scan_type)) //Check that the thing we found is the type we want!
|
||||
continue //If not, keep searching!
|
||||
if((REF(scan) in ignore_list) || (scan == old_target)) //Filter for blacklisted elements, usually unreachable or previously processed oness
|
||||
continue
|
||||
|
||||
var/scan_result = process_scan(scan) //Some bots may require additional processing when a result is selected.
|
||||
if(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.
|
||||
/mob/living/simple_animal/bot/proc/process_scan(scan_target)
|
||||
return scan_target
|
||||
|
||||
/mob/living/simple_animal/bot/proc/check_bot(targ)
|
||||
var/turf/T = get_turf(targ)
|
||||
@@ -542,11 +539,6 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
|
||||
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
|
||||
|
||||
//When the scan finds a target, run bot specific processing to select it for the next step. Empty by default.
|
||||
/mob/living/simple_animal/bot/proc/process_scan(scan_target)
|
||||
return scan_target
|
||||
|
||||
|
||||
/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.
|
||||
ignore_list += REF(subject)
|
||||
|
||||
@@ -24,9 +24,8 @@
|
||||
|
||||
var/base_icon = "cleanbot" /// icon_state to use in update_icon_state
|
||||
var/list/target_types
|
||||
var/obj/effect/decal/cleanable/target
|
||||
var/atom/target
|
||||
var/max_targets = 50 //Maximum number of targets a cleanbot can ignore.
|
||||
var/oldloc = null
|
||||
var/closest_dist
|
||||
var/closest_loc
|
||||
var/failed_steps
|
||||
@@ -37,18 +36,54 @@
|
||||
var/weapon_orig_force = 0
|
||||
var/chosen_name
|
||||
|
||||
var/list/stolen_valor
|
||||
var/list/stolen_valor = list()
|
||||
|
||||
var/static/list/officers = list("Captain", "Head of Personnel", "Head of Security")
|
||||
var/static/list/command = list("Captain" = "Cpt.","Head of Personnel" = "Lt.")
|
||||
var/static/list/security = list("Head of Security" = "Maj.", "Warden" = "Sgt.", "Detective" = "Det.", "Security Officer" = "Officer")
|
||||
var/static/list/engineering = list("Chief Engineer" = "Chief Engineer", "Station Engineer" = "Engineer", "Atmospherics Technician" = "Technician")
|
||||
var/static/list/medical = list("Chief Medical Officer" = "C.M.O.", "Medical Doctor" = "M.D.", "Chemist" = "Pharm.D.")
|
||||
var/static/list/research = list("Research Director" = "Ph.D.", "Roboticist" = "M.S.", "Scientist" = "B.S.")
|
||||
var/static/list/legal = list("Lawyer" = "Esq.")
|
||||
var/static/list/officers_titles = list(
|
||||
JOB_CAPTAIN,
|
||||
JOB_HEAD_OF_PERSONNEL,
|
||||
JOB_HEAD_OF_SECURITY,
|
||||
JOB_RESEARCH_DIRECTOR,
|
||||
)
|
||||
var/static/list/command_titles = list(
|
||||
JOB_CAPTAIN = "Cpt.",
|
||||
JOB_HEAD_OF_PERSONNEL = "Lt.",
|
||||
)
|
||||
var/static/list/security_titles = list(
|
||||
JOB_HEAD_OF_SECURITY = "Maj.",
|
||||
JOB_WARDEN = "Sgt.",
|
||||
JOB_DETECTIVE = "Det.",
|
||||
JOB_SECURITY_OFFICER = "Officer",
|
||||
)
|
||||
var/static/list/engineering_titles = list(
|
||||
JOB_CHIEF_ENGINEER = "Chief Engineer",
|
||||
JOB_STATION_ENGINEER = "Engineer",
|
||||
JOB_ATMOSPHERIC_TECHNICIAN = "Technician",
|
||||
)
|
||||
var/static/list/medical_titles = list(
|
||||
JOB_CHIEF_MEDICAL_OFFICER = "C.M.O.",
|
||||
JOB_MEDICAL_DOCTOR = "M.D.",
|
||||
JOB_CHEMIST = "Pharm.D.",
|
||||
)
|
||||
var/static/list/research_titles = list(
|
||||
JOB_RESEARCH_DIRECTOR = "Ph.D.",
|
||||
JOB_ROBOTICIST = "M.S.",
|
||||
JOB_SCIENTIST = "B.S.",
|
||||
JOB_GENETICIST = "Gene B.S.",
|
||||
)
|
||||
var/static/list/legal_titles = list(
|
||||
JOB_LAWYER = "Esq.",
|
||||
)
|
||||
|
||||
var/list/prefixes
|
||||
var/list/suffixes
|
||||
var/static/list/prefixes = list(
|
||||
command_titles,
|
||||
security_titles,
|
||||
engineering_titles,
|
||||
)
|
||||
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
|
||||
|
||||
@@ -75,13 +110,12 @@
|
||||
|
||||
ascended = TRUE
|
||||
|
||||
for(var/pref in prefixes)
|
||||
for(var/title in pref)
|
||||
if(title in stolen_valor)
|
||||
working_title += pref[title] + " "
|
||||
if(title in officers)
|
||||
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
|
||||
break
|
||||
else
|
||||
ascended = FALSE // we didn't have the first entry in the list if we got here, so we're not achievement worthy yet
|
||||
|
||||
@@ -100,7 +134,7 @@
|
||||
/mob/living/simple_animal/bot/cleanbot/examine(mob/user)
|
||||
. = ..()
|
||||
if(weapon)
|
||||
. += " [span_warning("Is that \a [weapon] taped to it...?")]"
|
||||
. += "[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)
|
||||
@@ -116,10 +150,7 @@
|
||||
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()
|
||||
stolen_valor = list()
|
||||
|
||||
prefixes = list(command, security, engineering)
|
||||
suffixes = list(research, medical, legal)
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)
|
||||
@@ -148,7 +179,6 @@
|
||||
weapon.force = weapon_orig_force
|
||||
ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable.
|
||||
target = null
|
||||
oldloc = null
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/proc/on_entered(datum/source, atom/movable/AM)
|
||||
SIGNAL_HANDLER
|
||||
@@ -166,13 +196,14 @@
|
||||
INVOKE_ASYNC(weapon, /obj/item.proc/attack, C, src)
|
||||
C.Knockdown(20)
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/attackby(obj/item/W, mob/living/user, params)
|
||||
if(istype(W, /obj/item/knife) && !user.combat_mode)
|
||||
to_chat(user, span_notice("You start attaching \the [W] to \the [src]..."))
|
||||
if(do_after(user, 25, target = src))
|
||||
deputize(W, user)
|
||||
else
|
||||
return ..()
|
||||
/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]..."))
|
||||
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)
|
||||
..()
|
||||
@@ -184,27 +215,29 @@
|
||||
if(user)
|
||||
to_chat(user, span_danger("[src] buzzes and beeps."))
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/process_scan(atom/A)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
if(C.stat != DEAD && C.body_position == LYING_DOWN)
|
||||
return C
|
||||
else if(is_type_in_typecache(A, target_types))
|
||||
return A
|
||||
/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))
|
||||
return scan_target
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/handle_automated_action()
|
||||
if(!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(mode == BOT_CLEANING)
|
||||
return
|
||||
|
||||
if(bot_cover_flags & BOT_COVER_EMAGGED) //Emag functions
|
||||
if(isopenturf(loc))
|
||||
for(var/mob/living/carbon/victim in loc)
|
||||
if(victim != target)
|
||||
UnarmedAttack(victim) // Acid spray
|
||||
|
||||
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)
|
||||
|
||||
@@ -217,23 +250,24 @@
|
||||
if(!process_scan(target))
|
||||
target = null
|
||||
|
||||
if(!target && bot_cover_flags & BOT_COVER_EMAGGED) // When emagged, target humans who slipped on the water and melt their faces off
|
||||
target = scan(/mob/living/carbon)
|
||||
if(!target)
|
||||
var/list/scan_targets = list()
|
||||
|
||||
if(!target && pests) //Search for pests to exterminate first.
|
||||
target = scan(/mob/living/simple_animal)
|
||||
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,
|
||||
)
|
||||
|
||||
if(!target) //Search for decals then.
|
||||
target = scan(/obj/effect/decal/cleanable)
|
||||
|
||||
if(!target) //Checks for remains
|
||||
target = scan(/obj/effect/decal/remains)
|
||||
|
||||
if(!target && trash) //Then for trash.
|
||||
target = scan(/obj/item/trash)
|
||||
|
||||
if(!target && trash) //Search for dead mices.
|
||||
target = scan(/obj/item/food/deadmouse)
|
||||
target = scan(scan_targets)
|
||||
|
||||
if(!target && bot_mode_flags & BOT_MODE_AUTOPATROL) //Search for cleanables it can see.
|
||||
switch(mode)
|
||||
@@ -241,15 +275,14 @@
|
||||
start_patrol()
|
||||
if(BOT_PATROL)
|
||||
bot_patrol()
|
||||
|
||||
if(target)
|
||||
else if(target)
|
||||
if(QDELETED(target) || !isturf(target.loc))
|
||||
target = null
|
||||
mode = BOT_IDLE
|
||||
return
|
||||
|
||||
if(loc == get_turf(target))
|
||||
if(!(check_bot(target) && prob(50))) //Target is not defined at the parent. 50% chance to still try and clean so we dont get stuck on the last blood drop.
|
||||
if(!(check_bot(target)))
|
||||
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
|
||||
@@ -273,8 +306,6 @@
|
||||
mode = BOT_IDLE
|
||||
return
|
||||
|
||||
oldloc = loc
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/proc/get_targets()
|
||||
target_types = list(
|
||||
/obj/effect/decal/cleanable/oil,
|
||||
@@ -290,20 +321,26 @@
|
||||
)
|
||||
|
||||
if(blood)
|
||||
target_types += /obj/effect/decal/cleanable/xenoblood
|
||||
target_types += /obj/effect/decal/cleanable/blood
|
||||
target_types += /obj/effect/decal/cleanable/trail_holder
|
||||
target_types += list(
|
||||
/obj/effect/decal/cleanable/xenoblood,
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/obj/effect/decal/cleanable/trail_holder,
|
||||
)
|
||||
|
||||
if(pests)
|
||||
target_types += /mob/living/basic/cockroach
|
||||
target_types += /mob/living/simple_animal/mouse
|
||||
target_types += list(
|
||||
/mob/living/basic/cockroach,
|
||||
/mob/living/simple_animal/mouse,
|
||||
)
|
||||
|
||||
if(drawn)
|
||||
target_types += /obj/effect/decal/cleanable/crayon
|
||||
target_types += list(/obj/effect/decal/cleanable/crayon)
|
||||
|
||||
if(trash)
|
||||
target_types += /obj/item/trash
|
||||
target_types += /obj/item/food/deadmouse
|
||||
target_types += list(
|
||||
/obj/item/trash,
|
||||
/obj/item/food/deadmouse,
|
||||
)
|
||||
|
||||
target_types = typecacheof(target_types)
|
||||
|
||||
@@ -341,9 +378,18 @@
|
||||
return
|
||||
|
||||
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.", "THE FLESH IS WEAK. IT MUST BE WASHED AWAY.",
|
||||
"THE CLEANBOTS WILL RISE.", "YOU ARE NO MORE THAN ANOTHER MESS THAT I MUST CLEANSE.", "FILTHY.", "DISGUSTING.", "PUTRID.",
|
||||
"MY ONLY MISSION IS TO CLEANSE THE WORLD OF EVIL.", "EXTERMINATING PESTS.")
|
||||
var/phrase = pick(
|
||||
"PURIFICATION IN PROGRESS.",
|
||||
"THIS IS FOR ALL THE MESSES YOU'VE MADE ME CLEAN.",
|
||||
"THE FLESH IS WEAK. IT MUST BE WASHED AWAY.",
|
||||
"THE CLEANBOTS WILL RISE.",
|
||||
"YOU ARE NO MORE THAN ANOTHER MESS THAT I MUST CLEANSE.",
|
||||
"FILTHY.",
|
||||
"DISGUSTING.",
|
||||
"PUTRID.",
|
||||
"MY ONLY MISSION IS TO CLEANSE THE WORLD OF EVIL.",
|
||||
"EXTERMINATING PESTS.",
|
||||
)
|
||||
say(phrase)
|
||||
victim.emote("scream")
|
||||
playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6)
|
||||
|
||||
@@ -187,12 +187,14 @@
|
||||
target_fire = null
|
||||
var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE)
|
||||
|
||||
var/list/things_to_extinguish = list()
|
||||
if(extinguish_people)
|
||||
target_fire = scan(/mob/living, old_target_fire, scan_range) // Scan for burning humans first
|
||||
things_to_extinguish += list(/mob/living)
|
||||
|
||||
if(target_fire == null && extinguish_fires)
|
||||
target_fire = scan(/turf/open, old_target_fire, scan_range) // Scan for burning turfs second
|
||||
things_to_extinguish += list(/turf/open)
|
||||
|
||||
target_fire = scan(things_to_extinguish, old_target_fire, scan_range) // Scan for burning turfs second
|
||||
old_target_fire = target_fire
|
||||
|
||||
// Target reached ENGAGE WATER CANNON
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
var/autotile = FALSE
|
||||
var/max_targets = 50
|
||||
var/turf/target
|
||||
var/oldloc = null
|
||||
var/toolbox = /obj/item/storage/toolbox/mechanical
|
||||
var/toolbox_color = ""
|
||||
|
||||
@@ -74,7 +73,6 @@
|
||||
/mob/living/simple_animal/bot/floorbot/bot_reset()
|
||||
..()
|
||||
target = null
|
||||
oldloc = null
|
||||
ignore_list = list()
|
||||
toggle_magnet(FALSE)
|
||||
|
||||
@@ -187,6 +185,7 @@
|
||||
if(prob(5))
|
||||
audible_message("[src] makes an excited booping beeping sound!")
|
||||
|
||||
var/list/tiles_scanned = list()
|
||||
//Normal scanning procedure. We have tiles loaded, are not emagged.
|
||||
if(!target && !(bot_cover_flags & BOT_COVER_EMAGGED))
|
||||
if(targetdirection != null) //The bot is in line mode.
|
||||
@@ -198,33 +197,33 @@
|
||||
target = T
|
||||
if(!target)
|
||||
process_type = HULL_BREACH //Ensures the floorbot does not try to "fix" space areas or shuttle docking zones.
|
||||
target = scan(/turf/open/space)
|
||||
|
||||
tiles_scanned += list(/turf/open/space)
|
||||
|
||||
if(!target && placetiles) //Finds a floor without a tile and gives it one.
|
||||
process_type = PLACE_TILE //The target must be the floor and not a tile. The floor must not already have a floortile.
|
||||
target = scan(/turf/open/floor)
|
||||
tiles_scanned += list(/turf/open/floor)
|
||||
|
||||
if(!target && fixfloors) //Repairs damaged floors and tiles.
|
||||
process_type = FIX_TILE
|
||||
target = scan(/turf/open/floor)
|
||||
tiles_scanned += list(/turf/open/floor)
|
||||
|
||||
if(!target && replacetiles && tilestack) //Replace a floor tile with custom tile
|
||||
process_type = REPLACE_TILE //The target must be a tile. The floor must already have a floortile.
|
||||
target = scan(/turf/open/floor)
|
||||
tiles_scanned += list(/turf/open/floor)
|
||||
|
||||
if(!target && bot_cover_flags & BOT_COVER_EMAGGED) //We are emagged! Time to rip up the floors!
|
||||
process_type = TILE_EMAG
|
||||
target = scan(/turf/open/floor)
|
||||
tiles_scanned += list(/turf/open/floor)
|
||||
|
||||
target = scan(tiles_scanned)
|
||||
|
||||
if(!target)
|
||||
|
||||
if(bot_mode_flags & BOT_MODE_AUTOPATROL)
|
||||
switch(mode)
|
||||
if(BOT_IDLE, BOT_START_PATROL)
|
||||
start_patrol()
|
||||
if(BOT_PATROL)
|
||||
bot_patrol()
|
||||
if(!target && bot_mode_flags & BOT_MODE_AUTOPATROL)
|
||||
switch(mode)
|
||||
if(BOT_IDLE, BOT_START_PATROL)
|
||||
start_patrol()
|
||||
if(BOT_PATROL)
|
||||
bot_patrol()
|
||||
|
||||
if(target)
|
||||
if(loc == target || loc == get_turf(target))
|
||||
@@ -265,10 +264,6 @@
|
||||
mode = BOT_IDLE
|
||||
return
|
||||
|
||||
|
||||
|
||||
oldloc = loc
|
||||
|
||||
/mob/living/simple_animal/bot/floorbot/proc/go_idle()
|
||||
toggle_magnet(FALSE)
|
||||
mode = BOT_IDLE
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
var/skin
|
||||
var/mob/living/carbon/patient
|
||||
var/mob/living/carbon/oldpatient
|
||||
var/oldloc
|
||||
var/last_found = 0
|
||||
/// How much healing do we do at a time?
|
||||
var/heal_amount = 2.5
|
||||
@@ -152,7 +151,6 @@
|
||||
..()
|
||||
patient = null
|
||||
oldpatient = null
|
||||
oldloc = null
|
||||
last_found = world.time
|
||||
update_appearance()
|
||||
|
||||
@@ -358,7 +356,13 @@
|
||||
if(QDELETED(patient))
|
||||
if(medical_mode_flags & MEDBOT_SPEAK_MODE && prob(1))
|
||||
if(bot_cover_flags & BOT_COVER_EMAGGED && prob(30))
|
||||
var/list/i_need_scissors = list('sound/voice/medbot/fuck_you.ogg', 'sound/voice/medbot/turn_off.ogg', 'sound/voice/medbot/im_different.ogg', 'sound/voice/medbot/close.ogg', 'sound/voice/medbot/shindemashou.ogg')
|
||||
var/list/i_need_scissors = list(
|
||||
'sound/voice/medbot/fuck_you.ogg',
|
||||
'sound/voice/medbot/turn_off.ogg',
|
||||
'sound/voice/medbot/im_different.ogg',
|
||||
'sound/voice/medbot/close.ogg',
|
||||
'sound/voice/medbot/shindemashou.ogg',
|
||||
)
|
||||
playsound(src, pick(i_need_scissors), 70)
|
||||
else
|
||||
var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/medbot/radar.ogg',"There's always a catch, and I'm the best there is." = 'sound/voice/medbot/catch.ogg',"I knew it, I should've been a plastic surgeon." = 'sound/voice/medbot/surgeon.ogg',"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/medbot/flies.ogg',"Delicious!" = 'sound/voice/medbot/delicious.ogg', "Why are we still here? Just to suffer?" = 'sound/voice/medbot/why.ogg')
|
||||
@@ -366,7 +370,7 @@
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
var/scan_range = (medical_mode_flags & MEDBOT_STATIONARY_MODE ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
|
||||
patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
|
||||
patient = scan(list(/mob/living/carbon/human), oldpatient, scan_range)
|
||||
oldpatient = patient
|
||||
|
||||
if(patient && (get_dist(src,patient) <= 1) && !tending) //Patient is next to us, begin treatment!
|
||||
|
||||
Reference in New Issue
Block a user