Difference between revisions of "TF2 Voting"

From AlliedModders Wiki
Jump to: navigation, search
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 00:35, 14 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.

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:
byte vote_option which option the player voted on
short team
long entityid entity id of the voter


Note: Sent to players before VoteStart UserMessage to populate choices for a multiple choice vote

Name: vote_options
Structure:
byte count Number of options - up to MAX_VOTE_OPTIONS [ed: 5]
string option1
string option2
string option3
string option4
string option5


Unused?

Name: vote_ended
Structure:


Name: vote_started
Structure:
string issue
string param1
byte team
long initiator entity id of the player who initiated the vote


Name: vote_changed
Structure:
byte option1
byte option2
byte option3
byte option4
byte option5
byte potentialVotes


Name: vote_passed
Structure:
string details
string param1
byte team


Name: vote_failed
Structure:
byte team


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:

Vote started

Vote passed

Vote failed