diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index d38200e7a71..0cf18591f2d 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -32257,7 +32257,6 @@
/obj/structure/tank_holder/extinguisher,
/obj/machinery/camera/directional/south{
c_tag = "Library - Art Gallery";
- default_camera_icon = "Service - Cafeteria Aft";
name = "library camera"
},
/turf/open/floor/wood/tile,
diff --git a/code/__DEFINES/cameranets.dm b/code/__DEFINES/cameranets.dm
index b88678db4a5..1dea0cd18ae 100644
--- a/code/__DEFINES/cameranets.dm
+++ b/code/__DEFINES/cameranets.dm
@@ -3,3 +3,26 @@
/// Takes a position, transforms it into a chunk bounded position. Indexes at 1 so it'll land on actual turfs always
#define GET_CHUNK_COORD(v) (max((FLOOR(v, CHUNK_SIZE)), 1))
+//List of different camera nets, cameras are given this in the map and camera consoles can only view them if
+//they share this network with them.
+#define CAMERANET_NETWORK_SS13 "ss13"
+#define CAMERANET_NETWORK_MINE "mine"
+#define CAMERANET_NETWORK_RD "rd"
+#define CAMERANET_NETWORK_LABOR "labor"
+#define CAMERANET_NETWORK_ORDNANCE "ordnance"
+#define CAMERANET_NETWORK_AUXBASE "auxbase"
+#define CAMERANET_NETWORK_VAULT "vault"
+#define CAMERANET_NETWORK_AI_CORE "aicore"
+#define CAMERANET_NETWORK_AI_UPLOAD "aiupload"
+#define CAMERANET_NETWORK_MINISAT "minisat"
+#define CAMERANET_NETWORK_XENOBIOLOGY "xeno"
+#define CAMERANET_NETWORK_TEST_CHAMBER "test"
+#define CAMERANET_NETWORK_PRISON "prison"
+#define CAMERANET_NETWORK_MEDBAY "medbay"
+#define CAMERANET_NETWORK_ENGINE "engine"
+#define CAMERANET_NETWORK_TELECOMMS "tcomms"
+#define CAMERANET_NETWORK_TURBINE "turbine"
+#define CAMERANET_NETWORK_THUNDERDOME "thunder"
+#define CAMERANET_NETWORK_BAR "bar"
+#define CAMERANET_NETWORK_INTERROGATION "interrogation"
+#define CAMERANET_NETWORK_ABDUCTOR "abductor"
diff --git a/code/__DEFINES/construction/structures.dm b/code/__DEFINES/construction/structures.dm
index e52b82f248e..1b4ea8aa112 100644
--- a/code/__DEFINES/construction/structures.dm
+++ b/code/__DEFINES/construction/structures.dm
@@ -83,3 +83,12 @@
#define FRAME_COMPUTER_STATE_WIRED 3
/// Frame has had glass applied to it
#define FRAME_COMPUTER_STATE_GLASSED 4
+
+///The camera assembly is wrenched in (aka placed on the wall), and wrenching will deconstruct.
+#define CAMERA_STATE_WRENCHED 1
+///The camera assembly is welded in place, so won't come off from wrench anymore.
+#define CAMERA_STATE_WELDED 2
+///The camera assembly is wired and ready to finish construction.
+#define CAMERA_STATE_WIRED 3
+///The camera assembly is finished construction fully, and is currently chilling in the camera machine.
+#define CAMERA_STATE_FINISHED 4
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index f0741f3d8f3..8f3ac9744da 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -255,7 +255,6 @@ GLOBAL_LIST_INIT(WALLITEMS_INTERIOR, typecacheof(list(
GLOBAL_LIST_INIT(WALLITEMS_EXTERIOR, typecacheof(list(
/obj/machinery/camera,
/obj/machinery/light,
- /obj/structure/camera_assembly,
/obj/structure/light_construct,
)))
diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm
index 8e3870acb47..cf8d9b23886 100644
--- a/code/datums/wires/robot.dm
+++ b/code/datums/wires/robot.dm
@@ -24,7 +24,7 @@
var/list/status = list()
status += "The law sync module is [R.lawupdate ? "on" : "off"]."
status += "The intelligence link display shows [R.connected_ai ? R.connected_ai.name : "NULL"]."
- status += "The camera light is [!isnull(R.builtInCamera) && R.builtInCamera.status ? "on" : "off"]."
+ status += "The camera light is [!isnull(R.builtInCamera) && R.builtInCamera.camera_enabled ? "on" : "off"]."
status += "The lockdown indicator is [R.lockcharge ? "on" : "off"]."
status += "There is a star symbol above the [get_color_of_wire(WIRE_RESET_MODEL)] wire."
return status
@@ -52,7 +52,7 @@
if(!QDELETED(R.builtInCamera) && !R.scrambledcodes)
R.builtInCamera.toggle_cam(usr, FALSE)
R.visible_message(span_notice("[R]'s camera lens focuses loudly."), span_notice("Your camera lens focuses loudly."))
- log_silicon("[key_name(usr)] toggled [key_name(R)]'s camera to [R.builtInCamera.status ? "on" : "off"] via pulse")
+ log_silicon("[key_name(usr)] toggled [key_name(R)]'s camera to [R.builtInCamera.camera_enabled ? "on" : "off"] via pulse")
if(WIRE_LAWSYNC) // Forces a law update if possible.
if(R.lawupdate)
R.visible_message(span_notice("[R] gently chimes."), span_notice("LawSync protocol engaged."))
@@ -90,7 +90,7 @@
R.logevent("Lawsync Module fault [mend ? "cleared" : "detected"]")
if (WIRE_CAMERA) // Disable the camera.
if(!QDELETED(R.builtInCamera) && !R.scrambledcodes)
- R.builtInCamera.status = mend
+ R.builtInCamera.camera_enabled = mend
R.builtInCamera.toggle_cam(usr, 0)
R.visible_message(span_notice("[R]'s camera lens focuses loudly."), span_notice("Your camera lens focuses loudly."))
R.logevent("Camera Module fault [mend?"cleared":"detected"]")
diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm
index 7a99de4dfdf..f6559d344c4 100644
--- a/code/game/area/ai_monitored.dm
+++ b/code/game/area/ai_monitored.dm
@@ -1,33 +1,31 @@
/area/station/ai_monitored
name = "\improper AI Monitored Area"
- var/list/obj/machinery/camera/motioncameras = list()
- var/list/datum/weakref/motionTargets = list()
sound_environment = SOUND_ENVIRONMENT_ROOM
+ var/list/obj/machinery/camera/motioncameras
+ var/list/datum/weakref/motionTargets = list()
/area/station/ai_monitored/Initialize(mapload)
. = ..()
- if(mapload)
- for (var/obj/machinery/camera/M in src)
- if(M.isMotion())
- motioncameras.Add(M)
- M.set_area_motion(src)
-
-//Only need to use one camera
+ if(!mapload)
+ return
+ for (var/obj/machinery/camera/ai_camera in src)
+ if(!ai_camera.isMotion())
+ continue
+ LAZYADD(motioncameras, ai_camera)
+ ai_camera.set_area_motion(src)
/area/station/ai_monitored/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
- if (ismob(arrived) && motioncameras.len)
- for(var/obj/machinery/camera/cam as anything in motioncameras)
- cam.newTarget(arrived)
- return
+ if (!ismob(arrived) || !LAZYLEN(motioncameras))
+ return
+ for(var/obj/machinery/camera/cam as anything in motioncameras)
+ cam.newTarget(arrived)
+ return
/area/station/ai_monitored/Exited(atom/movable/gone, atom/old_loc, list/atom/old_locs)
- ..()
- if (ismob(gone) && motioncameras.len)
- for(var/obj/machinery/camera/cam as anything in motioncameras)
- cam.lostTargetRef(WEAKREF(gone))
- return
-
-/area/station/ai_monitored/turret_protected/ai/Initialize(mapload)
. = ..()
- src.area_flags |= ABDUCTOR_PROOF
+ if (!ismob(gone) || !LAZYLEN(motioncameras))
+ return
+ for(var/obj/machinery/camera/cam as anything in motioncameras)
+ cam.lostTargetRef(WEAKREF(gone))
+ return
diff --git a/code/game/area/areas/ai_monitored.dm b/code/game/area/areas/ai_monitored.dm
index 0fc34c96abb..77ac5d6a2fd 100644
--- a/code/game/area/areas/ai_monitored.dm
+++ b/code/game/area/areas/ai_monitored.dm
@@ -47,6 +47,7 @@
name = "\improper AI Chamber"
icon_state = "ai_chamber"
ai_will_not_hear_this = null
+ area_flags = parent_type::area_flags | ABDUCTOR_PROOF
/area/station/ai_monitored/turret_protected/aisat
name = "\improper AI Satellite"
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index b4d4c4d3cea..058d78fab72 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -191,7 +191,7 @@
update_current_power_usage()
setup_area_power_relationship()
-/obj/machinery/Destroy()
+/obj/machinery/Destroy(force)
SSmachines.unregister_machine(src)
end_processing()
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index e3a26fb54b6..33dde81af58 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -1,8 +1,25 @@
+/**
+ * Camera assembly frame
+ * Putting this on a wall will put a deconstructed camera machine on the wall.
+ */
+/obj/item/wallframe/camera
+ name = "camera assembly"
+ desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
+ icon = 'icons/obj/machines/camera.dmi'
+ icon_state = "cameracase"
+ custom_materials = list(
+ /datum/material/iron = SMALL_MATERIAL_AMOUNT * 4,
+ /datum/material/glass = SMALL_MATERIAL_AMOUNT * 2.5,
+ )
+ result_path = /obj/machinery/camera/autoname/deconstructed
+ wall_external = TRUE
+
/obj/machinery/camera
name = "security camera"
desc = "It's used to monitor rooms."
icon = 'icons/obj/machines/camera.dmi'
- icon_state = "camera" //mapping icon to represent upgrade states. if you want a different base icon, update default_camera_icon as well as this.
+ icon_state = "camera"
+ base_icon_state = "camera"
use_power = ACTIVE_POWER_USE
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.02
layer = WALL_OBJ_LAYER
@@ -11,29 +28,54 @@
armor_type = /datum/armor/machinery_camera
max_integrity = 100
integrity_failure = 0.5
- var/default_camera_icon = "camera" //the camera's base icon used by update_appearance - icon_state is primarily used for mapping display purposes.
- var/list/network = list("ss13")
+
+ ///An analyzer in the camera being used for x-ray upgrade.
+ var/obj/item/analyzer/xray_module
+ ///used to keep from revealing malf AI upgrades for user facing isXRay() checks when they use Upgrade Camera Network ability
+ ///will be false if the camera is upgraded with the proper parts.
+ var/malf_xray_firmware_active
+ ///so the malf upgrade is restored when the normal upgrade part is removed.
+ var/malf_xray_firmware_present
+ ///A sheet of plasma stored inside of the camera, giving it EMP protection.
+ var/obj/item/stack/sheet/mineral/plasma/emp_module
+ ///used to keep from revealing malf AI upgrades for user facing isEmp() checks after they use Upgrade Camera Network ability
+ ///will be false if the camera is upgraded with the proper parts.
+ var/malf_emp_firmware_active
+ ///so the malf upgrade is restored when the normal upgrade part is removed.
+ var/malf_emp_firmware_present
+
+ ///The current state of the camera's construction, all mapped in ones start off already built.
+ var/camera_construction_state = CAMERA_STATE_FINISHED
+
+ ///Bitflag of upgrades this camera has: (CAMERA_UPGRADE_XRAY | CAMERA_UPGRADE_EMP_PROOF | CAMERA_UPGRADE_MOTION)
+ var/camera_upgrade_bitflags = NONE
+
+ ///List of all networks that can see this camera through the security console.
+ var/list/network = list(CAMERANET_NETWORK_SS13)
+ ///The tag the camera has, which is essentially its name to security camera consoles.
var/c_tag = null
- var/status = TRUE
- var/start_active = FALSE //If it ignores the random chance to start broken on round start
- var/invuln = null
- var/datum/weakref/assembly_ref = null
+ ///Boolean on whether the camera is activated, so can be seen on camera consoles or will just be static.
+ var/camera_enabled = TRUE
+ ///Boolean for special cameras to bypass the random chance of being broken on roundstart.
+ var/start_active = FALSE
+ ///The area this camera is built in, which we will add/remove ourselves to the list of cameras in that area from.
var/area/myarea = null
- //OTHER
-
+ ///The max range (and default range) the camera can see.
var/view_range = 7
+ ///The short range the camera can see, if tampered with to be short-sighted.
var/short_range = 2
+ ///Boolean on whether the camera's alarm is triggered.
var/alarm_on = FALSE
- var/busy = FALSE
- var/emped = FALSE //Number of consecutive EMP's on this camera
+ ///How many times this camera has been EMP'ed consecutively, will reset back to 0 when fixed.
+ var/emped
+ ///Boolean on whether the AI can even turn on this camera's light- borg caneras dont have one, for example.
+ var/internal_light = TRUE
+ ///Number of AIs watching this camera with lights on, used for icons.
var/in_use_lights = 0
- // Upgrades bitflag
- var/upgrades = 0
- var/internal_light = TRUE //Whether it can light up when an AI views it
- ///Represents a signel source of camera alarms about movement or camera tampering
+ ///Represents a signal source of camera alarms about movement or camera tampering
var/datum/alarm_handler/alarm_manager
///Proximity monitor associated with this atom, for motion sensitive cameras.
var/datum/proximity_monitor/proximity_monitor
@@ -41,6 +83,11 @@
/// A copy of the last paper object that was shown to this camera.
var/obj/item/paper/last_shown_paper
+ var/list/datum/weakref/localMotionTargets = list()
+ var/detectTime = 0
+ var/area/station/ai_monitored/area_motion = null
+ var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
+
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera, 0)
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/autoname, 0)
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/emp_proof, 0)
@@ -55,51 +102,27 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
fire = 90
acid = 50
-/obj/machinery/camera/preset/ordnance //Bomb test site in space
- name = "Hardened Bomb-Test Camera"
- desc = "A specially-reinforced camera with a long lasting battery, used to monitor the bomb testing site. An external light is attached to the top."
- c_tag = "Bomb Testing Site"
- network = list("rd","ordnance")
- use_power = NO_POWER_USE //Test site is an unpowered area
- invuln = TRUE
- light_range = 10
- start_active = TRUE
-
-/obj/machinery/camera/Initialize(mapload, obj/structure/camera_assembly/old_assembly)
+/obj/machinery/camera/Initialize(mapload, ndir, building)
. = ..()
- for(var/i in network)
- network -= i
- network += lowertext(i)
- var/obj/structure/camera_assembly/assembly
- if(old_assembly) //check to see if the camera assembly was upgraded at all.
- assembly = old_assembly
- assembly_ref = WEAKREF(assembly) //important to do this now since upgrades call back to the assembly_ref
- if(assembly.xray_module)
- upgradeXRay()
- else if(assembly.malf_xray_firmware_present) //if it was secretly upgraded via the MALF AI Upgrade Camera Network ability
- upgradeXRay(TRUE)
- if(assembly.emp_module)
- upgradeEmpProof()
- else if(assembly.malf_xray_firmware_present) //if it was secretly upgraded via the MALF AI Upgrade Camera Network ability
- upgradeEmpProof(TRUE)
+ if(building)
+ setDir(ndir)
+
+ for(var/network_name in network)
+ network -= network_name
+ network += lowertext(network_name)
- if(assembly.proxy_module)
- upgradeMotion()
- else
- assembly = new(src)
- assembly.state = 4 //STATE_FINISHED
- assembly_ref = WEAKREF(assembly)
GLOB.cameranet.cameras += src
- GLOB.cameranet.addCamera(src)
+
myarea = get_room_area()
- LAZYADD(myarea.cameras, src)
-
- if(mapload && is_station_level(z) && prob(3) && !start_active)
- toggle_cam()
- else //this is handled by toggle_camera, so no need to update it twice.
- update_appearance()
+ if(camera_enabled)
+ GLOB.cameranet.addCamera(src)
+ LAZYADD(myarea.cameras, src)
+ if(mapload && !start_active && is_station_level(z) && prob(3))
+ toggle_cam()
+ else //this is handled by toggle_camera, so no need to update it twice.
+ update_appearance()
alarm_manager = new(src)
find_and_hang_on_wall(directional = TRUE, \
@@ -107,11 +130,45 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur))
+/obj/machinery/camera/Destroy(force)
+ if(can_use())
+ toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
+ GLOB.cameranet.removeCamera(src)
+ GLOB.cameranet.cameras -= src
+ cancelCameraAlarm()
+ if(isarea(myarea))
+ LAZYREMOVE(myarea.cameras, src)
+ QDEL_NULL(alarm_manager)
+ QDEL_NULL(last_shown_paper)
+ QDEL_NULL(xray_module)
+ QDEL_NULL(emp_module)
+ QDEL_NULL(proximity_monitor)
+ return ..()
+
/obj/machinery/camera/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
for(var/i in network)
network -= i
network += "[port.shuttle_id]_[i]"
+/obj/machinery/camera/Exited(atom/movable/gone, direction)
+ . = ..()
+ if(gone == xray_module)
+ xray_module = null
+ update_appearance()
+ if(malf_xray_firmware_present)
+ malf_xray_firmware_active = malf_xray_firmware_present //re-enable firmware based upgrades after the part is removed.
+ removeXRay(malf_xray_firmware_present) //make sure we don't remove MALF upgrades.
+
+ else if(gone == emp_module)
+ emp_module = null
+ if(malf_emp_firmware_present)
+ malf_emp_firmware_active = malf_emp_firmware_present //re-enable firmware based upgrades after the part is removed.
+ removeEmpProof(malf_emp_firmware_present) //make sure we don't remove MALF upgrades
+
+ else if(gone == proximity_monitor)
+ emp_module = null
+ removeMotion()
+
/obj/machinery/camera/proc/create_prox_monitor()
if(!proximity_monitor)
proximity_monitor = new(src, 1)
@@ -125,63 +182,53 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
area_motion = A
create_prox_monitor()
-/obj/machinery/camera/Destroy()
- if(can_use())
- toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
- GLOB.cameranet.removeCamera(src)
- GLOB.cameranet.cameras -= src
- cancelCameraAlarm()
- if(isarea(myarea))
- LAZYREMOVE(myarea.cameras, src)
- QDEL_NULL(alarm_manager)
- QDEL_NULL(assembly_ref)
- QDEL_NULL(last_shown_paper)
- return ..()
-
/obj/machinery/camera/examine(mob/user)
. = ..()
+
if(isEmpProof(TRUE)) //don't reveal it's upgraded if was done via MALF AI Upgrade Camera Network ability
. += span_info("It has electromagnetic interference shielding installed.")
else
. += span_info("It can be shielded against electromagnetic interference with some plasma.")
+
if(isXRay(TRUE)) //don't reveal it's upgraded if was done via MALF AI Upgrade Camera Network ability
. += span_info("It has an X-ray photodiode installed.")
else
. += span_info("It can be upgraded with an X-ray photodiode with an analyzer.")
+
if(isMotion())
. += span_info("It has a proximity sensor installed.")
else
. += span_info("It can be upgraded with a proximity sensor.")
- if(!status)
+ if(!camera_enabled)
. += span_info("It's currently deactivated.")
if(!panel_open && powered())
. += span_notice("You'll need to open its maintenance panel with a screwdriver to turn it back on.")
+
if(panel_open)
. += span_info("Its maintenance panel is currently open.")
- if(!status && powered())
+ if(!camera_enabled && powered())
. += span_info("It can reactivated with wirecutters.")
/obj/machinery/camera/emp_act(severity, reset_time = 90 SECONDS)
. = ..()
- if(!status)
+ if(!camera_enabled)
return
- if(!(. & EMP_PROTECT_SELF))
- if(prob(150/severity))
- update_appearance()
- network = list()
- GLOB.cameranet.removeCamera(src)
- set_machine_stat(machine_stat | EMPED)
- set_light(0)
- emped = emped+1 //Increase the number of consecutive EMP's
- update_appearance()
- addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time)
- for(var/i in GLOB.player_list)
- var/mob/M = i
- if (M.client?.eye == src)
- M.unset_machine()
- M.reset_perspective(null)
- to_chat(M, span_warning("The screen bursts into static!"))
+ if(. & EMP_PROTECT_SELF)
+ return
+ if(prob(150 / severity))
+ network = list()
+ GLOB.cameranet.removeCamera(src)
+ set_machine_stat(machine_stat | EMPED)
+ set_light(0)
+ emped++ //Increase the number of consecutive EMP's
+ update_appearance()
+ addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time)
+ for(var/mob/M as anything in GLOB.player_list)
+ if (M.client?.eye == src)
+ M.unset_machine()
+ M.reset_perspective(null)
+ to_chat(M, span_warning("The screen bursts into static!"))
/obj/machinery/camera/proc/on_saboteur(datum/source, disrupt_duration)
SIGNAL_HANDLER
@@ -203,11 +250,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
emped = 0 //Resets the consecutive EMP count
addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), 10 SECONDS)
-/obj/machinery/camera/ex_act(severity, target)
- if(invuln)
- return FALSE
- return ..()
-
/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user)
if (!istype(user))
return
@@ -225,211 +267,26 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
user.electrocute_act(10, src)
/obj/machinery/camera/singularity_pull(S, current_size)
- if (status && current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects and the camera is still active, turn off the camera as it gets ripped off the wall.
+ if (camera_enabled && current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects and the camera is still active, turn off the camera as it gets ripped off the wall.
toggle_cam(null, 0)
- ..()
-
-// Construction/Deconstruction
-/obj/machinery/camera/screwdriver_act(mob/living/user, obj/item/I)
- if(..())
- return TRUE
- toggle_panel_open()
- to_chat(user, span_notice("You screw the camera's panel [panel_open ? "open" : "closed"]."))
- I.play_tool_sound(src)
- update_appearance()
- return TRUE
-
-/obj/machinery/camera/crowbar_act(mob/living/user, obj/item/I)
- . = ..()
- if(!panel_open)
- return
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
- if(!assembly)
- assembly_ref = null
- return
- var/list/droppable_parts = list()
- if(assembly.xray_module)
- droppable_parts += assembly.xray_module
- if(assembly.emp_module)
- droppable_parts += assembly.emp_module
- if(assembly.proxy_module)
- droppable_parts += assembly.proxy_module
- if(!length(droppable_parts))
- return
- var/obj/item/choice = tgui_input_list(user, "Select a part to remove", "Part Removal", sort_names(droppable_parts))
- if(isnull(choice))
- return
- if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
- return
- to_chat(user, span_notice("You remove [choice] from [src]."))
- if(choice == assembly.xray_module)
- assembly.drop_upgrade(assembly.xray_module)
- removeXRay()
- if(choice == assembly.emp_module)
- assembly.drop_upgrade(assembly.emp_module)
- removeEmpProof()
- if(choice == assembly.proxy_module)
- assembly.drop_upgrade(assembly.proxy_module)
- removeMotion()
- I.play_tool_sound(src)
- return TRUE
-
-/obj/machinery/camera/wirecutter_act(mob/living/user, obj/item/I)
- . = ..()
- if(!panel_open)
- return
- toggle_cam(user, 1)
- atom_integrity = max_integrity //this is a pretty simplistic way to heal the camera, but there's no reason for this to be complex.
- set_machine_stat(machine_stat & ~BROKEN)
- I.play_tool_sound(src)
- return TRUE
-
-/obj/machinery/camera/multitool_act(mob/living/user, obj/item/I)
- . = ..()
- if(!panel_open)
- return
-
- setViewRange((view_range == initial(view_range)) ? short_range : initial(view_range))
- to_chat(user, span_notice("You [(view_range == initial(view_range)) ? "restore" : "mess up"] the camera's focus."))
- return TRUE
-
-/obj/machinery/camera/welder_act(mob/living/user, obj/item/I)
- . = ..()
- if(!panel_open)
- return
-
- if(!I.tool_start_check(user, amount=2))
- return TRUE
-
- to_chat(user, span_notice("You start to weld [src]..."))
- if(I.use_tool(src, user, 100, volume=50))
- user.visible_message(span_warning("[user] unwelds [src], leaving it as just a frame bolted to the wall."),
- span_warning("You unweld [src], leaving it as just a frame bolted to the wall"))
- deconstruct(TRUE)
-
- return TRUE
-
-/obj/machinery/camera/attackby(obj/item/attacking_item, mob/living/user, params)
- // UPGRADES
- if(panel_open)
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
- if(!assembly)
- assembly_ref = null
- if(attacking_item.tool_behaviour == TOOL_ANALYZER)
- if(!isXRay(TRUE)) //don't reveal it was already upgraded if was done via MALF AI Upgrade Camera Network ability
- if(!user.temporarilyRemoveItemFromInventory(attacking_item))
- return
- upgradeXRay(FALSE, TRUE)
- to_chat(user, span_notice("You attach [attacking_item] into [assembly]'s inner circuits."))
- qdel(attacking_item)
- else
- to_chat(user, span_warning("[src] already has that upgrade!"))
- return
-
- else if(istype(attacking_item, /obj/item/stack/sheet/mineral/plasma))
- if(!isEmpProof(TRUE)) //don't reveal it was already upgraded if was done via MALF AI Upgrade Camera Network ability
- if(attacking_item.use_tool(src, user, 0, amount=1))
- upgradeEmpProof(FALSE, TRUE)
- to_chat(user, span_notice("You attach [attacking_item] into [assembly]'s inner circuits."))
- else
- to_chat(user, span_warning("[src] already has that upgrade!"))
- return
-
- else if(isprox(attacking_item))
- if(!isMotion())
- if(!user.temporarilyRemoveItemFromInventory(attacking_item))
- return
- upgradeMotion()
- to_chat(user, span_notice("You attach [attacking_item] into [assembly]'s inner circuits."))
- qdel(attacking_item)
- else
- to_chat(user, span_warning("[src] already has that upgrade!"))
- return
-
- // OTHER
- if(istype(attacking_item, /obj/item/modular_computer))
- var/itemname = ""
- var/info = ""
-
- var/obj/item/modular_computer/computer = attacking_item
- for(var/datum/computer_file/program/notepad/notepad_app in computer.stored_files)
- info = notepad_app.written_note
- break
-
- itemname = computer.name
- itemname = sanitize(itemname)
- info = sanitize(info)
- to_chat(user, span_notice("You hold \the [itemname] up to the camera..."))
- user.log_talk(itemname, LOG_GAME, log_globally=TRUE, tag="Pressed to camera")
- user.changeNext_move(CLICK_CD_MELEE)
-
- for(var/mob/potential_viewer as anything in GLOB.player_list)
- if(isAI(potential_viewer))
- var/mob/living/silicon/ai/ai = potential_viewer
- if(ai.control_disabled || (ai.stat == DEAD))
- continue
-
- ai.log_talk(itemname, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
- ai.last_tablet_note_seen = "
[itemname][info]"
-
- if(user.name == "Unknown")
- to_chat(ai, "[span_name(user)] holds \a [itemname] up to one of your cameras ...")
- else
- to_chat(ai, "[user] holds \a [itemname] up to one of your cameras ...")
- continue
-
- if (potential_viewer.client?.eye == src)
- to_chat(potential_viewer, "[span_name("[user]")] holds \a [itemname] up to one of the cameras ...")
- potential_viewer.log_talk(itemname, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
- potential_viewer << browse("[itemname][info]", "window=[itemname]")
- return
-
- if(istype(attacking_item, /obj/item/paper))
- // Grab the paper, sanitise the name as we're about to just throw it into chat wrapped in HTML tags.
- var/obj/item/paper/paper = attacking_item
-
- // Make a complete copy of the paper, store a ref to it locally on the camera.
- last_shown_paper = paper.copy(paper.type, null);
-
- // Then sanitise the name because we're putting it directly in chat later.
- var/item_name = sanitize(last_shown_paper.name)
-
- // Start the process of holding it up to the camera.
- to_chat(user, span_notice("You hold \the [item_name] up to the camera..."))
- user.log_talk(item_name, LOG_GAME, log_globally=TRUE, tag="Pressed to camera")
- user.changeNext_move(CLICK_CD_MELEE)
-
- // And make a weakref we can throw around to all potential viewers.
- last_shown_paper.camera_holder = WEAKREF(src)
-
- // Iterate over all living mobs and check if anyone is elibile to view the paper.
- // This is backwards, but cameras don't store a list of people that are looking through them,
- // and we'll have to iterate this list anyway so we can use it to pull out AIs too.
- for(var/mob/potential_viewer in GLOB.player_list)
- // All AIs view through cameras, so we need to check them regardless.
- if(isAI(potential_viewer))
- var/mob/living/silicon/ai/ai = potential_viewer
- if(ai.control_disabled || (ai.stat == DEAD))
- continue
-
- ai.log_talk(item_name, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
- log_paper("[key_name(user)] held [last_shown_paper] up to [src], requesting [key_name(ai)] read it.")
-
- if(user.name == "Unknown")
- to_chat(ai, "[span_name(user.name)] holds \a [item_name] up to one of your cameras ...")
- else
- to_chat(ai, "[user] holds \a [item_name] up to one of your cameras ...")
- continue
-
- // If it's not an AI, eye if the client's eye is set to the camera. I wonder if this even works anymore with tgui camera apps and stuff?
- if (potential_viewer.client?.eye == src)
- log_paper("[key_name(user)] held [last_shown_paper] up to [src], and [key_name(potential_viewer)] may read it.")
- potential_viewer.log_talk(item_name, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
- to_chat(potential_viewer, "[span_name(user)] holds \a [item_name] up to your camera...")
- return
-
return ..()
+///Drops a specific upgrade and nulls it where necessary.
+/obj/machinery/camera/proc/drop_upgrade(obj/item/upgrade_dropped)
+ upgrade_dropped.forceMove(drop_location())
+ if(upgrade_dropped == xray_module)
+ xray_module = null
+ if(malf_xray_firmware_present)
+ malf_xray_firmware_active = malf_xray_firmware_present //re-enable firmware based upgrades after the part is removed.
+ update_appearance()
+
+ else if(upgrade_dropped == emp_module)
+ emp_module = null
+ if(malf_emp_firmware_present)
+ malf_emp_firmware_active = malf_emp_firmware_present //re-enable firmware based upgrades after the part is removed.
+
+ else if(upgrade_dropped == proximity_monitor)
+ proximity_monitor = null
/obj/machinery/camera/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
if(machine_stat & BROKEN)
@@ -437,7 +294,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
. = ..()
/obj/machinery/camera/atom_break(damage_flag)
- if(!status)
+ if(!camera_enabled)
return
. = ..()
if(.)
@@ -445,36 +302,40 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
toggle_cam(null, 0)
/obj/machinery/camera/on_deconstruction(disassembled)
- if(disassembled)
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
- if(!assembly)
- assembly = new()
- assembly.forceMove(drop_location())
- assembly.state = 1
- assembly.setDir(dir)
- assembly_ref = null
- return
-
- var/obj/item/I = new /obj/item/wallframe/camera (loc)
- I.update_integrity(I.max_integrity * 0.5)
- new /obj/item/stack/cable_coil(loc, 2)
+ if(!(obj_flags & NO_DECONSTRUCTION))
+ if(disassembled)
+ var/obj/item/wallframe/camera/dropped_cam = new(drop_location())
+ dropped_cam.update_integrity(dropped_cam.max_integrity * 0.5)
+ if(camera_construction_state >= CAMERA_STATE_WIRED)
+ new /obj/item/stack/cable_coil(drop_location(), 2)
+ if(xray_module)
+ drop_upgrade(xray_module)
+ if(emp_module)
+ drop_upgrade(emp_module)
+ if(proximity_monitor)
+ drop_upgrade(proximity_monitor)
+ else
+ if(camera_construction_state >= CAMERA_STATE_WIRED)
+ new /obj/item/stack/cable_coil(drop_location(), 2)
+ new /obj/item/stack/sheet/iron(loc)
+ return ..()
/obj/machinery/camera/update_icon_state() //TO-DO: Make panel open states, xray camera, and indicator lights overlays instead.
var/xray_module
if(isXRay(TRUE))
xray_module = "xray"
- if(!status)
- icon_state = "[xray_module][default_camera_icon]_off"
+ if(!camera_enabled)
+ icon_state = "[xray_module][base_icon_state]_off"
return ..()
if(machine_stat & EMPED)
- icon_state = "[xray_module][default_camera_icon]_emp"
+ icon_state = "[xray_module][base_icon_state]_emp"
return ..()
- icon_state = "[xray_module][default_camera_icon][in_use_lights ? "_in_use" : ""]"
+ icon_state = "[xray_module][base_icon_state][in_use_lights ? "_in_use" : ""]"
return ..()
/obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = TRUE)
- status = !status
+ camera_enabled = !camera_enabled
if(can_use())
GLOB.cameranet.addCamera(src)
if (isturf(loc))
@@ -491,7 +352,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
var/turf/our_turf = get_turf(src)
GLOB.cameranet.updateChunk(our_turf.x, our_turf.y, our_turf.z)
var/change_msg = "deactivates"
- if(status)
+ if(camera_enabled)
change_msg = "reactivates"
triggerCameraAlarm()
if(!QDELETED(src)) //We'll be doing it anyway in destroy
@@ -509,7 +370,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
// now disconnect anyone using the camera
//Apparently, this will disconnect anyone even if the camera was re-activated.
//I guess that doesn't matter since they can't use it anyway?
- for(var/mob/O in GLOB.player_list)
+ for(var/mob/O as anything in GLOB.player_list)
if (O.client?.eye == src)
O.unset_machine()
O.reset_perspective(null)
@@ -524,7 +385,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
alarm_manager.clear_alarm(ALARM_CAMERA)
/obj/machinery/camera/proc/can_use()
- if(!status)
+ if(!camera_enabled)
return FALSE
if(machine_stat & EMPED)
return FALSE
@@ -581,4 +442,4 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
user.add_sight(SEE_TURFS|SEE_MOBS|SEE_OBJS)
else
user.clear_sight(SEE_TURFS|SEE_MOBS|SEE_OBJS)
- return 1
+ return TRUE
diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm
deleted file mode 100644
index e684b383e36..00000000000
--- a/code/game/machinery/camera/camera_assembly.dm
+++ /dev/null
@@ -1,280 +0,0 @@
-#define STATE_WRENCHED 1
-#define STATE_WELDED 2
-#define STATE_WIRED 3
-#define STATE_FINISHED 4
-
-/obj/item/wallframe/camera
- name = "camera assembly"
- desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
- icon = 'icons/obj/machines/camera.dmi'
- icon_state = "cameracase"
- custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT * 4, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 2.5)
- result_path = /obj/structure/camera_assembly
- wall_external = TRUE
-
-/obj/structure/camera_assembly
- name = "camera assembly"
- desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
- icon = 'icons/obj/machines/camera.dmi'
- icon_state = "camera_assembly"
- max_integrity = 150
- // Motion, EMP-Proof, X-ray
- var/obj/item/analyzer/xray_module
- var/malf_xray_firmware_active //used to keep from revealing malf AI upgrades for user facing isXRay() checks when they use Upgrade Camera Network ability
- //will be false if the camera is upgraded with the proper parts.
- var/malf_xray_firmware_present //so the malf upgrade is restored when the normal upgrade part is removed.
- var/obj/item/stack/sheet/mineral/plasma/emp_module
- var/malf_emp_firmware_active //used to keep from revealing malf AI upgrades for user facing isEmp() checks after they use Upgrade Camera Network ability
- //will be false if the camera is upgraded with the proper parts.
- var/malf_emp_firmware_present //so the malf upgrade is restored when the normal upgrade part is removed.
- var/obj/item/assembly/prox_sensor/proxy_module
- var/state = STATE_WRENCHED
-
-/obj/structure/camera_assembly/examine(mob/user)
- . = ..()
- //upgrade messages
- var/has_upgrades
- if(emp_module)
- . += span_info("It has electromagnetic interference shielding installed.")
- has_upgrades = TRUE
- else if(state == STATE_WIRED)
- . += span_info("It can be shielded against electromagnetic interference with some plasma.")
- if(xray_module)
- . += span_info("It has an X-ray photodiode installed.")
- has_upgrades = TRUE
- else if(state == STATE_WIRED)
- . += span_info("It can be upgraded with an X-ray photodiode with an analyzer.")
- if(proxy_module)
- . += span_info("It has a proximity sensor installed.")
- has_upgrades = TRUE
- else if(state == STATE_WIRED)
- . += span_info("It can be upgraded with a proximity sensor.")
-
- //construction states
- switch(state)
- if(STATE_WRENCHED)
- . += span_info("You can secure it in place with a welder, or removed with a wrench.")
- if(STATE_WELDED)
- . += span_info("You can add wires to it, or unweld it from the wall.")
- if(STATE_WIRED)
- if(has_upgrades)
- . += span_info("You can remove the contained upgrades with a crowbar.")
- . += span_info("You can complete it with a screwdriver, or unwire it to start removal.")
- if(STATE_FINISHED)
- . += span_boldwarning("You shouldn't be seeing this, tell a coder!")
-
-/obj/structure/camera_assembly/Initialize(mapload, ndir, building)
- . = ..()
- if(building)
- setDir(ndir)
- find_and_hang_on_wall()
-
-/obj/structure/camera_assembly/update_icon_state()
- icon_state = "[xray_module ? "xray" : null][initial(icon_state)]"
- return ..()
-
-/obj/structure/camera_assembly/Exited(atom/movable/gone, direction)
- . = ..()
- if(gone == xray_module)
- xray_module = null
- update_appearance()
- if(malf_xray_firmware_present)
- malf_xray_firmware_active = malf_xray_firmware_present //re-enable firmware based upgrades after the part is removed.
- if(istype(loc, /obj/machinery/camera))
- var/obj/machinery/camera/contained_camera = loc
- contained_camera.removeXRay(malf_xray_firmware_present) //make sure we don't remove MALF upgrades.
-
- else if(gone == emp_module)
- emp_module = null
- if(malf_emp_firmware_present)
- malf_emp_firmware_active = malf_emp_firmware_present //re-enable firmware based upgrades after the part is removed.
- if(istype(loc, /obj/machinery/camera))
- var/obj/machinery/camera/contained_camera = loc
- contained_camera.removeEmpProof(malf_emp_firmware_present) //make sure we don't remove MALF upgrades
-
- else if(gone == proxy_module)
- emp_module = null
- if(istype(loc, /obj/machinery/camera))
- var/obj/machinery/camera/contained_camera = loc
- contained_camera.removeMotion()
-
-
-/obj/structure/camera_assembly/Destroy()
- QDEL_NULL(xray_module)
- QDEL_NULL(emp_module)
- QDEL_NULL(proxy_module)
- return ..()
-
-/obj/structure/camera_assembly/proc/drop_upgrade(obj/item/I)
- I.forceMove(drop_location())
- if(I == xray_module)
- xray_module = null
- if(malf_xray_firmware_present)
- malf_xray_firmware_active = malf_xray_firmware_present //re-enable firmware based upgrades after the part is removed.
- update_appearance()
-
- else if(I == emp_module)
- emp_module = null
- if(malf_emp_firmware_present)
- malf_emp_firmware_active = malf_emp_firmware_present //re-enable firmware based upgrades after the part is removed.
-
- else if(I == proxy_module)
- proxy_module = null
-
-/obj/structure/camera_assembly/welder_act(mob/living/user, obj/item/tool)
- if(state != STATE_WRENCHED && state != STATE_WELDED)
- return
- . = TRUE
- if(!tool.tool_start_check(user, amount=1))
- return
- user.balloon_alert_to_viewers("[state == STATE_WELDED ? "un" : null]welding...")
- audible_message(span_hear("You hear welding."))
- if(!tool.use_tool(src, user, 2 SECONDS, volume = 50))
- user.balloon_alert_to_viewers("stopped [state == STATE_WELDED ? "un" : null]welding!")
- return
- state = ((state == STATE_WELDED) ? STATE_WRENCHED : STATE_WELDED)
- set_anchored(state == STATE_WELDED)
- user.balloon_alert_to_viewers(state == STATE_WELDED ? "welded" : "unwelded")
-
-
-/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params)
- switch(state)
- if(STATE_WELDED)
- if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = W
- if(C.use(2))
- to_chat(user, span_notice("You add wires to [src]."))
- state = STATE_WIRED
- else
- to_chat(user, span_warning("You need two lengths of cable to wire a camera!"))
- return
- if(STATE_WIRED) // Upgrades!
- if(istype(W, /obj/item/stack/sheet/mineral/plasma)) //emp upgrade
- if(emp_module)
- to_chat(user, span_warning("[src] already contains a [emp_module]!"))
- return
- if(!W.use_tool(src, user, 0, amount=1)) //only use one sheet, otherwise the whole stack will be consumed.
- return
- emp_module = new(src)
- if(malf_xray_firmware_active)
- malf_xray_firmware_active = FALSE //flavor reason: MALF AI Upgrade Camera Network ability's firmware is incompatible with the new part
- //real reason: make it a normal upgrade so the finished camera's icons and examine texts are restored.
- to_chat(user, span_notice("You attach [W] into [src]'s inner circuits."))
- return
-
- else if(istype(W, /obj/item/analyzer)) //xray upgrade
- if(xray_module)
- to_chat(user, span_warning("[src] already contains a [xray_module]!"))
- return
- if(!user.transferItemToLoc(W, src))
- return
- to_chat(user, span_notice("You attach [W] into [src]'s inner circuits."))
- xray_module = W
- if(malf_xray_firmware_active)
- malf_xray_firmware_active = FALSE //flavor reason: MALF AI Upgrade Camera Network ability's firmware is incompatible with the new part
- //real reason: make it a normal upgrade so the finished camera's icons and examine texts are restored.
- update_appearance()
- return
-
- else if(isprox(W)) //motion sensing upgrade
- if(proxy_module)
- to_chat(user, span_warning("[src] already contains a [proxy_module]!"))
- return
- if(!user.transferItemToLoc(W, src))
- return
- to_chat(user, span_notice("You attach [W] into [src]'s inner circuits."))
- proxy_module = W
- return
-
- return ..()
-
-/obj/structure/camera_assembly/crowbar_act(mob/user, obj/item/tool)
- if(state != STATE_WIRED)
- return FALSE
- var/list/droppable_parts = list()
- if(xray_module)
- droppable_parts += xray_module
- if(emp_module)
- droppable_parts += emp_module
- if(proxy_module)
- droppable_parts += proxy_module
- if(!length(droppable_parts))
- return
- var/obj/item/choice = tgui_input_list(user, "Select a part to remove", "Part Removal", sort_names(droppable_parts))
- if(isnull(choice))
- return
- if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
- return
- to_chat(user, span_notice("You remove [choice] from [src]."))
- drop_upgrade(choice)
- tool.play_tool_sound(src)
- return TRUE
-
-/obj/structure/camera_assembly/screwdriver_act(mob/user, obj/item/tool)
- . = ..()
- if(.)
- return TRUE
- if(state != STATE_WIRED)
- return FALSE
-
- tool.play_tool_sound(src)
- var/input = tgui_input_text(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret", "Set Network", "SS13")
- if(isnull(input))
- return
- var/list/tempnetwork = splittext(input, ",")
- if(!length(tempnetwork))
- to_chat(user, span_warning("No network found, please hang up and try your call again!"))
- return
- for(var/i in tempnetwork)
- tempnetwork -= i
- tempnetwork += lowertext(i)
- state = STATE_FINISHED
- var/obj/machinery/camera/C = new(loc, src)
- forceMove(C)
- C.setDir(src.dir)
-
- C.network = tempnetwork
- var/area/A = get_area(src)
- C.c_tag = "[format_text(A.name)] ([rand(1, 999)])"
- return TRUE
-
-/obj/structure/camera_assembly/wirecutter_act(mob/user, obj/item/I)
- . = ..()
- if(state != STATE_WIRED)
- return
-
- new /obj/item/stack/cable_coil(drop_location(), 2)
- I.play_tool_sound(src)
- to_chat(user, span_notice("You cut the wires from the circuits."))
- state = STATE_WELDED
- return TRUE
-
-/obj/structure/camera_assembly/wrench_act(mob/user, obj/item/I)
- . = ..()
- if(state != STATE_WRENCHED)
- return
- I.play_tool_sound(src)
- to_chat(user, span_notice("You detach [src] from its place."))
- new /obj/item/wallframe/camera(drop_location())
- //drop upgrades
- if(xray_module)
- drop_upgrade(xray_module)
- if(emp_module)
- drop_upgrade(emp_module)
- if(proxy_module)
- drop_upgrade(proxy_module)
-
- qdel(src)
- return TRUE
-
-
-/obj/structure/camera_assembly/deconstruct(disassembled = TRUE)
- if(!(obj_flags & NO_DECONSTRUCTION))
- new /obj/item/stack/sheet/iron(loc)
- qdel(src)
-
-
-#undef STATE_WRENCHED
-#undef STATE_WELDED
-#undef STATE_WIRED
-#undef STATE_FINISHED
diff --git a/code/game/machinery/camera/camera_construction.dm b/code/game/machinery/camera/camera_construction.dm
new file mode 100644
index 00000000000..48bf4ccabaa
--- /dev/null
+++ b/code/game/machinery/camera/camera_construction.dm
@@ -0,0 +1,247 @@
+/obj/machinery/camera/welder_act(mob/living/user, obj/item/tool)
+ switch(camera_construction_state)
+ if(CAMERA_STATE_WRENCHED, CAMERA_STATE_WELDED)
+ if(!tool.tool_start_check(user, amount = 1))
+ return ITEM_INTERACT_BLOCKING
+ user.balloon_alert_to_viewers("[camera_construction_state == CAMERA_STATE_WELDED ? "un" : null]welding...")
+ audible_message(span_hear("You hear welding."))
+ if(!tool.use_tool(src, user, 2 SECONDS, volume = 50))
+ user.balloon_alert_to_viewers("stopped [camera_construction_state == CAMERA_STATE_WELDED ? "un" : null]welding!")
+ return
+ camera_construction_state = ((camera_construction_state == CAMERA_STATE_WELDED) ? CAMERA_STATE_WRENCHED : CAMERA_STATE_WELDED)
+ set_anchored(camera_construction_state == CAMERA_STATE_WELDED)
+ user.balloon_alert_to_viewers(camera_construction_state == CAMERA_STATE_WELDED ? "welded" : "unwelded")
+ return ITEM_INTERACT_SUCCESS
+ if(CAMERA_STATE_FINISHED)
+ if(!panel_open)
+ return ITEM_INTERACT_BLOCKING
+ if(!tool.tool_start_check(user, amount=2))
+ return ITEM_INTERACT_BLOCKING
+ audible_message(span_hear("You hear welding."))
+ if(!tool.use_tool(src, user, 100, volume=50))
+ return ITEM_INTERACT_BLOCKING
+ user.visible_message(span_warning("[user] unwelds [src], leaving it as just a frame bolted to the wall."),
+ span_warning("You unweld [src], leaving it as just a frame bolted to the wall"))
+ deconstruct(TRUE)
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/machinery/camera/screwdriver_act(mob/user, obj/item/tool)
+ switch(camera_construction_state)
+ if(CAMERA_STATE_WIRED)
+ tool.play_tool_sound(src)
+ var/input = tgui_input_text(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret", "Set Network", "SS13")
+ if(isnull(input))
+ return ITEM_INTERACT_BLOCKING
+ var/list/tempnetwork = splittext(input, ",")
+ if(!length(tempnetwork))
+ to_chat(user, span_warning("No network found, please hang up and try your call again!"))
+ return ITEM_INTERACT_BLOCKING
+ for(var/i in tempnetwork)
+ tempnetwork -= i
+ tempnetwork += lowertext(i)
+ camera_construction_state = CAMERA_STATE_FINISHED
+ toggle_cam(user, displaymessage = FALSE)
+ network = tempnetwork
+ return ITEM_INTERACT_SUCCESS
+ if(CAMERA_STATE_FINISHED)
+ toggle_panel_open()
+ to_chat(user, span_notice("You screw the camera's panel [panel_open ? "open" : "closed"]."))
+ tool.play_tool_sound(src)
+ update_appearance()
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/machinery/camera/wirecutter_act(mob/user, obj/item/tool)
+ switch(camera_construction_state)
+ if(CAMERA_STATE_WIRED)
+ new /obj/item/stack/cable_coil(drop_location(), 2)
+ tool.play_tool_sound(src)
+ to_chat(user, span_notice("You cut the wires from the circuits."))
+ camera_construction_state = CAMERA_STATE_WELDED
+ return ITEM_INTERACT_SUCCESS
+ if(CAMERA_STATE_FINISHED)
+ if(!panel_open)
+ return ITEM_INTERACT_BLOCKING
+ toggle_cam(user, 1)
+ atom_integrity = max_integrity //this is a pretty simplistic way to heal the camera, but there's no reason for this to be complex.
+ set_machine_stat(machine_stat & ~BROKEN)
+ tool.play_tool_sound(src)
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/machinery/camera/wrench_act(mob/user, obj/item/tool)
+ if(camera_construction_state == CAMERA_STATE_WRENCHED)
+ tool.play_tool_sound(src)
+ to_chat(user, span_notice("You detach [src] from its place."))
+ deconstruct(TRUE)
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/machinery/camera/crowbar_act(mob/living/user, obj/item/tool)
+ if(camera_construction_state == CAMERA_STATE_FINISHED)
+ if(!panel_open)
+ return ITEM_INTERACT_BLOCKING
+ var/list/droppable_parts = list()
+ if(xray_module)
+ droppable_parts += xray_module
+ if(emp_module)
+ droppable_parts += emp_module
+ if(proximity_monitor)
+ droppable_parts += proximity_monitor
+ if(!length(droppable_parts))
+ return ITEM_INTERACT_BLOCKING
+ var/obj/item/choice = tgui_input_list(user, "Select a part to remove", "Part Removal", sort_names(droppable_parts))
+ if(isnull(choice))
+ return ITEM_INTERACT_BLOCKING
+ if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
+ return ITEM_INTERACT_BLOCKING
+ to_chat(user, span_notice("You remove [choice] from [src]."))
+ if(choice == xray_module)
+ drop_upgrade(xray_module)
+ removeXRay()
+ if(choice == emp_module)
+ drop_upgrade(emp_module)
+ removeEmpProof()
+ if(choice == proximity_monitor)
+ drop_upgrade(proximity_monitor)
+ removeMotion()
+ tool.play_tool_sound(src)
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/machinery/camera/multitool_act(mob/living/user, obj/item/tool)
+ if(camera_construction_state == CAMERA_STATE_FINISHED)
+ if(!panel_open)
+ return ITEM_INTERACT_BLOCKING
+ setViewRange((view_range == initial(view_range)) ? short_range : initial(view_range))
+ to_chat(user, span_notice("You [(view_range == initial(view_range)) ? "restore" : "mess up"] the camera's focus."))
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/machinery/camera/attackby(obj/item/attacking_item, mob/living/user, params)
+ if(camera_construction_state != CAMERA_STATE_FINISHED || panel_open)
+ if(attacking_item.tool_behaviour == TOOL_ANALYZER)
+ if(!isXRay(TRUE)) //don't reveal it was already upgraded if was done via MALF AI Upgrade Camera Network ability
+ if(!user.temporarilyRemoveItemFromInventory(attacking_item))
+ return
+ upgradeXRay(FALSE, TRUE)
+ to_chat(user, span_notice("You attach [attacking_item] into [name]'s inner circuits."))
+ qdel(attacking_item)
+ else
+ to_chat(user, span_warning("[src] already has that upgrade!"))
+ return
+ else if(istype(attacking_item, /obj/item/stack/sheet/mineral/plasma))
+ if(!isEmpProof(TRUE)) //don't reveal it was already upgraded if was done via MALF AI Upgrade Camera Network ability
+ if(attacking_item.use_tool(src, user, 0, amount=1))
+ upgradeEmpProof(FALSE, TRUE)
+ to_chat(user, span_notice("You attach [attacking_item] into [name]'s inner circuits."))
+ else
+ to_chat(user, span_warning("[src] already has that upgrade!"))
+ return
+ else if(isprox(attacking_item))
+ if(!isMotion())
+ if(!user.temporarilyRemoveItemFromInventory(attacking_item))
+ return
+ upgradeMotion()
+ to_chat(user, span_notice("You attach [attacking_item] into [name]'s inner circuits."))
+ qdel(attacking_item)
+ else
+ to_chat(user, span_warning("[src] already has that upgrade!"))
+ return
+ switch(camera_construction_state)
+ if(CAMERA_STATE_WELDED)
+ if(istype(attacking_item, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/attacking_cable = attacking_item
+ if(attacking_cable.use(2))
+ to_chat(user, span_notice("You add wires to [src]."))
+ camera_construction_state = CAMERA_STATE_WIRED
+ else
+ to_chat(user, span_warning("You need two lengths of cable to wire a camera!"))
+ return
+ if(CAMERA_STATE_FINISHED)
+ if(istype(attacking_item, /obj/item/modular_computer))
+ var/itemname = ""
+ var/info = ""
+
+ var/obj/item/modular_computer/computer = attacking_item
+ for(var/datum/computer_file/program/notepad/notepad_app in computer.stored_files)
+ info = notepad_app.written_note
+ break
+
+ if(!info)
+ return
+
+ itemname = computer.name
+ itemname = sanitize(itemname)
+ info = sanitize(info)
+ to_chat(user, span_notice("You hold \the [itemname] up to the camera..."))
+ user.log_talk(itemname, LOG_GAME, log_globally=TRUE, tag="Pressed to camera")
+ user.changeNext_move(CLICK_CD_MELEE)
+
+ for(var/mob/potential_viewer as anything in GLOB.player_list)
+ if(isAI(potential_viewer))
+ var/mob/living/silicon/ai/ai = potential_viewer
+ if(ai.control_disabled || (ai.stat == DEAD))
+ continue
+
+ ai.log_talk(itemname, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
+ ai.last_tablet_note_seen = "[itemname][info]"
+
+ if(user.name == "Unknown")
+ to_chat(ai, "[span_name(user)] holds \a [itemname] up to one of your cameras ...")
+ else
+ to_chat(ai, "[user] holds \a [itemname] up to one of your cameras ...")
+ continue
+
+ if (potential_viewer.client?.eye == src)
+ to_chat(potential_viewer, "[span_name("[user]")] holds \a [itemname] up to one of the cameras ...")
+ potential_viewer.log_talk(itemname, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
+ potential_viewer << browse("[itemname][info]", "window=[itemname]")
+ return
+
+ if(istype(attacking_item, /obj/item/paper))
+ // Grab the paper, sanitise the name as we're about to just throw it into chat wrapped in HTML tags.
+ var/obj/item/paper/paper = attacking_item
+
+ // Make a complete copy of the paper, store a ref to it locally on the camera.
+ last_shown_paper = paper.copy(paper.type, null)
+
+ // Then sanitise the name because we're putting it directly in chat later.
+ var/item_name = sanitize(last_shown_paper.name)
+
+ // Start the process of holding it up to the camera.
+ to_chat(user, span_notice("You hold \the [item_name] up to the camera..."))
+ user.log_talk(item_name, LOG_GAME, log_globally=TRUE, tag="Pressed to camera")
+ user.changeNext_move(CLICK_CD_MELEE)
+
+ // And make a weakref we can throw around to all potential viewers.
+ last_shown_paper.camera_holder = WEAKREF(src)
+
+ // Iterate over all living mobs and check if anyone is elibile to view the paper.
+ // This is backwards, but cameras don't store a list of people that are looking through them,
+ // and we'll have to iterate this list anyway so we can use it to pull out AIs too.
+ for(var/mob/potential_viewer in GLOB.player_list)
+ // All AIs view through cameras, so we need to check them regardless.
+ if(isAI(potential_viewer))
+ var/mob/living/silicon/ai/ai = potential_viewer
+ if(ai.control_disabled || (ai.stat == DEAD))
+ continue
+
+ ai.log_talk(item_name, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
+ log_paper("[key_name(user)] held [last_shown_paper] up to [src], requesting [key_name(ai)] read it.")
+
+ if(user.name == "Unknown")
+ to_chat(ai, "[span_name(user.name)] holds \a [item_name] up to one of your cameras ...")
+ else
+ to_chat(ai, "[user] holds \a [item_name] up to one of your cameras ...")
+ continue
+
+ // If it's not an AI, eye if the client's eye is set to the camera. I wonder if this even works anymore with tgui camera apps and stuff?
+ if (potential_viewer.client?.eye == src)
+ log_paper("[key_name(user)] held [last_shown_paper] up to [src], and [key_name(potential_viewer)] may read it.")
+ potential_viewer.log_talk(item_name, LOG_VICTIM, tag="Pressed to camera from [key_name(user)]", log_globally=FALSE)
+ to_chat(potential_viewer, "[span_name(user)] holds \a [item_name] up to your camera...")
+ return
+
+ return ..()
diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm
index ec01c2365f8..ba5e793d68c 100644
--- a/code/game/machinery/camera/motion.dm
+++ b/code/game/machinery/camera/motion.dm
@@ -1,10 +1,3 @@
-/obj/machinery/camera
-
- var/list/datum/weakref/localMotionTargets = list()
- var/detectTime = 0
- var/area/station/ai_monitored/area_motion = null
- var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
-
/obj/machinery/camera/process()
// motion camera event loop
if(!isMotion())
@@ -39,7 +32,7 @@
/obj/machinery/camera/Destroy()
localMotionTargets = null
if(area_motion)
- area_motion.motioncameras -= src
+ LAZYREMOVE(area_motion.motioncameras, src)
cancelAlarm()
return ..()
@@ -50,7 +43,7 @@
cancelAlarm()
/obj/machinery/camera/proc/cancelAlarm()
- if (detectTime == -1 && status)
+ if (detectTime == -1 && camera_enabled)
alarm_manager.clear_alarm(ALARM_MOTION)
detectTime = 0
return TRUE
@@ -58,7 +51,7 @@
/obj/machinery/camera/proc/triggerAlarm()
if (!detectTime)
return FALSE
- if(status)
+ if(camera_enabled)
if(alarm_manager.send_alarm(ALARM_MOTION, src, src))
visible_message(span_warning("A red light flashes on [src]!"))
detectTime = -1
@@ -72,7 +65,7 @@
/obj/machinery/camera/motion/thunderdome
name = "entertainment camera"
- network = list("thunder")
+ network = list(CAMERANET_NETWORK_THUNDERDOME)
c_tag = "Arena"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index e79eadf53b9..bb9ef7d3fc5 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -1,6 +1,16 @@
-// PRESETS
+/**
+ * Deconstructed Camera
+ * Used by wallmounted cameras, starts off deconstructed and requires building by a player.
+ */
+/obj/machinery/camera/autoname/deconstructed
+ icon_state = "camera_off"
+ camera_construction_state = CAMERA_STATE_WRENCHED
+ camera_enabled = FALSE
-// EMP
+/**
+ * EMP Proof
+ * Starts off with the EMP protection upgrade, and can't start unactivated.
+ */
/obj/machinery/camera/emp_proof
start_active = TRUE
@@ -8,23 +18,30 @@
. = ..()
upgradeEmpProof()
-// EMP + Motion
-
+/**
+ * Motion EMP proof
+ * Same as EMP but also starts with motion upgrade.
+ */
/obj/machinery/camera/emp_proof/motion/Initialize(mapload)
. = ..()
upgradeMotion()
-// X-ray
-
+/**
+ * X-Ray Cameras
+ * Starts off with x-ray, and can't start deactivated.
+ */
/obj/machinery/camera/xray
start_active = TRUE
- icon_state = "xraycamera" //mapping icon - Thanks to Krutchen for the icons.
+ icon_state = "xraycamera" //mapping icon only
/obj/machinery/camera/xray/Initialize(mapload)
. = ..()
upgradeXRay()
-// MOTION
+/**
+ * Motion camera
+ * Starts off with the motion detector and can't be disablede on roundstart.
+ */
/obj/machinery/camera/motion
start_active = TRUE
name = "motion-sensitive security camera"
@@ -33,7 +50,10 @@
. = ..()
upgradeMotion()
-// ALL UPGRADES
+/**
+ * All camera
+ * Has all upgrades by default, can't be disabled roundstart.
+ */
/obj/machinery/camera/all
start_active = TRUE
icon_state = "xraycamera" //mapping icon.
@@ -44,33 +64,47 @@
upgradeXRay()
upgradeMotion()
-// AUTONAME
-
+/**
+ * Autonaming camera
+ * Automatically names itself after the area it's in during LateInitialize,
+ * good for mappers who don't want to manually name them all.
+ */
/obj/machinery/camera/autoname
var/number = 0 //camera number in area
-//This camera type automatically sets it's name to whatever the area that it's in is called.
/obj/machinery/camera/autoname/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/camera/autoname/LateInitialize()
. = ..()
-
var/static/list/autonames_in_areas = list()
-
var/area/camera_area = get_area(src)
-
number = autonames_in_areas[camera_area] + 1
autonames_in_areas[camera_area] = number
-
c_tag = "[format_text(camera_area.name)] #[number]"
+
+/**
+ * Bomb preset
+ * Can't be disabled, sees further, doesn't cost power, can be seen by ordnance
+ * cameras, and is indestructible (so bomb-proof).
+ */
+/obj/machinery/camera/preset/ordnance
+ name = "Hardened Bomb-Test Camera"
+ desc = "A specially-reinforced camera with a long lasting battery, used to monitor the bomb testing site. An external light is attached to the top."
+ c_tag = "Bomb Testing Site"
+ network = list(CAMERANET_NETWORK_RD, CAMERANET_NETWORK_ORDNANCE)
+ use_power = NO_POWER_USE //Test site is an unpowered area
+ resistance_flags = parent_type::resistance_flags | INDESTRUCTIBLE
+ light_range = 10
+ start_active = TRUE
+
///The internal camera object for exosuits, applied by the camera upgrade
/obj/machinery/camera/exosuit
c_tag = "Exosuit: unspecified"
desc = "This camera belongs in a mecha. If you see this, tell a coder!"
- network = list("ss13", "rd")
+ network = list(CAMERANET_NETWORK_SS13, CAMERANET_NETWORK_RD)
short_range = 1 //used when the camera gets EMPd
///Number of the camera and thus the name of the mech
var/number = 0
@@ -103,78 +137,69 @@
// UPGRADE PROCS
/obj/machinery/camera/proc/isEmpProof(ignore_malf_upgrades)
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
- return (upgrades & CAMERA_UPGRADE_EMP_PROOF) && (!(ignore_malf_upgrades && assembly?.malf_emp_firmware_active))
+ return (camera_upgrade_bitflags & CAMERA_UPGRADE_EMP_PROOF) && (!(ignore_malf_upgrades && malf_emp_firmware_active))
/obj/machinery/camera/proc/upgradeEmpProof(malf_upgrade, ignore_malf_upgrades)
if(isEmpProof(ignore_malf_upgrades)) //pass a malf upgrade to ignore_malf_upgrades so we can replace the malf module with the normal one
return //that way if someone tries to upgrade an already malf-upgraded camera, it'll just upgrade it to a normal version.
AddElement(/datum/element/empprotection, EMP_PROTECT_ALL)
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
if(malf_upgrade)
- assembly.malf_emp_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade.
- assembly.malf_emp_firmware_present = TRUE //so the upgrade is retained after incompatible parts are removed.
+ malf_emp_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade.
+ malf_emp_firmware_present = TRUE //so the upgrade is retained after incompatible parts are removed.
- else if(!assembly.emp_module) //only happens via upgrading in camera/attackby()
- assembly.emp_module = new(assembly)
- if(assembly.malf_emp_firmware_active)
- assembly.malf_emp_firmware_active = FALSE //make it appear like it's just normally upgraded so the icons and examine texts are restored.
+ else if(!emp_module) //only happens via upgrading in camera/attackby()
+ emp_module = new(src)
+ if(malf_emp_firmware_active)
+ malf_emp_firmware_active = FALSE //make it appear like it's just normally upgraded so the icons and examine texts are restored.
- upgrades |= CAMERA_UPGRADE_EMP_PROOF
+ camera_upgrade_bitflags |= CAMERA_UPGRADE_EMP_PROOF
/obj/machinery/camera/proc/removeEmpProof(ignore_malf_upgrades)
if(ignore_malf_upgrades) //don't downgrade it if malf software is forced onto it.
return
RemoveElement(/datum/element/empprotection, EMP_PROTECT_ALL)
- upgrades &= ~CAMERA_UPGRADE_EMP_PROOF
-
-
+ camera_upgrade_bitflags &= ~CAMERA_UPGRADE_EMP_PROOF
/obj/machinery/camera/proc/isXRay(ignore_malf_upgrades)
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
- return (upgrades & CAMERA_UPGRADE_XRAY) && (!(ignore_malf_upgrades && assembly.malf_xray_firmware_active))
+ return (camera_upgrade_bitflags & CAMERA_UPGRADE_XRAY) && (!(ignore_malf_upgrades && malf_xray_firmware_active))
/obj/machinery/camera/proc/upgradeXRay(malf_upgrade, ignore_malf_upgrades)
if(isXRay(ignore_malf_upgrades)) //pass a malf upgrade to ignore_malf_upgrades so we can replace the malf upgrade with the normal one
return //that way if someone tries to upgrade an already malf-upgraded camera, it'll just upgrade it to a normal version.
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
if(malf_upgrade)
- assembly.malf_xray_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade.
- assembly.malf_xray_firmware_present = TRUE //so the upgrade is retained after incompatible parts are removed.
+ malf_xray_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade.
+ malf_xray_firmware_present = TRUE //so the upgrade is retained after incompatible parts are removed.
- else if(!assembly.xray_module) //only happens via upgrading in camera/attackby()
- assembly.xray_module = new(assembly)
- if(assembly.malf_xray_firmware_active)
- assembly.malf_xray_firmware_active = FALSE //make it appear like it's just normally upgraded so the icons and examine texts are restored.
+ else if(!xray_module) //only happens via upgrading in camera/attackby()
+ xray_module = new(src)
+ if(malf_xray_firmware_active)
+ malf_xray_firmware_active = FALSE //make it appear like it's just normally upgraded so the icons and examine texts are restored.
- upgrades |= CAMERA_UPGRADE_XRAY
+ camera_upgrade_bitflags |= CAMERA_UPGRADE_XRAY
update_appearance()
/obj/machinery/camera/proc/removeXRay(ignore_malf_upgrades)
if(!ignore_malf_upgrades) //don't downgrade it if malf software is forced onto it.
- upgrades &= ~CAMERA_UPGRADE_XRAY
+ camera_upgrade_bitflags &= ~CAMERA_UPGRADE_XRAY
update_appearance()
-
-
/obj/machinery/camera/proc/isMotion()
- return upgrades & CAMERA_UPGRADE_MOTION
+ return camera_upgrade_bitflags & CAMERA_UPGRADE_MOTION
/obj/machinery/camera/proc/upgradeMotion()
if(isMotion())
return
- var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
if(name == initial(name))
name = "motion-sensitive security camera"
- if(!assembly.proxy_module)
- assembly.proxy_module = new(assembly)
- upgrades |= CAMERA_UPGRADE_MOTION
+ if(!proximity_monitor)
+ proximity_monitor = new(src)
+ camera_upgrade_bitflags |= CAMERA_UPGRADE_MOTION
create_prox_monitor()
/obj/machinery/camera/proc/removeMotion()
if(name == "motion-sensitive security camera")
name = "security camera"
- upgrades &= ~CAMERA_UPGRADE_MOTION
+ camera_upgrade_bitflags &= ~CAMERA_UPGRADE_MOTION
if(!area_motion)
QDEL_NULL(proximity_monitor)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index d0f137d18ab..0c6dd3d9c55 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -8,7 +8,7 @@
circuit = /obj/item/circuitboard/computer/security
light_color = COLOR_SOFT_RED
- var/list/network = list("ss13")
+ var/list/network = list(CAMERANET_NETWORK_SS13)
var/obj/machinery/camera/active_camera
/// The turf where the camera was last updated.
var/turf/last_camera_turf
@@ -89,7 +89,7 @@
data["activeCamera"] = list(
name = active_camera.c_tag,
ref = REF(active_camera),
- status = active_camera.status,
+ status = active_camera.camera_enabled,
)
return data
@@ -194,31 +194,31 @@
desc = "Used to access the various cameras on the outpost."
icon_screen = "mining"
icon_keyboard = "mining_key"
- network = list("mine", "auxbase")
+ network = list(CAMERANET_NETWORK_MINE, CAMERANET_NETWORK_AUXBASE)
circuit = /obj/item/circuitboard/computer/mining
/obj/machinery/computer/security/research
name = "research camera console"
desc = "Used to access the various cameras in science."
- network = list("rd")
+ network = list(CAMERANET_NETWORK_RD)
circuit = /obj/item/circuitboard/computer/research
/obj/machinery/computer/security/hos
name = "\improper Head of Security's camera console"
desc = "A custom security console with added access to the labor camp network."
- network = list("ss13", "labor")
+ network = list(CAMERANET_NETWORK_SS13, CAMERANET_NETWORK_LABOR)
circuit = null
/obj/machinery/computer/security/labor
name = "labor camp monitoring"
desc = "Used to access the various cameras on the labor camp."
- network = list("labor")
+ network = list(CAMERANET_NETWORK_LABOR)
circuit = null
/obj/machinery/computer/security/qm
name = "\improper Quartermaster's camera console"
desc = "A console with access to the mining, auxiliary base and vault camera networks."
- network = list("mine", "auxbase", "vault")
+ network = list(CAMERANET_NETWORK_MINE, CAMERANET_NETWORK_AUXBASE, CAMERANET_NETWORK_VAULT)
circuit = null
#undef DEFAULT_MAP_SIZE
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index a2b1b30183b..a271517b0c4 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -8,7 +8,7 @@
var/lock_override = NONE
var/mob/camera/ai_eye/remote/eyeobj
var/mob/living/current_user = null
- var/list/networks = list("ss13")
+ var/list/networks = list(CAMERANET_NETWORK_SS13)
/// Typepath of the action button we use as "off"
/// It's a typepath so subtypes can give it fun new names
var/datum/action/innate/camera_off/off_action = /datum/action/innate/camera_off
diff --git a/code/game/machinery/computer/telescreen.dm b/code/game/machinery/computer/telescreen.dm
index daba0b62f10..2c17e1e088a 100644
--- a/code/game/machinery/computer/telescreen.dm
+++ b/code/game/machinery/computer/telescreen.dm
@@ -6,7 +6,7 @@
icon_keyboard = null
icon_screen = null
layer = SIGN_LAYER
- network = list("thunder")
+ network = list(CAMERANET_NETWORK_THUNDERDOME)
density = FALSE
circuit = null
light_power = 0
@@ -137,7 +137,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/rd
name = "\improper Research Director's telescreen"
desc = "Used for watching the AI and the RD's goons from the safety of his office."
- network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test", "toxins")
+ network = list(
+ CAMERANET_NETWORK_RD,
+ CAMERANET_NETWORK_AI_CORE,
+ CAMERANET_NETWORK_AI_UPLOAD,
+ CAMERANET_NETWORK_MINISAT,
+ CAMERANET_NETWORK_XENOBIOLOGY,
+ CAMERANET_NETWORK_TEST_CHAMBER,
+ CAMERANET_NETWORK_ORDNANCE,
+ )
frame_type = /obj/item/wallframe/telescreen/rd
/obj/item/wallframe/telescreen/rd
@@ -147,7 +155,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/research
name = "research telescreen"
desc = "A telescreen with access to the research division's camera network."
- network = list("rd")
+ network = list(CAMERANET_NETWORK_RD)
frame_type = /obj/item/wallframe/telescreen/research
/obj/item/wallframe/telescreen/research
@@ -157,7 +165,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/ce
name = "\improper Chief Engineer's telescreen"
desc = "Used for watching the engine, telecommunications and the minisat."
- network = list("engine", "singularity", "tcomms", "minisat")
+ network = list(CAMERANET_NETWORK_ENGINE, CAMERANET_NETWORK_TELECOMMS, CAMERANET_NETWORK_MINISAT)
frame_type = /obj/item/wallframe/telescreen/ce
/obj/item/wallframe/telescreen/ce
@@ -167,7 +175,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/cmo
name = "\improper Chief Medical Officer's telescreen"
desc = "A telescreen with access to the medbay's camera network."
- network = list("medbay")
+ network = list(CAMERANET_NETWORK_MEDBAY)
frame_type = /obj/item/wallframe/telescreen/cmo
/obj/item/wallframe/telescreen/cmo
@@ -177,7 +185,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/vault
name = "vault monitor"
desc = "A telescreen that connects to the vault's camera network."
- network = list("vault")
+ network = list(CAMERANET_NETWORK_VAULT)
frame_type = /obj/item/wallframe/telescreen/vault
/obj/item/wallframe/telescreen/vault
@@ -187,7 +195,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/ordnance
name = "bomb test site monitor"
desc = "A telescreen that connects to the bomb test site's camera."
- network = list("ordnance")
+ network = list(CAMERANET_NETWORK_ORDNANCE)
frame_type = /obj/item/wallframe/telescreen/ordnance
/obj/item/wallframe/telescreen/ordnance
@@ -197,7 +205,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/engine
name = "engine monitor"
desc = "A telescreen that connects to the engine's camera network."
- network = list("engine")
+ network = list(CAMERANET_NETWORK_ENGINE)
frame_type = /obj/item/wallframe/telescreen/engine
/obj/item/wallframe/telescreen/engine
@@ -207,7 +215,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/turbine
name = "turbine monitor"
desc = "A telescreen that connects to the turbine's camera."
- network = list("turbine")
+ network = list(CAMERANET_NETWORK_TURBINE)
frame_type = /obj/item/wallframe/telescreen/turbine
/obj/item/wallframe/telescreen/turbine
@@ -217,7 +225,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/interrogation
name = "interrogation room monitor"
desc = "A telescreen that connects to the interrogation room's camera."
- network = list("interrogation")
+ network = list(CAMERANET_NETWORK_INTERROGATION)
frame_type = /obj/item/wallframe/telescreen/interrogation
/obj/item/wallframe/telescreen/interrogation
@@ -227,7 +235,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/prison
name = "prison monitor"
desc = "A telescreen that connects to the permabrig's camera network."
- network = list("prison")
+ network = list(CAMERANET_NETWORK_PRISON)
frame_type = /obj/item/wallframe/telescreen/prison
/obj/item/wallframe/telescreen/prison
@@ -237,7 +245,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/auxbase
name = "auxiliary base monitor"
desc = "A telescreen that connects to the auxiliary base's camera."
- network = list("auxbase")
+ network = list(CAMERANET_NETWORK_AUXBASE)
frame_type = /obj/item/wallframe/telescreen/auxbase
/obj/item/wallframe/telescreen/auxbase
@@ -247,7 +255,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/minisat
name = "minisat monitor"
desc = "A telescreen that connects to the minisat's camera network."
- network = list("minisat")
+ network = list(CAMERANET_NETWORK_MINISAT)
frame_type = /obj/item/wallframe/telescreen/minisat
/obj/item/wallframe/telescreen/minisat
@@ -257,7 +265,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/aiupload
name = "\improper AI upload monitor"
desc = "A telescreen that connects to the AI upload's camera network."
- network = list("aiupload")
+ network = list(CAMERANET_NETWORK_AI_UPLOAD)
frame_type = /obj/item/wallframe/telescreen/aiupload
/obj/item/wallframe/telescreen/aiupload
@@ -267,7 +275,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/bar
name = "bar monitor"
desc = "A telescreen that connects to the bar's camera network. Perfect for checking on customers."
- network = list("bar")
+ network = list(CAMERANET_NETWORK_BAR)
frame_type = /obj/item/wallframe/telescreen/bar
/obj/item/wallframe/telescreen/bar
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index df5f5ea4e1e..e670fdec914 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -261,7 +261,7 @@
//cameras: chance to EMP the camera
else if(istype(target, /obj/machinery/camera))
var/obj/machinery/camera/target_camera = target
- if(!target_camera.status && !target_camera.emped)
+ if(!target_camera.camera_enabled && !target_camera.emped)
outmsg = span_notice("You point [src] at [target_camera], but it seems to be disabled.")
else if(prob(effectchance * diode.rating))
target_camera.emp_act(EMP_HEAVY)
diff --git a/code/game/objects/structures/construction_console/construction_console.dm b/code/game/objects/structures/construction_console/construction_console.dm
index 720f568369e..d3ae2984e31 100644
--- a/code/game/objects/structures/construction_console/construction_console.dm
+++ b/code/game/objects/structures/construction_console/construction_console.dm
@@ -10,7 +10,7 @@
/obj/machinery/computer/camera_advanced/base_construction
name = "generic base construction console"
desc = "An industrial computer integrated with a camera-assisted rapid construction drone."
- networks = list("ss13")
+ networks = list(CAMERANET_NETWORK_SS13)
circuit = /obj/item/circuitboard/computer/base_construction
off_action = /datum/action/innate/camera_off/base_construction
jump_action = null
diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm
index 36618e62269..bbf6ea2db39 100644
--- a/code/modules/antagonists/abductor/machinery/camera.dm
+++ b/code/modules/antagonists/abductor/machinery/camera.dm
@@ -1,7 +1,7 @@
/obj/machinery/computer/camera_advanced/abductor
name = "Human Observation Console"
var/team_number = 0
- networks = list("ss13", "abductor")
+ networks = list(CAMERANET_NETWORK_SS13, CAMERANET_NETWORK_ABDUCTOR)
var/obj/machinery/abductor/console/console
/// We can't create our actions until after LateInitialize
/// So we instead do it on the first call to GrantActions
diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm
index 6a82c961d22..ab88a6f02fc 100644
--- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm
+++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm
@@ -801,7 +801,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module))
for(var/obj/machinery/camera/C as anything in GLOB.cameranet.cameras)
if(!uses)
break
- if(!C.status || C.view_range != initial(C.view_range))
+ if(!C.camera_enabled || C.view_range != initial(C.view_range))
C.toggle_cam(owner_AI, 0) //Reactivates the camera based on status. Badly named proc.
C.view_range = initial(C.view_range)
fixed_cameras++
@@ -831,10 +831,6 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module))
var/upgraded_cameras = 0
for(var/obj/machinery/camera/camera as anything in GLOB.cameranet.cameras)
- var/obj/structure/camera_assembly/assembly = camera.assembly_ref?.resolve()
- if(!assembly)
- continue
-
var/upgraded = FALSE
if(!camera.isXRay())
diff --git a/code/modules/asset_cache/assets/tcomms.dm b/code/modules/asset_cache/assets/tcomms.dm
index ecfdb4a498c..fdbab5f4c9b 100644
--- a/code/modules/asset_cache/assets/tcomms.dm
+++ b/code/modules/asset_cache/assets/tcomms.dm
@@ -1,5 +1,5 @@
/datum/asset/spritesheet/telecomms
- name="tcomms"
+ name = "tcomms"
/datum/asset/spritesheet/telecomms/create_spritesheets()
var/list/inserted_states = list() // No need to send entire `telecomms.dmi`.
diff --git a/code/modules/events/camerafailure.dm b/code/modules/events/camerafailure.dm
index 453b919c5b8..d2fcdda8314 100644
--- a/code/modules/events/camerafailure.dm
+++ b/code/modules/events/camerafailure.dm
@@ -17,8 +17,8 @@
var/obj/machinery/camera/C = pick_n_take(cameras)
if (!C)
break
- if (!("ss13" in C.network))
+ if (!(CAMERANET_NETWORK_SS13 in C.network))
continue
- if(C.status)
+ if(C.camera_enabled)
C.toggle_cam(null, 0)
iterations *= 2.5
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index a7d5b085799..2b79d0dbcbf 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -30,7 +30,7 @@
radio = /obj/item/radio/headset/silicon/ai
can_buckle_to = FALSE
var/battery = 200 //emergency power if the AI's APC is off
- var/list/network = list("ss13")
+ var/list/network = list(CAMERANET_NETWORK_SS13)
var/obj/machinery/camera/current
var/list/connected_robots = list()
var/aiRestorePowerRoutine = POWER_RESTORATION_OFF
@@ -188,7 +188,7 @@
GLOB.shuttle_caller_list += src
builtInCamera = new (src)
- builtInCamera.network = list("ss13")
+ builtInCamera.network = list(CAMERANET_NETWORK_SS13)
ai_tracking_tool = new(src)
RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target))
@@ -657,11 +657,11 @@
var/turf/camera_turf = get_turf(C) //get camera's turf in case it's built into something so we don't get z=0
var/list/tempnetwork = C.network
- if(!camera_turf || !(is_station_level(camera_turf.z) || is_mining_level(camera_turf.z) || ("ss13" in tempnetwork)))
+ if(!camera_turf || !(is_station_level(camera_turf.z) || is_mining_level(camera_turf.z) || (CAMERANET_NETWORK_SS13 in tempnetwork)))
continue
if(!C.can_use())
continue
- tempnetwork.Remove("rd", "ordnance", "prison")
+ tempnetwork.Remove(CAMERANET_NETWORK_RD, CAMERANET_NETWORK_ORDNANCE, CAMERANET_NETWORK_PRISON)
if(length(tempnetwork))
for(var/i in C.network)
cameralist[i] = i
diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm
index 45924e2fe98..8980a1017f2 100644
--- a/code/modules/mob/living/silicon/ai/multicam.dm
+++ b/code/modules/mob/living/silicon/ai/multicam.dm
@@ -172,15 +172,13 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
add = visible - cameras_telegraphed
remove = cameras_telegraphed - visible
- for (var/V in remove)
- var/obj/machinery/camera/C = V
+ for (var/obj/machinery/camera/C as anything in remove)
if(QDELETED(C))
continue
cameras_telegraphed -= C
C.in_use_lights--
C.update_appearance()
- for (var/V in add)
- var/obj/machinery/camera/C = V
+ for (var/obj/machinery/camera/C as anything in add)
if(QDELETED(C))
continue
cameras_telegraphed |= C
@@ -189,8 +187,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
/mob/camera/ai_eye/pic_in_pic/proc/disable_camera_telegraphing()
telegraph_cameras = FALSE
- for (var/V in cameras_telegraphed)
- var/obj/machinery/camera/C = V
+ for (var/obj/machinery/camera/C as anything in cameras_telegraphed)
if(QDELETED(C))
continue
C.in_use_lights--
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index 81026bf11b9..3a8cec66efd 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -25,7 +25,7 @@
locked = FALSE //unlock cover
- if(!QDELETED(builtInCamera) && builtInCamera.status)
+ if(!QDELETED(builtInCamera) && builtInCamera.camera_enabled)
builtInCamera.toggle_cam(src,0)
toggle_headlamp(TRUE) //So borg lights are disabled when killed.
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index be713b429a6..a28718c8c83 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -157,7 +157,7 @@
audible_message(span_warning("[src] sounds an alarm! \"CRITICAL ERROR: ALL modules OFFLINE.\""))
if(builtInCamera)
- builtInCamera.status = FALSE
+ builtInCamera.camera_enabled = FALSE
to_chat(src, span_userdanger("CRITICAL ERROR: Built in security camera OFFLINE."))
to_chat(src, span_userdanger("CRITICAL ERROR: ALL modules OFFLINE."))
@@ -211,7 +211,7 @@
inv1.icon_state = initial(inv1.icon_state)
disabled_modules &= ~BORG_MODULE_ALL_DISABLED
if(builtInCamera)
- builtInCamera.status = TRUE
+ builtInCamera.camera_enabled = TRUE
to_chat(src, span_notice("You hear your built in security camera focus adjust as it comes back online!"))
if(BORG_CHOOSE_MODULE_TWO)
if(!(disabled_modules & BORG_MODULE_TWO_DISABLED))
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 569d51a6e98..1bcd7033651 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -51,10 +51,10 @@
if(!scrambledcodes && !builtInCamera)
builtInCamera = new (src)
builtInCamera.c_tag = real_name
- builtInCamera.network = list("ss13")
+ builtInCamera.network = list(CAMERANET_NETWORK_SS13)
builtInCamera.internal_light = FALSE
if(wires.is_cut(WIRE_CAMERA))
- builtInCamera.status = 0
+ builtInCamera.camera_enabled = 0
update_icons()
. = ..()
diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm
index e1444b74577..eee170e7c2c 100644
--- a/code/modules/modular_computers/file_system/programs/secureye.dm
+++ b/code/modules/modular_computers/file_system/programs/secureye.dm
@@ -17,7 +17,7 @@
///Boolean on whether or not the app will make noise when flipping around the channels.
var/spying = FALSE
- var/list/network = list("ss13")
+ var/list/network = list(CAMERANET_NETWORK_SS13)
///List of weakrefs of all users watching the program.
var/list/concurrent_users = list()
@@ -43,7 +43,14 @@
can_run_on_flags = PROGRAM_ALL
program_flags = PROGRAM_ON_SYNDINET_STORE | PROGRAM_UNIQUE_COPY
- network = list("ss13", "mine", "rd", "labor", "ordnance", "minisat")
+ network = list(
+ CAMERANET_NETWORK_SS13,
+ CAMERANET_NETWORK_MINE,
+ CAMERANET_NETWORK_RD,
+ CAMERANET_NETWORK_LABOR,
+ CAMERANET_NETWORK_ORDNANCE,
+ CAMERANET_NETWORK_MINISAT,
+ )
spying = TRUE
/datum/computer_file/program/secureye/human_ai
@@ -111,7 +118,7 @@
data["activeCamera"] = list(
name = active_camera.c_tag,
ref = REF(active_camera),
- status = active_camera.status,
+ status = active_camera.camera_enabled,
)
return data
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 27de108c0cb..0b86fc7437f 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -27,7 +27,7 @@
/obj/machinery/computer/camera_advanced/xenobio
name = "Slime management console"
desc = "A computer used for remotely handling slimes."
- networks = list("ss13")
+ networks = list(CAMERANET_NETWORK_SS13)
circuit = /obj/item/circuitboard/computer/xenobiology
///The recycler connected to the camera console
diff --git a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
index 2a166411b17..6a71c00605c 100644
--- a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
+++ b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
@@ -519,7 +519,7 @@
. = ..()
- mech.chassis_camera = new /obj/machinery/camera/exosuit (mech)
+ mech.chassis_camera = new /obj/machinery/camera/exosuit(mech)
mech.chassis_camera.update_c_tag(mech)
mech.diag_hud_set_camera()
diff --git a/tgstation.dme b/tgstation.dme
index 0bb4356e926..4ba8fc1a12d 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2003,7 +2003,7 @@
#include "code\game\machinery\washing_machine.dm"
#include "code\game\machinery\wishgranter.dm"
#include "code\game\machinery\camera\camera.dm"
-#include "code\game\machinery\camera\camera_assembly.dm"
+#include "code\game\machinery\camera\camera_construction.dm"
#include "code\game\machinery\camera\motion.dm"
#include "code\game\machinery\camera\presets.dm"
#include "code\game\machinery\camera\trackable.dm"