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)
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
Left 4 Dead has a new VGUI voting system, it's controlled by a bunch of events.  If you want to use this, you are fairly limited as there's no way of adding your own issues, you are stuck with what's there.  Still, some of the issues allowed in the resource file are not implemented in game.
+
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.
  
You can use a question from the left4dead_english.txt file.  
+
== How voting works ==
 +
 
 +
# 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 appropriate. Unfortunately, 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}}
  
== How voting works ==
+
=== vote_cast_yes ===
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.
+
{{begin-hl2msg|vote_cast_yes|string}}
 +
{{hl2msg|byte|team|}}
 +
{{hl2msg|long|entityid|entity id of the voter}}
 +
{{end-hl2msg}}
  
When the vote is complete, the server sends vote_ended, followed by either vote_passed or vote_failed. 
+
=== 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 handles voting to kick a user named "gaben" from the server.  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.
 +
 
 +
<sourcepawn>#include <sourcemod>
 +
 
 +
int g_iYesVotes;
 +
int g_iNoVotes;
  
<pre>#include <sourcemod>
 
new yesvotes;
 
new novotes;
 
 
#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_vote_kick_player");
+
    event.SetString("issue", "#L4D_TargetID_Player");
SetEventString(msg,"param1","gaben");
+
    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_vote_kick_player");
+
        {
SetEventString(msg,"param1","gaben");
+
            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:
 +
 
 +
http://devicenull.org/temp/l4d_question.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