Merge pull request #9081 from tigercat2000/multivis

PiP Multivis
This commit is contained in:
variableundefined
2018-10-25 09:45:02 +08:00
committed by GitHub
22 changed files with 3639 additions and 1924 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+8
View File
@@ -32,6 +32,14 @@
return
changeNext_click(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(control_disabled || stat)
return
+2
View File
@@ -146,6 +146,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"
// Bots
#define ui_bot_radio "EAST-1:28,SOUTH:7"
+29
View File
@@ -140,6 +140,25 @@
var/mob/living/silicon/robot/borg = usr
borg.sensor_mode()
/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()
/mob/living/silicon/ai/create_mob_hud()
if(client && !hud_used)
@@ -228,3 +247,13 @@
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
+144
View File
@@ -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_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)
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
overlays += 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
overlays += 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
overlays.Cut()
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] = 1
C.screen += src
/obj/screen/movable/pic_in_pic/proc/unshow_to(client/C)
if(C)
shown_to -= C
C.screen -= src
+15
View File
@@ -23,6 +23,9 @@
master = null
return ..()
/obj/screen/proc/component_click(obj/screen/component_button/component, params)
return
/obj/screen/text
icon = null
icon_state = null
@@ -461,3 +464,15 @@
icon_state = "healthdoll_DEAD"
screen_loc = ui_healthdoll
var/list/cached_healthdoll_overlays = list() // List of icon states (strings) for overlays
/obj/screen/component_button
var/obj/screen/parent
/obj/screen/component_button/Initialize(mapload, obj/screen/new_parent)
. = ..()
parent = new_parent
/obj/screen/component_button/Click(params)
if(parent)
parent.component_click(src, params)
+2 -2
View File
@@ -50,11 +50,11 @@
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
. = ..()
attempt_init(...)
attempt_init(arglist(args))
// This is distinct from /tg/ because of our space management system
// This is overriden in /atom/movable and the parent isn't called if the SMS wants to deal with it's init
/atom/proc/attempt_init(loc, ...)
/atom/proc/attempt_init(...)
var/do_initialize = SSatoms.initialized
if(do_initialize != INITIALIZATION_INSSATOMS)
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
+2
View File
@@ -30,8 +30,10 @@
var/busy = FALSE
var/emped = FALSE //Number of consecutive EMP's on this camera
var/in_use_lights = 0 // TO BE IMPLEMENTED
var/toggle_sound = 'sound/items/Wirecutter.ogg'
/obj/machinery/camera/New()
..()
wires = new(src)
@@ -138,7 +138,8 @@
return
T = get_turf(T)
loc = T
cameranet.visibility(src)
if(use_static)
cameranet.visibility(src, GetViewerClient())
if(visible_icon)
if(eye_user.client)
eye_user.client.images -= user_image
+19 -1
View File
@@ -104,6 +104,13 @@ var/list/ai_verbs_default = list(
var/arrivalmsg = "$name, $rank, has arrived on the station."
var/multicam_allowed = FALSE
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/proc/add_ai_verbs()
verbs |= ai_verbs_default
verbs |= silicon_subsystems
@@ -691,10 +698,13 @@ var/list/ai_verbs_default = list(
light_cameras()
if(istype(A, /obj/machinery/camera))
current = A
if(A != GLOB.ai_camera_room_landmark)
end_multicam()
. = ..()
if(.)
if(!A && isturf(loc) && eyeobj)
end_multicam()
client.eye = eyeobj
client.perspective = MOB_PERSPECTIVE
eyeobj.get_remote_view_fullscreens(src)
@@ -1249,6 +1259,14 @@ var/list/ai_verbs_default = list(
else
to_chat(src, "<span class='warning'>Target is not on or near any active cameras on the station.</span>")
/mob/living/silicon/ai/proc/camera_visibility(mob/camera/aiEye/moved_eye)
cameranet.visibility(moved_eye, client, all_eyes)
/mob/living/silicon/ai/forceMove(atom/destination)
. = ..()
if(.)
end_multicam()
/mob/living/silicon/ai/handle_fire()
return
@@ -1259,4 +1277,4 @@ var/list/ai_verbs_default = list(
return FALSE
/mob/living/silicon/ai/ExtinguishMob()
return
return
@@ -38,29 +38,64 @@ var/datum/cameranet/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/visibleChunks = list()
var/list/chunks_pre_seen = list()
var/list/chunks_post_seen = list()
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
visibleChunks += getCameraChunk(x, y, ai.z)
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/remove = ai.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - ai.visibleCameraChunks
var/list/visibleChunks = list()
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(ai)
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)
if(C)
chunks_post_seen |= eye.visibleCameraChunks
if(C)
for(var/V in other_eyes)
var/mob/camera/aiEye/eye = V
chunks_post_seen |= eye.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.images -= c.obscured
for(var/chunk in add)
var/datum/camerachunk/c = chunk
C.images += c.obscured
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(ai)
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
@@ -21,10 +21,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
@@ -33,10 +34,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)
@@ -14,6 +14,8 @@
var/list/visibleCameraChunks = list()
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.
@@ -25,10 +27,13 @@
return
T = get_turf(T)
loc = T
cameranet.visibility(src)
if(ai.client)
if(use_static)
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src
//Holopad
if(ai.master_multicam)
ai.master_multicam.refresh_view()
if(istype(ai.current, /obj/machinery/hologram/holopad))
var/obj/machinery/hologram/holopad/H = ai.current
H.move_hologram(ai, T)
@@ -41,18 +46,16 @@
return ai.client
return null
/mob/camera/aiEye/proc/RemoveImages()
var/client/C = GetViewerClient()
if(C)
if(C && use_static)
for(var/V in visibleCameraChunks)
var/datum/camerachunk/chunk = V
C.images -= chunk.obscured
/mob/camera/aiEye/Destroy()
if(ai)
//ai.all_eyes -= src
ai.all_eyes -= src
ai = null
for(var/V in visibleCameraChunks)
var/datum/camerachunk/chunk = V
@@ -62,9 +65,9 @@
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
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))
if(isturf(loc) || isturf(src))
AI.eyeobj.setLoc(src)
// AI MOVEMENT
@@ -124,6 +127,7 @@
if(eyeobj)
return
eyeobj = new /mob/camera/aiEye()
all_eyes += eyeobj
eyeobj.ai = src
eyeobj.setLoc(loc)
eyeobj.name = "[name] (AI Eye)"
@@ -59,6 +59,7 @@
spawn(20)
to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.")
end_multicam()
sleep(50)
my_area = get_area(src)
T = get_turf(src)
@@ -10,4 +10,6 @@
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 1
O.emotion = "Neutral"
if(multicam_on)
end_multicam()
view_core()
@@ -0,0 +1,260 @@
//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_NULL(aiEye)
return ..()
/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
overlays += highlighted ? highlighted_background : standard_background
/obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE)
aiEye.static_visibility_range = (round(max(width, height) / 2) + 1)
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/refresh_view()
..()
aiEye.setLoc(get_turf(center))
/obj/screen/movable/pic_in_pic/ai/proc/highlight()
if(highlighted)
return
highlighted = TRUE
overlays -= standard_background
overlays += highlighted_background
/obj/screen/movable/pic_in_pic/ai/proc/unhighlight()
if(!highlighted)
return
highlighted = FALSE
overlays -= highlighted_background
overlays += 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/unsimulated/ai_visible
name = ""
icon = 'icons/misc/pic_in_pic.dmi'
icon_state = "room_background"
flags = NOJAUNT
/turf/unsimulated/ai_visible/Initialize()
. = ..()
obscured = image(null, src, null)
/area/ai_multicam_room
name = "ai_multicam_room"
icon_state = "ai_camera_room"
dynamic_lighting = FALSE
valid_territory = FALSE
ambientsounds = list()
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/screen_gen.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
return ..()
//Dummy camera eyes
/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)
return screen.ai.client
/mob/camera/aiEye/pic_in_pic/setLoc(turf/T)
T = get_turf(T)
forceMove(T)
if(screen && screen.ai)
screen.ai.camera_visibility(src)
else
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
/mob/living/silicon/ai/proc/drop_new_multicam(silent = FALSE)
if(!multicam_allowed)
if(!silent)
to_chat(src, "<span class='warning'>This action is currently disabled. Contact an administrator to enable this feature.</span>")
return
if(!eyeobj)
return
if(multicam_screens.len >= max_multicams)
if(!silent)
to_chat(src, "<span class='warning'>Cannot place more than [max_multicams] multicamera windows.</span>")
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, "<span class='notice'>Added new multicamera window.</span>")
return C
/mob/living/silicon/ai/proc/toggle_multicam()
if(!multicam_allowed)
to_chat(src, "<span class='warning'>This action is currently disabled. Contact an administrator to enable this feature.</span>")
return
if(multicam_on)
end_multicam()
else
start_multicam()
/mob/living/silicon/ai/proc/start_multicam()
if(multicam_on || aiRestorePowerRoutine || !isturf(loc))
return
if(!GLOB.ai_camera_room_landmark)
to_chat(src, "<span class='warning'>This function is not available at this time.</span>")
return
multicam_on = TRUE
refresh_multicam()
to_chat(src, "<span class='notice'>Multiple-camera viewing mode activated.</span>")
/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
select_main_multicam_window(null)
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, "<span class='notice'>Multiple-camera viewing mode deactivated.</span>")
/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
@@ -64,7 +64,6 @@
actions += monkey_recycle_action
/obj/machinery/computer/camera_advanced/xenobio/attack_hand(mob/user)
if(!ishuman(user)) //AIs using it might be weird
return
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

+2
View File
@@ -135,6 +135,7 @@
#include "code\_onclick\hud\monkey.dm"
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
#include "code\_onclick\hud\picture_in_picture.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
#include "code\_onclick\hud\swarmer.dm"
@@ -1736,6 +1737,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\update_status.dm"
#include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm"