mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-25 04:57:12 +01:00
+1242
-680
File diff suppressed because it is too large
Load Diff
+1834
-1205
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user