From 0417e090cc2182bab4d53e391dc2751b98ea4891 Mon Sep 17 00:00:00 2001 From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:35:07 -0400 Subject: [PATCH] Removes camera assembly structures (#81656) ## About The Pull Request Removes the camera assembly structure middleman between the camera wallframe and camera machine. All its behavior has been instead moved to the camera, and I've tried to keep as much of the behavior the same as before. This also fixes the issue that camera assemblies had where, upon the construction being finished, it would move itself into the newly finished camera machine, therefore taking itself off a wall, therefore deconstructing itself. This resulted in 2 piece of iron being in each camera machine (except roundstart ones), and because camera machines rely on the assembly inside of them for upgrades and such, upgrading didn't work at all. I've also made camera nets use defines (not in map) so it's easier to find a list of them all, and tried to add autodoc comments to nearly every var in camera code. ## Why It's Good For The Game Removes copy paste and spaghetti code between structure and machine camera, thus making it easier to work around with. Closes https://github.com/tgstation/tgstation/issues/79019 ## Changelog :cl: fix: Cameras built in-round can be upgraded again. fix: Deconstructing cameras now more consistently return to you the upgrades inside of the camera. fix: RD's telescreen can now properly see Ordnance cameras again. fix: [Deltastation] Library art gallery no longer has an invisible camera. /:cl: --------- Co-authored-by: san7890 --- .../map_files/Deltastation/DeltaStation2.dmm | 1 - code/__DEFINES/cameranets.dm | 23 + code/__DEFINES/construction/structures.dm | 9 + code/__HELPERS/global_lists.dm | 1 - code/datums/wires/robot.dm | 6 +- code/game/area/ai_monitored.dm | 40 +- code/game/area/areas/ai_monitored.dm | 1 + code/game/machinery/_machinery.dm | 2 +- code/game/machinery/camera/camera.dm | 493 +++++++----------- code/game/machinery/camera/camera_assembly.dm | 280 ---------- .../machinery/camera/camera_construction.dm | 247 +++++++++ code/game/machinery/camera/motion.dm | 15 +- code/game/machinery/camera/presets.dm | 123 +++-- code/game/machinery/computer/camera.dm | 14 +- .../machinery/computer/camera_advanced.dm | 2 +- code/game/machinery/computer/telescreen.dm | 38 +- .../objects/items/devices/laserpointer.dm | 2 +- .../construction_console.dm | 2 +- .../antagonists/abductor/machinery/camera.dm | 2 +- .../antagonists/malf_ai/malf_ai_modules.dm | 6 +- code/modules/asset_cache/assets/tcomms.dm | 2 +- code/modules/events/camerafailure.dm | 4 +- code/modules/mob/living/silicon/ai/ai.dm | 8 +- .../modules/mob/living/silicon/ai/multicam.dm | 9 +- .../modules/mob/living/silicon/robot/death.dm | 2 +- .../mob/living/silicon/robot/inventory.dm | 4 +- .../modules/mob/living/silicon/robot/robot.dm | 4 +- .../file_system/programs/secureye.dm | 13 +- .../research/xenobiology/xenobio_camera.dm | 2 +- .../mecha/equipment/tools/other_tools.dm | 2 +- tgstation.dme | 2 +- 31 files changed, 621 insertions(+), 738 deletions(-) delete mode 100644 code/game/machinery/camera/camera_assembly.dm create mode 100644 code/game/machinery/camera/camera_construction.dm 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"