From 4b4c2d11fae7769390a4ac02a42df48edea71b26 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Thu, 4 Sep 2014 09:12:22 +0200 Subject: [PATCH] Beepsky and ED209 are now closer friends than ever, now actually sharing code instead of each having gone and bought their own. There is potential for breaking out all the special stuff for laser code but for now I'm happy to simply have a shared codebase. I imagine pathfinding/patrolling may be sharable with bots in general as well. --- code/datums/spells/conjure.dm | 2 +- code/game/machinery/bots/ed209bot.dm | 887 +------------------ code/game/machinery/bots/secbot.dm | 309 +++++-- code/game/objects/items/robot/robot_parts.dm | 2 +- 4 files changed, 241 insertions(+), 959 deletions(-) diff --git a/code/datums/spells/conjure.dm b/code/datums/spells/conjure.dm index de84db5915b..1a489524517 100644 --- a/code/datums/spells/conjure.dm +++ b/code/datums/spells/conjure.dm @@ -58,7 +58,7 @@ name = "Dispense Wizard Justice" desc = "This spell dispenses wizard justice." - summon_type = list(/obj/machinery/bot/ed209) + summon_type = list(/obj/item/weapon/secbot_assembly/ed209_assembly) summon_amt = 10 range = 3 newVars = list("emagged" = 1,"name" = "Wizard's Justicebot") diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index fe7425ee8ce..2b7515e35ab 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -1,785 +1,34 @@ -/obj/machinery/bot/ed209 +/obj/machinery/bot/secbot/ed209 name = "ED-209 Security Robot" desc = "A security robot. He looks less than thrilled." icon = 'icons/obj/aibots.dmi' icon_state = "ed2090" - layer = 5.0 density = 1 - anchored = 0 -// weight = 1.0E7 - req_one_access = list(access_security, access_forensics_lockers) health = 100 maxhealth = 100 - fire_dam_coeff = 0.7 - brute_dam_coeff = 0.5 - var/lastfired = 0 - var/shot_delay = 3 //.3 seconds between shots - var/lasercolor = "" - var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag + bot_version = "2.5" + search_range = 12 - //var/lasers = 0 + preparing_arrest_sounds = new() + secbot_assembly = /obj/item/weapon/secbot_assembly/ed209_assembly - var/mob/living/carbon/target - var/oldtarget_name - var/threatlevel = 0 - var/target_lastloc //Loc of target when arrested. - var/last_found //There's a delay - var/frustration = 0 -//var/emagged = 0 //Emagged Secbots view everyone as a criminal - var/idcheck = 1 //If false, all station IDs are authorized for weapons. - var/check_records = 1 //Does it check security records? - var/arrest_type = 0 //If true, don't handcuff - var/declare_arrests = 0 //When making an arrest, should it notify everyone wearing sechuds? - var/projectile = null//Holder for projectile type, to avoid so many else if chains - - var/mode = 0 -#define SECBOT_IDLE 0 // idle -#define SECBOT_HUNT 1 // found target, hunting -#define SECBOT_PREP_ARREST 2 // at target, preparing to arrest -#define SECBOT_ARREST 3 // arresting target -#define SECBOT_START_PATROL 4 // start patrol -#define SECBOT_PATROL 5 // patrolling -#define SECBOT_SUMMON 6 // summoned by PDA - - var/auto_patrol = 0 // set to make bot automatically patrol - - var/beacon_freq = 1445 // navigation beacon frequency - var/control_freq = 1447 // bot control frequency - - - var/turf/patrol_target // this is turf to navigate to (location of beacon) - var/new_destination // pending new destination (waiting for beacon response) - var/destination // destination description tag - var/next_destination // the next destination in the patrol route - var/list/path = new // list of path turfs - - var/blockcount = 0 //number of times retried a blocked path - var/awaiting_beacon = 0 // count of pticks awaiting a beacon response - - var/nearest_beacon // the nearest beacon's tag - var/turf/nearest_beacon_loc // the nearest beacon's location - - -/obj/item/weapon/ed209_assembly +/obj/item/weapon/secbot_assembly/ed209_assembly name = "ED-209 assembly" desc = "Some sort of bizarre assembly." icon = 'icons/obj/aibots.dmi' icon_state = "ed209_frame" item_state = "ed209_frame" - var/build_step = 0 - var/created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess + created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess var/lasercolor = "" - -/obj/machinery/bot/ed209/New(loc,created_name,created_lasercolor) - ..() - if(created_name) name = created_name - if(created_lasercolor) lasercolor = created_lasercolor - src.icon_state = "[lasercolor]ed209[src.on]" - spawn(3) - src.botcard = new /obj/item/weapon/card/id(src) - var/datum/job/detective/J = new/datum/job/detective - src.botcard.access = J.get_access() - - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - if(lasercolor) - shot_delay = 6//Longer shot delay because JESUS CHRIST - check_records = 0//Don't actively target people set to arrest - arrest_type = 1//Don't even try to cuff - req_access = list(access_maint_tunnels) - arrest_type = 1 - if((lasercolor == "b") && (name == "ED-209 Security Robot"))//Picks a name if there isn't already a custome one - name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") - if((lasercolor == "r") && (name == "ED-209 Security Robot")) - name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") - -/obj/machinery/bot/ed209/turn_on() - . = ..() - src.icon_state = "[lasercolor]ed209[src.on]" - src.mode = SECBOT_IDLE - src.updateUsrDialog() - -/obj/machinery/bot/ed209/turn_off() - ..() - src.target = null - src.oldtarget_name = null - src.anchored = 0 - src.mode = SECBOT_IDLE - walk_to(src,0) - src.icon_state = "[lasercolor]ed209[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/ed209/attack_hand(mob/user as mob) - . = ..() - if (.) - return - var/dat - - dat += text({" -Automatic Security Unit v2.5

-Status: []
-Behaviour controls are [src.locked ? "locked" : "unlocked"]
-Maintenance panel panel is [src.open ? "opened" : "closed"]"}, - -"[src.on ? "On" : "Off"]" ) - - if(!src.locked || issilicon(user)) - if(!lasercolor) - dat += text({"
-Check for Weapon Authorization: []
-Check Security Records: []
-Operating Mode: []
-Report Arrests: []
-Auto Patrol: []"}, - -"[src.idcheck ? "Yes" : "No"]", -"[src.check_records ? "Yes" : "No"]", -"[src.arrest_type ? "Detain" : "Arrest"]", -"[src.declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) - else - dat += text({"
-Auto Patrol: []"}, - -"[auto_patrol ? "On" : "Off"]" ) - - - user << browse("Securitron v2.5 controls[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/bot/ed209/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(lasercolor && (istype(usr,/mob/living/carbon/human))) - var/mob/living/carbon/human/H = usr - if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it - return - else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - if ((href_list["power"]) && (src.allowed(usr))) - if (src.on) - turn_off() - else - turn_on() - return - - switch(href_list["operation"]) - if ("idcheck") - src.idcheck = !src.idcheck - src.updateUsrDialog() - if ("ignorerec") - src.check_records = !src.check_records - src.updateUsrDialog() - if ("switchmode") - src.arrest_type = !src.arrest_type - src.updateUsrDialog() - if("patrol") - auto_patrol = !auto_patrol - mode = SECBOT_IDLE - updateUsrDialog() - if("declarearrests") - src.declare_arrests = !src.declare_arrests - src.updateUsrDialog() - -/obj/machinery/bot/ed209/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user) && !open && !emagged) - src.locked = !src.locked - user << "Controls are now [src.locked ? "locked" : "unlocked"]." - else - if(emagged) - user << "ERROR" - if(open) - user << "Please close the access panel before locking it." - else - user << "Access denied." +/obj/machinery/bot/secbot/ed209/update_icon() + if(on && is_attacking) + src.icon_state = "[lasercolor]ed209-c" else - ..() - if (!istype(W, /obj/item/weapon/screwdriver) && (!src.target)) - if(hasvar(W,"force") && W.force)//If force is defined and non-zero - src.target = user - if(lasercolor)//To make up for the fact that lasertag bots don't hunt - src.shootAt(user) - src.mode = SECBOT_HUNT - -/obj/machinery/bot/ed209/Emag(mob/user as mob) - ..() - if(open && !locked) - if(user) user << "You short out [src]'s target assessment circuits." - spawn(0) - for(var/mob/O in hearers(src, null)) - O.show_message("\red [src] buzzes oddly!", 1) - src.target = null - if(user) src.oldtarget_name = user.name - src.last_found = world.time - src.anchored = 0 - src.emagged = 2 - src.on = 1 src.icon_state = "[lasercolor]ed209[src.on]" - src.projectile = null - mode = SECBOT_IDLE - -/obj/machinery/bot/ed209/process() - set background = 1 - - if (!src.on) - return - var/list/targets = list() - for (var/mob/living/carbon/C in view(12,src)) //Let's find us a target - var/threatlevel = 0 - if ((C.stat) || (C.lying)) - continue - if (istype(C, /mob/living/carbon/human)) - threatlevel = src.assess_perp(C) - //src.speak(C.real_name + text(": threat: []", threatlevel)) - if (threatlevel < 4 ) - continue - - var/dst = get_dist(src, C) - if ( dst <= 1 || dst > 12) - continue - - targets += C - if (targets.len>0) - var/mob/t = pick(targets) - if (istype(t, /mob/living)) - if ((t.stat!=2) && (t.lying != 1)) - //src.speak("selected target: " + t.real_name) - src.shootAt(t) - switch(mode) - - if(SECBOT_IDLE) // idle - walk_to(src,0) - look_for_perp() // see if any criminals are in range - if(!mode && auto_patrol) // still idle, and set to patrol - mode = SECBOT_START_PATROL // switch to patrol mode - - if(SECBOT_HUNT) // hunting for perp - if(src.lasercolor)//Lasertag bots do not tase or arrest anyone, just patrol and shoot and whatnot - mode = SECBOT_IDLE - return - // if can't reach perp for long enough, go idle - if (src.frustration >= 8) - // for(var/mob/O in hearers(src, null)) - // O << "[src] beeps, \"Backup requested! Suspect has evaded arrest.\"" - src.target = null - src.last_found = world.time - src.frustration = 0 - src.mode = 0 - walk_to(src,0) - - if (target) // make sure target exists - if (Adjacent(target)) // if right next to perp - playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - src.icon_state = "[lasercolor]ed209-c" - spawn(2) - src.icon_state = "[lasercolor]ed209[src.on]" - var/mob/living/carbon/M = src.target - var/maxstuns = 4 - if (istype(M, /mob/living/carbon/human)) - if (M.stuttering < 10 && (!(HULK in M.mutations)) /*&& (!istype(M:wear_suit, /obj/item/clothing/suit/judgerobe))*/) - M.stuttering = 10 - M.Stun(10) - M.Weaken(10) - else - M.Weaken(10) - M.stuttering = 10 - M.Stun(10) - maxstuns-- - if (maxstuns <= 0) - target = null - - if(declare_arrests) - var/area/location = get_area(src) - broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) - visible_message("\red [src.target] has been stunned by [src]!") - - mode = SECBOT_PREP_ARREST - src.anchored = 1 - src.target_lastloc = M.loc - return - - else // not next to perp - var/turf/olddist = get_dist(src, src.target) - walk_to(src, src.target,1,4) - if ((get_dist(src, src.target)) >= (olddist)) - src.frustration++ - else - src.frustration = 0 - - if(SECBOT_PREP_ARREST) // preparing to arrest target - if(src.lasercolor) - mode = SECBOT_IDLE - return - if (!target) - mode = SECBOT_IDLE - src.anchored = 0 - return - // see if he got away - if ((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:weakened < 2)) - src.anchored = 0 - mode = SECBOT_HUNT - return - - if(istype(src.target,/mob/living/carbon)) - if (!src.target.handcuffed && !src.arrest_type) - playsound(src.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) - mode = SECBOT_ARREST - visible_message("\red [src] is trying to put handcuffs on [src.target]!") - - spawn(60) - if (get_dist(src, src.target) <= 1) - if (src.target.handcuffed) - return - - if(istype(src.target,/mob/living/carbon)) - src.target.handcuffed = new /obj/item/weapon/handcuffs(src.target) - target.update_inv_handcuffed() //update handcuff overlays - - mode = SECBOT_IDLE - src.target = null - src.anchored = 0 - src.last_found = world.time - src.frustration = 0 - - // playsound(src.loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) - // var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.") - // src.speak(arrest_message) - else - mode = SECBOT_IDLE - src.target = null - src.anchored = 0 - src.last_found = world.time - src.frustration = 0 - - if(SECBOT_ARREST) // arresting - if(src.lasercolor) - mode = SECBOT_IDLE - return - if (!target || src.target.handcuffed) - src.anchored = 0 - mode = SECBOT_IDLE - return - - - if(SECBOT_START_PATROL) // start a patrol - - if(path.len > 0 && patrol_target) // have a valid path, so just resume - mode = SECBOT_PATROL - return - - else if(patrol_target) // has patrol target already - spawn(0) - calc_path() // so just find a route to it - if(path.len == 0) - patrol_target = 0 - return - mode = SECBOT_PATROL - - - else // no patrol target, so need a new one - find_patrol_target() - speak("Engaging patrol mode.") - - - if(SECBOT_PATROL) // patrol mode - patrol_step() - spawn(5) - if(mode == SECBOT_PATROL) - patrol_step() - - if(SECBOT_SUMMON) // summoned to PDA - patrol_step() - spawn(4) - if(mode == SECBOT_SUMMON) - patrol_step() - sleep(4) - patrol_step() - - return - - -// perform a single patrol step - -/obj/machinery/bot/ed209/proc/patrol_step() - - if(loc == patrol_target) // reached target - at_patrol_target() - return - - else if(path.len > 0 && patrol_target) // valid path - - var/turf/next = path[1] - if(next == loc) - path -= next - return - - - if(istype( next, /turf/simulated)) - - var/moved = step_towards(src, next) // attempt to move - if(moved) // successful move - blockcount = 0 - path -= loc - - look_for_perp() - if(lasercolor) - sleep(20) - else // failed to move - - blockcount++ - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - - spawn(2) - calc_path(next) - if(path.len == 0) - find_patrol_target() - else - blockcount = 0 - - return - - return - - else // not a valid turf - mode = SECBOT_IDLE - return - - else // no path, so calculate new one - mode = SECBOT_START_PATROL - - -// finds a new patrol target -/obj/machinery/bot/ed209/proc/find_patrol_target() - send_status() - if(awaiting_beacon) // awaiting beacon response - awaiting_beacon++ - if(awaiting_beacon > 5) // wait 5 secs for beacon response - find_nearest_beacon() // then go to nearest instead - return - - if(next_destination) - set_destination(next_destination) - else - find_nearest_beacon() - return - - -// finds the nearest beacon to self -// signals all beacons matching the patrol code -/obj/machinery/bot/ed209/proc/find_nearest_beacon() - nearest_beacon = null - new_destination = "__nearest__" - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - spawn(10) - awaiting_beacon = 0 - if(nearest_beacon) - set_destination(nearest_beacon) - else - auto_patrol = 0 - mode = SECBOT_IDLE - speak("Disengaging patrol mode.") - send_status() - - -/obj/machinery/bot/ed209/proc/at_patrol_target() - find_patrol_target() - return - - -// sets the current destination -// signals all beacons matching the patrol code -// beacons will return a signal giving their locations -/obj/machinery/bot/ed209/proc/set_destination(var/new_dest) - new_destination = new_dest - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - - -// receive a radio signal -// used for beacon reception - -/obj/machinery/bot/ed209/receive_signal(datum/signal/signal) - - if(!on) - return - - /* - world << "rec signal: [signal.source]" - for(var/x in signal.data) - world << "* [x] = [signal.data[x]]" - */ - - var/recv = signal.data["command"] - // process all-bot input - if(recv=="bot_status") - send_status() - - // check to see if we are the commanded bot - if(signal.data["active"] == src) - // process control input - switch(recv) - if("stop") - mode = SECBOT_IDLE - auto_patrol = 0 - return - - if("go") - mode = SECBOT_IDLE - auto_patrol = 1 - return - - if("summon") - patrol_target = signal.data["target"] - next_destination = destination - destination = null - awaiting_beacon = 0 - mode = SECBOT_SUMMON - calc_path() - speak("Responding.") - - return - - - - // receive response from beacon - recv = signal.data["beacon"] - var/valid = signal.data["patrol"] - if(!recv || !valid) - return - - if(recv == new_destination) // if the recvd beacon location matches the set destination - // the we will navigate there - destination = new_destination - patrol_target = signal.source.loc - next_destination = signal.data["next_patrol"] - awaiting_beacon = 0 - - // if looking for nearest beacon - else if(new_destination == "__nearest__") - var/dist = get_dist(src,signal.source.loc) - if(nearest_beacon) - - // note we ignore the beacon we are located at - if(dist>1 && dist 1) - nearest_beacon = recv - nearest_beacon_loc = signal.source.loc - return - - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/ed209/proc/post_signal(var/freq, var/key, var/value) - post_signal_multiple(freq, list("[key]" = value) ) - -// send a radio signal with multiple data key/values -/obj/machinery/bot/ed209/proc/post_signal_multiple(var/freq, var/list/keyval) - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = new() - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - //world << "sent [key],[keyval[key]] on [freq]" - signal.data = keyval - if (signal.data["findbeacon"]) - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - else if (signal.data["type"] == "secbot") - frequency.post_signal(src, signal, filter = RADIO_SECBOT) - else - frequency.post_signal(src, signal) - -// signals bot status etc. to controller -/obj/machinery/bot/ed209/proc/send_status() - var/list/kv = list( - "type" = "secbot", - "name" = name, - "loca" = loc.loc, // area - "mode" = mode, - ) - post_signal_multiple(control_freq, kv) - - - -// calculates a path to the current destination -// given an optional turf to avoid -/obj/machinery/bot/ed209/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) - if (!src.path) src.path = list() - - -// look for a criminal in view of the bot - -/obj/machinery/bot/ed209/proc/look_for_perp() - if(src.disabled) - return - src.anchored = 0 - src.threatlevel = 0 - for (var/mob/living/carbon/C in view(12,src)) //Let's find us a criminal - if ((C.stat) || (C.handcuffed)) - continue - - if((src.lasercolor) && (C.lying)) - continue//Does not shoot at people lyind down when in lasertag mode, because it's just annoying, and they can fire once they get up. - - if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) - continue - - if (istype(C, /mob/living/carbon/human)) - src.threatlevel = src.assess_perp(C) - - if (!src.threatlevel) - continue - - else if (src.threatlevel >= 4) - src.target = C - src.oldtarget_name = C.name - src.speak("Level [src.threatlevel] infraction alert!") - if(!src.lasercolor) - playsound(src.loc, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) - src.visible_message("[src] points at [C.name]!") - mode = SECBOT_HUNT - spawn(0) - process() // ensure bot quickly responds to a perp - break - else - continue - - -//If the security records say to arrest them, arrest them -//Or if they have weapons and aren't security, arrest them. -/obj/machinery/bot/ed209/proc/assess_perp(mob/living/carbon/human/perp as mob) - var/threatcount = 0 - - if(src.emagged == 2) return 10 //Everyone is a criminal! - - if((src.idcheck) || (isnull(perp:wear_id)) || (istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate))) - - if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) - if(!istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 4 - - if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) - if(!istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 4 - - if(istype(perp:belt, /obj/item/weapon/gun) || istype(perp:belt, /obj/item/weapon/melee)) - if(!istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 2 - - if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) - threatcount += 2 - - if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") - threatcount += 2 - -//Agent cards lower threatlevel when normal idchecking is off. - if((perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) && src.idcheck) - threatcount -= 2 - - if(src.lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - threatcount = 0//They will not, however shoot at people who have guns, because it gets really fucking annoying - if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) - threatcount += 4 - if((istype(perp:r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp:l_hand,/obj/item/weapon/gun/energy/laser/redtag))) - threatcount += 4 - if(istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 2 - - if(src.lasercolor == "r") - threatcount = 0 - if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) - threatcount += 4 - if((istype(perp:r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp:l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) - threatcount += 4 - if(istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 2 - - if(src.check_records) - for (var/datum/data/record/E in data_core.general) - var/perpname = perp.name - if(perp.wear_id) - var/obj/item/weapon/card/id/id = perp.wear_id.GetID() - if(id) - perpname = id.registered_name - - if(E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - threatcount = 4 - break - - if((src.idcheck) && (src.allowed(perp)) && !(src.lasercolor)) - threatcount = 0//Corrupt cops cannot exist beep boop - - return threatcount - -/obj/machinery/bot/ed209/Bump(M as mob|obj) //Leave no door unopened! - if ((istype(M, /obj/machinery/door)) && !isnull(src.botcard)) - var/obj/machinery/door/D = M - if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/poddoor)) - D.open() - src.frustration = 0 - else if(!src.anchored) - if ((istype(M, /mob/living/))) - var/mob/living/O = M - src.loc = O.loc - src.frustration = 0 - else if (istype(M, /obj/machinery/bot)) - var/obj/machinery/bot/B = M - if (B.dir != src.dir) // Avoids issues if two bots are currently patrolling in the same direction - src.loc = B.loc - src.frustration = 0 - return - -/* terrible -/obj/machinery/bot/ed209/Bumped(atom/movable/M as mob|obj) - spawn(0) - if (M) - var/turf/T = get_turf(src) - M:loc = T -*/ - -/obj/machinery/bot/ed209/proc/speak(var/message) - for(var/mob/O in hearers(src, null)) - O.show_message("[src] beeps, \"[message]\"",2) - return - -/obj/machinery/bot/ed209/explode() - walk_to(src,0) - src.visible_message("\red [src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - var/obj/item/weapon/ed209_assembly/Sa = new /obj/item/weapon/ed209_assembly(Tsec) - Sa.build_step = 1 - Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") - Sa.created_name = src.name - new /obj/item/device/assembly/prox_sensor(Tsec) +/obj/machinery/bot/secbot/ed209/on_explosion(var/turf/Tsec) if(!lasercolor) var/obj/item/weapon/gun/energy/taser/G = new /obj/item/weapon/gun/energy/taser(Tsec) G.power_supply.charge = 0 @@ -789,7 +38,6 @@ Auto Patrol: []"}, else if(lasercolor == "r") var/obj/item/weapon/gun/energy/laser/redtag/G = new /obj/item/weapon/gun/energy/laser/redtag(Tsec) G.power_supply.charge = 0 - if (prob(50)) new /obj/item/robot_parts/l_leg(Tsec) if (prob(25)) @@ -805,104 +53,7 @@ Auto Patrol: []"}, if(lasercolor == "r") new /obj/item/clothing/suit/redtag(Tsec) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - new /obj/effect/decal/cleanable/blood/oil(src.loc) - del(src) - - -/obj/machinery/bot/ed209/proc/shootAt(var/mob/target) - if(lastfired && world.time - lastfired < shot_delay) - return - lastfired = world.time - var/turf/T = loc - var/atom/U = (istype(target, /atom/movable) ? target.loc : target) - if ((!( U ) || !( T ))) - return - while(!( istype(U, /turf) )) - U = U.loc - if (!( istype(T, /turf) )) - return - - //if(lastfired && world.time - lastfired < 100) - // playsound(src.loc, 'ed209_shoot.ogg', 50, 0) - - if(!projectile) - if(!lasercolor) - if (src.emagged == 2) - projectile = /obj/item/projectile/beam - else - projectile = /obj/item/projectile/beam/stun - else if(lasercolor == "b") - if (src.emagged == 2) - projectile = /obj/item/projectile/beam/lastertag/omni - else - projectile = /obj/item/projectile/beam/lastertag/blue - else if(lasercolor == "r") - if (src.emagged == 2) - projectile = /obj/item/projectile/beam/lastertag/omni - else - projectile = /obj/item/projectile/beam/lastertag/red - - if (!( istype(U, /turf) )) - return - var/obj/item/projectile/A = new projectile (loc) - A.current = U - A.yo = U.y - T.y - A.xo = U.x - T.x - spawn( 0 ) - A.process() - return - return - -/obj/machinery/bot/ed209/attack_alien(var/mob/living/carbon/alien/user as mob) - ..() - if (!isalien(target)) - src.target = user - src.mode = SECBOT_HUNT - - -/obj/machinery/bot/ed209/emp_act(severity) - - if(severity==2 && prob(70)) - ..(severity-1) - else - var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.dir = pick(cardinal) - spawn(10) - pulse2.delete() - var/list/mob/living/carbon/targets = new - for (var/mob/living/carbon/C in view(12,src)) - if (C.stat==2) - continue - targets += C - if(targets.len) - if(prob(50)) - var/mob/toshoot = pick(targets) - if (toshoot) - targets-=toshoot - if (prob(50) && emagged < 2) - emagged = 2 - shootAt(toshoot) - emagged = 0 - else - shootAt(toshoot) - else if(prob(50)) - if(targets.len) - var/mob/toarrest = pick(targets) - if (toarrest) - src.target = toarrest - src.mode = SECBOT_HUNT - - - -/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) +/obj/item/weapon/secbot_assembly/ed209_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() if(istype(W, /obj/item/weapon/pen)) @@ -1021,14 +172,14 @@ Auto Patrol: []"}, build_step++ user << "You complete the ED-209." var/turf/T = get_turf(src) - new /obj/machinery/bot/ed209(T,created_name,lasercolor) + new /obj/machinery/bot/secbot/ed209(T,created_name,lasercolor) user.drop_item() del(W) user.drop_from_inventory(src) del(src) -/obj/machinery/bot/ed209/bullet_act(var/obj/item/projectile/Proj) +/obj/machinery/bot/secbot/ed209/bullet_act(var/obj/item/projectile/Proj) if((src.lasercolor == "b") && (src.disabled == 0)) if(istype(Proj, /obj/item/projectile/beam/lastertag/red)) src.disabled = 1 @@ -1048,11 +199,11 @@ Auto Patrol: []"}, else ..() -/obj/machinery/bot/ed209/bluetag/New()//If desired, you spawn red and bluetag bots easily - new /obj/machinery/bot/ed209(get_turf(src),null,"b") +/obj/machinery/bot/secbot/ed209/bluetag/New()//If desired, you spawn red and bluetag bots easily + new /obj/machinery/bot/secbot/ed209(get_turf(src),null,"b") del(src) -/obj/machinery/bot/ed209/redtag/New() - new /obj/machinery/bot/ed209(get_turf(src),null,"r") - del(src) \ No newline at end of file +/obj/machinery/bot/secbot/ed209/redtag/New() + new /obj/machinery/bot/secbot/ed209(get_turf(src),null,"r") + del(src) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index fa7df5de995..9c05abb7fae 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -10,20 +10,26 @@ maxhealth = 25 fire_dam_coeff = 0.7 brute_dam_coeff = 0.5 -// weight = 1.0E7 req_one_access = list(access_security, access_forensics_lockers) + var/mob/target var/oldtarget_name var/threatlevel = 0 var/target_lastloc //Loc of target when arrested. var/last_found //There's a delay var/frustration = 0 -// var/emagged = 0 //Emagged Secbots view everyone as a criminal + var/idcheck = 0 //If false, all station IDs are authorized for weapons. var/check_records = 1 //Does it check security records? var/arrest_type = 0 //If true, don't handcuff var/declare_arrests = 0 //When making an arrest, should it notify everyone wearing sechuds? + var/next_harm_time = 0 + var/lastfired = 0 + var/shot_delay = 3 //.3 seconds between shots + var/lasercolor = "" + var/projectile = null//Holder for projectile type, to avoid so many else if chains + var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag var/mode = 0 #define SECBOT_IDLE 0 // idle @@ -52,6 +58,14 @@ var/nearest_beacon // the nearest beacon's tag var/turf/nearest_beacon_loc // the nearest beacon's location + var/bot_version = "1.3" + var/search_range = 7 + var/is_attacking = 0 + + var/obj/item/weapon/secbot_assembly = /obj/item/weapon/secbot_assembly + + var/list/threat_found_sounds = new('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg') + var/list/preparing_arrest_sounds = new('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg') /obj/machinery/bot/secbot/beepsky name = "Officer Beep O'sky" @@ -68,24 +82,39 @@ var/build_step = 0 var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess +/obj/machinery/bot/secbot/New(loc, created_name, created_lasercolor) + ..() + if(created_name) name = created_name + if(created_lasercolor) lasercolor = created_lasercolor + update_icon() + spawn(3) + src.botcard = new /obj/item/weapon/card/id(src) + var/datum/job/detective/J = new/datum/job/detective + src.botcard.access = J.get_access() + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + if(lasercolor) + shot_delay = 6 //Longer shot delay because JESUS CHRIST + check_records = 0 //Don't actively target people set to arrest + arrest_type = 1 //Don't even try to cuff + req_access = list(access_maint_tunnels) + arrest_type = 1 + if((lasercolor == "b") && (name == created_name))//Picks a name if there isn't already a custome one + name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") + if((lasercolor == "r") && (name == created_name)) + name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") -/obj/machinery/bot/secbot - New() - ..() +/obj/machinery/bot/secbot/update_icon() + if(on && is_attacking) + src.icon_state = "secbot-c" + else src.icon_state = "secbot[src.on]" - spawn(3) - src.botcard = new /obj/item/weapon/card/id(src) - var/datum/job/detective/J = new/datum/job/detective - src.botcard.access = J.get_access() - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - /obj/machinery/bot/secbot/turn_on() ..() - src.icon_state = "secbot[src.on]" + update_icon() src.updateUsrDialog() /obj/machinery/bot/secbot/turn_off() @@ -95,7 +124,7 @@ src.anchored = 0 src.mode = SECBOT_IDLE walk_to(src,0) - src.icon_state = "secbot[src.on]" + update_icon() src.updateUsrDialog() /obj/machinery/bot/secbot/attack_hand(mob/user as mob) @@ -109,7 +138,7 @@ var/dat dat += text({" -Automatic Security Unit v1.3

+Automatic Security Unit v[bot_version]

Status: []
Behaviour controls are [src.locked ? "locked" : "unlocked"]
Maintenance panel panel is [src.open ? "opened" : "closed"]"}, @@ -131,60 +160,67 @@ Auto Patrol: []"}, "[auto_patrol ? "On" : "Off"]" ) - user << browse("Securitron v1.3 controls[dat]", "window=autosec") + user << browse("Securitron v[bot_version] controls[dat]", "window=autosec") onclose(user, "autosec") return /obj/machinery/bot/secbot/Topic(href, href_list) + if(..()) + return usr.set_machine(src) src.add_fingerprint(usr) + if(lasercolor && (istype(usr,/mob/living/carbon/human))) + var/mob/living/carbon/human/H = usr + if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it + return + else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) + return if((href_list["power"]) && (src.allowed(usr))) if(src.on) turn_off() else turn_on() + src.updateUsrDialog() return switch(href_list["operation"]) if("idcheck") src.idcheck = !src.idcheck - src.updateUsrDialog() if("ignorerec") src.check_records = !src.check_records - src.updateUsrDialog() if("switchmode") src.arrest_type = !src.arrest_type - src.updateUsrDialog() if("patrol") auto_patrol = !auto_patrol mode = SECBOT_IDLE - updateUsrDialog() if("declarearrests") src.declare_arrests = !src.declare_arrests - src.updateUsrDialog() + src.updateUsrDialog() /obj/machinery/bot/secbot/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) if(src.allowed(user) && !open && !emagged) src.locked = !src.locked - user << "Controls are now [src.locked ? "locked." : "unlocked."]" + user << "Controls are now [src.locked ? "locked" : "unlocked"]." else if(emagged) user << "ERROR" if(open) - user << "\red Please close the access panel before locking it." + user << "Please close the access panel before locking it." else - user << "\red Access denied." + user << "Access denied." else ..() - if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!src.target)) + if(!istype(W, /obj/item/weapon/screwdriver) && W.force && !src.target) src.target = user + if(lasercolor)//To make up for the fact that lasertag bots don't hunt + src.shootAt(user) src.mode = SECBOT_HUNT /obj/machinery/bot/secbot/Emag(mob/user as mob) ..() if(open && !locked) - if(user) user << "\red You short out [src]'s target assessment circuits." + if(user) user << "You short out [src]'s target assessment circuits." spawn(0) for(var/mob/O in hearers(src, null)) O.show_message("\red [src] buzzes oddly!", 1) @@ -194,7 +230,8 @@ Auto Patrol: []"}, src.anchored = 0 src.emagged = 2 src.on = 1 - src.icon_state = "secbot[src.on]" + update_icon() + src.projectile = null mode = SECBOT_IDLE /obj/machinery/bot/secbot/process() @@ -206,14 +243,15 @@ Auto Patrol: []"}, switch(mode) if(SECBOT_IDLE) // idle - walk_to(src,0) look_for_perp() // see if any criminals are in range if(!mode && auto_patrol) // still idle, and set to patrol mode = SECBOT_START_PATROL // switch to patrol mode if(SECBOT_HUNT) // hunting for perp - + if(src.lasercolor)//Lasertag bots do not tase or arrest anyone, just patrol and shoot and whatnot + mode = SECBOT_IDLE + return // if can't reach perp for long enough, go idle if(src.frustration >= 8) // for(var/mob/O in hearers(src, null)) @@ -228,9 +266,11 @@ Auto Patrol: []"}, if(Adjacent(target)) // if right next to perp if(istype(src.target,/mob/living/carbon)) playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - src.icon_state = "secbot-c" + is_attacking = 1 + update_icon() spawn(2) - src.icon_state = "secbot[src.on]" + is_attacking = 0 + update_icon() var/mob/living/carbon/M = src.target var/maxstuns = 4 if(istype(M, /mob/living/carbon/human)) @@ -271,7 +311,6 @@ Auto Patrol: []"}, if(S.stat) src.frustration = 8 playsound(src.loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg'), 50, 0) - else // not next to perp var/turf/olddist = get_dist(src, src.target) walk_to(src, src.target,1,4) @@ -283,9 +322,15 @@ Auto Patrol: []"}, src.frustration = 8 if(SECBOT_PREP_ARREST) // preparing to arrest target - + if(src.lasercolor) + mode = SECBOT_IDLE + return + if(!target) + mode = SECBOT_IDLE + src.anchored = 0 + return // see if he got away - if((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:weakened < 2)) + if((get_dist(src, src.target) > 1) || ((src.target.loc != src.target_lastloc) && src.target.weakened < 2)) src.anchored = 0 mode = SECBOT_HUNT return @@ -314,10 +359,10 @@ Auto Patrol: []"}, src.last_found = world.time src.frustration = 0 - playsound(src.loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + if(preparing_arrest_sounds.len > 0) + playsound(src.loc, pick(preparing_arrest_sounds), 50, 0) // var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.") // src.speak(arrest_message) - else mode = SECBOT_IDLE src.target = null @@ -326,7 +371,9 @@ Auto Patrol: []"}, src.frustration = 0 if(SECBOT_ARREST) // arresting - + if(src.lasercolor) + mode = SECBOT_IDLE + return if(!target || !istype(target, /mob/living/carbon)) src.anchored = 0 mode = SECBOT_IDLE @@ -360,7 +407,6 @@ Auto Patrol: []"}, if(SECBOT_PATROL) // patrol mode - patrol_step() spawn(5) if(mode == SECBOT_PATROL) @@ -378,33 +424,27 @@ Auto Patrol: []"}, // perform a single patrol step - /obj/machinery/bot/secbot/proc/patrol_step() - if(loc == patrol_target) // reached target at_patrol_target() return - else if(path.len > 0 && patrol_target) // valid path - var/turf/next = path[1] if(next == loc) path -= next return - if(istype( next, /turf/simulated)) - var/moved = step_towards(src, next) // attempt to move if(moved) // successful move blockcount = 0 path -= loc look_for_perp() + if(lasercolor) + sleep(20) else // failed to move - blockcount++ - if(blockcount > 5) // attempt 5 times before recomputing // find new path excluding blocked turf @@ -414,19 +454,14 @@ Auto Patrol: []"}, find_patrol_target() else blockcount = 0 - return - return - else // not a valid turf mode = SECBOT_IDLE return - else // no path, so calculate new one mode = SECBOT_START_PATROL - // finds a new patrol target /obj/machinery/bot/secbot/proc/find_patrol_target() send_status() @@ -442,7 +477,6 @@ Auto Patrol: []"}, find_nearest_beacon() return - // finds the nearest beacon to self // signals all beacons matching the patrol code /obj/machinery/bot/secbot/proc/find_nearest_beacon() @@ -460,12 +494,10 @@ Auto Patrol: []"}, speak("Disengaging patrol mode.") send_status() - /obj/machinery/bot/secbot/proc/at_patrol_target() find_patrol_target() return - // sets the current destination // signals all beacons matching the patrol code // beacons will return a signal giving their locations @@ -477,7 +509,6 @@ Auto Patrol: []"}, // receive a radio signal // used for beacon reception - /obj/machinery/bot/secbot/receive_signal(datum/signal/signal) //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])") if(!on) @@ -587,24 +618,26 @@ Auto Patrol: []"}, ) post_signal_multiple(control_freq, kv) - - // calculates a path to the current destination // given an optional turf to avoid /obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null) src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) - if (!path) path = list() + if(!path) path = list() // look for a criminal in view of the bot - /obj/machinery/bot/secbot/proc/look_for_perp() + if(src.disabled) + return src.anchored = 0 - for (var/mob/living/M in view(7,src)) //Let's find us a criminal + for(var/mob/living/M in view(search_range,src)) //Let's find us a criminal if(istype(M, /mob/living/carbon)) var/mob/living/carbon/C = M if((C.stat) || (C.handcuffed)) continue + if((src.lasercolor) && (C.lying)) + continue//Does not shoot at people lying down when in lasertag mode, because it's just annoying, and they can fire once they get up. + if((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue @@ -624,7 +657,8 @@ Auto Patrol: []"}, src.target = M src.oldtarget_name = M.name src.speak("Level [src.threatlevel] infraction alert!") - playsound(src.loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) + if(!src.lasercolor && threat_found_sounds.len > 0) + playsound(src.loc, pick(threat_found_sounds), 50, 0) src.visible_message("[src] points at [M.name]!") mode = SECBOT_HUNT spawn(0) @@ -633,7 +667,6 @@ Auto Patrol: []"}, else continue - //If the security records say to arrest them, arrest them //Or if they have weapons and aren't security, arrest them. /obj/machinery/bot/secbot/proc/assess_perp(mob/living/carbon/human/perp as mob) @@ -642,7 +675,6 @@ Auto Patrol: []"}, if(src.emagged == 2) return 10 //Everyone is a criminal! if(src.idcheck && !src.allowed(perp)) - if(istype(perp.l_hand, /obj/item/weapon/gun) || istype(perp.l_hand, /obj/item/weapon/melee)) if(!istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/redtag) \ @@ -655,24 +687,42 @@ Auto Patrol: []"}, && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/practice)) threatcount += 4 - if(istype(perp:belt, /obj/item/weapon/gun) || istype(perp:belt, /obj/item/weapon/melee)) - if(!istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/practice)) + if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee)) + if(!istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp.belt, /obj/item/weapon/gun/energy/laser/practice)) threatcount += 2 - if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) + if(istype(perp.wear_suit, /obj/item/clothing/suit/wizrobe)) threatcount += 2 if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") threatcount += 2 //Agent cards lower threatlevel. - if(perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + if(perp.wear_id && istype(perp.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) threatcount -= 2 + if(src.lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve + threatcount = 0//They will not, however shoot at people who have guns, because it gets really fucking annoying + if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) + threatcount += 4 + if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/redtag))) + threatcount += 4 + if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 2 + + if(src.lasercolor == "r") + threatcount = 0 + if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) + threatcount += 4 + if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + threatcount += 4 + if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 2 + if(src.check_records) - for (var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in data_core.general) var/perpname = perp.name if(perp.wear_id) var/obj/item/weapon/card/id/id = perp.wear_id.GetID() @@ -680,7 +730,7 @@ Auto Patrol: []"}, perpname = id.registered_name if(E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in data_core.security) if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) threatcount = 4 break @@ -688,45 +738,41 @@ Auto Patrol: []"}, return threatcount /obj/machinery/bot/secbot/Bump(M as mob|obj) //Leave no door unopened! - if((istype(M, /obj/machinery/door)) && (!isnull(src.botcard))) + if((istype(M, /obj/machinery/door)) && !isnull(src.botcard)) var/obj/machinery/door/D = M if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/poddoor)) D.open() src.frustration = 0 - else if((istype(M, /mob/living/)) && (!src.anchored)) - src.loc = M:loc - src.frustration = 0 + else if(!src.anchored) + if((istype(M, /mob/living/))) + var/mob/living/O = M + src.loc = O.loc + src.frustration = 0 + else if(istype(M, /obj/machinery/bot)) + var/obj/machinery/bot/B = M + if(B.dir != src.dir) // Avoids issues if two bots are currently patrolling in the same direction + src.loc = B.loc + src.frustration = 0 return -/* terrible -/obj/machinery/bot/secbot/Bumped(atom/movable/M as mob|obj) - spawn(0) - if(M) - var/turf/T = get_turf(src) - M:loc = T -*/ - /obj/machinery/bot/secbot/proc/speak(var/message) for(var/mob/O in hearers(src, null)) O.show_message("[src] beeps, \"[message]\"",2) return - /obj/machinery/bot/secbot/explode() - walk_to(src,0) src.visible_message("\red [src] blows apart!", 1) var/turf/Tsec = get_turf(src) - var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec) + var/obj/item/weapon/secbot_assembly/Sa = new secbot_assembly(Tsec) Sa.build_step = 1 Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") Sa.created_name = src.name new /obj/item/device/assembly/prox_sensor(Tsec) new /obj/item/weapon/melee/baton(Tsec) - if(prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) + on_explosion() var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) @@ -735,6 +781,12 @@ Auto Patrol: []"}, new /obj/effect/decal/cleanable/blood/oil(src.loc) del(src) + +/obj/machinery/bot/secbot/proc/on_explosion(var/turf/Tsec) + new /obj/item/weapon/melee/baton(Tsec) + if(prob(50)) + new /obj/item/robot_parts/l_arm(Tsec) + /obj/machinery/bot/secbot/attack_alien(var/mob/living/carbon/alien/user as mob) ..() if(!isalien(target)) @@ -804,3 +856,82 @@ Auto Patrol: []"}, if(!in_range(src, usr) && src.loc != usr) return src.created_name = t + +/obj/machinery/bot/secbot/proc/shootAt(var/mob/target) + if(lastfired && world.time - lastfired < shot_delay) + return + lastfired = world.time + var/turf/T = loc + var/atom/U = (istype(target, /atom/movable) ? target.loc : target) + if((!( U ) || !( T ))) + return + while(!( istype(U, /turf) )) + U = U.loc + if(!( istype(T, /turf) )) + return + + //if(lastfired && world.time - lastfired < 100) + // playsound(src.loc, 'ed209_shoot.ogg', 50, 0) + + if(!projectile) + if(!lasercolor) + if(src.emagged == 2) + projectile = /obj/item/projectile/beam + else + projectile = /obj/item/projectile/beam/stun + else if(lasercolor == "b") + if(src.emagged == 2) + projectile = /obj/item/projectile/beam/lastertag/omni + else + projectile = /obj/item/projectile/beam/lastertag/blue + else if(lasercolor == "r") + if(src.emagged == 2) + projectile = /obj/item/projectile/beam/lastertag/omni + else + projectile = /obj/item/projectile/beam/lastertag/red + + if(!( istype(U, /turf) )) + return + var/obj/item/projectile/A = new projectile (loc) + A.current = U + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn( 0 ) + A.process() + return + return + +/obj/machinery/bot/secbot/emp_act(severity) + if(severity==2 && prob(70)) + ..(severity-1) + else + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + spawn(10) + pulse2.delete() + var/list/mob/living/carbon/targets = new + for(var/mob/living/carbon/C in view(12,src)) + if(C.stat==2) + continue + targets += C + if(targets.len) + if(prob(50)) + var/mob/toshoot = pick(targets) + if(toshoot) + targets-=toshoot + if(prob(50) && emagged < 2) + emagged = 2 + shootAt(toshoot) + emagged = 0 + else + shootAt(toshoot) + else if(prob(50)) + if(targets.len) + var/mob/toarrest = pick(targets) + if(toarrest) + src.target = toarrest + src.mode = SECBOT_HUNT diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 1c9bec63e98..a5274598dd6 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -106,7 +106,7 @@ if(istype(W, /obj/item/stack/sheet/metal) && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head) var/obj/item/stack/sheet/metal/M = W if (M.use(1)) - var/obj/item/weapon/ed209_assembly/B = new /obj/item/weapon/ed209_assembly + var/obj/item/weapon/secbot_assembly/ed209_assembly/B = new /obj/item/weapon/secbot_assembly/ed209_assembly B.loc = get_turf(src) user << "You armed the robot frame." if (user.get_inactive_hand()==src)