mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-21 08:06:43 +01:00
311 lines
9.3 KiB
Plaintext
311 lines
9.3 KiB
Plaintext
SUBSYSTEM_DEF(vote)
|
|
name = "Vote"
|
|
wait = 10
|
|
priority = FIRE_PRIORITY_VOTE
|
|
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
|
subsystem_flags = SS_KEEP_TIMING | SS_NO_INIT
|
|
|
|
//Current vote
|
|
var/initiator
|
|
var/started_time
|
|
var/time_remaining
|
|
var/duration
|
|
var/mode
|
|
var/question
|
|
/// Options to choose from
|
|
var/list/choices = list()
|
|
/// Votes by option
|
|
var/list/votes_by_choice = list()
|
|
/// Stores each ckeys vote
|
|
var/list/current_votes = list()
|
|
/// Who has voted
|
|
var/list/voting = list()
|
|
/// Anonymous votes
|
|
var/secret = FALSE
|
|
/// Ghost_weight on votes in %
|
|
var/ghost_weight_percent = 25
|
|
|
|
|
|
/datum/config_entry/number/ghost_weight
|
|
default = 25
|
|
|
|
/datum/config_entry/flag/transfer_vote_obfuscation
|
|
default = FALSE
|
|
|
|
/datum/config_entry/string/default_on_transfer_tie
|
|
default = "Extend the Shift"
|
|
|
|
/datum/controller/subsystem/vote/Initialize()
|
|
ghost_weight_percent = CONFIG_GET(number/ghost_weight)
|
|
return SS_INIT_SUCCESS
|
|
|
|
/datum/controller/subsystem/vote/fire(resumed)
|
|
if(mode)
|
|
time_remaining = round((started_time + duration - world.time)/10)
|
|
if(mode == VOTE_GAMEMODE && SSticker.current_state >= GAME_STATE_SETTING_UP)
|
|
to_chat(world, "<b>Gamemode vote aborted: Game has already started.</b>")
|
|
reset()
|
|
return
|
|
if(time_remaining <= 0)
|
|
result()
|
|
reset()
|
|
|
|
/datum/controller/subsystem/vote/proc/autotransfer()
|
|
// Before doing the vote, see if anyone is playing.
|
|
// If not, just do the transfer.
|
|
var/players_are_in_round = FALSE
|
|
for(var/a in GLOB.player_list) // Mobs with clients attached.
|
|
var/mob/living/L = a
|
|
if(!istype(L)) // Exclude ghosts and other weird things.
|
|
continue
|
|
if(L.stat == DEAD) // Dead mobs aren't playing.
|
|
continue
|
|
// Everything else is, however.
|
|
players_are_in_round = TRUE
|
|
break
|
|
|
|
if(!players_are_in_round)
|
|
log_debug(SPAN_DEBUG("The crew transfer shuttle was automatically called at vote time due to no players being present."))
|
|
init_shift_change(null, 1)
|
|
return
|
|
|
|
initiate_vote(VOTE_CREW_TRANSFER, "the server", 1)
|
|
subsystem_log("The server has called a crew transfer vote.")
|
|
|
|
/datum/controller/subsystem/vote/proc/reset()
|
|
initiator = null
|
|
started_time = null
|
|
duration = null
|
|
time_remaining = null
|
|
mode = null
|
|
question = null
|
|
choices.Cut()
|
|
votes_by_choice.Cut()
|
|
current_votes.Cut()
|
|
secret = FALSE
|
|
ghost_weight_percent = CONFIG_GET(number/ghost_weight)
|
|
|
|
/datum/controller/subsystem/vote/proc/get_result() // Get the highest number of votes
|
|
var/greatest_votes = 0
|
|
var/total_votes = 0
|
|
var/list/winning = list()
|
|
|
|
for(var/option in choices)
|
|
var/votes = votes_by_choice[option]
|
|
total_votes += votes
|
|
if(votes <= 0)
|
|
continue
|
|
if(votes > greatest_votes)
|
|
winning = list()
|
|
LAZYDISTINCTADD(winning, option)
|
|
greatest_votes = votes
|
|
else if(votes == greatest_votes)
|
|
LAZYDISTINCTADD(winning, option)
|
|
return winning
|
|
//there used to be code here for giving default votes from non voters, but if you dont vote you dont get to default either
|
|
|
|
/datum/controller/subsystem/vote/proc/announce_result()
|
|
var/list/winners = get_result()
|
|
var/text
|
|
if(mode == VOTE_CREW_TRANSFER)
|
|
switch(LAZYLEN(winners))
|
|
if(0)
|
|
. = "Initiate Crew Transfer"
|
|
if(2)
|
|
. = CONFIG_GET(string/default_on_transfer_tie)
|
|
if(LAZYLEN(winners) > 0)
|
|
if(!.)
|
|
if(LAZYLEN(winners) > 1)
|
|
text += "More than one winner, result chosen at random."
|
|
. = pick(winners)
|
|
text += "<b>Vote Result: [.]</b>"
|
|
else
|
|
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
|
|
|
|
for(var/option in choices)
|
|
text += SPAN_NOTICE("\n[option] - [votes_by_choice[option] || 0]")
|
|
log_vote(text)
|
|
to_chat(world, "<font color='purple'>[text]</font>")
|
|
|
|
/datum/controller/subsystem/vote/proc/result()
|
|
. = announce_result()
|
|
var/restart = 0
|
|
if(.)
|
|
switch(mode)
|
|
if(VOTE_RESTART)
|
|
if(. == "Restart Round")
|
|
restart = 1
|
|
if(VOTE_CREW_TRANSFER)
|
|
if(. == "Initiate Crew Transfer")
|
|
init_shift_change(null, 1)
|
|
|
|
if(restart)
|
|
to_chat(world, "World restarting due to vote...")
|
|
feedback_set_details("end_error", "restart vote")
|
|
if(blackbox)
|
|
blackbox.save_all_data_to_sql()
|
|
sleep(50)
|
|
log_game("Rebooting due to restart vote")
|
|
world.Reboot()
|
|
|
|
/datum/controller/subsystem/vote/proc/submit_vote(user, ckey, newVote)
|
|
//if they are a observer or a newplayer(in lobby) use ghost weight, otherwise use 1
|
|
var/weight = (isobserver(user) || isnewplayer(user)) ? ghost_weight_percent / 100 : 1
|
|
if(mode)
|
|
if(weight == 0)
|
|
return
|
|
if(newVote)
|
|
if(current_votes[ckey])
|
|
votes_by_choice[current_votes[ckey][2]] -= current_votes[ckey][1]
|
|
current_votes[ckey] = list(weight, choices[newVote])
|
|
votes_by_choice[current_votes[ckey][2]] += current_votes[ckey][1]
|
|
else
|
|
votes_by_choice[current_votes[ckey][2]] -= current_votes[ckey][1]
|
|
current_votes[ckey] = null
|
|
|
|
|
|
|
|
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, automatic = FALSE, time = config_legacy.vote_period)
|
|
if(!mode)
|
|
if(started_time != null && !(check_rights(R_ADMIN) || automatic))
|
|
var/next_allowed_time = (started_time + config_legacy.vote_delay)
|
|
if(next_allowed_time > world.time)
|
|
return 0
|
|
|
|
//reset()
|
|
|
|
switch(vote_type)
|
|
if(VOTE_RESTART)
|
|
choices.Add("Restart Round", "Continue Playing")
|
|
votes_by_choice["Restart Round"] = 0
|
|
votes_by_choice["Continue Playing"] = 0
|
|
if(VOTE_CREW_TRANSFER)
|
|
question = "Your PDA beeps with a message from Central. Would you like an additional hour to finish ongoing projects?"
|
|
choices.Add("Initiate Crew Transfer", "Extend the Shift")
|
|
votes_by_choice["Initiate Crew Transfer"] = 0
|
|
votes_by_choice["Extend the Shift"] = 0
|
|
secret = CONFIG_GET(flag/transfer_vote_obfuscation)
|
|
if(VOTE_CUSTOM)
|
|
question = sanitizeSafe(input(usr, "What is the vote for?") as text|null)
|
|
if(!question)
|
|
return 0
|
|
var/list/temp = list()
|
|
for(var/i = 1 to 10)
|
|
var/option = capitalize(sanitize(input(usr, "Please enter an option or hit cancel to finish") as text|null))
|
|
if(!option || mode || !usr.client)
|
|
break
|
|
temp.Add(option)
|
|
votes_by_choice[temp] = 0
|
|
choices = temp
|
|
else
|
|
return 0
|
|
|
|
mode = vote_type
|
|
initiator = initiator_key
|
|
started_time = world.time
|
|
duration = time
|
|
var/text = SPAN_VOTENOTIFICATION("[capitalize(mode)] vote started by [initiator].")
|
|
if(mode == VOTE_CUSTOM)
|
|
text += SPAN_VOTENOTIFICATION("\n[question]")
|
|
if(ghost_weight_percent <= 0)
|
|
text += SPAN_NOTICE("\nGhosts are excluded from the vote.")
|
|
log_vote(text)
|
|
|
|
to_chat(world, SPAN_INFOPLAIN("<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_legacy.vote_period / 10] seconds to vote.</font>"))
|
|
if(vote_type == VOTE_CREW_TRANSFER || vote_type == VOTE_GAMEMODE)
|
|
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3))
|
|
|
|
if(vote_type == VOTE_CUSTOM)
|
|
SEND_SOUND(world, sound('sound/custom_vote.ogg', repeat = 0, wait = 0, volume = 30, channel = 3))
|
|
|
|
time_remaining = round(config_legacy.vote_period / 10)
|
|
return 1
|
|
return 0
|
|
|
|
/datum/controller/subsystem/vote/Topic(href, href_list[])
|
|
usr.client.vote()
|
|
|
|
/client/verb/vote()
|
|
set category = VERB_CATEGORY_OOC
|
|
set name = "Vote"
|
|
|
|
if(SSvote)
|
|
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
|
|
//current_votes[user.client?.ckey] = null
|
|
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, datum/tgui/ui)
|
|
var/list/data = list(
|
|
"choices" = list(),
|
|
"question" = question,
|
|
"selected_choice" = LAZYACCESS(current_votes,user.key) ? LAZYACCESS(current_votes,user.key)[2] : "",
|
|
"time_remaining" = time_remaining,
|
|
"admin" = check_rights_for(user.client, R_ADMIN),
|
|
|
|
"vote_happening" = !!choices.len,
|
|
"secret" = secret,
|
|
"ghost_weight" = ghost_weight_percent,
|
|
"ghost" = isobserver(user) || isnewplayer(user),
|
|
)
|
|
|
|
for(var/key in choices)
|
|
data["choices"] += list(list(
|
|
"name" = key,
|
|
"votes" = votes_by_choice[key] || 0
|
|
))
|
|
|
|
return data
|
|
|
|
/datum/controller/subsystem/vote/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state, datum/event_args/actor/actor)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
var/admin = FALSE
|
|
var/client/C = usr.client
|
|
if(C.holder)
|
|
if(C.holder.rights & R_ADMIN)
|
|
admin = TRUE
|
|
|
|
switch(action)
|
|
if("cancel")
|
|
if(admin)
|
|
log_and_message_admins("[key_name_admin(usr)] has cancelled the current vote.")
|
|
reset()
|
|
if("restart")
|
|
if(admin || config_legacy.allow_vote_restart)
|
|
initiate_vote(VOTE_RESTART, usr.key)
|
|
if("transfer")
|
|
if(config_legacy.allow_vote_restart || usr.client.holder)
|
|
initiate_vote(VOTE_CREW_TRANSFER, usr.key)
|
|
if("custom")
|
|
if(admin)
|
|
initiate_vote(VOTE_CUSTOM, usr.key)
|
|
if("vote")
|
|
//current_votes[usr.client.ckey] = round(text2num(params["index"]))
|
|
submit_vote(usr, usr.key,params["index"])
|
|
if("unvote")
|
|
submit_vote(usr, usr.key, null)
|
|
if("hide")
|
|
if(admin)
|
|
secret = !secret
|
|
log_and_message_admins("[usr] made the individual vote numbers [(secret ? "invisibile" : "visible")].")
|
|
if("ghost_weight")
|
|
if(admin)
|
|
ghost_weight_percent = params["ghost_weight"] ? max(0, text2num(params["ghost_weight"])) : ghost_weight_percent
|
|
log_and_message_admins("[usr] changed the ghost vote weight to [ghost_weight_percent].")
|
|
|
|
return TRUE
|