From 45c283a93557230c50dfabc4b76e68ff8ff44ba8 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 16 May 2017 22:59:41 -0500 Subject: [PATCH] applies the previous fixes for cult on a closed PR --- code/__DEFINES/antagonists.dm | 7 +- code/__HELPERS/game.dm | 156 +++++++++-------- code/_globalvars/game_modes.dm | 14 +- code/_onclick/hud/alert.dm | 21 ++- code/datums/antagonists/datum_cult.dm | 68 ++++++-- .../scripture_applications.dm | 2 +- code/game/gamemodes/cult/cult_comms.dm | 163 ++++++++++-------- code/game/gamemodes/cult/ritual.dm | 4 +- code/game/gamemodes/wizard/soulstone.dm | 2 +- .../objects/items/weapons/holy_weapons.dm | 2 +- code/modules/admin/verbs/one_click_antag.dm | 10 +- code/modules/events/ghost_role.dm | 2 +- .../carbon/alien/special/alien_embryo.dm | 4 +- .../living/simple_animal/guardian/guardian.dm | 4 +- 14 files changed, 263 insertions(+), 196 deletions(-) diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index d30a2d098f..433f44e095 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -1,3 +1,4 @@ -#define ANTAG_DATUM_CULT /datum/antagonist/cult -#define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult -#define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent \ No newline at end of file +#define ANTAG_DATUM_CULT /datum/antagonist/cult +#define ANTAG_DATUM_CULT_MASTER /datum/antagonist/cult/master +#define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult +#define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent \ No newline at end of file diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index ec78eb49b2..db405d2878 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -415,68 +415,83 @@ return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y) -/proc/showCandidatePollWindow(mob/dead/observer/G, poll_time, Question, list/candidates, ignore_category, time_passed, flashwindow = TRUE) +/proc/showCandidatePollWindow(mob/M, poll_time, Question, list/candidates, ignore_category, time_passed, flashwindow = TRUE) set waitfor = 0 - G << 'sound/misc/notice2.ogg' //Alerting them to their consideration + M << 'sound/misc/notice2.ogg' //Alerting them to their consideration if(flashwindow) - window_flash(G.client) - switch(ignore_category ? askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time)) + window_flash(M.client) + switch(ignore_category ? askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time)) if(1) - to_chat(G, "Choice registered: Yes.") + to_chat(M, "Choice registered: Yes.") if((world.time-time_passed)>poll_time) - to_chat(G, "Sorry, you were too late for the consideration!") - G << 'sound/machines/buzz-sigh.ogg' + to_chat(M, "Sorry, you answered too late to be considered!") + M << 'sound/machines/buzz-sigh.ogg' + candidates -= M else - candidates += G + candidates += M if(2) - to_chat(G, "Choice registered: No.") + to_chat(M, "Choice registered: No.") + candidates -= M if(3) var/list/L = GLOB.poll_ignore[ignore_category] if(!L) GLOB.poll_ignore[ignore_category] = list() - GLOB.poll_ignore[ignore_category] += G.ckey - to_chat(G, "Choice registered: Never for this round.") + GLOB.poll_ignore[ignore_category] += M.ckey + to_chat(M, "Choice registered: Never for this round.") + candidates -= M + else + candidates -= M -/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300, var/ignore_category = null, flashwindow = TRUE) - var/list/mob/dead/observer/candidates = list() +/proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE) + var/list/candidates = list() + + for(var/mob/dead/observer/G in GLOB.player_list) + candidates += G + + pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates) + + return candidates + +/proc/pollCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, list/group = null) var/time_passed = world.time if (!Question) Question = "Would you like to be a special role?" - for(var/mob/dead/observer/G in GLOB.player_list) - if(!G.key || !G.client || (ignore_category && GLOB.poll_ignore[ignore_category] && G.ckey in GLOB.poll_ignore[ignore_category])) + for(var/m in group) + var/mob/M = m + if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && M.ckey in GLOB.poll_ignore[ignore_category])) continue if(be_special_flag) - if(!(G.client.prefs) || !(be_special_flag in G.client.prefs.be_special)) + if(!(M.client.prefs) || !(be_special_flag in M.client.prefs.be_special)) continue - if (gametypeCheck) - if(!gametypeCheck.age_check(G.client)) + if(gametypeCheck) + if(!gametypeCheck.age_check(M.client)) continue - if (jobbanType) - if(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate")) + if(jobbanType) + if(jobban_isbanned(M, jobbanType) || jobban_isbanned(M, "Syndicate")) continue - showCandidatePollWindow(G, poll_time, Question, candidates, ignore_category, time_passed, flashwindow) + showCandidatePollWindow(M, poll_time, Question, group, ignore_category, time_passed, flashwindow) sleep(poll_time) - //Check all our candidates, to make sure they didn't log off during the wait period. - for(var/mob/dead/observer/G in candidates) - if(!G.key || !G.client) - candidates.Remove(G) + //Check all our candidates, to make sure they didn't log off or get deleted during the wait period. + for(var/mob/M in group) + if(!M.key || !M.client) + group -= M - listclearnulls(candidates) + listclearnulls(group) - return candidates + return group /proc/pollCandidatesForMob(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, mob/M, ignore_category = null) - var/list/L = pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) + var/list/L = pollGhostCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) if(!M || QDELETED(M) || !M.loc) return list() return L /proc/pollCandidatesForMobs(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, list/mobs, ignore_category = null) - var/list/L = pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) + var/list/L = pollGhostCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) var/i=1 for(var/v in mobs) var/atom/A = v @@ -487,62 +502,51 @@ return L /proc/pollCultists(var/mob/living/Nominee) // Cult Master Poll - var/time_passed = world.time - var/list/yes_voters = new - var/list/cult_total = new if(world.time < CULT_POLL_WAIT) - Nominee << "It would be premature to select a leader while everyone is still settling in, try again in [round((CULT_POLL_WAIT-world.time)/10)] seconds" + to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [round((CULT_POLL_WAIT-world.time)/10)] seconds.") return for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(!M.incapacitated()) - M << 'sound/hallucinations/im_here1.ogg' - M.verbs -= /mob/living/proc/cult_master - to_chat(M, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.") + if(B.current) + B.current.verbs -= /mob/living/proc/cult_master + if(!B.current.incapacitated()) + B.current << 'sound/hallucinations/im_here1.ogg' + to_chat(B.current, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.") sleep(250) + var/list/asked_cultists = list() for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(!M.incapacitated()) - M << 'sound/magic/exit_blood.ogg' - switch(askuser(M,"[Nominee] seeks to lead your cult, do you support them?","Please answer in 20 seconds!","Yes","No","Abstain", StealFocus=0, Timeout=200)) - if(1) - if((world.time-time_passed)>500) - to_chat(M, "Sorry, your vote came too late!") - M << 'sound/machines/buzz-sigh.ogg' - else - M << "Choice registered: Yes." - yes_voters += M - cult_total += M - if(2) - if((world.time-time_passed)>500) - to_chat(M, "Sorry, your vote came too late!") - M << 'sound/machines/buzz-sigh.ogg' - else - to_chat(M, "Choice registered: No.") - cult_total += M - if(3) - to_chat(M, "Choice registered: Abstain.") + if(B.current && B.current != Nominee && !B.current.incapacitated()) + B.current << 'sound/magic/exit_blood.ogg' + asked_cultists += B.current + var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 1200, group = asked_cultists) sleep(300) - if(yes_voters.len > (cult_total.len/2)) - var/datum/action/innate/cultmast/finalreck/FinalReckoning = new() - var/datum/action/innate/cultmast/cultmark/Mark = new() - FinalReckoning.Grant(Nominee) - Mark.Grant(Nominee) - Nominee.mind.special_role = "Cult Master" - Nominee.update_action_buttons_icon() - Nominee.apply_status_effect(/datum/status_effect/cult_master) - SSticker.mode.set_antag_hud(Nominee,"cultmaster") - GLOB.cult_mastered = TRUE + if(QDELETED(Nominee) || Nominee.incapacitated()) for(var/datum/mind/B in SSticker.mode.cult) - if(!B.current.incapacitated()) - to_chat(B.current,"[Nominee] has the cult's support and is now their master. Follow their orders to the best of your ability!") - return TRUE - else - for(var/datum/mind/B in SSticker.mode.cult) - if(!B.current.incapacitated()) - to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") + if(B.current) B.current.verbs += /mob/living/proc/cult_master + if(!B.current.incapacitated()) + to_chat(B.current,"[Nominee] has died in the process of attempting to win the cult's support!") return FALSE + if(!Nominee.mind) + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + B.current.verbs += /mob/living/proc/cult_master + if(!B.current.incapacitated()) + to_chat(B.current,"[Nominee] has gone insane and catatonic in the process of attempting to win the cult's support!") + return FALSE + if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5) + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + B.current.verbs += /mob/living/proc/cult_master + if(!B.current.incapacitated()) + to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") + return FALSE + SSticker.mode.remove_cultist(Nominee.mind, FALSE) + Nominee.mind.add_antag_datum(ANTAG_DATUM_CULT_MASTER) + GLOB.cult_mastered = TRUE + for(var/datum/mind/B in SSticker.mode.cult) + if(!B.current.incapacitated()) + to_chat(B.current,"[Nominee] has won the cult's support and is now their master. Follow [Nominee.p_their()] orders to the best of your ability!") + return TRUE /proc/poll_helper(var/mob/living/M) diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm index 912ae78a04..299113795d 100644 --- a/code/_globalvars/game_modes.dm +++ b/code/_globalvars/game_modes.dm @@ -3,10 +3,12 @@ GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret" GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report - -// Cult, needs to be global so admin cultists are functional -GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master -GLOBAL_DATUM(sac_mind, /datum/mind) -GLOBAL_VAR_INIT(sac_image, null) -GLOBAL_VAR_INIT(cult_mastered, FALSE) + +// Cult, needs to be global so admin cultists are functional +GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master +GLOBAL_DATUM(blood_target_image, /image) +GLOBAL_DATUM(sac_mind, /datum/mind) +GLOBAL_VAR_INIT(sac_image, null) +GLOBAL_VAR_INIT(cult_mastered, FALSE) +GLOBAL_VAR_INIT(reckoning_complete, FALSE) GLOBAL_VAR_INIT(sac_complete, FALSE) \ No newline at end of file diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index b95750009f..7cbd997db6 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -265,20 +265,20 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "Allows you to sense blood that is manipulated by dark magicks." icon_state = "cult_sense" alerttooltipstyle = "cult" - var/image/sacimage + var/static/image/narnar var/angle = 0 var/mob/living/simple_animal/hostile/construct/Cviewer = null /obj/screen/alert/bloodsense/Initialize() - ..() - sacimage = GLOB.sac_image + . = ..() + if(!narnar) + narnar = new('icons/mob/screen_alert.dmi', "mini_nar") START_PROCESSING(SSprocessing, src) /obj/screen/alert/bloodsense/Destroy() - sacimage = null - Cviewer = null - STOP_PROCESSING(SSprocessing, src) - return ..() + Cviewer = null + STOP_PROCESSING(SSprocessing, src) + return ..() /obj/screen/alert/bloodsense/process() var/atom/blood_target @@ -298,7 +298,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." cut_overlays() icon_state = "runed_sense0" desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin." - add_overlay(sacimage) + add_overlay(GLOB.sac_image) return if(!blood_target && GLOB.sac_complete) if(icon_state == "runed_sense1") @@ -307,7 +307,6 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." angle = 0 cut_overlays() icon_state = "runed_sense1" - var/image/narnar = new('icons/mob/screen_alert.dmi', "mini_nar") desc = "The sacrifice is complete, prepare to summon Nar-Sie!" add_overlay(narnar) return @@ -318,8 +317,8 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." var/area/A = get_area(P) if(P.z != Q.z) //The target is on a different Z level, we cannot sense that far. return - desc = "You are currently tracking [blood_target] in [A.name]" - var/target_angle = Get_Angle(mob_viewer, blood_target) + desc = "You are currently tracking [blood_target] in [A.name]." + var/target_angle = Get_Angle(Q, P) var/target_dist = get_dist(P, Q) cut_overlays() switch(target_dist) diff --git a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm index 59f165ff37..9016331440 100644 --- a/code/datums/antagonists/datum_cult.dm +++ b/code/datums/antagonists/datum_cult.dm @@ -2,20 +2,21 @@ var/datum/action/innate/cultcomm/communion = new /datum/antagonist/cult/Destroy() - qdel(communion) + QDEL_NULL(communion) return ..() /datum/antagonist/cult/proc/add_objectives() var/list/target_candidates = list() for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !is_convertable_to_cult(player) && (player != owner) && isliving(player)) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD) target_candidates += player.mind if(target_candidates.len == 0) message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && (player != owner) && isliving(player)) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD) target_candidates += player.mind - if(target_candidates.len > 0) + listclearnulls(target_candidates) + if(LAZYLEN(target_candidates)) GLOB.sac_mind = pick(target_candidates) if(!GLOB.sac_mind) message_admins("Cult Sacrifice: ERROR - Null target chosen!") @@ -33,7 +34,6 @@ GLOB.sac_complete = TRUE SSticker.mode.cult_objectives += "sacrifice" SSticker.mode.cult_objectives += "eldergod" - on_gain() /datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind) var/mob/living/current = cult_mind.current @@ -47,7 +47,8 @@ explanation = "The veil has already been weakened here, proceed to the final objective." if("eldergod") explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie' with nine acolytes on it. You must do this after sacrificing your target." - to_chat(current, "Objective #[obj_count]: [explanation]") + if(!silent) + to_chat(current, "Objective #[obj_count]: [explanation]") cult_mind.memory += "Objective #[obj_count]: [explanation]
" /datum/antagonist/cult/can_be_owned(datum/mind/new_owner) @@ -58,16 +59,16 @@ /datum/antagonist/cult/on_gain() . = ..() var/mob/living/current = owner.current - if(SSticker.mode.cult_objectives.len == 0) + if(!LAZYLEN(SSticker.mode.cult_objectives)) add_objectives() - return SSticker.mode.cult += owner // Only add after they've been given objectives cult_memorization(owner) if(jobban_isbanned(current, ROLE_CULTIST)) addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, current, ROLE_CULTIST, ROLE_CULTIST), 0) SSticker.mode.update_cult_icons_added(owner) - current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) + if(GLOB.blood_target && GLOB.blood_target_image && current.client) + current.client.images += GLOB.blood_target_image /datum/antagonist/cult/apply_innate_effects(mob/living/mob_override) . = ..() @@ -79,6 +80,7 @@ if(!GLOB.cult_mastered) current.verbs += /mob/living/proc/cult_master communion.Grant(current) + current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) /datum/antagonist/cult/remove_innate_effects(mob/living/mob_override) . = ..() @@ -97,8 +99,50 @@ owner.wipe_memory() SSticker.mode.cult -= owner SSticker.mode.update_cult_icons_removed(owner) - to_chat(owner, "An unfamiliar white light flashes through your mind, cleansing the taint of the Dark One and all your memories as its servant.") - owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) if(!silent) - owner.current.visible_message("[owner] looks like [owner.current.p_they()] just reverted to their old faith!") + to_chat(owner.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.") + owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) + owner.current.visible_message("[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!") + if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client) + owner.current.client.images -= GLOB.blood_target_image . = ..() + +/datum/antagonist/cult/master + var/datum/action/innate/cultmast/finalreck/reckoning = new + var/datum/action/innate/cultmast/cultmark/bloodmark = new + +/datum/antagonist/cult/master/Destroy() + QDEL_NULL(reckoning) + QDEL_NULL(bloodmark) + return ..() + +/datum/antagonist/cult/master/on_gain() + . = ..() + var/mob/living/current = owner.current + SSticker.mode.set_antag_hud(current, "cultmaster") + +/datum/antagonist/cult/master/greet() + to_chat(owner.current, "You are the cult's Master. As the cult's Master, you have a unique title and loud voice when communicating, are capable of marking \ + targets, such as a location or a noncultist, to direct the cult to them, and, finally, you are capable of summoning the entire living cult to your location once.") + to_chat(owner.current, "Use these abilities to direct the cult to victory at any cost.") + +/datum/antagonist/cult/master/apply_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current = owner.current + if(mob_override) + current = mob_override + if(!GLOB.reckoning_complete) + reckoning.Grant(current) + bloodmark.Grant(current) + current.update_action_buttons_icon() + current.apply_status_effect(/datum/status_effect/cult_master) + +/datum/antagonist/cult/master/remove_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current = owner.current + if(mob_override) + current = mob_override + reckoning.Remove(current) + bloodmark.Remove(current) + current.update_action_buttons_icon() + current.remove_status_effect(/datum/status_effect/cult_master) diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm index aa1a07ac2f..21da8fab00 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm @@ -135,7 +135,7 @@ if(!check_special_requirements()) return FALSE to_chat(invoker, "The tendril shivers slightly as it selects a marauder...") - var/list/marauder_candidates = pollCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER) + var/list/marauder_candidates = pollGhostCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER) if(!check_special_requirements()) return FALSE if(!marauder_candidates.len) diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index ff8ee97de7..ffaaf46b80 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -24,12 +24,19 @@ var/my_message if(!message) return - user.whisper("O bidai nabora se[pick("'","`")]sma!") + user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common) user.whisper(html_decode(message)) - if (user.mind.special_role == "Cult Master") - my_message = "[(ishuman(user) ? "Master" : "Lord")] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" - else - my_message = "[(ishuman(user) ? "Acolyte" : "Construct")] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" + var/title = "Acolyte" + var/span = "cultitalic" + if(user.mind && user.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) + span = "cultlarge" + if(ishuman(user)) + title = "Master" + else + title = "Lord" + else if(!ishuman(user)) + title = "Construct" + my_message = "[title] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" for(var/mob/M in GLOB.mob_list) if(iscultist(M)) to_chat(M, my_message) @@ -83,83 +90,88 @@ check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS /datum/action/innate/cultmast/IsAvailable() - if(owner.mind.special_role != "Cult Master") + if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) return 0 return ..() /datum/action/innate/cultmast/finalreck name = "Final Reckoning" - desc = "A single-use spell that brings the entire cult to the master's location" + desc = "A single-use spell that brings the entire cult to the master's location." button_icon_state = "sintouch" /datum/action/innate/cultmast/finalreck/Activate() - var/list/destinations = list() - for(var/turf/T in orange(1,owner)) - if(istype(T, /turf/open)) - destinations += T for(var/i in 1 to 4) - owner.chant(i) + chant(i) + var/list/destinations = list() + for(var/turf/T in orange(1, owner)) + if(!is_blocked_turf(T, TRUE)) + destinations += T + if(!LAZYLEN(destinations)) + to_chat(owner, "You need more space to summon the cult!") + return if(do_after(owner, 30, target = owner)) for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(isliving(M) && M.stat != DEAD) - var/turf/mobloc = get_turf(M) + if(B.current && B.current.stat != DEAD) + var/turf/mobloc = get_turf(B.current) switch(i) - if (1) - new /obj/effect/overlay/temp/cult/sparks(mobloc, M.dir) + if(1) + new /obj/effect/overlay/temp/cult/sparks(mobloc, B.current.dir) playsound(mobloc, "sparks", 50, 1) - if (2) - new /obj/effect/overlay/temp/dir_setting/cult/phase/out(mobloc, M.dir) + if(2) + new /obj/effect/overlay/temp/dir_setting/cult/phase/out(mobloc, B.current.dir) playsound(mobloc, "sparks", 75, 1) - if (3) - new /obj/effect/overlay/temp/dir_setting/cult/phase(mobloc, M.dir) + if(3) + new /obj/effect/overlay/temp/dir_setting/cult/phase(mobloc, B.current.dir) playsound(mobloc, "sparks", 100, 1) - if (4) + if(4) playsound(mobloc, 'sound/magic/exit_blood.ogg', 100, 1) - if(M != owner) + if(B.current != owner) + B.current.setDir(SOUTH) var/turf/final = pick(destinations) new /obj/effect/overlay/temp/cult/blood(final) - addtimer(CALLBACK(M, /mob/.proc/reckon, final), 10) - else - for(var/datum/action/innate/cultmast/finalreck/H in owner.actions) - qdel(H) + addtimer(CALLBACK(B.current, /mob/.proc/reckon, final), 10) else return + GLOB.reckoning_complete = TRUE + Remove(owner) -/mob/proc/reckon(var/turf/final) +/mob/proc/reckon(turf/final) new /obj/effect/overlay/temp/cult/blood/out(get_turf(src)) forceMove(final) -/mob/proc/chant(var/i) - switch(i) - if (1) - say("C'arta Forbici!") - if (2) - say("Pleggh E'ntrath!") - playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 50, 1) - if (3) - say("Barhah hra Zar'garis!") - playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 75, 1) - if (4) - say("N'ath reth Sh'yro eth D'rekkathnor!!!") - playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 100, 1) +/datum/action/innate/cultmast/finalreck/proc/chant(chant_number) + switch(chant_number) + if(1) + owner.say("C'arta forbici!", language = /datum/language/common) + if(2) + owner.say("Pleggh e'ntrath!", language = /datum/language/common) + playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 50, 1) + if(3) + owner.say("Barhah hra zar'garis!", language = /datum/language/common) + playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 75, 1) + if(4) + owner.say("N'ath reth sh'yro eth d'rekkathnor!!!", language = /datum/language/common) + playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 100, 1) /datum/action/innate/cultmast/cultmark name = "Mark Target" - desc = "Marks a target for the cult" + desc = "Marks a target for the cult." button_icon_state = "cult_mark" var/obj/effect/proc_holder/cultmark/CM - var/time = 0 + var/cooldown = 0 + var/base_cooldown = 1200 /datum/action/innate/cultmast/cultmark/New() - CM = new() - ..() + CM = new() + CM.attached_action = src + ..() /datum/action/innate/cultmast/cultmark/IsAvailable() - if(owner.mind.special_role != "Cult Master") + if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) return 0 - if((world.time - time)<1200 && !CM.active) - owner << "You need to wait [round((1200-(world.time-time))/10)] seconds before you can mark another target!" + if(cooldown > world.time) + if(!CM.active) + owner << "You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can mark another target!" return 0 return ..() @@ -169,22 +181,22 @@ /datum/action/innate/cultmast/cultmark/Activate() CM.toggle(owner) //the important bit - if(!active) - time = world.time - else - time = 0 return TRUE /obj/effect/proc_holder/cultmark - active = FALSE - ranged_mousepointer = 'icons/effects/cult_target.dmi' + active = FALSE + ranged_mousepointer = 'icons/effects/cult_target.dmi' + var/datum/action/innate/cultmast/cultmark/attached_action +/obj/effect/proc_holder/cultmark/Destroy() + attached_action = null + return ..() /obj/effect/proc_holder/cultmark/proc/toggle(mob/user) - if(active) - remove_ranged_ability("You cease the marking ritual...") - else - add_ranged_ability(user, "You prepare to mark a target for your cult...") + if(active) + remove_ranged_ability("You cease the marking ritual.") + else + add_ranged_ability(user, "You prepare to mark a target for your cult...") /obj/effect/proc_holder/cultmark/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) @@ -196,24 +208,29 @@ if(!isturf(T)) return FALSE if(target in view(7, get_turf(ranged_ability_user))) - remove_ranged_ability(caller, "The marking rite is complete! It will last for 90 seconds.") GLOB.blood_target = target var/area/A = get_area(target) + attached_action.cooldown = world.time + attached_action.base_cooldown + addtimer(CALLBACK(attached_action.owner, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown) + GLOB.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) + GLOB.blood_target_image.appearance_flags = RESET_COLOR + GLOB.blood_target_image.pixel_x = -target.pixel_x + GLOB.blood_target_image.pixel_y = -target.pixel_y for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(M.stat != DEAD) - to_chat(M, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!") - M << pick(sound('sound/hallucinations/over_here2.ogg',0,1,75), sound('sound/hallucinations/over_here3.ogg',0,1,75)) - var/image/cult_marker = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) - M.client.images |= cult_marker - addtimer(CALLBACK(M, /mob/living/proc/reset_blood_image, cult_marker), 900, TIMER_OVERRIDE) + if(B.current && B.current.stat != DEAD && B.current.client) + to_chat(B.current, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!") + B.current << pick(sound('sound/hallucinations/over_here2.ogg',0,1,75), sound('sound/hallucinations/over_here3.ogg',0,1,75)) + B.current.client.images += GLOB.blood_target_image + attached_action.owner.update_action_buttons_icon() + remove_ranged_ability("The marking rite is complete! It will last for 90 seconds.") + addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target), 900, TIMER_OVERRIDE) return TRUE return FALSE -/mob/living/proc/reset_blood_image(var/image/cult_marker) - if(GLOB.blood_target && src.stat!=DEAD) - to_chat(src,"The blood mark has expired!") - if(client) - client.images.Remove(cult_marker) - QDEL_NULL(cult_marker) - GLOB.blood_target = null \ No newline at end of file +/proc/reset_blood_target() + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current && B.current.stat != DEAD && B.current.client) + if(GLOB.blood_target) + to_chat(B.current,"The blood mark has expired!") + B.current.client.images -= GLOB.blood_target_image + QDEL_NULL(GLOB.blood_target) \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index f393929463..069a422480 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -200,7 +200,7 @@ This file contains the arcane tome files. if(!("eldergod" in SSticker.mode.cult_objectives)) to_chat(user, "Nar-Sie does not wish to be summoned!") return - if(GLOB.sac_complete) + if(!GLOB.sac_complete) to_chat(user, "The sacrifice is not complete. The portal would lack the power to open if you tried!") return if(!SSticker.mode.eldergod) @@ -209,7 +209,7 @@ This file contains the arcane tome files. if((loc.z && loc.z != ZLEVEL_STATION) || !A.blob_allowed) to_chat(user, "The Geometer is not interested in lesser locations; the station is the prize!") return - var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No") + var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie; it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No") if(confirm_final == "No") to_chat(user, "You decide to prepare further before scribing the rune.") return diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index b840b64c93..09412a79ac 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -253,7 +253,7 @@ break if(!chosen_ghost) //Failing that, we grab a ghost - var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50) + var/list/consenting_candidates = pollGhostCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50) if(consenting_candidates.len) chosen_ghost = pick(consenting_candidates) if(!T) diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index aa720f1979..4b5acd949d 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -214,7 +214,7 @@ possessed = TRUE - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE) var/mob/dead/observer/theghost = null if(LAZYLEN(candidates)) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index d7b06ee9c8..87a9e5a040 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -132,7 +132,7 @@ /datum/admins/proc/makeWizard() - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", null) var/mob/dead/observer/selected = pick_n_take(candidates) @@ -215,7 +215,7 @@ /datum/admins/proc/makeNukeTeam() var/datum/game_mode/nuclear/temp = new - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp) var/list/mob/dead/observer/chosen = list() var/mob/dead/observer/theghost = null @@ -288,7 +288,7 @@ // DEATH SQUADS /datum/admins/proc/makeDeathsquad() var/mission = input("Assign a mission to the deathsquad", "Assign Mission", "Leave no witnesses.") - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null) var/squadSpawned = 0 if(candidates.len >= 2) //Minimum 2 to be considered a squad @@ -396,7 +396,7 @@ /datum/admins/proc/makeOfficial() var/mission = input("Assign a task for the official", "Assign Task", "Conduct a routine preformance review of [station_name()] and its Captain.") - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered to be a Centcom Official?", "deathsquad") + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered to be a Centcom Official?", "deathsquad") if(candidates.len) var/mob/dead/observer/chosen_candidate = pick(candidates) @@ -457,7 +457,7 @@ var/mission = input("Assign a mission to the Emergency Response Team", "Assign Mission", "Assist the station.") as null|text if(!mission) return - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null) var/teamSpawned = 0 if(candidates.len > 0) diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm index 93eff54b27..2468ddb5c6 100644 --- a/code/modules/events/ghost_role.dm +++ b/code/modules/events/ghost_role.dm @@ -59,7 +59,7 @@ var/list/mob/dead/observer/regular_candidates // don't get their hopes up if(priority_candidates.len < minimum_required) - regular_candidates = pollCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special) + regular_candidates = pollGhostCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special) else regular_candidates = list() diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 68d94b4c04..6e9bcc08cc 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -69,7 +69,7 @@ bursting = TRUE - var/list/candidates = pollCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA) + var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA) if(QDELETED(src) || QDELETED(owner)) return @@ -81,7 +81,7 @@ var/mob/dead/observer/ghost = pick(candidates) - var/mutable_appearance/overlay = mutable_appearance('icons/mob/alien.dmi', "burst_lie") + var/mutable_appearance/overlay = mutable_appearance('icons/mob/alien.dmi', "burst_lie") owner.add_overlay(overlay) var/atom/xeno_loc = get_turf(owner) diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index be889a4183..fe6e22bcab 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -414,7 +414,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/mob/living/simple_animal/hostile/guardian/G = input(src, "Pick the guardian you wish to reset", "Guardian Reset") as null|anything in guardians if(G) to_chat(src, "You attempt to reset [G.real_name]'s personality...") - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", "pAI", null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", "pAI", null, FALSE, 100) var/mob/dead/observer/new_stand = null if(candidates.len) new_stand = pick(candidates) @@ -489,7 +489,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians return used = TRUE to_chat(user, "[use_message]") - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100) var/mob/dead/observer/theghost = null if(candidates.len)