mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-19 22:23:11 +00:00
179 lines
6.0 KiB
Plaintext
179 lines
6.0 KiB
Plaintext
#define MAP_VOTE_CACHE_LOCATION "data/map_vote_cache.json"
|
|
|
|
SUBSYSTEM_DEF(map_vote)
|
|
name = "Map Vote"
|
|
flags = SS_NO_FIRE
|
|
|
|
/// Has an admin specifically set a map.
|
|
var/admin_override = FALSE
|
|
|
|
/// Have we already done a vote.
|
|
var/already_voted = FALSE
|
|
|
|
/// The map that has been chosen for next round.
|
|
var/datum/map_config/next_map_config
|
|
|
|
/// Stores the current map vote cache, so that players can look at the current tally.
|
|
var/list/map_vote_cache
|
|
|
|
/// Stores the previous map vote cache, used when a map vote is reverted.
|
|
var/list/previous_cache
|
|
|
|
/// Stores a formatted html string of the tally counts
|
|
var/tally_printout = span_red("Loading...")
|
|
|
|
/datum/controller/subsystem/map_vote/Initialize()
|
|
if(rustg_file_exists(MAP_VOTE_CACHE_LOCATION))
|
|
map_vote_cache = json_decode(file2text(MAP_VOTE_CACHE_LOCATION))
|
|
var/carryover = CONFIG_GET(number/map_vote_tally_carryover_percentage)
|
|
for(var/map_id in map_vote_cache)
|
|
map_vote_cache[map_id] = round(map_vote_cache[map_id] * (carryover / 100))
|
|
sanitize_cache()
|
|
else
|
|
map_vote_cache = list()
|
|
update_tally_printout()
|
|
return SS_INIT_SUCCESS
|
|
|
|
/datum/controller/subsystem/map_vote/proc/write_cache()
|
|
rustg_file_write(json_encode(map_vote_cache), MAP_VOTE_CACHE_LOCATION)
|
|
|
|
/datum/controller/subsystem/map_vote/proc/sanitize_cache()
|
|
var/max = CONFIG_GET(number/map_vote_maximum_tallies)
|
|
for(var/map_id in map_vote_cache)
|
|
if(!(map_id in config.maplist))
|
|
map_vote_cache -= map_id
|
|
var/count = map_vote_cache[map_id]
|
|
if(count > max)
|
|
map_vote_cache[map_id] = max
|
|
|
|
/datum/controller/subsystem/map_vote/proc/send_map_vote_notice(...)
|
|
var/static/last_message_at
|
|
if(last_message_at == world.time)
|
|
message_admins("Call to send_map_vote_notice twice in one game tick. Yell at someone to condense messages.")
|
|
last_message_at = world.time
|
|
|
|
var/list/messages = args.Copy()
|
|
to_chat(world, span_purple(examine_block("Map Vote\n<hr>\n[messages.Join("\n")]")))
|
|
|
|
/datum/controller/subsystem/map_vote/proc/finalize_map_vote(datum/vote/map_vote/map_vote)
|
|
if(already_voted)
|
|
message_admins("Attempted to finalize a map vote after a map vote has already been finalized.")
|
|
return
|
|
already_voted = TRUE
|
|
|
|
var/flat = CONFIG_GET(number/map_vote_flat_bonus)
|
|
previous_cache = map_vote_cache.Copy()
|
|
for(var/map_id in map_vote.choices)
|
|
var/datum/map_config/map = config.maplist[map_id]
|
|
map_vote_cache[map_id] += (map_vote.choices[map_id] * map.voteweight) + flat
|
|
sanitize_cache()
|
|
write_cache()
|
|
update_tally_printout()
|
|
|
|
if(admin_override)
|
|
send_map_vote_notice("Admin Override is in effect. Map will not be changed.", "Tallies are recorded and saved.")
|
|
return
|
|
|
|
var/list/valid_maps = filter_cache_to_valid_maps()
|
|
if(!length(valid_maps))
|
|
send_map_vote_notice("No valid maps.")
|
|
return
|
|
|
|
var/winner
|
|
var/winner_amount = 0
|
|
for(var/map in valid_maps)
|
|
if(!winner_amount)
|
|
winner = map
|
|
winner_amount = map_vote_cache[map]
|
|
continue
|
|
if(map_vote_cache[map] <= winner_amount)
|
|
continue
|
|
winner = map
|
|
winner_amount = map_vote_cache[map]
|
|
|
|
ASSERT(winner, "No winner found in map vote.")
|
|
set_next_map(config.maplist[winner])
|
|
var/list/messages = list("Map Selected - [span_bold(next_map_config.map_name)]")
|
|
messages += "Tallies at the time of selection:"
|
|
messages += tally_printout
|
|
|
|
// do not reset tallies if only one map is even possible
|
|
if(length(valid_maps) > 1)
|
|
map_vote_cache[winner] = CONFIG_GET(number/map_vote_minimum_tallies)
|
|
write_cache()
|
|
update_tally_printout()
|
|
else
|
|
messages += "Only one map was possible, tallies were not reset."
|
|
|
|
send_map_vote_notice(arglist(messages))
|
|
|
|
/// Returns a list of all map options that are invalid for the current population.
|
|
/datum/controller/subsystem/map_vote/proc/get_valid_map_vote_choices()
|
|
var/list/valid_maps = list()
|
|
|
|
// Fill in our default choices with all of the maps in our map config, if they are votable and not blocked.
|
|
var/list/maps = shuffle(global.config.maplist)
|
|
for(var/map in maps)
|
|
var/datum/map_config/possible_config = config.maplist[map]
|
|
if(!possible_config.votable || (possible_config.map_name in SSpersistence.blocked_maps))
|
|
continue
|
|
valid_maps += possible_config.map_name
|
|
|
|
var/filter_threshold = 0
|
|
if(SSticker.HasRoundStarted())
|
|
filter_threshold = get_active_player_count(alive_check = FALSE, afk_check = TRUE, human_check = FALSE)
|
|
else
|
|
filter_threshold = length(GLOB.clients)
|
|
|
|
for(var/map in valid_maps)
|
|
var/datum/map_config/possible_config = config.maplist[map]
|
|
if(possible_config.config_min_users > 0 && filter_threshold < possible_config.config_min_users)
|
|
valid_maps -= map
|
|
|
|
else if(possible_config.config_max_users > 0 && filter_threshold > possible_config.config_max_users)
|
|
valid_maps -= map
|
|
|
|
return valid_maps
|
|
|
|
/datum/controller/subsystem/map_vote/proc/filter_cache_to_valid_maps()
|
|
var/connected_players = length(GLOB.player_list)
|
|
var/list/valid_maps = list()
|
|
for(var/map_id in map_vote_cache)
|
|
var/datum/map_config/map = config.maplist[map_id]
|
|
if(!map.votable)
|
|
continue
|
|
if(map.config_min_users > 0 && (connected_players < map.config_min_users))
|
|
continue
|
|
if(map.config_max_users > 0 && (connected_players > map.config_max_users))
|
|
continue
|
|
valid_maps[map_id] = map_vote_cache[map_id]
|
|
return valid_maps
|
|
|
|
/datum/controller/subsystem/map_vote/proc/set_next_map(datum/map_config/change_to)
|
|
if(!change_to.MakeNextMap())
|
|
message_admins("Failed to set new map with next_map.json for [change_to.map_name]!")
|
|
return FALSE
|
|
|
|
next_map_config = change_to
|
|
return TRUE
|
|
|
|
/datum/controller/subsystem/map_vote/proc/revert_next_map()
|
|
if(!next_map_config)
|
|
return
|
|
if(previous_cache)
|
|
map_vote_cache = previous_cache
|
|
previous_cache = null
|
|
|
|
already_voted = FALSE
|
|
admin_override = FALSE
|
|
send_map_vote_notice("Next map reverted. Voting re-enabled.")
|
|
|
|
#undef MAP_VOTE_CACHE_LOCATION
|
|
|
|
/datum/controller/subsystem/map_vote/proc/update_tally_printout()
|
|
var/list/data = list()
|
|
for(var/map_id in map_vote_cache)
|
|
var/datum/map_config/map = config.maplist[map_id]
|
|
data += "[map.map_name] - [map_vote_cache[map_id]]"
|
|
tally_printout = examine_block("Current Tallies\n<hr>\n[data.Join("\n")]")
|