Raised This Month: $ Target: $400
 0% 

[L4D/2] Additional bots disappear after map change


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
gbr161
Member
Join Date: May 2012
Old 11-25-2013 , 07:55   [L4D/2] Additional bots disappear after map change
Reply With Quote #1

Hello.
Iam able to spawn additional takeover bots but after map change they disappear.
Is there any way to prevent it? It makes gameplay buggy because if i respawn them it gives them full hp
gbr161 is offline
GsiX
gee, six eggs
Join Date: Aug 2012
Location: Land Below The Wind
Old 11-25-2013 , 08:08   Re: [L4D/2] Additional bots disappear after map change
Reply With Quote #2

show us the code?
GsiX is offline
gbr161
Member
Join Date: May 2012
Old 11-25-2013 , 08:14   Re: [L4D/2] Additional bots disappear after map change
Reply With Quote #3

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
						}
					}
				}
			}
		}
	}
}
This is modified multislots plugin.
gbr161 is offline
gbr161
Member
Join Date: May 2012
Old 11-26-2013 , 12:35   Re: [L4D/2] Additional bots disappear after map change
Reply With Quote #4

Maby ill describe more: what i want to do is to have constant number of bots on my server and all is good they are spawned when map starts but when we get to the saferoom and map changes bots that were playing with me in last round get replaced by new once. It seems that game kicks empty bots when more than 4 player team.
Is there any way to prevent this?
This is the part of code that spawns bots
PHP Code:
bool:SpawnFakeClientAndTeleport()
{
    new 
bool:fakeclientKicked false
    
    
// create fakeclient
    
new fakeclient CreateFakeClient("FakeClient")

    
    
// if entity is valid
    
if(fakeclient != 0)
    {
        
// move into survivor team
        
ChangeClientTeam(fakeclientTEAM_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 1<= MaxClientsi++)
                {
                    if(
IsClientInGame(i) && (GetClientTeam(i) == TEAM_SURVIVORS) && !IsFakeClient(i) && IsAlive(i) && != fakeclient)
                    {                        
                        
// get the position coordinates of any active alive player
                        
new Float:teleportOrigin[3]
                        
GetClientAbsOrigin(iteleportOrigin)                
                        
TeleportEntity(fakeclientteleportOriginNULL_VECTORNULL_VECTOR)                        
                        break
                    }
                }
                
StripWeapons(fakeclient)
                
BypassAndExecuteCommand(fakeclient"give""pistol")
                
GiveWeapon(fakeclient)
                
// kick the fake client to make the bot take over
                
CreateTimer(DELAY_KICK_FAKECLIENTTimer_KickFakeBotfakeclientTIMER_REPEAT)
                
fakeclientKicked true
            
}
        }            
        
// if something went wrong, kick the created FakeClient
        
if(fakeclientKicked == false)
            
KickClient(fakeclient"Kicking FakeClient")
    }    
    return 
fakeclientKicked

Ive tried to put fakeclients on them when map_transition event fires so bots wont be "empty" but it didnt help.

Any suggestions what to do?
(ive spent 3 days but cant solve this problem)
gbr161 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 06:03.


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