var/global/datum/controller/vote/vote = new() #define vote_head "" #define VOTE_SCREEN_WIDTH 400 #define VOTE_SCREEN_HEIGHT 400 /datum/html_interface/nanotrasen/vote/registerResources() . = ..() register_asset("voting.js", 'voting.js') register_asset("voting.css", 'voting.css') /datum/html_interface/nanotrasen/vote/sendAssets(var/client/client) ..() send_asset(client, "voting.js") send_asset(client, "voting.css") /datum/html_interface/nanotrasen/vote/Topic(href, href_list[]) ..() if(href_list["html_interface_action"] == "onclose") var/datum/html_interface_client/hclient = getClient(usr.client) if (istype(hclient)) src.hide(hclient) vote.voting -= usr.client /datum/controller/vote var/initiator = null var/started_time = null var/time_remaining = 0 var/mode = null var/question = null var/list/choices = list() var/list/voted = list() var/list/voting = list() var/list/current_votes = list() var/list/ismapvote var/chosen_map var/name = "datum" var/datum/html_interface/nanotrasen/vote/interface var/list/data var/list/status_data var/last_update = 0 var/initialized = 0 var/lastupdate = 0 /datum/controller/vote/New() . = ..() src.data = list() src.status_data = list() spawn(5) if(!src.interface) src.interface = new/datum/html_interface/nanotrasen/vote(src, "Voting Panel", 400, 400, vote_head) src.interface.updateContent("content", "
") initialized = 1 if (vote != src) if (istype(vote)) qdel(vote) vote = src //datum/controller/vote/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\//datum/controller/vote/proc/ui_interact() called tick#: [world.time]") // return /datum/controller/vote/proc/process() //called by master_controller //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/process() called tick#: [world.time]") if(mode) // No more change mode votes after the game has started. // 3 is GAME_STATE_PLAYING, but that #define is undefined for some reason if(mode == "gamemode" && ticker.current_state >= 2) 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 = (ismapvote && ismapvote.len) ? (round((started_time + 600 - world.time)/10)) : (round((started_time + config.vote_period - world.time)/10)) if(time_remaining <= 0) result() for(var/client/C in voting) if(C) //nanomanager.close_user_uis(C.mob, src) src.interface.hide(C) src.reset() else update(1) /datum/controller/vote/proc/reset() //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/reset() called tick#: [world.time]") initiator = null time_remaining = 0 mode = null question = null choices.len = 0 voted.len = 0 voting.len = 0 current_votes.len = 0 update(1) /datum/controller/vote/proc/get_result() //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/get_result() called tick#: [world.time]") //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 //default-vote for everyone who didn't vote if(!config.vote_no_default && choices.len) var/non_voters = (clients.len - total_votes) if(non_voters > 0) if(mode == "restart") choices["Continue Playing"] += non_voters if(choices["Continue Playing"] >= greatest_votes) greatest_votes = choices["Continue Playing"] else if(mode == "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 == "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"]) //get all options with that many votes and return them in a list . = list() if(greatest_votes) for(var/option in choices) if(choices[option] == greatest_votes) . += option return . /datum/controller/vote/proc/announce_result() //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/announce_result() called tick#: [world.time]") var/list/winners = get_result() var/text var/feedbackanswer if(winners.len > 0) if(winners.len > 1) text = "Vote Tied Between:
" for(var/option in winners) text += "\t[option]
" feedbackanswer = list2text(winners, " ") . = pick(winners) if(mode == "map") if(!feedbackanswer) feedbackanswer = . feedback_set("map vote winner", feedbackanswer) else feedback_set("map vote tie", "[feedbackanswer] chosen: [.]") text += "Vote Result: [.] with [choices[.]] vote\s" for(var/choice in choices) if(. == choice) continue text += "
\t [choice] had [choices[choice] != null ? choices[choice] : "0"] vote\s" else text += "Vote Result: Inconclusive - No Votes!" log_vote(text) world << "[text]" return . /datum/controller/vote/proc/result() //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/result() called tick#: [world.time]") . = announce_result() var/restart = 0 if(.) switch(mode) if("restart") if(. == "Restart Round") restart = 1 if("gamemode") if(master_mode != .) world.save_mode(.) if(ticker && ticker.mode) restart = 1 else master_mode = . if(!going) going = 1 world << "The round will start soon." if("crew_transfer") if(. == "Initiate Crew Transfer") init_shift_change(null, 1) if("map") if(.) chosen_map = ismapvote[.] var/mapname = . watchdog.chosen_map = copytext(mapname,1,(length(mapname))) log_game("Players voted and chose.... [watchdog.chosen_map]!") //testing("Vote picked [chosen_map]") if(restart) world << "World restarting due to vote..." feedback_set_details("end_error","restart vote") if(blackbox) blackbox.save_all_data_to_sql() CallHook("Reboot",list()) sleep(50) log_game("Rebooting due to restart vote") world.Reboot() return . /datum/controller/vote/proc/submit_vote(var/ckey, var/vote) //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/submit_vote() called tick#: [world.time]") if(mode) if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder) return 0 if(current_votes[ckey]) choices[choices[current_votes[ckey]]]-- if(vote && 1<=vote && vote<=choices.len) voted += usr.ckey choices[choices[vote]]++ //check this current_votes[ckey] = vote return vote return 0 /datum/controller/vote/proc/initiate_vote(var/vote_type, var/initiator_key, var/popup = 0) //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/datum/controller/vote/proc/initiate_vote() called tick#: [world.time]") if(!mode) if(started_time != null && !check_rights(R_ADMIN)) var/next_allowed_time = (started_time + config.vote_delay) if(next_allowed_time > world.time) return 0 reset() switch(vote_type) if("restart") choices.Add("Restart Round","Continue Playing") question = "Restart the round?" if("gamemode") if(ticker.current_state >= 2) return 0 choices.Add(config.votable_modes) question = "What gamemode?" if("crew_transfer") if(ticker.current_state <= 2) return 0 question = "End the shift?" choices.Add("Initiate Crew Transfer", "Continue The Round") if("custom") question = html_encode(input(usr,"What is the vote for?") as text|null) if(!question) return 0 for(var/i=1,i<=10,i++) var/option = capitalize(html_encode(input(usr,"Please enter an option or hit cancel to finish") as text|null)) if(!option || mode || !usr.client) break choices.Add(option) if("map") question = "What should the next map be?" var/list/maps = get_maps() for(var/key in maps) choices.Add(key) if(!choices.len) world << "Failed to initiate map vote, no maps found." return 0 ismapvote = maps else return 0 mode = vote_type initiator = initiator_key started_time = world.time var/text = "[capitalize(mode)] vote started by [initiator]." choices = shuffle(choices) if(mode == "custom") text += "
[question]" log_vote(text) update(1) if(popup) for(var/client/C in clients) interact(C) else if(istype(usr) && usr.client) interact(usr.client) world << "[text]
Type vote to place your votes.
You have [ismapvote && ismapvote.len ? "60" : config.vote_period/10] seconds to vote.
" switch(vote_type) if("crew_transfer") world << sound('sound/voice/Serithi/Shuttlehere.ogg') if("gamemode") world << sound('sound/voice/Serithi/pretenddemoc.ogg') if("custom") world << sound('sound/voice/Serithi/weneedvote.ogg') if("map") world << sound('sound/misc/rockthevote.ogg') if(mode == "gamemode" && going) going = 0 world << "Round start has been delayed." time_remaining = (ismapvote && ismapvote.len ? 60 : round(config.vote_period/10)) return 1 return 0 /datum/controller/vote/proc/updateFor(hclient_or_mob) //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\datum/interactive_map/proc/updateFor() called tick#: [world.time]") // This check will succeed if updateFor is called after showing to the player, but will fail // on regular updates. Since we only really need this once we don't care if it fails. interface.callJavaScript("clearAll", new/list(), hclient_or_mob) interface.callJavaScript("update_mode", status_data, hclient_or_mob) if(data.len) for (var/list/L in data) interface.callJavaScript("update_choices", L, hclient_or_mob) /datum/controller/vote/proc/interact(client/user) if(!user || !initialized) return if(ismob(user)) user = user:client voting |= user interface.show(user) var/list/client_data = list() var/admin = 0 var/currvote = 0 if(current_votes[user.ckey]) currvote = current_votes[user.ckey] client_data[++client_data.len] = (currvote) //interface.callJavascript("current_vote", current_votes[user.ckey]) if(user.holder) admin = 1 if(user.holder.rights & R_ADMIN) admin = 2 client_data[++client_data.len] = (admin) interface.callJavaScript("client_data", client_data, user) src.updateFor(user, interface) /datum/controller/vote/proc/update(refresh = 0) if(!interface) interface = new/datum/html_interface/nanotrasen/vote(src, "Voting Panel", 400, 400, vote_head) interface.updateContent("content", "
") if(world.time < last_update + 2) return last_update = world.time status_data.len = 0 status_data[++status_data.len] = mode status_data[++status_data.len] = question status_data[++status_data.len] = time_remaining if(config.allow_vote_restart) status_data[++status_data.len] = 1 else status_data[++status_data.len] = 0 if(config.allow_vote_mode) status_data[++status_data.len] = 1 else status_data[++status_data.len] = 0 var/list/choices_list = list() if(mode) for(var/i = 1; i <= choices.len; i++) choices_list[++choices_list.len] = list(i, choices[i], (!isnull(choices[choices[i]]) ? choices[choices[i]] : 0)) data = choices_list if(refresh && interface) updateFor() /datum/controller/vote/Topic(href,href_list[],hsrc) if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid switch(href_list["vote"]) if("cancel") if(usr.client.holder) reset() update() if("toggle_restart") if(usr.client.holder) config.allow_vote_restart = !config.allow_vote_restart update() if("toggle_gamemode") if(usr.client.holder) config.allow_vote_mode = !config.allow_vote_mode update() if("restart") if(config.allow_vote_restart || usr.client.holder) initiate_vote("restart",usr.key) if("gamemode") if(config.allow_vote_mode || usr.client.holder) initiate_vote("gamemode",usr.key) if("crew_transfer") if(config.allow_vote_restart || usr.client.holder) initiate_vote("crew_transfer",usr.key) if("custom") if(usr.client.holder) initiate_vote("custom",usr.key) else submit_vote(usr.ckey, round(text2num(href_list["vote"]))) usr.vote() /mob/verb/vote() set category = "OOC" set name = "Vote" //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/mob/verb/vote() called tick#: [world.time]") if(vote) if(!vote.initialized) usr << "The voting controller isn't fully initialized yet." else vote.interact(usr.client)