Difference between revisions of "TF2 Voting"
m (→Failure reasons) |
(→How voting works) |
||
Line 2: | Line 2: | ||
== How voting works == | == How voting works == | ||
− | + | The server begins by sending a vote_options event, which has values set if it's a multiple choice votes or repeats the last valid multiple choice set (or garbage data if no multiple choice votes have occurred yet). This is followed by the VoteStart User Message, the last argument determines the vote type. Clients use the "vote" command to register their votes (option1 through option5), after which the server sends a vote_cast event with a 0-based option number (so option1 = 0, option5 = 4). | |
When the vote is complete, the server send either a VotePass or VoteFailed User Message. | When the vote is complete, the server send either a VotePass or VoteFailed User Message. | ||
− | |||
− | |||
== Failure reasons == | == Failure reasons == |
Revision as of 12:55, 15 July 2011
Team Fortress 2 has a new voting system based on the Left 4 Dead Voting system and is controlled by Game Events and User Messages. You can use either a string from the resource file, or TF_playerid_noteam which will let you create any vote you want.
Contents
How voting works
The server begins by sending a vote_options event, which has values set if it's a multiple choice votes or repeats the last valid multiple choice set (or garbage data if no multiple choice votes have occurred yet). This is followed by the VoteStart User Message, the last argument determines the vote type. Clients use the "vote" command to register their votes (option1 through option5), after which the server sends a vote_cast event with a 0-based option number (so option1 = 0, option5 = 4).
When the vote is complete, the server send either a VotePass or VoteFailed User Message.
Failure reasons
The VoteFailed User Message does not take a string to display. Instead, it takes a number that corresponds to a specific message.
The values that work are:
0 - Generic "Vote Failed" message
3 - Yes votes must outnumber No votes
4 - Not Enough Votes
Other error numbers exist, but they are used by the CallVoteFailed User Message, which is sent to a single client:
1 = Cannot call vote while other players are still loading
2 = You called a vote recently and cannot call another one for X seconds (second argument to CallVoteFailed specifies the number of seconds)
5 - Server has disabled that issue.
6 - That map does not exist.
7 - You must specify a map name
8 - This vote failed recently
9 - Your team cannot call this vote
10 - Voting not allowed while Waiting for Players
User Messages
The User Messages that exist in the TF2 Voting system are:
VoteSetup
- Byte Count of vote issues allowed on this server * String Vote Issues, same number as Count above.
VoteStart
- Byte Team index or -1 for all - Byte Client index (NOT USERID) of person who started the vote, or 99 for the server. - String Vote issue translation string - String Vote issue text - Bool true for Yes/No, false for Multiple choice
VotePass
- Byte Team index or -1 for all - String Vote issue translation string - String Vote winner (same as vote issue text for Yes/No?)
VoteFail
- Byte Team index or -1 for all - Byte Failure reason code (0, 3-4)
CallVoteFailed
- Byte Failure reason code (1-2, 5-10) - Short If above is 2, number of seconds until you can next start a vote.
Events
Note: Sent to all players when a player chooses a vote option (or more specifically, the server receives a vote command)
Name: | vote_cast | |||||||||
Structure: |
|
Note: Sent to players before VoteStart UserMessage to populate choices for a multiple choice vote
Name: | vote_options | ||||||||||||||||||
Structure: |
|
Unused?
Name: | vote_ended | |
Structure: |
|
Name: | vote_started | ||||||||||||
Structure: |
|
Name: | vote_changed | ||||||||||||||||||
Structure: |
|
Name: | vote_passed | |||||||||
Structure: |
|
Name: | vote_failed | |||
Structure: |
|
Example voting plugin
This is a basic plugin that starts a vote, "Is gaben fat?". It does not ensure the same client does not vote multiple times, nor does it actually kick the user.
#include <sourcemod> // TF2's internal map vote uses client index 99 for the server #define TF2_SERVER_CLIENT_INDEX 99 #define TF2_TEAM_ALL -1 new yesvotes; new novotes; #define MAX_VOTES 4 public Plugin:myinfo = { name = "Test Yes/No Vote", author = "Powerlord", description = "A test vote plugin for the AlliedMods wiki", version = "1.0", url = "http://wiki.alliedmods.net/TF2_Voting" } public OnPluginStart() { RegConsoleCmd("testvote",Callvote_Handler); RegConsoleCmd("vote", vote); } public Action:Callvote_Handler(client, args) { new Handle:bf = StartMessageAll("VoteStart", USERMSG_RELIABLE); BfWriteByte(bf, TF2_TEAM_ALL); BfWriteByte(bf, TF2_SERVER_CLIENT_INDEX); BfWriteString(bf, "#TF_playerid_noteam"); BfWriteString(bf, "Is gaben fat?"); BfWriteBool(bf, true); EndMessage(); yesvotes = 0; novotes = 0; return Plugin_Handled; } UpdateVotes() { if (yesvotes+novotes >= MAX_VOTES) { PrintToServer("voting complete!"); if (yesvotes > novotes) { new Handle:bf = StartMessageAll("VotePass"); BfWriteByte(bf, TF2_TEAM_ALL); BfWriteString(bf, "#TF_playerid_noteam"); BfWriteString(bf, "Gaben is fat"); EndMessage(); } else { new Handle:bf = StartMessageAll("VoteFailed"); BfWriteByte(bf, TF2_TEAM_ALL); // Check list of failure reasons BfWriteByte(bf, 3); EndMessage(); } } } // If the TF2 vote system is running (sv_allow_votes 1), this needs to be a command listener because TF2 registers the vote command only when a vote is ongoing, and thus hooking it using RegConsoleCmd doesn't work. public Action:vote(client, args) { new String:arg[8]; new option = 0; GetCmdArg(1,arg,8); PrintToServer("Got vote %s from %i",arg,client); if (strcmp(arg,"option1",true) == 0) { yesvotes++; option = 0; } else if (strcmp(arg,"option2",true) == 0) { novotes++; option = 1; } new Handle:msg = CreateEvent("vote_cast"); SetEventInt(msg, "entityid", client); SetEventInt(msg, "team", -1); SetEventInt(msg, "vote_option", option); FireEvent(msg); UpdateVotes(); return Plugin_Continue; }
See the following images for examples what this looks like: