Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix camera console feeds not following moving cameras #27851

Merged
merged 8 commits into from
Jan 28, 2025
1 change: 1 addition & 0 deletions code/_globalvars/lists/objects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(pandemics)
GLOBAL_LIST_EMPTY(all_areas)
GLOBAL_LIST_EMPTY(all_unique_areas) // List of all unique areas. AKA areas with there_can_be_many = FALSE
GLOBAL_LIST_EMPTY(machines)
GLOBAL_LIST_EMPTY(telescreens) /// List of entertainment telescreens connected to the "news" cameranet
GLOBAL_LIST_EMPTY(rcd_list) //list of Rapid Construction Devices.

GLOBAL_LIST_EMPTY(apcs)
Expand Down
58 changes: 41 additions & 17 deletions code/game/machinery/computer/camera_console.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/// The root type of all camera consoles. When used, these open a UI that has a left-hand sidebar
/// displaying a list of active cameras in the console's assigned camera `network`. The bulk of the window
/// on the right hand side displays a camera feed of the selected camera. This feed will attempt to refresh
/// every time process() is called by SSobj as long as there are active watchers, living or dead.
/obj/machinery/computer/security
name = "security camera console"
desc = "Used to access the various cameras networks on the station."
Expand All @@ -10,7 +14,10 @@

var/list/network = list("SS13","Mining Outpost")
var/obj/machinery/camera/active_camera
/// The list of total watchers, living and dead, of this console.
var/list/watchers = list()
/// The list of living watchers of this console. Used for playing a "terminal on" sound on first live viewer.
var/list/living_watchers = list()

// Stuff needed to render the map
var/map_name
Expand All @@ -20,7 +27,7 @@
var/list/cam_plane_masters
var/atom/movable/screen/background/cam_background

// Parent object this camera is assigned to. Used for camera bugs
/// Parent object this camera is assigned to. Used for camera bugs
var/atom/movable/parent

/// is the console silent when switching cameras?
Expand All @@ -46,6 +53,7 @@
cam_background.del_on_map_removal = FALSE

/obj/machinery/computer/security/Destroy()
STOP_PROCESSING(SSobj, src)
qdel(cam_screen)
qdel(cam_background)
return ..()
Expand All @@ -64,10 +72,11 @@
var/is_living = isliving(user)
// Ghosts shouldn't count towards concurrent users, which produces
// an audible terminal_on click.
watchers += user_uid
if(is_living)
watchers += user_uid
living_watchers += user_uid
// Turn on the console
if(length(watchers) == 1 && is_living)
if(length(living_watchers) == 1 && is_living)
if(!silent_console)
playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE)
use_power(active_power_consumption)
Expand All @@ -85,10 +94,18 @@
// Open UI
ui = new(user, src, "CameraConsole", name)
ui.open()
START_PROCESSING(SSobj, src)

/obj/machinery/computer/security/process()
update_viewer()
if(length(watchers))
return
STOP_PROCESSING(SSobj, src)

/obj/machinery/computer/security/ui_close(mob/user)
..()
watchers -= user.UID()
living_watchers -= user.UID()
user.client.clear_map(map_name)

/obj/machinery/computer/security/ui_data()
Expand Down Expand Up @@ -126,25 +143,27 @@
active_camera = C
if(!silent_console)
playsound(src, get_sfx("terminal_type"), 25, FALSE)
return update_viewer()

// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
return TRUE
/obj/machinery/computer/security/proc/update_viewer()
// 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 view(C.view_range, get_turf(C)))
visible_turfs += T
var/list/visible_turfs = list()
for(var/turf/T in view(active_camera.view_range, get_turf(active_camera)))
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
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)
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)

return TRUE
return TRUE

// Returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
Expand Down Expand Up @@ -233,6 +252,11 @@
/obj/machinery/computer/security/telescreen/entertainment/Initialize(mapload)
. = ..()
set_light(1, LIGHTING_MINIMUM_POWER) //so byond doesnt cull, and we get an emissive appearance
GLOB.telescreens += src

/obj/machinery/computer/security/telescreen/entertainment/Destroy()
GLOB.telescreens -= src
return ..()

/obj/machinery/computer/security/telescreen/entertainment/update_overlays()
if(feeds_on)
Expand Down
10 changes: 6 additions & 4 deletions code/modules/paperwork/photography.dm
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
/**************
*video camera *
***************/
/// The amount of time after being turned off that the camera is too hot to turn back on.
#define CAMERA_STATE_COOLDOWN 2 SECONDS

/obj/item/videocam
Expand All @@ -608,12 +609,13 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
w_class = WEIGHT_CLASS_NORMAL
materials = list(MAT_METAL = 1000, MAT_GLASS = 500)
var/on = FALSE
var/video_cooldown = 0
var/obj/machinery/camera/camera
var/icon_on = "videocam_on"
var/icon_off = "videocam"
var/canhear_range = 7

COOLDOWN_DECLARE(video_cooldown)

/obj/item/videocam/proc/camera_state(mob/living/carbon/user)
if(!on)
on = TRUE
Expand All @@ -627,16 +629,16 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
camera.c_tag = null
QDEL_NULL(camera)
visible_message("<span class='notice'>The video camera has been turned [on ? "on" : "off"].</span>")
for(var/obj/machinery/computer/security/telescreen/entertainment/TV in GLOB.machines)
for(var/obj/machinery/computer/security/telescreen/entertainment/TV in GLOB.telescreens)
if(on)
TV.feeds_on++
else
TV.feeds_on--
TV.update_icon(UPDATE_OVERLAYS)
video_cooldown = world.time + CAMERA_STATE_COOLDOWN
COOLDOWN_START(src, video_cooldown, CAMERA_STATE_COOLDOWN)

/obj/item/videocam/attack_self__legacy__attackchain(mob/user)
if(world.time < video_cooldown)
if(!COOLDOWN_FINISHED(src, video_cooldown))
to_chat(user, "<span class='warning'>[src] is overheating, give it some time.</span>")
return
camera_state(user)
Expand Down
Loading