/* AMX Mod script.
*
* (c) Copyright 2002, OLO
* This file is provided as is (no warranties).
*
*/
#include <amxmod>
#include <csstats>
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
new name[32], stats[8], body[8]
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 = c // save what index of team the player has
if (c!=0&&c!=1) continue // Spectator
get_user_wstats(b,0,stats,body)
frags = float(stats[0])
deaths = float(stats[1])
tempf = (frags / (deaths ? deaths : 1.0)) + (frags * 0.15)
ppower = 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
if (c!=0&&c!=1) continue // Spectator
if ( ppower > 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 >= 5 ){
blockjoining[ e ] = PLUGIN_HANDLED /* Block joining to the better team. */
transfer = 1 /* 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 >= 3 ){
blockjoining[ e ] = PLUGIN_HANDLED /* Block joining to the better team. */
transfer = 1 /* 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 >= 1.5 ){
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 balanced. T 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]
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,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,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 ( (goodnum[1]-goodnum[0])>=4 && ( (scores[1] - scores[0]) >= 3 ) )
{
transfer = 1
}
else if( (goodnum[0]-goodnum[1])>=4 && ( (scores[0] - scores[1]) >= 3) )
{
transfer = 0
}
else if ( ( (scores[0] - scores[1]) >=4 ) && (playersnum[0] > playersnum[1]) )
{
transfer = 0
}
else if ( ( (scores[1] - scores[0]) >=4 ) && (playersnum[1] > playersnum[0]) )
{
transfer = 1
}
else
{
transfer = -1
}
client_print(0,print_chat,"transfer is %i",transfer)
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 /* 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){ // Get best dead player
bestalive[c] = ppower
baplayer[c] = b
}
if (worstalive[c] > ppower){ // Get worst dead player
worstalive[c] = ppower
woplayer[c] = b
}
}
new optransfer = transfer ? 0 : 1
if (baplayer[transfer] && woplayer[optransfer] ){
client_print(0,print_chat,"transfer best %i",baplayer[transfer])
client_print(0,print_chat,"transfer worst %i",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() {
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){
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),"team_select")
register_menucmd(-2,(1<<0)|(1<<1),"team_select") // VGUI menu
return PLUGIN_CONTINUE
} |