From 6cf332bfa77be73c644e5d7c77c5789240b4f073 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sat, 13 May 2017 04:37:43 -0500 Subject: [PATCH] Merge voting controller into SSvote (#2183) changes: Merged the voting controller into the voting subsystem. Changed the voting UI to use /datum/browser. Converted /datum/browser to use HTML5 & attempt to use edge if available. All users of the browser datum have been confirmed functional with Edge. Changed the ChemMaster to use SSassets for resource download. --- baystation12.dme | 1 - code/controllers/subsystems/ticker.dm | 7 +- code/controllers/subsystems/vote.dm | 457 ++++++++++++++++++- code/controllers/voting.dm | 436 ------------------ code/datums/browser.dm | 3 +- code/game/gamemodes/game_mode.dm | 2 +- code/modules/client/asset_cache.dm | 19 + code/modules/mob/mob.dm | 2 +- code/modules/reagents/Chemistry-Machinery.dm | 19 +- code/modules/telesci/telesci_computer.dm | 4 +- html/changelogs/lohikar-vote.yml | 4 + 11 files changed, 494 insertions(+), 460 deletions(-) delete mode 100644 code/controllers/voting.dm create mode 100644 html/changelogs/lohikar-vote.yml diff --git a/baystation12.dme b/baystation12.dme index b8c20e305f4..17eac17015a 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -137,7 +137,6 @@ #include "code\controllers\hooks-defs.dm" #include "code\controllers\hooks.dm" #include "code\controllers\verbs.dm" -#include "code\controllers\voting.dm" #include "code\controllers\master\admin.dm" #include "code\controllers\master\failsafe.dm" #include "code\controllers\master\master.dm" diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index 9ae08fe2a7d..1babbcd9bf4 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -125,8 +125,9 @@ var/datum/controller/subsystem/ticker/SSticker pregame_timeleft-- if (current_state == GAME_STATE_PREGAME && pregame_timeleft == config.vote_autogamemode_timeleft) - if (!vote.time_remaining) - vote.autogamemode() + if (!SSvote.time_remaining) + SSvote.autogamemode() + pregame_timeleft-- return if (pregame_timeleft <= 10 && !tipped) @@ -196,7 +197,7 @@ var/datum/controller/subsystem/ticker/SSticker if(!round_end_announced) // Spam Prevention. Now it should announce only once. world << "The round has ended!" round_end_announced = 1 - vote.autotransfer() + SSvote.autotransfer() return 1 diff --git a/code/controllers/subsystems/vote.dm b/code/controllers/subsystems/vote.dm index 6a444ffd452..68653520008 100644 --- a/code/controllers/subsystems/vote.dm +++ b/code/controllers/subsystems/vote.dm @@ -2,18 +2,467 @@ var/datum/controller/subsystem/vote/SSvote /datum/controller/subsystem/vote name = "Voting" - wait = 1 SECONDS - flags = SS_KEEP_TIMING | SS_FIRE_IN_LOBBY + wait = 1 SECOND + flags = SS_KEEP_TIMING | SS_FIRE_IN_LOBBY | SS_NO_TICK_CHECK priority = SS_PRIORITY_VOTE var/next_transfer_time + var/initiator = null + 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/voting = list() + var/list/current_votes = list() + var/list/additional_text = list() + var/auto_muted = 0 + var/last_transfer_vote = null + + var/list/round_voters = list() + +/datum/controller/subsystem/vote/New() + NEW_SS_GLOBAL(SSvote) + /datum/controller/subsystem/vote/Initialize(timeofday) next_transfer_time = config.vote_autotransfer_initial /datum/controller/subsystem/vote/fire(resumed = FALSE) - vote.process() + if (mode) + // No more change mode votes after the game has started. + if(mode == "gamemode" && ROUND_IS_STARTED) + 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() + for(var/client/C in voting) + if(C) + if (C.vote_window) + C.vote_window.close() + else + log_debug("SSvote: Client [C] had no vote_window but was in voting list!") + + reset() + else + for(var/client/C in voting) + if(C) + if (C.vote_window) + C.vote_window.open() + else + log_debug("SSvote: Client [C]'s vote_window was missing!") + setup_vote_window(C) + C.vote_window.open() + + voting.Cut() if (world.time >= next_transfer_time - 600) - vote.autotransfer() + autotransfer() next_transfer_time += config.vote_autotransfer_interval + +/datum/controller/subsystem/vote/proc/autotransfer() + initiate_vote("crew_transfer","the server", 1) + log_debug("The server has called a crew transfer vote") + +/datum/controller/subsystem/vote/proc/autogamemode() + initiate_vote("gamemode","the server", 1) + log_debug("The server has called a gamemode vote") + +/datum/controller/subsystem/vote/proc/reset() + initiator = null + time_remaining = 0 + mode = null + question = null + choices.Cut() + voted.Cut() + voting.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 + //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"]) + + if(mode == "crew_transfer") + if(round(world.time / 36000)+12 <= 14) + // Credit to Scopes @ oldcode. + world << "Majority voting rule in effect. 2/3rds majority needed to initiate transfer." + choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] - round(total_votes / 3)) + 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 + +/datum/controller/subsystem/vote/proc/announce_result() + var/list/winners = get_result() + var/text + if(winners.len > 0) + if(winners.len > 1) + if(mode != "gamemode" || SSticker.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 == "gamemode" && . == "Extended") || SSticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes + text += "Vote Result: [.]" + else + if(mode != "gamemode") + text += "Vote Result: [.]" + else + text += "The vote has ended." // What will be shown if it is a gamemode vote that isn't extended + + else + text += "Vote Result: Inconclusive - No Votes!" + if(mode == "add_antagonist") + antag_add_failed = 1 + log_vote(text) + world << "[text]" + +/datum/controller/subsystem/vote/proc/result() + . = announce_result() + var/restart = 0 + if(.) + switch(mode) + if("restart") + if(. == "Restart Round") + restart = 1 + if("gamemode") + if(master_mode != .) + world.save_mode(.) + if(SSticker.mode) + restart = 1 + else + master_mode = . + if("crew_transfer") + if(. == "Initiate Crew Transfer") + init_shift_change(null, 1) + last_transfer_vote = world.time + if("add_antagonist") + if(isnull(.) || . == "None") + antag_add_failed = 1 + else + additional_antag_types |= antag_names_to_ids[.] + + if(mode == "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") + sleep(50) + log_game("Rebooting due to restart vote") + world.Reboot() + +/datum/controller/subsystem/vote/proc/submit_vote(ckey, vote) + if(mode) + if (mode == "crew_transfer") + if(config.vote_no_dead && usr && !usr.client.holder) + if (isnewplayer(usr)) + usr << "You must be playing or have been playing to start a vote." + return 0 + else if (isobserver(usr)) + var/mob/dead/observer/O = usr + if (O.started_as_observer) + usr << "You must be playing or have been playing to start a vote." + return 0 + if(vote && vote >= 1 && vote <= choices.len) + if(current_votes[ckey]) + choices[choices[current_votes[ckey]]]-- + voted += usr.ckey + choices[choices[vote]]++ //check this + current_votes[ckey] = vote + return vote + return 0 + + +/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, automatic = FALSE) + if(!mode) + if(started_time != null && !(check_rights(R_ADMIN|R_MOD) || automatic)) + // Transfer votes are their own little special snowflake + var/next_allowed_time = 0 + if (vote_type == "crew_transfer") + if (config.vote_no_dead && !usr.client.holder) + if (isnewplayer(usr)) + usr << "You must be playing or have been playing to start a vote." + return 0 + else if (isobserver(usr)) + var/mob/dead/observer/O = usr + if (O.started_as_observer) + usr << "You must be playing or have been playing to start a vote." + return 0 + + if (last_transfer_vote) + next_allowed_time = (last_transfer_vote + config.vote_delay) + else + next_allowed_time = config.transfer_timeout + else + 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") + if("gamemode") + if(SSticker.current_state >= 2) + 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("crew_transfer") + if(check_rights(R_ADMIN|R_MOD, 0)) + question = "End the shift?" + choices.Add("Initiate Crew Transfer", "Continue The Round") + else + 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(SSticker.current_state <= 2) + return 0 + initiator_key << "The crew transfer button has been disabled!" + question = "End the shift?" + choices.Add("Initiate Crew Transfer", "Continue The Round") + if("add_antagonist") + if(!config.allow_extra_antags || SSticker.current_state >= 2) + 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("custom") + question = sanitizeSafe(input(usr,"What is the vote for?") as text|null) + if(!question) return 0 + for(var/i=1,i<=10,i++) + 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 == "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." + for(var/cc in clients) + var/client/C = cc + if(C.prefs.asfx_togs & ASFX_VOTE) //Personal mute + switch(vote_type) + if("crew_transfer") + C << sound('sound/effects/vote.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) + if("gamemode") + C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) + if("custom") + C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) + if(mode == "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(client/C) + if(!C) + return + var/is_staff = 0 + if(C.holder) + if(C.holder.rights & (R_ADMIN|R_MOD)) + is_staff = 1 + voting |= C + + . = "" + if(mode) + if(question) . += "

Vote: '[question]'

" + else . += "

Vote: [capitalize(mode)]

" + . += "Time Left: [time_remaining] s
" + . += "" + if(capitalize(mode) == "Gamemode") .+= "" + + for(var/i = 1, i <= choices.len, i++) + var/votes = choices[choices[i]] + if(!votes) votes = 0 + . += "" + if(mode == "gamemode") + if(current_votes[C.ckey] == i) + . += "" + else + . += "" + else + if(current_votes[C.ckey] == i) + . += "" + else + . += "" + if (additional_text.len >= i) + . += additional_text[i] + . += "" + + . += "
ChoicesVotesMinimum Players
[gamemode_names[choices[i]]][votes][gamemode_names[choices[i]]][votes][choices[i]][votes][choices[i]][votes]

" + if(is_staff) + . += "(Cancel Vote) " + else + . += "

Start a vote:



" + . += "Close" + +/datum/controller/subsystem/vote/Topic(href, list/href_list = list(), hsrc) + if(!usr || !usr.client) + return //not necessary but meh...just in-case somebody does something stupid + + switch(href_list["vote"]) + if("close") + voting -= usr.client + if (usr.client.vote_window) + usr.client.vote_window.close() + else + log_debug("SSvote: User [usr] had an invalid vote_window, but was the source of a Topic() call!") + 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("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("add_antagonist") + if(config.allow_extra_antags) + initiate_vote("add_antagonist",usr.key) + if("custom") + if(usr.client.holder) + initiate_vote("custom",usr.key) + 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.vote() + +/datum/controller/subsystem/vote/proc/setup_vote_window(client/C) + if (!QDELETED(C.vote_window)) + return + + C.vote_window = new(C.mob, "vote", "Voting") + C.vote_window.add_head_content("Voting panel") + +/mob/verb/vote() + set category = "OOC" + set name = "Vote" + + if (!client.vote_window) + SSvote.setup_vote_window(client) + + var/datum/browser/vote_window = client.vote_window + + vote_window.set_user(src) + vote_window.set_content(SSvote.interface(client)) + vote_window.open() + +/client + var/tmp/datum/browser/vote_window diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm deleted file mode 100644 index 1109b4fd0b9..00000000000 --- a/code/controllers/voting.dm +++ /dev/null @@ -1,436 +0,0 @@ -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. - -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/gamemode_names = list() - var/list/voted = list() - var/list/voting = list() - var/list/current_votes = list() - var/list/additional_text = list() - var/auto_muted = 0 - var/last_transfer_vote = null - - New() - if(vote != src) - if(istype(vote)) - qdel(vote) - vote = src - - Destroy() - return QDEL_HINT_HARDDEL_NOW - - process() //called by master_controller - 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" && SSticker.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 = round((started_time + config.vote_period - world.time)/10) - - if(time_remaining < 0) - result() - for(var/client/C in voting) - if(C) - C << browse(null,"window=vote") - reset() - else - for(var/client/C in voting) - if(C) - C << browse(vote.interface(C),"window=vote") - - voting.Cut() - - proc/autotransfer() - initiate_vote("crew_transfer","the server", 1) - log_debug("The server has called a crew transfer vote") - - proc/autogamemode() - initiate_vote("gamemode","the server", 1) - log_debug("The server has called a gamemode vote") - - proc/reset() - initiator = null - time_remaining = 0 - mode = null - question = null - choices.Cut() - voted.Cut() - voting.Cut() - current_votes.Cut() - additional_text.Cut() - - 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 - //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"]) - - if(mode == "crew_transfer") - if(round(world.time / 36000)+12 <= 14) - // Credit to Scopes @ oldcode. - world << "Majority voting rule in effect. 2/3rds majority needed to initiate transfer." - choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] - round(total_votes / 3)) - 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 . - - proc/announce_result() - var/list/winners = get_result() - var/text - if(winners.len > 0) - if(winners.len > 1) - if(mode != "gamemode" || SSticker.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 == "gamemode" && . == "Extended") || SSticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes - text += "Vote Result: [.]" - else - if(mode != "gamemode") - text += "Vote Result: [.]" - else - text += "The vote has ended." // What will be shown if it is a gamemode vote that isn't extended - - else - text += "Vote Result: Inconclusive - No Votes!" - if(mode == "add_antagonist") - antag_add_failed = 1 - log_vote(text) - world << "[text]" - return . - - proc/result() - . = announce_result() - var/restart = 0 - if(.) - switch(mode) - if("restart") - if(. == "Restart Round") - restart = 1 - if("gamemode") - if(master_mode != .) - world.save_mode(.) - if(SSticker.mode) - restart = 1 - else - master_mode = . - if("crew_transfer") - if(. == "Initiate Crew Transfer") - init_shift_change(null, 1) - last_transfer_vote = world.time - if("add_antagonist") - if(isnull(.) || . == "None") - antag_add_failed = 1 - else - additional_antag_types |= antag_names_to_ids[.] - - if(mode == "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") - sleep(50) - log_game("Rebooting due to restart vote") - world.Reboot() - - return . - - proc/submit_vote(var/ckey, var/vote) - if(mode) - if (mode == "crew_transfer") - if(config.vote_no_dead && usr && !usr.client.holder) - if (isnewplayer(usr)) - usr << "You must be playing or have been playing to start a vote." - return 0 - else if (isobserver(usr)) - var/mob/dead/observer/O = usr - if (O.started_as_observer) - usr << "You must be playing or have been playing to start a vote." - return 0 - if(vote && vote >= 1 && vote <= choices.len) - if(current_votes[ckey]) - choices[choices[current_votes[ckey]]]-- - voted += usr.ckey - choices[choices[vote]]++ //check this - current_votes[ckey] = vote - return vote - return 0 - - proc/initiate_vote(var/vote_type, var/initiator_key, var/automatic = 0) - if(!mode) - if(started_time != null && !(check_rights(R_ADMIN|R_MOD) || automatic)) - // Transfer votes are their own little special snowflake - var/next_allowed_time = 0 - if (vote_type == "crew_transfer") - if (config.vote_no_dead && !usr.client.holder) - if (isnewplayer(usr)) - usr << "You must be playing or have been playing to start a vote." - return 0 - else if (isobserver(usr)) - var/mob/dead/observer/O = usr - if (O.started_as_observer) - usr << "You must be playing or have been playing to start a vote." - return 0 - - if (last_transfer_vote) - next_allowed_time = (last_transfer_vote + config.vote_delay) - else - next_allowed_time = config.transfer_timeout - else - 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") - if("gamemode") - if(SSticker.current_state >= 2) - 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("crew_transfer") - if(check_rights(R_ADMIN|R_MOD, 0)) - question = "End the shift?" - choices.Add("Initiate Crew Transfer", "Continue The Round") - else - 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(SSticker.current_state <= 2) - return 0 - initiator_key << "The crew transfer button has been disabled!" - question = "End the shift?" - choices.Add("Initiate Crew Transfer", "Continue The Round") - if("add_antagonist") - if(!config.allow_extra_antags || SSticker.current_state >= 2) - 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("custom") - question = sanitizeSafe(input(usr,"What is the vote for?") as text|null) - if(!question) return 0 - for(var/i=1,i<=10,i++) - 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 == "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." - for(var/cc in clients) - var/client/C = cc - if(C.prefs.asfx_togs & ASFX_VOTE) //Personal mute - switch(vote_type) - if("crew_transfer") - C << sound('sound/effects/vote.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) - if("gamemode") - C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) - if("custom") - C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) - if(mode == "gamemode" && round_progressing) - round_progressing = 0 - world << "Round start has been delayed." - - time_remaining = round(config.vote_period/10) - return 1 - return 0 - - proc/interface(var/client/C) - if(!C) return - var/is_staff = 0 - if(C.holder) - if(C.holder.rights & (R_ADMIN|R_MOD)) - is_staff = 1 - voting |= C - - . = "Voting Panel" - if(mode) - if(question) . += "

Vote: '[question]'

" - else . += "

Vote: [capitalize(mode)]

" - . += "Time Left: [time_remaining] s
" - . += "" - if(capitalize(mode) == "Gamemode") .+= "" - - for(var/i = 1, i <= choices.len, i++) - var/votes = choices[choices[i]] - if(!votes) votes = 0 - . += "" - if(mode == "gamemode") - if(current_votes[C.ckey] == i) - . += "" - else - . += "" - else - if(current_votes[C.ckey] == i) - . += "" - else - . += "" - if (additional_text.len >= i) - . += additional_text[i] - . += "" - - . += "
ChoicesVotesMinimum Players
[gamemode_names[choices[i]]][votes][gamemode_names[choices[i]]][votes][choices[i]][votes][choices[i]][votes]

" - if(is_staff) - . += "(Cancel Vote) " - else - . += "

Start a vote:



" - . += "Close" - return . - - - 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("close") - voting -= usr.client - 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("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("add_antagonist") - if(config.allow_extra_antags) - initiate_vote("add_antagonist",usr.key) - if("custom") - if(usr.client.holder) - initiate_vote("custom",usr.key) - 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.vote() - - -/mob/verb/vote() - set category = "OOC" - set name = "Vote" - - if(vote) - src << browse(vote.interface(client),"window=vote") diff --git a/code/datums/browser.dm b/code/datums/browser.dm index 4d428d997d2..2a29debafa6 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -74,8 +74,9 @@ if (title_image) title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'" - return {" + return {" + [head_content] diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 6a06646b9a6..d19949682bd 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -469,7 +469,7 @@ var/global/list/additional_antag_types = list() // If we don't have enough antags, draft people who voted for the round. if(candidates.len < required_enemies) for(var/mob/new_player/player in players) - if(player.ckey in round_voters) + if(player.ckey in SSvote.round_voters) log_debug("[player.key] voted for this round, so we are drafting them.") candidates += player.mind players -= player diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 219adb408fd..fb84b0f4f21 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -210,3 +210,22 @@ var/list/asset_datums = list() "changelog.css" = 'html/changelog.css', "changelog.js" = 'html/changelog.js' ) + +/datum/asset/chem_master + var/list/bottle_sprites = list("bottle-1", "bottle-2", "bottle-3", "bottle-4") + var/max_pill_sprite = 20 + var/list/assets = list() + +/datum/asset/chem_master/register() + for (var/i = 1 to max_pill_sprite) + var/name = "pill[i].png" + register_asset(name, icon('icons/obj/chemical.dmi', "pill[i]")) + assets += name + + for (var/sprite in bottle_sprites) + var/name = "[sprite].png" + register_asset(name, icon('icons/obj/chemical.dmi', sprite)) + assets += name + +/datum/asset/chem_master/send(client) + send_asset_list(client, assets) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3fd48e0ebb0..3aa6865b7bc 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -734,7 +734,7 @@ stat("Game ID", game_id) stat("Station Time", worldtime2text()) stat("Round Duration", round_duration()) - stat("Last Transfer Vote", vote.last_transfer_vote ? time2text(vote.last_transfer_vote, "hh:mm") : "Never") + stat("Last Transfer Vote", SSvote.last_transfer_vote ? time2text(SSvote.last_transfer_vote, "hh:mm") : "Never") if(client.holder) if(statpanel("Status")) diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index c13fb0c206c..a5a44bd1b77 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -2,8 +2,10 @@ #define LIQUID 2 #define GAS 3 +// Update asset_cache.dm if you change these. #define BOTTLE_SPRITES list("bottle-1", "bottle-2", "bottle-3", "bottle-4") //list of available bottle sprites #define REAGENTS_PER_SHEET 20 +#define MAX_PILL_SPRITE 20 //max icon state of the pill sprites ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -25,12 +27,11 @@ var/pillamount = 10 var/bottlesprite = "bottle-1" //yes, strings var/pillsprite = "1" - var/client/has_sprites = list() var/max_pill_count = 20 flags = OPENCONTAINER -/obj/machinery/chem_master/New() - ..() +/obj/machinery/chem_master/Initialize() + . = ..() var/datum/reagents/R = new/datum/reagents(120) reagents = R R.my_atom = src @@ -201,7 +202,6 @@ var/obj/item/weapon/reagent_containers/food/condiment/P = new/obj/item/weapon/reagent_containers/food/condiment(src.loc) reagents.trans_to_obj(P,50) else if(href_list["change_pill"]) - #define MAX_PILL_SPRITE 20 //max icon state of the pill sprites var/dat = "" for(var/i = 1 to MAX_PILL_SPRITE) dat += "" @@ -230,13 +230,10 @@ if(inoperable()) return user.set_machine(src) - if(!(user.client in has_sprites)) - spawn() - has_sprites += user.client - for(var/i = 1 to MAX_PILL_SPRITE) - usr << browse_rsc(icon('icons/obj/chemical.dmi', "pill" + num2text(i)), "pill[i].png") - for(var/sprite in BOTTLE_SPRITES) - usr << browse_rsc(icon('icons/obj/chemical.dmi', sprite), "[sprite].png") + + var/datum/asset/pill_icons = get_asset_datum(/datum/asset/chem_master) + pill_icons.send(user.client) + var/dat = "" if(!beaker) dat = "Please insert beaker.
" diff --git a/code/modules/telesci/telesci_computer.dm b/code/modules/telesci/telesci_computer.dm index d7bba1294d7..551d8b3896b 100644 --- a/code/modules/telesci/telesci_computer.dm +++ b/code/modules/telesci/telesci_computer.dm @@ -94,9 +94,9 @@ t += "Set GPS memory" t += "
[temp_msg]

" t += "Set Bearing" - t += "
[rotation]°
" + t += "
[rotation]°
" t += "Set Elevation" - t += "
[angle]°
" + t += "
[angle]°
" t += "Set Power" t += "
" diff --git a/html/changelogs/lohikar-vote.yml b/html/changelogs/lohikar-vote.yml new file mode 100644 index 00000000000..f5a97ed05b9 --- /dev/null +++ b/html/changelogs/lohikar-vote.yml @@ -0,0 +1,4 @@ +author: Lohikar +delete-after: True +changes: + - rscadd: "Added some styling to the Voting panel."