Raised This Month: $ Target: $400
 0% 

H-Balance (Team balancer) Modification / Help Requests


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Darkwob
BANNED
Join Date: Oct 2018
Old 08-29-2020 , 05:04   H-Balance (Team balancer) Modification / Help Requests
Reply With Quote #1

Can anybody recompile this Plugin for Left 4 dead 2?
Let the balance system run automatically, I think it is unnecessary to use any cvar.

maybe only for plugins enable/disable cvar

Quote:
Feature list:

* automatic teambalance on round end (round based mode) / player death (continous mode)
* adjusts team sizes on imbalance and swaps players on team strengh difference
* team balance is calculated based on team score and players kill/death ratio
* designed NOT to anoy single players by repeatedly swapping them around
* supports CS:GO
* NEW: supports games with respawning like TF2 or DOD


Reference server:
If you want to have a look at it before installing:46.228.195.116:27015 (CS:GO),

CVARS:

sm_teambalance [1/0]: Activate/Disable team balancer (default 1)
sm_balance_log_level [0-2]: Verbosity of chat logging (0=off, 1=on balance, 2=always)
sm_balanceDamping: increase to slow down balancing (default 2), recommendation: just do not touch ;)
sm_adminProtection [0/1/2]: protects admins from beeing balanced (0=no protection, 1=moderate protection, 2=full protection [BALANCE PERFORMANCE MAY BE REDUCED MASIVELY], default=0)
sm_balance_min_players [>=2]: Minimum players in game to start balancing
sm_balance_mode [1/0]: !EXPERIMENTAL! Balancing mode (0=continous/respawn, 1=round based)
Round based mode: intended for games like "Counter Strike". This is the mode known from plugin version <= 1.5
Continous Mode: intended for Games like TF2 or DOD with long round times and respawning. This is not tested that much and the algorithm may need some fine tuning. It will balance dead players only, so rethink twice if you intend to use it along with admin immunity ...

CMDS:

sm_force_balance: trigger a balance operation exactly now (note: players will be slayed on swap)

Changelog:

1.6.2: added some secure coding and debug output
1.6: added config variables sm_balance_min_players and sm_balance_mode [EXPERIMENTAL STATE]
1.5.1 crash fix
1.5: admin protection
1.4: balancing disabled during warmup
1.3: added sm_force_balance command , added translation-support, switch is triggered at the end of round restart delay to avoid kills after switch, chat output verbosity
1.0: first public release

Installation instructions:

Just copy the .smx to your plugins directory and hbalance.phrases.txt to your translations file

Supported languages:

* English
* German
* French (thx Avo)
* Polish (thx SanKen/dzej dzej)

Future plans:
PHP Code:
#pragma semicolon 1
/*
                        
*/

#include <sourcemod>
#include <sdktools>
#undef REQUIRE_EXTENSIONS
#include <cstrike>

#define PLUGIN_VERSION "1.6.2"
#define TRANSLATION_FILE "hbalance.phrases"

#define MIN_DAMPING 3
#define _DEBUG 1

#define LOG_NEVER 0
#define LOG_ONACTION 1
#define LOG_ALWAYS 2

#define ADMIN_PROT_NONE 0
#define ADMIN_PROT_MODERATE 1
#define ADMIN_PROT_FULL 2

#define MODE_CONTINOUS 0
#define MODE_ROUND_BASED 1
    
new Handle:s_activatePlugin INVALID_HANDLE;
new 
Handle:s_dampingFactor INVALID_HANDLE;
new 
Handle:s_logLevel INVALID_HANDLE;
new 
Handle:s_roundRestartDelay INVALID_HANDLE;
new 
Handle:s_warmupTime INVALID_HANDLE;
new 
Handle:s_adminProt INVALID_HANDLE;
new 
Handle:s_gameMode INVALID_HANDLE;
new 
Handle:s_minPlayers INVALID_HANDLE;

public 
Plugin:myinfo 
{
    
name "HANSE-Balance",
    
author "red!",
    
description "Generic Team balancer (supporting CS:GO)",
    
version PLUGIN_VERSION,
    
url "http://www.hanse-clan.de"
};


// globals
new s_streak[4]={0000};
new 
s_kills[4]={0000};
new 
bool:s_isCstrike=true;
new 
s_lastSwitch[MAXPLAYERS+1];
new 
s_minGracePeriod 3;
new 
s_teamCountCT=0;
new 
s_teamCountT=0;
new 
Handle:s_teamTableCT INVALID_HANDLE;
new 
Handle:s_teamTableT INVALID_HANDLE;
new 
s_lastBalanceTime=0;
new 
bool:s_isWarmup=false;
new 
bool:s_continousMode=false;

public 
OnPluginStart(){

    new 
String:GameType[10];
    
GetGameFolderName(GameTypesizeof(GameType));
    
    if (
StrEqual(GameType"cstrike"false) || StrEqual(GameType"csgo"false)) {
        
s_isCstrike true
        
LogMessage("hbalance is running in counter strike mode");
    } else {
        
s_isCstrike false
        
LogMessage("hbalance is running in generic game mode");
    }

    
LoadTranslations(TRANSLATION_FILE);
    
CreateConVar("hbalance_version"PLUGIN_VERSION"Version of [HANSE] Team Balance"FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_SPONLY);
    
s_teamTableCT CreateArray(2,MAXPLAYERS);
    
s_teamTableT CreateArray(2,MAXPLAYERS);
    
    
// register commands & events
    
RegAdminCmd("sm_hbalance_dbg"consoleDbgCmdADMFLAG_GENERIC);
    
RegAdminCmd("sm_force_balance"consoleForceBalanceADMFLAG_CHANGEMAP ADMFLAG_KICK ); 
    
s_activatePluginCreateConVar("sm_teambalance""1""Activate H-Balance team balancer",0true0.0true1.0);
    
s_dampingFactor CreateConVar("sm_balanceDamping""2""The higher the value, the slower the plugin reacts"0true0.0);
    
s_adminProt CreateConVar("sm_adminProtection""0""0=no protection, 1=moderate protection, 2=full protection (BALANCE PERFORMANCE MAY BE REDUCED MASIVELY)"0true0.0true2.0);
    
s_roundRestartDelay FindConVar("mp_round_restart_delay");
    
s_warmupTime FindConVar("mp_warmuptime");
    
s_logLevelCreateConVar("sm_balance_log_level""1""Amount of logging (0=off, 1=on balance, 2=always)",0true0.0true2.0);
    
s_gameModeCreateConVar("sm_balance_mode", (s_isCstrike) ? "1" "0""EXPERIMENTAL[!!!]: Balancing mode (0=continous/respawn, 1=round based)",0true0.0true1.0);
    
s_minPlayers CreateConVar("sm_balance_min_players""3""Minimum players in game to start balancing",0true2.0);
    
s_lastBalanceTime GetTime();
    
    
AutoExecConfig(true"hbalance");
    
    
HookEvent("round_end",             EventRoundEnd,EventHookMode_PostNoCopy);
    
HookEvent("player_death",         EventPlayerDeath);
    
CreateTimer(60.0Timer_GraceINVALID_HANDLETIMER_REPEAT);
}

public 
OnClientPutInServer(client)
{
    
s_lastSwitch[client]=0;
}

public 
OnMapStart() 
{
    
s_streak[CS_TEAM_CT]=0
    
s_streak[CS_TEAM_T]=0
    
    new 
Float:warmupTime 0.0;
    if (
s_warmupTime !=INVALID_HANDLE) {
        
warmupTime=GetConVarFloat(s_warmupTime);
    }
    if (
warmupTime>0.0) {
        
s_isWarmup=true;
        if (
CreateTimer(warmupTimeTimer_WarmupEnd0TIMER_FLAG_NO_MAPCHANGE)==INVALID_HANDLE) {
            
s_isWarmup=false;
        }            
    }
}

public 
Action:Timer_WarmupEnd(Handle:timerany:param)
{
    
s_isWarmup=false;
}

public 
Action:Timer_Grace(Handle:timerany:null)
{
    for ( new 
1<= MaxClients i++ ) {
        if ( 
IsClientInGame(i)) {
            
s_lastSwitch[i]++;
        }
    }
}

public 
EventRoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
    if (!
s_isWarmup && GetConVarInt(s_gameMode)==MODE_ROUND_BASED)
    {
        
s_continousMode=false;
        new 
winner GetEventInt(event"winner");
        if (
winner==CS_TEAM_T) {
            
s_streak[CS_TEAM_T]++; 
            
s_streak[CS_TEAM_CT]=0
        }
        if (
winner==CS_TEAM_CT) { 
            
s_streak[CS_TEAM_CT]++; 
            
s_streak[CS_TEAM_T]=0
        }
        
        new 
Float:restartDelay=1.0;

        if (
s_roundRestartDelay !=INVALID_HANDLE) {
            
restartDelay=GetConVarFloat(s_roundRestartDelay)-1.0;
            if (
restartDelay<0.0) { restartDelay=0.0; }
        }    
        
        if (
isPluginActive()) {        
            
CreateTimer(restartDelayTimer_BalancewinnerTIMER_FLAG_NO_MAPCHANGE); 
        }
    }
}

public 
EventPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
    if (!
s_isWarmup && GetConVarInt(s_gameMode)==MODE_CONTINOUS
    {
        
s_continousMode=true;
        new 
victim GetClientOfUserId(GetEventInt(event"userid"));
        new 
winner getOpposingTeamOf(GetClientTeam(victim));
        if (
winner==CS_TEAM_T) {
            
s_kills[CS_TEAM_T]++; 
            
s_kills[CS_TEAM_CT]=(s_kills[CS_TEAM_CT]*2)/3
        }
        if (
winner==CS_TEAM_CT) { 
            
s_kills[CS_TEAM_CT]++; 
            
s_kills[CS_TEAM_T]=(s_kills[CS_TEAM_T]*2)/3
        }
        
        if (
isPluginActive()) {        
            
            if (
isValidPlayer(victim)) {
                if ((
GetTime() - s_lastBalanceTime)>2*60) {
                    
#if defined DEBUG
                    
LogMessage("triggering continous balance for team");
                    
#endif
                    
CreateTimer(0.1Timer_BalancegetOpposingTeamOf(GetClientTeam(victim)), TIMER_FLAG_NO_MAPCHANGE); 
                }
            }
        }
    }
}

public 
Action:Timer_Balance(Handle:timerany:winner)
{
    
refreshRanking();
    
#if defined DEBUG
    
LogMessage("score %d:%d, score weight %d:%d, team weight %d:%d, team members %d:%d, imbalance %d:%d"GetTeamScore(CS_TEAM_CT), GetTeamScore(CS_TEAM_T),s_streak[CS_TEAM_CT], s_streak[CS_TEAM_T], getTeamWeight(CS_TEAM_CT), getTeamWeight(CS_TEAM_T),    s_teamCountCTs_teamCountTgetImbalanceRating(CS_TEAM_CT),getImbalanceRating(CS_TEAM_T));
    
#endif
    
    // balance team size
    
new bool:balanced=false;
    new 
largerTeam=-1;
    if (
s_teamCountT >(s_teamCountCT+1)) { largerTeam=CS_TEAM_T; }
    if (
s_teamCountCT>(s_teamCountT +1)) { largerTeam=CS_TEAM_CT; }
    if (
largerTeam!=-1) {
        
balanceByMove(largerTeamfalse);
        
balanced=true;
    }
    
    
// balance team strengh
    
if ((s_teamCountCT+s_teamCountT)>=GetConVarInt(s_minPlayers)) {
        if ((
getImbalanceRating(CS_TEAM_CT)-getImbalanceRating(CS_TEAM_T)) >= getDampingFactor()) {
            
balanceTeam(CS_TEAM_CTfalse);
            
balanced=true;
        } else if ((
getImbalanceRating(CS_TEAM_T)-getImbalanceRating(CS_TEAM_CT)) >= getDampingFactor()) {
            
balanceTeam(CS_TEAM_Tfalse);
            
balanced=true;
        } 
    }
    
    if (
balanced
    {
        if (
GetConVarInt(s_logLevel)!=LOG_NEVER) { PrintToChatAll("%T""Teams have been balanced"LANG_SERVER); }
        
#if defined DEBUG
        
new leadingTeamWeight  getTeamWeight(winner); 
        new 
inferiorTeamWeight getTeamWeight(getOpposingTeamOf(winner));
        
LogMessage("debug: difference %d:%d (%d)"leadingTeamWeightinferiorTeamWeightinferiorTeamWeight leadingTeamWeight);
        
#endif    
    
} else {
        if (
GetConVarInt(s_logLevel)==LOG_ALWAYS) { PrintToChatAll("%T""No team balancing necessary"LANG_SERVER); }
    }
}

balanceTeam(leadingTeambool:slay) {
    new 
leadingTeamWeight  getTeamWeight(leadingTeam); 
    new 
inferiorTeamWeight getTeamWeight(getOpposingTeamOf(leadingTeam));
    
    new 
deltaRef inferiorTeamWeight leadingTeamWeight;
    new 
result deltaRef;
    
    if (
getTeamTableSize(leadingTeam) > getTeamTableSize(getOpposingTeamOf(leadingTeam))) {
        
result balanceByMove(leadingTeamslay);
    } else {
        
result balanceBySwap(leadingTeamtrueslay);
    } 
    
    
// optional second stage
    
if (((s_teamCountCT+s_teamCountT)>=(3+getDampingFactor())) && ((result<0) || (result>(100 + (getDampingFactor()*10))))) {
        
LogMessage("balance result before stage2 from team balance difference %d to %d"deltaRefresult);
        
result =  balanceBySwap(leadingTeamfalseslay);
    }
    
    
LogMessage("balanced from team balance difference %d to %d"deltaRefresult);
    
    
s_streak[leadingTeam] = s_streak[leadingTeam] / 2;
}

balanceByMove(leadingTeambool:slay) {

    new 
leadingTeamWeight  getTeamWeight(leadingTeam); 
    new 
inferiorTeamWeight getTeamWeight(getOpposingTeamOf(leadingTeam));
    
    new 
deltaRef inferiorTeamWeight leadingTeamWeight;
    new 
deltaBestGuess deltaRef;
    
    new 
bestGuess = -1;        
    
    for (new 
i=0;i<getTeamTableSize(leadingTeam);i++) {
        if (!
isProtected(GetArrayCell(getTeamTable(leadingTeam) , i1))) {
            new 
ldscore=GetArrayCell(getTeamTable(leadingTeam), i0);
            new 
deltaThis = (inferiorTeamWeight+ldscore) - (leadingTeamWeight-ldscore);
            if (((
deltaBestGuess<0) && (deltaThis>deltaBestGuess)) ||
                ((
deltaBestGuess>0) && (deltaThis>0) && (deltaThis<deltaBestGuess))) {
                
bestGuess i;
                
deltaBestGuess deltaThis;
            }
        }
    }

    if (
bestGuess<0) {
        if (
s_continousMode) {
            
LogMessage("move; no adequate target found in continous mode."); 
            return 
deltaRef;
        } else if (
GetConVarInt(s_adminProt)!=ADMIN_PROT_FULL) {
            
bestGuess=GetRandomInt(0getTeamTableSize(leadingTeam)-1);
            new 
ldscore=GetArrayCell(getTeamTable(leadingTeam), bestGuess0);
            
deltaBestGuess = (inferiorTeamWeight+ldscore) - (leadingTeamWeight-ldscore);
            
LogMessage("move; no adequate target found, using random target"); 
        } else {
            
LogMessage("move; no adequate target found, not using backup strategy in FULL ADMIN PROTECTION mode"); 
            return 
deltaRef;
        }
    }
        
    
movePlayerToTeam(GetArrayCell(getTeamTable(leadingTeam) , bestGuess1), getOpposingTeamOf(leadingTeam), slay);
    return 
deltaBestGuess;
}

balanceBySwap(leadingTeambool:forcebool:slay) {
    new 
leadingTeamWeight  getTeamWeight(leadingTeam); 
    new 
inferiorTeamWeight getTeamWeight(getOpposingTeamOf(leadingTeam));
    
    new 
deltaRef inferiorTeamWeight leadingTeamWeight;
    new 
deltaBestGuess deltaRef;
    
    new 
bestGuessLT = -1;
    new 
bestGuessIT = -1;
    
    for (new 
i=0;i<getTeamTableSize(leadingTeam);i++) {
        new 
ldscore=GetArrayCell(getTeamTable(leadingTeam), i0);
        for (new 
j=0;j<getTeamTableSize(getOpposingTeamOf(leadingTeam));j++) {
            if ((!
isProtected(GetArrayCell(getTeamTable(leadingTeam) , i1))) && (!isProtected(GetArrayCell(getTeamTable(getOpposingTeamOf(leadingTeam)) , j1)))) {
                new 
ifScore GetArrayCell(getTeamTable(getOpposingTeamOf(leadingTeam)), j0);
                new 
deltaThis = (inferiorTeamWeight-ifScore+ldscore) - (leadingTeamWeight+ifScore-ldscore);
                if (((
deltaBestGuess<0) && (deltaThis>deltaBestGuess)) ||
                    ((
deltaBestGuess>0) && (deltaThis<deltaBestGuess) && (deltaThis>0))) {
                    
bestGuessLT i;
                    
bestGuessIT j;
                    
deltaBestGuess deltaThis;
                }
            } 
        }
    }
    if ((
bestGuessLT<0) ||(bestGuessIT<0)) {
        if (
s_continousMode) {
            
LogMessage("swap; no adequate targets found in continous mode."); 
            return 
deltaRef;
        } else if (
GetConVarInt(s_adminProt)==ADMIN_PROT_FULL) {
            
LogMessage("swap; no adequate targets found, not using backup strategy in FULL ADMIN PROTECTION mode"); 
            return 
deltaRef;
        } else if (
force) {
            
bestGuessLT=0;
            
bestGuessIT=getTeamTableSize(getOpposingTeamOf(leadingTeam))-1;
            new 
ldscore=GetArrayCell(getTeamTable(leadingTeam), bestGuessLT0);
            new 
ifScore GetArrayCell(getTeamTable(getOpposingTeamOf(leadingTeam)), bestGuessIT0);
            
deltaBestGuess = (inferiorTeamWeight-ifScore+ldscore) - (leadingTeamWeight+ifScore-ldscore);
            
LogMessage("swap; no adequate targets found, using best and worst in force mode"); 
        } else {
            
LogMessage("swap; no adequate targets found, doing nothing when not forced"); 
            return 
deltaRef;
        }
    } 
    
    new 
clientLT GetArrayCell(getTeamTable(leadingTeam), bestGuessLT1);
    new 
clientIT GetArrayCell(getTeamTable(getOpposingTeamOf(leadingTeam)), bestGuessIT1);
    
movePlayerToTeam(clientLTgetOpposingTeamOf(leadingTeam), slay);
    
movePlayerToTeam(clientITleadingTeamslay);
    
    return 
deltaBestGuess;
}

movePlayerToTeam(clienttargetTeambool:slay) {
    if (
isValidPlayer(client)) {
        
        new 
id; new score;
        new 
bool:success=false;
        for (new 
i=0;i<getTeamTableSize(getOpposingTeamOf(targetTeam));i++) {
            
id GetArrayCell(getTeamTable(getOpposingTeamOf(targetTeam)), i1);
            if (
id==client) {
                
// move in player tables
                
score GetArrayCell(getTeamTable(getOpposingTeamOf(targetTeam)), i0);
                
SetArrayCell(getTeamTable(targetTeam), getTeamTableSize(targetTeam), score0); 
                
SetArrayCell(getTeamTable(targetTeam), getTeamTableSize(targetTeam), id1); 
                
setTeamTableSize(targetTeamgetTeamTableSize(targetTeam)+1);
                
SetArrayCell(getTeamTable(getOpposingTeamOf(targetTeam)), i00); 
                
SetArrayCell(getTeamTable(getOpposingTeamOf(targetTeam)), i01); 
                
setTeamTableSize(getOpposingTeamOf(targetTeam), getTeamTableSize(getOpposingTeamOf(targetTeam))-1);
                
SortADTArray(s_teamTableCT,Sort_DescendingSort_Integer);
                
SortADTArray(s_teamTableT ,Sort_DescendingSort_Integer);
                
                
// trigger team change
                
new String:name[20] = ""GetClientName(clientname20);
                
LogMessage("moving player %s to team %s"name, (targetTeam==CS_TEAM_T) ? "Team1" "Team2" );
                 
                new 
Handle:pack CreateDataPack();
                
WritePackCell(packclient);
                
WritePackCell(packtargetTeam);
                
WritePackCell(pack, (slay) ? 1:0);
                
PrintCenterText(client"%T""You have been moved"client);
                
CreateTimer(0.5Timer_ChangeClientTeampackTIMER_FLAG_NO_MAPCHANGE);
                
success=true;
                
s_lastBalanceTime GetTime();
                
s_lastSwitch[client]=0;
            }
        }
        if (!
success) { LogMessage("failed moving player %d to team %s (not in source list)"client, (targetTeam==CS_TEAM_T) ? "Team1" "Team2" ); }
        if (!
validateTeamTables()) { LogMessage("failed internal validation after moving player %d to team %s"client, (targetTeam==CS_TEAM_T) ? "Team1" "Team2" ); }
    } else {
        
LogMessage("trying to move invalid player %d to team %s"client, (targetTeam==CS_TEAM_T) ? "Team1" "Team2" );
    }
}

bool:isValidPlayer(client) {
    return (
client 0) && (client <= MaxClients) && IsClientInGame(client);
}

public 
Action:Timer_ChangeClientTeam(Handle:timerany:pack) {
    
ResetPack(pack);
    new 
client ReadPackCell(pack);
    new 
team ReadPackCell(pack);
    new 
bool:slay = (ReadPackCell(pack)==1) ? true:false;
    
CloseHandle(pack);
    if (
isValidPlayer(client) && (GetClientTeam(client)==getOpposingTeamOf(team))) {
        if (
slay && IsPlayerAlive(client)) { ForcePlayerSuicide(client); }
        if (
s_isCstrike) {
            
CS_SwitchTeam(clientteam);
        } else {
            
ChangeClientTeam(clientteam);
        }
        
PrintCenterText(client"%T""You have been moved"client);
    } else {
        
LogMessage("failed on moving invalid player %d to team %s"client, (team==CS_TEAM_T) ? "Team1" "Team2" );
    }
}

getOpposingTeamOf(team) {
    return(
team==CS_TEAM_T) ? CS_TEAM_CT  CS_TEAM_T;
}

refreshRanking() {
    
s_continousMode GetConVarInt(s_gameMode)==MODE_CONTINOUS;
    
s_teamCountCT=0;
    
s_teamCountT=0;
    for ( new 
1<= MaxClientsi++ )
    {
        if ( 
IsClientInGame(i) )
        {
            new 
team=GetClientTeam(i);
            if (
team==CS_TEAM_T) {
                
SetArrayCell(s_teamTableTs_teamCountTgetPlayerScore(i), 0); 
                
SetArrayCell(s_teamTableTs_teamCountTi1); 
                
s_teamCountT++;
            } else if (
team==CS_TEAM_CT) {
                
SetArrayCell(s_teamTableCTs_teamCountCTgetPlayerScore(i), 0); 
                
SetArrayCell(s_teamTableCTs_teamCountCTi1); 
                
s_teamCountCT++;
            }
        }
    }
    
// pad table with zeros and sort.
    
for ( new s_teamCountTMAXPLAYERSi++ ) {
        
SetArrayCell(s_teamTableTi00); 
        
SetArrayCell(s_teamTableTi01); 
    }
    for ( new 
s_teamCountCTMAXPLAYERSj++ ) {
        
SetArrayCell(s_teamTableCTj00); 
        
SetArrayCell(s_teamTableCTj01); 
    }
    
SortADTArray(s_teamTableCT,Sort_DescendingSort_Integer);
    
SortADTArray(s_teamTableT ,Sort_DescendingSort_Integer);
    
validateTeamTables();
}


dumpTeamTable(team) {
    for (new 
i=0;i<getTeamTableSize(team);i++) {
        new 
GetArrayCell(getTeamTable(team), i1);
        new 
String:name[20]= "<invalid>";
        if (
isValidPlayer(c)) {
            
GetClientName(cname20);
        }
        
LogError("     %d, %d: id %d; name %s"teamcGetArrayCell(getTeamTable(team) , i0), name);
    }
}

bool:validateTeamTables() {
    new 
bool:res1 validateTeamTable(CS_TEAM_T);
    new 
bool:res2 validateTeamTable(CS_TEAM_CT);
    return 
res1 && res2;
}

bool:validateTeamTable(team) {
    new 
Handle:table getTeamTable(team);
    new 
tablesize=getTeamTableSize(team);
    new 
bool:res=true;
    for ( new 
0MAXPLAYERSi++ )
    {
        new 
score GetArrayCell(table,i,0);
        new 
id GetArrayCell(table,i,1);
        if (
i<tablesize && (id==|| id>=MaxClients)) {
            
res=falseLogError("validation error A at %d (%d,%d)"iscoreid);
        }
        if (
i>=tablesize && (id!=|| score!=0)) {
            
res=falseLogError("validation error B at %d (%d,%d)"iscoreid);
        }
    }
    if (!
res) { dumpTeamTable(team); }
    return 
res;
}

bool:isProtected(client) {
    
    if (!
isValidPlayer(client)) {
        
LogError("isProtected called with invalid client id %i"client);
        
dumpTeamTable(CS_TEAM_T);
        
dumpTeamTable(CS_TEAM_CT);
        return 
true;
    }
    
    if (
s_continousMode && IsPlayerAlive(client))  {
        return 
true;
    } 
    
    new 
bool:isAdmin = (GetUserFlagBits(client) & ADMFLAG_ROOT)!=|| (GetUserFlagBits(client) & ADMFLAG_GENERIC)!=0;
    if (
GetConVarInt(s_adminProt)==ADMIN_PROT_FULL) {
        if (
isAdmin) { return true; }
    } else if (
GetConVarInt(s_adminProt)==ADMIN_PROT_MODERATE) {
        if (
isAdmin && s_lastSwitch[client]<(s_minGracePeriod*3)) { 
            if (
s_lastSwitch[client]>=s_minGracePeriod){ LogMessage("applying extended grace period [%d] to admin %d"s_lastSwitch[client], client); }
            return 
true
        }
    } 
    
    return 
s_lastSwitch[client]<s_minGracePeriod;
}

 
#define DEFAULT_SCORE 100

getPlayerScore(client) {
    new 
score 50+(10*getDampingFactor());
    if ( 
isValidPlayer(client) )
    {
        new 
kills GetClientFrags(client);
        new 
deaths GetClientDeaths(client);
        if (
kills==0) {kills=1;}
        if (
deaths==0) {deaths=1;}
        new 
kdscore DEFAULT_SCORE kills deaths;
        new 
kds 10 - (kills deaths);
        if (
kds>0) { 
            
score = (score + (DEFAULT_SCORE kds)) / (kds+1); 
        }
        
score += kdscore;
    }
    return 
score;
}

getTeamWeight(team) {
    return 
getTeamWeightInt(getTeamTable(team), getTeamTableSize(team));
}
getTeamWeightInt(Handle:scoreTablesize) {
    new 
score 0;
    for (new 
i=0;i<size;i++) {
        
score+=GetArrayCell(scoreTablei0);
    }
    return 
score;
}


Handle:getTeamTable(team) {
    return (
team==CS_TEAM_T) ? s_teamTableT  s_teamTableCT;
}
getTeamTableSize(team) {
    return (
team==CS_TEAM_T) ? s_teamCountT  s_teamCountCT;
}
setTeamTableSize(teamsize) {
    if (
team==CS_TEAM_T)  {
        
s_teamCountT=size;
    } else {
        
s_teamCountCT=size;
    }
}

getImbalanceRating(team) {    
    if (
s_continousMode) {
        if (
s_kills[team]==0) {
            return 
0;
        } else {
            new 
weightTeam     getTeamWeight(team);
            new 
weightOpponent getTeamWeight(getOpposingTeamOf(team));
            if (
weightOpponent==0) {weightOpponent=1;} 
            return 
s_kills[team] * weightTeam weightOpponent;
        }
    } else {
        if (
s_streak[team]==0) {
            return 
0;
        } else {
            new 
weightTeam     getTeamWeight(team);
            new 
weightOpponent getTeamWeight(getOpposingTeamOf(team));
            if (
weightOpponent==0) {weightOpponent=1;} 
            return 
s_streak[team] * weightTeam weightOpponent;
        }
    }
}

getDampingFactor() {
    return 
MIN_DAMPING GetConVarInt(s_dampingFactor);
}


public 
Action:consoleForceBalance(clientargs)
{
    
refreshRanking();
    if ((
s_teamCountCT+s_teamCountT)>0) {
    
        new 
String:outbuf[256]="";
        
        if (
s_teamCountT >(s_teamCountCT+1)) { balanceByMove(CS_TEAM_T true); Format(outbuf256"%sMoving player to team %s. ",  outbuf, (s_isCstrike) ? "CT" "B"); }
        if (
s_teamCountCT>(s_teamCountT +1)) { balanceByMove(CS_TEAM_CTtrue); Format(outbuf256"%sMoving player to team %s. ",  outbuf, (s_isCstrike) ? "T" "A"); }
        
        new 
tTeamWeight  getTeamWeight(CS_TEAM_T); 
        new 
ctTeamWeight getTeamWeight(CS_TEAM_CT);
        
        if (
tTeamWeight>(ctTeamWeight+(DEFAULT_SCORE/2))) {
            
balanceTeam(CS_TEAM_Ttrue);
            
Format(outbuf256"%sStrenghened team %s from %d to %d. "outbuf, (s_isCstrike) ? "CT" "B"ctTeamWeight-tTeamWeightgetTeamWeight(CS_TEAM_CT)-getTeamWeight(CS_TEAM_T));
        } else if (
ctTeamWeight>(tTeamWeight+(DEFAULT_SCORE/2))) {
            
balanceTeam(CS_TEAM_CTtrue);
            
Format(outbuf256"%sStrenghened team %d from %d to %d. "outbuf, (s_isCstrike) ? "T" "A"tTeamWeight-ctTeamWeightgetTeamWeight(CS_TEAM_T)-getTeamWeight(CS_TEAM_CT));
        } else {
            
Format(outbuf256"%sTeams are sufficiently balanced."outbuf);
        }
        
PrintToConsole(client"%s"outbuf);
    } else {
        
PrintToConsole(client"%s""No players -> no balance.");
    }
    return 
Plugin_Handled;
}

printScoreTable(Handle:scoreTablesizeclientConsole) {
    for (new 
i=0;i<size;i++) {
        new 
pointsGetArrayCell(scoreTablei0);
        new 
clientGetArrayCell(scoreTablei1);
        if (
isValidPlayer(client)) {
            new 
String:name[20] = ""GetClientName(clientname20);
            
PrintToConsole(clientConsole,"%d: %s (%d)"pointsnames_lastSwitch[client]);
        } else {
            
PrintToConsole(clientConsole,"--- (id %d)"client);
        }
    }
}

public 
Action:consoleDbgCmd(clientargs)
{
    
refreshRanking();
    
PrintToConsole(client,"Team 1:");
    
printScoreTable(s_teamTableT s_teamCountTclient );
    
PrintToConsole(client,"Team 2:");
    
printScoreTable(s_teamTableCTs_teamCountCTclient);
    
    
PrintToConsole(client,"1 score %d, weight %d, score weight %d, members %d, imbalance rate %d"GetTeamScore(CS_TEAM_T ), getTeamWeight(CS_TEAM_T ), (s_continousMode) ? s_kills[CS_TEAM_T ]  : s_streak[CS_TEAM_T ] , s_teamCountT getImbalanceRating(CS_TEAM_T ));
    
PrintToConsole(client,"2 score %d, weight %d, score weight %d, members %d, imbalance rate %d"GetTeamScore(CS_TEAM_CT), getTeamWeight(CS_TEAM_CT), (s_continousMode) ? s_kills[CS_TEAM_CT ] : s_streak[CS_TEAM_CT ], s_teamCountCTgetImbalanceRating(CS_TEAM_CT)); 
    return 
Plugin_Handled;
}

bool:isPluginActive()
{
    return ((
GetConVarInt(s_activatePlugin)!=0) && !s_isWarmup);


Last edited by Darkwob; 08-29-2020 at 05:07.
Darkwob is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 03:07.


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