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.
This commit is contained in:
PsiOmega
2014-09-04 09:12:22 +02:00
parent 7a228c9677
commit 4b4c2d11fa
4 changed files with 241 additions and 959 deletions

View File

@@ -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")

View File

@@ -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({"
<TT><B>Automatic Security Unit v2.5</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [src.open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A>" )
if(!src.locked || issilicon(user))
if(!lasercolor)
dat += text({"<BR>
Check for Weapon Authorization: []<BR>
Check Security Records: []<BR>
Operating Mode: []<BR>
Report Arrests: []<BR>
Auto Patrol: []"},
"<A href='?src=\ref[src];operation=idcheck'>[src.idcheck ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=ignorerec'>[src.check_records ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=switchmode'>[src.arrest_type ? "Detain" : "Arrest"]</A>",
"<A href='?src=\ref[src];operation=declarearrests'>[src.declare_arrests ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
else
dat += text({"<BR>
Auto Patrol: []"},
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
user << browse("<HEAD><TITLE>Securitron v2.5 controls</TITLE></HEAD>[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 << "<span class='notice'>Controls are now [src.locked ? "locked" : "unlocked"].</span>"
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='notice'>Access denied.</span>"
/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 << "<span class='warning'>You short out [src]'s target assessment circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 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 << "<span class='game say'><span class='name'>[src]</span> 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 <b>[target]</b> in <b>[location]</b>", src)
visible_message("\red <B>[src.target] has been stunned by [src]!</B>")
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 <B>[src] is trying to put handcuffs on [src.target]!</B>")
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<get_dist(src,nearest_beacon_loc))
nearest_beacon = recv
nearest_beacon_loc = signal.source.loc
return
else
return
else if(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("<b>[src]</b> 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("<span class='game say'><span class='name'>[src]</span> beeps, \"[message]\"",2)
return
/obj/machinery/bot/ed209/explode()
walk_to(src,0)
src.visible_message("\red <B>[src] blows apart!</B>", 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 << "<span class='notice'>You complete the ED-209.</span>"
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)
/obj/machinery/bot/secbot/ed209/redtag/New()
new /obj/machinery/bot/secbot/ed209(get_turf(src),null,"r")
del(src)

View File

@@ -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({"
<TT><B>Automatic Security Unit v1.3</B></TT><BR><BR>
<TT><B>Automatic Security Unit v[bot_version]</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [src.open ? "opened" : "closed"]"},
@@ -131,60 +160,67 @@ Auto Patrol: []"},
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
user << browse("<HEAD><TITLE>Securitron v1.3 controls</TITLE></HEAD>[dat]", "window=autosec")
user << browse("<HEAD><TITLE>Securitron v[bot_version] controls</TITLE></HEAD>[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 << "<span class='notice'>Controls are now [src.locked ? "locked" : "unlocked"].</span>"
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "\red Please close the access panel before locking it."
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "\red Access denied."
user << "<span class='notice'>Access denied.</span>"
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 << "<span class='warning'>You short out [src]'s target assessment circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 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("<b>[src]</b> 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("<span class='game say'><span class='name'>[src]</span> beeps, \"[message]\"",2)
return
/obj/machinery/bot/secbot/explode()
walk_to(src,0)
src.visible_message("\red <B>[src] blows apart!</B>", 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

View File

@@ -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 << "<span class='notice'>You armed the robot frame.</span>"
if (user.get_inactive_hand()==src)