diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index a799dd0ee1c..e50f6555116 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -8,6 +8,7 @@ var/global/list/shuttle_caller_list = list() //list of all communication cons
var/global/list/machines = list()
var/global/list/processing_objects = list()
var/global/list/active_diseases = list()
+var/global/list/aibots = list()
var/global/list/chemical_reactions_list //list of all /datum/chemical_reaction datums. Used during chemical reactions
var/global/list/chemical_reagents_list //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm
index f6e4a84aed8..49e827c58b4 100644
--- a/code/game/machinery/bots/bots.dm
+++ b/code/game/machinery/bots/bots.dm
@@ -84,6 +84,15 @@
"Waiting for clear path","Calculating navigation path","Pinging beacon network","Unable to reach destination")
//This holds text for what the bot is mode doing, reported on the AI's bot control interface.
+ var/tickerPeriod = 10 //in deciseconds
+
+//Controller for bots so they cannot lag the MC.
+/obj/machinery/bot/proc/ticker()
+ while(src && !src.gc_destroyed)
+ bot_process()
+ sleep(src.tickerPeriod)
+ return
+
/obj/machinery/bot/proc/turn_on()
if(stat) return 0
@@ -98,11 +107,15 @@
/obj/machinery/bot/New()
..()
+ aibots += src //Global bot list
botcard = new /obj/item/weapon/card/id(src)
set_custom_texts()
Radio = new /obj/item/device/radio(src)
Radio.listening = 0 //Makes bot radios transmit only so no one hears things while adjacent to one.
+ spawn()
+ ticker() //Activates the bot's controller.
+
/obj/machinery/bot/proc/add_to_beacons(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots.
if(radio_controller)
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
@@ -110,6 +123,7 @@
radio_controller.add_object(src, control_freq, filter = bot_filter)
/obj/machinery/bot/proc/explode()
+ aibots -= src
qdel(src)
/obj/machinery/bot/proc/healthcheck()
@@ -210,7 +224,7 @@
else
return 0
-/obj/machinery/bot/process() //Master process which handles code common across most bots.
+/obj/machinery/bot/proc/bot_process() //Master process which handles code common across most bots.
set background = BACKGROUND_ENABLED
diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm
index 8a3b033d149..0508cfedb88 100644
--- a/code/game/machinery/bots/cleanbot.dm
+++ b/code/game/machinery/bots/cleanbot.dm
@@ -141,7 +141,7 @@ text("[on ? "On" : "Off"]"))
if(istype(D, T))
return D
-/obj/machinery/bot/cleanbot/process()
+/obj/machinery/bot/cleanbot/bot_process()
if (!..())
return
diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm
index fd42c38f7b1..489075161f6 100644
--- a/code/game/machinery/bots/ed209bot.dm
+++ b/code/game/machinery/bots/ed209bot.dm
@@ -206,7 +206,7 @@ Auto Patrol[]"},
icon_state = "[lasercolor]ed209[on]"
set_weapon()
-/obj/machinery/bot/ed209/process()
+/obj/machinery/bot/ed209/bot_process()
if (!..())
return
@@ -351,14 +351,14 @@ Auto Patrol[]"},
last_found = world.time
frustration = 0
spawn(0)
- process() //ensure bot quickly responds
+ bot_process() //ensure bot quickly responds
/obj/machinery/bot/ed209/proc/back_to_hunt()
anchored = 0
frustration = 0
mode = BOT_HUNT
spawn(0)
- process() //ensure bot quickly responds
+ bot_process() //ensure bot quickly responds
// look for a criminal in view of the bot
@@ -387,7 +387,7 @@ Auto Patrol[]"},
visible_message("[src] points at [C.name]!")
mode = BOT_HUNT
spawn(0)
- process() // ensure bot quickly responds to a perp
+ bot_process() // ensure bot quickly responds to a perp
break
else
continue
diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm
index 889bd774238..ae644a52f42 100644
--- a/code/game/machinery/bots/floorbot.dm
+++ b/code/game/machinery/bots/floorbot.dm
@@ -117,6 +117,7 @@
dat += "Make pieces of metal into tiles when empty: [maketiles ? "Yes" : "No"]
"
dat += "Transmit notice when empty: [nag_on_empty ? "Yes" : "No"]
"
dat += "Repair damaged tiles and platings: [fixfloors ? "Yes" : "No"]
"
+ dat += "Traction Magnets: [anchored ? "Engaged" : "Disengaged"]
"
dat += "Patrol Station: [auto_patrol ? "Yes" : "No"]
"
var/bmode
if (targetdirection)
@@ -181,6 +182,8 @@
autotile = !autotile
if("emptynag")
nag_on_empty = !nag_on_empty
+ if("anchor")
+ anchored = !anchored
if("bridgemode")
var/setdir = input("Select construction direction:") as null|anything in list("north","east","south","west","disable")
@@ -197,7 +200,7 @@
targetdirection = null
updateUsrDialog()
-/obj/machinery/bot/floorbot/process()
+/obj/machinery/bot/floorbot/bot_process()
if (!..())
return
@@ -230,30 +233,23 @@
else //Find a space tile farther way!
target = scan(/turf/space, oldtarget)
- anchored = 1
process_type = BRIDGE_MODE
- return
if(!target)
process_type = HULL_BREACH //Ensures the floorbot does not try to "fix" space areas or shuttle docking zones.
target = scan(/turf/space, oldtarget)
- anchored = 1 //Prevent the floorbot being blown off-course while trying to reach a hull breach.
- return
if(!target && replacetiles) //Finds a floor without a tile and gives it one.
process_type = REPLACE_TILE //The target must be the floor and not a tile. The floor must not already have a floortile.
- //target = scan(/turf/simulated/floor, oldtarget)
- return
+ target = scan(/turf/simulated/floor, oldtarget)
if(!target && fixfloors) //Repairs damaged floors and tiles.
process_type = FIX_TILE
target = scan(/turf/simulated/floor, oldtarget)
- return
if(!target && emagged == 2) //We are emagged! Time to rip up the floors!
process_type = TILE_EMAG
target = scan(/turf/simulated/floor, oldtarget)
- return
if(!target)
@@ -336,9 +332,11 @@ obj/machinery/bot/floorbot/process_scan(var/scan_target)
if(HULL_BREACH) //The most common job, patching breaches in the station's hull.
if(is_hull_breach(scan_target)) //Ensure that the targeted space turf is actually part of the station, and not random space.
result = scan_target
+ anchored = 1 //Prevent the floorbot being blown off-course while trying to reach a hull breach.
if(BRIDGE_MODE) //Only space turfs in our chosen direction are considered.
if(get_dir(src, scan_target) == targetdirection)
result = scan_target
+ anchored = 1
if(REPLACE_TILE)
F = scan_target
if(istype(F, /turf/simulated/floor/plating)) //The floor must not already have a tile.
diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm
index 7fe74099a1a..ff55f572225 100644
--- a/code/game/machinery/bots/medbot.dm
+++ b/code/game/machinery/bots/medbot.dm
@@ -273,7 +273,7 @@
else
return
-/obj/machinery/bot/medbot/process()
+/obj/machinery/bot/medbot/bot_process()
if (!..())
return
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index e796be551c6..a3cd8c03707 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -496,7 +496,7 @@ var/global/mulebot_count = 0
pathset = 1 //Indicates the AI's custom path is initialized.
start()
-/obj/machinery/bot/mulebot/process()
+/obj/machinery/bot/mulebot/bot_process()
if(!has_power())
on = 0
return
diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm
index 25c76ba6872..25b6073a389 100644
--- a/code/game/machinery/bots/secbot.dm
+++ b/code/game/machinery/bots/secbot.dm
@@ -189,7 +189,7 @@ Auto Patrol: []"},
declare_arrests = 0
icon_state = "secbot[on]"
-/obj/machinery/bot/secbot/process()
+/obj/machinery/bot/secbot/bot_process()
if (!..())
return
@@ -314,14 +314,14 @@ Auto Patrol: []"},
last_found = world.time
frustration = 0
spawn(0)
- process() //ensure bot quickly responds
+ bot_process() //ensure bot quickly responds
/obj/machinery/bot/secbot/proc/back_to_hunt()
anchored = 0
frustration = 0
mode = BOT_HUNT
spawn(0)
- process() //ensure bot quickly responds
+ bot_process() //ensure bot quickly responds
// look for a criminal in view of the bot
/obj/machinery/bot/secbot/proc/look_for_perp()
@@ -346,7 +346,7 @@ Auto Patrol: []"},
visible_message("[src] points at [C.name]!")
mode = BOT_HUNT
spawn(0)
- process() // ensure bot quickly responds to a perp
+ bot_process() // ensure bot quickly responds to a perp
break
else
continue
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index abe9b340810..fc15cf0972c 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -364,7 +364,7 @@ var/list/ai_list = list()
return
if (href_list["callbot"]) //Command a bot to move to a selected location.
- Bot = locate(href_list["callbot"]) in machines
+ Bot = locate(href_list["callbot"]) in aibots
if(!Bot || Bot.remote_disabled || src.control_disabled)
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
waypoint_mode = 1
@@ -372,7 +372,7 @@ var/list/ai_list = list()
return
if (href_list["interface"]) //Remotely connect to a bot!
- Bot = locate(href_list["interface"]) in machines
+ Bot = locate(href_list["interface"]) in aibots
if(!Bot || Bot.remote_disabled || src.control_disabled)
return
Bot.attack_ai(src)
@@ -493,7 +493,7 @@ var/list/ai_list = list()
d += "Query network status
"
d += "
Name | Status | Location | Control |
| [Bot.hacked ? "(!) [Bot.name]" : Bot.name] | "