/* ================= CG_DrawActiveFrame Generates and draws a game scene and status information at the given time. ================= */ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) { int inwater; qboolean renderClientViewport[MAX_SPLITVIEW]; int i; cg.time = serverTime; cg.demoPlayback = demoPlayback; // update cvars CG_UpdateCvars(); // if we are only updating the screen as a loading // pacifier, don't even try to read snapshots if ( cg.infoScreenText[0] != 0 ) { CG_DrawInformation(); return; } // any looped sounds will be respecified as entities // are added to the render list trap_S_ClearLoopingSounds(qfalse); // clear all the render lists trap_R_ClearScene(); // set up cg.snap and possibly cg.nextSnap CG_ProcessSnapshots(); // if we haven't received any snapshots yet, all // we can draw is the information screen if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) { CG_DrawInformation(); return; } // this counter will be bumped for every valid scene we generate cg.clientFrame++; // Use single camera/viewport at intermission for (i = 0; i < CG_MaxSplitView(); i++) { if (cg.snap->lcIndex[i] != -1 && cg.snap->pss[i].pm_type != PM_INTERMISSION) { // client present and not at intermission, keep viewports separate. break; } } cg.singleCamera = (cg.snap->numPSs > 1) && (i == CG_MaxSplitView()); cg.numViewports = 0; for (i = 0; i < CG_MaxSplitView(); i++) { if (cg.snap->lcIndex[i] == -1) { renderClientViewport[i] = qfalse; continue; } cg.cur_localClientNum = i; cg.cur_lc = &cg.localClients[i]; cg.cur_ps = &cg.snap->pss[cg.snap->lcIndex[i]]; // Check if viewport should be drawn. if ( cg.singleCamera && cg.numViewports >= 1 ) { renderClientViewport[i] = qfalse; } else { cg.numViewports++; renderClientViewport[i] = qtrue; } // let the client system know what our weapon and zoom settings are trap_SetUserCmdValue( cg.cur_lc->weaponSelect, cg.cur_lc->zoomSensitivity, cg.cur_localClientNum ); // update cg.predictedPlayerState CG_PredictPlayerState(); // Remove expired console lines if( cg.cur_lc->consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 ) { CG_RemoveNotifyLine( cg.cur_lc ); } } // If all local clients dropped out from playing still draw main local client. if (cg.numViewports == 0) { cg.numViewports = 1; renderClientViewport[0] = qtrue; } // play lead change annoucement and time/frag limit warnings CG_CheckGameSounds(); // add buffered sounds CG_PlayBufferedSounds(); #ifdef MISSIONPACK // play buffered voice chats CG_PlayBufferedVoiceChats(); #endif for (i = 0, cg.viewport = -1; i < CG_MaxSplitView(); i++) { if (!renderClientViewport[i]) { continue; } cg.viewport++; cg.cur_localClientNum = i; cg.cur_lc = &cg.localClients[i]; cg.cur_ps = &cg.snap->pss[cg.snap->lcIndex[i]]; // decide on third person view cg.cur_lc->renderingThirdPerson = cg_thirdPerson[cg.cur_localClientNum].integer || (cg.cur_ps->stats[STAT_HEALTH] <= 0); CG_PB_ClearPolyBuffers(); // build cg.refdef inwater = CG_CalcViewValues(); CG_SetupFrustum(); // first person blend blobs, done after AnglesToAxis if ( !cg.cur_lc->renderingThirdPerson ) { CG_DamageBlendBlob(); } // build the render lists if ( !cg.cur_lc->hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); CG_AddParticles (); CG_AddLocalEntities(); CG_AddAtmosphericEffects(); } CG_AddViewWeapon( &cg.cur_lc->predictedPlayerState ); // finish up the rest of the refdef if ( cg.testModelEntity.hModel ) { CG_AddTestModel(); } cg.refdef.time = cg.time; memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) ); // warning sounds when powerup is wearing off CG_PowerupTimerSounds(); // update audio positions trap_S_Respatialize( cg.cur_ps->clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater, !cg.cur_lc->renderingThirdPerson ); // make sure the lagometerSample and frame timing isn't done twice when in stereo if ( stereoView != STEREO_RIGHT && cg.viewport == 0 ) { cg.frametime = cg.time - cg.oldTime; if ( cg.frametime < 0 ) { cg.frametime = 0; } cg.oldTime = cg.time; CG_AddLagometerFrameInfo(); } if (cg_timescale.value != cg_timescaleFadeEnd.value) { if (cg_timescale.value < cg_timescaleFadeEnd.value) { cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000; if (cg_timescale.value > cg_timescaleFadeEnd.value) cg_timescale.value = cg_timescaleFadeEnd.value; } else { cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000; if (cg_timescale.value < cg_timescaleFadeEnd.value) cg_timescale.value = cg_timescaleFadeEnd.value; } if (cg_timescaleFadeSpeed.value) { trap_Cvar_Set("timescale", va("%f", cg_timescale.value)); } } // actually issue the rendering calls CG_DrawActive( stereoView ); } // load any models that have been deferred if a scoreboard is shown if ( !CG_AnyScoreboardShowing() ) { cg.deferredPlayerLoading = 0; } else if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } if (cg.numViewports != 1) { // Setup single viewport cg.numViewports = 1; cg.viewport = 0; // calculate size of viewport CG_CalcVrect(); } // Not drawing single client view. cg.cur_lc = NULL; cg.cur_ps = NULL; cg.cur_localClientNum = -1; // Draw over all viewports CG_DrawScreen2D( stereoView ); if ( cg_stats.integer ) { CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame ); } }
/* ================= CG_DrawActiveFrame Generates and draws a game scene and status information at the given time. ================= */ void CG_DrawActiveFrame( int serverTime, qboolean demoPlayback ) { int inwater; cg.time = serverTime; cg.demoPlayback = demoPlayback; trap_Rocket_ClearText(); CG_NotifyHooks(); // any looped sounds will be respecified as entities // are added to the render list trap_S_ClearLoopingSounds( qfalse ); // clear all the render lists trap_R_ClearScene(); // set up cg.snap and possibly cg.nextSnap CG_ProcessSnapshots(); // if we haven't received any snapshots yet, all // we can draw is the information screen if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) { return; } // let the client system know what our weapon and zoom settings are trap_SetUserCmdValue( cg.weaponSelect, 0, cg.zoomSensitivity ); // this counter will be bumped for every valid scene we generate cg.clientFrame++; // update cg.predictedPlayerState CG_PredictPlayerState(); // update unlockables data (needs valid predictedPlayerState) CG_UpdateUnlockables( &cg.predictedPlayerState ); // update cvars (needs valid unlockables data) CG_UpdateCvars(); // decide on third person view cg.renderingThirdPerson = ( cg_thirdPerson.integer || ( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 ) || ( cg.chaseFollow && cg.snap->ps.pm_flags & PMF_FOLLOW ) ); // update speedometer CG_AddSpeed(); // build cg.refdef inwater = CG_CalcViewValues(); //build culling planes CG_SetupFrustum(); // build the render lists if ( !cg.hyperspace ) { CG_AddPacketEntities(); // after calcViewValues, so predicted player state is correct CG_AddMarks(); } CG_AddViewWeapon( &cg.predictedPlayerState ); //after CG_AddViewWeapon if ( !cg.hyperspace ) { CG_AddParticles(); CG_AddTrails(); } // finish up the rest of the refdef if ( cg.testModelEntity.hModel ) { CG_AddTestModel(); } cg.refdef.time = cg.time; memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) ); //remove expired console lines if ( cg.consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 ) { CG_RemoveNotifyLine(); } // update audio positions if (cg_thirdPerson.value) { trap_S_Respatialize( -1, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); } else { trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); } cg.frametime = cg.time - cg.oldTime; if ( cg.frametime < 0 ) { cg.frametime = 0; } cg.oldTime = cg.time; CG_AddLagometerFrameInfo(); if ( cg_timescale.value != cg_timescaleFadeEnd.value ) { if ( cg_timescale.value < cg_timescaleFadeEnd.value ) { cg_timescale.value += cg_timescaleFadeSpeed.value * ( ( float ) cg.frametime ) / 1000; if ( cg_timescale.value > cg_timescaleFadeEnd.value ) { cg_timescale.value = cg_timescaleFadeEnd.value; } } else { cg_timescale.value -= cg_timescaleFadeSpeed.value * ( ( float ) cg.frametime ) / 1000; if ( cg_timescale.value < cg_timescaleFadeEnd.value ) { cg_timescale.value = cg_timescaleFadeEnd.value; } } if ( cg_timescaleFadeSpeed.value ) { trap_Cvar_Set( "timescale", va( "%f", cg_timescale.value ) ); } } // actually issue the rendering calls CG_DrawActive(); if ( cg_stats.integer ) { CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame ); } }
/* ================= CG_DrawActiveFrame Generates and draws a game scene and status information at the given time. ================= */ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qbool demoPlayback ) { int inwater; cg.time = serverTime; //unlagged - lag simulation #1 // adjust the clock to reflect latent snaps cg.time -= cg_latentSnaps.integer * (1000 / sv_fps.integer); //unlagged - lag simulation #1 cg.demoPlayback = demoPlayback; // update cvars CG_UpdateCvars(); // if we are only updating the screen as a loading // pacifier, don't even try to read snapshots if ( cg.infoScreenText[0] != 0 ) { CG_DrawInformation(); return; } // any looped sounds will be respecified as entities // are added to the render list trap_S_ClearLoopingSounds(qfalse); // clear all the render lists trap_R_ClearScene(); // set up cg.snap and possibly cg.nextSnap CG_ProcessSnapshots(); // if we haven't received any snapshots yet, all // we can draw is the information screen if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) { CG_DrawInformation(); return; } // let the client system know what our weapon and zoom settings are trap_SetUserCmdValue( cg.weaponSelect, cg.zoomSensitivity ); // WP_SEC_PISTOL 's special value has been transmitted. // Restore cg.weaponSelect if (cg.weaponSelect == WP_SEC_PISTOL) cg.weaponSelect = cg._weaponSelect; // this counter will be bumped for every valid scene we generate cg.clientFrame++; // check if duel start sound has to be played if(cg.roundstarttime && cg.roundstarttime <= cg.time && cgs.gametype == GT_DUEL) { cg.introstart = cg.roundstarttime; cg.introend = cg.introstart + DU_INTRO_CAM + DU_INTRO_DRAW; cg.roundstarttime = 0; // cycle through the start tracks trap_S_StartLocalSound( cgs.media.duelstart[cg.duelstartsound], CHAN_ANNOUNCER ); cg.duelstartsound++; if(cg.duelstartsound == 5) cg.duelstartsound = 0; } // update cg.predictedPlayerState CG_PredictPlayerState(); // decide on third person view cg.renderingThirdPerson = cg_thirdPerson.integer || cg.introstart || (cgs.deathcam && (cg.snap->ps.stats[STAT_HEALTH] <= 0) && !(cg.snap->ps.pm_flags & PMF_SUICIDE) && !(cg.snap->ps.pm_flags & PMF_FOLLOW) && (cg.snap->ps.pm_type != PM_CHASECAM) && (cgs.gametype != GT_DUEL)); // build cg.refdef inwater = CG_CalcViewValues(); // build cg_frustum, from cg.refdef CG_SetupFrustum(); // first person blend blobs, done after AnglesToAxis if ( !cg.renderingThirdPerson ) { CG_DamageBlendBlob(); } // build the render lists if ( !cg.hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); CG_AddLocalEntities(); } CG_AddViewWeapon( &cg.predictedPlayerState ); // add buffered sounds CG_PlayBufferedSounds(); // finish up the rest of the refdef if ( cg.testModelEntity.hModel ) { CG_AddTestModel(); } cg.refdef.time = cg.time; memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) ); // update audio positions trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); // make sure the lagometerSample and frame timing isn't done twice when in stereo if ( stereoView != STEREO_RIGHT ) { cg.frametime = cg.time - cg.oldTime; if ( cg.frametime < 0 ) { cg.frametime = 0; } cg.oldTime = cg.time; CG_AddLagometerFrameInfo(); } if (cg_timescale.value != cg_timescaleFadeEnd.value) { if (cg_timescale.value < cg_timescaleFadeEnd.value) { cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000; if (cg_timescale.value > cg_timescaleFadeEnd.value) cg_timescale.value = cg_timescaleFadeEnd.value; } else { cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000; if (cg_timescale.value < cg_timescaleFadeEnd.value) cg_timescale.value = cg_timescaleFadeEnd.value; } if (cg_timescaleFadeSpeed.value) { trap_Cvar_Set("timescale", va("%f", cg_timescale.value)); } } // actually issue the rendering calls CG_DrawActive( stereoView ); if ( cg_stats.integer ) { CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame ); } }