AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting Help (https://forums.alliedmods.net/forumdisplay.php?f=11)
-   -   Team Balencer for AMXX (https://forums.alliedmods.net/showthread.php?t=2343)

roguE 06-02-2004 01:39

Team Balencer for AMXX
 
I'm having troubles; The balancer works perfectly fine, But it does not show the 'best player' and 'best team'; I was wondering if I have made this wrong- Please let me know if so; Feel free to correct it.

Code:

#include <amxmodx>

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]
}

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 (teamCounts[winnerTeam] <= teamCounts[loserTeam])
                        doSwitch()
                else if (teamCounts[loserTeam] < teamCounts[winnerTeam])
                        doTransfer()
        }
}

createValidTargets(theTeam, bool:deadonly) {
        new n = 0
        for (new i = 0; i < teamCounts[theTeam]; ++i) {
                // Dead only condition
                if ( deadonly && is_user_alive(sortedTeams[theTeam][i]) ) continue
                // Already switched or in PTB_PLAYERFREQ time condition
                if ((lastRoundSwitched[sortedTeams[theTeam][i]] == roundCounter) ||
                        (roundCounter - lastRoundSwitched[sortedTeams[theTeam][i]] < PTB_PLAYERFREQ))        continue
                sortedValidTargets[theTeam][n++] = sortedTeams[theTeam][i]
        }
        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[i] != 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][i]])
                                || ( (kills[sortedTeams[theTeam][k]]==kills[sortedTeams[theTeam][i]])        &&
                                (deaths[sortedTeams[theTeam][k]]>deaths[sortedTeams[theTeam][i]]))) {
                                // swap
                                swap = sortedTeams[theTeam][k]
                                sortedTeams[theTeam][k] = sortedTeams[theTeam][i]
                                sortedTeams[theTeam][i] = 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[i]!=team&&i!=toBeAdded)        || (i==toBeRemoved)        )
                        continue
                sumKD += fdivWorkaround(float(kills[i]), float(deaths[i]))
        }
        new Float:strength = float(teamCounts[team])
        if (sumKD) strength *= sumKD
        return strength
}

oSwitch() {
        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
                }
        }

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),"team_select")
        register_menucmd(-2,(1<<0)|(1<<1),"team_select")        // VGUI menu
        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(1.5,"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[i]]-- // Unregister from old team
        teamCounts[team]++ // Increase ammount in new team
        playerTeam[i] = 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[i] = 0
                deaths[i] = 0
                wtjCount[i] = 0
                lastRoundSwitched[i] = -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
        }
}


if defined CS16_SWITCH
public delay_transfer(args[]) {
        new id = args[0]
        if defined PTB_DEBUG
        og_message("[PTB] Delayed Transfer #%i ('%s',%i)",id,clientVGUIMenu[id],isBeingTransfered[id])
        endif
        if (!isBeingTransfered[id]) return
        user_kill(id,1)
        engclient_cmd(id,"jointeam",(playerTeam[id]==TS) ? "2" : "1")
        engclient_cmd(id,"joinclass","5")
        if (clientVGUIMenu[id][0] != '0') {
                set_user_info( id, "_vgui_menus", clientVGUIMenu[id] )
                clientVGUIMenu[id][0] = '0'
        }
}

Thanks for your time.

[FBX] 06-05-2004 23:28

you spelled average wrong :P

are you porting PTB to amxx or revising it or you the original author...?

if a function isn't working correctly and it should, then check the server console for runtime errors, because if you get those it drops out of the function without executing any more code.

roguE 06-06-2004 00:07

Just transfering to amxx.

Vindicator 09-15-2004 16:21

do you have a working version of this?
If so would it be possible to get a copy plz :)

griesimatt 11-18-2004 15:19

Please inform us when you get a completed/working copy of this plug-in. It would be nice to have a working AMXX team balancer!!!

lantz69 11-18-2004 16:01

This func is wrong:
Code:
oSwitch() {    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    }

Should be:
Code:
doSwitch() { //<-----------------------------HERE    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    }


All times are GMT -4. The time now is 14:48.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.