Jump to content
GIGN Forum

Recommended Posts

Luuk kods vai varetu kads pateikt ko tieshi te janomaina

#include <amxmodx>

#include <amxmisc>

#include <cstrike>

// Change admin protection flag here

#define ADMIN_PROTECT_PTB ADMIN_IMMUNITY // admin flag b

// Change admin access flag here

#define ACCESS_PTB ADMIN_RCON

// team ids

#define UNASSIGNED 0

#define TS 1

#define CTS 2

#define AUTO_TEAM 5

new const PTB_VERSION[] = "1.7b9.2"

// Uncomment to activate log debug messages.

//#define PTB_DEBUG

// team selection control

new bool:PTB_LIMITJOIN = true // set limits on team joining

new PTB_LIMITAFTER = 0 // number of rounds after which teams limiting begins

new PTB_LIMITMIN = 0 // number of minimum players on map for team limiting

new PTB_MAXSIZE = 10 // maximum team size per team

new PTB_MAXDIFF = 2 // maximum team size difference

new PTB_AUTOROUNDS = 3 // number of first rounds into match, which allow autojoin only

new PTB_WTJAUTO = 3 // wtj tries needed to become autojoined

new PTB_WTJKICK = 5 // wtj tries needed to become kicked

new bool:PTB_KICK = true // kick for wtj counts

new bool:PTB_SAVEWTJ = false // save wtjs to wtj.log

// team balancing actions

new bool:PTB_SWITCH = true // switch/transfer players

new PTB_SWITCHAFTER = 0 // number of rounds after which switching begins

new PTB_SWITCHMIN = 3 // number of minimum players on map for switching

new PTB_SWITCHFREQ = 1 // relative next possible switch round

new PTB_PLAYERFREQ = 3 // relative next possible switch round for player

new PTB_FORCESWITCH = 3 // number of tries after which PTB switches alive, if neccessary

new bool:PTB_DEADONLY = false // switch dead only

// messages

new bool:PTB_TELLWTJ = true // tell about wtj tries

new bool:PTB_ANNOUNCE = true // announce team status at beginning of round

new bool:PTB_SAYOK = true // announce team status, if teams are alright

new bool:PTB_TYPESAY = true // use typesay

// team strength limits

new PTB_MAXSTREAK = 2 // max. allowed team win streak

new PTB_MAXSCORE = 2 // max. allowed team score difference

new Float:PTB_MINRATING = 1.5 // minimum critical team rating

new Float:PTB_MAXRATING = 2.0 // maximum critical team rating

new Float:PTB_SUPERRATING = 3.0 // super critical team rating

new PTB_MAXINCIDENTS = 50 // maximum kills + deaths before the score is divided by PTB_SCALEDOWN

new PTB_SCALEDOWN = 2 // divisor for kills and deaths, when PTB_MAXINCIDENTS is reached

// sorted player indices are 0-based

new sortedTeams[3][32]

new sortedValidTargets[3][32]

new validTargetCounts[3]

new teamKills[3]

new teamDeaths[3]

new teamScores[3]

new winStreaks[3]

new wtConditions[3]

new winnerTeam

new loserTeam

new Float:ctKD

new Float:tKD

new Float:ctStrength

new Float:tStrength

new Float:ctRating

new Float:tRating

// player arrays are 1-based, there is no player 0

new clientVGUIMenu[33][2]

new bool:isBeingTransfered[33]

new playerTeam[33]

new lastRoundSwitched[33]

new wtjCount[33]

new teamCounts[3]

new kills[33]

new deaths[33]

new roundCounter

new lastSwitchRound

new couldNotSwitchCounter

new lastTeamBalanceCheck[32]

public plugin_init(){

register_plugin("Team Balancer",PTB_VERSION,"Ptahhotep")

register_cvar("amx_ptb_version",PTB_VERSION,FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_UNLOGGED|FCVAR_SPONLY)

register_cvar("ptb_saychat", "1")

register_cvar("ptb_transfer_type", "1")

register_menucmd(register_menuid("Team_Select",1),(1<<0)|(1<<1)|(1<<4),"teamselect")

register_event("ShowMenu","menuclass","b","4&CT_Select","4&Terrorist_Select")

register_clcmd("jointeam","jointeam")

register_clcmd("team_join","team_join")

#if defined PTB_DEBUG

register_clcmd("say /last","check_lasttransfer")

#endif

register_event("SendAudio","round_end","a","2=%!MRAD_terwin","2=%!MRAD_ctwin","2=%!MRAD_rounddraw") // Round End

register_event("TeamScore","team_score","a") // Team Score

register_event("RoundTime", "new_round", "bc") // Round Time

register_event("DeathMsg","death_msg","a") // Kill

register_event("TeamInfo","team_assign","a") // Team Assigment (also UNASSIGNED and SPECTATOR)

register_event("TextMsg","team_join","a","1=1","2&Game_join_te","2&Game_join_ct") // Team Joining

register_event("TextMsg","game_restart","a","1=4","2Game_C","2Game_w") // Game restart

register_concmd("amx_ptb","admin_ptb",ACCESS_PTB,"- displays PTB options")

new configsDir[64]

get_configsdir(configsDir, 63)

server_cmd("exec %s/ptb/ptb.cfg", configsDir) // Execute main configuration file

// Init clients VGUI-menu setting

// Set terminating 0 to allow use of char processing instead of string

// to improve performance.

for (new i=0;i<33;i++){

clientVGUIMenu[0] = '0'

clientVGUIMenu[1] = 0

}

return PLUGIN_CONTINUE

}

Float:fabs(Float:n)

return ( n < 0.0 ) ? -n : n

Float:fdivWorkaround(Float:nom, Float:denom){

if ( denom == 0.0) return nom

return fabs(nom / denom)

}

doTypesay(string[], duration, r, g, B) {

if (!PTB_TYPESAY) return

set_hudmessage(r, g, b, 0.05, 0.25, 0, 6.0, float(duration) , 0.5, 0.15, 2)

show_hudmessage(0, string )

}

say(string[]){

if(get_cvar_num("ptb_saychat") == 1 || get_cvar_num("ptb_saychat") == 3){

client_print(0,print_chat,string)

server_print(string)

}

}

bool:check_param_bool(param[])

return (equali(param, "on") || equal(param, "1")) ? true : false

Float:check_param_float(param[],Float:n){

new Float:a = floatstr(param)

if (a < n) a = n

return a

}

check_param_num(param[],n){

new a = str_to_num(param)

if (a < n) a = n

return a

}

transferPlayer(id){

if (isBeingTransfered[id]) return

isBeingTransfered[id] = false

new name[32]

get_user_name(id,name,31)

cs_set_user_team(id, (playerTeam[id]==TS) ? 2 : 1)

cs_reset_user_model(id)

// This must be done here or lastroundswithed will not be registered

lastRoundSwitched[id] = roundCounter

// This makes you able to see transfers with HLSW in the chat

log_message("^"<><><>^" triggered ^"amx_chat^" (text ^"[PTB] Transfered %s to %s^")",

name, (playerTeam[id]==TS) ? "CT" : "TERRORIST" )

#if defined PTB_DEBUG

log_amx("Transfer player: %s lastRoundSwitched[id]: %i roundCounter:%i", name, lastRoundSwitched[id], roundCounter)

client_print(0,print_chat,"Transfer player: %s lastRoundSwitched[id]: %i roundCounter:%i", name, lastRoundSwitched[id], roundCounter)

#endif

}

#if defined PTB_DEBUG

public check_lasttransfer(id) {

new lasttransfer, text[255]

lasttransfer = lastRoundSwitched[id]

format(text,255,"LastRound transfered: %i", lasttransfer)

say(text)

}

#endif

actAtEndOfRound(){

if (!PTB_SWITCH) return

// skip switching for the first few rounds

if (roundCounter <= PTB_SWITCHAFTER) return

// honor switch frequency setting

if (roundCounter - lastSwitchRound < PTB_SWITCHFREQ) return

// skip switching for a small number of players

if (get_playersnum() < PTB_SWITCHMIN) return

say("PTB: Round ended, checking teams.")

checkTeamBalance()

if (winnerTeam) {

sortTeam(CTS)

sortTeam(TS)

// If they set the cvar(ptb_transfer_type) 1 or less than 2 or bigger than 3

// then standard transfers will be selected

if(get_cvar_num("ptb_transfer_type") < 2 || get_cvar_num("ptb_agressive_transfer") > 3){

// This is the standard if it should be a swith of to players or just one transfer

if (teamCounts[winnerTeam] <= teamCounts[loserTeam]) // Original formula

doSwitch()

else if (teamCounts[loserTeam] < teamCounts[winnerTeam]) // Original formula

doTransfer()

}

if(get_cvar_num("ptb_transfer_type") == 2){

// This is more agressive but not so much as the one below

if (teamCounts[winnerTeam] < teamCounts[loserTeam])

doSwitch()

else if (teamCounts[loserTeam] <= teamCounts[winnerTeam])

doTransfer()

}

if(get_cvar_num("ptb_transfer_type") == 3){

// This is the most agressive transfertype

if ((teamCounts[winnerTeam]+(PTB_MAXDIFF/2)) < teamCounts[loserTeam])

doSwitch()

else if (teamCounts[loserTeam] <= (teamCounts[winnerTeam]+(PTB_MAXDIFF/2)))

doTransfer()

}

}

}

createValidTargets(theTeam, bool:deadonly) {

new n = 0

for (new i = 0; i < teamCounts[theTeam]; ++i) {

// Protection for admins

if (get_user_flags(sortedTeams[theTeam]) & ADMIN_PROTECT_PTB) continue

// Dead only condition

if ( deadonly && is_user_alive(sortedTeams[theTeam]) ) continue

// Already switched or in PTB_PLAYERFREQ time condition

if ((lastRoundSwitched[sortedTeams[theTeam]] == roundCounter) ||

(roundCounter - lastRoundSwitched[sortedTeams[theTeam]] < PTB_PLAYERFREQ)) continue

sortedValidTargets[theTeam][n++] = sortedTeams[theTeam]

}

validTargetCounts[theTeam] = n

}

sortTeam(theTeam) {

// create list of players

new n = 0, a = get_maxplayers()

for (new i = 1; i <= a; ++i) {

// Get only members of specified team

if (playerTeam != theTeam) continue

sortedTeams[theTeam][n++] = i

}

// do a selection sort

new swap, count = n

for (new i = count-1; i > 0; --i){

for (new k = i-1; k >= 0; --k){

// compare players (kills better then other or if equal then with less deaths)

if ( (kills[sortedTeams[theTeam][k]]<kills[sortedTeams[theTeam]])

|| ( (kills[sortedTeams[theTeam][k]]==kills[sortedTeams[theTeam]]) &&

(deaths[sortedTeams[theTeam][k]]>deaths[sortedTeams[theTeam]]))) {

// swap

swap = sortedTeams[theTeam][k]

sortedTeams[theTeam][k] = sortedTeams[theTeam]

sortedTeams[theTeam] = swap

}

}

}

}

Float:score(team, toBeAdded=0, toBeRemoved=0){

new Float:sumKD = 0.0

new a = get_maxplayers()

for (new i = 1; i <= a; ++i) {

if ( (playerTeam!=team&&i!=toBeAdded) || (i==toBeRemoved) )

continue

sumKD += fdivWorkaround(float(kills), float(deaths))

}

new Float:strength = float(teamCounts[team])

if (sumKD) strength *= sumKD

return strength

}

doSwitch() {

new text[256]

//displayStatistics(0,true)

// don't switch, if at least one team is empty

if ( teamCounts[winnerTeam] == 0 || teamCounts[loserTeam] == 0 ) {

copy(text,255, "PTB: Can't switch players, need players in each team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

// don't switch, if winner is alone (RULER!!!)

if (teamCounts[winnerTeam] == 1) {

copy(text,255, "PTB: Won't switch players, best player makes the winning team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

// don't switch, if both teams are full

if (teamCounts[winnerTeam] >= PTB_MAXSIZE && teamCounts[loserTeam] >= PTB_MAXSIZE) {

copy(text,255, "PTB: Can't switch players, both teams are full.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

if (!PTB_DEADONLY || couldNotSwitchCounter > PTB_FORCESWITCH) {

// choose from random top or bottom x

createValidTargets(winnerTeam, false)

createValidTargets(loserTeam, false)

if (validTargetCounts[winnerTeam] == 0 || validTargetCounts[loserTeam] == 0) {

++couldNotSwitchCounter

copy(text,255, "PTB: Can't switch players, need valid target in each team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

}

else {

//say("switch dead")

createValidTargets(winnerTeam, true)

createValidTargets(loserTeam, true)

if (validTargetCounts[winnerTeam] == 0 || validTargetCounts[loserTeam] == 0) {

if (++couldNotSwitchCounter > PTB_FORCESWITCH) {

say("PTB: Couldn't switch dead, switching alive.")

doSwitch()

return

}

copy(text, 255,"PTB: Can't switch players, need valid target in each team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

}

// Now search through the possible 1 to 1 swaps to equalize the strength as much as possible

new Float:closestScore = fabs(score(winnerTeam) - score(loserTeam))

new Float:myScore, toLoser, toWinner

new winner = 0

new loser = 0

for (new w = 0; w < validTargetCounts[winnerTeam]; ++w) {

toLoser = sortedValidTargets[winnerTeam][w]

for (new l = 0; l < validTargetCounts[loserTeam]; ++l) {

toWinner = sortedValidTargets[loserTeam][l]

myScore = fabs(score(winnerTeam, toWinner, toLoser) - score(loserTeam, toLoser, toWinner))

if (myScore < closestScore) {

closestScore = myScore

winner = toLoser

loser = toWinner

}

}

}

if (winner == 0 && loser == 0) {

copy(text, 255,"PTB: No switch would improve team balancing.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

couldNotSwitchCounter = 0

lastSwitchRound = roundCounter

new winnerName[32], loserName[32]

get_user_name(winner,winnerName,31)

get_user_name(loser,loserName,31)

// if one team is full, first move the the player from the full team ...

if (teamCounts[winnerTeam] >= PTB_MAXSIZE){

transferPlayer(winner)

transferPlayer(loser)

}

else {

transferPlayer(loser)

transferPlayer(winner)

}

format(text,255,"PTB: Switching %s with %s.",winnerName,loserName)

if(get_cvar_num("ptb_saychat") == 2 || get_cvar_num("ptb_saychat") == 3){

//say(text)

set_hudmessage(0, 255, 0, 0.05, 0.25, 0, 6.0, 5.0 , 0.5, 0.15, 2)

show_hudmessage(0, text )

client_print(0,print_chat,"PTB: Switching %s with %s.",winnerName,loserName)

}else{

doTypesay(text, 5, 0, 255, 0)

}

}

doTransfer() {

//displayStatistics(0,true)

new text[256]

if (teamCounts[winnerTeam] == 0) {

copy(text,255, "PTB: Can't switch players, need players in each team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

if (teamCounts[loserTeam] >= PTB_MAXSIZE) {

copy(text,255, "PTB: Can't transfer player, losing team is full.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

if (!PTB_DEADONLY || couldNotSwitchCounter > PTB_FORCESWITCH) {

createValidTargets(winnerTeam, false)

if (validTargetCounts[winnerTeam] == 0) {

copy(text,255, "PTB: Can't transfer player, no valid target in winning team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

++couldNotSwitchCounter

return

}

}

else {

//say("switch dead")

createValidTargets(winnerTeam, true)

if (validTargetCounts[winnerTeam] == 0) {

if (++couldNotSwitchCounter > PTB_FORCESWITCH) {

say("PTB: Couldn't transfer dead, transferring alive.")

doTransfer()

return

}

copy(text,255, "PTB: Can't transfer player, no valid target in winning team.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

}

new Float:closestScore = fabs(score(winnerTeam) - score(loserTeam))

new Float:myScore, toLoser

new winner = 0

for (new w = 0; w < validTargetCounts[winnerTeam]; ++w) {

toLoser = sortedValidTargets[winnerTeam][w]

myScore = fabs(score(winnerTeam, 0, toLoser) - score(loserTeam, toLoser, 0))

if (myScore < closestScore) {

closestScore = myScore

winner = toLoser

}

}

if (winner == 0) {

copy(text, 255,"PTB: No transfer would improve team balancing.")

doTypesay(text, 5, 0, 255, 0)

say(text)

return

}

couldNotSwitchCounter = 0

new winnerName[32]

get_user_name(winner,winnerName,31)

transferPlayer(winner)

format(text,255,"PTB: Transfering %s to the %s",winnerName, (winnerTeam == CTS) ? "Ts" : "CTs")

if(get_cvar_num("ptb_saychat") == 2 || get_cvar_num("ptb_saychat") == 3){

//say(text)

set_hudmessage(0, 255, 0, 0.05, 0.25, 0, 6.0, 5.0 , 0.5, 0.15, 2)

show_hudmessage(0, text )

client_print(0,print_chat,"PTB: Transfering %s to the %s",winnerName, (winnerTeam == CTS) ? "Ts" : "CTs")

}else{

doTypesay(text, 5, 0, 255, 0)

}

}

checkTeamBalance() {

get_time("%m/%d/%Y - %H:%M:%S",lastTeamBalanceCheck,31 )

calcTeamScores()

ctStrength = score(CTS)

tStrength = score(TS)

ctRating = fdivWorkaround(ctStrength, tStrength)

tRating = fdivWorkaround(tStrength, ctStrength)

wtConditions[TS] = 0

wtConditions[CTS] = 0

// compare scores for unequal rating scores

if (teamScores[TS] - teamScores[CTS] > PTB_MAXSCORE && tRating >= PTB_MINRATING)

wtConditions[TS]++

if (teamScores[CTS] - teamScores[TS] > PTB_MAXSCORE && ctRating >= PTB_MINRATING)

wtConditions[CTS]++

// check streaks for unequal rating scores

if (winStreaks[TS] > PTB_MAXSTREAK && tRating >= PTB_MINRATING)

wtConditions[TS]++

if (winStreaks[CTS] > PTB_MAXSTREAK && ctRating >= PTB_MINRATING)

wtConditions[CTS]++

// check ratings

if (tRating >= PTB_MAXRATING)

wtConditions[TS]++

if (ctRating >= PTB_MAXRATING)

wtConditions[CTS]++

// check ratings

if (tRating >= PTB_SUPERRATING)

wtConditions[TS]++

if (ctRating >= PTB_SUPERRATING)

wtConditions[CTS]++

// check team sizes for unequal ratings

if (teamCounts[TS] > teamCounts[CTS] && tRating >= PTB_MINRATING)

wtConditions[TS]++

if (teamCounts[CTS] > teamCounts[TS] && ctRating >= PTB_MINRATING)

wtConditions[CTS]++

// check conditions

if (wtConditions[TS] >= 2) {

winnerTeam = TS

loserTeam = CTS

}

else if (wtConditions[CTS] >= 2) {

winnerTeam = CTS

loserTeam = TS

}

else {

winnerTeam = 0

loserTeam = 0

}

}

manageWtjFile(id) {

if (!PTB_SAVEWTJ) return

//say("Trying to write wtj.log ....")

//if (wtjCount[id] < 4) return

//say("wtj.log should be written to now ....")

new text[256], stime[32], mapname[32], name[32], authid[32]

get_time("%m/%d/%Y - %H:%M:%S",stime,31 )

get_mapname(mapname,31)

get_user_name(id,name,31)

get_user_authid(id,authid,31)

format(text, 255, "%s %s <%s> %s", stime, name, authid, mapname)

new basedir[64]

get_basedir(basedir, 63)

format(basedir, 63, "%s/logs/custom/wtj.log", basedir)

write_file(basedir, text)

}

public menuclass(id) {

if (!isBeingTransfered[id]) return PLUGIN_CONTINUE

client_cmd(id,"slot1")

isBeingTransfered[id] = false

return PLUGIN_CONTINUE

}

public jointeam(id) {

new arg[2]

read_argv(1,arg,1)

if (isBeingTransfered[id]) return PLUGIN_HANDLED

return checkTeamSwitch(id,str_to_num(arg)) // team is key pressed + 1

}

public teamselect(id,key) {

return checkTeamSwitch(id,key+1) // team is key pressed + 1

}

checkTeamSwitch(id,iNewTeam) {

// don't care where player joins

if (!PTB_LIMITJOIN) return PLUGIN_CONTINUE

// Protection for admins

if (get_user_flags(id) & ADMIN_PROTECT_PTB) return PLUGIN_CONTINUE

// players is transfered so don't care with rest

if (isBeingTransfered[id]) {

//say("TRANSFER")

isBeingTransfered[id] = false

return PLUGIN_CONTINUE

}

//say("NO TRANSFER")

// skip limiting for a few rounds into the map

if (PTB_LIMITAFTER && roundCounter <= PTB_LIMITAFTER) return PLUGIN_CONTINUE

// skip limiting for a small number of players

if (get_playersnum() < PTB_LIMITMIN) return PLUGIN_CONTINUE

new iOldTeam = playerTeam[id]

// disallow free team choices in the first rounds of a map

if (PTB_AUTOROUNDS&&(iOldTeam==UNASSIGNED)&&roundCounter<=PTB_AUTOROUNDS)

iNewTeam = AUTO_TEAM

// prevent unwanted rejoining of the same team ...

if (iNewTeam == iOldTeam) {

//say("Preventing rejoining of the same team.")

client_print(id,print_chat,"PTB: Joining to the same team is not allowed...")

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

checkTeamBalance()

//displayStatistics(0,true)

// Player for sure was in CT or T team and now is joining to the opposite team

if ((iNewTeam==CTS&&iOldTeam==TS)||(iNewTeam==TS&&iOldTeam==CTS)){

// If someone is in new team and old team weren't full

// and the winning team is a destination team or in

// new team is more players than in old then treat it as wtj

if ( teamCounts[iNewTeam]&&(teamCounts[iOldTeam]<PTB_MAXSIZE)&&

((iNewTeam==winnerTeam)||(teamCounts[iNewTeam]>=teamCounts[iOldTeam])) ) {

// player is wtjing

new text[256],name[32]

get_user_name(id,name,31)

// Kick wtj player if reached set limit

if (++wtjCount[id] >= PTB_WTJKICK && PTB_KICK) {

format(text, 255, "PTB: Kicking %s for a WTJ count %d of %d.", name, wtjCount[id],PTB_WTJKICK )

doTypesay(text, 5, 0, 255, 0)

say(text)

server_cmd("kick #%d",get_user_userid(id))

return PLUGIN_HANDLED

}

// Announce about WTJ

if (PTB_TELLWTJ) {

if (iNewTeam == CTS) {

format(text, 255, "PTB: The CTs are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)

doTypesay(text, 5, 0, 50, 255)

}

else {

format(text, 255, "PTB: The Ts are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)

doTypesay(text, 5, 255, 50, 0)

}

say(text)

}

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

// check for maximum team size

if (teamCounts[iNewTeam] >= PTB_MAXSIZE) {

client_print(id,print_chat,"PTB: Maximum team size prohibits team change.")

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

// check team size difference limits

if ( teamCounts[iNewTeam]+1-teamCounts[iOldTeam] >= PTB_MAXDIFF ) {

client_print(id,print_chat,"PTB: Maximum team size difference prohibits team change.")

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

return PLUGIN_CONTINUE // OK! He can join to the oppsoite team!!!

}

// Player is choosing his team for the first time!

if (iNewTeam==CTS||iNewTeam==TS){

// Get opposite team

new opposingTeam = (iNewTeam==CTS)? TS : CTS

// Players is joining to one team but the opposite is not full

// and his team is bettter then opposite or has more players

if (teamCounts[iNewTeam] && teamCounts[opposingTeam]<PTB_MAXSIZE &&

(iNewTeam==winnerTeam||(!winnerTeam&&teamCounts[iNewTeam]>teamCounts[opposingTeam]))) {

new text[256],name[32]

get_user_name(id,name,31)

if (++wtjCount[id] >= PTB_WTJKICK && PTB_KICK) {

format(text, 255, "PTB: Kicking %s for a WTJ count %d of %d.", name, wtjCount[id],PTB_WTJKICK)

doTypesay(text, 5, 0, 255, 0)

say(text)

server_cmd("kick #%d", get_user_userid(id))

return PLUGIN_HANDLED

}

if (iNewTeam==CTS) {

if (wtjCount[id]>=PTB_WTJAUTO && is_user_connected(id)) {

manageWtjFile(id)

format(text, 255, "PTB: Forcing %s to the Ts (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)

engclient_cmd(id,"jointeam","1")

doTypesay(text, 5, 255, 50, 0)

say(text)

}

else if (PTB_TELLWTJ) {

format(text, 255, "PTB: The CTs are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)

doTypesay(text, 5, 0, 50, 255)

say(text)

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

}

}

else {

if (wtjCount[id]>=PTB_WTJAUTO) {

manageWtjFile(id)

format(text, 255, "PTB: Forcing %s to the CTs (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)

engclient_cmd(id,"jointeam","2")

doTypesay(text, 5, 0, 50, 255)

say(text)

}

else if (PTB_TELLWTJ) {

format(text, 255, "PTB: The Ts are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)

doTypesay(text, 5, 255, 50, 0)

say(text)

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

}

}

return PLUGIN_HANDLED

}

// check for maximum team size

if (teamCounts[iNewTeam] >= PTB_MAXSIZE) {

client_print(id,print_chat,"PTB: Maximum team size prohibits team join.")

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

// check team size difference limits

if ( teamCounts[iNewTeam]-teamCounts[opposingTeam] >= PTB_MAXDIFF) {

client_print(id,print_chat,"PTB: Maximum team size difference prohibits team join.")

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

return PLUGIN_CONTINUE // OK! He can join to the oppsoite team!!!

}

// He is choosing the AUTO-SELECT but he was already in game (He wants to play fair!)

if (iNewTeam==AUTO_TEAM&&(iOldTeam==CTS||iOldTeam==TS)) {

//say("Changing team automatically.")

new opposingTeam = (iOldTeam==CTS) ? TS : CTS

if (teamCounts[opposingTeam] && ( (teamCounts[opposingTeam]>=PTB_MAXSIZE)

|| (iOldTeam==loserTeam) || (!loserTeam&&teamCounts[iOldTeam]<=teamCounts[opposingTeam])

|| (teamCounts[opposingTeam]+1-teamCounts[iOldTeam]>=PTB_MAXDIFF)) ) {

client_print(id,print_chat,"PTB: You have better stay in your current team...")

return PLUGIN_HANDLED

}

client_print(id,print_chat,"PTB: You have been auto-assigned...")

engclient_cmd(id,"jointeam",(opposingTeam==CTS)?"2":"1")

return PLUGIN_HANDLED

}

// He is choosing the team for the first time with AUTO-SELECT (What a nice kid!)

if (iNewTeam==AUTO_TEAM) {

/* this is the "always smaller team" version

if (teamCounts[CTS] < teamCounts[TS] || teamCounts[TS] >= PTB_MAXSIZE) iNewTeam = CTS

else if (teamCounts[TS] < teamCounts[CTS] || teamCounts[CTS] >= PTB_MAXSIZE) iNewTeam = TS

// both teams have same size ...

else if (winnerTeam && teamCounts[loserTeam]<PTB_MAXSIZE) iNewTeam = loserTeam

else if (teamCounts[TS] >= PTB_MAXSIZE) iNewTeam = CTS

else if (teamCounts[CTS] >= PTB_MAXSIZE) iNewTeam = TS

else iNewTeam = (random_num(0,100) < 50) ? CTS : TS

*/

// this version prefers the losing team (but still honors PTB_MAXDIFF)

if (teamCounts[CTS] >= PTB_MAXSIZE) iNewTeam = TS

else if (teamCounts[TS] >= PTB_MAXSIZE) iNewTeam = CTS

else if (teamCounts[CTS]-teamCounts[TS] >= PTB_MAXDIFF) iNewTeam = TS

else if (teamCounts[TS]-teamCounts[CTS] >= PTB_MAXDIFF) iNewTeam = CTS

else if (winnerTeam) iNewTeam = loserTeam

else if (teamCounts[CTS]<teamCounts[TS]) iNewTeam = CTS

else if (teamCounts[TS]<teamCounts[CTS]) iNewTeam = TS

// both teams have same size ...

else iNewTeam = (random_num(0,100) < 50) ? CTS : TS

// check for maximum team size

if (teamCounts[iNewTeam]>=PTB_MAXSIZE) {

client_print(id,print_chat,"PTB: Maximum team size prohibits team join.") // ??? - only a spectator???

#if !defined MANUAL_SWITCH

engclient_cmd(id,"chooseteam") // display menu again

#endif

return PLUGIN_HANDLED

}

client_print(id,print_chat,"PTB: You have been auto-assigned...")

engclient_cmd(id,"jointeam",(iNewTeam==CTS)?"2":"1")

return PLUGIN_HANDLED

}

return PLUGIN_CONTINUE

}

public team_score(){

new arg[2]

read_data(1,arg,1)

teamScores[ ( arg[0] == 'T' ) ? TS : CTS ] = read_data(2)

}

public win_streaks(param[]){

new winner = param[0]

new looser = param[1]

if (winStreaks[winner] < 0) {

winStreaks[winner] = 1

winStreaks[looser] = -1

}

else {

winStreaks[winner]++

winStreaks[looser]--

}

actAtEndOfRound()

}

public round_end(){

new param[12]

read_data(2,param,8)

if (param[7]=='c') {//%!MRAD_ctwin

param[0] = CTS

param[1] = TS

}

else if (param[7]=='t') {//%!MRAD_terwin

param[0] = TS

param[1] = CTS

}

else

return // %!MRAD_rounddraw (both teams have left the game)

set_task(4.0,"win_streaks",0,param,2)

}

public new_round() {

if ( floatround(get_cvar_float("mp_roundtime") * 60.0) != read_data(1) ) return

++roundCounter

announceStatus()

}

// Happen only at team select (also auto-join)

public team_join() {

new arg[32]

read_data(3,arg,31)

lastRoundSwitched[ get_user_index(arg) ] = roundCounter

}

// Can happen at begin of round or team select

public team_assign() {

new arg[2], team

new i = read_data(1)

read_data(2,arg,1)

if ( arg[0] == 'C' )

team = CTS

else if ( arg[0] == 'T' )

team = TS

else

team = UNASSIGNED

teamCounts[playerTeam]-- // Unregister from old team

teamCounts[team]++ // Increase ammount in new team

playerTeam = team // Assign to new

}

public game_restart(){

roundCounter = 0

lastSwitchRound = 0

couldNotSwitchCounter = 0

teamKills[0] = teamKills[1] = teamKills[2] = 0

teamDeaths[0] = teamDeaths[1] = teamDeaths[2] = 0

teamScores[0] = teamScores[1] = teamScores[2] = 0

winStreaks[0] = winStreaks[1] = winStreaks[2] = 0

wtConditions[0] = wtConditions[1] = wtConditions[2] = 0

validTargetCounts[0] = validTargetCounts[1] = validTargetCounts[2] = 0

new a = get_maxplayers()

for (new i = 1; i <= a; ++i){

kills = 0

deaths = 0

wtjCount = 0

lastRoundSwitched = -999

}

}

public death_msg(){

new iWinner = read_data(1)

new iLoser = read_data(2)

if ( iWinner < 1 || iWinner > 32 || iLoser < 1 || iLoser > 32 )

return

if ( playerTeam[iWinner] == playerTeam[iLoser] )

return // no TKS!!!

kills[iWinner]++

deaths[iLoser]++

if (PTB_SCALEDOWN <= 1) return

if (kills[iWinner] + deaths[iWinner] >= PTB_MAXINCIDENTS) {

kills[iWinner] /= PTB_SCALEDOWN

deaths[iWinner] /= PTB_SCALEDOWN

}

if (kills[iLoser] + deaths[iLoser] >= PTB_MAXINCIDENTS) {

kills[iLoser] /= PTB_SCALEDOWN

deaths[iLoser] /= PTB_SCALEDOWN

}

}

calcTeamScores() {

teamDeaths[uNASSIGNED] = 0

teamDeaths[CTS] = 0

teamDeaths[TS] = 0

teamKills[uNASSIGNED] = 0

teamKills[CTS] = 0

teamKills[TS] = 0

new team, a = get_maxplayers()

for (new i = 1; i <= a; ++i) {

team = playerTeam

teamKills[team] += kills

teamDeaths[team] += deaths

}

ctKD = fdivWorkaround(float(teamKills[CTS]), float(teamDeaths[CTS]))

tKD = fdivWorkaround(float(teamKills[TS]), float(teamDeaths[TS]))

}

announceStatus() {

if (!PTB_ANNOUNCE) return

checkTeamBalance()

new text[256]

if (winnerTeam == TS) {

format(text, 255, "PTB: The COUNTER-TERRORIST team could use some support.")

doTypesay(text, 5, 0, 50, 255)

say("PTB: The COUNTER-TERRORIST team could use some support.")

}

else if (winnerTeam == CTS) {

format(text, 255, "PTB: The TERRORIST team could use some support.")

doTypesay(text, 5, 255, 50, 0)

say("PTB: The TERRORIST team could use some support.")

}

else if (wtConditions[TS] > wtConditions[CTS]) {

format(text, 255, "PTB: Observing TERRORIST team advantage.")

doTypesay(text, 5, 255, 50, 0)

say("PTB: Observing TERRORIST team advantage.")

}

else if (wtConditions[CTS] > wtConditions[TS]) {

format(text, 255, "PTB: Observing COUNTER-TERRORIST team advantage.")

doTypesay(text, 5, 0, 50, 255)

say("PTB: Observing COUNTER-TERRORIST team advantage.")

}

else if (PTB_SAYOK) {

format(text, 255, "PTB: Teams look fine, no action required.")

doTypesay(text, 5, 200, 100, 0)

say("PTB: Teams look fine, no action required.")

}

}

public admin_ptb(id,level,cid) {

if (!cmd_access(id,level,cid,1))

return PLUGIN_HANDLED

new cmd[32], arg[32], lastcmd

if ( read_argv(1,cmd,31) == 0 ) { // no command - plain amx_ptb

//console_print(id,"PTB: Ptahhotep's Team Balancer %s", PTB_VERSION)

//console_print(id,"PTB: ([email protected])")

checkTeamBalance()

displayStatistics(id)

return PLUGIN_HANDLED

}

if (equali(cmd, "on") || equal(cmd, "1")) {

PTB_LIMITJOIN = true

PTB_SWITCH = true

PTB_ANNOUNCE = true

console_print(id,"PTB: Enabled all PTB actions.")

return PLUGIN_HANDLED

}

if (equali(cmd, "off") || equal(cmd, "0")) {

PTB_SWITCH = false

PTB_ANNOUNCE = false

PTB_LIMITJOIN = false

console_print(id,"PTB: Disabled all PTB actions.")

return PLUGIN_HANDLED

}

if (equal(cmd, "list") || equal(cmd, "help")) {

console_print(id,"PTB: Available Commands:")

console_print(id,"PTB: Team Join Control: ^"limitjoin^", ^"limitafter^", ^"limitmin^", ^"maxsize^", ^"autorounds^",")

console_print(id,"PTB: ^"maxdiff^", ^"wtjauto^", ^"wtjkick^", ^"kick^", ^"savewtj^"")

console_print(id,"PTB: Team Balancing Actions: ^"switch^", ^"switchafter^", ^"switchmin^", ^"switchfreq^", ^"playerfreq^",")

console_print(id,"PTB: ^"forceswitch^", ^"deadonly^"")

console_print(id,"PTB: Team Strength Limits: ^"maxstreak^", ^"maxscore^", ^"minrating^", ^"maxrating^", ^"superrating^"")

console_print(id,"PTB: Messages: ^"tellwtj^", ^"announce^", ^"sayok^", ^"typesay^"")

console_print(id,"PTB: Misc: ^"^", ^"status^", ^"list^", ^"help^", ^"on^", ^"off^", ^"save^", ^"load^"")

console_print(id,"PTB: To view all PTB settings, type ^"amx_ptb status^".")

console_print(id,"PTB: To view or change a single PTB setting, type ^"amx_ptb <setting> <on|off|value>^".")

console_print(id,"PTB: For PTB statistics, simply type ^"amx_ptb^".")

return PLUGIN_HANDLED

}

new arglen = read_argv(2,arg,31)

new status = equal(cmd, "status")

// team selection control

if ( status ) console_print(id,"PTB: ---------- Team Selection Control ----------")

// PTB_LIMITJOIN

if ( (lastcmd = equal(cmd, "limitjoin")) && arglen ) PTB_LIMITJOIN = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (limitjoin) WTJ prevention is %s.", PTB_LIMITJOIN ? "ON" : "OFF")

// PTB_LIMITAFTER

if ( (lastcmd = equal(cmd, "limitafter")) && arglen ) PTB_LIMITAFTER = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (limitafter) Team limiting starts after %d round(s).", PTB_LIMITAFTER)

// PTB_LIMITMIN

if ( (lastcmd = equal(cmd, "limitmin")) && arglen ) PTB_LIMITMIN = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (limitmin) Team limiting needs at least %d player(s).", PTB_LIMITMIN)

// PTB_MAXSIZE

if ( (lastcmd = equal(cmd, "maxsize")) && arglen ) PTB_MAXSIZE = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (maxsize) Maximum team size is %d player(s).", PTB_MAXSIZE)

// PTB_MAXDIFF

if ( (lastcmd = equal(cmd, "maxdiff")) && arglen ) PTB_MAXDIFF = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (maxdiff) Maximum team size difference is %d.", PTB_MAXDIFF)

// PTB_AUTOROUNDS

if ( (lastcmd = equal(cmd, "autorounds")) && arglen ) PTB_AUTOROUNDS = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id, "PTB: (autorounds) First %d rounds no free team choice.", PTB_AUTOROUNDS)

// PTB_WTJAUTO

if ( (lastcmd = equal(cmd, "wtjauto")) && arglen ) PTB_WTJAUTO = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (wtjauto) Auto-joining WTJ after %d tr(y/ies).", PTB_WTJAUTO)

// PTB_WTJKICK

if ( (lastcmd = equal(cmd, "wtjkick")) && arglen ) PTB_WTJKICK = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (wtjauto) Auto-kicking WTJ after %d tr(y/ies).", PTB_WTJKICK)

// PTB_KICK

if ( (lastcmd = equal(cmd, "kick")) && arglen ) PTB_KICK = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (kick) WTJ kicking is %s.", PTB_KICK ? "ON" : "OFF" )

// PTB_SAVEWTJ

if ( (lastcmd = equal(cmd, "savewtj")) && arglen ) PTB_SAVEWTJ = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (savewtj) Saving to wtj.log is %s.", PTB_SAVEWTJ ? "ON" : "OFF");

// team balancing actions

if ( status ) console_print(id,"PTB: ---------- Team Balancing Actions ----------")

// PTB_SWITCH

if ( (lastcmd = equal(cmd, "switch")) && arglen ) PTB_SWITCH = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (switch) Team switching is %s.", PTB_SWITCH ? "ON" : "OFF")

// PTB_SWITCHAFTER

if ( (lastcmd = equal(cmd, "switchafter")) && arglen ) PTB_SWITCHAFTER = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (switchafter) Switching starts after %d round(s).", PTB_SWITCHAFTER)

// PTB_SWITCHMIN

if ( (lastcmd = equal(cmd, "switchmin")) && arglen ) PTB_SWITCHMIN = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (switchmin) Switching needs at least %d player(s).", PTB_SWITCHMIN)

// PTB_PLAYERFREQ

if ( (lastcmd = equal(cmd, "playerfreq")) && arglen ) PTB_PLAYERFREQ = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (playerfreq) Individual players are switched every %d round(s) at maximum.", PTB_PLAYERFREQ)

// PTB_SWITCHFREQ

if ( (lastcmd = equal(cmd, "switchfreq")) && arglen ) PTB_SWITCHFREQ = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (switchfreq) Switch occurs every %d round(s) at maximum.", PTB_SWITCHFREQ)

// PTB_FORCESWITCH

if ( (lastcmd = equal(cmd, "forceswitch")) && arglen ) PTB_FORCESWITCH = check_param_num(arg,0)

if ( status || lastcmd ) console_print(id,"PTB: (forceswitch) Forcing switch after %d unsuccessful switch(es).", PTB_FORCESWITCH)

// PTB_DEADONLY

if ( (lastcmd = equal(cmd, "deadonly")) && arglen ) PTB_DEADONLY = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (deadonly) Switching dead only is %s.",PTB_DEADONLY ? "ON" : "OFF" )

// messages

if ( status ) console_print(id,"PTB: ---------- Messages ----------")

// PTB_TELLWTJ

if ( (lastcmd = equal(cmd, "tellwtj")) && arglen ) PTB_TELLWTJ = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (tellwtj) Telling about WTJ tries is %s.",PTB_TELLWTJ ? "ON" : "OFF")

// PTB_ANNOUNCE

if ( (lastcmd = equal(cmd, "announce")) && arglen ) PTB_ANNOUNCE = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (announce) Announcements are %s.",PTB_ANNOUNCE ? "ON" : "OFF")

// PTB_SAYOK

if ( (lastcmd = equal(cmd, "sayok")) && arglen ) PTB_SAYOK = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (sayok) ^"OK^" announcements are %s.",PTB_SAYOK ? "ON" : "OFF")

// PTB_TYPESAY

if ( (lastcmd = equal(cmd, "typesay")) && arglen ) PTB_TYPESAY = check_param_bool(arg)

if ( status || lastcmd ) console_print(id,"PTB: (typesay) typesay usage is %s.",PTB_TYPESAY ? "ON" : "OFF")

// team strength limits

if ( status ) console_print(id,"PTB: ---------- Team Strength Limits ----------")

// PTB_MAXSTREAK

if ( (lastcmd = equal(cmd, "maxstreak")) && arglen ) PTB_MAXSTREAK = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (maxstreak) Maximum accepted win streak is %d.", PTB_MAXSTREAK)

// PTB_MAXSCORE

if ( (lastcmd = equal(cmd, "maxscore")) && arglen ) PTB_MAXSCORE = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (maxscore) Maximum accepted team score difference is %d.", PTB_MAXSCORE)

// PTB_MINRATING

if ( (lastcmd = equal(cmd, "minrating")) && arglen ) PTB_MINRATING = check_param_float(arg,1.0)

if ( status || lastcmd ) console_print(id,"PTB: (minrating) Minimum critical strength rating is %.2f.",PTB_MINRATING)

// PTB_MAXRATING

if ( (lastcmd = equal(cmd, "maxrating")) && arglen ) PTB_MAXRATING = check_param_float(arg,1.0)

if ( status || lastcmd ) console_print(id,"PTB: (maxrating) Maximum critical strength rating is %.2f.",PTB_MAXRATING)

// PTB_SUPERRATING

if ( (lastcmd = equal(cmd, "superrating")) && arglen ) PTB_SUPERRATING = check_param_float(arg,1.0)

if ( status || lastcmd ) console_print(id,"PTB: (superrating) Super critical strength rating is %.2f.",PTB_SUPERRATING)

// PTB_MAXINCIDENTS

if ( (lastcmd = equal(cmd, "maxincidents")) && arglen ) PTB_MAXINCIDENTS = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (maxincidents) Maximum incidents before internal player score scale down is %d.", PTB_MAXINCIDENTS)

// PTB_SCALEDOWN

if ( (lastcmd = equal(cmd, "scaledown")) && arglen ) PTB_SCALEDOWN = check_param_num(arg,1)

if ( status || lastcmd ) console_print(id,"PTB: (scaledown) Integer scale down factor for player scores is %d.", PTB_SCALEDOWN)

// misc

if ( status ) {

console_print(id,"PTB: ---------- Misc ----------")

console_print(id,"PTB: To enable or disable PTB, type ^"admin_ptb <on|1|off|0>^".")

console_print(id,"PTB: To view or change a single PTB setting, type ^"amx_ptb <setting> <on|off|value>^".")

console_print(id,"PTB: To view a brief overview of PTB commands, type ^"amx_ptb help^" or ^"amx_ptb list^".")

console_print(id,"PTB: For PTB statistics, simply type ^"amx_ptb^".")

}

return PLUGIN_HANDLED

}

stock displayStatistics(id,bool:toLog = false) {

//say("displayStatistics")

new text[256]

// time

/*format(text, 255, "PTB: Statistics generated at: %s", lastTeamBalanceCheck)

if (toLog) log_amx(text)

console_print(id,text)*/

// connected players

format(text, 255, "PTB: Connected players: %d", get_playersnum())

if (toLog) log_amx(text)

console_print(id,text)

// team sizes

format(text, 255, "PTB: Team sizes: CTs %d, Ts %d", teamCounts[CTS], teamCounts[TS])

if (toLog) log_amx(text)

console_print(id,text)

// team scores

format(text, 255, "PTB: Team scores: CTs %d, Ts %d", teamScores[CTS], teamScores[TS])

if (toLog) log_amx(text)

console_print(id,text)

// Kills:Deaths

format(text, 255, "PTB: Team kills:deaths: CTs %d:%d, Ts %d:%d", teamKills[CTS], teamDeaths[CTS], teamKills[TS], teamDeaths[TS])

if (toLog) log_amx(text)

console_print(id,text)

// Kills/Deaths

format(text, 255, "PTB: Team kills/deaths: CTs %.2f, Ts %.2f", ctKD , tKD )

if (toLog) log_amx(text)

console_print(id,text)

// strength

format(text, 255, "PTB: Team strengths: CTs %.2f, Ts %.2f",ctStrength , tStrength )

if (toLog) log_amx(text)

console_print(id,text)

// rating

format(text, 255, "PTB: Team ratings: CTs %.2f, Ts %.2f",ctRating,tRating )

if (toLog) log_amx(text)

console_print(id,text)

// won rounds

if (winStreaks[CTS] > 0) {

format(text, 255, "PTB: Last %d round(s) won by CTs.", winStreaks[CTS])

if (toLog) log_amx(text)

console_print(id,text)

}

else if (winStreaks[TS] > 0) {

format(text, 255, "PTB: Last %d round(s) won by Ts.", winStreaks[TS])

if (toLog) log_amx(text)

console_print(id,text)

}

// winning team

switch(winnerTeam){

case CTS: format(text, 255, "PTB: The CTs are the winning team.")

case TS: format(text, 255, "PTB: The Ts are the winning team.")

default: format(text, 255, "PTB: Teams are balanced.")

}

if (toLog) log_amx(text)

console_print(id,text)

/*format(text, 255, "PTB: These statistics might be already outdated.")

if (toLog) log_amx(text)

console_print(id,text)

format(text, 255, "PTB: To view a brief overview of PTB commands, type ^"amx_ptb help^" or ^"amx_ptb list^".")

if (toLog) log_amx(text)

console_print(id,text)

format(text, 255, "PTB: To view all PTB settings, type ^"amx_ptb status^".")

if (toLog) log_amx(text)

console_print(id,text)*/

}

public client_connect(id){

kills[id] = 0

deaths[id] = 0

isBeingTransfered[id] = false

playerTeam[id] = UNASSIGNED

lastRoundSwitched[id] = -999

wtjCount[id] = 0

get_user_info(id,"_vgui_menus",clientVGUIMenu[id],1)

clientVGUIMenu[id][0] = '0'

return PLUGIN_CONTINUE

}

public client_disconnect(id) {

kills[id] = 0

deaths[id] = 0

isBeingTransfered[id] = false

playerTeam[id] = UNASSIGNED

lastRoundSwitched[id] = -999

wtjCount[id] = 0

// redundant team size check

teamCounts[uNASSIGNED] = 0

teamCounts[CTS] = 0

teamCounts[TS] = 0

new a = get_maxplayers()

for (new i = 1; i <= a; ++i)

++teamCounts[playerTeam]

if (clientVGUIMenu[id][0] != '0') {

set_user_info( id, "_vgui_menus", clientVGUIMenu[id] )

clientVGUIMenu[id][0] = '0'

}

return PLUGIN_CONTINUE

}

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...