00001 #include "b_local.h"
00002 #include "g_nav.h"
00003
00004
00005 #define MIN_DISTANCE 48
00006 #define MIN_DISTANCE_SQR ( MIN_DISTANCE * MIN_DISTANCE )
00007
00008 #define MAX_DISTANCE 1024
00009 #define MAX_DISTANCE_SQR ( MAX_DISTANCE * MAX_DISTANCE )
00010
00011 #define LSTATE_CLEAR 0
00012 #define LSTATE_WAITING 1
00013
00014 float enemyDist = 0;
00015
00016 void Wampa_SetBolts( gentity_t *self )
00017 {
00018 if ( self && self->client )
00019 {
00020 renderInfo_t *ri = &self->client->renderInfo;
00021 ri->headBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*head_eyes");
00022
00023
00024
00025 ri->torsoBolt = trap_G2API_AddBolt(self->ghoul2, 0, "lower_spine");
00026 ri->crotchBolt = trap_G2API_AddBolt(self->ghoul2, 0, "rear_bone");
00027
00028
00029 ri->handLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_hand");
00030 ri->handRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_hand");
00031
00032
00033 ri->footLBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*l_leg_foot");
00034 ri->footRBolt = trap_G2API_AddBolt(self->ghoul2, 0, "*r_leg_foot");
00035 }
00036 }
00037
00038
00039
00040
00041
00042
00043 void NPC_Wampa_Precache( void )
00044 {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 G_SoundIndex( "sound/chars/rancor/swipehit.wav" );
00057
00058 }
00059
00060
00061
00062
00063
00064
00065
00066 void Wampa_Idle( void )
00067 {
00068 NPCInfo->localState = LSTATE_CLEAR;
00069
00070
00071 if ( UpdateGoal() )
00072 {
00073 ucmd.buttons &= ~BUTTON_WALKING;
00074 NPC_MoveToGoal( qtrue );
00075 }
00076 }
00077
00078 qboolean Wampa_CheckRoar( gentity_t *self )
00079 {
00080 if ( self->wait < level.time )
00081 {
00082 self->wait = level.time + Q_irand( 5000, 20000 );
00083 NPC_SetAnim( self, SETANIM_BOTH, Q_irand(BOTH_GESTURE1,BOTH_GESTURE2), (SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD) );
00084 TIMER_Set( self, "rageTime", self->client->ps.legsTimer );
00085 return qtrue;
00086 }
00087 return qfalse;
00088 }
00089
00090
00091
00092
00093
00094 void Wampa_Patrol( void )
00095 {
00096 NPCInfo->localState = LSTATE_CLEAR;
00097
00098
00099 if ( UpdateGoal() )
00100 {
00101 ucmd.buttons |= BUTTON_WALKING;
00102 NPC_MoveToGoal( qtrue );
00103 }
00104 else
00105 {
00106 if ( TIMER_Done( NPC, "patrolTime" ))
00107 {
00108 TIMER_Set( NPC, "patrolTime", crandom() * 5000 + 5000 );
00109 }
00110 }
00111
00112 if ( NPC_CheckEnemyExt( qtrue ) == qfalse )
00113 {
00114 Wampa_Idle();
00115 return;
00116 }
00117 Wampa_CheckRoar( NPC );
00118 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00119 }
00120
00121
00122
00123
00124
00125
00126 void Wampa_Move( qboolean visible )
00127 {
00128 if ( NPCInfo->localState != LSTATE_WAITING )
00129 {
00130 NPCInfo->goalEntity = NPC->enemy;
00131
00132 if ( NPC->enemy )
00133 {
00134
00135 ucmd.buttons &= ~BUTTON_WALKING;
00136 if ( !TIMER_Done( NPC, "runfar" )
00137 || !TIMER_Done( NPC, "runclose" ) )
00138 {
00139 }
00140 else if ( !TIMER_Done( NPC, "walk" ) )
00141 {
00142 ucmd.buttons |= BUTTON_WALKING;
00143 }
00144 else if ( visible && enemyDist > 384 && NPCInfo->stats.runSpeed == 180 )
00145 {
00146 NPCInfo->stats.runSpeed = 300;
00147 TIMER_Set( NPC, "runfar", Q_irand( 2000, 4000 ) );
00148 }
00149 else if ( enemyDist > 256 && NPCInfo->stats.runSpeed == 300 )
00150 {
00151 NPCInfo->stats.runSpeed = 180;
00152 TIMER_Set( NPC, "runclose", Q_irand( 3000, 5000 ) );
00153 }
00154 else if ( enemyDist < 128 )
00155 {
00156 NPCInfo->stats.runSpeed = 180;
00157 ucmd.buttons |= BUTTON_WALKING;
00158 TIMER_Set( NPC, "walk", Q_irand( 4000, 6000 ) );
00159 }
00160 }
00161
00162 if ( NPCInfo->stats.runSpeed == 300 )
00163 {
00164 NPC->client->ps.eFlags2 |= EF2_USE_ALT_ANIM;
00165 }
00166 NPC_MoveToGoal( qtrue );
00167 NPCInfo->goalRadius = MAX_DISTANCE;
00168 }
00169 }
00170
00171
00172
00173 extern void G_Knockdown( gentity_t *victim );
00174 extern void G_Dismember( gentity_t *ent, gentity_t *enemy, vec3_t point, int limbType, float limbRollBase, float limbPitchBase, int deathAnim, qboolean postDeath );
00175 extern int NPC_GetEntsNearBolt( int *radiusEnts, float radius, int boltIndex, vec3_t boltOrg );
00176
00177 void Wampa_Slash( int boltIndex, qboolean backhand )
00178 {
00179 int radiusEntNums[128];
00180 int numEnts;
00181 const float radius = 88;
00182 const float radiusSquared = (radius*radius);
00183 int i;
00184 vec3_t boltOrg;
00185 int damage = (backhand)?Q_irand(10,15):Q_irand(20,30);
00186
00187 numEnts = NPC_GetEntsNearBolt( radiusEntNums, radius, boltIndex, boltOrg );
00188
00189 for ( i = 0; i < numEnts; i++ )
00190 {
00191 gentity_t *radiusEnt = &g_entities[radiusEntNums[i]];
00192 if ( !radiusEnt->inuse )
00193 {
00194 continue;
00195 }
00196
00197 if ( radiusEnt == NPC )
00198 {
00199 continue;
00200 }
00201
00202 if ( radiusEnt->client == NULL )
00203 {
00204 continue;
00205 }
00206
00207 if ( DistanceSquared( radiusEnt->r.currentOrigin, boltOrg ) <= radiusSquared )
00208 {
00209
00210 G_Damage( radiusEnt, NPC, NPC, vec3_origin, radiusEnt->r.currentOrigin, damage, ((backhand)?DAMAGE_NO_ARMOR:(DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK)), MOD_MELEE );
00211 if ( backhand )
00212 {
00213
00214 vec3_t pushDir;
00215 vec3_t angs;
00216 VectorCopy( NPC->client->ps.viewangles, angs );
00217 angs[YAW] += flrand( 25, 50 );
00218 angs[PITCH] = flrand( -25, -15 );
00219 AngleVectors( angs, pushDir, NULL, NULL );
00220 if ( radiusEnt->client->NPC_class != CLASS_WAMPA
00221 && radiusEnt->client->NPC_class != CLASS_RANCOR
00222 && radiusEnt->client->NPC_class != CLASS_ATST )
00223 {
00224 G_Throw( radiusEnt, pushDir, 65 );
00225 if ( BG_KnockDownable(&radiusEnt->client->ps) &&
00226 radiusEnt->health > 0 && Q_irand( 0, 1 ) )
00227 {
00228 radiusEnt->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
00229 radiusEnt->client->ps.forceDodgeAnim = 0;
00230 radiusEnt->client->ps.forceHandExtendTime = level.time + 1100;
00231 radiusEnt->client->ps.quickerGetup = qfalse;
00232 }
00233 }
00234 }
00235 else if ( radiusEnt->health <= 0 && radiusEnt->client )
00236 {
00237 if ( !Q_irand( 0, 1 ) )
00238 {
00239 int hitLoc = Q_irand( G2_MODELPART_HEAD, G2_MODELPART_RLEG );
00240 if ( hitLoc == G2_MODELPART_HEAD )
00241 {
00242 NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_DEATH17, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00243 }
00244 else if ( hitLoc == G2_MODELPART_WAIST )
00245 {
00246 NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_DEATHBACKWARD2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00247 }
00248 G_Dismember( radiusEnt, NPC, radiusEnt->r.currentOrigin, hitLoc, 90, 0, radiusEnt->client->ps.torsoAnim, qtrue);
00249 }
00250 }
00251 else if ( !Q_irand( 0, 3 ) && radiusEnt->health > 0 )
00252 {
00253 vec3_t pushDir;
00254 vec3_t angs;
00255 VectorCopy( NPC->client->ps.viewangles, angs );
00256 angs[YAW] += flrand( 25, 50 );
00257 angs[PITCH] = flrand( -25, -15 );
00258 AngleVectors( angs, pushDir, NULL, NULL );
00259 G_Knockdown( radiusEnt );
00260 }
00261 G_Sound( radiusEnt, CHAN_WEAPON, G_SoundIndex( "sound/chars/rancor/swipehit.wav" ) );
00262 }
00263 }
00264 }
00265
00266
00267 void Wampa_Attack( float distance, qboolean doCharge )
00268 {
00269 if ( !TIMER_Exists( NPC, "attacking" ) )
00270 {
00271 if ( Q_irand(0, 2) && !doCharge )
00272 {
00273 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00274 TIMER_Set( NPC, "attack_dmg", 750 );
00275 }
00276 else if ( doCharge || (distance > 270 && distance < 430 && !Q_irand(0, 1)) )
00277 {
00278 vec3_t fwd, yawAng;
00279 VectorSet( yawAng, 0, NPC->client->ps.viewangles[YAW], 0 );
00280 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00281 TIMER_Set( NPC, "attack_dmg", 500 );
00282 AngleVectors( yawAng, fwd, NULL, NULL );
00283 VectorScale( fwd, distance*1.5f, NPC->client->ps.velocity );
00284 NPC->client->ps.velocity[2] = 150;
00285 NPC->client->ps.groundEntityNum = ENTITYNUM_NONE;
00286 }
00287 else
00288 {
00289 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK3, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00290 TIMER_Set( NPC, "attack_dmg", 250 );
00291 }
00292
00293 TIMER_Set( NPC, "attacking", NPC->client->ps.legsTimer + random() * 200 );
00294
00295 TIMER_Set( NPC, "runfar", -1 );
00296 TIMER_Set( NPC, "runclose", -1 );
00297 TIMER_Set( NPC, "walk", -1 );
00298 }
00299
00300
00301
00302 if ( TIMER_Done2( NPC, "attack_dmg", qtrue ) )
00303 {
00304 switch ( NPC->client->ps.legsAnim )
00305 {
00306 case BOTH_ATTACK1:
00307 Wampa_Slash( NPC->client->renderInfo.handRBolt, qfalse );
00308
00309 TIMER_Set( NPC, "attack_dmg2", 100 );
00310 break;
00311 case BOTH_ATTACK2:
00312 Wampa_Slash( NPC->client->renderInfo.handRBolt, qfalse );
00313 TIMER_Set( NPC, "attack_dmg2", 100 );
00314 break;
00315 case BOTH_ATTACK3:
00316 Wampa_Slash( NPC->client->renderInfo.handLBolt, qtrue );
00317 break;
00318 }
00319 }
00320 else if ( TIMER_Done2( NPC, "attack_dmg2", qtrue ) )
00321 {
00322 switch ( NPC->client->ps.legsAnim )
00323 {
00324 case BOTH_ATTACK1:
00325 Wampa_Slash( NPC->client->renderInfo.handLBolt, qfalse );
00326 break;
00327 case BOTH_ATTACK2:
00328 Wampa_Slash( NPC->client->renderInfo.handLBolt, qfalse );
00329 break;
00330 }
00331 }
00332
00333
00334 TIMER_Done2( NPC, "attacking", qtrue );
00335
00336 if ( NPC->client->ps.legsAnim == BOTH_ATTACK1 && distance > (NPC->r.maxs[0]+MIN_DISTANCE) )
00337 {
00338 ucmd.buttons |= BUTTON_WALKING;
00339 Wampa_Move( 1 );
00340 }
00341 }
00342
00343
00344 void Wampa_Combat( void )
00345 {
00346
00347 if ( !NPC_ClearLOS( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) )
00348 {
00349 if ( !Q_irand( 0, 10 ) )
00350 {
00351 if ( Wampa_CheckRoar( NPC ) )
00352 {
00353 return;
00354 }
00355 }
00356 NPCInfo->combatMove = qtrue;
00357 NPCInfo->goalEntity = NPC->enemy;
00358 NPCInfo->goalRadius = MAX_DISTANCE;
00359
00360 Wampa_Move( 0 );
00361 return;
00362 }
00363 else if ( UpdateGoal() )
00364 {
00365 NPCInfo->combatMove = qtrue;
00366 NPCInfo->goalEntity = NPC->enemy;
00367 NPCInfo->goalRadius = MAX_DISTANCE;
00368
00369 Wampa_Move( 1 );
00370 return;
00371 }
00372 else
00373 {
00374 float distance = enemyDist = Distance( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );
00375 qboolean advance = (qboolean)( distance > (NPC->r.maxs[0]+MIN_DISTANCE) ? qtrue : qfalse );
00376 qboolean doCharge = qfalse;
00377
00378
00379
00380 NPC_FaceEnemy( qtrue );
00381
00382
00383 if ( advance )
00384 {
00385 vec3_t yawOnlyAngles;
00386 VectorSet( yawOnlyAngles, 0, NPC->r.currentAngles[YAW], 0 );
00387 if ( NPC->enemy->health > 0
00388 && fabs(distance-350) <= 80
00389 && InFOV3( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, yawOnlyAngles, 20, 20 ) )
00390 {
00391 if ( !Q_irand( 0, 9 ) )
00392 {
00393 doCharge = qtrue;
00394 advance = qfalse;
00395 }
00396 }
00397 }
00398
00399 if (( advance || NPCInfo->localState == LSTATE_WAITING ) && TIMER_Done( NPC, "attacking" ))
00400 {
00401 if ( TIMER_Done2( NPC, "takingPain", qtrue ))
00402 {
00403 NPCInfo->localState = LSTATE_CLEAR;
00404 }
00405 else
00406 {
00407 Wampa_Move( 1 );
00408 }
00409 }
00410 else
00411 {
00412 if ( !Q_irand( 0, 20 ) )
00413 {
00414 if ( Wampa_CheckRoar( NPC ) )
00415 {
00416 return;
00417 }
00418 }
00419 if ( !Q_irand( 0, 1 ) )
00420 {
00421 Wampa_Attack( distance, doCharge );
00422 }
00423 }
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433 void NPC_Wampa_Pain( gentity_t *self, gentity_t *attacker, int damage )
00434 {
00435 qboolean hitByWampa = qfalse;
00436 if ( attacker&&attacker->client&&attacker->client->NPC_class==CLASS_WAMPA )
00437 {
00438 hitByWampa = qtrue;
00439 }
00440 if ( attacker
00441 && attacker->inuse
00442 && attacker != self->enemy
00443 && !(attacker->flags&FL_NOTARGET) )
00444 {
00445 if ( (!attacker->s.number&&!Q_irand(0,3))
00446 || !self->enemy
00447 || self->enemy->health == 0
00448 || (self->enemy->client&&self->enemy->client->NPC_class == CLASS_WAMPA)
00449 || (!Q_irand(0, 4 ) && DistanceSquared( attacker->r.currentOrigin, self->r.currentOrigin ) < DistanceSquared( self->enemy->r.currentOrigin, self->r.currentOrigin )) )
00450 {
00451
00452 G_SetEnemy( self, attacker );
00453 TIMER_Set( self, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00454 if ( hitByWampa )
00455 {
00456 TIMER_Set( self, "wampaInfight", Q_irand( 2000, 5000 ) );
00457 }
00458 }
00459 }
00460 if ( (hitByWampa|| Q_irand( 0, 100 ) < damage )
00461 && self->client->ps.legsAnim != BOTH_GESTURE1
00462 && self->client->ps.legsAnim != BOTH_GESTURE2
00463 && TIMER_Done( self, "takingPain" ) )
00464 {
00465 if ( !Wampa_CheckRoar( self ) )
00466 {
00467 if ( self->client->ps.legsAnim != BOTH_ATTACK1
00468 && self->client->ps.legsAnim != BOTH_ATTACK2
00469 && self->client->ps.legsAnim != BOTH_ATTACK3 )
00470 {
00471 if ( self->health > 100 || hitByWampa )
00472 {
00473 TIMER_Remove( self, "attacking" );
00474
00475 VectorCopy( self->NPC->lastPathAngles, self->s.angles );
00476
00477 if ( !Q_irand( 0, 1 ) )
00478 {
00479 NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00480 }
00481 else
00482 {
00483 NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
00484 }
00485 TIMER_Set( self, "takingPain", self->client->ps.legsTimer+Q_irand(0, 500) );
00486
00487 TIMER_Set( self, "runfar", -1 );
00488 TIMER_Set( self, "runclose", -1 );
00489 TIMER_Set( self, "walk", -1 );
00490
00491 if ( self->NPC )
00492 {
00493 self->NPC->localState = LSTATE_WAITING;
00494 }
00495 }
00496 }
00497 }
00498 }
00499 }
00500
00501
00502
00503
00504
00505
00506 void NPC_BSWampa_Default( void )
00507 {
00508 NPC->client->ps.eFlags2 &= ~EF2_USE_ALT_ANIM;
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 if ( !TIMER_Done( NPC, "rageTime" ) )
00522 {
00523 NPC_FaceEnemy( qtrue );
00524 return;
00525 }
00526 if ( NPC->enemy )
00527 {
00528 if ( !TIMER_Done(NPC,"attacking") )
00529 {
00530
00531 NPC_FaceEnemy( qtrue );
00532
00533 enemyDist = Distance( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );
00534 Wampa_Attack( enemyDist, qfalse );
00535 return;
00536 }
00537 else
00538 {
00539 if ( TIMER_Done(NPC,"angrynoise") )
00540 {
00541 G_Sound( NPC, CHAN_VOICE, G_SoundIndex( va("sound/chars/wampa/misc/anger%d.wav", Q_irand(1, 2)) ) );
00542
00543 TIMER_Set( NPC, "angrynoise", Q_irand( 5000, 10000 ) );
00544 }
00545
00546 if( NPC->enemy->client && NPC->enemy->client->NPC_class == CLASS_WAMPA )
00547 {
00548 if ( TIMER_Done( NPC, "wampaInfight" ) )
00549 {
00550 NPC_CheckEnemyExt( qtrue );
00551 }
00552 }
00553 else
00554 {
00555 if ( ValidEnemy( NPC->enemy ) == qfalse )
00556 {
00557 TIMER_Remove( NPC, "lookForNewEnemy" );
00558 if ( !NPC->enemy->inuse || level.time - NPC->enemy->s.time > Q_irand( 10000, 15000 ) )
00559 {
00560 NPC->enemy = NULL;
00561 Wampa_Patrol();
00562 NPC_UpdateAngles( qtrue, qtrue );
00563
00564 if ( (NPC->spawnflags&2) )
00565 {
00566 NPC_BSSearchStart( NPC->waypoint, BS_SEARCH );
00567 NPCInfo->tempBehavior = BS_DEFAULT;
00568 }
00569 else if ( (NPC->spawnflags&1) )
00570 {
00571 NPC_BSSearchStart( NPC->waypoint, BS_WANDER );
00572 NPCInfo->tempBehavior = BS_DEFAULT;
00573 }
00574 return;
00575 }
00576 }
00577 if ( TIMER_Done( NPC, "lookForNewEnemy" ) )
00578 {
00579 gentity_t *newEnemy, *sav_enemy = NPC->enemy;
00580 NPC->enemy = NULL;
00581 newEnemy = NPC_CheckEnemy( NPCInfo->confusionTime < level.time, qfalse, qfalse );
00582 NPC->enemy = sav_enemy;
00583 if ( newEnemy && newEnemy != sav_enemy )
00584 {
00585 NPC->lastEnemy = NPC->enemy;
00586 G_SetEnemy( NPC, newEnemy );
00587
00588 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00589 }
00590 else
00591 {
00592 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 2000, 5000 ) );
00593 }
00594 }
00595 }
00596 Wampa_Combat();
00597 return;
00598 }
00599 }
00600 else
00601 {
00602 if ( TIMER_Done(NPC,"idlenoise") )
00603 {
00604 G_Sound( NPC, CHAN_AUTO, G_SoundIndex( "sound/chars/wampa/misc/anger3.wav" ) );
00605
00606 TIMER_Set( NPC, "idlenoise", Q_irand( 2000, 4000 ) );
00607 }
00608 if ( (NPC->spawnflags&2) )
00609 {
00610 if ( NPCInfo->homeWp == WAYPOINT_NONE )
00611 {
00612 NPC_BSSearchStart( WAYPOINT_NONE, BS_SEARCH );
00613 NPCInfo->tempBehavior = BS_DEFAULT;
00614 }
00615 ucmd.buttons |= BUTTON_WALKING;
00616 NPC_BSSearch();
00617 }
00618 else if ( (NPC->spawnflags&1) )
00619 {
00620 if ( NPCInfo->homeWp == WAYPOINT_NONE )
00621 {
00622 NPC_BSSearchStart( WAYPOINT_NONE, BS_WANDER );
00623 NPCInfo->tempBehavior = BS_DEFAULT;
00624 }
00625 ucmd.buttons |= BUTTON_WALKING;
00626 NPC_BSWander();
00627 if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00628 {
00629 if ( NPC_CheckEnemyExt( qtrue ) == qfalse )
00630 {
00631 Wampa_Idle();
00632 }
00633 else
00634 {
00635 Wampa_CheckRoar( NPC );
00636 TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00637 }
00638 }
00639 }
00640 else
00641 {
00642 if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00643 {
00644 Wampa_Patrol();
00645 }
00646 else
00647 {
00648 Wampa_Idle();
00649 }
00650 }
00651 }
00652
00653 NPC_UpdateAngles( qtrue, qtrue );
00654 }