示例#1
0
// add or remove bots to match team size targets set by 'bot fill' command
void G_BotFill(bool immediately)
{
	static int nextCheck = 0;
	if (!immediately && level.time < nextCheck) {
		return;  // don't check every frame to prevent warning spam
	}
	nextCheck = level.time + 2000;

	for (team_t team : {TEAM_ALIENS, TEAM_HUMANS}) {
		auto& t = level.team[team];
		int teamSize = t.numClients;
		if (teamSize > t.botFillTeamSize && t.numBots > 0) {
			for (int client = 0; client < MAX_CLIENTS; client++) {
				if (level.clients[client].pers.connected == CON_CONNECTED
						&& level.clients[client].pers.team == team
						&& level.clients[client].pers.isFillerBot) {
					G_BotDel(client);
					if (--teamSize <= t.botFillTeamSize) {
						break;
					}
				}
			}
		} else if (teamSize < t.botFillTeamSize) {
			int additionalBots = t.botFillTeamSize - teamSize;
			while (additionalBots--) {
				if (!G_BotAdd(BOT_NAME_FROM_LIST, team, t.botFillSkillLevel, BOT_DEFAULT_BEHAVIOR, true)) {
					break;
				}
			}
		}
	}
}
示例#2
0
void G_BotDelAllBots()
{
	int i;

	for ( i = 0; i < MAX_CLIENTS; i++ )
	{
		if ( g_entities[i].r.svFlags & SVF_BOT && level.clients[i].pers.connected != CON_DISCONNECTED )
		{
			G_BotDel( i );
		}
	}

	for ( i = 0; i < botNames[TEAM_ALIENS].count; ++i )
	{
		botNames[TEAM_ALIENS].name[i].inUse = false;
	}

	for ( i = 0; i < botNames[TEAM_HUMANS].count; ++i )
	{
		botNames[TEAM_HUMANS].name[i].inUse = false;
	}

	for (team_t team : {TEAM_ALIENS, TEAM_HUMANS})
	{
		level.team[team].botFillTeamSize = 0;
	}
}
示例#3
0
void G_BotCleanup()
{
	for ( int i = 0; i < MAX_CLIENTS; ++i )
	{
		if ( g_entities[i].r.svFlags & SVF_BOT && level.clients[i].pers.connected != CON_DISCONNECTED )
		{
			G_BotDel( i );
		}
	}

	G_BotClearNames();

	FreeTreeList( &treeList );
	G_BotNavCleanup();
}
示例#4
0
/**
 * Deletes all bots
 */
void G_BotDelAll( void )
{
	int i;
	gentity_t *bot;
	//If there are no bots, don't try to remove them
	if(level.humanBots + level.alienBots == 0) return;
	
	bot = &g_entities[ 0 ];
	for( i = 0; i < level.maxclients; i++, bot++ )
	{
		if(bot && bot->inuse == qtrue) {
			if(bot->r.svFlags & SVF_BOT)  {
				G_BotDel(i);
			}
		}
	}
}
示例#5
0
/**
 * Delete a random bot from a team (the worst score)
 * @param team
 */
void G_BotDelRandom ( team_t team ) {
	int i;
	gentity_t *ent;
	int score;
	int worst = -1;
	int worstScore = 9999;
	
	int reservedSlots = trap_Cvar_VariableIntegerValue( "sv_privateclients" );
	for( i = level.maxclients - 1; i > level.maxclients - reservedSlots - 1; i-- ) {
		ent = &g_entities[ i ];
		if(ent->r.svFlags & SVF_BOT && ent->client->pers.teamSelection == team) {
			score = ent->client->ps.persistant[ PERS_SCORE ];
			if(score < worstScore) {
				worst = i;
				worstScore = score;
			}
		}
	}
	if(worst > 0) {
		G_BotDel(worst);
	}
}
示例#6
0
bool G_BotAdd( const char *name, team_t team, int skill, const char *behavior, bool filler )
{
	int clientNum;
	char userinfo[MAX_INFO_STRING];
	const char* s = 0;
	gentity_t *bot;
	bool autoname = false;
	bool okay;

	if ( !navMeshLoaded )
	{
		Log::Warn( "No Navigation Mesh file is available for this map" );
		return false;
	}

	// find what clientNum to use for bot
	clientNum = trap_BotAllocateClient();

	if ( clientNum < 0 )
	{
		Log::Warn( "no more slots for bot" );
		return false;
	}
	bot = &g_entities[ clientNum ];
	bot->r.svFlags |= SVF_BOT;
	bot->inuse = true;

	if ( !Q_stricmp( name, BOT_NAME_FROM_LIST ) )
	{
		name = G_BotSelectName( team );
		autoname = name != nullptr;
	}

	//default bot data
	okay = G_BotSetDefaults( clientNum, team, skill, behavior );

	// register user information
	userinfo[0] = '\0';
	Info_SetValueForKey( userinfo, "name", name ? name : "", false ); // allow defaulting
	Info_SetValueForKey( userinfo, "rate", "25000", false );
	Info_SetValueForKey( userinfo, "snaps", "20", false );
	if ( autoname )
	{
		Info_SetValueForKey( userinfo, "autoname", name, false );
	}

	//so we can connect if server is password protected
	if ( g_needpass.integer == 1 )
	{
		Info_SetValueForKey( userinfo, "password", g_password.string, false );
	}

	trap_SetUserinfo( clientNum, userinfo );

	// have it connect to the game as a normal client
	if ( ( s = ClientBotConnect( clientNum, true, team ) ) )
	{
		// won't let us join
		Log::Warn( s );
		okay = false;
	}

	if ( !okay )
	{
		G_BotDel( clientNum );
		return false;
	}

	if ( autoname )
	{
		G_BotNameUsed( team, name, true );
	}

	ClientBegin( clientNum );
	bot->pain = BotPain; // ClientBegin resets the pain function
	level.clients[clientNum].pers.isFillerBot = filler;
	G_ChangeTeam( bot, team );
	return true;
}