From 6ff7a6c0e868e408a11d35247e6065071255f532 Mon Sep 17 00:00:00 2001 From: Uristqwerty Date: Sat, 19 May 2012 11:07:49 -0400 Subject: [PATCH 1/3] AI Visibility cleanup First commit: - Splitting files - Starting to add comments describbing the purpose of various procs --- baystation12.dme | 7 +- .../_old_AI_Visibility.dm} | 1144 ++++++++--------- code/WorkInProgress/AI_Visibility/ai.dm | 110 ++ .../WorkInProgress/AI_Visibility/cameranet.dm | 162 +++ code/WorkInProgress/AI_Visibility/chunk.dm | 190 +++ code/WorkInProgress/AI_Visibility/minimap.dm | 110 ++ code/WorkInProgress/AI_Visibility/util.dm | 41 + 7 files changed, 1191 insertions(+), 573 deletions(-) rename code/WorkInProgress/{AI_Visibility.dm => AI_Visibility/_old_AI_Visibility.dm} (96%) create mode 100644 code/WorkInProgress/AI_Visibility/ai.dm create mode 100644 code/WorkInProgress/AI_Visibility/cameranet.dm create mode 100644 code/WorkInProgress/AI_Visibility/chunk.dm create mode 100644 code/WorkInProgress/AI_Visibility/minimap.dm create mode 100644 code/WorkInProgress/AI_Visibility/util.dm diff --git a/baystation12.dme b/baystation12.dme index e40d128308..854927d58a 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -159,6 +159,7 @@ #define FILE_DIR "code/unused/powerarmor" #define FILE_DIR "code/unused/spacecraft" #define FILE_DIR "code/WorkInProgress" +#define FILE_DIR "code/WorkInProgress/AI_Visibility" #define FILE_DIR "code/WorkInProgress/animusstation" #define FILE_DIR "code/WorkInProgress/Apples" #define FILE_DIR "code/WorkInProgress/Cael_Aislinn" @@ -1139,9 +1140,13 @@ #include "code\modules\scripting\Scanner\Tokens.dm" #include "code\modules\security levels\keycard authentication.dm" #include "code\modules\security levels\security levels.dm" -#include "code\WorkInProgress\AI_Visibility.dm" #include "code\WorkInProgress\buildmode.dm" #include "code\WorkInProgress\explosion_particles.dm" +#include "code\WorkInProgress\AI_Visibility\ai.dm" +#include "code\WorkInProgress\AI_Visibility\cameranet.dm" +#include "code\WorkInProgress\AI_Visibility\chunk.dm" +#include "code\WorkInProgress\AI_Visibility\minimap.dm" +#include "code\WorkInProgress\AI_Visibility\util.dm" #include "code\WorkInProgress\animusstation\atm.dm" #include "code\WorkInProgress\Cael_Aislinn\BirdMan\bird_transformation.dm" #include "code\WorkInProgress\Cael_Aislinn\BirdMan\birdman.dm" diff --git a/code/WorkInProgress/AI_Visibility.dm b/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm similarity index 96% rename from code/WorkInProgress/AI_Visibility.dm rename to code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm index cf3eadb2b3..fb7aab4dd0 100644 --- a/code/WorkInProgress/AI_Visibility.dm +++ b/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm @@ -1,573 +1,573 @@ -//All credit for this goes to Uristqwerty. - -//And some to me! -Mini - - - -//This file is partly designed around being able to uninclude it to go back to the old ai viewing system completely. -//(And therefore also be portable to another similar codebase simply by transferring the file and including it after the other AI code files.) -//There are probably a few parts that don't do that at the moment, but I'll fix them at some point. - - -#define MINIMAP_UPDATE_DELAY 1200 - -/turf - var/image/obscured - var/image/dim - -/turf/proc/visibilityChanged() - cameranet.updateVisibility(src) - -/turf/New() - ..() - cameranet.updateVisibility(src) -/* -/turf/Del() - ..() - cameranet.updateVisibility(src) -*/ -/datum/camerachunk - var/list/obscuredTurfs = list() - var/list/visibleTurfs = list() - var/list/dimTurfs = list() - var/list/obscured = list() - var/list/dim = list() - var/list/cameras = list() - var/list/turfs = list() - var/list/seenby = list() - var/visible = 0 - var/changed = 1 - var/updating = 0 - - var/x - var/y - var/z - - var/minimap_updating = 0 - - var/icon/minimap_icon = new('minimap.dmi', "chunk_base") - var/obj/minimap_obj/minimap_obj = new() - -/obj/minimap_obj/Click(location, control, params) - if(!istype(usr, /mob/dead) && !istype(usr, /mob/living/silicon/ai) && !(usr.client && usr.client.holder && usr.client.holder.level >= 4)) - return - - var/list/par = params2list(params) - var/screen_loc = par["screen-loc"] - - if(findtext(screen_loc, "minimap:") != 1) - return - - screen_loc = copytext(screen_loc, length("minimap:") + 1) - - var/x_text = copytext(screen_loc, 1, findtext(screen_loc, ",")) - var/y_text = copytext(screen_loc, findtext(screen_loc, ",") + 1) - - var/x = (text2num(copytext(x_text, 1, findtext(x_text, ":"))) - 1) * 16 - x += round((text2num(copytext(x_text, findtext(x_text, ":") + 1)) + 1) / 2) - - var/y = (text2num(copytext(y_text, 1, findtext(y_text, ":"))) - 1) * 16 - y += round((text2num(copytext(y_text, findtext(y_text, ":") + 1)) + 1) / 2) - - if(istype(usr, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/ai = usr - ai.freelook() - ai.eyeobj.loc = locate(max(1, x - 1), max(1, y - 1), ai.eyeobj.z) - cameranet.visibility(ai.eyeobj) - - else - usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.z) - -/mob/dead/verb/Open_Minimap() - set category = "Ghost" - winshow(src, "minimapwindow", 1) - client.screen |= cameranet.minimap - - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src - -/mob/living/silicon/ai/verb/Open_Minimap() - set category = "AI Commands" - winshow(src, "minimapwindow", 1) - client.screen |= cameranet.minimap - - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src - -/client/proc/Open_Minimap() - set category = "Admin" - winshow(src, "minimapwindow", 1) - screen |= cameranet.minimap - - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src.mob - -/datum/camerachunk/proc/update_minimap() - if(changed && !updating) - update() - - minimap_icon.Blend(rgb(255, 0, 0), ICON_MULTIPLY) - - var/list/turfs = visibleTurfs | dimTurfs - - for(var/turf/turf in turfs) - var/x = (turf.x & 0xf) * 2 - var/y = (turf.y & 0xf) * 2 - - if(turf.density) - minimap_icon.DrawBox(rgb(100, 100, 100), x + 1, y + 1, x + 2, y + 2) - continue - - else if(istype(turf, /turf/space)) - minimap_icon.DrawBox(rgb(0, 0, 0), x + 1, y + 1, x + 2, y + 2) - - else - minimap_icon.DrawBox(rgb(200, 200, 200), x + 1, y + 1, x + 2, y + 2) - - for(var/obj/structure/o in turf) - if(o.density) - if(istype(o, /obj/structure/window) && (o.dir == NORTH || o.dir == SOUTH || o.dir == EAST || o.dir == WEST)) - if(o.dir == NORTH) - minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 2, x + 2, y + 2) - else if(o.dir == SOUTH) - minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 1, x + 2, y + 1) - else if(o.dir == EAST) - minimap_icon.DrawBox(rgb(150, 150, 200), x + 3, y + 1, x + 2, y + 2) - else if(o.dir == WEST) - minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 1, x + 1, y + 2) - - else - minimap_icon.DrawBox(rgb(150, 150, 150), x + 1, y + 1, x + 2, y + 2) - break - - for(var/obj/machinery/door/o in turf) - if(istype(o, /obj/machinery/door/window)) - if(o.dir == NORTH) - minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 2, x + 2, y + 2) - else if(o.dir == SOUTH) - minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 2, y + 1) - else if(o.dir == EAST) - minimap_icon.DrawBox(rgb(100, 150, 100), x + 2, y + 1, x + 2, y + 2) - else if(o.dir == WEST) - minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 1, y + 2) - - else - minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 2, y + 2) - break - - minimap_obj.screen_loc = "minimap:[src.x / 16],[src.y / 16]" - minimap_obj.icon = minimap_icon - -/mob/aiEye - var/list/visibleCameraChunks = list() - var/mob/ai = null - density = 0 - -/datum/camerachunk/proc/add(mob/aiEye/ai) - ai.visibleCameraChunks += src - if(ai.ai.client) - ai.ai.client.images += obscured - ai.ai.client.images += dim - visible++ - seenby += ai - if(changed && !updating) - update() - changed = 0 - -/datum/camerachunk/proc/remove(mob/aiEye/ai) - ai.visibleCameraChunks -= src - if(ai.ai.client) - ai.ai.client.images -= obscured - ai.ai.client.images -= dim - seenby -= ai - if(visible > 0) - visible-- - -/datum/camerachunk/proc/visibilityChanged(turf/loc) - if(!(loc in visibleTurfs)) - return - - hasChanged() - -/datum/camerachunk/proc/hasChanged() - if(visible) - if(!updating) - updating = 1 - spawn(10)//Batch large changes, such as many doors opening or closing at once - update() - updating = 0 - else - changed = 1 - - if(!minimap_updating) - minimap_updating = 1 - - spawn(MINIMAP_UPDATE_DELAY) - if(changed && !updating) - update() - changed = 0 - - update_minimap() - minimap_updating = 0 - -/datum/camerachunk/proc/update() - - var/list/newDimTurfs = list() - var/list/newVisibleTurfs = list() - - for(var/obj/machinery/camera/c in cameras) - var/lum = c.luminosity - c.luminosity = 7 - - newDimTurfs |= turfs & view(7, c) - newVisibleTurfs |= turfs & view(6, c) - - c.luminosity = lum - - var/list/dimAdded = newDimTurfs - dimTurfs - var/list/dimRemoved = dimTurfs - newDimTurfs - var/list/visAdded = newVisibleTurfs - visibleTurfs - var/list/visRemoved = visibleTurfs - newVisibleTurfs - - visibleTurfs = newVisibleTurfs - dimTurfs = newDimTurfs - obscuredTurfs = turfs - dimTurfs - dimTurfs -= visibleTurfs - - for(var/turf/t in dimRemoved) - if(t.dim) - dim -= t.dim - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images -= t.dim - - if(!(t in visibleTurfs)) - if(!t.obscured) - t.obscured = image('cameravis.dmi', t, "black", 15) - - obscured += t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images += t.obscured - - for(var/turf/t in dimAdded) - if(!(t in visibleTurfs)) - if(!t.dim) - t.dim = image('cameravis.dmi', t, "dim", 15) - t.mouse_opacity = 0 - - dim += t.dim - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images += t.dim - - if(t.obscured) - obscured -= t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images -= t.obscured - - for(var/turf/t in visAdded) - if(t.obscured) - obscured -= t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images -= t.obscured - - for(var/turf/t in visRemoved) - if(t in obscuredTurfs) - if(!t.obscured) - t.obscured = image('cameravis.dmi', t, "black", 15) - - obscured += t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images += t.obscured - - -/datum/camerachunk/New(loc, x, y, z) - x &= ~0xf - y &= ~0xf - - src.x = x - src.y = y - src.z = z - - for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) - if(c.status) - cameras += c - - turfs = block(locate(x, y, z), locate(min(world.maxx, x + 15), min(world.maxy, y + 15), z)) - - for(var/obj/machinery/camera/c in cameras) - var/lum = c.luminosity - c.luminosity = 7 - - dimTurfs |= turfs & view(7, c) - visibleTurfs |= turfs & view(6, c) - - c.luminosity = lum - - obscuredTurfs = turfs - dimTurfs - dimTurfs -= visibleTurfs - - for(var/turf/t in obscuredTurfs) - if(!t.obscured) - t.obscured = image('cameravis.dmi', t, "black", 15) - - obscured += t.obscured - - for(var/turf/t in dimTurfs) - if(!(t in visibleTurfs)) - if(!t.dim) - t.dim = image('cameravis.dmi', t, "dim", TURF_LAYER) - t.dim.mouse_opacity = 0 - - dim += t.dim - - cameranet.minimap += minimap_obj - -var/datum/cameranet/cameranet = new() - -/datum/cameranet - var/list/cameras = list() - var/list/chunks = list() - var/network = "net1" - var/ready = 0 - - var/list/minimap = list() - - var/generating_minimap = TRUE - var/list/minimap_viewers = list() - -/datum/cameranet/New() - ..() - - spawn(200) - for(var/x = 0, x <= world.maxx, x += 16) - for(var/y = 0, y <= world.maxy, y += 16) - sleep(1) - var/datum/camerachunk/c = getCameraChunk(x, y, 1) - c.update_minimap() - - for(var/mob/m in minimap_viewers) - m.client.screen |= c.minimap_obj - - generating_minimap = FALSE - minimap_viewers = list() - -/datum/cameranet/proc/chunkGenerated(x, y, z) - var/key = "[x],[y],[z]" - return key in chunks - -/datum/cameranet/proc/getCameraChunk(x, y, z) - var/key = "[x],[y],[z]" - - if(!(key in chunks)) - chunks[key] = new /datum/camerachunk(null, x, y, z) - - return chunks[key] - -/datum/cameranet/proc/visibility(mob/aiEye/ai) - var/x1 = max(0, ai.x - 16) & ~0xf - var/y1 = max(0, ai.y - 16) & ~0xf - var/x2 = min(world.maxx, ai.x + 16) & ~0xf - var/y2 = min(world.maxy, ai.y + 16) & ~0xf - - var/list/visibleChunks = list() - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - visibleChunks += getCameraChunk(x, y, ai.z) - - var/list/remove = ai.visibleCameraChunks - visibleChunks - var/list/add = visibleChunks - ai.visibleCameraChunks - - for(var/datum/camerachunk/c in remove) - c.remove(ai) - - for(var/datum/camerachunk/c in add) - c.add(ai) - -/datum/cameranet/proc/updateVisibility(turf/loc) - if(!chunkGenerated(loc.x & ~0xf, loc.y & ~0xf, loc.z)) - return - - var/datum/camerachunk/chunk = getCameraChunk(loc.x & ~0xf, loc.y & ~0xf, loc.z) - chunk.visibilityChanged(loc) - -/datum/cameranet/proc/addCamera(obj/machinery/camera/c) - var/x1 = max(0, c.x - 16) & ~0xf - var/y1 = max(0, c.y - 16) & ~0xf - var/x2 = min(world.maxx, c.x + 16) & ~0xf - var/y2 = min(world.maxy, c.y + 16) & ~0xf - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - if(chunkGenerated(x, y, c.z)) - var/datum/camerachunk/chunk = getCameraChunk(x, y, c.z) - if(!(c in chunk.cameras)) - chunk.cameras += c - chunk.hasChanged() - -/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) - var/x1 = max(0, c.x - 16) & ~0xf - var/y1 = max(0, c.y - 16) & ~0xf - var/x2 = min(world.maxx, c.x + 16) & ~0xf - var/y2 = min(world.maxy, c.y + 16) & ~0xf - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - if(chunkGenerated(x, y, c.z)) - var/datum/camerachunk/chunk = getCameraChunk(x, y, c.z) - if(!c) - chunk.hasChanged() - if(c in chunk.cameras) - chunk.cameras -= c - chunk.hasChanged() - -/mob/living/silicon/ai/var/mob/aiEye/eyeobj = new() - -/mob/living/silicon/ai/New() - ..() - eyeobj.ai = src - spawn(20) - freelook() - -/mob/living/silicon/ai/death(gibbed) - if(client && client.eye == eyeobj) - for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) - c.remove(eyeobj) - client.eye = src - return ..(gibbed) - -/mob/living/silicon/ai/verb/freelook() - set category = "AI Commands" - set name = "freelook" - current = null //cancel camera view first, it causes problems - cameraFollow = null -// machine = null - if(!eyeobj) //if it got deleted somehow (like an admin trying to fix things <.<') - eyeobj = new() - eyeobj.ai = src - client.eye = eyeobj - eyeobj.loc = loc - cameranet.visibility(eyeobj) - cameraFollow = null - -/mob/aiEye/Move() - . = ..() - if(.) - cameranet.visibility(src) - -/client/AIMove(n, direct, var/mob/living/silicon/ai/user) - if(eye == user.eyeobj) - user.eyeobj.loc = get_step(user.eyeobj, direct) - cameranet.visibility(user.eyeobj) - - else - return ..() - -/* -/client/AIMoveZ(direct, var/mob/living/silicon/ai/user) - if(eye == user.eyeobj) - var/dif = 0 - if(direct == UP && user.eyeobj.z > 1) - dif = -1 - else if(direct == DOWN && user.eyeobj.z < 4) - dif = 1 - user.eyeobj.loc = locate(user.eyeobj.x, user.eyeobj.y, user.eyeobj.z + dif) - cameranet.visibility(user.eyeobj) - else - return ..() -*/ - -/turf/move_camera_by_click() - if(istype(usr, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = usr - if(AI.client.eye == AI.eyeobj) - return - return ..() - - -/obj/machinery/door/update_nearby_tiles(need_rebuild) - . = ..(need_rebuild) - cameranet.updateVisibility(loc) - -/obj/machinery/camera/New() - ..() - cameranet.addCamera(src) - -/obj/machinery/camera/Del() - cameranet.removeCamera(src) - ..() - -/obj/machinery/camera/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - . = ..(W, user) - if(istype(W, /obj/item/weapon/wirecutters)) - if(status) - cameranet.addCamera(src) - else - cameranet.removeCamera(src) - -/proc/checkcameravis(atom/A) - for(var/obj/machinery/camera/C in view(A,7)) - if(!C.status || C.stat == 2) - continue - return 1 - return 0 - -/mob/living/silicon/ai/attack_ai(var/mob/user as mob) - if (user != src) - return - - if (stat == 2) - return - - var/list/L = list() - for (var/obj/machinery/camera/C in world) - L.Add(C) - - camera_sort(L) - L = camera_network_sort(L) - - var/list/D = list() - for (var/obj/machinery/camera/C in L) - if ( C.network in src.networks ) - D[text("[]: [][]", C.network, C.c_tag, (C.status ? null : " (Deactivated)"))] = C - D["Cancel"] = "Cancel" - - var/t = input(user, "Which camera should you change to?") as null|anything in D - - if (!t || t == "Cancel") - return 0 - - var/obj/machinery/camera/C = D[t] - - eyeobj.loc = C.loc - cameranet.visibility(eyeobj) - - return - -/mob/living/silicon/ai/cancel_camera() - set name = "Cancel Camera View" - set category = "OOC" - reset_view(null) - machine = null - -/mob/living/silicon/ai/reset_view(atom/A) - if (client) - if(!eyeobj) - eyeobj = new() - eyeobj.ai = src - - client.eye = eyeobj - client.perspective = EYE_PERSPECTIVE - - if (istype(A, /atom/movable)) - eyeobj.loc = locate(A.x, A.y, A.z) - - else - eyeobj.loc = locate(src.x, src.y, src.z) - +//All credit for this goes to Uristqwerty. + +//And some to me! -Mini + + + +//This file is partly designed around being able to uninclude it to go back to the old ai viewing system completely. +//(And therefore also be portable to another similar codebase simply by transferring the file and including it after the other AI code files.) +//There are probably a few parts that don't do that at the moment, but I'll fix them at some point. + + +#define MINIMAP_UPDATE_DELAY 1200 + +/turf + var/image/obscured + var/image/dim + +/turf/proc/visibilityChanged() + cameranet.updateVisibility(src) + +/turf/New() + ..() + cameranet.updateVisibility(src) +/* +/turf/Del() + ..() + cameranet.updateVisibility(src) +*/ +/datum/camerachunk + var/list/obscuredTurfs = list() + var/list/visibleTurfs = list() + var/list/dimTurfs = list() + var/list/obscured = list() + var/list/dim = list() + var/list/cameras = list() + var/list/turfs = list() + var/list/seenby = list() + var/visible = 0 + var/changed = 1 + var/updating = 0 + + var/x + var/y + var/z + + var/minimap_updating = 0 + + var/icon/minimap_icon = new('minimap.dmi', "chunk_base") + var/obj/minimap_obj/minimap_obj = new() + +/obj/minimap_obj/Click(location, control, params) + if(!istype(usr, /mob/dead) && !istype(usr, /mob/living/silicon/ai) && !(usr.client && usr.client.holder && usr.client.holder.level >= 4)) + return + + var/list/par = params2list(params) + var/screen_loc = par["screen-loc"] + + if(findtext(screen_loc, "minimap:") != 1) + return + + screen_loc = copytext(screen_loc, length("minimap:") + 1) + + var/x_text = copytext(screen_loc, 1, findtext(screen_loc, ",")) + var/y_text = copytext(screen_loc, findtext(screen_loc, ",") + 1) + + var/x = (text2num(copytext(x_text, 1, findtext(x_text, ":"))) - 1) * 16 + x += round((text2num(copytext(x_text, findtext(x_text, ":") + 1)) + 1) / 2) + + var/y = (text2num(copytext(y_text, 1, findtext(y_text, ":"))) - 1) * 16 + y += round((text2num(copytext(y_text, findtext(y_text, ":") + 1)) + 1) / 2) + + if(istype(usr, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/ai = usr + ai.freelook() + ai.eyeobj.loc = locate(max(1, x - 1), max(1, y - 1), ai.eyeobj.z) + cameranet.visibility(ai.eyeobj) + + else + usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.z) + +/mob/dead/verb/Open_Minimap() + set category = "Ghost" + winshow(src, "minimapwindow", 1) + client.screen |= cameranet.minimap + + if(cameranet.generating_minimap) + cameranet.minimap_viewers += src + +/mob/living/silicon/ai/verb/Open_Minimap() + set category = "AI Commands" + winshow(src, "minimapwindow", 1) + client.screen |= cameranet.minimap + + if(cameranet.generating_minimap) + cameranet.minimap_viewers += src + +/client/proc/Open_Minimap() + set category = "Admin" + winshow(src, "minimapwindow", 1) + screen |= cameranet.minimap + + if(cameranet.generating_minimap) + cameranet.minimap_viewers += src.mob + +/datum/camerachunk/proc/update_minimap() + if(changed && !updating) + update() + + minimap_icon.Blend(rgb(255, 0, 0), ICON_MULTIPLY) + + var/list/turfs = visibleTurfs | dimTurfs + + for(var/turf/turf in turfs) + var/x = (turf.x & 0xf) * 2 + var/y = (turf.y & 0xf) * 2 + + if(turf.density) + minimap_icon.DrawBox(rgb(100, 100, 100), x + 1, y + 1, x + 2, y + 2) + continue + + else if(istype(turf, /turf/space)) + minimap_icon.DrawBox(rgb(0, 0, 0), x + 1, y + 1, x + 2, y + 2) + + else + minimap_icon.DrawBox(rgb(200, 200, 200), x + 1, y + 1, x + 2, y + 2) + + for(var/obj/structure/o in turf) + if(o.density) + if(istype(o, /obj/structure/window) && (o.dir == NORTH || o.dir == SOUTH || o.dir == EAST || o.dir == WEST)) + if(o.dir == NORTH) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 2, x + 2, y + 2) + else if(o.dir == SOUTH) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 1, x + 2, y + 1) + else if(o.dir == EAST) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 3, y + 1, x + 2, y + 2) + else if(o.dir == WEST) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 1, x + 1, y + 2) + + else + minimap_icon.DrawBox(rgb(150, 150, 150), x + 1, y + 1, x + 2, y + 2) + break + + for(var/obj/machinery/door/o in turf) + if(istype(o, /obj/machinery/door/window)) + if(o.dir == NORTH) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 2, x + 2, y + 2) + else if(o.dir == SOUTH) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 2, y + 1) + else if(o.dir == EAST) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 2, y + 1, x + 2, y + 2) + else if(o.dir == WEST) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 1, y + 2) + + else + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 2, y + 2) + break + + minimap_obj.screen_loc = "minimap:[src.x / 16],[src.y / 16]" + minimap_obj.icon = minimap_icon + +/mob/aiEye + var/list/visibleCameraChunks = list() + var/mob/ai = null + density = 0 + +/datum/camerachunk/proc/add(mob/aiEye/ai) + ai.visibleCameraChunks += src + if(ai.ai.client) + ai.ai.client.images += obscured + ai.ai.client.images += dim + visible++ + seenby += ai + if(changed && !updating) + update() + changed = 0 + +/datum/camerachunk/proc/remove(mob/aiEye/ai) + ai.visibleCameraChunks -= src + if(ai.ai.client) + ai.ai.client.images -= obscured + ai.ai.client.images -= dim + seenby -= ai + if(visible > 0) + visible-- + +/datum/camerachunk/proc/visibilityChanged(turf/loc) + if(!(loc in visibleTurfs)) + return + + hasChanged() + +/datum/camerachunk/proc/hasChanged() + if(visible) + if(!updating) + updating = 1 + spawn(10)//Batch large changes, such as many doors opening or closing at once + update() + updating = 0 + else + changed = 1 + + if(!minimap_updating) + minimap_updating = 1 + + spawn(MINIMAP_UPDATE_DELAY) + if(changed && !updating) + update() + changed = 0 + + update_minimap() + minimap_updating = 0 + +/datum/camerachunk/proc/update() + + var/list/newDimTurfs = list() + var/list/newVisibleTurfs = list() + + for(var/obj/machinery/camera/c in cameras) + var/lum = c.luminosity + c.luminosity = 7 + + newDimTurfs |= turfs & view(7, c) + newVisibleTurfs |= turfs & view(6, c) + + c.luminosity = lum + + var/list/dimAdded = newDimTurfs - dimTurfs + var/list/dimRemoved = dimTurfs - newDimTurfs + var/list/visAdded = newVisibleTurfs - visibleTurfs + var/list/visRemoved = visibleTurfs - newVisibleTurfs + + visibleTurfs = newVisibleTurfs + dimTurfs = newDimTurfs + obscuredTurfs = turfs - dimTurfs + dimTurfs -= visibleTurfs + + for(var/turf/t in dimRemoved) + if(t.dim) + dim -= t.dim + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images -= t.dim + + if(!(t in visibleTurfs)) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images += t.obscured + + for(var/turf/t in dimAdded) + if(!(t in visibleTurfs)) + if(!t.dim) + t.dim = image('cameravis.dmi', t, "dim", 15) + t.mouse_opacity = 0 + + dim += t.dim + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images += t.dim + + if(t.obscured) + obscured -= t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images -= t.obscured + + for(var/turf/t in visAdded) + if(t.obscured) + obscured -= t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images -= t.obscured + + for(var/turf/t in visRemoved) + if(t in obscuredTurfs) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images += t.obscured + + +/datum/camerachunk/New(loc, x, y, z) + x &= ~0xf + y &= ~0xf + + src.x = x + src.y = y + src.z = z + + for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) + if(c.status) + cameras += c + + turfs = block(locate(x, y, z), locate(min(world.maxx, x + 15), min(world.maxy, y + 15), z)) + + for(var/obj/machinery/camera/c in cameras) + var/lum = c.luminosity + c.luminosity = 7 + + dimTurfs |= turfs & view(7, c) + visibleTurfs |= turfs & view(6, c) + + c.luminosity = lum + + obscuredTurfs = turfs - dimTurfs + dimTurfs -= visibleTurfs + + for(var/turf/t in obscuredTurfs) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + + for(var/turf/t in dimTurfs) + if(!(t in visibleTurfs)) + if(!t.dim) + t.dim = image('cameravis.dmi', t, "dim", TURF_LAYER) + t.dim.mouse_opacity = 0 + + dim += t.dim + + cameranet.minimap += minimap_obj + +var/datum/cameranet/cameranet = new() + +/datum/cameranet + var/list/cameras = list() + var/list/chunks = list() + var/network = "net1" + var/ready = 0 + + var/list/minimap = list() + + var/generating_minimap = TRUE + var/list/minimap_viewers = list() + +/datum/cameranet/New() + ..() + + spawn(200) + for(var/x = 0, x <= world.maxx, x += 16) + for(var/y = 0, y <= world.maxy, y += 16) + sleep(1) + var/datum/camerachunk/c = getCameraChunk(x, y, 1) + c.update_minimap() + + for(var/mob/m in minimap_viewers) + m.client.screen |= c.minimap_obj + + generating_minimap = FALSE + minimap_viewers = list() + +/datum/cameranet/proc/chunkGenerated(x, y, z) + var/key = "[x],[y],[z]" + return key in chunks + +/datum/cameranet/proc/getCameraChunk(x, y, z) + var/key = "[x],[y],[z]" + + if(!(key in chunks)) + chunks[key] = new /datum/camerachunk(null, x, y, z) + + return chunks[key] + +/datum/cameranet/proc/visibility(mob/aiEye/ai) + var/x1 = max(0, ai.x - 16) & ~0xf + var/y1 = max(0, ai.y - 16) & ~0xf + var/x2 = min(world.maxx, ai.x + 16) & ~0xf + var/y2 = min(world.maxy, ai.y + 16) & ~0xf + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + visibleChunks += getCameraChunk(x, y, ai.z) + + var/list/remove = ai.visibleCameraChunks - visibleChunks + var/list/add = visibleChunks - ai.visibleCameraChunks + + for(var/datum/camerachunk/c in remove) + c.remove(ai) + + for(var/datum/camerachunk/c in add) + c.add(ai) + +/datum/cameranet/proc/updateVisibility(turf/loc) + if(!chunkGenerated(loc.x & ~0xf, loc.y & ~0xf, loc.z)) + return + + var/datum/camerachunk/chunk = getCameraChunk(loc.x & ~0xf, loc.y & ~0xf, loc.z) + chunk.visibilityChanged(loc) + +/datum/cameranet/proc/addCamera(obj/machinery/camera/c) + var/x1 = max(0, c.x - 16) & ~0xf + var/y1 = max(0, c.y - 16) & ~0xf + var/x2 = min(world.maxx, c.x + 16) & ~0xf + var/y2 = min(world.maxy, c.y + 16) & ~0xf + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + if(chunkGenerated(x, y, c.z)) + var/datum/camerachunk/chunk = getCameraChunk(x, y, c.z) + if(!(c in chunk.cameras)) + chunk.cameras += c + chunk.hasChanged() + +/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) + var/x1 = max(0, c.x - 16) & ~0xf + var/y1 = max(0, c.y - 16) & ~0xf + var/x2 = min(world.maxx, c.x + 16) & ~0xf + var/y2 = min(world.maxy, c.y + 16) & ~0xf + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + if(chunkGenerated(x, y, c.z)) + var/datum/camerachunk/chunk = getCameraChunk(x, y, c.z) + if(!c) + chunk.hasChanged() + if(c in chunk.cameras) + chunk.cameras -= c + chunk.hasChanged() + +/mob/living/silicon/ai/var/mob/aiEye/eyeobj = new() + +/mob/living/silicon/ai/New() + ..() + eyeobj.ai = src + spawn(20) + freelook() + +/mob/living/silicon/ai/death(gibbed) + if(client && client.eye == eyeobj) + for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) + c.remove(eyeobj) + client.eye = src + return ..(gibbed) + +/mob/living/silicon/ai/verb/freelook() + set category = "AI Commands" + set name = "freelook" + current = null //cancel camera view first, it causes problems + cameraFollow = null +// machine = null + if(!eyeobj) //if it got deleted somehow (like an admin trying to fix things <.<') + eyeobj = new() + eyeobj.ai = src + client.eye = eyeobj + eyeobj.loc = loc + cameranet.visibility(eyeobj) + cameraFollow = null + +/mob/aiEye/Move() + . = ..() + if(.) + cameranet.visibility(src) + +/client/AIMove(n, direct, var/mob/living/silicon/ai/user) + if(eye == user.eyeobj) + user.eyeobj.loc = get_step(user.eyeobj, direct) + cameranet.visibility(user.eyeobj) + + else + return ..() + +/* +/client/AIMoveZ(direct, var/mob/living/silicon/ai/user) + if(eye == user.eyeobj) + var/dif = 0 + if(direct == UP && user.eyeobj.z > 1) + dif = -1 + else if(direct == DOWN && user.eyeobj.z < 4) + dif = 1 + user.eyeobj.loc = locate(user.eyeobj.x, user.eyeobj.y, user.eyeobj.z + dif) + cameranet.visibility(user.eyeobj) + else + return ..() +*/ + +/turf/move_camera_by_click() + if(istype(usr, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = usr + if(AI.client.eye == AI.eyeobj) + return + return ..() + + +/obj/machinery/door/update_nearby_tiles(need_rebuild) + . = ..(need_rebuild) + cameranet.updateVisibility(loc) + +/obj/machinery/camera/New() + ..() + cameranet.addCamera(src) + +/obj/machinery/camera/Del() + cameranet.removeCamera(src) + ..() + +/obj/machinery/camera/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + . = ..(W, user) + if(istype(W, /obj/item/weapon/wirecutters)) + if(status) + cameranet.addCamera(src) + else + cameranet.removeCamera(src) + +/proc/checkcameravis(atom/A) + for(var/obj/machinery/camera/C in view(A,7)) + if(!C.status || C.stat == 2) + continue + return 1 + return 0 + +/mob/living/silicon/ai/attack_ai(var/mob/user as mob) + if (user != src) + return + + if (stat == 2) + return + + var/list/L = list() + for (var/obj/machinery/camera/C in world) + L.Add(C) + + camera_sort(L) + L = camera_network_sort(L) + + var/list/D = list() + for (var/obj/machinery/camera/C in L) + if ( C.network in src.networks ) + D[text("[]: [][]", C.network, C.c_tag, (C.status ? null : " (Deactivated)"))] = C + D["Cancel"] = "Cancel" + + var/t = input(user, "Which camera should you change to?") as null|anything in D + + if (!t || t == "Cancel") + return 0 + + var/obj/machinery/camera/C = D[t] + + eyeobj.loc = C.loc + cameranet.visibility(eyeobj) + + return + +/mob/living/silicon/ai/cancel_camera() + set name = "Cancel Camera View" + set category = "OOC" + reset_view(null) + machine = null + +/mob/living/silicon/ai/reset_view(atom/A) + if (client) + if(!eyeobj) + eyeobj = new() + eyeobj.ai = src + + client.eye = eyeobj + client.perspective = EYE_PERSPECTIVE + + if (istype(A, /atom/movable)) + eyeobj.loc = locate(A.x, A.y, A.z) + + else + eyeobj.loc = locate(src.x, src.y, src.z) + cameranet.visibility(eyeobj) diff --git a/code/WorkInProgress/AI_Visibility/ai.dm b/code/WorkInProgress/AI_Visibility/ai.dm new file mode 100644 index 0000000000..ae797da52d --- /dev/null +++ b/code/WorkInProgress/AI_Visibility/ai.dm @@ -0,0 +1,110 @@ + + +/mob/aiEye + var/list/visibleCameraChunks = list() + var/mob/ai = null + density = 0 + +/mob/living/silicon/ai/var/mob/aiEye/eyeobj = new() + +/mob/living/silicon/ai/New() + ..() + eyeobj.ai = src + spawn(20) + freelook() + +/mob/living/silicon/ai/death(gibbed) + if(client && client.eye == eyeobj) + for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) + c.remove(eyeobj) + client.eye = src + return ..(gibbed) + +/mob/living/silicon/ai/verb/freelook() + set category = "AI Commands" + set name = "freelook" + current = null //cancel camera view first, it causes problems + cameraFollow = null +// machine = null + if(!eyeobj) //if it got deleted somehow (like an admin trying to fix things <.<') + eyeobj = new() + eyeobj.ai = src + client.eye = eyeobj + eyeobj.loc = loc + cameranet.visibility(eyeobj) + cameraFollow = null + +/mob/aiEye/Move() + . = ..() + if(.) + cameranet.visibility(src) + +/client/AIMove(n, direct, var/mob/living/silicon/ai/user) + if(eye == user.eyeobj) + user.eyeobj.loc = get_step(user.eyeobj, direct) + cameranet.visibility(user.eyeobj) + + else + return ..() + +/turf/move_camera_by_click() + if(istype(usr, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = usr + if(AI.client.eye == AI.eyeobj) + return + return ..() + +/mob/living/silicon/ai/attack_ai(var/mob/user as mob) + if (user != src) + return + + if (stat == 2) + return + + var/list/L = list() + for (var/obj/machinery/camera/C in world) + L.Add(C) + + camera_sort(L) + L = camera_network_sort(L) + + var/list/D = list() + for (var/obj/machinery/camera/C in L) + if ( C.network in src.networks ) + D[text("[]: [][]", C.network, C.c_tag, (C.status ? null : " (Deactivated)"))] = C + D["Cancel"] = "Cancel" + + var/t = input(user, "Which camera should you change to?") as null|anything in D + + if (!t || t == "Cancel") + return 0 + + var/obj/machinery/camera/C = D[t] + + eyeobj.loc = C.loc + cameranet.visibility(eyeobj) + + return + +/mob/living/silicon/ai/cancel_camera() + set name = "Cancel Camera View" + set category = "OOC" + reset_view(null) + machine = null + +/mob/living/silicon/ai/reset_view(atom/A) + if (client) + if(!eyeobj) + eyeobj = new() + eyeobj.ai = src + + client.eye = eyeobj + client.perspective = EYE_PERSPECTIVE + + if (istype(A, /atom/movable)) + eyeobj.loc = locate(A.x, A.y, A.z) + + else + eyeobj.loc = locate(src.x, src.y, src.z) + + cameranet.visibility(eyeobj) diff --git a/code/WorkInProgress/AI_Visibility/cameranet.dm b/code/WorkInProgress/AI_Visibility/cameranet.dm new file mode 100644 index 0000000000..d5b001419f --- /dev/null +++ b/code/WorkInProgress/AI_Visibility/cameranet.dm @@ -0,0 +1,162 @@ + +//------------------------------------------------------------ +// +// The Cameranet +// +// The cameranet is a single global instance of a unique +// datum, which contains logic for managing the individual +// chunks. +// +//------------------------------------------------------------ + +/datum/cameranet + var/list/cameras = list() + var/list/chunks = list() + var/network = "net1" + var/ready = 0 + + var/list/minimap = list() + + var/generating_minimap = TRUE + var/list/minimap_viewers = list() + +var/datum/cameranet/cameranet = new() + + + +/datum/cameranet/New() + ..() + + spawn(100) + init_minimap() + + +/datum/cameranet/proc/init_minimap() + for(var/x = 0, x <= world.maxx, x += 16) + for(var/y = 0, y <= world.maxy, y += 16) + sleep(1) + var/datum/camerachunk/c = getCameraChunk(x, y, 1) + c.update_minimap() + + for(var/mob/m in minimap_viewers) + m.client.screen |= c.minimap_obj + + generating_minimap = FALSE + minimap_viewers = list() + + +/datum/cameranet/proc/chunkGenerated(x, y, z) + var/key = "[x],[y],[z]" + return key in chunks + + +/datum/cameranet/proc/getCameraChunk(x, y, z) + var/key = "[x],[y],[z]" + + if(!(key in chunks)) + chunks[key] = new /datum/camerachunk(null, x, y, z) + + return chunks[key] + + + + +// This proc updates what chunks are considered seen +// by an aiEye. As part of the process, it will force +// any newly visible chunks with pending unscheduled +// updates to update, and show the correct obscuring +// and dimming image sets. If you do not call this +// after the eye has moved, it may result in the +// affected AI gaining (partial) xray, seeing through +// now-closed doors, not seeing through open doors, +// or other visibility oddities, depending on if/when +// they last visited any of the chunks in the nearby +// area. + +// It must be called manually, as there is no way to +// have a proc called automatically every time an +// object's loc changes. + +/datum/cameranet/proc/visibility(mob/aiEye/ai) + var/x1 = max(0, ai.x - 16) & ~0xf + var/y1 = max(0, ai.y - 16) & ~0xf + var/x2 = min(world.maxx, ai.x + 16) & ~0xf + var/y2 = min(world.maxy, ai.y + 16) & ~0xf + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + visibleChunks += getCameraChunk(x, y, ai.z) + + var/list/remove = ai.visibleCameraChunks - visibleChunks + var/list/add = visibleChunks - ai.visibleCameraChunks + + for(var/datum/camerachunk/c in remove) + c.remove(ai) + + for(var/datum/camerachunk/c in add) + c.add(ai) + + + + +// This proc should be called if a turf, or the contents +// of a turf, changes opacity. This includes such things +// as changing the turf, opening or closing a door, or +// anything else that would alter line of sight in the +// general area. + +/datum/cameranet/proc/updateVisibility(turf/loc) + if(!chunkGenerated(loc.x & ~0xf, loc.y & ~0xf, loc.z)) + return + + var/datum/camerachunk/chunk = getCameraChunk(loc.x & ~0xf, loc.y & ~0xf, loc.z) + chunk.visibilityChanged(loc) + + + + +// This proc updates all relevant chunks when enabling or +// creating a camera, allowing freelook and the minimap to +// respond correctly. + +/datum/cameranet/proc/addCamera(obj/machinery/camera/c) + var/x1 = max(0, c.x - 16) & ~0xf + var/y1 = max(0, c.y - 16) & ~0xf + var/x2 = min(world.maxx, c.x + 16) & ~0xf + var/y2 = min(world.maxy, c.y + 16) & ~0xf + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + if(chunkGenerated(x, y, c.z)) + var/datum/camerachunk/chunk = getCameraChunk(x, y, c.z) + + if(!(c in chunk.cameras)) + chunk.cameras += c + chunk.hasChanged() + + + + +// This proc updates all relevant chunks when disabling or +// deleting a camera, allowing freelook and the minimap to +// respond correctly. + +/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) + var/x1 = max(0, c.x - 16) & ~0xf + var/y1 = max(0, c.y - 16) & ~0xf + var/x2 = min(world.maxx, c.x + 16) & ~0xf + var/y2 = min(world.maxy, c.y + 16) & ~0xf + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + if(chunkGenerated(x, y, c.z)) + var/datum/camerachunk/chunk = getCameraChunk(x, y, c.z) + + if(!c) + chunk.hasChanged() + + if(c in chunk.cameras) + chunk.cameras -= c + chunk.hasChanged() diff --git a/code/WorkInProgress/AI_Visibility/chunk.dm b/code/WorkInProgress/AI_Visibility/chunk.dm new file mode 100644 index 0000000000..1ed5ef967e --- /dev/null +++ b/code/WorkInProgress/AI_Visibility/chunk.dm @@ -0,0 +1,190 @@ + +/datum/camerachunk + var/list/turfs = list() + + var/list/obscuredTurfs = list() + var/list/visibleTurfs = list() + var/list/dimTurfs = list() + + var/list/obscured = list() + var/list/dim = list() + + var/list/cameras = list() + var/list/seenby = list() + + var/visible = 0 + var/changed = 1 + var/updating = 0 + var/minimap_updating = 0 + + var/x + var/y + var/z + + + var/icon/minimap_icon = new('minimap.dmi', "chunk_base") + var/obj/minimap_obj/minimap_obj = new() + +/datum/camerachunk/proc/add(mob/aiEye/ai) + ai.visibleCameraChunks += src + if(ai.ai.client) + ai.ai.client.images += obscured + ai.ai.client.images += dim + visible++ + seenby += ai + if(changed && !updating) + update() + changed = 0 + +/datum/camerachunk/proc/remove(mob/aiEye/ai) + ai.visibleCameraChunks -= src + if(ai.ai.client) + ai.ai.client.images -= obscured + ai.ai.client.images -= dim + seenby -= ai + if(visible > 0) + visible-- + +/datum/camerachunk/proc/visibilityChanged(turf/loc) + if(!(loc in visibleTurfs)) + return + + hasChanged() + +/datum/camerachunk/proc/hasChanged() + if(visible) + if(!updating) + updating = 1 + spawn(10)//Batch large changes, such as many doors opening or closing at once + update() + updating = 0 + else + changed = 1 + + if(!minimap_updating) + minimap_updating = 1 + + spawn(MINIMAP_UPDATE_DELAY) + if(changed && !updating) + update() + changed = 0 + + update_minimap() + minimap_updating = 0 + +/datum/camerachunk/proc/update() + + var/list/newDimTurfs = list() + var/list/newVisibleTurfs = list() + + for(var/obj/machinery/camera/c in cameras) + var/lum = c.luminosity + c.luminosity = 7 + + newDimTurfs |= turfs & view(7, c) + newVisibleTurfs |= turfs & view(6, c) + + c.luminosity = lum + + var/list/dimAdded = newDimTurfs - dimTurfs + var/list/dimRemoved = dimTurfs - newDimTurfs + var/list/visAdded = newVisibleTurfs - visibleTurfs + var/list/visRemoved = visibleTurfs - newVisibleTurfs + + visibleTurfs = newVisibleTurfs + dimTurfs = newDimTurfs + obscuredTurfs = turfs - dimTurfs + dimTurfs -= visibleTurfs + + for(var/turf/t in dimRemoved) + if(t.dim) + dim -= t.dim + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images -= t.dim + + if(!(t in visibleTurfs)) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images += t.obscured + + for(var/turf/t in dimAdded) + if(!(t in visibleTurfs)) + if(!t.dim) + t.dim = image('cameravis.dmi', t, "dim", 15) + t.mouse_opacity = 0 + + dim += t.dim + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images += t.dim + + if(t.obscured) + obscured -= t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images -= t.obscured + + for(var/turf/t in visAdded) + if(t.obscured) + obscured -= t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images -= t.obscured + + for(var/turf/t in visRemoved) + if(t in obscuredTurfs) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + for(var/mob/aiEye/m in seenby) + if(m.ai.client) + m.ai.client.images += t.obscured + + +/datum/camerachunk/New(loc, x, y, z) + x &= ~0xf + y &= ~0xf + + src.x = x + src.y = y + src.z = z + + for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) + if(c.status) + cameras += c + + turfs = block(locate(x, y, z), locate(min(world.maxx, x + 15), min(world.maxy, y + 15), z)) + + for(var/obj/machinery/camera/c in cameras) + var/lum = c.luminosity + c.luminosity = 7 + + dimTurfs |= turfs & view(7, c) + visibleTurfs |= turfs & view(6, c) + + c.luminosity = lum + + obscuredTurfs = turfs - dimTurfs + dimTurfs -= visibleTurfs + + for(var/turf/t in obscuredTurfs) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + + for(var/turf/t in dimTurfs) + if(!(t in visibleTurfs)) + if(!t.dim) + t.dim = image('cameravis.dmi', t, "dim", TURF_LAYER) + t.dim.mouse_opacity = 0 + + dim += t.dim + + cameranet.minimap += minimap_obj diff --git a/code/WorkInProgress/AI_Visibility/minimap.dm b/code/WorkInProgress/AI_Visibility/minimap.dm new file mode 100644 index 0000000000..18003ceb6b --- /dev/null +++ b/code/WorkInProgress/AI_Visibility/minimap.dm @@ -0,0 +1,110 @@ + +/obj/minimap_obj/Click(location, control, params) + if(!istype(usr, /mob/dead) && !istype(usr, /mob/living/silicon/ai) && !(usr.client && usr.client.holder && usr.client.holder.level >= 4)) + return + + var/list/par = params2list(params) + var/screen_loc = par["screen-loc"] + + if(findtext(screen_loc, "minimap:") != 1) + return + + screen_loc = copytext(screen_loc, length("minimap:") + 1) + + var/x_text = copytext(screen_loc, 1, findtext(screen_loc, ",")) + var/y_text = copytext(screen_loc, findtext(screen_loc, ",") + 1) + + var/x = (text2num(copytext(x_text, 1, findtext(x_text, ":"))) - 1) * 16 + x += round((text2num(copytext(x_text, findtext(x_text, ":") + 1)) + 1) / 2) + + var/y = (text2num(copytext(y_text, 1, findtext(y_text, ":"))) - 1) * 16 + y += round((text2num(copytext(y_text, findtext(y_text, ":") + 1)) + 1) / 2) + + if(istype(usr, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/ai = usr + ai.freelook() + ai.eyeobj.loc = locate(max(1, x - 1), max(1, y - 1), ai.eyeobj.z) + cameranet.visibility(ai.eyeobj) + + else + usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.z) + +/mob/dead/verb/Open_Minimap() + set category = "Ghost" + winshow(src, "minimapwindow", 1) + client.screen |= cameranet.minimap + + if(cameranet.generating_minimap) + cameranet.minimap_viewers += src + +/mob/living/silicon/ai/verb/Open_Minimap() + set category = "AI Commands" + winshow(src, "minimapwindow", 1) + client.screen |= cameranet.minimap + + if(cameranet.generating_minimap) + cameranet.minimap_viewers += src + +/client/proc/Open_Minimap() + set category = "Admin" + winshow(src, "minimapwindow", 1) + screen |= cameranet.minimap + + if(cameranet.generating_minimap) + cameranet.minimap_viewers += src.mob + +/datum/camerachunk/proc/update_minimap() + if(changed && !updating) + update() + + minimap_icon.Blend(rgb(255, 0, 0), ICON_MULTIPLY) + + var/list/turfs = visibleTurfs | dimTurfs + + for(var/turf/turf in turfs) + var/x = (turf.x & 0xf) * 2 + var/y = (turf.y & 0xf) * 2 + + if(turf.density) + minimap_icon.DrawBox(rgb(100, 100, 100), x + 1, y + 1, x + 2, y + 2) + continue + + else if(istype(turf, /turf/space)) + minimap_icon.DrawBox(rgb(0, 0, 0), x + 1, y + 1, x + 2, y + 2) + + else + minimap_icon.DrawBox(rgb(200, 200, 200), x + 1, y + 1, x + 2, y + 2) + + for(var/obj/structure/o in turf) + if(o.density) + if(istype(o, /obj/structure/window) && (o.dir == NORTH || o.dir == SOUTH || o.dir == EAST || o.dir == WEST)) + if(o.dir == NORTH) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 2, x + 2, y + 2) + else if(o.dir == SOUTH) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 1, x + 2, y + 1) + else if(o.dir == EAST) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 3, y + 1, x + 2, y + 2) + else if(o.dir == WEST) + minimap_icon.DrawBox(rgb(150, 150, 200), x + 1, y + 1, x + 1, y + 2) + + else + minimap_icon.DrawBox(rgb(150, 150, 150), x + 1, y + 1, x + 2, y + 2) + break + + for(var/obj/machinery/door/o in turf) + if(istype(o, /obj/machinery/door/window)) + if(o.dir == NORTH) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 2, x + 2, y + 2) + else if(o.dir == SOUTH) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 2, y + 1) + else if(o.dir == EAST) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 2, y + 1, x + 2, y + 2) + else if(o.dir == WEST) + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 1, y + 2) + + else + minimap_icon.DrawBox(rgb(100, 150, 100), x + 1, y + 1, x + 2, y + 2) + break + + minimap_obj.screen_loc = "minimap:[src.x / 16],[src.y / 16]" + minimap_obj.icon = minimap_icon diff --git a/code/WorkInProgress/AI_Visibility/util.dm b/code/WorkInProgress/AI_Visibility/util.dm new file mode 100644 index 0000000000..9b5a257839 --- /dev/null +++ b/code/WorkInProgress/AI_Visibility/util.dm @@ -0,0 +1,41 @@ + + +#define MINIMAP_UPDATE_DELAY 1200 + +/turf + var/image/obscured + var/image/dim + +/turf/proc/visibilityChanged() + cameranet.updateVisibility(src) + +/turf/New() + ..() + cameranet.updateVisibility(src) + +/obj/machinery/door/update_nearby_tiles(need_rebuild) + . = ..(need_rebuild) + cameranet.updateVisibility(loc) + +/obj/machinery/camera/New() + ..() + cameranet.addCamera(src) + +/obj/machinery/camera/Del() + cameranet.removeCamera(src) + ..() + +/obj/machinery/camera/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + . = ..(W, user) + if(istype(W, /obj/item/weapon/wirecutters)) + if(status) + cameranet.addCamera(src) + else + cameranet.removeCamera(src) + +/proc/checkcameravis(atom/A) + for(var/obj/machinery/camera/C in view(A,7)) + if(!C.status || C.stat == 2) + continue + return 1 + return 0 From 1b0f9daf99e1819e0498a1894a4e9549f451099e Mon Sep 17 00:00:00 2001 From: Uristqwerty Date: Sat, 19 May 2012 13:31:05 -0400 Subject: [PATCH 2/3] Continuing... Moved some code around Removed some unneeded lines Actually compiles (A #define from the previous commit was in the wrong file) --- code/WorkInProgress/AI_Visibility/ai.dm | 2 - code/WorkInProgress/AI_Visibility/chunk.dm | 186 ++++++++++++--------- code/WorkInProgress/AI_Visibility/util.dm | 2 - 3 files changed, 109 insertions(+), 81 deletions(-) diff --git a/code/WorkInProgress/AI_Visibility/ai.dm b/code/WorkInProgress/AI_Visibility/ai.dm index ae797da52d..aba5304a9b 100644 --- a/code/WorkInProgress/AI_Visibility/ai.dm +++ b/code/WorkInProgress/AI_Visibility/ai.dm @@ -25,14 +25,12 @@ set name = "freelook" current = null //cancel camera view first, it causes problems cameraFollow = null -// machine = null if(!eyeobj) //if it got deleted somehow (like an admin trying to fix things <.<') eyeobj = new() eyeobj.ai = src client.eye = eyeobj eyeobj.loc = loc cameranet.visibility(eyeobj) - cameraFollow = null /mob/aiEye/Move() . = ..() diff --git a/code/WorkInProgress/AI_Visibility/chunk.dm b/code/WorkInProgress/AI_Visibility/chunk.dm index 1ed5ef967e..fdcc68bd07 100644 --- a/code/WorkInProgress/AI_Visibility/chunk.dm +++ b/code/WorkInProgress/AI_Visibility/chunk.dm @@ -1,4 +1,6 @@ +#define MINIMAP_UPDATE_DELAY 1200 + /datum/camerachunk var/list/turfs = list() @@ -12,7 +14,6 @@ var/list/cameras = list() var/list/seenby = list() - var/visible = 0 var/changed = 1 var/updating = 0 var/minimap_updating = 0 @@ -25,25 +26,101 @@ var/icon/minimap_icon = new('minimap.dmi', "chunk_base") var/obj/minimap_obj/minimap_obj = new() -/datum/camerachunk/proc/add(mob/aiEye/ai) - ai.visibleCameraChunks += src - if(ai.ai.client) - ai.ai.client.images += obscured - ai.ai.client.images += dim - visible++ - seenby += ai + + +/datum/camerachunk/New(loc, x, y, z) + //Round X and Y down to a multiple of 16, if nessecary + src.x = x & ~0xF + src.y = y & ~0xF + src.z = z + + rebuild_chunk() + + + +// Completely re-calculate the whole chunk. + +/datum/camerachunk/proc/rebuild_chunk() + for(var/mob/aiEye/eye in seenby) + if(!eye.ai) + seenby -= eye + continue + + if(eye.ai.client) + eye.ai.client.images -= obscured + eye.ai.client.images -= dim + + var/start = locate(x, y, z) + var/end = locate(min(x + 15, world.maxx), min(y + 15, world.maxy), z) + + turfs = block(start, end) + dimTurfs = list() + visibleTurfs = list() + obscured = list() + dim = list() + cameras = list() + + for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) + if(c.status) + cameras += c + + for(var/obj/machinery/camera/c in cameras) + var/lum = c.luminosity + c.luminosity = 7 + + dimTurfs |= turfs & view(7, c) + visibleTurfs |= turfs & view(6, c) + + c.luminosity = lum + + obscuredTurfs = turfs - dimTurfs + dimTurfs -= visibleTurfs + + for(var/turf/t in obscuredTurfs) + if(!t.obscured) + t.obscured = image('cameravis.dmi', t, "black", 15) + + obscured += t.obscured + + for(var/turf/t in dimTurfs) + if(!t.dim) + t.dim = image('cameravis.dmi', t, "dim", TURF_LAYER) + t.dim.mouse_opacity = 0 + + dim += t.dim + + cameranet.minimap |= minimap_obj + + for(var/mob/aiEye/eye in seenby) + if(eye.ai.client) + eye.ai.client.images |= obscured + eye.ai.client.images |= dim + + + +/datum/camerachunk/proc/add(mob/aiEye/eye) + eye.visibleCameraChunks |= src + + if(eye.ai.client) + eye.ai.client.images |= obscured + eye.ai.client.images |= dim + + seenby |= eye + if(changed && !updating) update() changed = 0 -/datum/camerachunk/proc/remove(mob/aiEye/ai) - ai.visibleCameraChunks -= src - if(ai.ai.client) - ai.ai.client.images -= obscured - ai.ai.client.images -= dim - seenby -= ai - if(visible > 0) - visible-- + + +/datum/camerachunk/proc/remove(mob/aiEye/eye) + eye.visibleCameraChunks -= src + + if(eye.ai.client) + eye.ai.client.images -= obscured + eye.ai.client.images -= dim + + seenby -= eye /datum/camerachunk/proc/visibilityChanged(turf/loc) if(!(loc in visibleTurfs)) @@ -52,12 +129,14 @@ hasChanged() /datum/camerachunk/proc/hasChanged() - if(visible) + if(length(seenby) > 0) if(!updating) updating = 1 + spawn(10)//Batch large changes, such as many doors opening or closing at once update() updating = 0 + else changed = 1 @@ -96,21 +175,20 @@ obscuredTurfs = turfs - dimTurfs dimTurfs -= visibleTurfs + var/list/images_added = list() + var/list/images_removed = list() + for(var/turf/t in dimRemoved) if(t.dim) dim -= t.dim - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images -= t.dim + images_removed += t.dim if(!(t in visibleTurfs)) if(!t.obscured) t.obscured = image('cameravis.dmi', t, "black", 15) obscured += t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images += t.obscured + images_added += t.obscured for(var/turf/t in dimAdded) if(!(t in visibleTurfs)) @@ -119,22 +197,16 @@ t.mouse_opacity = 0 dim += t.dim - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images += t.dim + images_added += t.dim if(t.obscured) obscured -= t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images -= t.obscured + images_removed += t.obscured for(var/turf/t in visAdded) if(t.obscured) obscured -= t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images -= t.obscured + images_removed += t.obscured for(var/turf/t in visRemoved) if(t in obscuredTurfs) @@ -142,49 +214,9 @@ t.obscured = image('cameravis.dmi', t, "black", 15) obscured += t.obscured - for(var/mob/aiEye/m in seenby) - if(m.ai.client) - m.ai.client.images += t.obscured + images_added += t.obscured - -/datum/camerachunk/New(loc, x, y, z) - x &= ~0xf - y &= ~0xf - - src.x = x - src.y = y - src.z = z - - for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) - if(c.status) - cameras += c - - turfs = block(locate(x, y, z), locate(min(world.maxx, x + 15), min(world.maxy, y + 15), z)) - - for(var/obj/machinery/camera/c in cameras) - var/lum = c.luminosity - c.luminosity = 7 - - dimTurfs |= turfs & view(7, c) - visibleTurfs |= turfs & view(6, c) - - c.luminosity = lum - - obscuredTurfs = turfs - dimTurfs - dimTurfs -= visibleTurfs - - for(var/turf/t in obscuredTurfs) - if(!t.obscured) - t.obscured = image('cameravis.dmi', t, "black", 15) - - obscured += t.obscured - - for(var/turf/t in dimTurfs) - if(!(t in visibleTurfs)) - if(!t.dim) - t.dim = image('cameravis.dmi', t, "dim", TURF_LAYER) - t.dim.mouse_opacity = 0 - - dim += t.dim - - cameranet.minimap += minimap_obj + for(var/mob/aiEye/eye in seenby) + if(eye.ai.client) + eye.ai.client.images -= images_removed + eye.ai.client.images |= images_added diff --git a/code/WorkInProgress/AI_Visibility/util.dm b/code/WorkInProgress/AI_Visibility/util.dm index 9b5a257839..4e06f7fa38 100644 --- a/code/WorkInProgress/AI_Visibility/util.dm +++ b/code/WorkInProgress/AI_Visibility/util.dm @@ -1,7 +1,5 @@ -#define MINIMAP_UPDATE_DELAY 1200 - /turf var/image/obscured var/image/dim From 4d8665579120aa2de8e89a14e6a814e7114d452c Mon Sep 17 00:00:00 2001 From: Uristqwerty Date: Sun, 20 May 2012 03:46:37 -0400 Subject: [PATCH 3/3] Minimap works correctly with Z levels now. --- .../WorkInProgress/AI_Visibility/cameranet.dm | 9 +-- code/WorkInProgress/AI_Visibility/minimap.dm | 60 ++++++++++++++----- interface/skin.dmf | 18 ++++++ 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/code/WorkInProgress/AI_Visibility/cameranet.dm b/code/WorkInProgress/AI_Visibility/cameranet.dm index d5b001419f..b7376b6b57 100644 --- a/code/WorkInProgress/AI_Visibility/cameranet.dm +++ b/code/WorkInProgress/AI_Visibility/cameranet.dm @@ -18,7 +18,6 @@ var/list/minimap = list() var/generating_minimap = TRUE - var/list/minimap_viewers = list() var/datum/cameranet/cameranet = new() @@ -35,14 +34,10 @@ var/datum/cameranet/cameranet = new() for(var/x = 0, x <= world.maxx, x += 16) for(var/y = 0, y <= world.maxy, y += 16) sleep(1) - var/datum/camerachunk/c = getCameraChunk(x, y, 1) - c.update_minimap() - - for(var/mob/m in minimap_viewers) - m.client.screen |= c.minimap_obj + getCameraChunk(x, y, 5) + getCameraChunk(x, y, 1) generating_minimap = FALSE - minimap_viewers = list() /datum/cameranet/proc/chunkGenerated(x, y, z) diff --git a/code/WorkInProgress/AI_Visibility/minimap.dm b/code/WorkInProgress/AI_Visibility/minimap.dm index 18003ceb6b..52de195475 100644 --- a/code/WorkInProgress/AI_Visibility/minimap.dm +++ b/code/WorkInProgress/AI_Visibility/minimap.dm @@ -1,4 +1,9 @@ +/client/var/minimap_view_z = 1 + +/obj/minimap_obj + var/datum/camerachunk/chunk + /obj/minimap_obj/Click(location, control, params) if(!istype(usr, /mob/dead) && !istype(usr, /mob/living/silicon/ai) && !(usr.client && usr.client.holder && usr.client.holder.level >= 4)) return @@ -14,44 +19,67 @@ var/x_text = copytext(screen_loc, 1, findtext(screen_loc, ",")) var/y_text = copytext(screen_loc, findtext(screen_loc, ",") + 1) - var/x = (text2num(copytext(x_text, 1, findtext(x_text, ":"))) - 1) * 16 + var/x = chunk.x x += round((text2num(copytext(x_text, findtext(x_text, ":") + 1)) + 1) / 2) - var/y = (text2num(copytext(y_text, 1, findtext(y_text, ":"))) - 1) * 16 + var/y = chunk.y y += round((text2num(copytext(y_text, findtext(y_text, ":") + 1)) + 1) / 2) if(istype(usr, /mob/living/silicon/ai)) var/mob/living/silicon/ai/ai = usr ai.freelook() - ai.eyeobj.loc = locate(max(1, x - 1), max(1, y - 1), ai.eyeobj.z) + ai.eyeobj.loc = locate(max(1, x - 1), max(1, y - 1), usr.client.minimap_view_z) cameranet.visibility(ai.eyeobj) else - usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.z) + usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.client.minimap_view_z) /mob/dead/verb/Open_Minimap() set category = "Ghost" - winshow(src, "minimapwindow", 1) - client.screen |= cameranet.minimap + cameranet.show_minimap(client) - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src /mob/living/silicon/ai/verb/Open_Minimap() set category = "AI Commands" - winshow(src, "minimapwindow", 1) - client.screen |= cameranet.minimap + cameranet.show_minimap(client) - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src /client/proc/Open_Minimap() set category = "Admin" - winshow(src, "minimapwindow", 1) - screen |= cameranet.minimap + cameranet.show_minimap(src) + + +/mob/verb/Open_Minimap_Z() + set hidden = 1 + + if(!istype(src, /mob/dead) && !istype(src, /mob/living/silicon/ai) && !(client && client.holder && client.holder.level >= 4)) + return + + var/level = input("Select a Z level", "Z select", null) as null | anything in cameranet.minimap + + if(level != null) + cameranet.show_minimap(client, level) + + + +/datum/cameranet/proc/show_minimap(client/client, z_level = "z-1") + if(!istype(client.mob, /mob/dead) && !istype(client.mob, /mob/living/silicon/ai) && !(client.holder && client.holder.level >= 4)) + return + + if(z_level in cameranet.minimap) + winshow(client, "minimapwindow", 1) + + for(var/key in cameranet.minimap) + client.screen -= cameranet.minimap[key] + + client.screen |= cameranet.minimap[z_level] + + if(cameranet.generating_minimap) + spawn(50) + show_minimap(client, z_level) + + client.minimap_view_z = text2num(copytext(z_level, 3)) - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src.mob /datum/camerachunk/proc/update_minimap() if(changed && !updating) diff --git a/interface/skin.dmf b/interface/skin.dmf index a7fb4994df..934b5e5751 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -373,6 +373,24 @@ menu "minimap_menu" group = "minimap_size" is-disabled = false saved-params = "is-checked" + elem + name = "View" + command = "" + category = "" + is-checked = false + can-check = false + group = "" + is-disabled = false + saved-params = "is-checked" + elem + name = "Change Z level" + command = "Open-Minimap-Z" + category = "View" + is-checked = false + can-check = false + group = "" + is-disabled = false + saved-params = "is-checked" window "Telecomms IDE"