mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
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:
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user