diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm index 95d4929acb..e95483cea4 100644 --- a/code/__defines/machinery.dm +++ b/code/__defines/machinery.dm @@ -56,6 +56,9 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define NETWORK_TELECOM "Tcomms" #define NETWORK_THUNDER "Thunderdome" #define NETWORK_COMMUNICATORS "Communicators" +#define NETWORK_ALARM_ATMOS "Atmosphere Alarms" +#define NETWORK_ALARM_POWER "Power Alarms" +#define NETWORK_ALARM_FIRE "Fire Alarms" // Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them. var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret", NETWORK_COMMUNICATORS) diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index b570aee7c6..d6e2fd4dce 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -191,6 +191,7 @@ #define NTNETSPEED_LOWSIGNAL 0.1 // GQ/s transfer speed when the device is wirelessly connected and on Low signal #define NTNETSPEED_HIGHSIGNAL 0.5 // GQ/s transfer speed when the device is wirelessly connected and on High signal #define NTNETSPEED_ETHERNET 1.0 // GQ/s transfer speed when the device is using wired connection +#define NTNETSPEED_DOS_AMPLIFICATION 5 // Multiplier for Denial of Service program. Resulting load on NTNet relay is this multiplied by NTNETSPEED of the device // Program bitflags #define PROGRAM_ALL 7 diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm index 35bb07cbc5..1724b9469c 100644 --- a/code/datums/wires/camera.dm +++ b/code/datums/wires/camera.dm @@ -57,9 +57,6 @@ var/const/CAMERA_WIRE_NOTHING2 = 32 var/new_range = (C.view_range == initial(C.view_range) ? C.short_range : initial(C.view_range)) C.setViewRange(new_range) - if(CAMERA_WIRE_POWER) - C.kick_viewers() // Kicks anyone watching the camera - if(CAMERA_WIRE_LIGHT) C.light_disabled = !C.light_disabled diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 6a1e96e18a..3f48c656ba 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -39,7 +39,6 @@ var/const/BORG_WIRE_CAMERA = 16 if (BORG_WIRE_CAMERA) if(!isnull(R.camera) && !R.scrambledcodes) R.camera.status = mended - R.camera.kick_viewers() // Will kick anyone who is watching the Cyborg's camera. if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh if (R.lawupdate) @@ -59,7 +58,6 @@ var/const/BORG_WIRE_CAMERA = 16 if (BORG_WIRE_CAMERA) if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes) - R.camera.kick_viewers() // Kick anyone watching the Cyborg's camera R.visible_message("[R]'s camera lense focuses loudly.") R << "Your camera lense focuses loudly." diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index d484e7c882..20b3ace0e0 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -88,7 +88,6 @@ stat |= EMPED set_light(0) triggerCameraAlarm() - kick_viewers() update_icon() update_coverage() START_PROCESSING(SSobj, src) @@ -241,26 +240,25 @@ user = null if(choice != 1) - //legacy support, if choice is != 1 then just kick viewers without changing status - kick_viewers() - else - set_status(!src.status) - if (!(src.status)) - if(user) - visible_message(" [user] has deactivated [src]!") - else - visible_message(" [src] clicks and shuts down. ") - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - icon_state = "[initial(icon_state)]1" - add_hiddenprint(user) + return + + set_status(!src.status) + if (!(src.status)) + if(user) + visible_message(" [user] has deactivated [src]!") else - if(user) - visible_message(" [user] has reactivated [src]!") - else - visible_message(" [src] clicks and reactivates itself. ") - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - icon_state = initial(icon_state) - add_hiddenprint(user) + visible_message(" [src] clicks and shuts down. ") + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + icon_state = "[initial(icon_state)]1" + add_hiddenprint(user) + else + if(user) + visible_message(" [user] has reactivated [src]!") + else + visible_message(" [src] clicks and reactivates itself. ") + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + icon_state = initial(icon_state) + add_hiddenprint(user) /obj/machinery/camera/proc/take_damage(var/force, var/message) //prob(25) gives an average of 3-4 hits @@ -272,7 +270,6 @@ stat |= BROKEN wires.RandomCutAll() - kick_viewers() triggerCameraAlarm() update_icon() update_coverage() @@ -287,26 +284,12 @@ if (status != newstatus) status = newstatus update_coverage() - // 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 couldn't use it anyway? - kick_viewers() /obj/machinery/camera/check_eye(mob/user) if(!can_use()) return -1 if(isXRay()) return SEE_TURFS|SEE_MOBS|SEE_OBJS return 0 -//This might be redundant, because of check_eye() -/obj/machinery/camera/proc/kick_viewers() - for(var/mob/O in player_list) - if (istype(O.machine, /obj/machinery/computer/security)) - var/obj/machinery/computer/security/S = O.machine - if (S.current_camera == src) - O.unset_machine() - O.reset_view(null) - O << "The screen bursts into static." - /obj/machinery/camera/update_icon() if (!status || (stat & BROKEN)) icon_state = "[initial(icon_state)]1" diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index d4b29b217e..abd0434c5e 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -26,9 +26,9 @@ var/global/list/engineering_networks = list( NETWORK_ENGINE, NETWORK_ENGINEERING, NETWORK_ENGINEERING_OUTPOST, - "Atmosphere Alarms", - "Fire Alarms", - "Power Alarms") + NETWORK_ALARM_ATMOS, + NETWORK_ALARM_FIRE, + NETWORK_ALARM_POWER) /obj/machinery/camera/network/crescent network = list(NETWORK_CRESCENT) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index cf08e5a9ed..ccd53918ac 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -8,6 +8,10 @@ return if(!loc) return + + if(machine && !CanMouseDrop(machine, src)) + machine = null + var/datum/gas_mixture/environment = loc.return_air() handle_modifiers() // Do this early since it might affect other things later. diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index 7d2848f9bf..bfff010d03 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -145,9 +145,6 @@ /datum/robot_component/camera/update_power_state() ..() if (camera) - //check if camera component was deactivated - if (!powered && camera.status != powered) - camera.kick_viewers() camera.status = powered /datum/robot_component/camera/install() @@ -157,12 +154,10 @@ /datum/robot_component/camera/uninstall() if (camera) camera.status = 0 - camera.kick_viewers() /datum/robot_component/camera/destroy() if (camera) camera.status = 0 - camera.kick_viewers() // SELF DIAGNOSIS MODULE // Analyses cyborg's modules, providing damage readouts and basic information diff --git a/code/modules/modular_computers/computers/item/modular_computer.dm b/code/modules/modular_computers/computers/item/modular_computer.dm index 05661c32de..2a6a57a1df 100644 --- a/code/modules/modular_computers/computers/item/modular_computer.dm +++ b/code/modules/modular_computers/computers/item/modular_computer.dm @@ -776,4 +776,11 @@ if(HALLOSS) take_damage(Proj.damage, Proj.damage / 3, 0) if(BURN) - take_damage(Proj.damage, Proj.damage / 1.5) \ No newline at end of file + take_damage(Proj.damage, Proj.damage / 1.5) + +// Used by camera monitor program +/obj/item/modular_computer/check_eye(var/mob/user) + if(active_program) + return active_program.check_eye(user) + else + return ..() \ No newline at end of file diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 5e9e7f4987..51098e5e44 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -17,7 +17,6 @@ cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/super(cpu) install_programs() -// Override in child types to install preset-specific programs. /obj/machinery/modular_computer/console/preset/proc/install_programs() return @@ -31,6 +30,7 @@ cpu.hard_drive.store_file(new/datum/computer_file/program/alarm_monitor()) cpu.hard_drive.store_file(new/datum/computer_file/program/atmos_control()) cpu.hard_drive.store_file(new/datum/computer_file/program/rcon_console()) + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor()) // ===== MEDICAL CONSOLE ===== @@ -40,6 +40,7 @@ /obj/machinery/modular_computer/console/preset/medical/install_programs() cpu.hard_drive.store_file(new/datum/computer_file/program/suit_sensors()) + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor()) // ===== RESEARCH CONSOLE ===== @@ -51,6 +52,7 @@ cpu.hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor()) cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer()) cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient()) + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor()) // ===== COMMAND CONSOLE ===== @@ -64,6 +66,7 @@ cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient()) cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod()) cpu.hard_drive.store_file(new/datum/computer_file/program/comm()) + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor()) // ===== SECURITY CONSOLE ===== @@ -72,7 +75,7 @@ desc = "A stationary computer. This one comes preloaded with security programs." /obj/machinery/modular_computer/console/preset/security/install_programs() - return // No security programs exist, yet, but the preset is ready so it may be mapped in. + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor()) // ===== CIVILIAN CONSOLE ===== @@ -83,3 +86,27 @@ /obj/machinery/modular_computer/console/preset/civilian/install_programs() cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient()) cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer()) + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor()) // Mainly for the entertainment channel, won't allow connection to other channels without access anyway + +// ===== ERT CONSOLE ===== +/obj/machinery/modular_computer/console/preset/ert + console_department = "Crescent" + desc = "A stationary computer. This one comes preloaded with various programs used by Nanotrasen response teams." + +/obj/machinery/modular_computer/console/preset/ert/install_programs() + cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer()) + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor/ert()) + cpu.hard_drive.store_file(new/datum/computer_file/program/alarm_monitor()) + cpu.hard_drive.store_file(new/datum/computer_file/program/comm()) + +// ===== MERCENARY CONSOLE ===== +/obj/machinery/modular_computer/console/preset/mercenary + console_department = "Unset" + desc = "A stationary computer. This one comes preloaded with various programs used by shady organizations." + _has_printer = 1 + _has_id_slot = 1 + emagged = 1 // Allows download of other antag programs for free. + +/obj/machinery/modular_computer/console/preset/ert/install_programs() + cpu.hard_drive.store_file(new/datum/computer_file/program/camera_monitor/hacked()) + cpu.hard_drive.store_file(new/datum/computer_file/program/alarm_monitor()) \ No newline at end of file diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 65e81f0ad6..06daed0dda 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -190,4 +190,7 @@ if(cpu) cpu.bullet_act(Proj) - +/obj/machinery/modular_computer/check_eye(var/mob/user) + if(cpu) + return cpu.check_eye(user) + return -1 diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index cfb51bd47b..d3878bd025 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -2,7 +2,9 @@ /datum/computer_file/program filetype = "PRG" filename = "UnknownProgram" // File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET! - var/required_access = null // List of required accesses to *run* the program. + var/required_access = null // List of required accesses to run/download the program. + var/requires_access_to_run = 1 // Whether the program checks for required_access when run. + var/requires_access_to_download = 1 // Whether the program checks for required_access when downloading. var/datum/nano_module/NM = null // If the program uses NanoModule, put it here and it will be automagically opened. Otherwise implement ui_interact. var/nanomodule_path = null // Path to nanomodule, make sure to set this if implementing new program. var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running. @@ -80,6 +82,9 @@ if(!access_to_check) // No required_access, allow it. return 1 + if(!istype(user)) + return 0 + var/obj/item/weapon/card/id/I = user.GetIdCard() if(!I) if(loud) @@ -101,7 +106,7 @@ // This is performed on program startup. May be overriden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure. // When implementing new program based device, use this to run the program. /datum/computer_file/program/proc/run_program(var/mob/living/user) - if(can_run(user, 1)) + if(can_run(user, 1) || !requires_access_to_run) if(nanomodule_path) NM = new nanomodule_path(src, new /datum/topic_manager/program(src), src) if(requires_ntnet && network_destination) @@ -143,3 +148,10 @@ return 1 if(computer) return computer.Topic(href, href_list) + +// Relays the call to nano module, if we have one +/datum/computer_file/program/proc/check_eye(var/mob/user) + if(NM) + return NM.check_eye(user) + else + return -1 \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/_program.dm b/code/modules/modular_computers/file_system/programs/_program.dm index cf7d88edc3..2cba7960c9 100644 --- a/code/modules/modular_computers/file_system/programs/_program.dm +++ b/code/modules/modular_computers/file_system/programs/_program.dm @@ -28,4 +28,4 @@ // Calls forwarded to PROGRAM itself should begin with "PRG_" // Calls forwarded to COMPUTER running the program should begin with "PC_" /datum/topic_manager/program/Topic(href, href_list) - return program && program.Topic(href, href_list) \ No newline at end of file + return program && program.Topic(href, href_list) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm index 2f21771147..a913e3ddf2 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm @@ -17,11 +17,11 @@ dos_speed = 0 switch(ntnet_status) if(1) - dos_speed = NTNETSPEED_LOWSIGNAL * 10 + dos_speed = NTNETSPEED_LOWSIGNAL * NTNETSPEED_DOS_AMPLIFICATION if(2) - dos_speed = NTNETSPEED_HIGHSIGNAL * 10 + dos_speed = NTNETSPEED_HIGHSIGNAL * NTNETSPEED_DOS_AMPLIFICATION if(3) - dos_speed = NTNETSPEED_ETHERNET * 10 + dos_speed = NTNETSPEED_ETHERNET * NTNETSPEED_DOS_AMPLIFICATION if(target && executed) target.dos_overload += dos_speed if(!target.is_operational()) diff --git a/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm b/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm new file mode 100644 index 0000000000..be69b012b9 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm @@ -0,0 +1,36 @@ +/datum/computer_file/program/camera_monitor/hacked + filename = "camcrypt" + filedesc = "Camera Decryption Tool" + nanomodule_path = /datum/nano_module/camera_monitor/hacked + program_icon_state = "hostile" + extended_desc = "This very advanced piece of software uses adaptive programming and large database of cipherkeys to bypass most encryptions used on camera networks. Be warned that system administrator may notice this." + size = 73 // Very large, a price for bypassing ID checks completely. + available_on_ntnet = 0 + available_on_syndinet = 1 + +/datum/computer_file/program/camera_monitor/hacked/process_tick() + ..() + if(program_state != PROGRAM_STATE_ACTIVE) // Background programs won't trigger alarms. + return + + var/datum/nano_module/camera_monitor/hacked/HNM = NM + + // The program is active and connected to one of the station's networks. Has a very small chance to trigger IDS alarm every tick. + if(HNM.current_network && (HNM.current_network in using_map.station_networks) && prob(0.1)) + if(ntnet_global.intrusion_detection_enabled) + ntnet_global.add_log("IDS WARNING - Unauthorised access detected to camera network [HNM.current_network] by device with NID [computer.network_card.get_network_tag()]") + ntnet_global.intrusion_detection_alarm = 1 + + +/datum/nano_module/camera_monitor/hacked + name = "Hacked Camera Monitoring Program" + +/datum/nano_module/camera_monitor/hacked/can_access_network(var/mob/user, var/network_access) + return 1 + +// The hacked variant has access to all commonly used networks. +/datum/nano_module/camera_monitor/hacked/modify_networks_list(var/list/networks) + networks.Add(list(list("tag" = NETWORK_MERCENARY, "has_access" = 1))) + networks.Add(list(list("tag" = NETWORK_ERT, "has_access" = 1))) + networks.Add(list(list("tag" = NETWORK_CRESCENT, "has_access" = 1))) + return networks \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/camera.dm b/code/modules/modular_computers/file_system/programs/camera.dm new file mode 100644 index 0000000000..6aaaa21b80 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/camera.dm @@ -0,0 +1,173 @@ +// Returns which access is relevant to passed network. Used by the program. +/proc/get_camera_access(var/network) + if(!network) + return 0 + + switch(network) + if(NETWORK_THUNDER) + return 0 + if(NETWORK_ENGINE || NETWORK_ENGINEERING || NETWORK_ENGINEERING_OUTPOST || NETWORK_ALARM_ATMOS || NETWORK_ALARM_FIRE || NETWORK_ALARM_POWER) + return access_engine + if(NETWORK_MEDICAL) + return access_medical + if(NETWORK_RESEARCH || NETWORK_RESEARCH_OUTPOST) + return access_research + if(NETWORK_MINE || NETWORK_SUPPLY ) + return access_mailsorting // Cargo office - all cargo staff should have access here. + if(NETWORK_COMMAND || NETWORK_TELECOM) + return access_heads + if(NETWORK_ERT) + return access_cent_specops + + return access_security // Default for all other networks + +/datum/computer_file/program/camera_monitor + filename = "cammon" + filedesc = "Camera Monitoring" + nanomodule_path = /datum/nano_module/camera_monitor + program_icon_state = "generic" + extended_desc = "This program allows remote access to station's camera system. Some camera networks may have additional access requirements." + size = 12 + available_on_ntnet = 1 + requires_ntnet = 1 + +/datum/nano_module/camera_monitor + name = "Camera Monitoring program" + var/obj/machinery/camera/current_camera = null + var/current_network = null + +/datum/nano_module/camera_monitor/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) + var/list/data = host.initial_data() + + data["current_camera"] = current_camera ? current_camera.nano_structure() : null + data["current_network"] = current_network + + var/list/all_networks[0] + for(var/network in using_map.station_networks) + all_networks.Add(list(list( + "tag" = network, + "has_access" = can_access_network(usr, get_camera_access(network)) + ))) + + all_networks = modify_networks_list(all_networks) + + data["networks"] = all_networks + + if(current_network) + data["cameras"] = camera_repository.cameras_in_network(current_network) + + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "mod_sec_camera.tmpl", "Camera Monitoring", 900, 800) + // ui.auto_update_layout = 1 // Disabled as with suit sensors monitor - breaks the UI map. Re-enable once it's fixed somehow. + + ui.add_template("mapContent", "sec_camera_map_content.tmpl") + ui.add_template("mapHeader", "mod_sec_camera_map_header.tmpl") + ui.set_initial_data(data) + ui.open() + +// Intended to be overriden by subtypes to manually add non-station networks to the list. +/datum/nano_module/camera_monitor/proc/modify_networks_list(var/list/networks) + return networks + +/datum/nano_module/camera_monitor/proc/can_access_network(var/mob/user, var/network_access) + // No access passed, or 0 which is considered no access requirement. Allow it. + if(!network_access) + return 1 + + return check_access(user, access_security) || check_access(user, network_access) + +/datum/nano_module/camera_monitor/Topic(href, href_list) + if(..()) + return 1 + + if(href_list["switch_camera"]) + var/obj/machinery/camera/C = locate(href_list["switch_camera"]) in cameranet.cameras + if(!C) + return + if(!(current_network in C.network)) + return + + switch_to_camera(usr, C) + return 1 + + else if(href_list["switch_network"]) + if(!(href_list["switch_network"] in using_map.station_networks)) + return + + // Either security access, or access to the specific camera network's department is required in order to access the network. + if(can_access_network(usr, get_camera_access(href_list["switch_network"]))) + current_network = href_list["switch_network"] + else + usr << "\The [nano_host()] shows an \"Network Access Denied\" error message." + return 1 + + else if(href_list["reset"]) + reset_current() + usr.reset_view(current_camera) + return 1 + +/datum/nano_module/camera_monitor/proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C) + //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras. + if(isAI(user)) + var/mob/living/silicon/ai/A = user + // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise. + if(!A.is_in_chassis()) + return 0 + + A.eyeobj.setLoc(get_turf(C)) + A.client.eye = A.eyeobj + return 1 + + set_current(C) + user.machine = nano_host() + user.reset_view(C) + return 1 + +/datum/nano_module/camera_monitor/proc/set_current(var/obj/machinery/camera/C) + if(current_camera == C) + return + + if(current_camera) + reset_current() + + current_camera = C + if(current_camera) + var/mob/living/L = current_camera.loc + if(istype(L)) + L.tracking_initiated() + +/datum/nano_module/camera_monitor/proc/reset_current() + if(current_camera) + var/mob/living/L = current_camera.loc + if(istype(L)) + L.tracking_cancelled() + current_camera = null + +/datum/nano_module/camera_monitor/check_eye(var/mob/user as mob) + if(!current_camera) + return 0 + var/viewflag = current_camera.check_eye(user) + if ( viewflag < 0 ) //camera doesn't work + reset_current() + return viewflag + + +// ERT Variant of the program +/datum/computer_file/program/camera_monitor/ert + filename = "ntcammon" + filedesc = "Advanced Camera Monitoring" + extended_desc = "This program allows remote access to station's camera system. Some camera networks may have additional access requirements. This version has an integrated database with additional encrypted keys." + size = 14 + nanomodule_path = /datum/nano_module/camera_monitor/ert + available_on_ntnet = 0 + +/datum/nano_module/camera_monitor/ert + name = "Advanced Camera Monitoring Program" + +// The ERT variant has access to ERT and crescent cams, but still checks for accesses. ERT members should be able to use it. +/datum/nano_module/camera_monitor/hacked/modify_networks_list(var/list/networks) + ..() + networks.Add(list(list("tag" = NETWORK_ERT, "has_access" = 1))) + networks.Add(list(list("tag" = NETWORK_CRESCENT, "has_access" = 1))) + return networks \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm index b0bb56928e..77c0d97a0a 100644 --- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm @@ -133,7 +133,7 @@ var/list/all_entries[0] for(var/datum/computer_file/program/P in ntnet_global.available_station_software) // Only those programs our user can run will show in the list - if(!P.can_run(user)) + if(!P.can_run(user) && P.requires_access_to_download) continue all_entries.Add(list(list( "filename" = P.filename, diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index 56a699aabb..a7ed86a207 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -221,15 +221,17 @@ var/list/data[0] data["state"] = state - data["devtype"] = devtype - data["hw_battery"] = dev_battery - data["hw_disk"] = dev_disk - data["hw_netcard"] = dev_netcard - data["hw_tesla"] = dev_tesla - data["hw_nanoprint"] = dev_nanoprint - data["hw_card"] = dev_card - data["hw_cpu"] = dev_cpu - data["totalprice"] = "[total_price]$" + if(state == 1) + data["devtype"] = devtype + data["hw_battery"] = dev_battery + data["hw_disk"] = dev_disk + data["hw_netcard"] = dev_netcard + data["hw_tesla"] = dev_tesla + data["hw_nanoprint"] = dev_nanoprint + data["hw_card"] = dev_card + data["hw_cpu"] = dev_cpu + if(state == 1 || state == 2) + data["totalprice"] = total_price ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) diff --git a/code/modules/nano/modules/nano_module.dm b/code/modules/nano/modules/nano_module.dm index 82b04a4ed4..e5e0bf64f1 100644 --- a/code/modules/nano/modules/nano_module.dm +++ b/code/modules/nano/modules/nano_module.dm @@ -14,6 +14,25 @@ /datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = default_state) return CanUseTopic(usr, state) == STATUS_INTERACTIVE +/datum/nano_module/proc/check_eye(var/mob/user) + return -1 + +/datum/nano_module/proc/check_access(var/mob/user, var/access) + if(!access) + return 1 + + if(!istype(user)) + return 0 + + var/obj/item/weapon/card/id/I = user.GetIdCard() + if(!I) + return 0 + + if(access in I.access) + return 1 + + return 0 + /datum/nano_module/Topic(href, href_list) if(topic_manager && topic_manager.Topic(href, href_list)) return TRUE diff --git a/nano/templates/computer_fabricator.tmpl b/nano/templates/computer_fabricator.tmpl index 2df5c3af2a..c8d8b572b3 100644 --- a/nano/templates/computer_fabricator.tmpl +++ b/nano/templates/computer_fabricator.tmpl @@ -12,7 +12,7 @@
| Current Price: - | {{:data.totalprice}} + | {{:data.totalprice}}T |
| Battery: | {{:helper.link('Standard', null, { "hw_battery" : 1 }, data.hw_battery == 1 ? 'selected' : null)}}
@@ -63,7 +63,7 @@
Step 3: PaymentYour device is now ready for fabrication..Please swipe your identification card to finish purchase. - Total price: {{:data.totalprice}} + Total price: {{:data.totalprice}}T {{else data.state == 3}} Step 4: Thank you for your purchaseShould you experience any issues with your new device, contact technical support at support@computerservice.nt diff --git a/nano/templates/mod_sec_camera.tmpl b/nano/templates/mod_sec_camera.tmpl new file mode 100644 index 0000000000..0afb80f4b8 --- /dev/null +++ b/nano/templates/mod_sec_camera.tmpl @@ -0,0 +1,36 @@ +
+ {{:helper.link('Show Map', 'pin-s', {'showMap' : 1})}}
+ {{:helper.link('Reset', 'refresh', {'reset' : 1})}}
+
+
+
+
+
+Current Camera:
+ {{if data.current_camera}}
+ {{:data.current_camera.name}}
+ {{else}}
+ None
+ {{/if}}
+
+
+{{for data.networks}}
+ {{if value.has_access}}
+ {{:helper.link(value.tag, '', {'switch_network' : value.tag}, null, data.current_network == value.tag ? 'selected' : null)}}
+ {{else}}
+ {{:helper.link(value.tag, '', {}, null, data.current_network == value.tag ? 'selected' : 'redButton')}}
+ {{/if}}
+{{/for}}
+Networks:
+
+
+{{for data.cameras}}
+ {{if data.current_camera && value.name == data.current_camera.name}}
+ {{:helper.link(value.name, '', {'switch_camera' : value.camera}, 'selected')}}
+ {{else value.deact}}
+ {{:helper.link(value.name + " (deactivated)", '', {}, 'inactive')}}
+ {{else}}
+ {{:helper.link(value.name, '', {'switch_camera' : value.camera})}}
+ {{/if}}
+{{/for}}
diff --git a/nano/templates/mod_sec_camera_map_header.tmpl b/nano/templates/mod_sec_camera_map_header.tmpl
new file mode 100644
index 0000000000..459027797f
--- /dev/null
+++ b/nano/templates/mod_sec_camera_map_header.tmpl
@@ -0,0 +1,44 @@
+Cameras:
+
+ {{:helper.link('Show Camera List', 'script', {'showMap' : 0})}}
+ {{:helper.link('Reset', 'refresh', {'reset' : 1})}}
+
+
+
+
+Current Camera:
+ {{if data.current_camera}}
+ {{:data.current_camera.name}}
+ {{else}}
+ None
+ {{/if}}
+
+
+
+ Z-Level:
+
+
+ {{for config.mapZLevels :zValue:zIndex}}
+ {{:helper.link(zValue, 'close', {'mapZLevel' : zValue}, null, config.mapZLevel == zValue ? 'selected' : null)}}
+ {{/for}}
+
+
+
+
+ Zoom Level:
+
+
+
+x1.0
+ x1.5
+ x2.0
+ x2.5
+
+
+{{for data.networks}}
+ {{if value.has_access}}
+ {{:helper.link(value.tag, '', {'switch_network' : value.tag}, null, data.current_network == value.tag ? 'selected' : null)}}
+ {{else}}
+ {{:helper.link(value.tag, '', {}, null, data.current_network == value.tag ? 'selected' : 'redButton')}}
+ {{/if}}
+{{/for}}
\ No newline at end of file
diff --git a/polaris.dme b/polaris.dme
index ccd27f2f85..1c60e35ea3 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -2112,6 +2112,7 @@
#include "code\modules\modular_computers\file_system\programs\_engineering.dm"
#include "code\modules\modular_computers\file_system\programs\_medical.dm"
#include "code\modules\modular_computers\file_system\programs\_program.dm"
+#include "code\modules\modular_computers\file_system\programs\camera.dm"
#include "code\modules\modular_computers\file_system\programs\card.dm"
#include "code\modules\modular_computers\file_system\programs\comm.dm"
#include "code\modules\modular_computers\file_system\programs\configurator.dm"
@@ -2121,6 +2122,7 @@
#include "code\modules\modular_computers\file_system\programs\ntnrc_client.dm"
#include "code\modules\modular_computers\file_system\programs\nttransfer.dm"
#include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm"
+#include "code\modules\modular_computers\file_system\programs\antagonist\hacked_camera.dm"
#include "code\modules\modular_computers\file_system\programs\antagonist\revelation.dm"
#include "code\modules\modular_computers\hardware\battery_module.dm"
#include "code\modules\modular_computers\hardware\card_slot.dm"
Networks:
+ |