00001
00002
00003
00004
00005 #include "cg_local.h"
00006
00007 #include "bg_saga.h"
00008
00009 #if !defined(CL_LIGHT_H_INC)
00010 #include "cg_lights.h"
00011 #endif
00012
00013 #define MASK_CAMERACLIP (MASK_SOLID|CONTENTS_PLAYERCLIP)
00014 #define CAMERA_SIZE 4
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 void CG_TestModel_f (void) {
00061 vec3_t angles;
00062
00063 memset( &cg.testModelEntity, 0, sizeof(cg.testModelEntity) );
00064 if ( trap_Argc() < 2 ) {
00065 return;
00066 }
00067
00068 Q_strncpyz (cg.testModelName, CG_Argv( 1 ), MAX_QPATH );
00069 cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
00070
00071 if ( trap_Argc() == 3 ) {
00072 cg.testModelEntity.backlerp = atof( CG_Argv( 2 ) );
00073 cg.testModelEntity.frame = 1;
00074 cg.testModelEntity.oldframe = 0;
00075 }
00076 if (! cg.testModelEntity.hModel ) {
00077 CG_Printf( "Can't register model\n" );
00078 return;
00079 }
00080
00081 VectorMA( cg.refdef.vieworg, 100, cg.refdef.viewaxis[0], cg.testModelEntity.origin );
00082
00083 angles[PITCH] = 0;
00084 angles[YAW] = 180 + cg.refdef.viewangles[1];
00085 angles[ROLL] = 0;
00086
00087 AnglesToAxis( angles, cg.testModelEntity.axis );
00088 cg.testGun = qfalse;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 void CG_TestGun_f (void) {
00099 CG_TestModel_f();
00100 cg.testGun = qtrue;
00101
00102
00103
00104 cg.testModelEntity.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON;
00105 }
00106
00107
00108 void CG_TestModelNextFrame_f (void) {
00109 cg.testModelEntity.frame++;
00110 CG_Printf( "frame %i\n", cg.testModelEntity.frame );
00111 }
00112
00113 void CG_TestModelPrevFrame_f (void) {
00114 cg.testModelEntity.frame--;
00115 if ( cg.testModelEntity.frame < 0 ) {
00116 cg.testModelEntity.frame = 0;
00117 }
00118 CG_Printf( "frame %i\n", cg.testModelEntity.frame );
00119 }
00120
00121 void CG_TestModelNextSkin_f (void) {
00122 cg.testModelEntity.skinNum++;
00123 CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
00124 }
00125
00126 void CG_TestModelPrevSkin_f (void) {
00127 cg.testModelEntity.skinNum--;
00128 if ( cg.testModelEntity.skinNum < 0 ) {
00129 cg.testModelEntity.skinNum = 0;
00130 }
00131 CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
00132 }
00133
00134 static void CG_AddTestModel (void) {
00135 int i;
00136
00137
00138 cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
00139 if (! cg.testModelEntity.hModel ) {
00140 CG_Printf ("Can't register model\n");
00141 return;
00142 }
00143
00144
00145 if ( cg.testGun ) {
00146 VectorCopy( cg.refdef.vieworg, cg.testModelEntity.origin );
00147 VectorCopy( cg.refdef.viewaxis[0], cg.testModelEntity.axis[0] );
00148 VectorCopy( cg.refdef.viewaxis[1], cg.testModelEntity.axis[1] );
00149 VectorCopy( cg.refdef.viewaxis[2], cg.testModelEntity.axis[2] );
00150
00151
00152 for (i=0 ; i<3 ; i++) {
00153 cg.testModelEntity.origin[i] += cg.refdef.viewaxis[0][i] * cg_gun_x.value;
00154 cg.testModelEntity.origin[i] += cg.refdef.viewaxis[1][i] * cg_gun_y.value;
00155 cg.testModelEntity.origin[i] += cg.refdef.viewaxis[2][i] * cg_gun_z.value;
00156 }
00157 }
00158
00159 trap_R_AddRefEntityToScene( &cg.testModelEntity );
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 static void CG_CalcVrect (void) {
00175 int size;
00176
00177
00178 if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
00179 size = 100;
00180 } else {
00181
00182 if (cg_viewsize.integer < 30) {
00183 trap_Cvar_Set ("cg_viewsize","30");
00184 size = 30;
00185 } else if (cg_viewsize.integer > 100) {
00186 trap_Cvar_Set ("cg_viewsize","100");
00187 size = 100;
00188 } else {
00189 size = cg_viewsize.integer;
00190 }
00191
00192 }
00193 cg.refdef.width = cgs.glconfig.vidWidth*size/100;
00194 cg.refdef.width &= ~1;
00195
00196 cg.refdef.height = cgs.glconfig.vidHeight*size/100;
00197 cg.refdef.height &= ~1;
00198
00199 cg.refdef.x = (cgs.glconfig.vidWidth - cg.refdef.width)/2;
00200 cg.refdef.y = (cgs.glconfig.vidHeight - cg.refdef.height)/2;
00201 }
00202
00203
00204
00205
00206
00207
00208 static void CG_StepOffset( void ) {
00209 int timeDelta;
00210
00211
00212 timeDelta = cg.time - cg.stepTime;
00213 if ( timeDelta < STEP_TIME ) {
00214 cg.refdef.vieworg[2] -= cg.stepChange
00215 * (STEP_TIME - timeDelta) / STEP_TIME;
00216 }
00217 }
00218
00219 #define CAMERA_DAMP_INTERVAL 50
00220
00221 static vec3_t cameramins = { -CAMERA_SIZE, -CAMERA_SIZE, -CAMERA_SIZE };
00222 static vec3_t cameramaxs = { CAMERA_SIZE, CAMERA_SIZE, CAMERA_SIZE };
00223 vec3_t camerafwd, cameraup;
00224
00225 vec3_t cameraFocusAngles, cameraFocusLoc;
00226 vec3_t cameraIdealTarget, cameraIdealLoc;
00227 vec3_t cameraCurTarget={0,0,0}, cameraCurLoc={0,0,0};
00228 vec3_t cameraOldLoc={0,0,0}, cameraNewLoc={0,0,0};
00229 int cameraLastFrame=0;
00230
00231 float cameraLastYaw=0;
00232 float cameraStiffFactor=0.0f;
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 extern qboolean gCGHasFallVector;
00249 extern vec3_t gCGFallVector;
00250
00251
00252
00253
00254
00255
00256
00257 static void CG_CalcIdealThirdPersonViewTarget(void)
00258 {
00259
00260 if (gCGHasFallVector)
00261 {
00262 VectorCopy(gCGFallVector, cameraFocusLoc);
00263 }
00264 else
00265 {
00266 VectorCopy(cg.refdef.vieworg, cameraFocusLoc);
00267 }
00268
00269
00270 cameraFocusLoc[2] += cg.snap->ps.viewheight;
00271
00272
00273
00274
00275
00276 VectorCopy( cameraFocusLoc, cameraIdealTarget );
00277
00278 {
00279 float vertOffset = cg_thirdPersonVertOffset.value;
00280
00281 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00282 {
00283 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00284 if (veh->m_pVehicle &&
00285 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00286 {
00287 if ( veh->m_pVehicle->m_pVehicleInfo->cameraPitchDependantVertOffset )
00288 {
00289 if ( cg.snap->ps.viewangles[PITCH] > 0 )
00290 {
00291 vertOffset = 130+cg.predictedPlayerState.viewangles[PITCH]*-10;
00292 if ( vertOffset < -170 )
00293 {
00294 vertOffset = -170;
00295 }
00296 }
00297 else if ( cg.snap->ps.viewangles[PITCH] < 0 )
00298 {
00299 vertOffset = 130+cg.predictedPlayerState.viewangles[PITCH]*-5;
00300 if ( vertOffset > 130 )
00301 {
00302 vertOffset = 130;
00303 }
00304 }
00305 else
00306 {
00307 vertOffset = 30;
00308 }
00309 }
00310 else
00311 {
00312 vertOffset = veh->m_pVehicle->m_pVehicleInfo->cameraVertOffset;
00313 }
00314 }
00315 else if ( veh->m_pVehicle
00316 && veh->m_pVehicle->m_pVehicleInfo
00317 && veh->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL )
00318 {
00319 vertOffset = 0;
00320 }
00321 }
00322 cameraIdealTarget[2] += vertOffset;
00323 }
00324
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 static void CG_CalcIdealThirdPersonViewLocation(void)
00336 {
00337 float thirdPersonRange = cg_thirdPersonRange.value;
00338
00339 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00340 {
00341 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00342 if (veh->m_pVehicle &&
00343 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00344 {
00345 thirdPersonRange = veh->m_pVehicle->m_pVehicleInfo->cameraRange;
00346 if ( veh->playerState->hackingTime )
00347 {
00348 thirdPersonRange += fabs(((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * 100.0f;
00349 }
00350 }
00351 }
00352
00353 if ( cg.snap
00354 && (cg.snap->ps.eFlags2&EF2_HELD_BY_MONSTER)
00355 && cg.snap->ps.hasLookTarget
00356 && cg_entities[cg.snap->ps.lookTarget].currentState.NPC_class == CLASS_RANCOR )
00357 {
00358
00359 thirdPersonRange = 120.0f;
00360 }
00361
00362 VectorMA(cameraIdealTarget, -(thirdPersonRange), camerafwd, cameraIdealLoc);
00363 }
00364
00365
00366
00367 static void CG_ResetThirdPersonViewDamp(void)
00368 {
00369 trace_t trace;
00370
00371
00372 if (cameraFocusAngles[PITCH] > 89.0)
00373 {
00374 cameraFocusAngles[PITCH] = 89.0;
00375 }
00376 else if (cameraFocusAngles[PITCH] < -89.0)
00377 {
00378 cameraFocusAngles[PITCH] = -89.0;
00379 }
00380
00381 AngleVectors(cameraFocusAngles, camerafwd, NULL, cameraup);
00382
00383
00384 CG_CalcIdealThirdPersonViewTarget();
00385
00386
00387 CG_CalcIdealThirdPersonViewLocation();
00388
00389
00390 VectorCopy(cameraIdealLoc, cameraCurLoc);
00391 VectorCopy(cameraIdealTarget, cameraCurTarget);
00392
00393
00394 CG_Trace(&trace, cameraFocusLoc, cameramins, cameramaxs, cameraCurTarget, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00395 if (trace.fraction <= 1.0)
00396 {
00397 VectorCopy(trace.endpos, cameraCurTarget);
00398 }
00399
00400
00401 CG_Trace(&trace, cameraCurTarget, cameramins, cameramaxs, cameraCurLoc, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00402 if (trace.fraction <= 1.0)
00403 {
00404 VectorCopy(trace.endpos, cameraCurLoc);
00405 }
00406
00407 cameraLastFrame = cg.time;
00408 cameraLastYaw = cameraFocusAngles[YAW];
00409 cameraStiffFactor = 0.0f;
00410 }
00411
00412
00413 static void CG_UpdateThirdPersonTargetDamp(void)
00414 {
00415 trace_t trace;
00416 vec3_t targetdiff;
00417 float dampfactor, dtime, ratio;
00418
00419
00420
00421 CG_CalcIdealThirdPersonViewTarget();
00422
00423 if ( cg.predictedVehicleState.hyperSpaceTime
00424 && (cg.time-cg.predictedVehicleState.hyperSpaceTime) < HYPERSPACE_TIME )
00425 {
00426 VectorCopy(cameraIdealTarget, cameraCurTarget);
00427 }
00428 else if (cg_thirdPersonTargetDamp.value>=1.0||cg.thisFrameTeleport||cg.predictedPlayerState.m_iVehicleNum)
00429 {
00430 VectorCopy(cameraIdealTarget, cameraCurTarget);
00431 }
00432 else if (cg_thirdPersonTargetDamp.value>=0.0)
00433 {
00434
00435 VectorSubtract(cameraIdealTarget, cameraCurTarget, targetdiff);
00436
00437
00438
00439 dampfactor = 1.0-cg_thirdPersonTargetDamp.value;
00440 dtime = (float)(cg.time-cameraLastFrame) * (1.0/(float)CAMERA_DAMP_INTERVAL);
00441
00442
00443
00444 ratio = powf(dampfactor, dtime);
00445
00446
00447 VectorMA(cameraIdealTarget, -ratio, targetdiff, cameraCurTarget);
00449 }
00450
00451
00452
00453
00454 CG_Trace(&trace, cameraFocusLoc, cameramins, cameramaxs, cameraCurTarget, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00455 if (trace.fraction < 1.0)
00456 {
00457 VectorCopy(trace.endpos, cameraCurTarget);
00458 }
00459
00460
00461
00462
00463
00464 }
00465
00466
00467 extern void CG_CalcEntityLerpPositions( centity_t *cent );
00468 static void CG_UpdateThirdPersonCameraDamp(void)
00469 {
00470 trace_t trace;
00471 vec3_t locdiff;
00472 float dampfactor, dtime, ratio;
00473
00474
00475 CG_CalcIdealThirdPersonViewLocation();
00476
00477
00478
00479 dampfactor=0.0;
00480 if ( cg.predictedVehicleState.hyperSpaceTime
00481 && (cg.time-cg.predictedVehicleState.hyperSpaceTime) < HYPERSPACE_TIME )
00482 {
00483 dampfactor = 1.0f;
00484 }
00485 else if (cg_thirdPersonCameraDamp.value != 0.0)
00486 {
00487 float pitch;
00488 float dFactor;
00489
00490 if (!cg.predictedPlayerState.m_iVehicleNum)
00491 {
00492 dFactor = cg_thirdPersonCameraDamp.value;
00493 }
00494 else
00495 {
00496 dFactor = 1.0f;
00497 }
00498
00499
00500 pitch = Q_fabs(cameraFocusAngles[PITCH]);
00501
00502
00503 pitch /= 115.0;
00504 dampfactor = (1.0-dFactor)*(pitch*pitch);
00505
00506 dampfactor += dFactor;
00507
00508
00509 if (cameraStiffFactor > 0.0f)
00510 {
00511 dampfactor += (1.0-dampfactor)*cameraStiffFactor;
00512 }
00513 }
00514
00515 if (dampfactor>=1.0||cg.thisFrameTeleport)
00516 {
00517 VectorCopy(cameraIdealLoc, cameraCurLoc);
00518 }
00519 else if (dampfactor>=0.0)
00520 {
00521
00522 VectorSubtract(cameraIdealLoc, cameraCurLoc, locdiff);
00523
00524
00525
00526 dampfactor = 1.0-dampfactor;
00527 dtime = (float)(cg.time-cameraLastFrame) * (1.0/(float)CAMERA_DAMP_INTERVAL);
00528
00529
00530
00531 ratio = powf(dampfactor, dtime);
00532
00533
00534 VectorMA(cameraIdealLoc, -ratio, locdiff, cameraCurLoc);
00536 }
00537
00538
00539 CG_Trace(&trace, cameraCurTarget, cameramins, cameramaxs, cameraCurLoc, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00540
00541 if (trace.fraction < 1.0)
00542 {
00543 if (trace.entityNum < ENTITYNUM_WORLD &&
00544 cg_entities[trace.entityNum].currentState.solid == SOLID_BMODEL &&
00545 cg_entities[trace.entityNum].currentState.eType == ET_MOVER)
00546 {
00547 centity_t *mover = &cg_entities[trace.entityNum];
00548
00549
00550
00551
00552 if (mover->currentState.pos.trType != TR_STATIONARY &&
00553 mover->currentState.pos.trType != TR_LINEAR)
00554 {
00555 int curTr = mover->currentState.pos.trType;
00556 vec3_t curTrB;
00557
00558 VectorCopy(mover->currentState.pos.trBase, curTrB);
00559
00560
00561 CG_CalcEntityLerpPositions(mover);
00562
00563
00564
00565 mover->currentState.pos.trType = TR_STATIONARY;
00566 VectorCopy(mover->lerpOrigin, mover->currentState.pos.trBase);
00567
00568
00569 CG_Trace(&trace, cameraCurTarget, cameramins, cameramaxs, cameraCurLoc, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00570
00571
00572 mover->currentState.pos.trType = (trType_t) curTr;
00573 VectorCopy(curTrB, mover->currentState.pos.trBase);
00574 }
00575 if (trace.fraction < 1.0f)
00576 {
00577 VectorCopy(trace.endpos, cameraCurLoc);
00578 }
00579 }
00580 else
00581 {
00582 VectorCopy( trace.endpos, cameraCurLoc );
00583 }
00584 }
00585
00586
00587
00588
00589
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 extern vmCvar_t cg_thirdPersonHorzOffset;
00602 extern qboolean BG_UnrestrainedPitchRoll( playerState_t *ps, Vehicle_t *pVeh );
00603 static void CG_OffsetThirdPersonView( void )
00604 {
00605 vec3_t diff;
00606 float thirdPersonHorzOffset = cg_thirdPersonHorzOffset.value;
00607 float deltayaw;
00608
00609 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00610 {
00611 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00612 if (veh->m_pVehicle &&
00613 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00614 {
00615 thirdPersonHorzOffset = veh->m_pVehicle->m_pVehicleInfo->cameraHorzOffset;
00616 if ( veh->playerState->hackingTime )
00617 {
00618 thirdPersonHorzOffset += (((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * -80.0f;
00619 }
00620 }
00621 }
00622
00623 cameraStiffFactor = 0.0;
00624
00625
00626 VectorCopy( cg.refdef.viewangles, cameraFocusAngles );
00627
00628
00629 if ( cg.snap
00630 && (cg.snap->ps.eFlags2&EF2_HELD_BY_MONSTER)
00631 && cg.snap->ps.hasLookTarget
00632 && cg_entities[cg.snap->ps.lookTarget].currentState.NPC_class == CLASS_RANCOR )
00633 {
00634
00635 centity_t *monster = &cg_entities[cg.snap->ps.lookTarget];
00636 VectorSet( cameraFocusAngles, 0, AngleNormalize180(monster->lerpAngles[YAW]+180), 0 );
00637
00638
00639
00640
00641
00642
00643
00644 }
00645 else if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 )
00646 {
00647 cameraFocusAngles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
00648 }
00649 else
00650 {
00651 cameraFocusAngles[YAW] += cg_thirdPersonAngle.value;
00652 {
00653 float pitchOffset = cg_thirdPersonPitchOffset.value;
00654 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00655 {
00656 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00657 if (veh->m_pVehicle &&
00658 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00659 {
00660 if ( veh->m_pVehicle->m_pVehicleInfo->cameraPitchDependantVertOffset )
00661 {
00662 if ( cg.snap->ps.viewangles[PITCH] > 0 )
00663 {
00664 pitchOffset = cg.predictedPlayerState.viewangles[PITCH]*-0.75;
00665 }
00666 else if ( cg.snap->ps.viewangles[PITCH] < 0 )
00667 {
00668 pitchOffset = cg.predictedPlayerState.viewangles[PITCH]*-0.75;
00669 }
00670 else
00671 {
00672 pitchOffset = 0;
00673 }
00674 }
00675 else
00676 {
00677 pitchOffset = veh->m_pVehicle->m_pVehicleInfo->cameraPitchOffset;
00678 }
00679 }
00680 }
00681 if ( 0 && cg.predictedPlayerState.m_iVehicleNum
00682 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
00683 {
00684 float pitchPerc = ((90.0f-fabs(cameraFocusAngles[ROLL]))/90.0f);
00685 cameraFocusAngles[PITCH] += pitchOffset*pitchPerc;
00686 if ( cameraFocusAngles[ROLL] > 0 )
00687 {
00688 cameraFocusAngles[YAW] -= pitchOffset-(pitchOffset*pitchPerc);
00689 }
00690 else
00691 {
00692 cameraFocusAngles[YAW] += pitchOffset-(pitchOffset*pitchPerc);
00693 }
00694 }
00695 else
00696 {
00697 cameraFocusAngles[PITCH] += pitchOffset;
00698 }
00699 }
00700 }
00701
00702
00703
00704
00705 if (cameraLastFrame == 0 || cameraLastFrame > cg.time)
00706 {
00707 CG_ResetThirdPersonViewDamp();
00708 }
00709 else
00710 {
00711
00712 if ( cg.predictedPlayerState.m_iVehicleNum
00713 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
00714 {
00715
00716 }
00717 else
00718 {
00719 if (cameraFocusAngles[PITCH] > 80.0)
00720 {
00721 cameraFocusAngles[PITCH] = 80.0;
00722 }
00723 else if (cameraFocusAngles[PITCH] < -80.0)
00724 {
00725 cameraFocusAngles[PITCH] = -80.0;
00726 }
00727 }
00728
00729 AngleVectors(cameraFocusAngles, camerafwd, NULL, cameraup);
00730
00731 deltayaw = fabs(cameraFocusAngles[YAW] - cameraLastYaw);
00732 if (deltayaw > 180.0f)
00733 {
00734 deltayaw = fabs(deltayaw - 360.0f);
00735 }
00736 cameraStiffFactor = deltayaw / (float)(cg.time-cameraLastFrame);
00737 if (cameraStiffFactor < 1.0)
00738 {
00739 cameraStiffFactor = 0.0;
00740 }
00741 else if (cameraStiffFactor > 2.5)
00742 {
00743 cameraStiffFactor = 0.75;
00744 }
00745 else
00746 {
00747 cameraStiffFactor = (cameraStiffFactor-1.0f)*0.5f;
00748 }
00749 cameraLastYaw = cameraFocusAngles[YAW];
00750
00751
00752 CG_UpdateThirdPersonTargetDamp();
00753 CG_UpdateThirdPersonCameraDamp();
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763 VectorSubtract(cameraCurTarget, cameraCurLoc, diff);
00764 {
00765 float dist = VectorNormalize(diff);
00766
00767 if ( !dist || (diff[0] == 0 || diff[1] == 0) )
00768 {
00769 VectorCopy( camerafwd, diff );
00770 }
00771 }
00772 if ( 0 && cg.predictedPlayerState.m_iVehicleNum
00773 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
00774 {
00775 float sav_Roll = cg.refdef.viewangles[ROLL];
00776 vectoangles(diff, cg.refdef.viewangles);
00777 cg.refdef.viewangles[ROLL] = sav_Roll;
00778 }
00779 else
00780 {
00781 vectoangles(diff, cg.refdef.viewangles);
00782 }
00783
00784
00785 if ( thirdPersonHorzOffset != 0.0f )
00786 {
00787 AnglesToAxis( cg.refdef.viewangles, cg.refdef.viewaxis );
00788 VectorMA( cameraCurLoc, thirdPersonHorzOffset, cg.refdef.viewaxis[1], cameraCurLoc );
00789 }
00790
00791
00792 VectorCopy(cameraCurLoc, cg.refdef.vieworg);
00793
00794 cameraLastFrame=cg.time;
00795 }
00796
00797 void CG_GetVehicleCamPos( vec3_t camPos )
00798 {
00799 VectorCopy( cg.refdef.vieworg, camPos );
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 static void CG_OffsetFirstPersonView( void ) {
00900 float *origin;
00901 float *angles;
00902 float bob;
00903 float ratio;
00904 float delta;
00905 float speed;
00906 float f;
00907 vec3_t predictedVelocity;
00908 int timeDelta;
00909 int kickTime;
00910
00911 if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
00912 return;
00913 }
00914
00915 origin = cg.refdef.vieworg;
00916 angles = cg.refdef.viewangles;
00917
00918
00919 if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
00920 angles[ROLL] = 40;
00921 angles[PITCH] = -15;
00922 angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
00923 origin[2] += cg.predictedPlayerState.viewheight;
00924 return;
00925 }
00926
00927
00928 kickTime = (cg.time - cg.kick_time);
00929 if ( kickTime < 800 )
00930 {
00931 float kickPerc = 0.0f;
00932 if ( kickTime <= 200 )
00933 {
00934 kickPerc = kickTime/200.0f;
00935 }
00936 else
00937 {
00938 kickTime = 800 - kickTime;
00939 kickPerc = kickTime/600.0f;
00940 }
00941 VectorMA( angles, kickPerc, cg.kick_angles, angles );
00942 }
00943
00944 if ( cg.damageTime ) {
00945 ratio = cg.time - cg.damageTime;
00946 if ( ratio < DAMAGE_DEFLECT_TIME ) {
00947 ratio /= DAMAGE_DEFLECT_TIME;
00948 angles[PITCH] += ratio * cg.v_dmg_pitch;
00949 angles[ROLL] += ratio * cg.v_dmg_roll;
00950 } else {
00951 ratio = 1.0 - ( ratio - DAMAGE_DEFLECT_TIME ) / DAMAGE_RETURN_TIME;
00952 if ( ratio > 0 ) {
00953 angles[PITCH] += ratio * cg.v_dmg_pitch;
00954 angles[ROLL] += ratio * cg.v_dmg_roll;
00955 }
00956 }
00957 }
00958
00959
00960 #if 0
00961 ratio = ( cg.time - cg.landTime) / FALL_TIME;
00962 if (ratio < 0)
00963 ratio = 0;
00964 angles[PITCH] += ratio * cg.fall_value;
00965 #endif
00966
00967
00968 VectorCopy( cg.predictedPlayerState.velocity, predictedVelocity );
00969
00970 delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[0]);
00971 angles[PITCH] += delta * cg_runpitch.value;
00972
00973 delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[1]);
00974 angles[ROLL] -= delta * cg_runroll.value;
00975
00976
00977
00978
00979 speed = cg.xyspeed > 200 ? cg.xyspeed : 200;
00980
00981 delta = cg.bobfracsin * cg_bobpitch.value * speed;
00982 if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
00983 delta *= 3;
00984 angles[PITCH] += delta;
00985 delta = cg.bobfracsin * cg_bobroll.value * speed;
00986 if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
00987 delta *= 3;
00988 if (cg.bobcycle & 1)
00989 delta = -delta;
00990 angles[ROLL] += delta;
00991
00992
00993
00994
00995 origin[2] += cg.predictedPlayerState.viewheight;
00996
00997
00998 timeDelta = cg.time - cg.duckTime;
00999 if ( timeDelta < DUCK_TIME) {
01000 cg.refdef.vieworg[2] -= cg.duckChange
01001 * (DUCK_TIME - timeDelta) / DUCK_TIME;
01002 }
01003
01004
01005 bob = cg.bobfracsin * cg.xyspeed * cg_bobup.value;
01006 if (bob > 6) {
01007 bob = 6;
01008 }
01009
01010 origin[2] += bob;
01011
01012
01013
01014 delta = cg.time - cg.landTime;
01015 if ( delta < LAND_DEFLECT_TIME ) {
01016 f = delta / LAND_DEFLECT_TIME;
01017 cg.refdef.vieworg[2] += cg.landChange * f;
01018 } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
01019 delta -= LAND_DEFLECT_TIME;
01020 f = 1.0 - ( delta / LAND_RETURN_TIME );
01021 cg.refdef.vieworg[2] += cg.landChange * f;
01022 }
01023
01024
01025 CG_StepOffset();
01026
01027
01028
01029 VectorAdd (origin, cg.kick_origin, origin);
01030
01031
01032 #if 0
01033 {
01034 #define NECK_LENGTH 8
01035 vec3_t forward, up;
01036
01037 cg.refdef.vieworg[2] -= NECK_LENGTH;
01038 AngleVectors( cg.refdef.viewangles, forward, NULL, up );
01039 VectorMA( cg.refdef.vieworg, 3, forward, cg.refdef.vieworg );
01040 VectorMA( cg.refdef.vieworg, NECK_LENGTH, up, cg.refdef.vieworg );
01041 }
01042 #endif
01043 }
01044
01045 static void CG_OffsetFighterView( void )
01046 {
01047 vec3_t vehFwd, vehRight, vehUp, backDir;
01048 vec3_t camOrg, camBackOrg;
01049 float horzOffset = cg_thirdPersonHorzOffset.value;
01050 float vertOffset = cg_thirdPersonVertOffset.value;
01051 float pitchOffset = cg_thirdPersonPitchOffset.value;
01052 float yawOffset = cg_thirdPersonAngle.value;
01053 float range = cg_thirdPersonRange.value;
01054 trace_t trace;
01055 centity_t *veh = &cg_entities[cg.predictedPlayerState.m_iVehicleNum];
01056
01057 AngleVectors( cg.refdef.viewangles, vehFwd, vehRight, vehUp );
01058
01059 if ( veh->m_pVehicle &&
01060 veh->m_pVehicle->m_pVehicleInfo->cameraOverride )
01061 {
01062 horzOffset = veh->m_pVehicle->m_pVehicleInfo->cameraHorzOffset;
01063 vertOffset = veh->m_pVehicle->m_pVehicleInfo->cameraVertOffset;
01064
01065 pitchOffset = veh->m_pVehicle->m_pVehicleInfo->cameraPitchOffset;
01066 range = veh->m_pVehicle->m_pVehicleInfo->cameraRange;
01067 if ( veh->playerState->hackingTime )
01068 {
01069 horzOffset += (((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * -80.0f;
01070 range += fabs(((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * 100.0f;
01071 }
01072 }
01073
01074
01075 VectorMA( cg.refdef.vieworg, horzOffset, vehRight, camOrg );
01076 VectorMA( camOrg, vertOffset, vehUp, camOrg );
01077
01078
01079 CG_Trace(&trace, cg.refdef.vieworg, cameramins, cameramaxs, camOrg, cg.snap->ps.clientNum, MASK_CAMERACLIP);
01080 if ( trace.fraction < 1.0 )
01081 {
01082 VectorCopy( trace.endpos, camOrg );
01083 }
01084
01085
01086 cg.refdef.viewangles[YAW] += yawOffset;
01087 cg.refdef.viewangles[PITCH] += pitchOffset;
01088
01089
01090 AngleVectors( cg.refdef.viewangles, backDir, NULL, NULL );
01091 VectorScale( backDir, -1, backDir );
01092
01093 VectorMA( camOrg, range, backDir, camBackOrg );
01094
01095
01096 CG_Trace(&trace, camOrg, cameramins, cameramaxs, camBackOrg, cg.snap->ps.clientNum, MASK_CAMERACLIP);
01097 VectorCopy( trace.endpos, camOrg );
01098
01099
01100
01101 VectorCopy(camOrg, cg.refdef.vieworg);
01102 }
01103
01104
01105 void CG_ZoomDown_f( void ) {
01106 if ( cg.zoomed ) {
01107 return;
01108 }
01109 cg.zoomed = qtrue;
01110 cg.zoomTime = cg.time;
01111 }
01112
01113 void CG_ZoomUp_f( void ) {
01114 if ( !cg.zoomed ) {
01115 return;
01116 }
01117 cg.zoomed = qfalse;
01118 cg.zoomTime = cg.time;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 qboolean CG_CalcFOVFromX( float fov_x )
01131 {
01132 float x;
01133
01134
01135
01136 float fov_y;
01137 qboolean inwater;
01138
01139 x = cg.refdef.width / tan( fov_x / 360 * M_PI );
01140 fov_y = atan2( cg.refdef.height, x );
01141 fov_y = fov_y * 360 / M_PI;
01142
01143
01144
01145
01146
01147
01148 #if 0
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 #else
01164 inwater = qfalse;
01165 #endif
01166
01167
01168
01169 cg.refdef.fov_x = fov_x;
01170 cg.refdef.fov_y = fov_y;
01171
01172 #ifdef _XBOX
01173 if(cg.widescreen)
01174 cg.refdef.fov_x *= 1.125f;
01175 #endif
01176
01177 return (inwater);
01178 }
01179
01180
01181
01182
01183
01184
01185
01186
01187 #define WAVE_AMPLITUDE 1
01188 #define WAVE_FREQUENCY 0.4
01189 float zoomFov;
01190
01191 static int CG_CalcFov( void ) {
01192 float x;
01193 float phase;
01194 float v;
01195 float fov_x, fov_y;
01196 float f;
01197 int inwater;
01198 float cgFov = cg_fov.value;
01199
01200 if (cgFov < 1)
01201 {
01202 cgFov = 1;
01203 }
01204 if (cgFov > 97)
01205 {
01206 cgFov = 97;
01207 }
01208
01209 if ( cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
01210
01211 fov_x = 80;
01212 } else {
01213
01214 if ( cgs.dmflags & DF_FIXED_FOV ) {
01215
01216 fov_x = 80;
01217 } else {
01218 fov_x = cgFov;
01219 if ( fov_x < 1 ) {
01220 fov_x = 1;
01221 } else if ( fov_x > 160 ) {
01222 fov_x = 160;
01223 }
01224 }
01225
01226 if (cg.predictedPlayerState.zoomMode == 2)
01227 {
01228 if (zoomFov > 40.0f)
01229 {
01230 zoomFov -= cg.frametime * 0.075f;
01231
01232 if (zoomFov < 40.0f)
01233 {
01234 zoomFov = 40.0f;
01235 }
01236 else if (zoomFov > cgFov)
01237 {
01238 zoomFov = cgFov;
01239 }
01240 }
01241
01242 fov_x = zoomFov;
01243 }
01244 else if (cg.predictedPlayerState.zoomMode)
01245 {
01246 if (!cg.predictedPlayerState.zoomLocked)
01247 {
01248 if (zoomFov > 50)
01249 {
01250 zoomFov = 50;
01251 }
01252 zoomFov -= cg.frametime * 0.035f;
01253
01254 if (zoomFov < MAX_ZOOM_FOV)
01255 {
01256 zoomFov = MAX_ZOOM_FOV;
01257 }
01258 else if (zoomFov > cgFov)
01259 {
01260 zoomFov = cgFov;
01261 }
01262 else
01263 {
01264 static int zoomSoundTime = 0;
01265
01266 if (zoomSoundTime < cg.time || zoomSoundTime > cg.time + 10000)
01267 {
01268 trap_S_StartSound(cg.refdef.vieworg, ENTITYNUM_WORLD, CHAN_LOCAL, cgs.media.disruptorZoomLoop);
01269 zoomSoundTime = cg.time + 300;
01270 }
01271 }
01272 }
01273
01274 if (zoomFov < MAX_ZOOM_FOV)
01275 {
01276 zoomFov = 50;
01277 }
01278 fov_x = zoomFov;
01279 }
01280 else
01281 {
01282 zoomFov = 80;
01283
01284 f = ( cg.time - cg.predictedPlayerState.zoomTime ) / ZOOM_OUT_TIME;
01285 if ( f > 1.0 )
01286 {
01287 fov_x = fov_x;
01288 }
01289 else
01290 {
01291 fov_x = cg.predictedPlayerState.zoomFov + f * ( fov_x - cg.predictedPlayerState.zoomFov );
01292 }
01293 }
01294 }
01295
01296 x = cg.refdef.width / tan( fov_x / 360 * M_PI );
01297 fov_y = atan2( cg.refdef.height, x );
01298 fov_y = fov_y * 360 / M_PI;
01299
01300
01301 cg.refdef.viewContents = CG_PointContents( cg.refdef.vieworg, -1 );
01302 if ( cg.refdef.viewContents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ){
01303 phase = cg.time / 1000.0 * WAVE_FREQUENCY * M_PI * 2;
01304 v = WAVE_AMPLITUDE * sin( phase );
01305 fov_x += v;
01306 fov_y -= v;
01307 inwater = qtrue;
01308 }
01309 else {
01310 inwater = qfalse;
01311 }
01312
01313 #ifdef _XBOX
01314 if(cg.widescreen)
01315 fov_x = fov_y * 1.77777f;
01316 #endif
01317
01318
01319
01320 cg.refdef.fov_x = fov_x;
01321 cg.refdef.fov_y = fov_y;
01322
01323 if (cg.predictedPlayerState.zoomMode)
01324 {
01325 cg.zoomSensitivity = zoomFov/cgFov;
01326 }
01327 else if ( !cg.zoomed ) {
01328 cg.zoomSensitivity = 1;
01329 } else {
01330 cg.zoomSensitivity = cg.refdef.fov_y / 75.0;
01331 }
01332
01333 return inwater;
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343 static void CG_DamageBlendBlob( void )
01344 {
01345 int t;
01346 int maxTime;
01347 refEntity_t ent;
01348
01349 if ( !cg.damageValue ) {
01350 return;
01351 }
01352
01353 maxTime = DAMAGE_TIME;
01354 t = cg.time - cg.damageTime;
01355 if ( t <= 0 || t >= maxTime ) {
01356 return;
01357 }
01358
01359 memset( &ent, 0, sizeof( ent ) );
01360 ent.reType = RT_SPRITE;
01361 ent.renderfx = RF_FIRST_PERSON;
01362
01363 VectorMA( cg.refdef.vieworg, 8, cg.refdef.viewaxis[0], ent.origin );
01364 VectorMA( ent.origin, cg.damageX * -8, cg.refdef.viewaxis[1], ent.origin );
01365 VectorMA( ent.origin, cg.damageY * 8, cg.refdef.viewaxis[2], ent.origin );
01366
01367 ent.radius = cg.damageValue * 3 * ( 1.0 - ((float)t / maxTime) );
01368
01369 if (cg.snap->ps.damageType == 0)
01370 {
01371 ent.customShader = cgs.media.viewPainShader;
01372 ent.shaderRGBA[0] = 180 * ( 1.0 - ((float)t / maxTime) );
01373 ent.shaderRGBA[1] = 50 * ( 1.0 - ((float)t / maxTime) );
01374 ent.shaderRGBA[2] = 50 * ( 1.0 - ((float)t / maxTime) );
01375 ent.shaderRGBA[3] = 255;
01376 }
01377 else if (cg.snap->ps.damageType == 1)
01378 {
01379 ent.customShader = cgs.media.viewPainShader_Shields;
01380 ent.shaderRGBA[0] = 50 * ( 1.0 - ((float)t / maxTime) );
01381 ent.shaderRGBA[1] = 180 * ( 1.0 - ((float)t / maxTime) );
01382 ent.shaderRGBA[2] = 50 * ( 1.0 - ((float)t / maxTime) );
01383 ent.shaderRGBA[3] = 255;
01384 }
01385 else
01386 {
01387 ent.customShader = cgs.media.viewPainShader_ShieldsAndHealth;
01388 ent.shaderRGBA[0] = 180 * ( 1.0 - ((float)t / maxTime) );
01389 ent.shaderRGBA[1] = 180 * ( 1.0 - ((float)t / maxTime) );
01390 ent.shaderRGBA[2] = 50 * ( 1.0 - ((float)t / maxTime) );
01391 ent.shaderRGBA[3] = 255;
01392 }
01393 trap_R_AddRefEntityToScene( &ent );
01394 }
01395
01396 int cg_actionCamLastTime = 0;
01397 vec3_t cg_actionCamLastPos;
01398
01399
01400 static qboolean CG_ThirdPersonActionCam(void)
01401 {
01402 centity_t *cent = &cg_entities[cg.snap->ps.clientNum];
01403 clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
01404 trace_t tr;
01405 vec3_t positionDir;
01406 vec3_t desiredAngles;
01407 vec3_t desiredPos;
01408 vec3_t v;
01409 const float smoothFactor = 0.1f*cg_timescale.value;
01410 int i;
01411
01412 if (!cent->ghoul2)
01413 {
01414 return qfalse;
01415 }
01416
01417 if (cent->currentState.weapon != WP_SABER)
01418 {
01419 return qfalse;
01420 }
01421
01422 if ((cg.time - ci->saber[0].blade[0].trail.lastTime) > 300)
01423 {
01424 return qfalse;
01425 }
01426
01427
01428 VectorSubtract(ci->saber[0].blade[0].trail.base, cent->lerpOrigin, positionDir);
01429 VectorNormalize(positionDir);
01430
01431
01432 VectorMA(cent->lerpOrigin, cg_thirdPersonRange.value*2, positionDir, desiredPos);
01433
01434
01435
01436 CG_Trace(&tr, cent->lerpOrigin, NULL, NULL, desiredPos, cent->currentState.number, MASK_SOLID);
01437 VectorCopy(tr.endpos, desiredPos);
01438
01439 if ((cg.time - cg_actionCamLastTime) > 300)
01440 {
01441
01442 CG_OffsetThirdPersonView();
01443 VectorCopy(cg.refdef.vieworg, cg_actionCamLastPos);
01444 }
01445
01446 cg_actionCamLastTime = cg.time;
01447
01448
01449 VectorSubtract(desiredPos, cg_actionCamLastPos, v);
01450
01451 if (VectorLength(v) > 64.0f)
01452 {
01453 for (i = 0; i < 3; i++)
01454 {
01455 cg_actionCamLastPos[i] = (cg_actionCamLastPos[i] + (v[i]*smoothFactor));
01456 cg.refdef.vieworg[i] = cg_actionCamLastPos[i];
01457 }
01458 }
01459 else
01460 {
01461 VectorCopy(cg_actionCamLastPos, cg.refdef.vieworg);
01462 }
01463
01464
01465 CG_Trace(&tr, cent->lerpOrigin, NULL, NULL, cg.refdef.vieworg, cent->currentState.number, MASK_SOLID);
01466 VectorCopy(tr.endpos, cg.refdef.vieworg);
01467
01468 VectorSubtract(cent->lerpOrigin, cg.refdef.vieworg, positionDir);
01469 vectoangles(positionDir, desiredAngles);
01470
01471
01472 VectorCopy(desiredAngles, cg.refdef.viewangles);
01473 return qtrue;
01474 }
01475
01476 vec3_t cg_lastTurretViewAngles={0};
01477 qboolean CG_CheckPassengerTurretView( void )
01478 {
01479 if ( cg.predictedPlayerState.m_iVehicleNum
01480 && cg.predictedPlayerState.generic1 )
01481 {
01482 centity_t *vehCent = &cg_entities[cg.predictedPlayerState.m_iVehicleNum];
01483 if ( vehCent->m_pVehicle
01484 && vehCent->m_pVehicle->m_pVehicleInfo
01485 && vehCent->m_pVehicle->m_pVehicleInfo->maxPassengers )
01486 {
01487 int turretNum;
01488 for ( turretNum = 0; turretNum < MAX_VEHICLE_TURRETS; turretNum++ )
01489 {
01490 if ( vehCent->m_pVehicle->m_pVehicleInfo->turret[turretNum].iAmmoMax )
01491 {
01492 if ( vehCent->m_pVehicle->m_pVehicleInfo->turret[turretNum].passengerNum == cg.predictedPlayerState.generic1 )
01493 {
01494 int boltIndex = -1;
01495 qboolean hackPosAndAngle = qfalse;
01496 if ( vehCent->m_pVehicle->m_iGunnerViewTag[turretNum] != -1 )
01497 {
01498 boltIndex = vehCent->m_pVehicle->m_iGunnerViewTag[turretNum];
01499 }
01500 else
01501 {
01502 hackPosAndAngle = qtrue;
01503 if ( vehCent->m_pVehicle->m_pVehicleInfo->turret[turretNum].yawBone )
01504 {
01505 boltIndex = trap_G2API_AddBolt( vehCent->ghoul2, 0, vehCent->m_pVehicle->m_pVehicleInfo->turret[turretNum].yawBone );
01506 }
01507 else if ( vehCent->m_pVehicle->m_pVehicleInfo->turret[turretNum].pitchBone )
01508 {
01509 boltIndex = trap_G2API_AddBolt( vehCent->ghoul2, 0, vehCent->m_pVehicle->m_pVehicleInfo->turret[turretNum].pitchBone );
01510 }
01511 else
01512 {
01513 return qfalse;
01514 }
01515 }
01516 if ( boltIndex != -1 )
01517 {
01518 mdxaBone_t boltMatrix;
01519 vec3_t fwd, up;
01520 trap_G2API_GetBoltMatrix_NoRecNoRot(vehCent->ghoul2, 0, boltIndex, &boltMatrix, vehCent->lerpAngles,
01521 vehCent->lerpOrigin, cg.time, NULL, vehCent->modelScale);
01522 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, cg.refdef.vieworg);
01523 if ( hackPosAndAngle )
01524 {
01525
01526 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_X, fwd);
01527 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, up);
01528 VectorMA( cg.refdef.vieworg, 8.0f, fwd, cg.refdef.vieworg );
01529 VectorMA( cg.refdef.vieworg, 4.0f, up, cg.refdef.vieworg );
01530 }
01531 else
01532 {
01533 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, fwd);
01534 }
01535 {
01536 vec3_t newAngles, deltaAngles;
01537 vectoangles( fwd, newAngles );
01538 AnglesSubtract( newAngles, cg_lastTurretViewAngles, deltaAngles );
01539 VectorMA( cg_lastTurretViewAngles, 0.5f*(float)cg.frametime/100.0f, deltaAngles, cg.refdef.viewangles );
01540 }
01541 return qtrue;
01542 }
01543 }
01544 }
01545 }
01546 }
01547 }
01548 return qfalse;
01549 }
01550
01551
01552
01553
01554
01555
01556
01557 void CG_EmplacedView(vec3_t angles);
01558 static int CG_CalcViewValues( void ) {
01559 qboolean manningTurret = qfalse;
01560 playerState_t *ps;
01561
01562 memset( &cg.refdef, 0, sizeof( cg.refdef ) );
01563
01564
01565
01566
01567
01568
01569 CG_CalcVrect();
01570
01571 ps = &cg.predictedPlayerState;
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587 if ( ps->pm_type == PM_INTERMISSION ) {
01588 VectorCopy( ps->origin, cg.refdef.vieworg );
01589 VectorCopy( ps->viewangles, cg.refdef.viewangles );
01590 AnglesToAxis( cg.refdef.viewangles, cg.refdef.viewaxis );
01591 return CG_CalcFov();
01592 }
01593
01594 cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
01595 cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );
01596 cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] +
01597 ps->velocity[1] * ps->velocity[1] );
01598
01599 if (cg.xyspeed > 270)
01600 {
01601 cg.xyspeed = 270;
01602 }
01603
01604 manningTurret = CG_CheckPassengerTurretView();
01605 if ( !manningTurret )
01606 {
01607 VectorCopy( ps->origin, cg.refdef.vieworg );
01608 #ifdef VEH_CONTROL_SCHEME_4
01609 if ( cg.predictedPlayerState.m_iVehicleNum )
01610 {
01611 Vehicle_t *pVeh = cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle;
01612 if ( BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, pVeh ) )
01613 {
01614 VectorCopy( cg.predictedVehicleState.viewangles, cg.refdef.viewangles );
01615 }
01616 else if ( pVeh
01617 && pVeh->m_pVehicleInfo
01618 && pVeh->m_pVehicleInfo->type == VH_FIGHTER )
01619 {
01620 VectorCopy( cg.predictedVehicleState.viewangles, cg.refdef.viewangles );
01621 cg.refdef.viewangles[PITCH] = AngleNormalize180( cg.refdef.viewangles[PITCH] );
01622 }
01623 else
01624 {
01625 VectorCopy( ps->viewangles, cg.refdef.viewangles );
01626 }
01627 }
01628 #else// VEH_CONTROL_SCHEME_4
01629 if ( cg.predictedPlayerState.m_iVehicleNum
01630 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
01631 {
01632 VectorCopy( cg.predictedVehicleState.viewangles, cg.refdef.viewangles );
01633 }
01634 #endif// VEH_CONTROL_SCHEME_4
01635 else
01636 {
01637 VectorCopy( ps->viewangles, cg.refdef.viewangles );
01638 }
01639 }
01640 VectorCopy( cg.refdef.viewangles, cg_lastTurretViewAngles );
01641
01642 if (cg_cameraOrbit.integer) {
01643 if (cg.time > cg.nextOrbitTime) {
01644 cg.nextOrbitTime = cg.time + cg_cameraOrbitDelay.integer;
01645 cg_thirdPersonAngle.value += cg_cameraOrbit.value;
01646 }
01647 }
01648
01649 if ( cg_errorDecay.value > 0 ) {
01650 int t;
01651 float f;
01652
01653 t = cg.time - cg.predictedErrorTime;
01654 f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
01655 if ( f > 0 && f < 1 ) {
01656 VectorMA( cg.refdef.vieworg, f, cg.predictedError, cg.refdef.vieworg );
01657 } else {
01658 cg.predictedErrorTime = 0;
01659 }
01660 }
01661
01662 if (cg.snap->ps.weapon == WP_EMPLACED_GUN &&
01663 cg.snap->ps.emplacedIndex)
01664 {
01665 CG_EmplacedView(cg_entities[cg.snap->ps.emplacedIndex].currentState.angles);
01666 }
01667
01668 if ( !manningTurret )
01669 {
01670 if ( cg.predictedPlayerState.m_iVehicleNum
01671 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
01672 {
01673 CG_OffsetFighterView();
01674 }
01675 else if ( cg.renderingThirdPerson ) {
01676
01677 if (cg_thirdPersonSpecialCam.integer &&
01678 BG_SaberInSpecial(cg.snap->ps.saberMove))
01679 {
01680 if (!CG_ThirdPersonActionCam())
01681 {
01682 CG_OffsetThirdPersonView();
01683 }
01684 }
01685 else
01686 {
01687 CG_OffsetThirdPersonView();
01688 }
01689 } else {
01690
01691 CG_OffsetFirstPersonView();
01692 }
01693 }
01694
01695
01696 AnglesToAxis( cg.refdef.viewangles, cg.refdef.viewaxis );
01697
01698 if ( cg.hyperspace ) {
01699 cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
01700 }
01701
01702
01703 return CG_CalcFov();
01704 }
01705
01706
01707
01708
01709
01710
01711
01712 static void CG_PowerupTimerSounds( void ) {
01713 int i;
01714 int t;
01715
01716
01717 for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
01718 t = cg.snap->ps.powerups[i];
01719 if ( t <= cg.time ) {
01720 continue;
01721 }
01722 if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
01723 continue;
01724 }
01725 if ( ( t - cg.time ) / POWERUP_BLINK_TIME != ( t - cg.oldTime ) / POWERUP_BLINK_TIME ) {
01726
01727 }
01728 }
01729 }
01730
01731
01732
01733
01734
01735
01736 extern qboolean cg_skyOri;
01737 extern vec3_t cg_skyOriPos;
01738 extern float cg_skyOriScale;
01739 extern qboolean cg_noFogOutsidePortal;
01740 void CG_DrawSkyBoxPortal(const char *cstr)
01741 {
01742 static float lastfov;
01743 refdef_t backuprefdef;
01744 float fov_x;
01745 float fov_y;
01746 float x;
01747 char *token;
01748 float f = 0;
01749
01750 lastfov = zoomFov;
01751
01752 backuprefdef = cg.refdef;
01753
01754 token = COM_ParseExt(&cstr, qfalse);
01755 if (!token || !token[0])
01756 {
01757 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring\n");
01758 }
01759 cg.refdef.vieworg[0] = atof(token);
01760
01761 token = COM_ParseExt(&cstr, qfalse);
01762 if (!token || !token[0])
01763 {
01764 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring\n");
01765 }
01766 cg.refdef.vieworg[1] = atof(token);
01767
01768 token = COM_ParseExt(&cstr, qfalse);
01769 if (!token || !token[0])
01770 {
01771 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring\n");
01772 }
01773 cg.refdef.vieworg[2] = atof(token);
01774
01775 token = COM_ParseExt(&cstr, qfalse);
01776 if (!token || !token[0])
01777 {
01778 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring\n");
01779 }
01780 fov_x = atoi(token);
01781
01782 if (!fov_x)
01783 {
01784 fov_x = cg_fov.value;
01785 }
01786
01787
01788 token = COM_ParseExt(&cstr, qfalse);
01789 if (!token || !token[0])
01790 {
01791 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring. No fog state\n");
01792 }
01793 else
01794 {
01795 vec4_t fogColor;
01796 int fogStart, fogEnd;
01797
01798 if(atoi(token))
01799 {
01800 token = COM_ParseExt(&cstr, qfalse);
01801
01802 if (!token || !token[0])
01803 {
01804 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring. No fog[0]\n");
01805 }
01806 fogColor[0] = atof(token);
01807
01808 token = COM_ParseExt(&cstr, qfalse);
01809 if (!token || !token[0])
01810 {
01811 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring. No fog[1]\n");
01812 }
01813 fogColor[1] = atof(token);
01814
01815 token = COM_ParseExt(&cstr, qfalse);
01816 if (!token || !token[0])
01817 {
01818 CG_Error( "CG_DrawSkyBoxPortal: error parsing skybox configstring. No fog[2]\n");
01819 }
01820 fogColor[2] = atof(token);
01821
01822 token = COM_ParseExt(&cstr, qfalse);
01823 if (!token || !token[0])
01824 {
01825 fogStart = 0;
01826 }
01827 else
01828 {
01829 fogStart = atoi(token);
01830 }
01831
01832 token = COM_ParseExt(&cstr, qfalse);
01833 if (!token || !token[0])
01834 {
01835 fogEnd = 0;
01836 }
01837 else
01838 {
01839 fogEnd = atoi(token);
01840 }
01841 }
01842 }
01843
01844 if ( cg.predictedPlayerState.pm_type == PM_INTERMISSION )
01845 {
01846
01847 fov_x = cg_fov.value;
01848 }
01849 else
01850 {
01851 fov_x = cg_fov.value;
01852 if ( fov_x < 1 )
01853 {
01854 fov_x = 1;
01855 }
01856 else if ( fov_x > 160 )
01857 {
01858 fov_x = 160;
01859 }
01860
01861 if (cg.predictedPlayerState.zoomMode)
01862 {
01863 fov_x = zoomFov;
01864 }
01865
01866
01867 if (cg.predictedPlayerState.zoomMode)
01868 {
01869 f = ( cg.time - cg.zoomTime ) / (float)ZOOM_OUT_TIME;
01870 if ( f > 1.0 ) {
01871 fov_x = zoomFov;
01872 } else {
01873 fov_x = fov_x + f * ( zoomFov - fov_x );
01874 }
01875 lastfov = fov_x;
01876 }
01877 else
01878 {
01879 f = ( cg.time - cg.zoomTime ) / (float)ZOOM_OUT_TIME;
01880 if ( f > 1.0 ) {
01881 fov_x = fov_x;
01882 } else {
01883 fov_x = zoomFov + f * ( fov_x - zoomFov);
01884 }
01885 }
01886 }
01887
01888 x = cg.refdef.width / tan( fov_x / 360 * M_PI );
01889 fov_y = atan2( cg.refdef.height, x );
01890 fov_y = fov_y * 360 / M_PI;
01891
01892 cg.refdef.fov_x = fov_x;
01893 cg.refdef.fov_y = fov_y;
01894
01895 cg.refdef.rdflags |= RDF_SKYBOXPORTAL;
01896 cg.refdef.rdflags |= RDF_DRAWSKYBOX;
01897
01898 cg.refdef.time = cg.time;
01899
01900 if ( !cg.hyperspace)
01901 {
01902 trap_FX_AddScheduledEffects(qtrue);
01903 }
01904
01905 CG_AddPacketEntities(qtrue);
01906
01907
01908 if (cg_skyOri)
01909 {
01910 vec3_t dif;
01911
01912 VectorSubtract(backuprefdef.vieworg, cg_skyOriPos, dif);
01913 VectorScale(dif, cg_skyOriScale, dif);
01914 VectorAdd(cg.refdef.vieworg, dif, cg.refdef.vieworg);
01915 }
01916
01917 if (cg_noFogOutsidePortal)
01918 {
01919 cg.refdef.rdflags &= ~RDF_NOFOG;
01920 backuprefdef.rdflags |= RDF_NOFOG;
01921 }
01922
01923
01924 trap_R_RenderScene( &cg.refdef );
01925
01926 cg.refdef = backuprefdef;
01927 }
01928
01929
01930
01931
01932
01933
01934 void CG_AddBufferedSound( sfxHandle_t sfx ) {
01935 if ( !sfx )
01936 return;
01937 cg.soundBuffer[cg.soundBufferIn] = sfx;
01938 cg.soundBufferIn = (cg.soundBufferIn + 1) % MAX_SOUNDBUFFER;
01939 if (cg.soundBufferIn == cg.soundBufferOut) {
01940 cg.soundBufferOut++;
01941 }
01942 }
01943
01944
01945
01946
01947
01948
01949 static void CG_PlayBufferedSounds( void ) {
01950 if ( cg.soundTime < cg.time ) {
01951 if (cg.soundBufferOut != cg.soundBufferIn && cg.soundBuffer[cg.soundBufferOut]) {
01952 trap_S_StartLocalSound(cg.soundBuffer[cg.soundBufferOut], CHAN_ANNOUNCER);
01953 cg.soundBuffer[cg.soundBufferOut] = 0;
01954 cg.soundBufferOut = (cg.soundBufferOut + 1) % MAX_SOUNDBUFFER;
01955 cg.soundTime = cg.time + 750;
01956 }
01957 }
01958 }
01959
01960 void CG_UpdateSoundTrackers()
01961 {
01962 int num;
01963 centity_t *cent;
01964
01965 for ( num = 0 ; num < ENTITYNUM_NONE ; num++ )
01966 {
01967 cent = &cg_entities[num];
01968
01969 if (cent && (cent->currentState.eFlags & EF_SOUNDTRACKER) && cent->currentState.number == num)
01970
01971 {
01972 if (cg.snap && cent->currentState.trickedentindex == cg.snap->ps.clientNum)
01973 {
01974 VectorCopy(cg.refdef.vieworg, cent->lerpOrigin);
01975 trap_S_UpdateEntityPosition( cent->currentState.number, cent->lerpOrigin );
01976 }
01977 else
01978 {
01979 trap_S_UpdateEntityPosition( cent->currentState.number, cg_entities[cent->currentState.trickedentindex].lerpOrigin );
01980 }
01981 }
01982
01983 if (cent->currentState.number == num)
01984 {
01985
01986 CG_S_UpdateLoopingSounds(num);
01987 }
01988 }
01989 }
01990
01991
01992
01993
01994
01995
01996
01997
01998 #define CAMERA_DEFAULT_FOV 90.0f
01999 #define MAX_SHAKE_INTENSITY 16.0f
02000
02001 cgscreffects_t cgScreenEffects;
02002
02003 void CG_SE_UpdateShake( vec3_t origin, vec3_t angles )
02004 {
02005 vec3_t moveDir;
02006 float intensity_scale, intensity;
02007 int i;
02008
02009 if ( cgScreenEffects.shake_duration <= 0 )
02010 return;
02011
02012 if ( cg.time > ( cgScreenEffects.shake_start + cgScreenEffects.shake_duration ) )
02013 {
02014 cgScreenEffects.shake_intensity = 0;
02015 cgScreenEffects.shake_duration = 0;
02016 cgScreenEffects.shake_start = 0;
02017 return;
02018 }
02019
02020 cgScreenEffects.FOV = CAMERA_DEFAULT_FOV;
02021 cgScreenEffects.FOV2 = CAMERA_DEFAULT_FOV;
02022
02023
02024 intensity_scale = 1.0f - ( (float) ( cg.time - cgScreenEffects.shake_start ) / (float) cgScreenEffects.shake_duration ) * (((cgScreenEffects.FOV+cgScreenEffects.FOV2)/2.0f)/90.0f);
02025
02026 intensity = cgScreenEffects.shake_intensity * intensity_scale;
02027
02028 for ( i = 0; i < 3; i++ )
02029 {
02030 moveDir[i] = ( crandom() * intensity );
02031 }
02032
02033
02034 VectorAdd( origin, moveDir, origin );
02035
02036 for ( i=0; i < 2; i++ )
02037 moveDir[i] = ( crandom() * intensity );
02038
02039
02040 VectorAdd( angles, moveDir, angles );
02041 }
02042
02043 void CG_SE_UpdateMusic(void)
02044 {
02045 if (cgScreenEffects.music_volume_multiplier < 0.1)
02046 {
02047 cgScreenEffects.music_volume_multiplier = 1.0;
02048 return;
02049 }
02050
02051 if (cgScreenEffects.music_volume_time < cg.time)
02052 {
02053 if (cgScreenEffects.music_volume_multiplier != 1.0 || cgScreenEffects.music_volume_set)
02054 {
02055 char musMultStr[512];
02056
02057 cgScreenEffects.music_volume_multiplier += 0.1;
02058 if (cgScreenEffects.music_volume_multiplier > 1.0)
02059 {
02060 cgScreenEffects.music_volume_multiplier = 1.0;
02061 }
02062
02063 Com_sprintf(musMultStr, sizeof(musMultStr), "%f", cgScreenEffects.music_volume_multiplier);
02064 trap_Cvar_Set("s_musicMult", musMultStr);
02065
02066 if (cgScreenEffects.music_volume_multiplier == 1.0)
02067 {
02068 cgScreenEffects.music_volume_set = qfalse;
02069 }
02070 else
02071 {
02072 cgScreenEffects.music_volume_time = cg.time + 200;
02073 }
02074 }
02075
02076 return;
02077 }
02078
02079 if (!cgScreenEffects.music_volume_set)
02080 {
02081 char musMultStr[512];
02082
02083 Com_sprintf(musMultStr, sizeof(musMultStr), "%f", cgScreenEffects.music_volume_multiplier);
02084 trap_Cvar_Set("s_musicMult", musMultStr);
02085 cgScreenEffects.music_volume_set = qtrue;
02086 }
02087 }
02088
02089
02090
02091
02092
02093
02094
02095
02096 void CG_CalcScreenEffects(void)
02097 {
02098 CG_SE_UpdateShake(cg.refdef.vieworg, cg.refdef.viewangles);
02099 CG_SE_UpdateMusic();
02100 }
02101
02102 void CGCam_Shake( float intensity, int duration )
02103 {
02104 if ( intensity > MAX_SHAKE_INTENSITY )
02105 intensity = MAX_SHAKE_INTENSITY;
02106
02107 cgScreenEffects.shake_intensity = intensity;
02108 cgScreenEffects.shake_duration = duration;
02109
02110
02111 cgScreenEffects.shake_start = cg.time;
02112
02113 #ifdef _XBOX
02114 extern void FF_XboxShake(float intensity, int duration);
02115
02116 FF_XboxShake(intensity, duration);
02117
02118 #endif
02119 }
02120
02121 void CG_DoCameraShake( vec3_t origin, float intensity, int radius, int time )
02122 {
02123
02124
02125 vec3_t dir;
02126 float dist, intensityScale;
02127 float realIntensity;
02128
02129 VectorSubtract( cg.refdef.vieworg, origin, dir );
02130 dist = VectorNormalize( dir );
02131
02132
02133
02134 if ( dist > radius )
02135 return;
02136
02137 intensityScale = 1 - ( dist / (float) radius );
02138 realIntensity = intensity * intensityScale;
02139
02140 CGCam_Shake( realIntensity, time );
02141 }
02142
02143 void CGCam_SetMusicMult( float multiplier, int duration )
02144 {
02145 if (multiplier < 0.1f)
02146 {
02147 multiplier = 0.1f;
02148 }
02149
02150 if (multiplier > 1.0f)
02151 {
02152 multiplier = 1.0f;
02153 }
02154
02155 cgScreenEffects.music_volume_multiplier = multiplier;
02156 cgScreenEffects.music_volume_time = cg.time + duration;
02157 cgScreenEffects.music_volume_set = qfalse;
02158 }
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173 #include "../namespace_begin.h"
02174 int BG_EmplacedView(vec3_t baseAngles, vec3_t angles, float *newYaw, float constraint);
02175 #include "../namespace_end.h"
02176
02177 void CG_EmplacedView(vec3_t angles)
02178 {
02179 float yaw;
02180 int override;
02181
02182 override = BG_EmplacedView(cg.refdef.viewangles, angles, &yaw,
02183 cg_entities[cg.snap->ps.emplacedIndex].currentState.origin2[0]);
02184
02185 if (override)
02186 {
02187 cg.refdef.viewangles[YAW] = yaw;
02188 AnglesToAxis(cg.refdef.viewangles, cg.refdef.viewaxis);
02189
02190 if (override == 2)
02191 {
02192 trap_SetClientForceAngle(cg.time + 5000, cg.refdef.viewangles);
02193 }
02194 }
02195
02196
02197 override = BG_EmplacedView(cg.predictedPlayerState.viewangles, angles, &yaw,
02198 cg_entities[cg.snap->ps.emplacedIndex].currentState.origin2[0]);
02199 if (override)
02200 {
02201 cg.predictedPlayerState.viewangles[YAW] = yaw;
02202 }
02203 }
02204
02205
02206 static void CG_AddRefentForAutoMap(centity_t *cent)
02207 {
02208 refEntity_t ent;
02209 vec3_t flat;
02210
02211 if (cent->currentState.eFlags & EF_NODRAW)
02212 {
02213 return;
02214 }
02215
02216 memset(&ent, 0, sizeof(refEntity_t));
02217 ent.reType = RT_MODEL;
02218
02219 VectorCopy(cent->lerpAngles, flat);
02220 flat[PITCH] = flat[ROLL] = 0.0f;
02221
02222 VectorCopy(cent->lerpOrigin, ent.origin);
02223 VectorCopy(flat, ent.angles);
02224 AnglesToAxis(flat, ent.axis);
02225
02226 if (cent->ghoul2 &&
02227 (cent->currentState.eType == ET_PLAYER ||
02228 cent->currentState.eType == ET_NPC ||
02229 cent->currentState.modelGhoul2))
02230 {
02231 ent.ghoul2 = cent->ghoul2;
02232 ent.radius = cent->currentState.g2radius;
02233
02234 if (!ent.radius)
02235 {
02236 ent.radius = 64.0f;
02237 }
02238 }
02239 else
02240 {
02241 ent.hModel = cgs.gameModels[cent->currentState.modelindex];
02242 }
02243
02244 trap_R_AddRefEntityToScene(&ent);
02245 }
02246
02247
02248 void CG_AddRadarAutomapEnts(void)
02249 {
02250 int i = 0;
02251
02252
02253 CG_AddRefentForAutoMap(&cg_entities[cg.predictedPlayerState.clientNum]);
02254
02255 while (i < cg.radarEntityCount)
02256 {
02257 CG_AddRefentForAutoMap(&cg_entities[cg.radarEntities[i]]);
02258 i++;
02259 }
02260 }
02261
02262
02263
02264
02265
02266
02267
02268
02269 float cg_autoMapZoom = 512.0f;
02270 float cg_autoMapZoomMainOffset = 0.0f;
02271 vec3_t cg_autoMapAngle = {90.0f, 0.0f, 0.0f};
02272 autoMapInput_t cg_autoMapInput;
02273 int cg_autoMapInputTime = 0;
02274 #define SIDEFRAME_WIDTH 16
02275 #define SIDEFRAME_HEIGHT 32
02276 void CG_DrawAutoMap(void)
02277 {
02278 clientInfo_t *local;
02279 refdef_t refdef;
02280 trace_t tr;
02281 vec3_t fwd;
02282 vec3_t playerMins, playerMaxs;
02283 int vWidth, vHeight;
02284 float hScale, vScale;
02285 float x, y, w, h;
02286
02287 if (!cg_autoMap.integer)
02288 {
02289 return;
02290 }
02291
02292 if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 )
02293 {
02294 return;
02295 }
02296
02297 if ( (cg.predictedPlayerState.pm_flags & PMF_FOLLOW) || cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_SPECTATOR )
02298 {
02299 return;
02300 }
02301
02302 local = &cgs.clientinfo[ cg.predictedPlayerState.clientNum ];
02303 if ( !local->infoValid )
02304 {
02305 return;
02306 }
02307
02308 if (cgs.gametype < GT_TEAM)
02309 {
02310 return;
02311 }
02312
02313 if (cg_autoMapInputTime >= cg.time)
02314 {
02315 if (cg_autoMapInput.up)
02316 {
02317 cg_autoMapZoom -= cg_autoMapInput.up;
02318 if (cg_autoMapZoom < cg_autoMapZoomMainOffset+64.0f)
02319 {
02320 cg_autoMapZoom = cg_autoMapZoomMainOffset+64.0f;
02321 }
02322 }
02323
02324 if (cg_autoMapInput.down)
02325 {
02326 cg_autoMapZoom += cg_autoMapInput.down;
02327 if (cg_autoMapZoom > cg_autoMapZoomMainOffset+4096.0f)
02328 {
02329 cg_autoMapZoom = cg_autoMapZoomMainOffset+4096.0f;
02330 }
02331 }
02332
02333 if (cg_autoMapInput.yaw)
02334 {
02335 cg_autoMapAngle[YAW] += cg_autoMapInput.yaw;
02336 }
02337
02338 if (cg_autoMapInput.pitch)
02339 {
02340 cg_autoMapAngle[PITCH] += cg_autoMapInput.pitch;
02341 }
02342
02343 if (cg_autoMapInput.goToDefaults)
02344 {
02345 cg_autoMapZoom = 512.0f;
02346 VectorSet(cg_autoMapAngle, 90.0f, 0.0f, 0.0f);
02347 }
02348 }
02349
02350 memset( &refdef, 0, sizeof( refdef ) );
02351
02352 refdef.rdflags = (RDF_NOWORLDMODEL|RDF_AUTOMAP);
02353
02354 VectorCopy(cg.predictedPlayerState.origin, refdef.vieworg);
02355 VectorCopy(cg_autoMapAngle, refdef.viewangles);
02356
02357
02358 AngleVectors(refdef.viewangles, fwd, 0, 0);
02359 VectorMA(refdef.vieworg, -cg_autoMapZoom, fwd, refdef.vieworg);
02360
02361 AnglesToAxis(refdef.viewangles, refdef.viewaxis);
02362
02363 refdef.fov_x = 50;
02364 refdef.fov_y = 50;
02365
02366
02367 trap_R_GetRealRes(&vWidth, &vHeight);
02368
02369
02370 hScale = vWidth/640.0f;
02371 vScale = vHeight/480.0f;
02372
02373 x = cg_autoMapX.value;
02374 y = cg_autoMapY.value;
02375 w = cg_autoMapW.value;
02376 h = cg_autoMapH.value;
02377
02378 refdef.x = x*hScale;
02379 refdef.y = y*vScale;
02380 refdef.width = w*hScale;
02381 refdef.height = h*vScale;
02382
02383 CG_DrawPic(x-SIDEFRAME_WIDTH, y, SIDEFRAME_WIDTH, h, cgs.media.wireframeAutomapFrame_left);
02384 CG_DrawPic(x+w, y, SIDEFRAME_WIDTH, h, cgs.media.wireframeAutomapFrame_right);
02385 CG_DrawPic(x-SIDEFRAME_WIDTH, y-SIDEFRAME_HEIGHT, w+(SIDEFRAME_WIDTH*2), SIDEFRAME_HEIGHT, cgs.media.wireframeAutomapFrame_top);
02386 CG_DrawPic(x-SIDEFRAME_WIDTH, y+h, w+(SIDEFRAME_WIDTH*2), SIDEFRAME_HEIGHT, cgs.media.wireframeAutomapFrame_bottom);
02387
02388 refdef.time = cg.time;
02389
02390 trap_R_ClearScene();
02391 CG_AddRadarAutomapEnts();
02392
02393 if (cg.predictedPlayerState.m_iVehicleNum &&
02394 cg_entities[cg.predictedPlayerState.m_iVehicleNum].currentState.eType == ET_NPC &&
02395 cg_entities[cg.predictedPlayerState.m_iVehicleNum].currentState.NPC_class == CLASS_VEHICLE &&
02396 cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle &&
02397 cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER)
02398 {
02399 trap_R_AutomapElevAdj(cg.predictedPlayerState.origin[2]);
02400 }
02401 else
02402 {
02403
02404 VectorSet(playerMins, -15, -15, DEFAULT_MINS_2);
02405 VectorSet(playerMaxs, 15, 15, DEFAULT_MAXS_2);
02406
02407 VectorCopy(cg.predictedPlayerState.origin, fwd);
02408 fwd[2] -= 4096.0f;
02409 CG_Trace(&tr, cg.predictedPlayerState.origin, playerMins, playerMaxs, fwd, cg.predictedPlayerState.clientNum, MASK_SOLID);
02410
02411 if (!tr.startsolid && !tr.allsolid)
02412 {
02413 trap_R_AutomapElevAdj(tr.endpos[2]);
02414 }
02415 }
02416 trap_R_RenderScene( &refdef );
02417 }
02418
02419
02420
02421
02422
02423
02424
02425
02426 static qboolean cg_rangedFogging = qfalse;
02427 float cg_linearFogOverride = 0.0f;
02428
02429 #include "../namespace_begin.h"
02430 extern void BG_VehicleTurnRateForSpeed( Vehicle_t *pVeh, float speed, float *mPitchOverride, float *mYawOverride );
02431 extern qboolean PM_InKnockDown( playerState_t *ps );
02432 #include "../namespace_end.h"
02433
02434 extern qboolean cgQueueLoad;
02435 extern void CG_ActualLoadDeferredPlayers( void );
02436
02437 static int cg_siegeClassIndex = -2;
02438
02439 void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) {
02440 int inwater;
02441 const char *cstr;
02442 float mSensitivity = cg.zoomSensitivity;
02443 float mPitchOverride = 0.0f;
02444 float mYawOverride = 0.0f;
02445 static centity_t *veh = NULL;
02446 #ifdef VEH_CONTROL_SCHEME_4
02447 float mSensitivityOverride = 0.0f;
02448 qboolean bUseFighterPitch = qfalse;
02449 qboolean isFighter = qfalse;
02450 #endif
02451
02452 if (cgQueueLoad)
02453 {
02454 CG_ActualLoadDeferredPlayers();
02455 cgQueueLoad = qfalse;
02456 }
02457
02458 cg.time = serverTime;
02459 cg.demoPlayback = demoPlayback;
02460
02461 if (cg.snap && ui_myteam.integer != cg.snap->ps.persistant[PERS_TEAM])
02462 {
02463 trap_Cvar_Set ( "ui_myteam", va("%i", cg.snap->ps.persistant[PERS_TEAM]) );
02464 }
02465 if (cgs.gametype == GT_SIEGE &&
02466 cg.snap &&
02467 cg_siegeClassIndex != cgs.clientinfo[cg.snap->ps.clientNum].siegeIndex)
02468 {
02469 cg_siegeClassIndex = cgs.clientinfo[cg.snap->ps.clientNum].siegeIndex;
02470 if (cg_siegeClassIndex == -1)
02471 {
02472 trap_Cvar_Set("ui_mySiegeClass", "<none>");
02473 }
02474 else
02475 {
02476 trap_Cvar_Set("ui_mySiegeClass", bgSiegeClasses[cg_siegeClassIndex].name);
02477 }
02478 }
02479
02480
02481 CG_UpdateCvars();
02482
02483
02484
02485 if ( cg.infoScreenText[0] != 0 ) {
02486 CG_DrawInformation();
02487 return;
02488 }
02489
02490 trap_FX_AdjustTime( cg.time );
02491
02492 CG_RunLightStyles();
02493
02494
02495
02496 trap_S_ClearLoopingSounds();
02497
02498
02499 trap_R_ClearScene();
02500
02501
02502 CG_ProcessSnapshots();
02503
02504 trap_ROFF_UpdateEntities();
02505
02506
02507
02508 if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) )
02509 {
02510 #if 0
02511
02512
02513
02514
02515 if ( !cg.snapshotTimeoutTime )
02516 {
02517 cg.snapshotTimeoutTime = -1;
02518 }
02519
02520
02521 else if ( cg.snapshotTimeoutTime == -1 )
02522 {
02523 cg.snapshotTimeoutTime = trap_Milliseconds ( );
02524 }
02525
02526
02527 if ( cg.snapshotTimeoutTime > 0 && (trap_Milliseconds ( ) - cg.snapshotTimeoutTime > cg_snapshotTimeout.integer * 1000) )
02528 {
02529 Com_Error ( ERR_DROP, CG_GetStringEdString("MP_SVGAME", "SNAPSHOT_TIMEOUT"));
02530 return;
02531 }
02532 #endif
02533 CG_DrawInformation();
02534 return;
02535 }
02536
02537
02538 if (cg.snap && cg.snap->ps.saberLockTime > cg.time)
02539 {
02540 mSensitivity = 0.01f;
02541 }
02542 else if (cg.predictedPlayerState.weapon == WP_EMPLACED_GUN)
02543 {
02544 mSensitivity = 0.2f;
02545 }
02546 #ifdef VEH_CONTROL_SCHEME_4
02547 else if (cg.predictedPlayerState.m_iVehicleNum
02548 && !cg.predictedPlayerState.generic1 )
02549 {
02550 centity_t *cent = &cg_entities[cg.predictedPlayerState.m_iVehicleNum];
02551 if ( cent->m_pVehicle
02552 && cent->m_pVehicle->m_pVehicleInfo
02553 && cent->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
02554 {
02555 BG_VehicleTurnRateForSpeed( cent->m_pVehicle, cent->currentState.speed, &mPitchOverride, &mYawOverride );
02556
02557 mSensitivityOverride = 0.0f;
02558 bUseFighterPitch = qtrue;
02559 trap_SetUserCmdValue( cg.weaponSelect, mSensitivity, mPitchOverride, mYawOverride, mSensitivityOverride, cg.forceSelect, cg.itemSelect, bUseFighterPitch );
02560 isFighter = qtrue;
02561 }
02562 }
02563
02564 if ( !isFighter )
02565 #endif //VEH_CONTROL_SCHEME_4
02566 {
02567 if (cg.predictedPlayerState.m_iVehicleNum)
02568 {
02569 veh = &cg_entities[cg.predictedPlayerState.m_iVehicleNum];
02570 }
02571 if (veh &&
02572 veh->currentState.eType == ET_NPC &&
02573 veh->currentState.NPC_class == CLASS_VEHICLE &&
02574 veh->m_pVehicle &&
02575 veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER &&
02576 bg_fighterAltControl.integer)
02577 {
02578 trap_SetUserCmdValue( cg.weaponSelect, mSensitivity, mPitchOverride, mYawOverride, 0.0f, cg.forceSelect, cg.itemSelect, qtrue );
02579 veh = NULL;
02580 }
02581 else
02582 {
02583 trap_SetUserCmdValue( cg.weaponSelect, mSensitivity, mPitchOverride, mYawOverride, 0.0f, cg.forceSelect, cg.itemSelect, qfalse );
02584 }
02585 }
02586
02587
02588 cg.clientFrame++;
02589
02590
02591 CG_PredictPlayerState();
02592
02593
02594 cg.renderingThirdPerson = cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0);
02595
02596 if (cg.snap->ps.stats[STAT_HEALTH] > 0)
02597 {
02598 if (cg.predictedPlayerState.weapon == WP_EMPLACED_GUN && cg.predictedPlayerState.emplacedIndex
02599 )
02600 {
02601 cg.renderingThirdPerson = 1;
02602 }
02603 else if (cg.predictedPlayerState.weapon == WP_SABER || cg.predictedPlayerState.weapon == WP_MELEE ||
02604 BG_InGrappleMove(cg.predictedPlayerState.torsoAnim) || BG_InGrappleMove(cg.predictedPlayerState.legsAnim) ||
02605 cg.predictedPlayerState.forceHandExtend == HANDEXTEND_KNOCKDOWN || cg.predictedPlayerState.fallingToDeath ||
02606 cg.predictedPlayerState.m_iVehicleNum || PM_InKnockDown(&cg.predictedPlayerState))
02607 {
02608 if (cg_fpls.integer && cg.predictedPlayerState.weapon == WP_SABER)
02609 {
02610 cg.renderingThirdPerson = 0;
02611 }
02612 else
02613 {
02614 cg.renderingThirdPerson = 1;
02615 }
02616 }
02617 else if (cg.snap->ps.zoomMode)
02618 {
02619 cg.renderingThirdPerson = 0;
02620 }
02621 }
02622
02623 if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
02624 {
02625 cg.renderingThirdPerson = 0;
02626 }
02627
02628
02629 if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR)
02630 {
02631 cg.renderingThirdPerson = 0;
02632 }
02633
02634
02635 inwater = CG_CalcViewValues();
02636
02637 if (cg_linearFogOverride)
02638 {
02639 trap_R_SetRangeFog(-cg_linearFogOverride);
02640 }
02641 else if (cg.predictedPlayerState.zoomMode)
02642 {
02643 cg_rangedFogging = qtrue;
02644
02645 trap_R_SetRangeFog(cg.refdef.fov_x*64.0f);
02646 }
02647 else if (cg_rangedFogging)
02648 {
02649 cg_rangedFogging = qfalse;
02650 trap_R_SetRangeFog(0.0f);
02651 }
02652
02653 cstr = CG_ConfigString(CS_SKYBOXORG);
02654
02655 if (cstr && cstr[0])
02656 {
02657 CG_DrawSkyBoxPortal(cstr);
02658 }
02659
02660 CG_CalcScreenEffects();
02661
02662
02663 if ( !cg.renderingThirdPerson && cg.predictedPlayerState.pm_type != PM_SPECTATOR ) {
02664 CG_DamageBlendBlob();
02665 }
02666
02667
02668 if ( !cg.hyperspace ) {
02669 CG_AddPacketEntities(qfalse);
02670 CG_AddMarks();
02671 CG_AddParticles ();
02672 CG_AddLocalEntities();
02673 CG_DrawMiscEnts();
02674 }
02675 CG_AddViewWeapon( &cg.predictedPlayerState );
02676
02677 if ( !cg.hyperspace)
02678 {
02679 trap_FX_AddScheduledEffects(qfalse);
02680 }
02681
02682
02683 CG_PlayBufferedSounds();
02684
02685
02686 if ( cg.testModelEntity.hModel ) {
02687 CG_AddTestModel();
02688 }
02689 cg.refdef.time = cg.time;
02690 memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) );
02691
02692
02693 CG_PowerupTimerSounds();
02694
02695
02696 CG_UpdateSoundTrackers();
02697
02698 if (gCGHasFallVector)
02699 {
02700 vec3_t lookAng;
02701
02702 VectorSubtract(cg.snap->ps.origin, cg.refdef.vieworg, lookAng);
02703 VectorNormalize(lookAng);
02704 vectoangles(lookAng, lookAng);
02705
02706 VectorCopy(gCGFallVector, cg.refdef.vieworg);
02707 AnglesToAxis(lookAng, cg.refdef.viewaxis);
02708 }
02709
02710
02711 cstr = CG_ConfigString( CS_GLOBAL_AMBIENT_SET );
02712
02713 if (cstr && cstr[0])
02714 {
02715 trap_S_UpdateAmbientSet( cstr, cg.refdef.vieworg );
02716 }
02717
02718
02719 trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater );
02720
02721
02722 if ( stereoView != STEREO_RIGHT ) {
02723 cg.frametime = cg.time - cg.oldTime;
02724 if ( cg.frametime < 0 ) {
02725 cg.frametime = 0;
02726 }
02727 cg.oldTime = cg.time;
02728 CG_AddLagometerFrameInfo();
02729 }
02730 if (cg_timescale.value != cg_timescaleFadeEnd.value) {
02731 if (cg_timescale.value < cg_timescaleFadeEnd.value) {
02732 cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
02733 if (cg_timescale.value > cg_timescaleFadeEnd.value)
02734 cg_timescale.value = cg_timescaleFadeEnd.value;
02735 }
02736 else {
02737 cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
02738 if (cg_timescale.value < cg_timescaleFadeEnd.value)
02739 cg_timescale.value = cg_timescaleFadeEnd.value;
02740 }
02741 if (cg_timescaleFadeSpeed.value) {
02742 trap_Cvar_Set("timescale", va("%f", cg_timescale.value));
02743 }
02744 }
02745
02746
02747 CG_DrawActive( stereoView );
02748
02749 CG_DrawAutoMap();
02750
02751 if ( cg_stats.integer ) {
02752 CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame );
02753 }
02754 }
02755