diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index a059c06284..e11cebdf51 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -129,18 +129,18 @@ detect_state = PROXIMITY_ON_SCREEN break - if(!detect_state && GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) - var/datum/camerachunk/chunk = GLOB.cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) - if(chunk) - if(chunk.seenby.len) - for(var/mob/camera/aiEye/A in chunk.seenby) - var/turf/detect_turf = get_turf(A) - if(get_dist(our_turf, detect_turf) < rangealert) - detect_state = PROXIMITY_ON_SCREEN - break - if(get_dist(our_turf, detect_turf) < rangewarning) - detect_state = PROXIMITY_NEAR - break + if(detect_state) + return + var/datum/camerachunk/chunk = GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z) + if(chunk && chunk.seenby.len) + for(var/mob/camera/aiEye/A in chunk.seenby) + var/turf/detect_turf = get_turf(A) + if(get_dist(our_turf, detect_turf) < rangealert) + detect_state = PROXIMITY_ON_SCREEN + break + if(get_dist(our_turf, detect_turf) < rangewarning) + detect_state = PROXIMITY_NEAR + break /obj/item/multitool/cyborg name = "multitool" diff --git a/code/game/turfs/simulated/floor/plating/misc_plating.dm b/code/game/turfs/simulated/floor/plating/misc_plating.dm index 6d4a949c75..3c4c8d9f85 100644 --- a/code/game/turfs/simulated/floor/plating/misc_plating.dm +++ b/code/game/turfs/simulated/floor/plating/misc_plating.dm @@ -47,8 +47,9 @@ /turf/open/floor/plating/ashplanet/Initialize() if(smooth) - pixel_y = -4 - pixel_x = -4 + var/matrix/M = new + M.Translate(-4, -4) + transform = M icon = smooth_icon . = ..() diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 8c907573d8..6123bf25e6 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -27,8 +27,9 @@ /turf/closed/mineral/Initialize() if (!canSmoothWith) canSmoothWith = list(/turf/closed/mineral, /turf/closed/indestructible) - pixel_y = -4 - pixel_x = -4 + var/matrix/M = new + M.Translate(-4, -4) + transform = M icon = smooth_icon . = ..() if (mineralType && mineralAmt && spread && spreadChance) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 9cc2d67020..987689cb9a 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -19,8 +19,6 @@ flags_1 = CAN_BE_DIRTY_1 - var/image/obscured //camerachunks - var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes var/explosion_level = 0 //for preventing explosion dodging @@ -44,6 +42,9 @@ stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 + // by default, vis_contents is inherited from the turf that was here before + vis_contents.Cut() + assemble_baseturfs() levelupdate() @@ -325,6 +326,14 @@ /turf/proc/visibilityChanged() GLOB.cameranet.updateVisibility(src) + // The cameranet usually handles this for us, but if we've just been + // recreated we should make sure we have the cameranet vis_contents. + var/datum/camerachunk/C = GLOB.cameranet.chunkGenerated(x, y, z) + if(C) + if(C.obscuredTurfs[src]) + vis_contents += GLOB.cameranet.vis_contents + else + vis_contents -= GLOB.cameranet.vis_contents /turf/proc/burn_tile() diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 5cc08ff1e0..36ae19b478 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -18,12 +18,21 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) // The object used for the clickable stat() button. var/obj/effect/statclick/statclick + // The object used in vis_contents of obscured turfs + var/vis_contents + // The image given to the effect in vis_contents on AI clients + var/image/obscured + +/datum/cameranet/New() + vis_contents = new /obj/effect/overlay/camera_static() + obscured = new('icons/effects/cameravis.dmi', vis_contents, null, BYOND_LIGHTING_LAYER + 0.1) + obscured.plane = BYOND_LIGHTING_PLANE + 1 + // Checks if a chunk has been Generated in x, y, z. /datum/cameranet/proc/chunkGenerated(x, y, z) x &= ~(CHUNK_SIZE - 1) y &= ~(CHUNK_SIZE - 1) - var/key = "[x],[y],[z]" - return (chunks[key]) + return chunks["[x],[y],[z]"] // Returns the chunk in the x, y, z. // If there is no chunk, it creates a new chunk and returns that. @@ -31,10 +40,9 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) x &= ~(CHUNK_SIZE - 1) y &= ~(CHUNK_SIZE - 1) var/key = "[x],[y],[z]" - if(!chunks[key]) - chunks[key] = new /datum/camerachunk(null, x, y, z) - - return chunks[key] + . = chunks[key] + if(!.) + chunks[key] = . = new /datum/camerachunk(x, y, z) // Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set. @@ -46,14 +54,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) 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) @@ -71,44 +73,26 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) for(var/chunk in remove) var/datum/camerachunk/c = chunk - c.remove(eye, FALSE) + c.remove(eye) for(var/chunk in add) var/datum/camerachunk/c = chunk - c.add(eye, FALSE) - - if(C) - chunks_post_seen |= eye.visibleCameraChunks + c.add(eye) 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 + C.images += obscured // Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. /datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1) - if(!SSticker || (opacity_check && !A.opacity)) return majorChunkChange(A, 2) /datum/cameranet/proc/updateChunk(x, y, z) - // 0xf = 15 - if(!chunkGenerated(x, y, z)) + var/datum/camerachunk/chunk = chunkGenerated(x, y, z) + if (!chunk) return - var/datum/camerachunk/chunk = getCameraChunk(x, y, z) chunk.hasChanged() // Removes a camera from a chunk. @@ -135,7 +119,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) // If you want to update the chunks around an object, without adding/removing a camera, use choice 2. /datum/cameranet/proc/majorChunkChange(atom/c, choice) - // 0xf = 15 if(!c) return @@ -147,8 +130,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) for(var/x = x1; x <= x2; x += CHUNK_SIZE) for(var/y = y1; y <= y2; y += CHUNK_SIZE) - if(chunkGenerated(x, y, T.z)) - var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z) + var/datum/camerachunk/chunk = chunkGenerated(x, y, T.z) + if(chunk) if(choice == 0) // Remove the camera. chunk.cameras -= c @@ -160,14 +143,12 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) // Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0. /datum/cameranet/proc/checkCameraVis(mob/living/target) - - // 0xf = 15 var/turf/position = get_turf(target) return checkTurfVis(position) /datum/cameranet/proc/checkTurfVis(turf/position) - var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z) + var/datum/camerachunk/chunk = chunkGenerated(position.x, position.y, position.z) if(chunk) if(chunk.changed) chunk.hasChanged(1) // Update now, no matter if it's visible or not. @@ -180,3 +161,17 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) stat(name, statclick.update("Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]")) + +/obj/effect/overlay/camera_static + name = "static" + icon = null + icon_state = null + anchored = TRUE // should only appear in vis_contents, but to be safe + appearance_flags = RESET_TRANSFORM | TILE_BOUND + // this combination makes the static block clicks to everything below it, + // without appearing in the right-click menu for non-AI clients + mouse_opacity = MOUSE_OPACITY_ICON + invisibility = INVISIBILITY_ABSTRACT + + layer = BYOND_LIGHTING_LAYER + 0.1 + plane = BYOND_LIGHTING_PLANE + 1 diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index e03bba3067..9a84616fbf 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -8,11 +8,9 @@ /datum/camerachunk var/list/obscuredTurfs = list() var/list/visibleTurfs = list() - var/list/obscured = list() var/list/cameras = list() var/list/turfs = list() var/list/seenby = list() - var/visible = FALSE var/changed = 0 var/x = 0 var/y = 0 @@ -20,28 +18,17 @@ // Add an AI eye to the chunk, then update if changed. -/datum/camerachunk/proc/add(mob/camera/aiEye/eye, add_images = TRUE) - if(add_images) - var/client/client = eye.GetViewerClient() - if(client) - client.images += obscured +/datum/camerachunk/proc/add(mob/camera/aiEye/eye) eye.visibleCameraChunks += src - visible++ seenby += eye if(changed) update() // Remove an AI eye from the chunk, then update if changed. -/datum/camerachunk/proc/remove(mob/camera/aiEye/eye, remove_images = TRUE) - if(remove_images) - var/client/client = eye.GetViewerClient() - if(client) - client.images -= obscured +/datum/camerachunk/proc/remove(mob/camera/aiEye/eye) eye.visibleCameraChunks -= src seenby -= eye - if(visible > 0) - visible-- // Called when a chunk has changed. I.E: A wall was deleted. @@ -54,7 +41,7 @@ // instead be flagged to update the next time an AI Eye moves near it. /datum/camerachunk/proc/hasChanged(update_now = 0) - if(visible || update_now) + if(seenby.len || update_now) addtimer(CALLBACK(src, .proc/update), UPDATE_BUFFER, TIMER_UNIQUE) else changed = 1 @@ -94,41 +81,18 @@ for(var/turf in visAdded) var/turf/t = turf - if(t.obscured) - obscured -= t.obscured - for(var/eye in seenby) - var/mob/camera/aiEye/m = eye - if(!m) - continue - var/client/client = m.GetViewerClient() - if(client) - client.images -= t.obscured + t.vis_contents -= GLOB.cameranet.vis_contents for(var/turf in visRemoved) var/turf/t = turf - if(obscuredTurfs[t]) - if(!t.obscured) - t.obscured = image('icons/effects/cameravis.dmi', t, null, BYOND_LIGHTING_LAYER+0.1) - t.obscured.pixel_x = -t.pixel_x - t.obscured.pixel_y = -t.pixel_y - t.obscured.plane = BYOND_LIGHTING_PLANE+0.1 - obscured += t.obscured - for(var/eye in seenby) - var/mob/camera/aiEye/m = eye - if(!m) - seenby -= m - continue - var/client/client = m.GetViewerClient() - if(client) - client.images += t.obscured + if(obscuredTurfs[t] && !istype(t, /turf/open/ai_visible)) + t.vis_contents += GLOB.cameranet.vis_contents changed = 0 // Create a new camera chunk, since the chunks are made as they are needed. -/datum/camerachunk/New(loc, x, y, z) - - // 0xf = 15 +/datum/camerachunk/New(x, y, z) x &= ~(CHUNK_SIZE - 1) y &= ~(CHUNK_SIZE - 1) @@ -164,12 +128,7 @@ for(var/turf in obscuredTurfs) var/turf/t = turf - if(!t.obscured) - t.obscured = image('icons/effects/cameravis.dmi', t, null, BYOND_LIGHTING_LAYER+0.1) - t.obscured.pixel_x = -t.pixel_x - t.obscured.pixel_y = -t.pixel_y - t.obscured.plane = BYOND_LIGHTING_PLANE+0.1 - obscured += t.obscured + t.vis_contents += GLOB.cameranet.vis_contents #undef UPDATE_BUFFER #undef CHUNK_SIZE diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 469639d58f..41c2902c73 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -50,9 +50,7 @@ /mob/camera/aiEye/proc/RemoveImages() var/client/C = GetViewerClient() if(C && use_static) - for(var/V in visibleCameraChunks) - var/datum/camerachunk/c = V - C.images -= c.obscured + C.images -= GLOB.cameranet.obscured /mob/camera/aiEye/Destroy() if(ai) diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index b6f3724fcf..d77e7f8a40 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -88,10 +88,6 @@ 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"