Files
2020-02-19 19:48:29 -08:00

1114 lines
31 KiB
Plaintext

/obj/machinery/bot/secbot
name = "Securitron"
#ifdef HALLOWEEN
desc = "A little security robot, apparently carved out of a pumpkin. He looks...spooky?"
icon = 'icons/misc/halloween.dmi'
#else
desc = "A little security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
#endif
icon_state = "secbot0"
layer = 5.0 //TODO LAYER
density = 0
anchored = 0
luminosity = 2
// weight = 1.0E7
req_access = list(access_security)
var/weapon_access = access_carrypermit
var/obj/item/baton/secbot/our_baton // Our baton
on = 1
locked = 1 //Behavior Controls lock
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
emagged = 0 //Emagged Secbots view everyone as a criminal
health = 25
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/report_arrests = 0 //If true, report arrests over PDA messages.
var/botcard_access = "Head of Security" //Job access for doors.
var/hat = null //Add an overlay from aibots.dmi with this state. hats.
var/our_baton_type = /obj/item/baton/secbot
var/loot_baton_type = /obj/item/baton
var/stun_type = "stun"
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 = null // list of path turfs
var/moving = 0 //Are we currently ON THE MOVE?
var/current_movepath = 0
var/datum/secbot_mover/mover = null
var/arrest_move_delay = 2.5
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
disposing()
radio_controller.remove_object(src, "1149")
..()
/obj/machinery/bot/secbot/autopatrol
auto_patrol = 1
/obj/machinery/bot/secbot/beepsky
name = "Officer Beepsky"
desc = "It's Officer Beepsky! He's a loose cannon but he gets the job done."
idcheck = 1
auto_patrol = 1
report_arrests = 1
hat = "nt"
/obj/machinery/bot/secbot/warden
name = "Warden Jack"
desc = "The mechanical guardian of the brig."
auto_patrol = 1
beacon_freq = 1444
hat = "helm"
/obj/machinery/bot/secbot/commissar
name = "Commissar Beepevich"
desc = "Nobody gets in his way and lives to tell about it."
health = 40000
hat = "hos"
/obj/machinery/bot/secbot/formal
name = "Lord Beepingshire"
desc = "The most distinguished of security robots."
hat = "that"
/obj/machinery/bot/secbot/haunted
name = "Beep-o-Lantern"
desc = "A little security robot, apparently carved out of a pumpkin. He looks...spooky?"
icon = 'icons/misc/halloween.dmi'
/obj/machinery/bot/secbot/brute
name = "Komisarz Beepinarska"
desc = "This little security robot seems to have a particularly large chip on its... shoulder? ...head?"
our_baton_type = /obj/item/baton/classic
loot_baton_type = /obj/item/baton/classic
stun_type = "harm_classic"
emagged = 2
control_freq = 0
demag()
//Nope
return
/obj/machinery/bot/secbot/stamina_test
name = "test secbot"
desc = "stamina test"
our_baton_type = /obj/item/baton/stamina
loot_baton_type = /obj/item/baton/stamina
/obj/item/secbot_assembly
name = "helmet/signaler assembly"
desc = "Some sort of bizarre assembly."
icon = 'icons/obj/aibots.dmi'
icon_state = "helmet_signaler"
item_state = "helmet"
var/build_step = 0
var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess
var/beacon_freq = 1445 //If it's running on another beacon circuit I guess
var/hat = null
/obj/machinery/bot/secbot
New()
..()
src.icon_state = "secbot[src.on]"
if (!src.our_baton || !istype(src.our_baton))
src.our_baton = new our_baton_type(src)
add_simple_light("secbot", list(255, 255, 255, 0.4 * 255))
SPAWN_DBG(5)
src.botcard = new /obj/item/card/id(src)
src.botcard.access = get_access(src.botcard_access)
if(radio_controller)
radio_controller.add_object(src, "[control_freq]")
radio_controller.add_object(src, "[beacon_freq]")
if(src.hat)
src.overlays += image('icons/obj/aibots.dmi', "hat-[src.hat]")
examine()
set src in view()
..()
if (src.health < initial(health))
if (src.health > 15)
boutput(usr, text("<span style=\"color:red\">[src]'s parts look loose.</span>"))
else
boutput(usr, text("<span style=\"color:red\"><B>[src]'s parts look very loose!</B></span>"))
return
attack_hand(mob/user as mob, params)
var/dat
dat += {"
<TT><B>Automatic Security Unit v2.0</B></TT><BR><BR>
Status: <A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A><BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]"}
if(!src.locked)
dat += {"<hr>
Check for Weapon Authorization: <A href='?src=\ref[src];operation=idcheck'>[src.idcheck ? "Yes" : "No"]</A><BR>
Check Security Records: <A href='?src=\ref[src];operation=ignorerec'>[src.check_records ? "Yes" : "No"]</A><BR>
Operating Mode: <A href='?src=\ref[src];operation=switchmode'>[src.arrest_type ? "Detain" : "Arrest"]</A><BR>
Auto Patrol: <A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A><BR>
Report Arrests: <A href='?src=\ref[src];operation=report'>[report_arrests ? "On" : "Off"]</A>"}
if (user.client.tooltipHolder)
user.client.tooltipHolder.showClickTip(src, list(
"params" = params,
"title" = "Securitron v2.0 controls",
"content" = dat,
))
return
Topic(href, href_list)
if(..())
return
usr.machine = src
src.add_fingerprint(usr)
if ((href_list["power"]) && (!src.locked || src.allowed(usr)))
src.on = !src.on
if (src.on)
add_simple_light("secbot", list(255, 255, 255, 0.4 * 255))
else
remove_simple_light("secbot")
src.target = null
src.oldtarget_name = null
src.anchored = 0
src.mode = SECBOT_IDLE
walk_to(src,0)
src.icon_state = "secbot[src.on][(src.on && src.emagged == 2) ? "-spaz" : null]"
src.updateUsrDialog()
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("report")
report_arrests = !src.report_arrests
updateUsrDialog()
attack_ai(mob/user as mob)
if (src.on && src.emagged)
boutput(user, "<span style=\"color:red\">[src] refuses your authority!</span>")
return
src.on = !src.on
src.target = null
src.oldtarget_name = null
mode = SECBOT_IDLE
src.anchored = 0
src.icon_state = "secbot[src.on][(src.on && src.emagged == 2) ? "-spaz" : null]"
walk_to(src,0)
emag_act(var/mob/user, var/obj/item/card/emag/E)
if (src.emagged < 2)
if (emagged)
if (user)
boutput(user, "<span style=\"color:red\">You short out [src]'s system clock inhibition circuis.</span>")
src.overlays.len = 0
else if (user)
boutput(user, "<span style=\"color:red\">You short out [src]'s target assessment circuits.</span>")
SPAWN_DBG(0)
for(var/mob/O in hearers(src, null))
O.show_message("<span style=\"color:red\"><B>[src] buzzes oddly!</B></span>", 1)
src.anchored = 0
src.emagged++
src.on = 1
src.icon_state = "secbot[src.on][(src.on && src.emagged == 2) ? "-spaz" : null]"
mode = SECBOT_IDLE
src.target = null
if(user)
src.oldtarget_name = user.name
src.last_found = world.time
logTheThing("station", user, null, "emagged a [src] at [log_loc(src)].")
return 1
return 0
demag(var/mob/user)
if (!src.emagged)
return 0
if (user)
user.show_text("You repair [src]'s damaged electronics. Thank God.", "blue")
src.emagged = 0
mode = SECBOT_IDLE
src.target = null
src.anchored = 0
src.icon_state = "secbot0"
return 1
emp_act()
..()
if(!src.emagged && prob(75))
src.emagged = 1
src.visible_message("<span style=\"color:red\"><B>[src] buzzes oddly!</B></span>")
src.on = 1
else
src.explode()
return
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/device/pda2) && W:ID_card)
W = W:ID_card
if (istype(W, /obj/item/card/id))
if (src.allowed(user))
src.locked = !src.locked
boutput(user, "Controls are now [src.locked ? "locked." : "unlocked."]")
src.updateUsrDialog()
else
boutput(user, "<span style=\"color:red\">Access denied.</span>")
else if (isscrewingtool(W))
if (src.health < initial(health))
src.health = initial(health)
src.visible_message("<span style=\"color:red\">[user] repairs [src]!</span>", "<span style=\"color:red\">You repair [src].</span>")
else
switch(W.damtype)
if("fire")
src.health -= W.force * 0.75
if("brute")
src.health -= W.force * 0.5
else
if (src.health <= 0)
src.explode()
else if (W.force && (!iscarbon(src.target) || (src.mode != SECBOT_HUNT)))
src.target = user
src.mode = SECBOT_HUNT
..()
proc/navigate_to(atom/the_target,var/move_delay=3,var/adjacent=0)
if(src.moving) return 1
src.moving = 1
src.frustration = 0
if(src.mover)
src.mover.master = null
src.mover = null
current_movepath = world.time
src.mover = new /datum/secbot_mover(src)
// drsingh for cannot modify null.delay
if (!isnull(src.mover))
src.mover.master_move(the_target,current_movepath,adjacent)
// drsingh again for the same thing further down in a moment.
// Because master_move can delete the mover
if (!isnull(src.mover))
src.mover.delay = max(min(move_delay,5),2)
return 0
process()
if (!src.on)
return
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 can't reach perp for long enough, go idle
if (src.frustration >= 8)
// for(var/mob/O in hearers(src, null))
// boutput(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
//qdel(src.mover)
if (src.mover)
src.mover.master = null
src.mover = null
src.moving = 0
//walk_to(src,0)
if (target) // make sure target exists
if (get_dist(src, src.target) <= 1) // if right next to perp
src.icon_state = "secbot-c[src.emagged == 2 ? "-spaz" : null]"
var/mob/living/carbon/M = src.target
var/maxstuns = 4
var/stuncount = (src.emagged == 2) ? rand(5,10) : 1
while (stuncount > 0 && src.target)
// No need for unnecessary hassle, just make it ignore charges entirely for the time being.
if (src.our_baton && istype(src.our_baton))
if (src.our_baton.uses_electricity == 0)
src.our_baton.uses_electricity = 1
if (src.our_baton.uses_charges != 0)
src.our_baton.uses_charges = 0
else
src.our_baton = new our_baton_type(src)
stuncount--
src.our_baton.do_stun(src, M, src.stun_type, 2)
if (!stuncount && maxstuns-- <= 0)
target = null
if (stuncount > 0)
sleep(3)
SPAWN_DBG(2 DECI SECONDS)
src.icon_state = "secbot[src.on][(src.on && src.emagged == 2) ? "-spaz" : null]"
if (src.target.getStatusDuration("weakened"))
mode = SECBOT_PREP_ARREST
src.anchored = 1
src.target_lastloc = M.loc
moving = 0
//qdel(src.mover)
if (src.mover)
src.mover.master = null
src.mover = null
src.frustration = 0
return
if(!path || !path.len || (4 < get_dist(src.target,path[path.len])) )
moving = 0
if (src.mover)
src.mover.master = null
src.mover = null
//current_movepath = "HEH" //Stop any current movement.
navigate_to(src.target,arrest_move_delay)
else // not next to perp
if(!(src.target in view(7,src)) || !moving)
//qdel(src.mover)
if (src.mover)
src.mover.master = null
src.mover = null
src.moving = 0
navigate_to(src.target,(src.emagged == 2) ? (arrest_move_delay/2) : arrest_move_delay)
return
/*
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
// see if he got away
if ((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:getStatusDuration("weakened") < 20))
src.anchored = 0
mode = SECBOT_HUNT
if (!src.mover)
src.moving = 0
navigate_to(src.target)
return
/*
if (ishuman(src.target))
var/mob/living/carbon/human/H = src.target
if(isabomination(H))
return
*/
if (!src.target.handcuffed && !src.arrest_type)
playsound(src.loc, "sound/weapons/handcuffs.ogg", 30, 1, -2)
mode = SECBOT_ARREST
src.visible_message("<span style=\"color:red\"><B>[src] is trying to put handcuffs on [src.target]!</B></span>")
SPAWN_DBG(6 SECONDS)
if (get_dist(src, src.target) <= 1)
if (!src.target || src.target.handcuffed)
return
var/uncuffable = 0
if (ishuman(src.target))
var/mob/living/carbon/human/H = src.target
//if(H.bioHolder.HasEffect("lost_left_arm") || H.bioHolder.HasEffect("lost_right_arm"))
if(!H.limbs.l_arm || !H.limbs.r_arm)
uncuffable = 1
if (!isturf(src.target.loc))
uncuffable = 1
if(iscarbon(src.target) && !uncuffable)
src.target.handcuffed = new /obj/item/handcuffs(src.target)
src.target.setStatus("handcuffed", duration = null)
var/last_target = target
mode = SECBOT_IDLE
src.target = null
src.anchored = 0
src.last_found = world.time
src.frustration = 0
if(!uncuffable) 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, 0, 1)
// 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)
if (src.report_arrests && !uncuffable)
var/bot_location = get_area(src)
//////PDA NOTIFY/////
var/datum/radio_frequency/transmit_connection = radio_controller.return_frequency("1149")
var/datum/signal/pdaSignal = get_free_signal()
pdaSignal.data = list("address_1"="00000000", "command"="text_message", "sender_name"="SECURITY-MAILBOT", "group"="security", "sender"="00000000", "message"="Notification: [last_target] detained by [src] in [bot_location].")
pdaSignal.transmission_method = TRANSMISSION_RADIO
if(transmit_connection != null)
transmit_connection.post_signal(src, pdaSignal)
if(SECBOT_ARREST) // arresting
if (src.frustration >= 8)
src.target = null
src.last_found = world.time
src.frustration = 0
src.mode = 0
//qdel(src.mover)
if (src.mover)
src.mover.master = null
src.mover = null
src.moving = 0
if(src.target)
if (src.target.handcuffed)
src.anchored = 0
mode = SECBOT_IDLE
return
else if (!src.target.getStatusDuration("weakened"))
src.anchored = 0
mode = SECBOT_HUNT
if (get_dist(src, src.target) > 1 && (!src.mover || !src.moving))
//qdel(src.mover)
if (src.mover)
src.mover.master = null
src.mover = null
src.moving = 0
navigate_to(src.target)
return
else
mode = SECBOT_IDLE
return
if(SECBOT_START_PATROL) // start a patrol
if(path && path.len && patrol_target) // have a valid path, so just resume
mode = SECBOT_PATROL
return
else if(patrol_target) // has patrol target already
SPAWN_DBG(0)
calc_path() // so just find a route to it
if(!path || !path.len)
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_DBG(5 DECI SECONDS)
if(mode == SECBOT_PATROL)
patrol_step()
if(SECBOT_SUMMON) // summoned to PDA
patrol_step()
SPAWN_DBG(4 DECI SECONDS)
if(mode == SECBOT_SUMMON)
patrol_step()
sleep(4)
patrol_step()
return
// perform a single patrol step
proc/patrol_step()
if(loc == patrol_target) // reached target
at_patrol_target()
return
else if (path && path.len && 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()
else // failed to move
blockcount++
if(blockcount > 5) // attempt 5 times before recomputing
// find new path excluding blocked turf
SPAWN_DBG(2 DECI SECONDS)
calc_path(next)
if (!path)
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
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 0
else
return 1
if(next_destination)
set_destination(next_destination)
return 1
else
find_nearest_beacon()
return 0
// finds the nearest beacon to self
// signals all beacons matching the patrol code
proc/find_nearest_beacon()
nearest_beacon = null
new_destination = "__nearest__"
post_signal(beacon_freq, "findbeacon", "patrol")
awaiting_beacon = 1
SPAWN_DBG(1 SECOND)
awaiting_beacon = 0
if(nearest_beacon)
set_destination(nearest_beacon)
else
auto_patrol = 0
mode = SECBOT_IDLE
//speak("Disengaging patrol mode.")
send_status()
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
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
receive_signal(datum/signal/signal)
if(!on)
return
/*
boutput(world, "rec signal: [signal.source]")
for(var/x in signal.data)
boutput(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
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
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 = get_free_signal()
signal.source = src
signal.transmission_method = 1
for(var/key in keyval)
signal.data[key] = keyval[key]
//boutput(world, "sent [key],[keyval[key]] on [freq]")
frequency.post_signal(src, signal)
// signals bot status etc. to controller
proc/send_status()
var/list/kv = new()
kv["type"] = "secbot"
kv["name"] = name
kv["loca"] = get_area(src)
kv["mode"] = mode
post_signal_multiple(control_freq, kv)
// calculates a path to the current destination
// given an optional turf to avoid
proc/calc_path(var/turf/avoid = null)
if (!isturf(src.loc))
return
src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 120, botcard, avoid)
// look for a criminal in view of the bot
proc/look_for_perp()
src.anchored = 0
for (var/mob/living/carbon/C in view(7,src)) //Let's find us a criminal
if ((C.stat) || (C.handcuffed))
continue
if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100))
continue
if (ishuman(C))
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!")
playsound(src.loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0)
src.visible_message("<b>[src]</b> points at [C.name]!")
mode = SECBOT_HUNT
SPAWN_DBG(0)
src.frustration = 0
if(!src.moving || !src.mover)
src.moving = 0
src.navigate_to(src.target)
process() // ensure bot quickly responds to a perp
// sorry for making a mess here i will clean it up later i promise xoxoxo -drsingh
SPAWN_DBG(0)
var/weeoo = 10
playsound(src.loc, "sound/machines/siren_police.ogg", 50, 1)
while (weeoo)
add_simple_light("secbot", list(255 * 0.9, 255 * 0.1, 255 * 0.1, 0.8 * 255))
sleep(3)
add_simple_light("secbot", list(255 * 0.1, 255 * 0.1, 255 * 0.9, 0.8 * 255))
sleep(3)
weeoo--
//old one in case we still want that
/*
light.set_brightness(0.8)
while (weeoo)
light.set_color(0.9, 0.1, 0.1)
sleep(3)
light.set_color(0.1, 0.1, 0.9)
sleep(3)
weeoo--
light.set_brightness(0.4)
light.set_color(1, 1, 1)
*/
add_simple_light("secbot", list(255, 255, 255, 0.4 * 255))
break
else
continue
//If the security records say to arrest them, arrest them
//Or if they have weapons and aren't security, arrest them.
proc/assess_perp(mob/living/carbon/human/perp as mob)
var/threatcount = 0
if(src.emagged) return 10 //Everyone is a criminal!
if((src.idcheck) || (isnull(perp:wear_id)) || (istype(perp:wear_id, /obj/item/card/id/syndicate)))
var/obj/item/card/id/perp_id = perp.equipped()
if (!istype(perp_id))
perp_id = perp.wear_id
if(perp_id && (weapon_access in perp_id.access)) //Corrupt cops cannot exist, beep boop
return 0
/*
if(istype(perp.l_hand, /obj/item/gun) || istype(perp.l_hand, /obj/item/baton) || istype(perp.l_hand, /obj/item/sword))
threatcount += 4
if(istype(perp.r_hand, /obj/item/gun) || istype(perp.r_hand, /obj/item/baton) || istype(perp.r_hand, /obj/item/sword))
threatcount += 4
if(istype(perp:belt, /obj/item/gun) || istype(perp:belt, /obj/item/baton) || istype(perp:belt, /obj/item/sword))
threatcount += 2
if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe))
threatcount += 4
*/
if (istype(perp.l_hand))
threatcount += perp.l_hand.contraband
if (istype(perp.r_hand))
threatcount += perp.r_hand.contraband
if (istype(perp:belt))
threatcount += perp:belt.contraband * 0.5
if (istype(perp:wear_suit))
threatcount += perp:wear_suit.contraband
if(istype(perp.mutantrace, /datum/mutantrace/abomination))
threatcount += 5
//Agent cards lower threatlevel when normal idchecking is off.
if((istype(perp:wear_id, /obj/item/card/id/syndicate)) && src.idcheck)
threatcount -= 2
if (src.check_records)
for (var/datum/data/record/E in data_core.general)
var/perpname = perp.name
if (perp:wear_id && perp:wear_id:registered)
perpname = perp.wear_id:registered
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
return threatcount
Bumped(M as mob|obj)
SPAWN_DBG(0)
var/turf/T = get_turf(src)
M:set_loc(T)
bullet_act(var/obj/projectile/P)
var/damage = 0
damage = round(((P.power/4)*P.proj_data.ks_ratio), 1.0)
if(P.proj_data.damage_type == D_KINETIC)
src.health -= damage
else if(P.proj_data.damage_type == D_PIERCING)
src.health -= (damage*2)
else if(P.proj_data.damage_type == D_ENERGY)
src.health -= damage
if (src.health <= 0)
src.explode()
return
if (ismob(P.shooter))
var/mob/living/M = P.shooter
if (P && iscarbon(M) && (!iscarbon(src.target) || (src.mode != SECBOT_HUNT)))
src.target = M
src.mode = SECBOT_HUNT
return
speak(var/message)
if (src.emagged == 2)
message = capitalize(ckeyEx(message))
..(message)
//Generally we want to explode() instead of just deleting the securitron.
ex_act(severity)
switch(severity)
if(1.0)
src.explode()
return
if(2.0)
src.health -= 15
if (src.health <= 0)
src.explode()
return
return
meteorhit()
src.explode()
return
blob_act(var/power)
if(prob(25 * power / 20))
src.explode()
return
explode()
walk_to(src,0)
for(var/mob/O in hearers(src, null))
O.show_message("<span style=\"color:red\"><B>[src] blows apart!</B></span>", 1)
var/turf/Tsec = get_turf(src)
var/obj/item/secbot_assembly/Sa = new /obj/item/secbot_assembly(Tsec)
Sa.build_step = 1
Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole")
Sa.created_name = src.name
Sa.beacon_freq = src.beacon_freq
Sa.hat = src.hat
new /obj/item/device/prox_sensor(Tsec)
// Not charged when dropped (ran on Beepsky's internal battery or whatever).
var/obj/item/baton/B = new loot_baton_type(Tsec)
B.status = 0
B.process_charges(-INFINITY)
if (prob(50))
new /obj/item/parts/robot_parts/arm/left(Tsec)
var/datum/effects/system/spark_spread/s = unpool(/datum/effects/system/spark_spread)
s.set_up(3, 1, src)
s.start()
qdel(src)
//movement control datum. Why yes, this is copied from guardbot.dm
/datum/secbot_mover
var/obj/machinery/bot/secbot/master = null
var/delay = 3
New(var/newmaster)
..()
if(istype(newmaster, /obj/machinery/bot/secbot))
src.master = newmaster
return
proc/master_move(var/atom/the_target as obj|mob, var/current_movepath,var/adjacent=0)
if(!master || !isturf(master.loc))
src.master = null
//dispose()
return
var/target_turf = null
if(isturf(the_target))
target_turf = the_target
else
target_turf = get_turf(the_target)
SPAWN_DBG(0)
if (!master)
return
var/compare_movepath = current_movepath
master.path = AStar(get_turf(master), target_turf, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 60, master.botcard)
if(adjacent && master.path && master.path.len) //Make sure to check it isn't null!!
master.path.len-- //Only go UP to the target, not the same tile.
if(!master.path || !master.path.len || !the_target)
//if(master.task)
// master.task.task_input("path_error")
master.frustration = INFINITY
master.mover = null
master = null
//dispose()
return 1
while(master && master.path && master.path.len && target_turf && master.moving)
// boutput(world, "[compare_movepath] : [current_movepath]")
if(compare_movepath != current_movepath) break
if(!master.on)
master.frustration = 0
break
step_to(master, master.path[1])
if(master.loc != master.path[1])
master.frustration++
sleep(delay)
continue
master.path -= master.path[1]
sleep(delay)
if (master)
master.moving = 0
master.mover = null
master = null
//dispose()
return
return
//Secbot Construction
/obj/item/clothing/head/helmet/hardhat/security/attackby(var/obj/item/device/radio/signaler/S, mob/user as mob)
if (!istype(S, /obj/item/device/radio/signaler))
..()
return
if (!S.b_stat)
return
else
var/obj/item/secbot_assembly/A = new /obj/item/secbot_assembly
user.u_equip(S)
user.put_in_hand_or_drop(A)
boutput(user, "You add the signaler to the helmet.")
qdel(S)
qdel(src)
/obj/item/secbot_assembly/attackby(obj/item/W as obj, mob/user as mob)
if ((istype(W, /obj/item/weldingtool)) && (!src.build_step))
if ((W:welding) && (W:get_fuel() >= 1))
W:use_fuel(1)
src.build_step++
src.overlays += image('icons/obj/aibots.dmi', "hs_hole")
boutput(user, "You weld a hole in [src]!")
else if ((istype(W, /obj/item/device/prox_sensor)) && (src.build_step == 1))
src.build_step++
boutput(user, "You add the prox sensor to [src]!")
src.overlays += image('icons/obj/aibots.dmi', "hs_eye")
src.name = "helmet/signaler/prox sensor assembly"
qdel(W)
else if (istype(W, /obj/item/parts/robot_parts/arm/) && src.build_step == 2)
src.build_step++
boutput(user, "You add the robot arm to [src]!")
src.name = "helmet/signaler/prox sensor/robot arm assembly"
src.overlays += image('icons/obj/aibots.dmi', "hs_arm")
qdel(W)
else if ((istype(W, /obj/item/baton)) && (src.build_step >= 3))
src.build_step++
boutput(user, "You complete the Securitron! Beep boop.")
var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot(get_turf(src))
S.beacon_freq = src.beacon_freq
S.hat = src.hat
S.name = src.created_name
qdel(W)
qdel(src)
else if (istype(W, /obj/item/pen))
var/t = input(user, "Enter new robot name", src.name, src.created_name) as text
t = strip_html(replacetext(t, "'",""))
t = copytext(t, 1, 45)
if (!t)
return
if (!in_range(src, usr) && src.loc != usr)
return
src.created_name = t