Files
Bubberstation/code/controllers/subsystem/vote.dm
SkyratBot 7d1d0e1fad [MIRROR] Refactors most spans into span procs (#6315)
* Refactors most spans into span procs

* AA

* a

* AAAAAAAAAAAAAAAAAAAAAA

* Update species.dm

Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
Co-authored-by: Gandalf <jzo123@hotmail.com>
2021-06-16 00:24:49 +01:00

380 lines
11 KiB
Plaintext

SUBSYSTEM_DEF(vote)
name = "Vote"
wait = 10
flags = SS_KEEP_TIMING|SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/choices = list()
var/list/choice_by_ckey = list()
var/list/generated_actions = list()
var/initiator
var/mode
var/question
var/started_time
var/time_remaining
var/list/voted = list()
var/list/voting = list()
// Called by master_controller
/datum/controller/subsystem/vote/fire()
if(!mode)
return
time_remaining = round((started_time + CONFIG_GET(number/vote_period) - world.time)/10)
if(time_remaining < 0)
result()
SStgui.close_uis(src)
reset()
/datum/controller/subsystem/vote/proc/reset()
choices.Cut()
choice_by_ckey.Cut()
initiator = null
mode = null
question = null
time_remaining = 0
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_GET(flag/default_no_vote) && 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 == "map")
for (var/non_voter_ckey in non_voters)
var/client/C = non_voters[non_voter_ckey]
var/preferred_map = C.prefs.preferred_map
if(isnull(global.config.defaultmap))
continue
if(!preferred_map)
preferred_map = global.config.defaultmap.map_name
choices[preferred_map] += 1
greatest_votes = max(greatest_votes, choices[preferred_map])
. = 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<span class='infoplain'><font color='purple'>[text]</font></span>")
return .
/datum/controller/subsystem/vote/proc/result()
. = announce_result()
var/restart = FALSE
if(.)
switch(mode)
if("restart")
if(. == "Restart Round")
restart = TRUE
if("map")
SSmapping.changemap(global.config.maplist[.])
SSmapping.map_voted = TRUE
//SKYRAT EDIT ADDITION BEGIN
if("mining_map")
SSrandommining.voted_next_map = TRUE
if(fexists("data/next_mining.dat"))
fdel("data/next_mining.dat")
var/F = file("data/next_mining.dat")
WRITE_FILE(F, .)
if("transfer")
if(. == "Initiate Crew Transfer")
SSshuttle.autoEnd()
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
if(C)
C.post_status("shuttle")
//SKYRAT EDIT ADDITION END
if(restart)
var/active_admins = FALSE
for(var/client/C in GLOB.admins + GLOB.deadmins)
if(!C.is_afk() && check_rights_for(C, R_SERVER))
active_admins = TRUE
break
if(!active_admins)
// No delay in case the restart is due to lag
SSticker.Reboot("Restart vote successful.", "restart vote", 1)
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)
return FALSE
if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !usr.client.holder)
return FALSE
if(!vote || vote < 1 || vote > choices.len)
return FALSE
// If user has already voted, remove their specific vote
if(usr.ckey in voted)
choices[choices[choice_by_ckey[usr.ckey]]]--
else
voted += usr.ckey
choice_by_ckey[usr.ckey] = vote
choices[choices[vote]]++
return vote
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
//Server is still intializing.
if(!Master.current_runlevel)
to_chat(usr, span_warning("Cannot start vote, server is not done initializing."))
return FALSE
var/lower_admin = FALSE
var/ckey = ckey(initiator_key)
if(GLOB.admin_datums[ckey])
lower_admin = TRUE
if(!mode)
if(started_time)
var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay))
if(mode)
to_chat(usr, span_warning("There is already a vote in progress! please wait for it to finish."))
return FALSE
if(next_allowed_time > world.time && !lower_admin)
to_chat(usr, span_warning("A vote was initiated recently, you must wait [DisplayTimeText(next_allowed_time-world.time)] before a new vote can be started!"))
return FALSE
reset()
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
if("map")
if(!lower_admin && SSmapping.map_voted)
to_chat(usr, span_warning("The next map has already been selected."))
return FALSE
// Randomizes the list so it isn't always METASTATION
var/list/maps = list()
for(var/map in global.config.maplist)
var/datum/map_config/VM = config.maplist[map]
if(!VM.votable || (VM.map_name in SSpersistence.blocked_maps) || GLOB.clients.len >= VM.config_max_users || GLOB.clients.len <= VM.config_min_users) //SKYRAT EDIT CHANGE - ORIGINAL: if(!VM.votable || (VM.map_name in SSpersistence.blocked_maps))
continue
maps += VM.map_name
shuffle_inplace(maps)
for(var/valid_map in maps)
choices.Add(valid_map)
//SKYRAT EDIT ADDITION
if("mining_map")
if(!lower_admin && SSrandommining.voted_next_map)
to_chat(usr, "<span class='warning'>The next map has already been selected.</span>")
return FALSE
var/list/maps = list()
for(var/map in SSrandommining.possible_names)
if(SSrandommining.previous_map == map)
continue
maps += map
for(var/valid_map in maps)
choices.Add(valid_map)
//SKYRAT EDIT ADDITON END
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
return FALSE
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)
//SKYRAT EDIT ADDITION BEGIN - AUTOTRANSFER
if("transfer")
choices.Add("Initiate Crew Transfer","Continue Playing")
//SKYRAT EDIT ADDITION END - AUTOTRANSFER
else
return FALSE
mode = vote_type
initiator = initiator_key
started_time = world.time
var/text = "[capitalize(mode)] vote started by [initiator || "CentCom"]."
if(mode == "custom")
text += "\n[question]"
log_vote(text)
var/vp = CONFIG_GET(number/vote_period)
to_chat(world, "\n<span class='infoplain'><font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='byond://winset?command=vote'>here</a> to place your votes.\nYou have [DisplayTimeText(vp)] to vote.</font></span>")
time_remaining = round(vp/10)
for(var/c in GLOB.clients)
var/client/C = c
var/datum/action/vote/V = new
if(question)
V.name = "Vote: [question]"
C.player_details.player_actions += V
V.Grant(C.mob)
generated_actions += V
if(C.prefs.toggles & SOUND_ANNOUNCEMENTS)
//SKYRAT EDIT START
/*
SEND_SOUND(C, sound('sound/misc/bloop.ogg'))
*/
SEND_SOUND(C, sound('sound/misc/announce_dig.ogg'))
//SKYRAT EDIT END
return TRUE
return FALSE
/mob/verb/vote()
set category = "OOC"
set name = "Vote"
SSvote.ui_interact(usr)
/datum/controller/subsystem/vote/ui_state()
return GLOB.always_state
/datum/controller/subsystem/vote/ui_interact(mob/user, datum/tgui/ui)
// Tracks who is voting
if(!(user.client?.ckey in voting))
voting += user.client?.ckey
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Vote")
ui.open()
/datum/controller/subsystem/vote/ui_data(mob/user)
var/list/data = list(
"allow_vote_map" = CONFIG_GET(flag/allow_vote_map),
"allow_vote_restart" = CONFIG_GET(flag/allow_vote_restart),
"choices" = list(),
"lower_admin" = !!user.client?.holder,
"mode" = mode,
"question" = question,
"selected_choice" = choice_by_ckey[user.client?.ckey],
"time_remaining" = time_remaining,
"upper_admin" = check_rights_for(user.client, R_ADMIN),
"voting" = list(),
)
if(!!user.client?.holder)
data["voting"] = voting
for(var/key in choices)
data["choices"] += list(list(
"name" = key,
"votes" = choices[key] || 0
))
return data
/datum/controller/subsystem/vote/ui_act(action, params)
. = ..()
if(.)
return
var/upper_admin = FALSE
if(usr.client.holder)
if(check_rights_for(usr.client, R_ADMIN))
upper_admin = TRUE
switch(action)
if("cancel")
if(usr.client.holder)
usr.log_message("[key_name_admin(usr)] cancelled a vote.", LOG_ADMIN)
message_admins("[key_name_admin(usr)] has cancelled the current vote.")
reset()
if("toggle_restart")
if(usr.client.holder && upper_admin)
CONFIG_SET(flag/allow_vote_restart, !CONFIG_GET(flag/allow_vote_restart))
if("toggle_map")
if(usr.client.holder && upper_admin)
CONFIG_SET(flag/allow_vote_map, !CONFIG_GET(flag/allow_vote_map))
if("restart")
if(CONFIG_GET(flag/allow_vote_restart) || usr.client.holder)
initiate_vote("restart",usr.key)
if("map")
if(CONFIG_GET(flag/allow_vote_map) || usr.client.holder)
initiate_vote("map",usr.key)
//SKYRAT EDIT ADDITION
if("mining_map")
if(CONFIG_GET(flag/allow_vote_map) || usr.client.holder)
initiate_vote("mining_map",usr.key)
//SKYRAT EDIT END
if("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
//SKYRAT EDIT ADDITION BEGIN - autotransfer
if("transfer")
if(usr.client.holder && upper_admin)
initiate_vote("transfer",usr.key)
//SKYRAT EDIT ADDITION END
if("vote")
submit_vote(round(text2num(params["index"])))
return TRUE
/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_from_client()
V.Remove(V.owner)
generated_actions = list()
/datum/controller/subsystem/vote/ui_close(mob/user)
voting -= user.client?.ckey
/datum/action/vote
name = "Vote!"
button_icon_state = "vote"
/datum/action/vote/Trigger()
if(owner)
owner.vote()
remove_from_client()
Remove(owner)
/datum/action/vote/IsAvailable()
return TRUE
/datum/action/vote/proc/remove_from_client()
if(!owner)
return
if(owner.client)
owner.client.player_details.player_actions -= src
else if(owner.ckey)
var/datum/player_details/P = GLOB.player_details[owner.ckey]
if(P)
P.player_actions -= src