TF2 Voting

From AlliedModders Wiki
Revision as of 23:50, 13 July 2011 by Powerlord (talk | contribs) (New page on TF2's voting. Not complete by any means (See the TF2 Voting UserMessages topic))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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.

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 1

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();
		}
	}
}

// This is 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