Suggested changes:
- Respawn players later. You are currently respawning the players before they are placed on a team.
- Check if the team change was successful. A side effect of using "jointeam" is that the command does not place players on a team if the team is full. A team is full when there are not enough spawn points available.
ChangeClientTeam does not care if there are enough spawnpoints available. It will just spawn the player inside of a teammate. An additional check would be required in this case - mp_solid_teammates. I am uncertain if there are other side effects to using ChangeClientTeam instead of the ClientCommand like you have been doing, so I have not included this in the snippet below. Instead, I just LogError and move the player from the unassigned team to spectator.
PHP Code:
#include <cstrike>
#include <sdktools>
ConVar g_ConVar_GraceTime;
bool g_bSpawnAllowed = true;
bool g_bJoinTeamAllowed[MAXPLAYERS +1];
public Plugin myinfo = {
name = "[CSGO] Auto Team Assign",
author = "SM9();",
description = "Assigns a team automatically when player connects and bypasses team menu",
version = "1.0.3",
url = "https://sm9.dev"
};
public void OnPluginStart() {
HookEvent("round_start", Event_RoundStart);
HookEvent("round_end", Event_RoundEnd);
HookEvent("player_connect_full", Event_PlayerConnectFull);
AddCommandListener(CommandListener_JoinTeam, "jointeam");
g_ConVar_GraceTime = FindConVar("mp_join_grace_time");
}
public void OnMapStart() {
g_bSpawnAllowed = true;
}
Action CommandListener_JoinTeam(int client, const char[] command, int args) {
if (g_bJoinTeamAllowed[client]) {
g_bJoinTeamAllowed[client] = false;
RequestFrame(Frame_CheckClientTeam, GetClientUserId(client));
return Plugin_Continue;
}
return Plugin_Handled;
}
void Frame_CheckClientTeam(int userid) {
int client = GetClientOfUserId(userid);
if (!client) {
return;
}
int team = GetClientTeam(client);
if (team == CS_TEAM_NONE) {
ChangeClientTeam(client, CS_TEAM_SPECTATOR);
LogError("Failed to assign client to a team because the map does not have enough spawnpoints");
return;
}
if (!IsPlayerAlive(client) && team > CS_TEAM_SPECTATOR && (g_bSpawnAllowed || areTeamsEmpty())) {
CS_RespawnPlayer(client);
}
}
void Event_PlayerConnectFull(Event event, const char[] name, bool dontBroadcast) {
int client = GetClientOfUserId(event.GetInt("userid"));
g_bJoinTeamAllowed[client] = true;
ClientCommand(client, "jointeam 0 %i", determineTeam());
}
void Event_RoundStart(Event event, char[] name, bool dontBroadcast) {
bool warmupActive = isWarmupActive();
if (warmupActive || g_ConVar_GraceTime.BoolValue) {
g_bSpawnAllowed = true;
}
if (warmupActive) {
return;
}
CreateTimer(g_ConVar_GraceTime.FloatValue, Timer_GraceTimeOver, _, TIMER_FLAG_NO_MAPCHANGE);
}
void Event_RoundEnd(Event event, char[] name, bool dontBroadcast) {
g_bSpawnAllowed = false;
}
Action Timer_GraceTimeOver(Handle timer) {
g_bSpawnAllowed = false;
}
public void OnClientDisconnect(int client) {
g_bJoinTeamAllowed[client] = false;
if (!areTeamsEmpty()) {
return;
}
g_bSpawnAllowed = true;
}
bool isWarmupActive() {
return view_as<bool>(GameRules_GetProp("m_bWarmupPeriod"));
}
bool areTeamsEmpty() {
return !(GetTeamClientCount(CS_TEAM_T) + GetTeamClientCount(CS_TEAM_CT));
}
int determineTeam() {
int tCount = GetTeamClientCount(CS_TEAM_T);
int ctCount = GetTeamClientCount(CS_TEAM_CT);
return tCount == ctCount ? GetRandomInt(CS_TEAM_T, CS_TEAM_CT) : tCount < ctCount ? CS_TEAM_T : CS_TEAM_CT;
}