This is a mixture of different TeamBalancers which i try to make usefull:
Code:
// ttb.sma
//
// TJAs Team Balancer
//
#include <amxmod>
#include <amxmisc>
new TTB_VERSION[] = "0.93"
#define MAX_PLAYERS 32
#define FREQ_TEAM_CHECK 1.0
#define UNASSIGNED 0
#define TS 1
#define CTS 2
#define AUTO_TEAM 5
new teamScore[3] // teamScore
new playerNumber[3] // number of players
new Float:teamKillDeath[3] // sum of Kills-Deaths Ratios
new teamName[3][] = { "Spectator", "TS", "CTS" }
new lastWinner
new lastLooser
new winStreak // number of successive wins
new bool:isBeingTransfered[MAX_PLAYERS+1]
new playerTeam[MAX_PLAYERS+1]
new lastRoundSwitched[MAX_PLAYERS+1]
new kills[MAX_PLAYERS+1]
new deaths[MAX_PLAYERS+1]
new Float:KillDeathRatio[MAX_PLAYERS+1]
new roundNumber
new lastRoundTB
Float:fabs(Float:n)
return ( n < 0.0 ) ? -n : n
public plugin_init(){
register_plugin("Team Balancer",TTB_VERSION,"[Murka] TJA")
register_cvar("amx_ttb_version",TTB_VERSION,FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_UNLOGGED|FCVAR_SPONLY)
register_event("SendAudio","round_end","a","2=%!MRAD_terwin","2=%!MRAD_ctwin","2=%!MRAD_rounddraw") // Round End
register_event("RoundTime", "new_round", "bc") // Round Time
register_event("TextMsg","game_restart","a","1=4","2&#Game_C","2&#Game_w") // Game restart
register_event("DeathMsg","death_msg","a") // Kill
register_event("TeamScore","team_score","a") // Team teamScore
set_task(FREQ_TEAM_CHECK, "check_teamcompos")
return PLUGIN_CONTINUE
}
public game_restart(){
roundNumber = 0
lastRoundTB = 0
teamScore[0] = teamScore[1] = teamScore[2] = 0
lastWinner = UNASSIGNED
lastLooser = UNASSIGNED
winStreak = 0
for (new i = 1; i <= MAX_PLAYERS; ++i){
kills[i] = 0
deaths[i] = 0
lastRoundSwitched[i] = -999
}
}
public new_round() {
if ( floatround(get_cvar_float("mp_roundtime") * 60.0) != read_data(1) ) return
++roundNumber
init_KillDeathRatio()
new msg[128]
if (lastWinner == CTS) {
format(msg, 127, "Round %d - CTS %d TS %d^nBalance: %.2f - %.2f^nWin-Streak CTs: %d", roundNumber, teamScore[CTS], teamScore[TS], teamKillDeath[CTS], teamKillDeath[TS], winStreak)
}
if (lastWinner == TS) {
format(msg, 127, "Round %d - CTS %d TS %d^nBalance: %.2f - %.2f^nWin-Streak Ts: %d", roundNumber, teamScore[CTS], teamScore[TS], teamKillDeath[CTS], teamKillDeath[TS], winStreak)
}
set_hudmessage(255, 255, 255, 0.45, 0.35, 0, 6.0, 10.0 , 0.5, 0.15, 2)
show_hudmessage( 0, msg )
server_print("[TTB] Round %d - CTS %d TS %d", roundNumber, teamScore[CTS], teamScore[TS])
server_print("[TTB] Balance: %.2f - %.2f", teamKillDeath[CTS], teamKillDeath[TS])
if (lastWinner == CTS) {
server_print("[TTB] Win-Streak CTs: %d", winStreak)
}
if (lastWinner == TS) {
server_print("[TTB] Win-Streak Ts: %d", winStreak)
}
}
public round_end(){
new param[12]
read_data(2,param,8)
if (param[7]=='c') {//%!MRAD_ctwin
if (lastWinner==CTS)
winStreak++
else {
lastWinner=CTS;
lastLooser=TS;
winStreak=1;
}
}
else if (param[7]=='t') {//%!MRAD_terwin
if (lastWinner==TS)
winStreak++
else {
lastWinner=TS;
lastLooser=CTS;
winStreak=1;
}
}
else
return // %!MRAD_rounddraw (both teams have left the game)
set_task(1.0,"round_end_tb")
}
public death_msg(){
new iWinner = read_data(1)
new iLoser = read_data(2)
if ( iWinner < 1 || iWinner > MAX_PLAYERS || iLoser < 1 || iLoser > MAX_PLAYERS )
return
if ( get_user_team(iWinner) == get_user_team(iLoser) )
return // no TKS!!!
kills[iWinner]++
deaths[iLoser]++
}
public team_score(){
new arg[2]
read_data(1,arg,1)
teamScore[ ( arg[0] == 'T' ) ? TS : CTS ] = read_data(2)
}
public client_authorized(id){
kills[id] = 0
deaths[id] = 0
KillDeathRatio[id] = 1.0
isBeingTransfered[id] = false
playerTeam[id] = UNASSIGNED
playerNumber[UNASSIGNED]++
lastRoundSwitched[id] = -999
return PLUGIN_CONTINUE
}
public client_disconnect(id) {
kills[id] = 0
deaths[id] = 0
KillDeathRatio[id] = 1.0
isBeingTransfered[id] = false
playerTeam[id] = UNASSIGNED
lastRoundSwitched[id] = -999
set_teams()
return PLUGIN_CONTINUE
}
public set_teams()
{
playerNumber[UNASSIGNED] = 0
playerNumber[CTS] = 0
playerNumber[TS] = 0
for (new i = 1; i <= MAX_PLAYERS; ++i) {
playerTeam[i] = UNASSIGNED
}
new inum
new players[MAX_PLAYERS]
get_players(players, inum)
for (new a = 0; a <inum; a++)
{
new i=players[a]
playerTeam[i] = get_user_team(i)
++playerNumber[playerTeam[i]]
}
}
public check_teamcompos(parm[])
{
new inum
new players[MAX_PLAYERS]
get_players(players, inum)
for (new a = 0; a <inum; a++)
{
new i = players[a]
new t = get_user_team(i)
if (playerTeam[i] != t)
{
++playerNumber[t]
--playerNumber[playerTeam[i]]
playerTeam[i] = t
}
}
set_task(FREQ_TEAM_CHECK, "check_teamcompos")
}
public transferPlayer(id, team)
{
new parm[4]
parm[0] = id
parm[1] = team
parm[2] = roundNumber
parm[3] = 0 // number of tries
isBeingTransfered[id] = true
engclient_cmd(id,"chooseteam")
engclient_cmd(id, "menuselect", team==1 ? "1" : "2" )
engclient_cmd(id, "menuselect", "5")
client_cmd(id,"slot1")
set_task(3.0, "check_transfer", 0, parm, 4)
}
public check_transfer(parm[4])
{
new name[32]
get_user_name(parm[0], name, 31)
if (get_user_team(parm[0]) == parm[1])
{
isBeingTransfered[parm[0]] = false
lastRoundSwitched[parm[0]] = roundNumber
lastRoundTB = roundNumber
client_print(0, print_chat, "[TTB] successfuly transfered %s to %s!", name, teamName[parm[1]])
server_print("[TTB] successfuly transfered %s to %s!", name, teamName[parm[1]])
return
}
parm[3]++
if (parm[3]>=2) {
client_print(0, print_chat, "[TTB] did'nt managed to transfer %s to %s after 2 tries!", name, teamName[parm[1]])
server_print("[TTB] did'nt managed to transfer %s to %s after 2 tries!", name, teamName[parm[1]])
isBeingTransfered[parm[0]] = false
return
}
if ( (roundNumber<parm[2]) || (roundNumber-parm[2]>1) ) {
client_print(0, print_chat, "[TTB] did'nt managed to transfer %s to %s in less than one round!", name, teamName[parm[1]])
server_print("[TTB] did'nt managed to transfer %s to %s in less than one round!", name, teamName[parm[1]])
isBeingTransfered[parm[0]] = false
return
}
client_print(0, print_chat, "[TTB] tries to transfer %s to %s (%d)!", name, teamName[parm[1]], parm[3])
server_print("[TTB] tries to transfer %s to %s (%d)!", name, teamName[parm[1]], parm[3])
engclient_cmd(parm[0],"chooseteam")
new id = parm[0]
new team = parm[1]
engclient_cmd(id, "menuselect", team==1 ? "1" : "2" )
engclient_cmd(id, "menuselect", "5")
client_cmd(id,"slot1")
set_task(3.0, "check_transfer", 0, parm, 4)
}
public sqrt(num) {
new div = num
new result = 1
while (div > result) {
div = (div + result) / 2
result = num / div
}
return div
}
public init_KillDeathRatio()
{
teamKillDeath[UNASSIGNED] = 0.0
teamKillDeath[CTS] = 0.0
teamKillDeath[TS] = 0.0
for (new i = 1; i <= MAX_PLAYERS; ++i)
{
KillDeathRatio[i] = float(kills[i]+1) / float(deaths[i]+1) + 1.0
teamKillDeath[playerTeam[i]] += KillDeathRatio[i]
}
}
public round_end_tb()
{
set_teams()
init_KillDeathRatio()
new pCT, pT
new nameCT[32], nameT[32]
init_KillDeathRatio()
new msg[128]
if (lastWinner == CTS) {
format(msg, 127, "Round %d - CTS %d TS %d^nBalance: %.2f - %.2f^nWin-Streak CTs: %d", roundNumber, teamScore[CTS], teamScore[TS], teamKillDeath[CTS], teamKillDeath[TS], winStreak)
}
if (lastWinner == TS) {
format(msg, 127, "Round %d - CTS %d TS %d^nBalance: %.2f - %.2f^nWin-Streak Ts: %d", roundNumber, teamScore[CTS], teamScore[TS], teamKillDeath[CTS], teamKillDeath[TS], winStreak)
}
set_hudmessage(200, 200, 200, 0.45, 0.35, 0, 6.0, 5.0 , 0.5, 0.5, 2)
show_hudmessage( 0, msg )
server_print("[TTB] Round %d - CTS %d TS %d", roundNumber, teamScore[CTS], teamScore[TS])
server_print("[TTB] Balance: %.2f - %.2f", teamKillDeath[CTS], teamKillDeath[TS])
if (lastWinner == CTS) {
server_print("[TTB] Win-Streak CTs: %d", winStreak)
}
if (lastWinner == TS) {
server_print("[TTB] Win-Streak Ts: %d", winStreak)
}
if ( ((winStreak>=3) && (roundNumber-lastRoundTB>=2)) || (winStreak>=5) || (teamKillDeath[lastWinner] / teamKillDeath[lastLooser] >= 2.0) || (teamKillDeath[lastWinner] - teamKillDeath[lastLooser] >= 10.0) )
{
client_print(0, print_chat, "[TTB] TEAMS need to be balanced!")
server_print("[TTB] TEAMS need to be balanced!")
if (lastWinner==CTS) {
pCT = searchBestTransfer(CTS, 1)
if (pCT!=0)
{
get_user_name(pCT, nameCT, 31)
//client_print(0, print_chat, "[TTB] Transfering %s to the Terrorists!", nameCT)
server_print("[TTB] Transfering %s to the Terrorists!", nameCT)
transferPlayer(pCT, TS)
}
}
if (lastWinner==TS) {
pT = searchBestTransfer(TS, 1)
if (pT!=0)
{
get_user_name(pT, nameT, 31)
//client_print(0, print_chat, "[TTB] Transfering %s to the Counter-Terrorists!", nameT)
server_print("[TTB] Transfering %s to the Counter-Terrorists!", nameT)
transferPlayer(pT, CTS)
}
}
}
}
public searchBestTransfer(team, deadonly)
{
new oteam = 3-team
if (playerNumber[oteam]==0)
{
new Float:bestKDR=0.0, p=0
for(new i=1; i<=MAX_PLAYERS; i++)
{
if ((playerTeam[i]==team)&&(KillDeathRatio[i]>bestKDR))
{
bestKDR = KillDeathRatio[i]
p=i
}
}
server_print("[TTB] Created opposing team: %d", p)
return p
}
new Float:bestBalance = fabs( teamKillDeath[CTS] / playerNumber[TS] - teamKillDeath[TS] / playerNumber[CTS] )
new p = 0
new divTeam = playerNumber[oteam] + 1, divOTeam = playerNumber[team] - 1
for (new i=1; i <= MAX_PLAYERS; i++) {
if ( (playerTeam[i] == team) && (roundNumber - lastRoundSwitched[i] > 10) && ((deadonly + is_user_alive(i)) != 2) )
{
new Float:b = fabs( (teamKillDeath[team] + winStreak - KillDeathRatio[i]) / divTeam - (teamKillDeath[oteam] + KillDeathRatio[i]) / divOTeam )
new name[32]
get_user_name(i, name, 31)
if (b < bestBalance ) {
bestBalance = b
p = i
}
}
}
return p
}
Welcome to the AMX Mod X 1.00-272 Compiler.
amxxsc: sc3.c:835: int hier14(value *): Assertion `lval3.arrayidx==arrayidx1' failed.