forked from tgstation/tgstation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_vote_datum.dm
211 lines (179 loc) · 6.28 KB
/
_vote_datum.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
* # 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
/// The counting method we use for votes.
var/count_method = VOTE_COUNT_METHOD_SINGLE
/**
* 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