2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
23
// cg_view.c -- setup all the parameters (position, angle, etc)
29
=============================================================================
33
The viewthing and gun positioning tools from Q2 have been integrated and
34
enhanced into a single model testing facility.
36
Model viewing can begin with either "testmodel <modelname>" or "testgun <modelname>".
38
The names must be the full pathname after the basedir, like
39
"models/weapons/v_launch/tris.md3" or "players/male/tris.md3"
41
Testmodel will create a fake entity 100 units in front of the current view
42
position, directly facing the viewer. It will remain immobile, so you can
43
move around it to view it from different angles.
45
Testgun will cause the model to follow the player around and supress the real
46
view weapon model. The default frame 0 of most guns is completely off screen,
47
so you will probably have to cycle a couple frames to see it.
49
"nextframe", "prevframe", "nextskin", and "prevskin" commands will change the
50
frame or skin of the testmodel. These are bound to F5, F6, F7, and F8 in
53
If a gun is being tested, the "gun_x", "gun_y", and "gun_z" variables will let
54
you adjust the positioning.
56
Note that none of the model testing features update while the game is paused, so
57
it may be convenient to test with deathmatch set to 1 so that bringing down the
58
console doesn't pause the game.
60
=============================================================================
67
Creates an entity in front of the current position, which
68
can then be moved around
71
void CG_TestModel_f (void) {
74
memset( &cg.testModelEntity, 0, sizeof(cg.testModelEntity) );
75
if ( trap_Argc() < 2 ) {
79
Q_strncpyz (cg.testModelName, CG_Argv( 1 ), MAX_QPATH );
80
cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
82
if ( trap_Argc() == 3 ) {
83
cg.testModelEntity.backlerp = atof( CG_Argv( 2 ) );
84
cg.testModelEntity.frame = 1;
85
cg.testModelEntity.oldframe = 0;
87
if (! cg.testModelEntity.hModel ) {
88
CG_Printf( "Can't register model\n" );
92
VectorMA( cg.refdef.vieworg, 100, cg.refdef.viewaxis[0], cg.testModelEntity.origin );
95
angles[YAW] = 180 + cg.refdefViewAngles[1];
98
AnglesToAxis( angles, cg.testModelEntity.axis );
106
Replaces the current view weapon with the given model
109
void CG_TestGun_f (void) {
112
cg.testModelEntity.renderfx = RF_MINLIGHT | RF_DEPTHHACK | RF_FIRST_PERSON;
116
void CG_TestModelNextFrame_f (void) {
117
cg.testModelEntity.frame++;
118
CG_Printf( "frame %i\n", cg.testModelEntity.frame );
121
void CG_TestModelPrevFrame_f (void) {
122
cg.testModelEntity.frame--;
123
if ( cg.testModelEntity.frame < 0 ) {
124
cg.testModelEntity.frame = 0;
126
CG_Printf( "frame %i\n", cg.testModelEntity.frame );
129
void CG_TestModelNextSkin_f (void) {
130
cg.testModelEntity.skinNum++;
131
CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
134
void CG_TestModelPrevSkin_f (void) {
135
cg.testModelEntity.skinNum--;
136
if ( cg.testModelEntity.skinNum < 0 ) {
137
cg.testModelEntity.skinNum = 0;
139
CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
142
static void CG_AddTestModel (void) {
145
// re-register the model, because the level may have changed
146
cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
147
if (! cg.testModelEntity.hModel ) {
148
CG_Printf ("Can't register model\n");
152
// if testing a gun, set the origin reletive to the view origin
154
VectorCopy( cg.refdef.vieworg, cg.testModelEntity.origin );
155
VectorCopy( cg.refdef.viewaxis[0], cg.testModelEntity.axis[0] );
156
VectorCopy( cg.refdef.viewaxis[1], cg.testModelEntity.axis[1] );
157
VectorCopy( cg.refdef.viewaxis[2], cg.testModelEntity.axis[2] );
159
// allow the position to be adjusted
160
for (i=0 ; i<3 ; i++) {
161
cg.testModelEntity.origin[i] += cg.refdef.viewaxis[0][i] * cg_gun_x.value;
162
cg.testModelEntity.origin[i] += cg.refdef.viewaxis[1][i] * cg_gun_y.value;
163
cg.testModelEntity.origin[i] += cg.refdef.viewaxis[2][i] * cg_gun_z.value;
167
trap_R_AddRefEntityToScene( &cg.testModelEntity );
172
//============================================================================
179
Sets the coordinates of the rendered window
182
static void CG_CalcVrect (void) {
185
// the intermission should allways be full screen
186
if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
189
// bound normal viewsize
190
if (cg_viewsize.integer < 30) {
191
trap_Cvar_Set ("cg_viewsize","30");
193
} else if (cg_viewsize.integer > 100) {
194
trap_Cvar_Set ("cg_viewsize","100");
197
size = cg_viewsize.integer;
201
cg.refdef.width = cgs.glconfig.vidWidth*size/100;
202
cg.refdef.width &= ~1;
204
cg.refdef.height = cgs.glconfig.vidHeight*size/100;
205
cg.refdef.height &= ~1;
207
cg.refdef.x = (cgs.glconfig.vidWidth - cg.refdef.width)/2;
208
cg.refdef.y = (cgs.glconfig.vidHeight - cg.refdef.height)/2;
211
//==============================================================================
216
CG_OffsetThirdPersonView
220
#define FOCUS_DISTANCE 512
221
static void CG_OffsetThirdPersonView( void ) {
222
vec3_t forward, right, up;
226
static vec3_t mins = { -4, -4, -4 };
227
static vec3_t maxs = { 4, 4, 4 };
230
float forwardScale, sideScale;
232
cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight;
234
VectorCopy( cg.refdefViewAngles, focusAngles );
236
// if dead, look at killer
237
if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
238
focusAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW];
239
cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW];
242
if ( focusAngles[PITCH] > 45 ) {
243
focusAngles[PITCH] = 45; // don't go too far overhead
245
AngleVectors( focusAngles, forward, NULL, NULL );
247
VectorMA( cg.refdef.vieworg, FOCUS_DISTANCE, forward, focusPoint );
249
VectorCopy( cg.refdef.vieworg, view );
253
cg.refdefViewAngles[PITCH] *= 0.5;
255
AngleVectors( cg.refdefViewAngles, forward, right, up );
257
forwardScale = cos( cg_thirdPersonAngle.value / 180 * M_PI );
258
sideScale = sin( cg_thirdPersonAngle.value / 180 * M_PI );
259
VectorMA( view, -cg_thirdPersonRange.value * forwardScale, forward, view );
260
VectorMA( view, -cg_thirdPersonRange.value * sideScale, right, view );
262
// trace a ray from the origin to the viewpoint to make sure the view isn't
263
// in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything
265
if (!cg_cameraMode.integer) {
266
CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID );
268
if ( trace.fraction != 1.0 ) {
269
VectorCopy( trace.endpos, view );
270
view[2] += (1.0 - trace.fraction) * 32;
271
// try another trace to this position, because a tunnel may have the ceiling
272
// close enogh that this is poking out
274
CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID );
275
VectorCopy( trace.endpos, view );
280
VectorCopy( view, cg.refdef.vieworg );
282
// select pitch to look at focus point from vieword
283
VectorSubtract( focusPoint, cg.refdef.vieworg, focusPoint );
284
focusDist = sqrt( focusPoint[0] * focusPoint[0] + focusPoint[1] * focusPoint[1] );
285
if ( focusDist < 1 ) {
286
focusDist = 1; // should never happen
288
cg.refdefViewAngles[PITCH] = -180 / M_PI * atan2( focusPoint[2], focusDist );
289
cg.refdefViewAngles[YAW] -= cg_thirdPersonAngle.value;
293
// this causes a compiler bug on mac MrC compiler
294
static void CG_StepOffset( void ) {
297
// smooth out stair climbing
298
timeDelta = cg.time - cg.stepTime;
299
if ( timeDelta < STEP_TIME ) {
300
cg.refdef.vieworg[2] -= cg.stepChange
301
* (STEP_TIME - timeDelta) / STEP_TIME;
307
CG_OffsetFirstPersonView
311
static void CG_OffsetFirstPersonView( void ) {
319
vec3_t predictedVelocity;
322
if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
326
origin = cg.refdef.vieworg;
327
angles = cg.refdefViewAngles;
329
// if dead, fix the angle and don't add any kick
330
if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
333
angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
334
origin[2] += cg.predictedPlayerState.viewheight;
338
// add angles based on weapon kick
339
VectorAdd (angles, cg.kick_angles, angles);
341
// add angles based on damage kick
342
if ( cg.damageTime ) {
343
ratio = cg.time - cg.damageTime;
344
if ( ratio < DAMAGE_DEFLECT_TIME ) {
345
ratio /= DAMAGE_DEFLECT_TIME;
346
angles[PITCH] += ratio * cg.v_dmg_pitch;
347
angles[ROLL] += ratio * cg.v_dmg_roll;
349
ratio = 1.0 - ( ratio - DAMAGE_DEFLECT_TIME ) / DAMAGE_RETURN_TIME;
351
angles[PITCH] += ratio * cg.v_dmg_pitch;
352
angles[ROLL] += ratio * cg.v_dmg_roll;
357
// add pitch based on fall kick
359
ratio = ( cg.time - cg.landTime) / FALL_TIME;
362
angles[PITCH] += ratio * cg.fall_value;
365
// add angles based on velocity
366
VectorCopy( cg.predictedPlayerState.velocity, predictedVelocity );
368
delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[0]);
369
angles[PITCH] += delta * cg_runpitch.value;
371
delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[1]);
372
angles[ROLL] -= delta * cg_runroll.value;
374
// add angles based on bob
376
// make sure the bob is visible even at low speeds
377
speed = cg.xyspeed > 200 ? cg.xyspeed : 200;
379
delta = cg.bobfracsin * cg_bobpitch.value * speed;
380
if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
381
delta *= 3; // crouching
382
angles[PITCH] += delta;
383
delta = cg.bobfracsin * cg_bobroll.value * speed;
384
if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
385
delta *= 3; // crouching accentuates roll
388
angles[ROLL] += delta;
390
//===================================
393
origin[2] += cg.predictedPlayerState.viewheight;
395
// smooth out duck height changes
396
timeDelta = cg.time - cg.duckTime;
397
if ( timeDelta < DUCK_TIME) {
398
cg.refdef.vieworg[2] -= cg.duckChange
399
* (DUCK_TIME - timeDelta) / DUCK_TIME;
403
bob = cg.bobfracsin * cg.xyspeed * cg_bobup.value;
412
delta = cg.time - cg.landTime;
413
if ( delta < LAND_DEFLECT_TIME ) {
414
f = delta / LAND_DEFLECT_TIME;
415
cg.refdef.vieworg[2] += cg.landChange * f;
416
} else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
417
delta -= LAND_DEFLECT_TIME;
418
f = 1.0 - ( delta / LAND_RETURN_TIME );
419
cg.refdef.vieworg[2] += cg.landChange * f;
427
VectorAdd (origin, cg.kick_origin, origin);
429
// pivot the eye based on a neck length
432
#define NECK_LENGTH 8
435
cg.refdef.vieworg[2] -= NECK_LENGTH;
436
AngleVectors( cg.refdefViewAngles, forward, NULL, up );
437
VectorMA( cg.refdef.vieworg, 3, forward, cg.refdef.vieworg );
438
VectorMA( cg.refdef.vieworg, NECK_LENGTH, up, cg.refdef.vieworg );
443
//======================================================================
445
void CG_ZoomDown_f( void ) {
450
cg.zoomTime = cg.time;
453
void CG_ZoomUp_f( void ) {
458
cg.zoomTime = cg.time;
466
Fixed fov at intermissions, otherwise account for fov variable and zooms.
469
#define WAVE_AMPLITUDE 1
470
#define WAVE_FREQUENCY 0.4
472
static int CG_CalcFov( void ) {
482
if ( cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
483
// if in intermission, use a fixed value
487
if ( cgs.dmflags & DF_FIXED_FOV ) {
488
// dmflag to prevent wide fov for all clients
491
fov_x = cg_fov.value;
494
} else if ( fov_x > 160 ) {
500
zoomFov = cg_zoomFov.value;
503
} else if ( zoomFov > 160 ) {
508
f = ( cg.time - cg.zoomTime ) / (float)ZOOM_TIME;
512
fov_x = fov_x + f * ( zoomFov - fov_x );
515
f = ( cg.time - cg.zoomTime ) / (float)ZOOM_TIME;
519
fov_x = zoomFov + f * ( fov_x - zoomFov );
524
x = cg.refdef.width / tan( fov_x / 360 * M_PI );
525
fov_y = atan2( cg.refdef.height, x );
526
fov_y = fov_y * 360 / M_PI;
528
// warp if underwater
529
contents = CG_PointContents( cg.refdef.vieworg, -1 );
530
if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ){
531
phase = cg.time / 1000.0 * WAVE_FREQUENCY * M_PI * 2;
532
v = WAVE_AMPLITUDE * sin( phase );
543
cg.refdef.fov_x = fov_x;
544
cg.refdef.fov_y = fov_y;
547
cg.zoomSensitivity = 1;
549
cg.zoomSensitivity = cg.refdef.fov_y / 75.0;
563
static void CG_DamageBlendBlob( void ) {
568
if ( !cg.damageValue ) {
572
//if (cg.cameraMode) {
576
// ragePro systems can't fade blends, so don't obscure the screen
577
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
581
maxTime = DAMAGE_TIME;
582
t = cg.time - cg.damageTime;
583
if ( t <= 0 || t >= maxTime ) {
588
memset( &ent, 0, sizeof( ent ) );
589
ent.reType = RT_SPRITE;
590
ent.renderfx = RF_FIRST_PERSON;
592
VectorMA( cg.refdef.vieworg, 8, cg.refdef.viewaxis[0], ent.origin );
593
VectorMA( ent.origin, cg.damageX * -8, cg.refdef.viewaxis[1], ent.origin );
594
VectorMA( ent.origin, cg.damageY * 8, cg.refdef.viewaxis[2], ent.origin );
596
ent.radius = cg.damageValue * 3;
597
ent.customShader = cgs.media.viewBloodShader;
598
ent.shaderRGBA[0] = 255;
599
ent.shaderRGBA[1] = 255;
600
ent.shaderRGBA[2] = 255;
601
ent.shaderRGBA[3] = 200 * ( 1.0 - ((float)t / maxTime) );
602
trap_R_AddRefEntityToScene( &ent );
610
Sets cg.refdef view values
613
static int CG_CalcViewValues( void ) {
616
memset( &cg.refdef, 0, sizeof( cg.refdef ) );
618
// strings for in game rendering
619
// Q_strncpyz( cg.refdef.text[0], "Park Ranger", sizeof(cg.refdef.text[0]) );
620
// Q_strncpyz( cg.refdef.text[1], "19", sizeof(cg.refdef.text[1]) );
622
// calculate size of 3D view
625
ps = &cg.predictedPlayerState;
628
vec3_t origin, angles;
629
if (trap_getCameraInfo(cg.time, &origin, &angles)) {
630
VectorCopy(origin, cg.refdef.vieworg);
632
VectorCopy(angles, cg.refdefViewAngles);
633
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
636
cg.cameraMode = qfalse;
641
if ( ps->pm_type == PM_INTERMISSION ) {
642
VectorCopy( ps->origin, cg.refdef.vieworg );
643
VectorCopy( ps->viewangles, cg.refdefViewAngles );
644
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
648
cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
649
cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );
650
cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] +
651
ps->velocity[1] * ps->velocity[1] );
654
VectorCopy( ps->origin, cg.refdef.vieworg );
655
VectorCopy( ps->viewangles, cg.refdefViewAngles );
657
if (cg_cameraOrbit.integer) {
658
if (cg.time > cg.nextOrbitTime) {
659
cg.nextOrbitTime = cg.time + cg_cameraOrbitDelay.integer;
660
cg_thirdPersonAngle.value += cg_cameraOrbit.value;
664
if ( cg_errorDecay.value > 0 ) {
668
t = cg.time - cg.predictedErrorTime;
669
f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
670
if ( f > 0 && f < 1 ) {
671
VectorMA( cg.refdef.vieworg, f, cg.predictedError, cg.refdef.vieworg );
673
cg.predictedErrorTime = 0;
677
if ( cg.renderingThirdPerson ) {
678
// back away from character
679
CG_OffsetThirdPersonView();
681
// offset for local bobbing and kicks
682
CG_OffsetFirstPersonView();
685
// position eye reletive to origin
686
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
688
if ( cg.hyperspace ) {
689
cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
698
=====================
699
CG_PowerupTimerSounds
700
=====================
702
static void CG_PowerupTimerSounds( void ) {
706
// powerup timers going away
707
for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
708
t = cg.snap->ps.powerups[i];
709
if ( t <= cg.time ) {
712
if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
715
if ( ( t - cg.time ) / POWERUP_BLINK_TIME != ( t - cg.oldTime ) / POWERUP_BLINK_TIME ) {
716
trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_ITEM, cgs.media.wearOffSound );
722
=====================
724
=====================
726
void CG_AddBufferedSound( sfxHandle_t sfx ) {
729
cg.soundBuffer[cg.soundBufferIn] = sfx;
730
cg.soundBufferIn = (cg.soundBufferIn + 1) % MAX_SOUNDBUFFER;
731
if (cg.soundBufferIn == cg.soundBufferOut) {
737
=====================
738
CG_PlayBufferedSounds
739
=====================
741
static void CG_PlayBufferedSounds( void ) {
742
if ( cg.soundTime < cg.time ) {
743
if (cg.soundBufferOut != cg.soundBufferIn && cg.soundBuffer[cg.soundBufferOut]) {
744
trap_S_StartLocalSound(cg.soundBuffer[cg.soundBufferOut], CHAN_ANNOUNCER);
745
cg.soundBuffer[cg.soundBufferOut] = 0;
746
cg.soundBufferOut = (cg.soundBufferOut + 1) % MAX_SOUNDBUFFER;
747
cg.soundTime = cg.time + 750;
752
//=========================================================================
758
Generates and draws a game scene and status information at the given time.
761
void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) {
764
cg.time = serverTime;
765
cg.demoPlayback = demoPlayback;
770
// if we are only updating the screen as a loading
771
// pacifier, don't even try to read snapshots
772
if ( cg.infoScreenText[0] != 0 ) {
773
CG_DrawInformation();
777
// any looped sounds will be respecified as entities
778
// are added to the render list
779
trap_S_ClearLoopingSounds(qfalse);
781
// clear all the render lists
784
// set up cg.snap and possibly cg.nextSnap
785
CG_ProcessSnapshots();
787
// if we haven't received any snapshots yet, all
788
// we can draw is the information screen
789
if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
790
CG_DrawInformation();
794
// let the client system know what our weapon and zoom settings are
795
trap_SetUserCmdValue( cg.weaponSelect, cg.zoomSensitivity );
797
// this counter will be bumped for every valid scene we generate
800
// update cg.predictedPlayerState
801
CG_PredictPlayerState();
803
// decide on third person view
804
cg.renderingThirdPerson = cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0);
807
inwater = CG_CalcViewValues();
809
// first person blend blobs, done after AnglesToAxis
810
if ( !cg.renderingThirdPerson ) {
811
CG_DamageBlendBlob();
814
// build the render lists
815
if ( !cg.hyperspace ) {
816
CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct
819
CG_AddLocalEntities();
821
CG_AddViewWeapon( &cg.predictedPlayerState );
823
// add buffered sounds
824
CG_PlayBufferedSounds();
826
// play buffered voice chats
827
CG_PlayBufferedVoiceChats();
829
// finish up the rest of the refdef
830
if ( cg.testModelEntity.hModel ) {
833
cg.refdef.time = cg.time;
834
memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) );
836
// warning sounds when powerup is wearing off
837
CG_PowerupTimerSounds();
839
// update audio positions
840
trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater );
842
// make sure the lagometerSample and frame timing isn't done twice when in stereo
843
if ( stereoView != STEREO_RIGHT ) {
844
cg.frametime = cg.time - cg.oldTime;
845
if ( cg.frametime < 0 ) {
848
cg.oldTime = cg.time;
849
CG_AddLagometerFrameInfo();
851
if (cg_timescale.value != cg_timescaleFadeEnd.value) {
852
if (cg_timescale.value < cg_timescaleFadeEnd.value) {
853
cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
854
if (cg_timescale.value > cg_timescaleFadeEnd.value)
855
cg_timescale.value = cg_timescaleFadeEnd.value;
858
cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
859
if (cg_timescale.value < cg_timescaleFadeEnd.value)
860
cg_timescale.value = cg_timescaleFadeEnd.value;
862
if (cg_timescaleFadeSpeed.value) {
863
trap_Cvar_Set("timescale", va("%f", cg_timescale.value));
867
// actually issue the rendering calls
868
CG_DrawActive( stereoView );
870
if ( cg_stats.integer ) {
871
CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame );