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)