/////////////////////////////
// Deployer Code //
/////////////////////////////
/obj/item/turret_deployer
name = "NAS-T Deployer"
desc = "A Nuclear Agent Sentry Turret Deployer. Use it in your hand to deploy."
icon = 'icons/obj/syndieturret.dmi'
icon_state = "st_deployer"
force = 3.0
throwforce = 10.0
throw_speed = 1
throw_range = 5
w_class = 3
health = 100
//var/emagged = 0 removing all emag stuff because it's a bad idea in retrospect
var/damage_words = "fully operational!"
var/icon_tag = "st"
var/quick_deploy_fuel = 2
New()
..()
icon_state = "[src.icon_tag]_deployer"
get_desc(dist)
. = "
It looks [damage_words]"
attack_self(mob/user as mob)
user.show_message("You assemble the turret parts.")
src.loc = get_turf(user)
src.spawn_turret(user.dir)
user.u_equip(src)
src.loc = get_turf(user)
qdel(src)
proc/spawn_turret(var/direct)
var/obj/deployable_turret/turret = new /obj/deployable_turret(src.loc,direction=direct)
turret.health = src.health // NO FREE REPAIRS, ASSHOLES
//turret.emagged = src.emagged
turret.damage_words = src.damage_words
turret.quick_deploy_fuel = src.quick_deploy_fuel
return turret
/*
emag_act(var/user, var/emag)
if(src.emagged)
return
src.emagged = 1
boutput(user,"You short out the safeties on the turret.")
src.damage_words += "
Its safety indicator is off!"
*/
throw_at(atom/target, range, speed, list/params, turf/thrown_from)
..(target,range,speed)
if(src.quick_deploy_fuel > 0)
var/turf/thrown_to = get_turf(src)
var/spawn_direction = get_dir(thrown_to,thrown_from)
var/obj/deployable_turret/turret = src.spawn_turret(spawn_direction)
turret.set_angle(get_angle(thrown_from,thrown_to))
turret.quick_deploy()
qdel(src)
/////////////////////////////
// Turret Code //
/////////////////////////////
/obj/deployable_turret
name = "NAS-T"
desc = "A Nuclear Agent Sentry Turret."
icon = 'icons/obj/syndieturret.dmi'
icon_state = "st_off"
anchored = 0
density = 1
var/health = 250
var/max_health = 250
var/list/mob/living/target_list = list()
var/mob/living/target = null
var/wait_time = 20 //wait if it can't find a target
var/range = 7 // tiles
var/internal_angle = 0 // used for the matrix transforms
var/external_angle = 180 // used for determining target validity
var/projectile_type = /datum/projectile/bullet/ak47
var/datum/projectile/current_projectile = new/datum/projectile/bullet/ak47
var/burst_size = 3 // number of shots to fire. Keep in mind the bullet's shot_count
var/fire_rate = 3 // rate of fire in shots per second
var/angle_arc_size = 45
var/active = 0 // are we gonna shoot some peeps?
//var/emagged = 0
var/damage_words = "fully operational!"
var/waiting = 0 // tracks whether or not the turret is waiting
var/shooting = 0 // tracks whether we're currently in the process of shooting someone
var/icon_tag = "st"
var/quick_deploy_fuel = 2 // number of quick deploys the turret has left
New(var/direction)
..()
src.dir = direction
src.set_initial_angle()
src.icon_state = "[src.icon_tag]_base"
src.appearance_flags |= RESET_TRANSFORM
src.underlays += src
src.appearance_flags &= ~RESET_TRANSFORM
src.icon_state = "[src.icon_tag]_off"
src.appearance_flags |= PIXEL_SCALE
var/matrix/M = matrix()
src.transform = M.Turn(src.external_angle)
if (!(src in processing_items))
processing_items.Add(src)
disposing()
processing_items.Remove(src)
..()
get_desc(dist)
. = "
It looks [damage_words]"
proc/set_initial_angle()
switch(src.dir)
if(NORTH)
src.external_angle = (0)
if(NORTHEAST)
src.external_angle = (45)
if(EAST)
src.external_angle = (90)
if(SOUTHEAST)
src.external_angle = (135)
if(SOUTH)
src.external_angle = (180)
if(SOUTHWEST)
src.external_angle = (225)
if(WEST)
src.external_angle = (270)
if(NORTHWEST)
src.external_angle = (315)
else
src.external_angle = (180) // how did you get here?
proc/process() //main turret processing loop
if(src.waiting || src.shooting)
return
if(src.active)
if(!src.target)
if(!src.seek_target())
src.waiting = 1
spawn(src.wait_time)
src.waiting = 0
return
if(!src.target_valid(src.target))
src.icon_state = "[src.icon_tag]_idle"
src.target = null
return
else
src.shooting = 1
src.icon_state = "[src.icon_tag]_fire"
spawn()
for (var/i = 0, iYou need more welding fuel to complete this task.")
return
if(src.anchored)
W:use_fuel(1)
user.show_message("You start to unweld the turret from the floor.")
playsound(src.loc, "sound/items/Welder2.ogg", 50, 1)
sleep(30)
if ((user.loc == T && user.equipped() == W))
user.show_message("You unweld the turret from the floor.")
W:eyecheck(user)
src.anchored = 0
else if((istype(user, /mob/living/silicon/robot) && (user.loc == T)))
user.show_message("You unweld the turret the floor.")
src.anchored = 0
else
W:use_fuel(1)
user.show_message("You start to weld the turret to the floor.")
playsound(src.loc, "sound/items/Welder2.ogg", 50, 1)
sleep(30)
if ((user.loc == T && user.equipped() == W))
user.show_message("You weld the turret to the floor.")
W:eyecheck(user)
src.anchored = 1
else if((istype(user, /mob/living/silicon/robot) && (user.loc == T)))
user.show_message("You weld the turret to the floor.")
src.anchored = 1
else if (istype(W, /obj/item/weldingtool) && W:welding && (src.active))
var/turf/T = user.loc
if (src.health >= max_health)
user.show_message("The turret is already fully repaired!.")
return
if (W:get_fuel() < 1)
user.show_message("You need more welding fuel to complete this task.")
return
W:use_fuel(1)
user.show_message("You start to repair the turret.")
playsound(src.loc, "sound/items/Welder2.ogg", 50, 1)
sleep(20)
if ((user.loc == T && user.equipped() == W))
W:eyecheck(user)
user.show_message("You repair some of the damage on the turret.")
src.health = min(src.max_health, (src.health + 10))
src.check_health()
else if (istype(W, /obj/item/wrench))
if(src.anchored)
user.show_message("Click where you want to aim the turret!")
var/datum/targetable/deployable_turret_aim/A = new()
user.targeting_spell = A
user.update_cursor()
A.my_turret = src
A.user_turf = get_turf(user)
playsound(src.loc, "sound/items/Ratchet.ogg", 50, 1)
else
var/turf/T = user.loc
user.show_message("You begin to disassemble the turret.")
playsound(src.loc, "sound/items/Ratchet.ogg", 50, 1)
sleep(20)
if ((user.loc == T && user.equipped() == W))
user.show_message("You disassemble the turret.")
src.active = 0
src.shooting = 0
src.waiting = 0
src.target = null
src.spawn_deployer()
qdel(src)
/*
else if (istype(W, /obj/item/card/emag))
return
*/
else if (istype(W, /obj/item/screwdriver))
if(!src.anchored)
user.show_message("The turret is too unstable to fire! Secure it to the ground with a welding tool first!")
return
var/turf/T = user.loc
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
sleep(10)
if ((user.loc == T && user.equipped() == W))
if(src.active)
user.show_message("You power off the turret.")
src.icon_state = "[src.icon_tag]_off"
src.active = 0
src.shooting = 0
src.waiting = 0
src.target = null
else
user.show_message("You power on the turret.")
src.active = 1
src.icon_state = "[src.icon_tag]_idle"
else if((istype(user, /mob/living/silicon/robot) && (user.loc == T)))
if(src.active)
user.show_message("You power off the turret.")
src.icon_state = "[src.icon_tag]_off"
src.active = 0
src.shooting = 0
src.waiting = 0
src.target = null
else
user.show_message("You power on the turret.")
src.active = 1
src.icon_state = "[src.icon_tag]_idle"
else
src.health = src.health - W.force
src.check_health()
..()
return
proc/quick_deploy()
if(!(src.quick_deploy_fuel > 0))
return
src.quick_deploy_fuel--
src.visible_message("[src]'s quick deploy system engages, automatically securing it!")
playsound(src.loc, "sound/items/Welder2.ogg", 50, 1)
src.anchored = 1
src.active = 1
src.icon_state = "[src.icon_tag]_idle"
bullet_act(var/obj/projectile/P)
if(istype(P.proj_data,/datum/projectile/energy_bolt)) // fuck tasers
return
else
src.health = src.health - max(P.power/2,0) // staples have a power of 5, .22 bullets have a power of 35
src.check_health()
proc/check_health()
if(src.health <= 0)
src.active = 0
src.shooting = 0
src.waiting = 0
src.target = null
src.die()
var/percent_damage = src.health/src.max_health * 100
switch(percent_damage)
if(90 to 100)
damage_words = "fully operational!"
if(75 to 89)
damage_words = "a little bit damaged."
if(30 to 74)
damage_words = "pretty beaten up."
if(0 to 29)
damage_words = "to be on the verge of falling apart!"
/*
if(src.emagged)
damage_words += "
Its safety indicator is off!"
*/
proc/die()
playsound(src.loc, "sound/effects/robogib.ogg", 50, 1)
new /obj/decal/cleanable/robot_debris(src.loc)
qdel(src)
proc/spawn_deployer()
var/obj/item/turret_deployer/deployer = new /obj/item/turret_deployer(src.loc)
deployer.health = src.health // NO FREE REPAIRS, ASSHOLES
//deployer.emagged = src.emagged
deployer.damage_words = src.damage_words
deployer.quick_deploy_fuel = src.quick_deploy_fuel
return deployer
proc/seek_target()
src.target_list = list()
for (var/mob/living/C in mobs)
if(!src)
break
if (src.target_valid(C))
src.target_list += C
var/distance = get_dist(C.loc,src.loc)
src.target_list[C] = distance
else
continue
if (src.target_list.len>0)
var/min_dist = 99999
for (var/mob/living/T in src.target_list)
if (src.target_list[T] < min_dist)
src.target = T
min_dist = src.target_list[T]
src.icon_state = "[src.icon_tag]_active"
playsound(src.loc, "sound/vox/woofsound.ogg", 40, 1)
return src.target
proc/target_valid(var/mob/living/C)
var/distance = get_dist(C.loc,src.loc)
if(distance > src.range)
return 0
if (!C)
return 0
if (C.health < 0)
return 0
if (C.stat == 2)
return 0
if (istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
if (H.resting || H.hasStatus("weakened")) // stops it from uselessly firing at people who are already suppressed. It's meant to be a suppression weapon!
return 0
if (is_friend(C))
return 0
/*var/turf/curr_step = src.loc // CAUSES GAME CRASH??
while(curr_step != C.loc)
curr_step = get_step(C.loc,get_dir(C.loc,curr_step))
if (curr_step.opacity || curr_step.density)
return 0 */
var/angle = get_angle(src,C)
var/anglemod = (-(angle < 180 ? angle : angle - 360) + 90) //Blatant Code Theft from showLine(), checks to see if there's something in the way of us and the target
var/crossed_turfs = list()
crossed_turfs = castRay(src,anglemod,distance)
for (var/turf/T in crossed_turfs)
if (T.opacity == 1)
return 0
if (T.density == 1)
return 0
angle = angle < 0 ? angle+360 : angle // make angles positive
angle = angle - src.external_angle
if (angle > 180) // rotate angle and convert into absolute terms from 0, where 0 is the seek-arc midpoint
angle = abs(360-angle)
else if (angle < -180)
angle = abs(360+angle)
else
angle = abs(angle)
if (angle <= (angle_arc_size/2)) //are we in the seeking arc?
return 1
return 0
proc/is_friend(var/mob/living/C) //tried to keep this generic in case you want to make a turret that only shoots monkeys or something
/*
if (src.emagged)
return 0 // NO FRIENDS :'[
*/
if (istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
if (istype(H.wear_id,/obj/item/card/id/syndicate))
return 1
return 0
proc/shoot(var/turf/target, var/start, var/user, var/bullet = 0)
if(target == start)
return
var/obj/projectile/A = unpool(/obj/projectile)
if(!A) return
A.set_loc(src.loc)
if (!current_projectile)
current_projectile = new projectile_type()
A.proj_data = new current_projectile.type
A.proj_data.master = A
A.set_icon()
A.power = A.proj_data.power
if(src.current_projectile.shot_sound)
playsound(src, src.current_projectile.shot_sound, 60)
if (!istype(target, /turf))
A.die()
return
A.target = target
A.yo = target:y - start:y
A.xo = target:x - start:x
A.shooter = src
spawn(0)
A.process()
return
proc/set_angle(var/angle)
angle = angle > 0 ? angle%360 : -((-angle)%360)+360 //limit user input to a sane range!
var/angle_diff = angle - src.external_angle
var/new_internal_angle = src.internal_angle + angle_diff
new_internal_angle = new_internal_angle > 0 ? new_internal_angle%360 : -((-new_internal_angle)%360)+360 //limit user input to a sane range!
src.animate_turret_turn(src.internal_angle,new_internal_angle)
src.internal_angle = new_internal_angle
src.external_angle = angle
proc/animate_turret_turn(var/curr_ang,var/new_ang)
var/ang = (new_ang - curr_ang)
if (abs(ang) > 180) // stops funky turret moving where it flips the long way around
ang = ang > 0 ? ang - 360 : ang + 360
var/matrix/transform_original = src.transform
animate(src, transform = matrix(transform_original, ang/3, MATRIX_ROTATE | MATRIX_MODIFY), time = 10/3, loop = 0) //blatant code theft from throw_at proc
animate(transform = matrix(transform_original, ang/3, MATRIX_ROTATE | MATRIX_MODIFY), time = 10/3, loop = 0) // needs to do in multiple steps because byond takes shortcuts
animate(transform = matrix(transform_original, ang/3, MATRIX_ROTATE | MATRIX_MODIFY), time = 10/3, loop = 0) // :argh:
/*
emag_act(var/user, var/emag)
if(src.emagged)
return
src.emagged = 1
boutput(user,"You short out the safeties on the turret.")
src.damage_words += "
Its safety indicator is off!"
*/
/////////////////////////////
// Turret Ability Stuff //
/////////////////////////////
/datum/targetable/deployable_turret_aim
name = "Turret Aim"
desc = "You are aiming a turret"
cooldown = 0
targeted = 1
target_anything = 1
max_range = 3000
var/obj/deployable_turret/my_turret = null
var/turf/user_turf = null
castcheck(var/mob/M)
if (M.client && M.client.holder)
return 1
handleCast(var/atom/target)
var/mob/M = usr
if (istype(M))
if(!istype(M.equipped(),/obj/item/wrench))
return
if(!(get_turf(usr) == src.user_turf))
return
if(target == my_turret)
return
if (!istype(target,/turf))
target = get_turf(target)
if(target == get_turf(my_turret))
return
spawn(0)
src.my_turret.set_angle(get_angle(my_turret,target))
return 0
/////////////////////////////
//Why not one for security?//
/////////////////////////////
/obj/item/turret_deployer/riot
name = "N.A.R.C.S."
desc = "A Nanotrasen Automatic Riot Control System."
icon_state = "st_deployer"
w_class = 4
health = 125
icon_tag = "nt"
quick_deploy_fuel = 0
spawn_turret(var/direct)
var/obj/deployable_turret/riot/turret = new /obj/deployable_turret/riot(src.loc,direction=direct)
turret.health = src.health
//turret.emagged = src.emagged
turret.damage_words = src.damage_words
turret.quick_deploy_fuel = src.quick_deploy_fuel
return turret
/obj/deployable_turret/riot
name = "N.A.R.C.S. Deployer"
desc = "A Nanotrasen Automatic Riot Control System Deployer. Use it in your hand to deploy."
health = 125
max_health = 125
wait_time = 20 //wait if it can't find a target
range = 5 // tiles
projectile_type = /datum/projectile/bullet/abg
current_projectile = new/datum/projectile/bullet/abg
burst_size = 1 // number of shots to fire. Keep in mind the bullet's shot_count
fire_rate = 1 // rate of fire in shots per second
angle_arc_size = 60
icon_tag = "nt"
quick_deploy_fuel = 0
New(var/direction)
..(direction=direction)
/*
spawn(src.wait_time)
if (src.emagged)
src.projectile_type = /datum/projectile/bullet/a12
src.current_projectile = new/datum/projectile/bullet/a12
*/
shoot(var/turf/target, var/start, var/user, var/bullet = 0)
flick("[src.icon_tag]_shoot",src)
..(target,start,user,bullet)
is_friend(var/mob/living/C)
/*
if (src.emagged)
return 0
*/
if (istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
if (istype(H.wear_id,/obj/item/card/id)) //This goes off appearance because people can change jobs mid-round... but that also means agent ids are a pretty hard counter. TODO: Fix?
var/obj/item/card/id/I = H.wear_id
switch(I.icon_state)
if("id_sec")
return 1
if("id_com")
return 1
if("gold")
return 1
else
return 0
return 0
spawn_deployer()
var/obj/item/turret_deployer/riot/deployer = new /obj/item/turret_deployer/riot(src.loc)
deployer.health = src.health
//deployer.emagged = src.emagged
deployer.damage_words = src.damage_words
deployer.quick_deploy_fuel = src.quick_deploy_fuel
return deployer
/*
emag_act(var/user, var/emag)
..()
src.projectile_type = /datum/projectile/bullet/a12
src.current_projectile = new/datum/projectile/bullet/a12
*/
/////////////////////////////
// User Manuals //
/////////////////////////////
/obj/item/paper/nast_manual
name = "paper- 'Nuclear Agent Sentry Turret Manual'"
info = {"Nuclear Agent Sentry Turret Manual
Congratulations, on your purchase of a Nuclear Agent Sentry Turret!
This a turret that fires at non-syndicate threats in a 30 degree arc.
Press its deploy button while it is your hand to deploy it.
The turret will start out facing the direction you are facing.
If the turret is unsecured, wrenching it will disassemble it.
Weld it to the floor to secure it.
While secured, using a screwdriver on the turret will turn it on, and using a wrench on it will set the angle.
Setting the angle will bring up a prompt to choose a target. Direct the turret to a sightline by pointing at it.
Welding the turret while it is active will allow you to perform repairs.
This turret is equipped with two quick-deploy charges installed.
When thrown, one quick-deploy charge will be used, automatically securing and activating the turret.
The quick-deployed turret will point in the direction it was thrown."}
/obj/item/paper/narcs_manual
name = "paper- 'Nanotrasen Automatic Riot Control System'"
info = {"Nanotrasen Automatic Riot Control System
Congratulations, on your purchase of a Nanotrasen Automatic Riot Control System!
This a turret that fires at non-security and non-command threats in a 60 degree arc.
Press its deploy button while it is your hand to deploy it.
The turret will start out facing the direction you are facing.
If the turret is unsecured, wrenching it will disassemble it.
Weld it to the floor to secure it.
While secured, using a screwdriver on the turret will turn it on, and using a wrench on it will set the angle.
Setting the angle will bring up a prompt to choose a target. Direct the turret to a sightline by pointing at it.
Welding the turret while it is active will allow you to perform repairs.
"}