View Single Post
PC Gamer
Veteran Member
Join Date: Mar 2014
Old 10-08-2019 , 15:51   Re: [ANY] How to properly switch team
Reply With Quote #13

Benoist3012,

I've used your changeteam code snippets in several of my TF2 plugins with much success. Using your code allows me to change players teams without the Server crashing. However, I notice that sometimes when I change a players team to the 'gray' team one or two other players will sometimes time out and have to rejoin the Server. One other rare issue is that sometimes players are left in spectate when they die while gray. It doesn't happen very often.

Can review the code below to see what, if anything, I may be doing wrong?

Code:
#pragma semicolon 1

#include <sdktools>
#include <tf2_stocks>

#define PLUGIN_VERSION "1.0" 

#define TEAM_CLASSNAME "tf_team"

Handle g_hSDKTeamAddPlayer;
Handle g_hSDKTeamRemovePlayer;

public Plugin:myinfo =  
{ 
	name = "Change Team", 
	author = "Benoist3012 and PC Gamer",
	description = "Change Player Team", 
	version = PLUGIN_VERSION, 
	url = "www.sourcemod.com" 
} 

public void OnPluginStart()
{
	LoadTranslations("common.phrases");

	Handle hGameData = LoadGameConfigFile("changeteam");
	
	StartPrepSDKCall(SDKCall_Entity);
	PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "CTeam::AddPlayer");
	PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer);
	g_hSDKTeamAddPlayer = EndPrepSDKCall();
	if(g_hSDKTeamAddPlayer == INVALID_HANDLE)
	SetFailState("Could not find CTeam::AddPlayer!");
	
	StartPrepSDKCall(SDKCall_Entity);
	PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "CTeam::RemovePlayer");
	PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer);
	g_hSDKTeamRemovePlayer = EndPrepSDKCall();
	if(g_hSDKTeamRemovePlayer == INVALID_HANDLE)
	SetFailState("Could not find CTeam::RemovePlayer!");
	
	delete hGameData;
	
	RegAdminCmd("sm_ctred", Command_changeteamred, ADMFLAG_SLAY, "Change a player to Red team");
	RegAdminCmd("sm_ctblue", Command_changeteamblue, ADMFLAG_SLAY, "Change a player to Blue team"); 
	RegAdminCmd("sm_ctgray", Command_changeteamgray, ADMFLAG_SLAY, "Change a player to Gray team");
	RegAdminCmd("sm_ctgrey", Command_changeteamgray, ADMFLAG_SLAY, "Change a player to Grey team");
	RegAdminCmd("sm_nospec", Command_MoveSpec, ADMFLAG_SLAY, "Move all players from spec to a team"); 
	RegAdminCmd("sm_noafk", Command_MoveSpec, ADMFLAG_SLAY, "Move all players from spec to a team");    	
}

public Action:Command_changeteamred(client, args) 
{ 
	decl String:arg1[32]; 
	if (args < 1) 
	{ 
		arg1 = "@me"; 
	} 
	else GetCmdArg(1, arg1, sizeof(arg1)); 
	new String:target_name[MAX_TARGET_LENGTH]; 
	new target_list[MAXPLAYERS], target_count; 
	new bool:tn_is_ml; 

	if ((target_count = ProcessTargetString( 
		arg1, 
		client, 
		target_list, 
		MAXPLAYERS, 
		COMMAND_FILTER_ALIVE|(args < 1 ? COMMAND_FILTER_NO_IMMUNITY : 0), 
		target_name, 
		sizeof(target_name), 
		tn_is_ml)) <= 0) 
	{ 
		ReplyToTargetError(client, target_count); 
		return Plugin_Handled; 
	} 
	for (new t = 0; t < target_count; t++) 
	{ 
		ChangeClientTeamEx(target_list[t], 2);     
		LogAction(client, target_list[t], "\"%L\" made \"%L\" change to the Red team", client, target_list[t]); 
		PrintToChat(target_list[t], "You were changed to Red team");
	} 
	return Plugin_Handled; 
} 

public Action:Command_changeteamblue(client, args) 
{ 
	decl String:arg1[32]; 
	if (args < 1) 
	{ 
		arg1 = "@me"; 
	} 
	else GetCmdArg(1, arg1, sizeof(arg1)); 
	new String:target_name[MAX_TARGET_LENGTH]; 
	new target_list[MAXPLAYERS], target_count; 
	new bool:tn_is_ml; 

	if ((target_count = ProcessTargetString( 
		arg1, 
		client, 
		target_list, 
		MAXPLAYERS, 
		COMMAND_FILTER_ALIVE|(args < 1 ? COMMAND_FILTER_NO_IMMUNITY : 0), 
		target_name, 
		sizeof(target_name), 
		tn_is_ml)) <= 0) 
	{ 
		ReplyToTargetError(client, target_count); 
		return Plugin_Handled; 
	} 
	for (new t = 0; t < target_count; t++) 
	{ 
		ChangeClientTeamEx(target_list[t], 3);     
		LogAction(client, target_list[t], "\"%L\" made \"%L\" change to the Blue team", client, target_list[t]); 
		PrintToChat(target_list[t], "You were changed to Blue team");
	} 
	return Plugin_Handled; 
} 

public Action:Command_changeteamgray(client, args) 
{ 
	decl String:arg1[32]; 
	if (args < 1) 
	{ 
		arg1 = "@me"; 
	} 
	else GetCmdArg(1, arg1, sizeof(arg1)); 
	new String:target_name[MAX_TARGET_LENGTH]; 
	new target_list[MAXPLAYERS], target_count; 
	new bool:tn_is_ml; 

	if ((target_count = ProcessTargetString( 
		arg1, 
		client, 
		target_list, 
		MAXPLAYERS, 
		COMMAND_FILTER_ALIVE|(args < 1 ? COMMAND_FILTER_NO_IMMUNITY : 0), 
		target_name, 
		sizeof(target_name), 
		tn_is_ml)) <= 0) 
	{ 
		ReplyToTargetError(client, target_count); 
		return Plugin_Handled; 
	} 
	for (new t = 0; t < target_count; t++) 
	{ 
		ChangeClientTeamEx(target_list[t], 0);     
		LogAction(client, target_list[t], "\"%L\" made \"%L\" change to the Gray team", client, target_list[t]); 
		PrintToChat(target_list[t], "You were changed to Gray team");
	} 
	return Plugin_Handled; 
} 


void ChangeClientTeamEx(iClient, int iNewTeamNum)
{
	int iTeamNum = GetEntProp(iClient, Prop_Send, "m_iTeamNum");
	
	// Safely swap team
	int iTeam = MaxClients+1;
	while ((iTeam = FindEntityByClassname(iTeam, TEAM_CLASSNAME)) != -1)
	{
		int iAssociatedTeam = GetEntProp(iTeam, Prop_Send, "m_iTeamNum");
		if (iAssociatedTeam == iTeamNum)
		SDK_Team_RemovePlayer(iTeam, iClient);
		else if (iAssociatedTeam == iNewTeamNum)
		SDK_Team_AddPlayer(iTeam, iClient);
	}
	
	SetEntProp(iClient, Prop_Send, "m_iTeamNum", iNewTeamNum);
}

void SDK_Team_AddPlayer(int iTeam, int iClient)
{
	if (g_hSDKTeamAddPlayer != INVALID_HANDLE)
	{
		SDKCall(g_hSDKTeamAddPlayer, iTeam, iClient);
	}
}

void SDK_Team_RemovePlayer(int iTeam, int iClient)
{
	if (g_hSDKTeamRemovePlayer != INVALID_HANDLE)
	{
		SDKCall(g_hSDKTeamRemovePlayer, iTeam, iClient);
	}
}

//This part adds in AFKtoTeam
public Action:Command_MoveSpec(client, args) {
	new ClientTeam;
	
	for (new i = 1; i <= MaxClients; i++) {
		if (IsClientConnected(i) && IsClientInGame(i)) {
			ClientTeam = GetClientTeam(i);
			if (ClientTeam == _:TFTeam_Unassigned || ClientTeam == _:TFTeam_Spectator) {
				new RedCount = GetTeamClientCount(_:TFTeam_Red);
				new BlueCount = GetTeamClientCount(_:TFTeam_Blue);
				
				if(BlueCount < RedCount) {
					JoinTeam(i, TFTeam_Blue);
				} else {
					JoinTeam(i, TFTeam_Red);
				}
			}
		}
	}
}

/* Returns false if client couldn't join any team. true otherwise */
bool:JoinTeam(client, TFTeam:team) {
	new ClientTeam;
	
	ChangeClientTeam(client, _:team);
	ClientTeam = GetClientTeam(client);
	
	if (ClientTeam == _:TFTeam_Unassigned || ClientTeam == _:TFTeam_Spectator) {
		//If Client was unable to join team try the other team.
		if(team == TFTeam_Red) {
			ChangeClientTeam(client, _:TFTeam_Blue);
		} else {
			ChangeClientTeam(client, _:TFTeam_Red);
		}
		ClientTeam = GetClientTeam(client);
		if (ClientTeam == _:TFTeam_Unassigned || ClientTeam == _:TFTeam_Spectator) {
			
			return false;
		}
	}
	SetClass(client);
	
	return true;
}

SetClass(client) {
	TF2_SetPlayerClass(client, TFClassType:GetRandomInt(1, 9), false);
}
PC Gamer is offline