diff --git a/baystation12.dme b/baystation12.dme index 722e05dfe7..1088ce6c88 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -155,6 +155,11 @@ #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\update_triggers.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" @@ -956,6 +961,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" @@ -1024,6 +1030,12 @@ #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\mob\spirit\viewpoint.dm" +#include "code\modules\mob\spirit\mask\mask.dm" +#include "code\modules\mob\spirit\mask\respawn.dm" #include "code\modules\nano\_JSON.dm" #include "code\modules\nano\JSON Reader.dm" #include "code\modules\nano\JSON Writer.dm" diff --git a/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm b/code/WorkInProgress/AI_Visibility/_old_AI_Visibility.dm index 9b50c74f68..831d20f229 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 7dcbf54e67..a8c5470036 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 3b46844e6b..d234142511 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 8a6886a1ad..134d6097b5 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 c97b01e0f8..e4d4f7274f 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 da576cbd40..0e32f8dec8 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/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index ce8d788f25..b0d609c78e 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -7,6 +7,7 @@ var/list/directory = list() //list of all ckeys with associated client var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player var/global/list/mob_list = list() //List of all mobs, including clientless +var/global/list/spirits = list() //List of all the spirits, including Masks var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 3faa6e4c80..1b8324ef43 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -28,7 +28,7 @@ return -/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply Shuttle","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller")) +/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply Shuttle","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller","CultNetwork")) set category = "Debug" set name = "Debug Controller" set desc = "Debug the various periodic loop controllers for the game (be careful!)" @@ -72,10 +72,14 @@ debug_variables(paiController) feedback_add_details("admin_verb","DpAI") if("Cameras") - debug_variables(cameranet) + debug_variables(cameraNetwork) feedback_add_details("admin_verb","DCameras") if("Transfer Controller") debug_variables(transfer_controller) feedback_add_details("admin_verb","DAutovoter") + if("CultNetwork") + debug_variables(cultNetwork) + feedback_add_details("admin_verb","DCultNetwork") + message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") return diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index dc3a3b36db..7c1dbb0f8c 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -263,6 +263,7 @@ client body += "" body += "" body += "" + body += "" body += "" body += "" body += "" @@ -724,7 +725,18 @@ client usr << "Mob doesn't exist anymore" return holder.Topic(href, list("makeai"=href_list["makeai"])) - + + + else if(href_list["makemask"]) + if(!check_rights(R_SPAWN)) return + var/mob/currentMob = locate(href_list["makemask"]) + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return + if(!currentMob) + usr << "Mob doesn't exist anymore" + return + holder.Topic(href, list("makemask"=href_list["makemask"])) + + else if(href_list["setmutantrace"]) if(!check_rights(R_SPAWN)) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 7adc6a9679..01f68d3ac0 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -578,25 +578,14 @@ datum/mind switch(href_list["cult"]) if("clear") if(src in ticker.mode.cult) - ticker.mode.cult -= src - ticker.mode.update_cult_icons_removed(src) - special_role = null - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memoize_cult_objectives(src) - current << "\red You have been brainwashed! You are no longer a cultist!" - memory = "" + ticker.mode.remove_cultist(src) log_admin("[key_name_admin(usr)] has de-cult'ed [current].") if("cultist") if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) + ticker.mode.add_cultist(src) special_role = "Cultist" current << "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." current << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memoize_cult_objectives(src) log_admin("[key_name_admin(usr)] has cult'ed [current].") if("tome") var/mob/living/carbon/human/H = current diff --git a/code/datums/visibility_networks/chunk.dm b/code/datums/visibility_networks/chunk.dm new file mode 100644 index 0000000000..4abc1340b0 --- /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 0000000000..3dcb1bc427 --- /dev/null +++ b/code/datums/visibility_networks/dictionary.dm @@ -0,0 +1,11 @@ +var/datum/visibility_network/cameras/cameraNetwork = new() +var/datum/visibility_network/cult/cultNetwork = new() +var/datum/visibility_network/list/visibility_networks = list("ALL_CAMERAS"=cameraNetwork, "CULT" = cultNetwork) + + +// used by turfs and objects to update all visibility networks +/proc/updateVisibilityNetworks(atom/A, var/opacity_check = 1) + var/datum/visibility_network/currentNetwork + for (var/networkName in visibility_networks) + currentNetwork = visibility_networks[networkName] + currentNetwork.updateVisibility(A, opacity_check) \ No newline at end of file diff --git a/code/datums/visibility_networks/update_triggers.dm b/code/datums/visibility_networks/update_triggers.dm new file mode 100644 index 0000000000..f1835eeeb5 --- /dev/null +++ b/code/datums/visibility_networks/update_triggers.dm @@ -0,0 +1,94 @@ +//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. + +// TURFS + +/turf + var/image/obscured + +/turf/proc/visibilityChanged() + if(ticker) + updateVisibilityNetworks(src) + +/turf/simulated/Del() + visibilityChanged() + ..() + +/turf/simulated/New() + ..() + visibilityChanged() + + + +// STRUCTURES + +/obj/structure/Del() + if(ticker) + updateVisibilityNetworks(src) + ..() + +/obj/structure/New() + ..() + if(ticker) + updateVisibilityNetworks(src) + +// EFFECTS + +/obj/effect/Del() + if(ticker) + updateVisibilityNetworks(src) + ..() + +/obj/effect/New() + ..() + if(ticker) + updateVisibilityNetworks(src) + + +// DOORS + +// Simply updates the visibility of the area when it opens/closes/destroyed. +/obj/machinery/door/proc/update_nearby_tiles(need_rebuild) + + if(!glass) + updateVisibilityNetworks(src,0) + + if(!air_master) + return 0 + + for(var/turf/simulated/turf in locs) + update_heat_protection(turf) + air_master.AddTurfToUpdate(turf) + + return 1 + + + +#define UPDATE_VISIBILITY_NETWORK_BUFFER 30 + +/mob + var/datum/visibility_network/list/visibilityNetworks=list() + var/updatingVisibilityNetworks=FALSE + +/mob/Move(n,direct) + var/oldLoc = src.loc + . = ..() + if(.) + if(src.visibilityNetworks.len) + if(!src.updatingVisibilityNetworks) + src.updatingVisibilityNetworks = 1 + spawn(UPDATE_VISIBILITY_NETWORK_BUFFER) + if(oldLoc != src.loc) + for (var/datum/visibility_network/currentNetwork in src.visibilityNetworks) + currentNetwork.updateMob(src) + src.updatingVisibilityNetworks = 0 + return ..(n,direct) + +/mob/proc/addToVisibilityNetwork(var/datum/visibility_network/network) + if(network) + src.visibilityNetworks+=network + +/mob/proc/removeFromVisibilityNetwork(var/datum/visibility_network/network) + if(network) + src.visibilityNetworks|=network + +#undef UPDATE_VISIBILITY_NETWORK_BUFFER \ 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 0000000000..7d8efba41d --- /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 0000000000..225b6e3def --- /dev/null +++ b/code/datums/visibility_networks/visibility_network.dm @@ -0,0 +1,141 @@ +/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/datum/visibility_chunk/chunk in remove) + chunk.remove(targetMob) + + for(var/datum/visibility_chunk/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/getViewpointFromMob(var/mob/currentMob) + return FALSE + +/datum/visibility_network/proc/updateMob(var/mob/currentMob) + var/viewpoint = getViewpointFromMob(currentMob) + if(viewpoint) + updateViewpoint(viewpoint) + + +/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 + + 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 b84388f583..36e5100750 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/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index ee16e21a77..e0e81a647e 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -8,6 +8,7 @@ /proc/iscultist(mob/living/M as mob) return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) + /proc/is_convertable_to_cult(datum/mind/mind) if(!istype(mind)) return 0 if(istype(mind.current, /mob/living/carbon/human) && (mind.assigned_role in list("Captain", "Chaplain"))) return 0 @@ -133,7 +134,8 @@ mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." mob.mutations.Remove(CLUMSY) - + add_cult_viewpoint(mob) // give them a viewpoint + var/obj/item/weapon/paper/talisman/supply/T = new(mob) var/list/slots = list ( "backpack" = slot_in_backpack, @@ -169,11 +171,20 @@ cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0) +/datum/game_mode/proc/add_cult_viewpoint(var/mob/target) + for(var/obj/cult_viewpoint/viewpoint in target) + return + var/obj/cult_viewpoint/viewpoint = new(target) + viewpoint.loc = target + return viewpoint + + /datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE if (!istype(cult_mind)) return 0 if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) cult += cult_mind + add_cult_viewpoint(cult_mind.current) update_cult_icons_added(cult_mind) return 1 @@ -189,57 +200,133 @@ cult -= cult_mind cult_mind.current << "\red An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it." cult_mind.memory = "" + + // remove the cult viewpoint object + var/obj/viewpoint = getCultViewpoint(cult_mind.current) + del(viewpoint) + update_cult_icons_removed(cult_mind) if(show_message) for(var/mob/M in viewers(cult_mind.current)) M << "[cult_mind.current] looks like they just reverted to their old faith!" + /datum/game_mode/proc/update_all_cult_icons() spawn(0) + // reset the cult + for(var/datum/mind/cultist in cult) + reset_cult_icons_for_cultist(cultist) + // reset the spirits + for(var/mob/spirit/currentSpirit in spirits) + reset_cult_icons_for_spirit(currentSpirit) + + +/datum/game_mode/proc/reset_cult_icons_for_cultist(var/datum/mind/target) + if(target.current) + if(target.current.client) + remove_all_cult_icons(target) + for(var/datum/mind/cultist in cult) + if(cultist.current) + add_cult_icon(target.current.client,cultist.current) + + +/datum/game_mode/proc/reset_cult_icons_for_spirit(mob/spirit/target) + if (target.client) + remove_all_cult_icons(target) for(var/datum/mind/cultist in cult) if(cultist.current) - if(cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult") - del(I) + add_cult_icon(target.client,cultist.current) + + +/datum/game_mode/proc/add_cult_icon(client/target_client,mob/target_mob) + var/I = image('icons/mob/mob.dmi', loc = target_mob, icon_state = "cult") + target_client.images += I - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/datum/mind/cultist_1 in cult) - if(cultist_1.current) - var/I = image('icons/mob/mob.dmi', loc = cultist_1.current, icon_state = "cult") - cultist.current.client.images += I + +/datum/game_mode/proc/remove_cult_icon(client/target_client,mob/target_mob) + for(var/image/I in target_client.images) + if(I.icon_state == "cult" && I.loc == target_mob) + del(I) + + +/datum/game_mode/proc/remove_all_cult_icons_from_client(client/target) + for(var/image/I in target.images) + if(I.icon_state == "cult") + del(I) + + +/datum/game_mode/proc/remove_all_cult_icons(target) + var/datum/mind/cultist = target + if(istype(cultist)) + if(cultist.current) + if(cultist.current.client) + remove_all_cult_icons_from_client(cultist.current.client) + return TRUE + var/mob/spirit/currentSpirit = target + if(istype(currentSpirit)) + if (currentSpirit.client) + remove_all_cult_icons_from_client(currentSpirit.client) + return TRUE + return FALSE + + +/datum/game_mode/proc/add_cult_icon_to_spirit(mob/spirit/currentSpirit,datum/mind/cultist) + if(!istype(currentSpirit) || !istype(cultist)) + return FALSE + if (currentSpirit.client) + if (cultist.current) + add_cult_icon(currentSpirit.client,cultist.current) + + +/datum/game_mode/proc/add_cult_icon_to_cultist(datum/mind/first_cultist,datum/mind/second_cultist) + if(first_cultist.current && second_cultist.current) + if(first_cultist.current.client) + add_cult_icon(first_cultist.current.client, second_cultist.current) + + +/datum/game_mode/proc/remove_cult_icon_from_cultist(datum/mind/first_cultist,datum/mind/second_cultist) + if(first_cultist.current && second_cultist.current) + if(first_cultist.current.client) + remove_cult_icon(first_cultist.current.client,second_cultist.current) + +/datum/game_mode/proc/remove_cult_icon_from_spirit(mob/spirit/currentSpirit,datum/mind/cultist) + if(!istype(currentSpirit) || !istype(cultist)) + return FALSE + if (currentSpirit.client) + if (cultist.current) + remove_cult_icon(currentSpirit.client,cultist.current) + + +/datum/game_mode/proc/cult_icon_pair_link(datum/mind/first_cultist,datum/mind/second_cultist) + if (!istype(first_cultist) || !istype(second_cultist)) + return 0 + add_cult_icon_to_cultist(first_cultist,second_cultist) + add_cult_icon_to_cultist(second_cultist,first_cultist) + +/datum/game_mode/proc/cult_icon_pair_unlink(datum/mind/first_cultist,datum/mind/second_cultist) + if (!istype(first_cultist) || !istype(second_cultist)) + return 0 + remove_cult_icon(first_cultist,second_cultist) + remove_cult_icon(second_cultist,first_cultist) + + /datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) spawn(0) for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - var/I = image('icons/mob/mob.dmi', loc = cult_mind.current, icon_state = "cult") - cultist.current.client.images += I - if(cult_mind.current) - if(cult_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = cultist.current, icon_state = "cult") - cult_mind.current.client.images += J - - + cult_icon_pair_link(cultist,cult_mind) + for(var/mob/spirit/currentSpirit in spirits) + add_cult_icon_to_spirit(currentSpirit,cult_mind) + + /datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) spawn(0) for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult" && I.loc == cult_mind.current) - del(I) - - if(cult_mind.current) - if(cult_mind.current.client) - for(var/image/I in cult_mind.current.client.images) - if(I.icon_state == "cult") - del(I) - + cult_icon_pair_unlink(cultist,cult_mind) + for(var/mob/spirit/currentSpirit in spirits) + remove_cult_icon_from_spirit(currentSpirit,cult_mind) + /datum/game_mode/cult/proc/get_unconvertables() var/list/ucs = list() @@ -275,6 +362,10 @@ return 1 +/atom/proc/cult_log(var/message) + investigate_log(message, "cult") + + /datum/game_mode/cult/declare_completion() if(!check_cult_victory()) diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 2d408a1a4f..2760a66d49 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -1,6 +1,7 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 var/cultwords = list() +var/rune_to_english = list() var/runedec = 0 var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide") @@ -16,19 +17,22 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", /proc/runerandom() //randomizes word meaning var/list/runewords=list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") ///"orkan" and "allaq" removed. for (var/word in engwords) - cultwords[word] = pick(runewords) + var/runeword = pick(runewords) + cultwords[word] = runeword + rune_to_english[runeword] = word runewords-=cultwords[word] + /obj/effect/rune desc = "" anchored = 1 icon = 'icons/obj/rune.dmi' icon_state = "1" var/visibility = 0 + var/view_range = 7 unacidable = 1 layer = TURF_LAYER - var/word1 var/word2 var/word3 @@ -61,122 +65,112 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", // self other technology - Communication rune //was other hear blood // join hide technology - stun rune. Rune color: bright pink. - New() - ..() - var/image/blood = image(loc = src) - blood.override = 1 - for(var/mob/living/silicon/ai/AI in player_list) - AI.client.images += blood - examine() - set src in view(2) +/obj/effect/rune/New() + ..() + var/image/blood = image(loc = src) + blood.override = 1 + for(var/mob/living/silicon/ai/AI in player_list) + AI.client.images += blood + cultNetwork.viewpoints+=src + cultNetwork.addViewpoint(src) - if(!iscultist(usr)) - usr << "A strange collection of symbols drawn in blood." - return - /* Explosions... really? - if(desc && !usr.stat) - usr << "It reads: [desc]." - sleep(30) - explosion(src.loc, 0, 2, 5, 5) - if(src) - del(src) - */ - if(!desc) - usr << "A spell circle drawn in blood. It reads: [word1] [word2] [word3]." - else - usr << "Explosive Runes inscription in blood. It reads: [desc]." +/obj/effect/rune/Del() + ..() + cultNetwork.viewpoints-=src + cultNetwork.removeViewpoint(src) +/obj/effect/rune/examine() + set src in view(2) + + if(!iscultist(usr) && !isSpirit(usr)) + usr << "A strange collection of symbols drawn in blood." return + if(!desc) + usr << "A spell circle drawn in blood. It reads: [word1] [word2] [word3]." + else + usr << "Explosive Runes inscription in blood. It reads: [desc]." + + return - attackby(I as obj, user as mob) - if(istype(I, /obj/item/weapon/tome) && iscultist(user)) - user << "You retrace your steps, carefully undoing the lines of the rune." - del(src) - return - else if(istype(I, /obj/item/weapon/nullrod)) - user << "\blue You disrupt the vile magic with the deadening field of the null rod!" - del(src) - return +/obj/effect/rune/attackby(I as obj, user as mob) + if(istype(I, /obj/item/weapon/tome) && iscultist(user)) + user << "You retrace your steps, carefully undoing the lines of the rune." + del(src) return + else if(istype(I, /obj/item/weapon/nullrod)) + user << "\blue You disrupt the vile magic with the deadening field of the null rod!" + del(src) + return + return - attack_hand(mob/living/user as mob) - if(!iscultist(user)) - user << "You can't mouth the arcane scratchings without fumbling over them." - return - if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) - user << "You are unable to speak the words of the rune." - return - if(!word1 || !word2 || !word3 || prob(user.getBrainLoss())) - return fizzle() -// if(!src.visibility) -// src.visibility=1 - if(word1 == cultwords["travel"] && word2 == cultwords["self"]) - return teleport(src.word3) - if(word1 == cultwords["see"] && word2 == cultwords["blood"] && word3 == cultwords["hell"]) - return tomesummon() - if(word1 == cultwords["hell"] && word2 == cultwords["destroy"] && word3 == cultwords["other"]) - return armor() - if(word1 == cultwords["join"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) - return convert() - if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) - return tearreality() - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) - return emp(src.loc,3) - if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) - return drain() - if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) - return seer() - if(word1 == cultwords["blood"] && word2 == cultwords["join"] && word3 == cultwords["hell"]) - return raise() - if(word1 == cultwords["hide"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) - return obscure(4) - if(word1 == cultwords["hell"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) - return ajourney() - if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["travel"]) - return manifest() - if(word1 == cultwords["hell"] && word2 == cultwords["technology"] && word3 == cultwords["join"]) - return talisman() - if(word1 == cultwords["hell"] && word2 == cultwords["blood"] && word3 == cultwords["join"]) - return sacrifice() - if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["hide"]) - return revealrunes(src) - if(word1 == cultwords["destroy"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) - return wall() - if(word1 == cultwords["travel"] && word2 == cultwords["technology"] && word3 == cultwords["other"]) - return freedom() - if(word1 == cultwords["join"] && word2 == cultwords["other"] && word3 == cultwords["self"]) - return cultsummon() - if(word1 == cultwords["hide"] && word2 == cultwords["other"] && word3 == cultwords["see"]) - return deafen() - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["other"]) - return blind() - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) - return bloodboil() - if(word1 == cultwords["self"] && word2 == cultwords["other"] && word3 == cultwords["technology"]) - return communicate() - if(word1 == cultwords["travel"] && word2 == cultwords["other"]) - return itemport(src.word3) - if(word1 == cultwords["join"] && word2 == cultwords["hide"] && word3 == cultwords["technology"]) - return runestun() - else - return fizzle() +/obj/effect/rune/proc/get_word_string() + if (word1 == cultwords["travel"]) + if (word2 == cultwords["self"]) + return "teleport" + if (word2 == cultwords["other"]) + return "itemport" + return "[rune_to_english[word1]]_[rune_to_english[word2]]_[rune_to_english[word3]]" + + +/obj/effect/rune + var/list/effect_dictionary = list( "teleport"=/obj/effect/rune/proc/teleportRune, + "itemport"=/obj/effect/rune/proc/itemportRune, + "see_blood_hell"=/obj/effect/rune/proc/tomesummon, + "hell_destroy_other"=/obj/effect/rune/proc/armor, + "join_blood_self"=/obj/effect/rune/proc/convert, + "hell_join_self"=/obj/effect/rune/proc/tearreality, + "destroy_see_technology"=/obj/effect/rune/proc/empRune, + "travel_blood_self"=/obj/effect/rune/proc/drain, + "see_hell_join"=/obj/effect/rune/proc/seer, + "blood_join_hell"=/obj/effect/rune/proc/raise, + "hide_see_blood"=/obj/effect/rune/proc/obscureRune, + "hell_travel_self"=/obj/effect/rune/proc/ajourney, + "blood_see_travel"=/obj/effect/rune/proc/manifest, + "hell_technology_join"=/obj/effect/rune/proc/talisman, + "hell_blood_join"=/obj/effect/rune/proc/sacrifice, + "blood_see_hide"=/obj/effect/rune/proc/revealrunesrune, + "destroy_travel_self"=/obj/effect/rune/proc/wall, + "travel_technology_other"=/obj/effect/rune/proc/freedom, + "join_other_self"=/obj/effect/rune/proc/cultsummon, + "hide_other_see"=/obj/effect/rune/proc/deafen, + "destroy_see_other"=/obj/effect/rune/proc/blind, + "destroy_see_blood"=/obj/effect/rune/proc/bloodboil, + "self_other_technology"=/obj/effect/rune/proc/communicate, + "join_hide_technology"=/obj/effect/rune/proc/runestun ) + +/obj/effect/rune/attack_hand(mob/living/user as mob) + if(!iscultist(user)) + user << "You can't mouth the arcane scratchings without fumbling over them." + return + if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) + user << "You are unable to speak the words of the rune." + return + if(user.silent) // checking if we've been muted somehow + user << "You are unable to speak at all! You cannot say the words of the rune." + if(!word1 || !word2 || !word3 || prob(user.getBrainLoss())) + return fizzle() + + var/word_string = get_word_string() + if (word_string in effect_dictionary) + cult_log("of type [effect_dictionary[word_string]] activated by [key_name_admin(user)].") + return call(src,effect_dictionary[word_string])() + return fizzle() - proc - fizzle() - if(istype(src,/obj/effect/rune)) - usr.say(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) - else - usr.whisper(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) - for (var/mob/V in viewers(src)) - V.show_message("\red The markings pulse with a small burst of light, then fall dark.", 3, "\red You hear a faint fizzle.", 2) - return +/obj/effect/rune/proc/fizzle() + if(istype(src,/obj/effect/rune)) + usr.say(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) + else + usr.whisper(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) + for (var/mob/V in viewers(src)) + V.show_message("\red The markings pulse with a small burst of light, then fall dark.", 3, "\red You hear a faint fizzle.", 2) + return - check_icon() - icon = get_uristrune_cult(word1, word2, word3) +/obj/effect/rune/proc/check_icon() + icon = get_uristrune_cult(word1, word2, word3) /obj/item/weapon/tome name = "arcane tome" diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index e5be5d60a7..e7f1e2ff26 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -1,197 +1,205 @@ var/list/sacrificed = list() -/obj/effect/rune + /////////////////////////////////////////FIRST RUNE - proc - teleport(var/key) - var/mob/living/user = usr - var/allrunesloc[] - allrunesloc = new/list() - var/index = 0 - // var/tempnum = 0 - for(var/obj/effect/rune/R in world) - if(R == src) - continue - if(R.word1 == cultwords["travel"] && R.word2 == cultwords["self"] && R.word3 == key && R.z != 2) - index++ - allrunesloc.len = index - allrunesloc[index] = R.loc - if(index >= 5) - user << "\red You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" - if (istype(user, /mob/living)) - user.take_overall_damage(5, 0) - del(src) - if(allrunesloc && index != 0) - if(istype(src,/obj/effect/rune)) - user.say("Sas[pick("'","`")]so c'arta forbici!")//Only you can stop auto-muting - else - user.whisper("Sas[pick("'","`")]so c'arta forbici!") - user.visible_message("\red [user] disappears in a flash of red light!", \ - "\red You feel as your body gets dragged through the dimension of Nar-Sie!", \ - "\red You hear a sickening crunch and sloshing of viscera.") - user.loc = allrunesloc[rand(1,index)] - return - if(istype(src,/obj/effect/rune)) - return fizzle() //Use friggin manuals, Dorf, your list was of zero length. - else - call(/obj/effect/rune/proc/fizzle)() - return +/obj/effect/rune/proc/teleportRune() + return teleport(src.word3) + +/obj/effect/rune/proc/teleport(var/key) + var/mob/living/user = usr + var/allrunesloc[] + allrunesloc = new/list() + var/index = 0 +// var/tempnum = 0 + for(var/obj/effect/rune/R in world) + if(R == src) + continue + if(R.word1 == cultwords["travel"] && R.word2 == cultwords["self"] && R.word3 == key && R.z != 2) + index++ + allrunesloc.len = index + allrunesloc[index] = R.loc + if(index >= 5) + user << "\red You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" + if (istype(user, /mob/living)) + user.take_overall_damage(5, 0) + del(src) + if(allrunesloc && index != 0) + if(istype(src,/obj/effect/rune)) + user.say("Sas[pick("'","`")]so c'arta forbici!")//Only you can stop auto-muting + else + user.whisper("Sas[pick("'","`")]so c'arta forbici!") + user.visible_message("\red [user] disappears in a flash of red light!", \ + "\red You feel as your body gets dragged through the dimension of Nar-Sie!", \ + "\red You hear a sickening crunch and sloshing of viscera.") + user.loc = allrunesloc[rand(1,index)] + return + if(istype(src,/obj/effect/rune)) + return fizzle() //Use friggin manuals, Dorf, your list was of zero length. + else + call(/obj/effect/rune/proc/fizzle)() + return - - itemport(var/key) +/obj/effect/rune/proc/itemportRune() + return itemport(src.word3) +/obj/effect/rune/proc/itemport(var/key) // var/allrunesloc[] // allrunesloc = new/list() // var/index = 0 - // var/tempnum = 0 - var/culcount = 0 - var/runecount = 0 - var/obj/effect/rune/IP = null - var/mob/living/user = usr - for(var/obj/effect/rune/R in world) - if(R == src) - continue - if(R.word1 == cultwords["travel"] && R.word2 == cultwords["other"] && R.word3 == key) - IP = R - runecount++ - if(runecount >= 2) - user << "\red You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" - if (istype(user, /mob/living)) - user.take_overall_damage(5, 0) - del(src) - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - culcount++ - if(culcount>=3) - user.say("Sas[pick("'","`")]so c'arta forbici tarem!") - user.visible_message("\red You feel air moving from the rune - like as it was swapped with somewhere else.", \ - "\red You feel air moving from the rune - like as it was swapped with somewhere else.", \ - "\red You smell ozone.") - for(var/obj/O in src.loc) - if(!O.anchored) - O.loc = IP.loc - for(var/mob/M in src.loc) - M.loc = IP.loc - return +// var/tempnum = 0 + var/culcount = 0 + var/runecount = 0 + var/obj/effect/rune/IP = null + var/mob/living/user = usr + for(var/obj/effect/rune/R in world) + if(R == src) + continue + if(R.word1 == cultwords["travel"] && R.word2 == cultwords["other"] && R.word3 == key) + IP = R + runecount++ + if(runecount >= 2) + user << "\red You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric" + if (istype(user, /mob/living)) + user.take_overall_damage(5, 0) + del(src) + for(var/mob/living/carbon/C in orange(1,src)) + if(iscultist(C) && !C.stat) + culcount++ + if(culcount>=3) + user.say("Sas[pick("'","`")]so c'arta forbici tarem!") + user.visible_message("\red You feel air moving from the rune - like as it was swapped with somewhere else.", \ + "\red You feel air moving from the rune - like as it was swapped with somewhere else.", \ + "\red You smell ozone.") + for(var/obj/O in src.loc) + if(!O.anchored) + O.loc = IP.loc + for(var/mob/M in src.loc) + M.loc = IP.loc + return - return fizzle() + return fizzle() /////////////////////////////////////////SECOND RUNE - tomesummon() - if(istype(src,/obj/effect/rune)) - usr.say("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") - else - usr.whisper("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") - usr.visible_message("\red Rune disappears with a flash of red light, and in its place now a book lies.", \ - "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ - "\red You hear a pop and smell ozone.") - if(istype(src,/obj/effect/rune)) - new /obj/item/weapon/tome(src.loc) - else - new /obj/item/weapon/tome(usr.loc) - del(src) - return +/obj/effect/rune/proc/tomesummon() + if(istype(src,/obj/effect/rune)) + usr.say("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") + else + usr.whisper("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") + usr.visible_message("\red Rune disappears with a flash of red light, and in its place now a book lies.", \ + "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ + "\red You hear a pop and smell ozone.") + if(istype(src,/obj/effect/rune)) + new /obj/item/weapon/tome(src.loc) + else + new /obj/item/weapon/tome(usr.loc) + del(src) + return /////////////////////////////////////////THIRD RUNE - convert() - for(var/mob/living/carbon/M in src.loc) - if(iscultist(M)) - continue - if(M.stat==2) - continue - usr.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!") - M.visible_message("\red [M] writhes in pain as the markings below him glow a bloody red.", \ - "\red AAAAAAHHHH!.", \ - "\red You hear an anguished scream.") - if(is_convertable_to_cult(M.mind) && !jobban_isbanned(M, "cultist"))//putting jobban check here because is_convertable uses mind as argument - ticker.mode.add_cultist(M.mind) - M.mind.special_role = "Cultist" - M << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." - M << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - return 1 - else - M << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." - M << "And you were able to force it out of your mind. You now know the truth, there's something horrible out there, stop it and its minions at all costs." - return 0 +/obj/effect/rune/proc/convert() + for(var/mob/living/carbon/M in src.loc) + if(iscultist(M)) + continue + if(M.stat==2) + continue + usr.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!") + M.visible_message("\red [M] writhes in pain as the markings below him glow a bloody red.", \ + "\red AAAAAAHHHH!.", \ + "\red You hear an anguished scream.") + cult_log("[key_name_admin(usr)] tried to convert [key_name_admin(M)]") + if(is_convertable_to_cult(M.mind) && !jobban_isbanned(M, "cultist"))//putting jobban check here because is_convertable uses mind as argument + ticker.mode.add_cultist(M.mind) + M.mind.special_role = "Cultist" + M << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." + M << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." + return 1 + else + M << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." + M << "And you were able to force it out of your mind. You now know the truth, there's something horrible out there, stop it and its minions at all costs." + return 0 - return fizzle() + return fizzle() /////////////////////////////////////////FOURTH RUNE - tearreality() - var/cultist_count = 0 - for(var/mob/M in range(1,src)) - if(iscultist(M) && !M.stat) - M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!") - cultist_count += 1 - if(cultist_count >= 9) - new /obj/machinery/singularity/narsie/large(src.loc) - if(ticker.mode.name == "cult") - ticker.mode:eldergod = 0 - return - else - return fizzle() +/obj/effect/rune/proc/tearreality() + var/cultist_count = 0 + for(var/mob/M in range(1,src)) + if(iscultist(M) && !M.stat) + M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!") + cultist_count += 1 + if(cultist_count >= 9) + cult_log("THE CULT HAS SUMMONED NAR'SIE. GGNORE") + new /obj/machinery/singularity/narsie/large(src.loc) + if(ticker.mode.name == "cult") + ticker.mode:eldergod = 0 + return + else + return fizzle() /////////////////////////////////////////FIFTH RUNE - - emp(var/U,var/range_red) //range_red - var which determines by which number to reduce the default emp range, U is the source loc, needed because of talisman emps which are held in hand at the moment of using and that apparently messes things up -- Urist - if(istype(src,/obj/effect/rune)) - usr.say("Ta'gh fara[pick("'","`")]qha fel d'amar det!") - else - usr.whisper("Ta'gh fara[pick("'","`")]qha fel d'amar det!") - playsound(U, 'sound/items/Welder2.ogg', 25, 1) - var/turf/T = get_turf(U) - if(T) - T.hotspot_expose(700,125) - var/rune = src // detaching the proc - in theory - empulse(U, (range_red - 2), range_red) - del(rune) - return +/obj/effect/rune/proc/empRune() + emp(src.loc,3) + +/obj/effect/rune/proc/emp(var/U,var/range_red) //range_red - var which determines by which number to reduce the default emp range, U is the source loc, needed because of talisman emps which are held in hand at the moment of using and that apparently messes things up -- Urist + if(istype(src,/obj/effect/rune)) + usr.say("Ta'gh fara[pick("'","`")]qha fel d'amar det!") + else + usr.whisper("Ta'gh fara[pick("'","`")]qha fel d'amar det!") + playsound(U, 'sound/items/Welder2.ogg', 25, 1) + var/turf/T = get_turf(U) + if(T) + T.hotspot_expose(700,125) + var/rune = src // detaching the proc - in theory + empulse(U, (range_red - 2), range_red) + del(rune) + return /////////////////////////////////////////SIXTH RUNE - drain() - var/drain = 0 - for(var/obj/effect/rune/R in world) - if(R.word1==cultwords["travel"] && R.word2==cultwords["blood"] && R.word3==cultwords["self"]) - for(var/mob/living/carbon/D in R.loc) - if(D.stat!=2) - var/bdrain = rand(1,25) - D << "\red You feel weakened." - D.take_overall_damage(bdrain, 0) - drain += bdrain - if(!drain) - return fizzle() - usr.say ("Yu[pick("'","`")]gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!") - usr.visible_message("\red Blood flows from the rune into [usr]!", \ - "\red The blood starts flowing from the rune and into your frail mortal body. You feel... empowered.", \ - "\red You hear a liquid flowing.") - var/mob/living/user = usr - if(user.bhunger) - user.bhunger = max(user.bhunger-2*drain,0) - if(drain>=50) - user.visible_message("\red [user]'s eyes give off eerie red glow!", \ - "\red ...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \ - "\red You hear a heartbeat.") - user.bhunger += drain - src = user - spawn() - for (,user.bhunger>0,user.bhunger--) - sleep(50) - user.take_overall_damage(3, 0) - return - user.heal_organ_damage(drain%5, 0) - drain-=drain%5 - for (,drain>0,drain-=5) - sleep(2) - user.heal_organ_damage(5, 0) - return +/obj/effect/rune/proc/drain() + var/drain = 0 + for(var/obj/effect/rune/R in world) + if(R.word1==cultwords["travel"] && R.word2==cultwords["blood"] && R.word3==cultwords["self"]) + for(var/mob/living/carbon/D in R.loc) + if(D.stat!=2) + cult_log("[key_name_admin(usr)] has drained blood from [key_name_admin(D)]") + var/bdrain = rand(1,25) + D << "\red You feel weakened." + D.take_overall_damage(bdrain, 0) + drain += bdrain + if(!drain) + return fizzle() + usr.say ("Yu[pick("'","`")]gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!") + usr.visible_message("\red Blood flows from the rune into [usr]!", \ + "\red The blood starts flowing from the rune and into your frail mortal body. You feel... empowered.", \ + "\red You hear a liquid flowing.") + var/mob/living/user = usr + if(user.bhunger) + user.bhunger = max(user.bhunger-2*drain,0) + if(drain>=50) + user.visible_message("\red [user]'s eyes give off eerie red glow!", \ + "\red ...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \ + "\red You hear a heartbeat.") + user.bhunger += drain + src = user + spawn() + for (,user.bhunger>0,user.bhunger--) + sleep(50) + user.take_overall_damage(3, 0) + return + user.heal_organ_damage(drain%5, 0) + drain-=drain%5 + for (,drain>0,drain-=5) + sleep(2) + user.heal_organ_damage(5, 0) + return @@ -200,98 +208,98 @@ var/list/sacrificed = list() /////////////////////////////////////////SEVENTH RUNE - seer() - if(usr.loc==src.loc) - if(usr.seer==1) - usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium viortia.") - usr << "\red The world beyond fades from your vision." - usr.see_invisible = SEE_INVISIBLE_LIVING - usr.seer = 0 - else if(usr.see_invisible!=SEE_INVISIBLE_LIVING) - usr << "\red The world beyond flashes your eyes but disappears quickly, as if something is disrupting your vision." - usr.see_invisible = SEE_INVISIBLE_OBSERVER - usr.seer = 0 - else - usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium vivira. Itonis al'ra matum!") - usr << "\red The world beyond opens to your eyes." - usr.see_invisible = SEE_INVISIBLE_OBSERVER - usr.seer = 1 - return - return fizzle() +/obj/effect/rune/proc/seer() + if(usr.loc==src.loc) + if(usr.seer==1) + usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium viortia.") + usr << "\red The world beyond fades from your vision." + usr.see_invisible = SEE_INVISIBLE_LIVING + usr.seer = 0 + else if(usr.see_invisible!=SEE_INVISIBLE_LIVING) + usr << "\red The world beyond flashes your eyes but disappears quickly, as if something is disrupting your vision." + usr.see_invisible = SEE_INVISIBLE_OBSERVER + usr.seer = 0 + else + usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium vivira. Itonis al'ra matum!") + usr << "\red The world beyond opens to your eyes." + usr.see_invisible = SEE_INVISIBLE_OBSERVER + usr.seer = 1 + return + return fizzle() /////////////////////////////////////////EIGHTH RUNE - raise() - var/mob/living/carbon/human/corpse_to_raise - var/mob/living/carbon/human/body_to_sacrifice +/obj/effect/rune/proc/raise() + var/mob/living/carbon/human/corpse_to_raise + var/mob/living/carbon/human/body_to_sacrifice - var/is_sacrifice_target = 0 - for(var/mob/living/carbon/human/M in src.loc) - if(M.stat == DEAD) - if(ticker.mode.name == "cult" && M.mind == ticker.mode:sacrifice_target) + var/is_sacrifice_target = 0 + for(var/mob/living/carbon/human/M in src.loc) + if(M.stat == DEAD) + if(ticker.mode.name == "cult" && M.mind == ticker.mode:sacrifice_target) + is_sacrifice_target = 1 + else + corpse_to_raise = M + if(M.key) + M.ghostize(1) //kick them out of their body + break + if(!corpse_to_raise) + if(is_sacrifice_target) + usr << "\red The Geometer of blood wants this mortal for himself." + return fizzle() + + + is_sacrifice_target = 0 + find_sacrifice: + for(var/obj/effect/rune/R in world) + if(R.word1==cultwords["blood"] && R.word2==cultwords["join"] && R.word3==cultwords["hell"]) + for(var/mob/living/carbon/human/N in R.loc) + if(ticker.mode.name == "cult" && N.mind && N.mind == ticker.mode:sacrifice_target) is_sacrifice_target = 1 else - corpse_to_raise = M - if(M.key) - M.ghostize(1) //kick them out of their body - break - if(!corpse_to_raise) - if(is_sacrifice_target) - usr << "\red The Geometer of blood wants this mortal for himself." - return fizzle() + if(N.stat!= DEAD) + body_to_sacrifice = N + break find_sacrifice + if(!body_to_sacrifice) + if (is_sacrifice_target) + usr << "\red The Geometer of blood wants that corpse for himself." + else + usr << "\red The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used." + return fizzle() - is_sacrifice_target = 0 - find_sacrifice: - for(var/obj/effect/rune/R in world) - if(R.word1==cultwords["blood"] && R.word2==cultwords["join"] && R.word3==cultwords["hell"]) - for(var/mob/living/carbon/human/N in R.loc) - if(ticker.mode.name == "cult" && N.mind && N.mind == ticker.mode:sacrifice_target) - is_sacrifice_target = 1 - else - if(N.stat!= DEAD) - body_to_sacrifice = N - break find_sacrifice + var/mob/dead/observer/ghost + for(var/mob/dead/observer/O in loc) + if(!O.client) continue + if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue + ghost = O + break - if(!body_to_sacrifice) - if (is_sacrifice_target) - usr << "\red The Geometer of blood wants that corpse for himself." - else - usr << "\red The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used." - return fizzle() + if(!ghost) + usr << "\red You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie." + return fizzle() - var/mob/dead/observer/ghost - for(var/mob/dead/observer/O in loc) - if(!O.client) continue - if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue - ghost = O - break + corpse_to_raise.revive() - if(!ghost) - usr << "\red You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie." - return fizzle() - - corpse_to_raise.revive() - - corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed) - //This means, should that player leave the body, the original may re-enter - usr.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") - corpse_to_raise.visible_message("\red [corpse_to_raise]'s eyes glow with a faint red as he stands up, slowly starting to breathe again.", \ - "\red Life... I'm alive again...", \ - "\red You hear a faint, slightly familiar whisper.") - body_to_sacrifice.visible_message("\red [body_to_sacrifice] is torn apart, a black smoke swiftly dissipating from his remains!", \ - "\red You feel as your blood boils, tearing you apart.", \ - "\red You hear a thousand voices, all crying in pain.") - body_to_sacrifice.gib() + corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed) + //This means, should that player leave the body, the original may re-enter + usr.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") + corpse_to_raise.visible_message("\red [corpse_to_raise]'s eyes glow with a faint red as he stands up, slowly starting to breathe again.", \ + "\red Life... I'm alive again...", \ + "\red You hear a faint, slightly familiar whisper.") + body_to_sacrifice.visible_message("\red [body_to_sacrifice] is torn apart, a black smoke swiftly dissipating from his remains!", \ + "\red You feel as your blood boils, tearing you apart.", \ + "\red You hear a thousand voices, all crying in pain.") + body_to_sacrifice.gib() // if(ticker.mode.name == "cult") // ticker.mode:add_cultist(corpse_to_raise.mind) // else // ticker.mode.cult |= corpse_to_raise.mind - corpse_to_raise << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." - corpse_to_raise << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - return + corpse_to_raise << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." + corpse_to_raise << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." + return @@ -299,111 +307,113 @@ var/list/sacrificed = list() /////////////////////////////////////////NINETH RUNE - obscure(var/rad) - var/S=0 - for(var/obj/effect/rune/R in orange(rad,src)) - if(R!=src) - R.invisibility=INVISIBILITY_OBSERVER - S=1 - if(S) - if(istype(src,/obj/effect/rune)) - usr.say("Kla[pick("'","`")]atu barada nikt'o!") - for (var/mob/V in viewers(src)) - V.show_message("\red The rune turns into gray dust, veiling the surrounding runes.", 3) - del(src) - else - usr.whisper("Kla[pick("'","`")]atu barada nikt'o!") - usr << "\red Your talisman turns into gray dust, veiling the surrounding runes." - for (var/mob/V in orange(1,src)) - if(V!=usr) - V.show_message("\red Dust emanates from [usr]'s hands for a moment.", 3) +/obj/effect/rune/proc/obscureRune() + return obscure(4) +/obj/effect/rune/proc/obscure(var/rad) + var/S=0 + for(var/obj/effect/rune/R in orange(rad,src)) + if(R!=src) + R.invisibility=INVISIBILITY_OBSERVER + S=1 + if(S) + if(istype(src,/obj/effect/rune)) + usr.say("Kla[pick("'","`")]atu barada nikt'o!") + for (var/mob/V in viewers(src)) + V.show_message("\red The rune turns into gray dust, veiling the surrounding runes.", 3) + del(src) + else + usr.whisper("Kla[pick("'","`")]atu barada nikt'o!") + usr << "\red Your talisman turns into gray dust, veiling the surrounding runes." + for (var/mob/V in orange(1,src)) + if(V!=usr) + V.show_message("\red Dust emanates from [usr]'s hands for a moment.", 3) - return - if(istype(src,/obj/effect/rune)) - return fizzle() - else - call(/obj/effect/rune/proc/fizzle)() - return + return + if(istype(src,/obj/effect/rune)) + return fizzle() + else + call(/obj/effect/rune/proc/fizzle)() + return /////////////////////////////////////////TENTH RUNE - ajourney() //some bits copypastaed from admin tools - Urist - if(usr.loc==src.loc) - var/mob/living/carbon/human/L = usr - usr.say("Fwe[pick("'","`")]sh mah erl nyag r'ya!") - usr.visible_message("\red [usr]'s eyes glow blue as \he freezes in place, absolutely motionless.", \ - "\red The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \ - "\red You hear only complete silence for a moment.") - usr.ghostize(1) - L.ajourn = 1 - while(L) - if(L.key) - L.ajourn=0 - return - else - L.take_organ_damage(10, 0) - sleep(100) - return fizzle() +/obj/effect/rune/proc/ajourney() //some bits copypastaed from admin tools - Urist + if(usr.loc==src.loc) + var/mob/living/carbon/human/L = usr + usr.say("Fwe[pick("'","`")]sh mah erl nyag r'ya!") + usr.visible_message("\red [usr]'s eyes glow blue as \he freezes in place, absolutely motionless.", \ + "\red The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \ + "\red You hear only complete silence for a moment.") + usr.ghostize(1) + L.ajourn = 1 + while(L) + if(L.key) + L.ajourn=0 + return + else + L.take_organ_damage(10, 0) + sleep(100) + return fizzle() /////////////////////////////////////////ELEVENTH RUNE - manifest() - var/obj/effect/rune/this_rune = src - src = null - if(usr.loc!=this_rune.loc) - return this_rune.fizzle() - var/mob/dead/observer/ghost - for(var/mob/dead/observer/O in this_rune.loc) - if(!O.client) continue - if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue - ghost = O - break - if(!ghost) - return this_rune.fizzle() - if(jobban_isbanned(ghost, "cultist")) - return this_rune.fizzle() +/obj/effect/rune/proc/manifest() + var/obj/effect/rune/this_rune = src + src = null + if(usr.loc!=this_rune.loc) + return this_rune.fizzle() + var/mob/dead/observer/ghost + for(var/mob/dead/observer/O in this_rune.loc) + if(!O.client) continue + if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue + ghost = O + break + if(!ghost) + return this_rune.fizzle() + if(jobban_isbanned(ghost, "cultist")) + return this_rune.fizzle() - usr.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!") - var/mob/living/carbon/human/dummy/D = new(this_rune.loc) - usr.visible_message("\red A shape forms in the center of the rune. A shape of... a man.", \ - "\red A shape forms in the center of the rune. A shape of... a man.", \ - "\red You hear liquid flowing.") - D.real_name = "Unknown" - var/chose_name = 0 - for(var/obj/item/weapon/paper/P in this_rune.loc) - if(P.info) - D.real_name = copytext(P.info, findtext(P.info,">")+1, findtext(P.info,"<",2) ) - chose_name = 1 - break - if(!chose_name) - D.real_name = "[pick(first_names_male)] [pick(last_names)]" - D.universal_speak = 1 - D.status_flags &= ~GODMODE + usr.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!") + var/mob/living/carbon/human/dummy/D = new(this_rune.loc) + usr.visible_message("\red A shape forms in the center of the rune. A shape of... a man.", \ + "\red A shape forms in the center of the rune. A shape of... a man.", \ + "\red You hear liquid flowing.") + D.real_name = "Unknown" + var/chose_name = 0 + for(var/obj/item/weapon/paper/P in this_rune.loc) + if(P.info) + D.real_name = copytext(P.info, findtext(P.info,">")+1, findtext(P.info,"<",2) ) + chose_name = 1 + break + if(!chose_name) + D.real_name = "[pick(first_names_male)] [pick(last_names)]" + D.universal_speak = 1 + D.status_flags &= ~GODMODE - D.key = ghost.key + D.key = ghost.key - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(D.mind) - else - ticker.mode.cult+=D.mind + if(ticker.mode.name == "cult") + ticker.mode:add_cultist(D.mind) + else + ticker.mode.cult+=D.mind - D.mind.special_role = "Cultist" - D << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." - D << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." + D.mind.special_role = "Cultist" + D << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." + D << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - var/mob/living/user = usr - while(this_rune && user && user.stat==CONSCIOUS && user.client && user.loc==this_rune.loc) - user.take_organ_damage(1, 0) - sleep(30) - if(D) - D.visible_message("\red [D] slowly dissipates into dust and bones.", \ - "\red You feel pain, as bonds formed between your soul and this homunculus break.", \ - "\red You hear faint rustle.") - D.dust() - return + var/mob/living/user = usr + while(this_rune && user && user.stat==CONSCIOUS && user.client && user.loc==this_rune.loc) + user.take_organ_damage(1, 0) + sleep(30) + if(D) + D.visible_message("\red [D] slowly dissipates into dust and bones.", \ + "\red You feel pain, as bonds formed between your soul and this homunculus break.", \ + "\red You hear faint rustle.") + D.dust() + return @@ -411,629 +421,649 @@ var/list/sacrificed = list() /////////////////////////////////////////TWELFTH RUNE - talisman()//only hide, emp, teleport, deafen, blind and tome runes can be imbued atm - var/obj/item/weapon/paper/newtalisman - var/unsuitable_newtalisman = 0 - for(var/obj/item/weapon/paper/P in src.loc) - if(!P.info) - newtalisman = P - break - else - unsuitable_newtalisman = 1 - if (!newtalisman) - if (unsuitable_newtalisman) - usr << "\red The blank is tainted. It is unsuitable." - return fizzle() +/obj/effect/rune/proc/talisman()//only hide, emp, teleport, deafen, blind and tome runes can be imbued atm + var/obj/item/weapon/paper/newtalisman + var/unsuitable_newtalisman = 0 + for(var/obj/item/weapon/paper/P in src.loc) + if(!P.info) + newtalisman = P + break + else + unsuitable_newtalisman = 1 + if (!newtalisman) + if (unsuitable_newtalisman) + usr << "\red The blank is tainted. It is unsuitable." + return fizzle() - var/obj/effect/rune/imbued_from - var/obj/item/weapon/paper/talisman/T - for(var/obj/effect/rune/R in orange(1,src)) - if(R==src) - continue - if(R.word1==cultwords["travel"] && R.word2==cultwords["self"]) //teleport - T = new(src.loc) - T.imbue = "[R.word3]" - T.info = "[R.word3]" - imbued_from = R - break - if(R.word1==cultwords["see"] && R.word2==cultwords["blood"] && R.word3==cultwords["hell"]) //tome - T = new(src.loc) - T.imbue = "newtome" - imbued_from = R - break - if(R.word1==cultwords["destroy"] && R.word2==cultwords["see"] && R.word3==cultwords["technology"]) //emp - T = new(src.loc) - T.imbue = "emp" - imbued_from = R - break - if(R.word1==cultwords["blood"] && R.word2==cultwords["see"] && R.word3==cultwords["destroy"]) //conceal - T = new(src.loc) - T.imbue = "conceal" - imbued_from = R - break - if(R.word1==cultwords["hell"] && R.word2==cultwords["destroy"] && R.word3==cultwords["other"]) //armor - T = new(src.loc) - T.imbue = "armor" - imbued_from = R - break - if(R.word1==cultwords["blood"] && R.word2==cultwords["see"] && R.word3==cultwords["hide"]) //reveal - T = new(src.loc) - T.imbue = "revealrunes" - imbued_from = R - break - if(R.word1==cultwords["hide"] && R.word2==cultwords["other"] && R.word3==cultwords["see"]) //deafen - T = new(src.loc) - T.imbue = "deafen" - imbued_from = R - break - if(R.word1==cultwords["destroy"] && R.word2==cultwords["see"] && R.word3==cultwords["other"]) //blind - T = new(src.loc) - T.imbue = "blind" - imbued_from = R - break - if(R.word1==cultwords["self"] && R.word2==cultwords["other"] && R.word3==cultwords["technology"]) //communicat - T = new(src.loc) - T.imbue = "communicate" - imbued_from = R - break - if(R.word1==cultwords["join"] && R.word2==cultwords["hide"] && R.word3==cultwords["technology"]) //communicat - T = new(src.loc) - T.imbue = "runestun" - imbued_from = R - break - if (imbued_from) - for (var/mob/V in viewers(src)) - V.show_message("\red The runes turn into dust, which then forms into an arcane image on the paper.", 3) - usr.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!") - del(imbued_from) - del(newtalisman) - else - return fizzle() + var/obj/effect/rune/imbued_from + var/obj/item/weapon/paper/talisman/T + for(var/obj/effect/rune/R in orange(1,src)) + if(R==src) + continue + if(R.word1==cultwords["travel"] && R.word2==cultwords["self"]) //teleport + T = new(src.loc) + T.imbue = "[R.word3]" + T.info = "[R.word3]" + imbued_from = R + break + if(R.word1==cultwords["see"] && R.word2==cultwords["blood"] && R.word3==cultwords["hell"]) //tome + T = new(src.loc) + T.imbue = "newtome" + imbued_from = R + break + if(R.word1==cultwords["destroy"] && R.word2==cultwords["see"] && R.word3==cultwords["technology"]) //emp + T = new(src.loc) + T.imbue = "emp" + imbued_from = R + break + if(R.word1==cultwords["blood"] && R.word2==cultwords["see"] && R.word3==cultwords["destroy"]) //conceal + T = new(src.loc) + T.imbue = "conceal" + imbued_from = R + break + if(R.word1==cultwords["hell"] && R.word2==cultwords["destroy"] && R.word3==cultwords["other"]) //armor + T = new(src.loc) + T.imbue = "armor" + imbued_from = R + break + if(R.word1==cultwords["blood"] && R.word2==cultwords["see"] && R.word3==cultwords["hide"]) //reveal + T = new(src.loc) + T.imbue = "revealrunes" + imbued_from = R + break + if(R.word1==cultwords["hide"] && R.word2==cultwords["other"] && R.word3==cultwords["see"]) //deafen + T = new(src.loc) + T.imbue = "deafen" + imbued_from = R + break + if(R.word1==cultwords["destroy"] && R.word2==cultwords["see"] && R.word3==cultwords["other"]) //blind + T = new(src.loc) + T.imbue = "blind" + imbued_from = R + break + if(R.word1==cultwords["self"] && R.word2==cultwords["other"] && R.word3==cultwords["technology"]) //communicat + T = new(src.loc) + T.imbue = "communicate" + imbued_from = R + break + if(R.word1==cultwords["join"] && R.word2==cultwords["hide"] && R.word3==cultwords["technology"]) //communicat + T = new(src.loc) + T.imbue = "runestun" + imbued_from = R + break + if (imbued_from) + for (var/mob/V in viewers(src)) + V.show_message("\red The runes turn into dust, which then forms into an arcane image on the paper.", 3) + usr.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!") + del(imbued_from) + del(newtalisman) + else + return fizzle() /////////////////////////////////////////THIRTEENTH RUNE - mend() - var/mob/living/user = usr - src = null - user.say("Uhrast ka'hfa heldsagen ver[pick("'","`")]lot!") - user.take_overall_damage(200, 0) - runedec+=10 - user.visible_message("\red [user] keels over dead, his blood glowing blue as it escapes his body and dissipates into thin air.", \ - "\red In the last moment of your humble life, you feel an immense pain as fabric of reality mends... with your blood.", \ - "\red You hear faint rustle.") - for(,user.stat==2) - sleep(600) - if (!user) - return - runedec-=10 +/obj/effect/rune/proc/mend() + var/mob/living/user = usr + src = null + user.say("Uhrast ka'hfa heldsagen ver[pick("'","`")]lot!") + user.take_overall_damage(200, 0) + runedec+=10 + user.visible_message("\red [user] keels over dead, his blood glowing blue as it escapes his body and dissipates into thin air.", \ + "\red In the last moment of your humble life, you feel an immense pain as fabric of reality mends... with your blood.", \ + "\red You hear faint rustle.") + for(,user.stat==2) + sleep(600) + if (!user) return + runedec-=10 + return /////////////////////////////////////////FOURTEETH RUNE - // returns 0 if the rune is not used. returns 1 if the rune is used. - communicate() - . = 1 // Default output is 1. If the rune is deleted it will return 1 - var/input = stripped_input(usr, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "") - if(!input) - if (istype(src)) - fizzle() - return 0 - else - return 0 - if(istype(src,/obj/effect/rune)) - usr.say("O bidai nabora se[pick("'","`")]sma!") - else - usr.whisper("O bidai nabora se[pick("'","`")]sma!") +// returns 0 if the rune is not used. returns 1 if the rune is used. +/obj/effect/rune/proc/communicate() + . = 1 // Default output is 1. If the rune is deleted it will return 1 + var/input = stripped_input(usr, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "") + if(!input) + if (istype(src)) + fizzle() + return 0 + else + return 0 + + // record this + cult_log("[key_name(usr,0)] says : [input]") - if(istype(src,/obj/effect/rune)) - usr.say("[input]") - else - usr.whisper("[input]") - for(var/datum/mind/H in ticker.mode.cult) - if (H.current) - H.current << "\red \b [input]" - del(src) - return 1 + var/obj/cult_viewpoint/vp = getCultViewpoint(usr) + if (!vp) + return 0 + + var/displayName = vp.get_display_name() + var/cultName = vp.get_cult_name() + + if(istype(src,/obj/effect/rune)) + usr.say("O bidai nabora se[pick("'","`")]sma!") + else + usr.whisper("O bidai nabora se[pick("'","`")]sma!") + + if(istype(src,/obj/effect/rune)) + usr.say("[input]") + else + usr.whisper("[input]") + + for(var/datum/mind/H in ticker.mode.cult) + if (H.current) + H.current << "[cultName]: [input]" + + for(var/mob/spirit/spirit in spirits) + spirit << "[displayName]: [input]" + + del(src) + return 1 /////////////////////////////////////////FIFTEENTH RUNE - sacrifice() - var/list/mob/living/carbon/human/cultsinrange = list() - var/list/mob/living/carbon/human/victims = list() - for(var/mob/living/carbon/human/V in src.loc)//Checks for non-cultist humans to sacrifice - if(ishuman(V)) - if(!(iscultist(V))) - victims += V//Checks for cult status and mob type - for(var/obj/item/I in src.loc)//Checks for MMIs/brains/Intellicards - if(istype(I,/obj/item/brain)) - var/obj/item/brain/B = I - victims += B.brainmob - else if(istype(I,/obj/item/device/mmi)) - var/obj/item/device/mmi/B = I - victims += B.brainmob - else if(istype(I,/obj/item/device/aicard)) - for(var/mob/living/silicon/ai/A in I) - victims += A - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - cultsinrange += C - C.say("Barhah hra zar[pick("'","`")]garis!") - for(var/mob/H in victims) - if (ticker.mode.name == "cult") - if(H.mind == ticker.mode:sacrifice_target) - if(cultsinrange.len >= 3) - sacrificed += H.mind - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - usr << "\red The Geometer of Blood accepts this sacrifice, your objective is now complete." - else - usr << "\red Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual." +/obj/effect/rune/proc/sacrifice() + var/list/mob/living/carbon/human/cultsinrange = list() + var/list/mob/living/carbon/human/victims = list() + for(var/mob/living/carbon/human/V in src.loc)//Checks for non-cultist humans to sacrifice + if(ishuman(V)) + if(!(iscultist(V))) + victims += V//Checks for cult status and mob type + for(var/obj/item/I in src.loc)//Checks for MMIs/brains/Intellicards + if(istype(I,/obj/item/brain)) + var/obj/item/brain/B = I + victims += B.brainmob + else if(istype(I,/obj/item/device/mmi)) + var/obj/item/device/mmi/B = I + victims += B.brainmob + else if(istype(I,/obj/item/device/aicard)) + for(var/mob/living/silicon/ai/A in I) + victims += A + for(var/mob/living/carbon/C in orange(1,src)) + if(iscultist(C) && !C.stat) + cultsinrange += C + C.say("Barhah hra zar[pick("'","`")]garis!") + for(var/mob/H in victims) + if (ticker.mode.name == "cult") + if(H.mind == ticker.mode:sacrifice_target) + if(cultsinrange.len >= 3) + sacrificed += H.mind + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining else - if(cultsinrange.len >= 3) - if(H.stat !=2) - if(prob(80)) - usr << "\red The Geometer of Blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, this soul was not enough to gain His favor." - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(H.stat !=2) - usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." - else - if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() + H.gib() + usr << "\red The Geometer of Blood accepts this sacrifice, your objective is now complete." else - if(cultsinrange.len >= 3) - if(H.stat !=2) - if(prob(80)) - usr << "\red The Geometer of Blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, this soul was not enough to gain His favor." - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(H.stat !=2) - usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." - else - if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere dead body is not enough to satisfy Him." - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - for(var/mob/living/carbon/monkey/M in src.loc) - if (ticker.mode.name == "cult") - if(M.mind == ticker.mode:sacrifice_target) - if(cultsinrange.len >= 3) - sacrificed += M.mind - usr << "\red The Geometer of Blood accepts this sacrifice, your objective is now complete." - else - usr << "\red Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual." - continue - else - if(prob(20)) - usr << "\red The Geometer of Blood accepts your meager sacrifice." + usr << "\red Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual." + else + if(cultsinrange.len >= 3) + if(H.stat !=2) + if(prob(80)) + usr << "\red The Geometer of Blood accepts this sacrifice." ticker.mode:grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." - usr << "\red However, a mere monkey is not enough to satisfy Him." + usr << "\red However, this soul was not enough to gain His favor." + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining + else + H.gib() + else + if(prob(40)) + usr << "\red The Geometer of blood accepts this sacrifice." + ticker.mode:grant_runeword(usr) + else + usr << "\red The Geometer of blood accepts this sacrifice." + usr << "\red However, a mere dead body is not enough to satisfy Him." + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining + else + H.gib() else - usr << "\red The Geometer of Blood accepts your meager sacrifice." - if(prob(20)) - ticker.mode.grant_runeword(usr) - M.gib() -/* for(var/mob/living/carbon/alien/A) - for(var/mob/K in cultsinrange) - K.say("Barhah hra zar'garis!") - A.dust() /// A.gib() doesnt work for some reason, and dust() leaves that skull and bones thingy which we dont really need. - if (ticker.mode.name == "cult") - if(prob(75)) - usr << "\red The Geometer of Blood accepts your exotic sacrifice." + if(H.stat !=2) + usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." + else + if(prob(40)) + usr << "\red The Geometer of blood accepts this sacrifice." + ticker.mode:grant_runeword(usr) + else + usr << "\red The Geometer of blood accepts this sacrifice." + usr << "\red However, a mere dead body is not enough to satisfy Him." + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining + else + H.gib() + else + if(cultsinrange.len >= 3) + if(H.stat !=2) + if(prob(80)) + usr << "\red The Geometer of Blood accepts this sacrifice." ticker.mode:grant_runeword(usr) else - usr << "\red The Geometer of Blood accepts your exotic sacrifice." - usr << "\red However, this alien is not enough to gain His favor." + usr << "\red The Geometer of blood accepts this sacrifice." + usr << "\red However, this soul was not enough to gain His favor." + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining + else + H.gib() else - usr << "\red The Geometer of Blood accepts your exotic sacrifice." - return - return fizzle() */ + if(prob(40)) + usr << "\red The Geometer of blood accepts this sacrifice." + ticker.mode:grant_runeword(usr) + else + usr << "\red The Geometer of blood accepts this sacrifice." + usr << "\red However, a mere dead body is not enough to satisfy Him." + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining + else + H.gib() + else + if(H.stat !=2) + usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed." + else + if(prob(40)) + usr << "\red The Geometer of blood accepts this sacrifice." + ticker.mode:grant_runeword(usr) + else + usr << "\red The Geometer of blood accepts this sacrifice." + usr << "\red However, a mere dead body is not enough to satisfy Him." + if(isrobot(H)) + H.dust()//To prevent the MMI from remaining + else + H.gib() + for(var/mob/living/carbon/monkey/M in src.loc) + if (ticker.mode.name == "cult") + if(M.mind == ticker.mode:sacrifice_target) + if(cultsinrange.len >= 3) + sacrificed += M.mind + usr << "\red The Geometer of Blood accepts this sacrifice, your objective is now complete." + else + usr << "\red Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual." + continue + else + if(prob(20)) + usr << "\red The Geometer of Blood accepts your meager sacrifice." + ticker.mode:grant_runeword(usr) + else + usr << "\red The Geometer of blood accepts this sacrifice." + usr << "\red However, a mere monkey is not enough to satisfy Him." + else + usr << "\red The Geometer of Blood accepts your meager sacrifice." + if(prob(20)) + ticker.mode.grant_runeword(usr) + M.gib() +/* for(var/mob/living/carbon/alien/A) + for(var/mob/K in cultsinrange) + K.say("Barhah hra zar'garis!") + A.dust() /// A.gib() doesnt work for some reason, and dust() leaves that skull and bones thingy which we dont really need. + if (ticker.mode.name == "cult") + if(prob(75)) + usr << "\red The Geometer of Blood accepts your exotic sacrifice." + ticker.mode:grant_runeword(usr) + else + usr << "\red The Geometer of Blood accepts your exotic sacrifice." + usr << "\red However, this alien is not enough to gain His favor." + else + usr << "\red The Geometer of Blood accepts your exotic sacrifice." + return + return fizzle() */ /////////////////////////////////////////SIXTEENTH RUNE - revealrunes(var/obj/W as obj) - var/go=0 - var/rad - var/S=0 - if(istype(W,/obj/effect/rune)) - rad = 6 - go = 1 - if (istype(W,/obj/item/weapon/paper/talisman)) - rad = 4 - go = 1 - if (istype(W,/obj/item/weapon/nullrod)) - rad = 1 - go = 1 - if(go) - for(var/obj/effect/rune/R in orange(rad,src)) - if(R!=src) - R:visibility=15 - S=1 - if(S) - if(istype(W,/obj/item/weapon/nullrod)) - usr << "\red Arcane markings suddenly glow from underneath a thin layer of dust!" - return - if(istype(W,/obj/effect/rune)) - usr.say("Nikt[pick("'","`")]o barada kla'atu!") - for (var/mob/V in viewers(src)) - V.show_message("\red The rune turns into red dust, reveaing the surrounding runes.", 3) - del(src) - return - if(istype(W,/obj/item/weapon/paper/talisman)) - usr.whisper("Nikt[pick("'","`")]o barada kla'atu!") - usr << "\red Your talisman turns into red dust, revealing the surrounding runes." - for (var/mob/V in orange(1,usr.loc)) - if(V!=usr) - V.show_message("\red Red dust emanates from [usr]'s hands for a moment.", 3) - return - return - if(istype(W,/obj/effect/rune)) - return fizzle() - if(istype(W,/obj/item/weapon/paper/talisman)) - call(/obj/effect/rune/proc/fizzle)() - return +/obj/effect/rune/proc/revealrunesrune() + revealrunes(src) + +/obj/effect/rune/proc/revealrunes(var/obj/W as obj) + var/go=0 + var/rad + var/S=0 + if(istype(W,/obj/effect/rune)) + rad = 6 + go = 1 + if (istype(W,/obj/item/weapon/paper/talisman)) + rad = 4 + go = 1 + if (istype(W,/obj/item/weapon/nullrod)) + rad = 1 + go = 1 + if(go) + for(var/obj/effect/rune/R in orange(rad,src)) + if(R!=src) + R:visibility=15 + S=1 + if(S) + if(istype(W,/obj/item/weapon/nullrod)) + usr << "\red Arcane markings suddenly glow from underneath a thin layer of dust!" + return + if(istype(W,/obj/effect/rune)) + usr.say("Nikt[pick("'","`")]o barada kla'atu!") + for (var/mob/V in viewers(src)) + V.show_message("\red The rune turns into red dust, reveaing the surrounding runes.", 3) + del(src) + return + if(istype(W,/obj/item/weapon/paper/talisman)) + usr.whisper("Nikt[pick("'","`")]o barada kla'atu!") + usr << "\red Your talisman turns into red dust, revealing the surrounding runes." + for (var/mob/V in orange(1,usr.loc)) + if(V!=usr) + V.show_message("\red Red dust emanates from [usr]'s hands for a moment.", 3) + return + return + if(istype(W,/obj/effect/rune)) + return fizzle() + if(istype(W,/obj/item/weapon/paper/talisman)) + call(/obj/effect/rune/proc/fizzle)() + return /////////////////////////////////////////SEVENTEENTH RUNE - wall() - usr.say("Khari[pick("'","`")]d! Eske'te tannin!") - src.density = !src.density - var/mob/living/user = usr - user.take_organ_damage(2, 0) - if(src.density) - usr << "\red Your blood flows into the rune, and you feel that the very space over the rune thickens." - else - usr << "\red Your blood flows into the rune, and you feel as the rune releases its grasp on space." - return +/obj/effect/rune/proc/wall() + usr.say("Khari[pick("'","`")]d! Eske'te tannin!") + src.density = !src.density + var/mob/living/user = usr + user.take_organ_damage(2, 0) + if(src.density) + usr << "\red Your blood flows into the rune, and you feel that the very space over the rune thickens." + else + usr << "\red Your blood flows into the rune, and you feel as the rune releases its grasp on space." + return /////////////////////////////////////////EIGHTTEENTH RUNE - freedom() - var/mob/living/user = usr - var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living/carbon)) - cultists+=H.current - var/list/mob/living/carbon/users = new - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - users+=C - if(users.len>=3) - var/mob/living/carbon/cultist = input("Choose the one who you want to free", "Followers of Geometer") as null|anything in (cultists - users) - if(!cultist) - return fizzle() - if (cultist == user) //just to be sure. - return - if(!(cultist.buckled || \ - cultist.handcuffed || \ - istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle) || \ - (istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) || \ - (istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) || \ - (istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) \ - )) - user << "\red The [cultist] is already free." - return - cultist.buckled = null - if (cultist.handcuffed) - cultist.handcuffed.loc = cultist.loc - cultist.handcuffed = null - cultist.update_inv_handcuffed() - if (cultist.legcuffed) - cultist.legcuffed.loc = cultist.loc - cultist.legcuffed = null - cultist.update_inv_legcuffed() - if (istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle)) - cultist.u_equip(cultist.wear_mask) - if(istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) - cultist.loc:welded = 0 - if(istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) - cultist.loc:locked = 0 - if(istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) - cultist.loc:locked = 0 - for(var/mob/living/carbon/C in users) - user.take_overall_damage(15, 0) - C.say("Khari[pick("'","`")]d! Gual'te nikka!") - del(src) +/obj/effect/rune/proc/freedom() + var/mob/living/user = usr + var/list/mob/living/carbon/cultists = new + for(var/datum/mind/H in ticker.mode.cult) + if (istype(H.current,/mob/living/carbon)) + cultists+=H.current + var/list/mob/living/carbon/users = new + for(var/mob/living/carbon/C in orange(1,src)) + if(iscultist(C) && !C.stat) + users+=C + if(users.len>=3) + var/mob/living/carbon/cultist = input("Choose the one who you want to free", "Followers of Geometer") as null|anything in (cultists - users) + if(!cultist) return fizzle() + if (cultist == user) //just to be sure. + return + if(!(cultist.buckled || \ + cultist.handcuffed || \ + istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle) || \ + (istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) || \ + (istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) || \ + (istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) \ + )) + user << "\red The [cultist] is already free." + return + cultist.buckled = null + if (cultist.handcuffed) + cultist.handcuffed.loc = cultist.loc + cultist.handcuffed = null + cultist.update_inv_handcuffed() + if (cultist.legcuffed) + cultist.legcuffed.loc = cultist.loc + cultist.legcuffed = null + cultist.update_inv_legcuffed() + if (istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle)) + cultist.u_equip(cultist.wear_mask) + if(istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) + cultist.loc:welded = 0 + if(istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) + cultist.loc:locked = 0 + if(istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) + cultist.loc:locked = 0 + for(var/mob/living/carbon/C in users) + user.take_overall_damage(15, 0) + C.say("Khari[pick("'","`")]d! Gual'te nikka!") + del(src) + return fizzle() /////////////////////////////////////////NINETEENTH RUNE - cultsummon() - var/mob/living/user = usr - var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living/carbon)) - cultists+=H.current - var/list/mob/living/carbon/users = new - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - users+=C - if(users.len>=3) - var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user) - if(!cultist) - return fizzle() - if (cultist == user) //just to be sure. - return - if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet))) - user << "\red You cannot summon the [cultist], for his shackles of blood are strong" - return fizzle() - cultist.loc = src.loc - cultist.lying = 1 - cultist.regenerate_icons() - for(var/mob/living/carbon/human/C in orange(1,src)) - if(iscultist(C) && !C.stat) - C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!") - C.take_overall_damage(25, 0) - user.visible_message("\red Rune disappears with a flash of red light, and in its place now a body lies.", \ - "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ - "\red You hear a pop and smell ozone.") - del(src) +/obj/effect/rune/proc/cultsummon() + var/mob/living/user = usr + var/list/mob/living/carbon/cultists = new + for(var/datum/mind/H in ticker.mode.cult) + if (istype(H.current,/mob/living/carbon)) + cultists+=H.current + var/list/mob/living/carbon/users = new + for(var/mob/living/carbon/C in orange(1,src)) + if(iscultist(C) && !C.stat) + users+=C + if(users.len>=3) + var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user) + if(!cultist) return fizzle() + if (cultist == user) //just to be sure. + return + if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet))) + user << "\red You cannot summon the [cultist], for his shackles of blood are strong" + return fizzle() + cultist.loc = src.loc + cultist.lying = 1 + cultist.regenerate_icons() + for(var/mob/living/carbon/human/C in orange(1,src)) + if(iscultist(C) && !C.stat) + C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!") + C.take_overall_damage(25, 0) + user.visible_message("\red Rune disappears with a flash of red light, and in its place now a body lies.", \ + "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ + "\red You hear a pop and smell ozone.") + del(src) + return fizzle() /////////////////////////////////////////TWENTIETH RUNES - deafen() - if(istype(src,/obj/effect/rune)) - var/affected = 0 - for(var/mob/living/carbon/C in range(7,src)) - if (iscultist(C)) - continue - var/obj/item/weapon/nullrod/N = locate() in C - if(N) - continue - C.ear_deaf += 50 - C.show_message("\red The world around you suddenly becomes quiet.", 3) - affected++ - if(prob(1)) - C.sdisabilities |= DEAF - if(affected) - usr.say("Sti[pick("'","`")] kaliedir!") - usr << "\red The world becomes quiet as the deafening rune dissipates into fine dust." - del(src) - else - return fizzle() - else - var/affected = 0 - for(var/mob/living/carbon/C in range(7,usr)) - if (iscultist(C)) - continue - var/obj/item/weapon/nullrod/N = locate() in C - if(N) - continue - C.ear_deaf += 30 - //talismans is weaker. - C.show_message("\red The world around you suddenly becomes quiet.", 3) - affected++ - if(affected) - usr.whisper("Sti[pick("'","`")] kaliedir!") - usr << "\red Your talisman turns into gray dust, deafening everyone around." - for (var/mob/V in orange(1,src)) - if(!(iscultist(V))) - V.show_message("\red Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3) - return +/obj/effect/rune/proc/deafen() + if(istype(src,/obj/effect/rune)) + var/affected = 0 + for(var/mob/living/carbon/C in range(7,src)) + if (iscultist(C)) + continue + var/obj/item/weapon/nullrod/N = locate() in C + if(N) + continue + C.ear_deaf += 50 + C.show_message("\red The world around you suddenly becomes quiet.", 3) + affected++ + if(prob(1)) + C.sdisabilities |= DEAF + if(affected) + usr.say("Sti[pick("'","`")] kaliedir!") + usr << "\red The world becomes quiet as the deafening rune dissipates into fine dust." + del(src) + else + return fizzle() + else + var/affected = 0 + for(var/mob/living/carbon/C in range(7,usr)) + if (iscultist(C)) + continue + var/obj/item/weapon/nullrod/N = locate() in C + if(N) + continue + C.ear_deaf += 30 + //talismans is weaker. + C.show_message("\red The world around you suddenly becomes quiet.", 3) + affected++ + if(affected) + usr.whisper("Sti[pick("'","`")] kaliedir!") + usr << "\red Your talisman turns into gray dust, deafening everyone around." + for (var/mob/V in orange(1,src)) + if(!(iscultist(V))) + V.show_message("\red Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3) + return - blind() - if(istype(src,/obj/effect/rune)) - var/affected = 0 - for(var/mob/living/carbon/C in viewers(src)) - if (iscultist(C)) - continue - var/obj/item/weapon/nullrod/N = locate() in C - if(N) - continue - C.eye_blurry += 50 - C.eye_blind += 20 - if(prob(5)) - C.disabilities |= NEARSIGHTED - if(prob(10)) - C.sdisabilities |= BLIND - C.show_message("\red Suddenly you see red flash that blinds you.", 3) - affected++ - if(affected) - usr.say("Sti[pick("'","`")] kaliesin!") - usr << "\red The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust." - del(src) - else - return fizzle() - else - var/affected = 0 - for(var/mob/living/carbon/C in view(2,usr)) - if (iscultist(C)) - continue - var/obj/item/weapon/nullrod/N = locate() in C - if(N) - continue - C.eye_blurry += 30 - C.eye_blind += 10 - //talismans is weaker. - affected++ - C.show_message("\red You feel a sharp pain in your eyes, and the world disappears into darkness..", 3) - if(affected) - usr.whisper("Sti[pick("'","`")] kaliesin!") - usr << "\red Your talisman turns into gray dust, blinding those who not follow the Nar-Sie." - return +/obj/effect/rune/proc/blind() + if(istype(src,/obj/effect/rune)) + var/affected = 0 + for(var/mob/living/carbon/C in viewers(src)) + if (iscultist(C)) + continue + var/obj/item/weapon/nullrod/N = locate() in C + if(N) + continue + C.eye_blurry += 50 + C.eye_blind += 20 + if(prob(5)) + C.disabilities |= NEARSIGHTED + if(prob(10)) + C.sdisabilities |= BLIND + C.show_message("\red Suddenly you see red flash that blinds you.", 3) + affected++ + if(affected) + usr.say("Sti[pick("'","`")] kaliesin!") + usr << "\red The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust." + del(src) + else + return fizzle() + else + var/affected = 0 + for(var/mob/living/carbon/C in view(2,usr)) + if (iscultist(C)) + continue + var/obj/item/weapon/nullrod/N = locate() in C + if(N) + continue + C.eye_blurry += 30 + C.eye_blind += 10 + //talismans is weaker. + affected++ + C.show_message("\red You feel a sharp pain in your eyes, and the world disappears into darkness..", 3) + if(affected) + usr.whisper("Sti[pick("'","`")] kaliesin!") + usr << "\red Your talisman turns into gray dust, blinding those who not follow the Nar-Sie." + return - bloodboil() //cultists need at least one DANGEROUS rune. Even if they're all stealthy. +/obj/effect/rune/proc/bloodboil() //cultists need at least one DANGEROUS rune. Even if they're all stealthy. /* - var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living/carbon)) - cultists+=H.current + var/list/mob/living/carbon/cultists = new + for(var/datum/mind/H in ticker.mode.cult) + if (istype(H.current,/mob/living/carbon)) + cultists+=H.current */ - var/culcount = 0 //also, wording for it is old wording for obscure rune, which is now hide-see-blood. + var/culcount = 0 //also, wording for it is old wording for obscure rune, which is now hide-see-blood. // var/list/cultboil = list(cultists-usr) //and for this words are destroy-see-blood. - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - culcount++ - if(culcount>=3) - for(var/mob/living/carbon/M in viewers(usr)) - if(iscultist(M)) - continue - var/obj/item/weapon/nullrod/N = locate() in M - if(N) - continue - M.take_overall_damage(51,51) - M << "\red Your blood boils!" - if(prob(5)) - spawn(5) - M.gib() - for(var/obj/effect/rune/R in view(src)) - if(prob(10)) - explosion(R.loc, -1, 0, 1, 5) - for(var/mob/living/carbon/human/C in orange(1,src)) - if(iscultist(C) && !C.stat) - C.say("Dedo ol[pick("'","`")]btoh!") - C.take_overall_damage(15, 0) - del(src) - else - return fizzle() - return + for(var/mob/living/carbon/C in orange(1,src)) + if(iscultist(C) && !C.stat) + culcount++ + if(culcount>=3) + for(var/mob/living/carbon/M in viewers(usr)) + if(iscultist(M)) + continue + var/obj/item/weapon/nullrod/N = locate() in M + if(N) + continue + cult_log(": Blood Boil damaged [key_name_admin(M)].") + M.take_overall_damage(51,51) + M << "\red Your blood boils!" + if(prob(5)) + spawn(5) + M.gib() + for(var/obj/effect/rune/R in view(src)) + if(prob(10)) + explosion(R.loc, -1, 0, 1, 5) + for(var/mob/living/carbon/human/C in orange(1,src)) + if(iscultist(C) && !C.stat) + C.say("Dedo ol[pick("'","`")]btoh!") + C.take_overall_damage(15, 0) + del(src) + else + return fizzle() + return // WIP rune, I'll wait for Rastaf0 to add limited blood. - burningblood() - var/culcount = 0 - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - culcount++ - if(culcount >= 5) - for(var/obj/effect/rune/R in world) - if(R.blood_DNA == src.blood_DNA) - for(var/mob/living/M in orange(2,R)) - M.take_overall_damage(0,15) - if (R.invisibility>M.see_invisible) - M << "\red Aargh it burns!" - else - M << "\red Rune suddenly ignites, burning you!" - var/turf/T = get_turf(R) - T.hotspot_expose(700,125) - for(var/obj/effect/decal/cleanable/blood/B in world) - if(B.blood_DNA == src.blood_DNA) - for(var/mob/living/M in orange(1,B)) - M.take_overall_damage(0,5) - M << "\red Blood suddenly ignites, burning you!" - var/turf/T = get_turf(B) - T.hotspot_expose(700,125) - del(B) - del(src) +/obj/effect/rune/proc/burningblood() + var/culcount = 0 + for(var/mob/living/carbon/C in orange(1,src)) + if(iscultist(C) && !C.stat) + culcount++ + if(culcount >= 5) + for(var/obj/effect/rune/R in world) + if(R.blood_DNA == src.blood_DNA) + for(var/mob/living/M in orange(2,R)) + M.take_overall_damage(0,15) + if (R.invisibility>M.see_invisible) + M << "\red Aargh it burns!" + else + M << "\red Rune suddenly ignites, burning you!" + var/turf/T = get_turf(R) + T.hotspot_expose(700,125) + for(var/obj/effect/decal/cleanable/blood/B in world) + if(B.blood_DNA == src.blood_DNA) + for(var/mob/living/M in orange(1,B)) + M.take_overall_damage(0,5) + M << "\red Blood suddenly ignites, burning you!" + var/turf/T = get_turf(B) + T.hotspot_expose(700,125) + del(B) + del(src) ////////// Rune 24 (counting burningblood, which kinda doesnt work yet.) - runestun(var/mob/living/T as mob) - if(istype(src,/obj/effect/rune)) ///When invoked as rune, flash and stun everyone around. - usr.say("Fuu ma[pick("'","`")]jin!") - for(var/mob/living/L in viewers(src)) +/obj/effect/rune/proc/runestun(var/mob/living/T as mob) + if(istype(src,/obj/effect/rune)) ///When invoked as rune, flash and stun everyone around. + usr.say("Fuu ma[pick("'","`")]jin!") + for(var/mob/living/L in viewers(src)) - if(iscarbon(L)) - var/mob/living/carbon/C = L - flick("e_flash", C.flash) - if(C.stuttering < 1 && (!(HULK in C.mutations))) - C.stuttering = 1 - C.Weaken(1) - C.Stun(1) - C.show_message("\red The rune explodes in a bright flash.", 3) + if(iscarbon(L)) + var/mob/living/carbon/C = L + flick("e_flash", C.flash) + if(C.stuttering < 1 && (!(HULK in C.mutations))) + C.stuttering = 1 + C.Weaken(1) + C.Stun(1) + C.show_message("\red The rune explodes in a bright flash.", 3) - else if(issilicon(L)) - var/mob/living/silicon/S = L - S.Weaken(5) - S.show_message("\red BZZZT... The rune has exploded in a bright flash.", 3) - del(src) - else ///When invoked as talisman, stun and mute the target mob. - usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!") - var/obj/item/weapon/nullrod/N = locate() in T - if(N) - for(var/mob/O in viewers(T, null)) - O.show_message(text("\red [] invokes a talisman at [], but they are unaffected!", usr, T), 1) - else - for(var/mob/O in viewers(T, null)) - O.show_message(text("\red [] invokes a talisman at []", usr, T), 1) + else if(issilicon(L)) + var/mob/living/silicon/S = L + S.Weaken(5) + S.show_message("\red BZZZT... The rune has exploded in a bright flash.", 3) + del(src) + else ///When invoked as talisman, stun and mute the target mob. + usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!") + var/obj/item/weapon/nullrod/N = locate() in T + if(N) + for(var/mob/O in viewers(T, null)) + O.show_message(text("\red [] invokes a talisman at [], but they are unaffected!", usr, T), 1) + else + for(var/mob/O in viewers(T, null)) + O.show_message(text("\red [] invokes a talisman at []", usr, T), 1) - if(issilicon(T)) - T.Weaken(15) + if(issilicon(T)) + T.Weaken(15) - else if(iscarbon(T)) - var/mob/living/carbon/C = T - flick("e_flash", C.flash) - if (!(HULK in C.mutations)) - C.silent += 15 - C.Weaken(25) - C.Stun(25) - return + else if(iscarbon(T)) + var/mob/living/carbon/C = T + flick("e_flash", C.flash) + if (!(HULK in C.mutations)) + C.silent += 15 + C.Weaken(25) + C.Stun(25) + return /////////////////////////////////////////TWENTY-FIFTH RUNE - armor() - var/mob/living/carbon/human/user = usr - if(istype(src,/obj/effect/rune)) - usr.say("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") - else - usr.whisper("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") - usr.visible_message("\red The rune disappears with a flash of red light, and a set of armor appears on [usr]...", \ - "\red You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of armor.") +/obj/effect/rune/proc/armor() + var/mob/living/carbon/human/user = usr + if(istype(src,/obj/effect/rune)) + usr.say("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") + else + usr.whisper("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") + usr.visible_message("\red The rune disappears with a flash of red light, and a set of armor appears on [usr]...", \ + "\red You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of armor.") - user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head) - user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit) - user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes) - user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back) - //the above update their overlay icons cache but do not call update_icons() - //the below calls update_icons() at the end, which will update overlay icons by using the (now updated) cache - user.put_in_hands(new /obj/item/weapon/melee/cultblade(user)) //put in hands or on floor + user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head) + user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit) + user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes) + user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back) + //the above update their overlay icons cache but do not call update_icons() + //the below calls update_icons() at the end, which will update overlay icons by using the (now updated) cache + user.put_in_hands(new /obj/item/weapon/melee/cultblade(user)) //put in hands or on floor - del(src) - return + del(src) + return diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 104fbf1cdb..60bb93912e 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 daea3219d6..38dc530fb0 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 d5408d3330..c4afc34edf 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 e088103fab..b745cd37f8 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 05d0ccea8d..46b9b22d2a 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) @@ -206,4 +206,4 @@ name = "Mission Monitor" desc = "Used to access the built-in cameras in helmets." icon_state = "syndicam" - network = list("NUKE") \ No newline at end of file + network = list("NUKE") diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index d3f276abe0..2d86981ebd 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -262,6 +262,8 @@ /obj/machinery/door/proc/requiresID() return 1 +/* + /obj/machinery/door/proc/update_nearby_tiles(need_rebuild) if(!air_master) return 0 @@ -272,6 +274,8 @@ return 1 +*/ + /obj/machinery/door/proc/update_heat_protection(var/turf/simulated/source) if(istype(source)) if(src.density && (src.opacity || src.heat_proof)) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index e2bf6f7be2..018d0fe882 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -108,6 +108,7 @@ var/global/floorIsLava = 0 body += "Is an AI " else if(ishuman(M)) body += {"Make AI | + Make Mask | Make Robot | Make Alien | Make slime diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index e601f069c6..7e1e967fc5 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -22,25 +22,29 @@ F << "[time2text(world.timeofday,"hh:mm")] \ref[src] ([x],[y],[z]) || [src] [message]
" //ADMINVERBS -/client/proc/investigate_show( subject in list("hrefs","notes","singulo") ) +/client/proc/investigate_show( subject in list("hrefs","notes","singulo","cult") ) set name = "Investigate" set category = "Admin" if(!holder) return - switch(subject) - if("singulo") //general one-round-only stuff - var/F = investigate_subject2file(subject) - if(!F) - src << "Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed." - return - src << browse(F,"window=investigate[subject];size=800x300") - - if("hrefs") //persistant logs and stuff - if(config && config.log_hrefs) - if(href_logfile) - src << browse(href_logfile,"window=investigate[subject];size=800x300") - else - src << "Error: admin_investigate: No href logfile found." - return + + var/list/basic_subjects = list("singulo","cult") + + if(subject in basic_subjects) + var/F = investigate_subject2file(subject) + if(!F) + src << "Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed." + return + src << browse(F,"window=investigate[subject];size=800x300") + return + + + if(subject=="hrefs") //persistant logs and stuff + if(config && config.log_hrefs) + if(href_logfile) + src << browse(href_logfile,"window=investigate[subject];size=800x300") else - src << "Error: admin_investigate: Href Logging is not on." + src << "Error: admin_investigate: No href logfile found." return + else + src << "Error: admin_investigate: Href Logging is not on." + return diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 66de256c9e..b5aa11c6e9 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1192,6 +1192,15 @@ 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 diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 76f1b42046..19edf26e77 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 90ae7667dd..efbee3cfd6 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 05411337bc..2e9c5185a6 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -96,7 +96,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/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 95ebdf2011..bd7d4fe3a8 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -58,9 +58,10 @@ var/datum/organ/external/head = get_organ("head") var/mob/living/simple_animal/borer/B - for(var/I in head.implants) - if(istype(I,/mob/living/simple_animal/borer)) - B = I + if(istype(head)) + 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 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index baceaa2073..a677bd2445 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -326,6 +326,7 @@ return /mob/living/Move(a, b, flag) + if (buckled) return diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 42c4b0745b..937ed92874 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 7d52fbd7a2..d857856b7f 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -1,148 +1,14 @@ -// CAMERA NET -// -// The datum containing all the chunks. +/datum/visibility_network/cameras + ChunkType = /datum/visibility_chunk/camera -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) -*/ \ No newline at end of file +/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() \ 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 33dbfd0966..89c88c1aaf 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -1,168 +1,23 @@ -#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 +/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()) - 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 \ No newline at end of file + viewpoints += c \ 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 c82fbb7c76..69af9a18aa 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 @@ -37,13 +40,12 @@ // 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 T = get_turf(T) loc = T - cameranet.visibility(src) + cameraNetwork.visibility(src) if(ai.client) ai.client.eye = src //Holopad @@ -136,7 +138,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 53e68ff137..aa3d99bdba 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 c1f6331372..e88d4c28eb 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -1,80 +1,5 @@ #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. @@ -82,23 +7,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 0000000000..b55598c609 --- /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 611243f654..030a3db08e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -106,6 +106,9 @@ camera.network = list("SS13","Robots") if(isWireCut(5)) // 5 = BORG CAMERA camera.status = 0 + + // hook the robot into the camera network + addToVisibilityNetwork(cameraNetwork) initialize_components() //if(!unfinished) @@ -143,6 +146,8 @@ if(T) mmi.loc = T if(mind) mind.transfer_to(mmi.brainmob) mmi = null + // remove blown up robots from the visibility network + removeFromVisibilityNetwork(cameraNetwork) ..() /mob/living/silicon/robot/proc/pick_module() @@ -1201,7 +1206,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.dm b/code/modules/mob/mob.dm index c82489cf35..66f7d58bbc 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -333,6 +333,9 @@ var/list/slot_equipment_priority = list( \ return */ +/mob + var/newPlayerType = /mob/new_player + /mob/verb/abandon_mob() set name = "Respawn" set category = "OOC" @@ -381,14 +384,12 @@ var/list/slot_equipment_priority = list( \ log_game("[usr.key] AM failed due to disconnect.") return - var/mob/new_player/M = new /mob/new_player() + var/mob/newPlayer = new newPlayerType() if(!client) log_game("[usr.key] AM failed due to disconnect.") - del(M) + del(newPlayer) return - - M.key = key -// M.Login() //wat + newPlayer.key = key return /client/verb/changes() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index dc984663dd..f8d8228718 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -203,6 +203,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 314a4026ab..66c665644f 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 1ea768d005..2fda2c141d 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -176,8 +176,15 @@ return if(mob.stat==2) return - - if(isAI(mob)) return AIMove(n,direct,mob) + + // handle possible spirit movement + var/mob/spirit/currentSpirit = mob + if(currentSpirit) + return currentSpirit.Spirit_Move(direct) + + // handle possible AI movement + 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/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 6237803638..380a6dfe9a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -303,9 +303,9 @@ data_core.manifest_inject(character) ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn AnnounceArrival(character, rank) - + return character else - character.Robotize() + return character.Robotize() del(src) proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank) diff --git a/code/modules/mob/spirit/cultnet.dm b/code/modules/mob/spirit/cultnet.dm new file mode 100644 index 0000000000..df0cd57ff5 --- /dev/null +++ b/code/modules/mob/spirit/cultnet.dm @@ -0,0 +1,80 @@ +/* + +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)) + diff --git a/code/modules/mob/spirit/mask/mask.dm b/code/modules/mob/spirit/mask/mask.dm new file mode 100644 index 0000000000..6b58f201cf --- /dev/null +++ b/code/modules/mob/spirit/mask/mask.dm @@ -0,0 +1,227 @@ +/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 << "[usr.name]: [input]" + for(var/mob/spirit/spirit in spirits) + spirit << "[usr.name]: [input]" + + +/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]") + + ..() \ No newline at end of file diff --git a/code/modules/mob/spirit/mask/respawn.dm b/code/modules/mob/spirit/mask/respawn.dm new file mode 100644 index 0000000000..acfb69073c --- /dev/null +++ b/code/modules/mob/spirit/mask/respawn.dm @@ -0,0 +1,20 @@ +/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) \ No newline at end of file diff --git a/code/modules/mob/spirit/movement.dm b/code/modules/mob/spirit/movement.dm new file mode 100644 index 0000000000..d8847cb480 --- /dev/null +++ b/code/modules/mob/spirit/movement.dm @@ -0,0 +1,62 @@ +// 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"]." \ 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 0000000000..ce85f4175f --- /dev/null +++ b/code/modules/mob/spirit/spirit.dm @@ -0,0 +1,76 @@ +/* +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) + world << "Spirit Topic!" + usr << "Topic: usr [usr], src [src]" + src << "Topic: usr [usr], src [src]" + + 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 \ No newline at end of file diff --git a/code/modules/mob/spirit/viewpoint.dm b/code/modules/mob/spirit/viewpoint.dm new file mode 100644 index 0000000000..5e06356129 --- /dev/null +++ b/code/modules/mob/spirit/viewpoint.dm @@ -0,0 +1,202 @@ +#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 << "[get_display_name()] has reached out to you." + 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 << "You pray to Nar'Sie: [input]" + + for(var/mob/spirit/spirit in spirits) + spirit << "[get_display_name()] prays : [input]" + +// 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 \ No newline at end of file diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 0015620cc5..ea45eca49e 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -133,7 +133,59 @@ . = 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 << "You are a Mask of Nar'sie now. You are a tiny fragment of the unknowable entity that is the god." + new_spirit << "Your job is to help your acolytes complete their goals. Be spooky. Do evil." + + 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) diff --git a/code/setup.dm b/code/setup.dm index 68b7552b40..46800d409f 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/stylesheet.dm b/code/stylesheet.dm index fda3fb64e2..9a0b8f14cf 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -63,6 +63,7 @@ h1.alert, h2.alert {color: #000000;} .skrell {color: #00CED1;} .soghun {color: #228B22;} .vox {color: #AA00AA;} +.cultspeech {color: #B20000;} .say_quote {font-family: Georgia, Verdana, sans-serif;} .interface {color: #330033;} diff --git a/code/unused/AI_Visibility.dm b/code/unused/AI_Visibility.dm index d218f4409b..0769f8ca87 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 diff --git a/icons/mob/spirits/mask.dmi b/icons/mob/spirits/mask.dmi new file mode 100644 index 0000000000..20fe26c4bc Binary files /dev/null and b/icons/mob/spirits/mask.dmi differ