Left 4 Voting 2

From AlliedModders Wiki
Revision as of 19:57, 13 June 2013 by Dr. Greg House (talk | contribs) (Added subsection "Values for "issue" and "param1" in standard votes". More coming soon.)
Jump to: navigation, search

Left 4 Dead 2 has a VGUI voting system controller by a bunch of Events and UserMessages. You can use either a string from the resource file, or L4D_TargetID_Player which will let you create any vote you want.

How voting works

  1. A client issues a callvote with the vote type and argument.
  2. The VoteStart User Message is sent.
  3. Clients use the "Vote" command to register their votes ("Yes" or "No"), after which the server sends a VoteRegistered UserMessage to that player to acknowledge their vote. A vote_changed event is sent to all players with updated numbers.
  4. When the vote is complete, the server sends either a VotePass or VoteFail UserMessage.

Server Entity

The server should update this as appropriate. Unfortunately, the valid values for m_iActiveIssueIndex is unknown.

Name: vote_controller (CVoteController)
Structure:
int m_activeIssueIndex Number of the active issue
int m_onlyTeamToVote Corresponds to VoteStart's team argument.
int m_votesYes Current Yes votes
int m_votesNo Current No votes
int m_potentialVotes Number of players eligible to vote


Console Commands

Vote

Note: This command is only valid when a vote is ongoing.

Name: Vote
Structure:
string option "Yes" or "No"


User Messages

Note: These user messages use unsigned bytes for the team number. Since Valve represents no team as -1, no team is instead represented as its two's complement, 255.

VoteStart

Note: Sent to all players in the vote group, corresponding with teams. The default implementation also sends it to bots.

Name: VoteStart
Structure:
byte team Team index or 255 for all
byte initiator Client index (NOT USERID) of person who started the vote, or 99 for the server.
string issue Vote issue translation string
string param1 Vote issue text
string initiatorName Name of person who started the vote


Values for "issue" and "param1" in standard votes

Coming soon...

Vote type issue param1
Kick #L4D_vote_kick_player Nickname of the person to be kicked without "#"
ReturnToLobby #L4D_vote_return_to_lobby
ChangeCampaign #L4D_vote_mission_change #L4D360UI_CampaignName_C5
  • Campaigns aren't specified by map name but by the index the campaign's entry has in the game menus. Example: "5" specifies the campaign "The Parish"

VoteRegistered

Note: Only sent to player who voted

Name: VoteRegistered
Structure:
byte vote 0 for No, 1 for Yes


VotePass

Note: Sent to all players after a vote passes.

Name: VotePass
Structure:
byte team Team index or 255 for all
string details Vote success translation string
string param1 Vote winner


VoteFail

Note: Sent to all players after a vote fails.

Name: VoteFail
Structure:
byte team Team index or 255 for all


Events

Note: team is -1 when sent to all players)

vote_changed

Name: vote_changed
Structure:
byte yesVotes
byte noVotes
byte potentialVotes


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>

#define L4D2_TEAM_ALL -1

new yesvotes;
new novotes;
#define MAX_VOTES 4

public OnPluginStart()
{
	RegConsoleCmd("testvote",Callvote_Handler);
	RegConsoleCmd("Vote",vote);
}
public Action:Callvote_Handler(client, args)
{
	new Handle:bf = StartMessageAll("VoteStart", USERMSG_RELIABLE);

	BfWriteByte(bf, L4D2_TEAM_ALL);
	BfWriteByte(bf, 0);
	BfWriteString(bf, "#L4D_TargetID_Player");
	BfWriteString(bf, "Is gaben fat?");
	BfWriteString(bf, "Server");
	EndMessage();
	
	yesvotes = 0;
	novotes = 0;
	UpdateVotes();
	
	return Plugin_Handled;
}
public UpdateVotes()
{
	new Handle:msg = CreateEvent("vote_changed");
	SetEventInt(msg,"yesVotes",yesvotes);
	SetEventInt(msg,"noVotes",novotes);
	SetEventInt(msg,"potentialVotes",MAX_VOTES);
	FireEvent(msg);
	
	if (yesvotes+novotes == MAX_VOTES)
	{
		PrintToServer("voting complete!");
		if (yesvotes > novotes)
		{
			new Handle:bf = StartMessageAll("VotePass");
			BfWriteByte(bf, L4D2_TEAM_ALL);
			BfWriteString(bf, "#L4D_TargetID_Player");
			BfWriteString(bf, "Gaben is fat");
			EndMessage();
		}
		else
		{
			new Handle:bf = StartMessageAll("VoteFailed");
			BfWriteByte(bf, L4D2_TEAM_ALL);
			EndMessage();
		}
	}
}
public Action:vote(client, args)
{
	new String:arg[8];
	GetCmdArg(1,arg,8);
	PrintToServer("Got vote %s from %i",arg,client);
	if (strcmp(arg,"Yes",true) == 0)
	{
		yesvotes++;
	}
	else if (strcmp(arg,"No",true) == 0)
	{
		novotes++;
	}
	
	UpdateVotes();
	return Plugin_Continue;
}

See Also