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
diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm index 90ae7667ddc..efbee3cfd68 100644 --- a/code/modules/clothing/spacesuits/ert.dm +++ b/code/modules/clothing/spacesuits/ert.dm @@ -13,7 +13,7 @@ else camera = new /obj/machinery/camera(src) camera.network = list("ERT") - cameranet.removeCamera(camera) + cameraNetwork.removeViewpoint(camera) camera.c_tag = user.name user << "\blue User scanned as [camera.c_tag]. Camera activated." diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 027a2e3a574..a898df5bcc9 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -97,7 +97,7 @@ else camera = new /obj/machinery/camera(src) camera.network = list("NUKE") - cameranet.removeCamera(camera) + cameraNetwork.removeViewpoint(camera) camera.c_tag = user.name user << "\blue User scanned as [camera.c_tag]. Camera activated." diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 42c4b0745b2..937ed928749 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -318,7 +318,7 @@ var/list/ai_list = list() unset_machine() src << browse(null, t1) if (href_list["switchcamera"]) - switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras + switchCamera(locate(href_list["switchcamera"])) in cameraNetwork.viewpoints if (href_list["showalerts"]) ai_alerts() //Carn: holopad requests @@ -548,7 +548,7 @@ var/list/ai_list = list() var/mob/living/silicon/ai/U = usr - for (var/obj/machinery/camera/C in cameranet.cameras) + for (var/obj/machinery/camera/C in cameraNetwork.viewpoints) if(!C.can_use()) continue @@ -566,7 +566,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.cameras) + for(var/obj/machinery/camera/C in cameraNetwork.viewpoints) if(!C.can_use()) continue if(network in C.network) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 7d52fbd7a24..8264f705a1b 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -1,3 +1,21 @@ +/datum/visibility_network/cameras + ChunkType = /datum/visibility_chunk/camera + +/datum/visibility_network/cameras/validViewpoint(var/viewpoint) + var/obj/machinery/camera/c = viewpoint + if (!c) + return FALSE + return c.can_use() + + + + + + + + + +/* // CAMERA NET // // The datum containing all the chunks. @@ -145,4 +163,6 @@ var/datum/cameranet/cameranet = new() if(cameranet.chunkGenerated(x, y, z)) var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z) usr.client.debug_variables(chunk) +*/ + */ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index 33dbfd09665..da1cc370f00 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -1,3 +1,29 @@ + +/datum/visibility_chunk/camera + +/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 + + +/datum/visibility_chunk/camera/getVisibleTurfsForViewpoint(var/viewpoint) + var/obj/machinery/camera/c = viewpoint + return c.can_see() + + +/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 +/* + #define UPDATE_BUFFER 25 // 2.5 seconds // CAMERA CHUNK @@ -165,4 +191,6 @@ t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) obscured += t.obscured -#undef UPDATE_BUFFER \ No newline at end of file +#undef UPDATE_BUFFER + +*/ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index c82fbb7c76d..44081bb636b 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -6,13 +6,16 @@ /mob/aiEye name = "Inactive AI Eye" 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 +/mob/aiEye/New() + ..() + visibility_interface = new /datum/visibility_interface/ai_eye(src) + // Movement code. Returns 0 to stop air movement from moving it. /mob/aiEye/Move() return 0 @@ -43,7 +46,7 @@ return T = get_turf(T) loc = T - cameranet.visibility(src) + cameraNetwork.visibility(src) if(ai.client) ai.client.eye = src //Holopad @@ -136,7 +139,8 @@ if(client && client.eye) client.eye = src - for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) + + for(var/datum/visibility_chunk/camera/c in eyeobj.visibility_interface.visible_chunks) c.remove(eyeobj) /mob/living/silicon/ai/verb/toggle_acceleration() diff --git a/code/modules/mob/living/silicon/ai/freelook/read_me.dm b/code/modules/mob/living/silicon/ai/freelook/read_me.dm index 53e68ff1377..aa3d99bdba0 100644 --- a/code/modules/mob/living/silicon/ai/freelook/read_me.dm +++ b/code/modules/mob/living/silicon/ai/freelook/read_me.dm @@ -43,7 +43,7 @@ WHERE IS EVERYTHING? - cameranet.dm = Everything about the cameranet datum. + cameraNetwork.dm = Everything about the cameraNetwork 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. diff --git a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm index c1f63313727..224d22f5067 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -9,7 +9,7 @@ /turf/proc/visibilityChanged() if(ticker) - cameranet.updateVisibility(src) + updateVisibilityNetworks(src) /turf/simulated/Del() visibilityChanged() @@ -25,25 +25,25 @@ /obj/structure/Del() if(ticker) - cameranet.updateVisibility(src) + updateVisibilityNetworks(src) ..() /obj/structure/New() ..() if(ticker) - cameranet.updateVisibility(src) + updateVisibilityNetworks(src) // EFFECTS /obj/effect/Del() if(ticker) - cameranet.updateVisibility(src) + updateVisibilityNetworks(src) ..() /obj/effect/New() ..() if(ticker) - cameranet.updateVisibility(src) + updateVisibilityNetworks(src) // DOORS @@ -53,8 +53,9 @@ . = ..(need_rebuild) // Glass door glass = 1 // don't check then? - if(!glass && cameranet) - cameranet.updateVisibility(src, 0) + if(!glass) + world << "Updating visibility for [src]" + updateVisibilityNetworks(src,0) // ROBOT MOVEMENT @@ -72,7 +73,7 @@ updating = 1 spawn(BORG_CAMERA_BUFFER) if(oldLoc != src.loc) - cameranet.updatePortableCamera(src.camera) + cameraNetwork.updateViewpoint(src.camera) updating = 0 // CAMERA @@ -82,23 +83,23 @@ /obj/machinery/camera/deactivate(user as mob, var/choice = 1) ..(user, choice) if(src.can_use()) - cameranet.addCamera(src) + cameraNetwork.addViewpoint(src) else src.SetLuminosity(0) - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(src) /obj/machinery/camera/New() ..() - cameranet.cameras += src //Camera must be added to global list of all cameras no matter what... + cameraNetwork.viewpoints += src //Camera must be added to global list of all cameras no matter what... 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.addCamera(src) + cameraNetwork.addViewpoint(src) /obj/machinery/camera/Del() - cameranet.cameras -= src + cameraNetwork.viewpoints -= src var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) if(open_networks.len) - cameranet.removeCamera(src) + cameraNetwork.removeViewpoint(src) ..() #undef BORG_CAMERA_BUFFER \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm b/code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm new file mode 100644 index 00000000000..b55598c6090 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm @@ -0,0 +1,10 @@ +/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 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 611243f6548..8740c4a4f97 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1201,7 +1201,7 @@ //Disconnect it's camera so it's not so easily tracked. if(src.camera) src.camera.network = list() - cameranet.removeCamera(src.camera) + cameraNetwork.removeViewpoint(src.camera) /mob/living/silicon/robot/proc/ResetSecurityCodes() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 5f7c707635f..fd0f6be9013 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -204,6 +204,7 @@ var/obj/control_object //Used by admins to possess objects. All mobs should have this var + var/datum/visibility_interface/visibility_interface = null // used by the visibility system to provide an interface for the visibility networks //Whether or not mobs can understand other mobtypes. These stay in /mob so that ghosts can hear everything. var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 314a4026ab1..66c665644f3 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -114,6 +114,11 @@ proc/isobserver(A) if(istype(A, /mob/dead/observer)) return 1 return 0 + +/proc/isSpirit(A) + if(istype(A, /mob/spirit)) + return 1 + return 0 proc/isorgan(A) if(istype(A, /datum/organ/external)) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 1ea768d0056..399e7b9a737 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -176,7 +176,8 @@ return if(mob.stat==2) return - + + if(isSpirit(mob)) return mob:Spirit_Move(direct) if(isAI(mob)) return AIMove(n,direct,mob) if(mob.monkeyizing) return//This is sota the goto stop mobs from moving var diff --git a/code/modules/mob/spirit/cultnet.dm b/code/modules/mob/spirit/cultnet.dm new file mode 100644 index 00000000000..9847a80b0c1 --- /dev/null +++ b/code/modules/mob/spirit/cultnet.dm @@ -0,0 +1,8 @@ +/* + +This file contains the code necessary to do the display code for cult spirits. + +It reuses a lot of code from the AIEye cameraNetwork. In order to work properly, some of those files needed to be modified as well. + +*/ + diff --git a/code/modules/mob/spirit/movement.dm b/code/modules/mob/spirit/movement.dm new file mode 100644 index 00000000000..a7b05856ff4 --- /dev/null +++ b/code/modules/mob/spirit/movement.dm @@ -0,0 +1,40 @@ +// spirits are not moved by airflow +mob/spirit/Move() + return 0 + +// this is the main move proc for spirits, it uses their 'setLoc' function to handle all the visibility shenanigans +// this, like most movement code for these guys, is cribbed from the AIEye movement code +mob/spirit/proc/Spirit_Move(direct) + + var/initial = initial(sprint) + var/max_sprint = 50 + + // if we haven't moved in a while, we stop sprinting + if(cooldown && cooldown < world.timeofday) // 3 seconds + sprint = initial + + for(var/i = 0; i < max(sprint, initial); i += 20) + var/turf/step = get_turf(get_step(src, direct)) + if(step) + setLoc(step) + + cooldown = world.timeofday + 5 + if(acceleration) + sprint = min(sprint + 0.5, max_sprint) + else + sprint = initial + + // if we're trying to move, we want to stop following our target + follow_target = null + +mob/spirit/proc/setLoc(var/T) + T = get_turf(T) + loc = T + //cultnet.visibility(src) + +mob/spirit/verb/toggle_acceleration() + set category = "Spirit" + set name = "Toggle Acceleration" + + acceleration = !acceleration + usr << "Acceleration has been toggled [acceleration ? "on" : "off"]." \ No newline at end of file diff --git a/code/modules/mob/spirit/spirit.dm b/code/modules/mob/spirit/spirit.dm new file mode 100644 index 00000000000..d03a679c573 --- /dev/null +++ b/code/modules/mob/spirit/spirit.dm @@ -0,0 +1,42 @@ +/* +This mob type is used for entities that exist within the Cult's spirit world. They share the same visibility network and are intangible. + + +NOTES + +- make chunks generic + - subclass them for camerachunks and for cultchunks +- do the same thing with visibility networks + - cultnet and cameraNetwork etc. +*/ + +mob/spirit + name = "spirit" + desc = "A spirit" + icon = 'icons/mob/mob.dmi' + icon_state = "ghost" + layer = 4 + stat = CONSCIOUS + status_flags = GODMODE // spirits cannot be killed + density = 0 + canmove = 0 + blinded = 0 + anchored = 1 + invisibility = INVISIBILITY_SPIRIT + + // pseudo-movement values + var/sprint = 10 + var/cooldown = 0 + var/acceleration = 1 + var/follow_target = null + +mob/spirit/New() + sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF + see_invisible = SEE_SPIRITS + see_in_dark = 100 + + loc = pick(latejoin) + + // no nameless spirits + if (!name) + name = "Boogyman" \ No newline at end of file diff --git a/code/setup.dm b/code/setup.dm index 62515d050ca..a689ec70115 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -529,6 +529,9 @@ var/list/liftable_structures = list(\ #define SEE_INVISIBLE_LEVEL_TWO 45 //Used by some other stuff in code. It's really poorly organized. #define INVISIBILITY_LEVEL_TWO 45 //Used by some other stuff in code. It's really poorly organized. +#define INVISIBILITY_SPIRIT 50 +#define SEE_SPIRITS 50 + #define INVISIBILITY_OBSERVER 60 #define SEE_INVISIBLE_OBSERVER 60 diff --git a/code/unused/AI_Visibility.dm b/code/unused/AI_Visibility.dm index d218f4409b8..0769f8ca87b 100644 --- a/code/unused/AI_Visibility.dm +++ b/code/unused/AI_Visibility.dm @@ -5,7 +5,7 @@ var/image/dim /turf/proc/visibilityChanged() - cameranet.updateVisibility(src) + cameraNetwork.updateVisibility(src) /datum/camerachunk var/list/obscuredTurfs = list() @@ -180,22 +180,22 @@ dim += t.dim -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" var/ready = 0 -/datum/cameranet/New() +/datum/cameraNetwork/New() ..() -/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)) @@ -203,7 +203,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 @@ -224,14 +224,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 @@ -265,17 +265,17 @@ var/datum/cameranet/cameranet = new() else 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 ..() @@ -289,7 +289,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 ..() */ @@ -303,8 +303,8 @@ 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) \ No newline at end of file + cameraNetwork.addViewpoint(src) \ No newline at end of file