GG1MapChooser is a CounterStrikeSharp map chooser for CS2 servers. It manages map votes, RTV, nominations, map pools, low-player map lists, admin map changes, automatic map rotation, next-map handling, and Discord reporting.
- Map Voting System - Players can vote for the next map. If no valid vote is cast, the plugin chooses a random valid map.
- Rock The Vote (RTV) - Players can request an immediate map vote during the game.
- Immediate RTV Option - If
RTVDelayFromStartis set to0or below, RTV is available immediately after the match starts. - Map Nominations - Players can nominate maps for upcoming votes. Each player can have one active nomination.
- Nomination Cooldown - Recently nominated maps can be temporarily blocked from being nominated again.
- Map Pools - Maps can be grouped into named pools. The active pool is used by RTV, map votes, admin votes, and automatic map changes.
- Pool Voting - Players can vote to start a pool vote and then choose the active pool.
- Low-Player Pool - A separate low-player map list can be used automatically when the server population is below the configured threshold.
- Menu Modes - Map votes, nominations, and pool votes can use
wasd,chat, orbothmenu modes. - Panorama Yes/No Vote - The admin "Vote to Change Map or Not" flow can use the native CS2 Panorama vote UI.
- Player Count Thresholds - Maps can define minimum and maximum player counts.
- Map Display Names - Maps can have friendly names shown in menus and messages.
- Map Weights - Random map selection can be weighted per map.
- Extend Map Limit - The number of map extensions per map can be limited.
- No Vote Line - Optional "No Vote" line can be added to vote menus to reduce accidental map selections.
- WASD Vote Counters - WASD vote menus can show live vote counts next to options.
- Admin Controls - Admins can change maps, start votes, start yes/no votes, set the next map, switch pools, and start pool votes.
- External Controls - Server commands allow other plugins or configs to start map votes and trigger selected map changes.
- Discord Logging - Loaded and voted maps can be reported to Discord with a configurable message template.
- Timer Reliability Improvements - Vote and map-change timer handling has been improved to avoid blocked or mistimed votes.
Define maps in csgo/cfg/GGMCmaps.json. Each map entry supports:
ws-truefor Workshop maps,falsefor classic maps.display- Friendly display name shown in menus and chat.mapid- Workshop map ID. Required for Workshop maps outside the server collection.minplayers- Minimum player count required for the map.0disables the lower limit.maxplayers- Maximum player count allowed for the map.0disables the upper limit.weight- Random selection weight. Higher values increase the chance of being selected.0disables random selection.-1usesOtherSettings.DefaultMapWeight.
The legacy flat format is still supported. When this format is used, the plugin treats the whole map list as one pool named default.
{
"de_mirage": {
"ws": false,
"display": "Mirage",
"mapid": "",
"minplayers": 0,
"maxplayers": 0,
"weight": 1
}
}
Maps can now be grouped into named pools. The active pool is used by normal map votes, RTV, admin map votes, and automatic random map changes.
{
"Small Maps": {
"gg_small_map": {
"ws": false,
"display": "Small Map",
"mapid": "",
"minplayers": 0,
"maxplayers": 12,
"weight": 1
}
},
"Large Maps": {
"gg_large_map": {
"ws": false,
"display": "Large Map",
"mapid": "",
"minplayers": 10,
"maxplayers": 0,
"weight": 1
}
}
}
When a pool-based map list is used, the active pool is selected in this order:
- The previous active pool, if it still exists.
PoolVoteSettings.DefaultPool, if configured and found.- The first available pool in
GGMCmaps.json.
When an admin switches the active pool manually, the plugin clears pending nominations, admin-selected maps, pending next map state, and temporary vote state.
Customise plugin behaviour in csgo/addons/counterstrikesharp/configs/plugins/GG1MapChooser/GG1MapChooser.json.
The config is divided into these sections:
VoteSettings- map vote, nomination, menu, no-vote, extend, and Panorama yes/no vote settings.RTVSettings- Rock The Vote settings.PoolVoteSettings- map pool voting settings.WinDrawSettings- round/win based vote timing.TimeLimitSettings- time-limit based vote timing.DiscordSettings- Discord webhook reporting.MenuSettings- WASD menu behaviour.OtherSettings- additional behaviour such as sounds, map-change delay, low-player maps, and default map weight.
RememberPlayedMaps- Number of recently played maps excluded from upcoming votes.RememberNominatedMaps- Number of recently nominated maps kept in nomination cooldown.0disables cooldown.MapsInVote- Number of maps shown in a vote.VotesToWin- Vote ratio required to win or start threshold-based actions. Example:0.6means 60%.AllowNominate- Allows players to nominate maps.NominationsMenuMode- Nomination menu mode:wasd,chat, orboth. Empty values fall back towasd.EndMapVoteMenuMode- End-of-map vote menu mode:wasd,chat, orboth. Empty values fall back towasd.YesNoVotePanorama- Enables native Panorama yes/no voting for the admin "Vote to Change Map or Not" flow.PanoramaSFUIString- SFUI string used by the Panorama yes/no vote.VotingTime- Duration in seconds for map votes.ExtendMapInVote- Adds the "Extend Map" option to map votes.ExtendMapTimeMinutes- Number of minutes added when "Extend Map" wins.MaxExtendMapCount- Maximum number of times the current map can be extended.0means unlimited.ChangeMapAfterVote- Changes the map after vote completion when the vote is not already configured as an immediate change.SpectatorsCanVote- Allows or blocks spectator voting.IncludeNoVote- Adds a "No Vote" option to vote menus.
AllowRTV- Enables Rock The Vote.RTVDelayFromStart- Initial delay in seconds before RTV is allowed. If this is0or below, RTV is available immediately after the match starts.IntervalBetweenRTV- Cooldown in seconds after an RTV starts before another RTV can start.NoRTVafterRoundsPlayed- Blocks RTV after this many rounds have been played.0disables this restriction.
Enable- Enables player/admin pool voting.DefaultPool- Preferred active pool name when the mapcycle is loaded. If empty or not found, the first available pool is used.DelayFromStart- Initial delay in seconds before pool voting is available.IntervalBetweenVotes- Cooldown in seconds after a pool vote starts before another pool vote can start.VotesToWin- Required player vote ratio to start a pool vote. If0,VoteSettings.VotesToWinis used.VotingTime- Time in seconds for players to choose a pool after the pool vote menu opens.BlockBeforeMapVoteSeconds- In time-limit mode, blocks pool voting when the scheduled map vote is this many seconds away or closer.BlockBeforeMapVoteRounds- In round-wins mode, blocks pool voting when the scheduled map vote is this many rounds away or closer.MenuMode- Pool vote menu mode:wasd,chat, orboth. Empty values fall back towasd.
VoteDependsOnRoundWins- Enables round/win based vote timing.TriggerRoundsBeforeEnd- Number of rounds before the end of the match to start the vote.TriggerRoundsBeforeEndVoteAtRoundStart- Starts the scheduled vote on round start when true, or round end when false.TriggerVoteAtRoundStartSecondsFromStart- Delay in seconds from round start before starting the vote.ChangeMapAfterWinDraw- Changes the map after the win/draw event if a next map has been selected.
VoteDependsOnTimeLimit- Enables time-limit based vote timing usingmp_timelimit.TriggerSecondsBeforeEnd- Number of seconds before the time limit ends to start the vote.ChangeMapAfterTimeLimit- Changes to the selected map when the time limit expires.VoteNextRoundStartAfterTrigger- Starts the vote at the next round start after the time-limit trigger.VoteRoundEndAfterTrigger- Starts the vote at round end after the time-limit trigger.MinutesExtendTimeLimitToRoundEnd- Temporarily extends the time limit so the delayed round-start or round-end vote can happen.
DiscordWebhook- Discord webhook URL used for map reports.DiscordMessageMapStart- Reports map starts to Discord.DiscordMessageAfterVote- Reports map vote results to Discord.PictureExtension- File extension used when building map image URLs for Discord embeds.
DisplayVotesCount- Shows vote counters next to options in WASD vote menus.SoundInMenu- Enables menu navigation sounds.FreezePlayerInMenu- Freezes regular players while they use WASD menus.FreezeAdminInMenu- Freezes admins while they use WASD admin menus.FreezeMode- Freeze method used by the menu.ScrollUp,ScrollDown,Choose,Back,Exit- Button bindings for WASD menus.
PrintPlayersChoiceInChat- Prints player choices to everyone instead of only to the player.PrintNextMapForAll- Printsnextmapoutput to all players.DelayBeforeChangeSeconds- Delay before changing the map after configured vote/end events.VoteStartSound- Sound played when a map vote starts.RandomMapOnStart- Changes to a random map after server start.RandomMapOnStartDelay- Delay before random map change after server start.LastDisconnectedChangeMap- Changes to a random map after the last player disconnects.WorkshopMapProblemCheck- Detects workshop map load failures and retries/falls back to random map handling.TvStopRecord- Stops TV recording before map changes.DefaultMapWeight- Default random selection weight for maps withweight = -1.LowPlayerMaxPlayers- Maximum real player count, including spectators, for low-player mode.LowPlayerMaps- Map list used while low-player mode is active. Entries use the same format as normal map entries.
Players can request a pool vote with rtm, !rtm, /rtm, css_rtm, or !css_rtm. Admins can also start a pool vote from css_maps.
Pool voting has two stages:
- Players first vote to start a pool vote, similar to RTV.
- When the threshold is reached, the plugin opens a menu where players choose the pool.
A pool wins only if it is the single option with the highest vote count. If no one votes, the result is tied, or the current pool wins, the active pool stays unchanged. If a different pool wins, it becomes the active pool and pool-sensitive state is cleared.
If a map vote is due while a pool vote is in progress, the map vote is queued and starts after the pool vote finishes.
Pool voting requires at least two pools and exactly one automatic map vote mode: either time-limit based voting or round/win based voting. If both are enabled or both are disabled, pool voting is disabled to avoid ambiguous timing.
Low-player maps are configured in OtherSettings.LowPlayerMaps. This list is separate from normal map pools and does not appear in pool votes.
Low-player mode is active when the number of real players, including spectators, is less than or equal to OtherSettings.LowPlayerMaxPlayers.
When active, normal map votes, RTV, and automatic random map changes use LowPlayerMaps. When the player count rises above the threshold, the plugin returns to the normal active pool.
wasd opens only the WASD HTML menu. chat or chatmenu opens only the CounterStrikeSharp chat menu. both opens both menu types at the same time; selecting in one closes the other. Empty or unknown values fall back to wasd.
The admin "Vote to Change Map or Not" flow uses Panorama voting when VoteSettings.YesNoVotePanorama is true. In that case, EndMapVoteMenuMode does not apply to that yes/no vote.
When VoteSettings.RememberNominatedMaps is greater than 0, nominated maps from completed votes are added to a recent nomination cooldown list. Maps in this list cannot be nominated again and are shown as disabled entries in nomination menus.
This is a map-count based cooldown, not a time-based cooldown.
VoteSettings.MaxExtendMapCount limits how many times the current map can be extended through the Extend Map vote option. 0 means unlimited. The counter resets with the map state.
If RTVSettings.AllowRTV is true and RTVSettings.RTVDelayFromStart is 0 or below, RTV is available immediately after the match starts. After an RTV starts, RTVSettings.IntervalBetweenRTV is still used as the cooldown before another RTV can start.
{
"VoteSettings": {
"RememberNominatedMaps": 3,
"NominationsMenuMode": "both",
"EndMapVoteMenuMode": "wasd",
"YesNoVotePanorama": true,
"PanoramaSFUIString": "#SFUI_Vote_None",
"MaxExtendMapCount": 2
},
"PoolVoteSettings": {
"Enable": true,
"DefaultPool": "Small Maps",
"DelayFromStart": 90,
"IntervalBetweenVotes": 120,
"VotesToWin": 0.6,
"VotingTime": 20,
"BlockBeforeMapVoteSeconds": 30,
"BlockBeforeMapVoteRounds": 1,
"MenuMode": "both"
},
"MenuSettings": {
"DisplayVotesCount": true
},
"OtherSettings": {
"LowPlayerMaxPlayers": 8,
"LowPlayerMaps": {
"gg_small_map": {
"ws": false,
"display": "Small Map",
"mapid": "",
"minplayers": 0,
"maxplayers": 8,
"weight": 1
}
}
}
}
Define the text you want to display in csgo/addons/counterstrikesharp/configs/plugins/GG1MapChooser/NextMapMessage.json:
- The config file is created automatically if it does not exist.
- You can modify or localise the text, for example:
content = "Next map: ". - To display map pictures, set the image folder URL in the message template.
- Map images must follow the naming convention
<mapname>.<PictureExtension>.
- RTV: Players can use
rtv,!rtv, or/rtv. - Pool Voting: Players can use
rtm,!rtm,/rtm,css_rtm, or!css_rtm. - Nominating: Players can use
nominate,!nominate <mapname>, or theydalias. - Revote: Players can use
revoteto reopen the active vote menu and change their vote. - Next Map: Players can use
nextmapto see the selected next map. - Time Left: Players can use
timeleftto see time or round information, depending on the active vote mode.
- If another plugin ends the game and only needs GG1MapChooser to select the next map, use
ggmc_mapvote_start. - If another plugin needs GG1MapChooser to select and immediately change to the winning map, use
ggmc_mapvote_with_change. - For round/win based voting, enable
WinDrawSettings.VoteDependsOnRoundWins, configureTriggerRoundsBeforeEnd, and decide whether the vote should start on round start or round end. - For time-limit based voting, enable
TimeLimitSettings.VoteDependsOnTimeLimitand make sureTriggerSecondsBeforeEndleaves enough time forVoteSettings.VotingTime. - For pool voting, use a pool-based
GGMCmaps.jsonwith at least two pools and enablePoolVoteSettings.Enable. - For low-player maps, fill
OtherSettings.LowPlayerMapsand setOtherSettings.LowPlayerMaxPlayersto the desired threshold.
rtv- Rock The Vote.rtm/css_rtm- Request a map pool vote.nominate- Open nomination menu.nominate <mapname>- Nominate a specific map.yd- Nomination alias.revote- Reopen the active vote menu.nextmap- Show the selected next map.timeleft- Show remaining time or round information.
css_maps/!maps- Opens the admin map menu.ggmap <partofmapname>- Quickly find and change to a map by partial name.ggmap <exactmapname>- Server-side exact map change command for scripts/plugins.setnextmap- Set the next map without starting a vote.
ggmc_mapvote_start [time]- Starts a map vote externally and setsnextlevelto the winning map.ggmc_mapvote_with_change [time]- Starts a map vote externally and changes map after the vote ends.ggmc_auto_mapchange- Changes to a random valid map.ggmc_nortv- Temporarily disables RTV.ggmc_change_nextmap- Immediately changes to the previously selected next map.reloadmaps- ReloadsGGMCmaps.json.
- Start with a pool-based
GGMCmaps.jsoncontaining at least two pools. - Set
PoolVoteSettings.Enable = true. - Use
rtm,!rtm, orcss_rtmand confirm that a pool vote starts after the configured vote threshold. - Confirm that ties and votes for the current pool keep the existing active pool.
- Switch pools from
css_mapsand confirm that nominations and pending selected maps are cleared. - Set
LowPlayerMaxPlayersabove the current online count and confirm RTV/map vote usesLowPlayerMaps. - Test
NominationsMenuMode,EndMapVoteMenuMode, andPoolVoteSettings.MenuModewithwasd,chat, andboth. - Set
RememberNominatedMapsabove0, nominate a map, complete a vote, and confirm the map cannot be nominated again until it leaves cooldown. - Set
MaxExtendMapCount = 1, enableExtendMapInVote, extend once, and confirm the extend option is not available again on the same map. - Set
RTVDelayFromStart = 0and confirm RTV is available immediately after the match starts.
- If the server has an assigned Workshop collection (
+host_workshop_collection [collection number]), map names from that collection can be used withoutmapid. - If Workshop maps are not from the assigned collection, fill in
mapid. - If
mapidis missing for a Workshop map outside the collection, the server might not be able to change to it by name. - Workshop map names should match the actual Workshop names exactly, especially when
WorkshopMapProblemCheckis enabled. - Pool voting requires at least two pools.
- Pool voting must happen before the next map vote. It can be blocked by
BlockBeforeMapVoteSecondsorBlockBeforeMapVoteRounds. - If both
VoteDependsOnTimeLimitandVoteDependsOnRoundWinsare enabled, or both are disabled, pool voting is disabled. - Low-player maps are separate from normal pools and do not appear in pool votes.
To compile the plugin, download or reference the API project from ggmcAPI.
The plugin exposes these capabilities to other plugins.
- Maps API:
public bool GGMC_IsVoteInProgress();- returns whether a map vote is currently in progress.
- WASD Menu API:
public IWasdMenu CreateMenu(string title = "", bool freezePlayer = true, bool displayOptionsCount = false);- creates a WASD menu.public void OpenMainMenu(CCSPlayerController? player, IWasdMenu? menu);- opens a menu as the main menu.public void OpenSubMenu(CCSPlayerController? player, IWasdMenu? menu);- opens a menu as a submenu.public void CloseActiveMenu(IWasdMenu? menu);- closes an active menu object.public void CloseActiveMenu(CCSPlayerController? player);- closes the player's active menu.public BaseMenu MenuByType(string menuType, string title, BasePlugin plugin);- creates an adapter menu by type name.public BaseMenu MenuByType(Type menuType, string title, BasePlugin plugin);- creates an adapter menu by type.
The plugin is provided "as-is" and fulfils the specific requirements it was designed for. Suggestions that benefit a broader user base are welcome.
Thank you to UMC Mapchooser for the main ideas.
Special thanks to T3Marius for WASD menu ideas and design.
Thanks to:
- crashzk for the Portuguese translation.
- YuYueCraft for the Chinese translation.