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 if ( trap_SP_GetStringTextString( va("SP_INGAME_%s",Q_strupr(upperKey)), text, sizeof( text )))
01361 {
01362 UI_DrawProportionalString(320, y+45+yOffset, text, UI_CENTER|UI_SMALLFONT, textColor);
01363 }
01364 else
01365 {
01366 UI_DrawProportionalString(320, y+45+yOffset, cg_weapons[ cg.weaponSelect ].item->classname, UI_CENTER|UI_SMALLFONT, textColor);
01367 }
01368 }
01369
01370 trap_R_SetColor( NULL );
01371 }
01372
01373
01374
01375
01376
01377
01378
01379 void CG_NextWeapon_f( void ) {
01380 int i;
01381 int original;
01382
01383 if ( !cg.snap ) {
01384 return;
01385 }
01386 if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
01387 return;
01388 }
01389
01390 if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
01391 {
01392 return;
01393 }
01394
01395 if (cg.snap->ps.emplacedIndex)
01396 {
01397 return;
01398 }
01399
01400 cg.weaponSelectTime = cg.time;
01401 original = cg.weaponSelect;
01402
01403 for ( i = 0 ; i < WP_NUM_WEAPONS ; i++ ) {
01404
01405 if ( cg.weaponSelect == WP_FLECHETTE )
01406 {
01407 cg.weaponSelect = WP_CONCUSSION;
01408 }
01409 else if ( cg.weaponSelect == WP_CONCUSSION )
01410 {
01411 cg.weaponSelect = WP_ROCKET_LAUNCHER;
01412 }
01413 else if ( cg.weaponSelect == WP_DET_PACK )
01414 {
01415 cg.weaponSelect = WP_BRYAR_OLD;
01416 }
01417 else
01418 {
01419 cg.weaponSelect++;
01420 }
01421 if ( cg.weaponSelect == WP_NUM_WEAPONS ) {
01422 cg.weaponSelect = 0;
01423 }
01424
01425
01426
01427 if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
01428 break;
01429 }
01430 }
01431 if ( i == WP_NUM_WEAPONS ) {
01432 cg.weaponSelect = original;
01433 }
01434 else
01435 {
01436 trap_S_MuteSound(cg.snap->ps.clientNum, CHAN_WEAPON);
01437 }
01438 }
01439
01440
01441
01442
01443
01444
01445 void CG_PrevWeapon_f( void ) {
01446 int i;
01447 int original;
01448
01449 if ( !cg.snap ) {
01450 return;
01451 }
01452 if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
01453 return;
01454 }
01455
01456 if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
01457 {
01458 return;
01459 }
01460
01461 if (cg.snap->ps.emplacedIndex)
01462 {
01463 return;
01464 }
01465
01466 cg.weaponSelectTime = cg.time;
01467 original = cg.weaponSelect;
01468
01469 for ( i = 0 ; i < WP_NUM_WEAPONS ; i++ ) {
01470
01471 if ( cg.weaponSelect == WP_ROCKET_LAUNCHER )
01472 {
01473 cg.weaponSelect = WP_CONCUSSION;
01474 }
01475 else if ( cg.weaponSelect == WP_CONCUSSION )
01476 {
01477 cg.weaponSelect = WP_FLECHETTE;
01478 }
01479 else if ( cg.weaponSelect == WP_BRYAR_OLD )
01480 {
01481 cg.weaponSelect = WP_DET_PACK;
01482 }
01483 else
01484 {
01485 cg.weaponSelect--;
01486 }
01487 if ( cg.weaponSelect == -1 ) {
01488 cg.weaponSelect = WP_NUM_WEAPONS-1;
01489 }
01490
01491
01492
01493 if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
01494 break;
01495 }
01496 }
01497 if ( i == WP_NUM_WEAPONS ) {
01498 cg.weaponSelect = original;
01499 }
01500 else
01501 {
01502 trap_S_MuteSound(cg.snap->ps.clientNum, CHAN_WEAPON);
01503 }
01504 }
01505
01506
01507
01508
01509
01510
01511 void CG_Weapon_f( void ) {
01512 int num;
01513
01514 if ( !cg.snap ) {
01515 return;
01516 }
01517 if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
01518 return;
01519 }
01520
01521 if (cg.snap->ps.emplacedIndex)
01522 {
01523 return;
01524 }
01525
01526 num = atoi( CG_Argv( 1 ) );
01527
01528 if ( num < 1 || num > LAST_USEABLE_WEAPON ) {
01529 return;
01530 }
01531
01532 if (num == 1 && cg.snap->ps.weapon == WP_SABER)
01533 {
01534 if (cg.snap->ps.weaponTime < 1)
01535 {
01536 trap_SendConsoleCommand("sv_saberswitch\n");
01537 }
01538 return;
01539 }
01540
01541
01542 if (num > WP_STUN_BATON)
01543 {
01544
01545 num += 2;
01546 }
01547 else
01548 {
01549 if (cg.snap->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
01550 {
01551 num = WP_SABER;
01552 }
01553 else
01554 {
01555 num = WP_MELEE;
01556 }
01557 }
01558
01559 if (num > LAST_USEABLE_WEAPON+1)
01560 {
01561 return;
01562 }
01563
01564 if (num >= WP_THERMAL && num <= WP_DET_PACK)
01565 {
01566 int weap, i = 0;
01567
01568 if (cg.snap->ps.weapon >= WP_THERMAL &&
01569 cg.snap->ps.weapon <= WP_DET_PACK)
01570 {
01571
01572 weap = cg.snap->ps.weapon + 1;
01573 }
01574 else
01575 {
01576
01577 weap = WP_THERMAL;
01578 }
01579
01580
01581 while ( i <= 4 )
01582 {
01583 if (weap > WP_DET_PACK)
01584 {
01585 weap = WP_THERMAL;
01586 }
01587
01588 if (CG_WeaponSelectable(weap))
01589 {
01590 num = weap;
01591 break;
01592 }
01593
01594 weap++;
01595 i++;
01596 }
01597 }
01598
01599 if (!CG_WeaponSelectable(num))
01600 {
01601 return;
01602 }
01603
01604 cg.weaponSelectTime = cg.time;
01605
01606 if ( ! ( cg.snap->ps.stats[STAT_WEAPONS] & ( 1 << num ) ) )
01607 {
01608 if (num == WP_SABER)
01609 {
01610 num = WP_MELEE;
01611
01612 if ( ! ( cg.snap->ps.stats[STAT_WEAPONS] & ( 1 << num ) ) )
01613 {
01614 return;
01615 }
01616 }
01617 else
01618 {
01619 return;
01620 }
01621 }
01622
01623 if (cg.weaponSelect != num)
01624 {
01625 trap_S_MuteSound(cg.snap->ps.clientNum, CHAN_WEAPON);
01626 }
01627
01628 cg.weaponSelect = num;
01629 }
01630
01631
01632
01633
01634 void CG_WeaponClean_f( void ) {
01635 int num;
01636
01637 if ( !cg.snap ) {
01638 return;
01639 }
01640 if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
01641 return;
01642 }
01643
01644 if (cg.snap->ps.emplacedIndex)
01645 {
01646 return;
01647 }
01648
01649 num = atoi( CG_Argv( 1 ) );
01650
01651 if ( num < 1 || num > LAST_USEABLE_WEAPON ) {
01652 return;
01653 }
01654
01655 if (num == 1 && cg.snap->ps.weapon == WP_SABER)
01656 {
01657 if (cg.snap->ps.weaponTime < 1)
01658 {
01659 trap_SendConsoleCommand("sv_saberswitch\n");
01660 }
01661 return;
01662 }
01663
01664 if(num == WP_STUN_BATON) {
01665 if (cg.snap->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
01666 {
01667 num = WP_SABER;
01668 }
01669 else
01670 {
01671 num = WP_MELEE;
01672 }
01673 }
01674
01675 if (num > LAST_USEABLE_WEAPON+1)
01676 {
01677 return;
01678 }
01679
01680 if (num >= WP_THERMAL && num <= WP_DET_PACK)
01681 {
01682 int weap, i = 0;
01683
01684 if (cg.snap->ps.weapon >= WP_THERMAL &&
01685 cg.snap->ps.weapon <= WP_DET_PACK)
01686 {
01687
01688 weap = cg.snap->ps.weapon + 1;
01689 }
01690 else
01691 {
01692
01693 weap = WP_THERMAL;
01694 }
01695
01696
01697 while ( i <= 4 )
01698 {
01699 if (weap > WP_DET_PACK)
01700 {
01701 weap = WP_THERMAL;
01702 }
01703
01704 if (CG_WeaponSelectable(weap))
01705 {
01706 num = weap;
01707 break;
01708 }
01709
01710 weap++;
01711 i++;
01712 }
01713 }
01714
01715 if (!CG_WeaponSelectable(num))
01716 {
01717 return;
01718 }
01719
01720 cg.weaponSelectTime = cg.time;
01721
01722 if ( ! ( cg.snap->ps.stats[STAT_WEAPONS] & ( 1 << num ) ) )
01723 {
01724 if (num == WP_SABER)
01725 {
01726 num = WP_MELEE;
01727
01728 if ( ! ( cg.snap->ps.stats[STAT_WEAPONS] & ( 1 << num ) ) )
01729 {
01730 return;
01731 }
01732 }
01733 else
01734 {
01735 return;
01736 }
01737 }
01738
01739 if (cg.weaponSelect != num)
01740 {
01741 trap_S_MuteSound(cg.snap->ps.clientNum, CHAN_WEAPON);
01742 }
01743
01744 cg.weaponSelect = num;
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756 void CG_OutOfAmmoChange( int oldWeapon )
01757 {
01758 int i;
01759
01760 cg.weaponSelectTime = cg.time;
01761
01762 for ( i = LAST_USEABLE_WEAPON ; i > 0 ; i-- )
01763 {
01764 if ( CG_WeaponSelectable( i ) )
01765 {
01766
01767
01768
01769
01770
01771 if (cg_autoswitch.integer != 1 || (i != WP_TRIP_MINE && i != WP_DET_PACK && i != WP_THERMAL && i != WP_ROCKET_LAUNCHER))
01772 {
01773 if (i != oldWeapon)
01774 {
01775 cg.weaponSelect = i;
01776 break;
01777 }
01778 }
01779 }
01780 }
01781
01782 trap_S_MuteSound(cg.snap->ps.clientNum, CHAN_WEAPON);
01783 }
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795 void CG_GetClientWeaponMuzzleBoltPoint(int clIndex, vec3_t to)
01796 {
01797 centity_t *cent;
01798 mdxaBone_t boltMatrix;
01799
01800 if (clIndex < 0 || clIndex >= MAX_CLIENTS)
01801 {
01802 return;
01803 }
01804
01805 cent = &cg_entities[clIndex];
01806
01807 if (!cent || !cent->ghoul2 || !trap_G2_HaveWeGhoul2Models(cent->ghoul2) ||
01808 !trap_G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
01809 {
01810 return;
01811 }
01812
01813 trap_G2API_GetBoltMatrix(cent->ghoul2, 1, 0, &boltMatrix, cent->turAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale);
01814 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, to);
01815 }
01816
01817
01818
01819
01820
01821
01822
01823
01824 void CG_FireWeapon( centity_t *cent, qboolean altFire ) {
01825 entityState_t *ent;
01826 int c;
01827 weaponInfo_t *weap;
01828
01829 ent = ¢->currentState;
01830 if ( ent->weapon == WP_NONE ) {
01831 return;
01832 }
01833 if ( ent->weapon >= WP_NUM_WEAPONS ) {
01834 CG_Error( "CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS" );
01835 return;
01836 }
01837 weap = &cg_weapons[ ent->weapon ];
01838
01839
01840
01841 cent->muzzleFlashTime = cg.time;
01842
01843 if (cg.predictedPlayerState.clientNum == cent->currentState.number)
01844 {
01845 if ((ent->weapon == WP_BRYAR_PISTOL && altFire) ||
01846 (ent->weapon == WP_BRYAR_OLD && altFire) ||
01847 (ent->weapon == WP_BOWCASTER && !altFire) ||
01848 (ent->weapon == WP_DEMP2 && altFire))
01849 {
01850 float val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
01851
01852 if (val > 3)
01853 {
01854 val = 3;
01855 }
01856 if (val < 0.2)
01857 {
01858 val = 0.2;
01859 }
01860
01861 val *= 2;
01862
01863 CGCam_Shake( val, 250 );
01864 }
01865 else if (ent->weapon == WP_ROCKET_LAUNCHER ||
01866 (ent->weapon == WP_REPEATER && altFire) ||
01867 ent->weapon == WP_FLECHETTE ||
01868 (ent->weapon == WP_CONCUSSION && !altFire))
01869 {
01870 if (ent->weapon == WP_CONCUSSION)
01871 {
01872 if (!cg.renderingThirdPerson )
01873 {
01874 cg.kick_angles[PITCH] = flrand( -10, -15 );
01875 cg.kick_time = cg.time;
01876 }
01877 }
01878 else if (ent->weapon == WP_ROCKET_LAUNCHER)
01879 {
01880 CGCam_Shake(flrand(2, 3), 350);
01881 }
01882 else if (ent->weapon == WP_REPEATER)
01883 {
01884 CGCam_Shake(flrand(2, 3), 350);
01885 }
01886 else if (ent->weapon == WP_FLECHETTE)
01887 {
01888 if (altFire)
01889 {
01890 CGCam_Shake(flrand(2, 3), 350);
01891 }
01892 else
01893 {
01894 CGCam_Shake(1.5, 250);
01895 }
01896 }
01897 }
01898 }
01899
01900 if ( ent->weapon == WP_DEMP2 ) {
01901 if ( cent->pe.lightningFiring ) {
01902 return;
01903 }
01904 }
01905
01906
01907 if ( cent->currentState.powerups & ( 1 << PW_QUAD ) ) {
01908
01909 }
01910
01911
01912
01913 if (altFire)
01914 {
01915
01916 for ( c = 0 ; c < 4 ; c++ ) {
01917 if ( !weap->altFlashSound[c] ) {
01918 break;
01919 }
01920 }
01921 if ( c > 0 ) {
01922 c = rand() % c;
01923 if ( weap->altFlashSound[c] )
01924 {
01925 trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->altFlashSound[c] );
01926 }
01927 }
01928
01929
01930
01931
01932 }
01933 else
01934 {
01935
01936 for ( c = 0 ; c < 4 ; c++ ) {
01937 if ( !weap->flashSound[c] ) {
01938 break;
01939 }
01940 }
01941 if ( c > 0 ) {
01942 c = rand() % c;
01943 if ( weap->flashSound[c] )
01944 {
01945 trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->flashSound[c] );
01946 }
01947 }
01948 }
01949 }
01950
01951 qboolean CG_VehicleWeaponImpact( centity_t *cent )
01952 {
01953 if ((cent->currentState.eFlags&EF_JETPACK_ACTIVE)
01954 && cent->currentState.otherEntityNum2
01955 && g_vehWeaponInfo[cent->currentState.otherEntityNum2].iImpactFX)
01956 {
01957 vec3_t normal;
01958 ByteToDir( cent->currentState.eventParm, normal );
01959
01960 trap_FX_PlayEffectID( g_vehWeaponInfo[cent->currentState.otherEntityNum2].iImpactFX, cent->lerpOrigin, normal, -1, -1 );
01961 return qtrue;
01962 }
01963 return qfalse;
01964 }
01965
01966
01967
01968
01969
01970
01971
01972
01973 void CG_MissileHitWall(int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType, qboolean altFire, int charge)
01974 {
01975 int parm;
01976 vec3_t up={0,0,1};
01977
01978 switch( weapon )
01979 {
01980 case WP_BRYAR_PISTOL:
01981 if ( altFire )
01982 {
01983 parm = charge;
01984 FX_BryarAltHitWall( origin, dir, parm );
01985 }
01986 else
01987 {
01988 FX_BryarHitWall( origin, dir );
01989 }
01990 break;
01991
01992 case WP_CONCUSSION:
01993 FX_ConcussionHitWall( origin, dir );
01994 break;
01995
01996 case WP_BRYAR_OLD:
01997 if ( altFire )
01998 {
01999 parm = charge;
02000 FX_BryarAltHitWall( origin, dir, parm );
02001 }
02002 else
02003 {
02004 FX_BryarHitWall( origin, dir );
02005 }
02006 break;
02007
02008 case WP_TURRET:
02009 FX_TurretHitWall( origin, dir );
02010 break;
02011
02012 case WP_BLASTER:
02013 FX_BlasterWeaponHitWall( origin, dir );
02014 break;
02015
02016 case WP_DISRUPTOR:
02017 FX_DisruptorAltMiss( origin, dir );
02018 break;
02019
02020 case WP_BOWCASTER:
02021 FX_BowcasterHitWall( origin, dir );
02022 break;
02023
02024 case WP_REPEATER:
02025 if ( altFire )
02026 {
02027 FX_RepeaterAltHitWall( origin, dir );
02028 }
02029 else
02030 {
02031 FX_RepeaterHitWall( origin, dir );
02032 }
02033 break;
02034
02035 case WP_DEMP2:
02036 if (altFire)
02037 {
02038 trap_FX_PlayEffectID(cgs.effects.mAltDetonate, origin, dir, -1, -1);
02039 }
02040 else
02041 {
02042 FX_DEMP2_HitWall( origin, dir );
02043 }
02044 break;
02045
02046 case WP_FLECHETTE:
02047
02048
02049
02050
02051
02052
02053 if (!altFire)
02054 {
02055 FX_FlechetteWeaponHitWall( origin, dir );
02056 }
02057 break;
02058
02059 case WP_ROCKET_LAUNCHER:
02060 FX_RocketHitWall( origin, dir );
02061 break;
02062
02063 case WP_THERMAL:
02064 trap_FX_PlayEffectID( cgs.effects.thermalExplosionEffect, origin, dir, -1, -1 );
02065 trap_FX_PlayEffectID( cgs.effects.thermalShockwaveEffect, origin, up, -1, -1 );
02066 break;
02067
02068 case WP_EMPLACED_GUN:
02069 FX_BlasterWeaponHitWall( origin, dir );
02070
02071 break;
02072 }
02073 }
02074
02075
02076
02077
02078
02079
02080
02081 void CG_MissileHitPlayer(int weapon, vec3_t origin, vec3_t dir, int entityNum, qboolean altFire)
02082 {
02083 qboolean humanoid = qtrue;
02084 vec3_t up={0,0,1};
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 switch ( weapon ) {
02105 case WP_BRYAR_PISTOL:
02106 if ( altFire )
02107 {
02108 FX_BryarAltHitPlayer( origin, dir, humanoid );
02109 }
02110 else
02111 {
02112 FX_BryarHitPlayer( origin, dir, humanoid );
02113 }
02114 break;
02115
02116 case WP_CONCUSSION:
02117 FX_ConcussionHitPlayer( origin, dir, humanoid );
02118 break;
02119
02120 case WP_BRYAR_OLD:
02121 if ( altFire )
02122 {
02123 FX_BryarAltHitPlayer( origin, dir, humanoid );
02124 }
02125 else
02126 {
02127 FX_BryarHitPlayer( origin, dir, humanoid );
02128 }
02129 break;
02130
02131 case WP_TURRET:
02132 FX_TurretHitPlayer( origin, dir, humanoid );
02133 break;
02134
02135 case WP_BLASTER:
02136 FX_BlasterWeaponHitPlayer( origin, dir, humanoid );
02137 break;
02138
02139 case WP_DISRUPTOR:
02140 FX_DisruptorAltHit( origin, dir);
02141 break;
02142
02143 case WP_BOWCASTER:
02144 FX_BowcasterHitPlayer( origin, dir, humanoid );
02145 break;
02146
02147 case WP_REPEATER:
02148 if ( altFire )
02149 {
02150 FX_RepeaterAltHitPlayer( origin, dir, humanoid );
02151 }
02152 else
02153 {
02154 FX_RepeaterHitPlayer( origin, dir, humanoid );
02155 }
02156 break;
02157
02158 case WP_DEMP2:
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168 if (altFire)
02169 {
02170 trap_FX_PlayEffectID(cgs.effects.mAltDetonate, origin, dir, -1, -1);
02171 }
02172 else
02173 {
02174 FX_DEMP2_HitPlayer( origin, dir, humanoid );
02175 }
02176 break;
02177
02178 case WP_FLECHETTE:
02179 FX_FlechetteWeaponHitPlayer( origin, dir, humanoid );
02180 break;
02181
02182 case WP_ROCKET_LAUNCHER:
02183 FX_RocketHitPlayer( origin, dir, humanoid );
02184 break;
02185
02186 case WP_THERMAL:
02187 trap_FX_PlayEffectID( cgs.effects.thermalExplosionEffect, origin, dir, -1, -1 );
02188 trap_FX_PlayEffectID( cgs.effects.thermalShockwaveEffect, origin, up, -1, -1 );
02189 break;
02190 case WP_EMPLACED_GUN:
02191
02192 FX_BlasterWeaponHitPlayer( origin, dir, humanoid );
02193 break;
02194
02195 default:
02196 break;
02197 }
02198 }
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215 qboolean CG_CalcMuzzlePoint( int entityNum, vec3_t muzzle ) {
02216 vec3_t forward, right;
02217 vec3_t gunpoint;
02218 centity_t *cent;
02219 int anim;
02220
02221 if ( entityNum == cg.snap->ps.clientNum )
02222 {
02223 int weapontype = cg.snap->ps.weapon;
02224 vec3_t weaponMuzzle;
02225 centity_t *pEnt = &cg_entities[cg.predictedPlayerState.clientNum];
02226
02227 VectorCopy(WP_MuzzlePoint[weapontype], weaponMuzzle);
02228
02229 if (weapontype == WP_DISRUPTOR || weapontype == WP_STUN_BATON || weapontype == WP_MELEE || weapontype == WP_SABER)
02230 {
02231 VectorClear(weaponMuzzle);
02232 }
02233
02234 if (cg.renderingThirdPerson)
02235 {
02236 VectorCopy( pEnt->lerpOrigin, gunpoint );
02237 AngleVectors( pEnt->lerpAngles, forward, right, NULL );
02238 }
02239 else
02240 {
02241 VectorCopy( cg.refdef.vieworg, gunpoint );
02242 AngleVectors( cg.refdef.viewangles, forward, right, NULL );
02243 }
02244
02245 if (weapontype == WP_EMPLACED_GUN && cg.snap->ps.emplacedIndex)
02246 {
02247 centity_t *gunEnt = &cg_entities[cg.snap->ps.emplacedIndex];
02248
02249 if (gunEnt)
02250 {
02251 vec3_t pitchConstraint;
02252
02253 VectorCopy(gunEnt->lerpOrigin, gunpoint);
02254 gunpoint[2] += 46;
02255
02256 if (cg.renderingThirdPerson)
02257 {
02258 VectorCopy(pEnt->lerpAngles, pitchConstraint);
02259 }
02260 else
02261 {
02262 VectorCopy(cg.refdef.viewangles, pitchConstraint);
02263 }
02264
02265 if (pitchConstraint[PITCH] > 40)
02266 {
02267 pitchConstraint[PITCH] = 40;
02268 }
02269 AngleVectors( pitchConstraint, forward, right, NULL );
02270 }
02271 }
02272
02273 VectorCopy(gunpoint, muzzle);
02274
02275 VectorMA(muzzle, weaponMuzzle[0], forward, muzzle);
02276 VectorMA(muzzle, weaponMuzzle[1], right, muzzle);
02277
02278 if (weapontype == WP_EMPLACED_GUN && cg.snap->ps.emplacedIndex)
02279 {
02280
02281 }
02282 else if (cg.renderingThirdPerson)
02283 {
02284 muzzle[2] += cg.snap->ps.viewheight + weaponMuzzle[2];
02285 }
02286 else
02287 {
02288 muzzle[2] += weaponMuzzle[2];
02289 }
02290
02291 return qtrue;
02292 }
02293
02294 cent = &cg_entities[entityNum];
02295 if ( !cent->currentValid ) {
02296 return qfalse;
02297 }
02298
02299 VectorCopy( cent->currentState.pos.trBase, muzzle );
02300
02301 AngleVectors( cent->currentState.apos.trBase, forward, NULL, NULL );
02302 anim = cent->currentState.legsAnim;
02303 if ( anim == BOTH_CROUCH1WALK || anim == BOTH_CROUCH1IDLE ) {
02304 muzzle[2] += CROUCH_VIEWHEIGHT;
02305 } else {
02306 muzzle[2] += DEFAULT_VIEWHEIGHT;
02307 }
02308
02309 VectorMA( muzzle, 14, forward, muzzle );
02310
02311 return qtrue;
02312
02313 }
02314
02315
02316
02317
02318
02319
02320
02321
02322 static void *g2WeaponInstances[MAX_WEAPONS];
02323
02324 void CG_InitG2Weapons(void)
02325 {
02326 int i = 0;
02327 gitem_t *item;
02328 memset(g2WeaponInstances, 0, sizeof(g2WeaponInstances));
02329 for ( item = bg_itemlist + 1 ; item->classname ; item++ )
02330 {
02331 if ( item->giType == IT_WEAPON )
02332 {
02333 assert(item->giTag < MAX_WEAPONS);
02334
02335
02336 trap_G2API_InitGhoul2Model(&g2WeaponInstances[item->giTag], item->world_model[0], 0, 0, 0, 0, 0);
02337
02338 if (g2WeaponInstances[item->giTag])
02339 {
02340
02341 trap_G2API_SetBoltInfo(g2WeaponInstances[item->giTag], 0, 0);
02342
02343 if (item->giTag == WP_SABER)
02344 {
02345 trap_G2API_AddBolt(g2WeaponInstances[item->giTag], 0, "*blade1");
02346 }
02347 else
02348 {
02349 trap_G2API_AddBolt(g2WeaponInstances[item->giTag], 0, "*flash");
02350 }
02351 i++;
02352 }
02353 if (i == MAX_WEAPONS)
02354 {
02355 assert(0);
02356 break;
02357 }
02358
02359 }
02360 }
02361 }
02362
02363
02364 void CG_ShutDownG2Weapons(void)
02365 {
02366 int i;
02367 for (i=0; i<MAX_WEAPONS; i++)
02368 {
02369 trap_G2API_CleanGhoul2Models(&g2WeaponInstances[i]);
02370 }
02371 }
02372
02373 void *CG_G2WeaponInstance(centity_t *cent, int weapon)
02374 {
02375 clientInfo_t *ci = NULL;
02376
02377 if (weapon != WP_SABER)
02378 {
02379 return g2WeaponInstances[weapon];
02380 }
02381
02382 if (cent->currentState.eType != ET_PLAYER &&
02383 cent->currentState.eType != ET_NPC)
02384 {
02385 return g2WeaponInstances[weapon];
02386 }
02387
02388 if (cent->currentState.eType == ET_NPC)
02389 {
02390 ci = cent->npcClient;
02391 }
02392 else
02393 {
02394 ci = &cgs.clientinfo[cent->currentState.number];
02395 }
02396
02397 if (!ci)
02398 {
02399 return g2WeaponInstances[weapon];
02400 }
02401
02402
02403 if (ci->saber[0].model[0] &&
02404 ci->ghoul2Weapons[0])
02405 {
02406 return ci->ghoul2Weapons[0];
02407 }
02408
02409
02410 return g2WeaponInstances[weapon];
02411 }
02412
02413
02414 void CG_CopyG2WeaponInstance(centity_t *cent, int weaponNum, void *toGhoul2)
02415 {
02416
02417 assert(weaponNum < MAX_WEAPONS);
02418 if (CG_G2WeaponInstance(cent, weaponNum))
02419 {
02420 if (weaponNum == WP_SABER)
02421 {
02422 clientInfo_t *ci = NULL;
02423
02424 if (cent->currentState.eType == ET_NPC)
02425 {
02426 ci = cent->npcClient;
02427 }
02428 else
02429 {
02430 ci = &cgs.clientinfo[cent->currentState.number];
02431 }
02432
02433 if (!ci)
02434 {
02435 trap_G2API_CopySpecificGhoul2Model(CG_G2WeaponInstance(cent, weaponNum), 0, toGhoul2, 1);
02436 }
02437 else
02438 {
02439 int i = 0;
02440
02441 while (i < MAX_SABERS)
02442 {
02443 if (ci->saber[i].model[0] &&
02444 ci->ghoul2Weapons[i])
02445 {
02446 trap_G2API_CopySpecificGhoul2Model(ci->ghoul2Weapons[i], 0, toGhoul2, i+1);
02447 }
02448 else if (ci->ghoul2Weapons[i])
02449 {
02450 qboolean g2HasSecondSaber = trap_G2API_HasGhoul2ModelOnIndex(&(toGhoul2), 2);
02451
02452 if (g2HasSecondSaber)
02453 {
02454 trap_G2API_RemoveGhoul2Model(&(toGhoul2), 2);
02455 }
02456 trap_G2API_CleanGhoul2Models(&ci->ghoul2Weapons[i]);
02457 }
02458
02459 i++;
02460 }
02461 }
02462 }
02463 else
02464 {
02465 qboolean g2HasSecondSaber = trap_G2API_HasGhoul2ModelOnIndex(&(toGhoul2), 2);
02466
02467 if (g2HasSecondSaber)
02468 {
02469 trap_G2API_RemoveGhoul2Model(&(toGhoul2), 2);
02470 }
02471
02472 if (weaponNum == WP_EMPLACED_GUN)
02473 {
02474 if (trap_G2API_HasGhoul2ModelOnIndex(&(toGhoul2), 1))
02475 {
02476 trap_G2API_RemoveGhoul2Model(&(toGhoul2), 1);
02477 }
02478 }
02479 else if (weaponNum == WP_MELEE)
02480 {
02481 if (trap_G2API_HasGhoul2ModelOnIndex(&(toGhoul2), 1))
02482 {
02483 trap_G2API_RemoveGhoul2Model(&(toGhoul2), 1);
02484 }
02485 }
02486 else
02487 {
02488 trap_G2API_CopySpecificGhoul2Model(CG_G2WeaponInstance(cent, weaponNum), 0, toGhoul2, 1);
02489 }
02490 }
02491 }
02492 }
02493
02494 void CG_CheckPlayerG2Weapons(playerState_t *ps, centity_t *cent)
02495 {
02496 if (!ps)
02497 {
02498 assert(0);
02499 return;
02500 }
02501
02502 if (ps->pm_flags & PMF_FOLLOW)
02503 {
02504 return;
02505 }
02506
02507 if (cent->currentState.eType == ET_NPC)
02508 {
02509 assert(0);
02510 return;
02511 }
02512
02513
02514 if (cent->currentState.saberInFlight)
02515 {
02516 cent->ghoul2weapon = CG_G2WeaponInstance(cent, WP_SABER);
02517 }
02518
02519 if (cent->currentState.eFlags & EF_DEAD)
02520 {
02521 cent->ghoul2weapon = NULL;
02522 return;
02523 }
02524
02525 if (cent->torsoBolt)
02526 {
02527 cent->ghoul2weapon = NULL;
02528 return;
02529 }
02530
02531 if (cgs.clientinfo[ps->clientNum].team == TEAM_SPECTATOR ||
02532 ps->persistant[PERS_TEAM] == TEAM_SPECTATOR)
02533 {
02534 cent->ghoul2weapon = cg_entities[ps->clientNum].ghoul2weapon = NULL;
02535 cent->weapon = cg_entities[ps->clientNum].weapon = 0;
02536 return;
02537 }
02538
02539 if (cent->ghoul2 && cent->ghoul2weapon != CG_G2WeaponInstance(cent, ps->weapon) &&
02540 ps->clientNum == cent->currentState.number)
02541 {
02542 CG_CopyG2WeaponInstance(cent, ps->weapon, cent->ghoul2);
02543 cent->ghoul2weapon = CG_G2WeaponInstance(cent, ps->weapon);
02544 if (cent->weapon == WP_SABER && cent->weapon != ps->weapon && !ps->saberHolstered)
02545 {
02546
02547 if (cgs.clientinfo[ps->clientNum].saber[0].soundOff && !ps->saberHolstered)
02548 {
02549 trap_S_StartSound(cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[0].soundOff);
02550 }
02551
02552 if (cgs.clientinfo[ps->clientNum].saber[1].soundOff &&
02553 cgs.clientinfo[ps->clientNum].saber[1].model[0] &&
02554 !ps->saberHolstered)
02555 {
02556 trap_S_StartSound(cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[1].soundOff);
02557 }
02558 }
02559 else if (ps->weapon == WP_SABER && cent->weapon != ps->weapon && !cent->saberWasInFlight)
02560 {
02561
02562 if (cgs.clientinfo[ps->clientNum].saber[0].soundOn)
02563 {
02564 trap_S_StartSound(cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[0].soundOn);
02565 }
02566
02567 if (cgs.clientinfo[ps->clientNum].saber[1].soundOn)
02568 {
02569 trap_S_StartSound(cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[1].soundOn);
02570 }
02571
02572 BG_SI_SetDesiredLength(&cgs.clientinfo[ps->clientNum].saber[0], 0, -1);
02573 BG_SI_SetDesiredLength(&cgs.clientinfo[ps->clientNum].saber[1], 0, -1);
02574 }
02575 cent->weapon = ps->weapon;
02576 }
02577 }
02578
02579
02580
02581
02582