diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index 17c3ab8923..803c2c9b77 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -64,6 +64,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_ORBIT 8
+#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_AIRFLOW 30
#define FIRE_PRIORITY_AIR 35
diff --git a/code/__defines/vote.dm b/code/__defines/vote.dm
new file mode 100644
index 0000000000..48be19e909
--- /dev/null
+++ b/code/__defines/vote.dm
@@ -0,0 +1,5 @@
+#define VOTE_RESTART "restart"
+#define VOTE_GAMEMODE "gamemode"
+#define VOTE_CREW_TRANSFER "crew_transfer"
+#define VOTE_ADD_ANTAGONIST "add_antagonist"
+#define VOTE_CUSTOM "custom"
diff --git a/code/controllers/Processes/vote.dm b/code/controllers/Processes/vote.dm
deleted file mode 100644
index 5df5ce6979..0000000000
--- a/code/controllers/Processes/vote.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/controller/process/vote/setup()
- name = "vote"
- schedule_interval = 10 // every second
-
-/datum/controller/process/vote/doWork()
- vote.process()
diff --git a/code/controllers/autotransfer.dm b/code/controllers/autotransfer.dm
index afd1435ffa..85497af9ac 100644
--- a/code/controllers/autotransfer.dm
+++ b/code/controllers/autotransfer.dm
@@ -13,5 +13,5 @@ datum/controller/transfer_controller/Destroy()
datum/controller/transfer_controller/proc/process()
currenttick = currenttick + 1
if (round_duration_in_ticks >= timerbuffer - 1 MINUTE)
- vote.autotransfer()
+ SSvote.autotransfer()
timerbuffer = timerbuffer + config.vote_autotransfer_interval
diff --git a/code/controllers/voting.dm b/code/controllers/subsystems/vote.dm
similarity index 81%
rename from code/controllers/voting.dm
rename to code/controllers/subsystems/vote.dm
index ba1bb23c33..f4492c7d6f 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/subsystems/vote.dm
@@ -1,388 +1,373 @@
-var/datum/controller/vote/vote = new()
-
-var/global/list/round_voters = list() // Keeps track of the individuals voting for a given round, for use in forcedrafting.
-
-#define VOTE_RESTART "restart"
-#define VOTE_GAMEMODE "gamemode"
-#define VOTE_CREW_TRANSFER "crew_transfer"
-#define VOTE_ADD_ANTAGONIST "add_antagonist"
-#define VOTE_CUSTOM "custom"
-
-/datum/controller/vote
- var/initiator = null // Key of the one who started the vote or "the server"
- var/started_time = null
- var/time_remaining = 0
- var/mode = null
- var/question = null
- var/list/choices = list()
- var/list/gamemode_names = list()
- var/list/voted = list()
- var/list/current_votes = list()
- var/list/additional_text = list()
-
-/datum/controller/vote/New()
- if(vote != src)
- if(istype(vote))
- Recover()
- qdel(vote)
- vote = src
-
-/datum/controller/vote/Destroy()
- ..()
- // Tell qdel() to Del() this object.
- return QDEL_HINT_HARDDEL_NOW
-
-/datum/controller/vote/proc/process() //called by master_controller
- if(mode)
- // No more change mode votes after the game has started.
- if(mode == VOTE_GAMEMODE && ticker.current_state >= GAME_STATE_SETTING_UP)
- world << "Voting aborted due to game start."
- src.reset()
- return
-
- // Calculate how much time is remaining by comparing current time, to time of vote start,
- // plus vote duration
- time_remaining = round((started_time + config.vote_period - world.time)/10)
-
- if(time_remaining < 0)
- result()
- reset()
-
-/datum/controller/vote/proc/autotransfer()
- initiate_vote(VOTE_CREW_TRANSFER, "the server", 1)
- log_debug("The server has called a crew transfer vote")
-
-/datum/controller/vote/proc/autogamemode()
- initiate_vote(VOTE_GAMEMODE, "the server", 1)
- log_debug("The server has called a gamemode vote")
-
-/datum/controller/vote/proc/reset()
- initiator = null
- time_remaining = 0
- mode = null
- question = null
- choices.Cut()
- voted.Cut()
- current_votes.Cut()
- additional_text.Cut()
-
-/datum/controller/vote/proc/get_result() // Get the highest number of votes
- var/greatest_votes = 0
- var/total_votes = 0
-
- for(var/option in choices)
- var/votes = choices[option]
- total_votes += votes
- if(votes > greatest_votes)
- greatest_votes = votes
-
- if(!config.vote_no_default && choices.len) // Default-vote for everyone who didn't vote
- var/non_voters = (clients.len - total_votes)
- if(non_voters > 0)
- if(mode == VOTE_RESTART)
- choices["Continue Playing"] += non_voters
- if(choices["Continue Playing"] >= greatest_votes)
- greatest_votes = choices["Continue Playing"]
- else if(mode == VOTE_GAMEMODE)
- if(master_mode in choices)
- choices[master_mode] += non_voters
- if(choices[master_mode] >= greatest_votes)
- greatest_votes = choices[master_mode]
- else if(mode == VOTE_CREW_TRANSFER)
- var/factor = 0.5
- switch(world.time / (10 * 60)) // minutes
- if(0 to 60)
- factor = 0.5
- if(61 to 120)
- factor = 0.8
- if(121 to 240)
- factor = 1
- if(241 to 300)
- factor = 1.2
- else
- factor = 1.4
- choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
- world << "Crew Transfer Factor: [factor]"
- greatest_votes = max(choices["Initiate Crew Transfer"], choices["Continue The Round"])
-
- . = list() // Get all options with that many votes and return them in a list
- if(greatest_votes)
- for(var/option in choices)
- if(choices[option] == greatest_votes)
- . += option
-
-/datum/controller/vote/proc/announce_result()
- var/list/winners = get_result()
- var/text
- if(winners.len > 0)
- if(winners.len > 1)
- if(mode != VOTE_GAMEMODE || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
- text = "Vote Tied Between:\n"
- for(var/option in winners)
- text += "\t[option]\n"
- . = pick(winners)
-
- for(var/key in current_votes)
- if(choices[current_votes[key]] == .)
- round_voters += key // Keep track of who voted for the winning round.
- if(mode != VOTE_GAMEMODE || . == "Extended" || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes
- text += "Vote Result: [mode == VOTE_GAMEMODE ? gamemode_names[.] : .]"
- else
- text += "The vote has ended."
-
- else
- text += "Vote Result: Inconclusive - No Votes!"
- if(mode == VOTE_ADD_ANTAGONIST)
- antag_add_failed = 1
- log_vote(text)
- world << "[text]"
-
-/datum/controller/vote/proc/result()
- . = announce_result()
- var/restart = 0
- if(.)
- switch(mode)
- if(VOTE_RESTART)
- if(. == "Restart Round")
- restart = 1
- if(VOTE_GAMEMODE)
- if(master_mode != .)
- world.save_mode(.)
- if(ticker && ticker.mode)
- restart = 1
- else
- master_mode = .
- if(VOTE_CREW_TRANSFER)
- if(. == "Initiate Crew Transfer")
- init_shift_change(null, 1)
- if(VOTE_ADD_ANTAGONIST)
- if(isnull(.) || . == "None")
- antag_add_failed = 1
- else
- additional_antag_types |= antag_names_to_ids[.]
-
- if(mode == VOTE_GAMEMODE) //fire this even if the vote fails.
- if(!round_progressing)
- round_progressing = 1
- world << "The round will start soon."
-
- if(restart)
- world << "World restarting due to vote..."
- feedback_set_details("end_error", "restart vote")
- if(blackbox)
- blackbox.save_all_data_to_sql()
- sleep(50)
- log_game("Rebooting due to restart vote")
- world.Reboot()
-
-/datum/controller/vote/proc/submit_vote(var/ckey, var/newVote)
- if(mode)
- if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
- return
- if(current_votes[ckey])
- choices[choices[current_votes[ckey]]]--
- if(newVote && newVote >= 1 && newVote <= choices.len)
- choices[choices[newVote]]++
- current_votes[ckey] = newVote
- else
- current_votes[ckey] = null
-
-/datum/controller/vote/proc/initiate_vote(var/vote_type, var/initiator_key, var/automatic = 0)
- if(!mode)
- if(started_time != null && !(check_rights(R_ADMIN) || automatic))
- var/next_allowed_time = (started_time + config.vote_delay)
- if(next_allowed_time > world.time)
- return 0
-
- reset()
-
- switch(vote_type)
- if(VOTE_RESTART)
- choices.Add("Restart Round", "Continue Playing")
- if(VOTE_GAMEMODE)
- if(ticker.current_state >= GAME_STATE_SETTING_UP)
- return 0
- choices.Add(config.votable_modes)
- for(var/F in choices)
- var/datum/game_mode/M = gamemode_cache[F]
- if(!M)
- continue
- gamemode_names[M.config_tag] = capitalize(M.name) //It's ugly to put this here but it works
- additional_text.Add("
[M.required_players] | ")
- gamemode_names["secret"] = "Secret"
- if(VOTE_CREW_TRANSFER)
- if(!check_rights(R_ADMIN|R_MOD, 0)) // The gods care not for the affairs of the mortals
- if(get_security_level() == "red" || get_security_level() == "delta")
- initiator_key << "The current alert status is too high to call for a crew transfer!"
- return 0
- if(ticker.current_state <= GAME_STATE_SETTING_UP)
- initiator_key << "The crew transfer button has been disabled!"
- return 0
- question = "End the shift?"
- choices.Add("Initiate Crew Transfer", "Continue The Round")
- if(VOTE_ADD_ANTAGONIST)
- if(!config.allow_extra_antags || ticker.current_state >= GAME_STATE_SETTING_UP)
- return 0
- for(var/antag_type in all_antag_types)
- var/datum/antagonist/antag = all_antag_types[antag_type]
- if(!(antag.id in additional_antag_types) && antag.is_votable())
- choices.Add(antag.role_text)
- choices.Add("None")
- if(VOTE_CUSTOM)
- question = sanitizeSafe(input(usr, "What is the vote for?") as text|null)
- if(!question)
- return 0
- for(var/i = 1 to 10)
- var/option = capitalize(sanitize(input(usr, "Please enter an option or hit cancel to finish") as text|null))
- if(!option || mode || !usr.client)
- break
- choices.Add(option)
- else
- return 0
-
- mode = vote_type
- initiator = initiator_key
- started_time = world.time
- var/text = "[capitalize(mode)] vote started by [initiator]."
- if(mode == VOTE_CUSTOM)
- text += "\n[question]"
-
- log_vote(text)
-
- world << "[text]\nType vote or click here to place your votes.\nYou have [config.vote_period / 10] seconds to vote."
- if(vote_type == VOTE_CREW_TRANSFER || vote_type == VOTE_GAMEMODE || vote_type == VOTE_CUSTOM)
- world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
-
- if(mode == VOTE_GAMEMODE && round_progressing)
- round_progressing = 0
- world << "Round start has been delayed."
-
- time_remaining = round(config.vote_period / 10)
- return 1
- return 0
-
-/datum/controller/vote/proc/interface(var/client/C)
- if(!istype(C))
- return
- var/admin = 0
- if(C.holder)
- if(C.holder.rights & R_ADMIN)
- admin = 1
-
- . = "Voting Panel"
- if(mode)
- if(question)
- . += "Vote: '[question]'
"
- else
- . += "Vote: [capitalize(mode)]
"
- . += "Time Left: [time_remaining] s
"
- . += "| Choices | Votes | "
- if(mode == VOTE_GAMEMODE)
- .+= "Minimum Players |
"
-
- for(var/i = 1 to choices.len)
- var/votes = choices[choices[i]]
- if(!votes)
- votes = 0
- . += ""
- var/thisVote = (current_votes[C.ckey] == i)
- if(mode == VOTE_GAMEMODE)
- . += "| [thisVote ? "" : ""][gamemode_names[choices[i]]][thisVote ? "" : ""] | [votes] | "
- else
- . += "[thisVote ? "" : ""][choices[i]][thisVote ? "" : ""] | [votes] | "
- if (additional_text.len >= i)
- . += additional_text[i]
- . += "
"
-
- . += "| Unvote |
"
-
- . += "
"
- if(admin)
- . += "(Cancel Vote) "
- else
- . += "Start a vote:
"
-
- . += "Close"
-
-/datum/controller/vote/Topic(href, href_list[])
- if(!usr || !usr.client)
- return
- switch(href_list["vote"])
- if("close")
- usr << browse(null, "window=vote")
- return
-
- if("cancel")
- if(usr.client.holder)
- reset()
- if("toggle_restart")
- if(usr.client.holder)
- config.allow_vote_restart = !config.allow_vote_restart
- if("toggle_gamemode")
- if(usr.client.holder)
- config.allow_vote_mode = !config.allow_vote_mode
-
- if(VOTE_RESTART)
- if(config.allow_vote_restart || usr.client.holder)
- initiate_vote(VOTE_RESTART, usr.key)
- if(VOTE_GAMEMODE)
- if(config.allow_vote_mode || usr.client.holder)
- initiate_vote(VOTE_GAMEMODE, usr.key)
- if(VOTE_CREW_TRANSFER)
- if(config.allow_vote_restart || usr.client.holder)
- initiate_vote(VOTE_CREW_TRANSFER, usr.key)
- if(VOTE_ADD_ANTAGONIST)
- if(config.allow_extra_antags || usr.client.holder)
- initiate_vote(VOTE_ADD_ANTAGONIST, usr.key)
- if(VOTE_CUSTOM)
- if(usr.client.holder)
- initiate_vote(VOTE_CUSTOM, usr.key)
-
- if("unvote")
- submit_vote(usr.ckey, null)
-
- else
- var/t = round(text2num(href_list["vote"]))
- if(t) // It starts from 1, so there's no problem
- submit_vote(usr.ckey, t)
- usr.client.vote()
-
-/client/verb/vote()
- set category = "OOC"
- set name = "Vote"
-
- if(vote)
- src << browse(vote.interface(src), "window=vote;size=500x[300 + vote.choices.len * 25]")
+SUBSYSTEM_DEF(vote)
+ name = "Vote"
+ wait = 10
+ priority = FIRE_PRIORITY_VOTE
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ flags = SS_KEEP_TIMING | SS_NO_INIT
+ var/list/round_voters = list()
+
+ //Current vote
+ var/initiator
+ var/started_time
+ var/time_remaining
+ var/duration
+ var/mode
+ var/question
+ var/list/choices = list()
+ var/list/gamemode_names = list()
+ var/list/voted = list()
+ var/list/current_votes = list()
+ var/list/additional_text = list()
+
+/datum/controller/subsystem/vote/fire(resumed)
+ if(mode)
+ time_remaining = round((started_time + duration - world.time)/10)
+ if(mode == VOTE_GAMEMODE && ticker.current_state >= GAME_STATE_SETTING_UP)
+ to_chat(world, "Gamemode vote aborted: Game has alread ystarted.")
+ reset()
+ return
+ if(time_remaining <= 0)
+ result()
+ reset()
+
+/datum/controller/subsystem/vote/proc/autotransfer()
+ initiate_vote(VOTE_CREW_TRANSFER, "the server", 1)
+ log_debug("The server has called a crew transfer vote.")
+
+/datum/controller/subsystem/vote/proc/autogamemode()
+ initiate_vote(VOTE_GAMEMODE, "the server", 1)
+ log_debug("The server has called a gamemode vote.")
+
+/datum/controller/subsystem/vote/proc/reset()
+ initiator = null
+ started_time = null
+ duration = null
+ time_remaining = null
+ mode = null
+ question = null
+ choices.Cut()
+ voted.Cut()
+ current_votes.Cut()
+ additional_text.Cut()
+
+/datum/controller/subsystem/vote/proc/get_result() // Get the highest number of votes
+ var/greatest_votes = 0
+ var/total_votes = 0
+
+ for(var/option in choices)
+ var/votes = choices[option]
+ total_votes += votes
+ if(votes > greatest_votes)
+ greatest_votes = votes
+
+ if(!config.vote_no_default && choices.len) // Default-vote for everyone who didn't vote
+ var/non_voters = (clients.len - total_votes)
+ if(non_voters > 0)
+ if(mode == VOTE_RESTART)
+ choices["Continue Playing"] += non_voters
+ if(choices["Continue Playing"] >= greatest_votes)
+ greatest_votes = choices["Continue Playing"]
+ else if(mode == VOTE_GAMEMODE)
+ if(master_mode in choices)
+ choices[master_mode] += non_voters
+ if(choices[master_mode] >= greatest_votes)
+ greatest_votes = choices[master_mode]
+ else if(mode == VOTE_CREW_TRANSFER)
+ var/factor = 0.5
+ switch(world.time / (10 * 60)) // minutes
+ if(0 to 60)
+ factor = 0.5
+ if(61 to 120)
+ factor = 0.8
+ if(121 to 240)
+ factor = 1
+ if(241 to 300)
+ factor = 1.2
+ else
+ factor = 1.4
+ choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
+ world << "Crew Transfer Factor: [factor]"
+ greatest_votes = max(choices["Initiate Crew Transfer"], choices["Continue The Round"])
+
+ . = list() // Get all options with that many votes and return them in a list
+ if(greatest_votes)
+ for(var/option in choices)
+ if(choices[option] == greatest_votes)
+ . += option
+
+/datum/controller/subsystem/vote/proc/announce_result()
+ var/list/winners = get_result()
+ var/text
+ if(winners.len > 0)
+ if(winners.len > 1)
+ if(mode != VOTE_GAMEMODE || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
+ text = "Vote Tied Between:\n"
+ for(var/option in winners)
+ text += "\t[option]\n"
+ . = pick(winners)
+
+ for(var/key in current_votes)
+ if(choices[current_votes[key]] == .)
+ round_voters += key // Keep track of who voted for the winning round.
+ if(mode != VOTE_GAMEMODE || . == "Extended" || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes
+ text += "Vote Result: [mode == VOTE_GAMEMODE ? gamemode_names[.] : .]"
+ else
+ text += "The vote has ended."
+
+ else
+ text += "Vote Result: Inconclusive - No Votes!"
+ if(mode == VOTE_ADD_ANTAGONIST)
+ antag_add_failed = 1
+ log_vote(text)
+ to_chat(world, "[text]")
+
+/datum/controller/subsystem/vote/proc/result()
+ . = announce_result()
+ var/restart = 0
+ if(.)
+ switch(mode)
+ if(VOTE_RESTART)
+ if(. == "Restart Round")
+ restart = 1
+ if(VOTE_GAMEMODE)
+ if(master_mode != .)
+ world.save_mode(.)
+ if(ticker && ticker.mode)
+ restart = 1
+ else
+ master_mode = .
+ if(VOTE_CREW_TRANSFER)
+ if(. == "Initiate Crew Transfer")
+ init_shift_change(null, 1)
+ if(VOTE_ADD_ANTAGONIST)
+ if(isnull(.) || . == "None")
+ antag_add_failed = 1
+ else
+ additional_antag_types |= antag_names_to_ids[.]
+
+ if(mode == VOTE_GAMEMODE) //fire this even if the vote fails.
+ if(!round_progressing)
+ round_progressing = 1
+ world << "The round will start soon."
+
+ if(restart)
+ world << "World restarting due to vote..."
+ feedback_set_details("end_error", "restart vote")
+ if(blackbox)
+ blackbox.save_all_data_to_sql()
+ sleep(50)
+ log_game("Rebooting due to restart vote")
+ world.Reboot()
+
+/datum/controller/subsystem/vote/proc/submit_vote(ckey, newVote)
+ if(mode)
+ if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
+ return
+ if(current_votes[ckey])
+ choices[choices[current_votes[ckey]]]--
+ if(newVote && newVote >= 1 && newVote <= choices.len)
+ choices[choices[newVote]]++
+ current_votes[ckey] = newVote
+ else
+ current_votes[ckey] = null
+
+/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, automatic = FALSE, time = config.vote_period)
+ if(!mode)
+ if(started_time != null && !(check_rights(R_ADMIN) || automatic))
+ var/next_allowed_time = (started_time + config.vote_delay)
+ if(next_allowed_time > world.time)
+ return 0
+
+ reset()
+
+ switch(vote_type)
+ if(VOTE_RESTART)
+ choices.Add("Restart Round", "Continue Playing")
+ if(VOTE_GAMEMODE)
+ if(ticker.current_state >= GAME_STATE_SETTING_UP)
+ return 0
+ choices.Add(config.votable_modes)
+ for(var/F in choices)
+ var/datum/game_mode/M = gamemode_cache[F]
+ if(!M)
+ continue
+ gamemode_names[M.config_tag] = capitalize(M.name) //It's ugly to put this here but it works
+ additional_text.Add("[M.required_players] | ")
+ gamemode_names["secret"] = "Secret"
+ if(VOTE_CREW_TRANSFER)
+ if(!check_rights(R_ADMIN|R_MOD, 0)) // The gods care not for the affairs of the mortals
+ if(get_security_level() == "red" || get_security_level() == "delta")
+ initiator_key << "The current alert status is too high to call for a crew transfer!"
+ return 0
+ if(ticker.current_state <= GAME_STATE_SETTING_UP)
+ initiator_key << "The crew transfer button has been disabled!"
+ return 0
+ question = "End the shift?"
+ choices.Add("Initiate Crew Transfer", "Continue The Round")
+ if(VOTE_ADD_ANTAGONIST)
+ if(!config.allow_extra_antags || ticker.current_state >= GAME_STATE_SETTING_UP)
+ return 0
+ for(var/antag_type in all_antag_types)
+ var/datum/antagonist/antag = all_antag_types[antag_type]
+ if(!(antag.id in additional_antag_types) && antag.is_votable())
+ choices.Add(antag.role_text)
+ choices.Add("None")
+ if(VOTE_CUSTOM)
+ question = sanitizeSafe(input(usr, "What is the vote for?") as text|null)
+ if(!question)
+ return 0
+ for(var/i = 1 to 10)
+ var/option = capitalize(sanitize(input(usr, "Please enter an option or hit cancel to finish") as text|null))
+ if(!option || mode || !usr.client)
+ break
+ choices.Add(option)
+ else
+ return 0
+
+ mode = vote_type
+ initiator = initiator_key
+ started_time = world.time
+ duration = time
+ var/text = "[capitalize(mode)] vote started by [initiator]."
+ if(mode == VOTE_CUSTOM)
+ text += "\n[question]"
+
+ log_vote(text)
+
+ world << "[text]\nType vote or click here to place your votes.\nYou have [config.vote_period / 10] seconds to vote."
+ if(vote_type == VOTE_CREW_TRANSFER || vote_type == VOTE_GAMEMODE || vote_type == VOTE_CUSTOM)
+ world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
+
+ if(mode == VOTE_GAMEMODE && round_progressing)
+ round_progressing = 0
+ world << "Round start has been delayed."
+
+ time_remaining = round(config.vote_period / 10)
+ return 1
+ return 0
+
+/datum/controller/subsystem/vote/proc/interface(var/client/C)
+ if(!istype(C))
+ return
+ var/admin = FALSE
+ if(C.holder)
+ if(C.holder.rights & R_ADMIN)
+ admin = TRUE
+
+ . = "Voting Panel"
+ if(mode)
+ if(question)
+ . += "Vote: '[question]'
"
+ else
+ . += "Vote: [capitalize(mode)]
"
+ . += "Time Left: [time_remaining] s
"
+ . += "| Choices | Votes | "
+ if(mode == VOTE_GAMEMODE)
+ .+= "Minimum Players |
"
+
+ for(var/i = 1 to choices.len)
+ var/votes = choices[choices[i]]
+ if(!votes)
+ votes = 0
+ . += ""
+ var/thisVote = (current_votes[C.ckey] == i)
+ if(mode == VOTE_GAMEMODE)
+ . += "| [thisVote ? "" : ""][gamemode_names[choices[i]]][thisVote ? "" : ""] | [votes] | "
+ else
+ . += "[thisVote ? "" : ""][choices[i]][thisVote ? "" : ""] | [votes] | "
+ if (additional_text.len >= i)
+ . += additional_text[i]
+ . += "
"
+
+ . += "| Unvote |
"
+
+ . += "
"
+ if(admin)
+ . += "(Cancel Vote) "
+ else
+ . += "Start a vote:
"
+
+ . += "Close"
+
+/datum/controller/subsystem/vote/Topic(href, href_list[])
+ if(!usr || !usr.client)
+ return
+ switch(href_list["vote"])
+ if("close")
+ usr << browse(null, "window=vote")
+ return
+
+ if("cancel")
+ if(usr.client.holder)
+ reset()
+ if("toggle_restart")
+ if(usr.client.holder)
+ config.allow_vote_restart = !config.allow_vote_restart
+ if("toggle_gamemode")
+ if(usr.client.holder)
+ config.allow_vote_mode = !config.allow_vote_mode
+
+ if(VOTE_RESTART)
+ if(config.allow_vote_restart || usr.client.holder)
+ initiate_vote(VOTE_RESTART, usr.key)
+ if(VOTE_GAMEMODE)
+ if(config.allow_vote_mode || usr.client.holder)
+ initiate_vote(VOTE_GAMEMODE, usr.key)
+ if(VOTE_CREW_TRANSFER)
+ if(config.allow_vote_restart || usr.client.holder)
+ initiate_vote(VOTE_CREW_TRANSFER, usr.key)
+ if(VOTE_ADD_ANTAGONIST)
+ if(config.allow_extra_antags || usr.client.holder)
+ initiate_vote(VOTE_ADD_ANTAGONIST, usr.key)
+ if(VOTE_CUSTOM)
+ if(usr.client.holder)
+ initiate_vote(VOTE_CUSTOM, usr.key)
+
+ if("unvote")
+ submit_vote(usr.ckey, null)
+
+ else
+ var/t = round(text2num(href_list["vote"]))
+ if(t) // It starts from 1, so there's no problem
+ submit_vote(usr.ckey, t)
+ usr.client.vote()
+
+/client/verb/vote()
+ set category = "OOC"
+ set name = "Vote"
+
+ if(SSvote)
+ src << browse(SSvote.interface(src), "window=vote;size=500x[300 + SSvote.choices.len * 25]")
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index 113072af4f..81842815a1 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -130,8 +130,4 @@
if("Chemistry")
debug_variables(chemistryProcess)
feedback_add_details("admin_verb", "DChem")
- if("Vote")
- debug_variables(vote)
- feedback_add_details("admin_verb", "DVote")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
- return
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 15113de8ab..eb3faaf64d 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -43,29 +43,25 @@ var/global/datum/controller/gameticker/ticker
'sound/music/title2.ogg',\
'sound/music/clouds.s3m',\
'sound/music/space_oddity.ogg') //Ground Control to Major Tom, this song is cool, what's going on?
-
+
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
-
- do
+
+ do
pregame_timeleft = 180
to_chat(world, "Welcome to the pregame lobby!")
to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")
while(current_state == GAME_STATE_PREGAME)
- for(var/i=0, i<10, i++)
- sleep(1)
- vote.process()
if(round_progressing)
pregame_timeleft--
if(pregame_timeleft == config.vote_autogamemode_timeleft)
- if(!vote.time_remaining)
- vote.autogamemode() //Quit calling this over and over and over and over.
- while(vote.time_remaining)
- for(var/i=0, i<10, i++)
- sleep(1)
- vote.process()
+ if(!SSvote.time_remaining)
+ SSvote.autogamemode() //Quit calling this over and over and over and over.
+ while(SSvote.time_remaining)
+ sleep(1)
if(pregame_timeleft <= 0)
current_state = GAME_STATE_SETTING_UP
Master.SetRunLevel(RUNLEVEL_SETUP)
+ sleep(10)
while (!setup())
@@ -90,7 +86,7 @@ var/global/datum/controller/gameticker/ticker
src.mode = gamemode_cache[pickweight(weighted_modes)]
else
src.mode = config.pick_mode(master_mode)
-
+
if(!src.mode)
current_state = GAME_STATE_PREGAME
Master.SetRunLevel(RUNLEVEL_LOBBY)
@@ -375,7 +371,7 @@ var/global/datum/controller/gameticker/ticker
if(!round_end_announced) // Spam Prevention. Now it should announce only once.
to_chat(world, "The round has ended!")
round_end_announced = 1
- vote.autotransfer()
+ SSvote.autotransfer()
return 1
diff --git a/polaris.dme b/polaris.dme
index 96695fcba4..367b169627 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -54,6 +54,7 @@
#include "code\__defines\targeting.dm"
#include "code\__defines\turfs.dm"
#include "code\__defines\unit_tests.dm"
+#include "code\__defines\vote.dm"
#include "code\__defines\xenoarcheaology.dm"
#include "code\__defines\ZAS.dm"
#include "code\_compatibility\509\_JSON.dm"
@@ -168,7 +169,6 @@
#include "code\controllers\master_controller.dm"
#include "code\controllers\subsystem.dm"
#include "code\controllers\verbs.dm"
-#include "code\controllers\voting.dm"
#include "code\controllers\observer_listener\atom\observer.dm"
#include "code\controllers\Processes\alarm.dm"
#include "code\controllers\Processes\chemistry.dm"
@@ -185,7 +185,6 @@
#include "code\controllers\Processes\supply.dm"
#include "code\controllers\Processes\ticker.dm"
#include "code\controllers\Processes\turf.dm"
-#include "code\controllers\Processes\vote.dm"
#include "code\controllers\ProcessScheduler\core\process.dm"
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
#include "code\controllers\subsystems\air.dm"
@@ -199,6 +198,7 @@
#include "code\controllers\subsystems\overlays.dm"
#include "code\controllers\subsystems\planets.dm"
#include "code\controllers\subsystems\shuttles.dm"
+#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\xenoarch.dm"
#include "code\datums\ai_law_sets.dm"
#include "code\datums\ai_laws.dm"