Aborting The Vote

Admin Mod provides a command admin_abort_vote in plugin_base that allows an administrator to abort a map or kick vote that is in progress. This section of the tutorial will show how to make admin_abort_vote cancel gravity votes as well as map or kick votes. This is an example of two plugins co-operating over implementing the same command.

Registering admin_abort_vote

admin_abort_vote is already implemented in plugin_base. In order for us to also respond to the command being issued, we must implement it a 2nd time in this plugin. We use the same access level and description as in plugin_base. However, there is no need to use the same command handler name (2nd argument).

/* Event Handlers */
public plugin_init() {
  plugin_registerinfo("Gravity Vote Plugin","Allows players to vote on/off low gravity",g_Version);

  plugin_registercmd("admin_vote_gravity","AdminVoteGravity",ACCESS_VOTE_MAP,
                     "admin_vote_gravity: Starts a vote to change gravity setting.");
  plugin_registercmd("admin_abort_vote","AdminAbortVote",ACCESS_ABORT_VOTE,
                     "admin_abort_vote: Aborts any vote that is in progress.");

  return PLUGIN_CONTINUE;
}

Implementing abort

Our implementation of the abort command is similar to that in plugin_base.sma, except we need to return PLUGIN_CONTINUE when no vote is in progress rather than presenting an error message to the user. This allows plugin_base, or any other plugin implementing admin_abort_vote to handle the command and abort any votes they may be running. To achieve this, we need two global variables - one to indicate a gravity vote is in proress, and one to indicate that it has been aborted:

/* Global Variables */
new g_VoteInProgress;     /* 1 if a gravity vote is in progress, 0 otherwise */
new g_VoteAborted;        /* 1 if a vote in progress is to be aborted, 0 otherwise */

The admin_vote_gravity function is modified to set both of these when a vote is sucessfully started:

public AdminVoteGravity(HLCommand,HLData,HLUserName,UserIndex) {
  new Command[MAX_COMMAND_LENGTH];
  new UserName[MAX_TEXT_LENGTH];

  if (vote_allowed()!=1) {
    selfmessage( "Vote not allowed at this time.");
    return PLUGIN_HANDLED;
  }

  convert_string(HLCommand,Command,MAX_COMMAND_LENGTH);
  convert_string(HLUserName,UserName,MAX_NAME_LENGTH);

  say_command(User,Command,"");
  if (vote("Choose a gravity setting:","Low Gravity","Normal Gravity","HandleGravityVote","")) {
    g_VoteInProgress = 1;
    g_VoteAborted = 0;
  }
  else {
    selfmessage("failed to start gravity vote");
  }
  return PLUGIN_HANDLED;
}

admin_abort_vote command

The implementation of admin_abort_vote in plugin_base will take care of displaying a message to the user if no vote is in progress. We only need to take action if a gravity vote is in progress, in which case we want to stop the command reaching plugin_base. If we allowed the command to continue, plugin_base would check its g_VoteInProgress variable, see that no map or kick vote was running and display a message to the user that no vote can aborted.

public AdminAbortVote(HLCommand,HLData,HLUserName,UserIndex) {
  if (g_VoteInProgress) {
    /* Record that we should abort the vote */
    g_VoteAborted = 1;
    selfmessage("Gravity vote will be aborted");

    /* Prevent plugin_base implementation from being called and sending its
     * message to the user - if a gravity vote is in progress, then it is
     * impossible for a map or kick vote to also be in progress, so it doesn't
     * need to know the user typed admin_abort_vote */
    return PLUGIN_HANDLED;
  }

  /* If no gravity vote is in progress, let plugin_base handle
   * this command */
  return PLUGIN_CONTINUE;
}

Reacting to an aborted vote

Finally, we need to modify our implementation of HandleGravityVote to check if the vote was aborted, and inform the users if so.

NOTE: It is necessary to set g_VoteInProgress back to 0 so that the implementation of admin_abort_vote in this plugin will pass on attempts to abort map/kick votes to plugin_base if they are made after a gravity vote is aborted. However, it is not necessary to reset g_VoteAborted, as we are only interested in the value of that variable whilst a vote is in progress, and it is set to 0 when starting a vote. Whether it is 1 or 0 while there is no vote in progress is unimportant.

/* Handle a gravity vote's results. */
public HandleGravityVote(WinningOption,HLParam,VoteCount,UserCount) {
  g_VoteInProgress = 0;
  if (g_VoteAborted) {
    say("Gravity vote aborted by an admin.");
  } else {
    if (WinningOption == 1) {
      say("Switching to low gravity due to vote.");
      setvar("sv_gravity",200);
    }
    else {
      say("Switching to normal gravity due to vote.");
      setvar("sv_gravity",800);
    }
  }
  return PLUGIN_HANDLED;
}

Complete source code

Copy the code below to a file plugin_vote_gravity, compile it and add it plugin.ini. You should then be able to perform gravity votes on your server.

/*********************************************************
 * Gravity Vote Plugin - Version 1.1                     *
 *********************************************************
 *                                                       *
 * Name: plugin_vote_gravity                             *
 * Author: ravenousbugblatterbeast@hotmail.com           *
 * Released: 1st September 2002                          *
 *                                                       *
 * Version 1.0:                                          *
 *                                                       *
 *  -  Added ablity for admin to cancel the vote         *
 *                                                       *
 * Version 1.0:                                          *
 *                                                       *
 *  -  Initial version                                   *
 *                                                       *
 *********************************************************
 */

/* Includes */
#include <core>
#include <console>
#include <string>
#include <plugin>
#include <admin>
#include <adminlib>

/* Constants */

/* Global Variables */
new g_Version[]="1.1";	/* Plugin version number */
new g_VoteInProgress;     /* 1 if a gravity vote is in progress, 0 otherwise */
new g_VoteAborted;        /* 1 if a vote in progress is to be aborted, 0 otherwise */


/* Function Declarations */
forward AdminVoteGravity(HLCommand,HLData,HLUserName,UserIndex);
forward HandleGravityVote(WinningOption,HLParam,VoteCount,UserCount);
forward AdminAbortVote(HLCommand,HLData,HLUserName,UserIndex);

/* Event Handlers */
public plugin_init() {
  plugin_registerinfo("Gravity Vote Plugin","Allows players to vote on/off low gravity",g_Version);

  plugin_registercmd("admin_vote_gravity","AdminVoteGravity",ACCESS_VOTE_MAP,
                     "admin_vote_gravity: Starts a vote to change gravity setting.");
  plugin_registercmd("admin_abort_vote","AdminAbortVote",ACCESS_ABORT_VOTE,
                     "admin_abort_vote: Aborts any vote that is in progress.");

  return PLUGIN_CONTINUE;
}

/* Command Handlers */

public AdminVoteGravity(HLCommand,HLData,HLUserName,UserIndex) {
  new Command[MAX_COMMAND_LENGTH];
  new UserName[MAX_TEXT_LENGTH];

  if (vote_allowed()!=1) {
    selfmessage( "Vote not allowed at this time.");
    return PLUGIN_HANDLED;
  }

  convert_string(HLCommand,Command,MAX_COMMAND_LENGTH);
  convert_string(HLUserName,UserName,MAX_NAME_LENGTH);

  say_command(User,Command,"");
  if (vote("Choose a gravity setting:","Low Gravity","Normal Gravity","HandleGravityVote","")) {
    g_VoteInProgress = 1;
    g_VoteAborted = 0;
  }
  else {
    selfmessage("failed to start gravity vote");
  }
  return PLUGIN_HANDLED;
}

public AdminAbortVote(HLCommand,HLData,HLUserName,UserIndex) {
  if (g_VoteInProgress) {
    /* Record that we should abort the vote */
    g_VoteAborted = 1;
    selfmessage("Gravity vote will be aborted");

    /* Prevent plugin_base implementation from being called and sending its
     * message to the user - if a gravity vote is in progress, then it is
     * impossible for a map or kick vote to also be in progress, so it doesn't
     * need to know the user typed admin_abort_vote */
    return PLUGIN_HANDLED;
  }

  /* If no gravity vote is in progress, let plugin_base handle
   * this command */
  return PLUGIN_CONTINUE;
}

/* Support Functions */

/* Handle a gravity vote's results. */
public HandleGravityVote(WinningOption,HLParam,VoteCount,UserCount) {
  g_VoteInProgress = 0;
  if (g_VoteAborted) {
    say("Gravity vote aborted by an admin.");
  } else {
    if (WinningOption == 1) {
      say("Switching to low gravity due to vote.");
      setvar("sv_gravity",200);
    }
    else {
      say("Switching to normal gravity due to vote.");
      setvar("sv_gravity",800);
    }
  }
  return PLUGIN_HANDLED;
}