Revert "Merge pull request #4985 from jack-fractal/dev"

This reverts commit 1679b4062f, reversing
changes made to b149b273d9.

Signed-off-by: Mloc-Argent <colmohici@gmail.com>

Conflicts:
	code/datums/visibility_networks/update_triggers.dm
This commit is contained in:
Mloc-Argent
2014-05-31 00:25:56 +01:00
parent ee2e68960a
commit 3d2cc3cd82
44 changed files with 1504 additions and 2520 deletions

View File

@@ -108,7 +108,6 @@ var/global/floorIsLava = 0
body += "<B>Is an AI</B> "
else if(ishuman(M))
body += {"<A href='?src=\ref[src];makeai=\ref[M]'>Make AI</A> |
<A href='?src=\ref[src];makemask=\ref[M]'>Make Mask</A> |
<A href='?src=\ref[src];makerobot=\ref[M]'>Make Robot</A> |
<A href='?src=\ref[src];makealien=\ref[M]'>Make Alien</A> |
<A href='?src=\ref[src];makeslime=\ref[M]'>Make slime</A>

View File

@@ -265,9 +265,6 @@
else if(isobserver(M))
M_job = "Ghost"
else if(isSpirit(M))
M_job = (ismask(M)) ? "Mask" : "Spirit"
M_job = replacetext(M_job, "'", "")
M_job = replacetext(M_job, "\"", "")
@@ -351,10 +348,6 @@
dat += "<td>Monkey</td>"
else if(isalien(M))
dat += "<td>Alien</td>"
else if(ismask(M))
dat += "<td>Mask</td>"
else if(isSpirit(M))
dat += "<td>Spirit</td>"
else
dat += "<td>Unknown</td>"

View File

@@ -1196,15 +1196,6 @@
message_admins("\red Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!", 1)
log_admin("[key_name(usr)] AIized [key_name(H)]")
H.AIize()
else if(href_list["makemask"])
if(!check_rights(R_SPAWN)) return
var/mob/currentMob = locate(href_list["makemask"])
message_admins("\red Admin [key_name_admin(usr)] made [key_name_admin(currentMob)] into a Mask of Nar'Sie!", 1)
log_admin("[key_name(usr)] made [key_name(currentMob)] into a Mask of Nar'Sie!")
currentMob.make_into_mask(0,0)
else if(href_list["makealien"])
if(!check_rights(R_SPAWN)) return

View File

@@ -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.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!
@@ -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.viewpoints)
for(var/obj/machinery/camera/C in cameranet.cameras)
CL += C
var/output = {"<B>CAMERA ANNOMALITIES REPORT</B><HR>

View File

@@ -71,10 +71,9 @@
var/datum/organ/external/head = get_organ("head")
var/mob/living/simple_animal/borer/B
if(istype(head))
for(var/I in head.implants)
if(istype(I,/mob/living/simple_animal/borer))
B = I
for(var/I in head.implants)
if(istype(I,/mob/living/simple_animal/borer))
B = I
if(B)
if(!B.ckey && ckey && B.controlling)
B.ckey = ckey

View File

@@ -358,7 +358,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
@@ -574,7 +574,7 @@ 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
@@ -592,7 +592,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)

View File

@@ -1,25 +1,148 @@
/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
/datum/visibility_network/cameras/validViewpoint(var/viewpoint)
var/obj/machinery/camera/c = viewpoint
if (!c)
return FALSE
return c.can_use()
// 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)
/datum/visibility_network/cameras/proc/removeCamera(var/camera)
return removeViewpoint(camera)
/datum/visibility_network/cameras/proc/checkCameraVis(var/atom/target)
return checkCanSee(target)
var/datum/cameranet/cameranet = new()
/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()
// The chunks of the map, mapping the areas that the cameras can see.
var/list/chunks = list()
var/ready = 0
// 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])
// 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)
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)
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)
*/

View File

@@ -1,23 +1,168 @@
/datum/visibility_chunk/camera
#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 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
// 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/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
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

View File

@@ -6,16 +6,13 @@
/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
@@ -40,6 +37,7 @@
// It will also stream the chunk that the new loc is in.
/mob/aiEye/proc/setLoc(var/T)
if(ai)
if(!isturf(ai.loc))
return
@@ -138,8 +136,7 @@
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)
/mob/living/silicon/ai/verb/toggle_acceleration()

View File

@@ -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.

View File

@@ -1,5 +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.
@@ -7,23 +82,23 @@
/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()
..()
cameranet.viewpoints += src //Camera must be added to global list of all cameras no matter what...
cameranet.cameras += 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.addViewpoint(src)
cameranet.addCamera(src)
/obj/machinery/camera/Del()
cameranet.viewpoints -= src
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

View File

@@ -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

View File

@@ -333,9 +333,6 @@ var/list/slot_equipment_priority = list( \
return
*/
/mob
var/newPlayerType = /mob/new_player
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
@@ -385,12 +382,14 @@ var/list/slot_equipment_priority = list( \
log_game("[usr.key] AM failed due to disconnect.")
return
var/mob/newPlayer = new newPlayerType()
var/mob/new_player/M = new /mob/new_player()
if(!client)
log_game("[usr.key] AM failed due to disconnect.")
del(newPlayer)
del(M)
return
newPlayer.key = key
M.key = key
// M.Login() //wat
return
/client/verb/changes()

View File

@@ -205,7 +205,6 @@
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

View File

@@ -114,17 +114,7 @@ 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/ismask(A)
if(istype(A, /mob/spirit/mask))
return 1
return 0
proc/isorgan(A)
if(istype(A, /datum/organ/external))
return 1

View File

@@ -176,15 +176,8 @@
return
if(mob.stat==2) return
// handle possible spirit movement
if(istype(mob,/mob/spirit))
var/mob/spirit/currentSpirit = mob
return currentSpirit.Spirit_Move(direct)
// handle possible AI movement
if(isAI(mob))
return AIMove(n,direct,mob)
if(isAI(mob)) return AIMove(n,direct,mob)
if(mob.monkeyizing) return//This is sota the goto stop mobs from moving var

View File

@@ -1,80 +0,0 @@
/*
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.
*/
/proc/isCultRune(var/viewpoint)
var/obj/effect/rune/test_rune = viewpoint
if (test_rune)
return TRUE
return FALSE
/proc/isCultViewpoint(var/viewpoint)
var/obj/cult_viewpoint/vp = viewpoint
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
*/
/obj/effect/rune/proc/can_use()
return TRUE
/obj/effect/rune/proc/can_see()
return hear(view_range, get_turf(src))

View File

@@ -1,227 +0,0 @@
/mob/spirit/mask
icon = 'icons/mob/spirits/mask.dmi'
icon_state = "depressurized"
/mob/spirit/mask/New()
..()
spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/create_talisman(src)
spell_list += new /obj/effect/proc_holder/spell/aoe_turf/blood_speech(src)
spell_list += new /obj/effect/proc_holder/spell/aoe_turf/shatter_lights(src)
/mob/spirit/mask/verb/go_to_follower()
set category = "Mask"
set name = "Go to follower"
set desc = "Select who you would like to go too."
var/obj/cult_viewpoint/cultist = pick_cultist()
if (cultist)
follow_cultist(cultist.owner)
cult_log("[key_name_admin(src)] started following [key_name_admin(cultist)].")
src << "You start following [cultist.get_display_name()]."
/mob/spirit/mask/verb/urge_cultist()
set category = "Mask"
set name = "Urge cultist"
set desc = "Push your cultists to do something."
var/obj/cult_viewpoint/cultist = pick_cultist()
if (cultist)
if (cultist.owner)
var/newUrge = stripped_input(usr, "", "Set Urge", "")
cultist.set_urge(newUrge)
src << "You urge [cultist.owner.name] to [newUrge]."
cult_log("controlled by [key_name_admin(src)] has urged [key_name_admin(cultist.owner)] to [newUrge].")
/mob/spirit/mask/verb/set_cult_name()
set category = "Mask"
set name = "Set Cult Name"
set desc = "Grant a cultist a name."
var/obj/cult_viewpoint/cultist = pick_cultist()
if (cultist)
var/newName = stripped_input(usr, "", "Set Cult Name", "")
if (!newName)
return
cultist.set_cult_name(newName)
src << "You grant [cultist.owner.name] the secret name of [newName]."
if (cultist.owner)
cult_log("[key_name_admin(src)] has set [key_name_admin(cultist.owner)] to \'[newName]\'")
/mob/spirit/mask/verb/urge_cult()
set category = "Mask"
set name = "Urge Cult"
set desc = "Set urge on the entire cult."
var/newUrge = stripped_input(usr, "Please choose an urge.", "Set Urge", "")
for(var/obj/cult_viewpoint/viewpoint in cult_viewpoints)
viewpoint.set_urge(newUrge)
src << "You urge the entire cult to [newUrge]."
cult_log("[key_name_admin(src)] has urged the entire cult to [newUrge]")
/mob/spirit/mask/verb/set_favor_for_cultist()
set category = "Mask"
set name = "Show your favor"
set desc = "Set the favor for a cultist"
var/obj/cult_viewpoint/cultist = pick_cultist()
if (cultist)
if (cultist.owner)
var/list/favor = list("Pleased", "Displeased", "Indifference")
var/emotion = input("Pick your emotion", "Mask", null, null) in favor
switch(emotion)
if("Pleased")
cultist.set_favor(1)
cult_log("[key_name_admin(src)] is pleased with [key_name_admin(cultist.owner)]")
if("Displeased")
cultist.set_favor(-1)
cult_log("[key_name_admin(src)] is displeased with [key_name_admin(cultist.owner)]")
if("Indifference")
cultist.set_favor(0)
cult_log("[key_name_admin(src)] is indifferent too [key_name_admin(cultist.owner)]")
/mob/spirit/mask/proc/set_name()
spawn(0)
var/newName = stripped_input(src, "Please pick a name.", "Pick Name for Mask", "")
name = newName ? newName : "Mask of Nar'sie"
src << "You have set your name to [name]."
/mob/spirit/mask/proc/pick_cultist()
var/list/cultists = list()
for(var/obj/cult_viewpoint/viewpoint in cult_viewpoints)
cultists[viewpoint.get_display_name()]=viewpoint
var/input = input("Please, select a cultist!", "Cult", null, null) as null|anything in cultists
var/obj/cult_viewpoint/result = cultists[input]
return result
// this proc makes the mask visible very briefly
/mob/spirit/mask/proc/flicker()
spawn(0)
alpha = 127
invisibility=0
sleep(5)
invisibility=initial(invisibility)
alpha = 255
/proc/flicker_mask(mob/spirit/mask/target)
if(istype(target))
target.flicker()
// SPELLS
/obj/effect/proc_holder/spell/aoe_turf/blood_speech
name = "Speak to your Acolytes"
desc = "This spell allows you to speak to your flock."
school = "unknown evil"
charge_type = "recharge"
charge_max = 2000
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
/obj/effect/proc_holder/spell/aoe_turf/blood_speech/cast(list/targets)
var/input = stripped_input(usr, "Please choose a message to tell your acolytes.", "Voice of Blood", "")
if(!input)
revert_cast(usr)
cult_log("[key_name_admin(usr)]says : [input]")
flicker_mask(usr)
for(var/datum/mind/H in ticker.mode.cult)
if (H.current)
H.current << "<span class='cultspeech'><font size=3><span class='name'>[usr.name]: </span><span class='message'>[input]</span></font></span>"
for(var/mob/spirit/spirit in spirits)
spirit << "<span class='cultspeech'><font size=3><span class='name'>[usr.name]: </span><span class='message'>[input]</span></font></span>"
/obj/effect/proc_holder/spell/aoe_turf/shatter_lights
name = "Spread Shadows"
desc = "This spell breaks lights near the mask."
school = "unknown evil"
charge_type = "recharge"
charge_max = 1000
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
/obj/effect/proc_holder/spell/aoe_turf/shatter_lights/cast(list/targets)
cult_log("[key_name_admin(usr)] used Spread Shadows.")
flicker_mask(usr)
spawn(0)
for(var/area/A in range(3,get_turf(usr)))
for(var/obj/machinery/light/L in A)
L.on = 1
L.broken()
sleep(1)
for(var/obj/item/device/flashlight/F in A)
F.on = 0
/obj/effect/proc_holder/spell/aoe_turf/conjure/create_talisman
name = "Create Talisman"
desc = "This spell conjures a talisman"
school = "conjuration"
charge_type = "recharge"
charge_max = 3000
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
summon_type = list(/obj/item/weapon/paper/talisman)
var/list/talismans = list( "Armor"="armor",
"Blind"="blind",
"Conceal"="conceal",
"Communicate"="communicate",
"Deafen"="deafen",
"EMP"="emp",
"Teleport"="teleport",
"Tome"="newtome",
"Reveal Runes",
"Stun"="runestun",
"Soul Stone"="soulstone",
"Construct"="construct")
/obj/effect/proc_holder/spell/aoe_turf/conjure/create_talisman/cast(list/targets)
var/talisman = input("Pick a talisman type", "Talisman", null, null) as null|anything in talismans
var/imbue_value = talismans[talisman]
if (!talisman)
usr << "You choose not to create a talisman."
revert_cast(usr)
return
cult_log("[key_name_admin(usr,0)] created a talisman of type [talisman].")
flicker_mask(usr)
switch(talisman)
if ("Teleport")
var/target_rune = input("Pick a teleport target", "Teleport Rune", null, null) as null|anything in engwords
if (!target_rune)
usr << "You choose not to create a talisman."
revert_cast(usr)
return
summon_type = list(/obj/item/weapon/paper/talisman)
newVars = list("imbue" = "[target_rune]", "info" = "[target_rune]")
if ("Soul Stone")
summon_type = list(/obj/item/device/soulstone)
newVars = list()
if ("Construct")
summon_type = list(/obj/structure/constructshell)
newVars = list()
else
summon_type = list(/obj/item/weapon/paper/talisman)
newVars = list("imbue" = "[imbue_value]")
..()

View File

@@ -1,20 +0,0 @@
/proc/there_can_be_only_one_mask(var/mob/spirit/mask/target)
if(!istype(target))
return
for(var/mob/spirit/mask/currentSpirit in spirits)
if(currentSpirit)
if(currentSpirit!=target)
// create the ghost
var/mob/dead/observer/ghost = currentSpirit.ghostize(TRUE)
// let the deposed mask respawn immediately, the poor dear
ghost.timeofdeath = world.time - 20000
ghost.newPlayerType = /mob/new_player/cultist
// remove old mask body
del(currentSpirit)
/mob/new_player/cultist/AttemptLateSpawn(rank)
var/mob/newCharacter = ..(rank)
if(ticker.mode)
if(is_convertable_to_cult(newCharacter.mind))
ticker.mode.add_cultist(newCharacter.mind)

View File

@@ -1,62 +0,0 @@
// 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)
dir = direct // update our sprite
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/follow_cultist(mob/living/target as mob)
if(!istype(target)) return
var/obj/cult_viewpoint/currentView = getCultViewpoint(target)
var/mob/spirit/U = usr
if (!currentView)
U << "As a spirit, you may only track cultists."
U.follow_target = target
U << "Now following [currentView.get_cult_name()]."
spawn (0)
while (U.follow_target == target)
if (U.follow_target == null)
return
U.setLoc(get_turf(target))
sleep(10)
mob/spirit/proc/setLoc(var/T)
T = get_turf(T)
loc = T
cultNetwork.visibility(src)
mob/spirit/verb/toggle_acceleration()
set category = "Spirit"
set name = "Toggle Acceleration"
acceleration = !acceleration
usr << "Acceleration has been toggled [acceleration ? "on" : "off"]."

View File

@@ -1,73 +0,0 @@
/*
This mob type is used for entities that exist within the Cult's spirit world. They share the same visibility network and are intangible.
*/
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
mouse_opacity = 0
invisibility = INVISIBILITY_SPIRIT
universal_speak = 1
// pseudo-movement values
var/sprint = 10
var/cooldown = 0
var/acceleration = 1
var/follow_target = null
mob/spirit/is_active()
if (client && client.inactivity <= 10 * 60 * 10)
return TRUE
return FALSE
mob/spirit/New()
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
see_invisible = SEE_SPIRITS
see_in_dark = 100
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"
spirits+=src
..()
mob/spirit/Del()
spirits-=src
..()
mob/spirit/Topic(href, href_list)
if(usr != src)
return
..()
usr << "Spirit Href = [href]"
for (var/tempref in href_list)
usr << "Spirit href list [tempref] = [href_list[tempref]]"
if (href_list["track"])
usr << "Got to tracking."
var/mob/target = locate(href_list["track"]) in mob_list
var/mob/spirit/A = locate(href_list["track2"]) in spirits
if(A && target)
A.follow_cultist(target)
return

View File

@@ -1,202 +0,0 @@
#define FAVOR_PLEASED 1
#define FAVOR_INDIFFERENT 0
#define FAVOR_DISPLEASED -1
var/obj/cult_viewpoint/list/cult_viewpoints = list()
/obj/cult_viewpoint
var/view_range = 7
var/updating = 0
var/mob/owner = null
var/urge = ""
var/favor = FAVOR_INDIFFERENT
var/cult_name = null
/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()
..()
/obj/cult_viewpoint/Del()
processing_objects.Remove(src)
cultNetwork.viewpoints-=src
cultNetwork.removeViewpoint(src)
cult_viewpoints-=src
owner.removeFromVisibilityNetwork(cultNetwork)
..()
return
// VERBS
/obj/cult_viewpoint/verb/check_urge()
set category = "Cult"
set desc = "Discover what your god commands of you."
set name = "Check Urge"
set src in usr
if (src.urge)
owner << "\red \b You feel the urge to [src.urge]"
else
owner << "\b You feel no supernatural compulsions."
/obj/cult_viewpoint/verb/reach_out()
set category = "Cult"
set desc = "Reach out for your gods presence."
set name = "Reach Out"
set src in usr
for(var/mob/spirit/mask/currentMask in spirits)
if (currentMask.is_active())
owner << "\red \b You feel the reassuring presence of your god."
currentMask << "<span class='cultspeech'><span class='name'><a href='byond://?src=\ref[currentMask];track2=\ref[currentMask];track=\ref[usr]'>[get_display_name()]</a></span><span class='message'> has reached out to you.</span></span>"
return
owner << "\b You feel a chilling absence."
handle_missing_mask()
/obj/cult_viewpoint/verb/check_favor()
set category = "Cult"
set desc = "Check your favor with your god."
set name = "Check Favor"
set src in usr
switch(favor)
if(FAVOR_PLEASED)
owner << "\red \b You bask in your gods favor."
if(FAVOR_INDIFFERENT)
owner << "\red \b You feel nothing."
if(FAVOR_DISPLEASED)
owner << "\red \b You cringe at your gods displeasure."
/obj/cult_viewpoint/verb/pray_to_mask()
set category = "Cult"
set desc = "Pray to your god"
set name = "Pray to Nar'Sie"
set src in usr
var/input = stripped_input(usr, "Please choose a message to say to your god.", "Pray to Nar'Sie", "")
if(!input)
return
cult_log("[key_name(usr,0)](Pray):[input]")
owner << "<span class='cultspeech'><b>You pray to Nar'Sie</b>: [input]</span>"
for(var/mob/spirit/spirit in spirits)
spirit << "<span class='cultspeech'><span class='name'><a href='byond://?src=\ref[spirit];track2=\ref[spirit];track=\ref[usr]'>[get_display_name()]</a> prays : </span><span class='message'>[input]</span></span>"
// PROCS
/obj/cult_viewpoint/proc/set_favor(var/newFavor)
favor = newFavor
check_favor()
/obj/cult_viewpoint/proc/set_urge(var/newUrge)
if (!newUrge)
src.urge = null
src.urge = copytext(newUrge, 1, MAX_MESSAGE_LEN)
check_urge()
/obj/cult_viewpoint/proc/can_use()
if (owner.stat != DEAD)
return TRUE
return FALSE
/obj/cult_viewpoint/proc/can_see()
return hear(view_range, get_turf(owner))
/obj/cult_viewpoint/proc/get_cult_name()
if (cult_name)
return cult_name
return "An Unknown Servent"
/obj/cult_viewpoint/proc/set_cult_name(var/newName)
if (!owner)
return FALSE
if (newName)
cult_name = newName
owner << "\red \b You have been blessed with the secret name of '[newName]'."
else
cult_name = null
owner << "\red \b Your god has taken your secret name."
/obj/cult_viewpoint/proc/get_display_name()
if (!owner)
return
if (cult_name)
return cult_name
return owner.name
/obj/cult_viewpoint/proc/become_mask()
set category = "Cult"
set name = "Become Mask"
set desc = "Sacrifice your life and become a Mask of Nar'sie."
set src in usr
cult_log("[key_name(usr,0)] has tried to become a Mask of Nar'sie.")
if (!active_mask())
var/transformation_type = alert(owner.client, "You are about to become a Mask. Do you want it to be subtle or violent?", "Mask", "Subtle", "Violent")
if(!active_mask())
cult_log("[key_name(usr,0)] has become a Mask of Nar'sie.")
if (transformation_type=="Subtle")
log_admin("[key_name_admin(owner)] has subtly become a Mask of Nar'sie")
owner.make_into_mask(0,0)
else
log_admin("[key_name_admin(owner)] has violently become a Mask of Nar'sie")
owner.make_into_mask(1,1)
else
owner << "\b You cannot become a mask of Nar'Sie because a Mask already exists."
mask_has_been_found()
return
/obj/cult_viewpoint/proc/active_mask()
for(var/mob/spirit/mask/currentMask in spirits)
if (currentMask.is_active())
return TRUE
return FALSE
/obj/cult_viewpoint/proc/handle_missing_mask()
if (active_mask())
mask_has_been_found()
else
mask_is_missing()
/obj/cult_viewpoint/proc/mask_has_been_found()
for(var/obj/cult_viewpoint/viewpoint in cult_viewpoints)
if (viewpoint.verbs.Find(/obj/cult_viewpoint/proc/become_mask))
viewpoint.verbs-=/obj/cult_viewpoint/proc/become_mask
/obj/cult_viewpoint/proc/mask_is_missing()
for(var/obj/cult_viewpoint/viewpoint in cult_viewpoints)
if (!viewpoint.verbs.Find(/obj/cult_viewpoint/proc/become_mask))
viewpoint.verbs+=/obj/cult_viewpoint/proc/become_mask
/proc/getCultViewpoint(var/mob/currentMob)
for(var/obj/cult_viewpoint/currentView in currentMob)
return currentView
return FALSE
#undef FAVOR_PLEASED
#undef FAVOR_INDIFFERENT
#undef FAVOR_DISPLEASED

View File

@@ -134,59 +134,7 @@
. = O
del(src)
/mob/living/carbon/human/make_into_mask(var/should_gib = 0)
for(var/t in organs)
del(t)
return ..(should_gib)
/mob/proc/make_into_mask(var/should_gib = 0, var/should_remove_items = 0)
if(!should_gib)
icon = null
invisibility = 101
if(!should_remove_items)
for(var/obj/item/W in src)
drop_from_inventory(W)
var/mob/spirit/mask/new_spirit = new()
if(mind)
new_spirit.mind = mind
new_spirit.mind.assigned_role = "Mask"
new_spirit.mind.original = new_spirit
new_spirit.key = key
new_spirit.loc=loc
if (should_gib)
spawn(0)
src.gib() // gib the body
else
spawn(0)//To prevent the proc from returning null.
src.visible_message( \
"[src] disappears into the shadows, never to be seen again.", \
"You disappear into the shadows, never to be seen again.", \
"You hear strange noise, you can't quite place it.")
del(src)
new_spirit << "<font color=\"purple\"><b><i>You are a Mask of Nar'sie now. You are a tiny fragment of the unknowable entity that is the god.</b></i></font>"
new_spirit << "<font color=\"purple\"><b><i>Your job is to help your acolytes complete their goals. Be spooky. Do evil.</b></i></font>"
new_spirit.set_name()
// let spirits identify cultists
if(ticker.mode)
ticker.mode.reset_cult_icons_for_spirit(new_spirit)
// highlander test
there_can_be_only_one_mask(new_spirit)
return new_spirit
//human -> robot
/mob/living/carbon/human/proc/Robotize()
if (monkeyizing)