예제 #1
0
void G_RunFrame( int levelTime ) {
	int			i;
	gentity_t	*ent;
	int			msec;
	int			ents_inuse=0; // someone's gonna be pissed I put this here...
#if	AI_TIMERS
	AITime = 0;
	navTime = 0;
#endif//	AI_TIMERS
	
	level.framenum++;
	level.previousTime = level.time;
	level.time = levelTime;
	msec = level.time - level.previousTime;
	
	NAV_CheckCalcPaths();
	//ResetTeamCounters();
	
	AI_UpdateGroups();

	if ( d_altRoutes->integer )
	{
		navigator.CheckAllFailedEdges();
	}
	navigator.ClearCheckedNodes();

	//remember last waypoint, clear current one
//	for ( i = 0, ent = &g_entities[0]; i < globals.num_entities ; i++, ent++) 
	for ( i = 0; i < globals.num_entities ; i++) 
	{
//		if ( !ent->inuse )
//			continue;

		if(!PInUse(i))
			continue;
		
		ent = &g_entities[i];
	
		if ( ent->waypoint != WAYPOINT_NONE 
			&& ent->noWaypointTime < level.time )
		{
			ent->lastWaypoint = ent->waypoint;
			ent->waypoint = WAYPOINT_NONE;
		}
		if ( d_altRoutes->integer )
		{
			navigator.CheckFailedNodes( ent );
		}
	}

	//Look to clear out old events
	ClearPlayerAlertEvents();

	//Run the frame for all entities
//	for ( i = 0, ent = &g_entities[0]; i < globals.num_entities ; i++, ent++)
	for ( i = 0; i < globals.num_entities ; i++) 
	{
//		if ( !ent->inuse )
//			continue;

		if(!PInUse(i))
			continue;
		ents_inuse++;
		ent = &g_entities[i];

		// clear events that are too old
		if ( level.time - ent->eventTime > EVENT_VALID_MSEC ) {
			if ( ent->s.event ) {
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if ( ent->client ) {
					ent->client->ps.externalEvent = 0;
				}
			}
			if ( ent->freeAfterEvent ) {
				// tempEntities or dropped items completely go away after their event
				G_FreeEntity( ent );
				continue;
			} else if ( ent->unlinkAfterEvent ) {
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent = qfalse;
				gi.unlinkentity( ent );
			}
		}

		// temporary entities don't think
		if ( ent->freeAfterEvent )
			continue;

		G_CheckTasksCompleted(ent);

		G_Roff( ent );

		if( !ent->client )
		{
			if ( !(ent->svFlags & SVF_SELF_ANIMATING) )
			{//FIXME: make sure this is done only for models with frames?
				//Or just flag as animating?
				if ( ent->s.eFlags & EF_ANIM_ONCE )
				{
					ent->s.frame++;
				}
				else if ( !(ent->s.eFlags & EF_ANIM_ALLFAST) )
				{
					G_Animate( ent );
				}
			}
		}
		G_CheckSpecialPersistentEvents( ent );

		if ( ent->s.eType == ET_MISSILE ) 
		{
			G_RunMissile( ent );
			continue;
		}

		if ( ent->s.eType == ET_ITEM ) 
		{
			G_RunItem( ent );
			continue;
		}

		if ( ent->s.eType == ET_MOVER ) 
		{
			if ( ent->model && Q_stricmp( "models/test/mikeg/tie_fighter.md3", ent->model ) == 0 )
			{
				TieFighterThink( ent );
			}
			G_RunMover( ent );
			continue;
		}

		//The player
		if ( i == 0 ) 
		{
			// decay batteries if the goggles are active
			if ( cg.zoomMode == 1 && ent->client->ps.batteryCharge > 0 )
			{
				ent->client->ps.batteryCharge--;
			}
			else if ( cg.zoomMode == 3 && ent->client->ps.batteryCharge > 0 )
			{
				ent->client->ps.batteryCharge -= 2;

				if ( ent->client->ps.batteryCharge < 0 )
				{
					ent->client->ps.batteryCharge = 0;
				}
			}

			G_CheckEndLevelTimers( ent );
			//Recalculate the nearest waypoint for the coming NPC updates
			NAV_FindPlayerWaypoint();

			if( ent->taskManager && !stop_icarus )
			{
				ent->taskManager->Update();
			}
			//dead
			if ( ent->health <= 0 )
			{
				if ( ent->client->ps.groundEntityNum != ENTITYNUM_NONE )
				{//on the ground
					pitch_roll_for_slope( ent, NULL );
				}
			}

			continue;	// players are ucmd driven
		}

		G_RunThink( ent );	// be aware that ent may be free after returning from here, at least one func frees them
		ClearNPCGlobals();			//	but these 2 funcs are ok
		//UpdateTeamCounters( ent );	//	   to call anyway on a freed ent.
	}

	// perform final fixups on the player
	ent = &g_entities[0];
	if ( ent->inuse ) 
	{
		ClientEndFrame( ent );
	}
	if( g_numEntities->integer )
	{
		gi.Printf( S_COLOR_WHITE"Number of Entities in use : %d\n", ents_inuse );
	}
	//DEBUG STUFF
	NAV_ShowDebugInfo();
	NPC_ShowDebugInfo();

	G_DynamicMusicUpdate();

#if	AI_TIMERS
	AITime -= navTime;
	if ( AITime > 20 )
	{
		gi.Printf( S_COLOR_RED"ERROR: total AI time: %d\n", AITime );
	}
	else if ( AITime > 10 )
	{
		gi.Printf( S_COLOR_YELLOW"WARNING: total AI time: %d\n", AITime );
	}
	else if ( AITime > 2 )
	{
		gi.Printf( S_COLOR_GREEN"total AI time: %d\n", AITime );
	}
	if ( navTime > 20 )
	{
		gi.Printf( S_COLOR_RED"ERROR: total nav time: %d\n", navTime );
	}
	else if ( navTime > 10 )
	{
		gi.Printf( S_COLOR_YELLOW"WARNING: total nav time: %d\n", navTime );
	}
	else if ( navTime > 2 )
	{
		gi.Printf( S_COLOR_GREEN"total nav time: %d\n", navTime );
	}
#endif//	AI_TIMERS

#ifndef FINAL_BUILD
	if ( delayedShutDown != 0 && delayedShutDown < level.time )
	{
		G_Error( "Game Errors. Scroll up the console to read them.\n" );
	}
#endif

#ifdef _DEBUG
	if(!(level.framenum&0xff))
	{
		ValidateInUseBits();
	}
#endif
}
/*
================
G_RunFrame

Advances the non-player objects in the world
================
*/
void G_RunFrame( int levelTime ) {
	int			i;
	gentity_t	*ent;

	// if we are waiting for the level to restart, do nothing
	if ( level.restarted ) {
		return;
	}

	level.framenum++;
	level.previousTime = level.time;
	level.time = levelTime;

	// get any cvar changes
	G_UpdateCvars();

	//
	// go through all allocated objects
	//
	ent = &g_entities[0];
	for (i=0 ; i<level.num_entities ; i++, ent++) {
		if ( !ent->inuse ) {
			continue;
		}

		// clear events that are too old
		if ( level.time - ent->eventTime > EVENT_VALID_MSEC ) {
			if ( ent->s.event ) {
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if ( ent->client ) {
					ent->client->ps.externalEvent = 0;
					// predicted events should never be set to zero
					//ent->client->ps.events[0] = 0;
					//ent->client->ps.events[1] = 0;
				}
			}
			if ( ent->freeAfterEvent ) {
				// tempEntities or dropped items completely go away after their event
				G_FreeEntity( ent );
				continue;
			} else if ( ent->unlinkAfterEvent ) {
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent = qfalse;
				trap_UnlinkEntity( ent );
			}
		}

		// temporary entities don't think
		if ( ent->freeAfterEvent ) {
			continue;
		}

		if ( !ent->r.linked && ent->neverFree ) {
			continue;
		}

		if ( ent->s.eType == ET_MISSILE ) {
			G_RunMissile( ent );
			continue;
		}

		if ( ent->s.eType == ET_ITEM || ent->physicsObject ) {
			G_RunItem( ent );
			continue;
		}

		if ( ent->s.eType == ET_MOVER ) {
			G_RunMover( ent );
			continue;
		}

		if ( i < MAX_CLIENTS ) {
			G_RunClient( ent );
			continue;
		}

		G_RunThink( ent );
	}

	// perform final fixups on the players
	ent = &g_entities[0];
	for (i=0 ; i < level.maxclients ; i++, ent++ ) {
		if ( ent->inuse ) {
			ClientEndFrame( ent );
		}
	}

	// see if it is time to do a tournement restart
	CheckTournament();

	// see if it is time to end the level
	CheckExitRules();

	// update to team status?
	CheckTeamStatus();

	// cancel vote if timed out
	CheckVote();

	// check team votes
	CheckTeamVote( TEAM_RED );
	CheckTeamVote( TEAM_BLUE );

	// for tracking changes
	CheckCvars();

	if (g_listEntity.integer) {
		for (i = 0; i < MAX_GENTITIES; i++) {
			G_Printf("%4i: %s\n", i, g_entities[i].classname);
		}
		trap_Cvar_Set("g_listEntity", "0");
	}
}
예제 #3
0
파일: g_main.c 프로젝트: osfpsproject/MF2
/*
================
G_RunFrame

Advances the non-player objects in the world
================
*/
void G_RunFrame( int levelTime ) 
{
	int i;
	// if we are waiting for the level to restart, do nothing
	if( theLevel.restarted_ )
		return;

	theLevel.framenum_++;
	theLevel.previousTime_ = theLevel.time_;
	theLevel.time_ = levelTime;
	int msec = theLevel.time_ - theLevel.previousTime_;

	// get any cvar changes
	G_UpdateCvars();

	//
	// go through all allocated objects
	//
	int start = Sys_Milliseconds();
	GameEntity* ent = 0;//&g_entities[0];
	for( i=0 ; i<theLevel.num_entities_ ; i++ )
	{
		ent = theLevel.getEntity(i);
		if( !ent || !ent->inuse_ ) 
			continue;

		// clear events that are too old
		if( theLevel.time_ - ent->eventTime_ > EVENT_VALID_MSEC ) 
		{
			if( ent->s.event ) 
			{
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if( ent->client_ ) 
				{
					ent->client_->ps_.externalEvent = 0;
					// predicted events should never be set to zero
					//ent->client->ps.events[0] = 0;
					//ent->client->ps.events[1] = 0;
				}
			}
			if( ent->freeAfterEvent_ ) 
			{
				// tempEntities or dropped items completely go away after their event
				ent->freeUp();// former G_FreeEntity
				continue;
			} 
			else if( ent->unlinkAfterEvent_ ) 
			{
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent_ = false;
				SV_UnlinkEntity( ent );
			}
		}
		// temporary entities don't think
		if( ent->freeAfterEvent_ ) 
			continue;

		if( ent->s.eType == ET_MISSILE ||
			 ent->s.eType == ET_BULLET ) 
		{
			G_RunMissile( ent );
			continue;
		}
		if( ent->s.eType == ET_ITEM || ent->physicsObject_ ) 
		{
			G_RunItem( ent );
			continue;
		}
		if( ent->s.eType == ET_MOVER )
		{
			G_RunMover( ent );
			continue;
		}
		if( ent->client_ )
		{
			G_RunClient( ent );
			continue;
		}
		G_RunThink( ent );
	}
	int end = Sys_Milliseconds();

	start = Sys_Milliseconds();
	// perform final fixups on the players
	//ent = &g_entities[0];
	for( i=1 ; i <= theLevel.maxclients_ ; i++ ) 
	{
		ent = theLevel.getEntity(i);
		if( ent && ent->inuse_ ) 
			ClientEndFrame( ent );
	}
	end = Sys_Milliseconds();

	// see if it is time to do a tournement restart
	CheckTournament();

	// see if it is time to end the level
	CheckExitRules();

	// update to team status?
	CheckTeamStatus();

	// cancel vote if timed out
	CheckVote();

	// check team votes
	CheckTeamVote( ClientBase::TEAM_RED );
	CheckTeamVote( ClientBase::TEAM_BLUE );

	// for tracking changes
	CheckCvars();

	if( g_listEntity.integer ) 
	{
		for( i = 0; i < MAX_GENTITIES; i++ )
		{
			ent = theLevel.getEntity(i);
			Com_Printf("%4i: %s\n", i, ent->classname_);
		}
		Cvar_Set("g_listEntity", "0");
	}
}