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"); } }
/* ================ 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"); } }