/obj/machinery/computer/security name = "security camera console" desc = "Used to access the various cameras on the station." icon_screen = "cameras" icon_keyboard = "security_key" circuit = /obj/item/circuitboard/computer/security light_color = LIGHT_COLOR_RED var/list/network = list("ss13") var/obj/machinery/camera/active_camera var/list/concurrent_users = list() // Stuff needed to render the map var/map_name var/const/default_map_size = 15 var/obj/screen/cam_screen var/obj/screen/plane_master/lighting/cam_plane_master var/obj/screen/background/cam_background /obj/machinery/computer/security/Initialize() . = ..() // Map name has to start and end with an A-Z character, // and definitely NOT with a square bracket or even a number. // I wasted 6 hours on this. :agony: map_name = "camera_console_[REF(src)]_map" // Convert networks to lowercase for(var/i in network) network -= i network += lowertext(i) // Initialize map objects cam_screen = new cam_screen.name = "screen" cam_screen.assigned_map = map_name cam_screen.del_on_map_removal = FALSE cam_screen.screen_loc = "[map_name]:1,1" cam_plane_master = new cam_plane_master.name = "plane_master" cam_plane_master.assigned_map = map_name cam_plane_master.del_on_map_removal = FALSE cam_plane_master.screen_loc = "[map_name]:CENTER" cam_background = new cam_background.assigned_map = map_name cam_background.del_on_map_removal = FALSE /obj/machinery/computer/security/Destroy() qdel(cam_screen) qdel(cam_plane_master) qdel(cam_background) return ..() /obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) for(var/i in network) network -= i network += "[idnum][i]" /obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui) // Update UI ui = SStgui.try_update_ui(user, src, ui) // Show static if can't use the camera if(!active_camera?.can_use()) show_camera_static() if(!ui) var/user_ref = REF(user) var/is_living = isliving(user) // Ghosts shouldn't count towards concurrent users, which produces // an audible terminal_on click. if(is_living) concurrent_users += user_ref // Turn on the console if(length(concurrent_users) == 1 && is_living) playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE) use_power(active_power_usage) // Register map objects user.client.register_map_obj(cam_screen) for(var/plane in cam_plane_master) user.client.register_map_obj(plane) user.client.register_map_obj(cam_background) // Open UI ui = new(user, src, "CameraConsole", name) ui.open() /obj/machinery/computer/security/ui_data() var/list/data = list() data["network"] = network data["activeCamera"] = null if(active_camera) data["activeCamera"] = list( name = active_camera.c_tag, status = active_camera.status, ) return data /obj/machinery/computer/security/ui_static_data() var/list/data = list() data["mapRef"] = map_name var/list/cameras = get_available_cameras() data["cameras"] = list() for(var/i in cameras) var/obj/machinery/camera/C = cameras[i] data["cameras"] += list(list( name = C.c_tag, )) return data /obj/machinery/computer/security/ui_act(action, params) . = ..() if(.) return if(action == "switch_camera") var/c_tag = params["name"] var/list/cameras = get_available_cameras() var/obj/machinery/camera/C = cameras[c_tag] active_camera = C playsound(src, get_sfx("terminal_type"), 25, FALSE) // Show static if can't use the camera if(!active_camera?.can_use()) show_camera_static() return TRUE var/list/visible_turfs = list() for(var/turf/T in (C.isXRay() \ ? range(C.view_range, C) \ : view(C.view_range, C))) visible_turfs += T var/list/bbox = get_bbox_of_atoms(visible_turfs) var/size_x = bbox[3] - bbox[1] + 1 var/size_y = bbox[4] - bbox[2] + 1 cam_screen.vis_contents = visible_turfs cam_background.icon_state = "clear" cam_background.fill_rect(1, 1, size_x, size_y) return TRUE /obj/machinery/computer/security/ui_close(mob/user) var/user_ref = REF(user) var/is_living = isliving(user) // Living creature or not, we remove you anyway. concurrent_users -= user_ref // Unregister map objects user.client.clear_map(map_name) // Turn off the console if(length(concurrent_users) == 0 && is_living) active_camera = null playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) use_power(0) /obj/machinery/computer/security/proc/show_camera_static() cam_screen.vis_contents.Cut() cam_background.icon_state = "scanline2" cam_background.fill_rect(1, 1, default_map_size, default_map_size) // Returns the list of cameras accessible from this computer /obj/machinery/computer/security/proc/get_available_cameras() var/list/L = list() for (var/obj/machinery/camera/C in GLOB.cameranet.cameras) if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras continue L.Add(C) var/list/D = list() for(var/obj/machinery/camera/C in L) if(!C.network) stack_trace("Camera in a cameranet has no camera network") continue if(!(islist(C.network))) stack_trace("Camera in a cameranet has a non-list camera network") continue var/list/tempnetwork = C.network & network if(tempnetwork.len) D["[C.c_tag]"] = C return D // SECURITY MONITORS /obj/machinery/computer/security/wooden_tv name = "security camera monitor" desc = "An old TV hooked into the station's camera network." icon_state = "television" icon_keyboard = null icon_screen = "detective_tv" pass_flags = PASSTABLE /obj/machinery/computer/security/mining name = "outpost camera console" desc = "Used to access the various cameras on the outpost." icon_screen = "mining" icon_keyboard = "mining_key" network = list("mine", "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") 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") 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") circuit = null /obj/machinery/computer/security/qm name = "\improper Quartermaster's camera console" desc = "A console with access to the mining, auxillary base and vault camera networks." network = list("mine", "auxbase", "vault") circuit = null // TELESCREENS /obj/machinery/computer/security/telescreen name = "\improper Telescreen" desc = "Used for watching an empty arena." icon = 'icons/obj/stationobjs.dmi' icon_state = "telescreen" network = list("thunder") density = FALSE circuit = null light_power = 0 /obj/machinery/computer/security/telescreen/Initialize() . = ..() var/turf/T = get_turf_pixel(src) if(iswallturf(T)) plane = ABOVE_WALL_PLANE /obj/machinery/computer/security/telescreen/update_icon_state() icon_state = initial(icon_state) if(stat & BROKEN) icon_state += "b" /obj/machinery/computer/security/telescreen/entertainment name = "entertainment monitor" desc = "Damn, they better have the /tg/ channel on these things." icon = 'icons/obj/status_display.dmi' icon_state = "entertainment_blank" network = list("thunder") density = FALSE circuit = null interaction_flags_atom = NONE // interact() is called by BigClick() var/icon_state_off = "entertainment_blank" var/icon_state_on = "entertainment" /obj/machinery/computer/security/telescreen/entertainment/Initialize() . = ..() RegisterSignal(src, COMSIG_CLICK, .proc/BigClick) // Bypass clickchain to allow humans to use the telescreen from a distance /obj/machinery/computer/security/telescreen/entertainment/proc/BigClick() interact(usr) /obj/machinery/computer/security/telescreen/entertainment/proc/notify(on) if(on && icon_state == icon_state_off) say(pick( "Feats of bravery live now at the thunderdome!", "Two enter, one leaves! Tune in now!", "Violence like you've never seen it before!", "Spears! Camera! Action! LIVE NOW!")) icon_state = icon_state_on else icon_state = icon_state_off /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") /obj/machinery/computer/security/telescreen/circuitry name = "circuitry telescreen" desc = "Used for watching the other eggheads from the safety of the circuitry lab." network = list("rd") /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") /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") /obj/machinery/computer/security/telescreen/vault name = "vault monitor" desc = "A telescreen that connects to the vault's camera network." network = list("vault") /obj/machinery/computer/security/telescreen/toxins name = "bomb test site monitor" desc = "A telescreen that connects to the bomb test site's camera." network = list("toxins") /obj/machinery/computer/security/telescreen/engine name = "engine monitor" desc = "A telescreen that connects to the engine's camera network." network = list("engine") /obj/machinery/computer/security/telescreen/turbine name = "turbine monitor" desc = "A telescreen that connects to the turbine's camera." network = list("turbine") /obj/machinery/computer/security/telescreen/interrogation name = "interrogation room monitor" desc = "A telescreen that connects to the interrogation room's camera." network = list("interrogation") /obj/machinery/computer/security/telescreen/prison name = "prison monitor" desc = "A telescreen that connects to the permabrig's camera network." network = list("prison") /obj/machinery/computer/security/telescreen/auxbase name = "auxillary base monitor" desc = "A telescreen that connects to the auxillary base's camera." network = list("auxbase") /obj/machinery/computer/security/telescreen/minisat name = "minisat monitor" desc = "A telescreen that connects to the minisat's camera network." network = list("minisat") /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") // Subtype that connects to shuttles. /obj/machinery/computer/security/shuttle circuit = /obj/item/circuitboard/computer/security/shuttle /obj/machinery/computer/security/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) for(var/i in network) network -= i network += "[idnum][i]"