Пример #1
0
//==========================================
// BOT_CreateUserinfo
// Creates UserInfo string to connect with
//==========================================
static void BOT_CreateUserinfo( char *userinfo, size_t userinfo_size, int bot_pers )
{
	char bot_skin[MAX_INFO_STRING];
	char bot_name[MAX_NAME_BYTES];
	char bot_model[MAX_INFO_STRING];

	//jalfixme: we have only one skin yet

	//GetUnusedSkin doesn't repeat already used skins/names
	if( !BOT_GetUnusedSkin( bot_model, bot_skin, bot_name ) )
	{
		float r;
		int i, botcount = 0;
		edict_t	*ent;

		//count spawned bots for the names
		for( i = 0, ent = game.edicts + 1; i < gs.maxclients; i++, ent++ )
		{
			if( !ent->r.inuse || !ent->ai ) continue;
			if( ent->r.svflags & SVF_FAKECLIENT && AI_GetType( ent->ai ) == AI_ISBOT )
				botcount++;
		}

		// Set the name for the bot.
		Q_snprintfz( bot_name, sizeof( bot_name ), "Bot%d", botcount+1 );

		// randomly choose skin
		r = random();
		if( r > 0.8f )
			Q_snprintfz( bot_model, sizeof( bot_model ), "bigvic" );
		else if( r > 0.6f )
			Q_snprintfz( bot_model, sizeof( bot_model ), "padpork" );
		else if( r > 0.4f )
			Q_snprintfz( bot_model, sizeof( bot_model ), "silverclaw" );
		else if( r > 0.2f )
			Q_snprintfz( bot_model, sizeof( bot_model ), "bobot" );
		else
			Q_snprintfz( bot_model, sizeof( bot_model ), "monada" );

		Q_snprintfz( bot_skin, sizeof( bot_skin ), "default" );
	}

	//Q_strncpyz( bot_name, bot_personalities[bot_pers].name, sizeof( bot_name ) );

	// initialize userinfo
	memset( userinfo, 0, userinfo_size );

	// add bot's name/skin/hand to userinfo
	Info_SetValueForKey( userinfo, "name", bot_name );
	Info_SetValueForKey( userinfo, "model", bot_model );
	//Info_SetValueForKey( userinfo, "skin", bot_skin );
	Info_SetValueForKey( userinfo, "skin", "default" ); // JALFIXME
	Info_SetValueForKey( userinfo, "hand", va( "%i", (int)( random()*2.5 ) ) );
	Info_SetValueForKey( userinfo, "color", va( "%i %i %i", (uint8_t)( random()*255 ), (uint8_t)( random()*255 ), (uint8_t)( random()*255 ) ) );
}
Пример #2
0
/*
* G_CheckNumBots
*/
static void G_CheckNumBots( void )
{
	edict_t	*ent;
	int desiredNumBots;

	if( level.spawnedTimeStamp + 5000 > game.realtime )
		return;

	// check sanity of g_numbots
	if( g_numbots->integer < 0 )
		trap_Cvar_Set( "g_numbots", "0" );

	if( g_numbots->integer > gs.maxclients )
		trap_Cvar_Set( "g_numbots", va( "%i", gs.maxclients ) );

	if( level.gametype.numBots > gs.maxclients )
		level.gametype.numBots = gs.maxclients;

	desiredNumBots = level.gametype.numBots ? level.gametype.numBots : g_numbots->integer;

	if( desiredNumBots < game.numBots )
	{
		// kick one bot
		for( ent = game.edicts + gs.maxclients; PLAYERNUM( ent ) >= 0; ent-- )
		{
			if( !ent->r.inuse || !( ent->r.svflags & SVF_FAKECLIENT ) )
				continue;
			if( AI_GetType( ent->ai ) == AI_ISBOT )
			{
				trap_DropClient( ent, DROP_TYPE_GENERAL, NULL );
				break;
			}
		}
		return;
	}

	if( desiredNumBots > game.numBots )
	{                                     // add a bot if there is room
		for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients && game.numBots < desiredNumBots; ent++ )
		{
			if( !ent->r.inuse && trap_GetClientState( PLAYERNUM( ent ) ) == CS_FREE )
				BOT_SpawnBot( NULL );
		}
	}
}
Пример #3
0
//==========================================
//	BOT_RemoveBot
//	Remove a bot by name or all bots
//==========================================
void BOT_RemoveBot( const char *name )
{
	int i;
	bool freed = false;
	edict_t	*ent;

	for( i = 0, ent = game.edicts + 1; i < gs.maxclients; i++, ent++ )
	{
		if( !ent->r.inuse || AI_GetType( ent->ai ) != AI_ISBOT )
			continue;

		if( !Q_stricmp( ent->r.client->netname, name ) || !Q_stricmp( name, "all" ) )
		{
			trap_DropClient( ent, DROP_TYPE_GENERAL, NULL );
			freed = true;
		}
	}

	if( !freed && Q_stricmp( name, "all" ) )
		G_Printf( "BOT: %s not found\n", name );
}
Пример #4
0
//==========================================
// BOT_Respawn
// Set up bot for Spawn. Called at first spawn & each respawn
//==========================================
void BOT_Respawn( edict_t *self )
{
	if( AI_GetType( self->ai ) != AI_ISBOT )
		return;

	self->enemy = NULL;
	self->movetarget = NULL;
	self->pain = BOT_pain;

	self->ai->statusUpdateTimeout = 0;
	self->ai->changeweapon_timeout = 0;
	self->ai->combatmovepush_timeout = 0;
	self->ai->state_combat_timeout = 0;
	self->ai->enemyReactionDelay = 0;
	self->ai->last_attacker = NULL;

	VectorClear( self->r.client->ps.pmove.delta_angles );
	self->r.client->level.last_activity = level.time;

	AI_ResetNavigation( self );
}
Пример #5
0
/*
* G_ClientThink
* Client frame think, and call to execute its usercommands thinking
*/
void G_ClientThink( edict_t *ent )
{
	if( !ent || !ent->r.client )
		return;

	if( trap_GetClientState( PLAYERNUM( ent ) ) < CS_SPAWNED )
		return;

	ent->r.client->ps.POVnum = ENTNUM( ent ); // set self

	// load instashield
	if( GS_Instagib() && g_instashield->integer )
	{
		if( ent->s.team >= TEAM_PLAYERS && ent->s.team < GS_MAX_TEAMS )
		{
			if( ent->r.client->ps.inventory[POWERUP_SHELL] > 0 )
			{
				ent->r.client->resp.instashieldCharge -= ( game.frametime * 0.001f ) * 60.0f;
				clamp( ent->r.client->resp.instashieldCharge, 0, INSTA_SHIELD_MAX );
				if( ent->r.client->resp.instashieldCharge == 0 )
					ent->r.client->ps.inventory[POWERUP_SHELL] = 0;
			}
			else
			{
				ent->r.client->resp.instashieldCharge += ( game.frametime * 0.001f ) * 20.0f;
				clamp( ent->r.client->resp.instashieldCharge, 0, INSTA_SHIELD_MAX );
			}
		}
	}

	// run bots thinking with the rest of clients
	if( ent->r.svflags & SVF_FAKECLIENT )
	{
		if( !ent->think && AI_GetType( ent->ai ) == AI_ISBOT )
			AI_Think( ent );
	}

	trap_ExecuteClientThinks( PLAYERNUM( ent ) );
}
Пример #6
0
//==========================================
// AI_InitLevel
// Inits Map local parameters
//==========================================
void AI_InitLevel( void )
{
	edict_t	*ent;

	//Init developer mode
	bot_showpath = trap_Cvar_Get( "bot_showpath", "0", 0 );
	bot_showcombat = trap_Cvar_Get( "bot_showcombat", "0", 0 );
	bot_showsrgoal = trap_Cvar_Get( "bot_showsrgoal", "0", 0 );
	bot_showlrgoal = trap_Cvar_Get( "bot_showlrgoal", "0", 0 );
	bot_dummy = trap_Cvar_Get( "bot_dummy", "0", 0 );
	sv_botpersonality =	    trap_Cvar_Get( "sv_botpersonality", "0", CVAR_ARCHIVE );

	nav.debugMode = false;

	AI_InitNavigationData( false );

	// count bots
	game.numBots = 0;
	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( !ent->r.inuse || !ent->ai ) continue;
		if( ent->r.svflags & SVF_FAKECLIENT && AI_GetType( ent->ai ) == AI_ISBOT )
			game.numBots++;
	}

	// set up weapon usage weights

	memset( &AIWeapons, 0, sizeof( ai_weapon_t )*WEAP_TOTAL );

	//WEAP_GUNBLADE
	AIWeapons[WEAP_GUNBLADE].aimType = AI_AIMSTYLE_INSTANTHIT;
	AIWeapons[WEAP_GUNBLADE].RangeWeight[AIWEAP_LONG_RANGE] = 0.1f;
	AIWeapons[WEAP_GUNBLADE].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.2f;
	AIWeapons[WEAP_GUNBLADE].RangeWeight[AIWEAP_SHORT_RANGE] = 0.3f;
	AIWeapons[WEAP_GUNBLADE].RangeWeight[AIWEAP_MELEE_RANGE] = 0.4f;

	//WEAP_MACHINEGUN
	AIWeapons[WEAP_MACHINEGUN].aimType = AI_AIMSTYLE_INSTANTHIT;
	AIWeapons[WEAP_MACHINEGUN].RangeWeight[AIWEAP_LONG_RANGE] = 0.8f;
	AIWeapons[WEAP_MACHINEGUN].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.7f;
	AIWeapons[WEAP_MACHINEGUN].RangeWeight[AIWEAP_SHORT_RANGE] = 0.4f;
	AIWeapons[WEAP_MACHINEGUN].RangeWeight[AIWEAP_MELEE_RANGE] = 0.1f;

	//WEAP_RIOTGUN
	AIWeapons[WEAP_RIOTGUN].aimType = AI_AIMSTYLE_INSTANTHIT;
	AIWeapons[WEAP_RIOTGUN].RangeWeight[AIWEAP_LONG_RANGE] = 0.1f;
	AIWeapons[WEAP_RIOTGUN].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.5f;
	AIWeapons[WEAP_RIOTGUN].RangeWeight[AIWEAP_SHORT_RANGE] = 0.8f;
	AIWeapons[WEAP_RIOTGUN].RangeWeight[AIWEAP_MELEE_RANGE] = 0.5f;

	//ROCKETLAUNCHER
	AIWeapons[WEAP_ROCKETLAUNCHER].aimType = AI_AIMSTYLE_PREDICTION_EXPLOSIVE;
	AIWeapons[WEAP_ROCKETLAUNCHER].RangeWeight[AIWEAP_LONG_RANGE] = 0.2f;
	AIWeapons[WEAP_ROCKETLAUNCHER].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.5f;
	AIWeapons[WEAP_ROCKETLAUNCHER].RangeWeight[AIWEAP_SHORT_RANGE] = 0.9f;
	AIWeapons[WEAP_ROCKETLAUNCHER].RangeWeight[AIWEAP_MELEE_RANGE] = 0.6f;

	//WEAP_GRENADELAUNCHER
	AIWeapons[WEAP_GRENADELAUNCHER].aimType = AI_AIMSTYLE_DROP;
	AIWeapons[WEAP_GRENADELAUNCHER].RangeWeight[AIWEAP_LONG_RANGE] = 0.0f;
	AIWeapons[WEAP_GRENADELAUNCHER].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.1f;
	AIWeapons[WEAP_GRENADELAUNCHER].RangeWeight[AIWEAP_SHORT_RANGE] = 0.4f;
	AIWeapons[WEAP_GRENADELAUNCHER].RangeWeight[AIWEAP_MELEE_RANGE] = 0.3f;

	//WEAP_PLASMAGUN
	AIWeapons[WEAP_PLASMAGUN].aimType = AI_AIMSTYLE_PREDICTION;
	AIWeapons[WEAP_PLASMAGUN].RangeWeight[AIWEAP_LONG_RANGE] = 0.1f;
	AIWeapons[WEAP_PLASMAGUN].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.5f;
	AIWeapons[WEAP_PLASMAGUN].RangeWeight[AIWEAP_SHORT_RANGE] = 0.7f;
	AIWeapons[WEAP_PLASMAGUN].RangeWeight[AIWEAP_MELEE_RANGE] = 0.4f;

	//WEAP_ELECTROBOLT
	AIWeapons[WEAP_ELECTROBOLT].aimType = AI_AIMSTYLE_INSTANTHIT;
	AIWeapons[WEAP_ELECTROBOLT].RangeWeight[AIWEAP_LONG_RANGE] = 0.9f;
	AIWeapons[WEAP_ELECTROBOLT].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.7f;
	AIWeapons[WEAP_ELECTROBOLT].RangeWeight[AIWEAP_SHORT_RANGE] = 0.4f;
	AIWeapons[WEAP_ELECTROBOLT].RangeWeight[AIWEAP_MELEE_RANGE] = 0.3f;

	//WEAP_LASERGUN
	AIWeapons[WEAP_LASERGUN].aimType = AI_AIMSTYLE_INSTANTHIT;
	AIWeapons[WEAP_LASERGUN].RangeWeight[AIWEAP_LONG_RANGE] = 0.0f;
	AIWeapons[WEAP_LASERGUN].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.0f;
	AIWeapons[WEAP_LASERGUN].RangeWeight[AIWEAP_SHORT_RANGE] = 0.7f;
	AIWeapons[WEAP_LASERGUN].RangeWeight[AIWEAP_MELEE_RANGE] = 0.6f;

	//WEAP_INSTAGUN
	AIWeapons[WEAP_INSTAGUN].aimType = AI_AIMSTYLE_INSTANTHIT;
	AIWeapons[WEAP_INSTAGUN].RangeWeight[AIWEAP_LONG_RANGE] = 0.9f;
	AIWeapons[WEAP_INSTAGUN].RangeWeight[AIWEAP_MEDIUM_RANGE] = 0.9f;
	AIWeapons[WEAP_INSTAGUN].RangeWeight[AIWEAP_SHORT_RANGE] = 0.9f;
	AIWeapons[WEAP_INSTAGUN].RangeWeight[AIWEAP_MELEE_RANGE] = 0.9f;
}
Пример #7
0
/*
* G_ClientRespawn
*/
void G_ClientRespawn( edict_t *self, bool ghost )
{
	int i;
	edict_t *spawnpoint;
	vec3_t hull_mins, hull_maxs;
	vec3_t spawn_origin, spawn_angles;
	gclient_t *client;
	int old_team;

	G_DeathAwards( self );

	G_SpawnQueue_RemoveClient( self );

	self->r.svflags &= ~SVF_NOCLIENT;

	//if invalid be spectator
	if( self->r.client->team < 0 || self->r.client->team >= GS_MAX_TEAMS )
		self->r.client->team = TEAM_SPECTATOR;

	// force ghost always to true when in spectator team
	if( self->r.client->team == TEAM_SPECTATOR )
		ghost = true;

	old_team = self->s.team;
	if( self->r.client->teamstate.is_coach )
		ghost = true;

	GClip_UnlinkEntity( self );

	client = self->r.client;

	memset( &client->resp, 0, sizeof( client->resp ) );
	memset( &client->ps, 0, sizeof( client->ps ) );
	client->resp.timeStamp = level.time;
	client->ps.playerNum = PLAYERNUM( self );

	// clear entity values
	memset( &self->snap, 0, sizeof( self->snap ) );
	memset( &self->s, 0, sizeof( self->s ) );
	memset( &self->olds, 0, sizeof( self->olds ) );
	memset( &self->invpak, 0, sizeof( self->invpak ) );

	self->s.number = self->olds.number = ENTNUM( self );

	// relink client struct
	self->r.client = &game.clients[PLAYERNUM( self )];

	// update team
	self->s.team = client->team;

	self->deadflag = DEAD_NO;
	self->s.type = ET_PLAYER;
	self->groundentity = NULL;
	self->takedamage = DAMAGE_AIM;
	self->think = player_think;
	self->pain = player_pain;
	self->die = player_die;
	self->viewheight = playerbox_stand_viewheight;
	self->r.inuse = true;
	self->mass = PLAYER_MASS;
	self->air_finished = level.time + ( 12 * 1000 );
	self->r.clipmask = MASK_PLAYERSOLID;
	self->waterlevel = 0;
	self->watertype = 0;
	self->flags &= ~FL_NO_KNOCKBACK;
	self->r.svflags &= ~SVF_CORPSE;
	self->enemy = NULL;
	self->r.owner = NULL;
	self->max_health = 100;
	self->health = self->max_health;

	if( AI_GetType( self->ai ) == AI_ISBOT )
	{
		self->think = NULL;
		self->classname = "bot";
	}
	else if( self->r.svflags & SVF_FAKECLIENT )
		self->classname = "fakeclient";
	else
		self->classname = "player";

	VectorCopy( playerbox_stand_mins, self->r.mins );
	VectorCopy( playerbox_stand_maxs, self->r.maxs );
	VectorClear( self->velocity );
	VectorClear( self->avelocity );

	VectorCopy( self->r.mins, hull_mins );
	VectorCopy( self->r.maxs, hull_maxs );
	trap_CM_RoundUpToHullSize( hull_mins, hull_maxs, NULL );
	if( self->r.maxs[2] > hull_maxs[2] )
		self->viewheight -= (self->r.maxs[2] - hull_maxs[2]);

	client->ps.POVnum = ENTNUM( self );

	// set movement info
	client->ps.pmove.stats[PM_STAT_MAXSPEED] = (short)DEFAULT_PLAYERSPEED;
	client->ps.pmove.stats[PM_STAT_JUMPSPEED] = (short)DEFAULT_JUMPSPEED;
	client->ps.pmove.stats[PM_STAT_DASHSPEED] = (short)DEFAULT_DASHSPEED;

	if( ghost )
	{
		self->r.solid = SOLID_NOT;
		self->movetype = MOVETYPE_NOCLIP;
		if( self->s.team == TEAM_SPECTATOR )
			self->r.svflags |= SVF_NOCLIENT;
	}
	else
	{
		self->r.client->resp.takeStun = true;
		self->r.solid = SOLID_YES;
		self->movetype = MOVETYPE_PLAYER;
		client->ps.pmove.stats[PM_STAT_FEATURES] = static_cast<unsigned short>(PMFEAT_DEFAULT);
		if( !g_allow_bunny->integer )
			client->ps.pmove.stats[PM_STAT_FEATURES] &= ~( PMFEAT_AIRCONTROL|PMFEAT_FWDBUNNY );
	}

	ClientUserinfoChanged( self, client->userinfo );

	if( old_team != self->s.team )
		G_Teams_UpdateMembersList();

	SelectSpawnPoint( self, &spawnpoint, spawn_origin, spawn_angles );
	VectorCopy( spawn_origin, client->ps.pmove.origin );
	VectorCopy( spawn_origin, self->s.origin );
	VectorCopy( self->s.origin, self->s.old_origin );

	// set angles
	self->s.angles[PITCH] = 0;
	self->s.angles[YAW] = anglemod( spawn_angles[YAW] );
	self->s.angles[ROLL] = 0;
	VectorCopy( self->s.angles, client->ps.viewangles );

	// set the delta angle
	for( i = 0; i < 3; i++ )
		client->ps.pmove.delta_angles[i] = ANGLE2SHORT( client->ps.viewangles[i] ) - client->ucmd.angles[i];

	// don't put spectators in the game
	if( !ghost )
	{
		if( KillBox( self ) )
		{
		}
	}

	self->s.attenuation = ATTN_NORM;

	self->s.teleported = true;

	// hold in place briefly
	client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
	client->ps.pmove.pm_time = 14;
	client->ps.pmove.stats[PM_STAT_NOUSERCONTROL] = CLIENT_RESPAWN_FREEZE_DELAY;
	client->ps.pmove.stats[PM_STAT_NOAUTOATTACK] = 1000;

	// set race stats to invisible
	client->ps.stats[STAT_TIME_SELF] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_BEST] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_RECORD] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_ALPHA] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_BETA] = STAT_NOTSET;

	BOT_Respawn( self );

	self->r.client->level.respawnCount++;

	G_UseTargets( spawnpoint, self );

	GClip_LinkEntity( self );

	// let the gametypes perform their changes
	if( game.asEngine != NULL )
		GT_asCallPlayerRespawn( self, old_team, self->s.team );
	else
		G_Gametype_GENERIC_ClientRespawn( self, old_team, self->s.team );
}