From 0ef5c3d049015ecbbb1d59fdf2aefd21b9742fc2 Mon Sep 17 00:00:00 2001 From: Zephyr <12817816+ZephyrTFA@users.noreply.github.com> Date: Sun, 29 Sep 2024 20:09:08 -0400 Subject: [PATCH] Persistent Map Vote Tallies (#86788) ## About The Pull Request Changes map votes to be based on a persistent tally count. Tallies for maps are cached between rounds and are added to by map votes. When a map is chosen, and it wasn't the only valid one, the tallies for said chosen map will be reset. Refactors map vote handling and moves it from SSmapping to SSmap_vote. Rock the Vote has been removed as a result of this refactor. ## Why It's Good For The Game Makes it more likely that all maps will be played over the course of a server instead of always being truly random. Removes some clutter off of SSmapping. :cl: refactor: Map Votes are now carried over between rounds. When a map vote is actually a contest, the winning map will have its votes reset. /:cl: --- code/__DEFINES/maps.dm | 2 +- code/__DEFINES/memory_defines.dm | 2 +- .../configuration/entries/general.dm | 24 +++ code/controllers/subsystem/blackbox.dm | 2 +- code/controllers/subsystem/library.dm | 6 +- code/controllers/subsystem/map_vote.dm | 160 ++++++++++++++++++ code/controllers/subsystem/mapping.dm | 145 +++------------- .../subsystem/persistence/_persistence.dm | 4 +- .../subsystem/persistence/engravings.dm | 4 +- code/controllers/subsystem/statpanel.dm | 4 +- code/controllers/subsystem/ticker.dm | 16 +- code/controllers/subsystem/time_track.dm | 2 +- code/controllers/subsystem/title.dm | 2 +- code/controllers/subsystem/vote.dm | 20 ++- code/datums/id_trim/jobs.dm | 2 +- code/datums/votes/map_vote.dm | 62 +------ code/datums/votes/restart_vote.dm | 4 +- code/datums/votes/rock_the_vote.dm | 62 ------- code/datums/world_topic.dm | 2 +- .../game/machinery/computer/communications.dm | 2 +- code/game/world.dm | 8 +- code/modules/admin/verbs/maprotation.dm | 17 +- .../wizard/grand_ritual/finales/armageddon.dm | 2 +- code/modules/client/verbs/ooc.dm | 6 + code/modules/discord/tgs_commands.dm | 2 +- code/modules/escape_menu/details.dm | 2 +- code/modules/photography/photos/frame.dm | 4 +- .../mapGenerators/repair.dm | 2 +- code/modules/shuttle/emergency.dm | 2 +- code/modules/shuttle/shuttle.dm | 2 +- code/modules/unit_tests/unit_test.dm | 6 +- config/map_vote.txt | 12 ++ tgstation.dme | 2 +- 33 files changed, 291 insertions(+), 303 deletions(-) create mode 100644 code/controllers/subsystem/map_vote.dm delete mode 100644 code/datums/votes/rock_the_vote.dm create mode 100644 config/map_vote.txt diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index 3c87195e990..33147916f4e 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -221,7 +221,7 @@ Always compile, always use that verb, and always make sure that it works for wha #define CLUSTER_CHECK_ALL 30 //!Don't let anything cluster, like, at all /// Checks the job changes in the map config for the passed change key. -#define CHECK_MAP_JOB_CHANGE(job, change) SSmapping.config.job_changes?[job]?[change] +#define CHECK_MAP_JOB_CHANGE(job, change) SSmapping.current_map.job_changes?[job]?[change] ///Identifiers for away mission spawnpoints #define AWAYSTART_BEACH "AWAYSTART_BEACH" diff --git a/code/__DEFINES/memory_defines.dm b/code/__DEFINES/memory_defines.dm index 2b07ab6270d..f6c537f9e81 100644 --- a/code/__DEFINES/memory_defines.dm +++ b/code/__DEFINES/memory_defines.dm @@ -1,7 +1,7 @@ ///name of the file that has all the memory strings #define MEMORY_FILE "memories.json" ///name of the file that has all the saved engravings -#define ENGRAVING_SAVE_FILE "data/engravings/[SSmapping.config.map_name]_engravings.json" +#define ENGRAVING_SAVE_FILE "data/engravings/[SSmapping.current_map.map_name]_engravings.json" ///name of the file that has all the prisoner tattoos #define PRISONER_TATTOO_SAVE_FILE "data/engravings/prisoner_tattoos.json" ///Current version of the engraving persistence json diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index d256ce5a584..e1ed3284441 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -738,3 +738,27 @@ /datum/config_entry/number/upload_limit_admin default = 5242880 min_val = 0 + +/// The minimum number of tallies a map vote entry can have. +/datum/config_entry/number/map_vote_minimum_tallies + default = 1 + min_val = 0 + max_val = 50 + +/// The flat amount all maps get by default +/datum/config_entry/number/map_vote_flat_bonus + default = 5 + min_val = 0 + max_val = INFINITY + +/// The maximum number of tallies a map vote entry can have. +/datum/config_entry/number/map_vote_maximum_tallies + default = 200 + min_val = 0 + max_val = INFINITY + +/// The number of tallies that are carried over between rounds. +/datum/config_entry/number/map_vote_tally_carryover_percentage + default = 100 + min_val = 0 + max_val = 100 diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 18ba37eb137..83c666de64a 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -357,7 +357,7 @@ Versioning "z_coord" = L.z, "last_words" = L.last_words, "suicide" = did_they_suicide, - "map" = SSmapping.config.map_name, + "map" = SSmapping.current_map.map_name, "internet_address" = world.internet_address || "0", "port" = "[world.port]", "round_id" = GLOB.round_id, diff --git a/code/controllers/subsystem/library.dm b/code/controllers/subsystem/library.dm index a657e442748..bfe77f70f02 100644 --- a/code/controllers/subsystem/library.dm +++ b/code/controllers/subsystem/library.dm @@ -26,14 +26,14 @@ SUBSYSTEM_DEF(library) /datum/controller/subsystem/library/proc/load_shelves() var/list/datum/callback/load_callbacks = list() - + for(var/obj/structure/bookcase/case_to_load as anything in shelves_to_load) if(!case_to_load) stack_trace("A null bookcase somehow ended up in SSlibrary's shelves_to_load list. Did something harddel?") continue load_callbacks += CALLBACK(case_to_load, TYPE_PROC_REF(/obj/structure/bookcase, load_shelf)) shelves_to_load = null - + //Load all of the shelves asyncronously at the same time, blocking until the last one is finished. callback_select(load_callbacks, savereturns = FALSE) @@ -59,6 +59,6 @@ SUBSYSTEM_DEF(library) /datum/controller/subsystem/library/proc/prepare_library_areas() library_areas = typesof(/area/station/service/library) - /area/station/service/library/abandoned - var/list/additional_areas = SSmapping.config.library_areas + var/list/additional_areas = SSmapping.current_map.library_areas if(additional_areas) library_areas += additional_areas diff --git a/code/controllers/subsystem/map_vote.dm b/code/controllers/subsystem/map_vote.dm new file mode 100644 index 00000000000..7d0be38f920 --- /dev/null +++ b/code/controllers/subsystem/map_vote.dm @@ -0,0 +1,160 @@ +#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
\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 = pick_weight(filter_cache_to_valid_maps()) + set_next_map(config.maplist[winner]) + send_map_vote_notice("Map Selected - [span_bold(next_map_config.map_name)]") + + // 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() + +/// 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
\n[data.Join("\n")]") diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 4d9d9b142ee..05f0746690b 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -6,15 +6,8 @@ SUBSYSTEM_DEF(mapping) var/list/nuke_tiles = list() var/list/nuke_threats = list() - var/datum/map_config/config - var/datum/map_config/next_map_config - - /// Has the map for the next round been voted for already? - var/map_voted = FALSE - /// Has the map for the next round been deliberately chosen by an admin? - var/map_force_chosen = FALSE - /// Has the map vote been rocked? - var/map_vote_rocked = FALSE + /// The current map config the server loaded at round start. + var/datum/map_config/current_map var/list/map_templates = list() @@ -95,20 +88,20 @@ SUBSYSTEM_DEF(mapping) /datum/controller/subsystem/mapping/PreInit() ..() #ifdef FORCE_MAP - config = load_map_config(FORCE_MAP, FORCE_MAP_DIRECTORY) + current_map = load_map_config(FORCE_MAP, FORCE_MAP_DIRECTORY) #else - config = load_map_config(error_if_missing = FALSE) + current_map = load_map_config(error_if_missing = FALSE) #endif /datum/controller/subsystem/mapping/Initialize() if(initialized) return SS_INIT_SUCCESS - if(config.defaulted) - var/old_config = config - config = global.config.defaultmap - if(!config || config.defaulted) - to_chat(world, span_boldannounce("Unable to load next or default map config, defaulting to MetaStation.")) - config = old_config + if(current_map.defaulted) + var/datum/map_config/old_config = current_map + current_map = config.defaultmap + if(!current_map || current_map.defaulted) + to_chat(world, span_boldannounce("Unable to load next or default map config, defaulting to [old_config.map_name].")) + current_map = old_config plane_offset_to_true = list() true_to_offset_planes = list() plane_to_offset = list() @@ -132,11 +125,11 @@ SUBSYSTEM_DEF(mapping) #ifndef LOWMEMORYMODE // Create space ruin levels - while (space_levels_so_far < config.space_ruin_levels) + while (space_levels_so_far < current_map.space_ruin_levels) add_new_zlevel("Ruin Area [space_levels_so_far+1]", ZTRAITS_SPACE) ++space_levels_so_far // Create empty space levels - while (space_levels_so_far < config.space_empty_levels + config.space_ruin_levels) + while (space_levels_so_far < current_map.space_empty_levels + current_map.space_ruin_levels) empty_space = add_new_zlevel("Empty Area [space_levels_so_far+1]", list(ZTRAIT_LINKAGE = CROSSLINKED)) ++space_levels_so_far @@ -144,7 +137,7 @@ SUBSYSTEM_DEF(mapping) if(CONFIG_GET(flag/roundstart_away)) createRandomZlevel(prob(CONFIG_GET(number/config_gateway_chance))) - else if (SSmapping.config.load_all_away_missions) // we're likely in a local testing environment, so punch it. + else if (SSmapping.current_map.load_all_away_missions) // we're likely in a local testing environment, so punch it. load_all_away_missions() loading_ruins = TRUE @@ -363,9 +356,7 @@ Used by the AI doomsday and the self-destruct nuke. holodeck_templates = SSmapping.holodeck_templates areas_in_z = SSmapping.areas_in_z - config = SSmapping.config - next_map_config = SSmapping.next_map_config - + current_map = SSmapping.current_map clearing_reserved_turfs = SSmapping.clearing_reserved_turfs z_list = SSmapping.z_list @@ -431,22 +422,22 @@ Used by the AI doomsday and the self-destruct nuke. // load the station station_start = world.maxz + 1 - INIT_ANNOUNCE("Loading [config.map_name]...") - LoadGroup(FailedZs, "Station", config.map_path, config.map_file, config.traits, ZTRAITS_STATION) + INIT_ANNOUNCE("Loading [current_map.map_name]...") + LoadGroup(FailedZs, "Station", current_map.map_path, current_map.map_file, current_map.traits, ZTRAITS_STATION) if(SSdbcore.Connect()) var/datum/db_query/query_round_map_name = SSdbcore.NewQuery({" UPDATE [format_table_name("round")] SET map_name = :map_name WHERE id = :round_id - "}, list("map_name" = config.map_name, "round_id" = GLOB.round_id)) + "}, list("map_name" = current_map.map_name, "round_id" = GLOB.round_id)) query_round_map_name.Execute() qdel(query_round_map_name) #ifndef LOWMEMORYMODE - if(config.minetype == "lavaland") + if(current_map.minetype == "lavaland") LoadGroup(FailedZs, "Lavaland", "map_files/Mining", "Lavaland.dmm", default_traits = ZTRAITS_LAVALAND) - else if (!isnull(config.minetype) && config.minetype != "none") - INIT_ANNOUNCE("WARNING: An unknown minetype '[config.minetype]' was set! This is being ignored! Update the maploader code!") + else if (!isnull(current_map.minetype) && current_map.minetype != "none") + INIT_ANNOUNCE("WARNING: An unknown minetype '[current_map.minetype]' was set! This is being ignored! Update the maploader code!") #endif if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen @@ -459,10 +450,8 @@ Used by the AI doomsday and the self-destruct nuke. #undef INIT_ANNOUNCE // Custom maps are removed after station loading so the map files does not persist for no reason. - if(config.map_path == CUSTOM_MAP_PATH) - fdel("_maps/custom/[config.map_file]") - // And as the file is now removed set the next map to default. - next_map_config = load_default_map_config() + if(current_map.map_path == CUSTOM_MAP_PATH) + fdel("_maps/custom/[current_map.map_file]") /** * Global list of AREA TYPES that are associated with the station. @@ -494,88 +483,6 @@ GLOBAL_LIST_EMPTY(the_station_areas) for(var/area/A as anything in GLOB.areas) A.RunTerrainPopulation() -/datum/controller/subsystem/mapping/proc/maprotate() - if(map_voted || SSmapping.next_map_config) //If voted or set by other means. - return - - var/players = GLOB.clients.len - var/list/mapvotes = list() - //count votes - var/pmv = CONFIG_GET(flag/preference_map_voting) - if(pmv) - for (var/client/c in GLOB.clients) - var/vote = c.prefs.read_preference(/datum/preference/choiced/preferred_map) - if (!vote) - if (global.config.defaultmap) - mapvotes[global.config.defaultmap.map_name] += 1 - continue - mapvotes[vote] += 1 - else - for(var/M in global.config.maplist) - mapvotes[M] = 1 - - //filter votes - for (var/map in mapvotes) - if (!map) - mapvotes.Remove(map) - continue - if (!(map in global.config.maplist)) - mapvotes.Remove(map) - continue - if(map in SSpersistence.blocked_maps) - mapvotes.Remove(map) - continue - var/datum/map_config/VM = global.config.maplist[map] - if (!VM) - mapvotes.Remove(map) - continue - if (VM.voteweight <= 0) - mapvotes.Remove(map) - continue - if (VM.config_min_users > 0 && players < VM.config_min_users) - mapvotes.Remove(map) - continue - if (VM.config_max_users > 0 && players > VM.config_max_users) - mapvotes.Remove(map) - continue - - if(pmv) - mapvotes[map] = mapvotes[map]*VM.voteweight - - var/pickedmap = pick_weight(mapvotes) - if (!pickedmap) - return - var/datum/map_config/VM = global.config.maplist[pickedmap] - message_admins("Randomly rotating map to [VM.map_name]") - . = changemap(VM) - if (. && VM.map_name != config.map_name) - to_chat(world, span_boldannounce("Map rotation has chosen [VM.map_name] for next round!")) - -/datum/controller/subsystem/mapping/proc/mapvote() - if(map_voted || SSmapping.next_map_config) //If voted or set by other means. - return - if(SSvote.current_vote) //Theres already a vote running, default to rotation. - maprotate() - return - SSvote.initiate_vote(/datum/vote/map_vote, "automatic map rotation", forced = TRUE) - -/datum/controller/subsystem/mapping/proc/changemap(datum/map_config/change_to) - if(!change_to.MakeNextMap()) - next_map_config = load_default_map_config() - message_admins("Failed to set new map with next_map.json for [change_to.map_name]! Using default as backup!") - return - - var/filter_threshold = get_active_player_count(alive_check = FALSE, afk_check = TRUE, human_check = FALSE) - if (change_to.config_min_users > 0 && filter_threshold != 0 && filter_threshold < change_to.config_min_users) - message_admins("[change_to.map_name] was chosen for the next map, despite there being less current players than its set minimum population range!") - log_game("[change_to.map_name] was chosen for the next map, despite there being less current players than its set minimum population range!") - if (change_to.config_max_users > 0 && filter_threshold > change_to.config_max_users) - message_admins("[change_to.map_name] was chosen for the next map, despite there being more current players than its set maximum population range!") - log_game("[change_to.map_name] was chosen for the next map, despite there being more current players than its set maximum population range!") - - next_map_config = change_to - return TRUE - /datum/controller/subsystem/mapping/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup var/list/filelist = flist(path) for(var/map in filelist) @@ -590,10 +497,10 @@ GLOBAL_LIST_EMPTY(the_station_areas) /datum/controller/subsystem/mapping/proc/preloadRuinTemplates() // Still supporting bans by filename var/list/banned = generateMapList("spaceruinblacklist.txt") - if(config.minetype == "lavaland") + if(current_map.minetype == "lavaland") banned += generateMapList("lavaruinblacklist.txt") - else if(config.blacklist_file) - banned += generateMapList(config.blacklist_file) + else if(current_map.blacklist_file) + banned += generateMapList(current_map.blacklist_file) for(var/item in sort_list(subtypesof(/datum/map_template/ruin), GLOBAL_PROC_REF(cmp_ruincost_priority))) var/datum/map_template/ruin/ruin_type = item @@ -953,7 +860,7 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away /// Returns true if the map we're playing on is on a planet /datum/controller/subsystem/mapping/proc/is_planetary() - return config.planetary + return current_map.planetary /// For debug purposes, will add every single away mission present in a given directory. /// You can optionally pass in a string directory to load from instead of the default. diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index 6438015d11d..d38d7fa372e 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -111,7 +111,7 @@ SUBSYSTEM_DEF(persistence) for(var/map in config.maplist) var/datum/map_config/VM = config.maplist[map] var/run = 0 - if(VM.map_name == SSmapping.config.map_name) + if(VM.map_name == SSmapping.current_map.map_name) run++ for(var/name in SSpersistence.saved_maps) if(VM.map_name == name) @@ -128,7 +128,7 @@ SUBSYSTEM_DEF(persistence) saved_maps += mapstosave for(var/i = mapstosave; i > 1; i--) saved_maps[i] = saved_maps[i-1] - saved_maps[1] = SSmapping.config.map_name + saved_maps[1] = SSmapping.current_map.map_name var/json_file = file(FILE_RECENT_MAPS) var/list/file_data = list() file_data["data"] = saved_maps diff --git a/code/controllers/subsystem/persistence/engravings.dm b/code/controllers/subsystem/persistence/engravings.dm index 6808a101bb8..ad00c7909d7 100644 --- a/code/controllers/subsystem/persistence/engravings.dm +++ b/code/controllers/subsystem/persistence/engravings.dm @@ -14,7 +14,7 @@ saved_engravings = json["entries"] if(!saved_engravings.len) - log_world("Failed to load engraved messages on map [SSmapping.config.map_name]") + log_world("Failed to load engraved messages on map [SSmapping.current_map.map_name]") return var/list/viable_turfs = get_area_turfs(/area/station/maintenance, subtypes = TRUE) + get_area_turfs(/area/station/security/prison, subtypes = TRUE) @@ -42,7 +42,7 @@ successfully_loaded_engravings++ turfs_to_pick_from -= engraved_wall - log_world("Loaded [successfully_loaded_engravings] engraved messages on map [SSmapping.config.map_name]") + log_world("Loaded [successfully_loaded_engravings] engraved messages on map [SSmapping.current_map.map_name]") ///Saves all new engravings in the world. /datum/controller/subsystem/persistence/proc/save_wall_engravings() diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 020598a573b..cf158586ce4 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -22,9 +22,9 @@ SUBSYSTEM_DEF(statpanels) /datum/controller/subsystem/statpanels/fire(resumed = FALSE) if (!resumed) num_fires++ - var/datum/map_config/cached = SSmapping.next_map_config + var/datum/map_config/cached = SSmap_vote.next_map_config global_data = list( - "Map: [SSmapping.config?.map_name || "Loading..."]", + "Map: [SSmapping.current_map?.map_name || "Loading..."]", cached ? "Next Map: [cached.map_name]" : null, "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]", "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]", diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 800eeaa41c9..bcd33f04c98 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -93,12 +93,12 @@ SUBSYSTEM_DEF(ticker) switch(L.len) if(3) //rare+MAP+sound.ogg or MAP+rare.sound.ogg -- Rare Map-specific sounds if(use_rare_music) - if(L[1] == "rare" && L[2] == SSmapping.config.map_name) + if(L[1] == "rare" && L[2] == SSmapping.current_map.map_name) music += S - else if(L[2] == "rare" && L[1] == SSmapping.config.map_name) + else if(L[2] == "rare" && L[1] == SSmapping.current_map.map_name) music += S if(2) //rare+sound.ogg or MAP+sound.ogg -- Rare sounds or Map-specific sounds - if((use_rare_music && L[1] == "rare") || (L[1] == SSmapping.config.map_name)) + if((use_rare_music && L[1] == "rare") || (L[1] == SSmapping.current_map.map_name)) music += S if(1) //sound.ogg -- common sound if(L[1] == "exclude") @@ -157,7 +157,7 @@ SUBSYSTEM_DEF(ticker) for(var/client/C in GLOB.clients) window_flash(C, ignorepref = TRUE) //let them know lobby has opened up. to_chat(world, span_notice("Welcome to [station_name()]!")) - send2chat(new /datum/tgs_message_content("New round starting on [SSmapping.config.map_name]!"), CONFIG_GET(string/channel_announce_new_game)) + send2chat(new /datum/tgs_message_content("New round starting on [SSmapping.current_map.map_name]!"), CONFIG_GET(string/channel_announce_new_game)) current_state = GAME_STATE_PREGAME SEND_SIGNAL(src, COMSIG_TICKER_ENTER_PREGAME) @@ -211,7 +211,6 @@ SUBSYSTEM_DEF(ticker) toggle_ooc(TRUE) // Turn it on toggle_dooc(TRUE) declare_completion(force_ending) - check_maprotate() Master.SetRunLevel(RUNLEVEL_POSTGAME) /// Checks if the round should be ending, called every ticker tick @@ -514,13 +513,6 @@ SUBSYSTEM_DEF(ticker) queued_players -= next_in_line queue_delay = 0 -/datum/controller/subsystem/ticker/proc/check_maprotate() - if(!CONFIG_GET(flag/maprotation)) - return - if(world.time - SSticker.round_start_time < 10 MINUTES) //Not forcing map rotation for very short rounds. - return - INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping/, maprotate)) - /datum/controller/subsystem/ticker/proc/HasRoundStarted() return current_state >= GAME_STATE_PLAYING diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm index b3a4fe7e869..4c706fdaf6d 100644 --- a/code/controllers/subsystem/time_track.dm +++ b/code/controllers/subsystem/time_track.dm @@ -42,7 +42,7 @@ SUBSYSTEM_DEF(time_track) ) /datum/controller/subsystem/time_track/Initialize() - GLOB.perf_log = "[GLOB.log_directory]/perf-[GLOB.round_id ? GLOB.round_id : "NULL"]-[SSmapping.config?.map_name].csv" + GLOB.perf_log = "[GLOB.log_directory]/perf-[GLOB.round_id ? GLOB.round_id : "NULL"]-[SSmapping.current_map.map_name].csv" world.Profile(PROFILE_RESTART, type = "sendmaps") //Need to do the sendmaps stuff in its own file, since it works different then everything else var/list/sendmaps_headers = list() diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm index dbaa7ddeb48..8df9349ff03 100644 --- a/code/controllers/subsystem/title.dm +++ b/code/controllers/subsystem/title.dm @@ -25,7 +25,7 @@ SUBSYSTEM_DEF(title) for(var/S in provisional_title_screens) var/list/L = splittext(S,"+") - if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && LOWER_TEXT(L[1]) == "rare") || (LOWER_TEXT(L[1]) == LOWER_TEXT(SSmapping.config.map_name))))) + if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && LOWER_TEXT(L[1]) == "rare") || (LOWER_TEXT(L[1]) == LOWER_TEXT(SSmapping.current_map.map_name))))) title_screens += S if(length(title_screens)) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 7bed63cc36f..d0e642bd3aa 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -101,24 +101,28 @@ SUBSYSTEM_DEF(vote) // stringify the winners to prevent potential unimplemented serialization errors. // Perhaps this can be removed in the future and we assert that vote choices must implement serialization. - var/final_winner_string = final_winner && "[final_winner]" + var/final_winner_string = (final_winner && "[final_winner]") || "NO WINNER" var/list/winners_string = list() - for(var/winner in winners) - winners_string += "[winner]" + + if(length(winners)) + for(var/winner in winners) + winners_string += "[winner]" + else + winners_string = list("NO WINNER") var/list/vote_log_data = list( + "type" = "[current_vote.type]", "choices" = vote_choice_data, "total" = total_votes, "winners" = winners_string, "final_winner" = final_winner_string, ) - var/log_string = replacetext(to_display, "\n", "\\n") // 'keep' the newlines, but dont actually print them as newlines - log_vote(log_string, vote_log_data) - to_chat(world, span_infoplain(vote_font("\n[to_display]"))) + log_vote("vote finalized", vote_log_data) + if(to_display) + to_chat(world, span_infoplain(vote_font("\n[to_display]"))) // Finally, doing any effects on vote completion - if (final_winner) // if no one voted, or the vote cannot be won, final_winner will be null - current_vote.finalize_vote(final_winner) + current_vote.finalize_vote(final_winner) /** * One selection per person, and the selection with the most votes wins. diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index a7bc17d7943..34432a638db 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -27,7 +27,7 @@ job = SSjob.get_job_type(job) if(isnull(job_changes)) - job_changes = SSmapping.config.job_changes + job_changes = SSmapping.current_map.job_changes if(!length(job_changes)) refresh_trim_access() diff --git a/code/datums/votes/map_vote.dm b/code/datums/votes/map_vote.dm index abe452ce4fe..b4f938a42e4 100644 --- a/code/datums/votes/map_vote.dm +++ b/code/datums/votes/map_vote.dm @@ -2,29 +2,18 @@ name = "Map" default_message = "Vote for next round's map!" count_method = VOTE_COUNT_METHOD_SINGLE - winner_method = VOTE_WINNER_METHOD_WEIGHTED_RANDOM + winner_method = VOTE_WINNER_METHOD_NONE display_statistics = FALSE /datum/vote/map_vote/New() . = ..() - - default_choices = 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 - - default_choices += possible_config.map_name + default_choices = SSmap_vote.get_valid_map_vote_choices() /datum/vote/map_vote/create_vote() . = ..() if(!.) return FALSE - choices -= get_choices_invalid_for_population() if(length(choices) == 1) // Only one choice, no need to vote. Let's just auto-rotate it to the only remaining map because it would just happen anyways. var/datum/map_config/change_me_out = global.config.maplist[choices[1]] finalize_vote(choices[1])// voted by not voting, very sad. @@ -48,35 +37,16 @@ . = ..() if(. != VOTE_AVAILABLE) return . - if(forced) - return VOTE_AVAILABLE - var/num_choices = length(default_choices - get_choices_invalid_for_population()) + + var/num_choices = length(default_choices) if(num_choices <= 1) return "There [num_choices == 1 ? "is only one map" : "are no maps"] to choose from." - if(SSmapping.map_vote_rocked) - return VOTE_AVAILABLE - if(SSmapping.map_voted) + if(SSmap_vote.next_map_config) return "The next map has already been selected." return VOTE_AVAILABLE -/// Returns a list of all map options that are invalid for the current population. -/datum/vote/map_vote/proc/get_choices_invalid_for_population() - 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 = GLOB.clients.len - - var/list/invalid_choices = list() - for(var/map in default_choices) - var/datum/map_config/possible_config = config.maplist[map] - if(possible_config.config_min_users > 0 && filter_threshold < possible_config.config_min_users) - invalid_choices += map - - else if(possible_config.config_max_users > 0 && filter_threshold > possible_config.config_max_users) - invalid_choices += map - - return invalid_choices +/datum/vote/map_vote/get_result_text(list/all_winners, real_winner, list/non_voters) + return null /datum/vote/map_vote/get_vote_result(list/non_voters) // Even if we have default no vote off, @@ -97,20 +67,4 @@ return ..() /datum/vote/map_vote/finalize_vote(winning_option) - var/datum/map_config/winning_map = global.config.maplist[winning_option] - if(!istype(winning_map)) - CRASH("[type] wasn't passed a valid winning map choice. (Got: [winning_option || "null"] - [winning_map || "null"])") - - SSmapping.changemap(winning_map) - SSmapping.map_voted = TRUE - if(SSmapping.map_vote_rocked) - SSmapping.map_vote_rocked = FALSE - -/proc/revert_map_vote() - var/datum/map_config/override_map = SSmapping.config - if(isnull(override_map)) - return - - SSmapping.changemap(override_map) - log_game("The next map has been reset to [override_map.map_name].") - send_to_playing_players(span_boldannounce("The next map is: [override_map.map_name].")) + SSmap_vote.finalize_map_vote(src) diff --git a/code/datums/votes/restart_vote.dm b/code/datums/votes/restart_vote.dm index 3c74d7e518e..ba0fdf78083 100644 --- a/code/datums/votes/restart_vote.dm +++ b/code/datums/votes/restart_vote.dm @@ -57,10 +57,10 @@ return // If there was a previous map vote, we revert the change. - if(!isnull(SSmapping.next_map_config)) + if(!isnull(SSmap_vote.next_map_config)) log_game("The next map has been reset due to successful restart vote.") send_to_playing_players(span_boldannounce("The next map has been reset due to successful restart vote.")) - revert_map_vote() + SSmap_vote.revert_next_map() SSticker.force_ending = FORCE_END_ROUND log_game("End round forced by successful restart vote.") diff --git a/code/datums/votes/rock_the_vote.dm b/code/datums/votes/rock_the_vote.dm deleted file mode 100644 index 6c7ac4ff257..00000000000 --- a/code/datums/votes/rock_the_vote.dm +++ /dev/null @@ -1,62 +0,0 @@ -#define CHOICE_TO_ROCK "Yes, re-do the map vote." -#define CHOICE_NOT_TO_ROCK "No, keep the currently selected map." - -/// If a map vote is called before the emergency shuttle leaves the station, the players can call another vote to re-run the vote on the shuttle leaving. -/datum/vote/rock_the_vote - name = "Rock the Vote" - override_question = "Rock the Vote?" - contains_vote_in_name = TRUE //lol - default_choices = list( - CHOICE_TO_ROCK, - CHOICE_NOT_TO_ROCK, - ) - default_message = "Override the current map vote." - /// The number of times we have rocked the vote thus far. - var/rocking_votes = 0 - -/datum/vote/rock_the_vote/toggle_votable() - CONFIG_SET(flag/allow_rock_the_vote, !CONFIG_GET(flag/allow_rock_the_vote)) - -/datum/vote/rock_the_vote/is_config_enabled() - return CONFIG_GET(flag/allow_rock_the_vote) - -/datum/vote/rock_the_vote/can_be_initiated(forced) - . = ..() - if(. != VOTE_AVAILABLE) - return . - - if(SSticker.current_state == GAME_STATE_FINISHED) - return "The game is finished, no map votes can be initiated." - - if(rocking_votes >= CONFIG_GET(number/max_rocking_votes)) - return "The maximum number of times to rock the vote has been reached." - - if(SSmapping.map_vote_rocked) - return "The vote has already been rocked! Initiate a map vote!" - - if(!SSmapping.map_voted) - return "Rocking the vote is disabled because no map has been voted on yet!" - - if(SSmapping.map_force_chosen) - return "Rocking the vote is disabled because an admin has forcibly set the map!" - - if(EMERGENCY_ESCAPED_OR_ENDGAMED && SSmapping.map_voted) - return "The emergency shuttle has already left the station and the next map has already been chosen!" - - return VOTE_AVAILABLE - -/datum/vote/rock_the_vote/finalize_vote(winning_option) - rocking_votes++ - if(winning_option == CHOICE_NOT_TO_ROCK) - return - - if(winning_option == CHOICE_TO_ROCK) - to_chat(world, span_boldannounce("The vote has been rocked! Players are now able to re-run the map vote once more.")) - message_admins("The players have successfully rocked the vote.") - SSmapping.map_vote_rocked = TRUE - return - - CRASH("[type] wasn't passed a valid winning choice. (Got: [winning_option || "null"])") - -#undef CHOICE_TO_ROCK -#undef CHOICE_NOT_TO_ROCK diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index f2bf896bb10..a9971f6068c 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -212,7 +212,7 @@ .["admins"] = presentmins.len + afkmins.len //equivalent to the info gotten from adminwho .["gamestate"] = SSticker.current_state - .["map_name"] = SSmapping.config?.map_name || "Loading..." + .["map_name"] = SSmapping.current_map.map_name || "Loading..." if(key_valid) .["active_players"] = get_active_player_count() diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 76701eca0d8..abbfb055e16 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -672,7 +672,7 @@ /// Returns TRUE if the user can buy shuttles. /// If they cannot, returns FALSE or a string detailing why. /obj/machinery/computer/communications/proc/can_buy_shuttles(mob/user) - if (!SSmapping.config.allow_custom_shuttles) + if (!SSmapping.current_map.allow_custom_shuttles) return FALSE if (HAS_SILICON_ACCESS(user)) return FALSE diff --git a/code/game/world.dm b/code/game/world.dm index 765aa7c18ef..184b13be642 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -399,10 +399,10 @@ GLOBAL_VAR(tracy_log) new_status += " | Shuttle: [SSshuttle.emergency.getModeStr()] [SSshuttle.emergency.getTimerStr()]" else if(SSticker.current_state == GAME_STATE_FINISHED) new_status += "
RESTARTING" - if(SSmapping.config) - new_status += "
Map: [SSmapping.config.map_path == CUSTOM_MAP_PATH ? "Uncharted Territory" : SSmapping.config.map_name]" - if(SSmapping.next_map_config) - new_status += "[SSmapping.config ? " | " : "
"]Next: [SSmapping.next_map_config.map_path == CUSTOM_MAP_PATH ? "Uncharted Territory" : SSmapping.next_map_config.map_name]" + if(SSmapping.current_map) + new_status += "
Map: [SSmapping.current_map.map_path == CUSTOM_MAP_PATH ? "Uncharted Territory" : SSmapping.current_map.map_name]" + if(SSmap_vote.next_map_config) + new_status += "[SSmapping.current_map ? " | " : "
"]Next: [SSmap_vote.next_map_config.map_path == CUSTOM_MAP_PATH ? "Uncharted Territory" : SSmap_vote.next_map_config.map_name]" status = new_status diff --git a/code/modules/admin/verbs/maprotation.dm b/code/modules/admin/verbs/maprotation.dm index 09d6d93bee6..38d7535758f 100644 --- a/code/modules/admin/verbs/maprotation.dm +++ b/code/modules/admin/verbs/maprotation.dm @@ -1,12 +1,3 @@ - -ADMIN_VERB(force_random_rotate, R_SERVER, "Trigger 'Random' Map Rotation", "Force a map vote.", ADMIN_CATEGORY_SERVER) - var/rotate = tgui_alert(user,"Force a random map rotation to trigger?", "Rotate map?", list("Yes", "Cancel")) - if (rotate != "Yes") - return - message_admins("[key_name_admin(user)] is forcing a random map rotation.") - log_admin("[key_name(user)] is forcing a random map rotation.") - SSmapping.maprotate() - ADMIN_VERB(admin_change_map, R_SERVER, "Change Map", "Set the next map.", ADMIN_CATEGORY_SERVER) var/list/maprotatechoices = list() for (var/map in config.maplist) @@ -119,14 +110,14 @@ ADMIN_VERB(admin_change_map, R_SERVER, "Change Map", "Set the next map.", ADMIN_ fdel(PATH_TO_NEXT_MAP_JSON) text2file(json_encode(json_value), PATH_TO_NEXT_MAP_JSON) - if(SSmapping.changemap(virtual_map)) + if(SSmap_vote.set_next_map(virtual_map)) message_admins("[key_name_admin(user)] has changed the map to [virtual_map.map_name]") - SSmapping.map_force_chosen = TRUE + SSmap_vote.admin_override = TRUE fdel("data/custom_map_json/[config_file]") else var/datum/map_config/virtual_map = maprotatechoices[chosenmap] message_admins("[key_name_admin(user)] is changing the map to [virtual_map.map_name]") log_admin("[key_name(user)] is changing the map to [virtual_map.map_name]") - if (SSmapping.changemap(virtual_map)) + if (SSmap_vote.set_next_map(virtual_map)) message_admins("[key_name_admin(user)] has changed the map to [virtual_map.map_name]") - SSmapping.map_force_chosen = TRUE + SSmap_vote.admin_override = TRUE diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm b/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm index 9b67aa24a53..3716a684c6a 100644 --- a/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm +++ b/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm @@ -38,7 +38,7 @@ var/static/list/doom_options = list() if (!length(doom_options)) doom_options = list(DOOM_SINGULARITY, DOOM_TESLA) - if (!SSmapping.config.planetary) + if (!SSmapping.is_planetary()) doom_options += DOOM_METEORS switch(pick(doom_options)) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 0bd1a9ea5a4..127840631d6 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -456,3 +456,9 @@ ADMIN_VERB(reset_ooc_color, R_FUN, "Reset Player OOC Color", "Returns player OOC ASSERT(prefs, "User attempted to export preferences while preferences were null!") // what the fuck prefs.savefile.export_json_to_client(usr, ckey) + +/client/verb/map_vote_tally_count() + set name = "Show Map Vote Tallies" + set desc = "View the current map vote tally counts." + set category = "Server" + to_chat(mob, SSmap_vote.tally_printout) diff --git a/code/modules/discord/tgs_commands.dm b/code/modules/discord/tgs_commands.dm index 42d6d19ba99..8c6796bc1ea 100644 --- a/code/modules/discord/tgs_commands.dm +++ b/code/modules/discord/tgs_commands.dm @@ -4,7 +4,7 @@ /datum/tgs_chat_command/tgscheck/Run(datum/tgs_chat_user/sender, params) var/server = CONFIG_GET(string/server) - return new /datum/tgs_message_content("[GLOB.round_id ? "Round #[GLOB.round_id]: " : ""][GLOB.clients.len] players on [SSmapping.config.map_name]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [server ? server : "[world.internet_address]:[world.port]"]") + return new /datum/tgs_message_content("[GLOB.round_id ? "Round #[GLOB.round_id]: " : ""][GLOB.clients.len] players on [SSmapping.current_map.map_name]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [server ? server : "[world.internet_address]:[world.port]"]") /datum/tgs_chat_command/gameversion name = "gameversion" diff --git a/code/modules/escape_menu/details.dm b/code/modules/escape_menu/details.dm index 49bd19ce97f..ab6ff05d3ea 100644 --- a/code/modules/escape_menu/details.dm +++ b/code/modules/escape_menu/details.dm @@ -35,7 +35,7 @@ GLOBAL_DATUM(escape_menu_details, /atom/movable/screen/escape_menu/details) Round ID: [GLOB.round_id || "Unset"]
Round Time: [ROUND_TIME()]
- Map: [SSmapping.config?.map_name || "Loading..."]
+ Map: [SSmapping.current_map.map_name || "Loading..."]
Time Dilation: [round(SStime_track.time_dilation_current,1)]%
"} diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm index 9efde283e07..989fbb596c6 100644 --- a/code/modules/photography/photos/frame.dm +++ b/code/modules/photography/photos/frame.dm @@ -278,6 +278,6 @@ ///Generates a persistence id unique to the current map. Every bar should feel a little bit different after all. /obj/structure/sign/picture_frame/portrait/bar/Initialize(mapload) - if(SSmapping.config.map_path != CUSTOM_MAP_PATH) //skip adminloaded custom maps. - persistence_id = "frame_bar_[SSmapping.config.map_name]" + if(SSmapping.current_map.map_path != CUSTOM_MAP_PATH) //skip adminloaded custom maps. + persistence_id = "frame_bar_[SSmapping.current_map.map_name]" return ..() diff --git a/code/modules/procedural_mapping/mapGenerators/repair.dm b/code/modules/procedural_mapping/mapGenerators/repair.dm index 505dc36f02c..da086773591 100644 --- a/code/modules/procedural_mapping/mapGenerators/repair.dm +++ b/code/modules/procedural_mapping/mapGenerators/repair.dm @@ -27,7 +27,7 @@ // changed to allow Z cropping and that's a mess var/z_offset = SSmapping.station_start var/list/bounds - for (var/path in SSmapping.config.GetFullMapPaths()) + for (var/path in SSmapping.current_map.GetFullMapPaths()) var/datum/parsed_map/parsed = load_map( file(path), 1, diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 8e59c63cfbd..8987af97817 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -549,7 +549,7 @@ color_override = "orange", ) INVOKE_ASYNC(SSticker, TYPE_PROC_REF(/datum/controller/subsystem/ticker, poll_hearts)) - SSmapping.mapvote() //If no map vote has been run yet, start one. + INVOKE_ASYNC(SSvote, TYPE_PROC_REF(/datum/controller/subsystem/vote, initiate_vote), /datum/vote/map_vote, initiator_name = "Map Rotation") if(!is_reserved_level(z)) CRASH("Emergency shuttle did not move to transit z-level!") diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 68a0a41a2e0..b5b0965ead9 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -264,7 +264,7 @@ /obj/docking_port/stationary/proc/load_roundstart() if(json_key) - var/sid = SSmapping.config.shuttles[json_key] + var/sid = SSmapping.current_map.shuttles[json_key] roundstart_template = SSmapping.shuttle_templates[sid] if(!roundstart_template) CRASH("json_key:[json_key] value \[[sid]\] resulted in a null shuttle template for [src]") diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 84c0fa20a67..b8b2b542f18 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -158,7 +158,7 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) /// Logs a test message. Will use GitHub action syntax found at https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions /datum/unit_test/proc/log_for_test(text, priority, file, line) - var/map_name = SSmapping.config.map_name + var/map_name = SSmapping.current_map.map_name // Need to escape the text to properly support newlines. var/annotation_text = replacetext(text, "%", "%25") @@ -177,14 +177,14 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) GLOB.current_test = test var/duration = REALTIMEOFDAY - var/skip_test = (test_path in SSmapping.config.skipped_tests) + var/skip_test = (test_path in SSmapping.current_map.skipped_tests) var/test_output_desc = "[test_path]" var/message = "" log_world("::group::[test_path]") if(skip_test) - log_world("[TEST_OUTPUT_YELLOW("SKIPPED")] Skipped run on map [SSmapping.config.map_name].") + log_world("[TEST_OUTPUT_YELLOW("SKIPPED")] Skipped run on map [SSmapping.current_map.map_name].") else diff --git a/config/map_vote.txt b/config/map_vote.txt new file mode 100644 index 00000000000..edc5629df95 --- /dev/null +++ b/config/map_vote.txt @@ -0,0 +1,12 @@ + +## A flat bonus to give to all maps after a map vote is concluded. +MAP_VOTE_FLAT_BONUS 5 + +## The minimum number of tallies a map can have for purposes of map rotation. +MAP_VOTE_MINIMUM_TALLIES 1 + +## The maximum number of tallies a map can have for purposes of keeping things sane. +MAP_VOTE_MAXIMUM_TALLIES 200 + +## The percentage of tallies that are carried over between rounds. +MAP_VOTE_TALLY_CARRYOVER_PERCENTAGE 100 diff --git a/tgstation.dme b/tgstation.dme index 9d5d9d705a1..c9efe12169b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -659,6 +659,7 @@ #include "code\controllers\subsystem\lighting.dm" #include "code\controllers\subsystem\lua.dm" #include "code\controllers\subsystem\machines.dm" +#include "code\controllers\subsystem\map_vote.dm" #include "code\controllers\subsystem\mapping.dm" #include "code\controllers\subsystem\market.dm" #include "code\controllers\subsystem\materials.dm" @@ -1924,7 +1925,6 @@ #include "code\datums\votes\custom_vote.dm" #include "code\datums\votes\map_vote.dm" #include "code\datums\votes\restart_vote.dm" -#include "code\datums\votes\rock_the_vote.dm" #include "code\datums\weather\weather.dm" #include "code\datums\weather\weather_types\ash_storm.dm" #include "code\datums\weather\weather_types\floor_is_lava.dm"