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"