#define SECBOT_WAIT_TIME 5 //number of in-game seconds to wait for someone to surrender #define SECBOT_THREAT_ARREST 4 //threat level at which we decide to arrest someone #define SECBOT_THREAT_ATTACK 8 //threat level at which was assume immediate danger and attack right away /mob/living/bot/secbot name = "Securitron" desc = "A little security robot. He looks less than thrilled." icon_state = "secbot0" maxHealth = 100 health = 100 req_one_access = list(access_security, access_forensics_lockers) botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels) patrol_speed = 2 target_speed = 3 var/idcheck = 0 // If true, arrests for having weapons without authorization. var/check_records = 0 // If true, arrests people without a record. var/check_arrest = 1 // If true, arrests people who are set to arrest. var/arrest_type = 0 // If true, doesn't handcuff. You monster. var/declare_arrests = 0 // If true, announces arrests over sechuds. var/is_ranged = 0 var/awaiting_surrender = 0 var/list/threat_found_sounds = list('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg') var/list/preparing_arrest_sounds = list('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg') //VOREStation Add - They don't like being pulled /mob/living/bot/secbot/Life() ..() if(health > 0 && on && pulledby) if(isliving(pulledby)) var/mob/living/L = pulledby UnarmedAttack(L) say("Do not interfere with active law enforcement routines!") broadcast_security_hud_message("[src] was interfered with in [get_area(src)], activating defense routines.", src) //VOREStation Add End /mob/living/bot/secbot/beepsky name = "Officer Beepsky" desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey." will_patrol = 1 /mob/living/bot/secbot/update_icons() if(on && busy) icon_state = "secbot-c" else icon_state = "secbot[on]" if(on) set_light(2, 1, "#FF6A00") else set_light(0) /mob/living/bot/secbot/attack_hand(var/mob/user) user.set_machine(src) var/list/dat = list() dat += "Automatic Security Unit

" dat += "Status: [on ? "On" : "Off"]
" dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
" dat += "Maintenance panel is [open ? "opened" : "closed"]" if(!locked || issilicon(user)) dat += "
Check for Weapon Authorization: [idcheck ? "Yes" : "No"]
" dat += "Check Security Records: [check_records ? "Yes" : "No"]
" dat += "Check Arrest Status: [check_arrest ? "Yes" : "No"]
" dat += "Operating Mode: [arrest_type ? "Detain" : "Arrest"]
" dat += "Report Arrests: [declare_arrests ? "Yes" : "No"]
" dat += "Auto Patrol: [will_patrol ? "On" : "Off"]" var/datum/browser/popup = new(user, "autosec", "Securitron controls") popup.set_content(jointext(dat,null)) popup.open() /mob/living/bot/secbot/Topic(href, href_list) if(..()) return usr.set_machine(src) add_fingerprint(usr) if((href_list["power"]) && (access_scanner.allowed(usr))) if(on) turn_off() else turn_on() return switch(href_list["operation"]) if("idcheck") idcheck = !idcheck if("ignorerec") check_records = !check_records if("ignorearr") check_arrest = !check_arrest if("switchmode") arrest_type = !arrest_type if("patrol") will_patrol = !will_patrol if("declarearrests") declare_arrests = !declare_arrests attack_hand(usr) /mob/living/bot/secbot/emag_act(var/remaining_uses, var/mob/user) . = ..() if(!emagged) if(user) user << "\The [src] buzzes and beeps." emagged = 1 patrol_speed = 3 target_speed = 4 return 1 else user << "\The [src] is already corrupt." /mob/living/bot/secbot/attackby(var/obj/item/O, var/mob/user) var/curhealth = health . = ..() if(health < curhealth) react_to_attack(user) /mob/living/bot/secbot/bullet_act(var/obj/item/projectile/P) var/curhealth = health var/mob/shooter = P.firer . = ..() //if we already have a target just ignore to avoid lots of checking if(!target && health < curhealth && shooter && (shooter in view(world.view, src))) react_to_attack(shooter) /mob/living/bot/secbot/proc/react_to_attack(mob/attacker) if(!target) playsound(src.loc, pick(threat_found_sounds), 50) broadcast_security_hud_message("[src] was attacked by a hostile [target_name(attacker)] in [get_area(src)].", src) target = attacker awaiting_surrender = INFINITY // Don't try and wait for surrender // Say "freeze!" and demand surrender /mob/living/bot/secbot/proc/demand_surrender(mob/target, var/threat) var/suspect_name = target_name(target) if(declare_arrests) broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [threat] suspect [suspect_name] in [get_area(src)].", src) say("Down on the floor, [suspect_name]! You have [SECBOT_WAIT_TIME] seconds to comply.") playsound(src.loc, pick(preparing_arrest_sounds), 50) // Register to be told when the target moves moved_event.register(target, src, /mob/living/bot/secbot/proc/target_moved) // Callback invoked if the registered target moves /mob/living/bot/secbot/proc/target_moved(atom/movable/moving_instance, atom/old_loc, atom/new_loc) if(get_dist(get_turf(src), get_turf(target)) >= 1) awaiting_surrender = INFINITY // Done waiting! moved_event.unregister(moving_instance, src) /mob/living/bot/secbot/resetTarget() ..() moved_event.unregister(target, src) awaiting_surrender = -1 walk_to(src, 0) /mob/living/bot/secbot/startPatrol() if(!locked) // Stop running away when we set you up return ..() /mob/living/bot/secbot/confirmTarget(var/atom/A) if(!..()) return 0 return (check_threat(A) >= SECBOT_THREAT_ARREST) /mob/living/bot/secbot/lookForTargets() for(var/mob/living/M in view(src)) if(M.stat == DEAD) continue if(confirmTarget(M)) var/threat = check_threat(M) target = M awaiting_surrender = -1 say("Level [threat] infraction alert!") custom_emote(1, "points at [M.name]!") return /mob/living/bot/secbot/handleAdjacentTarget() var/mob/living/carbon/human/H = target var/threat = check_threat(target) if(awaiting_surrender < SECBOT_WAIT_TIME && istype(H) && !H.lying && threat < SECBOT_THREAT_ATTACK) if(awaiting_surrender == -1) // On first tick of awaiting... demand_surrender(target, threat) ++awaiting_surrender else if(declare_arrests) broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [threat] suspect [target_name(target)] in [get_area(src)].", src) UnarmedAttack(target) /mob/living/bot/secbot/UnarmedAttack(var/mob/M, var/proximity) if(!..()) return if(!istype(M)) return if(istype(M, /mob/living/carbon)) var/mob/living/carbon/C = M var/cuff = 1 if(istype(C, /mob/living/carbon/human)) var/mob/living/carbon/human/H = C if(istype(H.back, /obj/item/weapon/rig) && istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig)) cuff = 0 if(!C.lying || C.handcuffed || arrest_type) cuff = 0 if(!cuff) C.stun_effect_act(0, 60, null) playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) do_attack_animation(C) busy = 1 update_icons() spawn(2) busy = 0 update_icons() visible_message("\The [C] was prodded by \the [src] with a stun baton!") else playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) visible_message("\The [src] is trying to put handcuffs on \the [C]!") busy = 1 if(do_mob(src, C, 60)) if(!C.handcuffed) C.handcuffed = new /obj/item/weapon/handcuffs(C) C.update_inv_handcuffed() busy = 0 else if(istype(M, /mob/living/simple_animal)) var/mob/living/simple_animal/S = M S.AdjustStunned(10) S.adjustBruteLoss(15) do_attack_animation(M) playsound(loc, "swing_hit", 50, 1, -1) busy = 1 update_icons() spawn(2) busy = 0 update_icons() visible_message("\The [M] was beaten by \the [src] with a stun baton!") /mob/living/bot/secbot/explode() visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec) Sa.build_step = 1 Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") Sa.created_name = 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) 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(Tsec) qdel(src) /mob/living/bot/secbot/proc/target_name(mob/living/T) if(ishuman(T)) var/mob/living/carbon/human/H = T return H.get_id_name("unidentified person") return "unidentified lifeform" /mob/living/bot/secbot/proc/check_threat(var/mob/living/M) if(!M || !istype(M) || M.stat == DEAD || src == M) return 0 if(emagged && !M.incapacitated()) //check incapacitated so emagged secbots don't keep attacking the same target forever return 10 return M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest) //Secbot Construction /obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob) ..() if(!issignaler(S)) ..() return if(type != /obj/item/clothing/head/helmet) //Eh, but we don't want people making secbots out of space helmets. return if(S.secured) qdel(S) var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly user.put_in_hands(A) user << "You add the signaler to the helmet." user.drop_from_inventory(src) qdel(src) else return /obj/item/weapon/secbot_assembly name = "helmet/signaler assembly" desc = "Some sort of bizarre assembly." icon = 'icons/obj/aibots.dmi' icon_state = "helmet_signaler" item_icons = list( slot_l_hand_str = 'icons/mob/items/lefthand_hats.dmi', slot_r_hand_str = 'icons/mob/items/righthand_hats.dmi', ) item_state = "helmet" var/build_step = 0 var/created_name = "Securitron" /obj/item/weapon/secbot_assembly/attackby(var/obj/item/W, var/mob/user) ..() if(istype(W, /obj/item/weapon/weldingtool) && !build_step) var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) build_step = 1 overlays += image('icons/obj/aibots.dmi', "hs_hole") user << "You weld a hole in \the [src]." else if(isprox(W) && (build_step == 1)) user.drop_item() build_step = 2 user << "You add \the [W] to [src]." overlays += image('icons/obj/aibots.dmi', "hs_eye") name = "helmet/signaler/prox sensor assembly" qdel(W) else if((istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm) || (istype(W, /obj/item/organ/external/arm) && ((W.name == "robotic right arm") || (W.name == "robotic left arm")))) && build_step == 2) user.drop_item() build_step = 3 user << "You add \the [W] to [src]." name = "helmet/signaler/prox sensor/robot arm assembly" overlays += image('icons/obj/aibots.dmi', "hs_arm") qdel(W) else if(istype(W, /obj/item/weapon/melee/baton) && build_step == 3) user.drop_item() user << "You complete the Securitron! Beep boop." var/mob/living/bot/secbot/S = new /mob/living/bot/secbot(get_turf(src)) S.name = created_name qdel(W) qdel(src) else if(istype(W, /obj/item/weapon/pen)) var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && loc != usr) return created_name = t