mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
651 lines
17 KiB
Plaintext
651 lines
17 KiB
Plaintext
/area/turret_protected
|
|
name = "Turret Protected Area"
|
|
var/list/turretTargets = list()
|
|
|
|
/area/turret_protected/proc/subjectDied(target)
|
|
if( isliving(target) )
|
|
if( !issilicon(target) )
|
|
var/mob/living/L = target
|
|
if( L.stat )
|
|
if( L in turretTargets )
|
|
src.Exited(L)
|
|
|
|
|
|
/area/turret_protected/Entered(O)
|
|
..()
|
|
if( master && master != src )
|
|
return master.Entered(O)
|
|
|
|
if( iscarbon(O) )
|
|
turretTargets |= O
|
|
else if( istype(O, /obj/mecha) )
|
|
var/obj/mecha/Mech = O
|
|
if( Mech.occupant )
|
|
turretTargets |= Mech
|
|
else if(istype(O,/mob/living/simple_animal))
|
|
turretTargets |= O
|
|
return 1
|
|
|
|
/area/turret_protected/Exited(O)
|
|
if( master && master != src )
|
|
return master.Exited(O)
|
|
|
|
if( ismob(O) && !issilicon(O) )
|
|
turretTargets -= O
|
|
else if( istype(O, /obj/mecha) )
|
|
turretTargets -= O
|
|
..()
|
|
return 1
|
|
|
|
|
|
/obj/machinery/turret
|
|
name = "turret"
|
|
icon = 'icons/obj/turrets.dmi'
|
|
icon_state = "grey_target_prism"
|
|
var/raised = 0
|
|
var/enabled = 1
|
|
anchored = 1
|
|
layer = 3
|
|
invisibility = INVISIBILITY_LEVEL_TWO
|
|
density = 1
|
|
var/lasers = 0
|
|
var/lasertype = 1
|
|
// 1 = lasers
|
|
// 2 = cannons
|
|
// 3 = pulse
|
|
// 4 = change (HONK)
|
|
// 5 = bluetag
|
|
// 6 = redtag
|
|
var/health = 80
|
|
var/obj/machinery/turretcover/cover = null
|
|
var/popping = 0
|
|
var/wasvalid = 0
|
|
var/lastfired = 0
|
|
var/shot_delay = 30 //3 seconds between shots
|
|
var/datum/effect/effect/system/spark_spread/spark_system
|
|
use_power = 1
|
|
idle_power_usage = 50
|
|
active_power_usage = 300
|
|
// var/list/targets
|
|
var/atom/movable/cur_target
|
|
var/targeting_active = 0
|
|
var/area/turret_protected/protected_area
|
|
|
|
|
|
/obj/machinery/turret/New()
|
|
spark_system = new /datum/effect/effect/system/spark_spread
|
|
spark_system.set_up(5, 0, src)
|
|
spark_system.attach(src)
|
|
// targets = new
|
|
..()
|
|
return
|
|
|
|
/obj/machinery/turretcover
|
|
name = "pop-up turret cover"
|
|
icon = 'icons/obj/turrets.dmi'
|
|
icon_state = "turretCover"
|
|
anchored = 1
|
|
layer = 3.5
|
|
density = 0
|
|
var/obj/machinery/turret/host = null
|
|
|
|
/obj/machinery/turret/proc/isPopping()
|
|
return (popping!=0)
|
|
|
|
/obj/machinery/turret/power_change()
|
|
..()
|
|
if(stat & BROKEN)
|
|
icon_state = "grey_target_prism"
|
|
else
|
|
if( !(stat & NOPOWER) )
|
|
if (src.enabled)
|
|
if (src.lasers)
|
|
icon_state = "orange_target_prism"
|
|
else
|
|
icon_state = "target_prism"
|
|
else
|
|
icon_state = "grey_target_prism"
|
|
stat &= ~NOPOWER
|
|
else
|
|
spawn(rand(0, 15))
|
|
src.icon_state = "grey_target_prism"
|
|
stat |= NOPOWER
|
|
|
|
/obj/machinery/turret/proc/setState(var/enabled, var/lethal)
|
|
src.enabled = enabled
|
|
src.lasers = lethal
|
|
src.power_change()
|
|
|
|
|
|
/obj/machinery/turret/proc/get_protected_area()
|
|
var/area/turret_protected/TP = get_area(src)
|
|
if(istype(TP))
|
|
if(TP.master && TP.master != TP)
|
|
TP = TP.master
|
|
return TP
|
|
return
|
|
|
|
/obj/machinery/turret/proc/check_target(var/atom/movable/T as mob|obj)
|
|
if( T && T in protected_area.turretTargets )
|
|
var/area/area_T = get_area(T)
|
|
if( !area_T || (area_T.type != protected_area.type) )
|
|
protected_area.Exited(T)
|
|
return 0 //If the guy is somehow not in the turret's area (teleportation), get them out the damn list. --NEO
|
|
if( iscarbon(T) )
|
|
var/mob/living/carbon/MC = T
|
|
if( !MC.stat )
|
|
if( !MC.lying || lasers )
|
|
return 1
|
|
else if( istype(T, /obj/mecha) )
|
|
var/obj/mecha/ME = T
|
|
if( ME.occupant )
|
|
return 1
|
|
else if(istype(T,/mob/living/simple_animal))
|
|
var/mob/living/simple_animal/A = T
|
|
if( !A.stat )
|
|
if(lasers)
|
|
return 1
|
|
return 0
|
|
|
|
/obj/machinery/turret/proc/get_new_target()
|
|
var/list/new_targets = new
|
|
var/new_target
|
|
for(var/mob/living/carbon/M in protected_area.turretTargets)
|
|
if(!M.stat)
|
|
if(!M.lying || lasers)
|
|
new_targets += M
|
|
for(var/obj/mecha/M in protected_area.turretTargets)
|
|
if(M.occupant)
|
|
new_targets += M
|
|
for(var/mob/living/simple_animal/M in protected_area.turretTargets)
|
|
if(!M.stat)
|
|
new_targets += M
|
|
if(new_targets.len)
|
|
new_target = pick(new_targets)
|
|
return new_target
|
|
|
|
|
|
/obj/machinery/turret/process()
|
|
if(stat & (NOPOWER|BROKEN))
|
|
return
|
|
if(src.cover==null)
|
|
src.cover = new /obj/machinery/turretcover(src.loc)
|
|
src.cover.host = src
|
|
protected_area = get_protected_area()
|
|
if(!enabled || !protected_area || protected_area.turretTargets.len<=0)
|
|
if(!isDown() && !isPopping())
|
|
popDown()
|
|
return
|
|
if(!check_target(cur_target)) //if current target fails target check
|
|
cur_target = get_new_target() //get new target
|
|
|
|
if(cur_target) //if it's found, proceed
|
|
// world << "[cur_target]"
|
|
if(!isPopping())
|
|
if(isDown())
|
|
popUp()
|
|
use_power = 2
|
|
else
|
|
spawn()
|
|
if(!targeting_active)
|
|
targeting_active = 1
|
|
target()
|
|
targeting_active = 0
|
|
|
|
if(prob(15))
|
|
if(prob(50))
|
|
playsound(src.loc, 'sound/effects/turret/move1.wav', 60, 1)
|
|
else
|
|
playsound(src.loc, 'sound/effects/turret/move2.wav', 60, 1)
|
|
else if(!isPopping())//else, pop down
|
|
if(!isDown())
|
|
popDown()
|
|
use_power = 1
|
|
return
|
|
|
|
|
|
/obj/machinery/turret/proc/target()
|
|
while(src && enabled && !stat && check_target(cur_target))
|
|
src.dir = get_dir(src, cur_target)
|
|
shootAt(cur_target)
|
|
sleep(shot_delay)
|
|
return
|
|
|
|
/obj/machinery/turret/proc/shootAt(var/atom/movable/target)
|
|
var/turf/T = get_turf(src)
|
|
var/turf/U = get_turf(target)
|
|
if (!T || !U)
|
|
return
|
|
var/obj/item/projectile/A
|
|
if (src.lasers)
|
|
switch(lasertype)
|
|
if(1)
|
|
A = new /obj/item/projectile/beam( loc )
|
|
if(2)
|
|
A = new /obj/item/projectile/beam/heavylaser( loc )
|
|
if(3)
|
|
A = new /obj/item/projectile/beam/pulse( loc )
|
|
if(4)
|
|
A = new /obj/item/projectile/change( loc )
|
|
if(5)
|
|
A = new /obj/item/projectile/beam/lastertag/blue( loc )
|
|
if(6)
|
|
A = new /obj/item/projectile/beam/lastertag/red( loc )
|
|
A.original = target
|
|
use_power(500)
|
|
else
|
|
A = new /obj/item/projectile/energy/electrode( loc )
|
|
use_power(200)
|
|
A.current = T
|
|
A.yo = U.y - T.y
|
|
A.xo = U.x - T.x
|
|
spawn( 0 )
|
|
A.process()
|
|
return
|
|
|
|
|
|
/obj/machinery/turret/proc/isDown()
|
|
return (invisibility!=0)
|
|
|
|
/obj/machinery/turret/proc/popUp()
|
|
if ((!isPopping()) || src.popping==-1)
|
|
invisibility = 0
|
|
popping = 1
|
|
playsound(src.loc, 'sound/effects/turret/open.wav', 60, 1)
|
|
if (src.cover!=null)
|
|
flick("popup", src.cover)
|
|
src.cover.icon_state = "openTurretCover"
|
|
spawn(10)
|
|
if (popping==1) popping = 0
|
|
|
|
/obj/machinery/turret/proc/popDown()
|
|
if ((!isPopping()) || src.popping==1)
|
|
popping = -1
|
|
playsound(src.loc, 'sound/effects/turret/open.wav', 60, 1)
|
|
if (src.cover!=null)
|
|
flick("popdown", src.cover)
|
|
src.cover.icon_state = "turretCover"
|
|
spawn(10)
|
|
if (popping==-1)
|
|
invisibility = INVISIBILITY_LEVEL_TWO
|
|
popping = 0
|
|
|
|
/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj)
|
|
src.health -= Proj.damage
|
|
..()
|
|
if(prob(45) && Proj.damage > 0) src.spark_system.start()
|
|
del (Proj)
|
|
if (src.health <= 0)
|
|
src.die()
|
|
return
|
|
|
|
/obj/machinery/turret/attackby(obj/item/weapon/W, mob/user)//I can't believe no one added this before/N
|
|
..()
|
|
playsound(src.loc, 'sound/weapons/smash.ogg', 60, 1)
|
|
src.spark_system.start()
|
|
src.health -= W.force * 0.5
|
|
if (src.health <= 0)
|
|
src.die()
|
|
return
|
|
|
|
/obj/machinery/turret/emp_act(severity)
|
|
switch(severity)
|
|
if(1)
|
|
enabled = 0
|
|
lasers = 0
|
|
power_change()
|
|
..()
|
|
|
|
/obj/machinery/turret/ex_act(severity)
|
|
if(severity < 3)
|
|
src.die()
|
|
|
|
/obj/machinery/turret/proc/die()
|
|
src.health = 0
|
|
src.density = 0
|
|
src.stat |= BROKEN
|
|
src.icon_state = "destroyed_target_prism"
|
|
if (cover!=null)
|
|
del(cover)
|
|
sleep(3)
|
|
flick("explosion", src)
|
|
spawn(13)
|
|
del(src)
|
|
|
|
/obj/machinery/turretid
|
|
name = "Turret deactivation control"
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "motion3"
|
|
anchored = 1
|
|
density = 0
|
|
var/enabled = 1
|
|
var/lethal = 0
|
|
var/locked = 1
|
|
var/control_area //can be area name, path or nothing.
|
|
var/ailock = 0 // AI cannot use this
|
|
req_access = list(access_ai_upload)
|
|
|
|
/obj/machinery/turretid/New()
|
|
..()
|
|
if(!control_area)
|
|
var/area/CA = get_area(src)
|
|
if(CA.master && CA.master != CA)
|
|
control_area = CA.master
|
|
else
|
|
control_area = CA
|
|
else if(istext(control_area))
|
|
for(var/area/A in world)
|
|
if(A.name && A.name==control_area)
|
|
control_area = A
|
|
break
|
|
//don't have to check if control_area is path, since get_area_all_atoms can take path.
|
|
return
|
|
|
|
/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user)
|
|
if(stat & BROKEN) return
|
|
if (istype(user, /mob/living/silicon))
|
|
return src.attack_hand(user)
|
|
|
|
if (istype(W, /obj/item/weapon/card/emag) && !emagged)
|
|
user << "\red You short out the turret controls' access analysis module."
|
|
emagged = 1
|
|
locked = 0
|
|
if(user.machine==src)
|
|
src.attack_hand(user)
|
|
|
|
return
|
|
|
|
else if( get_dist(src, user) == 0 ) // trying to unlock the interface
|
|
if (src.allowed(usr))
|
|
if(emagged)
|
|
user << "<span class='notice'>The turret control is unresponsive.</span>"
|
|
return
|
|
|
|
locked = !locked
|
|
user << "<span class='notice'>You [ locked ? "lock" : "unlock"] the panel.</span>"
|
|
if (locked)
|
|
if (user.machine==src)
|
|
user.unset_machine()
|
|
user << browse(null, "window=turretid")
|
|
else
|
|
if (user.machine==src)
|
|
src.attack_hand(user)
|
|
else
|
|
user << "<span class='warning'>Access denied.</span>"
|
|
|
|
/obj/machinery/turretid/attack_ai(mob/user as mob)
|
|
if(!ailock)
|
|
return attack_hand(user)
|
|
else
|
|
user << "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>"
|
|
|
|
/obj/machinery/turretid/attack_hand(mob/user as mob)
|
|
if ( get_dist(src, user) > 0 )
|
|
if ( !issilicon(user) )
|
|
user << "<span class='notice'>You are too far away.</span>"
|
|
user.unset_machine()
|
|
user << browse(null, "window=turretid")
|
|
return
|
|
|
|
user.set_machine(src)
|
|
var/loc = src.loc
|
|
if (istype(loc, /turf))
|
|
loc = loc:loc
|
|
if (!istype(loc, /area))
|
|
user << text("Turret badly positioned - loc.loc is [].", loc)
|
|
return
|
|
var/area/area = loc
|
|
var/t = "<TT><B>Turret Control Panel</B> ([area.name])<HR>"
|
|
|
|
if(src.locked && (!istype(user, /mob/living/silicon)))
|
|
t += "<I>(Swipe ID card to unlock control panel.)</I><BR>"
|
|
else
|
|
t += text("Turrets [] - <A href='?src=\ref[];toggleOn=1'>[]?</a><br>\n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable")
|
|
t += text("Currently set for [] - <A href='?src=\ref[];toggleLethal=1'>Change to []?</a><br>\n", src.lethal?"lethal":"stun repeatedly", src, src.lethal?"Stun repeatedly":"Lethal")
|
|
|
|
user << browse(t, "window=turretid")
|
|
onclose(user, "turretid")
|
|
|
|
|
|
/obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob)
|
|
if(M.melee_damage_upper == 0) return
|
|
if(!(stat & BROKEN))
|
|
visible_message("\red <B>[M] [M.attacktext] [src]!</B>")
|
|
M.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name]</font>")
|
|
//src.attack_log += text("\[[time_stamp()]\] <font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
|
|
src.health -= M.melee_damage_upper
|
|
if (src.health <= 0)
|
|
src.die()
|
|
else
|
|
M << "\red That object is useless to you."
|
|
return
|
|
|
|
|
|
|
|
|
|
/obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob)
|
|
if(!(stat & BROKEN))
|
|
playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
|
visible_message("\red <B>[] has slashed at []!</B>", M, src)
|
|
src.health -= 15
|
|
if (src.health <= 0)
|
|
src.die()
|
|
else
|
|
M << "\green That object is useless to you."
|
|
return
|
|
|
|
|
|
|
|
/obj/machinery/turretid/Topic(href, href_list, var/nowindow = 0)
|
|
if(..(href, href_list))
|
|
return
|
|
if (src.locked)
|
|
if (!istype(usr, /mob/living/silicon))
|
|
usr << "Control panel is locked!"
|
|
return
|
|
if ( get_dist(src, usr) == 0 || issilicon(usr))
|
|
if (href_list["toggleOn"])
|
|
src.enabled = !src.enabled
|
|
src.updateTurrets()
|
|
else if (href_list["toggleLethal"])
|
|
src.lethal = !src.lethal
|
|
src.updateTurrets()
|
|
if(!nowindow)
|
|
src.attack_hand(usr)
|
|
|
|
/obj/machinery/turretid/proc/updateTurrets()
|
|
if(control_area)
|
|
for (var/obj/machinery/turret/aTurret in get_area_all_atoms(control_area))
|
|
aTurret.setState(enabled, lethal)
|
|
src.update_icons()
|
|
|
|
/obj/machinery/turretid/proc/update_icons()
|
|
if (src.enabled)
|
|
if (src.lethal)
|
|
icon_state = "motion1"
|
|
else
|
|
icon_state = "motion3"
|
|
else
|
|
icon_state = "motion0"
|
|
//CODE FIXED BUT REMOVED
|
|
// if(control_area) //USE: updates other controls in the area
|
|
// for (var/obj/machinery/turretid/Turret_Control in world) //I'm not sure if this is what it was
|
|
// if( Turret_Control.control_area != src.control_area ) continue //supposed to do. Or whether the person
|
|
// Turret_Control.icon_state = icon_state //who coded it originally was just tired
|
|
// Turret_Control.enabled = enabled //or something. I don't see any situation
|
|
// Turret_Control.lethal = lethal //in which this would be used on the current map.
|
|
//If he wants it back he can uncomment it
|
|
|
|
|
|
/obj/structure/turret/gun_turret
|
|
name = "Gun Turret"
|
|
density = 1
|
|
anchored = 1
|
|
var/cooldown = 20
|
|
var/projectiles = 100
|
|
var/projectiles_per_shot = 2
|
|
var/deviation = 0.3
|
|
var/list/exclude = list()
|
|
var/atom/cur_target
|
|
var/scan_range = 7
|
|
var/health = 40
|
|
var/list/scan_for = list("human"=0,"cyborg"=0,"mecha"=0,"alien"=1)
|
|
var/on = 0
|
|
icon = 'icons/obj/turrets.dmi'
|
|
icon_state = "gun_turret"
|
|
|
|
|
|
ex_act()
|
|
del src
|
|
return
|
|
|
|
emp_act()
|
|
del src
|
|
return
|
|
|
|
meteorhit()
|
|
del src
|
|
return
|
|
|
|
proc/update_health()
|
|
if(src.health<=0)
|
|
del src
|
|
return
|
|
|
|
proc/take_damage(damage)
|
|
src.health -= damage
|
|
if(src.health<=0)
|
|
del src
|
|
return
|
|
|
|
|
|
bullet_act(var/obj/item/projectile/Proj)
|
|
src.take_damage(Proj.damage)
|
|
..()
|
|
return
|
|
|
|
|
|
attack_hand(mob/user as mob)
|
|
user.set_machine(src)
|
|
var/dat = {"<html>
|
|
<head><title>[src] Control</title></head>
|
|
<body>
|
|
<b>Power: </b><a href='?src=\ref[src];power=1'>[on?"on":"off"]</a><br>
|
|
<b>Scan Range: </b><a href='?src=\ref[src];scan_range=-1'>-</a> [scan_range] <a href='?src=\ref[src];scan_range=1'>+</a><br>
|
|
<b>Scan for: </b>"}
|
|
for(var/scan in scan_for)
|
|
dat += "<div style=\"margin-left: 15px;\">[scan] (<a href='?src=\ref[src];scan_for=[scan]'>[scan_for[scan]?"Yes":"No"]</a>)</div>"
|
|
|
|
dat += {"<b>Ammo: </b>[max(0, projectiles)]<br>
|
|
</body>
|
|
</html>"}
|
|
user << browse(dat, "window=turret")
|
|
onclose(user, "turret")
|
|
return
|
|
|
|
attack_ai(mob/user as mob)
|
|
return attack_hand(user)
|
|
|
|
|
|
attack_alien(mob/user as mob)
|
|
user.visible_message("[user] slashes at [src]", "You slash at [src]")
|
|
src.take_damage(15)
|
|
return
|
|
|
|
Topic(href, href_list)
|
|
if(href_list["power"])
|
|
src.on = !src.on
|
|
if(src.on)
|
|
spawn(50)
|
|
if(src)
|
|
src.process()
|
|
if(href_list["scan_range"])
|
|
src.scan_range = between(1,src.scan_range+text2num(href_list["scan_range"]),8)
|
|
if(href_list["scan_for"])
|
|
if(href_list["scan_for"] in scan_for)
|
|
scan_for[href_list["scan_for"]] = !scan_for[href_list["scan_for"]]
|
|
src.updateUsrDialog()
|
|
return
|
|
|
|
|
|
proc/validate_target(atom/target)
|
|
if(get_dist(target, src)>scan_range)
|
|
return 0
|
|
if(istype(target, /mob))
|
|
var/mob/M = target
|
|
if(!M.stat && !M.lying)//ninjas can't catch you if you're lying
|
|
return 1
|
|
else if(istype(target, /obj/mecha))
|
|
return 1
|
|
return 0
|
|
|
|
|
|
process()
|
|
spawn while(on)
|
|
if(projectiles<=0)
|
|
on = 0
|
|
return
|
|
if(cur_target && !validate_target(cur_target))
|
|
cur_target = null
|
|
if(!cur_target)
|
|
cur_target = get_target()
|
|
fire(cur_target)
|
|
sleep(cooldown)
|
|
return
|
|
|
|
proc/get_target()
|
|
var/list/pos_targets = list()
|
|
var/target = null
|
|
if(scan_for["human"])
|
|
for(var/mob/living/carbon/human/M in oview(scan_range,src))
|
|
if(M.stat || M.lying || M in exclude)
|
|
continue
|
|
pos_targets += M
|
|
if(scan_for["cyborg"])
|
|
for(var/mob/living/silicon/M in oview(scan_range,src))
|
|
if(M.stat || M.lying || M in exclude)
|
|
continue
|
|
pos_targets += M
|
|
if(scan_for["mecha"])
|
|
for(var/obj/mecha/M in oview(scan_range, src))
|
|
if(M in exclude)
|
|
continue
|
|
pos_targets += M
|
|
if(scan_for["alien"])
|
|
for(var/mob/living/carbon/alien/M in oview(scan_range,src))
|
|
if(M.stat || M.lying || M in exclude)
|
|
continue
|
|
pos_targets += M
|
|
if(pos_targets.len)
|
|
target = pick(pos_targets)
|
|
return target
|
|
|
|
|
|
proc/fire(atom/target)
|
|
if(!target)
|
|
cur_target = null
|
|
return
|
|
src.dir = get_dir(src,target)
|
|
var/turf/targloc = get_turf(target)
|
|
var/target_x = targloc.x
|
|
var/target_y = targloc.y
|
|
var/target_z = targloc.z
|
|
targloc = null
|
|
spawn for(var/i=1 to min(projectiles, projectiles_per_shot))
|
|
if(!src) break
|
|
var/turf/curloc = get_turf(src)
|
|
targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z)
|
|
if (!targloc || !curloc)
|
|
continue
|
|
if (targloc == curloc)
|
|
continue
|
|
playsound(src, 'sound/weapons/Gunshot.ogg', 50, 1)
|
|
var/obj/item/projectile/A = new /obj/item/projectile(curloc)
|
|
src.projectiles--
|
|
A.current = curloc
|
|
A.yo = targloc.y - curloc.y
|
|
A.xo = targloc.x - curloc.x
|
|
A.process()
|
|
sleep(2)
|
|
return
|