00001
00002
00003
00004 #include "cg_local.h"
00005 #include "fx_local.h"
00006
00007 extern vec4_t bluehudtint;
00008 extern vec4_t redhudtint;
00009 extern float *hudTintColor;
00010
00011
00012
00013
00014
00015 void CG_SetGhoul2InfoRef( refEntity_t *ent, refEntity_t *s1)
00016 {
00017 ent->ghoul2 = s1->ghoul2;
00018 VectorCopy( s1->modelScale, ent->modelScale);
00019 ent->radius = s1->radius;
00020 VectorCopy( s1->angles, ent->angles);
00021 }
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 void CG_RegisterItemVisuals( int itemNum ) {
00035 itemInfo_t *itemInfo;
00036 gitem_t *item;
00037 int handle;
00038
00039 if ( itemNum < 0 || itemNum >= bg_numItems ) {
00040 CG_Error( "CG_RegisterItemVisuals: itemNum %d out of range [0-%d]", itemNum, bg_numItems-1 );
00041 }
00042
00043 itemInfo = &cg_items[ itemNum ];
00044 if ( itemInfo->registered ) {
00045 return;
00046 }
00047
00048 item = &bg_itemlist[ itemNum ];
00049
00050 memset( itemInfo, 0, sizeof( &itemInfo ) );
00051 itemInfo->registered = qtrue;
00052
00053 if (item->giType == IT_TEAM &&
00054 (item->giTag == PW_REDFLAG || item->giTag == PW_BLUEFLAG) &&
00055 cgs.gametype == GT_CTY)
00056 {
00057 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[1] );
00058 }
00059 else if (item->giType == IT_WEAPON &&
00060 (item->giTag == WP_THERMAL || item->giTag == WP_TRIP_MINE || item->giTag == WP_DET_PACK))
00061 {
00062 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[1] );
00063 }
00064 else
00065 {
00066 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[0] );
00067 }
00068
00069
00070
00071 if (!Q_stricmp(&item->world_model[0][strlen(item->world_model[0]) - 4], ".glm"))
00072 {
00073 handle = trap_G2API_InitGhoul2Model(&itemInfo->g2Models[0], item->world_model[0], 0 , 0, 0, 0, 0);
00074 if (handle<0)
00075 {
00076 itemInfo->g2Models[0] = NULL;
00077 }
00078 else
00079 {
00080 itemInfo->radius[0] = 60;
00081 }
00082 }
00083
00084
00085
00086 if (item->icon)
00087 {
00088 if (item->giType == IT_HEALTH)
00089 {
00090 itemInfo->icon = trap_R_RegisterShaderNoMip( item->icon );
00091 }
00092 else
00093 {
00094 itemInfo->icon = trap_R_RegisterShader( item->icon );
00095 }
00096 }
00097 else
00098 {
00099 itemInfo->icon = 0;
00100 }
00101
00102 if ( item->giType == IT_WEAPON ) {
00103 CG_RegisterWeapon( item->giTag );
00104 }
00105
00106
00107
00108
00109 if ( item->giType == IT_POWERUP || item->giType == IT_HEALTH ||
00110 item->giType == IT_ARMOR || item->giType == IT_HOLDABLE ) {
00111 if ( item->world_model[1] ) {
00112 itemInfo->models[1] = trap_R_RegisterModel( item->world_model[1] );
00113 }
00114 }
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 #define WEAPON_FORCE_BUSY_HOLSTER
00127
00128 #ifdef WEAPON_FORCE_BUSY_HOLSTER
00129
00130 static int cgWeapFrame = 0;
00131 static int cgWeapFrameTime = 0;
00132 #endif
00133
00134
00135
00136
00137
00138
00139
00140 static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame, int animNum ) {
00141 animation_t *animations = bgHumanoidAnimations;
00142 #ifdef WEAPON_FORCE_BUSY_HOLSTER
00143 if (cg.snap->ps.forceHandExtend != HANDEXTEND_NONE || cgWeapFrameTime > cg.time)
00144 {
00145
00146 if (cgWeapFrame < 6)
00147 {
00148 cgWeapFrame = 6;
00149 cgWeapFrameTime = cg.time + 10;
00150 }
00151
00152 if (cgWeapFrameTime < cg.time && cgWeapFrame < 10)
00153 {
00154 cgWeapFrame++;
00155 cgWeapFrameTime = cg.time + 10;
00156 }
00157
00158 if (cg.snap->ps.forceHandExtend != HANDEXTEND_NONE &&
00159 cgWeapFrame == 10)
00160 {
00161 cgWeapFrameTime = cg.time + 100;
00162 }
00163
00164 return cgWeapFrame;
00165 }
00166 else
00167 {
00168 cgWeapFrame = 0;
00169 cgWeapFrameTime = 0;
00170 }
00171 #endif
00172
00173 switch( animNum )
00174 {
00175 case TORSO_DROPWEAP1:
00176 if ( frame >= animations[animNum].firstFrame && frame < animations[animNum].firstFrame + 5 )
00177 {
00178 return frame - animations[animNum].firstFrame + 6;
00179 }
00180 break;
00181
00182 case TORSO_RAISEWEAP1:
00183 if ( frame >= animations[animNum].firstFrame && frame < animations[animNum].firstFrame + 4 )
00184 {
00185 return frame - animations[animNum].firstFrame + 6 + 4;
00186 }
00187 break;
00188 case BOTH_ATTACK1:
00189 case BOTH_ATTACK2:
00190 case BOTH_ATTACK3:
00191 case BOTH_ATTACK4:
00192 case BOTH_ATTACK10:
00193 case BOTH_THERMAL_THROW:
00194 if ( frame >= animations[animNum].firstFrame && frame < animations[animNum].firstFrame + 6 )
00195 {
00196 return 1 + ( frame - animations[animNum].firstFrame );
00197 }
00198
00199 break;
00200 }
00201 return -1;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
00211 float scale;
00212 int delta;
00213 float fracsin;
00214
00215 VectorCopy( cg.refdef.vieworg, origin );
00216 VectorCopy( cg.refdef.viewangles, angles );
00217
00218
00219 if ( cg.bobcycle & 1 ) {
00220 scale = -cg.xyspeed;
00221 } else {
00222 scale = cg.xyspeed;
00223 }
00224
00225
00226 angles[ROLL] += scale * cg.bobfracsin * 0.005;
00227 angles[YAW] += scale * cg.bobfracsin * 0.01;
00228 angles[PITCH] += cg.xyspeed * cg.bobfracsin * 0.005;
00229
00230
00231 delta = cg.time - cg.landTime;
00232 if ( delta < LAND_DEFLECT_TIME ) {
00233 origin[2] += cg.landChange*0.25 * delta / LAND_DEFLECT_TIME;
00234 } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
00235 origin[2] += cg.landChange*0.25 *
00236 (LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta) / LAND_RETURN_TIME;
00237 }
00238
00239 #if 0
00240
00241 delta = cg.time - cg.stepTime;
00242 if ( delta < STEP_TIME/2 ) {
00243 origin[2] -= cg.stepChange*0.25 * delta / (STEP_TIME/2);
00244 } else if ( delta < STEP_TIME ) {
00245 origin[2] -= cg.stepChange*0.25 * (STEP_TIME - delta) / (STEP_TIME/2);
00246 }
00247 #endif
00248
00249
00250 scale = cg.xyspeed + 40;
00251 fracsin = sin( cg.time * 0.001 );
00252 angles[ROLL] += scale * fracsin * 0.01;
00253 angles[YAW] += scale * fracsin * 0.01;
00254 angles[PITCH] += scale * fracsin * 0.01;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 static void CG_LightningBolt( centity_t *cent, vec3_t origin ) {
00270
00271 refEntity_t beam;
00272
00273
00274
00275
00276 if ( cent->currentState.weapon == WP_DEMP2 && cent->currentState.eFlags & EF_ALT_FIRING )
00277 { }
00278 else
00279 {
00280 return;
00281 }
00282
00283 memset( &beam, 0, sizeof( beam ) );
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 static void CG_AddWeaponWithPowerups( refEntity_t *gun, int powerups ) {
00375
00376 trap_R_AddRefEntityToScene( gun );
00377
00378 if (cg.predictedPlayerState.electrifyTime > cg.time)
00379 {
00380 int preShader = gun->customShader;
00381 if ( rand() & 1 )
00382 {
00383 gun->customShader = cgs.media.electricBodyShader;
00384 }
00385 else
00386 {
00387 gun->customShader = cgs.media.electricBody2Shader;
00388 }
00389 trap_R_AddRefEntityToScene( gun );
00390 gun->customShader = preShader;
00391 }
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team, vec3_t newAngles, qboolean thirdPerson ) {
00405 refEntity_t gun;
00406 refEntity_t barrel;
00407 vec3_t angles;
00408 weapon_t weaponNum;
00409 weaponInfo_t *weapon;
00410 centity_t *nonPredictedCent;
00411 refEntity_t flash;
00412
00413 weaponNum = cent->currentState.weapon;
00414
00415 if (cent->currentState.weapon == WP_EMPLACED_GUN)
00416 {
00417 return;
00418 }
00419
00420 if (cg.predictedPlayerState.pm_type == PM_SPECTATOR &&
00421 cent->currentState.number == cg.predictedPlayerState.clientNum)
00422 {
00423 return;
00424 }
00425
00426 CG_RegisterWeapon( weaponNum );
00427 weapon = &cg_weapons[weaponNum];
00428
00429
00430
00431
00432 memset( &gun, 0, sizeof( gun ) );
00433
00434
00435 if (!thirdPerson)
00436 {
00437
00438
00439 VectorCopy( parent->lightingOrigin, gun.lightingOrigin );
00440 gun.shadowPlane = parent->shadowPlane;
00441 gun.renderfx = parent->renderfx;
00442
00443 if (ps)
00444 {
00445 gun.hModel = weapon->viewModel;
00446 }
00447 else
00448 {
00449 gun.hModel = weapon->weaponModel;
00450 }
00451 if (!gun.hModel) {
00452 return;
00453 }
00454
00455 if ( !ps ) {
00456
00457 cent->pe.lightningFiring = qfalse;
00458 if ( ( cent->currentState.eFlags & EF_FIRING ) && weapon->firingSound ) {
00459
00460 trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->firingSound );
00461 cent->pe.lightningFiring = qtrue;
00462 } else if ( weapon->readySound ) {
00463 trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound );
00464 }
00465 }
00466
00467 CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon");
00468
00469 if (!CG_IsMindTricked(cent->currentState.trickedentindex,
00470 cent->currentState.trickedentindex2,
00471 cent->currentState.trickedentindex3,
00472 cent->currentState.trickedentindex4,
00473 cg.snap->ps.clientNum))
00474 {
00475 CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups );
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 }
00487
00488 if (weaponNum == WP_STUN_BATON)
00489 {
00490 int i = 0;
00491
00492 while (i < 3)
00493 {
00494 memset( &barrel, 0, sizeof( barrel ) );
00495 VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
00496 barrel.shadowPlane = parent->shadowPlane;
00497 barrel.renderfx = parent->renderfx;
00498
00499 if (i == 0)
00500 {
00501 barrel.hModel = trap_R_RegisterModel("models/weapons2/stun_baton/baton_barrel.md3");
00502 }
00503 else if (i == 1)
00504 {
00505 barrel.hModel = trap_R_RegisterModel("models/weapons2/stun_baton/baton_barrel2.md3");
00506 }
00507 else
00508 {
00509 barrel.hModel = trap_R_RegisterModel("models/weapons2/stun_baton/baton_barrel3.md3");
00510 }
00511 angles[YAW] = 0;
00512 angles[PITCH] = 0;
00513 angles[ROLL] = 0;
00514
00515 AnglesToAxis( angles, barrel.axis );
00516
00517 if (i == 0)
00518 {
00519 CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel" );
00520 }
00521 else if (i == 1)
00522 {
00523 CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel2" );
00524 }
00525 else
00526 {
00527 CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel3" );
00528 }
00529 CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
00530
00531 i++;
00532 }
00533 }
00534 else
00535 {
00536
00537 if ( weapon->barrelModel ) {
00538 memset( &barrel, 0, sizeof( barrel ) );
00539 VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
00540 barrel.shadowPlane = parent->shadowPlane;
00541 barrel.renderfx = parent->renderfx;
00542
00543 barrel.hModel = weapon->barrelModel;
00544 angles[YAW] = 0;
00545 angles[PITCH] = 0;
00546 angles[ROLL] = 0;
00547
00548 AnglesToAxis( angles, barrel.axis );
00549
00550 CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel" );
00551
00552 CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
00553 }
00554 }
00555 }
00556
00557
00558
00559
00560 memset (&flash, 0, sizeof(flash));
00561 CG_PositionEntityOnTag( &flash, &gun, gun.hModel, "tag_flash");
00562
00563 VectorCopy(flash.origin, cg.lastFPFlashPoint);
00564
00565
00566
00567 if ( (ps || cg.renderingThirdPerson || cg.predictedPlayerState.clientNum != cent->currentState.number) &&
00568 ( ( cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && cent->currentState.weapon == WP_BRYAR_PISTOL ) ||
00569 ( cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && cent->currentState.weapon == WP_BRYAR_OLD ) ||
00570 ( cent->currentState.weapon == WP_BOWCASTER && cent->currentState.modelindex2 == WEAPON_CHARGING ) ||
00571 ( cent->currentState.weapon == WP_DEMP2 && cent->currentState.modelindex2 == WEAPON_CHARGING_ALT) ) )
00572 {
00573 int shader = 0;
00574 float val = 0.0f;
00575 float scale = 1.0f;
00576 addspriteArgStruct_t fxSArgs;
00577 vec3_t flashorigin, flashdir;
00578
00579 if (!thirdPerson)
00580 {
00581 VectorCopy(flash.origin, flashorigin);
00582 VectorCopy(flash.axis[0], flashdir);
00583 }
00584 else
00585 {
00586 mdxaBone_t boltMatrix;
00587
00588 if (!trap_G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
00589 {
00590 return;
00591 }
00592
00593
00594 if (!(trap_G2API_GetBoltMatrix(cent->ghoul2, 1, 0, &boltMatrix, newAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale)))
00595 {
00596 return;
00597 }
00598
00599 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, flashorigin);
00600 BG_GiveMeVectorFromMatrix(&boltMatrix, POSITIVE_X, flashdir);
00601 }
00602
00603 if ( cent->currentState.weapon == WP_BRYAR_PISTOL ||
00604 cent->currentState.weapon == WP_BRYAR_OLD)
00605 {
00606
00607 val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
00608 shader = cgs.media.bryarFrontFlash;
00609 }
00610 else if ( cent->currentState.weapon == WP_BOWCASTER )
00611 {
00612
00613 val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
00614 shader = cgs.media.greenFrontFlash;
00615 }
00616 else if ( cent->currentState.weapon == WP_DEMP2 )
00617 {
00618 val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
00619 shader = cgs.media.lightningFlash;
00620 scale = 1.75f;
00621 }
00622
00623 if ( val < 0.0f )
00624 {
00625 val = 0.0f;
00626 }
00627 else if ( val > 1.0f )
00628 {
00629 val = 1.0f;
00630 if (ps && cent->currentState.number == ps->clientNum)
00631 {
00632 CGCam_Shake( 0.2f, 100 );
00633 }
00634 }
00635 else
00636 {
00637 if (ps && cent->currentState.number == ps->clientNum)
00638 {
00639 CGCam_Shake( val * val * 0.6f, 100 );
00640 }
00641 }
00642
00643 val += random() * 0.5f;
00644
00645 VectorCopy(flashorigin, fxSArgs.origin);
00646 VectorClear(fxSArgs.vel);
00647 VectorClear(fxSArgs.accel);
00648 fxSArgs.scale = 3.0f*val*scale;
00649 fxSArgs.dscale = 0.0f;
00650 fxSArgs.sAlpha = 0.7f;
00651 fxSArgs.eAlpha = 0.7f;
00652 fxSArgs.rotation = random()*360;
00653 fxSArgs.bounce = 0.0f;
00654 fxSArgs.life = 1.0f;
00655 fxSArgs.shader = shader;
00656 fxSArgs.flags = 0x08000000;
00657
00658
00659 trap_FX_AddSprite(&fxSArgs);
00660 }
00661
00662
00663 nonPredictedCent = &cg_entities[cent->currentState.clientNum];
00664
00665
00666
00667
00668 if( ( nonPredictedCent - cg_entities ) != cent->currentState.clientNum ) {
00669 nonPredictedCent = cent;
00670 }
00671
00672
00673 if ( ( weaponNum == WP_DEMP2)
00674 && ( nonPredictedCent->currentState.eFlags & EF_FIRING ) )
00675 {
00676
00677 } else {
00678
00679 if ( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME) {
00680 return;
00681 }
00682 }
00683
00684 if ( ps || cg.renderingThirdPerson ||
00685 cent->currentState.number != cg.predictedPlayerState.clientNum )
00686 {
00687 vec3_t flashorigin, flashdir;
00688 refEntity_t flash;
00689
00690 memset (&flash, 0, sizeof(flash));
00691
00692 if (!thirdPerson)
00693 {
00694 CG_PositionEntityOnTag( &flash, &gun, gun.hModel, "tag_flash");
00695 VectorCopy(flash.origin, flashorigin);
00696 VectorCopy(flash.axis[0], flashdir);
00697 }
00698 else
00699 {
00700 mdxaBone_t boltMatrix;
00701
00702 if (!trap_G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
00703 {
00704 return;
00705 }
00706
00707
00708 if (!(trap_G2API_GetBoltMatrix(cent->ghoul2, 1, 0, &boltMatrix, newAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale)))
00709 {
00710 return;
00711 }
00712
00713 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, flashorigin);
00714 BG_GiveMeVectorFromMatrix(&boltMatrix, POSITIVE_X, flashdir);
00715 }
00716
00717 if ( cg.time - cent->muzzleFlashTime <= MUZZLE_FLASH_TIME + 10 )
00718 {
00719 if ( cent->currentState.eFlags & EF_ALT_FIRING )
00720 {
00721 if (weapon->altMuzzleEffect)
00722 {
00723 if (!thirdPerson)
00724 {
00725 trap_FX_PlayEntityEffectID(weapon->altMuzzleEffect, flashorigin, flash.axis, -1, -1, -1, -1 );
00726 }
00727 else
00728 {
00729 trap_FX_PlayEffectID(weapon->altMuzzleEffect, flashorigin, flashdir, -1, -1);
00730 }
00731 }
00732 }
00733 else
00734 {
00735 if (weapon->muzzleEffect)
00736 {
00737 if (!thirdPerson)
00738 {
00739 trap_FX_PlayEntityEffectID(weapon->muzzleEffect, flashorigin, flash.axis, -1, -1, -1, -1 );
00740 }
00741 else
00742 {
00743 trap_FX_PlayEffectID(weapon->muzzleEffect, flashorigin, flashdir, -1, -1);
00744 }
00745 }
00746 }
00747 }
00748
00749
00750 CG_LightningBolt( nonPredictedCent, flashorigin );
00751
00752 if ( weapon->flashDlightColor[0] || weapon->flashDlightColor[1] || weapon->flashDlightColor[2] ) {
00753 trap_R_AddLightToScene( flashorigin, 300 + (rand()&31), weapon->flashDlightColor[0],
00754 weapon->flashDlightColor[1], weapon->flashDlightColor[2] );
00755 }
00756 }
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766 void CG_AddViewWeapon( playerState_t *ps ) {
00767 refEntity_t hand;
00768 centity_t *cent;
00769 clientInfo_t *ci;
00770 float fovOffset;
00771 vec3_t angles;
00772 weaponInfo_t *weapon;
00773 float cgFov = cg_fov.value;
00774
00775 if (cgFov < 1)
00776 {
00777 cgFov = 1;
00778 }
00779 if (cgFov > 97)
00780 {
00781 cgFov = 97;
00782 }
00783
00784 if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
00785 return;
00786 }
00787
00788 if ( ps->pm_type == PM_INTERMISSION ) {
00789 return;
00790 }
00791
00792
00793
00794 if ( cg.renderingThirdPerson ) {
00795 return;
00796 }
00797
00798
00799 if ( !cg_drawGun.integer || cg.predictedPlayerState.zoomMode) {
00800 vec3_t origin;
00801
00802 if ( cg.predictedPlayerState.eFlags & EF_FIRING ) {
00803
00804 VectorCopy( cg.refdef.vieworg, origin );
00805 VectorMA( origin, -8, cg.refdef.viewaxis[2], origin );
00806 CG_LightningBolt( &cg_entities[ps->clientNum], origin );
00807 }
00808 return;
00809 }
00810
00811
00812 if ( cg.testGun ) {
00813 return;
00814 }
00815
00816
00817 if ( cgFov > 90 ) {
00818 fovOffset = -0.2 * ( cgFov - 90 );
00819 } else {
00820 fovOffset = 0;
00821 }
00822
00823 cent = &cg_entities[cg.predictedPlayerState.clientNum];
00824 CG_RegisterWeapon( ps->weapon );
00825 weapon = &cg_weapons[ ps->weapon ];
00826
00827 memset (&hand, 0, sizeof(hand));
00828
00829
00830 CG_CalculateWeaponPosition( hand.origin, angles );
00831
00832 VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[0], hand.origin );
00833 VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
00834 VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );
00835
00836 AnglesToAxis( angles, hand.axis );
00837
00838
00839 if ( cg_gun_frame.integer ) {
00840
00841 hand.frame = hand.oldframe = cg_gun_frame.integer;
00842 hand.backlerp = 0;
00843 } else {
00844
00845 if (cent->currentState.eType == ET_NPC)
00846 {
00847 if (!cent->npcClient)
00848 {
00849 return;
00850 }
00851
00852 ci = cent->npcClient;
00853 }
00854 else
00855 {
00856 ci = &cgs.clientinfo[ cent->currentState.clientNum ];
00857 }
00858 hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame, cent->currentState.torsoAnim );
00859 hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame, cent->currentState.torsoAnim );
00860 hand.backlerp = cent->pe.torso.backlerp;
00861
00862
00863 if ( hand.frame == -1 )
00864 {
00865 hand.frame = 0;
00866 hand.oldframe = 0;
00867 hand.backlerp = 0;
00868 }
00869 else if ( hand.oldframe == -1 )
00870 {
00871 hand.oldframe = hand.frame;
00872 hand.backlerp = 0;
00873 }
00874 }
00875
00876 hand.hModel = weapon->handsModel;
00877 hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON;
00878
00879
00880 CG_AddPlayerWeapon( &hand, ps, &cg_entities[cg.predictedPlayerState.clientNum], ps->persistant[PERS_TEAM], angles, qfalse );
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890 #define ICON_WEAPONS 0
00891 #define ICON_FORCE 1
00892 #define ICON_INVENTORY 2
00893
00894
00895 void CG_DrawIconBackground(void)
00896 {
00897 int height,xAdd,x2,y2,t;
00898
00899 float inTime = cg.invenSelectTime+WEAPON_SELECT_TIME;
00900 float wpTime = cg.weaponSelectTime+WEAPON_SELECT_TIME;
00901 float fpTime = cg.forceSelectTime+WEAPON_SELECT_TIME;
00902
00903
00904
00905 #ifdef _XBOX
00906
00907 #endif
00908
00909
00910 if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 )
00911 {
00912 return;
00913 }
00914
00915 if (cg_hudFiles.integer)
00916 {
00917 return;
00918 }
00919
00920 x2 = 30;
00921 y2 = SCREEN_HEIGHT-70;
00922
00923
00924
00925
00926 if (inTime > wpTime)
00927 {
00928
00929 cg.iconSelectTime = cg.invenSelectTime;
00930 }
00931 else
00932 {
00933
00934 cg.iconSelectTime = cg.weaponSelectTime;
00935 }
00936
00937 if (fpTime > inTime && fpTime > wpTime)
00938 {
00939
00940 cg.iconSelectTime = cg.forceSelectTime;
00941 }
00942
00943 if ((cg.iconSelectTime+WEAPON_SELECT_TIME)<cg.time)
00944 {
00945 if (cg.iconHUDActive)
00946 {
00947 t = cg.time - (cg.iconSelectTime+WEAPON_SELECT_TIME);
00948 cg.iconHUDPercent = t/ 130.0f;
00949 cg.iconHUDPercent = 1 - cg.iconHUDPercent;
00950
00951 if (cg.iconHUDPercent<0)
00952 {
00953 cg.iconHUDActive = qfalse;
00954 cg.iconHUDPercent=0;
00955 }
00956
00957 xAdd = (int) 8*cg.iconHUDPercent;
00958
00959 height = (int) (60.0f*cg.iconHUDPercent);
00960
00961
00962
00963 }
00964 else
00965 {
00966 xAdd = 0;
00967 }
00968
00969 return;
00970 }
00971
00972
00973
00974 if (!cg.iconHUDActive)
00975 {
00976 t = cg.time - cg.iconSelectTime;
00977 cg.iconHUDPercent = t/ 130.0f;
00978
00979
00980 if (cg.iconHUDPercent>1)
00981 {
00982 cg.iconHUDActive = qtrue;
00983 cg.iconHUDPercent=1;
00984 }
00985 else if (cg.iconHUDPercent<0)
00986 {
00987 cg.iconHUDPercent=0;
00988 }
00989 }
00990 else
00991 {
00992 cg.iconHUDPercent=1;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 }
01023
01024 qboolean CG_WeaponCheck(int weap)
01025 {
01026 if (cg.snap->ps.ammo[weaponData[weap].ammoIndex] < weaponData[weap].energyPerShot &&
01027 cg.snap->ps.ammo[weaponData[weap].ammoIndex] < weaponData[weap].altEnergyPerShot)
01028 {
01029 return qfalse;
01030 }
01031
01032 return qtrue;
01033 }
01034
01035
01036
01037
01038
01039
01040 static qboolean CG_WeaponSelectable( int i ) {
01041
01042
01043
01044 if (!i)
01045 {
01046 return qfalse;
01047 }
01048
01049 if (cg.predictedPlayerState.ammo[weaponData[i].ammoIndex] < weaponData[i].energyPerShot &&
01050 cg.predictedPlayerState.ammo[weaponData[i].ammoIndex] < weaponData[i].altEnergyPerShot)
01051 {
01052 return qfalse;
01053 }
01054
01055 if (i == WP_DET_PACK && cg.predictedPlayerState.ammo[weaponData[i].ammoIndex] < 1 &&
01056 !cg.predictedPlayerState.hasDetPackPlanted)
01057 {
01058 return qfalse;
01059 }
01060
01061 if ( ! (cg.predictedPlayerState.stats[ STAT_WEAPONS ] & ( 1 << i ) ) ) {
01062 return qfalse;
01063 }
01064
01065 return qtrue;
01066 }
01067
01068
01069
01070
01071
01072
01073 #ifdef _XBOX
01074 extern bool CL_ExtendSelectTime(void);
01075 #endif
01076 void CG_DrawWeaponSelect( void ) {
01077 int i;
01078 int bits;
01079 int count;
01080 int smallIconSize,bigIconSize;
01081 int holdX,x,y,pad;
01082 int sideLeftIconCnt,sideRightIconCnt;
01083 int sideMax,holdCount,iconCnt;
01084 int height;
01085 int yOffset = 0;
01086 qboolean drewConc = qfalse;
01087
01088 if (cg.predictedPlayerState.emplacedIndex)
01089 {
01090 cg.weaponSelectTime = 0;
01091 }
01092
01093 if ((cg.weaponSelectTime+WEAPON_SELECT_TIME)<cg.time)
01094 {
01095 return;
01096 }
01097
01098
01099 if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 )
01100 {
01101 return;
01102 }
01103
01104 #ifdef _XBOX
01105 if(CL_ExtendSelectTime()) {
01106 cg.weaponSelectTime = cg.time;
01107 }
01108
01109 yOffset = -50;
01110 #endif
01111
01112
01113 cg.itemPickupTime = 0;
01114
01115 bits = cg.predictedPlayerState.stats[ STAT_WEAPONS ];
01116
01117
01118 count = 0;
01119
01120 if ( !CG_WeaponSelectable(cg.weaponSelect) &&
01121 (cg.weaponSelect == WP_THERMAL || cg.weaponSelect == WP_TRIP_MINE) )
01122 {
01123
01124 count++;
01125 }
01126
01127 for ( i = 1 ; i < WP_NUM_WEAPONS ; i++ )
01128 {
01129 if ( bits & ( 1 << i ) )
01130 {
01131 if ( CG_WeaponSelectable(i) ||
01132 (i != WP_THERMAL && i != WP_TRIP_MINE) )
01133 {
01134 count++;
01135 }
01136 }
01137 }
01138
01139 if (count == 0)
01140 {
01141 return;
01142 }
01143
01144 sideMax = 3;
01145
01146
01147 holdCount = count - 1;
01148 if (holdCount == 0)
01149 {
01150 sideLeftIconCnt = 0;
01151 sideRightIconCnt = 0;
01152 }
01153 else if (count > (2*sideMax))
01154 {
01155 sideLeftIconCnt = sideMax;
01156 sideRightIconCnt = sideMax;
01157 }
01158 else
01159 {
01160 sideLeftIconCnt = holdCount/2;
01161 sideRightIconCnt = holdCount - sideLeftIconCnt;
01162 }
01163
01164 if ( cg.weaponSelect == WP_CONCUSSION )
01165 {
01166 i = WP_FLECHETTE;
01167 }
01168 else
01169 {
01170 i = cg.weaponSelect - 1;
01171 }
01172 if (i<1)
01173 {
01174 i = LAST_USEABLE_WEAPON;
01175 }
01176
01177 smallIconSize = 40;
01178 bigIconSize = 80;
01179 pad = 12;
01180
01181 x = 320;
01182 y = 410;
01183
01184
01185
01186
01187
01188
01189
01190 trap_R_SetColor(colorTable[CT_WHITE]);
01191
01192 holdX = x - ((bigIconSize/2) + pad + smallIconSize);
01193 height = smallIconSize * 1;
01194 drewConc = qfalse;
01195
01196 for (iconCnt=1;iconCnt<(sideLeftIconCnt+1);i--)
01197 {
01198 if ( i == WP_CONCUSSION )
01199 {
01200 i--;
01201 }
01202 else if ( i == WP_FLECHETTE && !drewConc && cg.weaponSelect != WP_CONCUSSION )
01203 {
01204 i = WP_CONCUSSION;
01205 }
01206 if (i<1)
01207 {
01208
01209
01210 i = LAST_USEABLE_WEAPON;
01211 }
01212
01213 if ( !(bits & ( 1 << i )))
01214 {
01215 if ( i == WP_CONCUSSION )
01216 {
01217 drewConc = qtrue;
01218 i = WP_ROCKET_LAUNCHER;
01219 }
01220 continue;
01221 }
01222
01223 if ( !CG_WeaponSelectable(i) &&
01224 (i == WP_THERMAL || i == WP_TRIP_MINE) )
01225 {
01226 continue;
01227 }
01228
01229 ++iconCnt;
01230
01231 if (cgs.media.weaponIcons[i])
01232 {
01233 weaponInfo_t *weaponInfo;
01234 CG_RegisterWeapon( i );
01235 weaponInfo = &cg_weapons[i];
01236
01237 trap_R_SetColor(colorTable[CT_WHITE]);
01238 if (!CG_WeaponCheck(i))
01239 {
01240 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, cgs.media.weaponIcons_NA[i] );
01241 }
01242 else
01243 {
01244 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, cgs.media.weaponIcons[i] );
01245 }
01246
01247 holdX -= (smallIconSize+pad);
01248 }
01249 if ( i == WP_CONCUSSION )
01250 {
01251 drewConc = qtrue;
01252 i = WP_ROCKET_LAUNCHER;
01253 }
01254 }
01255
01256
01257 height = bigIconSize * cg.iconHUDPercent;
01258 if (cgs.media.weaponIcons[cg.weaponSelect])
01259 {
01260 weaponInfo_t *weaponInfo;
01261 CG_RegisterWeapon( cg.weaponSelect );
01262 weaponInfo = &cg_weapons[cg.weaponSelect];
01263
01264 trap_R_SetColor( colorTable[CT_WHITE]);
01265 if (!CG_WeaponCheck(cg.weaponSelect))
01266 {
01267 CG_DrawPic( x-(bigIconSize/2), (y-((bigIconSize-smallIconSize)/2))+10+yOffset, bigIconSize, bigIconSize, cgs.media.weaponIcons_NA[cg.weaponSelect] );
01268 }
01269 else
01270 {
01271 CG_DrawPic( x-(bigIconSize/2), (y-((bigIconSize-smallIconSize)/2))+10+yOffset, bigIconSize, bigIconSize, cgs.media.weaponIcons[cg.weaponSelect] );
01272 }
01273 }
01274
01275 if ( cg.weaponSelect == WP_CONCUSSION )
01276 {
01277 i = WP_ROCKET_LAUNCHER;
01278 }
01279 else
01280 {
01281 i = cg.weaponSelect + 1;
01282 }
01283 if (i> LAST_USEABLE_WEAPON)
01284 {
01285 i = 1;
01286 }
01287
01288
01289
01290 holdX = x + (bigIconSize/2) + pad;
01291 height = smallIconSize * cg.iconHUDPercent;
01292 for (iconCnt=1;iconCnt<(sideRightIconCnt+1);i++)
01293 {
01294 if ( i == WP_CONCUSSION )
01295 {
01296 i++;
01297 }
01298 else if ( i == WP_ROCKET_LAUNCHER && !drewConc && cg.weaponSelect != WP_CONCUSSION )
01299 {
01300 i = WP_CONCUSSION;
01301 }
01302 if (i>LAST_USEABLE_WEAPON)
01303 {
01304 i = 1;
01305 }
01306
01307 if ( !(bits & ( 1 << i )))
01308 {
01309 if ( i == WP_CONCUSSION )
01310 {
01311 drewConc = qtrue;
01312 i = WP_FLECHETTE;
01313 }
01314 continue;
01315 }
01316
01317 if ( !CG_WeaponSelectable(i) &&
01318 (i == WP_THERMAL || i == WP_TRIP_MINE) )
01319 {
01320 continue;
01321 }
01322
01323 ++iconCnt;
01324
01325 if (cgs.media.weaponIcons[i])
01326 {
01327 weaponInfo_t *weaponInfo;
01328 CG_RegisterWeapon( i );
01329 weaponInfo = &cg_weapons[i];
01330
01331 trap_R_SetColor( colorTable[CT_WHITE]);
01332 if (!CG_WeaponCheck(i))
01333 {
01334 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, cgs.media.weaponIcons_NA[i] );
01335 }
01336 else
01337 {
01338 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, cgs.media.weaponIcons[i] );
01339 }
01340
01341
01342 holdX += (smallIconSize+pad);
01343 }
01344 if ( i == WP_CONCUSSION )
01345 {
01346 drewConc = qtrue;
01347 i = WP_FLECHETTE;
01348 }
01349 }
01350
01351
01352 if ( cg_weapons[ cg.weaponSelect ].item )
01353 {
01354 vec4_t textColor = { .875f, .718f, .121f, 1.0f };
01355 char text[1024];
01356 char upperKey[1024];
01357
01358 strcpy(upperKey, cg_weapons[ cg.weaponSelect ].item->classname);
01359
01360