/*********************************************************
 *        Bugblatter Team Change Extension - V3.4        *
 *********************************************************
 *                                                       *
 * This plug-in is linux & win32 friendly.               *
 *                                                       *
 * Version history                                       *
 *                                                       *
 * Version 3.4:                                          *
 *  - Removed debug and warnings compiling on V2.50.56   *
 *  - Announces changes to other admins                  *
 * Version 3.3:                                          *
 *  - Added "now" option to admin_t/admin_ct             *
 *  - Made team changes occur on restart round           *
 *  - Attempts to prevent temporary imbalances during    *
 *    swapping causing 1 team to exceed 50% of players   *
 *    as this can make a swap fail.                      *
 *  - Removed missing warning when transfering a live    *
 *    player to the terrorist team.                      *
 *                                                       *
 * Version 3.2:                                          *
 *  - Updated for language plugin version 3.3            *
 *                                                       *
 * Version 3.1:                                          *
 *  -  No Changes                                        *
 *                                                       *
 * Version 2.6:                                          *
 *  -  Fixed broken insertion string                     *
 *                                                       *
 * Version 2.5:                                          *
 *  -  Initial Version                                   *
 *                                                       *
 *********************************************************/
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
#include <plugin>
 
#include "settings"
#include "clientio"
#include "language"
 
#define ACCESS_CHANGE_TEAM 8192
#define ACCESS_RESTART 2
 
new g_Version[]="3.4";
new g_TeamChange[MAX_PLAYERS+1];
 
new g_SILLYBEAR[]="Laf. You can't move %1s onto another team, you silly bear.|Beubeuh. Tu ne peux pas bouger %1s vers une autre equipe, espece de cretin.|Laf. Du kannst %1s nicht ins andere Team schicken, Knallkopf.";
new g_PLAYERALIVE[]="Player is alive. Team will change at the end of the round.|Le joueur est en vie. L'equipe changera a la fin du round.|Der Spieler lebt noch. Er wechselt am Ende der Runde das Team.";
new g_UNKNOWNPLAYER[]="Unrecognised player %1s.|Joueur non reconnu %1s.|Spieler wurde nicht erkannt %1s.";
 
forward AnnounceToAdmins(msg[],print_type:location,Except);
 
/*********************************************************/
/* Standard event handlers for adminmod                  */
/*********************************************************/
 
public plugin_init() {
  plugin_registerinfo("Bugblatter's Team Change plugin","Better team changing than plugin CS",g_Version);
 
  /* Check server is configured properly */
  new fOK = checkAllowClientExec();
  if (fOK == 0) {
    return PLUGIN_CONTINUE;
  }
 
  language_init();
  RegisterPlugin();
 
  return PLUGIN_CONTINUE;
}
 
 
RegisterPlugin() {
  /* Register commands with adminmod */
 
  plugin_registercmd("admin_ct","admin_changeteam",ACCESS_CHANGE_TEAM,"admin_ct <target>: Changes target to the counter-terrorist team.");
  plugin_registercmd("admin_t", "admin_changeteam",ACCESS_CHANGE_TEAM,"admin_t <target>: Changes target to the terrorist team.");
  plugin_registercmd("admin_restartround", "admin_restartround",ACCESS_RESTART,"admin_restartround <seconds>: Restarts the round.");
 
  plugin_registercmd("bbteam_logdwa","BBLogdWorldAction",131072,"");
  exec("logd_reg 62 admin_command bbteam_logdwa",0);
}
 
isdead(i) {
  new userid = 0;
  new wonid=0;
  new AuthID[MAX_AUTHID_LENGTH];
  new teamid = 0;
  new username[MAX_NAME_LENGTH];
  new dead=0;
 
  if (playerinfo(i, username, 200, userid, wonid,teamid,dead,AuthID)==1) {
    if (dead==0) {
      return 0;
    }
  }
 
  return 1;
 
}
 
 
/* admin_ct <target>
   admin_t <target> */
public admin_changeteam(HLCommand,HLData,HLUserName,UserIndex) {
  new Command[MAX_COMMAND_LENGTH];
  new Data[MAX_DATA_LENGTH];
  new TargetName[MAX_NAME_LENGTH];
  new Text[MAX_TEXT_LENGTH];
  new User[MAX_NAME_LENGTH];
  new Msg[MAX_TEXT_LENGTH];
  new Now=0;
 
  convert_string(HLCommand,Command,MAX_NAME_LENGTH);
  convert_string(HLData,Data,MAX_NAME_LENGTH);
  convert_string(HLUserName,User,MAX_NAME_LENGTH);
 
  new len=strlen(Data);
  if (len>4) {
    if ((Data[len-4]==' ') && (Data[len-3]=='n') && (Data[len-2]=='o') && (Data[len-1]=='w')) {
      Now=1;
      Data[len-4]=0;
    }
  }
 
 
  if (check_user(Data) == 1) {
    get_username(Data,TargetName,MAX_NAME_LENGTH);
    say_command(User,Command,TargetName);
 
    new TargetIndex;
    get_userindex(TargetName,TargetIndex);
 
    if (check_immunity(TargetName) != 0) {
      language_sayf(UserIndex,g_SILLYBEAR,print_type:print_console, 0,0,0,0,TargetName);
      messageex(User,Text,print_type:print_chat);
    } else if (streq(Command,"admin_ct")==1) {
      if ((Now==1) || isdead(TargetIndex)) {    	
        execclient(TargetName, "chooseteam;menuselect 2;menuselect 3");
        g_TeamChange[TargetIndex]=0;
        snprintf(Msg,MAX_TEXT_LENGTH,"### %s has moved %s to the counter-terrorist team.",User,TargetName);
        AnnounceToAdmins(Msg,print_type:print_chat,UserIndex);
      }
      else {
        language_say(UserIndex,g_PLAYERALIVE,print_type:print_console);
        g_TeamChange[TargetIndex]=2;
        snprintf(Msg,MAX_TEXT_LENGTH,"### %s has moved %s to the counter-terrorist team. They will swap at the end of this round.",User,TargetName);
        AnnounceToAdmins(Msg,print_type:print_chat,UserIndex);
 
      }
    } else if (streq(Command,"admin_t")==1) {
      if ((Now==1) || isdead(TargetIndex)) {
        execclient(TargetName, "chooseteam;menuselect 1;menuselect 3");
        g_TeamChange[TargetIndex]=0;
        snprintf(Msg,MAX_TEXT_LENGTH,"### %s has moved %s to the terrorist team.",User,TargetName);
        AnnounceToAdmins(Msg,print_type:print_chat,UserIndex);
      }
      else {
        language_say(UserIndex,g_PLAYERALIVE,print_type:print_console);
        g_TeamChange[TargetIndex]=1;
        snprintf(Msg,MAX_TEXT_LENGTH,"### %s has moved %s to the terrorist team. They will swap at the end of this round.",User,TargetName);
        AnnounceToAdmins(Msg,print_type:print_chat,UserIndex);
      }
    }
  } else {
    language_sayf(UserIndex,g_UNKNOWNPLAYER,print_type:print_console,0,0,0,0,Data);
  }
 
  return PLUGIN_HANDLED;
}
 
 
checkteams() {
  new name[MAX_NAME_LENGTH];
  new i;
  new wonid;
  new team;
  new m=maxplayercount();
  new Ts=0;
  new CTs=0;
  new changes=0;
 
  /* Count players on each side and number of changes to be made */
  for(i=1;i<=m;i++) {
    if (playerinfo(i, name, MAX_NAME_LENGTH,wonid,team)==1) {
      if (team==1) {Ts=Ts+1;}
      if (team==2) {CTs=CTs+1;}
      if (g_TeamChange[i]>0) {
        changes=changes+1;
      }
    }
    else {
      g_TeamChange[i]=0;
    }
  }
 
  /* Attempt to order team changes */
  new pass=0;
  new teammax=(m+1)/2;
  for(pass=0;pass<7;pass++) {
    for(i=1;i<=m;i++) {
      if (g_TeamChange[i] > 0) {
        if (playerinfo(i, name, MAX_NAME_LENGTH,wonid,team)==1) {
          if (g_TeamChange[i] == 1) {
            if ((Ts<=CTs) || ((Ts<teammax) && (pass>2)) || (pass>=4)) {
              execclient(name, "chooseteam;menuselect 1;menuselect 3");
              Ts=Ts+1;
              if (team==2) {CTs=CTs-1;}
              changes=changes-1;
              g_TeamChange[i]=0;
              if (changes==0) { return; }
            }
          }
          else {
            if ((CTs<=Ts) || ((CTs<teammax) && (pass>2))|| (pass>=4)) {
              execclient(name, "chooseteam;menuselect 2;menuselect 3");
              CTs=CTs+1;
              if (team==1) {Ts=Ts-1;}
              changes=changes-1;
              g_TeamChange[i]=0;
              if (changes==0) { return; }
            }
          }
        }
      }
    }
  }
}
 
public BBLogdWorldAction(HLCommand,HLData,HLUserName,UserIndex) {
 
  new Data[MAX_DATA_LENGTH];
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
 
  if (strmatch(Data,"Round_End",9)==1) {
    checkteams();
  }
 
  return PLUGIN_HANDLED;
}
 
/* admin_restartround <seconds> */
public admin_restartround(HLCommand,HLData,HLUserName,UserIndex) {
  new Data[MAX_DATA_LENGTH];
  new time;
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
  time=strtonum(Data);
  if (time>5) {
    set_timer("CheckTeamsTimer",5,1,"");
  }
  else {
    checkteams();
  }
  return PLUGIN_CONTINUE;
}
 
public CheckTeamsTimer(Timer,Repeat,HLUserName,HLParam) {
  checkteams();
  return PLUGIN_HANDLED;
}
 
AnnounceToAdmins(msg[],print_type:location,Except) {
  new j;
  new strAdmin[MAX_NAME_LENGTH];
  new c=maxplayercount();
  for(j=1;j<c;j++) {
    if (j!=Except) {
      if (playerinfo(j,strAdmin,MAX_NAME_LENGTH)) {
        if (access(ACCESS_CHANGE_TEAM,strAdmin)) {
          language_saybyname(strAdmin,msg,location,0,0,0,0);
        }
      }
    }
  }
}