mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-16 20:52:33 +00:00
210 lines
6.2 KiB
Plaintext
210 lines
6.2 KiB
Plaintext
|
|
/**
|
|
* # Vote Singleton
|
|
*
|
|
* A singleton datum that represents a type of vote for the voting subsystem.
|
|
*/
|
|
/datum/vote
|
|
/// The name of the vote.
|
|
var/name
|
|
/// If supplied, an override question will be displayed instead of the name of the vote.
|
|
var/override_question
|
|
/// The sound effect played to everyone when this vote is initiated.
|
|
var/vote_sound = 'sound/misc/bloop.ogg'
|
|
/// A list of default choices we have for this vote.
|
|
var/list/default_choices
|
|
/// Does the name of this vote contain the word "vote"?
|
|
var/contains_vote_in_name = FALSE
|
|
/// What message do we want to pass to the player-side vote panel as a tooltip?
|
|
var/message = "Click to initiate a vote."
|
|
|
|
// Internal values used when tracking ongoing votes.
|
|
// Don't mess with these, change the above values / override procs for subtypes.
|
|
/// An assoc list of [all choices] to [number of votes in the current running vote].
|
|
var/list/choices = list()
|
|
/// A assoc list of [ckey] to [what they voted for in the current running vote].
|
|
var/list/choices_by_ckey = list()
|
|
/// The world time this vote was started.
|
|
var/started_time
|
|
/// The time remaining in this vote's run.
|
|
var/time_remaining
|
|
|
|
/**
|
|
* Used to determine if this vote is a possible
|
|
* vote type for the vote subsystem.
|
|
*
|
|
* If FALSE is returned, this vote singleton
|
|
* will not be created when the vote subsystem initializes,
|
|
* meaning no one will be able to hold this vote.
|
|
*/
|
|
/datum/vote/proc/is_accessible_vote()
|
|
return !!length(default_choices)
|
|
|
|
/**
|
|
* Resets our vote to its default state.
|
|
*/
|
|
/datum/vote/proc/reset()
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
choices.Cut()
|
|
choices_by_ckey.Cut()
|
|
started_time = null
|
|
time_remaining = null
|
|
|
|
/**
|
|
* If this vote has a config associated, toggles it between enabled and disabled.
|
|
* Returns TRUE on a successful toggle, FALSE otherwise
|
|
*/
|
|
/datum/vote/proc/toggle_votable(mob/toggler)
|
|
return FALSE
|
|
|
|
/**
|
|
* If this vote has a config associated, returns its value (True or False, usually).
|
|
* If it has no config, returns -1.
|
|
*/
|
|
/datum/vote/proc/is_config_enabled()
|
|
return -1
|
|
|
|
/**
|
|
* Checks if the passed mob can initiate this vote.
|
|
*
|
|
* Return TRUE if the mob can begin the vote, allowing anyone to actually vote on it.
|
|
* Return FALSE if the mob cannot initiate the vote.
|
|
*/
|
|
/datum/vote/proc/can_be_initiated(mob/by_who, forced = FALSE)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
if(started_time)
|
|
var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay))
|
|
if(next_allowed_time > world.time && !forced)
|
|
message = "A vote was initiated recently. You must wait [DisplayTimeText(next_allowed_time - world.time)] before a new vote can be started!"
|
|
return FALSE
|
|
|
|
message = initial(message)
|
|
return TRUE
|
|
|
|
/**
|
|
* Called prior to the vote being initiated.
|
|
*
|
|
* Return FALSE to prevent the vote from being initiated.
|
|
*/
|
|
/datum/vote/proc/create_vote(mob/vote_creator)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
for(var/key in default_choices)
|
|
choices[key] = 0
|
|
|
|
return TRUE
|
|
|
|
/**
|
|
* Called when this vote is actually initiated.
|
|
*
|
|
* Return a string - the text displayed to the world when the vote is initiated.
|
|
*/
|
|
/datum/vote/proc/initiate_vote(initiator, duration)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
started_time = world.time
|
|
time_remaining = round(duration / 10)
|
|
|
|
return "[contains_vote_in_name ? "[capitalize(name)]" : "[capitalize(name)] vote"] started by [initiator || "Central Command"]."
|
|
|
|
/**
|
|
* Gets the result of the vote.
|
|
*
|
|
* non_voters - a list of all ckeys who didn't vote in the vote.
|
|
*
|
|
* Returns a list of all options that won.
|
|
* If there were no votes at all, the list will be length = 0, non-null.
|
|
* If only one option one, the list will be length = 1.
|
|
* If there was a tie, the list will be length > 1.
|
|
*/
|
|
/datum/vote/proc/get_vote_result(list/non_voters)
|
|
RETURN_TYPE(/list)
|
|
|
|
var/list/winners = list()
|
|
var/highest_vote = 0
|
|
|
|
for(var/option in choices)
|
|
|
|
var/vote_count = choices[option]
|
|
// If we currently have no winners...
|
|
if(!length(winners))
|
|
// And the current option has any votes, it's the new highest.
|
|
if(vote_count > 0)
|
|
winners += option
|
|
highest_vote = vote_count
|
|
continue
|
|
|
|
// If we're greater than, and NOT equal to, the highest vote,
|
|
// we are the new supreme winner - clear all others
|
|
if(vote_count > highest_vote)
|
|
winners.Cut()
|
|
winners += option
|
|
highest_vote = vote_count
|
|
|
|
// If we're equal to the highest vote, we tie for winner
|
|
else if(vote_count == highest_vote)
|
|
winners += option
|
|
|
|
return winners
|
|
|
|
/**
|
|
* Gets the resulting text displayed when the vote is completed.
|
|
*
|
|
* all_winners - list of all options that won. Can be multiple, in the event of ties.
|
|
* real_winner - the option that actually won.
|
|
* non_voters - a list of all ckeys who didn't vote in the vote.
|
|
*
|
|
* Return a formatted string of text to be displayed to everyone.
|
|
*/
|
|
/datum/vote/proc/get_result_text(list/all_winners, real_winner, list/non_voters)
|
|
if(length(all_winners) <= 0 || !real_winner)
|
|
return span_bold("Vote Result: Inconclusive - No Votes!")
|
|
|
|
var/returned_text = ""
|
|
if(override_question)
|
|
returned_text += span_bold(override_question)
|
|
else
|
|
returned_text += span_bold("[capitalize(name)] Vote")
|
|
|
|
for(var/option in choices)
|
|
returned_text += "\n[span_bold(option)]: [choices[option]]"
|
|
|
|
returned_text += "\n"
|
|
returned_text += get_winner_text(all_winners, real_winner, non_voters)
|
|
|
|
return returned_text
|
|
|
|
/**
|
|
* Gets the text that displays the winning options within the result text.
|
|
*
|
|
* all_winners - list of all options that won. Can be multiple, in the event of ties.
|
|
* real_winner - the option that actually won.
|
|
* non_voters - a list of all ckeys who didn't vote in the vote.
|
|
*
|
|
* Return a formatted string of text to be displayed to everyone.
|
|
*/
|
|
/datum/vote/proc/get_winner_text(list/all_winners, real_winner, list/non_voters)
|
|
var/returned_text = ""
|
|
if(length(all_winners) > 1)
|
|
returned_text += "\n[span_bold("Vote Tied Between:")]"
|
|
for(var/a_winner in all_winners)
|
|
returned_text += "\n\t[a_winner]"
|
|
|
|
returned_text += span_bold("\nVote Result: [real_winner]")
|
|
return returned_text
|
|
|
|
/**
|
|
* How this vote handles a tiebreaker between multiple winners.
|
|
*/
|
|
/datum/vote/proc/tiebreaker(list/winners)
|
|
return pick(winners)
|
|
|
|
/**
|
|
* Called when a vote is actually all said and done.
|
|
* Apply actual vote effects here.
|
|
*/
|
|
/datum/vote/proc/finalize_vote(winning_option)
|
|
return
|