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.
This commit is contained in:
Lohikar
2017-05-13 12:37:43 +03:00
committed by skull132
parent 0d1d0f6429
commit 6cf332bfa7
11 changed files with 494 additions and 460 deletions
+4 -3
View File
@@ -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 << "<span class='danger'>The round has ended!</span>"
round_end_announced = 1
vote.autotransfer()
SSvote.autotransfer()
return 1
+453 -4
View File
@@ -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 << "<b>Voting aborted due to game start.</b>"
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 << "<font color='purple'>Crew Transfer Factor: [factor]</font>"
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 << "<font color='purple'><b>Majority voting rule in effect. 2/3rds majority needed to initiate transfer.</b></font>"
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 = "<b>Vote Tied Between:</b>\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 += "<b>Vote Result: [.]</b>"
else
if(mode != "gamemode")
text += "<b>Vote Result: [.]</b>"
else
text += "<b>The vote has ended.</b>" // What will be shown if it is a gamemode vote that isn't extended
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
if(mode == "add_antagonist")
antag_add_failed = 1
log_vote(text)
world << "<font color='purple'>[text]</font>"
/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 << "<font color='red'><b>The round will start soon.</b></font>"
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 << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
else if (isobserver(usr))
var/mob/dead/observer/O = usr
if (O.started_as_observer)
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
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 << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
else if (isobserver(usr))
var/mob/dead/observer/O = usr
if (O.started_as_observer)
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
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("<td align = 'center'>[M.required_players]</td>")
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 << "<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
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 << "<font color='red'><b>Round start has been delayed.</b></font>"
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) . += "<h2>Vote: '[question]'</h2>"
else . += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr>"
. += "<table width = '100%'><tr><td align = 'center'><b>Choices</b></td><td align = 'center'><b>Votes</b></td>"
if(capitalize(mode) == "Gamemode") .+= "<td align = 'center'><b>Minimum Players</b></td></tr>"
for(var/i = 1, i <= choices.len, i++)
var/votes = choices[choices[i]]
if(!votes) votes = 0
. += "<tr>"
if(mode == "gamemode")
if(current_votes[C.ckey] == i)
. += "<td><b><a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a></b></td><td align = 'center'>[votes]</td>"
else
. += "<td><a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a></td><td align = 'center'>[votes]</td>"
else
if(current_votes[C.ckey] == i)
. += "<td><b><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a></b></td><td align = 'center'>[votes]</td>"
else
. += "<td><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a></td><td align = 'center'>[votes]</td>"
if (additional_text.len >= i)
. += additional_text[i]
. += "</tr>"
. += "</table><hr>"
if(is_staff)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
if(is_staff || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(is_staff || config.allow_vote_restart)
if (get_security_level() == "red" || get_security_level() == "delta")
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer (Disallowed, Code Red or above)</a>"
else
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(is_staff)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//gamemode
if(is_staff || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(is_staff)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//extra antagonists
if(!antag_add_failed && config.allow_extra_antags)
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li>"
//custom
if(is_staff)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a></body></html>"
/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("<title>Voting panel</title>")
/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
-436
View File
@@ -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 << "<b>Voting aborted due to game start.</b>"
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 << "<font color='purple'>Crew Transfer Factor: [factor]</font>"
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 << "<font color='purple'><b>Majority voting rule in effect. 2/3rds majority needed to initiate transfer.</b></font>"
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 = "<b>Vote Tied Between:</b>\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 += "<b>Vote Result: [.]</b>"
else
if(mode != "gamemode")
text += "<b>Vote Result: [.]</b>"
else
text += "<b>The vote has ended.</b>" // What will be shown if it is a gamemode vote that isn't extended
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
if(mode == "add_antagonist")
antag_add_failed = 1
log_vote(text)
world << "<font color='purple'>[text]</font>"
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 << "<font color='red'><b>The round will start soon.</b></font>"
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 << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
else if (isobserver(usr))
var/mob/dead/observer/O = usr
if (O.started_as_observer)
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
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 << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
else if (isobserver(usr))
var/mob/dead/observer/O = usr
if (O.started_as_observer)
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
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("<td align = 'center'>[M.required_players]</td>")
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 << "<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
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 << "<font color='red'><b>Round start has been delayed.</b></font>"
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
. = "<html><head><title>Voting Panel</title></head><body>"
if(mode)
if(question) . += "<h2>Vote: '[question]'</h2>"
else . += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr>"
. += "<table width = '100%'><tr><td align = 'center'><b>Choices</b></td><td align = 'center'><b>Votes</b></td>"
if(capitalize(mode) == "Gamemode") .+= "<td align = 'center'><b>Minimum Players</b></td></tr>"
for(var/i = 1, i <= choices.len, i++)
var/votes = choices[choices[i]]
if(!votes) votes = 0
. += "<tr>"
if(mode == "gamemode")
if(current_votes[C.ckey] == i)
. += "<td><b><a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a></b></td><td align = 'center'>[votes]</td>"
else
. += "<td><a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a></td><td align = 'center'>[votes]</td>"
else
if(current_votes[C.ckey] == i)
. += "<td><b><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a></b></td><td align = 'center'>[votes]</td>"
else
. += "<td><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a></td><td align = 'center'>[votes]</td>"
if (additional_text.len >= i)
. += additional_text[i]
. += "</tr>"
. += "</table><hr>"
if(is_staff)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
if(is_staff || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(is_staff || config.allow_vote_restart)
if (get_security_level() == "red" || get_security_level() == "delta")
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer (Disallowed, Code Red or above)</a>"
else
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(is_staff)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//gamemode
if(is_staff || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(is_staff)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//extra antagonists
if(!antag_add_failed && config.allow_extra_antags)
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li>"
//custom
if(is_staff)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a></body></html>"
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")
+2 -1
View File
@@ -74,8 +74,9 @@
if (title_image)
title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'"
return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
return {"<!DOCTYPE html>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<head>
[head_content]
+1 -1
View File
@@ -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
+19
View File
@@ -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)
+1 -1
View File
@@ -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"))
+8 -11
View File
@@ -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 = "<table>"
for(var/i = 1 to MAX_PILL_SPRITE)
dat += "<tr><td><a href=\"?src=\ref[src]&pill_sprite=[i]\"><img src=\"pill[i].png\" /></a></td></tr>"
@@ -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.<BR>"
+2 -2
View File
@@ -94,9 +94,9 @@
t += "<span class='linkOff'>Set GPS memory</span>"
t += "<div class='statusDisplay'>[temp_msg]</div><BR>"
t += "<A href='?src=\ref[src];setrotation=1'>Set Bearing</A>"
t += "<div class='statusDisplay'>[rotation]°</div>"
t += "<div class='statusDisplay'>[rotation]&deg;</div>"
t += "<A href='?src=\ref[src];setangle=1'>Set Elevation</A>"
t += "<div class='statusDisplay'>[angle]°</div>"
t += "<div class='statusDisplay'>[angle]&deg;</div>"
t += "<span class='linkOn'>Set Power</span>"
t += "<div class='statusDisplay'>"