NTNet Extensibility (#22908)

Fixes https://github.com/Aurorastation/Aurora.3/issues/21944

Spiritual successor of
https://github.com/Aurorastation/Aurora.3/pull/22352
Cherrypicked changes from the C3 Crew Management branch, this PR
contains all NTNet extensibility features, including Field Relay
construction, off-site camera usage (contingent on standing up remote
hardware and being out of jamming), etc. This also fixes a handful of
outstanding telecomms and view/mobeye-related bugs adjacent to where I
was working.

changes:
- rscadd: "Adds NTNet extensibility, requires new machinery constructed
on away-site z-levels."
- rscadd: "Breaks NTNet Relay machinery into Quantum Relay ('core' obj
on Horizon) and Field Relay (deployable off-site constructions)."
- qol: "Embedded cameras (basically every video camera EXCEPT those
which are installed on walls) can now be viewed from NTNet-connected
z-level, not just connected ones."
- rscadd: "Adds several public camera monitor consoles to the Horizon
(near where public sensor grid feed consoles already exist)."
- rscadd: "Adds some spare camera console boards to Horizon technical
storage."
- qol: "Adds action button for 'cancel-camera-view' verb while viewing
cameras or looking up/down z-level."
- bugfix: "Fixes Jockey comms (frequency was missing from ANTAG_FREQS)."
- bugfix: "Fixes look-up/look-down actions intermittently failing
without first using cancel-camera-view."
This commit is contained in:
Batrachophreno
2026-08-02 01:24:45 +00:00
committed by GitHub
parent 886ca9237f
commit 7172d3dbe3
48 changed files with 4864 additions and 4153 deletions
@@ -381,14 +381,23 @@
alarm_on = 0
GLOB.camera_alarm.clearAlarm(loc, src)
//if false, then the camera is listed as DEACTIVATED and cannot be used
/// If FALSE, then the camera is listed as DEACTIVATED and cannot be used
/obj/structure/machinery/camera/proc/can_use()
if(!status)
return 0
if(stat & (EMPED|BROKEN))
return 0
if(is_wireless_jammed())
return 0
return 1
/// Only used below, but has separate proc for potential future use.
/obj/structure/machinery/camera/proc/is_wireless_camera()
return !isturf(loc)
/obj/structure/machinery/camera/proc/is_wireless_jammed()
return is_wireless_camera() && get_turf(src) && within_jamming_range(src)
/obj/structure/machinery/camera/proc/can_see()
var/list/see = null
var/turf/pos = get_turf(src)
@@ -98,6 +98,7 @@
state = 4
var/obj/structure/machinery/camera/C = new(src.loc)
QDEL_NULL(C.assembly)
src.forceMove(C)
C.assembly = src
@@ -106,6 +107,10 @@
C.replace_networks(uniquelist(tempnetwork))
C.c_tag = input
C.setPowerUsage()
if(C.isMotion() && !(SSmachinery.processing[C]))
START_PROCESSING_MACHINE(C, MACHINERY_PROCESS_SELF)
C.update_coverage()
for(var/i = 5; i >= 0; i -= 1)
var/direct = tgui_input_list(user, "Direction?", "Assembling Camera", list("Confirm", "NORTH", "EAST", "SOUTH", "WEST"))
@@ -127,20 +132,35 @@
return TRUE
// Upgrades!
if(is_type_in_list(attacking_item, possible_upgrades) && !is_type_in_list(attacking_item, upgrades)) // Is a possible upgrade and isn't in the camera already.
var/upgrade_type
for(var/possible_upgrade in possible_upgrades)
if(istype(attacking_item, possible_upgrade))
upgrade_type = possible_upgrade
break
if(upgrade_type)
if(state != 3)
to_chat(user, SPAN_WARNING("You need to wire the assembly before installing upgrades."))
return TRUE
if(locate(upgrade_type) in upgrades)
to_chat(user, SPAN_WARNING("\The [src] already has that upgrade installed."))
return TRUE
if(istype(attacking_item, /obj/item/stock_parts/scanning_module))
var/obj/item/stock_parts/scanning_module/SM = attacking_item
if(SM.rating < 2)
to_chat(user, SPAN_WARNING("That scanning module doesn't seem advanced enough."))
return
return TRUE
to_chat(user, "You attach \the [attacking_item] into the assembly inner circuits.")
upgrades += attacking_item
user.remove_from_mob(attacking_item)
attacking_item.forceMove(src)
return
return TRUE
// Taking out upgrades
else if(attacking_item.tool_behaviour == TOOL_CROWBAR && upgrades.len)
if(state != 3)
to_chat(user, SPAN_WARNING("You need access to the wired circuits before removing upgrades."))
return TRUE
var/obj/U = locate(/obj) in upgrades
if(U)
to_chat(user, "You unattach an upgrade from the assembly.")
@@ -80,6 +80,9 @@ GLOBAL_LIST_INIT(engineering_networks, list(
/obj/structure/machinery/camera/network/news
network = list(NETWORK_NEWS)
/obj/structure/machinery/camera/network/expedition
network = list(NETWORK_EXPEDITION)
// EMP
/obj/structure/machinery/camera/emp_proof/Initialize()
@@ -26,13 +26,23 @@
camera_monitor_program = new("Compless")
// Make sure that camera_monitor knows its been generated from a dedicated console; this will define its network access.
camera_monitor_program.monitored_networks = console_networks
camera_monitor_program.ntnet_endpoint = src
camera_monitor_program.ntnet_endpoint_ethernet = TRUE
/obj/structure/machinery/computer/security/Destroy()
reset_remote_viewers()
if(camera_monitor_program)
camera_monitor_program.reset_current()
camera_monitor_program = null
. = ..()
/obj/structure/machinery/computer/security/proc/reset_remote_viewers()
for(var/mob/M in GLOB.player_list)
if(M.machine == src && M.is_viewing_remote_view())
M.unset_machine()
M.reset_view(null)
/obj/structure/machinery/computer/security/attack_ai(var/mob/user as mob)
if(!ai_can_interact(user))
return
@@ -41,6 +51,8 @@
/obj/structure/machinery/computer/security/check_eye(var/mob/user as mob)
if (user.stat || user.blinded || !operable())
return -1
if(camera_monitor_program?.current_camera)
return camera_monitor_program.check_eye(user)
if(!current_camera)
return 0
var/viewflag = current_camera.check_eye(user)
@@ -51,6 +63,8 @@
/obj/structure/machinery/computer/security/grants_equipment_vision(var/mob/user as mob)
if(user.stat || user.blinded || !operable())
return FALSE
if(camera_monitor_program?.current_camera)
return camera_monitor_program.grants_equipment_vision(user)
if(!current_camera)
return FALSE
var/viewflag = current_camera.check_eye(user)
@@ -91,7 +105,7 @@
. = camera_monitor_program.ui_act(action, params, ui, state)
/obj/structure/machinery/computer/security/attack_hand(var/mob/user as mob)
if (!(src.z in GetConnectedZlevels(starting_z_level)))
if (!(src.z in GetConnectedZlevels(starting_z_level)) && !SSatlas.current_map.is_always_available_network_level(src.z))
to_chat(user, "Unable to establish a connection.")
return
if(stat & (NOPOWER|BROKEN)) return
@@ -115,9 +129,11 @@
if (user.stat || user.blinded || !operable())
return 0
if(!C.can_use())
return 0
set_current(C)
if (!(C.z in GetConnectedZlevels(starting_z_level)))
if (!(C.z in GetConnectedZlevels(starting_z_level)) && !(SSatlas.current_map.is_always_available_network_level(src.z) && C.z == src.z))
to_chat(user, SPAN_NOTICE("This camera is too far away to connect to!"))
return FALSE
@@ -311,7 +327,7 @@
req_access = list(150)
/obj/structure/machinery/computer/security/terminal
name = "camera monitor terminal"
name = "public camera monitor"
icon = 'icons/obj/modular_computers/modular_terminal.dmi'
icon_screen = "cameras"
icon_keyboard = "security_key"
@@ -320,3 +336,7 @@
has_off_keyboards = TRUE
can_pass_under = FALSE
light_power_on = 1
/obj/structure/machinery/computer/security/terminal/public
console_networks = list(NETWORK_EXPEDITION, NETWORK_NEWS)
circuit = /obj/item/circuitboard/security/public