diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm
index d2283e26664..71a2a82d689 100644
--- a/code/game/machinery/bots/bots.dm
+++ b/code/game/machinery/bots/bots.dm
@@ -34,11 +34,11 @@
src.explode()
/obj/machinery/bot/proc/Emag(mob/user as mob)
- if(locked && user)
+ if(locked)
locked = 0
emagged = 1
user << "You bypass [src]'s controls."
- if((!locked && open) || !user) //Ion storm does not require unlocking for emagging
+ if(!locked && open)
emagged = 2
/obj/machinery/bot/examine()
@@ -153,6 +153,7 @@
/obj/machinery/bot/attack_ai(mob/user as mob)
+ src.add_hiddenprint(user)
src.attack_hand(user)
/******************************************************************/
diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm
index 950529552bf..cbaa8285e01 100644
--- a/code/game/machinery/bots/cleanbot.dm
+++ b/code/game/machinery/bots/cleanbot.dm
@@ -55,8 +55,6 @@
var/datum/job/janitor/J = new/datum/job/janitor
src.botcard.access = J.get_access()
- src.locked = 0 // Start unlocked so roboticist can set them to patrol.
-
if(radio_controller)
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
@@ -68,6 +66,8 @@
/obj/machinery/bot/cleanbot/turn_off()
..()
+ if(!isnull(src.target))
+ target.targeted_by = null
src.target = null
src.oldtarget = null
src.oldloc = null
@@ -155,7 +155,7 @@ text("[src.oddbutton ? "Yes" : "No"
/obj/machinery/bot/cleanbot/Emag(mob/user as mob)
..()
- if((!locked && open) || !user)
+ if(open && !locked)
if(user) user << "The [src] buzzes and beeps."
src.oddbutton = 1
src.screwloose = 1
@@ -167,7 +167,6 @@ text("[src.oddbutton ? "Yes" : "No"
return
if(src.cleaning)
return
- var/list/cleanbottargets = list()
if(!src.screwloose && !src.oddbutton && prob(5))
visible_message("[src] makes an excited beeping booping sound!")
@@ -196,9 +195,10 @@ text("[src.oddbutton ? "Yes" : "No"
if(!src.target || src.target == null)
for (var/obj/effect/decal/cleanable/D in view(7,src))
for(var/T in src.target_types)
- if(!(D in cleanbottargets) && (D.type == T || D.parent_type == T) && D != src.oldtarget)
- src.oldtarget = D
- src.target = D
+ if(isnull(D.targeted_by) && (D.type == T || D.parent_type == T) && D != src.oldtarget) // If the mess isn't targeted
+ src.oldtarget = D // or if it is but the bot is gone.
+ src.target = D // and it's stuff we clean? Clean it.
+ D.targeted_by = src // Claim the mess we are targeting.
return
if(!src.target || src.target == null)
@@ -232,6 +232,8 @@ text("[src.oddbutton ? "Yes" : "No"
return
+ if(!path)
+ path = new()
if(target && path.len == 0)
spawn(0)
if(!src || !target) return
@@ -239,6 +241,7 @@ text("[src.oddbutton ? "Yes" : "No"
if (!path) path = list()
if(src.path.len == 0)
src.oldtarget = src.target
+ target.targeted_by = null
src.target = null
return
if(src.path.len > 0 && src.target && (src.target != null))
@@ -297,36 +300,36 @@ text("[src.oddbutton ? "Yes" : "No"
target_types += /obj/effect/decal/cleanable/oil
target_types += /obj/effect/decal/cleanable/vomit
+ target_types += /obj/effect/decal/cleanable/poop
target_types += /obj/effect/decal/cleanable/robot_debris
target_types += /obj/effect/decal/cleanable/crayon
target_types += /obj/effect/decal/cleanable/liquid_fuel
- target_types += /obj/effect/decal/cleanable/poop
+ target_types += /obj/effect/decal/cleanable/mucus
+
if(src.blood)
target_types += /obj/effect/decal/cleanable/xenoblood
target_types += /obj/effect/decal/cleanable/xenoblood/xgibs
target_types += /obj/effect/decal/cleanable/blood/
+ target_types += /obj/effect/decal/cleanable/blood/green
target_types += /obj/effect/decal/cleanable/blood/tracks
- target_types += /obj/effect/decal/cleanable/blood/gibs
+ target_types += /obj/effect/decal/cleanable/blood/gibs/
target_types += /obj/effect/decal/cleanable/dirt
/obj/machinery/bot/cleanbot/proc/clean(var/obj/effect/decal/cleanable/target)
- anchored = 1
- icon_state = "cleanbot-c"
+ src.anchored = 1
+ src.icon_state = "cleanbot-c"
visible_message("\red [src] begins to clean up the [target]")
- cleaning = 1
+ src.cleaning = 1
var/cleantime = 50
if(istype(target,/obj/effect/decal/cleanable/dirt)) // Clean Dirt much faster
cleantime = 10
spawn(cleantime)
- if(istype(loc,/turf/simulated))
- var/turf/simulated/f = loc
- f.dirt = 0
- cleaning = 0
+ src.cleaning = 0
del(target)
- icon_state = "cleanbot[on]"
- anchored = 0
- target = null
+ src.icon_state = "cleanbot[src.on]"
+ src.anchored = 0
+ src.target = null
/obj/machinery/bot/cleanbot/explode()
src.on = 0
diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm
index 846b3650661..2976cdc40d9 100644
--- a/code/game/machinery/bots/ed209bot.dm
+++ b/code/game/machinery/bots/ed209bot.dm
@@ -204,7 +204,7 @@ Auto Patrol: []"},
/obj/machinery/bot/ed209/Emag(mob/user as mob)
..()
- if((!locked && open) || !user)
+ if(open && !locked)
if(user) user << "You short out [src]'s target assessment circuits."
spawn(0)
for(var/mob/O in hearers(src, null))
@@ -363,7 +363,8 @@ Auto Patrol: []"},
if(SECBOT_START_PATROL) // start a patrol
-
+ if(!path || !istype(path))
+ path = list()
if(path.len > 0 && patrol_target) // have a valid path, so just resume
mode = SECBOT_PATROL
return
@@ -406,7 +407,7 @@ Auto Patrol: []"},
if(loc == patrol_target) // reached target
at_patrol_target()
return
-
+ if(!path || !istype(path)) path = list()
else if(path.len > 0 && patrol_target) // valid path
var/turf/next = path[1]
diff --git a/code/game/machinery/bots/farmbot.dm b/code/game/machinery/bots/farmbot.dm
index 0635616611a..421bfc6d009 100644
--- a/code/game/machinery/bots/farmbot.dm
+++ b/code/game/machinery/bots/farmbot.dm
@@ -12,6 +12,8 @@
// The behavior panel can be unlocked with hydroponics access and be modified to disable certain behaviors
// By default, it will ignore weeds and mushrooms, but can be set to tend to these types of plants as well.
+//Seems a little stupid handling multiple Go direction X,Y,Z to do Job F,G,H if it's in multiple directions so I'd reccomend only enabling 1 water/fertilize/weed task at a time. - SarahJohnson
+
#define FARMBOT_MODE_WATER 1
#define FARMBOT_MODE_FERTILIZE 2
@@ -100,7 +102,7 @@
if (.)
return
var/dat
- dat += "Automatic Hyrdoponic Assisting Unit v1.0
"
+ dat += "Automatic Hydroponic Assisting Unit v1.0
"
dat += "Status: [src.on ? "On" : "Off"]
"
dat += "Water Tank: "
@@ -350,9 +352,8 @@
mode = 0
frustration = 0
src.path = new()
- if(src.path)
- if(src.target && (src.path.len) && (get_dist(src.target,src.path[src.path.len]) > 2))
- src.path = new()
+ if(src.target && (src.path.len) && (get_dist(src.target,src.path[src.path.len]) > 2))
+ src.path = new()
if(src.target && src.path.len == 0 && (get_dist(src,src.target) > 1))
spawn(0)
var/turf/dest = get_step_towards(target,src) //Can't pathfind to a tray, as it is dense, so pathfind to the spot next to the tray
diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm
index 96fb18e2f8a..de1f4fe2c68 100644
--- a/code/game/machinery/bots/floorbot.dm
+++ b/code/game/machinery/bots/floorbot.dm
@@ -25,6 +25,9 @@
flags = TABLEPASS
var/created_name = "Floorbot"
+// Tell other floorbots what we're fucking with so two floorbots don't dick with the same tile.
+var/global/list/floorbot_targets=list()
+
//Floorbot
/obj/machinery/bot/floorbot
name = "Floorbot"
@@ -37,6 +40,13 @@
health = 25
maxhealth = 25
//weight = 1.0E7
+ var/mode = 0
+#define FLOORBOT_IDLE 0 // idle
+#define FLOORBOT_FIXING_SHIT 1
+#define FLOORBOT_START_PATROL 2 // start patrol
+#define FLOORBOT_PATROL 3 // patrolling
+
+ var/auto_patrol = 0 // set to make bot automatically patrol
var/amount = 10
var/repairing = 0
var/improvefloors = 0
@@ -48,6 +58,20 @@
req_access = list(access_construction)
var/path[] = new()
var/targetdirection
+ var/beacon_freq = 1445 // navigation beacon frequency
+
+
+ var/turf/patrol_target // this is turf to navigate to (location of beacon)
+ var/new_destination // pending new destination (waiting for beacon response)
+ var/destination // destination description tag
+ var/next_destination // the next destination in the patrol route
+ var/list/patpath = new // list of path turfs
+
+ var/blockcount = 0 //number of times retried a blocked path
+ var/awaiting_beacon = 0 // count of pticks awaiting a beacon response
+
+ var/nearest_beacon // the nearest beacon's tag
+ var/turf/nearest_beacon_loc // the nearest beacon's location
/obj/machinery/bot/floorbot/New()
@@ -61,12 +85,16 @@
/obj/machinery/bot/floorbot/turn_off()
..()
+ if(!isnull(src.target))
+ floorbot_targets -= src.target
src.target = null
src.oldtarget = null
src.oldloc = null
src.updateicon()
src.path = new()
+ src.patpath = new()
src.updateUsrDialog()
+ src.mode=FLOORBOT_IDLE
/obj/machinery/bot/floorbot/attack_hand(mob/user as mob)
. = ..()
@@ -85,19 +113,18 @@
if(!src.locked || issilicon(user))
dat += "Improves floors: [src.improvefloors ? "Yes" : "No"]
"
dat += "Finds tiles: [src.eattiles ? "Yes" : "No"]
"
- dat += "Make singles pieces of metal into tiles when empty: [src.maketiles ? "Yes" : "No"]
"
- var/bmode
- if (src.targetdirection)
- bmode = dir2text(src.targetdirection)
- else
- bmode = "Disabled"
- dat += "
Bridge Mode : [bmode]
"
+ dat += "Make single pieces of metal into tiles when empty: [src.maketiles ? "Yes" : "No"]
"
user << browse("
Repairbot v1.0 controls[dat]", "window=autorepair")
onclose(user, "autorepair")
return
+/obj/machinery/bot/floorbot/proc/speak(var/message)
+ for(var/mob/O in hearers(src, null))
+ O.show_message("[src] beeps, \"[message]\"",2)
+ return
+
/obj/machinery/bot/floorbot/attackby(var/obj/item/W , mob/user as mob)
if(istype(W, /obj/item/stack/tile/plasteel))
var/obj/item/stack/tile/plasteel/T = W
@@ -125,7 +152,7 @@
/obj/machinery/bot/floorbot/Emag(mob/user as mob)
..()
- if((!locked && open) || !user)
+ if(open && !locked)
if(user) user << "The [src] buzzes and beeps."
/obj/machinery/bot/floorbot/Topic(href, href_list)
@@ -148,21 +175,38 @@
if("make")
src.maketiles = !src.maketiles
src.updateUsrDialog()
- if("bridgemode")
- switch(src.targetdirection)
- if(null)
- targetdirection = 1
- if(1)
- targetdirection = 2
- if(2)
- targetdirection = 4
- if(4)
- targetdirection = 8
- if(8)
- targetdirection = null
- else
- targetdirection = null
- src.updateUsrDialog()
+
+/obj/machinery/bot/floorbot/proc/is_obj_valid_target(var/atom/T,var/list/floorbottargets)
+ if(T in floorbottargets)
+ return 0
+ if(T == src.oldtarget)
+ return 0
+ if(istype(T.loc, /turf/simulated/wall))
+ return 0
+ if(!T.loc.Enter(src))
+ return 0
+ return 1
+
+/obj/machinery/bot/floorbot/proc/hunt_for_tiles(var/list/shit_in_view, var/list/floorbottargets)
+ for(var/obj/item/stack/tile/plasteel/T in shit_in_view)
+ if(!(T in floorbot_targets) && src.is_obj_valid_target(T,floorbottargets))
+ src.oldtarget = T
+ src.target = T
+ floorbot_targets +=T
+ mode=FLOORBOT_FIXING_SHIT
+ return
+
+/obj/machinery/bot/floorbot/proc/hunt_for_metal(var/list/shit_in_view, var/list/floorbottargets)
+ for(var/obj/item/stack/sheet/metal/M in shit_in_view)
+ if(!(M in floorbot_targets) && src.is_obj_valid_target(M) && M.amount == 1)
+ src.oldtarget = M
+ src.target = M
+ floorbot_targets += M
+ mode=FLOORBOT_FIXING_SHIT
+ return
+
+/obj/machinery/bot/floorbot/proc/have_target()
+ return (src.target != null)
/obj/machinery/bot/floorbot/process()
//set background = 1
@@ -171,73 +215,49 @@
return
if(src.repairing)
return
- var/list/floorbottargets = list()
- if(src.amount <= 0 && ((src.target == null) || !src.target))
- if(src.eattiles)
- for(var/obj/item/stack/tile/plasteel/T in view(7, src))
- if(T != src.oldtarget && !(target in floorbottargets))
- src.oldtarget = T
- src.target = T
- break
- if(src.target == null || !src.target)
- if(src.maketiles)
- if(src.target == null || !src.target)
- for(var/obj/item/stack/sheet/metal/M in view(7, src))
- if(!(M in floorbottargets) && M != src.oldtarget && M.amount == 1 && !(istype(M.loc, /turf/simulated/wall)))
- src.oldtarget = M
- src.target = M
- break
- else
+
+ switch(mode)
+ if(FLOORBOT_IDLE) // idle
+ walk_to(src,0)
+ if(checkforwork()) // see if any criminals are in range
+ return
+ if(!mode && auto_patrol) // still idle, and set to patrol
+ mode = FLOORBOT_START_PATROL // switch to patrol mode
+ if(FLOORBOT_FIXING_SHIT)
+ src.fix_shit()
return
- if(prob(5))
- visible_message("[src] makes an excited booping beeping sound!")
+ if(FLOORBOT_START_PATROL) // start a patrol
+ if(patpath.len > 0 && patrol_target) // have a valid path, so just resume
+ mode = FLOORBOT_PATROL
+ return
- if((!src.target || src.target == null) && emagged < 2)
- if(targetdirection != null)
- /*
- for (var/turf/space/D in view(7,src))
- if(!(D in floorbottargets) && D != src.oldtarget) // Added for bridging mode -- TLE
- if(get_dir(src, D) == targetdirection)
- src.oldtarget = D
- src.target = D
- break
- */
- var/turf/T = get_step(src, targetdirection)
- if(istype(T, /turf/space))
- src.oldtarget = T
- src.target = T
- if(!src.target || src.target == null)
- for (var/turf/space/D in view(7,src))
- if(!(D in floorbottargets) && D != src.oldtarget && (D.loc.name != "Space"))
- src.oldtarget = D
- src.target = D
- break
- if((!src.target || src.target == null ) && src.improvefloors)
- for (var/turf/simulated/floor/F in view(7,src))
- if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating)))
- src.oldtarget = F
- src.target = F
- break
- if((!src.target || src.target == null) && src.eattiles)
- for(var/obj/item/stack/tile/plasteel/T in view(7, src))
- if(!(T in floorbottargets) && T != src.oldtarget)
- src.oldtarget = T
- src.target = T
- break
+ else if(patrol_target) // has patrol target already
+ spawn(0)
+ calc_path() // so just find a route to it
+ if(patpath.len == 0)
+ patrol_target = 0
+ return
+ mode = FLOORBOT_PATROL
- if((!src.target || src.target == null) && emagged == 2)
- if(!src.target || src.target == null)
- for (var/turf/simulated/floor/D in view(7,src))
- if(!(D in floorbottargets) && D != src.oldtarget && D.floor_tile)
- src.oldtarget = D
- src.target = D
- break
- if(!src.target || src.target == null)
+ else // no patrol target, so need a new one
+ find_patrol_target()
+ speak("That's done, what's next?")
+
+
+ if(FLOORBOT_PATROL) // patrol mode
+ patrol_step()
+ spawn(5)
+ if(mode == FLOORBOT_PATROL)
+ patrol_step()
+
+/obj/machinery/bot/floorbot/proc/fix_shit()
+ if(!src.have_target())
if(src.loc != src.oldloc)
src.oldtarget = null
- return
-
+ return 0
+ if(!src.path)
+ src.path = new()
if(src.target && (src.target != null) && src.path.len == 0)
spawn(0)
if(!istype(src.target, /turf/))
@@ -247,8 +267,9 @@
if (!src.path) src.path = list()
if(src.path.len == 0)
src.oldtarget = src.target
+ floorbot_targets -= src.target
src.target = null
- return
+ return 1
if(src.path.len > 0 && src.target && (src.target != null))
step_to(src, src.path[1])
src.path -= src.path[1]
@@ -259,11 +280,26 @@
if(src.loc == src.target || src.loc == src.target.loc)
if(istype(src.target, /obj/item/stack/tile/plasteel))
src.eattile(src.target)
+ mode=FLOORBOT_IDLE
else if(istype(src.target, /obj/item/stack/sheet/metal))
src.maketile(src.target)
- else if(istype(src.target, /turf/) && emagged < 2)
+ mode=FLOORBOT_IDLE
+ //else if(istype(src.target, /turf/) && emagged < 2)
+ else if((src.target.is_plating() || istype(src.target,/turf/space/)) && emagged < 2)
repair(src.target)
- else if(emagged == 2 && istype(src.target,/turf/simulated/floor))
+ mode=FLOORBOT_IDLE
+ else if(src.target.is_plasteel_floor() && (src.target:broken || src.target:burnt) && emagged < 2)
+ var/turf/simulated/floor/F = src.target
+ src.anchored = 1
+ src.repairing = 1
+ F.break_tile_to_plating()
+ spawn(50)
+ src.anchored = 0
+ src.repairing = 0
+ src.target = null
+ floorbot_targets -= src.target
+ mode=FLOORBOT_IDLE
+ else if(src.target.is_plating() && emagged == 2)
var/turf/simulated/floor/F = src.target
src.anchored = 1
src.repairing = 1
@@ -277,11 +313,90 @@
src.anchored = 0
src.repairing = 0
src.target = null
+ floorbot_targets -= src.target
+ mode=FLOORBOT_IDLE
src.path = new()
- return
+ mode=FLOORBOT_IDLE
+ return 1
src.oldloc = src.loc
+ return 1
+/obj/machinery/bot/floorbot/proc/checkforwork()
+ if(src.have_target())
+ return 0
+ var/list/floorbottargets = list()
+
+ // Needed because we used to look this up 15 goddamn times per process. - Nexypoo
+ var/list/shitICanSee = view(7, src)
+
+ if(src.amount <= 0 && !src.have_target())
+ if(src.eattiles)
+ if(src.hunt_for_tiles(shitICanSee, floorbottargets))
+ return 1
+ if(src.maketiles && !src.have_target())
+ if(src.hunt_for_metal(shitICanSee, floorbottargets))
+ return 1
+ else
+ return 0
+
+ if(prob(5))
+ visible_message("[src] makes an excited booping beeping sound!")
+
+ if(!src.have_target() && emagged < 2)
+ if(targetdirection != null)
+ /*
+ for (var/turf/space/D in shitICanSee)
+ if(!(D in floorbottargets) && D != src.oldtarget) // Added for bridging mode -- TLE
+ if(get_dir(src, D) == targetdirection)
+ src.oldtarget = D
+ src.target = D
+ break
+ */
+ var/turf/T = get_step(src, targetdirection)
+ if(istype(T, /turf/space) && !(T in floorbot_targets))
+ src.oldtarget = T
+ src.target = T
+ floorbot_targets+=T
+ mode=FLOORBOT_FIXING_SHIT
+ return 1
+ if(!src.have_target())
+ for (var/turf/space/D in shitICanSee)
+ if(!(D in floorbottargets) && D != src.oldtarget && (D.loc.name != "Space") && !(D in floorbot_targets))
+ src.oldtarget = D
+ src.target = D
+ floorbot_targets += D
+ mode=FLOORBOT_FIXING_SHIT
+ return 1
+ if((!src.target || src.target == null ) && src.improvefloors)
+ for (var/turf/simulated/floor/F in shitICanSee)
+ // So, what the dick are we doing, here?
+ // ORIGINAL: if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating)))
+ // Using new erro flags:
+ if(!(F in floorbottargets) && F != src.oldtarget && F.is_plating() && !(istype(F, /turf/simulated/wall)) && !(F in floorbot_targets))
+ if(!F.broken && !F.burnt)
+ src.oldtarget = F
+ src.target = F
+ floorbot_targets += F
+ mode=FLOORBOT_FIXING_SHIT
+ return 1
+ if(!(F in floorbottargets) && !(F in floorbot_targets) && F != src.oldtarget && F.is_plasteel_floor() && (F.broken||F.burnt))
+ src.oldtarget = F
+ src.target = F
+ floorbot_targets += F
+ mode=FLOORBOT_FIXING_SHIT
+ return 1
+
+ if(!src.have_target() && emagged == 2)
+ for (var/turf/simulated/floor/D in shitICanSee)
+ //if(!(D in floorbottargets) && D != src.oldtarget && D.floor_tile)
+ if(!(D in floorbottargets) && D != src.oldtarget && D.is_plasteel_floor() && !(D in floorbot_targets))
+ src.oldtarget = D
+ src.target = D
+ floorbot_targets += D
+ mode=FLOORBOT_FIXING_SHIT
+ return 1
+ return 0
/obj/machinery/bot/floorbot/proc/repair(var/turf/target)
if(istype(target, /turf/space/))
@@ -303,17 +418,33 @@
src.amount -= 1
src.updateicon()
src.anchored = 0
+ floorbot_targets -= src.target
src.target = null
else
- visible_message("\red [src] begins to improve the floor.")
- src.repairing = 1
- spawn(50)
- src.loc.icon_state = "floor"
- src.repairing = 0
- src.amount -= 1
- src.updateicon()
- src.anchored = 0
- src.target = null
+ var/turf/simulated/floor/F = src.loc
+ if(!F.broken && !F.burnt)
+ visible_message("\red [src] begins to improve the floor.")
+ src.repairing = 1
+ spawn(50)
+ F.make_plasteel_floor()
+ src.repairing = 0
+ src.amount -= 1
+ src.updateicon()
+ src.anchored = 0
+ floorbot_targets -= src.target
+ src.target = null
+ else
+ if(F.is_plating())
+ visible_message("\red [src] begins to fix dents in the floor.")
+ src.repairing = 1
+ spawn(20)
+ src.repairing = 0
+ // Cheap, and does the job.
+ F.icon_state = "plating"
+ F.burnt = 0
+ F.broken = 0
+ floorbot_targets -= src.target
+ src.target = null
/obj/machinery/bot/floorbot/proc/eattile(var/obj/item/stack/tile/plasteel/T)
if(!istype(T, /obj/item/stack/tile/plasteel))
@@ -333,6 +464,7 @@
src.amount += T.amount
del(T)
src.updateicon()
+ floorbot_targets -= src.target
src.target = null
src.repairing = 0
@@ -351,7 +483,11 @@
var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
T.amount = 4
T.loc = M.loc
- del(M)
+ if(M.amount==1)
+ del(M)
+ else
+ M.amount--
+ floorbot_targets -= src.target
src.target = null
src.repairing = 0
@@ -361,6 +497,174 @@
else
src.icon_state = "floorbot[src.on]e"
+
+/obj/machinery/bot/floorbot/proc/calc_path(var/turf/avoid = null)
+ src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
+ src.path = reverselist(src.path)
+
+// perform a single patrol step
+
+/obj/machinery/bot/floorbot/proc/patrol_step()
+
+ if(loc == patrol_target) // reached target
+ at_patrol_target()
+ return
+
+ else if(patpath.len > 0 && patrol_target) // valid path
+
+ var/turf/next = patpath[1]
+ if(next == loc)
+ patpath -= next
+ return
+
+
+ if(istype( next, /turf/simulated))
+
+ var/moved = step_towards(src, next) // attempt to move
+ if(moved) // successful move
+ blockcount = 0
+ patpath -= loc
+
+ checkforwork()
+ else // failed to move
+
+ blockcount++
+
+ if(blockcount > 5) // attempt 5 times before recomputing
+ // find new path excluding blocked turf
+
+ spawn(2)
+ calc_path(next)
+ if(patpath.len == 0)
+ find_patrol_target()
+ else
+ blockcount = 0
+
+ return
+
+ return
+
+ else // not a valid turf
+ mode = FLOORBOT_IDLE
+ return
+
+ else // no path, so calculate new one
+ mode = FLOORBOT_START_PATROL
+
+
+// finds a new patrol target
+/obj/machinery/bot/floorbot/proc/find_patrol_target()
+// send_status()
+ if(awaiting_beacon) // awaiting beacon response
+ awaiting_beacon++
+ if(awaiting_beacon > 5) // wait 5 secs for beacon response
+ find_nearest_beacon() // then go to nearest instead
+ return
+
+ if(next_destination)
+ set_destination(next_destination)
+ else
+ find_nearest_beacon()
+ return
+
+
+// finds the nearest beacon to self
+// signals all beacons matching the patrol code
+/obj/machinery/bot/floorbot/proc/find_nearest_beacon()
+ nearest_beacon = null
+ new_destination = "__nearest__"
+ post_signal(beacon_freq, "findbeacon", "patrol")
+ awaiting_beacon = 1
+ spawn(10)
+ awaiting_beacon = 0
+ if(nearest_beacon)
+ set_destination(nearest_beacon)
+ else
+ auto_patrol = 0
+ mode = FLOORBOT_IDLE
+ speak("Disengaging patrol mode.")
+ //send_status()
+
+
+/obj/machinery/bot/floorbot/proc/at_patrol_target()
+ find_patrol_target()
+ return
+
+/obj/machinery/bot/floorbot/Bump(M as mob|obj) //Leave no door unopened!
+ if((istype(M, /obj/machinery/door)) && (!isnull(src.botcard)))
+ var/obj/machinery/door/D = M
+ if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard))
+ D.open()
+ return
+
+/obj/machinery/bot/floorbot/receive_signal(datum/signal/signal)
+ //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])")
+ if(!on)
+ return
+
+ var/recv = signal.data["command"]
+
+ // receive response from beacon
+ recv = signal.data["beacon"]
+ var/valid = signal.data["patrol"]
+ if(!recv || !valid)
+ return
+
+ if(recv == new_destination) // if the recvd beacon location matches the set destination
+ // the we will navigate there
+ destination = new_destination
+ patrol_target = signal.source.loc
+ next_destination = signal.data["next_patrol"]
+ awaiting_beacon = 0
+
+ // if looking for nearest beacon
+ else if(new_destination == "__nearest__")
+ var/dist = get_dist(src,signal.source.loc)
+ if(nearest_beacon)
+
+ // note we ignore the beacon we are located at
+ if(dist>1 && dist 1)
+ nearest_beacon = recv
+ nearest_beacon_loc = signal.source.loc
+ return
+
+// send a radio signal with a single data key/value pair
+/obj/machinery/bot/floorbot/proc/post_signal(var/freq, var/key, var/value)
+ post_signal_multiple(freq, list("[key]" = value) )
+
+// send a radio signal with multiple data key/values
+/obj/machinery/bot/floorbot/proc/post_signal_multiple(var/freq, var/list/keyval)
+
+ var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
+
+ if(!frequency) return
+
+ var/datum/signal/signal = new()
+ signal.source = src
+ signal.transmission_method = 1
+ //for(var/key in keyval)
+ // signal.data[key] = keyval[key]
+ signal.data = keyval
+ //world << "sent [key],[keyval[key]] on [freq]"
+ if(signal.data["findbeacon"])
+ frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
+ else
+ frequency.post_signal(src, signal)
+
+// sets the current destination
+// signals all beacons matching the patrol code
+// beacons will return a signal giving their locations
+/obj/machinery/bot/floorbot/proc/set_destination(var/new_dest)
+ new_destination = new_dest
+ post_signal(beacon_freq, "findbeacon", "patrol")
+ awaiting_beacon = 1
+
/obj/machinery/bot/floorbot/explode()
src.on = 0
src.visible_message("\red [src] blows apart!", 1)
@@ -374,6 +678,9 @@
if (prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
+ if(src.target)
+ floorbot_targets -= src.target
+
while (amount)//Dumps the tiles into the appropriate sized stacks
if(amount >= 16)
var/obj/item/stack/tile/plasteel/T = new (Tsec)
diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm
index 3925fb4cfd3..771771388a4 100644
--- a/code/game/machinery/bots/medbot.dm
+++ b/code/game/machinery/bots/medbot.dm
@@ -215,7 +215,7 @@
/obj/machinery/bot/medbot/Emag(mob/user as mob)
..()
- if((!locked && open) || !user)
+ if(open && !locked)
if(user) user << "You short out [src]'s reagent synthesis circuits."
spawn(0)
for(var/mob/O in hearers(src, null))
@@ -283,7 +283,8 @@
else
continue
-
+ if(!src.path)
+ src.path = new()
if(src.patient && (get_dist(src,src.patient) <= 1))
if(!src.currently_healing)
src.currently_healing = 1
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index 1d548de3bd1..547af6f227d 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -63,6 +63,7 @@ var/global/mulebot_count = 0
var/bloodiness = 0 // count of bloodiness
+ var/currentBloodColor = "#A10808"
/obj/machinery/bot/mulebot/New()
..()
@@ -180,13 +181,10 @@ var/global/mulebot_count = 0
/obj/machinery/bot/mulebot/interact(var/mob/user, var/ai=0)
var/dat
+ dat += "Multiple Utility Load Effector Mk. III
"
+ dat += "ID: [suffix]
"
+ dat += "Power: [on ? "On" : "Off"]
"
- // AUTOFIXED BY fix_string_idiocy.py
- // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\bots\mulebot.dm:209: dat += "Multiple Utility Load Effector Mk. III
"
- dat += {"Multiple Utility Load Effector Mk. III
- ID: [suffix]
- Power: [on ? "On" : "Off"]
"}
- // END AUTOFIX
if(!open)
dat += "Status: "
@@ -206,41 +204,34 @@ var/global/mulebot_count = 0
if(7)
dat += "Unable to locate destination"
- // AUTOFIXED BY fix_string_idiocy.py
- // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\bots\mulebot.dm:233: dat += "
Current Load: [load ? load.name : "none"]
"
- dat += {"
Current Load: [load ? load.name : "none"]
- Destination: [!destination ? "none" : destination]
- Power level: [cell ? cell.percent() : 0]%
"}
- // END AUTOFIX
+
+ dat += "
Current Load: [load ? load.name : "none"]
"
+ dat += "Destination: [!destination ? "none" : destination]
"
+ dat += "Power level: [cell ? cell.percent() : 0]%
"
+
if(locked && !ai)
dat += "
Controls are locked (unlock)"
else
+ dat += "
Controls are unlocked (lock)
"
+
+ dat += "Toggle Power
"
+ dat += "Stop
"
+ dat += "Proceed
"
+ dat += "Return to Home
"
+ dat += "Set Destination
"
+ dat += "Set Bot ID
"
+ dat += "Set Home
"
+ dat += "Toggle Auto Return Home ([auto_return ? "On":"Off"])
"
+ dat += "Toggle Auto Pickup Crate ([auto_pickup ? "On":"Off"])
"
- // AUTOFIXED BY fix_string_idiocy.py
- // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\bots\mulebot.dm:240: dat += "
Controls are unlocked (lock)
"
- dat += {"
Controls are unlocked (lock)
- Toggle Power
- Stop
- Proceed
- Return to Home
- Set Destination
- Set Bot ID
- Set Home
- Toggle Auto Return Home ([auto_return ? "On":"Off"])
- Toggle Auto Pickup Crate ([auto_pickup ? "On":"Off"])
"}
- // END AUTOFIX
if(load)
dat += "Unload Now
"
dat += "
The maintenance hatch is closed.
"
else
if(!ai)
-
- // AUTOFIXED BY fix_string_idiocy.py
- // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\bots\mulebot.dm:258: dat += "The maintenance hatch is open.
"
- dat += {"The maintenance hatch is open.
- Power cell: "}
- // END AUTOFIX
+ dat += "The maintenance hatch is open.
"
+ dat += "Power cell: "
if(cell)
dat += "Installed
"
else
@@ -565,7 +556,7 @@ var/global/mulebot_count = 0
else if(newdir == 12)
newdir = 4
goingdir = newdir
- T.AddTracks(/obj/effect/decal/cleanable/blood/tracks/wheels,list(),0,goingdir)
+ T.AddTracks(/obj/effect/decal/cleanable/blood/tracks/wheels,list(),0,goingdir,currentBloodColor)
bloodiness--
var/moved = step_towards(src, next) // attempt to move
@@ -734,7 +725,7 @@ var/global/mulebot_count = 0
return get_turf(src)
-// called from mob/living/carbon/human/Crossed()
+// called from mob/living/carbon/human/HasEntered()
// when mulebot is in the same loc
/obj/machinery/bot/mulebot/proc/RunOver(var/mob/living/carbon/human/H)
src.visible_message("\red [src] drives over [H]!")
@@ -753,6 +744,13 @@ var/global/mulebot_count = 0
B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
bloodiness += 4
+ currentBloodColor="#A10808" // For if species get different blood colors.
+
+/obj/machinery/bot/mulebot/proc/RunOverCreature(var/mob/living/H,var/bloodcolor)
+ src.visible_message("\red [src] drives over [H]!")
+ playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
+ bloodiness += 4
+ currentBloodColor=bloodcolor // For if species get different blood colors.
// player on mulebot attempted to move
/obj/machinery/bot/mulebot/relaymove(var/mob/user)
diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm
index 27ef0c4fa91..8eaab542fe8 100644
--- a/code/game/machinery/bots/secbot.dm
+++ b/code/game/machinery/bots/secbot.dm
@@ -177,7 +177,7 @@ Auto Patrol: []"},
/obj/machinery/bot/secbot/Emag(mob/user as mob)
..()
- if((!locked && open) || !user)
+ if(open && !locked)
if(user) user << "\red You short out [src]'s target assessment circuits."
spawn(0)
for(var/mob/O in hearers(src, null))
@@ -333,23 +333,23 @@ Auto Patrol: []"},
if(SECBOT_START_PATROL) // start a patrol
-
- if(path.len > 0 && patrol_target) // have a valid path, so just resume
- mode = SECBOT_PATROL
- return
-
- else if(patrol_target) // has patrol target already
- spawn(0)
- calc_path() // so just find a route to it
- if(path.len == 0)
- patrol_target = 0
- return
+ if(path != null)
+ if(path.len > 0 && patrol_target) // have a valid path, so just resume
mode = SECBOT_PATROL
+ return
+
+ else if(patrol_target) // has patrol target already
+ spawn(0)
+ calc_path() // so just find a route to it
+ if(path.len == 0)
+ patrol_target = 0
+ return
+ mode = SECBOT_PATROL
- else // no patrol target, so need a new one
- find_patrol_target()
- speak("Engaging patrol mode.")
+ else // no patrol target, so need a new one
+ find_patrol_target()
+ speak("Engaging patrol mode.")
if(SECBOT_PATROL) // patrol mode
@@ -585,8 +585,10 @@ Auto Patrol: []"},
// calculates a path to the current destination
// given an optional turf to avoid
/obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null)
- src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
- if (!path) path = list()
+ src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 120, id=botcard, exclude=avoid)
+ if(!src.path)
+ src.path = list()
+
// look for a criminal in view of the bot
@@ -718,7 +720,7 @@ Auto Patrol: []"},
Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole")
Sa.created_name = src.name
new /obj/item/device/assembly/prox_sensor(Tsec)
- new /obj/item/weapon/melee/baton(Tsec)
+ new /obj/item/weapon/melee/baton/loaded(Tsec)
if(prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index d1227d3aa38..471a32a6c92 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,6 +1,6 @@
/obj/effect/decal/cleanable
var/list/random_icon_states = list()
-
+ var/targeted_by = null // Used so cleanbots can't claim a mess.
/obj/effect/decal/cleanable/New()
if (random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)