//Floorbot assemblies /obj/item/weapon/toolbox_tiles desc = "It's a toolbox with tiles sticking out the top" name = "tiles and toolbox" icon = 'icons/obj/aibots.dmi' icon_state = "toolbox_tiles" force = 3.0 throwforce = 10.0 throw_speed = 2 throw_range = 5 w_class = 3.0 var/created_name = "Floorbot" /obj/item/weapon/toolbox_tiles_sensor desc = "It's a toolbox with tiles sticking out the top and a sensor attached" name = "tiles, toolbox and sensor arrangement" icon = 'icons/obj/aibots.dmi' icon_state = "toolbox_tiles_sensor" force = 3.0 throwforce = 10.0 throw_speed = 2 throw_range = 5 w_class = 3.0 var/created_name = "Floorbot" //Floorbot /obj/machinery/bot/floorbot name = "\improper Floorbot" desc = "A little floor repairing robot, he looks so excited!" icon = 'icons/obj/aibots.dmi' icon_state = "floorbot0" layer = 5.0 density = 0 anchored = 0 health = 25 maxhealth = 25 //weight = 1.0E7 var/amount = 10 var/replacetiles = 0 var/eattiles = 0 var/maketiles = 0 var/fixfloors = 0 var/autotile = 0 var/nag_on_empty = 1 var/nagged = 0 //Prevents the Floorbot nagging more than once per refill. var/max_targets = 50 var/turf/target var/turf/oldtarget var/oldloc = null req_one_access = list(access_construction, access_robotics) var/targetdirection radio_name = "Engineering" bot_type = FLOOR_BOT bot_type_name = "Floorbot" bot_filter = RADIO_FLOORBOT var/process_type //Determines what to do when process_scan() recieves a target. See process_scan() for details. #define HULL_BREACH 1 #define BRIDGE_MODE 2 #define FIX_TILE 3 #define AUTO_TILE 4 #define REPLACE_TILE 5 #define TILE_EMAG 6 /obj/machinery/bot/floorbot/New() ..() updateicon() var/datum/job/engineer/J = new/datum/job/engineer botcard.access = J.get_access() prev_access = botcard.access spawn(5) add_to_beacons(bot_filter) /obj/machinery/bot/floorbot/turn_on() . = ..() updateicon() updateUsrDialog() /obj/machinery/bot/floorbot/turn_off() ..() updateicon() updateUsrDialog() /obj/machinery/bot/floorbot/bot_reset() ..() target = null oldtarget = null oldloc = null ignore_list = list() nagged = 0 anchored = 0 update_icon() /obj/machinery/bot/floorbot/set_custom_texts() text_hack = "You corrupt [name]'s construction protocols." text_dehack = "You detect errors in [name] and reset his programming." text_dehack_fail = "[name] is not responding to reset commands!" /obj/machinery/bot/floorbot/attack_hand(mob/user as mob) . = ..() if (.) return usr.set_machine(src) interact(user) /obj/machinery/bot/floorbot/interact(mob/user as mob) var/dat dat += hack(user) dat += "Floor Repairer Controls v1.1

" dat += "Status: [on ? "On" : "Off"]
" dat += "Maintenance panel panel is [open ? "opened" : "closed"]
" dat += "Tiles left: [amount]
" dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
" if(!locked || issilicon(user)) dat += "Add tiles to new hull plating: [autotile ? "Yes" : "No"]
" dat += "Replace floor tiles: [replacetiles ? "Yes" : "No"]
" dat += "Finds tiles: [eattiles ? "Yes" : "No"]
" 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) bmode = dir2text(targetdirection) else bmode = "disabled" dat += "Bridge Mode : [bmode]
" var/datum/browser/popup = new(user, "autofloor", "Automatic Station Floor Repairer v1.1") popup.set_content(dat) popup.open() return /obj/machinery/bot/floorbot/attackby(var/obj/item/W , mob/user as mob, params) if(istype(W, /obj/item/stack/tile/plasteel)) var/obj/item/stack/tile/plasteel/T = W if(amount >= 50) return var/loaded = min(50-amount, T.amount) T.use(loaded) amount += loaded if (loaded > 0) user << "You load [loaded] tiles into the floorbot. He now contains [amount] tiles." nagged = 0 updateicon() else user << "You need at least one floor tile to put into [src]" else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) if(allowed(user) && !open && !emagged) locked = !locked user << "You [locked ? "lock" : "unlock"] \the [src] behaviour controls." updateUsrDialog() else if(emagged) user << "ERROR" if(open) user << "Please close the access panel before locking it." else user << "Access denied." updateUsrDialog() else ..() /obj/machinery/bot/floorbot/Emag(mob/user as mob) ..() if(emagged == 2) if(user) user << "[src] buzzes and beeps." /obj/machinery/bot/floorbot/Topic(href, href_list) ..() switch(href_list["operation"]) if("replace") replacetiles = !replacetiles if("tiles") eattiles = !eattiles if("make") maketiles = !maketiles if("fix") fixfloors = !fixfloors if("autotile") 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") switch(setdir) if("north") targetdirection = 1 if("south") targetdirection = 2 if("east") targetdirection = 4 if("west") targetdirection = 8 if("disable") targetdirection = null updateUsrDialog() /obj/machinery/bot/floorbot/bot_process() if (!..()) return if(mode == BOT_REPAIRING) return if(amount <= 0 && !target) //Out of tiles! We must refill! if(eattiles) //Configured to find and consume floortiles! target = scan(/obj/item/stack/tile/plasteel, oldtarget) process_type = null if(!target && maketiles) //We did not manage to find any floor tiles! Scan for metal stacks and make our own! target = scan(/obj/item/stack/sheet/metal, oldtarget) process_type = null return else if(nag_on_empty) //Floorbot is empty and cannot acquire more tiles, nag the engineers for more! nag() if(prob(5)) visible_message("[src] makes an excited booping beeping sound!") //Normal scanning procedure. We have tiles loaded, are not emagged. if(!target && emagged < 2 && amount > 0) if(targetdirection != null) //The bot is in bridge mode. //Try to find a space tile immediately in our selected direction. var/turf/T = get_step(src, targetdirection) if(istype(T, /turf/space)) target = T else //Find a space tile farther way! target = scan(/turf/space, oldtarget) process_type = BRIDGE_MODE 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) 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) if(!target && fixfloors) //Repairs damaged floors and tiles. process_type = FIX_TILE target = scan(/turf/simulated/floor, oldtarget) if(!target && emagged == 2) //We are emagged! Time to rip up the floors! process_type = TILE_EMAG target = scan(/turf/simulated/floor, oldtarget) if(!target) if(auto_patrol) if(mode == BOT_IDLE || mode == BOT_START_PATROL) start_patrol() if(mode == BOT_PATROL) bot_patrol() if(!target) if(loc != oldloc) oldtarget = null return if(target) if(path.len == 0) if(!istype(target, /turf/)) var/turf/TL = get_turf(target) path = get_path_to(loc, TL, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) else path = get_path_to(loc, target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) if(!bot_move(target)) add_to_ignore(target) oldtarget = target target = null mode = BOT_IDLE return else if( !bot_move(target) ) oldtarget = target target = null mode = BOT_IDLE return ignore_list = list() // Reset the ignore list if(loc == target || loc == target.loc) if(istype(target, /obj/item/stack/tile/plasteel)) eattile(target) else if(istype(target, /obj/item/stack/sheet/metal)) maketile(target) else if(istype(target, /turf/) && emagged < 2) repair(target) else if(emagged == 2 && istype(target,/turf/simulated/floor)) var/turf/simulated/floor/F = target anchored = 1 mode = BOT_REPAIRING if(prob(90)) F.break_tile_to_plating() else F.ReplaceWithLattice() visible_message("[src] makes an excited booping sound.") spawn(50) amount ++ anchored = 0 mode = BOT_IDLE target = null path = list() return oldloc = loc /obj/machinery/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us! if(!nagged) var/area/location = get_area(src) speak("Requesting refill at [location]!", radio_name) nagged = 1 /obj/machinery/bot/floorbot/proc/is_hull_breach(var/turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas. var/area/t_area = get_area(t) if (t_area && (t_area.name == "Space" || findtext(t_area.name, "huttle"))) return 0 else return 1 //Floorbots, having several functions, need sort out special conditions here. obj/machinery/bot/floorbot/process_scan(var/scan_target) var/result var/turf/simulated/floor/F switch(process_type) 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. result = F if(FIX_TILE) //Selects only damaged floors. F = scan_target if(istype(F) && (F.broken || F.burnt)) result = F if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space! F = scan_target if(!istype(F, /turf/simulated/floor/plating)) result = F else //If no special processing is needed, simply return the result. result = scan_target return result /obj/machinery/bot/floorbot/proc/repair(var/turf/target_turf) if(istype(target_turf, /turf/space/)) //Must be a hull breach or in bridge mode to continue. if(!is_hull_breach(target_turf) && !targetdirection) target = null return else if(!istype(target_turf, /turf/simulated/floor)) return if(amount <= 0) mode = BOT_IDLE target = null return anchored = 1 icon_state = "floorbot-c" if(istype(target_turf, /turf/space/)) //If we are fixing an area not part of pure space, it is visible_message("[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] ") mode = BOT_REPAIRING spawn(50) if(mode == BOT_REPAIRING) if(autotile) //Build the floor and include a tile. target_turf.ChangeTurf(/turf/simulated/floor) else //Build a hull plating without a floor tile. target_turf.ChangeTurf(/turf/simulated/floor/plating) mode = BOT_IDLE amount -= 1 updateicon() anchored = 0 target = null else var/turf/simulated/floor/F = target_turf mode = BOT_REPAIRING visible_message("[src] begins repairing the floor.") spawn(50) if(mode == BOT_REPAIRING) F.broken = 0 F.burnt = 0 F.ChangeTurf(/turf/simulated/floor) mode = BOT_IDLE amount -= 1 updateicon() anchored = 0 target = null /obj/machinery/bot/floorbot/proc/eattile(var/obj/item/stack/tile/plasteel/T) if(!istype(T, /obj/item/stack/tile/plasteel)) return visible_message(" [src] begins to collect tiles.") mode = BOT_REPAIRING spawn(20) if(isnull(T)) target = null mode = BOT_IDLE return if(amount + T.amount > 50) var/i = 50 - amount amount += i T.amount -= i else amount += T.amount qdel(T) updateicon() target = null mode = BOT_IDLE /obj/machinery/bot/floorbot/proc/maketile(var/obj/item/stack/sheet/metal/M) if(!istype(M, /obj/item/stack/sheet/metal)) return visible_message(" [src] begins to create tiles.") mode = BOT_REPAIRING spawn(20) if(isnull(M)) target = null mode = BOT_IDLE return var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel T.amount = 4 T.loc = M.loc if(M.amount > 1) M.amount-- else qdel(M) target = null mode = BOT_IDLE /obj/machinery/bot/floorbot/proc/updateicon() if(amount > 0) icon_state = "floorbot[on]" else icon_state = "floorbot[on]e" /obj/machinery/bot/floorbot/explode() on = 0 visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec) N.contents = list() new /obj/item/device/assembly/prox_sensor(Tsec) if (prob(50)) new /obj/item/robot_parts/l_arm(Tsec) while (amount)//Dumps the tiles into the appropriate sized stacks if(amount >= 16) var/obj/item/stack/tile/plasteel/T = new (Tsec) T.amount = 16 amount -= 16 else var/obj/item/stack/tile/plasteel/T = new (Tsec) T.amount = amount amount = 0 var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() qdel(src) return /obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/plasteel/T, mob/user as mob, params) if(!istype(T, /obj/item/stack/tile/plasteel)) ..() return if(contents.len >= 1) user << "They won't fit in, as there is already stuff inside." return if(T.use(10)) if(user.s_active) user.s_active.close(user) var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles user.put_in_hands(B) user << "You add the tiles into the empty toolbox. They protrude from the top." user.unEquip(src, 1) qdel(src) else user << "You need 10 floor tiles to start building a floorbot." return /obj/item/weapon/toolbox_tiles/attackby(var/obj/item/W, mob/user as mob, params) ..() if(isprox(W)) qdel(W) var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor() B.created_name = created_name user.put_in_hands(B) user << "You add the sensor to the toolbox and tiles!" user.unEquip(src, 1) qdel(src) else if (istype(W, /obj/item/weapon/pen)) var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if (!t) return if (!in_range(src, usr) && loc != usr) return created_name = t /obj/item/weapon/toolbox_tiles_sensor/attackby(var/obj/item/W, mob/user as mob, params) ..() if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) qdel(W) var/turf/T = get_turf(user.loc) var/obj/machinery/bot/floorbot/A = new /obj/machinery/bot/floorbot(T) A.name = created_name user << "You add the robot arm to the odd looking toolbox assembly! Boop beep!" user.unEquip(src, 1) qdel(src) else if (istype(W, /obj/item/weapon/pen)) var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) if (!t) return if (!in_range(src, usr) && loc != usr) return created_name = t