Difference between revisions of "Left 4 Voting"

From AlliedModders Wiki
Jump to: navigation, search
(Example voting plugin)
m (Example voting plugin: Update syntax, highlighting, methodmap, and formatting)
 
(4 intermediate revisions by 2 users not shown)
Line 2: Line 2:
  
 
== How voting works ==
 
== How voting works ==
Server begins by sending a vote_started event, followed by a vote_changed event.  Client's use the "Vote" command to register their votes, after which the server sends a vote_cast_yes or vote_case_no event, along with a vote_changed event.
 
  
When the vote is complete, the server sends vote_ended, followed by either vote_passed or vote_failed.   
+
# Server sends a vote_started event
 +
# Servers sends a vote_changed event
 +
# Clients use the "Vote" command to register their votes ("Yes" or "No"), after which the server sends a vote_cast_yes or vote_cast_no event, followed by a vote_changed event with updated numbers.
 +
# Server ends the vote by sending vote_ended event, followed by a vote_passed or vote_failed event.
 +
 
 +
== Server Entity ==
 +
 
 +
The server should update this as appropriateUnfortunately, the valid values for m_iActiveIssueIndex is unknown.
 +
 
 +
{{begin-hl2msg|vote_controller (CVoteController)|string}}
 +
{{hl2msg|int|m_activeIssueIndex|Number of the active issue}}
 +
{{hl2msg|int|m_onlyTeamToVote|Corresponds to VoteStart's team argument.}}
 +
{{hl2msg|int|m_votesYes|Current Yes votes}}
 +
{{hl2msg|int|m_votesNo|Current No votes}}
 +
{{hl2msg|int|m_potentialVotes|Number of players eligible to vote}}
 +
{{end-hl2msg}}
 +
 
 +
== Console Commands ==
 +
 
 +
=== Vote ===
 +
 
 +
{{qnotice|This command is only valid when a vote is ongoing.}}<br />
 +
{{begin-hl2msg|Vote|string}}
 +
{{hl2msg|string|option|"Yes" or "No"}}
 +
{{end-hl2msg}}
 +
 
 +
== Events ==
 +
{{qnotice|team is -1 when sent to all players)}}<br>
 +
 
 +
=== vote_ended ===
 +
{{begin-hl2msg|vote_ended|string}}
 +
{{hl2msg|None|None|}}
 +
{{end-hl2msg}}
 +
 
 +
=== vote_started ===
 +
{{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}}
 +
 
 +
=== vote_changed ===
 +
{{begin-hl2msg|vote_changed|string}}
 +
{{hl2msg|byte|yesVotes|}}
 +
{{hl2msg|byte|noVotes|}}
 +
{{hl2msg|byte|potentialVotes|}}
 +
{{end-hl2msg}}
 +
 
 +
=== vote_passed ===
 +
{{begin-hl2msg|vote_passed|string}}
 +
{{hl2msg|string|details|}}
 +
{{hl2msg|string|param1|}}
 +
{{hl2msg|byte|team|}}
 +
{{end-hl2msg}}
 +
 
 +
=== vote_failed ===
 +
{{begin-hl2msg|vote_failed|string}}
 +
{{hl2msg|byte|team|}}
 +
{{end-hl2msg}}
 +
 
 +
=== vote_cast_yes ===
 +
{{begin-hl2msg|vote_cast_yes|string}}
 +
{{hl2msg|byte|team|}}
 +
{{hl2msg|long|entityid|entity id of the voter}}
 +
{{end-hl2msg}}
 +
 
 +
=== vote_cast_no ===
 +
{{begin-hl2msg|vote_cast_no|string}}
 +
{{hl2msg|byte|team|}}
 +
{{hl2msg|long|entityid|entity id of the voter}}
 +
{{end-hl2msg}}
  
 
== Example voting plugin ==
 
== 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.
 
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.
  
<pre>#include <sourcemod>
+
<sourcepawn>#include <sourcemod>
new yesvotes;
+
 
new novotes;
+
int g_iYesVotes;
 +
int g_iNoVotes;
 +
 
 
#define MAX_VOTES 4
 
#define MAX_VOTES 4
 
+
public OnPluginStart()
+
public void OnPluginStart()
 
{
 
{
RegConsoleCmd("testvote",Callvote_Handler);
+
    RegConsoleCmd("testvote", Callvote_Handler);
RegConsoleCmd("Vote",vote);
+
    RegConsoleCmd("Vote", vote);
 
}
 
}
public Action:Callvote_Handler(client, args)
+
 +
public Action Callvote_Handler(int client, int args)
 
{
 
{
new Handle:msg = CreateEvent("vote_started");
+
    Event event = CreateEvent("vote_started");
SetEventString(msg,"issue","#L4D_TargetID_Player");
+
    event.SetString("issue", "#L4D_TargetID_Player");
SetEventString(msg,"param1","Is gaben fat?");
+
    event.SetString("param1", "Is gaben fat?");
SetEventInt(msg,"team",0);
+
    event.SetInt("team", 0);
SetEventInt(msg,"initiator",0);
+
    event.SetInt("initiator", 0);
FireEvent(msg);
+
    event.Fire();
+
yesvotes = 0;
+
    g_iYesVotes = 0;
novotes = 0;
+
    g_iNoVotes = 0;
UpdateVotes();
+
+
    UpdateVotes();
return Plugin_Handled;
+
 +
    return Plugin_Handled;
 
}
 
}
public UpdateVotes()
+
 +
public void UpdateVotes()
 
{
 
{
new Handle:msg = CreateEvent("vote_changed");
+
    Event event = CreateEvent("vote_changed");
SetEventInt(msg,"yesVotes",yesvotes);
+
    event.SetInt("yesVotes", g_iYesVotes);
SetEventInt(msg,"noVotes",novotes);
+
    event.SetInt("noVotes", g_iNoVotes);
SetEventInt(msg,"potentialVotes",MAX_VOTES);
+
    event.SetInt("potentialVotes", MAX_VOTES);
FireEvent(msg);
+
    event.Fire();
+
if (yesvotes+novotes == MAX_VOTES)
+
    if (g_iYesVotes + g_iNoVotes == MAX_VOTES)
{
+
    {
PrintToServer("voting complete!");
+
        PrintToServer("voting complete!");
msg = CreateEvent("vote_ended");
+
FireEvent(msg);
+
        event = CreateEvent("vote_ended");
if (yesvotes > novotes)
+
        event.Fire();
{
+
msg = CreateEvent("vote_passed");
+
        if (g_iYesVotes > g_iNoVotes)
SetEventString(msg,"details","#L4D_TargetID_Player");
+
        {
SetEventString(msg,"param1","Gaben is fat");
+
            event = CreateEvent("vote_passed");
SetEventInt(msg,"team",0);
+
            event.SetString("details", "#L4D_TargetID_Player");
FireEvent(msg);
+
            event.SetString("param1", "Gaben is fat");
}
+
            event.SetInt("team", 0);
else
+
            event.Fire();
{
+
        }
msg = CreateEvent("vote_failed");
+
        else
SetEventInt(msg,"team",0);
+
        {
FireEvent(msg);
+
            event = CreateEvent("vote_failed");
}
+
            event.SetInt("team", 0);
}
+
            event.Fire();
 +
        }
 +
    }
 
}
 
}
public Action:vote(client, args)
+
 +
public Action vote(int client, int args)
 
{
 
{
new String:arg[8];
+
    char arg[8];
GetCmdArg(1,arg,8);
+
    GetCmdArg(1, arg, sizeof arg);  
PrintToServer("Got vote %s from %i",arg,client);
+
if (strcmp(arg,"Yes",true) == 0)
+
    PrintToServer("Got vote %s from %i", arg, client);
{
+
yesvotes++;
+
    if (strcmp(arg, "Yes", true) == 0)
}
+
    {
else if (strcmp(arg,"No",true) == 0)
+
        g_iYesVotes++;
{
+
    }
novotes++;
+
    else if (strcmp(arg, "No", true) == 0)
}
+
    {
+
        g_iNoVotes++;
UpdateVotes();
+
    }
return Plugin_Continue;
+
}</pre>
+
    UpdateVotes();
 +
 +
    return Plugin_Continue;
 +
}</sourcepawn>
  
 
See the following images for examples what this looks like:
 
See the following images for examples what this looks like:
Line 86: Line 167:
  
 
http://devicenull.org/temp/l4d_result.jpg
 
http://devicenull.org/temp/l4d_result.jpg
 +
 +
==See Also==
 +
* [[Left 4 Voting 2]]
 +
* [[TF2 Voting]]
 +
* [https://forums.alliedmods.net/showthread.php?t=162164 BuiltinVotes], a SourceMod extension that exposes a voting API that uses this voting system.

Latest revision as of 22:28, 29 March 2020

Left 4 Dead has a new VGUI voting system, it's controlled by a bunch of events. 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. Server sends a vote_started event
  2. Servers sends a vote_changed event
  3. Clients use the "Vote" command to register their votes ("Yes" or "No"), after which the server sends a vote_cast_yes or vote_cast_no event, followed by a vote_changed event with updated numbers.
  4. Server ends the vote by sending vote_ended event, followed by a vote_passed or vote_failed event.

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"


Events

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

vote_ended

Name: vote_ended
Structure:
None None


vote_started

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


vote_changed

Name: vote_changed
Structure:
byte yesVotes
byte noVotes
byte potentialVotes


vote_passed

Name: vote_passed
Structure:
string details
string param1
byte team


vote_failed

Name: vote_failed
Structure:
byte team


vote_cast_yes

Name: vote_cast_yes
Structure:
byte team
long entityid entity id of the voter


vote_cast_no

Name: vote_cast_no
Structure:
byte team
long entityid entity id of the voter


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>
 
int g_iYesVotes;
int g_iNoVotes;
 
#define MAX_VOTES 4
 
public void OnPluginStart()
{
    RegConsoleCmd("testvote", Callvote_Handler);
    RegConsoleCmd("Vote", vote);
}
 
public Action Callvote_Handler(int client, int args)
{
    Event event = CreateEvent("vote_started");
    event.SetString("issue", "#L4D_TargetID_Player");
    event.SetString("param1", "Is gaben fat?");
    event.SetInt("team", 0);
    event.SetInt("initiator", 0);
    event.Fire();
 
    g_iYesVotes = 0;
    g_iNoVotes = 0;
 
    UpdateVotes();
 
    return Plugin_Handled;
}
 
public void UpdateVotes()
{
    Event event = CreateEvent("vote_changed");
    event.SetInt("yesVotes", g_iYesVotes);
    event.SetInt("noVotes", g_iNoVotes);
    event.SetInt("potentialVotes", MAX_VOTES);
    event.Fire();
 
    if (g_iYesVotes + g_iNoVotes == MAX_VOTES)
    {
        PrintToServer("voting complete!");
 
        event = CreateEvent("vote_ended");
        event.Fire();
 
        if (g_iYesVotes > g_iNoVotes)
        {
            event = CreateEvent("vote_passed");
            event.SetString("details", "#L4D_TargetID_Player");
            event.SetString("param1", "Gaben is fat");
            event.SetInt("team", 0);
            event.Fire();
        }
        else
        {
            event = CreateEvent("vote_failed");
            event.SetInt("team", 0);
            event.Fire();
        }
    }
}
 
public Action vote(int client, int args)
{
    char arg[8];
    GetCmdArg(1, arg, sizeof arg); 
 
    PrintToServer("Got vote %s from %i", arg, client);
 
    if (strcmp(arg, "Yes", true) == 0)
    {
        g_iYesVotes++;
    }
    else if (strcmp(arg, "No", true) == 0)
    {
        g_iNoVotes++;
    }
 
    UpdateVotes();
 
    return Plugin_Continue;
}

See the following images for examples what this looks like:

http://devicenull.org/temp/l4d_question.jpg

http://devicenull.org/temp/l4d_result.jpg

See Also