I was looking event "switch_team" which only human player can trigger,
this event tell you about
Code:
Server event "switch_team", Tick 24275:
- "numPlayers" = "1"
- "numSpectators" = "0"
- "avg_rank" = "0"
- "numTSlotsFree" = "4"
- "numCTSlotsFree" = "5"
These variables inform you how many free team slots are left, so human player can enter in team T or CT to play.
- CT/T teams max slot number is dynamic, it depends gamemodes
maxplayers count and how many map
spawn points.
As reminder, when server is using
maxplayers_override value, gamemodes maxplayers would not change anymore max player count.
In this plugin sample, command
sm_check mimic event "switch_team" calculation.
There are two SDKCalls:
MaxNumPlayersOnTerrTeam &
MaxNumPlayersOnCTTeam
These return team T and CT maximum slot count, how many players will fit in team. In that map, in that gamemode.
I just share this in here, if someone want test.
PHP Code:
/*
LINUX Signature for MaxNumPlayersOnTerrTeam_sub_B2B7C0:
55 89 E5 83 EC 18 89 5D F8 8B 5D 08 89 75 FC 89 1C 24 E8 ? ? ? ? 84 C0 74 ?
\x55\x89\xE5\x83\xEC\x18\x89\x5D\xF8\x8B\x5D\x08\x89\x75\xFC\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x84\xC0\x74\x2A
Linux Signature for MaxNumPlayersOnCTTeam_sub_B23970:
55 89 E5 53 83 EC 14 A1 ? ? ? ? 8B 5D 08 3D ? ? ? ? 74 ? 8B 10 89 04 24 FF 52 40 83 F8 01
\x55\x89\xE5\x53\x83\xEC\x14\xA1\x2A\x2A\x2A\x2A\x8B\x5D\x08\x3D\x2A\x2A\x2A\x2A\x74\x2A\x8B\x10\x89\x04\x24\xFF\x52\x40\x83\xF8\x01
windows Signature for MaxNumPlayersOnTerrTeam_sub_1041C990:
56 8B F1 8B 0D ? ? ? ? 8B 01 FF 50 20 83 F8 04 75 ? 8B 0D ? ? ? ? 8B 01 FF 50 24 83 F8 01 0F 84 ? ? ? ?
\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\xFF\x50\x20\x83\xF8\x04\x75\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\xFF\x50\x24\x83\xF8\x01\x0F\x84\x2A\x2A\x2A\x2A
windows Signature for MaxNumPlayersOnCTTeam_sub_1041CA80:
56 8B F1 8B 0D ? ? ? ? 81 F9 ? ? ? ? 75 ? A1 ? ? ? ? 8B D0 81 F2 ? ? ? ? EB ? 8B 01 FF 50 34 8B 0D ? ? ? ? 8B D0 A1 ? ? ? ? 83 FA 01 74 ? 81 F9 ? ? ? ? 75 ? 35 ? ? ? ? EB ? 8B 01 FF 50 34 83 F8 03
\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x81\xF9\x2A\x2A\x2A\x2A\x75\x2A\xA1\x2A\x2A\x2A\x2A\x8B\xD0\x81\xF2\x2A\x2A\x2A\x2A\xEB\x2A\x8B\x01\xFF\x50\x34\x8B\x0D\x2A\x2A\x2A\x2A\x8B\xD0\xA1\x2A\x2A\x2A\x2A\x83\xFA\x01\x74\x2A\x81\xF9\x2A\x2A\x2A\x2A\x75\x2A\x35\x2A\x2A\x2A\x2A\xEB\x2A\x8B\x01\xFF\x50\x34\x83\xF8\x03
*/
#include <sdktools>
enum struct ServerInfo
{
int numPlayers;
int numSpectators;
int numTSlotsFree;
int numCTSlotsFree;
int numMaxHumans;
}
ServerInfo serverinfo;
Handle hMaxNumPlayersOnTerrTeam;
Handle hMaxNumPlayersOnCTTeam;
public void OnPluginStart()
{
RegConsoleCmd("sm_check", check);
HookEventEx("switch_team", switch_team);
}
public Action check(int client, int args)
{
UpdateServerInfo();
return Plugin_Handled;
}
public void OnConfigsExecuted()
{
GameData configfile = new GameData("test");
if(hMaxNumPlayersOnTerrTeam == null)
{
StartPrepSDKCall(SDKCall_GameRules);
if(PrepSDKCall_SetFromConf(configfile, SDKConf_Signature, "MaxNumPlayersOnTerrTeam"))
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_ByValue);
hMaxNumPlayersOnTerrTeam = EndPrepSDKCall();
}
if(hMaxNumPlayersOnCTTeam == null)
{
StartPrepSDKCall(SDKCall_GameRules);
if(PrepSDKCall_SetFromConf(configfile, SDKConf_Signature, "MaxNumPlayersOnCTTeam"))
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_ByValue);
hMaxNumPlayersOnCTTeam = EndPrepSDKCall();
}
delete configfile;
UpdateServerInfo();
}
void UpdateServerInfo()
{
if(hMaxNumPlayersOnTerrTeam == null || hMaxNumPlayersOnCTTeam == null)
{
return;
}
serverinfo.numTSlotsFree = SDKCall(hMaxNumPlayersOnTerrTeam);
serverinfo.numCTSlotsFree = SDKCall(hMaxNumPlayersOnCTTeam);
serverinfo.numPlayers = 0;
serverinfo.numSpectators = 0;
serverinfo.numMaxHumans = GetMaxHumanPlayers();
for(int i = 1; i <= MaxClients; i++)
{
if(!IsClientInGame(i) || IsFakeClient(i))
continue;
switch(GetClientTeam(i))
{
case 0:
serverinfo.numPlayers++;
case 1:
serverinfo.numSpectators++;
case 2:
{
serverinfo.numTSlotsFree--;
serverinfo.numPlayers++;
}
case 3:
{
serverinfo.numCTSlotsFree--;
serverinfo.numPlayers++;
}
}
}
PrintToServer("numPlayers %i", serverinfo.numPlayers);
PrintToServer("numSpectators %i", serverinfo.numSpectators);
PrintToServer("numTSlotsFree %i", serverinfo.numTSlotsFree);
PrintToServer("numCTSlotsFree %i", serverinfo.numCTSlotsFree);
PrintToServer("numMaxHumans %i", serverinfo.numMaxHumans);
}
public void switch_team(Event event, const char[] name, bool dontBroadcast)
{
/*
Server event "switch_team", Tick 9006:
- "numPlayers" = "1"
- "numSpectators" = "0"
- "avg_rank" = "0"
- "numTSlotsFree" = "11"
- "numCTSlotsFree" = "12"
*/
serverinfo.numPlayers = event.GetInt("numPlayers", -1);
serverinfo.numSpectators = event.GetInt("numSpectators", -1);
serverinfo.numTSlotsFree = event.GetInt("numTSlotsFree", -1);
serverinfo.numCTSlotsFree = event.GetInt("numCTSlotsFree", -1);
serverinfo.numMaxHumans = GetMaxHumanPlayers();
PrintToServer("numPlayers %i", serverinfo.numPlayers);
PrintToServer("numSpectators %i", serverinfo.numSpectators);
PrintToServer("numTSlotsFree %i", serverinfo.numTSlotsFree);
PrintToServer("numCTSlotsFree %i", serverinfo.numCTSlotsFree);
PrintToServer("numMaxHumans %i", serverinfo.numMaxHumans);
}
gamedata/test.txt
Code:
"Games"
{
"csgo"
{
"Signatures"
{
"MaxNumPlayersOnCTTeam"
{
"library" "server"
"windows" "\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x81\xF9\x2A\x2A\x2A\x2A\x75\x2A\xA1\x2A\x2A\x2A\x2A\x8B\xD0\x81\xF2\x2A\x2A\x2A\x2A\xEB\x2A\x8B\x01\xFF\x50\x34\x8B\x0D\x2A\x2A\x2A\x2A\x8B\xD0\xA1\x2A\x2A\x2A\x2A\x83\xFA\x01\x74\x2A\x81\xF9\x2A\x2A\x2A\x2A\x75\x2A\x35\x2A\x2A\x2A\x2A\xEB\x2A\x8B\x01\xFF\x50\x34\x83\xF8\x03"
"linux" "\x55\x89\xE5\x53\x83\xEC\x14\xA1\x2A\x2A\x2A\x2A\x8B\x5D\x08\x3D\x2A\x2A\x2A\x2A\x74\x2A\x8B\x10\x89\x04\x24\xFF\x52\x40\x83\xF8\x01"
}
"MaxNumPlayersOnTerrTeam"
{
"library" "server"
"windows" "\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\xFF\x50\x20\x83\xF8\x04\x75\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\xFF\x50\x24\x83\xF8\x01\x0F\x84\x2A\x2A\x2A\x2A"
"linux" "\x55\x89\xE5\x83\xEC\x18\x89\x5D\xF8\x8B\x5D\x08\x89\x75\xFC\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x84\xC0\x74\x2A"
}
}
}
}