Exemplo n.º 1
0
/*
=======================================================================================================================================
BotMatch_Kill
=======================================================================================================================================
*/
void BotMatch_Kill(bot_state_t *bs, bot_match_t *match) {
	char enemy[MAX_MESSAGE_SIZE];
	int client;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}

	trap_BotMatchVariable(match, ENEMY, enemy, sizeof(enemy));
	client = FindEnemyByName(bs, enemy);

	if (client < 0) {
		BotAI_BotInitialChat(bs, "whois", enemy, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}

	bs->teamgoal.entitynum = client;
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_KILL;
	// set the team goal time
	bs->teamgoal_time = trap_AAS_Time() + TEAM_KILL_SOMEONE;
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Exemplo n.º 2
0
/*
==================
BotChat_ExitGame
==================
*/
int BotChat_ExitGame( bot_state_t *bs ) {
	char name[32];
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_ENTEREXITGAME, 0, 1 );
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	//
	BotAI_BotInitialChat( bs, "game_exit",
						  EasyClientName( bs->client, name, 32 ), // 0
						  BotRandomOpponentName( bs ),  // 1
						  "[invalid var]",          // 2
						  "[invalid var]",          // 3
						  BotMapTitle(),                // 4
						  NULL );
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 3
0
/*
==================
BotChat_HitNoDeath
==================
*/
int BotChat_HitNoDeath( bot_state_t *bs ) {
	char name[32];
    const char* weap;
	float rnd;
	int lasthurt_client;
	aas_entityinfo_t entinfo;

	lasthurt_client = g_entities[bs->client].client->lasthurt_client;
	if ( !lasthurt_client ) {
		return qfalse;
	}
	if ( lasthurt_client == bs->client ) {
		return qfalse;
	}
	//
	if ( lasthurt_client < 0 || lasthurt_client >= MAX_CLIENTS ) {
		return qfalse;
	}
	//
	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_HITNODEATH, 0, 1 );
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	//if fast chat is off
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd * 0.5 ) {
			return qfalse;
		}
	}
	if ( !BotValidChatPosition( bs ) ) {
		return qfalse;
	}
	//if the enemy is visible
	if ( BotEntityVisible( bs->client, bs->eye, bs->viewangles, 360, bs->enemy ) ) {
		return qfalse;
	}
	//
	BotEntityInfo( bs->enemy, &entinfo );
	if ( EntityIsShooting( &entinfo ) ) {
		return qfalse;
	}
	//
	ClientName( lasthurt_client, name, sizeof( name ) );
	weap = BotWeaponNameForMeansOfDeath( g_entities[bs->client].client->lasthurt_mod );
	//
	BotAI_BotInitialChat( bs, "hit_nodeath", name, weap, NULL );
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 4
0
/*
==================
BotChat_StartLevel
==================
*/
int BotChat_StartLevel( bot_state_t *bs ) {
	char name[32];
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( BotIsObserver( bs ) ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_STARTENDLEVEL, 0, 1 );
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	BotAI_BotInitialChat( bs, "level_start",
						  EasyClientName( bs->client, name, 32 ), // 0
						  NULL );
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 5
0
/*
=======================================================================================================================================
BotMatch_GetItem
=======================================================================================================================================
*/
void BotMatch_GetItem(bot_state_t *bs, bot_match_t *match) {
	char itemname[MAX_MESSAGE_SIZE];

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// get the match variable
	trap_BotMatchVariable(match, ITEM, itemname, sizeof(itemname));

	if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
		// BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
		// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_GETITEM;
	// set the team goal time
	bs->teamgoal_time = trap_AAS_Time() + TEAM_GETITEM_TIME;
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Exemplo n.º 6
0
/*
=======================================================================================================================================
BotMatch_Patrol
=======================================================================================================================================
*/
void BotMatch_Patrol(bot_state_t *bs, bot_match_t *match) {

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// get the patrol waypoints
	if (!BotGetPatrolWaypoints(bs, match)) {
		return;
	}
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_PATROL;
	// get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	// set the team goal time if not set already
	if (!bs->teamgoal_time) {
		bs->teamgoal_time = trap_AAS_Time() + TEAM_PATROL_TIME;
	}
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Exemplo n.º 7
0
/*
==================
BotChat_Kill
==================
*/
int BotChat_Kill( bot_state_t *bs ) {
	char name[32];
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_KILL, 0, 1 );
	//if fast chat is off
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
	}
	if ( bs->lastkilledplayer == bs->client ) {
		return qfalse;
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	if ( !BotValidChatPosition( bs ) ) {
		return qfalse;
	}
	//
	EasyClientName( bs->lastkilledplayer, name, 32 );
	//
	bs->chatto = CHAT_ALL;
	if ( TeamPlayIsOn() && BotSameTeam( bs, bs->lastkilledplayer ) ) {
		BotAI_BotInitialChat( bs, "kill_teammate", name, NULL );
		bs->chatto = CHAT_TEAM;
	} else
	{
		//don't chat in teamplay
		if ( TeamPlayIsOn() ) {
			return qfalse;
		}
		//
		if ( bs->enemydeathtype == MOD_GAUNTLET ) {
			BotAI_BotInitialChat( bs, "kill_gauntlet", name, NULL );
		} else if ( bs->enemydeathtype == MOD_RAILGUN )     {
			BotAI_BotInitialChat( bs, "kill_rail", name, NULL );
		} else if ( bs->enemydeathtype == MOD_TELEFRAG )     {
			BotAI_BotInitialChat( bs, "kill_telefrag", name, NULL );
		}
		//choose between insult and praise
		else if ( random() < trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_INSULT, 0, 1 ) ) {
			BotAI_BotInitialChat( bs, "kill_insult", name, NULL );
		} else {
			BotAI_BotInitialChat( bs, "kill_praise", name, NULL );
		}
	}
	bs->lastchat_time = trap_AAS_Time();
	return qtrue;
}
Exemplo n.º 8
0
/*
==================
BotChat_EndLevel
==================
*/
int BotChat_EndLevel( bot_state_t *bs ) {
	char name[32];
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( BotIsObserver( bs ) ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_STARTENDLEVEL, 0, 1 );
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	//
	if ( BotIsFirstInRankings( bs ) ) {
		BotAI_BotInitialChat( bs, "level_end_victory",
							  EasyClientName( bs->client, name, 32 ), // 0
							  BotRandomOpponentName( bs ), // 1
							  "[invalid var]",      // 2
							  BotLastClientInRankings(), // 3
							  BotMapTitle(),            // 4
							  NULL );
	} else if ( BotIsLastInRankings( bs ) )       {
		BotAI_BotInitialChat( bs, "level_end_lose",
							  EasyClientName( bs->client, name, 32 ), // 0
							  BotRandomOpponentName( bs ), // 1
							  BotFirstClientInRankings(), // 2
							  "[invalid var]",      // 3
							  BotMapTitle(),            // 4
							  NULL );
	} else {
		BotAI_BotInitialChat( bs, "level_end",
							  EasyClientName( bs->client, name, 32 ), // 0
							  BotRandomOpponentName( bs ), // 1
							  BotFirstClientInRankings(), // 2
							  BotLastClientInRankings(), // 3
							  BotMapTitle(),            // 4
							  NULL );
	}
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 9
0
/*
==================
BotChat_HitTalking
==================
*/
int BotChat_HitTalking( bot_state_t *bs ) {
	char name[32];
    const char* weap;
	int lasthurt_client;
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	lasthurt_client = g_entities[bs->client].client->lasthurt_client;
	if ( !lasthurt_client ) {
		return qfalse;
	}
	if ( lasthurt_client == bs->client ) {
		return qfalse;
	}
	//
	if ( lasthurt_client < 0 || lasthurt_client >= MAX_CLIENTS ) {
		return qfalse;
	}
	//
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_HITTALKING, 0, 1 );
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	//if fast chat is off
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd * 0.5 ) {
			return qfalse;
		}
	}
	if ( !BotValidChatPosition( bs ) ) {
		return qfalse;
	}
	//
	ClientName( g_entities[bs->client].client->lasthurt_client, name, sizeof( name ) );
	weap = BotWeaponNameForMeansOfDeath( g_entities[bs->client].client->lasthurt_client );
	//
	BotAI_BotInitialChat( bs, "hit_talking", name, weap, NULL );
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 10
0
/*
=======================================================================================================================================
BotGetTime
=======================================================================================================================================
*/
float BotGetTime(bot_match_t *match) {
	bot_match_t timematch;
	char timestring[MAX_MESSAGE_SIZE];
	float t;
	// if the matched string has a time
	if (match->subtype & ST_TIME) {
		// get the time string
		trap_BotMatchVariable(match, TIME, timestring, MAX_MESSAGE_SIZE);
		// match it to find out if the time is in seconds or minutes
		if (trap_BotFindMatch(timestring, &timematch, MTCONTEXT_TIME)) {
			if (timematch.type == MSG_FOREVER) {
				t = 99999999;
			} else {
				trap_BotMatchVariable(&timematch, TIME, timestring, MAX_MESSAGE_SIZE);

				if (timematch.type == MSG_MINUTES) {
					t = atof(timestring) * 60;
				} else if (timematch.type == MSG_SECONDS) {
					t = atof(timestring);
				} else {t = 0;}
			}
			// if there's a valid time
			if (t > 0) {
				return trap_AAS_Time() + t;
			}
		}
	}

	return 0;
}
Exemplo n.º 11
0
/*
==============
AICast_SetupClient
==============
*/
int AICast_SetupClient(int client)
{
	cast_state_t	*cs;
	bot_state_t		*bs;

	if (!botstates[client]) {
		botstates[client] = G_Alloc(sizeof(bot_state_t));
		memset( botstates[client], 0, sizeof(bot_state_t) );
	}
	bs = botstates[client];

	if (bs->inuse) {
		BotAI_Print(PRT_FATAL, "client %d already setup\n", client);
		return qfalse;
	}

	cs = AICast_GetCastState(client);
	cs->bs = bs;

	//allocate a goal state
	bs->gs = trap_BotAllocGoalState(client);

	bs->inuse = qtrue;
	bs->client = client;
	bs->entitynum = client;
	bs->setupcount = qtrue;
	bs->entergame_time = trap_AAS_Time();
	bs->ms = trap_BotAllocMoveState();

	return qtrue;
}
Exemplo n.º 12
0
/*
==============
AICast_RequestCrouchAttack
==============
*/
qboolean AICast_RequestCrouchAttack( cast_state_t *cs, vec3_t org, float time ) {
	if ( cs->attributes[ATTACK_CROUCH] > 0 && AICast_CheckAttackAtPos( cs->entityNum, cs->bs->enemy, org, qtrue, qfalse ) ) {
		if ( time ) {
			cs->bs->attackcrouch_time = trap_AAS_Time() + time;
		}
		return qtrue;
	}

	return qfalse;
}
Exemplo n.º 13
0
/*
=======================================================================================================================================
BotMatch_GetFlag
=======================================================================================================================================
*/
void BotMatch_GetFlag(bot_state_t *bs, bot_match_t *match) {
	// if not in CTF mode
	if (gametype != GT_CTF || !ctf_redflag.areanum || !ctf_blueflag.areanum) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_GETFLAG;
	// set the team goal time
	bs->teamgoal_time = trap_AAS_Time() + CTF_GETFLAG_TIME;
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Exemplo n.º 14
0
/*
=======================================================================================================================================
BotMatch_ReturnFlag
=======================================================================================================================================
*/
void BotMatch_ReturnFlag(bot_state_t *bs, bot_match_t *match) {
	// if not in CTF mode
	if (gametype != GT_CTF) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_RETURNFLAG;
	// set the team goal time
	bs->teamgoal_time = trap_AAS_Time() + CTF_RETURNFLAG_TIME;
	bs->rushbaseaway_time = 0;
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Exemplo n.º 15
0
/*
==================
BotChat_EnemySuicide
==================
*/
int BotChat_EnemySuicide( bot_state_t *bs ) {
	char name[32];
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	//
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_KILL, 0, 1 );
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	//if fast chat is off
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
	}
	if ( !BotValidChatPosition( bs ) ) {
		return qfalse;
	}
	//
	if ( bs->enemy >= 0 ) {
		EasyClientName( bs->enemy, name, 32 );
	} else { strcpy( name, "" );}
	BotAI_BotInitialChat( bs, "enemy_suicide", name, NULL );
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 16
0
/*
==================
BotChat_Death
==================
*/
int BotChat_Death( bot_state_t *bs ) {
	char name[32];
	float rnd;

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_DEATH, 0, 1 );
	//if fast chatting is off
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	//
	if ( bs->lastkilledby >= 0 && bs->lastkilledby < MAX_CLIENTS ) {
		EasyClientName( bs->lastkilledby, name, 32 );
	} else {
		strcpy( name, "[world]" );
	}
	//
	if ( TeamPlayIsOn() && BotSameTeam( bs, bs->lastkilledby ) ) {
		if ( bs->lastkilledby == bs->client ) {
			return qfalse;
		}
		BotAI_BotInitialChat( bs, "death_teammate", name, NULL );
		bs->chatto = CHAT_TEAM;
	} else
	{
		//don't chat in teamplay
		if ( TeamPlayIsOn() ) {
			return qfalse;
		}
		//
		if ( bs->botdeathtype == MOD_WATER ) {
			BotAI_BotInitialChat( bs, "death_drown", BotRandomOpponentName( bs ), NULL );
		} else if ( bs->botdeathtype == MOD_SLIME ) {
			BotAI_BotInitialChat( bs, "death_slime", BotRandomOpponentName( bs ), NULL );
		} else if ( bs->botdeathtype == MOD_LAVA ) {
			BotAI_BotInitialChat( bs, "death_lava", BotRandomOpponentName( bs ), NULL );
		} else if ( bs->botdeathtype == MOD_FALLING ) {
			BotAI_BotInitialChat( bs, "death_cratered", BotRandomOpponentName( bs ), NULL );
		} else if ( bs->botsuicide || //all other suicides by own weapon
					bs->botdeathtype == MOD_CRUSH ||
					bs->botdeathtype == MOD_SUICIDE ||
					bs->botdeathtype == MOD_TARGET_LASER ||
					bs->botdeathtype == MOD_TRIGGER_HURT ||
					bs->botdeathtype == MOD_UNKNOWN ) {
			BotAI_BotInitialChat( bs, "death_suicide", BotRandomOpponentName( bs ), NULL );
		} else if ( bs->botdeathtype == MOD_TELEFRAG ) {
			BotAI_BotInitialChat( bs, "death_telefrag", name, NULL );
		} else {
			if ( ( bs->botdeathtype == MOD_GAUNTLET ||
				   bs->botdeathtype == MOD_RAILGUN ||
				   bs->botdeathtype == MOD_BFG ||
				   bs->botdeathtype == MOD_BFG_SPLASH ) && random() < 0.5 ) {

				if ( bs->botdeathtype == MOD_GAUNTLET ) {
					BotAI_BotInitialChat( bs, "death_gauntlet",
										  name,                                 // 0
										  BotWeaponNameForMeansOfDeath( bs->botdeathtype ), // 1
										  NULL );
				} else if ( bs->botdeathtype == MOD_RAILGUN ) {
					BotAI_BotInitialChat( bs, "death_rail",
										  name,                                 // 0
										  BotWeaponNameForMeansOfDeath( bs->botdeathtype ), // 1
										  NULL );
				} else {
					BotAI_BotInitialChat( bs, "death_bfg",
										  name,                                 // 0
										  BotWeaponNameForMeansOfDeath( bs->botdeathtype ), // 1
										  NULL );
				}
			}
			//choose between insult and praise
			else if ( random() < trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_INSULT, 0, 1 ) ) {
				BotAI_BotInitialChat( bs, "death_insult",
									  name,                                     // 0
									  BotWeaponNameForMeansOfDeath( bs->botdeathtype ), // 1
									  NULL );
			} else {
				BotAI_BotInitialChat( bs, "death_praise",
									  name,                                     // 0
									  BotWeaponNameForMeansOfDeath( bs->botdeathtype ), // 1
									  NULL );
			}
		}
		bs->chatto = CHAT_ALL;
	}
	bs->lastchat_time = trap_AAS_Time();
	return qtrue;
}
Exemplo n.º 17
0
/*
============
AICast_Think

  entry point for all cast AI
============
*/
void AICast_Think( int client, float thinktime ) {
	gentity_t       *ent;
	cast_state_t    *cs;
	int i;
	int animIndex;
	animation_t     *anim;

//	if (saveGamePending || (strlen( g_missionStats.string ) > 2 )) {
//		return;
//	}

	//
	// get the cast ready for processing
	//
	cs = AICast_GetCastState( client );
	ent = &g_entities[client];
	//
	// make sure we are using the right AAS data for this entity (one's that don't get set will default to the player's AAS data)
	trap_AAS_SetCurrentWorld( cs->aasWorldIndex );
	//
	// make sure we have a valid navigation system
	//
	if ( !trap_AAS_Initialized() ) {
		return;
	}
	//
	trap_EA_ResetInput( client, NULL );
	cs->aiFlags &= ~AIFL_VIEWLOCKED;
	//cs->bs->weaponnum = ent->client->ps.weapon;
	//
	// turn off flags that are set each frame if needed
	ent->client->ps.eFlags &= ~( EF_NOSWINGANGLES | EF_MONSTER_EFFECT | EF_MONSTER_EFFECT2 | EF_MONSTER_EFFECT3 );
	// conditional flags
	if ( ent->aiCharacter == AICHAR_ZOMBIE ) {
		if ( COM_BitCheck( ent->client->ps.weapons, WP_MONSTER_ATTACK1 ) ) {
			cs->aiFlags |= AIFL_NO_FLAME_DAMAGE;
			SET_FLAMING_ZOMBIE( ent->s, 1 );
		} else {
			SET_FLAMING_ZOMBIE( ent->s, 0 );
		}
	}
	//
	// if we're dead, do special stuff only
	if ( ent->health <= 0 || cs->revivingTime || cs->rebirthTime ) {
		//
		if ( cs->revivingTime && cs->revivingTime < level.time ) {
			// start us thinking again
			ent->client->ps.pm_type = PM_NORMAL;
			cs->revivingTime = 0;
		}
		//
		if ( cs->rebirthTime && cs->rebirthTime < level.time ) {
			vec3_t mins, maxs;
			int touch[10], numTouch;
			float oldmaxZ;

			oldmaxZ = ent->r.maxs[2];

			// make sure the area is clear
			AIChar_SetBBox( ent, cs );

			VectorAdd( ent->r.currentOrigin, ent->r.mins, mins );
			VectorAdd( ent->r.currentOrigin, ent->r.maxs, maxs );
			trap_UnlinkEntity( ent );

			numTouch = trap_EntitiesInBox( mins, maxs, touch, 10 );

			if ( numTouch ) {
				for ( i = 0; i < numTouch; i++ ) {
					//if (!g_entities[touch[i]].client || g_entities[touch[i]].r.contents == CONTENTS_BODY)
					if ( g_entities[touch[i]].r.contents & MASK_PLAYERSOLID ) {
						break;
					}
				}
				if ( i == numTouch ) {
					numTouch = 0;
				}
			}

			if ( numTouch == 0 ) {    // ok to spawn

				// give them health when they start reviving, so we won't gib after
				// just a couple shots while reviving
				ent->health =
					ent->client->ps.stats[STAT_HEALTH] =
						ent->client->ps.stats[STAT_MAX_HEALTH] =
							( ( cs->attributes[STARTING_HEALTH] - 50 ) > 30 ? ( cs->attributes[STARTING_HEALTH] - 50 ) : 30 );

				ent->r.contents = CONTENTS_BODY;
				ent->clipmask = MASK_PLAYERSOLID;
				ent->takedamage = qtrue;
				ent->waterlevel = 0;
				ent->watertype = 0;
				ent->flags = 0;
				ent->die = AICast_Die;
				ent->client->ps.eFlags &= ~EF_DEAD;
				ent->s.eFlags &= ~EF_DEAD;

				cs->rebirthTime = 0;
				cs->deathTime = 0;

				// play the revive animation
				cs->revivingTime = level.time + BG_AnimScriptEvent( &ent->client->ps, ANIM_ET_REVIVE, qfalse, qtrue );;
			} else {
				// can't spawn yet, so set bbox back, and wait
				ent->r.maxs[2] = oldmaxZ;
				ent->client->ps.maxs[2] = ent->r.maxs[2];
			}
			trap_LinkEntity( ent );
		}
		// ZOMBIE should set effect flag if really dead
		if ( cs->aiCharacter == AICHAR_ZOMBIE && !ent->r.contents ) {
			ent->client->ps.eFlags |= EF_MONSTER_EFFECT2;
		}
		//
		if ( ent->health > GIB_HEALTH && cs->deathTime && cs->deathTime < ( level.time - 3000 ) ) {
/*
			// been dead for long enough, set our animation to the end frame
			switch ( ent->s.legsAnim & ~ANIM_TOGGLEBIT ) {
			case BOTH_DEATH1:
			case BOTH_DEAD1:
				anim = BOTH_DEAD1;
				break;
			case BOTH_DEATH2:
			case BOTH_DEAD2:
				anim = BOTH_DEAD2;
				break;
			case BOTH_DEATH3:
			case BOTH_DEAD3:
				anim = BOTH_DEAD3;
				break;
			default:
				G_Error( "%s has unknown death animation\n", ent->classname);
			}
			ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
			ent->client->ps.legsAnim = ( ( ent->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
*/
			cs->deathTime = 0;
			ent->r.svFlags &= ~SVF_BROADCAST;
		}
		//
		// no more thinking required
		return;
	}
	//
	// set some anim conditions
	if ( cs->secondDeadTime ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SECONDLIFE, qtrue, qfalse );
	} else {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SECONDLIFE, qfalse, qfalse );
	}
	// set health value
	if ( ent->health <= 0.25 * cs->attributes[STARTING_HEALTH] ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 3, qfalse );
	} else if ( ent->health <= 0.5 * cs->attributes[STARTING_HEALTH] ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 2, qfalse );
	} else {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 1, qfalse );
	}
	//
	cs->speedScale = 1.0;           // reset each frame, set if required
	cs->actionFlags = 0;            // FIXME: move this to a Cast AI movement init function!
	//retrieve the current client state
	BotAI_GetClientState( client, &( cs->bs->cur_ps ) );
	//
	// setup movement speeds for the given state
	// walking
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_WALK );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[WALKING_SPEED] = anim->moveSpeed;
	}
	// crouching
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_WALKCR );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[CROUCHING_SPEED] = anim->moveSpeed;
	}
	// running
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_RUN );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[RUNNING_SPEED] = anim->moveSpeed;
	}
	// update crouch speed scale
	ent->client->ps.crouchSpeedScale = cs->attributes[CROUCHING_SPEED] / cs->attributes[RUNNING_SPEED];
	//
	// only enable headlook if we want to this frame
	ent->client->ps.eFlags &= ~EF_HEADLOOK;
	if ( cs->bs->enemy >= 0 ) {
		ent->client->ps.eFlags &= ~EF_STAND_IDLE2;  // never use alt idle if fighting
	}
	//
	// check for dead leader
	if ( cs->leaderNum >= 0 && g_entities[cs->leaderNum].health <= 0 ) {
		cs->leaderNum = -1;
	}
	//
#if 0
	// HACK for village2, if they are stuck, find a good position (there is a friendly guy placed inside a table)
	{
		trace_t tr;
		vec3_t org;
		trap_Trace( &tr, cs->bs->cur_ps.origin, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, cs->bs->cur_ps.origin, cs->entityNum, CONTENTS_SOLID );
		while ( tr.startsolid ) {
			VectorCopy( cs->bs->cur_ps.origin, org );
			org[0] += 96 * crandom();
			org[1] += 96 * crandom();
			org[2] += 16 * crandom();
			trap_Trace( &tr, org, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, org, cs->entityNum, CONTENTS_SOLID );
			G_SetOrigin( &g_entities[cs->entityNum], org );
			VectorCopy( org, g_entities[cs->entityNum].client->ps.origin );
		}
	}
#endif
	//add the delta angles to the cast's current view angles
	for ( i = 0; i < 3; i++ ) {
		cs->bs->viewangles[i] = AngleMod( cs->bs->viewangles[i] + SHORT2ANGLE( cs->bs->cur_ps.delta_angles[i] ) );
	}
	//
	//increase the local time of the cast
	cs->bs->ltime += thinktime;
	//
	cs->bs->thinktime = thinktime;
	//origin of the cast
	VectorCopy( cs->bs->cur_ps.origin, cs->bs->origin );
	//eye coordinates of the cast
	VectorCopy( cs->bs->cur_ps.origin, cs->bs->eye );
	cs->bs->eye[2] += cs->bs->cur_ps.viewheight;
	//get the area the cast is in
	cs->bs->areanum = BotPointAreaNum( cs->bs->origin );
	// clear flags each frame
	cs->bs->flags = 0;
	//
	// check enemy health
	if ( cs->bs->enemy >= 0 && g_entities[cs->bs->enemy].health <= 0 ) {
		cs->bs->enemy = -1;
	}
	//
	// if the previous movetype was temporary, set it back
	if ( cs->movestateType == MSTYPE_TEMPORARY ) {
		cs->movestate = MS_DEFAULT;
		cs->movestateType = MSTYPE_NONE;
	}
	// crouching?
	if (    ( cs->bs->attackcrouch_time > trap_AAS_Time() ) &&
			( ( cs->lastAttackCrouch > level.time - 500 ) || ( cs->thinkFuncChangeTime < level.time - 1000 ) ) ) {
		// if we are not moving, and we are firing, always stand, unless we are allowed to crouch + fire
		if ( VectorLength( cs->bs->cur_ps.velocity ) || ( cs->lastWeaponFired < level.time - 2000 ) || ( cs->aiFlags & AIFL_ATTACK_CROUCH ) ) {
			cs->lastAttackCrouch = level.time;
			trap_EA_Crouch( cs->bs->client );
		}
	}
	//
	//if (cs->bs->enemy >= 0) {
	//update the attack inventory values
	AICast_UpdateBattleInventory( cs, cs->bs->enemy );
	//}
	//
	// if we don't have ammo for the current weapon, get rid of it
	if ( !( COM_BitCheck( cs->bs->cur_ps.weapons, cs->bs->weaponnum ) ) || !AICast_GotEnoughAmmoForWeapon( cs, cs->bs->weaponnum ) ) {
		// select a weapon
		AICast_ChooseWeapon( cs, qfalse );
		// if still no ammo, select a blank weapon
		//if (!AICast_GotEnoughAmmoForWeapon( cs, cs->bs->weaponnum )) {
		//	cs->bs->weaponnum = WP_NONE;
		//}
	}
	//
	// in query mode, we do special handling (pause scripting, check for transition to alert/combat, etc)
	if ( cs->aiState == AISTATE_QUERY ) {
		AICast_QueryThink( cs );
	} else if ( cs->pauseTime < level.time )     {
		// do the thinking
		AICast_ProcessAIFunctions( cs, thinktime );
		//
		// make sure the correct weapon is selected
		trap_EA_SelectWeapon( cs->bs->client, cs->bs->weaponnum );
		//
		// process current script if it exists
		cs->castScriptStatusCurrent = cs->castScriptStatus;
		AICast_ScriptRun( cs, qfalse );
	}
	//
	// set special movestate if necessary
	if ( cs->movestateType != MSTYPE_NONE ) {
		switch ( cs->movestate ) {
		case MS_WALK:
			cs->actionFlags |= CASTACTION_WALK;
			break;
		case MS_CROUCH:
			trap_EA_Crouch( cs->entityNum );
			break;
		default:
			break; // TTimo gcc: MS_DEFAULT MS_RUN not handled in switch
		}
	}
	//
	//subtract the delta angles
	for ( i = 0; i < 3; i++ ) {
		cs->bs->viewangles[i] = AngleMod( cs->bs->viewangles[i] - SHORT2ANGLE( cs->bs->cur_ps.delta_angles[i] ) );
	}
}
Exemplo n.º 18
0
/*
==================
BotTeamAI
==================
*/
void BotTeamAI(bot_state_t *bs) {
    int numteammates, flagstatus;
    char netname[MAX_NETNAME];

    if(!bs) return;

    //
    if (gametype != GT_TEAM && gametype != GT_CTF) return;
    //make sure we've got a valid team leader
    if (!BotValidTeamLeader(bs)) {
        //
        if (!bs->askteamleader_time && !bs->becometeamleader_time) {
            if (bs->entergame_time + 10 > trap_AAS_Time()) {
                bs->askteamleader_time = trap_AAS_Time() + 5 + random() * 10;
            }
            else {
                bs->becometeamleader_time = trap_AAS_Time() + 5 + random() * 10;
            }
        }
        if (bs->askteamleader_time && bs->askteamleader_time < trap_AAS_Time()) {
            //if asked for a team leader and no repsonse
            BotAI_BotInitialChat(bs, "whoisteamleader", NULL);
            trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
            bs->askteamleader_time = 0;
            bs->becometeamleader_time = trap_AAS_Time() + 15 + random() * 10;
        }
        if (bs->becometeamleader_time && bs->becometeamleader_time < trap_AAS_Time()) {
            BotAI_BotInitialChat(bs, "iamteamleader", NULL);
            trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
            ClientName(bs->client, netname, sizeof(netname));
            strncpy(bs->teamleader, netname, sizeof(bs->teamleader));
            bs->teamleader[sizeof(bs->teamleader)-1] = '\0';
            bs->becometeamleader_time = 0;
        }
        return;
    }
    bs->askteamleader_time = 0;
    bs->becometeamleader_time = 0;

    //return if this bot is NOT the team leader
    ClientName(bs->client, netname, sizeof(netname));
    if (Q_stricmp(netname, bs->teamleader) != 0) return;
    //
    //if the game starts OR a new player comes onto the team OR a player leaves the team
    //
    numteammates = BotNumTeamMates(bs);
    //give orders
    switch(gametype) {
    case GT_TEAM:
    {
        if (bs->numteammates != numteammates || bs->forceorders) {
            bs->teamgiveorders_time = trap_AAS_Time();
            bs->numteammates = numteammates;
            bs->forceorders = qfalse;
        }
        //if it's time to give orders
        if (bs->teamgiveorders_time < trap_AAS_Time() - 5) {
            BotTeamOrders(bs);
            //
            bs->teamgiveorders_time = 0;
        }
        break;
    }
    case GT_CTF:
    {
        //if the number of team mates changed or the flag status changed
        //or someone wants to know what to do
        if (bs->numteammates != numteammates || bs->flagstatuschanged || bs->forceorders) {
            bs->teamgiveorders_time = trap_AAS_Time();
            bs->numteammates = numteammates;
            bs->flagstatuschanged = qfalse;
            bs->forceorders = qfalse;
        }
        //if there were no flag captures the last 3 minutes
        if (bs->lastflagcapture_time < trap_AAS_Time() - 240) {
            bs->lastflagcapture_time = trap_AAS_Time();
            //randomly change the CTF strategy
            if (random() < 0.4) {
                bs->ctfstrategy ^= CTFS_PASSIVE;
                bs->teamgiveorders_time = trap_AAS_Time();
            }
        }
        //if it's time to give orders
        if (bs->teamgiveorders_time && bs->teamgiveorders_time < trap_AAS_Time() - 3) {
            //
            if (BotCTFTeam(bs) == CTF_TEAM_RED) flagstatus = bs->redflagstatus * 2 + bs->blueflagstatus;
            else flagstatus = bs->blueflagstatus * 2 + bs->redflagstatus;
            //
            switch(flagstatus) {
            case 0:
                BotCTFOrders_BothFlagsAtBase(bs);
                break;
            case 1:
                BotCTFOrders_EnemyFlagNotAtBase(bs);
                break;
            case 2:
                BotCTFOrders_FlagNotAtBase(bs);
                break;
            case 3:
                BotCTFOrders_BothFlagsNotAtBase(bs);
                break;
            }
            //
            bs->teamgiveorders_time = 0;
        }
        break;
    }
    }
}
Exemplo n.º 19
0
/*
==================
BotAIStartFrame
==================
*/
int BotAIStartFrame(int time) {
	int i;
	gentity_t	*ent;
	bot_entitystate_t state;
	int elapsed_time, thinktime;
	static int local_time;
	static int botlib_residual;
	static int lastbotthink_time;

	G_CheckBotSpawn();

	trap_Cvar_Update(&bot_rocketjump);
	trap_Cvar_Update(&bot_grapple);
	trap_Cvar_Update(&bot_fastchat);
	trap_Cvar_Update(&bot_nochat);
	trap_Cvar_Update(&bot_testrchat);
	trap_Cvar_Update(&bot_thinktime);
	trap_Cvar_Update(&bot_memorydump);
	trap_Cvar_Update(&bot_saveroutingcache);
	trap_Cvar_Update(&bot_pause);
	trap_Cvar_Update(&bot_report);
	trap_Cvar_Update(&bot_droppedweight);
	trap_Cvar_Update(&bot_offhandgrapple);
	trap_Cvar_Update(&bot_shownodechanges);
	trap_Cvar_Update(&bot_showteamgoals);
	trap_Cvar_Update(&bot_reloadcharacters);

	BotUpdateInfoConfigStrings();

	if (bot_pause.integer) {
		// execute bot user commands every frame
		for( i = 0; i < level.maxplayers; i++ ) {
			if( !botstates[i] || !botstates[i]->inuse ) {
				continue;
			}
			if( g_entities[i].player->pers.connected != CON_CONNECTED ) {
				continue;
			}
			botstates[i]->lastucmd.forwardmove = 0;
			botstates[i]->lastucmd.rightmove = 0;
			botstates[i]->lastucmd.upmove = 0;
			botstates[i]->lastucmd.buttons = 0;
			botstates[i]->lastucmd.serverTime = time;
			trap_BotUserCommand(botstates[i]->playernum, &botstates[i]->lastucmd);
		}
		return qtrue;
	}

	if (bot_memorydump.integer) {
		trap_BotLibVarSet("memorydump", "1");
		trap_Cvar_SetValue("bot_memorydump", 0);
	}
	if (bot_saveroutingcache.integer) {
		trap_BotLibVarSet("saveroutingcache", "1");
		trap_Cvar_SetValue("bot_saveroutingcache", 0);
	}
	//check if bot interbreeding is activated
	BotInterbreeding();
	//cap the bot think time
	if (bot_thinktime.integer > 200) {
		trap_Cvar_SetValue("bot_thinktime", 200);
	}
	//if the bot think time changed we should reschedule the bots
	if (bot_thinktime.integer != lastbotthink_time) {
		lastbotthink_time = bot_thinktime.integer;
		BotScheduleBotThink();
	}

	elapsed_time = time - local_time;
	local_time = time;

	botlib_residual += elapsed_time;

	if (elapsed_time > bot_thinktime.integer) thinktime = elapsed_time;
	else thinktime = bot_thinktime.integer;

	// update the bot library
	if ( botlib_residual >= thinktime ) {
		botlib_residual -= thinktime;

		trap_BotLibStartFrame((float) time / 1000);

		if (!trap_AAS_Initialized()) return qfalse;

		//update entities in the botlib
		for (i = 0; i < MAX_GENTITIES; i++) {
			ent = &g_entities[i];
			ent->botvalid = qfalse;
			if (!ent->inuse) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			if (!ent->r.linked) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			if (ent->r.svFlags & SVF_NOCLIENT) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			// do not update missiles
			if (ent->s.eType == ET_MISSILE && ent->s.weapon != WP_GRAPPLING_HOOK) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			// do not update event only entities
			if (ent->s.eType > ET_EVENTS) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
#ifdef MISSIONPACK
			// never link prox mine triggers
			if (ent->s.contents == CONTENTS_TRIGGER) {
				if (ent->touch == ProximityMine_Trigger) {
					trap_BotLibUpdateEntity(i, NULL);
					continue;
				}
			}
#endif
			//
			ent->botvalid = qtrue;
			ent->update_time = trap_AAS_Time() - ent->ltime;
			ent->ltime = trap_AAS_Time();
			//
			memset(&state, 0, sizeof(bot_entitystate_t));
			//
			VectorCopy(ent->r.currentOrigin, state.origin);
			if (i < MAX_CLIENTS) {
				VectorCopy(ent->s.apos.trBase, state.angles);
			} else {
				VectorCopy(ent->r.currentAngles, state.angles);
			}
			VectorCopy( ent->r.absmin, state.absmins );
			VectorCopy( ent->r.absmax, state.absmaxs );
			state.type = ent->s.eType;
			state.flags = ent->s.eFlags;
			//
			if (ent->s.collisionType == CT_SUBMODEL) {
				state.solid = SOLID_BSP;
				//if the angles of the model changed
				if ( !VectorCompare( state.angles, ent->lastAngles ) ) {
					VectorCopy(state.angles, ent->lastAngles);
					state.relink = qtrue;
				}
			} else {
				state.solid = SOLID_BBOX;
				VectorCopy(state.angles, ent->lastAngles);
			}
			//previous frame visorigin
			VectorCopy( ent->visorigin, ent->lastvisorigin );
			//if the origin changed
			if ( !VectorCompare( state.origin, ent->visorigin ) ) {
				VectorCopy( state.origin, ent->visorigin );
				state.relink = qtrue;
			}
			//if the bounding box size changed
			if (!VectorCompare(ent->s.mins, ent->lastMins) ||
					!VectorCompare(ent->s.maxs, ent->lastMaxs))
			{
				VectorCopy( ent->s.mins, ent->lastMins );
				VectorCopy( ent->s.maxs, ent->lastMaxs );
				state.relink = qtrue;
			}
			//
			trap_BotLibUpdateEntity(i, &state);
		}

		BotAIRegularUpdate();
	}

	floattime = trap_AAS_Time();

	// execute scheduled bot AI
	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( !botstates[i] || !botstates[i]->inuse ) {
			continue;
		}
		//
		botstates[i]->botthink_residual += elapsed_time;
		//
		if ( botstates[i]->botthink_residual >= thinktime ) {
			botstates[i]->botthink_residual -= thinktime;

			if (!trap_AAS_Initialized()) return qfalse;

			if (g_entities[i].player->pers.connected == CON_CONNECTED) {
				BotAI(i, (float) thinktime / 1000);
			}
		}
	}


	// execute bot user commands every frame
	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( !botstates[i] || !botstates[i]->inuse ) {
			continue;
		}
		if( g_entities[i].player->pers.connected != CON_CONNECTED ) {
			continue;
		}

		BotUpdateInput(botstates[i], time, elapsed_time);
		trap_BotUserCommand(botstates[i]->playernum, &botstates[i]->lastucmd);
	}

	return qtrue;
}
Exemplo n.º 20
0
/*
=======================================================================================================================================
BotPrintTeamGoal
=======================================================================================================================================
*/
void BotPrintTeamGoal(bot_state_t *bs) {
	char netname[MAX_NETNAME];
	float t;

	ClientName(bs->client, netname, sizeof(netname));
	t = bs->teamgoal_time - trap_AAS_Time();

	switch (bs->ltgtype) {
	case LTG_TEAMHELP:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna help a team mate for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_TEAMACCOMPANY:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna accompany a team mate for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_GETFLAG:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna get the flag for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_RUSHBASE:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna rush to the base for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_RETURNFLAG:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna try to return the flag for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_DEFENDKEYAREA:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna defend a key area for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_GETITEM:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna get an item for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_KILL:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna kill someone for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_CAMP:
	case LTG_CAMPORDER:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna camp for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_PATROL:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna patrol for %1.0f secs\n", netname, t);
		break;
	}

	default:
	{
		if (bs->ctfroam_time > trap_AAS_Time()) {
			t = bs->ctfroam_time - trap_AAS_Time();
			BotAI_Print(PRT_MESSAGE, "%s: I'm gonna roam for %1.0f secs\n", netname, t);
		} else {
			BotAI_Print(PRT_MESSAGE, "%s: I've got a regular goal\n", netname);
		}
	}
	}
}
Exemplo n.º 21
0
/*
==============
BotAIRegularUpdate
==============
*/
void BotAIRegularUpdate( void ) {
	if ( regularupdate_time < trap_AAS_Time() ) {
		trap_BotUpdateEntityItems();
		regularupdate_time = trap_AAS_Time() + 1;
	}
}
Exemplo n.º 22
0
/*
==================
BotAIStartFrame
==================
*/
int BotAIStartFrame(int time) {
	int i;
	gentity_t	*ent;
	bot_entitystate_t state;
	int elapsed_time, thinktime;
	static int local_time;
	static int botlib_residual;
	static int lastbotthink_time;

	G_CheckBotSpawn();

	trap_Cvar_Update(&bot_rocketjump);
	trap_Cvar_Update(&bot_grapple);
	trap_Cvar_Update(&bot_fastchat);
	trap_Cvar_Update(&bot_nochat);
	trap_Cvar_Update(&bot_testrchat);
	trap_Cvar_Update(&bot_thinktime);
	trap_Cvar_Update(&bot_memorydump);
	trap_Cvar_Update(&bot_saveroutingcache);
	trap_Cvar_Update(&bot_pause);
	trap_Cvar_Update(&bot_report);

	if (bot_report.integer) {
//		BotTeamplayReport();
//		trap_Cvar_Set("bot_report", "0");
		BotUpdateInfoConfigStrings();
	}

	if (bot_pause.integer) {
		// execute bot user commands every frame
		for( i = 0; i < MAX_CLIENTS; i++ ) {
			if( !botstates[i] || !botstates[i]->inuse ) {
				continue;
			}
			if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
				continue;
			}
			botstates[i]->lastucmd.forwardmove = 0;
			botstates[i]->lastucmd.rightmove = 0;
			botstates[i]->lastucmd.upmove = 0;
			botstates[i]->lastucmd.buttons = 0;
			botstates[i]->lastucmd.serverTime = time;
			trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
		}
		return qtrue;
	}

	if (bot_memorydump.integer) {
		trap_BotLibVarSet("memorydump", "1");
		trap_Cvar_Set("bot_memorydump", "0");
	}
	if (bot_saveroutingcache.integer) {
		trap_BotLibVarSet("saveroutingcache", "1");
		trap_Cvar_Set("bot_saveroutingcache", "0");
	}
	//check if bot interbreeding is activated
	BotInterbreeding();
	//cap the bot think time
	if (bot_thinktime.integer > 200) {
		trap_Cvar_Set("bot_thinktime", "200");
	}
	//if the bot think time changed we should reschedule the bots
	if (bot_thinktime.integer != lastbotthink_time) {
		lastbotthink_time = bot_thinktime.integer;
		BotScheduleBotThink();
	}

	elapsed_time = time - local_time;
	local_time = time;

	botlib_residual += elapsed_time;

	if (elapsed_time > bot_thinktime.integer) thinktime = elapsed_time;
	else thinktime = bot_thinktime.integer;

	// update the bot library
	if ( botlib_residual >= thinktime ) {
		botlib_residual -= thinktime;

		trap_BotLibStartFrame((float) time / 1000);

		if (!trap_AAS_Initialized()) return qfalse;

		//update entities in the botlib
		for (i = 0; i < MAX_GENTITIES; i++) {
			ent = &g_entities[i];
			if (!ent->inuse) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			if (!ent->r.linked) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			if (ent->r.svFlags & SVF_NOCLIENT) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			// do not update missiles
			if (ent->s.eType == ET_MISSILE && ent->s.weapon != WP_GRAPPLING_HOOK) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			// do not update event only entities
			if (ent->s.eType > ET_EVENTS) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
#if 1  //def MPACK
			// never link prox mine triggers
			if (ent->r.contents == CONTENTS_TRIGGER) {
				if (ent->touch == ProximityMine_Trigger) {
					trap_BotLibUpdateEntity(i, NULL);
					continue;
				}
			}
#endif
			//
			memset(&state, 0, sizeof(bot_entitystate_t));
			//
			VectorCopy(ent->r.currentOrigin, state.origin);
			if (i < MAX_CLIENTS) {
				VectorCopy(ent->s.apos.trBase, state.angles);
			} else {
				VectorCopy(ent->r.currentAngles, state.angles);
			}
			VectorCopy(ent->s.origin2, state.old_origin);
			VectorCopy(ent->r.mins, state.mins);
			VectorCopy(ent->r.maxs, state.maxs);
			state.type = ent->s.eType;
			state.flags = ent->s.eFlags;
			if (ent->r.bmodel) state.solid = SOLID_BSP;
			else state.solid = SOLID_BBOX;
			state.groundent = ent->s.groundEntityNum;
			state.modelindex = ent->s.modelindex;
			state.modelindex2 = ent->s.modelindex2;
			state.frame = ent->s.frame;
			state.event = ent->s.event;
			state.eventParm = ent->s.eventParm;
			state.powerups = ent->s.powerups;
			state.legsAnim = ent->s.legsAnim;
			state.torsoAnim = ent->s.torsoAnim;
			state.weapon = ent->s.weapon;
			//
			trap_BotLibUpdateEntity(i, &state);
		}

		BotAIRegularUpdate();
	}

	floattime = trap_AAS_Time();

	// execute scheduled bot AI
	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( !botstates[i] || !botstates[i]->inuse ) {
			continue;
		}
		//
		botstates[i]->botthink_residual += elapsed_time;
		//
		if ( botstates[i]->botthink_residual >= thinktime ) {
			botstates[i]->botthink_residual -= thinktime;

			if (!trap_AAS_Initialized()) return qfalse;

			if (g_entities[i].client->pers.connected == CON_CONNECTED) {
				BotAI(i, (float) thinktime / 1000);
			}
		}
	}


	// execute bot user commands every frame
	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( !botstates[i] || !botstates[i]->inuse ) {
			continue;
		}
		if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
			continue;
		}

		BotUpdateInput(botstates[i], time, elapsed_time);
		trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
	}

	return qtrue;
}
Exemplo n.º 23
0
/*
=======================================================================================================================================
BotMatch_LeadTheWay
=======================================================================================================================================
*/
void BotMatch_LeadTheWay(bot_state_t *bs, bot_match_t *match) {
	aas_entityinfo_t entinfo;
	char netname[MAX_MESSAGE_SIZE], teammate[MAX_MESSAGE_SIZE];
	int client, areanum, other;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// if someone asks for someone else
	if (match->subtype & ST_SOMEONE) {
		// get the team mate name
		trap_BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate));
		client = FindClientByName(teammate);
		// if this is the bot self
		if (client == bs->client) {
			other = qfalse;
		} else if (!BotSameTeam(bs, client)) {
			// FIXME: say "I don't help the enemy"
			return;
		} else {
			other = qtrue;
		}
	} else {
		// get the netname
		trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
		client = ClientFromName(netname);
		other = qfalse;
	}
	// if the bot doesn't know who to help (FindClientByName returned -1)
	if (client < 0) {
		BotAI_BotInitialChat(bs, "whois", netname, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}

	bs->lead_teamgoal.entitynum = -1;
	BotEntityInfo(client, &entinfo);
	// if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);

		if (areanum && trap_AAS_AreaReachability(areanum)) {
			bs->lead_teamgoal.entitynum = client;
			bs->lead_teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->lead_teamgoal.origin);
			VectorSet(bs->lead_teamgoal.mins, -8, -8, -8);
			VectorSet(bs->lead_teamgoal.maxs, 8, 8, 8);
		}
	}

	if (bs->teamgoal.entitynum < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whereis", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}

	bs->lead_teammate = client;
	bs->lead_time = trap_AAS_Time() + TEAM_LEAD_TIME;
	bs->leadvisible_time = 0;
	bs->leadmessage_time = -(trap_AAS_Time() + 2 * random());
}
Exemplo n.º 24
0
/*
=======================================================================================================================================
BotMatch_Camp
=======================================================================================================================================
*/
void BotMatch_Camp(bot_state_t *bs, bot_match_t *match) {
	int client, areanum;
	char netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}

	trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	// asked for someone else
	client = FindClientByName(netname);
	// if there's no valid client with this name
	if (client < 0) {
		BotAI_BotInitialChat(bs, "whois", netname, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// get the match variable
	trap_BotMatchVariable(match, KEYAREA, itemname, sizeof(itemname));
	// in CTF it could be the base
	if (match->subtype & ST_THERE) {
		// camp at the spot the bot is currently standing
		bs->teamgoal.entitynum = bs->entitynum;
		bs->teamgoal.areanum = bs->areanum;
		VectorCopy(bs->origin, bs->teamgoal.origin);
		VectorSet(bs->teamgoal.mins, -8, -8, -8);
		VectorSet(bs->teamgoal.maxs, 8, 8, 8);
	} else if (match->subtype & ST_HERE) {
		// if this is the bot self
		if (client == bs->client) {
			return;
		}

		bs->teamgoal.entitynum = -1;
		BotEntityInfo(client, &entinfo);
		// if info is valid (in PVS)
		if (entinfo.valid) {
			areanum = BotPointAreaNum(entinfo.origin);

			if (areanum && trap_AAS_AreaReachability(areanum)) {
				// NOTE: just cheat and assume the bot knows where the person is
				// if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, client)) {
				bs->teamgoal.entitynum = client;
				bs->teamgoal.areanum = areanum;
				VectorCopy(entinfo.origin, bs->teamgoal.origin);
				VectorSet(bs->teamgoal.mins, -8, -8, -8);
				VectorSet(bs->teamgoal.maxs, 8, 8, 8);
				//}
			}
		}
		// if the other is not visible
		if (bs->teamgoal.entitynum < 0) {
			BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);
			trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
			return;
		}
	} else if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
		// BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
		// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_CAMPORDER;
	// get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	// set the team goal time
	if (!bs->teamgoal_time) {
		bs->teamgoal_time = trap_AAS_Time() + TEAM_CAMP_TIME;
	}
	// the teammate that requested the camping
	bs->teammate = client;
	// not arrived yet
	bs->arrive_time = 0;
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Exemplo n.º 25
0
/*
==============
BotAISetupClient
==============
*/
int BotAISetupClient( int client, struct bot_settings_s *settings ) {
	char filename[MAX_PATH], name[MAX_PATH], gender[MAX_PATH];
	bot_state_t *bs;
	int errnum;

	if ( !botstates[client] ) {
		botstates[client] = G_Alloc( sizeof( bot_state_t ) );
	}
	bs = botstates[client];

	if ( bs && bs->inuse ) {
		BotAI_Print( PRT_FATAL, "client %d already setup\n", client );
		return qfalse;
	}

	if ( !trap_AAS_Initialized() ) {
		BotAI_Print( PRT_FATAL, "AAS not initialized\n" );
		return qfalse;
	}

	//load the bot character
	bs->character = trap_BotLoadCharacter( settings->characterfile, settings->skill );
	if ( !bs->character ) {
		BotAI_Print( PRT_FATAL, "couldn't load skill %f from %s\n", settings->skill, settings->characterfile );
		return qfalse;
	}
	//copy the settings
	memcpy( &bs->settings, settings, sizeof( bot_settings_t ) );
	//allocate a goal state
	bs->gs = trap_BotAllocGoalState( client );
	//load the item weights
	trap_Characteristic_String( bs->character, CHARACTERISTIC_ITEMWEIGHTS, filename, MAX_PATH );
	errnum = trap_BotLoadItemWeights( bs->gs, filename );
	if ( errnum != BLERR_NOERROR ) {
		trap_BotFreeGoalState( bs->gs );
		return qfalse;
	}
	//allocate a weapon state
	bs->ws = trap_BotAllocWeaponState();
	//load the weapon weights
	trap_Characteristic_String( bs->character, CHARACTERISTIC_WEAPONWEIGHTS, filename, MAX_PATH );
	errnum = trap_BotLoadWeaponWeights( bs->ws, filename );
	if ( errnum != BLERR_NOERROR ) {
		trap_BotFreeGoalState( bs->gs );
		trap_BotFreeWeaponState( bs->ws );
		return qfalse;
	}
	//allocate a chat state
	bs->cs = trap_BotAllocChatState();
	//load the chat file
	trap_Characteristic_String( bs->character, CHARACTERISTIC_CHAT_FILE, filename, MAX_PATH );
	trap_Characteristic_String( bs->character, CHARACTERISTIC_CHAT_NAME, name, MAX_PATH );
	errnum = trap_BotLoadChatFile( bs->cs, filename, name );
	if ( errnum != BLERR_NOERROR ) {
		trap_BotFreeChatState( bs->cs );
		trap_BotFreeGoalState( bs->gs );
		trap_BotFreeWeaponState( bs->ws );
		return qfalse;
	}
	//get the gender characteristic
	trap_Characteristic_String( bs->character, CHARACTERISTIC_GENDER, gender, MAX_PATH );
	//set the chat gender
	if ( *gender == 'f' || *gender == 'F' ) {
		trap_BotSetChatGender( bs->cs, CHAT_GENDERFEMALE );
	} else if ( *gender == 'm' || *gender == 'M' )  {
		trap_BotSetChatGender( bs->cs, CHAT_GENDERMALE );
	} else { trap_BotSetChatGender( bs->cs, CHAT_GENDERLESS );}

	bs->inuse = qtrue;
	bs->client = client;
	bs->entitynum = client;
	bs->setupcount = 4;
	bs->entergame_time = trap_AAS_Time();
	bs->ms = trap_BotAllocMoveState();
	bs->walker = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_WALKER, 0, 1 );
	numbots++;

	if ( trap_Cvar_VariableIntegerValue( "bot_testichat" ) ) {
		trap_BotLibVarSet( "bot_testichat", "1" );
		BotChatTest( bs );
	}
	//NOTE: reschedule the bot thinking
	BotScheduleBotThink();
	//
	return qtrue;
}
Exemplo n.º 26
0
/*
==================
BotChat_Random
==================
*/
int BotChat_Random( bot_state_t *bs ) {
	float rnd;
	char name[32];

	if ( bot_nochat.integer ) {
		return qfalse;
	}
	if ( BotIsObserver( bs ) ) {
		return qfalse;
	}
	if ( bs->lastchat_time > trap_AAS_Time() - 3 ) {
		return qfalse;
	}
	//don't chat in teamplay
	if ( TeamPlayIsOn() ) {
		return qfalse;
	}
	//don't chat when doing something important :)
	if ( bs->ltgtype == LTG_TEAMHELP ||
		 bs->ltgtype == LTG_TEAMACCOMPANY ||
		 bs->ltgtype == LTG_RUSHBASE ) {
		return qfalse;
	}
	//
	rnd = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_RANDOM, 0, 1 );
	if ( random() > bs->thinktime * 0.1 ) {
		return qfalse;
	}
	if ( !bot_fastchat.integer ) {
		if ( random() > rnd ) {
			return qfalse;
		}
		if ( random() > 0.25 ) {
			return qfalse;
		}
	}
	if ( BotNumActivePlayers() <= 1 ) {
		return qfalse;
	}
	if ( !BotValidChatPosition( bs ) ) {
		return qfalse;
	}
	//
	if ( bs->lastkilledplayer == bs->client ) {
		strcpy( name, BotRandomOpponentName( bs ) );
	} else {
		EasyClientName( bs->lastkilledplayer, name, sizeof( name ) );
	}
	//
	if ( random() < trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_CHAT_MISC, 0, 1 ) ) {
		BotAI_BotInitialChat( bs, "random_misc",
							  BotRandomOpponentName( bs ), // 0
							  name,             // 1
							  "[invalid var]", // 2
							  "[invalid var]", // 3
							  BotMapTitle(),    // 4
							  BotRandomWeaponName(), // 5
							  NULL );
	} else {
		BotAI_BotInitialChat( bs, "random_insult",
							  BotRandomOpponentName( bs ), // 0
							  name,             // 1
							  "[invalid var]", // 2
							  "[invalid var]", // 3
							  BotMapTitle(),    // 4
							  BotRandomWeaponName(), // 5
							  NULL );
	}
	bs->lastchat_time = trap_AAS_Time();
	bs->chatto = CHAT_ALL;
	return qtrue;
}
Exemplo n.º 27
0
/*
=======================================================================================================================================
BotMatch_HelpAccompany
=======================================================================================================================================
*/
void BotMatch_HelpAccompany(bot_state_t *bs, bot_match_t *match) {
	int client, other, areanum;
	char teammate[MAX_MESSAGE_SIZE], netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	bot_match_t teammatematch;
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// get the team mate name
	trap_BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate));
	// get the client to help
	if (trap_BotFindMatch(teammate, &teammatematch, MTCONTEXT_TEAMMATE) &&
		// if someone asks for him or herself
		 teammatematch.type == MSG_ME) {
		// get the netname
		trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
		client = ClientFromName(netname);
		other = qfalse;
	} else {
		// asked for someone else
		client = FindClientByName(teammate);
		// if this is the bot self
		if (client == bs->client) {
			other = qfalse;
		} else if (!BotSameTeam(bs, client)) {
			// FIXME: say "I don't help the enemy"
			return;
		} else {
			other = qtrue;
		}
	}
	// if the bot doesn't know who to help (FindClientByName returned -1)
	if (client < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whois", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whois", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// don't help or accompany yourself
	if (client == bs->client) {
		return;
	}

	bs->teamgoal.entitynum = -1;
	BotEntityInfo(client, &entinfo);
	// if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);

		if (areanum && trap_AAS_AreaReachability(areanum)) {
			bs->teamgoal.entitynum = client;
			bs->teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->teamgoal.origin);
			VectorSet(bs->teamgoal.mins, -8, -8, -8);
			VectorSet(bs->teamgoal.maxs, 8, 8, 8);
		}
	}
	// if no teamgoal yet
	if (bs->teamgoal.entitynum < 0) {
		// if near an item
		if (match->subtype & ST_NEARITEM) {
			// get the match variable
			trap_BotMatchVariable(match, ITEM, itemname, sizeof(itemname));

			if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
				// BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
				// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
				return;
			}
		}
	}

	if (bs->teamgoal.entitynum < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whereis", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// the team mate
	bs->teammate = client;
	// last time the team mate was assumed visible
	bs->teammatevisible_time = trap_AAS_Time();
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	// set the ltg type
	if (match->type == MSG_HELP) {
		bs->ltgtype = LTG_TEAMHELP;

		if (!bs->teamgoal_time) {
			bs->teamgoal_time = trap_AAS_Time() + TEAM_HELP_TIME;
		}
	} else {
		bs->ltgtype = LTG_TEAMACCOMPANY;

		if (!bs->teamgoal_time) {
			bs->teamgoal_time = trap_AAS_Time() + TEAM_ACCOMPANY_TIME;
		}

		bs->formation_dist = 3.5 * 32;     // 3.5 meter
		bs->arrive_time = 0;
	}
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}