diff --git a/baystation12.dme b/baystation12.dme index 2a699386a96..74dea3f7ff8 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -153,6 +153,10 @@ #include "code\datums\spells\trigger.dm" #include "code\datums\spells\turf_teleport.dm" #include "code\datums\spells\wizard.dm" +#include "code\datums\visibility_networks\chunk.dm" +#include "code\datums\visibility_networks\dictionary.dm" +#include "code\datums\visibility_networks\visibility_interface.dm" +#include "code\datums\visibility_networks\visibility_network.dm" #include "code\defines\obj.dm" #include "code\defines\obj\hydro.dm" #include "code\defines\obj\weapon.dm" @@ -950,6 +954,7 @@ #include "code\modules\mob\living\silicon\ai\freelook\eye.dm" #include "code\modules\mob\living\silicon\ai\freelook\read_me.dm" #include "code\modules\mob\living\silicon\ai\freelook\update_triggers.dm" +#include "code\modules\mob\living\silicon\ai\freelook\visibility_interface.dm" #include "code\modules\mob\living\silicon\decoy\death.dm" #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" @@ -1018,6 +1023,9 @@ #include "code\modules\mob\new_player\preferences_setup.dm" #include "code\modules\mob\new_player\skill.dm" #include "code\modules\mob\new_player\sprite_accessories.dm" +#include "code\modules\mob\spirit\cultnet.dm" +#include "code\modules\mob\spirit\movement.dm" +#include "code\modules\mob\spirit\spirit.dm" #include "code\modules\nano\_JSON.dm" #include "code\modules\nano\JSON Reader.dm" #include "code\modules\nano\JSON Writer.dm" @@ -1291,7 +1299,6 @@ #include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen.dm" #include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen_external.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\LaserComputer.dm" -#include "code\WorkInProgress\Cael_Aislinn\Supermatter\SuperMatter.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm" #include "code\WorkInProgress\Chinsky\ashtray.dm" #include "code\WorkInProgress\Cib\MedicalSideEffects.dm" @@ -1300,6 +1307,7 @@ #include "code\WorkInProgress\Ported\policetape.dm" #include "code\WorkInProgress\SkyMarshal\officer_stuff.dm" #include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm" +#include "code\WorkInProgress\Yinadele\Supermatter.dm" #include "code\ZAS\Airflow.dm" #include "code\ZAS\Connection.dm" #include "code\ZAS\Debug.dm" diff --git a/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm b/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm index 9b50c74f686..831d20f2299 100644 --- a/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm +++ b/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm @@ -16,15 +16,15 @@ var/image/dim /turf/proc/visibilityChanged() - cameranet.updateVisibility(src) + cameraNetwork.updateVisibility(src) /turf/New() ..() - cameranet.updateVisibility(src) + cameraNetwork.updateVisibility(src) /* /turf/Del() ..() - cameranet.updateVisibility(src) + cameraNetwork.updateVisibility(src) */ /datum/camerachunk var/list/obscuredTurfs = list() @@ -73,7 +73,7 @@ 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) + cameraNetwork.visibility(ai.eyeobj) else usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.z) @@ -81,26 +81,26 @@ /mob/dead/verb/Open_Minimap() set category = "Ghost" winshow(src, "minimapwindow", 1) - client.screen |= cameranet.minimap + client.screen |= cameraNetwork.minimap - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src + if(cameraNetwork.generating_minimap) + cameraNetwork.minimap_viewers += src /mob/living/silicon/ai/verb/Open_Minimap() set category = "AI Commands" winshow(src, "minimapwindow", 1) - client.screen |= cameranet.minimap + client.screen |= cameraNetwork.minimap - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src + if(cameraNetwork.generating_minimap) + cameraNetwork.minimap_viewers += src /client/proc/Open_Minimap() set category = "Admin" winshow(src, "minimapwindow", 1) - screen |= cameranet.minimap + screen |= cameraNetwork.minimap - if(cameranet.generating_minimap) - cameranet.minimap_viewers += src.mob + if(cameraNetwork.generating_minimap) + cameraNetwork.minimap_viewers += src.mob /datum/camerachunk/proc/update_minimap() if(changed && !updating) @@ -325,11 +325,11 @@ dim += t.dim - cameranet.minimap += minimap_obj + cameraNetwork.minimap += minimap_obj -var/datum/cameranet/cameranet = new() +var/datum/cameraNetwork/cameraNetwork = new() -/datum/cameranet +/datum/cameraNetwork var/list/cameras = list() var/list/chunks = list() var/network = "net1" @@ -340,7 +340,7 @@ var/datum/cameranet/cameranet = new() var/generating_minimap = TRUE var/list/minimap_viewers = list() -/datum/cameranet/New() +/datum/cameraNetwork/New() ..() spawn(200) @@ -356,11 +356,11 @@ var/datum/cameranet/cameranet = new() generating_minimap = FALSE minimap_viewers = list() -/datum/cameranet/proc/chunkGenerated(x, y, z) +/datum/cameraNetwork/proc/chunkGenerated(x, y, z) var/key = "[x],[y],[z]" return key in chunks -/datum/cameranet/proc/getCameraChunk(x, y, z) +/datum/cameraNetwork/proc/getCameraChunk(x, y, z) var/key = "[x],[y],[z]" if(!(key in chunks)) @@ -368,7 +368,7 @@ var/datum/cameranet/cameranet = new() return chunks[key] -/datum/cameranet/proc/visibility(mob/aiEye/ai) +/datum/cameraNetwork/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 @@ -389,14 +389,14 @@ var/datum/cameranet/cameranet = new() for(var/datum/camerachunk/c in add) c.add(ai) -/datum/cameranet/proc/updateVisibility(turf/loc) +/datum/cameraNetwork/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) +/datum/cameraNetwork/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 @@ -410,7 +410,7 @@ var/datum/cameranet/cameranet = new() chunk.cameras += c chunk.hasChanged() -/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) +/datum/cameraNetwork/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 @@ -452,18 +452,18 @@ var/datum/cameranet/cameranet = new() eyeobj.ai = src client.eye = eyeobj eyeobj.loc = loc - cameranet.visibility(eyeobj) + cameraNetwork.visibility(eyeobj) cameraFollow = null /mob/aiEye/Move() . = ..() if(.) - cameranet.visibility(src) + cameraNetwork.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) + cameraNetwork.visibility(user.eyeobj) else return ..() @@ -477,7 +477,7 @@ var/datum/cameranet/cameranet = new() 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) + cameraNetwork.visibility(user.eyeobj) else return ..() */ @@ -492,23 +492,23 @@ var/datum/cameranet/cameranet = new() /obj/machinery/door/update_nearby_tiles(need_rebuild) . = ..(need_rebuild) - cameranet.updateVisibility(loc) + cameraNetwork.updateVisibility(loc) /obj/machinery/camera/New() ..() - cameranet.addCamera(src) + cameraNetwork.addViewpoint(src) /obj/machinery/camera/Del() - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(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) + cameraNetwork.addViewpoint(src) else - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(src) /proc/checkcameravis(atom/A) for(var/obj/machinery/camera/C in view(A,7)) @@ -545,7 +545,7 @@ var/datum/cameranet/cameranet = new() var/obj/machinery/camera/C = D[t] eyeobj.loc = C.loc - cameranet.visibility(eyeobj) + cameraNetwork.visibility(eyeobj) return @@ -570,4 +570,4 @@ var/datum/cameranet/cameranet = new() else eyeobj.loc = locate(src.x, src.y, src.z) - cameranet.visibility(eyeobj) + cameraNetwork.visibility(eyeobj) diff --git a/code/WorkInProgress/AI_Visibility/ai.dm b/code/WorkInProgress/AI_Visibility/ai.dm index 7dcbf54e679..a8c5470036e 100644 --- a/code/WorkInProgress/AI_Visibility/ai.dm +++ b/code/WorkInProgress/AI_Visibility/ai.dm @@ -29,17 +29,17 @@ eyeobj.ai = src client.eye = eyeobj eyeobj.loc = loc - cameranet.visibility(eyeobj) + cameraNetwork.visibility(eyeobj) /mob/aiEye/Move() . = ..() if(.) - cameranet.visibility(src) + cameraNetwork.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) + cameraNetwork.visibility(user.eyeobj) else return ..() @@ -79,7 +79,7 @@ var/obj/machinery/camera/C = D[t] eyeobj.loc = C.loc - cameranet.visibility(eyeobj) + cameraNetwork.visibility(eyeobj) return @@ -104,4 +104,4 @@ else eyeobj.loc = locate(src.x, src.y, src.z) - cameranet.visibility(eyeobj) + cameraNetwork.visibility(eyeobj) diff --git a/code/WorkInProgress/AI_Visibility/cameranet.dm b/code/WorkInProgress/AI_Visibility/cameranet.dm index 3b46844e6be..d2341425111 100644 --- a/code/WorkInProgress/AI_Visibility/cameranet.dm +++ b/code/WorkInProgress/AI_Visibility/cameranet.dm @@ -1,14 +1,14 @@ //------------------------------------------------------------ // -// The Cameranet +// The cameraNetwork // -// The cameranet is a single global instance of a unique +// The cameraNetwork is a single global instance of a unique // datum, which contains logic for managing the individual // chunks. // //------------------------------------------------------------ -/datum/cameranet +/datum/cameraNetwork var/list/cameras = list() var/list/chunks = list() var/network = "net1" @@ -18,18 +18,18 @@ var/generating_minimap = TRUE -var/datum/cameranet/cameranet = new() +var/datum/cameraNetwork/cameraNetwork = new() -/datum/cameranet/New() +/datum/cameraNetwork/New() ..() spawn(100) init_minimap() -/datum/cameranet/proc/init_minimap() +/datum/cameraNetwork/proc/init_minimap() for(var/x = 0, x <= world.maxx, x += 16) for(var/y = 0, y <= world.maxy, y += 16) sleep(1) @@ -39,12 +39,12 @@ var/datum/cameranet/cameranet = new() generating_minimap = FALSE -/datum/cameranet/proc/chunkGenerated(x, y, z) +/datum/cameraNetwork/proc/chunkGenerated(x, y, z) var/key = "[x],[y],[z]" return key in chunks -/datum/cameranet/proc/getCameraChunk(x, y, z) +/datum/cameraNetwork/proc/getCameraChunk(x, y, z) var/key = "[x],[y],[z]" if(!(key in chunks)) @@ -71,7 +71,7 @@ var/datum/cameranet/cameranet = new() // have a proc called automatically every time an // object's loc changes. -/datum/cameranet/proc/visibility(mob/aiEye/ai) +/datum/cameraNetwork/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 @@ -101,7 +101,7 @@ var/datum/cameranet/cameranet = new() // anything else that would alter line of sight in the // general area. -/datum/cameranet/proc/updateVisibility(turf/loc) +/datum/cameraNetwork/proc/updateVisibility(turf/loc) if(!chunkGenerated(loc.x & ~0xf, loc.y & ~0xf, loc.z)) return @@ -115,7 +115,7 @@ var/datum/cameranet/cameranet = new() // creating a camera, allowing freelook and the minimap to // respond correctly. -/datum/cameranet/proc/addCamera(obj/machinery/camera/c) +/datum/cameraNetwork/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 @@ -137,7 +137,7 @@ var/datum/cameranet/cameranet = new() // deleting a camera, allowing freelook and the minimap to // respond correctly. -/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) +/datum/cameraNetwork/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 diff --git a/code/WorkInProgress/AI_Visibility/chunk.dm b/code/WorkInProgress/AI_Visibility/chunk.dm index 8a6886a1ade..134d6097b56 100644 --- a/code/WorkInProgress/AI_Visibility/chunk.dm +++ b/code/WorkInProgress/AI_Visibility/chunk.dm @@ -88,7 +88,7 @@ dim += t.dim - cameranet.minimap |= minimap_obj + cameraNetwork.minimap |= minimap_obj for(var/mob/aiEye/eye in seenby) if(eye.ai.client) diff --git a/code/WorkInProgress/AI_Visibility/minimap.dm b/code/WorkInProgress/AI_Visibility/minimap.dm index c97b01e0f82..e4d4f7274f9 100644 --- a/code/WorkInProgress/AI_Visibility/minimap.dm +++ b/code/WorkInProgress/AI_Visibility/minimap.dm @@ -28,24 +28,24 @@ var/mob/living/silicon/ai/ai = usr ai.freelook() ai.eyeobj.loc = locate(max(1, x - 1), max(1, y - 1), usr.client.minimap_view_z) - cameranet.visibility(ai.eyeobj) + cameraNetwork.visibility(ai.eyeobj) else usr.loc = locate(max(1, x - 1), max(1, y - 1), usr.client.minimap_view_z) /mob/dead/verb/Open_Minimap() set category = "Ghost" - cameranet.show_minimap(client) + cameraNetwork.show_minimap(client) /mob/living/silicon/ai/verb/Open_Minimap() set category = "AI Commands" - cameranet.show_minimap(client) + cameraNetwork.show_minimap(client) /client/proc/Open_Minimap() set category = "Admin" - cameranet.show_minimap(src) + cameraNetwork.show_minimap(src) /mob/verb/Open_Minimap_Z() @@ -54,26 +54,26 @@ 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 + var/level = input("Select a Z level", "Z select", null) as null | anything in cameraNetwork.minimap if(level != null) - cameranet.show_minimap(client, level) + cameraNetwork.show_minimap(client, level) -/datum/cameranet/proc/show_minimap(client/client, z_level = "z-1") +/datum/cameraNetwork/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) + if(z_level in cameraNetwork.minimap) winshow(client, "minimapwindow", 1) - for(var/key in cameranet.minimap) - client.screen -= cameranet.minimap[key] + for(var/key in cameraNetwork.minimap) + client.screen -= cameraNetwork.minimap[key] - client.screen |= cameranet.minimap[z_level] + client.screen |= cameraNetwork.minimap[z_level] - if(cameranet.generating_minimap) + if(cameraNetwork.generating_minimap) spawn(50) show_minimap(client, z_level) diff --git a/code/WorkInProgress/AI_Visibility/util.dm b/code/WorkInProgress/AI_Visibility/util.dm index da576cbd406..0e32f8dec88 100644 --- a/code/WorkInProgress/AI_Visibility/util.dm +++ b/code/WorkInProgress/AI_Visibility/util.dm @@ -4,31 +4,31 @@ var/image/dim /turf/proc/visibilityChanged() - cameranet.updateVisibility(src) + cameraNetwork.updateVisibility(src) /turf/New() ..() - cameranet.updateVisibility(src) + cameraNetwork.updateVisibility(src) /obj/machinery/door/update_nearby_tiles(need_rebuild) . = ..(need_rebuild) - cameranet.updateVisibility(loc) + cameraNetwork.updateVisibility(loc) /obj/machinery/camera/New() ..() - cameranet.addCamera(src) + cameraNetwork.addViewpoint(src) /obj/machinery/camera/Del() - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(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) + cameraNetwork.addViewpoint(src) else - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(src) /proc/checkcameravis(atom/A) for(var/obj/machinery/camera/C in view(A,7)) diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index d659d2fa68c..3b2d9697bf9 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -72,7 +72,7 @@ debug_variables(paiController) feedback_add_details("admin_verb","DpAI") if("Cameras") - debug_variables(cameranet) + debug_variables(cameraNetwork) feedback_add_details("admin_verb","DCameras") message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") return diff --git a/code/datums/visibility_networks/chunk.dm b/code/datums/visibility_networks/chunk.dm new file mode 100644 index 00000000000..4abc1340b0f --- /dev/null +++ b/code/datums/visibility_networks/chunk.dm @@ -0,0 +1,179 @@ +#define UPDATE_BUFFER 25 // 2.5 seconds + +// CAMERA CHUNK +// +// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed. +// Allows the mob using this chunk to stream these chunks and know what it can and cannot see. + +/datum/visibility_chunk + var/obscured_image = 'icons/effects/cameravis.dmi' + var/obscured_sub = "black" + var/list/obscuredTurfs = list() + var/list/visibleTurfs = list() + var/list/obscured = list() + var/list/viewpoints = list() + var/list/turfs = list() + var/list/seenby = list() + var/visible = 0 + var/changed = 0 + var/updating = 0 + var/x = 0 + var/y = 0 + var/z = 0 + +/datum/visibility_chunk/proc/add(mob/new_mob) + + // if this thing doesn't use one of these visibility systems, kick it out + if (!new_mob.visibility_interface) + return + + // if the mob being added isn't a valid form of that mob, kick it out + if (!new_mob.visibility_interface:canBeAddedToChunk(src)) + return + + // add this chunk to the list of visible chunks + new_mob.visibility_interface:addChunk(src) + + visible++ + seenby += new_mob + if(changed && !updating) + update() + +/datum/visibility_chunk/proc/remove(mob/new_mob) + // if this thing doesn't use one of these visibility systems, kick it out + if (!new_mob.visibility_interface) + return + + // if the mob being added isn't a valid form of that mob, kick it out + if (!new_mob.visibility_interface:canBeAddedToChunk(src)) + return + + // remove the chunk + new_mob.visibility_interface:removeChunk(src) + + // remove the mob from out lists + seenby -= new_mob + if(visible > 0) + visible-- + +/datum/visibility_chunk/proc/visibilityChanged(turf/loc) + if(!visibleTurfs[loc]) + return + hasChanged() + +/datum/visibility_chunk/proc/hasChanged(var/update_now = 0) + if(visible || update_now) + if(!updating) + updating = 1 + spawn(UPDATE_BUFFER) // Batch large changes, such as many doors opening or closing at once + update() + updating = 0 + else + changed = 1 + + +/* +This function needs to be overwritten to return True if the viewpoint object is valid, and false if it is not. +*/ +/datum/visibility_chunk/proc/validViewpoint(var/viewpoint) + return FALSE + +/* +This function needs to be overwritten to return a list of visible turfs for that viewpoint +*/ +/datum/visibility_chunk/proc/getVisibleTurfsForViewpoint(var/viewpoint) + return list() + +// returns a list of turfs which can be seen in by the chunks viewpoints +/datum/visibility_chunk/proc/getVisibleTurfs() + var/list/newVisibleTurfs = list() + for(var/viewpoint in viewpoints) + if (validViewpoint(viewpoint)) + for (var/turf/t in getVisibleTurfsForViewpoint(viewpoint)) + newVisibleTurfs[t]=t + return newVisibleTurfs + +/* +This function needs to be overwritten to find nearby viewpoint objects to the chunk center. +*/ +/datum/visibility_chunk/proc/findNearbyViewpoints() + return FALSE + +/* +This function can be overwritten to change or randomize the obscuring images +*/ +/datum/visibility_chunk/proc/setObscuredImage(var/turf/target_turf) + if(!target_turf.obscured) + target_turf.obscured = image(obscured_image, target_turf, obscured_sub, 15) + +/datum/visibility_chunk/proc/update() + + set background = 1 + + // get a list of all the turfs that our viewpoints can see + var/list/newVisibleTurfs = getVisibleTurfs() + + // Removes turf that isn't in turfs. + newVisibleTurfs &= turfs + + var/list/visAdded = newVisibleTurfs - visibleTurfs + var/list/visRemoved = visibleTurfs - newVisibleTurfs + + visibleTurfs = newVisibleTurfs + obscuredTurfs = turfs - newVisibleTurfs + + // update the visibility overlays + for(var/turf in visAdded) + var/turf/t = turf + if(t.obscured) + obscured -= t.obscured + for(var/mob/current_mob in seenby) + if (current_mob.visibility_interface) + current_mob.visibility_interface:removeObscuredTurf(t) + + for(var/turf in visRemoved) + var/turf/t = turf + if(obscuredTurfs[t]) + setObscuredImage(t) + obscured += t.obscured + for(var/mob/current_mob in seenby) + if (current_mob.visibility_interface) + current_mob.visibility_interface:addObscuredTurf(t) + else + seenby -= current_mob + + +// Create a new chunk, since the chunks are made as they are needed. +/datum/visibility_chunk/New(loc, x, y, z) + + // 0xf = 15 + x &= ~0xf + y &= ~0xf + + src.x = x + src.y = y + src.z = z + + for(var/turf/t in range(10, locate(x + 8, y + 8, z))) + if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16) + turfs[t] = t + + // locate all nearby viewpoints + findNearbyViewpoints() + + // get the turfs that are visible to those viewpoints + visibleTurfs = getVisibleTurfs() + + // Removes turf that isn't in turfs. + visibleTurfs &= turfs + + // create the list of turfs we can't see + obscuredTurfs = turfs - visibleTurfs + + // create the list of obscuring images to add to viewing clients + for(var/turf in obscuredTurfs) + var/turf/t = turf + setObscuredImage(t) + obscured += t.obscured + +#undef UPDATE_BUFFER \ No newline at end of file diff --git a/code/datums/visibility_networks/dictionary.dm b/code/datums/visibility_networks/dictionary.dm new file mode 100644 index 00000000000..38773329850 --- /dev/null +++ b/code/datums/visibility_networks/dictionary.dm @@ -0,0 +1,7 @@ +var/datum/visibility_network/cameras/cameraNetwork = new /datum/visibility_network/cameras() +var/datum/visibility_network/list/visibility_networks = list("ALL_CAMERAS"=cameraNetwork) + +// used by turfs and objects to update all visibility networks +/proc/updateVisibilityNetworks(atom/A, var/opacity_check = 1) + for (var/datum/visibility_network/currentNetwork in visibility_networks) + currentNetwork.updateVisibility(A, opacity_check) \ No newline at end of file diff --git a/code/datums/visibility_networks/visibility_interface.dm b/code/datums/visibility_networks/visibility_interface.dm new file mode 100644 index 00000000000..7d8efba41d3 --- /dev/null +++ b/code/datums/visibility_networks/visibility_interface.dm @@ -0,0 +1,46 @@ +/datum/visibility_interface + var/chunk_type = null + var/mob/controller = null + var/list/visible_chunks = list() + + +/datum/visibility_interface/New(var/mob/controller) + src.controller = controller + + +/datum/visibility_interface/proc/validMob() + return getClient() + +/datum/visibility_interface/proc/getClient() + return controller.client + +/datum/visibility_interface/proc/canBeAddedToChunk(var/datum/visibility_chunk/test_chunk) + return istype(test_chunk,chunk_type) + + +/datum/visibility_interface/proc/addChunk(var/datum/visibility_chunk/test_chunk) + visible_chunks+=test_chunk + var/client/currentClient = getClient() + if(currentClient) + currentClient.images += test_chunk.obscured + + +/datum/visibility_interface/proc/removeChunk(var/datum/visibility_chunk/test_chunk) + visible_chunks-=test_chunk + var/client/currentClient = getClient() + if(currentClient) + currentClient.images -= test_chunk.obscured + + +/datum/visibility_interface/proc/removeObscuredTurf(var/turf/target_turf) + if(validMob()) + var/client/currentClient = getClient() + if(currentClient) + currentClient.images -= target_turf.obscured + + +/datum/visibility_interface/proc/addObscuredTurf(var/turf/target_turf) + if(validMob()) + var/client/currentClient = getClient() + if(currentClient) + currentClient.images -= target_turf.obscured \ No newline at end of file diff --git a/code/datums/visibility_networks/visibility_network.dm b/code/datums/visibility_networks/visibility_network.dm new file mode 100644 index 00000000000..99fe810a6ed --- /dev/null +++ b/code/datums/visibility_networks/visibility_network.dm @@ -0,0 +1,135 @@ +/datum/visibility_network + var/list/viewpoints = list() + + // the type of chunk used by this network + var/datum/visibility_chunk/ChunkType = /datum/visibility_chunk + + // The chunks of the map, mapping the areas that the viewpoints can see. + var/list/chunks = list() + + var/ready = 0 + + +// Creates a chunk key string from x,y,z coordinates +/datum/visibility_network/proc/createChunkKey(x,y,z) + x &= ~0xf + y &= ~0xf + return "[x],[y],[z]" + + +// Checks if a chunk has been Generated in x, y, z. +/datum/visibility_network/proc/chunkGenerated(x, y, z) + return (chunks[createChunkKey(x, y, z)]) + + +// Returns the chunk in the x, y, z. +// If there is no chunk, it creates a new chunk and returns that. +/datum/visibility_network/proc/getChunk(x, y, z) + var/key = createChunkKey(x, y, z) + if(!chunks[key]) + chunks[key] = new ChunkType(null, x, y, z) + return chunks[key] + + +/datum/visibility_network/proc/visibility(var/mob/targetMob) + + // if we've got not visibility interface on the mob, we canot do this + if (!targetMob.visibility_interface) + return + + // 0xf = 15 + var/x1 = max(0, targetMob.x - 16) & ~0xf + var/y1 = max(0, targetMob.y - 16) & ~0xf + var/x2 = min(world.maxx, targetMob.x + 16) & ~0xf + var/y2 = min(world.maxy, targetMob.y + 16) & ~0xf + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + visibleChunks += getChunk(x, y, targetMob.z) + + var/list/remove = targetMob.visibility_interface:visible_chunks - visibleChunks + var/list/add = visibleChunks - targetMob.visibility_interface:visible_chunks + + for(var/chunk in remove) + chunk:remove(targetMob) + + for(var/chunk in add) + chunk:add(targetMob) + + +// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. +/datum/visibility_network/proc/updateVisibility(atom/A, var/opacity_check = 1) + if(!ticker || (opacity_check && !A.opacity)) + return + majorChunkChange(A, 2) + + +/datum/visibility_network/proc/updateChunk(x, y, z) + if(!chunkGenerated(x, y, z)) + return + var/datum/visibility_chunk/chunk = getChunk(x, y, z) + chunk.hasChanged() + + +/datum/visibility_network/proc/validViewpoint(var/viewpoint) + return FALSE + + +/datum/visibility_network/proc/addViewpoint(var/viewpoint) + if(validViewpoint(viewpoint)) + majorChunkChange(viewpoint, 1) + + +/datum/visibility_network/proc/removeViewpoint(var/viewpoint) + if(validViewpoint(viewpoint)) + majorChunkChange(viewpoint, 0) + + +/datum/visibility_network/proc/updateViewpoint(var/viewpoint) + if(validViewpoint(viewpoint)) + majorChunkChange(viewpoint, 1) + + +// Never access this proc directly!!!! +// This will update the chunk and all the surrounding chunks. +// It will also add the atom to the cameras list if you set the choice to 1. +// Setting the choice to 0 will remove the viewpoint from the chunks. +// If you want to update the chunks around an object, without adding/removing a viewpoint, use choice 2. +/datum/visibility_network/proc/majorChunkChange(atom/c, var/choice) + // 0xf = 15 + if(!c) + return + + var/turf/T = get_turf(c) + if(T) + var/x1 = max(0, T.x - 8) & ~0xf + var/y1 = max(0, T.y - 8) & ~0xf + var/x2 = min(world.maxx, T.x + 8) & ~0xf + var/y2 = min(world.maxy, T.y + 8) & ~0xf + + //world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]" + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + if(chunkGenerated(x, y, T.z)) + var/datum/visibility_chunk/chunk = getChunk(x, y, T.z) + if(choice == 0) + // Remove the viewpoint. + chunk.viewpoints -= c + else if(choice == 1) + // You can't have the same viewpoint in the list twice. + chunk.viewpoints |= c + chunk.hasChanged() + +// checks if the network can see a particular atom +/datum/visibility_network/proc/checkCanSee(var/atom/target) + var/turf/position = get_turf(target) + var/datum/visibility_chunk/chunk = getChunk(position.x, position.y, position.z) + if(chunk) + if(chunk.changed) + chunk.hasChanged(1) // Update now, no matter if it's visible or not. + if(chunk.visibleTurfs[position]) + return 1 + return 0 \ No newline at end of file diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index b84388f5838..36e51007507 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -422,7 +422,8 @@ /obj/item/weapon/camera_bug/attack_self(mob/usr as mob) var/list/cameras = new/list() - for (var/obj/machinery/camera/C in cameranet.cameras) + + for (var/obj/machinery/camera/C in cameraNetwork.viewpoints) if (C.bugged && C.status) cameras.Add(C) if (length(cameras) == 0) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 104fbf1cdb7..60bb93912e1 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -122,7 +122,7 @@ rcd light flash thingy on matter drain mod_pick_name = "recam" uses = 10 -/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) +/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameraNetwork.viewpoints) set name = "Reactivate Camera" set category = "Malfunction" if (istype (C, /obj/machinery/camera)) @@ -143,7 +143,7 @@ rcd light flash thingy on matter drain mod_pick_name = "upgradecam" uses = 10 -/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) +/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameraNetwork.viewpoints) set name = "Upgrade Camera" set category = "Malfunction" if(istype(C)) @@ -156,7 +156,7 @@ rcd light flash thingy on matter drain if(!C.isXRay()) C.upgradeXRay() //Update what it can see. - cameranet.updateVisibility(C) + cameraNetwork.updateVisibility(C) upgraded = 1 if(!C.isEmpProof()) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index daea3219d6e..38dc530fb0f 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -39,7 +39,7 @@ assembly = new(src) assembly.state = 4 /* // Use this to look for cameras that have the same c_tag. - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in cameraNetwork.viewpoints) var/list/tempnetwork = C.network&src.network if(C != src && C.c_tag == src.c_tag && tempnetwork.len) world.log << "[src.c_tag] [src.x] [src.y] [src.z] conflicts with [C.c_tag] [C.x] [C.y] [C.z]" @@ -59,7 +59,7 @@ icon_state = "[initial(icon_state)]emp" var/list/previous_network = network network = list() - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(src) stat |= EMPED SetLuminosity(0) triggerCameraAlarm() @@ -69,7 +69,7 @@ stat &= ~EMPED cancelCameraAlarm() if(can_use()) - cameranet.addCamera(src) + cameraNetwork.addViewpoint(src) for(var/mob/O in mob_list) if (istype(O.machine, /obj/machinery/computer/security)) var/obj/machinery/computer/security/S = O.machine @@ -92,7 +92,7 @@ /obj/machinery/camera/proc/setViewRange(var/num = 7) src.view_range = num - cameranet.updateVisibility(src, 0) + cameraNetwork.updateVisibility(src, 0) /obj/machinery/camera/proc/shock(var/mob/living/user) if(!istype(user)) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index d5408d33308..c4afc34edf7 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -100,7 +100,7 @@ C.network = uniquelist(tempnetwork) tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS) if(!tempnetwork.len)//Camera isn't on any open network - remove its chunk from AI visibility. - cameranet.removeCamera(C) + cameraNetwork.removeViewpoint(C) C.c_tag = input diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index e088103fabd..b745cd37f8e 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -4,7 +4,7 @@ return var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.cameras) + for (var/obj/machinery/camera/C in cameraNetwork.viewpoints) L.Add(C) camera_sort(L) @@ -168,9 +168,9 @@ return 0 if(isrobot(M)) var/mob/living/silicon/robot/R = M - if(!(R.camera && R.camera.can_use()) && !cameranet.checkCameraVis(M)) + if(!(R.camera && R.camera.can_use()) && !cameraNetwork.checkCanSee(M)) return 0 - else if(!cameranet.checkCameraVis(M)) + else if(!cameraNetwork.checkCanSee(M)) return 0 return 1 diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1b21ecac955..2392eed9944 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -36,7 +36,7 @@ user.set_machine(src) var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.cameras) + for (var/obj/machinery/camera/C in cameraNetwork.viewpoints) L.Add(C) camera_sort(L) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 76f1b420461..19edf26e774 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -58,7 +58,7 @@ var/intercom_range_display_status = 0 del(C) if(camera_range_display_status) - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in cameraNetwork.viewpoints) new/obj/effect/debugging/camera_range(C.loc) feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -74,7 +74,7 @@ var/intercom_range_display_status = 0 var/list/obj/machinery/camera/CL = list() - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in cameraNetwork.viewpoints) CL += C var/output = {"CAMERA ANNOMALITIES REPORT