
   /* AMX Mod script.
   *
   * (c) Copyright 2002, OLO
   * This file is provided as is (no warranties).
   *
   */
   #include <amxmod>
   new bool:endscore = true
   new blockjoining[2]
   new scores[2]
   new Float:ppower[33]
   new Float:tpower[2]
   new Float:tempf
   new Float:avepower
   new playersnum[2]
   Float:maxf(Float:a,Float:b)
       return a < b ? b : a
   Float:minf(Float:a,Float:b)
       return a < b ? a : b

   absn(a)
       return a < 0 ? -a : a

   public calculate_power(){
       new teams[33], ppl[32], ippl
       new a, b, c , d, e
       new Float:frags
       new Float:deaths
       new transfer = -1

       playersnum[0] = playersnum[1] = 0 // reset player num
       tpower[0] = tpower[1] = 0.0 // reset teams power
       avepower = 0.0 // reset averange skill
       blockjoining[  0  ] = blockjoining[ 1 ] = PLUGIN_CONTINUE // reset
   blocking

       get_players(ppl,ippl)    // get all players in game

       /* Get avarange efficiency, player efficiency and team efficiency.
   */
       for(a=0;a<ippl;++a){ // calculate efficiency for each player
           b = ppl[a]
           c  = get_user_team(b) - 1 // in CS the T team has id #1 and CT
   has id #2
           teams[b]  =  c  //  save  what  index  of  team the player has
           if (c!=0&&c!=1) continue        // Spectator
           frags = float(get_user_frags(b))
           deaths = float(get_user_deaths(b))
           tempf = (frags / (deaths ? deaths : 1.0)) + (frags * 0.1)
           ppower[b] = tempf
           avepower  +=  tempf  //  add  to  sum  of all efficiencies for
   avarange calculation
           playersnum[c]++ // increase number of player in that team
           tpower[c]  +=  tempf    //  add  the player efficiency to team
   efficiency
       }
       avepower  /=  float(playersnum[0]  +  playersnum[1])  //  averange
   efficiency

       /* Get best players. */
       new goodlist[2][32]    // array for list of good players
       new goodnum[2] // how many good player the team has
       goodnum[0] = goodnum[1] = 0
       for(a=0;a<ippl;++a){ // sum eff. for each team
           b = ppl[a]
           c = teams[b]
           if (c!=0&&c!=1) continue        // Spectator
           if  (  ppower[b] > avepower ){ // if better than avarange then
   save him to list
               goodlist[c][goodnum[c]] = b
               goodnum[c]++
           }
       }

       /* Display score. */
       new Float: cscore = tpower[1]
       new Float: tscore = tpower[0]
       client_print(0,print_chat,"CT    %d   (%.2f)   --   TERRORIST   %d
   (%.2f)",scores[1],cscore,scores[0],tscore)

       /* Try to estimate which team is better and announce about it. */
       new Float: winner = maxf(cscore,tscore)
       new Float: looser = minf(cscore,tscore)
       new Float: compratio = winner / looser

       /* Determine index of better team (with higher skill ratio). */
       e = (cscore > tscore) ? 1 : 0

       if ( compratio >= 6 ){
           blockjoining[  e  ]  =  PLUGIN_HANDLED /* Block joining to the
   better team. */
           transfer = e /* Save index of better them to switch from. */
           client_print(0,print_chat,"%s  team  beats  %s",  e  ?  "Ct" :
   "Terrorist", e ? "Terrorists" : "Cts" )
       }
       else if ( compratio >= 4 ){
           blockjoining[  e  ]  =  PLUGIN_HANDLED /* Block joining to the
   better team. */
           transfer  =  e    /* Save index of better them to switch from.
   */
           client_print(0,print_chat,"%s    team   seems   to   be   more
   powerful",e ? "Ct" : "Terrorist" )
       }
       else if ( compratio >= 2 ){
           blockjoining[  e ] = PLUGIN_HANDLED    /* Block joining to the
   better team. */
           client_print(0,print_chat,"%s  team  is  slightly  better",e ?
   "Ct" : "Terrorist" )
       }
       else{
           /*Sometimes  there  is  a  situation that team is balanced but
   there are different
                 numbers  of  players  in each team. If the difference is
   higher then 1 then transfer someone.
                 NOTE:  That  this  condition  will  be  never  true  for
   mp_limitteams 2.0 (this is now, however
                we will leave it for possibly future modifications.)

                 e.g,  T 6 -- CT 2, the difference is 4 then get the best
   from T and worst from CT
                and transfor them. Yes it won't balance them but make one
   team a bit better than
                 second,  ppl  tend to switch the team following with the
   best. If team is to
                 powerful  they  won't  unbalance  team  more due to team
   switching block :)
           */
           if (  absn(playersnum[0] - playersnum[1]) > 1 )
               transfer = (playersnum[0] > playersnum[1]) ? 0 : 1
           client_print(0,print_chat,"Teams are balanced. Terrorists have
   %d and Cts %d good player(s)",goodnum[0],goodnum[1])
       }

       /* Build list of best players for each team and display them. */
       new list[256], name[32]
       c = goodnum[0]
       b = 0
       for(a=0;a<c;++a)    { // TERRORIST
           d = goodlist[0][a]
           get_user_name(d,name,31)
           b += format(list[b],255-b,"%s, ",name )
       }
       if (c) {
           list[b-2] = 0 // remove ", " from after last name
           client_print(0,print_chat,"In      Terrorists     good     %s:
   %s",(c==1)?"is":"are",list)
       }
       c = goodnum[1]
       b = 0
       for(a=0;a<c;++a)    { // CT
           d = goodlist[1][a]
           get_user_name(d,name,31)
           b += format(list[b],255-b,"%s, ",name )
       }
       if (c) {
           list[b-2] = 0
           client_print(0,print_chat,"In        Cts        good       %s:
   %s",(c==1)?"is":"are",list)
       }

       /* if there is need to switch someone then determine
       best and worst then switch them. */
       if (transfer != -1){
           new baplayer[2], woplayer[2]
           new Float:bestalive[2]
           new Float:worstalive[2]
           baplayer[0] = baplayer[1] = 0
           woplayer[0] = woplayer[1] = 0
           bestalive[0] = bestalive[1] = 0.0
           worstalive[0] = worstalive[1] = 100.0
           for(a=0;a<ippl;++a){ /* For each player. */
               b = ppl[a]
               c  = teams[b] /* The team index will put results to proper
   place. */
               if (c!=0&&c!=1) continue        // Spectator
               if (is_user_alive(b)) continue
               if (bestalive[c] < ppower[b]){ // Get best dead player
                   bestalive[c] = ppower[b]
                   baplayer[c] = b
               }
               if (worstalive[c] > ppower[b]){ // Get worst dead player
                   worstalive[c] = ppower[b]
                   woplayer[c] = b
               }
           }
           /* Get the oposite index of team for worst player to transfer.
   */
           new optransfer = transfer ? 0 : 1
           /*  If  there  is need for transfering the players then switch
   them. */
           if (baplayer[transfer] && woplayer[optransfer] ){
               if (playersnum[transfer] > 1) // if has more than 1 player
   then you may transfer him
                   transfer_player(baplayer[transfer],transfer  ?  "1"  :
   "2" )
               if  (playersnum[optransfer]  >  1)  //  if has more than 1
   player then you may transfer him
                   transfer_player(woplayer[optransfer], optransfer ? "1"
   : "2" )
           }
       }
   }
   transfer_player(id,key[]){
       new oldone[2]
       oldone[0] = blockjoining[ 0 ]
       oldone[1] = blockjoining[ 1 ]
       blockjoining[ 0 ] = blockjoining[ 1 ] = PLUGIN_CONTINUE
       //set_cvar_float("mp_limitteams",0.0)
       engclient_cmd(id,"chooseteam")
       engclient_cmd(id,"menuselect",key)
       engclient_cmd(id,"menuselect","5")
       client_print(id,print_center,"You   have  been  moved  to  another
   team.")
       client_cmd(id,"slot10")
       //set_cvar_float("mp_limitteams",2.0)
       blockjoining[ 0 ] = oldone[0]
       blockjoining[ 1 ] = oldone[1]
   }
   public team_score() {
       set_cvar_float("mp_autoteambalance",0.0)
       set_cvar_float("mp_limitteams",0.0)
       new tid[2]
       read_data(1,tid,1)
       scores[ (tid[0]=='C') ? 1 : 0 ] = read_data(2)
       if ((endscore = !endscore))// Round end
           set_task(1.0,"calculate_power")
   }
   public team_select(id, key){
       if ( blockjoining[ key ] == PLUGIN_HANDLED ){
           client_print(id,print_center,"Teams  are not balanced.^nPlease
   join to the opposite side.")
           engclient_cmd(id,"chooseteam")
           return PLUGIN_HANDLED
       }
       return PLUGIN_CONTINUE
   }
   public plugin_init() {
       register_plugin("Simple Team Balancer","0.5","default")
       register_event("TeamScore","team_score","a")
       register_menucmd(register_menuid("Team_Select"),(1<<0)|(1<<1),"tea
   m_select")
       register_menucmd(-2,(1<<0)|(1<<1),"team_select")    // VGUI menu
       return PLUGIN_CONTINUE
   }
