Skip to content

Map Vote

Person8880 edited this page Sep 2, 2023 · 32 revisions

Overview

The map vote plugin allows for voting to change the map, similar to "rock the vote" from SourceMod. Players vote to change the map. Once enough have voted, the plugin provides a set of maps as options and players vote for the one they want. Players can nominate maps before the vote has started.

Once the vote completes, the map with the most votes wins. Ties can be configured to fail the vote, choose randomly between them, or revote.

The plugin also now facilitates a mid map vote for the next map. The vote can also be configured to allow extending the duration of the current map. If the map is extended, another vote is called later to determine the next map again.

All players are given access to sh_timeleft, sh_nominate, sh_votemap, sh_vote and sh_revote automatically. If you want a rank to be able to cancel a map change vote (not the vote for next map) then you'll need to give them access to sh_veto.

All players are also given access to the vote menu. If you bind a key to sh_votemenu (e.g type "bind N sh_votemenu" without the " into your console), you can use it to vote and revote in the currently running map vote. When a player joins, if they do not have anything bound to M, N or C then the vote menu will bind itself to that (unless they've already bound the vote menu to another key).

There are 2 types of menu for voting in map votes:

  • Full vote menu - displays the maps with preview images in a full-screen grid, with the ability to view the overview of the map and open a mod's Steam workshop page. This is the default.
  • Minimal vote menu - the old radial menu built into the main vote menu, that can display overviews on hover but not preview images.

Clients may configure which menu they use to vote.

Minimal vote menu:

Vote Menu

Full vote menu:

Map vote menu

Default Config

The default config looks something like this:

{
    "Maps": {
      "ns2_mineshaft": true,
      "ns2_summit": true,
      "ns2_tram": true,
      "ns2_veil": true,
      "ns2_refinery": true,
      "ns2_docking": true,
      "ns2_descent": true
    },
    "ForcedMaps": {
      "ns2_docking": true
    },
    "DontExtend": {
      "ns2_descent": true
    },
    "IgnoreAutoCycle": {
      "ns2_descent": true
    },
    "GetMapsFromMapCycle": true,
    "ExcludeLastMaps": {
        "Min": 0,
        "Max": 0,
        "UseStrictMatching": true
    },
    "GroupCycleMode": "SEQUENTIAL",

    "AllowExtend": true,
    "ExtendTimeInMinutes": 15,
    "AlwaysExtend": true,
    "MaxExtends": 1,
    "ConsiderSimilarMapsAsExtension": false,

    "MaxRevotes": 1,
    "ChooseRandomOnTie": true,
    "TieFails": false,

    "VoteDelayInMinutes": 10,
    "ChangeDelayInSeconds": 10,
    "ForceChangeWhenSecondsLeft": 60,
    "VoteTimeoutInSeconds": 60,

    "CycleOnEmpty": false,
    "EmptyPlayerCount": 0,

    "RoundLimit": 0,

    "EnableNextMapVote": true,
    "EnableRTV": true,
    "BlockAfterRoundTimeInMinutes": 0,
    "NextMapVoteMapTimeFraction": 1,
    "MaxOptions": 8,
    "VoteLengthInMinutes": 1,
    "ShowVoteChoices": true,
    "ForceMenuOpenOnMapVote": false,
    "VotingMode": "SINGLE_CHOICE",
    "MaxVoteChoicesPerPlayer": 4,
    "Constraints": {
        "MapVote": {
            "MinVotesRequired": {
                "Type": "ABSOLUTE",
                "Value": 0
            },
            "MinVotesToFinish": {
                "Type": "FRACTION_OF_PLAYERS",
                "Value": 0.8
            }
        },
        "NextMapVote": {
            "MinVotesRequired": {
                "Type": "ABSOLUTE",
                "Value": 0
            },
            "MinVotesToFinish": {
                "Type": "FRACTION_OF_PLAYERS",
                "Value": 2
            }
        },
        "StartVote": {
            "MinPlayers": {
                "Type": "ABSOLUTE",
                "Value": 10
            },
            "MinVotesRequired": {
                "Type": "FRACTION_OF_PLAYERS",
                "Value": 0.6
            }
        }
    },
    "Nominations": {
        "AllowExcludedMaps": false,
        "AllowMapsOutsideOfCycle": false,
        "MaxOptionsExceededAction": "ADD_MAP",
        "MaxPerPlayer": 3,
        "MaxTotalType": "AUTO",
        "MaxTotalValue": 0,
        "MinTotalValue": 0
    },
    "VoteSettings": {
      "AFKTimeInSeconds": 60,
      "ConsiderAFKPlayersInVotes": true,
      "ConsiderSpectatorsDuringActiveRound": true,
      "ConsiderSpectatorsInVotes": true
    },
    "__Version": "1.14"
}

The file should be called "MapVote.json" and should be placed in the directory defined as your plugin config directory (default is config://shine/plugins).

Config Options

Map options

Option Description
GetMapsFromMapCycle If true, then the votemaps are taken from the map cycle list directly.
Maps If GetMapsFromMapCycle is false, then this is the list of maps that can be voted for.
ForcedMaps These maps will always be an option in a map vote.
DontExtend Maps in this table ignore the AlwaysExtend setting and are never allowed to be extended.
IgnoreAutoCycle These maps will not be cycled to unless they were voted as the next map.
ExcludeLastMaps Sets how many previous maps to exclude from map votes.
  • Min - the minimum number of previous maps to exclude.
  • Max - the maximum number of previous maps to exclude.
  • UseStrictMatching - whether to treat maps with the same base name as equal when removing previous maps (e.g. ns2_veil and ns2_veil_five).
At least Min will always be excluded, even if it brings the total below the desired number of choices. However, the Max may not always be removed if there are not enough choices remaining.
GroupCycleMode Sets how map groups are cycled (if GetMapsFromMapCycle is true).
  • SEQUENTIAL - advances through the list of map groups every map change.
  • WEIGHTED_CHOICE - Picks maps from each group based on their selection weight.

Voting options

Option Description
EnableNextMapVote Decides whether to hold a vote for the next map.
EnableRTV Decides whether to allow players to 'rock the vote' (vote to change the map at any time).
BlockAfterRoundTimeInMinutes If greater than 0, sets how long in minutes after a round start to block player-initiated map votes.
NextMapVoteMapTimeFraction The fraction of the way through the current map the next map vote should be held. For example, a value of 0.5 with a 30 minute map time would display the vote after 15 minutes. The default value is 1, which will hold the next map vote at the end of the map rather than after a fixed time.
VotingMode The voting mode to use. One of:
  • SINGLE_CHOICE - players can select only one map. Choosing another map removes their previous choice. The map with the most votes at the end of the vote wins.
  • MULTIPLE_CHOICE - players can select up to MaxVoteChoicesPerPlayer maps. The map with the most votes at the end of the vote wins.
MaxOptions Maximum number of maps to provide as voting options per vote.
MaxVoteChoicesPerPlayer Maximum number of maps a player can choose in a vote when VotingMode is MULTIPLE_CHOICE.
VoteLengthInMinutes Time in minutes a map vote should last before determining the winner.
ShowVoteChoices Determines whether to broadcast when a player makes a choice in the vote.
ForceMenuOpenOnMapVote Determines whether to force the vote menu open when a vote starts and there is no round in progress. Clients may override this setting.
Constraints Determines the rules for starting/ending votes.
  • StartVote controls the minimum number of players required to allow players to start a map vote (MinPlayers), and the number required to vote for one in order for it to start (MinVotesRequired).
  • MapVote controls the number of votes required to pass a player-initiated vote (MinVotesRequired), and the number of votes that will finish it early (MinVotesToFinish).
  • NextMapVote controls the number of votes required to pass an end-of-map vote (MinVotesRequired), and the number of votes that will finish it early (MinVotesToFinish).
Each entry can be either:
  • ABSOLUTE - an exact amount of players
  • FRACTION_OF_PLAYERS - a fraction of the total players
VoteSettings Allows for controlling whether AFK players and spectators are considered in map votes. Set ConsiderAFKPlayersInVotes to false to prevent AFK players from counting towards the total votes. AFKTimeInSeconds controls how long a player should be AFK before they are no longer counted. Set ConsiderSpectatorsInVotes to false to prevent spectators from counting towards the total votes, and ConsiderSpectatorsDuringActiveRound to false (with ConsiderSpectatorsInVotes set to true) to prevent spectators from voting during an active round.

Nomination Options

Option Description
AllowExcludedMaps Whether to allow maps that would be excluded due to being played recently to be nominated. Maps can also have this overridden individually by adding allowNominationWhenExcluded to their entry in the map cycle/Maps table.
AllowMapsOutsideOfCycle Whether to allow maps that are not in the map cycle to be nominated (note this only works for maps that are mounted).
MaxOptionsExceededAction What to do when a nomination would cause the number of choices in the map vote to exceed the maximum. Options are:
  • ADD_MAP - add the map regardless.
  • REPLACE_MAP - replace another map in the current choices that wasn't nominated.
  • SKIP - do not add the nomination.
MaxPerPlayer The maximum number of nominations to allow per player.
MaxTotalType The type of maximum value to apply to nominations. Options are:
  • AUTO - allow as many nominations as can fit after adding all forced maps.
  • ABSOLUTE - allow MaxTotalValue nominations.
  • FRACTION_OF_PLAYERS - allow the maximum of MinTotalValue and MaxTotalValue * NumberOfPlayers nominations (rounded up).
MaxTotalValue Depends on MaxTotalType as described above.
MinTotalValue When MaxTotalType is FRACTION_OF_PLAYERS, this is the minimum number of nominations to allow regardless of player count.

Vote result options

Option Description
TieFails Determines whether a tied result should fail the vote.
ChooseRandomOnTie If TieFails is false and this is true, then a random map out of those that tied will be chosen as the winner.
MaxRevotes If both TieFails and ChooseRandomOnTie are false, then a revote is called on a tied vote. This controls how many revotes are allowed before giving up.

Vote delay options

Option Description
ChangeDelayInSeconds Time in seconds after a map vote before changing the map.
VoteDelayInMinutes Time in minutes after a map change or failed vote before allowing another vote.
ForceChangeWhenSecondsLeft Time in seconds left in the current map which should force a change to the next one. The default of 60 means that if a round ends with less than 1 minute remaining, the map will change.
VoteTimeoutInSeconds After this many seconds with no votes, the vote count is reset to 0 if it never passed.

Extending map options

Option Description
AllowExtend Sets whether to allow the current map into the vote or not.
AlwaysExtend Sets whether to always have the current map as a vote option.
ExtendTime Time in minutes to extend the current map if it is chosen as the next map.
MaxExtends Maximum number of times the current map can be extended before it is no longer an option.
ConsiderSimilarMapsAsExtension Whether to treat maps with the same base name as an extension of the current map (and thus exclude them when extension is not permitted).

Empty map cycling options

Option Description
CycleOnEmpty Sets whether the map should automatically advance to the next in the cycle if the server is empty and the map is past its timelimit.
EmptyPlayerCount When there is less than or equal to this many players on the server, the "CycleOnEmpty" setting considers the server empty.

Round limit options

Option Description
RoundLimit Sets the maximum number of rounds allowed on the map. This adds an additional constraint that ensures there can be no more than the given amount of rounds before a map cycle/vote.

Commands

Command Chat Command Arguments Description
sh_nextmap !nextmap N/A Displays the currently set next map.
sh_timeleft !timeleft N/A Displays the remaining map time.
sh_nominate !nominate <map> Nominates the given map for the next map vote.
sh_votemap !rtv or !votemap or !mapvote N/A Votes to begin a map vote.
sh_vote !vote <map> Votes for the given map in the current map vote. Map name does not need the ns2_ bit.
sh_veto !veto N/A Cancels a map change from a successful map vote.
sh_forcemapvote !forcemapvote N/A Force starts an RTV vote if possible.

Defining min/max player counts

To define a minimum and/or maximum player count required for a map, you need to edit your MapCycle.json file.

{
  "mode": "order",
  "maps": [
    "ns2_biodome",
    "ns2_docking",
    "ns2_mineshaft",
    "ns2_refinery",
    "ns2_summit",
    "ns2_tram",
    { "map": "ns2_veil", "max": 14 },
    { "map": "ns2_descent", "min": 14 }
  ],
  "time": 30,
  "mods": [ "706d242" ]
}

For maps you want to limit, make them a table entry in the maps list, and set the "min" and "max" values.

Defining percentage played limits

Alongside player counts, you can also restrict maps to only be permitted if they have been played below a certain percentage of the total maps played. To do this, you need to edit your MapCycle.json file and add "percent" fields to the maps you want to limit. For example:

{
  "mode": "order",
  "maps": [
    "ns2_biodome",
    "ns2_docking",
    "ns2_mineshaft",
    "ns2_refinery",
    "ns2_summit",
    "ns2_tram",
    { "map": "ns2_veil", "percent": 8 },
    { "map": "ns2_descent", "percent": 5 }
  ],
  "time": 30,
  "mods": [ "706d242" ]
}

This configuration limits ns2_veil to be up to 8% of the total maps played, and ns2_descent to be up to 5% of the total maps played.

Note: If no map is set to have a percentage limit, then the total maps played will not be tracked. The file containing the stats is located under config://shine/temp/mapstats.json.

Defining per map round or time limits

To define a round or time limit for specific maps, you again need to edit your "MapCycle.json" file.

{
  "mode": "order",
  "maps": [
    "ns2_biodome",
    "ns2_docking",
    "ns2_mineshaft",
    "ns2_refinery",
    "ns2_summit",
    "ns2_tram",
    { "map": "ns2_veil", "time": 45 },
    { "map": "ns2_descent", "rounds": 2 }
  ],
  "time": 30,
  "mods": [ "706d242" ]
}

Here we've set ns2_veil to have a 45 minute time limit instead of the global 30, and we've set ns2_descent to have a fixed 2 round limit.

Making maps have different chances to be picked for a vote

From revision 173 onwards, it is now possible to define a relative "chance" for a map to be picked as a vote option. The value goes in the "MapCycle.json" file.

This "chance" value should be a number between 0 and 1. The default value for a map with no chance value set is 1. A value of 0 means the map will never be picked. Note that the precision is only down to 0.1, so for example: a value of 0.1 and 0.15 are the same.

{
  "mode": "order",
  "maps": [
    "ns2_biodome",
    "ns2_docking",
    "ns2_mineshaft",
    "ns2_refinery",
    "ns2_summit",
    "ns2_tram",
    { "map": "ns2_veil", "chance": 0.5 },
    { "map": "ns2_descent", "chance": 0.1 }
  ],
  "time": 30,
  "mods": [ "706d242" ]
}

This file would set the chance for veil to be picked to 0.5, and the chance for descent to be 0.1. All other maps would have a chance of 1.

Group based voting

Maps can be sorted into named groups which are used to determine the maps available in a given vote. There are two modes available for grouping:

  1. SEQUENTIAL - advances one-by-one through the groups every map change, with the map vote using maps from the current group.
  2. WEIGHTED_CHOICE - picks random maps from all of the available groups based on their selection weighting.

Note that when using groups, other rules such as player counts, chances, number of map choices etc. will all still affect the final map choice set. Also, groups require the setting "GetMapsFromMapCycle" to be set to true.

Sequential Mode

If you want to set a cycle of vote options, set GroupCycleMode to SEQUENTIAL and add the following to your MapCycle.json file:

{
  "mode": "order",
  "maps": [
    "ns2_biodome",
    "ns2_docking",
    "ns2_mineshaft",
    "ns2_refinery",
    "ns2_summit",
    "ns2_tram",
    "ns2_veil",
    "ns2_descent",
    "ns2_derelict",
    "ns2_kodiak",
    "ns2_eclipse"
  ],
  "groups": [
    { "name": "Classic Maps", "maps": [ "ns2_docking", "ns2_tram", "ns2_summit", "ns2_veil" ] },
    { "name": "Update Maps", "maps": [ "ns2_descent", "ns2_kodiak", "ns2_eclipse", "ns2_biodome", "ns2_derelict" ] },
    { "name": "Mixed Maps", "maps": [ "ns2_docking", "ns2_derelict", "ns2_summit", "ns2_biodome", "ns2_veil" ] }
  ],
  "time": 30,
  "mods": [ "706d242" ]
}

Every map vote will then choose from only those maps in the current group. The group cycles forward after each map change, and starts on the first group in the "groups" list.

For example, starting on the group "Classic Maps", the only options available will be "ns2_docking", "ns2_tram", "ns2_summit" and "ns2_veil". Once the map changes, the group will change to "Update Maps". Now the only options will be "ns2_descent", "ns2_kodiak", "ns2_eclipse", "ns2_biodome" and "ns2_derelict".

Weighted Choice Mode

Alternatively, if you want to pick a certain number of maps from different groups, set GroupCycleMode to WEIGHTED_CHOICE and add the following to your MapCycle.json file:

{
  "mode": "order",
  "maps": [
    "ns2_biodome",
    "ns2_docking",
    "ns2_mineshaft",
    "ns2_refinery",
    "ns2_summit",
    "ns2_tram",
    "ns2_veil",
    "ns2_descent",
    "ns2_derelict",
    "ns2_kodiak",
    "ns2_eclipse"
  ],
  "groups": [
    {
      "name": "Classic Maps",
      "maps": [ "ns2_docking", "ns2_tram", "ns2_summit", "ns2_veil", "ns2_mineshaft", "ns2_refinery" ],
      "select": 3
    },
    {
      "name": "Update Maps",
      "maps": [
        "ns2_descent", "ns2_kodiak", "ns2_eclipse", "ns2_biodome", "ns2_derelict", "ns2_tanith", "ns2_ayumi",
        "ns2_metro"
      ],
      "select": 5
    }
  ],
  "time": 30,
  "mods": [ "706d242" ]
}

In this example, map votes will pick 3 random maps from the "Classic Maps" group, and 5 random maps from the "Update Maps" group. This is done for every map vote, no cycling occurs.

You can specify as many map groups as you like, but note that the total number of vote options will be constrained by your configured maximum, excluded maps, forced maps, nominations etc. You should ensure the sum of the select weights equals your MaxOptions setting, otherwise less maps will be available.

Map mod detection

The full-screen map vote menu can display preview and overview images for maps that are loaded from mods. Normally a map's mod is automatically detected when first added to the map cycle using a Steam API query. However, if this query fails, the fallback is to assume the first mod in the mods list is the mod ID of the map itself.

Thus when adding mod maps to the map cycle, ensure the map's mod ID is the first value in the mods list to avoid the wrong mod preview image displaying in the vote menu.

Clone this wiki locally