April sync (#360)
* Maps and things no code/icons * helpers defines globalvars * Onclick world.dm orphaned_procs * subsystems Round vote and shuttle autocall done here too * datums * Game folder * Admin - chatter modules * clothing - mining * modular computers - zambies * client * mob level 1 * mob stage 2 + simple_animal * silicons n brains * mob stage 3 + Alien/Monkey * human mobs * icons updated * some sounds * emitter y u no commit * update tgstation.dme * compile fixes * travis fixes Also removes Fast digest mode, because reasons. * tweaks for travis Mentors are broke again Also fixes Sizeray guns * oxygen loss fix for vore code. * removes unused code * some code updates * bulk fixes * further fixes * outside things * whoops. * Maint bar ported * GLOBs.
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
SUBSYSTEM_DEF(vote)
|
||||
name = "Vote"
|
||||
wait = 10
|
||||
|
||||
flags = SS_FIRE_IN_LOBBY|SS_KEEP_TIMING|SS_NO_INIT
|
||||
|
||||
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/generated_actions = list()
|
||||
|
||||
/datum/controller/subsystem/vote/fire() //called by master_controller
|
||||
if(mode)
|
||||
time_remaining = round((started_time + config.vote_period - world.time)/10)
|
||||
|
||||
if(time_remaining < 0)
|
||||
result()
|
||||
for(var/client/C in voting)
|
||||
C << browse(null, "window=vote;can_close=0")
|
||||
reset()
|
||||
else
|
||||
var/datum/browser/client_popup
|
||||
for(var/client/C in voting)
|
||||
client_popup = new(C, "vote", "Voting Panel")
|
||||
client_popup.set_window_options("can_close=0")
|
||||
client_popup.set_content(interface(C))
|
||||
client_popup.open(0)
|
||||
|
||||
|
||||
/datum/controller/subsystem/vote/proc/reset()
|
||||
initiator = null
|
||||
time_remaining = 0
|
||||
mode = null
|
||||
question = null
|
||||
choices.Cut()
|
||||
voted.Cut()
|
||||
voting.Cut()
|
||||
remove_action_buttons()
|
||||
|
||||
/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/list/non_voters = GLOB.directory.Copy()
|
||||
non_voters -= voted
|
||||
for (var/non_voter_ckey in non_voters)
|
||||
var/client/C = non_voters[non_voter_ckey]
|
||||
if (!C || C.is_afk())
|
||||
non_voters -= non_voter_ckey
|
||||
if(non_voters.len > 0)
|
||||
if(mode == "restart")
|
||||
choices["Continue Playing"] += non_voters.len
|
||||
if(choices["Continue Playing"] >= greatest_votes)
|
||||
greatest_votes = choices["Continue Playing"]
|
||||
else if(mode == "gamemode")
|
||||
if(GLOB.master_mode in choices)
|
||||
choices[GLOB.master_mode] += non_voters.len
|
||||
if(choices[GLOB.master_mode] >= greatest_votes)
|
||||
greatest_votes = choices[GLOB.master_mode]
|
||||
//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/subsystem/vote/proc/announce_result()
|
||||
var/list/winners = get_result()
|
||||
var/text
|
||||
if(winners.len > 0)
|
||||
if(question)
|
||||
text += "<b>[question]</b>"
|
||||
else
|
||||
text += "<b>[capitalize(mode)] Vote</b>"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
if(!votes)
|
||||
votes = 0
|
||||
text += "\n<b>[choices[i]]:</b> [votes]"
|
||||
if(mode != "custom")
|
||||
if(winners.len > 1)
|
||||
text = "\n<b>Vote Tied Between:</b>"
|
||||
for(var/option in winners)
|
||||
text += "\n\t[option]"
|
||||
. = pick(winners)
|
||||
text += "\n<b>Vote Result: [.]</b>"
|
||||
else
|
||||
text += "\n<b>Did not vote:</b> [GLOB.clients.len-voted.len]"
|
||||
else
|
||||
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
|
||||
log_vote(text)
|
||||
remove_action_buttons()
|
||||
to_chat(world, "\n<font color='purple'>[text]</font>")
|
||||
return .
|
||||
|
||||
/datum/controller/subsystem/vote/proc/result()
|
||||
. = announce_result()
|
||||
var/restart = 0
|
||||
if(.)
|
||||
switch(mode)
|
||||
if("restart")
|
||||
if(. == "Restart Round")
|
||||
restart = 1
|
||||
if("gamemode")
|
||||
if(GLOB.master_mode != .)
|
||||
world.save_mode(.)
|
||||
if(SSticker && SSticker.mode)
|
||||
restart = 1
|
||||
else
|
||||
GLOB.master_mode = .
|
||||
if(restart)
|
||||
var/active_admins = 0
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(!C.is_afk() && check_rights_for(C, R_SERVER))
|
||||
active_admins = 1
|
||||
break
|
||||
if(!active_admins)
|
||||
world.Reboot("Restart vote successful.", "end_error", "restart vote")
|
||||
else
|
||||
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
|
||||
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
|
||||
|
||||
return .
|
||||
|
||||
/datum/controller/subsystem/vote/proc/submit_vote(vote)
|
||||
if(mode)
|
||||
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
|
||||
return 0
|
||||
if(!(usr.ckey in voted))
|
||||
if(vote && 1<=vote && vote<=choices.len)
|
||||
voted += usr.ckey
|
||||
choices[choices[vote]]++ //check this
|
||||
return vote
|
||||
return 0
|
||||
|
||||
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
|
||||
if(!mode)
|
||||
if(started_time)
|
||||
var/next_allowed_time = (started_time + config.vote_delay)
|
||||
if(mode)
|
||||
to_chat(usr, "<span class='warning'>There is already a vote in progress! please wait for it to finish.</span>")
|
||||
return 0
|
||||
|
||||
var/admin = FALSE
|
||||
var/ckey = ckey(initiator_key)
|
||||
if((GLOB.admin_datums[ckey]) || (ckey in GLOB.deadmins))
|
||||
admin = TRUE
|
||||
|
||||
if(next_allowed_time > world.time && !admin)
|
||||
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait roughly [(next_allowed_time-world.time)/10] seconds before a new vote can be started!</span>")
|
||||
return 0
|
||||
|
||||
reset()
|
||||
switch(vote_type)
|
||||
if("restart")
|
||||
choices.Add("Restart Round","Continue Playing")
|
||||
if("gamemode")
|
||||
choices.Add(config.votable_modes)
|
||||
if("custom")
|
||||
question = stripped_input(usr,"What is the vote for?")
|
||||
if(!question)
|
||||
return 0
|
||||
for(var/i=1,i<=10,i++)
|
||||
var/option = capitalize(stripped_input(usr,"Please enter an option or hit cancel to finish"))
|
||||
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)
|
||||
to_chat(world, "\n<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>")
|
||||
time_remaining = round(config.vote_period/10)
|
||||
for(var/c in GLOB.clients)
|
||||
var/client/C = c
|
||||
var/datum/action/vote/V = new
|
||||
if(question)
|
||||
V.name = "Vote: [question]"
|
||||
V.Grant(C.mob)
|
||||
generated_actions += V
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/controller/subsystem/vote/proc/interface(client/C)
|
||||
if(!C)
|
||||
return
|
||||
var/admin = 0
|
||||
var/trialmin = 0
|
||||
if(C.holder)
|
||||
admin = 1
|
||||
if(check_rights_for(C, R_ADMIN))
|
||||
trialmin = 1
|
||||
voting |= C
|
||||
|
||||
if(mode)
|
||||
if(question)
|
||||
. += "<h2>Vote: '[question]'</h2>"
|
||||
else
|
||||
. += "<h2>Vote: [capitalize(mode)]</h2>"
|
||||
. += "Time Left: [time_remaining] s<hr><ul>"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
if(!votes)
|
||||
votes = 0
|
||||
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
|
||||
. += "</ul><hr>"
|
||||
if(admin)
|
||||
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
|
||||
else
|
||||
. += "<h2>Start a vote:</h2><hr><ul><li>"
|
||||
//restart
|
||||
if(trialmin || config.allow_vote_restart)
|
||||
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
|
||||
else
|
||||
. += "<font color='grey'>Restart (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
|
||||
. += "</li><li>"
|
||||
//gamemode
|
||||
if(trialmin || config.allow_vote_mode)
|
||||
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
|
||||
else
|
||||
. += "<font color='grey'>GameMode (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
|
||||
|
||||
. += "</li>"
|
||||
//custom
|
||||
if(trialmin)
|
||||
. += "<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>"
|
||||
return .
|
||||
|
||||
|
||||
/datum/controller/subsystem/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("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("custom")
|
||||
if(usr.client.holder)
|
||||
initiate_vote("custom",usr.key)
|
||||
else
|
||||
submit_vote(round(text2num(href_list["vote"])))
|
||||
usr.vote()
|
||||
|
||||
/datum/controller/subsystem/vote/proc/remove_action_buttons()
|
||||
for(var/v in generated_actions)
|
||||
var/datum/action/vote/V = v
|
||||
if(!QDELETED(V))
|
||||
V.Remove(V.owner)
|
||||
generated_actions = list()
|
||||
|
||||
/mob/verb/vote()
|
||||
set category = "OOC"
|
||||
set name = "Vote"
|
||||
|
||||
var/datum/browser/popup = new(src, "vote", "Voting Panel")
|
||||
popup.set_window_options("can_close=0")
|
||||
popup.set_content(SSvote.interface(client))
|
||||
popup.open(0)
|
||||
|
||||
/datum/action/vote
|
||||
name = "Vote!"
|
||||
button_icon_state = "vote"
|
||||
|
||||
/datum/action/vote/Trigger()
|
||||
if(owner)
|
||||
owner.vote()
|
||||
Remove(owner)
|
||||
|
||||
/datum/action/vote/IsAvailable()
|
||||
return 1
|
||||
Reference in New Issue
Block a user