Raised This Month: $ Target: $400
 0% 

Half-Life Auto Team Balancer Does Not Work Correctly


  
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Author Message
AN0TH3R
Junior Member
Join Date: Feb 2020
Old 05-15-2020 , 06:55   Half-Life Auto Team Balancer Does Not Work Correctly
Reply With Quote #1

I found an auto team balancer plugin for my new Half-Life TDM server. But plugin does not work correctly on my server. Teams were not balancing when 1v1. I tried different cvars like mp_teamplay 1 and mp_teamplay 2. (I already wrote mp_teamlist "gman;gordon") I hope you can help me.

Code:
/*	AMX Mod X script.

	http://aghl.ru/forum/ - Russian Half-Life and Adrenaline Gamer Community

	AutoTeam Blancer plugin for Half-Life by Lev.

	URL: http://aghl.ru/forum/viewtopic.php?f=19&t=638

	Info:
		Plugin balances teams trying to keep teams equals by players counts.
		Takes into account: players counts, spectators, hltv.
		Transfers last connected player or player with least score.
		Plugin works only if mp_teamplay is 1 and mp_teamlist is set.
		Correctly works with any amount of teams and any team names.
		
	CVARs:
		teambalancer_exclude "abc" // (default = "c") Flags that excludes player from being transferred by auto team balancing. Flags on bots are ignored.
		teambalancer_balancebots "1" // (default = "1") Bots are allowed to be transfered in balancing process.
		teambalancer_botsfirst "1" // (default = "1") Bots are preffered before players to transfer.

	Installation:
		put hl_auto_team_balancer.amxx to plugins folder;
		add hl_auto_team_balancer.amxx to config\plugins.ini file.

	Thanks to:
		koko76 for bug reporting.

	Change Log:
		v1.1 [2012.01.30]
			Initial release.
		v1.2 [2012.02.04]
			[!] Change: access flags on bots are ignored.
			[+] Added: new cvars to regulate bots transferring.
			[!] Fixed: possible crash with 32 players.
		v1.3 [2012.02.05]
			[!] Fixed: bug in balancer code (thanks to koko76).
		v1.4 [2012.02.06]
			[!] Fixed: minor bug in balancer code.

*/

#pragma semicolon 1
#pragma ctrlchar '\'

#include <amxmodx>
#include <amxmisc>
#include <fakemeta_util>

#define AUTHOR "Lev"
#define PLUGIN "HL Auto Team Balancer"
#define VERSION "1.4"
#define VERSION_CVAR "hlautoteambalancer_version"

// Compilation options
//#define _DEBUG		// Enable debug output at server console.

#define MAX_TEAMS		32
#define MAX_TEAMNAME	16
#define MAX_PLAYERS		32

enum PlayerInfo
{
	PiId,
	PiIsBot,
	PiTeamId,
	PiFrags,
	PiDeaths
}

new _playerInfo[MAX_PLAYERS + 1][PlayerInfo];
new _teamNames[MAX_TEAMS][MAX_TEAMNAME + 1];
new _teams;
new _counts[MAX_TEAMS], _frags[MAX_TEAMS], _deaths[MAX_TEAMS];
new pcvar_teambalancer_exclude, pcvar_teambalancer_balancebots, pcvar_teambalancer_botsfirst;

public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR);
	register_cvar(VERSION_CVAR, VERSION, FCVAR_SPONLY | FCVAR_SERVER | FCVAR_UNLOGGED);

	pcvar_teambalancer_exclude		= register_cvar("teambalancer_exclude", "c");		// Flags that excludes player from being transferred by auto team balancing. Flags on bots are ignored.
	pcvar_teambalancer_balancebots	= register_cvar("teambalancer_balancebots", "1");	// Bots are allowed to be transfered in balancing process.
	pcvar_teambalancer_botsfirst	= register_cvar("teambalancer_botsfirst", "1");		// Bots are preffered before players to transfer.

#if defined _DEBUG
	register_concmd("bal", "BalanceTeamsByCount");
#endif

	GetTeamNames();

	if (!get_cvar_num("mp_teamplay") || _teams == 0)
	{
		log_amx("Current mode is not team play or team list is not limited. Plugin is paused...");
		pause("ad");
		return;
	}
}

public client_putinserver(id)
{
	set_task(0.2, "BalanceTeamsByCount", id);
}

public client_command(id)
{
	new cmd[33];
	read_argv(0, cmd, charsmax(cmd));

	if (equal(cmd, "spectate"))
		set_task(0.2, "BalanceTeamsByCount");

	return PLUGIN_CONTINUE;
}

public client_infochanged(id)
{
	new teamId = get_user_team(id) - 1;
	new i = 0;
	// Find previous player team
	while(_playerInfo[i][PiId])
	{
		if (_playerInfo[i][PiId] == id)
		{
			if (_playerInfo[i][PiTeamId] != teamId)
			{
#if defined _DEBUG
				server_print("Team change detected: player %i, prev team: %i, new team: %i", id, _playerInfo[i][PiTeamId], teamId);
#endif
				BalanceTeamsByCount(id);
			}
			break;
		}
		i++;
	}
}

public client_disconnect(id)
{
	set_task(0.2, "BalanceTeamsByCount", 0);
}

public BalanceTeamsByCount(idLast)
{
#if defined _DEBUG
	server_print("idLast: %i", idLast);
#endif
	RecountTeams();

	static i, id, j, selected, maxPlayers, minPlayers, largestTeamId, smallestTeamId, minFrags, minFragsSet, flagsStr[33], flags, teambalancer_balancebots, teambalancer_botsfirst;
	maxPlayers = 0;
	minPlayers = MAX_PLAYERS;
	largestTeamId = 0;
	smallestTeamId = 0;
	for (j = 0; j < _teams; j++)
	{
		if (_counts[j] > maxPlayers)
		{
			maxPlayers = _counts[j];
			largestTeamId = j;
		}
		if (_counts[j] < minPlayers)
		{
			minPlayers = _counts[j];
			smallestTeamId = j;
		}
	}
#if defined _DEBUG
	server_print("Largest team %i %s: count: %i", largestTeamId, _teamNames[largestTeamId], maxPlayers);
	server_print("Smallest team %i %s: count: %i", smallestTeamId, _teamNames[smallestTeamId], minPlayers);
#endif

	if (maxPlayers - minPlayers > 1)
	{
#if defined _DEBUG
		server_print("Going to find player to transfer...");
#endif
		get_pcvar_string(pcvar_teambalancer_exclude, flagsStr, charsmax(flagsStr));
		flags = read_flags_fixed(flagsStr);
		i = 0;
		id = 0;
		selected = 0;
		minFrags = 0;
		minFragsSet = 0;
		teambalancer_balancebots = get_pcvar_num(pcvar_teambalancer_balancebots);
		teambalancer_botsfirst = get_pcvar_num(pcvar_teambalancer_botsfirst);
		// Select player from largest team to transfer
		while(_playerInfo[i][PiId])
		{
			if (!teambalancer_balancebots && _playerInfo[i][PiIsBot]) continue;	// Skip bots
			if (_playerInfo[i][PiTeamId] == largestTeamId)
			{
#if defined _DEBUG
				server_print("Testing player %i, flags: %i, %i, is bot: %i, selected: %i, minFragsSet: %i, minFrags: %i", _playerInfo[i][PiId], get_user_flags(_playerInfo[i][PiId]), get_user_flags(_playerInfo[i][PiId]) & flags, _playerInfo[i][PiIsBot], selected, minFragsSet, minFrags);
#endif
				// If bots are first we will pick bot regardless of the score and who was last
				if (teambalancer_botsfirst && _playerInfo[i][PiIsBot])
				{
					id = _playerInfo[i][PiId];
#if defined _DEBUG
					server_print("Selected %i: because bots are first", id);
#endif
					break;
				}
				if (selected) { i++; continue; }	// We have found last player within the largest team so we will need to check others only if a bot can be found
				// If last player is within largest team we will transfer him
				if (_playerInfo[i][PiId] == idLast && get_user_flags(idLast) & flags == 0)
				{
					id = idLast;
					selected = 1;
#if defined _DEBUG
					server_print("Selected %i: cos was last", id);
#endif
					if (!teambalancer_botsfirst) break;	// If don't need to find a bot - break
					i++;
					continue;
				}
				// Select player from largest team with lowest frags
				if ((!minFragsSet || _playerInfo[i][PiFrags] < minFrags) &&
					(_playerInfo[i][PiIsBot] || get_user_flags(_playerInfo[i][PiId]) & flags == 0))	// Ignore access flags on bots
				{
					minFragsSet = 1;
					minFrags = _playerInfo[i][PiFrags];
					id = _playerInfo[i][PiId];
#if defined _DEBUG
					server_print("Selected %i: with %i frags", id, minFrags);
#endif
				}
			}
			i++;
		}
		if (id)
		{
#if defined _DEBUG
			server_print("Transferring %i to %s", id, _teamNames[smallestTeamId]);
#endif
			set_user_info(id, "model", _teamNames[smallestTeamId]);
			client_cmd(id,"model \"%s\"", _teamNames[smallestTeamId]);
		}
	}
}

RecountTeams()
{
	static players[MAX_PLAYERS], num;
	static i, j, id, teamId;
	get_players(players, num);
	for (j = 0; j < _teams; j++)
	{
		_counts[j] = 0;
		_frags[j] = 0;
		_deaths[j] = 0;
	}
	for (i = 0; i < num; i++)
	{
		id = players[i];
		teamId = get_user_team(id) - 1;
		_playerInfo[i][PiId] = id;
		_playerInfo[i][PiIsBot] = is_user_bot(id);
		_playerInfo[i][PiTeamId] = teamId;
		_playerInfo[i][PiFrags] = get_user_frags(id);
		_playerInfo[i][PiDeaths] = get_user_deaths(id);
#if defined _DEBUG
		server_print("PlayerInfo %i: id: %i, team id: %i, frags: %i, death: %i", i, _playerInfo[i][PiId], _playerInfo[i][PiTeamId], _playerInfo[i][PiFrags], _playerInfo[i][PiDeaths]);
#endif
		if (pev(id, pev_iuser1)) continue;				// Spectator.
		if (teamId < 0 || teamId >= _teams) continue;	// Team not set yet.
		_counts[teamId]++;
		_frags[teamId] += get_user_frags(id);
		_deaths[teamId] += get_user_deaths(id);
	}
	_playerInfo[i][PiId] = 0;	// End of the list
#if defined _DEBUG
	server_print("Stats:");
	for (j = 0; j < _teams; j++)
		server_print("Team %i: %s, counts: %i, frags: %i, deaths: %i", j, _teamNames[j], _counts[j], _frags[j], _deaths[j]);
#endif
}

GetTeamNames()
{
	new j, teams[MAX_TEAMS * MAX_TEAMNAME + 1], team[MAX_TEAMNAME + 1];
	get_cvar_string("mp_teamlist", teams, charsmax(teams));
	for (j = 0; j < MAX_TEAMS; j++)
	{
		strtok(teams, team, charsmax(team), teams, charsmax(teams), ';');
		if (team[0] == 0) break;
		copy(_teamNames[j], MAX_TEAMNAME, team);
		_teams++;
	}
#if defined _DEBUG
	server_print("Teams count: %i", _teams);
	for (j = 0; j < _teams; j++)
		server_print("Team %i name: %s", j, _teamNames[j]);
#endif
}

/// Converts string of flags into int.
/// Only chars from 'a' to 'z' are converted, others are skipped.
stock read_flags_fixed(const flags[])
{
	new result, i = 0;
	while (flags[i] != 0)
	{
		if (flags[i] >= 'a' && flags[i] <= 'z')
			result |= 1 << (flags[i] - 'a');
		i++;	
	}
	return result;
}
Attached Files
File Type: sma Get Plugin or Get Source (hl_auto_team_balancer.sma - 172 views - 9.1 KB)
AN0TH3R is offline
 



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 16:55.


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