Difference between revisions of "TF2 Voting"
m (→Example voting plugin) |
(Added events) |
||
Line 7: | Line 7: | ||
A multiple choice vote is much the same as a Yes/No vote, but the server sends a "vote_options" event first, and sets the last argument of the VoteStart usermessage to false instead of true. | A multiple choice vote is much the same as a Yes/No vote, but the server sends a "vote_options" event first, and sets the last argument of the VoteStart usermessage to false instead of true. | ||
+ | |||
+ | == Failure reasons == | ||
+ | |||
+ | The VoteFailed Usermessage 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 CallVoteFailed: | ||
+ | 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 | ||
+ | |||
+ | == Usermessages == | ||
+ | |||
+ | The Usermessages 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 == | ||
+ | |||
+ | {{qnotice|Sent to all players when a player chooses a vote option (or more specifically, the server receives a vote command)}}<br> | ||
+ | {{begin-hl2msg|vote_cast|string}} | ||
+ | {{hl2msg|byte|vote_option|which option the player voted on}} | ||
+ | {{hl2msg|short|team|}} | ||
+ | {{hl2msg|long|entityid|entity id of the voter}} | ||
+ | {{end-hl2msg}} | ||
+ | |||
+ | {{qnotice|Sent to players before VoteStart UserMessage to populate choices for a multiple choice vote}}<br> | ||
+ | {{begin-hl2msg|vote_options|string}} | ||
+ | {{hl2msg|byte|count|Number of options - up to MAX_VOTE_OPTIONS [ed: 5]}} | ||
+ | {{hl2msg|string|option1|}} | ||
+ | {{hl2msg|string|option2|}} | ||
+ | {{hl2msg|string|option3|}} | ||
+ | {{hl2msg|string|option4|}} | ||
+ | {{hl2msg|string|option5|}} | ||
+ | {{end-hl2msg}} | ||
+ | |||
+ | === Unused? === | ||
+ | {{begin-hl2msg|vote_ended|string}} | ||
+ | {{end-hl2msg}} | ||
+ | |||
+ | {{begin-hl2msg|vote_started|string}} | ||
+ | {{hl2msg|string|issue|}} | ||
+ | {{hl2msg|string|param1|}} | ||
+ | {{hl2msg|byte|team|}} | ||
+ | {{hl2msg|long|initiator|entity id of the player who initiated the vote}} | ||
+ | {{end-hl2msg}} | ||
+ | |||
+ | {{begin-hl2msg|vote_changed|string}} | ||
+ | {{hl2msg|byte|option1|}} | ||
+ | {{hl2msg|byte|option2|}} | ||
+ | {{hl2msg|byte|option3|}} | ||
+ | {{hl2msg|byte|option4|}} | ||
+ | {{hl2msg|byte|option5|}} | ||
+ | {{hl2msg|byte|potentialVotes|}} | ||
+ | {{end-hl2msg}} | ||
+ | |||
+ | {{begin-hl2msg|vote_passed|string}} | ||
+ | {{hl2msg|string|details|}} | ||
+ | {{hl2msg|string|param1|}} | ||
+ | {{hl2msg|byte|team|}} | ||
+ | {{end-hl2msg}} | ||
+ | |||
+ | {{begin-hl2msg|vote_failed|string}} | ||
+ | {{hl2msg|byte|team|}} | ||
+ | {{end-hl2msg}} | ||
== Example voting plugin == | == Example voting plugin == |
Revision as of 23:35, 13 July 2011
Team Fortress 2 has a new voting system based on the Left 4 Dead Voting system and is controlled by events and Usermessages. 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
For a Yes/No vote, the server begins by sending a VoteStart Usermessage. Clients use the "vote" command to register their votes, after which the server sends a vote_cast event.
When the vote is complete, the server send either a VotePass or VoteFailed Usermessage.
A multiple choice vote is much the same as a Yes/No vote, but the server sends a "vote_options" event first, and sets the last argument of the VoteStart usermessage to false instead of true.
Failure reasons
The VoteFailed Usermessage 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 CallVoteFailed: 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
Usermessages
The Usermessages 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: