Point Defense Turret Adjustments (#18126)

* Initial

* Rename

* Proper multitool
This commit is contained in:
Cameron Lennox
2025-08-02 19:39:55 -04:00
committed by GitHub
parent ed800174e0
commit 19eb84c107
37 changed files with 236 additions and 251 deletions
+34 -81
View File
@@ -4,7 +4,7 @@
//
GLOBAL_LIST_BOILERPLATE(pointdefense_controllers, /obj/machinery/pointdefense_control)
GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
/obj/machinery/pointdefense_control
name = "fire assist mainframe"
@@ -12,6 +12,9 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
description_info = "To connect the mainframe to turrets, use a multitool to set the ident tag to that of the turrets."
icon = 'icons/obj/pointdefense.dmi'
icon_state = "control"
power_channel = EQUIP
use_power = USE_POWER_ACTIVE
active_power_usage = 5 KILOWATTS
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/pointdefense_control
@@ -50,7 +53,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
return TRUE
if(action == "toggle_active")
var/obj/machinery/power/pointdefense/PD = locate(params["target"])
var/obj/machinery/pointdefense/PD = locate(params["target"])
if(!istype(PD))
return FALSE
@@ -73,7 +76,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
if(id_tag)
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
for(var/i = 1 to LAZYLEN(GLOB.pointdefense_turrets))
var/obj/machinery/power/pointdefense/PD = GLOB.pointdefense_turrets[i]
var/obj/machinery/pointdefense/PD = GLOB.pointdefense_turrets[i]
if(!(PD.id_tag == id_tag && (get_z(PD) in connected_z_levels)))
continue
var/list/turret = list()
@@ -114,7 +117,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
// The acutal point defense battery
//
/obj/machinery/power/pointdefense
/obj/machinery/pointdefense
name = "\improper point defense battery"
icon = 'icons/obj/pointdefense.dmi'
icon_state = "pointdefense2"
@@ -123,80 +126,40 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/pointdefense
idle_power_usage = 0.1 KILOWATTS
active_power_usage = 1 KILOWATTS
appearance_flags = PIXEL_SCALE
var/active = TRUE
var/charge_cooldown = 1 SECOND //time between it can fire at different targets
var/last_shot = 0
var/kill_range = 18
var/rotation_speed = 0.25 SECONDS //How quickly we turn to face threats
var/rotation_speed = 4.5 SECONDS //How quickly we turn to face threats
var/datum/weakref/engaging = null // The meteor we're shooting at
var/id_tag = null
var/fire_sounds = list('sound/weapons/frigate_turret/frigate_turret_fire1.ogg', 'sound/weapons/frigate_turret/frigate_turret_fire2.ogg', 'sound/weapons/frigate_turret/frigate_turret_fire3.ogg', 'sound/weapons/frigate_turret/frigate_turret_fire4.ogg') // CHOMPEdit: Pew
/obj/machinery/power/pointdefense/Initialize(mapload)
/obj/machinery/pointdefense/Initialize(mapload)
. = ..()
default_apply_parts()
if(anchored)
connect_to_network()
update_icon()
var/image/I = image(icon, icon_state = "[icon_state]_under")
I.appearance_flags |= RESET_TRANSFORM
underlays += I
/obj/machinery/power/pointdefense/examine(mob/user)
. = ..()
if(powernet)
. += "It is connected to a power cable below."
/obj/machinery/power/pointdefense/get_description_interaction()
/obj/machinery/pointdefense/get_description_interaction()
. = ..()
if(!id_tag)
. += "[desc_panel_image("multitool")]to set ident tag and connect to a mainframe."
/obj/machinery/power/pointdefense/update_icon()
/obj/machinery/pointdefense/update_icon()
if(!active || !id_tag || inoperable())
icon_state = "[initial(icon_state)]_off"
else
icon_state = initial(icon_state)
/obj/machinery/power/pointdefense/default_unfasten_wrench(var/mob/user, var/obj/item/W, var/time)
if((. = ..()))
src.transform = null // Reset rotation if we're anchored/unanchored
////////// This machine is willing to take power from cables OR APCs. Handle NOPOWER stat specially here! ////////
/obj/machinery/power/pointdefense/connect_to_network()
if((. = ..()))
stat &= ~NOPOWER // We now ignore APC power
update_icon()
/obj/machinery/power/pointdefense/disconnect_from_network()
if((. = ..()))
power_change() // We're back on APC power.
/obj/machinery/power/pointdefense/power_change()
if(powernet)
return // We don't care, we are cable powered anyway
/obj/machinery/pointdefense/power_change()
var/old_stat = stat
..()
if(old_stat != stat)
update_icon()
// Decide where to get the power to fire from
/obj/machinery/power/pointdefense/use_power_oneoff(var/amount, var/chan = CURRENT_CHANNEL)
if(powernet)
return draw_power(amount)
// We are not connected to a powernet, so we want APC power. Reproduce that code here since this is weird.
if(chan == CURRENT_CHANNEL)
chan = power_channel
var/area/A = get_area(src) // make sure it's in an area
if(!A || !A.powered(chan)) // and that the area is powered
return 0 // if not, then not powered
return A.use_power_oneoff(amount, chan)
// Find controller with the same tag on connected z levels (if any)
/obj/machinery/power/pointdefense/proc/get_controller()
/obj/machinery/pointdefense/proc/get_controller()
if(!id_tag)
return null
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
@@ -204,11 +167,11 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
if(PDC.id_tag == id_tag && (get_z(PDC) in connected_z_levels))
return PDC
/obj/machinery/power/pointdefense/attackby(var/obj/item/W, var/mob/user)
/obj/machinery/pointdefense/attackby(var/obj/item/W, var/mob/user)
if(W?.has_tool_quality(TOOL_MULTITOOL))
var/new_ident = tgui_input_text(user, "Enter a new ident tag.", "[src]", id_tag, MAX_NAME_LEN)
new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, GLOB.tgui_physical_state))
if(new_ident && new_ident != id_tag && user.Adjacent(src))
to_chat(user, span_notice("You register [src] with the [new_ident] network."))
id_tag = new_ident
return
@@ -218,18 +181,16 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
return
if(default_part_replacement(user, W))
return
if(default_unfasten_wrench(user, W, 40))
return
return ..()
//Guns cannot shoot through hull or generally dense turfs.
/obj/machinery/power/pointdefense/proc/space_los(meteor)
/obj/machinery/pointdefense/proc/space_los(meteor)
for(var/turf/T in getline(src,meteor))
if(T.density)
return FALSE
return TRUE
/obj/machinery/power/pointdefense/proc/Shoot(var/datum/weakref/target)
/obj/machinery/pointdefense/proc/Shoot(var/datum/weakref/target)
var/obj/effect/meteor/M = target.resolve()
if(!istype(M))
engaging = null
@@ -243,7 +204,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
set_dir(ATAN2(transform.b, transform.a) > 0 ? NORTH : SOUTH)
/obj/machinery/power/pointdefense/proc/finish_shot(var/datum/weakref/target)
/obj/machinery/pointdefense/proc/finish_shot(var/datum/weakref/target)
var/obj/machinery/pointdefense_control/PC = get_controller()
engaging = null
@@ -253,34 +214,28 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
var/obj/effect/meteor/M = target.resolve()
if(!istype(M))
return
if(use_power_oneoff(active_power_usage) < active_power_usage)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
visible_message("[src] sputters as browns out while attempting to fire.")
flick(src, "[initial(icon_state)]_off")
return
//We throw a laser but it doesnt have to hit for meteor to explode
var/obj/item/projectile/beam/pointdefense/beam = new(get_turf(src))
playsound(src, 'sound/weapons/mandalorian.ogg', 75, 1)
beam.launch_projectile(target = M.loc, user = src)
var/obj/item/projectile/beam/coildefense/coil = new(get_turf(src))
playsound(src, fire_sounds, 75, 1, 40, pressure_affected = FALSE, ignore_walls = TRUE)
use_power_oneoff(idle_power_usage * 10)
coil.launch_projectile(target = M.loc, user = src)
spawn(10)
playsound(src, fire_sounds, 75, 1, 40, pressure_affected = FALSE, ignore_walls = TRUE)
/obj/machinery/power/pointdefense/process()
/obj/machinery/pointdefense/process()
..()
if(!anchored || stat & (NOPOWER|BROKEN))
if(stat & (BROKEN))
return
if(!active)
return
/*
var/desiredir = ATAN2(transform.b, transform.a) > 0 ? NORTH : SOUTH
if(dir != desiredir)
set_dir(desiredir)
*/
if(LAZYLEN(GLOB.meteor_list) > 0)
find_and_shoot()
/obj/machinery/power/pointdefense/proc/find_and_shoot()
/obj/machinery/pointdefense/proc/find_and_shoot()
// There ARE meteors to shoot
if(LAZYLEN(GLOB.meteor_list) == 0)
return
@@ -289,7 +244,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
return
var/obj/machinery/pointdefense_control/PC = get_controller()
if(!istype(PC))
if(!istype(PC) || !PC.powered(EQUIP))
return
// Compile list of known targets
@@ -316,7 +271,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
Shoot(target)
return
/obj/machinery/power/pointdefense/proc/targeting_check(var/obj/effect/meteor/M)
/obj/machinery/pointdefense/proc/targeting_check(var/obj/effect/meteor/M)
// Target in range
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
if(!(M.z in connected_z_levels))
@@ -329,7 +284,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
return TRUE
/obj/machinery/power/pointdefense/RefreshParts()
/obj/machinery/pointdefense/RefreshParts()
. = ..()
// Calculates an average rating of components that affect shooting rate
var/shootrate_divisor = total_component_rating_of_type(/obj/item/stock_parts/capacitor)
@@ -343,23 +298,21 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
kill_range = 10 + 4 * killrange_multiplier
var/rotation_divisor = total_component_rating_of_type(/obj/item/stock_parts/manipulator)
rotation_speed = 0.5 SECONDS / (rotation_divisor ? rotation_divisor : 1)
rotation_speed = 4.5 SECONDS / (rotation_divisor ? rotation_divisor : 1)
/obj/machinery/power/pointdefense/proc/Activate()
/obj/machinery/pointdefense/proc/Activate()
if(active)
return FALSE
playsound(src, 'sound/weapons/flash.ogg', 100, 0)
update_use_power(USE_POWER_IDLE)
active = TRUE
update_icon()
return TRUE
/obj/machinery/power/pointdefense/proc/Deactivate()
/obj/machinery/pointdefense/proc/Deactivate()
if(!active)
return FALSE
playsound(src, 'sound/machines/apc_nopower.ogg', 50, 0)
update_use_power(USE_POWER_OFF)
active = FALSE
update_icon()
return TRUE
@@ -102,3 +102,9 @@
light_range = 3
light_power = 1
light_color = "#ffffff"
/obj/effect/projectile/impact/coildefense
icon_state = "impact_coildef"
light_range = 2
light_power = 3
light_color = "#FFFFFF"
@@ -114,3 +114,9 @@
light_range = 3
light_power = 1
light_color = "#ffffff"
/obj/effect/projectile/muzzle/coildefense
icon_state = "muzzle_coildef"
light_range = 3
light_power = 1
light_color = "#FFFFFF"
@@ -141,3 +141,9 @@
light_range = 3
light_power = 1
light_color = "#ffffff"
/obj/effect/projectile/tracer/coildefense
icon_state = "tracer_coildef"
light_range = 1
light_power = 2
light_color = "#FFFFFF"
@@ -6,7 +6,7 @@
name = T_BOARD("point defense battery")
board_type = new /datum/frame/frame_types/machine
desc = "Control systems for a Kuiper pattern point defense battery. Aim away from vessel."
build_path = /obj/machinery/power/pointdefense
build_path = /obj/machinery/pointdefense
origin_tech = list(TECH_ENGINEERING = 3, TECH_COMBAT = 2)
req_components = list(
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser = 1,