diff --git a/code/WorkInProgress/computer3/computers/camera.dm b/code/WorkInProgress/computer3/computers/camera.dm index 17e639166d5..d5f1218151c 100644 --- a/code/WorkInProgress/computer3/computers/camera.dm +++ b/code/WorkInProgress/computer3/computers/camera.dm @@ -142,7 +142,7 @@ return null var/list/L = list() - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in cameranet.viewpoints) var/list/temp = C.network & key.networks if(temp.len) L.Add(C) diff --git a/code/datums/visibility_networks/dictionary.dm b/code/datums/visibility_networks/dictionary.dm index 5f57ddd7a17..0ce800a8c04 100644 --- a/code/datums/visibility_networks/dictionary.dm +++ b/code/datums/visibility_networks/dictionary.dm @@ -1,6 +1,7 @@ var/datum/visibility_network/cameras/cameranet = new() -var/datum/visibility_network/cult/cultNetwork = new() -var/datum/visibility_network/list/visibility_networks = list("ALL_CAMERAS"=cameranet, "CULT" = cultNetwork) +//var/datum/visibility_network/cult/cultNetwork = new() +var/datum/visibility_network/list/visibility_networks = list("ALL_CAMERAS"=cameranet) +//var/datum/visibility_network/list/visibility_networks = list("ALL_CAMERAS"=cameranet, "CULT" = cultNetwork) // used by turfs and objects to update all visibility networks diff --git a/code/datums/visibility_networks/update_triggers.dm b/code/datums/visibility_networks/update_triggers.dm index f1835eeeb5a..9a366e7d642 100644 --- a/code/datums/visibility_networks/update_triggers.dm +++ b/code/datums/visibility_networks/update_triggers.dm @@ -57,18 +57,18 @@ for(var/turf/simulated/turf in locs) update_heat_protection(turf) - air_master.AddTurfToUpdate(turf) + air_master.mark_for_update(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 . = ..() @@ -86,9 +86,9 @@ /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/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 1db2ba3bee4..1eb60d3a301 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -149,11 +149,12 @@ rcd light flash thingy on matter drain var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor." +/* var/datum/camerachunk/C = cameranet.getCameraChunk(middle.x, middle.y, middle.z) if(!C.visibleTurfs[middle]) alert(src, "We cannot get camera vision of this location.") return - +*/ for(var/T in turfs) // Make sure the turfs are clear and the correct type. @@ -225,7 +226,7 @@ rcd light flash thingy on matter drain set name = "Reactivate Camera" set category = "Malfunction" if (istype (C, /obj/machinery/camera)) - for(var/datum/AI_Module/small/reactivate_camera/camera in current_modules) + for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules) if(camera.uses > 0) if(!C.status) C.deactivate(src) @@ -248,7 +249,7 @@ rcd light flash thingy on matter drain set name = "Upgrade Camera" set category = "Malfunction" if(istype(C)) - var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in current_modules + var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules if(UC) if(UC.uses > 0) if(C.assembly) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 766aa7d663e..ef294831b38 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -263,16 +263,6 @@ /obj/machinery/door/proc/requiresID() return 1 -/obj/machinery/door/proc/update_nearby_tiles(need_rebuild) - if(!air_master) - return 0 - - for(var/turf/simulated/turf in locs) - update_heat_protection(turf) - air_master.mark_for_update(turf) - - return 1 - /obj/machinery/door/proc/update_heat_protection(var/turf/simulated/source) if(istype(source)) diff --git a/code/game/objects/items/devices/handtv.dm b/code/game/objects/items/devices/handtv.dm index 48e22348f32..0406db85852 100644 --- a/code/game/objects/items/devices/handtv.dm +++ b/code/game/objects/items/devices/handtv.dm @@ -7,7 +7,7 @@ /obj/item/device/handtv/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 cameranet.viewpoints) if (C.hasbug && C.status) cameras.Add(C) if (length(cameras) == 0) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 31e4cae6a61..b0caf3b4a69 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -11,4 +11,15 @@ var/obj/machinery/camera/c = viewpoint if (!c) return FALSE - return c.can_use() \ No newline at end of file + return c.can_use() + + +// adding some indirection so that I don't have to edit a ton of files +/datum/visibility_network/cameras/proc/addCamera(var/camera) + return addViewpoint(camera) + +/datum/visibility_network/cameras/proc/removeCamera(var/camera) + return removeViewpoint(camera) + +/datum/visibility_network/cameras/proc/checkCameraVis(var/atom/target) + return checkCanSee(target) diff --git a/code/modules/mob/spirit/cultnet.dm b/code/modules/mob/spirit/cultnet.dm new file mode 100644 index 00000000000..df0cd57ff5d --- /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 00000000000..6b58f201cf2 --- /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 00000000000..acfb69073c2 --- /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 00000000000..d8847cb480a --- /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 00000000000..ce85f4175f0 --- /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 00000000000..5e063561297 --- /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