Veteran Member
|
02-03-2009
, 06:24
[Incomplete Plugin] Simple Team Balancer
|
#1
|
This was a simple team balancer that I'm most likely never going to complete as well. The idea behind the balancing algorithm is averages in score differences.
It also tries to truly enforce randomization of teams, if force auto-assign is enabled it allows the player to select any team, but ultimately forces them to a team based on what team would result in them being number balanced.
This also enforces players REMAIN on their assigned teams
This can also enforce a map change to next map in mapcycle if the win difference is too high
Planned features:
Admin immunity
a "buddy feature" (similar to antithysis' simple team balancer)
Upgrade to win difference so as to include "rounds in a row won" as well.
Note: This is currently fairly bugged and is not perfect, but certain features do work.
Code:
#pragma semicolon 1
#pragma dynamic 65536
#include <sourcemod>
#include <cstrike>
#include <sdktools>
#define DEFAULTCOLOR 0x01
#define GREEN 0x04
#define FMTB_VERSION "1.0.0"
public Plugin:myinfo =
{
name = "FlyingMongoose's Team Balancer",
author = "FlyingMongoose",
description = "Team Balancer for Counter-Strike: Source",
version = FMTB_VERSION,
url = "http://www.interwavestuiods.com/"
}
new Handle:cvarForceAutoAssign;
new Handle:cvarRoundDifferenceBalance;
new Handle:cvarEnforceTeam;
new Handle:cvarWinDiffMapChange;
new iPlayersTeam[MAXPLAYERS + 1];
new iLastBalanced[4];
new iMaxClients;
new RoundStartTime;
public OnPluginStart()
{
CreateConVar("fmtb_version",FMTB_VERSION, _,FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY);
cvarForceAutoAssign = CreateConVar("fmtb_forceautoassign","1","Turns force auto assign on or off",FCVAR_PLUGIN,true,0.0,true,1.0);
cvarRoundDifferenceBalance = CreateConVar("fmtb_rounddifference","3","The difference in score between teams for a balance to occur. Setting to 0 disables the balancer.",FCVAR_PLUGIN,true,0.0,false);
cvarEnforceTeam = CreateConVar("fmtb_enforceteam","1","Enforces player stay on the team they were either balanced to or auto-assigned to",FCVAR_PLUGIN,true,0.0,true,1.0);
cvarWinDiffMapChange = CreateConVar("fmtb_windifferencemapchange","8","Number of wins difference before a map will change.",FCVAR_PLUGIN,true,0.0,false);
HookEvent("player_team",ev_PlayerTeam,EventHookMode_Post);
HookEvent("round_end",ev_RoundEnd,EventHookMode_Post);
HookEvent("round_start",ev_RoundStart,EventHookMode_Pre);
}
public OnMapStart()
{
iMaxClients = GetMaxClients();
}
public OnMapEnd()
{
for(new i = 0; i <= iMaxClients; i++) {
iPlayersTeam[i] = 0;
}
}
public OnClientDisconnect_Post(client)
{
if (iLastBalanced[iPlayersTeam[client]] == client)
iLastBalanced[iPlayersTeam[client]] = 0;
iPlayersTeam[client] = 0;
}
public OnConfigsExecuted()
{
AutoExecConfig(true,"fmtb","sourcemod");
}
public Action:Timer_DelayMapChange(Handle:timer, Handle:NextMapPack)
{
decl String:NextMap[255];
ResetPack(NextMapPack,false);
ReadPackString(NextMapPack,NextMap,sizeof(NextMap));
ServerCommand("changelevel %s",NextMap);
}
public Action:ev_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
new CTScore = GetTeamScore(CS_TEAM_CT);
new TScore = GetTeamScore(CS_TEAM_T);
new scoreDiff = RoundFloat(FloatAbs(float(CTScore - TScore)));
new winDiffMapChange = GetConVarInt(cvarWinDiffMapChange);
if(winDiffMapChange > 0)
{
if(scoreDiff >= winDiffMapChange)
{
decl String:NextMap[255];
GetNextMap(NextMap,sizeof(NextMap));
PrintToChatAll("%c[FMTB]%c The score difference is too high, the map is changing in 5 seconds.",GREEN,DEFAULTCOLOR);
new Handle:NextMapPack = CreateDataPack();
WritePackString(NextMapPack,NextMap);
CreateTimer(5.0,Timer_DelayMapChange,NextMapPack);
}
}
new scoreDiffBal = GetConVarInt(cvarRoundDifferenceBalance);
if(scoreDiffBal > 0)
{
if (CTScore + TScore != 0)
{
if (scoreDiff >= scoreDiffBal) {
new winningteam, losingteam;
if (CTScore > TScore) {
winningteam = CS_TEAM_CT;
losingteam = CS_TEAM_T;
} else {
winningteam = CS_TEAM_T;
losingteam = CS_TEAM_CT;
}
new balanceWPlayer = FindScoreDifference(winningteam, true);
new balanceLPlayer = FindScoreDifference(losingteam, false);
if (balanceWPlayer != 0 && balanceLPlayer !=0) {
iPlayersTeam[balanceLPlayer] = winningteam;
iPlayersTeam[balanceWPlayer] = losingteam;
iLastBalanced[losingteam] = balanceWPlayer;
iLastBalanced[winningteam] = balanceLPlayer;
if(iPlayersTeam[balanceWPlayer] == CS_TEAM_CT)
{
GetPlayerWeaponSlot(balanceWPlayer,5);
ClientCommand(balanceWPlayer,"slot5; wait; slot5; wait; slot5; wait; drop");
}
CS_SwitchTeam(balanceWPlayer, iPlayersTeam[balanceWPlayer]);
if(iPlayersTeam[balanceLPlayer] == CS_TEAM_CT)
{
GetPlayerWeaponSlot(balanceLPlayer,5);
ClientCommand(balanceLPlayer,"slot5; wait; slot5; wait; slot5; wait; drop");
}
CS_SwitchTeam(balanceLPlayer, iPlayersTeam[balanceLPlayer]);
PrintToChat(balanceWPlayer,"%c[FMTB]%c You have been balanced to the other team.",GREEN,DEFAULTCOLOR);
PrintToChat(balanceLPlayer,"%c[FMTB]%c You have been balanced to the other team.",GREEN,DEFAULTCOLOR);
}
}
}
}
new CTCount = GetTeamClientCount(CS_TEAM_CT);
new TCount = GetTeamClientCount(CS_TEAM_T);
new playerDifferences = RoundFloat(FloatAbs(float(CTCount - TCount)));
if(playerDifferences >= 2)
{
if(CTCount < TCount)
{
for(new i = 1; i <= iMaxClients; i++)
{
if(CTCount == TCount || CTCount == TCount + 1 || CTCount == TCount - 1)
{
break;
}
if(i != 0 && IsClientConnected(i) && IsClientInGame(i) && CS_TEAM_T == GetClientTeam(i))
{
iPlayersTeam[i] = CS_TEAM_T;
PrintToChat(i,"%c[FMTB]%c You have been balanced to the other team.",GREEN,DEFAULTCOLOR);
CS_SwitchTeam(i,CS_TEAM_T);
}
}
}
if(CTCount > TCount)
{
for(new i = 1; i <= iMaxClients; i++)
{
if(CTCount > TCount)
{
if(CTCount == TCount || CTCount == TCount + 1 || CTCount == TCount - 1)
{
break;
}
if(i != 0 && IsClientConnected(i) && IsClientInGame(i) && CS_TEAM_CT == GetClientTeam(i)){
GetPlayerWeaponSlot(i,5);
ClientCommand(i,"slot5; wait; slot5; wait; slot5; wait; drop");
PrintToChat(i,"%c[FMTB]%c You have been balanced to the other team.",GREEN,DEFAULTCOLOR);
CS_SwitchTeam(i,CS_TEAM_CT);
}
}
}
}
}
}
public Action:ev_PlayerTeam(Handle:event,const String:name[],bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event,"userid"));
if (client != 0 && !IsClientConnected(client) && !IsClientInGame(client))
return Plugin_Handled;
new team = GetEventInt(event,"team");
if (team <= 1)
return Plugin_Continue;
if (iPlayersTeam[client] == 0 && GetConVarInt(cvarForceAutoAssign) == 1 && iLastBalanced[CS_TEAM_CT] != client && iLastBalanced[CS_TEAM_T] != client) {
CreateTimer(0.5, Timer_DelaySelectTeam, client, TIMER_FLAG_NO_MAPCHANGE);
PrintToChat(client,"%c[FMTB]%c You have been force auto-assigned.",GREEN,DEFAULTCOLOR);
return Plugin_Continue;
}
if (iPlayersTeam[client] != team && GetConVarInt(cvarEnforceTeam) == 1 && iLastBalanced[CS_TEAM_CT] != client && iLastBalanced[CS_TEAM_T] != client) {
CreateTimer(0.5, Timer_DelaySwitchTeam, client, TIMER_FLAG_NO_MAPCHANGE);
PrintToChat(client,"%c[FMTB]%c You are not allowed to change teams.",GREEN,DEFAULTCOLOR);
return Plugin_Continue;
}
return Plugin_Continue;
}
public Action:ev_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
RoundStartTime = GetTime();
}
public Action:Timer_DelaySelectTeam(Handle:timer, any:client)
{
iPlayersTeam[client] = SelectTeam();
if(iPlayersTeam[client] < 0){
if(RoundFloat(float(GetTime() - RoundStartTime)) > 45)
{
CreateTimer(0.5,Timer_DelayRespawn,client);
}
if(iPlayersTeam[client] == CS_TEAM_CT)
{
GetPlayerWeaponSlot(client,5);
ClientCommand(client,"slot5; wait; slot5; wait; slot5; wait; drop");
}
CS_SwitchTeam(client, iPlayersTeam[client]);
}
return Plugin_Handled;
}
public Action:Timer_DelayRespawn(Handle:timer, any:client)
{
CS_RespawnPlayer(client);
}
public Action:Timer_DelaySwitchTeam(Handle:timer, any:client)
{
if(iPlayersTeam[client] == CS_TEAM_CT)
{
new bombIndex = GetPlayerWeaponSlot(client,5);
if(bombIndex > -1)
{
EquipPlayerWeapon(client,bombIndex);
ClientCommand(client,"slot5; wait; slot5; wait; slot5; wait; drop");
}
}
CS_SwitchTeam(client, iPlayersTeam[client]);
iLastBalanced[iPlayersTeam[client]] = 0;
return Plugin_Handled;
}
stock SelectTeam()
{
new CTCount = GetTeamClientCount(CS_TEAM_CT);
new TCount = GetTeamClientCount(CS_TEAM_T);
new Team = 0;
if(CTCount == TCount){
Team = -1;
} else if (CTCount > TCount){
Team = CS_TEAM_T;
} else if (CTCount < TCount){
Team = CS_TEAM_CT;
} else {
Team = GetRandomInt(CS_TEAM_T, CS_TEAM_CT);
}
return Team;
}
stock FindScoreDifference(teamIndex,bool:isLowest)
{
new currClientDiff;
new lastClientDiff = 0;
new client = 0;
new teamavg = GetTeamAverage(teamIndex);
if(teamavg != 0){
if(isLowest) {
for(new i = 1; i <= iMaxClients; i++) {
if(IsClientInGame(i)
&& GetClientTeam(i) == teamIndex) {
currClientDiff = GetClientFrags(i) - GetClientDeaths(i);
if(currClientDiff <= teamavg
&& currClientDiff <= lastClientDiff
&& iLastBalanced[CS_TEAM_CT] != i
&& iLastBalanced[CS_TEAM_T] != i) {
lastClientDiff = GetClientFrags(i) - GetClientDeaths(i);
client = i;
}
}
}
} else if(!isLowest){
for(new i = 1; i <= iMaxClients; i++){
if(IsClientInGame(i)
&& GetClientTeam(i) == teamIndex) {
currClientDiff = GetClientFrags(i) - GetClientDeaths(i);
if(currClientDiff >= teamavg
&& currClientDiff >= lastClientDiff
&& iLastBalanced[CS_TEAM_CT] != i
&& iLastBalanced[CS_TEAM_T] != i) {
lastClientDiff = GetClientFrags(i) - GetClientDeaths(i);
client = i;
}
}
}
}
iLastBalanced[teamIndex] = client;
return client;
}else{
return 0;
}
}
stock GetTeamAverage(teamIndex)
{
new ScoreCount;
for(new i = 1; i <= iMaxClients; i++) {
if(IsClientInGame(i) && GetClientTeam(i) == teamIndex) {
ScoreCount = (GetClientFrags(i) - GetClientDeaths(i)) + ScoreCount;
}
}
new teamCount = GetTeamClientCount(teamIndex);
if(teamCount > 0){
new AverageScore = ScoreCount/GetTeamClientCount(teamIndex);
return AverageScore;
}else{
return 0;
}
}
I will not provide tech support for this, however I will provide support in the form of answers to questions provided by whomever wishes to pick up where I left off.
__________________
|
|