Skip to content

Commit

Permalink
[MIRROR] Fixes Cult voting for a leader (#713) (#1780)
Browse files Browse the repository at this point in the history
* Fixes Cult voting for a leader (#81169)

## About The Pull Request

With the recent changes to polling, it seems like it didn't properly
poll cultists, I fixed that and fixed other issues with it (such as it
telling players that they are signing up to BE a cult leader, when they
arent).

Also fixed the button to put yourself forward as cult leader, it
properly removes and gives itself when necessary.

## Why It's Good For The Game

Cult button works again how cool is that

Closes tgstation/tgstation#80620

## Changelog

:cl:
fix: Cultists can now vote for a Cult leader again.
/:cl:

* Fixes Cult voting for a leader

---------

Co-authored-by: NovaBot <[email protected]>
Co-authored-by: John Willard <[email protected]>
  • Loading branch information
3 people authored Feb 6, 2024
1 parent 803cfae commit 4b60813
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 52 deletions.
11 changes: 11 additions & 0 deletions code/__DEFINES/polls.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@
#define POLLTYPE_RATING "NUMVAL"
#define POLLTYPE_MULTI "MULTICHOICE"
#define POLLTYPE_IRV "IRV"

///The message sent when you sign up to a poll.
#define POLL_RESPONSE_SIGNUP "signup"
///The message sent when you've already signed up for a poll and are trying to sign up again.
#define POLL_RESPONSE_ALREADY_SIGNED "already_signed"
///The message sent when you are not signed up for a poll.
#define POLL_RESPONSE_NOT_SIGNED "not_signed"
///The message sent when you are too late to unregister from a poll.
#define POLL_RESPONSE_TOO_LATE_TO_UNREGISTER "failed_unregister"
///The message sent when you successfully unregister from a poll.
#define POLL_RESPONSE_UNREGISTERED "unregistered"
12 changes: 6 additions & 6 deletions code/controllers/subsystem/polling.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SUBSYSTEM_DEF(polling)
if(running_poll.time_left() <= 0)
polling_finished(running_poll)

/datum/controller/subsystem/polling/proc/poll_candidates(question, role, check_jobban, poll_time = 30 SECONDS, ignore_category = null, flash_window = TRUE, list/group = null, pic_source, role_name_text)
/datum/controller/subsystem/polling/proc/poll_candidates(question, role, check_jobban, poll_time = 30 SECONDS, ignore_category = null, flash_window = TRUE, list/group = null, pic_source, role_name_text, list/custom_response_messages)
if(group.len == 0)
return list()
if(role && !role_name_text)
Expand All @@ -32,21 +32,21 @@ SUBSYSTEM_DEF(polling)

var/jumpable = isatom(pic_source) ? pic_source : null

var/datum/candidate_poll/new_poll = new(role_name_text, question, poll_time, ignore_category, jumpable)
var/datum/candidate_poll/new_poll = new(role_name_text, question, poll_time, ignore_category, jumpable, custom_response_messages)
LAZYADD(currently_polling, new_poll)

var/category = "[new_poll.poll_key]_poll_alert"

for(var/mob/candidate_mob as anything in group)
if(!candidate_mob.client)
continue
// Universal opt-out for all players.
if((!candidate_mob.client.prefs.read_preference(/datum/preference/toggle/ghost_roles)))
// Universal opt-out for all players if it's for a role.
if(role && (!candidate_mob.client.prefs.read_preference(/datum/preference/toggle/ghost_roles)))
continue
// Opt-out for admins whom are currently adminned.
if((!candidate_mob.client.prefs.read_preference(/datum/preference/toggle/ghost_roles_as_admin)) && candidate_mob.client.holder)
if(role && (!candidate_mob.client.prefs.read_preference(/datum/preference/toggle/ghost_roles_as_admin)) && candidate_mob.client.holder)
continue
if(!is_eligible(candidate_mob, role, check_jobban, ignore_category))
if(role && !is_eligible(candidate_mob, role, check_jobban, ignore_category))
continue

SEND_SOUND(candidate_mob, 'sound/misc/notice2.ogg')
Expand Down
31 changes: 25 additions & 6 deletions code/datums/candidate_poll.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,23 @@
var/finished = FALSE
/// Used to categorize in the alerts system and identify polls of same question+role so we can stack the alert buttons
var/poll_key
///Response messages sent in specific key areas for full customization of polling.
var/list/response_messages = list(
POLL_RESPONSE_SIGNUP = "You have signed up for %ROLE%! A candidate will be picked randomly soon.",
POLL_RESPONSE_ALREADY_SIGNED = "You have already signed up for this!",
POLL_RESPONSE_NOT_SIGNED = "You aren't signed up for this!",
POLL_RESPONSE_TOO_LATE_TO_UNREGISTER = "It's too late to unregister yourself, selection has already begun!",
POLL_RESPONSE_UNREGISTERED = "You have been unregistered as a candidate for %ROLE%. You can sign up again before the poll ends.",
)

/datum/candidate_poll/New(polled_role, polled_question, poll_duration, poll_ignoring_category, poll_jumpable)
/datum/candidate_poll/New(
polled_role,
polled_question,
poll_duration,
poll_ignoring_category,
poll_jumpable,
list/custom_response_messages = list(),
)
role = polled_role
question = polled_question
duration = poll_duration
Expand All @@ -30,6 +45,10 @@
signed_up = list()
time_started = world.time
poll_key = "[question]_[role ? role : "0"]"
if(custom_response_messages.len)
response_messages = custom_response_messages
for(var/individual_message in response_messages)
response_messages[individual_message] = replacetext(response_messages[individual_message], "%ROLE%", role)
return ..()

/datum/candidate_poll/Destroy()
Expand All @@ -49,7 +68,7 @@
return FALSE
if(candidate in signed_up)
if(!silent)
to_chat(candidate, span_warning("You have already signed up for this!"))
to_chat(candidate, span_warning(response_messages[POLL_RESPONSE_ALREADY_SIGNED]))
return FALSE
if(time_left() <= 0)
if(!silent)
Expand All @@ -59,7 +78,7 @@

signed_up += candidate
if(!silent)
to_chat(candidate, span_notice("You have signed up for [role]! A candidate will be picked randomly soon."))
to_chat(candidate, span_notice(response_messages[POLL_RESPONSE_SIGNUP]))
// Sign them up for any other polls with the same mob type
for(var/datum/candidate_poll/existing_poll as anything in SSpolling.currently_polling)
if(src != existing_poll && poll_key == existing_poll.poll_key && !(candidate in existing_poll.signed_up))
Expand All @@ -73,17 +92,17 @@
return FALSE
if(!(candidate in signed_up))
if(!silent)
to_chat(candidate, span_warning("You aren't signed up for this!"))
to_chat(candidate, span_warning(response_messages[POLL_RESPONSE_NOT_SIGNED]))
return FALSE

if(time_left() <= 0)
if(!silent)
to_chat(candidate, span_danger("It's too late to unregister yourself, selection has already begun!"))
to_chat(candidate, span_danger(response_messages[POLL_RESPONSE_TOO_LATE_TO_UNREGISTER]))
return FALSE

signed_up -= candidate
if(!silent)
to_chat(candidate, span_danger("You have been unregistered as a candidate for [role]. You can sign up again before the poll ends."))
to_chat(candidate, span_danger(response_messages[POLL_RESPONSE_UNREGISTERED]))

for(var/datum/candidate_poll/existing_poll as anything in SSpolling.currently_polling)
if(src != existing_poll && poll_key == existing_poll.poll_key && (candidate in existing_poll.signed_up))
Expand Down
6 changes: 4 additions & 2 deletions code/modules/antagonists/cult/cult.dm
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@
owner.current.update_mob_action_buttons()

for(var/datum/mind/cult_mind as anything in cult_team.members)
vote_ability.Remove(cult_mind.current)
var/datum/antagonist/cult/cult_datum = cult_mind.has_antag_datum(/datum/antagonist/cult)
cult_datum.vote_ability.Remove(cult_mind.current)
to_chat(cult_mind.current, span_cultlarge("[owner.current] has won the cult's support and is now their master. \
Follow [owner.current.p_their()] orders to the best of your ability!"))

Expand Down Expand Up @@ -234,7 +235,8 @@
throwing.Remove(owner.current)
owner.current.update_mob_action_buttons()
for(var/datum/mind/cult_mind as anything in cult_team.members)
vote_ability.Grant(cult_mind.current)
var/datum/antagonist/cult/cult_datum = cult_mind.has_antag_datum(/datum/antagonist/cult)
cult_datum.vote_ability.Grant(cult_mind.current)

to_chat(owner.current, span_cultlarge("You have been demoted from being the cult's Master, you are now an acolyte once more!"))

Expand Down
116 changes: 78 additions & 38 deletions code/modules/antagonists/cult/cult_comms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -99,60 +99,100 @@
/datum/action/innate/cult/mastervote/IsAvailable(feedback = FALSE)
if(!owner || !owner.mind)
return FALSE
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!C || C.cult_team.cult_vote_called || !ishuman(owner))
var/datum/antagonist/cult/mind_cult_datum = owner.mind.has_antag_datum(/datum/antagonist/cult)
if(!mind_cult_datum || mind_cult_datum.cult_team.cult_leader_datum || mind_cult_datum.cult_team.cult_vote_called || !ishuman(owner))
return FALSE
return ..()

/datum/action/innate/cult/mastervote/Activate()
var/choice = tgui_alert(owner, "The mantle of leadership is heavy. Success in this role requires an expert level of communication and experience. Are you sure?",, list("Yes", "No"))
if(choice == "Yes" && IsAvailable())
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
pollCultists(owner,C.cult_team)
var/datum/antagonist/cult/mind_cult_datum = owner.mind.has_antag_datum(/datum/antagonist/cult)
start_poll_cultists_for_leader(owner, mind_cult_datum.cult_team)

/proc/pollCultists(mob/living/Nominee, datum/team/cult/team) //Cult Master Poll
///Start the poll for Cult Leaeder.
/proc/start_poll_cultists_for_leader(mob/living/nominee, datum/team/cult/team)
if(world.time < CULT_POLL_WAIT)
to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].")
to_chat(nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].")
return
team.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_mob_action_buttons()
if(!B.current.incapacitated())
SEND_SOUND(B.current, 'sound/hallucinations/im_here1.ogg')
to_chat(B.current, span_cultlarge("Acolyte [Nominee] has asserted that [Nominee.p_theyre()] worthy of leading the cult. A vote will be called shortly."))
sleep(10 SECONDS)
var/list/asked_cultists = list()
for(var/datum/mind/B in team.members)
if(B.current && B.current != Nominee && !B.current.incapacitated())
SEND_SOUND(B.current, 'sound/magic/exit_blood.ogg')
asked_cultists += B.current
var/list/yes_voters = SSpolling.poll_candidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 30 SECONDS, group = asked_cultists, pic_source = Nominee, role_name_text = "cult master")
if(QDELETED(Nominee) || Nominee.incapacitated())
team.cult_vote_called = TRUE
for(var/datum/mind/team_member as anything in team.members)
if(!team_member.current)
continue
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
SEND_SOUND(team_member.current, 'sound/hallucinations/im_here1.ogg')
to_chat(team_member.current, span_cultlarge("Acolyte [nominee] has asserted that [nominee.p_theyre()] worthy of leading the cult. A vote will be called shortly."))

addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(poll_cultists_for_leader), nominee, team), 10 SECONDS)

///Polls all Cultists on whether the person putting themselves forward should be made the Cult Leader, if they can actually be such.
/proc/poll_cultists_for_leader(mob/living/nominee, datum/team/cult/team)
if(QDELETED(nominee) || nominee.incapacitated())
team.cult_vote_called = FALSE
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_mob_action_buttons()
if(!B.current.incapacitated())
to_chat(B.current,span_cultlarge("[Nominee] has died in the process of attempting to win the cult's support!"))
for(var/datum/mind/team_member as anything in team.members)
if(!team_member.current)
continue
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current,span_cultlarge("[nominee] has died in the process of attempting to start a vote!"))
return FALSE
if(!Nominee.mind)
var/list/mob/living/asked_cultists = list()
for(var/datum/mind/team_member as anything in team.members)
if(!team_member.current || team_member.current == nominee || team_member.current.incapacitated())
continue
SEND_SOUND(team_member.current, 'sound/magic/exit_blood.ogg')
asked_cultists += team_member.current

var/list/yes_voters = SSpolling.poll_candidates(
question = "[nominee] seeks to lead your cult, do you support [nominee.p_them()]?",
poll_time = 30 SECONDS,
group = asked_cultists,
pic_source = nominee,
role_name_text = "cult master",
custom_response_messages = list(
POLL_RESPONSE_SIGNUP = "You have pledged your allegience to [nominee].",
POLL_RESPONSE_ALREADY_SIGNED = "You have already pledged your allegience!",
POLL_RESPONSE_NOT_SIGNED = "You aren't nominated for this.",
POLL_RESPONSE_TOO_LATE_TO_UNREGISTER = "It's too late to unregister yourself, voting has already begun!",
POLL_RESPONSE_UNREGISTERED = "You have been removed your pledge to [nominee].",
)
)
if(QDELETED(nominee) || nominee.incapacitated())
team.cult_vote_called = FALSE
for(var/datum/mind/team_member as anything in team.members)
if(!team_member.current)
continue
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current,span_cultlarge("[nominee] has died in the process of attempting to win the cult's support!"))
return FALSE
if(!nominee.mind)
team.cult_vote_called = FALSE
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_mob_action_buttons()
if(!B.current.incapacitated())
to_chat(B.current,span_cultlarge("[Nominee] has gone catatonic in the process of attempting to win the cult's support!"))
for(var/datum/mind/team_member as anything in team.members)
if(!team_member.current)
continue
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current,span_cultlarge("[nominee] has gone catatonic in the process of attempting to win the cult's support!"))
return FALSE
if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5)
team.cult_vote_called = FALSE
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_mob_action_buttons()
if(!B.current.incapacitated())
to_chat(B.current, span_cultlarge("[Nominee] could not win the cult's support and shall continue to serve as an acolyte."))
for(var/datum/mind/team_member as anything in team.members)
if(!team_member.current)
continue
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current, span_cultlarge("[nominee] could not win the cult's support and shall continue to serve as an acolyte."))
return FALSE
var/datum/antagonist/cult/cult_datum = Nominee.mind.has_antag_datum(/datum/antagonist/cult)

team.cult_vote_called = FALSE
var/datum/antagonist/cult/cult_datum = nominee.mind.has_antag_datum(/datum/antagonist/cult)
if(!cult_datum.make_cult_leader())
CRASH("[cult_datum.owner.current] was supposed to turn into the leader, but they didn't for some reason. This isn't supposed to happen unless an Admin messed with it.")
return TRUE
Expand Down

0 comments on commit 4b60813

Please sign in to comment.