Raised This Month: $32 Target: $400
 8% 

[ANY] How to properly switch team


Post New Thread Reply   
 
Thread Tools Display Modes
Benoist3012
Veteran Member
Join Date: Mar 2014
Location: CWave::ForceFinish()
Old 04-02-2019 , 12:14   Re: [ANY] How to properly switch team
Reply With Quote #11

Quote:
Originally Posted by Whai View Post
For switch to spectator team, you can just use that :
Again, your snippet, while it might work for this particular use case, just remains a workaround the many hidden rules one game might have when using
PHP Code:
TF2_ChangeClientTeam 
or
PHP Code:
TF2_RespawnPlayer 
Here you miss the point that my snippet is all about switching a player's team, without changing their current state or calling any game functions.


Quote:
Originally Posted by Whai View Post
because with your method, we have to check offsets every updates
PHP Code:
CTeam 
hasn't changed in years by Valve, the vtable offsets used today are likely to be still valid in 20 years from now.

Quote:
Originally Posted by Whai View Post
If you want to change team but not in spectator, just use this
I'm already aware of this method, I've been using it myself for as long as I can remember
https://github.com/Kenzzer/Slender-F...stocks.sp#L600

Again this misses the point of this snippet, here it's provide something that will work "universally" across all source games. (hence the tag [ANY])
You're not safe from a game where the dev decided that they don't care if the player is alive or not, and will make the player respawn anyway regardless of their state/team upon calling sourcemod's
PHP Code:
ChangeClientTeam 


While on the other hand the snippet I provided will work, regardless of the set of "hidden" rules behind the function
PHP Code:
ChangeClientTeam 
__________________

Last edited by Benoist3012; 04-02-2019 at 12:16.
Benoist3012 is offline
gubka
Veteran Member
Join Date: Jan 2012
Location: Russia
Old 04-03-2019 , 09:22   Re: [ANY] How to properly switch team
Reply With Quote #12

FOR CS:GO
Quote:
void ToolsSetClientTeam(int clientIndex, int iValue)
{
// Validate team
if(GetClientTeam(clientIndex) <= TEAM_SPECTATOR)
{
// Sets team of the client
ChangeClientTeam(clientIndex, iValue);
}
else
{
// Switch team of the client
CS_SwitchTeam(clientIndex, iValue);
}
}
__________________
gubka is offline
Send a message via ICQ to gubka
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
eyal282
Veteran Member
Join Date: Aug 2011
Old 10-10-2019 , 03:37   Re: [ANY] How to properly switch team
Reply With Quote #14

In CS:GO when using m_iTeamNum it doesn't crash, however it kicks me to my previous team. I assume this will allow ghost spectators
__________________
I am available to make plugins for pay.

Discord: Eyal282#1334
eyal282 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 16:47.


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