/* Forced Team Balancing - Killarny (killarny@espnow.com)
 
This plugin allows forced team balancing by denying team join/switch to teams
that would become uneven. In addition to this, the plugin also notifies the players
in the server when teams are uneven (due to people disconnecting, etc).
This plugin currently only works in mods that have two teams, since I don't know
how to get the number of teams in adminmod.
 
New Commands:
      admin_balance <on|off>: Sets the forced team balancing.
 
TODO:
      - find out how to get number of teams, and allow the mod to support any
      number of teams
      - find out how to get team names, and use those in the message, instead
      of "Team #"
      - add an option for forced automatic team switching when teams are
      unbalanced
*/
/* based loosely on admin_TFC.sma */
/* $Id: plugin_balance.sma, 2001/06/14 Killarny Exp $ */
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
 
#define ACCESS_BALANCE 32
 
new STRING_VERSION[MAX_DATA_LENGTH] = "2.50.0";
new NOTEAMSWITCH[MAX_DATA_LENGTH] = "Sorry, you can't switch to this team right now. That would make teams uneven.";
new NOTEAMJOIN[MAX_DATA_LENGTH] = "Sorry, you can't join this team right now. That would make teams uneven.";
 
public admin_balance( HLCommand, HLData, HLUserName, UserIndex ) {
      new Command[MAX_COMMAND_LENGTH];
      new Data[MAX_DATA_LENGTH];
      new User[MAX_NAME_LENGTH];
 
      convert_string( HLCommand, Command, MAX_NAME_LENGTH );
      convert_string( HLData, Data, MAX_NAME_LENGTH );
      convert_string( HLUserName, User, MAX_NAME_LENGTH );
 
      if( strlen( Data ) == 0 ) {
            if( getvar( "admin_balance_teams" ) == 1 )
                  selfmessage( "Team balancing is on." );
            if( getvar( "admin_balance_teams" ) == 0 )
                  selfmessage( "Team balancing is off." );
            return PLUGIN_HANDLED;
      }
 
      if( check_param( Data ) == 1 )
            execute_command( User, Command, "admin_balance_teams", "1" );
      else if( check_param( Data ) == 0 )
            execute_command( User, Command, "admin_balance_teams", "0" );
 
      return PLUGIN_HANDLED;
}
 
public HandleJoinTeam( HLCommand, HLData, HLUserName, UserIndex ) {
      new Data[MAX_DATA_LENGTH];
      new iNewTeam;
      new iNewTeamCount;
      new iOldTeamCount;
      new iTeam;
      new Name[MAX_NAME_LENGTH];
      new SessionID;
      new strNewTeam[MAX_DATA_LENGTH];
      new User[MAX_NAME_LENGTH];
      new WONID;
 
      if( UserIndex < 1 )
            return PLUGIN_CONTINUE;
 
      if( getvar( "admin_balance_teams" ) == 0 )
            return PLUGIN_CONTINUE;
 
      convert_string(HLData,Data,MAX_DATA_LENGTH);
      convert_string(HLUserName,User,MAX_NAME_LENGTH);
 
      playerinfo( UserIndex, Name, MAX_NAME_LENGTH, SessionID, WONID, iTeam );
      strcpy( strNewTeam, Data, MAX_DATA_LENGTH );
      iNewTeam = strtonum( strNewTeam );
 
      /* If they're not trying to switch to team 1 or 2, ignore it. Hopefully,
      this will allow builtin team 0 autoteam (like in Global Warfare) and
      spectator mode (team 15, I believe) team switches */
      if( ( iNewTeam < 1 ) || ( iNewTeam > 2 ) )
            return PLUGIN_CONTINUE;
 
      /* If they're trying to switch to the team they're already on, ignore it. */
      if( iTeam == iNewTeam )
            return PLUGIN_CONTINUE;
 
      iOldTeamCount = getteamcount( iTeam );
      iNewTeamCount = getteamcount( iNewTeam );
 
      /* Allow a new player to join iNewTeam only if it has less players
      than the other team */
      if( ( iTeam < 1 ) || ( iTeam > 2 ) ) {
            /* player wants to join team 1, allow if team 1 is less than
            or equal to team 2 */
            if( ( iNewTeam == 1 ) && ( getteamcount( 1 ) <= getteamcount( 2 ) ) ) {
                  return PLUGIN_CONTINUE;
            }
            /* player wants to join team 2, allow if team 2 is less than
            or equal to team 1 */
            if( ( iNewTeam == 2 ) && ( getteamcount( 2 ) <= getteamcount( 1 ) ) ) {
                  return PLUGIN_CONTINUE;
            }
            /* if either of the above isn't true, deny the team join */
            messageex( Name, NOTEAMJOIN, print_chat );
            return PLUGIN_HANDLED;
      }
 
      /* If they're the only one on their current team, ignore it (this is for
      instances like 'Hunted', where the hunted team has only one person on it) */
      if( iOldTeamCount <= 1 )
            return PLUGIN_CONTINUE;
 
      /* If there's only one person on the other team, ignore it. */
      if( iNewTeamCount <= 1 )
            return PLUGIN_CONTINUE;
 
      /* Otherwise, only allow the switch if the new team has
      less people than the old team. */
      if( iNewTeamCount >= iOldTeamCount ) {
            messageex( Name, NOTEAMSWITCH, print_chat );
            return PLUGIN_HANDLED;
      }
 
      return PLUGIN_CONTINUE;
}
 
public CheckTeams() {
      new Text[256];
 
      // FIXME: For some reason, this doesn't work
      // if( getvar( "admin_balance_teams" ) == 0 )
      //       return PLUGIN_CONTINUE;
 
      /* If there's only one person on one of the teams, ignore (this
      is for instances like 'Hunted', where the hunted team has only
      one person on it) */
      if( ( getteamcount( 2 ) <= 1 ) || ( getteamcount( 1 ) <= 1 ) )
            return PLUGIN_CONTINUE;
 
      /* if a team count minus one is greater than the other team count,
      then the team is too large, check each team */
      if(
            ( ( getteamcount( 1 ) - 1 ) > getteamcount( 2 ) ) ||
            ( ( getteamcount( 2 ) - 1 ) > getteamcount( 1 ) )
      ) {
            /* teams are uneven, so notify the players */
            snprintf( Text, 256, "[Teams Uneven] Team 1: %i Team 2: %i", getteamcount( 1 ), getteamcount( 2 ) );
            centersay( Text, 10, 255, 255, 255 );
            say( Text );
            set_timer( "CheckTeams", 10, 1 );
            return PLUGIN_HANDLED;
      }
 
      return PLUGIN_CONTINUE;
}
 
public plugin_init() {
      plugin_registerinfo( "Team Balancing Plugin", "Forces team balancing.", STRING_VERSION );
 
      plugin_registercmd( "admin_balance", "admin_balance", ACCESS_BALANCE, "admin_balance <^"on^" | ^"off^">: Sets the forced team balancing." );
      plugin_registercmd( "jointeam", "HandleJoinTeam", ACCESS_ALL );
 
      set_timer( "CheckTeams", 60, 99999 ); // repeat forever
 
      return PLUGIN_CONTINUE;
}