Remove legacy viewpoint code, move back to Bay's and /tg/'s system

This commit is contained in:
Markolie
2015-02-10 17:02:27 +01:00
parent c507158b8f
commit 64fe9e8600
34 changed files with 454 additions and 711 deletions
+2 -2
View File
@@ -52,7 +52,7 @@ var/intercom_range_display_status = 0
del(C)
if(camera_range_display_status)
for(var/obj/machinery/camera/C in cameranet.viewpoints)
for(var/obj/machinery/camera/C in cameranet.cameras)
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!
@@ -68,7 +68,7 @@ var/intercom_range_display_status = 0
var/list/obj/machinery/camera/CL = list()
for(var/obj/machinery/camera/C in cameranet.viewpoints)
for(var/obj/machinery/camera/C in cameranet.cameras)
CL += C
var/output = {"<B>CAMERA ANOMALIES REPORT</B><HR>
+1 -1
View File
@@ -185,7 +185,7 @@
return null
var/list/L = list()
for(var/obj/machinery/camera/C in cameranet.viewpoints)
for(var/obj/machinery/camera/C in cameranet.cameras)
var/list/temp = C.network & key.networks
if(temp.len)
L.Add(C)
+4 -4
View File
@@ -406,7 +406,7 @@ var/list/ai_list = list()
unset_machine()
src << browse(null, t1)
if (href_list["switchcamera"])
switchCamera(locate(href_list["switchcamera"])) in cameranet.viewpoints
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
if (href_list["showalerts"])
ai_alerts()
//Carn: holopad requests
@@ -712,11 +712,11 @@ var/list/ai_list = list()
var/mob/living/silicon/ai/U = usr
for (var/obj/machinery/camera/C in cameranet.viewpoints)
for (var/obj/machinery/camera/C in cameranet.cameras)
if(!C.can_use())
continue
var/list/tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS,1)
var/list/tempnetwork = difflist(C.network,restricted_camera_networks,1)
if(tempnetwork.len)
for(var/i in tempnetwork)
cameralist[i] = i
@@ -730,7 +730,7 @@ var/list/ai_list = list()
if(isnull(network))
network = old_network // If nothing is selected
else
for(var/obj/machinery/camera/C in cameranet.viewpoints)
for(var/obj/machinery/camera/C in cameranet.cameras)
if(!C.can_use())
continue
if(network in C.network)
@@ -1,25 +1,156 @@
/datum/visibility_network/cameras
ChunkType = /datum/visibility_chunk/camera
// CAMERA NET
//
// The datum containing all the chunks.
/datum/visibility_network/cameras/getViewpointFromMob(var/mob/currentMob)
var/mob/living/silicon/robot/currentRobot=currentMob
if(currentRobot)
return currentRobot.camera
return FALSE
var/datum/cameranet/cameranet = new()
/datum/visibility_network/cameras/validViewpoint(var/viewpoint)
var/obj/machinery/camera/c = viewpoint
if (!c)
return FALSE
return c.can_use()
/datum/cameranet
// The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Del().
var/list/cameras = list()
var/cameras_unsorted = 1
// The chunks of the map, mapping the areas that the cameras can see.
var/list/chunks = list()
var/ready = 0
/datum/cameranet/proc/process_sort()
if(cameras_unsorted)
cameras = dd_sortedObjectList(cameras)
cameras_unsorted = 0
// adding some indirection so that I don't have to edit a ton of files
/datum/visibility_network/cameras/proc/addCamera(var/camera)
return addViewpoint(camera)
// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
x &= ~0xf
y &= ~0xf
var/key = "[x],[y],[z]"
return (chunks[key])
/datum/visibility_network/cameras/proc/removeCamera(var/camera)
return removeViewpoint(camera)
// Returns the chunk in the x, y, z.
// If there is no chunk, it creates a new chunk and returns that.
/datum/cameranet/proc/getCameraChunk(x, y, z)
x &= ~0xf
y &= ~0xf
var/key = "[x],[y],[z]"
if(!chunks[key])
chunks[key] = new /datum/camerachunk(null, x, y, z)
/datum/visibility_network/cameras/proc/checkCameraVis(var/atom/target)
return checkCanSee(target)
return chunks[key]
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(mob/aiEye/ai)
// 0xf = 15
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/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(ai)
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(ai)
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
/datum/cameranet/proc/updateVisibility(atom/A, var/opacity_check = 1)
if(!ticker || (opacity_check && !A.opacity))
return
majorChunkChange(A, 2)
/datum/cameranet/proc/updateChunk(x, y, z)
// 0xf = 15
if(!chunkGenerated(x, y, z))
return
var/datum/camerachunk/chunk = getCameraChunk(x, y, z)
chunk.hasChanged()
// Removes a camera from a chunk.
/datum/cameranet/proc/removeCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 0)
// Add a camera to a chunk.
/datum/cameranet/proc/addCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 1)
// Used for Cyborg cameras. Since portable cameras can be in ANY chunk.
/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 1)
//else
// majorChunkChange(c, 0)
// 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 camera from the chunks.
// If you want to update the chunks around an object, without adding/removing a camera, use choice 2.
/datum/cameranet/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/camerachunk/chunk = getCameraChunk(x, y, T.z)
if(choice == 0)
// Remove the camera.
chunk.cameras -= c
else if(choice == 1)
// You can't have the same camera in the list twice.
chunk.cameras |= c
chunk.hasChanged()
// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
/datum/cameranet/proc/checkCameraVis(mob/living/target as mob)
// 0xf = 15
var/turf/position = get_turf(target)
return checkTurfVis(position)
/datum/cameranet/proc/checkTurfVis(var/turf/position)
var/datum/camerachunk/chunk = getCameraChunk(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
// Debug verb for VVing the chunk that the turf is in.
/*
/turf/verb/view_chunk()
set src in world
if(cameranet.chunkGenerated(x, y, z))
var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z)
usr.client.debug_variables(chunk)
*/
@@ -1,23 +1,168 @@
/datum/visibility_chunk/camera
#define UPDATE_BUFFER 25 // 2.5 seconds
/datum/visibility_chunk/camera/validViewpoint(var/viewpoint)
var/obj/machinery/camera/c = viewpoint
if(!c)
return FALSE
if(!c.can_use())
return FALSE
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
if(get_dist(point, c) > 24)
return FALSE
return TRUE
// CAMERA CHUNK
//
// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed.
// Allows the AI Eye to stream these chunks and know what it can and cannot see.
/datum/camerachunk
var/list/obscuredTurfs = list()
var/list/visibleTurfs = list()
var/list/obscured = list()
var/list/cameras = list()
var/list/turfs = list()
var/list/seenby = list()
var/visible = 0
var/changed = 0
var/updating = 0
var/x = 0
var/y = 0
var/z = 0
/datum/visibility_chunk/camera/getVisibleTurfsForViewpoint(var/viewpoint)
var/obj/machinery/camera/c = viewpoint
return c.can_see()
// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/aiEye/ai)
if(!ai.ai)
return
ai.visibleCameraChunks += src
if(ai.ai.client)
ai.ai.client.images += obscured
visible++
seenby += ai
if(changed && !updating)
update()
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/aiEye/ai)
if(!ai.ai)
return
ai.visibleCameraChunks -= src
if(ai.ai.client)
ai.ai.client.images -= obscured
seenby -= ai
if(visible > 0)
visible--
// Called when a chunk has changed. I.E: A wall was deleted.
/datum/camerachunk/proc/visibilityChanged(turf/loc)
if(!visibleTurfs[loc])
return
hasChanged()
// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will
// instead be flagged to update the next time an AI Eye moves near it.
/datum/camerachunk/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
// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
set background = 1
var/list/newVisibleTurfs = list()
for(var/camera in cameras)
var/obj/machinery/camera/c = camera
if(!c)
continue
if(!c.can_use())
continue
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
if(get_dist(point, c) > 24)
continue
for(var/turf/t in c.can_see())
newVisibleTurfs[t] = t
// Removes turf that isn't in turfs.
newVisibleTurfs &= turfs
var/list/visAdded = newVisibleTurfs - visibleTurfs
var/list/visRemoved = visibleTurfs - newVisibleTurfs
visibleTurfs = newVisibleTurfs
obscuredTurfs = turfs - newVisibleTurfs
for(var/turf in visAdded)
var/turf/t = turf
if(t.obscured)
obscured -= t.obscured
for(var/eye in seenby)
var/mob/aiEye/m = eye
if(!m || !m.ai)
continue
if(m.ai.client)
m.ai.client.images -= t.obscured
for(var/turf in visRemoved)
var/turf/t = turf
if(obscuredTurfs[t])
if(!t.obscured)
t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15)
obscured += t.obscured
for(var/eye in seenby)
var/mob/aiEye/m = eye
if(!m || !m.ai)
seenby -= m
continue
if(m.ai.client)
m.ai.client.images += t.obscured
// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(loc, x, y, z)
// 0xf = 15
x &= ~0xf
y &= ~0xf
src.x = x
src.y = y
src.z = z
/datum/visibility_chunk/camera/findNearbyViewpoints()
for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z)))
if(c.can_use())
viewpoints += c
cameras += c
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
for(var/camera in cameras)
var/obj/machinery/camera/c = camera
if(!c)
continue
if(!c.can_use())
continue
for(var/turf/t in c.can_see())
visibleTurfs[t] = t
// Removes turf that isn't in turfs.
visibleTurfs &= turfs
obscuredTurfs = turfs - visibleTurfs
for(var/turf in obscuredTurfs)
var/turf/t = turf
if(!t.obscured)
t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15)
obscured += t.obscured
#undef UPDATE_BUFFER
@@ -1,51 +1,41 @@
// AI EYE
//
// A mob that the AI controls to look around the station with.
// An invisible (no icon) mob that the AI controls to look around the station with.
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
/mob/aiEye
name = "Inactive AI Eye"
icon = 'icons/mob/AI.dmi'
icon_state = "eye"
alpha = 127
icon = 'icons/obj/status_display.dmi' // For AI friend secret shh :o
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
density = 0
status_flags = GODMODE // You can't damage it.
mouse_opacity = 0
see_in_dark = 7
invisibility = INVISIBILITY_AI_EYE
/mob/aiEye/New()
..()
visibility_interface = new /datum/visibility_interface/ai_eye(src)
invisibility = INVISIBILITY_MAXIMUM
// Movement code. Returns 0 to stop air movement from moving it.
/mob/aiEye/Move()
return 0
// Hide popout menu verbs
/mob/aiEye/examine()
/mob/aiEye/examine(atom/A as mob|obj|turf in view())
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/pull()
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/point()
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/examine(mob/user)
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/aiEye/setLoc(var/T, var/cancel_tracking = 1)
/mob/aiEye/setLoc(var/T)
if(ai)
if(!isturf(ai.loc))
return
if(cancel_tracking)
ai.ai_cancel_tracking()
T = get_turf(T)
loc = T
cameranet.visibility(src)
@@ -54,7 +44,6 @@
//Holopad
if(ai.holo)
ai.holo.move_hologram()
/mob/aiEye/proc/getLoc()
@@ -63,10 +52,6 @@
return
return ai.eyeobj.loc
/mob/aiEye/Move()
return 0
// AI MOVEMENT
// The AI's "eye". Described on the top of the page.
@@ -78,7 +63,6 @@
var/acceleration = 1
var/obj/machinery/hologram/holopad/holo = null
// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us.
/mob/living/silicon/ai/New()
..()
@@ -87,7 +71,7 @@
spawn(5)
eyeobj.loc = src.loc
/mob/living/silicon/ai/Destroy()
/mob/living/silicon/ai/Del()
eyeobj.ai = null
del(eyeobj) // No AI, no Eye
..()
@@ -96,9 +80,7 @@
if(istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = usr
if(AI.eyeobj && AI.client.eye == AI.eyeobj)
AI.cameraFollow = null
if (isturf(src.loc) || isturf(src))
AI.eyeobj.setLoc(src)
AI.eyeobj.setLoc(src)
// This will move the AIEye. It will also cause lights near the eye to light up, if toggled.
// This is handled in the proc below this one.
@@ -122,23 +104,24 @@
else
user.sprint = initial
user.cameraFollow = null
//user.unset_machine() //Uncomment this if it causes problems.
//user.lightNearbyCamera()
// Return to the Core.
/mob/living/silicon/ai/proc/view_core()
/mob/living/silicon/ai/proc/core()
set category = "AI Commands"
set name = "AI Core"
view_core()
/mob/living/silicon/ai/proc/view_core()
current = null
cameraFollow = null
unset_machine()
if(src.eyeobj && src.loc)
src.eyeobj.z = src.z
src.eyeobj.loc = src.loc
else
if(!src.eyeobj)
src << "ERROR: Eyeobj not found. Creating new eye..."
src.eyeobj = new(src.loc)
src.eyeobj.ai = src
@@ -146,11 +129,11 @@
if(client && client.eye)
client.eye = src
for(var/datum/visibility_chunk/camera/c in eyeobj.visibility_interface.visible_chunks)
for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks)
c.remove(eyeobj)
src.eyeobj.setLoc(src)
/mob/living/silicon/ai/verb/toggle_acceleration()
/mob/living/silicon/ai/proc/toggle_acceleration()
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
@@ -20,7 +20,7 @@
HOW IT WORKS
It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be
explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Destroy().
explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Del().
Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk.
These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside
@@ -43,7 +43,7 @@
WHERE IS EVERYTHING?
cameraNetwork.dm = Everything about the cameraNetwork datum.
cameranet.dm = Everything about the cameranet datum.
chunk.dm = Everything about the chunk datum.
eye.dm = Everything about the AI and the AIEye.
updating.dm = Everything about triggers that will update chunks.
@@ -1,3 +1,80 @@
#define BORG_CAMERA_BUFFER 30
//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update.
// TURFS
/turf
var/image/obscured
/turf/proc/visibilityChanged()
if(ticker)
cameranet.updateVisibility(src)
/turf/simulated/Del()
visibilityChanged()
..()
/turf/simulated/New()
..()
visibilityChanged()
// STRUCTURES
/obj/structure/Del()
if(ticker)
cameranet.updateVisibility(src)
..()
/obj/structure/New()
..()
if(ticker)
cameranet.updateVisibility(src)
// EFFECTS
/obj/effect/Del()
if(ticker)
cameranet.updateVisibility(src)
..()
/obj/effect/New()
..()
if(ticker)
cameranet.updateVisibility(src)
// DOORS
// Simply updates the visibility of the area when it opens/closes/destroyed.
/obj/machinery/door/update_nearby_tiles(need_rebuild)
. = ..(need_rebuild)
// Glass door glass = 1
// don't check then?
if(!glass && cameranet)
cameranet.updateVisibility(src, 0)
// ROBOT MOVEMENT
// Update the portable camera everytime the Robot moves.
// This might be laggy, comment it out if there are problems.
/mob/living/silicon/robot/var/updating = 0
/mob/living/silicon/robot/Move()
var/oldLoc = src.loc
. = ..()
if(.)
if(src.camera && src.camera.network.len)
if(!updating)
updating = 1
spawn(BORG_CAMERA_BUFFER)
if(oldLoc != src.loc)
cameranet.updatePortableCamera(src.camera)
updating = 0
// CAMERA
// An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not.
@@ -5,30 +82,29 @@
/obj/machinery/camera/deactivate(user as mob, var/choice = 1)
..(user, choice)
if(src.can_use())
cameranet.addViewpoint(src)
cameranet.addCamera(src)
else
src.SetLuminosity(0)
cameranet.removeViewpoint(src)
cameranet.removeCamera(src)
/obj/machinery/camera/New()
..()
//Camera must be added to global list of all cameras no matter what...
if(cameranet.cameras_unsorted || !ticker)
cameranet.viewpoints += src
cameranet.cameras += src
cameranet.cameras_unsorted = 1
else
dd_insertObjectList(cameranet.viewpoints, src)
dd_insertObjectList(cameranet.cameras, src)
var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) //...but if all of camera's networks are restricted, it only works for specific camera consoles.
var/list/open_networks = difflist(network,restricted_camera_networks) //...but if all of camera's networks are restricted, it only works for specific camera consoles.
if(open_networks.len) //If there is at least one open network, chunk is available for AI usage.
cameranet.addViewpoint(src)
cameranet.addCamera(src)
/obj/machinery/camera/Del()
cameranet.viewpoints -= src
var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS)
cameranet.cameras -= src
var/list/open_networks = difflist(network,restricted_camera_networks)
if(open_networks.len)
cameranet.removeViewpoint(src)
cameranet.removeCamera(src)
..()
#undef BORG_CAMERA_BUFFER
@@ -1,10 +0,0 @@
/datum/visibility_interface/ai_eye
chunk_type = /datum/visibility_chunk/camera
/datum/visibility_interface/ai_eye/getClient()
var/mob/aiEye/eye = controller
if (!eye)
return FALSE
if (!eye.ai)
return FALSE
return eye.ai.client
-48
View File
@@ -19,54 +19,6 @@ It reuses a lot of code from the AIEye cameraNetwork. In order to work properly,
if (vp)
return TRUE
return FALSE
/datum/visibility_chunk/cult/validViewpoint(var/atom/viewpoint)
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
if(get_dist(point, viewpoint) > 24)
return FALSE
if (isCultRune(viewpoint) || isCultViewpoint(viewpoint))
return viewpoint:can_use()
return FALSE
/datum/visibility_chunk/cult/getVisibleTurfsForViewpoint(var/viewpoint)
var/obj/effect/rune/rune = viewpoint
if (rune)
return rune.can_see()
var/obj/cult_viewpoint/cvp = viewpoint
if (cvp)
return cvp.can_see()
return null
/datum/visibility_chunk/cult/findNearbyViewpoints()
for(var/obj/cult_viewpoint/vp in range(16, locate(x + 8, y + 8, z)))
if(vp.can_use())
viewpoints += vp
for(var/obj/effect/rune/rune in range(16, locate(x + 8, y + 8, z)))
viewpoints += rune
/datum/visibility_network/cult
ChunkType = /datum/visibility_chunk/cult
/datum/visibility_network/cult/validViewpoint(var/viewpoint)
if (isCultRune(viewpoint) || isCultViewpoint(viewpoint))
return viewpoint:can_use()
return FALSE
/datum/visibility_network/cult/getViewpointFromMob(var/mob/currentMob)
for(var/obj/cult_viewpoint/currentView in currentMob)
return currentView
return FALSE
/datum/visibility_interface/cult
chunk_type = /datum/visibility_chunk/cult
/*
RUNE JUNK
-1
View File
@@ -52,7 +52,6 @@ mob/spirit/proc/Spirit_Move(direct)
mob/spirit/setLoc(var/T)
T = get_turf(T)
loc = T
cultNetwork.visibility(src)
mob/spirit/verb/toggle_acceleration()
set category = "Spirit"
-3
View File
@@ -38,9 +38,6 @@ mob/spirit/New()
loc = pick(latejoin)
// hook them to the cult visibility network
visibility_interface = new /datum/visibility_interface/cult(src)
// no nameless spirits
if (!name)
name = "Boogyman"
+2 -6
View File
@@ -18,9 +18,6 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list()
/obj/cult_viewpoint/New(var/mob/target)
owner = target
//src.loc = owner
owner.addToVisibilityNetwork(cultNetwork)
cultNetwork.viewpoints+=src
cultNetwork.addViewpoint(src)
cult_viewpoints+=src
//handle_missing_mask()
..()
@@ -28,10 +25,7 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list()
/obj/cult_viewpoint/Del()
processing_objects.Remove(src)
cultNetwork.viewpoints-=src
cultNetwork.removeViewpoint(src)
cult_viewpoints-=src
owner.removeFromVisibilityNetwork(cultNetwork)
..()
return
@@ -134,6 +128,8 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list()
/obj/cult_viewpoint/proc/get_display_name()
if(istype(src,/obj/effect/rune))
return name
if (!owner)
return
if (cult_name)