diff --git a/aurorastation.dme b/aurorastation.dme
index 9f0122c6294..35258b8cd38 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -1222,6 +1222,7 @@
#include "code\game\objects\items\weapons\circuitboards\machinery\recharge_station.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\research.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\shieldgen.dm"
+#include "code\game\objects\items\weapons\circuitboards\machinery\ship.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\telecomms.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\trashcompactor.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\trolley.dm"
@@ -3384,6 +3385,7 @@
#include "code\modules\research\designs\circuit\mining_circuits.dm"
#include "code\modules\research\designs\circuit\misc_electronics.dm"
#include "code\modules\research\designs\circuit\shield_designs.dm"
+#include "code\modules\research\designs\circuit\ship_circuits.dm"
#include "code\modules\research\designs\circuit\tcom_designs.dm"
#include "code\modules\research\designs\mechfab\hardsuit\modules.dm"
#include "code\modules\research\designs\mechfab\hardsuit\rigs.dm"
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 525758f3870..88748a47855 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -174,6 +174,10 @@
if(component_check)
attacking_item.play_tool_sound(get_turf(src), 50)
var/obj/machinery/new_machine = new circuit.build_path(loc, dir, FALSE)
+ if(istype(circuit, /obj/item/circuitboard/unary_atmos))
+ var/obj/item/circuitboard/unary_atmos/U = circuit
+ U.init_dirs = dir
+ U.machine_dir = U
if(istype(new_machine))
if(new_machine.component_parts)
new_machine.component_parts.Cut()
diff --git a/code/game/objects/items/weapons/circuitboards/machinery/ship.dm b/code/game/objects/items/weapons/circuitboards/machinery/ship.dm
new file mode 100644
index 00000000000..e2e313b193b
--- /dev/null
+++ b/code/game/objects/items/weapons/circuitboards/machinery/ship.dm
@@ -0,0 +1,117 @@
+//Thrusters
+/obj/item/circuitboard/unary_atmos/engine
+ name = T_BOARD("gas thruster")
+ icon_state = "mcontroller"
+ build_path = /obj/machinery/atmospherics/unary/engine
+ origin_tech = list(TECH_POWER = 1, TECH_ENGINEERING = 2)
+ req_components = list(
+ "/obj/item/stack/cable_coil" = 30,
+ "/obj/item/pipe" = 2)
+
+/obj/item/circuitboard/unary_atmos/engine/scc_shuttle
+ build_path = /obj/machinery/atmospherics/unary/engine/scc_shuttle
+
+/obj/item/circuitboard/unary_atmos/engine/scc_ship
+ build_path = /obj/machinery/atmospherics/unary/engine/scc_ship_engine
+
+/obj/item/circuitboard/engine/ion
+ name = T_BOARD("ion propulsion device")
+ board_type = "machine"
+ icon_state = "mcontroller"
+ build_path = /obj/machinery/ion_engine
+ origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3)
+ req_components = list(
+ "/obj/item/stack/cable_coil" = 2,
+ "/obj/item/stock_parts/matter_bin" = 1,
+ "/obj/item/stock_parts/capacitor" = 2)
+
+/obj/item/circuitboard/engine/maneuvering
+ name = T_BOARD("pulse-maneuvering device")
+ board_type = "machine"
+ icon_state = "mcontroller"
+ build_path = /obj/machinery/maneuvering_engine
+ origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3)
+ req_components = list(
+ "/obj/item/stack/cable_coil" = 2,
+ "/obj/item/stock_parts/matter_bin" = 1,
+ "/obj/item/stock_parts/capacitor" = 2
+ )
+
+//IFF Beacon
+/obj/item/circuitboard/iff_beacon
+ name = T_BOARD("IFF transponder")
+ board_type = "machine"
+ icon_state = "mcontroller"
+ build_path = /obj/machinery/iff_beacon
+ origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
+ req_components = list(
+ "/obj/item/stack/cable_coil" = 2,
+ "/obj/item/stock_parts/subspace/transmitter" = 1,
+ "/obj/item/stock_parts/capacitor" = 2
+ )
+
+//Sensors
+/obj/item/circuitboard/shipsensors
+ name = T_BOARD("sensor suite")
+ board_type = "machine"
+ icon_state = "mcontroller"
+ build_path = /obj/machinery/shipsensors
+ origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 5, TECH_BLUESPACE = 3)
+ req_components = list(
+ "/obj/item/stock_parts/subspace/ansible" = 1,
+ "/obj/item/stock_parts/subspace/filter" = 1,
+ "/obj/item/stock_parts/subspace/treatment" = 1,
+ "/obj/item/stock_parts/subspace/analyzer" = 1,
+ "/obj/item/stock_parts/scanning_module" = 2,
+ "/obj/item/stock_parts/manipulator" = 3
+ )
+
+/obj/item/circuitboard/shipsensors/weak
+ name = T_BOARD("low-power sensor suite")
+ board_type = "machine"
+ icon_state = "mcontroller"
+ build_path = /obj/machinery/shipsensors/weak
+ origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 1)
+ req_components = list(
+ "/obj/item/stock_parts/subspace/ansible" = 1,
+ "/obj/item/stock_parts/subspace/filter" = 1,
+ "/obj/item/stock_parts/subspace/treatment" = 1,
+ "/obj/item/stock_parts/scanning_module" = 1,
+ "/obj/item/stock_parts/manipulator" = 3
+ )
+
+/obj/item/circuitboard/shipsensors/weak/scc
+ build_path = /obj/machinery/shipsensors/weak/scc_shuttle
+
+/obj/item/circuitboard/shipsensors/strong
+ name = T_BOARD("high-power sensor suite")
+ build_path = /obj/machinery/shipsensors/strong
+ origin_tech = list(TECH_POWER = 6, TECH_ENGINEERING = 8, TECH_BLUESPACE = 5)
+ req_components = list(
+ "/obj/item/stock_parts/subspace/ansible" = 1,
+ "/obj/item/stock_parts/subspace/filter" = 1,
+ "/obj/item/stock_parts/subspace/treatment" = 1,
+ "/obj/item/stock_parts/subspace/analyzer" = 1,
+ "/obj/item/stock_parts/manipulator/pico" = 3,
+ "/obj/item/stock_parts/scanning_module/phasic" = 1,
+ "/obj/item/stack/cable_coil" = 30
+ )
+
+/obj/item/circuitboard/shipsensors/strong/scc
+ build_path = /obj/machinery/shipsensors/strong/scc_shuttle
+
+/obj/item/circuitboard/shipsensors/venator
+ name = T_BOARD("venator-class quantum sensor array")
+ build_path = /obj/machinery/shipsensors/strong/venator
+ origin_tech = list(TECH_POWER = 8, TECH_ENGINEERING = 10, TECH_BLUESPACE = 8, TECH_PHORON = 4)
+ req_components = list(
+ "/obj/item/stock_parts/subspace/ansible" = 1,
+ "/obj/item/stock_parts/subspace/filter" = 1,
+ "/obj/item/stock_parts/subspace/treatment" = 1,
+ "/obj/item/stock_parts/subspace/analyzer" = 1,
+ "/obj/item/stock_parts/subspace/amplifier" = 1,
+ "/obj/item/stock_parts/manipulator/pico" = 4,
+ "/obj/item/stock_parts/scanning_module/phasic" = 3,
+ "/obj/item/stack/cable_coil" = 30,
+ "/obj/item/bluespace_crystal" = 1
+ )
diff --git a/code/game/objects/items/weapons/circuitboards/machinery/unary_atmos.dm b/code/game/objects/items/weapons/circuitboards/machinery/unary_atmos.dm
index 91409d6b2a2..172344a798c 100644
--- a/code/game/objects/items/weapons/circuitboards/machinery/unary_atmos.dm
+++ b/code/game/objects/items/weapons/circuitboards/machinery/unary_atmos.dm
@@ -7,17 +7,6 @@
var/machine_dir = SOUTH
var/init_dirs = SOUTH
-/obj/item/circuitboard/unary_atmos/attackby(obj/item/attacking_item, mob/user)
- if(attacking_item.isscrewdriver())
- machine_dir = turn(machine_dir, 90)
- init_dirs = machine_dir
- user.visible_message("\The [user] adjusts the jumper on the [src]'s port configuration pins.", "You adjust the jumper on the port configuration pins. Now set to [dir2text(machine_dir)].")
- return
-
-/obj/item/circuitboard/unary_atmos/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
- . = ..()
- . += "The jumper is connecting the [dir2text(machine_dir)] pins."
-
/obj/item/circuitboard/unary_atmos/construct(var/obj/machinery/atmospherics/unary/U)
//TODO: Move this stuff into the relevant constructor when pipe/construction.dm is cleaned up.
U.dir = src.machine_dir
diff --git a/code/modules/overmap/ships/computers/sensors.dm b/code/modules/overmap/ships/computers/sensors.dm
index a0214ef56ca..99814bdc7d2 100644
--- a/code/modules/overmap/ships/computers/sensors.dm
+++ b/code/modules/overmap/ships/computers/sensors.dm
@@ -4,7 +4,6 @@
icon_keyboard = "cyan_key"
light_color = LIGHT_COLOR_CYAN
extra_view = 4
- var/obj/machinery/shipsensors/sensors
var/obj/machinery/iff_beacon/identification
circuit = /obj/item/circuitboard/ship/sensors
linked_type = /obj/effect/overmap/visitable
@@ -38,6 +37,9 @@
light_power_on = 1
/obj/machinery/computer/ship/sensors/proc/get_sensors()
+ var/obj/machinery/shipsensors/sensors = sensor_ref?.resolve()
+ if(!istype(sensors) || QDELETED(sensors))
+ sensor_ref = null
return sensors
/obj/machinery/computer/ship/sensors/attempt_hook_up(var/obj/effect/overmap/visitable/sector)
@@ -54,7 +56,7 @@
return
for(var/obj/machinery/shipsensors/S in SSmachinery.machinery)
if(linked.check_ownership(S))
- sensors = S
+ sensor_ref = WEAKREF(S)
break
for(var/obj/machinery/iff_beacon/IB in SSmachinery.machinery)
if(linked.check_ownership(IB))
@@ -91,7 +93,7 @@
/obj/machinery/computer/ship/sensors/ui_data(mob/user)
simple_asset_ensure_is_sent(user, /datum/asset/simple/paper)
-
+ var/obj/machinery/shipsensors/sensors = get_sensors()
var/data = list()
data["viewing"] = viewing_overmap(user)
@@ -229,7 +231,7 @@
if(contact_details)
data["contact_details"] = contact_details
else
- data["id_status"] = "NOBEACON" //Should not really happen.
+ data["id_status"] = "MISSING"
return data
@@ -248,7 +250,7 @@
if (action == "link")
find_sensors_and_iff()
return TRUE
-
+ var/obj/machinery/shipsensors/sensors = get_sensors()
if(sensors)
if (action == "range")
var/nrange = tgui_input_number("Set new sensors range", "Sensor range", sensors.range, sensors.max_range, 1)
@@ -398,6 +400,15 @@
var/deep_scan_toggled = FALSE //When TRUE, this sensor is using long range sensors.
var/deep_scan_sensor_name = "High-Power Sensor Array"
idle_power_usage = 5000
+ component_types = list(
+ /obj/item/circuitboard/shipsensors,
+ /obj/item/stock_parts/subspace/ansible,
+ /obj/item/stock_parts/subspace/filter,
+ /obj/item/stock_parts/subspace/treatment,
+ /obj/item/stock_parts/subspace/analyzer,
+ /obj/item/stock_parts/scanning_module = 2,
+ /obj/item/stock_parts/manipulator = 3
+ )
var/base_icon_state
@@ -406,6 +417,12 @@
return ..()
/obj/machinery/shipsensors/attackby(obj/item/attacking_item, mob/user)
+ if(default_deconstruction_screwdriver(user, attacking_item))
+ return TRUE
+ if(default_deconstruction_crowbar(user, attacking_item))
+ return TRUE
+ if(default_part_replacement(user, attacking_item))
+ return TRUE
var/damage = max_health - health
if(damage && attacking_item.iswelder())
@@ -550,10 +567,26 @@
max_range = 7
desc = "Miniturized gravity scanner with various other sensors, used to detect irregularities in surrounding space. Can only run in vacuum to protect delicate quantum BS elements."
deep_scan_range = 0
+ component_types = list(
+ /obj/item/circuitboard/shipsensors/weak,
+ /obj/item/stock_parts/subspace/ansible,
+ /obj/item/stock_parts/subspace/filter,
+ /obj/item/stock_parts/subspace/treatment,
+ /obj/item/stock_parts/scanning_module,
+ /obj/item/stock_parts/manipulator = 3
+ )
/obj/machinery/shipsensors/weak/scc_shuttle
icon_state = "sensors"
icon = 'icons/obj/spaceship/scc/helm_pieces.dmi'
+ component_types = list(
+ /obj/item/circuitboard/shipsensors/weak/scc,
+ /obj/item/stock_parts/subspace/ansible,
+ /obj/item/stock_parts/subspace/filter,
+ /obj/item/stock_parts/subspace/treatment,
+ /obj/item/stock_parts/scanning_module,
+ /obj/item/stock_parts/manipulator = 3
+ )
/obj/machinery/shipsensors/strong
desc = "An upgrade to the standard ship-mounted sensor array, this beast has massive cooling systems running beneath it, allowing it to run hotter for much longer. Can only run in vacuum to protect delicate quantum BS elements."
@@ -561,10 +594,30 @@
max_range = 14
deep_scan_range = 6
deep_scan_sensor_name = "High-Power Sensor Array"
+ component_types = list(
+ /obj/item/circuitboard/shipsensors/strong,
+ /obj/item/stock_parts/subspace/ansible,
+ /obj/item/stock_parts/subspace/filter,
+ /obj/item/stock_parts/subspace/treatment,
+ /obj/item/stock_parts/subspace/analyzer,
+ /obj/item/stock_parts/manipulator/pico = 3,
+ /obj/item/stock_parts/scanning_module/phasic,
+ /obj/item/stack/cable_coil = 30
+ )
/obj/machinery/shipsensors/strong/scc_shuttle //Exclusively for the Horizon scout shuttle.
icon_state = "sensors"
icon = 'icons/obj/spaceship/scc/shuttle_sensors.dmi'
+ component_types = list(
+ /obj/item/circuitboard/shipsensors/strong/scc,
+ /obj/item/stock_parts/subspace/ansible,
+ /obj/item/stock_parts/subspace/filter,
+ /obj/item/stock_parts/subspace/treatment,
+ /obj/item/stock_parts/subspace/analyzer,
+ /obj/item/stock_parts/manipulator/pico = 3,
+ /obj/item/stock_parts/scanning_module/phasic,
+ /obj/item/stack/cable_coil = 30
+ )
/obj/machinery/shipsensors/strong/venator
name = "venator-class quantum sensor array"
@@ -575,3 +628,15 @@
layer = ABOVE_HUMAN_LAYER
pixel_x = -32
pixel_y = -32
+ component_types = list(
+ /obj/item/circuitboard/shipsensors/venator,
+ /obj/item/stock_parts/subspace/ansible,
+ /obj/item/stock_parts/subspace/filter,
+ /obj/item/stock_parts/subspace/treatment,
+ /obj/item/stock_parts/subspace/analyzer,
+ /obj/item/stock_parts/subspace/amplifier,
+ /obj/item/stock_parts/manipulator/pico = 4,
+ /obj/item/stock_parts/scanning_module/phasic = 3,
+ /obj/item/bluespace_crystal,
+ /obj/item/stack/cable_coil = 30
+ )
diff --git a/code/modules/overmap/ships/computers/ship.dm b/code/modules/overmap/ships/computers/ship.dm
index 0ce4d286c5e..f5cf67c06ea 100644
--- a/code/modules/overmap/ships/computers/ship.dm
+++ b/code/modules/overmap/ships/computers/ship.dm
@@ -126,9 +126,9 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
. = ..()
/obj/machinery/computer/ship/sensors/Destroy()
- QDEL_NULL(sound_token)
- sensors = null
+ sensor_ref = null
identification = null
+ QDEL_NULL(sound_token)
if(LAZYLEN(viewers))
for(var/datum/weakref/W in viewers)
var/M = W.resolve()
diff --git a/code/modules/overmap/ships/engines/gas_thruster.dm b/code/modules/overmap/ships/engines/gas_thruster.dm
index c46e081e9a5..c9fa51950ed 100644
--- a/code/modules/overmap/ships/engines/gas_thruster.dm
+++ b/code/modules/overmap/ships/engines/gas_thruster.dm
@@ -66,6 +66,11 @@
power_channel = EQUIP
idle_power_usage = 21600 //6 Wh per tick for default 2 capacitor. Gives them a reason to turn it off, really to nerf backup battery
+ component_types = list(
+ /obj/item/circuitboard/unary_atmos/engine,
+ /obj/item/stack/cable_coil = 30,
+ /obj/item/pipe = 2)
+
var/datum/ship_engine/gas_thruster/controller
var/thrust_limit = 1 //Value between 1 and 0 to limit the resulting thrust
var/volume_per_burn = 15 //20 litres(with bin)
@@ -78,6 +83,10 @@
/obj/machinery/atmospherics/unary/engine/scc_shuttle
icon = 'icons/obj/spaceship/scc/ship_engine.dmi'
+ component_types = list(
+ /obj/item/circuitboard/unary_atmos/engine/scc_shuttle,
+ /obj/item/stack/cable_coil = 30,
+ /obj/item/pipe = 2)
/obj/machinery/atmospherics/unary/engine/scc_ship_engine
name = "ship thruster"
@@ -86,6 +95,19 @@
opacity = FALSE
pixel_x = -64
exhaust_offset = 3
+ component_types = list(
+ /obj/item/circuitboard/unary_atmos/engine/scc_ship,
+ /obj/item/stack/cable_coil = 30,
+ /obj/item/pipe = 2)
+
+/obj/machinery/atmospherics/unary/engine/attackby(obj/item/attacking_item, mob/user)
+ . = ..()
+ if(default_deconstruction_screwdriver(user, attacking_item))
+ return TRUE
+ if(default_deconstruction_crowbar(user, attacking_item))
+ return TRUE
+ if(default_part_replacement(user, attacking_item))
+ return TRUE
/obj/machinery/atmospherics/unary/engine/scc_ship_engine/check_blockage()
return 0
@@ -231,11 +253,3 @@
spawn(20)
qdel(src)
-/obj/item/circuitboard/unary_atmos/engine//why don't we move this elsewhere?
- name = T_BOARD("gas thruster")
- icon_state = "mcontroller"
- build_path = /obj/machinery/atmospherics/unary/engine
- origin_tech = list(TECH_POWER = 1, TECH_ENGINEERING = 2)
- req_components = list(
- /obj/item/stack/cable_coil = 30,
- /obj/item/pipe = 2)
diff --git a/code/modules/overmap/ships/engines/ion_thruster.dm b/code/modules/overmap/ships/engines/ion_thruster.dm
index 39e51a965e2..50d290f3474 100644
--- a/code/modules/overmap/ships/engines/ion_thruster.dm
+++ b/code/modules/overmap/ships/engines/ion_thruster.dm
@@ -43,6 +43,12 @@
power_channel = ENVIRON
idle_power_usage = 19600
anchored = TRUE
+ component_types = list(
+ /obj/item/circuitboard/engine/ion,
+ /obj/item/stack/cable_coil = 2,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/capacitor = 2
+ )
var/datum/ship_engine/ion/controller
var/thrust_limit = 1
@@ -75,13 +81,11 @@
/obj/machinery/ion_engine/proc/get_thrust()
return thrust_limit * generated_thrust * on
-/obj/item/circuitboard/engine/ion
- name = T_BOARD("ion propulsion device")
- board_type = "machine"
- icon_state = "mcontroller"
- build_path = /obj/machinery/ion_engine
- origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3)
- req_components = list(
- /obj/item/stack/cable_coil = 2,
- /obj/item/stock_parts/matter_bin = 1,
- /obj/item/stock_parts/capacitor = 2)
+/obj/machinery/ion_engine/attackby(obj/item/attacking_item, mob/user)
+ . = ..()
+ if(default_deconstruction_screwdriver(user, attacking_item))
+ return TRUE
+ if(default_deconstruction_crowbar(user, attacking_item))
+ return TRUE
+ if(default_part_replacement(user, attacking_item))
+ return TRUE
diff --git a/code/modules/overmap/ships/engines/maneuvering_thrusters.dm b/code/modules/overmap/ships/engines/maneuvering_thrusters.dm
index 14d6ba343db..53f64ed8f90 100644
--- a/code/modules/overmap/ships/engines/maneuvering_thrusters.dm
+++ b/code/modules/overmap/ships/engines/maneuvering_thrusters.dm
@@ -40,6 +40,12 @@
icon = 'icons/obj/ship_engine.dmi'
icon_state = "nozzle"
anchored = TRUE
+ component_types = list(
+ /obj/item/circuitboard/engine/maneuvering,
+ /obj/item/stack/cable_coil = 2,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/capacitor = 2
+ )
var/datum/ship_engine/maneuvering/controller
var/thrust_limit = 1
@@ -54,6 +60,15 @@
QDEL_NULL(controller)
return ..()
+/obj/machinery/maneuvering_engine/attackby(obj/item/attacking_item, mob/user)
+ . = ..()
+ if(default_deconstruction_screwdriver(user, attacking_item))
+ return TRUE
+ if(default_deconstruction_crowbar(user, attacking_item))
+ return TRUE
+ if(default_part_replacement(user, attacking_item))
+ return TRUE
+
/obj/machinery/maneuvering_engine/proc/get_status()
. = list()
.+= "Location: [get_area(src)]."
@@ -64,15 +79,3 @@
/obj/machinery/maneuvering_engine/proc/get_thrust()
return thrust_limit * generated_thrust * on
-
-/obj/item/circuitboard/engine/maneuvering
- name = T_BOARD("pulse-maneuvering device")
- board_type = "machine"
- icon_state = "mcontroller"
- build_path = /obj/machinery/maneuvering_engine
- origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3)
- req_components = list(
- /obj/item/stack/cable_coil = 2,
- /obj/item/stock_parts/matter_bin = 1,
- /obj/item/stock_parts/capacitor = 2
- )
diff --git a/code/modules/overmap/ships/identification.dm b/code/modules/overmap/ships/identification.dm
index 102932d4392..c48fcd8fe88 100644
--- a/code/modules/overmap/ships/identification.dm
+++ b/code/modules/overmap/ships/identification.dm
@@ -5,6 +5,12 @@
icon_state = "iff"
anchored = TRUE
idle_power_usage = 500
+ component_types = list(
+ /obj/item/circuitboard/iff_beacon,
+ /obj/item/stack/cable_coil = 2,
+ /obj/item/stock_parts/subspace/transmitter,
+ /obj/item/stock_parts/capacitor
+ )
var/datum/wires/iff/wires
var/disabled = FALSE
var/obfuscating = FALSE
@@ -25,6 +31,10 @@
/obj/machinery/iff_beacon/attackby(obj/item/attacking_item, mob/user)
if(default_deconstruction_screwdriver(user, attacking_item))
return TRUE
+ if(default_deconstruction_crowbar(user, attacking_item))
+ return TRUE
+ if(default_part_replacement(user, attacking_item))
+ return TRUE
if(panel_open)
if(attacking_item.ismultitool() || attacking_item.iswirecutter())
diff --git a/code/modules/research/designs/circuit/ship_circuits.dm b/code/modules/research/designs/circuit/ship_circuits.dm
new file mode 100644
index 00000000000..85f6eb031dc
--- /dev/null
+++ b/code/modules/research/designs/circuit/ship_circuits.dm
@@ -0,0 +1,34 @@
+/datum/design/circuit/ship
+ p_category = "Ship Component Circuit Designs"
+
+/datum/design/circuit/ship/engine
+ name = "Gas Propulsion Thruster"
+ req_tech = list(TECH_POWER = 1, TECH_ENGINEERING = 2)
+ build_path = /obj/item/circuitboard/unary_atmos/engine
+
+/datum/design/circuit/ship/engine/ion
+ name = "Ion Propulsion Engine"
+ req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6)
+ materials = list(MATERIAL_GOLD = 250, MATERIAL_GLASS = 2000)
+ build_path = /obj/item/circuitboard/engine/ion
+
+/datum/design/circuit/ship/sensors_weak
+ name = "Low-Power Sensor Suite"
+ req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 3, TECH_BLUESPACE = 1)
+ build_path = /obj/item/circuitboard/shipsensors/weak
+
+/datum/design/circuit/ship/sensors
+ name = "Sensor Suite"
+ req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 5, TECH_BLUESPACE = 3)
+ build_path = /obj/item/circuitboard/shipsensors
+
+/datum/design/circuit/ship/sensors_strong
+ name = "High-Power Sensor Suite"
+ req_tech = list(TECH_POWER = 6, TECH_ENGINEERING = 8, TECH_BLUESPACE = 5)
+ build_path = /obj/item/circuitboard/shipsensors/strong
+ materials = list(MATERIAL_GOLD = 250, MATERIAL_GLASS = 2000)
+
+/datum/design/circuit/ship/iff
+ name = "IFF Transponder"
+ req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 5, TECH_DATA = 3)
+ build_path = /obj/item/circuitboard/iff_beacon
diff --git a/html/changelogs/RustingWithYou - buildthemachine.yml b/html/changelogs/RustingWithYou - buildthemachine.yml
new file mode 100644
index 00000000000..bf12f286fbe
--- /dev/null
+++ b/html/changelogs/RustingWithYou - buildthemachine.yml
@@ -0,0 +1,58 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# - (fixes bugs)
+# wip
+# - (work in progress)
+# qol
+# - (quality of life)
+# soundadd
+# - (adds a sound)
+# sounddel
+# - (removes a sound)
+# rscadd
+# - (adds a feature)
+# rscdel
+# - (removes a feature)
+# imageadd
+# - (adds an image or sprite)
+# imagedel
+# - (removes an image or sprite)
+# spellcheck
+# - (fixes spelling or grammar)
+# experiment
+# - (experimental change)
+# balance
+# - (balance changes)
+# code_imp
+# - (misc internal code change)
+# refactor
+# - (refactors code)
+# config
+# - (makes a change to the config files)
+# admin
+# - (makes changes to administrator tools)
+# server
+# - (miscellaneous changes to server)
+#################################
+
+# Your name.
+author: RustingWithYou
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
+# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - qol: "Sensors, thrusters, and IFF beacons are now buildable and deconstructable."
diff --git a/tgui/packages/tgui/interfaces/Sensors.tsx b/tgui/packages/tgui/interfaces/Sensors.tsx
index e891d9b2b8f..ec72ca0e109 100644
--- a/tgui/packages/tgui/interfaces/Sensors.tsx
+++ b/tgui/packages/tgui/interfaces/Sensors.tsx
@@ -63,8 +63,12 @@ type DistressBeaconData = {
};
const SensorSection = function (act, data: SensorsData) {
- const range_choice_max = data.range_choices[data.range_choices.length - 1];
-
+ let range_choice_max = 0;
+ if (data.range_choices && data.range_choices.length) {
+ range_choice_max = data.range_choices[data.range_choices.length - 1];
+ } else {
+ range_choice_max = 0;
+ }
return (