<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ReCreator</id>
	<title>AlliedModders Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ReCreator"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/ReCreator"/>
	<updated>2026-05-28T03:57:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Left_4_Voting_2&amp;diff=11255</id>
		<title>Left 4 Voting 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Left_4_Voting_2&amp;diff=11255"/>
		<updated>2021-11-15T17:52:46Z</updated>

		<summary type="html">&lt;p&gt;ReCreator: Example plugin corrections: added timer for vote end(it was endless if someone doesn't vote),а fixed number of voters replaced via max players number, fixed bug when 1 player could vote unlimited number of times, corrected VoteFailed user msg to VoteFail&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;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.&lt;br /&gt;
&lt;br /&gt;
== How voting works ==&lt;br /&gt;
# A client issues a callvote with the vote type and argument.&lt;br /&gt;
# The VoteStart User Message is sent.&lt;br /&gt;
# Clients use the &amp;quot;Vote&amp;quot; command to register their votes (&amp;quot;Yes&amp;quot; or &amp;quot;No&amp;quot;), 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.&lt;br /&gt;
# When the vote is complete, the server sends either a VotePass or VoteFail UserMessage.&lt;br /&gt;
&lt;br /&gt;
== Server Entity ==&lt;br /&gt;
&lt;br /&gt;
The server should update this as appropriate.  Unfortunately, the valid values for m_iActiveIssueIndex is unknown.&lt;br /&gt;
&lt;br /&gt;
{{begin-hl2msg|vote_controller (CVoteController)|string}}&lt;br /&gt;
{{hl2msg|int|m_activeIssueIndex|Number of the active issue}}&lt;br /&gt;
{{hl2msg|int|m_onlyTeamToVote|Corresponds to VoteStart's team argument.}}&lt;br /&gt;
{{hl2msg|int|m_votesYes|Current Yes votes}}&lt;br /&gt;
{{hl2msg|int|m_votesNo|Current No votes}}&lt;br /&gt;
{{hl2msg|int|m_potentialVotes|Number of players eligible to vote}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
== Console Commands ==&lt;br /&gt;
&lt;br /&gt;
=== Vote ===&lt;br /&gt;
&lt;br /&gt;
{{qnotice|This command is only valid when a vote is ongoing.}}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{begin-hl2msg|Vote|string}}&lt;br /&gt;
{{hl2msg|string|option|&amp;quot;Yes&amp;quot; or &amp;quot;No&amp;quot;}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
== User Messages ==&lt;br /&gt;
{{qnotice|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.}}&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===VoteStart===&lt;br /&gt;
{{qnotice|Sent to all players in the vote group, corresponding with teams.  The default implementation also sends it to bots.}}&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{begin-hl2msg|VoteStart|string}}&lt;br /&gt;
{{hl2msg|byte|team|Team index or 255 for all}}&lt;br /&gt;
{{hl2msg|byte|initiator|Client index (NOT USERID) of person who started the vote, or 99 for the server.}}&lt;br /&gt;
{{hl2msg|string|issue|Vote issue translation string}}&lt;br /&gt;
{{hl2msg|string|param1|Vote issue text}}&lt;br /&gt;
{{hl2msg|string|initiatorName|Name of person who started the vote}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
====Values for &amp;quot;issue&amp;quot; and &amp;quot;param1&amp;quot; in standard votes====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Vote type !! issue !! param1&lt;br /&gt;
|-&lt;br /&gt;
| Kick || #L4D_vote_kick_player || Nickname of the person to be kicked without &amp;quot;#&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| ReturnToLobby || #L4D_vote_return_to_lobby || &lt;br /&gt;
|-&lt;br /&gt;
| ChangeCampaign || #L4D_vote_mission_change || #L4D360UI_CampaignName_C5&lt;br /&gt;
|-&lt;br /&gt;
| RestartChapter || #L4D_vote_passed_versus_level_restart ||&lt;br /&gt;
|-&lt;br /&gt;
| ChangeDifficulty (easy) || #L4D_vote_change_difficulty || #L4D_DifficultyEasy&lt;br /&gt;
|-&lt;br /&gt;
| ChangeDifficulty (hard) || #L4D_vote_change_difficulty || #L4D_DifficultyHard&lt;br /&gt;
|-&lt;br /&gt;
| Alltalk On || #L4D_vote_alltalk_change || #L4D_vote_alltalk_enable&lt;br /&gt;
|-&lt;br /&gt;
| Alltalk Off || #L4D_vote_alltalk_change || #L4D_vote_alltalk_disable&lt;br /&gt;
|}&lt;br /&gt;
*Campaigns aren't specified by map name but by the index the campaign's entry has in the game menus. Example: &amp;quot;5&amp;quot; specifies the campaign &amp;quot;The Parish&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===VoteRegistered===&lt;br /&gt;
{{qnotice|Only sent to player who voted}}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{begin-hl2msg|VoteRegistered|string}}&lt;br /&gt;
{{hl2msg|byte|vote|0 for No, 1 for Yes}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
===VotePass===&lt;br /&gt;
{{qnotice|Sent to all players after a vote passes.}}&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{begin-hl2msg|VotePass|string}}&lt;br /&gt;
{{hl2msg|byte|team|Team index or 255 for all}}&lt;br /&gt;
{{hl2msg|string|details|Vote success translation string}}&lt;br /&gt;
{{hl2msg|string|param1|Vote winner}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
===VoteFail===&lt;br /&gt;
{{qnotice|Sent to all players after a vote fails.}}&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{begin-hl2msg|VoteFail|string}}&lt;br /&gt;
{{hl2msg|byte|team|Team index or 255 for all}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
{{qnotice|team is -1 when sent to all players)}}&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== vote_changed ===&lt;br /&gt;
{{begin-hl2msg|vote_changed|string}}&lt;br /&gt;
{{hl2msg|byte|yesVotes|}}&lt;br /&gt;
{{hl2msg|byte|noVotes|}}&lt;br /&gt;
{{hl2msg|byte|potentialVotes|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
== Example voting plugin ==&lt;br /&gt;
This is a basic plugin that starts a vote, &amp;quot;Is gaben fat?&amp;quot;.  It does not ensure the same client does not vote multiple times, nor does it actually kick the user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define L4D2_TEAM_ALL -1&lt;br /&gt;
&lt;br /&gt;
int g_iYesVotes;&lt;br /&gt;
int g_iNoVotes;&lt;br /&gt;
int g_iPlayersCount;&lt;br /&gt;
bool VoteInProgress;&lt;br /&gt;
bool CanPlayerVote[MAXPLAYERS + 1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegConsoleCmd(&amp;quot;testvote&amp;quot;, Callvote_Handler);&lt;br /&gt;
	RegConsoleCmd(&amp;quot;Vote&amp;quot;, vote);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Callvote_Handler(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	BfWrite bf = UserMessageToBfWrite(StartMessageAll(&amp;quot;VoteStart&amp;quot;, USERMSG_RELIABLE));&lt;br /&gt;
&lt;br /&gt;
	bf.WriteByte(L4D2_TEAM_ALL);&lt;br /&gt;
	bf.WriteByte(0);&lt;br /&gt;
	bf.WriteString(&amp;quot;#L4D_TargetID_Player&amp;quot;);&lt;br /&gt;
	bf.WriteString(&amp;quot;Is gaben fat?&amp;quot;);&lt;br /&gt;
	bf.WriteString(&amp;quot;Server&amp;quot;);&lt;br /&gt;
	EndMessage();&lt;br /&gt;
&lt;br /&gt;
	g_iYesVotes = 0;&lt;br /&gt;
	g_iNoVotes = 0;&lt;br /&gt;
	g_iPlayersCount = 0;&lt;br /&gt;
	VoteInProgress = true;&lt;br /&gt;
&lt;br /&gt;
	for(int i = 1; i &amp;lt;= MaxClients; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if(IsValidClient(i) &amp;amp;&amp;amp; !IsFakeClient(i))&lt;br /&gt;
		{&lt;br /&gt;
			CanPlayerVote[i] = true;&lt;br /&gt;
			g_iPlayersCount ++;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	UpdateVotes();&lt;br /&gt;
	CreateTimer(10.0, Timer_VoteCheck, TIMER_FLAG_NO_MAPCHANGE);&lt;br /&gt;
	&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
public Action Timer_VoteCheck(Handle timer)&lt;br /&gt;
{&lt;br /&gt;
	if(VoteInProgress)&lt;br /&gt;
	{&lt;br /&gt;
		VoteInProgress = false;&lt;br /&gt;
		UpdateVotes();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void UpdateVotes()&lt;br /&gt;
{&lt;br /&gt;
	Event event = CreateEvent(&amp;quot;vote_changed&amp;quot;);&lt;br /&gt;
	event.SetInt(&amp;quot;yesVotes&amp;quot;, g_iYesVotes);&lt;br /&gt;
	event.SetInt(&amp;quot;noVotes&amp;quot;, g_iNoVotes);&lt;br /&gt;
	event.SetInt(&amp;quot;potentialVotes&amp;quot;, g_iPlayersCount);&lt;br /&gt;
	event.Fire();&lt;br /&gt;
	&lt;br /&gt;
	if ((g_iYesVotes + g_iNoVotes == g_iPlayersCount) || !VoteInProgress)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToServer(&amp;quot;voting complete!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
		for(int i = 1; i &amp;lt;= MaxClients; i++)&lt;br /&gt;
		{&lt;br /&gt;
			if(IsValidClient(i) &amp;amp;&amp;amp; !IsFakeClient(i))&lt;br /&gt;
			{&lt;br /&gt;
				CanPlayerVote[i] = false;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		VoteInProgress = false;&lt;br /&gt;
&lt;br /&gt;
		if (g_iYesVotes &amp;gt; g_iNoVotes)&lt;br /&gt;
		{&lt;br /&gt;
			BfWrite bf = UserMessageToBfWrite(StartMessageAll(&amp;quot;VotePass&amp;quot;));&lt;br /&gt;
			bf.WriteByte(L4D2_TEAM_ALL);&lt;br /&gt;
			bf.WriteString(&amp;quot;#L4D_TargetID_Player&amp;quot;);&lt;br /&gt;
			bf.WriteString(&amp;quot;Gaben is fat&amp;quot;);&lt;br /&gt;
			EndMessage();&lt;br /&gt;
		}&lt;br /&gt;
		else&lt;br /&gt;
		{&lt;br /&gt;
			BfWrite bf = UserMessageToBfWrite(StartMessageAll(&amp;quot;VoteFail&amp;quot;));&lt;br /&gt;
			bf.WriteByte(L4D2_TEAM_ALL);&lt;br /&gt;
			EndMessage();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action vote(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	if(VoteInProgress &amp;amp;&amp;amp; CanPlayerVote[client] == true)&lt;br /&gt;
	{&lt;br /&gt;
		char arg[8];&lt;br /&gt;
		GetCmdArg(1, arg, sizeof arg);&lt;br /&gt;
&lt;br /&gt;
		PrintToServer(&amp;quot;Got vote %s from %i&amp;quot;, arg, client);&lt;br /&gt;
&lt;br /&gt;
		if (strcmp(arg, &amp;quot;Yes&amp;quot;, true) == 0)&lt;br /&gt;
		{&lt;br /&gt;
			g_iYesVotes++;&lt;br /&gt;
		}&lt;br /&gt;
		else if (strcmp(arg, &amp;quot;No&amp;quot;, true) == 0)&lt;br /&gt;
		{&lt;br /&gt;
			g_iNoVotes++;&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
		UpdateVotes();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Continue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
stock bool IsValidClient(int client){&lt;br /&gt;
	return (client &amp;gt; 0 &amp;amp;&amp;amp; client &amp;lt;= MaxClients &amp;amp;&amp;amp; IsClientInGame(client));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Left 4 Voting]]&lt;br /&gt;
* [[TF2 Voting]]&lt;br /&gt;
* [https://forums.alliedmods.net/showthread.php?t=162164 BuiltinVotes], a SourceMod extension that exposes a voting API that uses this voting system.&lt;/div&gt;</summary>
		<author><name>ReCreator</name></author>
		
	</entry>
</feed>