-
Notifications
You must be signed in to change notification settings - Fork 23
Map Vote
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.
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).
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 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 ).
|
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:
|
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.
|
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. |
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:
|
MaxPerPlayer | The maximum number of nominations to allow per player. |
MaxTotalType | The type of maximum value to apply to nominations. Options are:
|
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. |
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. |
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. |
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). |
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. |
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. |
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. |
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.
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
.
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.
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.
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:
-
SEQUENTIAL
- advances one-by-one through the groups every map change, with the map vote using maps from the current group. -
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
.
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".
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.
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.