From 2268c332962930787cd9c1bee49e1835edf178a9 Mon Sep 17 00:00:00 2001 From: Ian Turk Date: Tue, 1 May 2018 21:40:01 -0700 Subject: [PATCH 1/5] Added multicamera mode for AIs --- _maps/map_files/generic/CentCom.dmm | 588 +++++++++--------- code/_onclick/ai.dm | 8 + code/_onclick/hud/_defines.dm | 2 + code/_onclick/hud/ai.dm | 30 +- code/_onclick/hud/movable_screen_objects.dm | 6 +- code/_onclick/hud/picture_in_picture.dm | 144 +++++ code/_onclick/hud/screen_objects.dm | 15 + code/datums/holocall.dm | 5 +- .../machinery/computer/camera_advanced.dm | 2 +- code/modules/lighting/lighting_object.dm | 2 - code/modules/mob/living/silicon/ai/ai.dm | 17 +- .../living/silicon/ai/freelook/cameranet.dm | 70 ++- .../mob/living/silicon/ai/freelook/chunk.dm | 18 +- .../mob/living/silicon/ai/freelook/eye.dm | 37 +- code/modules/mob/living/silicon/ai/login.dm | 2 + .../modules/mob/living/silicon/ai/multicam.dm | 207 ++++++ icons/misc/pic_in_pic.dmi | Bin 0 -> 15633 bytes icons/mob/screen_ai.dmi | Bin 2398 -> 2543 bytes icons/turf/areas.dmi | Bin 36625 -> 36866 bytes tgstation.dme | 2 + 20 files changed, 817 insertions(+), 338 deletions(-) create mode 100644 code/_onclick/hud/picture_in_picture.dm create mode 100644 code/modules/mob/living/silicon/ai/multicam.dm create mode 100644 icons/misc/pic_in_pic.dmi diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 66cfb66cdbbecc..d6e9ec1115ef2c 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -13454,6 +13454,9 @@ }, /turf/open/floor/plasteel, /area/centcom/control) +"TY" = ( +/turf/open/ai_visible, +/area/ai_multicam_room) "Un" = ( /obj/machinery/door/airlock/centcom{ name = "Thunderdome"; @@ -13466,6 +13469,10 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plasteel, /area/tdome/tdomeobserve) +"UB" = ( +/obj/effect/landmark/ai_multicam_room, +/turf/open/ai_visible, +/area/ai_multicam_room) "UO" = ( /obj/machinery/door/airlock/centcom{ name = "CentCom Security"; @@ -13527,6 +13534,9 @@ }, /turf/open/floor/plasteel, /area/centcom/ferry) +"WR" = ( +/turf/closed/indestructible/riveted, +/area/ai_multicam_room) "Xt" = ( /obj/machinery/door/airlock/centcom{ name = "CentCom Security"; @@ -18446,23 +18456,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR aa aa aa @@ -18703,23 +18713,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -18960,23 +18970,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -19217,23 +19227,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -19474,23 +19484,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -19731,23 +19741,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -19988,23 +19998,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -20245,23 +20255,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -20502,23 +20512,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +UB +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -20759,23 +20769,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -21016,23 +21026,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -21273,23 +21283,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -21530,23 +21540,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -21787,23 +21797,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -22044,23 +22054,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -22301,23 +22311,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +TY +WR aa aa aa @@ -22558,23 +22568,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR +WR aa aa aa diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 9ef689de8bc2fc..e15d4f035c45f2 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -26,6 +26,14 @@ return next_click = world.time + 1 + if(multicam_on) + var/turf/T = get_turf(A) + if(T) + for(var/obj/screen/movable/pic_in_pic/ai/P in T.vis_locs) + if(P.ai == src) + P.Click(params) + break + if(check_click_intercept(params,A)) return diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 9a325dfa1a5a79..cb170ffbf0aa87 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -134,6 +134,8 @@ #define ui_ai_take_picture "SOUTH:6,WEST+12" #define ui_ai_view_images "SOUTH:6,WEST+13" #define ui_ai_sensor "SOUTH:6,WEST+14" +#define ui_ai_multicam "SOUTH+1:6,WEST+13" +#define ui_ai_add_multicam "SOUTH+1:6,WEST+14" //Pop-up inventory #define ui_shoes "WEST+1:8,SOUTH:5" diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index 8d4aca5fbf1833..463051c6b4e51d 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -164,6 +164,26 @@ var/mob/living/silicon/S = usr S.toggle_sensors() +/obj/screen/ai/multicam + name = "Multicamera Mode" + icon_state = "multicam" + +/obj/screen/ai/multicam/Click() + if(..()) + return + var/mob/living/silicon/ai/AI = usr + AI.toggle_multicam() + +/obj/screen/ai/add_multicam + name = "New Camera" + icon_state = "new_cam" + +/obj/screen/ai/add_multicam/Click() + if(..()) + return + var/mob/living/silicon/ai/AI = usr + AI.drop_new_multicam() + /datum/hud/ai ui_style_icon = 'icons/mob/screen_ai.dmi' @@ -247,12 +267,20 @@ using.screen_loc = ui_ai_view_images static_inventory += using - //Medical/Security sensors using = new /obj/screen/ai/sensors() using.screen_loc = ui_ai_sensor static_inventory += using +//Multicamera mode + using = new /obj/screen/ai/multicam() + using.screen_loc = ui_ai_multicam + static_inventory += using + +//Add multicamera camera + using = new /obj/screen/ai/add_multicam() + using.screen_loc = ui_ai_add_multicam + static_inventory += using /mob/living/silicon/ai/create_mob_hud() if(client && !hud_used) diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index 4da721012d47fa..f71ced7a9d2741 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -12,6 +12,8 @@ var/snap2grid = FALSE var/moved = FALSE var/locked = FALSE + var/x_off = -16 + var/y_off = -16 //Snap Screen Object //Tied to the grid, snaps to the nearest turf @@ -42,8 +44,8 @@ screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]" else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off) - var/pix_X = text2num(screen_loc_X[2]) - 16 - var/pix_Y = text2num(screen_loc_Y[2]) - 16 + var/pix_X = text2num(screen_loc_X[2]) + x_off + var/pix_Y = text2num(screen_loc_Y[2]) + y_off screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]" moved = screen_loc diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm new file mode 100644 index 00000000000000..494adbd4547259 --- /dev/null +++ b/code/_onclick/hud/picture_in_picture.dm @@ -0,0 +1,144 @@ +/obj/screen/movable/pic_in_pic + name = "Picture-in-picture" + screen_loc = "CENTER" + plane = GAME_PLANE + var/atom/center + var/width = 0 + var/height = 0 + var/list/shown_to = list() + var/list/viewing_turfs = list() + var/obj/screen/component_button/button_x + var/obj/screen/component_button/button_expand + var/obj/screen/component_button/button_shrink + + var/mutable_appearance/standard_background + var/const/max_dimensions = 10 + +/obj/screen/movable/pic_in_pic/Initialize() + . = ..() + make_backgrounds() + +/obj/screen/movable/pic_in_pic/Destroy() + . = ..() + for(var/C in shown_to) + unshow_to(C) + qdel(button_x) + qdel(button_shrink) + qdel(button_expand) + +/obj/screen/movable/pic_in_pic/component_click(obj/screen/component_button/component, params) + if(component == button_x) + qdel(src) + else if(component == button_expand) + set_view_size(width+1, height+1) + else if(component == button_shrink) + set_view_size(width-1, height-1) + +/obj/screen/movable/pic_in_pic/proc/make_backgrounds() + standard_background = new /mutable_appearance() + standard_background.icon = 'icons/misc/pic_in_pic.dmi' + standard_background.icon_state = "background" + standard_background.layer = SPACE_LAYER + +/obj/screen/movable/pic_in_pic/proc/add_buttons() + var/static/mutable_appearance/move_tab + if(!move_tab) + move_tab = new /mutable_appearance() + //all these properties are always the same, and since adding something to the overlay + //list makes a copy, there is no reason to make a new one each call + move_tab.icon = 'icons/misc/pic_in_pic.dmi' + move_tab.icon_state = "move" + move_tab.plane = HUD_PLANE + var/matrix/M = matrix() + M.Translate(0, (height + 0.25) * world.icon_size) + move_tab.transform = M + add_overlay(move_tab) + + if(!button_x) + button_x = new /obj/screen/component_button(null, src) + var/mutable_appearance/MA = new /mutable_appearance() + MA.name = "close" + MA.icon = 'icons/misc/pic_in_pic.dmi' + MA.icon_state = "x" + MA.plane = HUD_PLANE + button_x.appearance = MA + M = matrix() + M.Translate((max(4, width) - 0.75) * world.icon_size, (height + 0.25) * world.icon_size) + button_x.transform = M + vis_contents += button_x + + if(!button_expand) + button_expand = new /obj/screen/component_button(null, src) + var/mutable_appearance/MA = new /mutable_appearance() + MA.name = "expand" + MA.icon = 'icons/misc/pic_in_pic.dmi' + MA.icon_state = "expand" + MA.plane = HUD_PLANE + button_expand.appearance = MA + M = matrix() + M.Translate(world.icon_size, (height + 0.25) * world.icon_size) + button_expand.transform = M + vis_contents += button_expand + + if(!button_shrink) + button_shrink = new /obj/screen/component_button(null, src) + var/mutable_appearance/MA = new /mutable_appearance() + MA.name = "shrink" + MA.icon = 'icons/misc/pic_in_pic.dmi' + MA.icon_state = "shrink" + MA.plane = HUD_PLANE + button_shrink.appearance = MA + M = matrix() + M.Translate(2 * world.icon_size, (height + 0.25) * world.icon_size) + button_shrink.transform = M + vis_contents += button_shrink + +/obj/screen/movable/pic_in_pic/proc/add_background() + if((width > 0) && (height > 0)) + var/matrix/M = matrix() + M.Scale(width + 0.5, height + 0.5) + M.Translate((width-1)/2 * world.icon_size, (height-1)/2 * world.icon_size) + standard_background.transform = M + add_overlay(standard_background) + +/obj/screen/movable/pic_in_pic/proc/set_view_size(width, height, do_refresh = TRUE) + width = CLAMP(width, 0, max_dimensions) + height = CLAMP(height, 0, max_dimensions) + src.width = width + src.height = height + + y_off = -height * world.icon_size - 16 + + cut_overlays() + add_background() + add_buttons() + if(do_refresh) + refresh_view() + +/obj/screen/movable/pic_in_pic/proc/set_view_center(atom/target, do_refresh = TRUE) + center = target + if(do_refresh) + refresh_view() + +/obj/screen/movable/pic_in_pic/proc/refresh_view() + vis_contents -= viewing_turfs + if(!width || !height) + return + var/turf/T = get_turf(center) + if(!T) + return + var/turf/lowerleft = locate(max(1, T.x - round(width/2)), max(1, T.y - round(height/2)), T.z) + var/turf/upperright = locate(min(world.maxx, lowerleft.x + width - 1), min(world.maxy, lowerleft.y + height - 1), lowerleft.z) + viewing_turfs = block(lowerleft, upperright) + vis_contents += viewing_turfs + + +/obj/screen/movable/pic_in_pic/proc/show_to(client/C) + if(C) + shown_to |= C + C.screen += src + +/obj/screen/movable/pic_in_pic/proc/unshow_to(client/C) + if(C) + shown_to -= C + C.screen -= src diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 02ece81b410610..d2ac10a83f6ed5 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -30,6 +30,9 @@ /obj/screen/orbit() return +/obj/screen/proc/component_click(obj/screen/component_button/component, params) + return + /obj/screen/text icon = null icon_state = null @@ -604,3 +607,15 @@ holder.screen -= src holder = null return ..() + + +/obj/screen/component_button + var/obj/screen/parent + +/obj/screen/component_button/Initialize(mapload, obj/screen/parent) + . = ..() + src.parent = parent + +/obj/screen/component_button/Click(params) + if(parent) + parent.component_click(src, params) diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index d19e8be2e1ac18..22dc6a767175b8 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -60,9 +60,6 @@ user.remote_control = null if(!QDELETED(eye)) - if(user_good && user.client) - for(var/datum/camerachunk/chunk in eye.visibleCameraChunks) - chunk.remove(eye) qdel(eye) eye = null @@ -284,7 +281,7 @@ else var/datum/preset_holoimage/H = new preset_image_type record.caller_image = H.build_image() - + //These build caller image from outfit and some additional data, for use by mappers for ruin holorecords /datum/preset_holoimage var/nonhuman_mobtype //Fill this if you just want something nonhuman diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 6112a5d7609432..26a8ac940e0916 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -190,7 +190,7 @@ else moveToNullspace() if(use_static) - GLOB.cameranet.visibility(src) + GLOB.cameranet.visibility(src, GetViewerClient()) if(visible_icon) if(eye_user.client) eye_user.client.images -= user_image diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index fe25dc94397465..c0c5a411e7de30 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -11,8 +11,6 @@ layer = LIGHTING_LAYER invisibility = INVISIBILITY_LIGHTING - blend_mode = BLEND_ADD - var/needs_update = FALSE var/turf/myturf diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 650e4c55cb4b43..b3828b877a43bc 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -74,7 +74,7 @@ var/nuking = FALSE var/obj/machinery/doomsday_device/doomsday_device - var/mob/camera/aiEye/eyeobj = new + var/mob/camera/aiEye/eyeobj var/sprint = 10 var/cooldown = 0 var/acceleration = 1 @@ -85,6 +85,12 @@ var/datum/action/innate/deploy_last_shell/redeploy_action = new var/chnotify = 0 + var/multicam_on = FALSE + var/obj/screen/movable/pic_in_pic/ai/master_multicam + var/list/multicam_screens = list() + var/list/all_eyes = list() + var/max_multicams = 6 + /mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai) . = ..() if(!target_ai) //If there is no player/brain inside. @@ -116,8 +122,7 @@ job = "AI" - eyeobj.ai = src - eyeobj.forceMove(src.loc) + create_eye() rename_self("ai") holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"default")) @@ -870,9 +875,12 @@ current = A if(client) if(ismovableatom(A)) + if(A != GLOB.ai_camera_room_landmark) + end_multicam() client.perspective = EYE_PERSPECTIVE client.eye = A else + end_multicam() if(isturf(loc)) if(eyeobj) client.eye = eyeobj @@ -992,3 +1000,6 @@ . = ..() if(!target_ai) target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct + +/mob/living/silicon/ai/proc/camera_visibility(mob/camera/aiEye/moved_eye) + GLOB.cameranet.visibility(moved_eye, client, all_eyes) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 815ddb64ea92b9..5cc08ff1e0d7ac 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -38,29 +38,63 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) // Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set. -/datum/cameranet/proc/visibility(mob/camera/aiEye/ai) - // 0xf = 15 - var/x1 = max(0, ai.x - 16) & ~(CHUNK_SIZE - 1) - var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1) - var/x2 = min(world.maxx, ai.x + 16) & ~(CHUNK_SIZE - 1) - var/y2 = min(world.maxy, ai.y + 16) & ~(CHUNK_SIZE - 1) +/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes) + if(!islist(moved_eyes)) + moved_eyes = moved_eyes ? list(moved_eyes) : list() + if(islist(other_eyes)) + other_eyes = (other_eyes - moved_eyes) + else + other_eyes = list() + + var/list/chunks_pre_seen = list() + var/list/chunks_post_seen = list() + + for(var/V in moved_eyes) + var/mob/camera/aiEye/eye = V + if(C) + chunks_pre_seen |= eye.visibleCameraChunks + // 0xf = 15 + var/static_range = eye.static_visibility_range + var/x1 = max(0, eye.x - static_range) & ~(CHUNK_SIZE - 1) + var/y1 = max(0, eye.y - static_range) & ~(CHUNK_SIZE - 1) + var/x2 = min(world.maxx, eye.x + static_range) & ~(CHUNK_SIZE - 1) + var/y2 = min(world.maxy, eye.y + static_range) & ~(CHUNK_SIZE - 1) + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += CHUNK_SIZE) + for(var/y = y1; y <= y2; y += CHUNK_SIZE) + visibleChunks |= getCameraChunk(x, y, eye.z) + + var/list/remove = eye.visibleCameraChunks - visibleChunks + var/list/add = visibleChunks - eye.visibleCameraChunks + + for(var/chunk in remove) + var/datum/camerachunk/c = chunk + c.remove(eye, FALSE) + + for(var/chunk in add) + var/datum/camerachunk/c = chunk + c.add(eye, FALSE) - var/list/visibleChunks = list() + if(C) + chunks_post_seen |= eye.visibleCameraChunks - for(var/x = x1; x <= x2; x += CHUNK_SIZE) - for(var/y = y1; y <= y2; y += CHUNK_SIZE) - visibleChunks |= getCameraChunk(x, y, ai.z) + if(C) + for(var/V in other_eyes) + var/mob/camera/aiEye/eye = V + chunks_post_seen |= eye.visibleCameraChunks - var/list/remove = ai.visibleCameraChunks - visibleChunks - var/list/add = visibleChunks - ai.visibleCameraChunks + var/list/remove = chunks_pre_seen - chunks_post_seen + var/list/add = chunks_post_seen - chunks_pre_seen - for(var/chunk in remove) - var/datum/camerachunk/c = chunk - c.remove(ai) + for(var/chunk in remove) + var/datum/camerachunk/c = chunk + C.images -= c.obscured - for(var/chunk in add) - var/datum/camerachunk/c = chunk - c.add(ai) + for(var/chunk in add) + var/datum/camerachunk/c = chunk + C.images += c.obscured // Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index f062c7e0104e9b..e03bba3067b592 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -20,10 +20,11 @@ // Add an AI eye to the chunk, then update if changed. -/datum/camerachunk/proc/add(mob/camera/aiEye/eye) - var/client/client = eye.GetViewerClient() - if(client) - client.images += obscured +/datum/camerachunk/proc/add(mob/camera/aiEye/eye, add_images = TRUE) + if(add_images) + var/client/client = eye.GetViewerClient() + if(client) + client.images += obscured eye.visibleCameraChunks += src visible++ seenby += eye @@ -32,10 +33,11 @@ // Remove an AI eye from the chunk, then update if changed. -/datum/camerachunk/proc/remove(mob/camera/aiEye/eye) - var/client/client = eye.GetViewerClient() - if(client) - client.images -= obscured +/datum/camerachunk/proc/remove(mob/camera/aiEye/eye, remove_images = TRUE) + if(remove_images) + var/client/client = eye.GetViewerClient() + if(client) + client.images -= obscured eye.visibleCameraChunks -= src seenby -= eye if(visible > 0) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index b5b1bd082b95ba..f14a56a38c93ab 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -11,6 +11,7 @@ var/mob/living/silicon/ai/ai = null var/relay_speech = FALSE var/use_static = TRUE + var/static_visibility_range = 16 // Use this when setting the aiEye's location. // It will also stream the chunk that the new loc is in. @@ -25,8 +26,8 @@ else moveToNullspace() // ???? if(use_static) - GLOB.cameranet.visibility(src) - if(ai.client) + ai.camera_visibility(src) + if(ai.client && !ai.multicam_on) ai.client.eye = src update_parallax_contents() //Holopad @@ -35,6 +36,8 @@ H.move_hologram(ai, T) if(ai.camera_light_on) ai.light_cameras() + if(ai.master_multicam) + ai.master_multicam.refresh_view() /mob/camera/aiEye/Move() return 0 @@ -45,18 +48,25 @@ return null /mob/camera/aiEye/proc/RemoveImages() - if(use_static) - for(var/datum/camerachunk/chunk in visibleCameraChunks) - chunk.remove(src) + var/client/C = GetViewerClient() + if(C && use_static) + for(var/V in visibleCameraChunks) + var/datum/camerachunk/c = V + C.images -= c.obscured /mob/camera/aiEye/Destroy() - ai = null + if(ai) + ai.all_eyes -= src + ai = null + for(var/V in visibleCameraChunks) + var/datum/camerachunk/c = V + c.remove(src) return ..() /atom/proc/move_camera_by_click() if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - if(AI.eyeobj && AI.client.eye == AI.eyeobj) + if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z)) AI.cameraFollow = null if (isturf(src.loc) || isturf(src)) AI.eyeobj.setLoc(src) @@ -95,12 +105,19 @@ if(!eyeobj || !eyeobj.loc || QDELETED(eyeobj)) to_chat(src, "ERROR: Eyeobj not found. Creating new eye...") - eyeobj = new(loc) - eyeobj.ai = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name + create_eye() eyeobj.setLoc(loc) +/mob/living/silicon/ai/proc/create_eye() + if(eyeobj) + return + eyeobj = new /mob/camera/aiEye() + all_eyes += eyeobj + eyeobj.ai = src + eyeobj.setLoc(src.loc) + eyeobj.name = "[src.name] (AI Eye)" + /mob/living/silicon/ai/verb/toggle_acceleration() set category = "AI Commands" set name = "Toggle Camera Acceleration" diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index c771f60aa2346b..2dc9a1fb1c8fbc 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -4,4 +4,6 @@ for(var/obj/machinery/ai_status_display/O in GLOB.ai_status_displays) //change status O.mode = 1 O.emotion = "Neutral" + if(multicam_on) + end_multicam() view_core() diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm new file mode 100644 index 00000000000000..8562e69de0a505 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -0,0 +1,207 @@ +//Picture in picture + +/obj/screen/movable/pic_in_pic/ai + var/mob/living/silicon/ai/ai + var/mutable_appearance/highlighted_background + var/highlighted = FALSE + var/mob/camera/aiEye/pic_in_pic/aiEye + +/obj/screen/movable/pic_in_pic/ai/Initialize() + . = ..() + aiEye = new /mob/camera/aiEye/pic_in_pic() + aiEye.screen = src + +/obj/screen/movable/pic_in_pic/ai/Destroy() + . = ..() + set_ai(null) + qdel(aiEye) + +/obj/screen/movable/pic_in_pic/ai/Click() + ..() + if(ai) + ai.select_main_multicam_window(src) + +/obj/screen/movable/pic_in_pic/ai/make_backgrounds() + ..() + highlighted_background = new /mutable_appearance() + highlighted_background.icon = 'icons/misc/pic_in_pic.dmi' + highlighted_background.icon_state = "background_highlight" + highlighted_background.layer = SPACE_LAYER + +/obj/screen/movable/pic_in_pic/ai/add_background() + if((width > 0) && (height > 0)) + var/matrix/M = matrix() + M.Scale(width + 0.5, height + 0.5) + M.Translate((width-1)/2 * world.icon_size, (height-1)/2 * world.icon_size) + highlighted_background.transform = M + standard_background.transform = M + add_overlay(highlighted ? highlighted_background : standard_background) + +/obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE) + aiEye.static_visibility_range = max(width, height) + if(ai) + ai.camera_visibility(aiEye) + ..() + +/obj/screen/movable/pic_in_pic/ai/set_view_center(atom/target, do_refresh = TRUE) + ..() + aiEye.setLoc(get_turf(target)) + +/obj/screen/movable/pic_in_pic/ai/proc/highlight() + if(highlighted) + return + highlighted = TRUE + cut_overlay(standard_background) + add_overlay(highlighted_background) + +/obj/screen/movable/pic_in_pic/ai/proc/unhighlight() + if(!highlighted) + return + highlighted = FALSE + cut_overlay(highlighted_background) + add_overlay(standard_background) + +/obj/screen/movable/pic_in_pic/ai/proc/set_ai(mob/living/silicon/ai/new_ai) + if(ai) + ai.multicam_screens -= src + ai.all_eyes -= aiEye + if(ai.master_multicam == src) + ai.master_multicam = null + if(ai.multicam_on) + unshow_to(ai.client) + ai = new_ai + if(new_ai) + new_ai.multicam_screens += src + ai.all_eyes += aiEye + if(new_ai.multicam_on) + show_to(new_ai.client) + +//Turf, area, and landmark for the viewing room + +/turf/open/ai_visible + name = "" + icon = 'icons/misc/pic_in_pic.dmi' + icon_state = "room_background" + flags_1 = NOJAUNT_1 + +/turf/open/ai_visible/Initialize() + . = ..() + obscured = image(null, src, null) + +/area/ai_multicam_room + name = "ai_multicam_room" + icon_state = "ai_camera_room" + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + valid_territory = FALSE + ambientsounds = list() + blob_allowed = FALSE + noteleport = TRUE + hidden = TRUE + safe = TRUE + +GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) + +/obj/effect/landmark/ai_multicam_room + name = "ai camera room" + icon = 'icons/mob/landmarks.dmi' + icon_state = "x" + +/obj/effect/landmark/ai_multicam_room/Initialize() + . = ..() + qdel(GLOB.ai_camera_room_landmark) + GLOB.ai_camera_room_landmark = src + +/obj/effect/landmark/ai_multicam_room/Destroy() + . = ..() + if(GLOB.ai_camera_room_landmark == src) + GLOB.ai_camera_room_landmark = null + +//Dummy camera eyes + +/mob/camera/aiEye/pic_in_pic + name = "Secondary AI Eye" + var/obj/screen/movable/pic_in_pic/ai/screen + +/mob/camera/aiEye/pic_in_pic/GetViewerClient() + if(screen && screen.ai) + return screen.ai.client + +/mob/camera/aiEye/pic_in_pic/setLoc(turf/T) + if (T) + forceMove(T) + else + moveToNullspace() + if(screen && screen.ai) + screen.ai.camera_visibility(src) + else + GLOB.cameranet.visibility(src) + +//AI procs + +/mob/living/silicon/ai/proc/drop_new_multicam(silent = FALSE) + if(!eyeobj) + return + if(multicam_screens.len >= max_multicams) + if(!silent) + to_chat(src, "Cannot place more than [max_multicams] multicamera windows.") + return + var/obj/screen/movable/pic_in_pic/ai/C = new /obj/screen/movable/pic_in_pic/ai() + C.set_view_size(3, 3, FALSE) + C.set_view_center(get_turf(eyeobj)) + C.set_ai(src) + if(!silent) + to_chat(src, "Added new multicamera window.") + return C + +/mob/living/silicon/ai/proc/toggle_multicam() + if(multicam_on) + end_multicam() + else + start_multicam() + +/mob/living/silicon/ai/proc/start_multicam() + if(multicam_on || !isturf(loc)) + return + if(!GLOB.ai_camera_room_landmark) + to_chat(src, "This function is not available at this time.") + return + multicam_on = TRUE + if(!master_multicam && eyeobj) + var/obj/screen/movable/pic_in_pic/ai/P = drop_new_multicam(TRUE) + select_main_multicam_window(P) + refresh_multicam() + to_chat(src, "Multiple-camera viewing mode activated.") + +/mob/living/silicon/ai/proc/refresh_multicam() + reset_perspective(GLOB.ai_camera_room_landmark) + if(client) + for(var/V in multicam_screens) + var/obj/screen/movable/pic_in_pic/P = V + P.show_to(client) + +/mob/living/silicon/ai/proc/end_multicam() + if(!multicam_on) + return + multicam_on = FALSE + if(client) + for(var/V in multicam_screens) + var/obj/screen/movable/pic_in_pic/P = V + P.unshow_to(client) + reset_perspective() + to_chat(src, "Multiple-camera viewing mode deactivated.") + + +/mob/living/silicon/ai/proc/select_main_multicam_window(obj/screen/movable/pic_in_pic/ai/P) + if(master_multicam == P) + return + + if(master_multicam) + master_multicam.set_view_center(get_turf(eyeobj), FALSE) + master_multicam.unhighlight() + master_multicam = null + + if(P) + P.highlight() + eyeobj.setLoc(get_turf(P.center)) + P.set_view_center(eyeobj) + master_multicam = P diff --git a/icons/misc/pic_in_pic.dmi b/icons/misc/pic_in_pic.dmi new file mode 100644 index 0000000000000000000000000000000000000000..e570907898b8a9ed333f893755afc8d575f9cc6f GIT binary patch literal 15633 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 P&In}%4fzkU7GeJbmt*7X literal 0 HcmV?d00001 diff --git a/icons/mob/screen_ai.dmi b/icons/mob/screen_ai.dmi index a449cad90645421b1dd90f63cfa4efe0bda8fd28..8388ea3f806c07006c698401c977fe138e692670 100644 GIT binary patch delta 2446 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 hicqKj_X`1wFXARuJ9c15WEHnI^ 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 diff --git a/tgstation.dme b/tgstation.dme index 0242d2c56b5845..de96cc1aad42b2 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -175,6 +175,7 @@ #include "code\_onclick\hud\monkey.dm" #include "code\_onclick\hud\movable_screen_objects.dm" #include "code\_onclick\hud\parallax.dm" +#include "code\_onclick\hud\picture_in_picture.dm" #include "code\_onclick\hud\plane_master.dm" #include "code\_onclick\hud\revenanthud.dm" #include "code\_onclick\hud\robot.dm" @@ -1905,6 +1906,7 @@ #include "code\modules\mob\living\silicon\ai\life.dm" #include "code\modules\mob\living\silicon\ai\login.dm" #include "code\modules\mob\living\silicon\ai\logout.dm" +#include "code\modules\mob\living\silicon\ai\multicam.dm" #include "code\modules\mob\living\silicon\ai\say.dm" #include "code\modules\mob\living\silicon\ai\vox_sounds.dm" #include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm" From 370f705aff918701ff75564f2e77d85c85eec3e1 Mon Sep 17 00:00:00 2001 From: Ian Turk Date: Sun, 6 May 2018 09:00:00 -0700 Subject: [PATCH 2/5] Minor multicamera fixes --- code/_onclick/hud/picture_in_picture.dm | 10 +++++----- .../mob/living/silicon/ai/freelook/eye.dm | 6 +++--- .../modules/mob/living/silicon/ai/multicam.dm | 6 +++--- icons/misc/pic_in_pic.dmi | Bin 15633 -> 3370 bytes 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm index 494adbd4547259..ce5f2c9884f89e 100644 --- a/code/_onclick/hud/picture_in_picture.dm +++ b/code/_onclick/hud/picture_in_picture.dm @@ -19,12 +19,12 @@ make_backgrounds() /obj/screen/movable/pic_in_pic/Destroy() - . = ..() for(var/C in shown_to) unshow_to(C) - qdel(button_x) - qdel(button_shrink) - qdel(button_expand) + QDEL_NULL(button_x) + QDEL_NULL(button_shrink) + QDEL_NULL(button_expand) + return ..() /obj/screen/movable/pic_in_pic/component_click(obj/screen/component_button/component, params) if(component == button_x) @@ -135,7 +135,7 @@ /obj/screen/movable/pic_in_pic/proc/show_to(client/C) if(C) - shown_to |= C + shown_to[C] = 1 C.screen += src /obj/screen/movable/pic_in_pic/proc/unshow_to(client/C) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index f14a56a38c93ab..469639d58f07b2 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -68,7 +68,7 @@ var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z)) AI.cameraFollow = null - if (isturf(src.loc) || isturf(src)) + if (isturf(loc) || isturf(src)) AI.eyeobj.setLoc(src) // This will move the AIEye. It will also cause lights near the eye to light up, if toggled. @@ -115,8 +115,8 @@ eyeobj = new /mob/camera/aiEye() all_eyes += eyeobj eyeobj.ai = src - eyeobj.setLoc(src.loc) - eyeobj.name = "[src.name] (AI Eye)" + eyeobj.setLoc(loc) + eyeobj.name = "[name] (AI Eye)" /mob/living/silicon/ai/verb/toggle_acceleration() set category = "AI Commands" diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index 8562e69de0a505..2ff925595b84f4 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -12,9 +12,9 @@ aiEye.screen = src /obj/screen/movable/pic_in_pic/ai/Destroy() - . = ..() set_ai(null) - qdel(aiEye) + QDEL_NULL(aiEye) + return ..() /obj/screen/movable/pic_in_pic/ai/Click() ..() @@ -112,9 +112,9 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) GLOB.ai_camera_room_landmark = src /obj/effect/landmark/ai_multicam_room/Destroy() - . = ..() if(GLOB.ai_camera_room_landmark == src) GLOB.ai_camera_room_landmark = null + return ..() //Dummy camera eyes diff --git a/icons/misc/pic_in_pic.dmi b/icons/misc/pic_in_pic.dmi index e570907898b8a9ed333f893755afc8d575f9cc6f..9c550f3c25ecdf6817afd63dc0843875e245dfaa 100644 GIT binary patch literal 3370 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 E2DHmSY5)KL literal 15633 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 P&In}%4fzkU7GeJbmt*7X From c67e84d2188bdaa648721c3b677a4432623e8a97 Mon Sep 17 00:00:00 2001 From: Ian Turk Date: Wed, 9 May 2018 00:16:21 -0700 Subject: [PATCH 3/5] Cameras near an AI multicamera eye now light up red --- code/game/machinery/camera/camera.dm | 3 +- .../modules/mob/living/silicon/ai/multicam.dm | 60 ++++++++++++++++-- icons/obj/machines/camera.dmi | Bin 6266 -> 8713 bytes 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index d19270f04e761e..5db07b3fad1a2e 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -36,6 +36,7 @@ var/alarm_on = FALSE var/busy = FALSE var/emped = FALSE //Number of consecutive EMP's on this camera + var/in_use_lights = 0 // Upgrades bitflag var/upgrades = 0 @@ -291,7 +292,7 @@ else if (stat & EMPED) icon_state = "[initial(icon_state)]emp" else - icon_state = "[initial(icon_state)]" + icon_state = "[initial(icon_state)][in_use_lights ? "_in_use" : ""]" /obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = 1) status = !status diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index 2ff925595b84f4..fc1bc862d3c7c5 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -38,7 +38,7 @@ add_overlay(highlighted ? highlighted_background : standard_background) /obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE) - aiEye.static_visibility_range = max(width, height) + aiEye.static_visibility_range = (round(max(width, height) / 2) + 1) if(ai) ai.camera_visibility(aiEye) ..() @@ -47,6 +47,10 @@ ..() aiEye.setLoc(get_turf(target)) +/obj/screen/movable/pic_in_pic/ai/refresh_view() + ..() + aiEye.setLoc(get_turf(center)) + /obj/screen/movable/pic_in_pic/ai/proc/highlight() if(highlighted) return @@ -121,6 +125,9 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) /mob/camera/aiEye/pic_in_pic name = "Secondary AI Eye" var/obj/screen/movable/pic_in_pic/ai/screen + var/list/cameras_telegraphed = list() + var/telegraph_cameras = TRUE + var/telegraph_range = 7 /mob/camera/aiEye/pic_in_pic/GetViewerClient() if(screen && screen.ai) @@ -135,6 +142,53 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) screen.ai.camera_visibility(src) else GLOB.cameranet.visibility(src) + update_camera_telegraphing() + +/mob/camera/aiEye/pic_in_pic/proc/update_camera_telegraphing() + if(!telegraph_cameras) + return + var/list/obj/machinery/camera/add = list() + var/list/obj/machinery/camera/remove = list() + var/list/obj/machinery/camera/visible = list() + for (var/VV in visibleCameraChunks) + var/datum/camerachunk/CC = VV + for (var/V in CC.cameras) + var/obj/machinery/camera/C = V + if (!C.can_use() || (get_dist(C, src) > telegraph_range)) + continue + visible |= C + + add = visible - cameras_telegraphed + remove = cameras_telegraphed - visible + + for (var/V in remove) + var/obj/machinery/camera/C = V + if(QDELETED(C)) + continue + cameras_telegraphed -= C + C.in_use_lights-- + C.update_icon() + for (var/V in add) + var/obj/machinery/camera/C = V + if(QDELETED(C)) + continue + cameras_telegraphed |= C + C.in_use_lights++ + C.update_icon() + +/mob/camera/aiEye/pic_in_pic/proc/disable_camera_telegraphing() + telegraph_cameras = FALSE + for (var/V in cameras_telegraphed) + var/obj/machinery/camera/C = V + if(QDELETED(C)) + continue + C.in_use_lights-- + C.update_icon() + cameras_telegraphed.Cut() + +/mob/camera/aiEye/pic_in_pic/Destroy() + disable_camera_telegraphing() + return ..() //AI procs @@ -166,9 +220,6 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) to_chat(src, "This function is not available at this time.") return multicam_on = TRUE - if(!master_multicam && eyeobj) - var/obj/screen/movable/pic_in_pic/ai/P = drop_new_multicam(TRUE) - select_main_multicam_window(P) refresh_multicam() to_chat(src, "Multiple-camera viewing mode activated.") @@ -183,6 +234,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) if(!multicam_on) return multicam_on = FALSE + select_main_multicam_window(null) if(client) for(var/V in multicam_screens) var/obj/screen/movable/pic_in_pic/P = V diff --git a/icons/obj/machines/camera.dmi b/icons/obj/machines/camera.dmi index 343a5118e812bab12c1c77d449f697a68a8687b7..1e1789d6431c11fd48a1303a2292bd7b40388bc2 100644 GIT binary patch literal 8713 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 From a9cb5a4e38c0869d880030e7502aca65be9d2522 Mon Sep 17 00:00:00 2001 From: Ian Turk Date: Wed, 9 May 2018 19:03:14 -0700 Subject: [PATCH 4/5] Disabled AI multicamera mode without admin intervention --- code/modules/mob/living/silicon/ai/ai.dm | 1 + code/modules/mob/living/silicon/ai/multicam.dm | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index b3828b877a43bc..5967b96d45907f 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -85,6 +85,7 @@ var/datum/action/innate/deploy_last_shell/redeploy_action = new var/chnotify = 0 + var/multicam_allowed = FALSE var/multicam_on = FALSE var/obj/screen/movable/pic_in_pic/ai/master_multicam var/list/multicam_screens = list() diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index fc1bc862d3c7c5..f5690645951194 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -193,6 +193,10 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) //AI procs /mob/living/silicon/ai/proc/drop_new_multicam(silent = FALSE) + if(!multicam_allowed) + if(!silent) + to_chat(src, "This action is currently disabled. Contact an administrator to enable this feature.") + return if(!eyeobj) return if(multicam_screens.len >= max_multicams) @@ -208,6 +212,9 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) return C /mob/living/silicon/ai/proc/toggle_multicam() + if(!multicam_allowed) + to_chat(src, "This action is currently disabled. Contact an administrator to enable this feature.") + return if(multicam_on) end_multicam() else From a5bf02506a7f5463786075a2dba3047d27113f06 Mon Sep 17 00:00:00 2001 From: Ian Turk Date: Fri, 25 May 2018 17:23:56 -0700 Subject: [PATCH 5/5] Fixed AIs being able to use multicamera mode when they should not --- code/modules/mob/living/silicon/ai/ai.dm | 5 +++++ code/modules/mob/living/silicon/ai/life.dm | 1 + code/modules/mob/living/silicon/ai/multicam.dm | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 5967b96d45907f..d2168628bde81d 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1004,3 +1004,8 @@ /mob/living/silicon/ai/proc/camera_visibility(mob/camera/aiEye/moved_eye) GLOB.cameranet.visibility(moved_eye, client, all_eyes) + +/mob/living/silicon/ai/forceMove(atom/destination) + . = ..() + if(.) + end_multicam() diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index a060c899d9c59b..0fd33110b6033b 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -96,6 +96,7 @@ /mob/living/silicon/ai/proc/start_RestorePowerRoutine() to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.") + end_multicam() sleep(50) var/turf/T = get_turf(src) var/area/AIarea = get_area(src) diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index f5690645951194..b6f3724fcf9e84 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -221,7 +221,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) start_multicam() /mob/living/silicon/ai/proc/start_multicam() - if(multicam_on || !isturf(loc)) + if(multicam_on || aiRestorePowerRoutine || !isturf(loc)) return if(!GLOB.ai_camera_room_landmark) to_chat(src, "This function is not available at this time.")