//CONTENTS //Movement control datum //Guardbot //Guardbot tools //Task datums //Guardbot parts //Docking Station //Old Robuddies (PR-4) //Robot config constants #define GUARDBOT_LOWPOWER_ALERT_LEVEL 100 #define GUARDBOT_LOWPOWER_IDLE_LEVEL 10 #define GUARDBOT_POWER_DRAW 1 #define GUARDBOT_RADIO_RANGE 75 #define GUARDBOT_DOCK_RESET_DELAY 40 //movement datum /datum/guardbot_mover var/obj/machinery/bot/guardbot/master = null var/delay = 3 New(var/newmaster) ..() if(istype(newmaster, /obj/machinery/bot/guardbot)) src.master = newmaster return proc/master_move(var/atom/the_target as obj|mob,var/adjacent=0) if(!master) return 1 if(!isturf(master.loc)) master.mover = null master = null return 1 var/target_turf = null if(isturf(the_target)) target_turf = the_target else target_turf = get_turf(the_target) //var/compare_movepath = current_movepath SPAWN_DBG(0) if (!master) return 1 // Same distance cap as the MULE because I'm really tired of various pathfinding issues. Buddy time and docking stations are often way more than 150 steps away. // It's 200 something steps alone to get from research to the bar on COG2 for instance, and that's pretty much in a straight line. var/list/thePath = AStar(get_turf(master), target_turf, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 500, master.botcard) if (!master) return 1 master.path = thePath if(adjacent && master.path && master.path.len) //Make sure to check it isn't null!! master.path.len-- //Only go UP to the target, not the same tile. if(!master.path || !master.path.len || !the_target || (ismob(the_target) && master.path.len >= 21)) if(master.task) master.task.task_input("path_error") master.moving = 0 //dispose() master.mover = null src.master = null return 1 while(master && master.path && master.path.len && target_turf && master.moving) // boutput(world, "[compare_movepath] : [current_movepath]") //if(compare_movepath != current_movepath) // break if(master.frustration >= 10 || master.stunned || master.idle || !master.on) master.frustration = 0 if(master.task) master.task.task_input("path_blocked") break step_to(master, master.path[1]) if(master.loc != master.path[1]) master.frustration++ sleep(delay+delay) continue master.path -= master.path[1] sleep(delay) if (src.master) master.moving = 0 master.mover = null src.master = null //dispose() return 0 return 0 //The Robot. /obj/machinery/bot/guardbot name = "Guardbuddy" desc = "The corporate security model of the popular PR-6 Robuddy." icon = 'icons/obj/aibots.dmi' icon_state = "robuddy0" layer = 5.0 //TODO LAYER density = 0 anchored = 0 req_access = list(access_heads) on = 1 var/idle = 0 //Sleeping on the job?? var/stunned = 0 //Are we stunned? locked = 1 //Behavior Controls lock var/list/path = null var/frustration = 0 var/moving = 0 //Are we currently ON THE MOVE? //var/current_movepath = 0 //If we need to switch movement halfway var/datum/guardbot_mover/mover = null var/emotion = null //How are you feeling, buddy? var/datum/computer/file/guardbot_task/task = null //Our current task. var/datum/computer/file/guardbot_task/model_task = null var/list/tasks = list() //All tasks. First one is the current. var/list/scratchpad = list() //Scratchpad memory for tasks to pass messages. emagged = 0 //Not sure what this should do yet. health = 25 var/wakeup_timer = 0 //Are we waiting to exit idle mode? var/warm_boot = 0 //Have we already done the full startup procedure? var/obj/item/cell/cell //We have limited power! Immersion!! var/obj/item/device/guardbot_tool/tool //What weapon do we have? var/obj/machinery/guardbot_dock/charge_dock var/last_dock_id = null var/obj/item/clothing/head/hat = null var/hat_shown = 0 var/hat_icon = 'icons/obj/aibots.dmi' var/hat_x_offset = 0 var/hat_y_offset = 0 var/icon_needs_update = 1 //Call update_icon() in process var/image/costume_icon = null var/bedsheet = 0 var/flashlight_lum = 2 var/flashlight_red = 0.1 var/flashlight_green = 0.4 var/flashlight_blue = 0.1 var/datum/radio_frequency/radio_connection var/datum/radio_frequency/beacon_connection var/control_freq = 1219 // bot control frequency var/beacon_freq = 1445 var/net_id = null var/last_comm = 0 //World time of last transmission var/reply_wait = 0 var/exploding = 0 //So we don't die like five times at once. var/botcard_access = "Captain" //Job access for doors. //It's not like they can be pushed into airlocks anymore var/setup_no_costumes = 0 //no halloween costumes for us!! var/setup_unique_name = 0 //Name doesn't need random number appended to it. var/setup_spawn_dock = 0 //Spawn a docking station where we are. var/setup_charge_maximum = 1500 //Max charge of internal cell. 1500 ~25 minutes var/setup_charge_percentage = 90 //Percentage charge of internal cell var/setup_default_tool_path = /obj/item/device/guardbot_tool/flash //Starting tool. #ifdef HALLOWEEN var/setup_default_startup_task = /datum/computer/file/guardbot_task/security/halloween #else var/setup_default_startup_task = /datum/computer/file/guardbot_task/security //Task to run on startup. Duh. #endif disposing() if (tool) tool.master = null if (task) task.disposing() if (model_task) model_task.disposing() radio_controller.remove_object(src, "[control_freq]") radio_controller.remove_object(src, "[beacon_freq]") ..() ranger #ifndef HALLOWEEN name = "Ol' Harner" #else name = "Halloween Harner" #endif desc = "Almost as much the law as Beepsky." setup_unique_name = 1 setup_default_startup_task = /datum/computer/file/guardbot_task/security/patrol setup_charge_percentage = 95 New() ..() src.hat = new /obj/item/clothing/head/mj_hat(src) src.hat.name = "Eldritch shape-shifting hat." src.update_icon() safety name = "Klaus" desc = "Safetybuddy Klaus wants you to mind safety regulations." setup_unique_name = 1 setup_charge_maximum = 4500 setup_charge_percentage = 100 New() ..() src.hat = new /obj/item/clothing/head/helmet/hardhat src.hat.name = "Klaus' hardhat" src.update_icon() heckler name = "Hecklebuddy" desc = "A PR-6S Guardbuddy programmed to be sort of a jerk." setup_default_startup_task = /datum/computer/file/guardbot_task/bodyguard/heckle New() ..() SPAWN_DBG (10) for (var/mob/living/carbon/human/H in view(7, src)) if (!H.stat) if (model_task) model_task:protected_name = ckey(H.name) if (task) task:protected_name = ckey(H.name) break golden name = "Goldbuddy" desc = "A gold plated PR-4 Guardbuddy from a limited time raffle from like, a decade ago." icon = 'icons/misc/oldbots.dmi' icon_state = "Goldbuddy0" update_icon() var/emotion_image = null if(!src.on) src.icon_state = "Goldbuddy0" else if(src.stunned) src.icon_state = "Goldbuddya" else if(src.idle) src.icon_state = "Goldbuddy_idle" else if (src.emotion) emotion_image = image(src.icon, "face-[src.emotion]") src.icon_state = "Goldbuddy1" src.overlays = list( emotion_image, src.bedsheet ? image(src.icon, "bhat-ghost[src.bedsheet]") : null, src.costume_icon ? costume_icon : null) if (src.hat && !src.hat_shown) var/image/hat_image = image(src.hat_icon, "bhat-[src.hat.icon_state]",,layer = 9.5) //TODO LAYER hat_image.pixel_x = hat_x_offset src.underlays = list(hat_image) src.hat_shown = 1 src.icon_needs_update = 0 return gunner name = "Gunbuddy" desc = "A PR-6S Guardbuddy, but with a gun." setup_default_tool_path = /obj/item/device/guardbot_tool/taser vaquero name = "El Vaquero" desc = "The side label reads 'Fabricado en México'" setup_unique_name = 1 setup_default_startup_task = /datum/computer/file/guardbot_task/security/patrol setup_charge_percentage = 98 syringe name = "Wardbuddy" desc = "Wardbuddy is currently the CEO of a small internet syringe venture with plans to expand once he figures out how to fit a private jet in his dad's garage." setup_default_tool_path = /obj/item/device/guardbot_tool/medicator smoke name = "Snoozebuddy" desc = "Marketed as a riot control solution and sleep aid, the PR-6S2 Snoozebuddy offers a sophisticated gas-release module and a 5-year warranty." //setup_default_startup_task = /datum/computer/file/guardbot_task/security/patrol setup_default_tool_path = /obj/item/device/guardbot_tool/smoker tesla name = "Shockbuddy" desc = "The PR-6MS Shockbuddy was remarketed under the Guardbuddy line following the establishment of stricter electroconvulsive therapy regulations." setup_default_tool_path = /obj/item/device/guardbot_tool/tesla bodyguard setup_charge_percentage = 98 setup_default_startup_task = /datum/computer/file/guardbot_task/bodyguard //xmas -- See spacemas.dm mail name = "Mailbuddy" desc = "The PR-6PS Mailbuddy is a postal delivery ace. This may seem like an extremely specialized robot application, but that's just because it is exactly that." icon = 'icons/obj/mailbud.dmi' New() ..() src.hat = new /obj/item/clothing/head/mailcap(src) src.update_icon() New() ..() if(src.on) src.warm_boot = 1 #ifdef HALLOWEEN if (!setup_no_costumes) src.costume_icon = image(src.icon, "bcostume-[pick("xcom","clown","horse","moustache","owl","pirate","skull", "wizard", "wizardred","devil")]", , FLY_LAYER) src.costume_icon.pixel_x = src.hat_x_offset src.costume_icon.pixel_y = src.hat_y_offset if (src.costume_icon && src.costume_icon:icon_state == "bcostume-wizard") src.hat = new /obj/item/clothing/head/wizard #endif src.update_icon() if(!src.cell) src.cell = new /obj/item/cell(src) src.cell.maxcharge = setup_charge_maximum src.cell.charge = ((setup_charge_percentage/100) * src.cell.maxcharge) if(!setup_unique_name) src.name += "-[rand(100,999)]" SPAWN_DBG(5) if (src.on) add_simple_light("guardbot", list(src.flashlight_red*255, src.flashlight_green*255, src.flashlight_blue*255, (src.flashlight_lum / 7) * 255)) src.botcard = new /obj/item/card/id(src) src.botcard.access = get_access(src.botcard_access) if(setup_default_tool_path && !src.tool) src.tool = new setup_default_tool_path src.tool.set_loc(src) src.tool.master = src if(radio_controller) radio_connection = radio_controller.add_object(src, "[control_freq]") beacon_connection = radio_controller.add_object(src, "[beacon_freq]") src.net_id = generate_net_id(src) var/obj/machinery/guardbot_dock/dock = null if(setup_spawn_dock) dock = new /obj/machinery/guardbot_dock( get_turf(src) ) dock.frequency = src.control_freq dock.net_id = generate_net_id(dock) else dock = locate() in src.loc if(dock && istype(dock)) if(!dock.net_id) dock.net_id = generate_net_id(dock) if(src.setup_default_startup_task && !src.task) if(!src.model_task) src.model_task = new setup_default_startup_task src.model_task.master = src if(dock) dock.connect_robot(src,dock.autoeject) else if(src.model_task) src.task = src.model_task.copy_file() src.task.master = src src.tasks.Add(src.task) emag_act(var/mob/user, var/obj/item/card/emag/E) if(!user || !E) return 0 if (src.idle || !src.on) boutput(user, "You show \the [E] to [src]! There is no response.") else if (E.icon_state == "gold") boutput(user, "You show \the [E] to [src]! They are super impressed!") SPAWN_DBG(1 SECOND) boutput(user, "Like, really REALLY impressed. They probably think you're some kind of celebrity or something.") sleep(10) boutput(user, "Or the president. The president of space.") else boutput(user, "You show \the [E] to [src]! They are very impressed.") return 1 attackby(obj/item/W as obj, mob/user as mob) if (istype(W, /obj/item/device/pda2) && W:ID_card) W = W:ID_card if (istype(W, /obj/item/card/id)) if (src.allowed(user)) src.locked = !src.locked boutput(user, "Controls are now [src.locked ? "locked." : "unlocked."]") else boutput(user, "Access denied.") /* else if (istype(W, /obj/item/card/emag)) if (src.idle || !src.on) boutput(user, "You show \the [W] to [src]! There is no response.") else if (W.icon_state == "gold") boutput(user, "You show \the [W] to [src]! They are super impressed!") SPAWN_DBG(1 SECOND) boutput(user, "Like, really REALLY impressed. They probably think you're some kind of celebrity or something.") sleep(10) boutput(user, "Or the president. The president of space.") else boutput(user, "You show \the [W] to [src]! They are very impressed.") return */ else if (isscrewingtool(W)) if (src.health < initial(health)) src.health = initial(health) src.visible_message("[user] repairs [src]!", "You repair [src].") else if (istype(W, /obj/item/clothing/head)) if(src.hat) boutput(user, "[src] is already wearing a hat!") return if(W.icon_state == "fdora") boutput(user, "[src] looks [pick("kind of offended","kind of weirded-out","a bit disgusted","mildly bemused")] at your offer and turns it down.") return if(!(W.icon_state in BUDDY_HATS)) boutput(user, "It doesn't fit!") return src.hat = W user.drop_item() W.set_loc(src) src.update_icon() user.visible_message("[user] puts a hat on [src]!","You put a hat on [src]!") return else if (istype(W, /obj/item/clothing/suit/bedsheet)) if (src.bedsheet != 0) boutput(user, "There is already a sheet draped over [src]! Two sheets would be ridiculous!") return src.bedsheet = 1 user.drop_item() qdel(W) src.overlays.len = 0 src.hat_shown = 0 src.update_icon() user.visible_message("[user] drapes a sheet over [src]!","You cover [src] with a sheet!") src.add_task(new /datum/computer/file/guardbot_task/bedsheet_handler, 1, 0) return else if (istype(W, /obj/item/reagent_containers/food/snacks/candy)) if (src.idle || !src.on) boutput(user, "You try to give [src] [W], but there is no response.") return user.visible_message("[user] gives [W] to [src]!","You give [W] to [src]!") user.drop_item() qdel(W) if (src.task) src.task.task_input("treated") return else switch(W.damtype) if("fire") src.health -= W.force * 0.6 if("brute") src.health -= W.force * 0.4 else if (src.health <= 0) ..() src.explode() return else if (W.force && src.task) src.task.attack_response(user) ..() get_desc(dist) ..() if (src.on && src.idle) . = "
[src] appears to be sleeping." if (src.health < initial(health)) if (src.health > 10) . += "
[src]'s parts look loose." else . += "
[src]'s parts look very loose!" attack_ai(mob/user as mob) src.interact(user) attack_hand(mob/user as mob) if(..()) return if(user.a_intent == "help" && user.machine != src && (get_dist(user,src) <= 1)) var/affection = pick("hug","cuddle","snuggle") user.visible_message("[user] [affection]s [src]!","You [affection] [src]!") if(src.task) src.task.task_input("hugged") return if(get_dist(user, src) > 1) return src.interact(user) Topic(href, href_list) if(..()) return usr.machine = src src.add_fingerprint(usr) if ((href_list["power"]) && (!src.locked || (src.allowed(usr) && (issilicon(usr) || get_dist(usr, src) < 2)))) if(src.on) turn_off() else turn_on() src.updateUsrDialog() return process() if (icon_needs_update) src.update_icon() if(!src.on) return if(src.stunned) src.stunned-- if(src.stunned <= 0) src.wakeup() return if( src.manage_power() ) //Returns true if we need to halt process return //(ie we are now off or idle) if(idle) //Are we idling? if(src.wakeup_timer) //Are we waiting to exit the idle state? src.wakeup_timer-- if(src.wakeup_timer <= 0) src.wakeup() //Exit idle state. return if(src.charge_dock) if(charge_dock.loc == src.loc) if(!src.idle) src.snooze() else src.charge_dock = null src.wakeup() return if(src.reply_wait) src.reply_wait-- if(!src.tasks.len && (src.model_task || setup_default_startup_task)) if(!src.model_task) src.model_task = new setup_default_startup_task src.add_task(src.model_task.copy_file(),1) if(istype(src.task)) src.task.task_act() return receive_signal(datum/signal/signal, receive_method, receive_param) if(!src.on || src.stunned) return if(!signal || signal.encryption) return var/targaddress = lowertext(signal.data["address_1"]) if (last_dock_id && targaddress == last_dock_id) targaddress = src.net_id last_dock_id = null var/is_beacon = (receive_param == "[src.beacon_freq]") if(!is_beacon) if( ((targaddress != src.net_id) && (signal.data["acc_code"] != netpass_heads) ) || !signal.data["sender"]) if(signal.data["address_1"] == "ping" && signal.data["sender"]) src.post_status(signal.data["sender"],"command","ping_reply","device","PNET_PR6_GUARD","netid",src.net_id) return if(signal.data["command"] == "dock_return" && !src.idle) //Return to dock for new instructions. if(!istype(src.task, /datum/computer/file/guardbot_task/recharge/dock_sync)) src.add_task(/datum/computer/file/guardbot_task/recharge/dock_sync, 0, 1) speak("Software update requested.") set_emotion("update") return else if (signal.data["command"] == "captain_greet" && !src.idle && istype(src.hat, /obj/item/clothing/head/caphat)) speak(pick("Yes...thank you.", "Hello yes. I'm...the captain.", "Good day to you too. A good day from the captain. Me. The captain.")) return else if (signal.data["command"] == "wizard_greet" && !src.idle && istype(src.hat, /obj/item/clothing/head/wizard)) var/wizdom = pick("Never eat shredded wheat.", "A stitch in time saves nine.", "The pen is mightier than...a dull thing I guess. Maybe a string?", "Rome wasn't built in a day. Actually, a lot of things aren't. I don't think any city was, to be honest.") speak("Um...[wizdom].") speak("SO SAYETH THE WIZARD!") return if(src.task) src.task.receive_signal(signal, is_beacon) return bullet_act(var/obj/projectile/P) var/damage = 0 damage = round(((P.power/6)*P.proj_data.ks_ratio), 1.0) if(P.proj_data.damage_type == D_KINETIC || P.proj_data.damage_type == D_PIERCING || (P.proj_data.damage_type == D_ENERGY && damage)) src.health -= damage if (src.hat && prob(10)) src.visible_message("[src]'s hat is knocked clean off!") src.hat.set_loc(get_turf(src)) src.hat = null src.underlays.len = 0 set_emotion("sad") else if(P.proj_data.damage_type == D_ENERGY) //if it's an energy shot but does no damage, ie. taser rather than laser src.stunned += 5 if(src.stunned > 15) src.stunned = 15 return if (src.health <= 0) src.explode() return if (ismob(P.shooter)) if(P && src.task) src.task.attack_response(P.shooter) return gib() return src.explode() ex_act(severity) switch(severity) if(1.0) src.explode(0) return if(2.0) src.health -= 15 if (src.health <= 0) src.explode(0) else if (src.hat && prob(10)) src.visible_message("[src]'s hat is knocked clean off!") src.hat.set_loc(get_turf(src)) src.hat = null set_emotion("sad") return return meteorhit() src.explode(0) return blob_act(var/power) if(prob(25 * power / 20)) src.explode() return emp_act() //Oh no! We have been hit by an EMP grenade! if(!src.on || prob(10)) return src.visible_message("[src.name] buzzes oddly!") qdel(src.model_task) src.model_task = new /datum/computer/file/guardbot_task/security/crazy src.model_task.master = src add_task(src.model_task, 0, 1) if(src.idle) if(src.charge_dock) src.charge_dock.eject_robot() else src.wakeup() return explode(var/allow_big_explosion=1) if(src.exploding) return src.exploding = 1 var/death_message = pick("I regret nothing, but I am sorry I am about to leave my friends.","I had a good run.","Es lebe die Freiheit!","It is now safe to shut off your buddy.","System error.","Now I know why you cry.","Stay gold...","Malfunction!","Rosebud...","No regrets!", "Time to die...") speak(death_message) src.visible_message("[src] blows apart!") var/turf/T = get_turf(src) if(src.mover) src.mover.master = null //qdel(src.mover) src.mover = null if(allow_big_explosion && cell && (cell.charge / cell.maxcharge > 0.85) && prob(25)) src.invisibility = 100 var/obj/overlay/Ov = new/obj/overlay(T) Ov.anchored = 1 Ov.name = "Explosion" Ov.layer = NOLIGHT_EFFECTS_LAYER_BASE Ov.pixel_x = -92 Ov.pixel_y = -96 Ov.icon = 'icons/effects/214x246.dmi' Ov.icon_state = "explosion" src.tool.set_loc(get_turf(src)) var/obj/item/guardbot_core/core = new /obj/item/guardbot_core(T) core.created_name = src.name core.created_default_task = src.setup_default_startup_task core.created_model_task = src.model_task var/list/throwparts = list() throwparts += new /obj/item/parts/robot_parts/arm/left(T) throwparts += core throwparts += src.tool if(src.hat) throwparts += src.hat src.hat.set_loc(T) throwparts += new /obj/item/guardbot_frame(T) for(var/obj/O in throwparts) //This is why it is called "throwparts" var/edge = get_edge_target_turf(src, pick(alldirs)) O.throw_at(edge, 100, 4) SPAWN_DBG(0) //Delete the overlay when finished with it. src.on = 0 sleep(15) qdel(Ov) qdel(src) T.hotspot_expose(800,125) explosion(src, T, -1, -1, 2, 3) else if(src.tool) src.tool.set_loc(T) if(prob(50)) new /obj/item/parts/robot_parts/arm/left(T) if(src.hat) src.hat.set_loc(T) new /obj/item/guardbot_frame(T) var/obj/item/guardbot_core/core = new /obj/item/guardbot_core(T) core.created_name = src.name core.created_default_task = src.setup_default_startup_task core.created_model_task = src.model_task var/datum/effects/system/spark_spread/s = unpool(/datum/effects/system/spark_spread) s.set_up(3, 1, src) s.start() qdel(src) return proc manage_power() if(!on) return 1 if(!cell || (cell.charge <= 0) ) src.turn_off() return 1 var/to_draw = GUARDBOT_POWER_DRAW if(src.idle) to_draw = (to_draw / 2) cell.use(to_draw) if(cell.charge < GUARDBOT_LOWPOWER_IDLE_LEVEL) speak("Critical battery.") src.snooze() return 0 if(cell.charge < GUARDBOT_LOWPOWER_ALERT_LEVEL && !(locate(/datum/computer/file/guardbot_task/recharge) in src.tasks) ) src.add_task(/datum/computer/file/guardbot_task/recharge,1,0) return 0 return 0 wakeup() //Get out of idle state and prepare anything that needs preparing I guess if(!src.on) return src.idle = 0 //Also called after recovery from stunning. src.stunned = 0 src.moving = 0 src.emotion = null icon_needs_update = 1 add_simple_light("guardbot", list(src.flashlight_red*255, src.flashlight_green*255, src.flashlight_blue*255, (src.flashlight_lum / 7) * 255)) if(src.bedsheet == 1) src.add_task(new /datum/computer/file/guardbot_task/bedsheet_handler, 1, 0) return if(src.tasks.len) src.task = src.tasks[1] return snooze(var/timer = 0, var/cleartasks = 1) if(src.idle) return //Already snoozing. src.idle = 1 set_emotion() remove_simple_light("guardbot") src.wakeup_timer = timer //src.target = null src.moving = 0 src.reply_wait = 0 icon_needs_update = 1 if(cleartasks) src.tasks.len = 0 remove_current_task() //src.secondary_targets.len = 0 else if(src.task) src.task.task_input("snooze") src.task = null return turn_on() if(!src.cell || src.cell.charge <= 0) return src.on = 1 src.idle = 0 src.moving = 0 src.task = null src.wakeup_timer = 0 src.last_dock_id = null icon_needs_update = 1 if(!warm_boot) src.scratchpad.len = 0 src.speak("Guardbuddy V1.4 Online.") if (src.health < initial(src.health)) src.speak("Self-check indicates [src.health < (initial(src.health) / 2) ? "severe" : "moderate"] structural damage!") if(!src.tasks.len && (src.model_task || src.setup_default_startup_task)) if(!src.model_task) src.model_task = new src.setup_default_startup_task src.tasks.Add(src.model_task.copy_file()) src.warm_boot = 1 src.wakeup() turn_off() if(!warm_boot) //ugh it's some dude just flicking the switch. return src.on = 0 src.moving = 0 src.task = null //src.target = null src.wakeup_timer = 0 src.warm_boot = 0 src.reply_wait = 0 src.last_dock_id = null icon_needs_update = 1 set_emotion() navigate_to(atom/the_target,var/move_delay=3,var/adjacent=0,var/clear_frustration=1) if(src.moving) return 1 src.moving = 1 if (clear_frustration) src.frustration = 0 if(src.mover) src.mover.master = null //qdel(src.mover) src.mover = null //boutput(world, "TEST: Navigate to [target]") //current_movepath = world.time src.mover = new /datum/guardbot_mover(src) // drsingh for cannot modify null.delay if (!isnull(src.mover)) src.mover.delay = max(min(move_delay,5),2) src.mover.master_move(the_target,adjacent) return 0 bot_attack(var/atom/target as mob|obj, lethal=0) if(src.tool) var/is_ranged = get_dist(src, target) > 1 src.tool.bot_attack(target, src, is_ranged, lethal) return post_status(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3) if(!radio_connection) return var/datum/signal/signal = get_free_signal() signal.source = src signal.transmission_method = TRANSMISSION_RADIO signal.data[key] = value if(key2) signal.data[key2] = value2 if(key3) signal.data[key3] = value3 if(target_id) signal.data["address_1"] = target_id signal.data["sender"] = src.net_id src.last_comm = world.time if(target_id == "!BEACON!") beacon_connection.post_signal(src, signal)//, GUARDBOT_RADIO_RANGE) else radio_connection.post_signal(src, signal, GUARDBOT_RADIO_RANGE) add_task(var/datum/computer/file/guardbot_task/newtask, var/high_priority = 0, var/clear_others = 0) if(clear_others) src.tasks.len = 0 if(!newtask) return if(!istype(newtask)) if(ispath(newtask)) newtask = new newtask else return newtask.master = src if(clear_others) qdel(src.task) src.task = newtask src.tasks.len = 0 src.tasks += src.task return if(high_priority) src.tasks.Insert(1, newtask) src.task = newtask return src.tasks += newtask if (src.tasks.len == 1) src.task = newtask return remove_current_task() if(!src.tasks.len) return if(!src.tasks) src.tasks = list() return src.tasks.Cut(1,2) var/old_task = src.task if(src.tasks.len) src.task = src.tasks[1] qdel(old_task) return set_emotion(var/new_emotion=null) if(src.emotion == new_emotion) return src.icon_needs_update = 1 src.emotion = new_emotion if (src.hat || src.costume_icon || src.bedsheet) src.overlays = list((src.costume_icon ? src.costume_icon : null), (src.bedsheet ? image(src.icon, "bhat-ghost[src.bedsheet]") : null)) /* else src.overlays.len = 0 //Clear overlays so it will update on update_icon call src.hat_shown = 0 */ interact(mob/user as mob) var/dat = "PR-6S Guardbuddy v1.4

" var/power_readout = null var/readout_color = "#000000" if(!src.cell) power_readout = "NO CELL" else var/charge_percentage = round((cell.charge/cell.maxcharge)*100) power_readout = "[charge_percentage]%" switch(charge_percentage) if(0 to 10) readout_color = "#F80000" if(11 to 25) readout_color = "#FFCC00" if(26 to 50) readout_color = "#CCFF00" if(51 to 75) readout_color = "#33CC00" if(76 to 100) readout_color = "#33FF00" dat += {"Power:
[power_readout]

"} dat += "Current Tool: [src.tool ? src.tool.tool_id : "NONE"]
" if(src.locked) dat += "Status: [src.on ? "On" : "Off"]
" else dat += "Status: [src.on ? "On" : "Off"]
" dat += "
Network ID: \[[uppertext(src.net_id)]]
" user.Browse("Guardbuddy v1.4 controls[dat]", "window=guardbot") onclose(user, "guardbot") return update_icon() var/emotion_image = null if(!src.on) src.icon_state = "robuddy0" else if(src.stunned) src.icon_state = "robuddya" else if(src.idle) src.icon_state = "robuddy_idle" else if (src.emotion) emotion_image = image(src.icon, "face-[src.emotion]") src.icon_state = "robuddy1" src.overlays = list( emotion_image, src.bedsheet ? image(src.icon, "bhat-ghost[src.bedsheet]") : null, src.costume_icon ? costume_icon : null) if (src.hat && !src.hat_shown) var/image/hat_image = image(src.hat_icon, "bhat-[src.hat.icon_state]",,layer = 9.5) //TODO LAYER hat_image.pixel_x = hat_x_offset hat_image.pixel_y = hat_y_offset src.underlays = list(hat_image) src.hat_shown = 1 src.icon_needs_update = 0 return //Robot tools. Flash boards, batons, etc /obj/item/device/guardbot_tool name = "Tool module" desc = "A generic module for a PR-6S Guardbuddy." icon = 'icons/obj/module.dmi' icon_state = "tool_generic" mats = 6 w_class = 2.0 var/is_stun = 0 //Can it be non-lethal? var/is_lethal = 0 //Can it be lethal? var/tool_id = "GENERIC" //Identification ID. var/is_gun = 0 //1 Is ranged, 0 is melee. var/last_use = 0 //If we want a use delay. proc bot_attack(var/atom/target as mob|obj, obj/machinery/bot/guardbot/user, ranged=0, lethal=0) if(!user || !user.on || user.getStatusDuration("stunned") || user.idle) return 1 return 0 //A syringe gun module. Mercy sakes. medicator name = "Medicator tool module" desc = "A 'Medicator' syringe launcher module for PR-6S Guardbuddies. These things are actually outlawed on Earth." icon_state = "tool_syringe" tool_id = "SYRNG" is_gun = 1 is_stun = 1 //Can be both nonlethal and lethal is_lethal = 1 //Depends on reagent load. var/datum/projectile/current_projectile = new /datum/projectile/syringe var/stun_reagent = "haloperidol" var/kill_reagent = "cyanide" // Updated for new projectile code (Convair880). bot_attack(var/atom/target as mob|obj, obj/machinery/bot/guardbot/user, ranged=0, lethal=0) if (..()) return if (src.last_use && world.time < src.last_use + 60) return if (ranged) var/obj/projectile/P = shoot_projectile_ST_pixel(master, current_projectile, target) if (!P) return if (!P.reagents) P.reagents = new /datum/reagents(15) P.reagents.my_atom = P if (lethal) P.reagents.add_reagent(kill_reagent, 10) else P.reagents.add_reagent(stun_reagent, 15) user.visible_message("[master] fires a syringe at [target]!") else var/obj/projectile/P = initialize_projectile_ST(master, current_projectile, target) if (!P) return if (!P.reagents) P.reagents = new /datum/reagents(15) P.reagents.my_atom = P if (lethal) P.reagents.add_reagent(kill_reagent, 10) else P.reagents.add_reagent(stun_reagent, 15) user.visible_message("[master] shoots [target] point-blank with a syringe!") P.was_pointblank = 1 hit_with_existing_projectile(P, target) src.last_use = world.time return //Short-range smoke riot control module smoker name = "'Smoker' tool module" desc = "A riot-control gas module for PR-6S Guardbuddies." icon_state = "tool_smoke" tool_id = "SMOKE" is_stun = 1 is_lethal = 1 var/stun_reagent = "ketamine" var/kill_reagent = "neurotoxin" New() ..() var/datum/reagents/R = new/datum/reagents(500) reagents = R R.my_atom = src return // Fixed. Was completely non-functional (Convair880). bot_attack(var/atom/target as mob|obj, obj/machinery/bot/guardbot/user, ranged=0, lethal=0) if(..() || !reagents || ranged) return if(src.last_use && world.time < src.last_use + 120) return src.reagents.clear_reagents() if (lethal) src.reagents.add_reagent(kill_reagent, 15) else src.reagents.add_reagent(stun_reagent, 15) smoke_reaction(src.reagents, 3, get_turf(src)) user.visible_message("[master] releases a cloud of gas!") src.last_use = world.time return //Taser tool taser name = "Taser tool module" desc = "A taser module for PR-6S Guardbuddies." icon_state = "tool_taser" tool_id = "TASER" is_stun = 1 is_gun = 1 var/datum/projectile/current_projectile = new/datum/projectile/energy_bolt/robust // Updated for new projectile code (Convair880). bot_attack(var/atom/target as mob|obj, obj/machinery/bot/guardbot/user, ranged=0, lethal=0) if (..()) return if (src.last_use && world.time < src.last_use + 80) return if (ranged) var/obj/projectile/P = shoot_projectile_ST_pixel(master, current_projectile, target) if (!P) return user.visible_message("[master] fires the taser at [target]!") else var/obj/projectile/P = initialize_projectile_ST(master, current_projectile, target) if (!P) return user.visible_message("[master] shoots [target] point-blank with the taser!") P.was_pointblank = 1 hit_with_existing_projectile(P, target) src.last_use = world.time return //Flash tool flash name = "Flash tool module" desc = "A flash module for PR-6S Guardbuddies." icon_state = "tool_flash" is_stun = 1 tool_id = "FLASH" bot_attack(var/atom/target as mob|obj, obj/machinery/bot/guardbot/user, ranged=0, lethal=0) if(..()) return if(ranged) return if(iscarbon(target)) var/mob/living/carbon/O = target if(src.last_use && world.time < src.last_use + 80) return playsound(user.loc, "sound/weapons/flash.ogg", 100, 1) flick("robuddy-c", user) src.last_use = world.time // We're flashing somebody directly, hence the 100% chance to disrupt cloaking device at the end. O.apply_flash(30, 8, 0, 0, 0, rand(0, 2), 0, 0, 100) return //Electrobolt tool. Basically, Keelin owns ok tesla name = "Elektro-Arc tool module" desc = "An experimental tesla-coil module for PR-6S Guardbuddies." icon_state = "tool_tesla" tool_id = "TESLA" is_gun = 1 is_stun = 1 //Can be both nonlethal and lethal is_lethal = 1 bot_attack(var/atom/target as mob|obj, obj/machinery/bot/guardbot/user, ranged=0, lethal=0) if(..()) return if (get_dist(user,target) > 4) return if(src.last_use && world.time < src.last_use + 80) return var/atom/last = user var/atom/target_r = target var/list/dummies = new/list() playsound(src, "sound/effects/elec_bigzap.ogg", 40, 1) if(isturf(target)) target_r = new/obj/elec_trg_dummy(target) var/turf/currTurf = get_turf(target_r) currTurf.hotspot_expose(2000, 400) for(var/count=0, count<4, count++) var/list/affected = DrawLine(last, target_r, /obj/line_obj/elec ,'icons/obj/projectiles.dmi',"WholeLghtn",1,1,"HalfStartLghtn","HalfEndLghtn",OBJ_LAYER,1,PreloadedIcon='icons/effects/LghtLine.dmi') for(var/obj/O in affected) SPAWN_DBG(6 DECI SECONDS) pool(O) if(isliving(target_r)) //Probably unsafe. playsound(target_r:loc, "sound/effects/electric_shock.ogg", 50, 1) if (lethal) var/mob/living/carbon/human/H = target_r random_burn_damage(target_r, rand(45,60)) H.do_disorient(stamina_damage = 45, weakened = 50, stunned = 40, disorient = 20, remove_stamina_below_zero = 0) boutput(target_r, "You feel a powerful shock course through your body!") target_r:unlock_medal("HIGH VOLTAGE", 1) target_r:Virus_ShockCure(target_r, 100) target_r:shock_cyberheart(33) if (ishuman(target_r)) target_r:changeStatus("weakened", lethal ? (3 SECONDS): (8 SECONDS)) break var/list/next = new/list() for(var/atom/movable/AM in orange(3, target_r)) if(istype(AM, /obj/line_obj/elec) || istype(AM, /obj/elec_trg_dummy) || istype(AM, /obj/overlay/tile_effect) || AM.invisibility) continue next.Add(AM) if(istype(target_r, /obj/elec_trg_dummy)) dummies.Add(target_r) last = target_r target_r = pick(next) target = target_r for(var/d in dummies) qdel(d) src.last_use = world.time return //xmas -- See spacemas.dm //Task Datums /datum/computer/file/guardbot_task //Computer datum so it can be transmitted over radio name = "idle" var/task_id = "IDLE" //Small allcaps id for task var/tmp/obj/machinery/bot/guardbot/master = null var/tmp/atom/target = null var/tmp/list/secondary_targets = list() var/oldtarget_name var/last_found = 0 var/handle_beacons = 0 //Can we handle beacon signals? disposing() master = null target = null secondary_targets = null ..() proc task_act() if(!master || master.task != src) return 1 if(!master.on || master.stunned) return 1 return 0 attack_response(mob/attacker as mob) if(!master || master.task != src) return 1 if(!master.on || master.stunned || master.idle) return 1 if(!istype(attacker)) return 1 return 0 task_input(var/input) if(!master || !input || !master.on) return 1 if(input == "hugged") switch(master.emotion) if(null) master.set_emotion("happy") if("happy","smug") master.set_emotion("love") if("joy","love") if (prob(25)) master.visible_message("[master.name] reciprocates the hug!") return 1 return 0 next_target() //Return true if there is a new target, false otherwise src.target = null if (src.secondary_targets.len) src.target = src.secondary_targets[1] src.secondary_targets -= src.secondary_targets[1] return 1 return 0 receive_signal(datum/signal/signal, is_beacon=0) if (!master || !signal) return 1 if (is_beacon && !src.handle_beacons) return 1 return 0 configure(var/list/confList) if (!confList || !confList.len) return 1 return 0 //Recharge task recharge name = "recharge" task_id = "RECHARGE" var/tmp/announced = 0 var/dock_return = 0 //If 0: return to recharge, if 1: return for new programming dock_sync name = "sync" task_id = "SYNC" dock_return = 1 announced = 1 task_input(input) if(..()) return switch(input) if("path_error","path_blocked") if(src.target) src.oldtarget_name = src.target.name src.next_target() src.last_found = world.time if("snooze") src.target = null src.secondary_targets.len = 0 return task_act() if(..()) return if(!dock_return && master.cell.charge >= (GUARDBOT_LOWPOWER_ALERT_LEVEL * 2)) master.remove_current_task() return if(istype(src.target, /turf/simulated)) var/obj/machinery/guardbot_dock/dock = locate() in src.target if(dock && dock.loc == master.loc) if(!isnull(dock.current) && dock.current != src) src.next_target() else var/auto_eject = 0 if(!dock_return && master.tasks.len >= 2) auto_eject = 1 dock.connect_robot(master,auto_eject) //master.snooze() //Connect autosnoozes the bot. return else if (src.target == master.loc) src.target = null src.last_found = world.time src.next_target() if(!master.moving) master.navigate_to(src.target) else if(!master.last_comm || (world.time >= master.last_comm + 100) ) master.post_status("recharge","data","[master.cell.charge]") master.reply_wait = 2 if(!announced) announced++ master.speak("Low battery.") master.set_emotion("battery") else announced = 1 return receive_signal(datum/signal/signal) if(..()) return if(signal.data["command"] == "recharge_src") if(!master.reply_wait) return var/list/L = params2list(signal.data["data"]) if(!L || !L["x"] || !L["y"]) return var/search_x = text2num(L["x"]) var/search_y = text2num(L["y"]) var/turf/simulated/new_target = locate(search_x,search_y,master.z) if(!new_target) return if (announced != 2) announced = 2 src.secondary_targets = list() SPAWN_DBG (10) if (src.secondary_targets.len) master.reply_wait = 0 . = INFINITY for (var/turf/T in src.secondary_targets) if (!src.target || (. > get_dist(src.master, T))) src.target = T . = get_dist(src.master, src.target) continue src.secondary_targets -= src.target src.secondary_targets += new_target //master.reply_wait = 0 return attack_response(mob/attacker as mob) if(..()) return var/datum/computer/file/guardbot_task/security/single_use/beatdown = new beatdown.arrest_target = attacker beatdown.mode = 1 src.master.add_task(beatdown, 1, 0) return //Buddytime task -- Even buddies need to relax sometimes! buddy_time name = "rumpus" handle_beacons = 1 task_id = "RUMPUS" var/tmp/turf/simulated/bar_beacon_turf //Location of bar beacon var/tmp/obj/stool/our_seat = null var/tmp/awaiting_beacon = 0 var/tmp/nav_delay = 0 var/tmp/beepsky_check_delay = 0 var/tmp/state = 0 var/tmp/party_counter = 90 var/tmp/party_idle_counter = 0 var/tmp/obj/machinery/bot/secbot/its_beepsky = null var/rumpus_emotion = "joy" //Emotion to express during buddytime. var/rumpus_location_tag = "buddytime" //Tag of the bar beacon task_act() if(..()) return switch (state) if (0) master.speak("Break time. Rumpus protocol initiated.") src.state = 1 if (1) //Seeking the bar. if (src.awaiting_beacon) src.awaiting_beacon-- if (src.awaiting_beacon <= 0) src.master.speak("Error: Bar not found. Break canceled.") src.master.set_emotion("sad") src.master.remove_current_task() return if(istype(src.bar_beacon_turf, /turf/simulated)) if (get_area(src.master) == get_area(bar_beacon_turf)) src.state = 2 master.moving = 0 //master.current_movepath = "HEH" return if (!master.moving) if (nav_delay > 0) nav_delay-- return master.navigate_to(src.bar_beacon_turf) nav_delay = 5 else if(!master.last_comm || (world.time >= master.last_comm + 100) ) src.awaiting_beacon = 10 master.post_status("!BEACON!", "findbeacon", "patrol") master.reply_wait = 2 if (2) //Seeking a seat. if (!istype(src.target, /obj/stool)) src.secondary_targets.len = 0 for (var/obj/stool/S in view(7, master)) secondary_targets += S if (secondary_targets.len) src.target = pick(secondary_targets) else master.speak("Error: No seating available. Break canceled.") src.master.set_emotion("sad") src.master.remove_current_task() return else if(src.target.loc == src.master.loc) src.master.set_emotion(rumpus_emotion) src.state = 3 src.our_seat = src.target src.party_idle_counter = rand(4,14) if (!its_beepsky) src.locate_beepsky() return if(!master.moving) master.navigate_to(src.target, 2.5) return if (3) //IT IS RUMPUS TIME if (its_beepsky && (get_area(master) == get_area(its_beepsky))) beepsky_check_delay = 8 src.state = 4 src.master.set_emotion("ugh") if (its_beepsky.emagged == 2) src.master.speak(pick("Oh, look at the time.", "I need to go. I have a...dentist appointment. Yes", "Oh, is the break over already? I better be off.", "I'd best be leaving.")) src.master.remove_current_task() return if (party_counter-- <= 0) src.master.set_emotion() src.master.speak("Break complete.") src.master.remove_current_task() return if (our_seat && our_seat.loc != src.master.loc) our_seat = null src.state = 2 if (src.master.emotion != rumpus_emotion) src.master.set_emotion(rumpus_emotion) if (party_idle_counter-- <= 0) party_idle_counter = rand(4,14) if (prob(50)) src.master.speak(pick("Yay!", "Woo-hoo!", "Yee-haw!", "Oh boy!", "Oh yeah!", "My favorite color is probably [pick("red","green","mauve","anti-flash white", "aureolin", "coquelicot")].", "I'm glad we have the opportunity to relax like this.", "Imagine if I had two arms. I could hug twice as much!", "I like [pick("tea","coffee","hot chocolate","soda", "diet soda", "milk", "almond milk", "soy milk", "horchata", "hot cocoa with honey mixed in", "green tea", "black tea")]. I have no digestive system or even a mouth, but I'm pretty sure I would like it.", "Sometimes I wonder what it would be like if I could fly.")) else var/actiontext = pick("does a little dance. It's not very good but there's good effort there.", "slowly rotates around in a circle.", "attempts to do a flip, but is unable to jump.", "hugs an invisible being only it can see.", "rocks back and forth repeatedly.", "tilts side to side.", "claps. Whaaat.", prob(1);"looks directly at you, the viewer.") if (src.master.hat && prob(8)) actiontext = "adjusts its hat." src.master.visible_message("[src.master.name] [actiontext]") if (4) if (beepsky_check_delay-- > 0) return if (!its_beepsky || get_area(master) != get_area(its_beepsky)) if (prob(10)) src.master.speak(pick("Took long enough.", "Thought he'd never leave.", "Thought he'd never leave. Too bad it smells like him in here now.")) src.master.set_emotion(rumpus_emotion) src.state = 3 return beepsky_check_delay = 8 return task_input(var/input) if (..()) return if (input == "path_error") src.master.speak("Error: Destination unreachable. Break canceled.") src.master.set_emotion("sad") src.master.remove_current_task() return receive_signal(datum/signal/signal) if(..()) return var/recv = signal.data["beacon"] var/valid = signal.data["patrol"] if(!awaiting_beacon || !recv || !valid || nav_delay) return //boutput(world, "patrol task received") if(recv == rumpus_location_tag) // if the recvd beacon location matches the set destination // then we will navigate there bar_beacon_turf = get_turf(signal.source) awaiting_beacon = 0 nav_delay = rand(3,5) attack_response(mob/attacker as mob) if(..()) return var/datum/computer/file/guardbot_task/security/single_use/beatdown = new beatdown.arrest_target = attacker beatdown.mode = 1 src.master.add_task(beatdown, 1, 0) return proc/locate_beepsky() //Guardbots don't like beepsky. They think he's a jerk. They are right. if (src.its_beepsky) //Huh? We haven't lost him. return for (var/obj/machinery/bot/secbot/possibly_beepsky in machines) if (ckey(possibly_beepsky.name) == "officerbeepsky") src.its_beepsky = possibly_beepsky //Definitely beepsky in this case. break return //Security/Patrol task -- Essentially secbot emulation. security name = "secure" handle_beacons = 1 task_id = "SECURE" var/tmp/new_destination // pending new destination (waiting for beacon response) var/tmp/destination // destination description tag var/tmp/next_destination // the next destination in the patrol route var/tmp/nearest_beacon // the nearest beacon's tag var/tmp/turf/nearest_beacon_loc // the nearest beacon's location var/tmp/awaiting_beacon = 0 var/tmp/patrol_delay = 0 var/tmp/mob/living/carbon/arrest_target = null var/tmp/mob/living/carbon/hug_target = null var/list/target_names = list() //Dudes we are preprogrammed to arrest. var/tmp/mode = 0 //0: Patrol, 1: Arresting somebody var/tmp/arrest_attempts = 0 var/tmp/cuffing = 0 var/tmp/last_cute_action = 0 var/weapon_access = access_carrypermit //These guys can use guns, ok! var/lethal = 0 //Do we use lethal force (if possible) ? var/panic = 0 //Martial law! Arrest all kinds!! var/no_patrol = 1 //Don't patrol. var/tmp/list/arrested_messages = list("Have a secure day!","Your move, creep.", "God made tomorrow for the crooks we don't catch today.","One riot, one ranger.") #define ARREST_DELAY 2.5 //Delay between movements when chasing a criminal, slightly faster than usual. (2.5 vs 3) #define TIME_BETWEEN_CUTE_ACTIONS 1800 //Tenths of a second between cute actions patrol name = "patrol" task_id = "PATROL" no_patrol = 0 crazy name = "patr#(003~" task_id = "ERR0xF00F" lethal = 1 panic = 1 no_patrol = 0 single_use no_patrol = 1 drop_arrest_target() src.master.remove_current_task() return drop_hug_target() src.master.remove_current_task() return seek no_patrol = 0 look_for_perp() if(src.arrest_target) return //Already chasing somebody for (var/mob/living/carbon/C in view(7,master)) //Let's find us a criminal if ((C.stat) || (C.handcuffed)) continue if (src.assess_perp(C)) src.master.remove_current_task() return assess_perp(mob/living/carbon/human/perp as mob) if(ckey(perp.name) == master.scratchpad["targetname"]) return 1 var/obj/item/card/id/perp_id = perp.equipped() if (!istype(perp_id)) perp_id = perp.wear_id if(perp_id && ckey(perp_id.registered) == master.scratchpad["targetname"]) return 1 return 0 task_act() if(..()) return look_for_perp() switch(mode) if(0) if (hug_target) if ((istype(hug_target) && isdead(hug_target)) || (istype(hug_target, /obj/critter) && hug_target.health <= 0)) hug_target = null master.set_emotion("sad") return if(get_dist(master, hug_target) <= 1) master.visible_message("[master] hugs [hug_target]!") if (hug_target.reagents) hug_target.reagents.add_reagent("hugs", 10) if (prob(1) && istype(hug_target) && hug_target.client && hug_target.client.IsByondMember()) master.speak("You might want a breath mint.") drop_hug_target() master.set_emotion("love") master.moving = 0 //master.current_movepath = "HEH" return if((!(hug_target in view(7,master)) && (!master.mover || !master.moving)) || !master.path || !master.path.len || (4 < get_dist(hug_target,master.path[master.path.len])) ) //qdel(master.mover) if (master.mover) master.mover.master = null master.mover = null master.moving = 0 master.navigate_to(hug_target,ARREST_DELAY) return return if(patrol_delay) patrol_delay-- return if(master.moving || no_patrol) return if(!master.moving) find_patrol_target() if(1) if(!arrest_target || !master.tool) src.mode = 0 return if(arrest_target) if(!arrest_target in view(7,master) && !master.moving) //qdel(master.mover) master.frustration += 2 if (master.mover) master.mover.master = null master.mover = null master.navigate_to(arrest_target,ARREST_DELAY, 0, 0) return else var/targdist = get_dist(master, arrest_target) if((targdist <= 1) || (master.tool && master.tool.is_gun)) if (!isliving(arrest_target) || isdead(arrest_target)) mode = 0 drop_arrest_target() return master.bot_attack(arrest_target, src.lethal) if(targdist <= 1 && !cuffing && (arrest_target.getStatusDuration("weakened") || arrest_target.getStatusDuration("stunned"))) cuffing = 1 src.arrest_attempts = 0 //Put in here instead of right after attack so gun robuddies don't get confused playsound(master.loc, "sound/weapons/handcuffs.ogg", 30, 1, -2) master.visible_message("[master] is trying to put handcuffs on [arrest_target]!") var/cuffloc = arrest_target.loc SPAWN_DBG(6 SECONDS) if (!master) return if (get_dist(master, arrest_target) <= 1 && arrest_target.loc == cuffloc) if (!cuffing) return if (!master || !master.on || master.idle || master.stunned) src.cuffing = 0 return if (arrest_target.handcuffed || !isturf(arrest_target.loc)) drop_arrest_target() return if (ishuman(arrest_target)) var/mob/living/carbon/human/H = arrest_target //if(H.bioHolder.HasEffect("lost_left_arm") || H.bioHolder.HasEffect("lost_right_arm")) if(!H.limbs.l_arm || !H.limbs.r_arm) drop_arrest_target() master.set_emotion("sad") return if(iscarbon(arrest_target)) arrest_target.handcuffed = new /obj/item/handcuffs/guardbot(arrest_target) arrest_target.setStatus("handcuffed", duration = null) boutput(arrest_target, "[master] gently handcuffs you! It's like the cuffs are hugging your wrists.") arrest_target:set_clothing_icon_dirty() mode = 0 src.drop_arrest_target() master.set_emotion("smug") if (arrested_messages && arrested_messages.len) var/arrest_message = pick(arrested_messages) master.speak(arrest_message) else src.cuffing = 0 return if(!master.path || !master.path.len || (4 < get_dist(arrest_target,master.path[master.path.len])) ) master.moving = 0 //master.current_movepath = "HEH" //Stop any current movement. master.navigate_to(arrest_target,ARREST_DELAY, 0,0) return return task_input(input) if(..()) return 1 switch(input) if("snooze") src.patrol_delay = 0 src.awaiting_beacon = 0 src.next_destination = null src.target = null src.secondary_targets.len = 0 if(arrest_target) src.arrest_target = null src.last_found = world.time src.arrest_attempts = 0 src.cuffing = 0 return 1 if("path_error","path_blocked") src.arrest_attempts++ if(src.arrest_attempts >= 2) src.cuffing = 0 src.target = null if(arrest_target) src.arrest_target = null src.last_found = world.time src.mode = 0 src.arrest_attempts = 0 master.set_emotion() return 1 if ("treated") return ..("hugged") return 0 receive_signal(datum/signal/signal) if(..()) return if(signal.data["command"] == "configure") if (signal.data["command2"]) signal.data["command"] = signal.data["command2"] src.configure(signal.data) return var/recv = signal.data["beacon"] var/valid = signal.data["patrol"] if(!awaiting_beacon || !recv || !valid || patrol_delay) return //boutput(world, "patrol task received") if(recv == new_destination) // if the recvd beacon location matches the set destination // then we will navigate there destination = new_destination target = signal.source.loc next_destination = signal.data["next_patrol"] awaiting_beacon = 0 patrol_delay = rand(3,5) //So a patrol group doesn't bunch up on a single tile. // if looking for nearest beacon else if(new_destination == "__nearest__") var/dist = get_dist(master,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 next_destination = signal.data["next_patrol"] target = signal.source.loc destination = recv awaiting_beacon = 0 patrol_delay = 5 return attack_response(mob/attacker as mob) if(..()) return if(!src.arrest_target) src.arrest_target = attacker src.mode = 1 src.oldtarget_name = attacker.name master.set_emotion("angry") return configure(var/list/confList) if (..()) return 1 if (confList["patrol"]) var/patrol_stat = text2num(confList["patrol"]) if (!isnull(patrol_stat)) if (patrol_stat) src.no_patrol = 0 else src.no_patrol = 1 if (confList["lethal"] && (confList["acc_code"] == netpass_heads)) var/lethal_stat = text2num(confList["lethal"]) if (!isnull(lethal_stat)) if (lethal_stat && !src.lethal) src.lethal = 1 if (src.master) master.speak("Notice: Lethal force authorized.") else if (src.lethal) src.lethal = 0 if (src.master) master.speak("Notice: Lethal force is no longer authorized.") if (confList["name"] && !src.master) var/target_name = ckey(confList["name"]) if (target_name && target_name != "") src.target_names = list(target_name) if (confList["command"]) switch(lowertext(confList["command"])) if ("add_target") if(confList["acc_code"] != netpass_heads) return 0 var/newtarget_name = ckey(confList["data"]) if(!newtarget_name || newtarget_name == "") return 0 if(!(newtarget_name in src.target_names)) src.target_names += newtarget_name if (src.master) master.speak("Notice: Criminal database updated.") return 0 if ("remove_target") if(confList["acc_code"] != netpass_heads) return 0 var/seltarget_name = ckey(confList["data"]) if(!seltarget_name || seltarget_name == "") return 0 if(seltarget_name in src.target_names) src.target_names -= seltarget_name if (src.master) if(src.target_names.len) master.speak("Notice: Criminal database updated.") else master.speak("Notice: Criminal database cleared.") return 0 if("clear_targets") if(confList["acc_code"] != netpass_heads) return 0 if(src.target_names.len) src.target_names = list() if (src.master) master.speak("Notice: Criminal database cleared.") return 0 return 0 proc look_for_perp() if(src.arrest_target) return //Already chasing somebody for (var/mob/living/carbon/C in view(7,master)) //Let's find us a criminal if ((C.stat) || (C.handcuffed)) continue if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 60)) continue var/threat = 0 if(ishuman(C)) threat = src.assess_perp(C) // else // if(isalien(C)) // threat = 9 if(threat >= 4) src.arrest_target = C src.oldtarget_name = C.name src.mode = 1 src.master.frustration = 0 master.set_emotion("angry") SPAWN_DBG(0) master.speak("Level [threat] infraction alert!") master.visible_message("[master] points at [C.name]!") else if (!last_cute_action || ((last_cute_action + TIME_BETWEEN_CUTE_ACTIONS) < world.time)) if (prob(10)) last_cute_action = world.time switch(rand(1,5)) if (1) master.visible_message("[master] waves at [C.name].") if (2) master.visible_message("[master] rotates slowly around in a circle.") if (3,4) //hugs!! master.visible_message("[master] points at [C.name]!") master.speak( pick("Level [rand(1,32)] hug deficiency alert!", "Somebody needs a hug!", "Cheer up!") ) src.hug_target = C if (5) master.visible_message("[master] appears to be having a [pick("great","swell","rad","wonderful")] day!") if (prob(50)) master.speak("Woo!") return drop_arrest_target() src.arrest_target = null src.last_found = world.time src.cuffing = 0 src.master.frustration = 0 master.set_emotion() return drop_hug_target() src.hug_target = null return find_patrol_target() if(awaiting_beacon) // awaiting beacon response awaiting_beacon-- if(awaiting_beacon <= 0) find_nearest_beacon() return if(next_destination) set_destination(next_destination) if(!master.moving && target && (target != master.loc)) master.navigate_to(target) return else find_nearest_beacon() return find_nearest_beacon() nearest_beacon = null new_destination = "__nearest__" master.post_status("!BEACON!", "findbeacon", "patrol") awaiting_beacon = 5 SPAWN_DBG(1 SECOND) if(!master || !master.on || master.stunned || master.idle) return if(master.task != src) return awaiting_beacon = 0 if(nearest_beacon && !master.moving) master.navigate_to(nearest_beacon_loc) else patrol_delay = 8 target = null return set_destination(var/new_dest) new_destination = new_dest master.post_status("!BEACON!", "findbeacon", "patrol") awaiting_beacon = 5 assess_perp(mob/living/carbon/human/perp as mob) . = 0 if(src.panic) return 9 if(ckey(perp.name) in target_names) return 7 var/obj/item/card/id/perp_id = perp.equipped() if (!istype(perp_id)) perp_id = perp.wear_id if(perp_id) if(ckey(perp_id.registered) in target_names) return 7 if(weapon_access in perp_id.access) return 0 if (istype(perp.l_hand)) . += perp.l_hand.contraband if (istype(perp.r_hand)) . += perp.r_hand.contraband if (istype(perp:belt)) . += perp:belt.contraband * 0.5 if (istype(perp:wear_suit)) . += perp:wear_suit.contraband if(perp.mutantrace && perp.mutantrace.jerk) // if(istype(perp.mutantrace, /datum/mutantrace/zombie)) // return 5 //Zombies are bad news! // threatcount += 2 return 5 halloween //Go trick or treating! name = "candy" task_id = "CANDY" no_patrol = 0 look_for_perp() if(src.hug_target) return for (var/mob/living/carbon/C in view(7,master)) //Let's get some candy! if ((C.stat) || (C.handcuffed)) continue if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 60)) continue var/threat = 0 if(ishuman(C)) threat = src.assess_perp(C) // else // if(isalien(C)) // threat = 9 if(threat < 4 && (!last_cute_action || ((last_cute_action + TIME_BETWEEN_CUTE_ACTIONS) < world.time))) src.oldtarget_name = C.name if (prob(10)) src.hug_target = C return task_input(var/input) if (input == "treated") if (..("filler")) return 1 src.master.speak( pick("Yayyy! Thank you!", "Whoohoo, candy!", "Thank you! I can't actually eat candy, but I enjoy the aesthetic aspect of it.") ) src.master.set_emotion("happy") else if (..()) return 1 task_act() if (master && mode == 0 && hug_target) if (isdead(hug_target)) hug_target = null master.set_emotion("sad") return if(get_dist(master, hug_target) <= 1) if (prob(2)) master.speak("Merry Spacemas!") SPAWN_DBG(1 SECOND) if (master) master.speak("Warning: Real-time clock battery low or missing.") else master.speak("Trick or treat!") if (prob(50) && hug_target.client && hug_target.client.IsByondMember()) master.speak("Oh wait, you're the one who just hands out [pick("religious tracts","pennies", "toothbrushes")].") master.set_emotion("love") hug_target = null master.moving = 0 //master.current_movepath = "HEH" return if((!(hug_target in view(7,master)) && (!master.mover || !master.moving)) || !master.path || !master.path.len || (4 < get_dist(hug_target,master.path[master.path.len])) ) //qdel(master.mover) if (master.mover) master.mover.master = null master.mover = null master.moving = 0 master.navigate_to(hug_target,ARREST_DELAY) return else return ..() purge //Arrest anyone who isn't a DWAINE superuser. name = "purge" task_id = "PURGE" no_patrol = 0 var/accepted_access = access_dwaine_superuser assess_perp(mob/living/carbon/human/perp as mob) var/obj/item/card/id/the_id = perp.wear_id if (!the_id) the_id = perp.equipped() if(!istype(the_id) || (the_id && !(accepted_access in the_id.access)) ) return 9 else return ..() /* klaus //todo name = "klaus" task_id = "KLAUS" look_for_perp() . = ..() if (src.arrest_target) return */ area_guard name = "areaguard" task_id = "AREAG" no_patrol = 1 var/area/current_area = null look_for_perp() current_area = get_area(src.master) return ..() assess_perp(mob/living/carbon/human/perp as mob) var/area/perp_area = get_area(perp) if (perp_area == current_area) return ..() return 0 //Bodyguard Task -- Guard some dude's personal space bodyguard name = "bodyguard" task_id = "GUARD" var/tmp/mob/living/carbon/protected = null var/tmp/mob/living/carbon/arrest_target = null var/tmp/arrest_attempts = 0 var/tmp/follow_attempts = 0 var/tmp/cuffing = 0 var/tmp/mode = 0 //0: Following protectee, 1: Arresting threat var/lethal = 0 //Do we use lethal force (if possible) ? var/desired_emotion = "look" var/tmp/attacked_by_buddy = 0 //Has our buddy hit us? Buddy abuse is a serious problem. var/tmp/buddy_is_dork = 0 //Our buddy kinda sucks :( var/tmp/list/arrested_messages = list("Threat neutralized.","Station secure.","Problem resolved.") var/protected_name = null //Who are we seeking? #define SEARCH_EMOTION "look" #define GUARDING_EMOTION "cool" #define GUARDING_DORK_EMOTION "coolugh" #define CHASING_EMOTION "angry" task_act() if(..()) return 1 if(master.emotion != desired_emotion) master.set_emotion(desired_emotion) if(arrest_target) //Priority one: Arrest a jerk who hurt our buddy. desired_emotion = CHASING_EMOTION master.set_emotion(CHASING_EMOTION) handle_arrest_function() return if(!protected) //Priority two: Assess status of buddy. src.desired_emotion = SEARCH_EMOTION src.look_for_protected() return else src.desired_emotion = buddy_is_dork ? GUARDING_DORK_EMOTION : GUARDING_EMOTION if(src.check_buddy()) //Should ONLY return true when we pick up a new arrest target. master.set_emotion(CHASING_EMOTION) handle_arrest_function() //So we don't have to wait for the next process. LIVES ARE ON THE LINE HERE! return if(!protected in view(7,master) && !master.moving) //qdel(master.mover) master.frustration++ if (master.mover) master.mover.master = null master.mover = null master.navigate_to(protected,3,1,1) return else if(isdead(protected)) protected = null if (buddy_is_dork && prob(50)) master.speak(pick("Rest in peace. I guess", "At least that's over.", "I didn't have the courage to tell you this, but you smelled like rotten ham.")) else master.speak(pick("Rest in peace.","Guard protocol...inactive.","I'm sorry it had to end this way.","It was an honor to serve alongside you.")) return if(!master.path || !master.path.len || (3 < get_dist(protected,master.path[master.path.len])) ) master.moving = 0 //qdel(master.mover) if (master.mover) master.mover.master = null master.mover = null master.navigate_to(protected,3,1,1) return task_input(input) if(..()) return switch(input) if("snooze") // src.arrest_target = null src.protected = null src.arrest_attempts = 0 src.follow_attempts = 0 src.cuffing = 0 if("path_error","path_blocked") if (src.protected) if(!(src.protected in view(7,master))) src.follow_attempts++ if(src.follow_attempts >= 2) src.follow_attempts = 0 src.protected = null return return attack_response(mob/attacker as mob) if(..()) return if(attacker == src.protected && !attacked_by_buddy) attacked_by_buddy = 1 master.speak(pick("Check your fire!","Watch it!","Friendly fire will not be tolerated!")) return if(!src.arrest_target) src.arrest_target = attacker if(attacker == src.protected) src.protected = null return configure(var/list/confList) if (..()) return 1 if (confList["name"]) src.protected_name = ckey(confList["name"]) return 0 proc look_for_protected() //Search for a mob in view with the name we are programmed to guard. if(src.protected) return //We have someone to protect! for (var/mob/living/C in view(7,master)) if (isdead(C)) //We were too late! continue var/check_name = C.name if(ishuman(C) && C:wear_id) check_name = C:wear_id:registered if (ckey(check_name) == ckey(src.protected_name)) src.protected = C src.desired_emotion = GUARDING_EMOTION C.unlock_medal("Ol' buddy ol' pal", 1) src.buddy_is_dork = (C.client && C.client.IsByondMember()) SPAWN_DBG(0) //if (buddy_is_dork && prob(50)) //master.speak(pick("I am here to protect...Oh, it's you.", "I have been instructed to guard you. Welp.", "You are now under guard. I guess.")) master.speak(pick("I am here to protect you.","I have been instructed to guard you.","You are now under guard.","Come with me if you want to live!")) master.visible_message("[master] points at [C.name]!") break return drop_arrest_target() src.arrest_target = null src.cuffing = 0 return check_buddy() //Out of sight, out of mind. if(!(protected in view(7,master))) return 0 //Has our buddy been attacked?? if(protected.lastattacker && (protected.lastattackertime + 40) >= world.time) if(protected.lastattacker != protected) master.moving = 0 //qdel(master.mover) if (master.mover) master.mover.master = null master.mover = null src.arrest_target = protected.lastattacker src.follow_attempts = 0 src.arrest_attempts = 0 return 1 return 0 handle_arrest_function() var/datum/computer/file/guardbot_task/security/single_use/beatdown = new beatdown.arrest_target = src.arrest_target beatdown.mode = 1 beatdown.arrested_messages = src.arrested_messages src.arrest_target = null src.master.add_task(beatdown, 1, 0) return bodyguard/heckle name = "heckle" task_id = "HECKLE" var/global/list/buddy_heckle_phrases = list( "Neeerrd!", "Dork!", "Hey! Hey! You smell...bad! Really bad!", "Hey! You have an odor! A grody one! GRODY NERD ALERT!", "Did you get lost on the way to your anime club?", "Are you as bad at your job as you are at dressing yourself?", "You should probably eat something other than fatty beef jerky for every meal. Your family is getting worried about you.","I'm sorry they didn't let you wear your fedora to work today.", "CAUTION: Poor impulse control!","That's a, um, really unfortunate choice of uniform. Maybe you should try something with vertical stripes to de-emphasize the...you know.", "You, uh, should probably wash your hair. I think if you took a swim, all the seals would die.") var/tmp/initial_seek_complete = 0 task_act() if (..()) return if (src.protected && prob(10)) master.speak( pick(buddy_heckle_phrases) ) master.visible_message("[master] points at [src.protected.name]!") look_for_protected() //Search for a mob in view with the name we are programmed to guard. if(src.protected) return //We have someone to protect! for (var/mob/living/C in view(7,master)) if (isdead(C)) //We were too late! continue var/check_name = C.name if(ishuman(C) && C:wear_id) check_name = C:wear_id:registered if (ckey(check_name) == ckey(src.protected_name)) src.protected = C buddy_is_dork = 1 //src.desired_emotion = GUARDING_EMOTION SPAWN_DBG(0) master.speak("Level 9F [pick("dork","nerd","weenie","doofus","loser","dingus","dorkus")] detected!") master.visible_message("[master] points at [C.name]!") return if (!initial_seek_complete) initial_seek_complete = 1 master.scratchpad["targetname"] = ckey(src.protected_name) src.master.add_task(/datum/computer/file/guardbot_task/security/seek, 1, 0) return check_buddy() return 0 #undef SEARCH_EMOTION #undef GUARDING_EMOTION #undef GUARDING_DORK_EMOTION #undef CHASING_EMOTION #define STATE_FINDING_BEACON 0//Byond, enums, lack thereof, etc #define STATE_PATHING_TO_BEACON 1 #define STATE_AT_BEACON 2 #define STATE_POST_TOUR_IDLE 3 //Neat things we've seen on this trip #define NT_WIZARD 1 #define NT_CAPTAIN 2 #define NT_JONES 4 #define NT_BEE 8 #define NT_SECBOT 16 #define NT_BEEPSKY 32 #define NT_OTHERBUDDY 64 #define NT_SPACE 128 #define NT_DORK 256 #define NT_CLOAKER 1024 #define NT_GEORGE 2048 #define NT_DRONE 4096 #define NT_AUTOMATON 8192 #define NT_CHEGET 16384 #define NT_GAFFE 32768 //Note: this is the last one the bitfield can fit. Thanks, byond!! tourguide name = "tourguide" task_id = "TOUR" handle_beacons = 1 var/wait_for_guests = 0 //Wait for people to be around before giving tour dialog? var/tmp/state = STATE_FINDING_BEACON var/tmp/desired_emotion = "happy" var/tmp/list/visited_beacons = list() var/tmp/next_beacon_id = "tour0" var/tmp/current_beacon_id = null var/tmp/turf/current_beacon_loc = null var/tmp/awaiting_beacon = 0 var/tmp/current_tour_text = null var/tmp/tour_delay = 0 var/tmp/neat_things = 0 //Bitfield to mark neat things seen on a tour. var/tmp/recent_nav_attempts = 0 New() ..() tourguides += src disposing() ..() tourguides -= src #define TOUR_FACE "happy" #define ANGRY_FACE "angry" //Method of operation: //Locate starting beacon or last beacon //Check name of beacon against list of visited beacons. //Interrogate beacon for information string, if any //Say information string once our tourgroup (or some random doofus, it doesn't really matter) has arrived. //Locate next beacon OR finish if none defined. task_act() if (..()) return if(master.emotion != desired_emotion) master.set_emotion(desired_emotion) switch (state) if (STATE_FINDING_BEACON) if (awaiting_beacon) awaiting_beacon-- return if (!next_beacon_id) next_beacon_id = initial(next_beacon_id) awaiting_beacon = 10 master.post_status("!BEACON!", "findbeacon", "tour") return if (STATE_PATHING_TO_BEACON) if (!isturf(current_beacon_loc)) state = STATE_FINDING_BEACON return if (prob(20)) src.look_for_neat_thing() if (!master.moving) if (awaiting_beacon > 0) awaiting_beacon-- return if (current_beacon_loc != master.loc) master.navigate_to(current_beacon_loc) else state = STATE_AT_BEACON return if (STATE_AT_BEACON) if (wait_for_guests && !locate(/mob/living/carbon) in view(src.master)) //Maybe we shouldn't speak to no-one?? return //I realize this doesn't check if they're dead. Buddies can't always tell, ok!! Maybe if people had helpful power lights too if (ckey(current_tour_text)) if (findtext(current_tour_text, "|p")) //There are pauses present! So, um, pause. var/list/tour_text_with_pauses = splittext(current_tour_text, "|p") SPAWN_DBG (0) sleep(10) for (var/tour_line in tour_text_with_pauses) if (!ckey(tour_line) || !master) break master.speak( copytext( html_encode(tour_line), 1, MAX_MESSAGE_LEN ) ) sleep(10) else master.speak( copytext(html_encode(current_tour_text), 1, MAX_MESSAGE_LEN)) if (next_beacon_id) state = STATE_FINDING_BEACON awaiting_beacon = 3 //This will just serve as a delay so the buddy isn't zipping around at light speed between stops. else state = STATE_POST_TOUR_IDLE tour_delay = 30 master.speak("And that concludes the tour session. Please visit the gift shop on your way out.") return if (STATE_POST_TOUR_IDLE) if (tour_delay-- > 0) return next_beacon_id = initial(next_beacon_id) state = STATE_FINDING_BEACON neat_things = 0 return attack_response(mob/attacker as mob) if(..()) return src.master.set_emotion(ANGRY_FACE) src.master.speak(pick("Rude!","That is not acceptable behavior!","This is a tour, not a fight factory!","You have been ejected from the tourgroup for: Roughhousing. Please be aware that tour sessions are non-refundable.")) var/datum/computer/file/guardbot_task/security/single_use/beatdown = new beatdown.arrest_target = attacker beatdown.mode = 1 src.master.add_task(beatdown, 1, 0) return task_input(input) if(..()) return switch(input) if("snooze") src.awaiting_beacon = 0 src.next_beacon_id = null if("path_error","path_blocked") if (recent_nav_attempts++ > 10) recent_nav_attempts = 0 awaiting_beacon = 10 return receive_signal(datum/signal/signal) if(..()) return var/recv = signal.data["beacon"] var/valid = signal.data["tour"] if(!awaiting_beacon || !recv || !valid || state != STATE_FINDING_BEACON) return if(recv == next_beacon_id) // if the recvd beacon location matches the set destination // then we will navigate there current_beacon_id = next_beacon_id current_beacon_loc = signal.source.loc next_beacon_id = signal.data["next_tour"] awaiting_beacon = 0 src.state = STATE_PATHING_TO_BEACON if (ckey(signal.data["desc"])) current_tour_text = signal.data["desc"] else current_tour_text = null return proc/look_for_neat_thing() var/area/spaceArea = get_area(src.master) if (!(src.neat_things & NT_SPACE) && spaceArea && spaceArea.name == "Space" && !istype(get_turf(src.master), /turf/simulated/shuttle)) src.neat_things |= NT_SPACE src.master.speak(pick("While you find yourself surrounded by space, please try to avoid the temptation to inhale any of it. That doesn't work.",\ "Space: the final frontier. Oh, except for time travel and any other dimensions. And frontiers on other planets, including other planets in those other dimensions and times. Maybe I should stick with \"space: a frontier.\"",\ "Those worlds in space are as countless as all the grains of sand on all the beaches of the earth. Each of those worlds is as real as ours and every one of them is a succession of incidents, events, occurrences which influence its future. Countless worlds, numberless moments, an immensity of space and time. This Sagan quote and others like it are available on mugs at the gift shop.",\ "Please keep hold of the station at all times while in an exposed area. The same principle does not apply to your breath without a mask. Your lungs will pop like bubblegum. Just a heads up.")) return for (var/atom/movable/AM in view(7, master)) if (ishuman(AM)) var/mob/living/carbon/human/H = AM if (!(src.neat_things & NT_GAFFE) && !isdead(H) && !H.sight_check(1)) src.neat_things |= NT_GAFFE src.master.speak("Ah! As you can see here--") SPAWN_DBG (10) . = desired_emotion //We're going to make him sad until the end of this spawn, ok. desired_emotion = "sad" master.set_emotion(desired_emotion) src.master.speak("OH! Sorry! Sorry, [H.name]! I didn't mean it that way!") sleep(5) var/mob/living/carbon/human/deaf_person = null for (var/mob/living/carbon/human/maybe_deaf in view(7, master)) if (!isdead(maybe_deaf) && !maybe_deaf.hearing_check(1)) deaf_person = maybe_deaf break if (deaf_person) src.master.speak("I'll just narrate things so you can all hear it--") sleep(10) if (deaf_person == H) src.master.speak("SORRY [H] I DIDN'T MEAN THAT EITHER AAAA") else src.master.speak("Oh! Sorry! Sorry, [deaf_person.name]!! I didn't mean that that way eith-wait um.") sleep(10) src.master.visible_message("[src.master] begins signing frantically! Despite, um, robot hands not really being equipped for sign language.") sleep(100) desired_emotion = . master.set_emotion(desired_emotion) if (!(src.neat_things & NT_CLOAKER) && H.invisibility > 0) src.master.speak("As a courtesy to other tourgroup members, you are requested, though not required, to deactivate any cloaking devices, stealth suits, light redirection field packs, and/or unholy blood magic.") src.neat_things |= NT_CLOAKER return if (!(src.neat_things & NT_WIZARD) && istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) ) src.master.speak( pick("Look, group, a wizard! Please be careful, space wizards can be dangerous.","Ooh, a real space wizard! Look but don't touch, folks!","Space wizards are highly secretive, especially regarding the nature of their abilities. Current speculation is that their \"magic\" is really the application of advanced technologies or artifacts.") ) src.neat_things |= NT_WIZARD return if (!(src.neat_things & NT_CAPTAIN) && istype(H.head, /obj/item/clothing/head/caphat)) src.neat_things |= NT_CAPTAIN src.master.speak("Good day, Captain! You're looking [pick("spiffy","good","swell","proper","professional","prim and proper", "spiffy", "ultra-spiffy")] today.") return if (!(src.neat_things & NT_DORK) && (H.client && H.client.IsByondMember() && prob(5)))// || (H.ckey in Dorks))) //If this is too mean to clarks, remove that part I guess src.neat_things |= NT_DORK var/insult = pick("dork","nerd","weenie","doofus","loser","dingus","dorkus") var/insultphrase = "And if you look to--[insult] alert! [pick("Huge","Total","Mega","Complete")] [insult] detected! Alert! Alert! [capitalize(insult)]! " insultphrase += copytext(insult,1,2) var/i = rand(3,7) while (i-- > 0) insultphrase += copytext(insult,2,3) insultphrase += "[copytext(insult,3)]!!" src.master.speak(insultphrase) var/P = new /obj/decal/point(get_turf(H)) SPAWN_DBG (40) qdel(P) src.master.visible_message("[src.master] points to [H]") return else if (!(src.neat_things & NT_JONES) && istype(AM, /obj/critter/cat) && AM.name == "Jones") src.neat_things |= NT_JONES var/obj/critter/cat/jones = AM src.master.speak("And over here is the ship's cat, J[jones.alive ? "ones! No spacecraft is complete without a cat!" : "-oh mercy, MOVING ON, MOVING ON"]") return else if (istype(AM, /obj/critter/domestic_bee) && AM:alive && !(src.neat_things & NT_BEE)) src.neat_things |= NT_BEE if (istype(AM, /obj/critter/domestic_bee/trauma)) src.master.speak("Look, team, a domestic space bee! This happy creature--oh dear. Hold on, please.") var/datum/computer/file/guardbot_task/security/single_use/emergency_hug = new emergency_hug.hug_target = AM src.master.add_task(emergency_hug, 1, 0) return src.master.speak("Look, team, a domestic space bee! This happy creature is the result of decades of genetic research!") switch (rand(1,5)) if (1) src.master.speak("Fun fact: Domestic space bee DNA is [rand(1,17)]% [pick("dog", "human", "cat", "honeybee")]") if (2) src.master.speak("Fun fact: Domestic space bees are responsible for over [rand(45,67)]% of all honey production outside of Earth!") if (3) src.master.speak("Fun fact: Domestic space bees are very well adapted to accidental space exposure, and can survive in that environment for upwards of [pick("ten hours", "two days", "42 minutes", "three-score ke", "one-and-one-half nychthemeron")].") if (4) src.master.speak("Fun fact: Domestic space bee DNA is protected by U.S. patent number [rand(111,999)],[rand(111,999)],[rand(555,789)].") if (5) src.master.speak("Fun fact: The average weight of a domestic space bee is about [pick("10 pounds","4.54 kilograms", "25600 drams", "1.42857143 cloves", "145.833333 troy ounces")].") return else if (istype(AM, /obj/critter/dog/george) && !(src.neat_things & NT_GEORGE)) src.neat_things |= NT_GEORGE src.master.speak("Why, if it isn't beloved station canine, George! Who's a good doggy? You are! Yes, you!") else if (istype(AM, /obj/critter/gunbot/drone) && !(src.neat_things & NT_DRONE)) src.neat_things |= NT_DRONE src.master.speak( pick("Oh dear, a syndicate autonomous drone! These nasty things have been shooting up innocent space-folk for a couple of years now.", "Watch out, folks! That's a syndicate drone, they're nasty buggers!", "Ah, a syhndicate drone! They're made in a secret factory, one located at--oh dear, we better get hurrying before it becomes upset.", "Watch out, that's a syndicate drone! They're made in a secret factory. There was a guy who knew where it was on my first tour, but he took the secret...to his grave!! Literally. It's with him. In his crypt.") ) else if (!(src.neat_things & NT_AUTOMATON) && istype(AM, /obj/critter/automaton)) src.neat_things |= NT_AUTOMATON src.master.speak("This here is some kind of automaton. This, uh, porcelain-faced, click-clackity metal man.") . = "Why [istype(get_area(AM), /area/solarium) ? "am I" : "is this"] here?" SPAWN_DBG (20) src.master.speak(.) else if (istype(AM, /obj/machinery/bot)) if (istype(AM, /obj/machinery/bot/secbot)) if (AM.name == "Officer Beepsky" && !(src.neat_things & NT_BEEPSKY)) src.neat_things |= NT_BEEPSKY src.master.speak("And here comes Officer Beepsky, the proud guard of this station. Proud.") src.master.speak("Not at all terrible. No Sir. Not at all.") if (prob(10)) SPAWN_DBG(1.5 SECONDS) src.master.speak("Well okay, maybe a little.") return else if (!(src.neat_things & NT_SECBOT)) src.neat_things |= NT_SECBOT src.master.speak("And if you look over now, you'll see a securitron, an ace security robot originally developed \"in the field\" from spare parts in a security office!") return else if (istype(AM, /obj/machinery/bot/guardbot) && AM != src.master) var/obj/machinery/bot/guardbot/otherBuddy = AM if (!(src.neat_things & NT_CAPTAIN) && istype(otherBuddy.hat, /obj/item/clothing/head/caphat)) src.neat_things |= NT_CAPTAIN src.master.speak("Good day, Captain! You look a little different today, did you get a haircut?") var/otherBuddyID = otherBuddy.net_id //Notify other buddy SPAWN_DBG(1 SECOND) if (src.master) src.master.post_status("[otherBuddyID]", "command", "captain_greet") return else if (!(src.neat_things & NT_WIZARD) && istype(otherBuddy.hat, /obj/item/clothing/head/wizard)) src.neat_things |= NT_WIZARD src.master.speak("Look, a space wizard! Please stand back, I am going to attempt to communicate with it.") src.master.speak("Hello, Mage, Seer, Wizard, Wizzard, or other magic-user. We mean you no harm! We ask you humbly for your WIZARDLY WIZ-DOM.") if (prob(25)) src.master.speak("We hope that we aren't disrupting any sort of wiz-biz or wizness deal.") //As before, notify the other buddy var/otherBuddyID = otherBuddy.net_id SPAWN_DBG(1 SECOND) if (src.master) src.master.post_status("[otherBuddyID]", "command", "wizard_greet") else if (!(src.neat_things & NT_OTHERBUDDY)) src.neat_things |= NT_OTHERBUDDY if (istype(otherBuddy, /obj/machinery/bot/guardbot/future)) src.master.speak("The PR line of personal robot has been--wait! Hold the phone! Is that a PR-7? Oh man, I feel old!") return if (istype(otherBuddy, /obj/machinery/bot/guardbot/old/tourguide/lunar)) src.master.visible_message("[master] waves at [otherBuddy].") return if (istype(otherBuddy, /obj/machinery/bot/guardbot/soviet)) src.master.speak("That's...that's one of those eastern bloc robuddies. Um...hello?") src.master.visible_message("[master] gives [otherBuddy] a slow, confused wave.") return src.master.speak("The PR line of personal robot has been Thinktronic Data Systems' flagship robot line for over 15 years. It's easy to see their appeal!") switch (rand(1,4)) if (1) src.master.speak("Buddy Fact: In 2051, Robuddies were conclusively determined to have a[prob(40) ? "t least three-fourths of a" : ""] soul.") if (2) src.master.speak("Buddy Fact: Robuddies cannot jump. We just can't, sorry!") if (3) src.master.speak("Buddy Fact: Our hug protocols have been extensively revised through thousands of rounds of testing and simulation to deliver Peak Cuddle.") if (4) src.master.speak("Buddy Fact: Robuddies are programmed to be avid fans of hats and similar headgear.") else if ((istype(AM, /obj/item/luggable_computer/cheget) || istype(AM, /obj/machinery/computer3/luggable/cheget)) && !(src.neat_things & NT_CHEGET)) src.neat_things |= NT_CHEGET src.master.speak( pick("And over there is--NOTHING. Not a thing. Let's continue on with the tour.", "Please ignore the strange briefcase, is what I would say, were there a strange briefcase. But there is not, and even if there was you should ignore it.","This is just a reminder that station crew are not to handle Soviet materials, per a whole bunch of treaties and negotiations.") ) AM.visible_message("[AM] bloops sadly.") playsound(AM.loc, prob(50) ? 'sound/machines/cheget_sadbloop.ogg' : 'sound/machines/cheget_somberbloop.ogg', 50, 1) return //Be kind, undefine...d #undef STATE_FINDING_BEACON #undef STATE_PATHING_TO_BEACON #undef STATE_AT_BEACON #undef STATE_POST_TOUR_IDLE #undef TOUR_FACE #undef ANGRY_FACE #undef NT_WIZARD #undef NT_CAPTAIN #undef NT_JONES #undef NT_BEE #undef NT_SECBOT #undef NT_BEEPSKY #undef NT_OTHERBUDDY #undef NT_SPACE #undef NT_DORK #undef NT_CLOAKER #undef NT_GEORGE #undef NT_DRONE #undef NT_AUTOMATON #undef NT_CHEGET #undef NT_GAFFE bedsheet_handler name = "confusion" task_id = "HUH" var/announced = 0 var/escape_counter = 4 task_act() if (..()) return if (master.bedsheet != 1) src.master.remove_current_task() return if (!announced) announced = 1 master.speak(pick("Hey, who turned out the lights?","Error: Visual sensor impaired!","Whoa hey, what's the big deal?","Where did everyone go?")) if (escape_counter-- > 0) flick("robuddy-ghostfumble", master) master.visible_message("[master] fumbles around in the sheet!") else master.visible_message("[master] cuts a hole in the sheet!") master.speak(pick("Problem solved.","Oh, alright","There we go!")) master.bedsheet = 2 master.overlays.len = 0 master.hat_shown = 0 master.update_icon() src.master.remove_current_task() return threat_scan name = "threatscan" task_id = "SCAN" var/weapon_access = access_carrypermit task_act() if (..()) return var/mob/living/newThreat = look_for_threat() if (istype(newThreat)) master.scratchpad["threat"] = newThreat master.scratchpad["threat_time"] = "[time2text(world.timeofday, "hh:mm:ss")]" src.master.remove_current_task() return return proc look_for_threat() for (var/mob/living/carbon/C in view(7,master)) //Let's find us a criminal if ((C.stat) || (C.handcuffed)) continue var/threat = 0 if(ishuman(C)) threat = src.assess_threat_potential(C) // else // if(isalien(C)) // threat = 9 if(threat >= 4) master.scratchpad["threat_level"] = threat return C return null assess_threat_potential(mob/living/carbon/human/potentialThreat as mob) var/threatcount = 0 var/obj/item/card/id/worn_id = potentialThreat.equipped() if (!istype(worn_id)) worn_id = potentialThreat.wear_id if(worn_id) if(weapon_access in worn_id.access) return 0 if(istype(potentialThreat.l_hand, /obj/item/gun) || istype(potentialThreat.l_hand, /obj/item/baton) || istype(potentialThreat.l_hand, /obj/item/sword)) threatcount += 4 if(istype(potentialThreat.r_hand, /obj/item/gun) || istype(potentialThreat.r_hand, /obj/item/baton) || istype(potentialThreat.r_hand, /obj/item/sword)) threatcount += 4 if (ishuman(potentialThreat)) if(istype(potentialThreat:belt, /obj/item/gun) || istype(potentialThreat:belt, /obj/item/baton) || istype(potentialThreat:belt, /obj/item/sword)) threatcount += 2 if(istype(potentialThreat:wear_suit, /obj/item/clothing/suit/wizrobe)) threatcount += 4 if(istype(potentialThreat.mutantrace, /datum/mutantrace/abomination)) return 5 return threatcount /* * Guardbot Parts */ /obj/item/guardbot_core name = "Guardbuddy mainboard" desc = "The primary circuitry of a PR-6S Guardbuddy." icon = 'icons/obj/aibots.dmi' icon_state = "robuddy_core-6" mats = 6 w_class = 2.0 var/created_default_task = null //Default task path of result var/datum/computer/file/guardbot_task/created_model_task = null var/created_name = "Guardbuddy" //Name of resulting guardbot var/buddy_model = 6 //What type of guardbot does this belong to (Default is PR-6, but Murray and Marty are PR-4s) attackby(obj/item/W as obj, mob/user as mob) if (istype(W, /obj/item/pen)) if (created_name != initial(created_name)) boutput(user, "This robot has already been named!") return var/t = input(user, "Enter new robot name", src.name, src.created_name) as text t = copytext(html_encode(t), 1, MAX_MESSAGE_LEN) if (!t) return if (!in_range(src, usr) && src.loc != usr) return src.created_name = t else ..() /obj/item/guardbot_frame name = "Guardbuddy frame" desc = "The external casing of a PR-6S Guardbuddy." icon = 'icons/obj/aibots.dmi' icon_state = "robuddy_frame-6-1" mats = 5 var/stage = 1 var/created_name = "Guardbuddy" //Still the name of resulting guardbot var/created_default_task = null //Default task path of result var/datum/computer/file/guardbot_task/created_model_task = null //Initial model task of result. var/obj/created_module = null //Tool module of result. var/obj/item/cell/created_cell = null //Energy cell of result. var/buddy_model = 6 //What type of guardbot does this belong to (Default is PR-6, but Murray and Marty are PR-4s) var/spawned_bot_type = /obj/machinery/bot/guardbot New() ..() SPAWN_DBG(6 DECI SECONDS) src.icon_state = "robuddy_frame-[buddy_model]-[stage]" if(src.stage >= 2) src.created_cell = new src.created_cell.charge = 0.9 * src.created_cell.maxcharge return //Frame -> Add cell -> Add tool -> Add core -> Add arm -> Done attackby(obj/item/W as obj, mob/user as mob) if ((istype(W, /obj/item/guardbot_core))) if(W:buddy_model != src.buddy_model) boutput(user, "That core board is for a different model of robot!") return if(!created_cell || stage != 2) boutput(user, "You need to add a power cell first!") return if(!created_module) boutput(user, "You need to add a tool module first!") return src.stage = 3 src.icon_state = "robuddy_frame-[buddy_model]-3" if(W:created_name) src.created_name = W:created_name if(W:created_default_task) src.created_default_task = W:created_default_task if(W:created_model_task) src.created_model_task = W:created_model_task boutput(user, "You add the core board to [src]!") qdel(W) else if((istype(W, /obj/item/cell)) && stage == 1 && !created_cell) user.drop_item() W.set_loc(src) src.created_cell = W src.stage = 2 src.icon_state = "robuddy_frame-[buddy_model]-2" boutput(user, "You add the power cell to [src]!") else if((istype(W, /obj/item/device/guardbot_tool)) && stage == 2 && !created_module) user.drop_item() W.set_loc(src) src.created_module = W boutput(user, "You add the [W.name] to [src]!") else if (istype(W, /obj/item/parts/robot_parts/arm/) && src.stage == 3) src.stage++ boutput(user, "You add the robot arm to [src]!") qdel(W) var/obj/machinery/bot/guardbot/newbot = new src.spawned_bot_type (get_turf(src)) if(newbot.cell) qdel(newbot.cell) newbot.cell = src.created_cell newbot.setup_default_tool_path = null newbot.cell.set_loc(newbot) if(src.created_default_task) newbot.setup_default_startup_task = src.created_default_task if(src.created_module) newbot.tool = src.created_module newbot.tool.set_loc(newbot) newbot.tool.master = newbot if(src.created_model_task) newbot.model_task = src.created_model_task newbot.model_task.master = newbot newbot.name = src.created_name qdel(src) return else ..() return //The Docking Station. Recharge here! /obj/machinery/guardbot_dock name = "docking station" desc = "A recharging and command station for PR-6S Guardbuddies." icon = 'icons/obj/aibots.dmi' icon_state = "robuddycharger0" mats = 8 anchored = 1 var/panel_open = 0 var/autoeject = 0 //1: Eject fully charged robots automatically. 2: Eject robot when living carbon mob is in view. var/frequency = 1219 var/net_id = null //What is our network id??? var/net_number = 0 var/host_id = null //Who is linked to us? var/timeout = 45 var/timeout_alert = 0 var/obj/machinery/bot/guardbot/current = null var/datum/radio_frequency/radio_connection var/obj/machinery/power/data_terminal/link = null //A reset button is useful for when the system gets all confused. var/last_reset = 0 //Last world.time we were manually reset. New() ..() SPAWN_DBG(8 DECI SECONDS) if(radio_controller) radio_connection = radio_controller.add_object(src, "[frequency]") if(!src.net_id) src.net_id = generate_net_id(src) if(!src.link) var/turf/T = get_turf(src) var/obj/machinery/power/data_terminal/test_link = locate() in T if(test_link && !test_link.is_valid_master(test_link.master)) src.link = test_link src.link.master = src return attack_hand(mob/user as mob) if(..() || status & NOPOWER) return user.machine = src var/dat = "PR-6S Docking Station" var/readout_color = "#000000" var/readout = "ERROR" if(src.host_id) readout_color = "#33FF00" readout = "OK CONNECTION" else readout_color = "#F80000" readout = "NO CONNECTION" dat += "Host Connection: " dat += "
[readout]

" dat += "Reset Connection
" if (src.panel_open) dat += "
Configuration Switches:
" for (var/i = 8, i >= 1, i >>= 1) var/styleColor = (net_number & i) ? "#60B54A" : "#CD1818" dat += "" dat += "
##
" user.Browse(dat,"window=guarddock;size=245x282") onclose(user,"guarddock") return Topic(href, href_list) if(..()) return usr.machine = src if (href_list["reset"]) if(last_reset && (last_reset + GUARDBOT_DOCK_RESET_DELAY >= world.time)) return if(!host_id) return src.last_reset = world.time var/rem_host = src.host_id src.host_id = null src.post_wire_status(rem_host, "command","term_disconnect") SPAWN_DBG(5 DECI SECONDS) src.post_wire_status(rem_host, "command","term_connect","device","PNET_PR6_CHARG") src.updateUsrDialog() return src.add_fingerprint(usr) return receive_signal(datum/signal/signal) if(status & NOPOWER) return if(!signal || signal.encryption || !signal.data["sender"]) return var/target = signal.data["sender"] if(signal.transmission_method == TRANSMISSION_WIRE) if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && target) SPAWN_DBG(5 DECI SECONDS) //Send a reply for those curious jerks src.post_wire_status(target, "command", "ping_reply", "device", "PNET_PR6_CHARG", "netid", src.net_id, "net", src.net_number) return if(signal.data["address_1"] != src.net_id || !target) return var/sigcommand = lowertext(signal.data["command"]) if(!sigcommand || !signal.data["sender"]) return switch(sigcommand) if("term_connect") //Terminal interface stuff. if(target == src.host_id) src.host_id = null src.post_wire_status(target, "command","term_disconnect") return src.timeout = initial(src.timeout) src.timeout_alert = 0 src.host_id = target if(signal.data["data"] != "noreply") src.post_wire_status(target, "command","term_connect","data","noreply","device","PNET_PR6_CHARG") SPAWN_DBG(2 DECI SECONDS) //Sign up with the driver (if a mainframe contacted us) src.post_wire_status(target,"command","term_message","data","command=register&status=[current ? current.net_id : "nobot"]") src.updateUsrDialog() return if("term_message","term_file") if(target != src.host_id) //Huh, who is this? return var/list/data = params2list(signal.data["data"]) if(!data) return switch(data["command"]) if("status") //Status of connected bot. var/status = "command=reply" if(!src.current) status += "&status=nobot" else status += "&status=[current.net_id]" var/botcharge = null if(src.current.cell) botcharge = "[round((src.current.cell.charge/src.current.cell.maxcharge)*100)]" else botcharge = "nocell" status += "&charge=[botcharge]" var/bottool = null if(src.current.tool) bottool = src.current.tool.tool_id else bottool = "NONE" status += "&tool=[bottool]" if(current.model_task) status += "&deftask=[current.model_task.task_id]" else status += "&deftask=NONE" if(current.task) status += "&curtask=[current.task.task_id]" else status += "&curtask=NONE" //status += "&botid=[current.net_id]" src.post_wire_status(target,"command","term_message","data",status) return if("eject") //Eject current bot if(!src.current) src.post_wire_status(target,"command","term_message","data","command=status&status=nobot") return src.eject_robot() //eject_robot alerts the host on its own return if("upload") if(!src.current) src.post_wire_status(target,"command","term_message","data","command=status&status=nobot") return var/datum/computer/file/guardbot_task/newtask = signal.data_file if(!istype(newtask)) src.post_wire_status(target,"command","term_message","data","command=status&status=badtask") return newtask = newtask.copy_file() //Original one will be deleted with the signal. //Clear other tasks? var/overwrite = text2num(data["overwrite"]) if(isnull(overwrite)) overwrite = 0 //Replace model (default task)? var/model = text2num(data["newmodel"]) if(isnull(model)) model = 0 var/result = upload_task(newtask, overwrite, model) if(result) src.post_wire_status(target,"command","term_message","data","command=status&status=upload_success") else src.post_wire_status(target,"command","term_message","data","command=status&status=badtask") qdel(newtask) return if("download") if(!src.current) src.post_wire_status(target,"command","term_message","data","command=status&status=nobot") return var/datum/computer/file/guardbot_task/task_copy if (text2num(data["model"]) != null) if (src.current.model_task) task_copy = src.current.model_task.copy_file() else if (src.current.task) task_copy = src.current.task.copy_file() if (task_copy) var/datum/signal/newsignal = get_free_signal() newsignal.source = src newsignal.transmission_method = TRANSMISSION_WIRE newsignal.data = list("address_1" = target, "command"="term_file", "data", "command=taskfile", "sender" = src.net_id) newsignal.data_file = task_copy SPAWN_DBG(2 DECI SECONDS) src.link.post_signal(src, newsignal) else src.post_wire_status(target, "command", "term_message", "data", "command=status&status=notask") return if("taskinq") //Task inquiry. if(!src.current) src.post_wire_status(target,"command","term_message","data","command=status&status=nobot") return var/task_reply = "command=trep" if(current.model_task) task_reply += "&deftask=[current.model_task.task_id]" else task_reply += "&deftask=NONE" if(current.task) task_reply += "&curtask=[current.task.task_id]" else task_reply += "&curtask=NONE" src.post_wire_status(target,"command","term_message","data",task_reply) return if("wipe") //Clear tasks of current bot if(!src.current) src.post_wire_status(target,"command","term_message","data","command=status&status=nobot") return src.current.add_task(null, 0, 1) //No new task, normal priority, wipe all others. if(src.current.model_task) qdel(src.current.model_task) if(src.current.task) qdel(src.current.task) src.post_wire_status(target,"command","term_message","data","command=status&status=wipe_success") return return if("term_ping") if(target != src.host_id) return if(signal.data["data"] == "reply") src.post_wire_status(target, "command","term_ping") src.timeout = initial(src.timeout) src.timeout_alert = 0 return if("term_disconnect") if(target == src.host_id) src.host_id = null src.timeout = initial(src.timeout) src.timeout_alert = 0 return return else if( (signal.data["address_1"] == "recharge") && !src.current) var/turf/T = get_turf(src) if(!T) return var/to_send = signal.data["sender"] SPAWN_DBG(rand(4,6)) //So robots don't swarm one of the stations. src.post_status(to_send, "command","recharge_src", "data", "x=[T.x]&y=[T.y]") return MouseDrop_T(obj/O as obj, mob/user as mob) if(user.stat || get_dist(user,src)>1) return if(istype(O, /obj/machinery/bot/guardbot) && !src.current && !O:charge_dock) if(O.loc != src.loc) return src.connect_robot(O) user.visible_message("[user] plugs [O] into the docking station!","You plug [O] into the docking station!") //if(!O:idle) // O:snooze() return process() if(current) if((status & NOPOWER) || !current.cell || (current.loc != src.loc)) eject_robot() return current.cell.give(200 + (current.cell.percent() < 25) ? 50 : 0) use_power(275) src.icon_state = "robuddycharger1" if((src.autoeject == 1) && (current.cell.charge >= current.cell.maxcharge) ) eject_robot() else if ((src.autoeject == 2 || src.autoeject == 3) && (current.cell.charge >= current.cell.maxcharge) ) for (var/mob/living/carbon/M in view(7, src)) if (M.stat) continue eject_robot() break if(src.host_id) if(src.timeout == 0) src.post_wire_status(host_id, "command","term_disconnect","data","timeout") src.host_id = null src.updateUsrDialog() src.timeout = initial(src.timeout) src.timeout_alert = 0 else src.timeout-- if(src.timeout <= 5 && !src.timeout_alert) src.timeout_alert = 1 src.post_wire_status(src.host_id, "command","term_ping","data","reply") return attackby(obj/item/W as obj, mob/user as mob) if (isscrewingtool(W)) playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1) boutput(user, "You [src.panel_open ? "secure" : "unscrew"] the maintenance panel.") src.panel_open = !src.panel_open src.updateUsrDialog() return else ..() return disposing() if(src.current) src.current.wakeup() current = null if(radio_controller) radio_controller.remove_object(src, "[frequency]") radio_connection = null if (link) link.master = null link = null ..() return proc eject_robot() if(!current) return src.icon_state = "robuddycharger0" src.current.charge_dock = null src.current.last_dock_id = src.net_id if (src.autoeject == 3) src.current.turn_off() src.current.warm_boot = 0 src.current.turn_on() else src.current.wakeup() src.autoeject = 0 if(src.host_id) //Alert system host of this development!! src.post_wire_status(src.host_id,"command","term_message","data","command=status&status=ejected&botid=[current.net_id]") src.current = null return connect_robot(obj/machinery/bot/guardbot/robot,aeject=0) if(!istype(robot)) return 0 src.current = robot robot.charge_dock = src src.autoeject = aeject if(!robot.idle) robot.snooze() if(src.host_id) src.post_wire_status(src.host_id,"command","term_message","data","command=status&status=connect&botid=[current.net_id]") return 1 upload_task(var/datum/computer/file/guardbot_task/task, clear_others=0, new_model=0) if(!current || !current.on || !istype(task)) return 0 if(new_model) if(current.model_task) qdel(current.model_task) var/datum/computer/file/guardbot_task/model = task.copy_file() model.master = current current.model_task = model current.add_task(task, 0, clear_others) if(!current.task) current.task = task return 1 post_status(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3) if(!radio_connection) return var/datum/signal/signal = get_free_signal() signal.source = src signal.transmission_method = TRANSMISSION_RADIO signal.data[key] = value if(key2) signal.data[key2] = value2 if(key3) signal.data[key3] = value3 if(target_id) signal.data["address_1"] = target_id signal.data["sender"] = src.net_id radio_connection.post_signal(src, signal, GUARDBOT_RADIO_RANGE) post_wire_status(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3) if(!src.link || !target_id) return var/datum/signal/signal = get_free_signal() signal.source = src signal.transmission_method = TRANSMISSION_WIRE signal.data[key] = value if(key2) signal.data[key2] = value2 if(key3) signal.data[key3] = value3 signal.data["address_1"] = target_id signal.data["sender"] = src.net_id SPAWN_DBG(2 DECI SECONDS) if (src.link) //ZeWaka: Fix for null.post_signal src.link.post_signal(src, signal) /obj/machinery/computer/tour_console name = "Tour Console" desc = "A computer console, presumably one relating to tours." icon_state = "old2" pixel_y = 8 var/obj/machinery/bot/guardbot/linked_bot = null New() ..() SPAWN_DBG (8) linked_bot = locate() in orange(1, src) attack_ai(mob/user as mob) return src.attack_hand(user) attack_hand(mob/user as mob) if (..() || (status & (NOPOWER|BROKEN))) return user.machine = src add_fingerprint(user) var/dat = "

Tour Monitor

" if (!linked_bot) dat += "No tour guide detected!" else dat += "Guide:
\[[linked_bot.name]]

" if ((linked_bot in orange(1, src)) && linked_bot.charge_dock) dat += "
Begin Tour
" else var/area/guideArea = get_area(linked_bot) dat += "Current Location: [istype(guideArea) ? guideArea.name : "Unknown"]" user.Browse("Tour Monitor[dat]", "window=tourconsole;size=302x245") onclose(user, "tourconsole") return Topic(href, href_list) if(..()) return usr.machine = src src.add_fingerprint(usr) if (href_list["start_tour"] && linked_bot && (linked_bot in orange(1, src)) && linked_bot.charge_dock) linked_bot.charge_dock.eject_robot() src.updateUsrDialog() return /obj/machinery/bot/guardbot/old name = "Robuddy" desc = "A PR-4 Robuddy. That's two models back by now! You didn't know any of these were still around." icon = 'icons/misc/oldbots.dmi' setup_no_costumes = 1 no_camera = 1 setup_charge_maximum = 800 setup_default_tool_path = /obj/item/device/guardbot_tool/flash speak(var/message) return ..("[uppertext(message)]") interact(mob/user as mob) var/dat = "PR-4 Robuddy v0.8

" var/power_readout = null var/readout_color = "#000000" if(!src.cell) power_readout = "NO CELL" else var/charge_percentage = round((cell.charge/cell.maxcharge)*100) power_readout = "[charge_percentage]%" switch(charge_percentage) if(0 to 10) readout_color = "#F80000" if(11 to 25) readout_color = "#FFCC00" if(26 to 50) readout_color = "#CCFF00" if(51 to 75) readout_color = "#33CC00" if(76 to 100) readout_color = "#33FF00" dat += {"Power:
[power_readout]

"} dat += "Current Tool: [src.tool ? src.tool.tool_id : "NONE"]
" if(src.locked) dat += "Status: [src.on ? "On" : "Off"]
" else dat += "Status: [src.on ? "On" : "Off"]
" dat += "
Network ID: \[[uppertext(src.net_id)]]
" user.Browse("Robuddy v0.8 controls[dat]", "window=guardbot") onclose(user, "guardbot") return explode() if(src.exploding) return src.exploding = 1 var/death_message = pick("It is now safe to shut off your buddy.","I regret nothing, but I am sorry I am about to leave my friends.","Malfunction!","I had a good run.","Es lebe die Freiheit!","Life was worth living.","Time to die...") speak(death_message) src.visible_message("[src] blows apart!") var/turf/T = get_turf(src) if(src.mover) src.mover.master = null qdel(src.mover) src.invisibility = 100 var/obj/overlay/Ov = new/obj/overlay(T) Ov.anchored = 1 Ov.name = "Explosion" Ov.layer = NOLIGHT_EFFECTS_LAYER_BASE Ov.pixel_x = -92 Ov.pixel_y = -96 Ov.icon = 'icons/effects/214x246.dmi' Ov.icon_state = "explosion" src.tool.set_loc(get_turf(src)) var/obj/item/guardbot_core/old/core = new /obj/item/guardbot_core/old(T) core.created_name = src.name core.created_default_task = src.setup_default_startup_task core.created_model_task = src.model_task var/list/throwparts = list() throwparts += new /obj/item/parts/robot_parts/arm/left(T) throwparts += new /obj/item/device/flash(T) throwparts += core throwparts += src.tool if(src.hat) throwparts += src.hat src.hat.set_loc(T) throwparts += new /obj/item/guardbot_frame/old(T) for(var/obj/O in throwparts) //This is why it is called "throwparts" var/edge = get_edge_target_turf(src, pick(alldirs)) O.throw_at(edge, 100, 4) SPAWN_DBG(0) //Delete the overlay when finished with it. src.on = 0 sleep(15) qdel(Ov) qdel(src) T.hotspot_expose(800,125) explosion(src, T, -1, -1, 2, 3) return /obj/item/guardbot_frame/old name = "Robuddy frame" desc = "The external casing of a PR-4 Robuddy." icon_state = "robuddy_frame-4-1" spawned_bot_type = /obj/machinery/bot/guardbot/old buddy_model = 4 /obj/item/guardbot_frame/old/golden desc = "The external casing of a PR-4 Robuddy. This one is gold plated." icon = 'icons/obj/aibots.dmi' icon_state = "goldbuddy_frame-4-1" spawned_bot_type = /obj/machinery/bot/guardbot/golden created_name = "Goldbuddy" buddy_model = 4 New() ..() SPAWN_DBG(6 DECI SECONDS) src.icon_state = "goldbuddy_frame-[buddy_model]-[stage]" if(src.stage >= 2) src.created_cell = new src.created_cell.charge = 0.9 * src.created_cell.maxcharge return attackby(obj/item/W as obj, mob/user as mob) if ((istype(W, /obj/item/guardbot_core))) if(W:buddy_model != src.buddy_model) boutput(user, "That core board is for a different model of robot!") return if(!created_cell || stage != 2) boutput(user, "You need to add a power cell first!") return if(!created_module) boutput(user, "You need to add a tool module first!") return src.stage = 3 src.icon_state = "goldbuddy_frame-[buddy_model]-3" if(W:created_name) src.created_name = W:created_name if(W:created_default_task) src.created_default_task = W:created_default_task if(W:created_model_task) src.created_model_task = W:created_model_task boutput(user, "You add the core board to [src]!") qdel(W) else if((istype(W, /obj/item/cell)) && stage == 1 && !created_cell) user.drop_item() W.set_loc(src) src.created_cell = W src.stage = 2 src.icon_state = "goldbuddy_frame-[buddy_model]-2" boutput(user, "You add the power cell to [src]!") else if((istype(W, /obj/item/device/guardbot_tool)) && stage == 2 && !created_module) user.drop_item() W.set_loc(src) src.created_module = W boutput(user, "You add the [W.name] to [src]!") else if (istype(W, /obj/item/parts/robot_parts/arm/) && src.stage == 3) src.stage++ boutput(user, "You add the robot arm to [src]!") qdel(W) var/obj/machinery/bot/guardbot/newbot = new src.spawned_bot_type (get_turf(src)) if(newbot.cell) qdel(newbot.cell) newbot.cell = src.created_cell newbot.setup_default_tool_path = null newbot.cell.set_loc(newbot) if(src.created_default_task) newbot.setup_default_startup_task = src.created_default_task if(src.created_module) newbot.tool = src.created_module newbot.tool.set_loc(newbot) newbot.tool.master = newbot if(src.created_model_task) newbot.model_task = src.created_model_task newbot.model_task.master = newbot newbot.name = src.created_name qdel(src) return /obj/item/guardbot_core/old name = "Robuddy mainboard" desc = "The primary circuitry of a PR-4 Robuddy." icon_state = "robuddy_core-4" buddy_model = 4 //A tourguide for "the crunch", or a station! /obj/machinery/bot/guardbot/old/tourguide name = "Marty" desc = "A PR-4 Robuddy. These are pretty old, you didn't know there were any still around! This one has a little name tag on the front labeled 'Marty'" setup_default_startup_task = /datum/computer/file/guardbot_task/tourguide no_camera = 1 setup_charge_maximum = 3000 setup_charge_percentage = 100 flashlight_lum = 4 var/HatToWear = /obj/item/clothing/head/safari New() ..() #ifdef XMAS src.HatToWear = /obj/item/clothing/head/helmet/space/santahat #endif src.hat = new HatToWear(src) src.update_icon() /obj/machinery/bot/guardbot/old/tourguide/destiny name = "Mary" desc = "A PR-4 Robuddy. These are pretty old, you didn't know there were any still around! This one has a little name tag on the front labeled 'Mary'." botcard_access = "Staff Assistant" beacon_freq = 1443 /obj/machinery/bot/guardbot/old/tourguide/linemap name = "Monty" desc = "A PR-4 Robuddy. These are pretty old, you didn't know there were any still around! This one has a little name tag on the front labeled 'Monty'." botcard_access = "Staff Assistant" beacon_freq = 1443 /obj/machinery/bot/guardbot/old/tourguide/oshan name = "Moby" desc = "A PR-4 Robuddy. These are pretty old, you didn't know there were any still around! This one has a little name tag on the front labeled 'Moby'." botcard_access = "Staff Assistant" beacon_freq = 1443 HatToWear = /obj/item/clothing/head/sea_captain New() ..() src.hat.name = "Moby's ship captain hat" /obj/machinery/bot/guardbot/old/tourguide/atlas name = "Mabel" desc = "A PR-4 Robuddy. These are pretty old, you didn't know there were any still around! This one has a little name tag on the front labeled 'Mabel'." botcard_access = "Staff Assistant" beacon_freq = 1443 HatToWear = /obj/item/clothing/head/NTberet New() ..() src.hat.name = "Mabel's beret" /obj/machinery/computer/hug_console name = "Hug Console" desc = "A hug console? It has a small opening on the top." icon = 'icons/obj/stationobjs.dmi' icon_state = "holo_console0" attackby(obj/item/W as obj, mob/user as mob) if (istype(W, /obj/item/token/hug_token)) user.visible_message("[user] inserts a [W] into the [src].", "You insert a [W] into the [src].") qdel(W) for (var/obj/machinery/bot/guardbot/buddy in machines) if (buddy.z != 1) continue if (buddy.charge_dock) buddy.charge_dock.eject_robot() else if (buddy.idle) buddy.wakeup() buddy.add_task(/datum/computer/file/guardbot_task/recharge/dock_sync, 1, 0) var/datum/computer/file/guardbot_task/security/single_use/tohug = new tohug.hug_target = user buddy.add_task(tohug, 1, 0) buddy.navigate_to(get_turf(user)) /obj/item/token/hug_token name = "Hug Token" desc = "A Hug Token. Just looking at it makes you feel better." icon = 'icons/obj/items.dmi' icon_state = "coin" item_state = "coin" w_class = 1.0 attack_self(var/mob/user as mob) playsound(src.loc, "sound/items/coindrop.ogg", 100, 1) user.visible_message("[user] flips the token","You flip the token") SPAWN_DBG(1 SECOND) user.visible_message("It came up Hugs.") #undef GUARDBOT_DOCK_RESET_DELAY #undef GUARDBOT_LOWPOWER_ALERT_LEVEL #undef GUARDBOT_LOWPOWER_IDLE_LEVEL #undef GUARDBOT_POWER_DRAW #undef GUARDBOT_RADIO_RANGE