Um sorry. Here you go:
Code:
/************************************************
* Plugin name: [L4D(2)] MultiSlots
* Plugin author: SwiftReal
*
* Based upon:
* - (L4D) Zombie Havoc by Bigbuck
* - (L4D2) Bebop by frool
*
* Version 1.0
* - Initial Release
************************************************/
#include <sourcemod>
#include <sdktools>
#define PLUGIN_VERSION "1.0"
#define CVAR_FLAGS FCVAR_PLUGIN|FCVAR_NOTIFY
#define DELAY_KICK_FAKECLIENT 0.1
#define DELAY_KICK_NONEEDBOT 1.0
#define DELAY_CHANGETEAM_NEWPLAYER 1.5
#define TEAM_SPECTATORS 1
#define TEAM_SURVIVORS 2
#define TEAM_INFECTED 3
#define DAMAGE_EVENTS_ONLY 1
#define DAMAGE_YES 2
#define MODEL_FRANCIS "models/survivors/survivor_biker.mdl"
#define MODEL_LOUIS "models/survivors/survivor_manager.mdl"
#define MODEL_ZOEY "models/survivors/survivor_teenangst.mdl"
#define MODEL_BILL "models/survivors/survivor_namvet.mdl"
#define MODEL_NICK "models/survivors/survivor_gambler.mdl"
#define MODEL_COACH "models/survivors/survivor_coach.mdl"
#define MODEL_ROCHELLE "models/survivors/survivor_producer.mdl"
#define MODEL_ELLIS "models/survivors/survivor_mechanic.mdl"
new Handle:maxplayers;
new Handle:hMaxSurvivors
new Handle:hMaxInfected
new Handle:timer_SpawnTick = INVALID_HANDLE
new Handle:timer_SpecCheck = INVALID_HANDLE
new Handle:hKickIdlers
new bool:gbVehicleLeaving
new bool:gbPlayedAsSurvivorBefore[MAXPLAYERS+1]
new bool:gbFirstItemPickedUp
new bool:gbPlayerPickedUpFirstItem[MAXPLAYERS+1]
new String:gMapName[128]
new giIdleTicks[MAXPLAYERS+1]
new clienthealth[MAXPLAYERS+1]=100
new announcejoin=0;
new Float:clienttemphealth[MAXPLAYERS+1]=0.0
new String:g_lastCampaign[80];
public Plugin:myinfo =
{
name = "[L4D(2)] MultiSlots",
author = "SwiftReal, MI 5",
description = "Allows additional survivor/infected players in coop, versus, and survival",
version = PLUGIN_VERSION,
url = "N/A"
}
public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
// This plugin will only work on L4D 1/2
decl String:GameName[64];
GetGameFolderName(GameName, sizeof(GameName));
if (StrContains(GameName, "left4dead", false) == -1)
return APLRes_Failure;
return APLRes_Success;
}
public OnPluginStart()
{
// Create plugin version cvar and set it
CreateConVar("l4d_multislots_version", PLUGIN_VERSION, "L4D(2) MultiSlots version", CVAR_FLAGS|FCVAR_SPONLY|FCVAR_REPLICATED)
SetConVarString(FindConVar("l4d_multislots_version"), PLUGIN_VERSION)
SetConVarInt(FindConVar("z_spawn_flow_limit"), 100000)
// Register commands
RegAdminCmd("sm_addbot", AddBot, ADMFLAG_KICK, "Attempt to add and teleport a survivor bot")
RegConsoleCmd("sm_join", JoinTeam, "Attempt to join Survivors")
// Register cvars
hMaxSurvivors = CreateConVar("l4d_multislots_max_survivors", "8", "How many survivors allowed?", ~FCVAR_NOTIFY, true, 4.0, true, 32.0)
hMaxInfected = CreateConVar("l4d_multislots_max_infected", "8", "How many infected allowed?", ~FCVAR_NOTIFY, true, 4.0, true, 32.0)
hKickIdlers = CreateConVar("l4d_multislots_kickafk", "2", "Kick idle players? (0 = no 1 = player 5 min, admins kickimmune 2 = player 5 min, admins 10 min)", ~FCVAR_NOTIFY, true, 0.0, true, 2.0)
// Hook events
HookEvent("item_pickup", evtRoundStartAndItemPickup)
HookEvent("player_left_start_area", evtPlayerLeftStart)
HookEvent("survivor_rescued", evtSurvivorRescued)
HookEvent("finale_vehicle_leaving", evtFinaleVehicleLeaving)
HookEvent("mission_lost", evtMissionLost)
HookEvent("player_activate", evtPlayerActivate)
HookEvent("bot_player_replace", evtPlayerReplacedBot)
HookEvent("player_team", evtPlayerTeam)
HookEvent("player_spawn", pspawn)
HookEvent("map_transition", map_transition)
HookEvent("round_freeze_end",round_freeze_end);
maxplayers = FindConVar("sv_maxplayers");
HookConVarChange(maxplayers, maxplayers_change);
// Create or execute plugin configuration file
AutoExecConfig(true, "l4dmultislots");
}
bool:CheckNewCampaign()
{
decl String:mapName[256];
decl String:mapParts[3][30];
decl String:campaign[30];
GetCurrentMap(mapName,sizeof(mapName));
ExplodeString(mapName,"_",mapParts,3,30);
new campaignNameEnd = strlen(mapParts[1])-2;
strcopy(campaign,sizeof(campaign), mapParts[1]);
campaign[campaignNameEnd] = '\0';
if( strcmp( campaign, g_lastCampaign, false ) == 0 )
{
//The lastCampaign is the same as current campaigns so not a new campaign
return false;
}
else
{
//The lastCampaign is not the same as current campaigns so its a new campaign
strcopy( g_lastCampaign, sizeof(g_lastCampaign), campaign);
return true;
}
}
public OnMapStart()
{
GetCurrentMap(gMapName, sizeof(gMapName))
//FindLocationStart()
TweakSettings()
gbFirstItemPickedUp = false
PrecacheModel(MODEL_FRANCIS, true)
PrecacheModel(MODEL_LOUIS, true)
PrecacheModel(MODEL_ZOEY, true)
PrecacheModel(MODEL_BILL, true)
PrecacheModel(MODEL_NICK, true)
PrecacheModel(MODEL_COACH, true)
PrecacheModel(MODEL_ROCHELLE, true)
PrecacheModel(MODEL_ELLIS, true)
}
public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
{
if(client)
{
gbPlayedAsSurvivorBefore[client] = false
gbPlayerPickedUpFirstItem[client] = false
giIdleTicks[client] = 0
}
return true
}
public OnClientDisconnect(client)
{
gbPlayedAsSurvivorBefore[client] = false
gbPlayerPickedUpFirstItem[client] = false
}
public OnMapEnd()
{
StopTimers()
gbVehicleLeaving = false
gbFirstItemPickedUp = false
}
////////////////////////////////////
// Callbacks
////////////////////////////////////
public Action:round_freeze_end(Handle:event, const String:name[], bool:dontBroadcast)
{
if(CheckNewCampaign())
{
for (new i = 1; i <= MaxClients; i++)
{
clienthealth[i]=100;
clienttemphealth[i]=0.0;
}
}
}
public Action:map_transition(Handle:event, const String:name[], bool:dontBroadcast)
{
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i) && (GetClientTeam(i) == TEAM_SURVIVORS))
{
if(IsAlive(i))
{
clienthealth[i]=GetEntProp(i, Prop_Send, "m_iHealth");
clienttemphealth[i]=GetEntPropFloat(i, Prop_Send, "m_healthBuffer");
}
if(!IsAlive(i))
{
clienthealth[i]=50;
clienttemphealth[i]=0.0;
}
new String:n[64];
GetClientName(i, n, 64)
PrintToServer("%s - HP:%i, THP:%i", n, clienthealth[i], clienttemphealth[i])
}
}
}
public Action:AddBot(client, args)
{
if(SpawnFakeClientAndTeleport())
{
return Plugin_Handled
}else
{
return Plugin_Continue
}
}
public Action:JoinTeam(client, args)
{
if(!IsClientConnected(client))
return Plugin_Handled
if(IsClientInGame(client))
{
if(GetClientTeam(client) == TEAM_SURVIVORS)
{
if(DispatchKeyValue(client, "classname", "player") == true)
{
PrintHintText(client, "You allready joined the Survivor team")
}
else if((DispatchKeyValue(client, "classname", "info_survivor_position") == true) && !IsAlive(client))
{
PrintHintText(client, "Please wait to be revived or rescued")
}
}
else if(IsClientIdle(client))
{
PrintHintText(client, "You are now idle. Press mouse to play as survivor")
}
else
{
if(TotalFreeBots() == 0)
{
SpawnFakeClientAndTeleport()
CreateTimer(1.0, Timer_AutoJoinTeam, client, TIMER_REPEAT)
}
else
TakeOverBot(client, false)
}
}
return Plugin_Handled
}
////////////////////////////////////
// Events
////////////////////////////////////
public pspawn(Handle:event, const String:name[], bool:dontBroadcast)
{
for (new i = 1; i <= MaxClients; i++)
{
PrintToServer("%i,%i,%f",i,clienthealth[i],clienttemphealth[i]);
}
CreateTimer(2.0,checkbotstimer)
//checkbots()
}
public evtRoundStartAndItemPickup(Handle:event, const String:name[], bool:dontBroadcast)
{
if(!gbFirstItemPickedUp)
{
// alternative to round start...
if(timer_SpecCheck == INVALID_HANDLE)
timer_SpecCheck = CreateTimer(15.0, Timer_SpecCheck, _, TIMER_REPEAT)
gbFirstItemPickedUp = true
}
new client = GetClientOfUserId(GetEventInt(event, "userid"))
if(!gbPlayerPickedUpFirstItem[client] && !IsFakeClient(client))
{
// force setting client cvars here...
//ForceClientCvars(client)
gbPlayerPickedUpFirstItem[client] = true
gbPlayedAsSurvivorBefore[client] = true
}
}
public evtPlayerActivate(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"))
if(client)
{
if(GetClientTeam(client) == TEAM_SURVIVORS)
{
//SetEntityHealth(client, clienthealth[client])
//SetEntityTempHealth(client, clienttemphealth[client])
}
}
if(client)
{
if((GetClientTeam(client) != TEAM_INFECTED) && (GetClientTeam(client) != TEAM_SURVIVORS) && !IsFakeClient(client) && !IsClientIdle(client))
CreateTimer(DELAY_CHANGETEAM_NEWPLAYER, Timer_AutoJoinTeam, client, TIMER_REPEAT)
}
}
public evtPlayerLeftStart(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"))
if(client)
{
if(IsClientConnected(client) && IsClientInGame(client))
{
if(GetClientTeam(client)==TEAM_SURVIVORS)
gbPlayedAsSurvivorBefore[client] = true
}
}
}
public evtPlayerTeam(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"))
new newteam = GetEventInt(event, "team")
if(client)
{
if(!IsClientConnected(client))
return
if(!IsClientInGame(client) || IsFakeClient(client) || !IsAlive(client))
return
if(newteam == TEAM_INFECTED)
{
new String:PlayerName[100]
GetClientName(client, PlayerName, sizeof(PlayerName))
PrintToChatAll("\x01[\x04MultiSlots\x01] %s joined the Infected Team", PlayerName)
giIdleTicks[client] = 0
}
if(newteam == TEAM_SPECTATORS)
{
new String:PlayerName[100]
GetClientName(client, PlayerName, sizeof(PlayerName))
if(StrEqual(PlayerName, "Bot", false) && IsFakeClient(client))
{
KickClient(client, "")
}
}
}
}
public evtPlayerReplacedBot(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "player"))
if(!client) return
if(GetClientTeam(client)!=TEAM_SURVIVORS) return
if(!gbPlayedAsSurvivorBefore[client])
{
//ForceClientCvars(client)
gbPlayedAsSurvivorBefore[client] = true
giIdleTicks[client] = 0
SetEntityHealth(client, clienthealth[client])
SetEntityTempHealth(client, clienttemphealth[client])
decl String:GameMode[30]
GetConVarString(FindConVar("mp_gamemode"), GameMode, sizeof(GameMode))
if(StrEqual(GameMode, "mutation3", false))
{
SetEntityHealth(client, 1)
SetEntityTempHealth(client, 99.0)
}
decl String:PlayerName[100]
GetClientName(client, PlayerName, sizeof(PlayerName))
PrintToChatAll("\x01[\x04MultiSlots\x01] %s joined the Survivor Team", PlayerName)
}
}
public evtSurvivorRescued(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "victim"))
if(client)
{
StripWeapons(client)
BypassAndExecuteCommand(client, "give", "pistol")
GiveWeapon(client)
}
}
public evtFinaleVehicleLeaving(Handle:event, const String:name[], bool:dontBroadcast)
{
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if((GetClientTeam(i) == TEAM_SURVIVORS) && IsAlive(i))
{
SetEntProp(i, Prop_Data, "m_takedamage", DAMAGE_EVENTS_ONLY, 1)
new Float:newOrigin[3] = { 0.0, 0.0, 0.0 }
TeleportEntity(i, newOrigin, NULL_VECTOR, NULL_VECTOR)
SetEntProp(i, Prop_Data, "m_takedamage", DAMAGE_YES, 1)
}
}
}
StopTimers()
gbVehicleLeaving = true
}
public evtMissionLost(Handle:event, const String:name[], bool:dontBroadcast)
{
gbFirstItemPickedUp = false
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if((GetClientTeam(i) == TEAM_SURVIVORS) && IsAlive(i))
{
clienthealth[i]=100;
clienttemphealth[i]=0.0;
}
if((GetClientTeam(i) == TEAM_SURVIVORS) && !IsAlive(i))
{
clienthealth[i]=50;
clienttemphealth[i]=0.0;
}
}
}
}
////////////////////////////////////
// timers
////////////////////////////////////
public Action:Timer_SpecCheck(Handle:timer)
{
if(gbVehicleLeaving) return Plugin_Stop
announcejoin++;
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if((GetClientTeam(i) == TEAM_SPECTATORS) && !IsFakeClient(i))
{
if(!IsClientIdle(i)&&announcejoin>=6)
{
new String:PlayerName[100]
GetClientName(i, PlayerName, sizeof(PlayerName))
PrintToChat(i, "\x01[\x04MultiSlots\x01] %s, type \x03!join\x01 to join the Survivor Team", PlayerName)
}
switch(GetConVarInt(hKickIdlers))
{
case 0: {}
case 1:
{
if(GetUserFlagBits(i) == 0)
{
giIdleTicks[i]++
if(giIdleTicks[i] == 20)
KickClient(i, "Player idle longer than 5 min.")
}
}
case 2:
{
giIdleTicks[i]++
if(GetUserFlagBits(i) == 0)
{
if(giIdleTicks[i] == 20)
KickClient(i, "Player idle longer than 5 min.")
}
else
{
if(giIdleTicks[i] == 40)
KickClient(i, "Admin idle longer than 10 min.")
}
}
}
}
}
}
if(announcejoin>=6)
{
announcejoin=0;
}
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if((GetClientTeam(i) == TEAM_SURVIVORS) && !IsFakeClient(i) && !IsAlive(i))
{
//new String:PlayerName[100]
//GetClientName(i, PlayerName, sizeof(PlayerName))
//PrintToChat(i, "\x01[\x04MultiSlots\x01] %s, please wait to be revived or rescued", PlayerName)
}
}
}
return Plugin_Continue
}
public Action:Timer_AutoJoinTeam(Handle:timer, any:client)
{
if(!IsClientConnected(client))
return Plugin_Stop
if(IsClientInGame(client))
{
if(GetClientTeam(client) == TEAM_SURVIVORS)
return Plugin_Stop
if(IsClientIdle(client))
return Plugin_Stop
JoinTeam(client, 0)
}
return Plugin_Continue
}
public Action:Timer_KickFakeBot(Handle:timer, any:fakeclient)
{
if(IsClientConnected(fakeclient))
{
KickClient(fakeclient, "Kicking FakeClient")
return Plugin_Stop
}
return Plugin_Continue
}
////////////////////////////////////
// stocks
////////////////////////////////////
stock TweakSettings()
{
new Handle:hMaxSurvivorsLimitCvar = FindConVar("survivor_limit")
SetConVarBounds(hMaxSurvivorsLimitCvar, ConVarBound_Lower, true, GetConVarInt(hMaxSurvivors)*1.0)
SetConVarBounds(hMaxSurvivorsLimitCvar, ConVarBound_Upper, true, 32.0)
SetConVarInt(hMaxSurvivorsLimitCvar, GetConVarInt(hMaxSurvivors))
new Handle:hMaxInfectedLimitCvar = FindConVar("z_max_player_zombies")
SetConVarBounds(hMaxInfectedLimitCvar, ConVarBound_Lower, true, 4.0)
SetConVarBounds(hMaxInfectedLimitCvar, ConVarBound_Upper, true, 32.0)
SetConVarInt(hMaxInfectedLimitCvar, GetConVarInt(hMaxInfected))
}
stock TakeOverBot(client, bool:completely)
{
if (!IsClientInGame(client)) return
if (GetClientTeam(client) == TEAM_SURVIVORS) return
if (IsFakeClient(client)) return
new bot = FindBotToTakeOver()
if (bot==0)
{
PrintHintText(client, "No survivor bots to take over.")
return
}
static Handle:hSetHumanSpec
if (hSetHumanSpec == INVALID_HANDLE)
{
new Handle:hGameConf
hGameConf = LoadGameConfigFile("l4dmultislots")
StartPrepSDKCall(SDKCall_Player)
PrepSDKCall_SetFromConf(hGameConf, SDKConf_Signature, "SetHumanSpec")
PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer)
hSetHumanSpec = EndPrepSDKCall()
}
static Handle:hTakeOverBot
if (hTakeOverBot == INVALID_HANDLE)
{
new Handle:hGameConf
hGameConf = LoadGameConfigFile("l4dmultislots")
StartPrepSDKCall(SDKCall_Player)
PrepSDKCall_SetFromConf(hGameConf, SDKConf_Signature, "TakeOverBot")
PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain)
hTakeOverBot = EndPrepSDKCall()
}
if(completely)
{
SDKCall(hSetHumanSpec, bot, client)
SDKCall(hTakeOverBot, client, true)
}
else
{
SDKCall(hSetHumanSpec, bot, client)
SetEntProp(client, Prop_Send, "m_iObserverMode", 5)
}
return
}
stock FindBotToTakeOver()
{
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i))
{
if(IsClientInGame(i))
{
if (IsFakeClient(i) && GetClientTeam(i)==TEAM_SURVIVORS && IsAlive(i) && !HasIdlePlayer(i))
return i
}
}
}
return 0
}
stock SetEntityTempHealth(client, Float:hp)
{
SetEntPropFloat(client, Prop_Send, "m_healthBufferTime", GetGameTime())
new Float:newOverheal = hp * 1.0; // prevent tag mismatch
SetEntPropFloat(client, Prop_Send, "m_healthBuffer", newOverheal)
}
stock BypassAndExecuteCommand(client, String: strCommand[], String: strParam1[])
{
new flags = GetCommandFlags(strCommand)
SetCommandFlags(strCommand, flags & ~FCVAR_CHEAT)
FakeClientCommand(client, "%s %s", strCommand, strParam1)
SetCommandFlags(strCommand, flags)
}
stock StripWeapons(client) // strip all items from client
{
new itemIdx
for (new x = 0; x <= 3; x++)
{
if((itemIdx = GetPlayerWeaponSlot(client, x)) != -1)
{
RemovePlayerItem(client, itemIdx)
RemoveEdict(itemIdx)
}
}
}
stock GiveWeapon(client) // give client random weapon
{
switch(GetRandomInt(0,1))
{
case 0: BypassAndExecuteCommand(client, "give", "smg")
case 1: BypassAndExecuteCommand(client, "give", "pumpshotgun")
}
BypassAndExecuteCommand(client, "give", "ammo")
}
/*stock GiveMedkit(client)
{
new ent = GetPlayerWeaponSlot(client, 3)
if(IsValidEdict(ent))
{
new String:sClass[128]
GetEdictClassname(ent, sClass, sizeof(sClass))
if(!StrEqual(sClass, "weapon_first_aid_kit", false))
{
RemovePlayerItem(client, ent)
RemoveEdict(ent)
BypassAndExecuteCommand(client, "give", "first_aid_kit")
}
}
else
{
BypassAndExecuteCommand(client, "give", "first_aid_kit")
}
}
*/
stock TotalSurvivors() // total bots, including players
{
new int = 0
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i))
{
if(IsClientInGame(i) && (GetClientTeam(i) == TEAM_SURVIVORS))
int++
}
}
return int
}
stock HumanConnected()
{
new int = 0
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(bot))
{
if(!IsFakeClient(i))
int++
}
}
return int
}
stock TotalFreeBots() // total bots (excl. IDLE players)
{
new int = 0
for(new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if(IsFakeClient(i) && GetClientTeam(i)==TEAM_SURVIVORS)
{
if(!HasIdlePlayer(i))
int++
}
}
}
return int
}
stock StopTimers()
{
if(timer_SpawnTick != INVALID_HANDLE)
{
KillTimer(timer_SpawnTick)
timer_SpawnTick = INVALID_HANDLE
}
if(timer_SpecCheck != INVALID_HANDLE)
{
KillTimer(timer_SpecCheck)
timer_SpecCheck = INVALID_HANDLE
}
}
////////////////////////////////////
// bools
////////////////////////////////////
bool:SpawnFakeClientAndTeleport()
{
new bool:fakeclientKicked = false
// create fakeclient
new fakeclient = CreateFakeClient("FakeClient")
// if entity is valid
if(fakeclient != 0)
{
// move into survivor team
ChangeClientTeam(fakeclient, TEAM_SURVIVORS)
// check if entity classname is survivorbot
if(DispatchKeyValue(fakeclient, "classname", "player") == true)
{
// spawn the client
if(DispatchSpawn(fakeclient) == true)
{
// teleport client to the position of any active alive player
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && (GetClientTeam(i) == TEAM_SURVIVORS) && !IsFakeClient(i) && IsAlive(i) && i != fakeclient)
{
// get the position coordinates of any active alive player
new Float:teleportOrigin[3]
GetClientAbsOrigin(i, teleportOrigin)
TeleportEntity(fakeclient, teleportOrigin, NULL_VECTOR, NULL_VECTOR)
break
}
}
StripWeapons(fakeclient)
BypassAndExecuteCommand(fakeclient, "give", "pistol")
GiveWeapon(fakeclient)
SetEntityHealth(fakeclient, clienthealth[fakeclient])
SetEntityTempHealth(fakeclient, clienttemphealth[fakeclient])
// kick the fake client to make the bot take over
CreateTimer(DELAY_KICK_FAKECLIENT, Timer_KickFakeBot, fakeclient, TIMER_REPEAT)
fakeclientKicked = true
}
}
// if something went wrong, kick the created FakeClient
if(fakeclientKicked == false)
KickClient(fakeclient, "Kicking FakeClient")
}
return fakeclientKicked
}
stock bool:HasIdlePlayer(bot)
{
new userid = GetEntData(bot, FindSendPropInfo("SurvivorBot", "m_humanSpectatorUserID"));
new client = GetClientOfUserId(userid);
if(client > 0)
{
if(IsClientConnected(client) && !IsFakeClient(client) && (GetClientTeam(client) == TEAM_SPECTATORS))
return true;
}
return false;
}
bool:IsClientIdle(client)
{
if(GetClientTeam(client) != TEAM_SPECTATORS)
return false
for(new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if((GetClientTeam(i) == TEAM_SURVIVORS) && IsAlive(i))
{
if(IsFakeClient(i))
{
if(GetClientOfUserId(GetEntProp(i, Prop_Send, "m_humanSpectatorUserID")) == client)
return true
}
}
}
}
return false
}
bool:IsAlive(client)
{
if(!GetEntProp(client, Prop_Send, "m_lifeState"))
return true
return false
}
public maxplayers_change(Handle:convar, const String:oldValue[], const String:newValue[])
{
if (strcmp(oldValue, newValue) != 0)
{
new c = 0
for (new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i))
{
if(IsClientInGame(i))
c++
}
}
if(c>0){
checkbots()
}
}
}
public Action:checkbotstimer(Handle:timer)
{
checkbots();
}
checkbots()
{
if(GetConVarInt(maxplayers)>TotalSurvivors())
{
while(GetConVarInt(maxplayers)!=TotalSurvivors())
{
SpawnFakeClientAndTeleport();
}
}else
{
new botstoremove=TotalSurvivors()-GetConVarInt(maxplayers)
for(new i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && IsClientInGame(i))
{
if((GetClientTeam(i) == TEAM_SURVIVORS) && IsAlive(i))
{
if(IsFakeClient(i) && !HasIdlePlayer(i))
{
if(botstoremove>0)
{
KickClient(i,"")
botstoremove--
}else
{
break
}
}
}
}
}
}
}