00001
00002
00003
00004
00005
00006 #include "q_shared.h"
00007 #include "bg_public.h"
00008 #include "bg_local.h"
00009 #include "bg_strap.h"
00010 #include "../ghoul2/G2.h"
00011
00012 #ifdef QAGAME
00013 #include "g_local.h"
00014 #endif
00015
00016 #define MAX_WEAPON_CHARGE_TIME 5000
00017
00018 #ifdef QAGAME
00019 extern void G_CheapWeaponFire(int entNum, int ev);
00020 extern qboolean TryGrapple(gentity_t *ent);
00021 extern void trap_FX_PlayEffect( const char *file, vec3_t org, vec3_t fwd, int vol, int rad );
00022 #endif
00023
00024 #include "../namespace_begin.h"
00025 extern qboolean BG_FullBodyTauntAnim( int anim );
00026 extern float PM_WalkableGroundDistance(void);
00027 extern qboolean PM_GroundSlideOkay( float zNormal );
00028 extern saberInfo_t *BG_MySaber( int clientNum, int saberNum );
00029
00030 pmove_t *pm;
00031 pml_t pml;
00032
00033 bgEntity_t *pm_entSelf = NULL;
00034 bgEntity_t *pm_entVeh = NULL;
00035
00036 qboolean gPMDoSlowFall = qfalse;
00037
00038 qboolean pm_cancelOutZoom = qfalse;
00039
00040
00041 float pm_stopspeed = 100.0f;
00042 float pm_duckScale = 0.50f;
00043 float pm_swimScale = 0.50f;
00044 float pm_wadeScale = 0.70f;
00045
00046 float pm_vehicleaccelerate = 36.0f;
00047 float pm_accelerate = 10.0f;
00048 float pm_airaccelerate = 1.0f;
00049 float pm_wateraccelerate = 4.0f;
00050 float pm_flyaccelerate = 8.0f;
00051
00052 float pm_friction = 6.0f;
00053 float pm_waterfriction = 1.0f;
00054 float pm_flightfriction = 3.0f;
00055 float pm_spectatorfriction = 5.0f;
00056
00057 int c_pmove = 0;
00058
00059 float forceSpeedLevels[4] =
00060 {
00061 1,
00062 1.25,
00063 1.5,
00064 1.75
00065 };
00066
00067 int forcePowerNeeded[NUM_FORCE_POWER_LEVELS][NUM_FORCE_POWERS] =
00068 {
00069 {
00070 999,
00071 999,
00072 999,
00073 999,
00074 999,
00075 999,
00076 999,
00077 999,
00078 999,
00079 999,
00080 999,
00081 999,
00082 999,
00083 999,
00084 999,
00085 999,
00086 999,
00087 999
00088
00089 },
00090 {
00091 65,
00092 10,
00093 50,
00094 20,
00095 20,
00096 20,
00097 30,
00098 1,
00099 50,
00100 50,
00101 50,
00102 50,
00103 50,
00104 20,
00105 20,
00106 0,
00107 2,
00108 20
00109
00110 },
00111 {
00112 60,
00113 10,
00114 50,
00115 20,
00116 20,
00117 20,
00118 30,
00119 1,
00120 50,
00121 25,
00122 25,
00123 33,
00124 33,
00125 20,
00126 20,
00127 0,
00128 1,
00129 20
00130
00131 },
00132 {
00133 50,
00134 10,
00135 50,
00136 20,
00137 20,
00138 20,
00139 60,
00140 1,
00141 50,
00142 10,
00143 10,
00144 25,
00145 25,
00146 20,
00147 20,
00148 0,
00149 0,
00150 20
00151
00152 }
00153 };
00154
00155 float forceJumpHeight[NUM_FORCE_POWER_LEVELS] =
00156 {
00157 32,
00158 96,
00159 192,
00160 384
00161 };
00162
00163 float forceJumpStrength[NUM_FORCE_POWER_LEVELS] =
00164 {
00165 JUMP_VELOCITY,
00166 420,
00167 590,
00168 840
00169 };
00170
00171
00172 bgEntity_t *PM_BGEntForNum( int num )
00173 {
00174 bgEntity_t *ent;
00175
00176 if (!pm)
00177 {
00178 assert(!"You cannot call PM_BGEntForNum outside of pm functions!");
00179 return NULL;
00180 }
00181
00182 if (!pm->baseEnt)
00183 {
00184 assert(!"Base entity address not set");
00185 return NULL;
00186 }
00187
00188 if (!pm->entSize)
00189 {
00190 assert(!"sizeof(ent) is 0, impossible (not set?)");
00191 return NULL;
00192 }
00193
00194 assert(num >= 0 && num < MAX_GENTITIES);
00195
00196 ent = (bgEntity_t *)((byte *)pm->baseEnt + pm->entSize*(num));
00197
00198 return ent;
00199 }
00200
00201 qboolean BG_SabersOff( playerState_t *ps )
00202 {
00203 if ( !ps->saberHolstered )
00204 {
00205 return qfalse;
00206 }
00207 if ( ps->fd.saberAnimLevelBase == SS_DUAL
00208 || ps->fd.saberAnimLevelBase == SS_STAFF )
00209 {
00210 if ( ps->saberHolstered < 2 )
00211 {
00212 return qfalse;
00213 }
00214 }
00215 return qtrue;
00216 }
00217
00218 qboolean BG_KnockDownable(playerState_t *ps)
00219 {
00220 if (!ps)
00221 {
00222 return qfalse;
00223 }
00224
00225 if (ps->m_iVehicleNum)
00226 {
00227 return qfalse;
00228 }
00229
00230 if (ps->emplacedIndex)
00231 {
00232 return qfalse;
00233 }
00234
00235
00236 return qtrue;
00237 }
00238
00239
00240 #ifndef __LCC__
00241 #define PM_INLINE ID_INLINE
00242 #else
00243 #define PM_INLINE //none
00244 #endif
00245
00246
00247 qboolean PM_INLINE PM_IsRocketTrooper(void)
00248 {
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 return qfalse;
00259 }
00260
00261 int PM_GetSaberStance(void)
00262 {
00263 int anim = BOTH_STAND2;
00264 saberInfo_t *saber1 = BG_MySaber( pm->ps->clientNum, 0 );
00265 saberInfo_t *saber2 = BG_MySaber( pm->ps->clientNum, 1 );
00266
00267 if (!pm->ps->saberEntityNum)
00268 {
00269 return BOTH_STAND1;
00270 }
00271
00272 if ( BG_SabersOff( pm->ps ) )
00273 {
00274 return BOTH_STAND1;
00275 }
00276
00277 if ( saber1
00278 && saber1->readyAnim != -1 )
00279 {
00280 return saber1->readyAnim;
00281 }
00282
00283 if ( saber2
00284 && saber2->readyAnim != -1 )
00285 {
00286 return saber2->readyAnim;
00287 }
00288
00289 if ( saber1
00290 && saber2
00291 && !pm->ps->saberHolstered )
00292 {
00293 return BOTH_SABERDUAL_STANCE;
00294 }
00295
00296 switch ( pm->ps->fd.saberAnimLevel )
00297 {
00298 case SS_DUAL:
00299 anim = BOTH_SABERDUAL_STANCE;
00300 break;
00301 case SS_STAFF:
00302 anim = BOTH_SABERSTAFF_STANCE;
00303 break;
00304 case SS_FAST:
00305 case SS_TAVION:
00306 anim = BOTH_SABERFAST_STANCE;
00307 break;
00308 case SS_STRONG:
00309 anim = BOTH_SABERSLOW_STANCE;
00310 break;
00311 case SS_NONE:
00312 case SS_MEDIUM:
00313 case SS_DESANN:
00314 default:
00315 anim = BOTH_STAND2;
00316 break;
00317 }
00318 return anim;
00319 }
00320
00321 qboolean PM_DoSlowFall(void)
00322 {
00323 if ( ( (pm->ps->legsAnim) == BOTH_WALL_RUN_RIGHT || (pm->ps->legsAnim) == BOTH_WALL_RUN_LEFT ) && pm->ps->legsTimer > 500 )
00324 {
00325 return qtrue;
00326 }
00327
00328 return qfalse;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 void PM_pitch_roll_for_slope( bgEntity_t *forwhom, vec3_t pass_slope, vec3_t storeAngles )
00347 {
00348 vec3_t slope;
00349 vec3_t nvf, ovf, ovr, startspot, endspot, new_angles = { 0, 0, 0 };
00350 float pitch, mod, dot;
00351
00352
00353 if( !pass_slope || VectorCompare( vec3_origin, pass_slope ) )
00354 {
00355 trace_t trace;
00356
00357 VectorCopy( pm->ps->origin, startspot );
00358 startspot[2] += pm->mins[2] + 4;
00359 VectorCopy( startspot, endspot );
00360 endspot[2] -= 300;
00361 pm->trace( &trace, pm->ps->origin, vec3_origin, vec3_origin, endspot, forwhom->s.number, MASK_SOLID );
00362
00363
00364
00365 if ( trace.fraction >= 1.0 )
00366 return;
00367
00368 if( !( &trace.plane ) )
00369 return;
00370
00371 if ( VectorCompare( vec3_origin, trace.plane.normal ) )
00372 return;
00373
00374 VectorCopy( trace.plane.normal, slope );
00375 }
00376 else
00377 {
00378 VectorCopy( pass_slope, slope );
00379 }
00380
00381 if ( forwhom->s.NPC_class == CLASS_VEHICLE )
00382 {
00383 Vehicle_t *pVeh = forwhom->m_pVehicle;
00384 vec3_t tempAngles;
00385
00386 tempAngles[PITCH] = tempAngles[ROLL] = 0;
00387 tempAngles[YAW] = pVeh->m_vOrientation[YAW];
00388 AngleVectors( tempAngles, ovf, ovr, NULL );
00389 }
00390 else
00391 {
00392 AngleVectors( pm->ps->viewangles, ovf, ovr, NULL );
00393 }
00394
00395 vectoangles( slope, new_angles );
00396 pitch = new_angles[PITCH] + 90;
00397 new_angles[ROLL] = new_angles[PITCH] = 0;
00398
00399 AngleVectors( new_angles, nvf, NULL, NULL );
00400
00401 mod = DotProduct( nvf, ovr );
00402
00403 if ( mod<0 )
00404 mod = -1;
00405 else
00406 mod = 1;
00407
00408 dot = DotProduct( nvf, ovf );
00409
00410 if ( storeAngles )
00411 {
00412 storeAngles[PITCH] = dot * pitch;
00413 storeAngles[ROLL] = ((1-Q_fabs(dot)) * pitch * mod);
00414 }
00415 else
00416 {
00417 float oldmins2;
00418
00419 pm->ps->viewangles[PITCH] = dot * pitch;
00420 pm->ps->viewangles[ROLL] = ((1-Q_fabs(dot)) * pitch * mod);
00421 oldmins2 = pm->mins[2];
00422 pm->mins[2] = -24 + 12 * fabs(pm->ps->viewangles[PITCH])/180.0f;
00423
00424 if ( oldmins2 > pm->mins[2] )
00425 {
00426
00427 pm->ps->origin[2] += (oldmins2 - pm->mins[2]);
00428
00429
00430 }
00431 }
00432
00433
00434
00435
00436
00437
00438
00439 }
00440
00441 #define FLY_NONE 0
00442 #define FLY_NORMAL 1
00443 #define FLY_VEHICLE 2
00444 #define FLY_HOVER 3
00445 static int pm_flying = FLY_NONE;
00446
00447 void PM_SetSpecialMoveValues (void)
00448 {
00449 bgEntity_t *pEnt;
00450
00451 if (pm->ps->clientNum < MAX_CLIENTS)
00452 {
00453 pm_flying = FLY_NONE;
00454 return;
00455 }
00456
00457
00458 pm_flying = FLY_NONE;
00459
00460 pEnt = pm_entSelf;
00461
00462 if ( pEnt )
00463 {
00464 if ( (pm->ps->eFlags2&EF2_FLYING) )
00465 {
00466 pm_flying = FLY_NORMAL;
00467 }
00468 else if ( pEnt->s.NPC_class == CLASS_VEHICLE )
00469 {
00470 if ( pEnt->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
00471 {
00472 pm_flying = FLY_VEHICLE;
00473 }
00474 else if ( pEnt->m_pVehicle->m_pVehicleInfo->hoverHeight > 0 )
00475 {
00476 pm_flying = FLY_HOVER;
00477 }
00478 }
00479 }
00480 }
00481
00482 static void PM_SetVehicleAngles( vec3_t normal )
00483 {
00484 bgEntity_t *pEnt = pm_entSelf;
00485 Vehicle_t *pVeh;
00486 vec3_t vAngles;
00487 float vehicleBankingSpeed;
00488 float pitchBias;
00489 int i;
00490
00491 if ( !pEnt || pEnt->s.NPC_class != CLASS_VEHICLE )
00492 {
00493 return;
00494 }
00495
00496 pVeh = pEnt->m_pVehicle;
00497
00498
00499 vehicleBankingSpeed = (pVeh->m_pVehicleInfo->bankingSpeed*32.0f)*pml.frametime;
00500
00501 if ( vehicleBankingSpeed <= 0
00502 || ( pVeh->m_pVehicleInfo->pitchLimit == 0 && pVeh->m_pVehicleInfo->rollLimit == 0 ) )
00503 {
00504 return;
00505 }
00506
00507
00508
00509
00510 if ( pVeh->m_pVehicleInfo->type == VH_FIGHTER )
00511 {
00512 pitchBias = 0.0f;
00513 }
00514 else
00515 {
00516
00517
00518 pitchBias = 90.0f*pVeh->m_pVehicleInfo->centerOfGravity[0];
00519 }
00520
00521 VectorClear( vAngles );
00522 if ( pm->waterlevel > 0 )
00523 {
00524
00525
00526 vAngles[PITCH] += (pm->ps->viewangles[PITCH]-vAngles[PITCH])*0.75f + (pitchBias*0.5);
00527 }
00528 else if ( normal )
00529 {
00530 PM_pitch_roll_for_slope( pEnt, normal, vAngles );
00531 if ( (pml.groundTrace.contents&(CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA)) )
00532 {
00533
00534
00535 vAngles[PITCH] += (pm->ps->viewangles[PITCH]-vAngles[PITCH])*0.5f + (pitchBias*0.5f);
00536 }
00537 }
00538 else
00539 {
00540
00541 vAngles[PITCH] = pm->ps->viewangles[PITCH]*0.5f + pitchBias;
00542
00543 vehicleBankingSpeed *= (0.125f*pml.frametime);
00544 }
00545
00546
00547 if ( pVeh->m_pVehicleInfo->rollLimit > 0 )
00548 {
00549
00550 vec3_t velocity;
00551 float speed;
00552 VectorCopy( pm->ps->velocity, velocity );
00553 velocity[2] = 0.0f;
00554 speed = VectorNormalize( velocity );
00555 if ( speed > 32.0f || speed < -32.0f )
00556 {
00557 vec3_t rt, tempVAngles;
00558 float side;
00559 float dp;
00560
00561
00562
00563 speed *= sin( (150 + pml.frametime) * 0.003 );
00564
00565
00566 if ( speed > 60 )
00567 speed = 60;
00568
00569 VectorCopy( pVeh->m_vOrientation, tempVAngles );
00570 tempVAngles[ROLL] = 0;
00571 AngleVectors( tempVAngles, NULL, rt, NULL );
00572 dp = DotProduct( velocity, rt );
00573 side = speed * dp;
00574 vAngles[ROLL] -= side;
00575 }
00576 }
00577
00578
00579 if ( pVeh->m_pVehicleInfo->pitchLimit != -1 )
00580 {
00581 if ( vAngles[PITCH] > pVeh->m_pVehicleInfo->pitchLimit )
00582 {
00583 vAngles[PITCH] = pVeh->m_pVehicleInfo->pitchLimit;
00584 }
00585 else if ( vAngles[PITCH] < -pVeh->m_pVehicleInfo->pitchLimit )
00586 {
00587 vAngles[PITCH] = -pVeh->m_pVehicleInfo->pitchLimit;
00588 }
00589 }
00590
00591 if ( vAngles[ROLL] > pVeh->m_pVehicleInfo->rollLimit )
00592 {
00593 vAngles[ROLL] = pVeh->m_pVehicleInfo->rollLimit;
00594 }
00595 else if ( vAngles[ROLL] < -pVeh->m_pVehicleInfo->rollLimit )
00596 {
00597 vAngles[ROLL] = -pVeh->m_pVehicleInfo->rollLimit;
00598 }
00599
00600
00601 for ( i = 0; i < 3; i++ )
00602 {
00603 if ( i == YAW )
00604 {
00605 continue;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 {
00621 if ( pVeh->m_vOrientation[i] >= vAngles[i] + vehicleBankingSpeed )
00622 {
00623 pVeh->m_vOrientation[i] -= vehicleBankingSpeed;
00624 }
00625 else if ( pVeh->m_vOrientation[i] <= vAngles[i] - vehicleBankingSpeed )
00626 {
00627 pVeh->m_vOrientation[i] += vehicleBankingSpeed;
00628 }
00629 else
00630 {
00631 pVeh->m_vOrientation[i] = vAngles[i];
00632 }
00633 }
00634 }
00635 }
00636
00637 #ifndef QAGAME
00638 extern vmCvar_t cg_paused;
00639 #endif
00640
00641 void BG_ExternThisSoICanRecompileInDebug( Vehicle_t *pVeh, playerState_t *riderPS )
00642 {
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 }
00675
00676 void BG_VehicleTurnRateForSpeed( Vehicle_t *pVeh, float speed, float *mPitchOverride, float *mYawOverride )
00677 {
00678 if ( pVeh && pVeh->m_pVehicleInfo )
00679 {
00680 float speedFrac = 1.0f;
00681 if ( pVeh->m_pVehicleInfo->speedDependantTurning )
00682 {
00683 if ( pVeh->m_LandTrace.fraction >= 1.0f
00684 || pVeh->m_LandTrace.plane.normal[2] < MIN_LANDING_SLOPE )
00685 {
00686 speedFrac = (speed/(pVeh->m_pVehicleInfo->speedMax*0.75f));
00687 if ( speedFrac < 0.25f )
00688 {
00689 speedFrac = 0.25f;
00690 }
00691 else if ( speedFrac > 1.0f )
00692 {
00693 speedFrac = 1.0f;
00694 }
00695 }
00696 }
00697 if ( pVeh->m_pVehicleInfo->mousePitch )
00698 {
00699 *mPitchOverride = pVeh->m_pVehicleInfo->mousePitch*speedFrac;
00700 }
00701 if ( pVeh->m_pVehicleInfo->mouseYaw )
00702 {
00703 *mYawOverride = pVeh->m_pVehicleInfo->mouseYaw*speedFrac;
00704 }
00705 }
00706 }
00707
00708 #include "../namespace_end.h"
00709
00710
00711 #ifdef QAGAME
00712 typedef struct gentity_s gentity_t;
00713 gentity_t *G_PlayEffectID(const int fxID, vec3_t org, vec3_t ang);
00714 #endif
00715
00716 #include "../namespace_begin.h"
00717
00718 static void PM_GroundTraceMissed( void );
00719 void PM_HoverTrace( void )
00720 {
00721 Vehicle_t *pVeh;
00722 float hoverHeight;
00723 vec3_t point, vAng, fxAxis[3];
00724 trace_t *trace;
00725 float relativeWaterLevel;
00726
00727 bgEntity_t *pEnt = pm_entSelf;
00728 if ( !pEnt || pEnt->s.NPC_class != CLASS_VEHICLE )
00729 {
00730 return;
00731 }
00732
00733 pVeh = pEnt->m_pVehicle;
00734 hoverHeight = pVeh->m_pVehicleInfo->hoverHeight;
00735 trace = &pml.groundTrace;
00736
00737 pml.groundPlane = qfalse;
00738
00739
00740 relativeWaterLevel = pm->waterlevel;
00741 if ( pm->waterlevel && relativeWaterLevel >= 0 )
00742 {
00743 if ( pVeh->m_pVehicleInfo->bouyancy <= 0.0f )
00744 {
00745 }
00746 else
00747 {
00748 float floatHeight = (pVeh->m_pVehicleInfo->bouyancy * ((pm->maxs[2]-pm->mins[2])*0.5f)) - (hoverHeight*0.5f);
00749 if ( relativeWaterLevel > floatHeight )
00750 {
00751 pm->ps->velocity[2] += (relativeWaterLevel - floatHeight) * pVeh->m_fTimeModifier;
00752 }
00753 }
00754
00755 if (pm->waterlevel <= 1)
00756 {
00757 if ( fabs(pm->ps->velocity[0]) + fabs(pm->ps->velocity[1]) > 100 )
00758 {
00759 if ( Q_irand( pml.frametime, 100 ) >= 50 )
00760 {
00761 vec3_t wakeOrg;
00762
00763 vAng[PITCH] = vAng[ROLL] = 0;
00764 vAng[YAW] = pVeh->m_vOrientation[YAW];
00765 AngleVectors( vAng, fxAxis[2], fxAxis[1], fxAxis[0] );
00766 VectorCopy( pm->ps->origin, wakeOrg );
00767
00768 if (pm->waterlevel >= 2)
00769 {
00770 wakeOrg[2] = pm->ps->origin[2]+16;
00771 }
00772 else
00773 {
00774 wakeOrg[2] = pm->ps->origin[2];
00775 }
00776 #ifdef QAGAME //yeah, this is kind of crappy and makes no use of prediction whatsoever
00777 if ( pVeh->m_pVehicleInfo->iWakeFX )
00778 {
00779
00780
00781 G_AddEvent((gentity_t *)pEnt, EV_PLAY_EFFECT_ID, pVeh->m_pVehicleInfo->iWakeFX);
00782 }
00783 #endif
00784 }
00785 }
00786 }
00787 }
00788 else
00789 {
00790 int traceContents;
00791 float minNormal = (float)MIN_WALK_NORMAL;
00792 minNormal = pVeh->m_pVehicleInfo->maxSlope;
00793
00794 point[0] = pm->ps->origin[0];
00795 point[1] = pm->ps->origin[1];
00796 point[2] = pm->ps->origin[2] - hoverHeight;
00797
00798
00799
00800
00801
00802
00803 traceContents = pm->tracemask;
00804 if ( pVeh->m_pVehicleInfo->bouyancy >= 2.0f )
00805 {
00806 traceContents |= (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA);
00807 }
00808 pm->trace( trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, traceContents );
00809 if (trace->plane.normal[0] > 0.5f || trace->plane.normal[0] < -0.5f ||
00810 trace->plane.normal[1] > 0.5f || trace->plane.normal[1] < -0.5f)
00811 {
00812 float d = fabs(trace->plane.normal[0]);
00813 float e = fabs(trace->plane.normal[1]);
00814 if (e > d)
00815 {
00816 d = e;
00817 }
00818 pm->ps->velocity[2] = -300.0f*d;
00819 }
00820 else if ( trace->plane.normal[2] >= minNormal )
00821 {
00822 if ( trace->fraction < 1.0f )
00823 {
00824 float hoverForce = pVeh->m_pVehicleInfo->hoverStrength;
00825 if ( trace->fraction > 0.5f )
00826 {
00827 pm->ps->velocity[2] += (1.0f-trace->fraction)*hoverForce*pVeh->m_fTimeModifier;
00828 }
00829 else
00830 {
00831 pm->ps->velocity[2] += (0.5f-(trace->fraction*trace->fraction))*hoverForce*2.0f*pVeh->m_fTimeModifier;
00832 }
00833 if ( (trace->contents&(CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA)) )
00834 {
00835 if ( fabs(pm->ps->velocity[0]) + fabs(pm->ps->velocity[1]) > 100 )
00836 {
00837 if ( Q_irand( pml.frametime, 100 ) >= 50 )
00838 {
00839 vAng[PITCH] = vAng[ROLL] = 0;
00840 vAng[YAW] = pVeh->m_vOrientation[YAW];
00841 AngleVectors( vAng, fxAxis[2], fxAxis[1], fxAxis[0] );
00842 #ifdef QAGAME
00843 if ( pVeh->m_pVehicleInfo->iWakeFX )
00844 {
00845 G_PlayEffectID( pVeh->m_pVehicleInfo->iWakeFX, trace->endpos, fxAxis[0] );
00846 }
00847 #endif
00848 }
00849 }
00850 }
00851 pml.groundPlane = qtrue;
00852 }
00853 }
00854 }
00855 if ( pml.groundPlane )
00856 {
00857 PM_SetVehicleAngles( pml.groundTrace.plane.normal );
00858
00859 pVeh->m_ulFlags &= ~VEH_FLYING;
00860
00861 pVeh->m_vAngularVelocity = 0.0f;
00862 }
00863 else
00864 {
00865 PM_SetVehicleAngles( NULL );
00866
00867 pVeh->m_ulFlags |= VEH_FLYING;
00868
00869
00870 if (pVeh->m_vAngularVelocity==0.0f)
00871 {
00872 pVeh->m_vAngularVelocity = pVeh->m_vOrientation[YAW] - pVeh->m_vPrevOrientation[YAW];
00873 if (pVeh->m_vAngularVelocity<-15.0f)
00874 {
00875 pVeh->m_vAngularVelocity = -15.0f;
00876 }
00877 if (pVeh->m_vAngularVelocity> 15.0f)
00878 {
00879 pVeh->m_vAngularVelocity = 15.0f;
00880 }
00881 }
00882
00883 if (pVeh->m_vAngularVelocity > 0.0f)
00884 {
00885 pVeh->m_vAngularVelocity -= pml.frametime;
00886 if (pVeh->m_vAngularVelocity < 0.0f)
00887 {
00888 pVeh->m_vAngularVelocity = 0.0f;
00889 }
00890 }
00891 else if (pVeh->m_vAngularVelocity < 0.0f)
00892 {
00893 pVeh->m_vAngularVelocity += pml.frametime;
00894 if (pVeh->m_vAngularVelocity > 0.0f)
00895 {
00896 pVeh->m_vAngularVelocity = 0.0f;
00897 }
00898 }
00899 }
00900 PM_GroundTraceMissed();
00901 }
00902
00903
00904
00905
00906
00907
00908
00909
00910 void PM_AddEvent( int newEvent ) {
00911 BG_AddPredictableEventToPlayerstate( newEvent, 0, pm->ps );
00912 }
00913
00914 void PM_AddEventWithParm( int newEvent, int parm )
00915 {
00916 BG_AddPredictableEventToPlayerstate( newEvent, parm, pm->ps );
00917 }
00918
00919
00920
00921
00922
00923
00924 void PM_AddTouchEnt( int entityNum ) {
00925 int i;
00926
00927 if ( entityNum == ENTITYNUM_WORLD ) {
00928 return;
00929 }
00930 if ( pm->numtouch == MAXTOUCH ) {
00931 return;
00932 }
00933
00934
00935 for ( i = 0 ; i < pm->numtouch ; i++ ) {
00936 if ( pm->touchents[ i ] == entityNum ) {
00937 return;
00938 }
00939 }
00940
00941
00942 pm->touchents[pm->numtouch] = entityNum;
00943 pm->numtouch++;
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce ) {
00955 float backoff;
00956 float change;
00957 float oldInZ;
00958 int i;
00959
00960 if ( (pm->ps->pm_flags&PMF_STUCK_TO_WALL) )
00961 {
00962 VectorCopy( in, out );
00963 return;
00964 }
00965 oldInZ = in[2];
00966
00967 backoff = DotProduct (in, normal);
00968
00969 if ( backoff < 0 ) {
00970 backoff *= overbounce;
00971 } else {
00972 backoff /= overbounce;
00973 }
00974
00975 for ( i=0 ; i<3 ; i++ ) {
00976 change = normal[i]*backoff;
00977 out[i] = in[i] - change;
00978 }
00979 if ( pm->stepSlideFix )
00980 {
00981 if ( pm->ps->clientNum < MAX_CLIENTS
00982 && pm->ps->groundEntityNum != ENTITYNUM_NONE
00983 && normal[2] < MIN_WALK_NORMAL )
00984 {
00985 out[2] = oldInZ;
00986 }
00987 }
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 static void PM_Friction( void ) {
00999 vec3_t vec;
01000 float *vel;
01001 float speed, newspeed, control;
01002 float drop;
01003 bgEntity_t *pEnt = NULL;
01004
01005 vel = pm->ps->velocity;
01006
01007 VectorCopy( vel, vec );
01008 if ( pml.walking ) {
01009 vec[2] = 0;
01010 }
01011
01012 speed = VectorLength(vec);
01013 if (speed < 1) {
01014 vel[0] = 0;
01015 vel[1] = 0;
01016 if (pm->ps->pm_type == PM_SPECTATOR)
01017 {
01018 vel[2] = 0;
01019 }
01020
01021 return;
01022 }
01023
01024 drop = 0;
01025
01026 if (pm->ps->clientNum >= MAX_CLIENTS)
01027 {
01028 pEnt = pm_entSelf;
01029 }
01030
01031
01032 if (pm_flying != FLY_VEHICLE &&
01033 pEnt &&
01034 pEnt->s.NPC_class == CLASS_VEHICLE &&
01035 pEnt->m_pVehicle &&
01036 pEnt->m_pVehicle->m_pVehicleInfo->type != VH_ANIMAL &&
01037 pEnt->m_pVehicle->m_pVehicleInfo->type != VH_WALKER &&
01038 pEnt->m_pVehicle->m_pVehicleInfo->friction )
01039 {
01040 float friction = pEnt->m_pVehicle->m_pVehicleInfo->friction;
01041 if ( !(pm->ps->pm_flags & PMF_TIME_KNOCKBACK) )
01042 {
01043 control = speed < pm_stopspeed ? pm_stopspeed : speed;
01044 drop += control*friction*pml.frametime;
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066 }
01067 }
01068 else if ( pm_flying != FLY_NORMAL && pm_flying != FLY_VEHICLE )
01069 {
01070
01071 if ( pm->waterlevel <= 1 ) {
01072 if ( pml.walking && !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) {
01073
01074 if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) {
01075 control = speed < pm_stopspeed ? pm_stopspeed : speed;
01076 drop += control*pm_friction*pml.frametime;
01077 }
01078 }
01079 }
01080 }
01081
01082 if ( pm_flying == FLY_VEHICLE )
01083 {
01084 if ( !(pm->ps->pm_flags & PMF_TIME_KNOCKBACK) )
01085 {
01086 control = speed;
01087 drop += control*pm_friction*pml.frametime;
01088 }
01089 }
01090
01091
01092 if ( pm->waterlevel ) {
01093 drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime;
01094 }
01095
01096 else if ( pm->ps->groundEntityNum < MAX_CLIENTS )
01097 {
01098 drop = 0;
01099 }
01100
01101 if ( pm->ps->pm_type == PM_SPECTATOR || pm->ps->pm_type == PM_FLOAT )
01102 {
01103 if (pm->ps->pm_type == PM_FLOAT)
01104 {
01105 drop += speed*0.1*pml.frametime;
01106 }
01107 else
01108 {
01109 drop += speed*pm_spectatorfriction*pml.frametime;
01110 }
01111 }
01112
01113
01114 newspeed = speed - drop;
01115 if (newspeed < 0) {
01116 newspeed = 0;
01117 }
01118 newspeed /= speed;
01119
01120 vel[0] = vel[0] * newspeed;
01121 vel[1] = vel[1] * newspeed;
01122 vel[2] = vel[2] * newspeed;
01123 }
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 static void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel )
01134 {
01135 if (pm->gametype != GT_SIEGE
01136 || pm->ps->m_iVehicleNum
01137 || pm->ps->clientNum >= MAX_CLIENTS
01138 || pm->ps->pm_type != PM_NORMAL)
01139 {
01140 int i;
01141 float addspeed, accelspeed, currentspeed;
01142
01143 currentspeed = DotProduct (pm->ps->velocity, wishdir);
01144 addspeed = wishspeed - currentspeed;
01145 if (addspeed <= 0 && pm->ps->clientNum < MAX_CLIENTS) {
01146 return;
01147 }
01148
01149 if (addspeed < 0)
01150 {
01151 accelspeed = (-accel)*pml.frametime*wishspeed;
01152 if (accelspeed < addspeed) {
01153 accelspeed = addspeed;
01154 }
01155 }
01156 else
01157 {
01158 accelspeed = accel*pml.frametime*wishspeed;
01159 if (accelspeed > addspeed) {
01160 accelspeed = addspeed;
01161 }
01162 }
01163
01164 for (i=0 ; i<3 ; i++) {
01165 pm->ps->velocity[i] += accelspeed*wishdir[i];
01166 }
01167 }
01168 else
01169 {
01170 vec3_t wishVelocity;
01171 vec3_t pushDir;
01172 float pushLen;
01173 float canPush;
01174
01175 VectorScale( wishdir, wishspeed, wishVelocity );
01176 VectorSubtract( wishVelocity, pm->ps->velocity, pushDir );
01177 pushLen = VectorNormalize( pushDir );
01178
01179 canPush = accel*pml.frametime*wishspeed;
01180 if (canPush > pushLen) {
01181 canPush = pushLen;
01182 }
01183
01184 VectorMA( pm->ps->velocity, canPush, pushDir, pm->ps->velocity );
01185 }
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 static float PM_CmdScale( usercmd_t *cmd ) {
01200 int max;
01201 float total;
01202 float scale;
01203 int umove = 0;
01204
01205
01206 max = abs( cmd->forwardmove );
01207 if ( abs( cmd->rightmove ) > max ) {
01208 max = abs( cmd->rightmove );
01209 }
01210 if ( abs( umove ) > max ) {
01211 max = abs( umove );
01212 }
01213 if ( !max ) {
01214 return 0;
01215 }
01216
01217 total = sqrt( (float)(cmd->forwardmove * cmd->forwardmove
01218 + cmd->rightmove * cmd->rightmove + umove * umove) );
01219 scale = (float)pm->ps->speed * max / ( 127.0 * total );
01220
01221 return scale;
01222 }
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 static void PM_SetMovementDir( void ) {
01234 if ( pm->cmd.forwardmove || pm->cmd.rightmove ) {
01235 if ( pm->cmd.rightmove == 0 && pm->cmd.forwardmove > 0 ) {
01236 pm->ps->movementDir = 0;
01237 } else if ( pm->cmd.rightmove < 0 && pm->cmd.forwardmove > 0 ) {
01238 pm->ps->movementDir = 1;
01239 } else if ( pm->cmd.rightmove < 0 && pm->cmd.forwardmove == 0 ) {
01240 pm->ps->movementDir = 2;
01241 } else if ( pm->cmd.rightmove < 0 && pm->cmd.forwardmove < 0 ) {
01242 pm->ps->movementDir = 3;
01243 } else if ( pm->cmd.rightmove == 0 && pm->cmd.forwardmove < 0 ) {
01244 pm->ps->movementDir = 4;
01245 } else if ( pm->cmd.rightmove > 0 && pm->cmd.forwardmove < 0 ) {
01246 pm->ps->movementDir = 5;
01247 } else if ( pm->cmd.rightmove > 0 && pm->cmd.forwardmove == 0 ) {
01248 pm->ps->movementDir = 6;
01249 } else if ( pm->cmd.rightmove > 0 && pm->cmd.forwardmove > 0 ) {
01250 pm->ps->movementDir = 7;
01251 }
01252 } else {
01253
01254
01255
01256 if ( pm->ps->movementDir == 2 ) {
01257 pm->ps->movementDir = 1;
01258 } else if ( pm->ps->movementDir == 6 ) {
01259 pm->ps->movementDir = 7;
01260 }
01261 }
01262 }
01263
01264 #define METROID_JUMP 1
01265
01266 qboolean PM_ForceJumpingUp(void)
01267 {
01268 if ( !(pm->ps->fd.forcePowersActive&(1<<FP_LEVITATION)) && pm->ps->fd.forceJumpCharge )
01269 {
01270 return qfalse;
01271 }
01272
01273 if ( BG_InSpecialJump( pm->ps->legsAnim ) )
01274 {
01275 return qfalse;
01276 }
01277
01278 if (BG_SaberInSpecial(pm->ps->saberMove))
01279 {
01280 return qfalse;
01281 }
01282
01283 if (BG_SaberInSpecialAttack(pm->ps->legsAnim))
01284 {
01285 return qfalse;
01286 }
01287
01288 if (BG_HasYsalamiri(pm->gametype, pm->ps))
01289 {
01290 return qfalse;
01291 }
01292
01293 if (!BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION))
01294 {
01295 return qfalse;
01296 }
01297
01298 if ( pm->ps->groundEntityNum == ENTITYNUM_NONE &&
01299 (pm->ps->pm_flags & PMF_JUMP_HELD) &&
01300 pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 &&
01301 pm->ps->velocity[2] > 0 )
01302 {
01303 return qtrue;
01304 }
01305 return qfalse;
01306 }
01307
01308 static void PM_JumpForDir( void )
01309 {
01310 int anim = BOTH_JUMP1;
01311 if ( pm->cmd.forwardmove > 0 )
01312 {
01313 anim = BOTH_JUMP1;
01314 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
01315 }
01316 else if ( pm->cmd.forwardmove < 0 )
01317 {
01318 anim = BOTH_JUMPBACK1;
01319 pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
01320 }
01321 else if ( pm->cmd.rightmove > 0 )
01322 {
01323 anim = BOTH_JUMPRIGHT1;
01324 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
01325 }
01326 else if ( pm->cmd.rightmove < 0 )
01327 {
01328 anim = BOTH_JUMPLEFT1;
01329 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
01330 }
01331 else
01332 {
01333 anim = BOTH_JUMP1;
01334 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
01335 }
01336 if(!BG_InDeathAnim(pm->ps->legsAnim))
01337 {
01338 PM_SetAnim(SETANIM_LEGS,anim,SETANIM_FLAG_OVERRIDE, 100);
01339 }
01340 }
01341
01342 void PM_SetPMViewAngle(playerState_t *ps, vec3_t angle, usercmd_t *ucmd)
01343 {
01344 int i;
01345
01346 for (i=0 ; i<3 ; i++)
01347 {
01348 int cmdAngle;
01349
01350 cmdAngle = ANGLE2SHORT(angle[i]);
01351 ps->delta_angles[i] = cmdAngle - ucmd->angles[i];
01352 }
01353 VectorCopy (angle, ps->viewangles);
01354 }
01355
01356 qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean doMove )
01357 {
01358 if (( (ps->legsAnim) == BOTH_WALL_RUN_RIGHT || (ps->legsAnim) == BOTH_WALL_RUN_LEFT ) && ps->legsTimer > 500 )
01359 {
01360
01361 vec3_t fwd, rt, traceTo, mins, maxs, fwdAngles;
01362 trace_t trace;
01363 float dist, yawAdjust;
01364
01365 VectorSet(mins, -15, -15, 0);
01366 VectorSet(maxs, 15, 15, 24);
01367 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
01368
01369 AngleVectors( fwdAngles, fwd, rt, NULL );
01370 if ( (ps->legsAnim) == BOTH_WALL_RUN_RIGHT )
01371 {
01372 dist = 128;
01373 yawAdjust = -90;
01374 }
01375 else
01376 {
01377 dist = -128;
01378 yawAdjust = 90;
01379 }
01380 VectorMA( ps->origin, dist, rt, traceTo );
01381
01382 pm->trace( &trace, ps->origin, mins, maxs, traceTo, ps->clientNum, MASK_PLAYERSOLID );
01383
01384 if ( trace.fraction < 1.0f
01385 && (trace.plane.normal[2] >= 0.0f && trace.plane.normal[2] <= 0.4f) )
01386 {
01387 trace_t trace2;
01388 vec3_t traceTo2;
01389 vec3_t wallRunFwd, wallRunAngles;
01390
01391 VectorClear( wallRunAngles );
01392 wallRunAngles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust;
01393 AngleVectors( wallRunAngles, wallRunFwd, NULL, NULL );
01394
01395 VectorMA( pm->ps->origin, 32, wallRunFwd, traceTo2 );
01396 pm->trace( &trace2, pm->ps->origin, mins, maxs, traceTo2, pm->ps->clientNum, MASK_PLAYERSOLID );
01397 if ( trace2.fraction < 1.0f && DotProduct( trace2.plane.normal, wallRunFwd ) <= -0.999f )
01398 {
01399 trace.fraction = 1.0f;
01400 }
01401 }
01402
01403 if ( trace.fraction < 1.0f
01404 && (trace.plane.normal[2] >= 0.0f&&trace.plane.normal[2] <= 0.4f) )
01405 {
01406 if ( (ps->legsAnim) == BOTH_WALL_RUN_RIGHT )
01407 {
01408 ucmd->rightmove = 127;
01409 }
01410 else
01411 {
01412 ucmd->rightmove = -127;
01413 }
01414 if ( ucmd->upmove < 0 )
01415 {
01416 ucmd->upmove = 0;
01417 }
01418
01419 ps->viewangles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust;
01420
01421 PM_SetPMViewAngle(ps, ps->viewangles, ucmd);
01422
01423 ucmd->angles[YAW] = ANGLE2SHORT( ps->viewangles[YAW] ) - ps->delta_angles[YAW];
01424 if ( doMove )
01425 {
01426
01427 float zVel = ps->velocity[2];
01428 if ( ps->legsTimer > 500 )
01429 {
01430 float speed = 175;
01431 if ( ucmd->forwardmove < 0 )
01432 {
01433 speed = 100;
01434 }
01435 else if ( ucmd->forwardmove > 0 )
01436 {
01437 speed = 250;
01438 }
01439 VectorScale( fwd, speed, ps->velocity );
01440 }
01441 ps->velocity[2] = zVel;
01442
01443 VectorMA( ps->velocity, dist, rt, ps->velocity );
01444 }
01445 ucmd->forwardmove = 0;
01446 return qtrue;
01447 }
01448 else if ( doMove )
01449 {
01450 if ( (ps->legsAnim) == BOTH_WALL_RUN_RIGHT )
01451 {
01452 PM_SetAnim(SETANIM_BOTH, BOTH_WALL_RUN_RIGHT_STOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
01453 }
01454 else if ( (ps->legsAnim) == BOTH_WALL_RUN_LEFT )
01455 {
01456 PM_SetAnim(SETANIM_BOTH, BOTH_WALL_RUN_LEFT_STOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
01457 }
01458 }
01459 }
01460
01461 return qfalse;
01462 }
01463
01464 qboolean PM_AdjustAnglesForWallRunUpFlipAlt( usercmd_t *ucmd )
01465 {
01466
01467
01468 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, ucmd);
01469 return qtrue;
01470 }
01471
01472 qboolean PM_AdjustAngleForWallRunUp( playerState_t *ps, usercmd_t *ucmd, qboolean doMove )
01473 {
01474 if ( ps->legsAnim == BOTH_FORCEWALLRUNFLIP_START )
01475 {
01476
01477 vec3_t fwd, traceTo, mins, maxs, fwdAngles;
01478 trace_t trace;
01479 float dist = 128;
01480
01481 VectorSet(mins, -15,-15,0);
01482 VectorSet(maxs, 15,15,24);
01483 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
01484
01485 AngleVectors( fwdAngles, fwd, NULL, NULL );
01486 VectorMA( ps->origin, dist, fwd, traceTo );
01487 pm->trace( &trace, ps->origin, mins, maxs, traceTo, ps->clientNum, MASK_PLAYERSOLID );
01488 if ( trace.fraction > 0.5f )
01489 {
01490 trace_t trace2;
01491 vec3_t top, bottom;
01492
01493 VectorCopy( trace.endpos, top );
01494 top[2] += (pm->mins[2]*-1) + 4.0f;
01495 VectorCopy( top, bottom );
01496 bottom[2] -= 64.0f;
01497 pm->trace( &trace2, top, pm->mins, pm->maxs, bottom, ps->clientNum, MASK_PLAYERSOLID );
01498 if ( !trace2.allsolid
01499 && !trace2.startsolid
01500 && trace2.fraction < 1.0f
01501 && trace2.plane.normal[2] > 0.7f )
01502 {
01503 VectorScale( fwd, 100, pm->ps->velocity );
01504 pm->ps->velocity[2] += 400;
01505 PM_SetAnim(SETANIM_BOTH, BOTH_FORCEWALLRUNFLIP_ALT, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
01506 pm->ps->pm_flags |= PMF_JUMP_HELD;
01507
01508
01509
01510 PM_AddEvent(EV_JUMP);
01511 ucmd->upmove = 0;
01512 return qfalse;
01513 }
01514 }
01515
01516 if (
01517 ps->legsTimer > 0 &&
01518 ucmd->forwardmove > 0 &&
01519 trace.fraction < 1.0f &&
01520 (trace.plane.normal[2] >= 0.0f&&trace.plane.normal[2]<=0.4f) )
01521 {
01522
01523 trace_t trace2;
01524 VectorCopy( ps->origin, traceTo );
01525 traceTo[2] += 64;
01526 pm->trace( &trace2, ps->origin, mins, maxs, traceTo, ps->clientNum, MASK_PLAYERSOLID );
01527 if ( trace2.fraction < 1.0f )
01528 {
01529
01530 }
01531 else
01532 {
01533
01534
01535 ucmd->forwardmove = 127;
01536 if ( ucmd->upmove < 0 )
01537 {
01538 ucmd->upmove = 0;
01539 }
01540
01541 ps->viewangles[YAW] = vectoyaw( trace.plane.normal )+180;
01542 PM_SetPMViewAngle(ps, ps->viewangles, ucmd);
01543
01544
01545
01546
01547
01548
01549 ucmd->angles[YAW] = ANGLE2SHORT( ps->viewangles[YAW] ) - ps->delta_angles[YAW];
01550
01551 if (1)
01552 {
01553 if ( doMove )
01554 {
01555
01556 VectorScale( trace.plane.normal, -dist*trace.fraction, ps->velocity );
01557
01558 if ( ps->legsTimer > 200 )
01559 {
01560 float speed = 300;
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 ps->velocity[2] = speed;
01572 }
01573 }
01574 }
01575 ucmd->forwardmove = 0;
01576 return qtrue;
01577 }
01578 }
01579
01580 if ( doMove )
01581 {
01582 VectorScale( fwd, -300.0f, ps->velocity );
01583 ps->velocity[2] += 200;
01584
01585
01586 PM_SetAnim(SETANIM_BOTH, BOTH_FORCEWALLRUNFLIP_END, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
01587 ps->pm_flags |= PMF_JUMP_HELD;
01588
01589
01590
01591
01592 PM_AddEvent(EV_JUMP);
01593 ucmd->upmove = 0;
01594
01595 }
01596 }
01597 return qfalse;
01598 }
01599
01600 #define JUMP_OFF_WALL_SPEED 200.0f
01601
01602 static float BG_ForceWallJumpStrength( void )
01603 {
01604 return (forceJumpStrength[FORCE_LEVEL_3]/2.5f);
01605 }
01606
01607 qboolean PM_AdjustAngleForWallJump( playerState_t *ps, usercmd_t *ucmd, qboolean doMove )
01608 {
01609 if ( ( ( BG_InReboundJump( ps->legsAnim ) || BG_InReboundHold( ps->legsAnim ) )
01610 && ( BG_InReboundJump( ps->torsoAnim ) || BG_InReboundHold( ps->torsoAnim ) ) )
01611 || (pm->ps->pm_flags&PMF_STUCK_TO_WALL) )
01612 {
01613
01614 vec3_t checkDir, traceTo, mins, maxs, fwdAngles;
01615 trace_t trace;
01616 float dist = 128.0f, yawAdjust;
01617
01618 VectorSet(mins, pm->mins[0],pm->mins[1],0);
01619 VectorSet(maxs, pm->maxs[0],pm->maxs[1],24);
01620 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
01621
01622 switch ( ps->legsAnim )
01623 {
01624 case BOTH_FORCEWALLREBOUND_RIGHT:
01625 case BOTH_FORCEWALLHOLD_RIGHT:
01626 AngleVectors( fwdAngles, NULL, checkDir, NULL );
01627 yawAdjust = -90;
01628 break;
01629 case BOTH_FORCEWALLREBOUND_LEFT:
01630 case BOTH_FORCEWALLHOLD_LEFT:
01631 AngleVectors( fwdAngles, NULL, checkDir, NULL );
01632 VectorScale( checkDir, -1, checkDir );
01633 yawAdjust = 90;
01634 break;
01635 case BOTH_FORCEWALLREBOUND_FORWARD:
01636 case BOTH_FORCEWALLHOLD_FORWARD:
01637 AngleVectors( fwdAngles, checkDir, NULL, NULL );
01638 yawAdjust = 180;
01639 break;
01640 case BOTH_FORCEWALLREBOUND_BACK:
01641 case BOTH_FORCEWALLHOLD_BACK:
01642 AngleVectors( fwdAngles, checkDir, NULL, NULL );
01643 VectorScale( checkDir, -1, checkDir );
01644 yawAdjust = 0;
01645 break;
01646 default:
01647
01648 pm->ps->pm_flags &= ~PMF_STUCK_TO_WALL;
01649 return qfalse;
01650 break;
01651 }
01652 if ( pm->debugMelee )
01653 {
01654 if ( ucmd->upmove > 0 )
01655 {
01656 if ( BG_InReboundHold( ps->legsAnim ) )
01657 {
01658 if ( ps->legsTimer < 150 )
01659 {
01660 ps->legsTimer = 150;
01661 }
01662 }
01663 else
01664 {
01665 if ( ps->legsTimer <= 300 )
01666 {
01667 ps->saberHolstered = 2;
01668 PM_SetAnim( SETANIM_BOTH, BOTH_FORCEWALLRELEASE_FORWARD+(ps->legsAnim-BOTH_FORCEWALLHOLD_FORWARD), SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
01669 ps->legsTimer = ps->torsoTimer = 150;
01670 }
01671 }
01672 }
01673 }
01674 VectorMA( ps->origin, dist, checkDir, traceTo );
01675 pm->trace( &trace, ps->origin, mins, maxs, traceTo, ps->clientNum, MASK_PLAYERSOLID );
01676 if (
01677 ps->legsTimer > 100 &&
01678 trace.fraction < 1.0f &&
01679 fabs(trace.plane.normal[2]) <= 0.2f )
01680 {
01681
01682
01683
01684
01685
01686
01687
01688 if ( ucmd->upmove < 0 )
01689 {
01690 ucmd->upmove = 0;
01691 }
01692
01693 ps->viewangles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust;
01694 PM_SetPMViewAngle(ps, ps->viewangles, ucmd);
01695
01696
01697
01698
01699
01700
01701 ucmd->angles[YAW] = ANGLE2SHORT( ps->viewangles[YAW] ) - ps->delta_angles[YAW];
01702
01703 if (1)
01704 {
01705 if ( doMove )
01706 {
01707
01708 VectorScale( trace.plane.normal, -128.0f, ps->velocity );
01709 }
01710 }
01711 ucmd->upmove = 0;
01712 ps->pm_flags |= PMF_STUCK_TO_WALL;
01713 return qtrue;
01714 }
01715 else if ( doMove
01716 && (ps->pm_flags&PMF_STUCK_TO_WALL))
01717 {
01718
01719 ps->pm_flags &= ~PMF_STUCK_TO_WALL;
01720 ps->velocity[0] = ps->velocity[1] = 0;
01721 VectorScale( checkDir, -JUMP_OFF_WALL_SPEED, ps->velocity );
01722 ps->velocity[2] = BG_ForceWallJumpStrength();
01723 ps->pm_flags |= PMF_JUMP_HELD;
01724
01725 ps->fd.forceJumpSound = 1;
01726
01727 if (ps->origin[2] < ps->fd.forceJumpZStart)
01728 {
01729 ps->fd.forceJumpZStart = ps->origin[2];
01730 }
01731
01732
01733 BG_ForcePowerDrain( ps, FP_LEVITATION, 10 );
01734
01735 ps->pm_flags |= PMF_TIME_KNOCKBACK;
01736 ps->pm_time = 500;
01737 ucmd->forwardmove = 0;
01738 ucmd->rightmove = 0;
01739 ucmd->upmove = 127;
01740
01741 if ( BG_InReboundHold( ps->legsAnim ) )
01742 {
01743 PM_SetAnim( SETANIM_BOTH, BOTH_FORCEWALLRELEASE_FORWARD+(ps->legsAnim-BOTH_FORCEWALLHOLD_FORWARD), SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
01744 }
01745 else
01746 {
01747
01748 PM_SetAnim(SETANIM_LEGS,BOTH_FORCEJUMP1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART, 0);
01749 }
01750
01751
01752 }
01753 }
01754 ps->pm_flags &= ~PMF_STUCK_TO_WALL;
01755 return qfalse;
01756 }
01757
01758
01759 void PM_SetForceJumpZStart(float value)
01760 {
01761 pm->ps->fd.forceJumpZStart = value;
01762 if (!pm->ps->fd.forceJumpZStart)
01763 {
01764 pm->ps->fd.forceJumpZStart -= 0.1;
01765 }
01766 }
01767
01768 float forceJumpHeightMax[NUM_FORCE_POWER_LEVELS] =
01769 {
01770 66,
01771 130,
01772 226,
01773 418
01774 };
01775
01776 void PM_GrabWallForJump( int anim )
01777 {
01778 PM_SetAnim( SETANIM_BOTH, anim, SETANIM_FLAG_RESTART|SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
01779 PM_AddEvent( EV_JUMP );
01780 pm->ps->pm_flags |= PMF_STUCK_TO_WALL;
01781 }
01782
01783
01784
01785
01786
01787
01788 static qboolean PM_CheckJump( void )
01789 {
01790 qboolean allowFlips = qtrue;
01791
01792 if (pm->ps->clientNum >= MAX_CLIENTS)
01793 {
01794 bgEntity_t *pEnt = pm_entSelf;
01795
01796 if (pEnt->s.eType == ET_NPC &&
01797 pEnt->s.NPC_class == CLASS_VEHICLE)
01798 {
01799 return qfalse;
01800 }
01801 }
01802
01803 if (pm->ps->forceHandExtend == HANDEXTEND_KNOCKDOWN ||
01804 pm->ps->forceHandExtend == HANDEXTEND_PRETHROWN ||
01805 pm->ps->forceHandExtend == HANDEXTEND_POSTTHROWN)
01806 {
01807 return qfalse;
01808 }
01809
01810 if (pm->ps->pm_type == PM_JETPACK)
01811 {
01812 return qfalse;
01813 }
01814
01815
01816 if ( pm->ps->pm_flags & PMF_RESPAWNED ) {
01817 return qfalse;
01818 }
01819
01820 if ( PM_InKnockDown( pm->ps ) || BG_InRoll( pm->ps, pm->ps->legsAnim ) )
01821 {
01822 return qfalse;
01823 }
01824
01825 if ( pm->ps->weapon == WP_SABER )
01826 {
01827 saberInfo_t *saber1 = BG_MySaber( pm->ps->clientNum, 0 );
01828 saberInfo_t *saber2 = BG_MySaber( pm->ps->clientNum, 1 );
01829 if ( saber1
01830 && (saber1->saberFlags&SFL_NO_FLIPS) )
01831 {
01832 allowFlips = qfalse;
01833 }
01834 if ( saber2
01835 && (saber2->saberFlags&SFL_NO_FLIPS) )
01836 {
01837 allowFlips = qfalse;
01838 }
01839 }
01840
01841 if (pm->ps->groundEntityNum != ENTITYNUM_NONE || pm->ps->origin[2] < pm->ps->fd.forceJumpZStart)
01842 {
01843 pm->ps->fd.forcePowersActive &= ~(1<<FP_LEVITATION);
01844 }
01845
01846 if (pm->ps->fd.forcePowersActive & (1 << FP_LEVITATION))
01847 {
01848 if (pm->ps->fd.forcePowerDebounce[FP_LEVITATION] < pm->cmd.serverTime)
01849 {
01850 if ( pm->gametype == GT_DUEL
01851 || pm->gametype == GT_POWERDUEL )
01852 {
01853 BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 1 );
01854 }
01855 else
01856 {
01857 BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 );
01858 }
01859 if (pm->ps->fd.forcePowerLevel[FP_LEVITATION] >= FORCE_LEVEL_2)
01860 {
01861 pm->ps->fd.forcePowerDebounce[FP_LEVITATION] = pm->cmd.serverTime + 300;
01862 }
01863 else
01864 {
01865 pm->ps->fd.forcePowerDebounce[FP_LEVITATION] = pm->cmd.serverTime + 200;
01866 }
01867 }
01868 }
01869
01870 if (pm->ps->forceJumpFlip)
01871 {
01872 int anim = BOTH_FORCEINAIR1;
01873 int parts = SETANIM_BOTH;
01874 if ( allowFlips )
01875 {
01876 if ( pm->cmd.forwardmove > 0 )
01877 {
01878 anim = BOTH_FLIP_F;
01879 }
01880 else if ( pm->cmd.forwardmove < 0 )
01881 {
01882 anim = BOTH_FLIP_B;
01883 }
01884 else if ( pm->cmd.rightmove > 0 )
01885 {
01886 anim = BOTH_FLIP_R;
01887 }
01888 else if ( pm->cmd.rightmove < 0 )
01889 {
01890 anim = BOTH_FLIP_L;
01891 }
01892 }
01893 else
01894 {
01895 if ( pm->cmd.forwardmove > 0 )
01896 {
01897 anim = BOTH_FORCEINAIR1;
01898 }
01899 else if ( pm->cmd.forwardmove < 0 )
01900 {
01901 anim = BOTH_FORCEINAIRBACK1;
01902 }
01903 else if ( pm->cmd.rightmove > 0 )
01904 {
01905 anim = BOTH_FORCEINAIRRIGHT1;
01906 }
01907 else if ( pm->cmd.rightmove < 0 )
01908 {
01909 anim = BOTH_FORCEINAIRLEFT1;
01910 }
01911 }
01912 if ( pm->ps->weaponTime )
01913 {
01914 parts = SETANIM_LEGS;
01915 }
01916
01917 PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 );
01918 pm->ps->forceJumpFlip = qfalse;
01919 return qtrue;
01920 }
01921 #if METROID_JUMP
01922 if ( pm->waterlevel < 2 )
01923 {
01924 if ( pm->ps->gravity > 0 )
01925 {
01926 if ( PM_ForceJumpingUp() )
01927 {
01928 float curHeight = pm->ps->origin[2] - pm->ps->fd.forceJumpZStart;
01929
01930 if ( ( curHeight<=forceJumpHeight[0] ||
01931 (pm->ps->fd.forcePower&&pm->cmd.upmove>=10) ) &&
01932 curHeight < forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]] &&
01933 pm->ps->fd.forceJumpZStart)
01934 {
01935 if ( curHeight > forceJumpHeight[0] )
01936 {
01937 if ( !(pm->ps->fd.forcePowersActive&(1<<FP_LEVITATION)) )
01938 {
01939
01940 pm->ps->fd.forcePowersActive |= (1<<FP_LEVITATION);
01941 pm->ps->fd.forceJumpSound = 1;
01942
01943 if ((pm->cmd.forwardmove || pm->cmd.rightmove) &&
01944 (pm->ps->legsAnim) != BOTH_FLIP_F &&
01945 (pm->ps->legsAnim) != BOTH_FLIP_B &&
01946 (pm->ps->legsAnim) != BOTH_FLIP_R &&
01947 (pm->ps->legsAnim) != BOTH_FLIP_L
01948 && allowFlips )
01949 {
01950 int anim = BOTH_FORCEINAIR1;
01951 int parts = SETANIM_BOTH;
01952
01953 if ( pm->cmd.forwardmove > 0 )
01954 {
01955 anim = BOTH_FLIP_F;
01956 }
01957 else if ( pm->cmd.forwardmove < 0 )
01958 {
01959 anim = BOTH_FLIP_B;
01960 }
01961 else if ( pm->cmd.rightmove > 0 )
01962 {
01963 anim = BOTH_FLIP_R;
01964 }
01965 else if ( pm->cmd.rightmove < 0 )
01966 {
01967 anim = BOTH_FLIP_L;
01968 }
01969 if ( pm->ps->weaponTime )
01970 {
01971 parts = SETANIM_LEGS;
01972 }
01973
01974 PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 );
01975 }
01976 else if ( pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 )
01977 {
01978 vec3_t facingFwd, facingRight, facingAngles;
01979 int anim = -1;
01980 float dotR, dotF;
01981
01982 VectorSet(facingAngles, 0, pm->ps->viewangles[YAW], 0);
01983
01984 AngleVectors( facingAngles, facingFwd, facingRight, NULL );
01985 dotR = DotProduct( facingRight, pm->ps->velocity );
01986 dotF = DotProduct( facingFwd, pm->ps->velocity );
01987
01988 if ( fabs(dotR) > fabs(dotF) * 1.5 )
01989 {
01990 if ( dotR > 150 )
01991 {
01992 anim = BOTH_FORCEJUMPRIGHT1;
01993 }
01994 else if ( dotR < -150 )
01995 {
01996 anim = BOTH_FORCEJUMPLEFT1;
01997 }
01998 }
01999 else
02000 {
02001 if ( dotF > 150 )
02002 {
02003 anim = BOTH_FORCEJUMP1;
02004 }
02005 else if ( dotF < -150 )
02006 {
02007 anim = BOTH_FORCEJUMPBACK1;
02008 }
02009 }
02010 if ( anim != -1 )
02011 {
02012 int parts = SETANIM_BOTH;
02013 if ( pm->ps->weaponTime )
02014 {
02015 parts = SETANIM_LEGS;
02016 }
02017
02018 PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 );
02019 }
02020 }
02021 }
02022 else
02023 {
02024 if ( pm->ps->legsTimer < 1 )
02025 {
02026 int anim = (pm->ps->legsAnim);
02027 int newAnim = -1;
02028 switch ( anim )
02029 {
02030 case BOTH_FORCEJUMP1:
02031 newAnim = BOTH_FORCELAND1;
02032 break;
02033 case BOTH_FORCEJUMPBACK1:
02034 newAnim = BOTH_FORCELANDBACK1;
02035 break;
02036 case BOTH_FORCEJUMPLEFT1:
02037 newAnim = BOTH_FORCELANDLEFT1;
02038 break;
02039 case BOTH_FORCEJUMPRIGHT1:
02040 newAnim = BOTH_FORCELANDRIGHT1;
02041 break;
02042 }
02043 if ( newAnim != -1 )
02044 {
02045 int parts = SETANIM_BOTH;
02046 if ( pm->ps->weaponTime )
02047 {
02048 parts = SETANIM_LEGS;
02049 }
02050
02051 PM_SetAnim( parts, newAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 );
02052 }
02053 }
02054 }
02055 }
02056
02057
02058 pm->ps->velocity[2] = (forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]]-curHeight)/forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]]*forceJumpStrength[pm->ps->fd.forcePowerLevel[FP_LEVITATION]];
02059 pm->ps->velocity[2] /= 10;
02060 pm->ps->velocity[2] += JUMP_VELOCITY;
02061 pm->ps->pm_flags |= PMF_JUMP_HELD;
02062 }
02063 else if ( curHeight > forceJumpHeight[0] && curHeight < forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]] - forceJumpHeight[0] )
02064 {
02065 if ( pm->ps->velocity[2] > JUMP_VELOCITY )
02066 {
02067 pm->ps->velocity[2] = JUMP_VELOCITY;
02068 }
02069 }
02070 else
02071 {
02072
02073
02074
02075 if ( pm->ps->velocity[2] > JUMP_VELOCITY )
02076 {
02077 pm->ps->velocity[2] = JUMP_VELOCITY;
02078 }
02079 }
02080 pm->cmd.upmove = 0;
02081 return qfalse;
02082 }
02083 }
02084 }
02085
02086 #endif
02087
02088
02089 if ( pm->cmd.upmove < 10 && pm->ps->groundEntityNum != ENTITYNUM_NONE) {
02090 return qfalse;
02091 }
02092
02093
02094 if ( pm->ps->pm_flags & PMF_JUMP_HELD )
02095 {
02096
02097 pm->cmd.upmove = 0;
02098 return qfalse;
02099 }
02100
02101 if ( pm->ps->gravity <= 0 )
02102 {
02103 vec3_t forward, back;
02104 trace_t trace;
02105
02106 AngleVectors( pm->ps->viewangles, forward, NULL, NULL );
02107 VectorMA( pm->ps->origin, -8, forward, back );
02108 pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, back, pm->ps->clientNum, pm->tracemask );
02109
02110 if ( trace.fraction <= 1.0f )
02111 {
02112 VectorMA( pm->ps->velocity, JUMP_VELOCITY*2, forward, pm->ps->velocity );
02113 PM_SetAnim(SETANIM_LEGS,BOTH_FORCEJUMP1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART, 150);
02114 }
02115 pm->cmd.upmove = 0;
02116 }
02117 else if ( pm->cmd.upmove > 0 && pm->waterlevel < 2 &&
02118 pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 &&
02119 !(pm->ps->pm_flags&PMF_JUMP_HELD) &&
02120 (pm->ps->weapon == WP_SABER || pm->ps->weapon == WP_MELEE) &&
02121 !PM_IsRocketTrooper() &&
02122 !BG_HasYsalamiri(pm->gametype, pm->ps) &&
02123 BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION) )
02124 {
02125 qboolean allowWallRuns = qtrue;
02126 qboolean allowWallFlips = qtrue;
02127 qboolean allowFlips = qtrue;
02128 qboolean allowWallGrabs = qtrue;
02129 if ( pm->ps->weapon == WP_SABER )
02130 {
02131 saberInfo_t *saber1 = BG_MySaber( pm->ps->clientNum, 0 );
02132 saberInfo_t *saber2 = BG_MySaber( pm->ps->clientNum, 1 );
02133 if ( saber1
02134 && (saber1->saberFlags&SFL_NO_WALL_RUNS) )
02135 {
02136 allowWallRuns = qfalse;
02137 }
02138 if ( saber2
02139 && (saber2->saberFlags&SFL_NO_WALL_RUNS) )
02140 {
02141 allowWallRuns = qfalse;
02142 }
02143 if ( saber1
02144 && (saber1->saberFlags&SFL_NO_WALL_FLIPS) )
02145 {
02146 allowWallFlips = qfalse;
02147 }
02148 if ( saber2
02149 && (saber2->saberFlags&SFL_NO_WALL_FLIPS) )
02150 {
02151 allowWallFlips = qfalse;
02152 }
02153 if ( saber1
02154 && (saber1->saberFlags&SFL_NO_FLIPS) )
02155 {
02156 allowFlips = qfalse;
02157 }
02158 if ( saber2
02159 && (saber2->saberFlags&SFL_NO_FLIPS) )
02160 {
02161 allowFlips = qfalse;
02162 }
02163 if ( saber1
02164 && (saber1->saberFlags&SFL_NO_WALL_GRAB) )
02165 {
02166 allowWallGrabs = qfalse;
02167 }
02168 if ( saber2
02169 && (saber2->saberFlags&SFL_NO_WALL_GRAB) )
02170 {
02171 allowWallGrabs = qfalse;
02172 }
02173 }
02174
02175 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
02176 {
02177
02178 int anim = -1;
02179 float vertPush = 0;
02180 if ( pm->cmd.rightmove > 0 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 )
02181 {
02182 if ( pm->cmd.forwardmove > 0 )
02183 {
02184 if ( allowWallRuns )
02185 {
02186 vertPush = forceJumpStrength[FORCE_LEVEL_2]/2.0f;
02187 anim = BOTH_WALL_RUN_RIGHT;
02188 }
02189 }
02190 else if ( pm->cmd.forwardmove == 0 )
02191 {
02192 if ( allowWallFlips )
02193 {
02194 vertPush = forceJumpStrength[FORCE_LEVEL_2]/2.25f;
02195 anim = BOTH_WALL_FLIP_RIGHT;
02196 }
02197 }
02198 }
02199 else if ( pm->cmd.rightmove < 0 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 )
02200 {
02201 if ( pm->cmd.forwardmove > 0 )
02202 {
02203 if ( allowWallRuns )
02204 {
02205 vertPush = forceJumpStrength[FORCE_LEVEL_2]/2.0f;
02206 anim = BOTH_WALL_RUN_LEFT;
02207 }
02208 }
02209 else if ( pm->cmd.forwardmove == 0 )
02210 {
02211 if ( allowWallFlips )
02212 {
02213 vertPush = forceJumpStrength[FORCE_LEVEL_2]/2.25f;
02214 anim = BOTH_WALL_FLIP_LEFT;
02215 }
02216 }
02217 }
02218 else if ( pm->cmd.forwardmove < 0 && !(pm->cmd.buttons&BUTTON_ATTACK) )
02219 {
02220 if ( allowFlips )
02221 {
02222 vertPush = JUMP_VELOCITY;
02223 anim = BOTH_FLIP_BACK1;
02224 }
02225 }
02226
02227 vertPush += 128;
02228
02229 if ( anim != -1 )
02230 {
02231 vec3_t fwd, right, traceto, mins, maxs, fwdAngles;
02232 vec3_t idealNormal={0}, wallNormal={0};
02233 trace_t trace;
02234 qboolean doTrace = qfalse;
02235 int contents = MASK_SOLID;
02236
02237 VectorSet(mins, pm->mins[0],pm->mins[1],0);
02238 VectorSet(maxs, pm->maxs[0],pm->maxs[1],24);
02239 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
02240
02241 memset(&trace, 0, sizeof(trace));
02242
02243 AngleVectors( fwdAngles, fwd, right, NULL );
02244
02245
02246 switch ( anim )
02247 {
02248 case BOTH_WALL_FLIP_LEFT:
02249
02250 case BOTH_WALL_RUN_LEFT:
02251 doTrace = qtrue;
02252 VectorMA( pm->ps->origin, -16, right, traceto );
02253 break;
02254
02255 case BOTH_WALL_FLIP_RIGHT:
02256
02257 case BOTH_WALL_RUN_RIGHT:
02258 doTrace = qtrue;
02259 VectorMA( pm->ps->origin, 16, right, traceto );
02260 break;
02261
02262 case BOTH_WALL_FLIP_BACK1:
02263 doTrace = qtrue;
02264 VectorMA( pm->ps->origin, 16, fwd, traceto );
02265 break;
02266 }
02267
02268 if ( doTrace )
02269 {
02270 pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, contents );
02271 VectorCopy( trace.plane.normal, wallNormal );
02272 VectorNormalize( wallNormal );
02273 VectorSubtract( pm->ps->origin, traceto, idealNormal );
02274 VectorNormalize( idealNormal );
02275 }
02276
02277 if ( !doTrace || (trace.fraction < 1.0f && (trace.entityNum < MAX_CLIENTS || DotProduct(wallNormal,idealNormal) > 0.7)) )
02278 {
02279 if ( (anim != BOTH_WALL_RUN_LEFT
02280 && anim != BOTH_WALL_RUN_RIGHT
02281 && anim != BOTH_FORCEWALLRUNFLIP_START)
02282 || (wallNormal[2] >= 0.0f&&wallNormal[2]<=0.4f) )
02283 {
02284 int parts;
02285
02286 if ( anim == BOTH_WALL_FLIP_LEFT )
02287 {
02288 pm->ps->velocity[0] = pm->ps->velocity[1] = 0;
02289 VectorMA( pm->ps->velocity, 150, right, pm->ps->velocity );
02290 }
02291 else if ( anim == BOTH_WALL_FLIP_RIGHT )
02292 {
02293 pm->ps->velocity[0] = pm->ps->velocity[1] = 0;
02294 VectorMA( pm->ps->velocity, -150, right, pm->ps->velocity );
02295 }
02296 else if ( anim == BOTH_FLIP_BACK1
02297 || anim == BOTH_FLIP_BACK2
02298 || anim == BOTH_FLIP_BACK3
02299 || anim == BOTH_WALL_FLIP_BACK1 )
02300 {
02301 pm->ps->velocity[0] = pm->ps->velocity[1] = 0;
02302 VectorMA( pm->ps->velocity, -150, fwd, pm->ps->velocity );
02303 }
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316 if ( vertPush )
02317 {
02318 pm->ps->velocity[2] = vertPush;
02319 pm->ps->fd.forcePowersActive |= (1 << FP_LEVITATION);
02320 }
02321
02322 parts = SETANIM_LEGS;
02323 if ( anim == BOTH_BUTTERFLY_LEFT )
02324 {
02325 parts = SETANIM_BOTH;
02326 pm->cmd.buttons&=~BUTTON_ATTACK;
02327 pm->ps->saberMove = LS_NONE;
02328 }
02329 else if ( !pm->ps->weaponTime )
02330 {
02331 parts = SETANIM_BOTH;
02332 }
02333 PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
02334 if ( anim == BOTH_BUTTERFLY_LEFT )
02335 {
02336 pm->ps->weaponTime = pm->ps->torsoTimer;
02337 }
02338 PM_SetForceJumpZStart(pm->ps->origin[2]);
02339 pm->ps->pm_flags |= PMF_JUMP_HELD;
02340 pm->cmd.upmove = 0;
02341 pm->ps->fd.forceJumpSound = 1;
02342 }
02343 }
02344 }
02345 }
02346 else
02347 {
02348 int legsAnim = pm->ps->legsAnim;
02349
02350 if ( legsAnim == BOTH_WALL_RUN_LEFT || legsAnim == BOTH_WALL_RUN_RIGHT )
02351 {
02352 vec3_t right, traceto, mins, maxs, fwdAngles;
02353 trace_t trace;
02354 int anim = -1;
02355
02356 VectorSet(mins, pm->mins[0], pm->mins[0], 0);
02357 VectorSet(maxs, pm->maxs[0], pm->maxs[0], 24);
02358 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
02359
02360 AngleVectors( fwdAngles, NULL, right, NULL );
02361
02362 if ( legsAnim == BOTH_WALL_RUN_LEFT )
02363 {
02364 if ( pm->ps->legsTimer > 400 )
02365 {
02366 float animLen = PM_AnimLength( 0, (animNumber_t)BOTH_WALL_RUN_LEFT );
02367 if ( pm->ps->legsTimer < animLen - 400 )
02368 {
02369 VectorMA( pm->ps->origin, -16, right, traceto );
02370 anim = BOTH_WALL_RUN_LEFT_FLIP;
02371 }
02372 }
02373 }
02374 else if ( legsAnim == BOTH_WALL_RUN_RIGHT )
02375 {
02376 if ( pm->ps->legsTimer > 400 )
02377 {
02378 float animLen = PM_AnimLength( 0, (animNumber_t)BOTH_WALL_RUN_RIGHT );
02379 if ( pm->ps->legsTimer < animLen - 400 )
02380 {
02381 VectorMA( pm->ps->origin, 16, right, traceto );
02382 anim = BOTH_WALL_RUN_RIGHT_FLIP;
02383 }
02384 }
02385 }
02386 if ( anim != -1 )
02387 {
02388 pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, CONTENTS_SOLID|CONTENTS_BODY );
02389 if ( trace.fraction < 1.0f )
02390 {
02391 int parts = 0;
02392
02393 if ( anim == BOTH_WALL_RUN_LEFT_FLIP )
02394 {
02395 pm->ps->velocity[0] *= 0.5f;
02396 pm->ps->velocity[1] *= 0.5f;
02397 VectorMA( pm->ps->velocity, 150, right, pm->ps->velocity );
02398 }
02399 else if ( anim == BOTH_WALL_RUN_RIGHT_FLIP )
02400 {
02401 pm->ps->velocity[0] *= 0.5f;
02402 pm->ps->velocity[1] *= 0.5f;
02403 VectorMA( pm->ps->velocity, -150, right, pm->ps->velocity );
02404 }
02405 parts = SETANIM_LEGS;
02406 if ( !pm->ps->weaponTime )
02407 {
02408 parts = SETANIM_BOTH;
02409 }
02410 PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
02411 pm->cmd.upmove = 0;
02412 }
02413 }
02414 if ( pm->cmd.upmove != 0 )
02415 {
02416 return qfalse;
02417 }
02418 }
02419
02420 else if ( pm->ps->legsAnim == BOTH_FORCEWALLRUNFLIP_START )
02421 {
02422 vec3_t fwd, traceto, mins, maxs, fwdAngles;
02423 trace_t trace;
02424 int anim = -1;
02425 float animLen;
02426
02427 VectorSet(mins, pm->mins[0], pm->mins[0], 0.0f);
02428 VectorSet(maxs, pm->maxs[0], pm->maxs[0], 24.0f);
02429
02430 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0.0f);
02431 AngleVectors( fwdAngles, fwd, NULL, NULL );
02432
02433 assert(pm_entSelf);
02434 animLen = BG_AnimLength( pm_entSelf->localAnimIndex, BOTH_FORCEWALLRUNFLIP_START );
02435 if ( pm->ps->legsTimer < animLen - 400 )
02436 {
02437 VectorMA( pm->ps->origin, 16, fwd, traceto );
02438 anim = BOTH_FORCEWALLRUNFLIP_END;
02439 }
02440 if ( anim != -1 )
02441 {
02442 pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, CONTENTS_SOLID|CONTENTS_BODY );
02443 if ( trace.fraction < 1.0f )
02444 {
02445 int parts = SETANIM_LEGS;
02446
02447 pm->ps->velocity[0] *= 0.5f;
02448 pm->ps->velocity[1] *= 0.5f;
02449 VectorMA( pm->ps->velocity, -300, fwd, pm->ps->velocity );
02450 pm->ps->velocity[2] += 200;
02451 if ( !pm->ps->weaponTime )
02452 {
02453 parts = SETANIM_BOTH;
02454 }
02455 PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
02456
02457
02458
02459 pm->cmd.upmove = 0;
02460 PM_AddEvent( EV_JUMP );
02461 }
02462 }
02463 if ( pm->cmd.upmove != 0 )
02464 {
02465 return qfalse;
02466 }
02467 }
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519 else if ( pm->cmd.forwardmove > 0
02520 && pm->ps->fd.forceRageRecoveryTime < pm->cmd.serverTime
02521 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1
02522 && PM_WalkableGroundDistance() <= 80
02523 && (pm->ps->legsAnim == BOTH_JUMP1 || pm->ps->legsAnim == BOTH_INAIR1 ) )
02524 {
02525 if ( allowWallRuns )
02526 {
02527
02528 int wallWalkAnim = BOTH_WALL_FLIP_BACK1;
02529 int parts = SETANIM_LEGS;
02530 int contents = MASK_SOLID;
02531
02532 if ( pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_2 )
02533 {
02534 wallWalkAnim = BOTH_FORCEWALLRUNFLIP_START;
02535 parts = SETANIM_BOTH;
02536
02537 }
02538 else
02539 {
02540 if ( !pm->ps->weaponTime )
02541 {
02542 parts = SETANIM_BOTH;
02543 }
02544 }
02545
02546 if (1)
02547 {
02548 vec3_t fwd, traceto, mins, maxs, fwdAngles;
02549 trace_t trace;
02550 vec3_t idealNormal;
02551 bgEntity_t *traceEnt;
02552
02553 VectorSet(mins, pm->mins[0], pm->mins[1], 0.0f);
02554 VectorSet(maxs, pm->maxs[0], pm->maxs[1], 24.0f);
02555 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0.0f);
02556
02557 AngleVectors( fwdAngles, fwd, NULL, NULL );
02558 VectorMA( pm->ps->origin, 32, fwd, traceto );
02559
02560 pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, contents );
02561 VectorSubtract( pm->ps->origin, traceto, idealNormal );
02562 VectorNormalize( idealNormal );
02563 traceEnt = PM_BGEntForNum(trace.entityNum);
02564
02565 if ( trace.fraction < 1.0f
02566 &&((trace.entityNum<ENTITYNUM_WORLD&&traceEnt&&traceEnt->s.solid!=SOLID_BMODEL)||DotProduct(trace.plane.normal,idealNormal)>0.7) )
02567 {
02568 pm->ps->velocity[0] = pm->ps->velocity[1] = 0;
02569 if ( wallWalkAnim == BOTH_FORCEWALLRUNFLIP_START )
02570 {
02571 pm->ps->velocity[2] = forceJumpStrength[FORCE_LEVEL_3]/2.0f;
02572 }
02573 else
02574 {
02575 VectorMA( pm->ps->velocity, -150, fwd, pm->ps->velocity );
02576 pm->ps->velocity[2] += 150.0f;
02577 }
02578
02579 PM_SetAnim( parts, wallWalkAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
02580
02581
02582
02583
02584 PM_SetForceJumpZStart(pm->ps->origin[2]);
02585 pm->cmd.upmove = 0;
02586 pm->ps->fd.forceJumpSound = 1;
02587 BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 );
02588
02589
02590
02591
02592
02593
02594
02595
02596 pm->cmd.rightmove = pm->cmd.forwardmove= 0;
02597 }
02598 }
02599 }
02600 }
02601 else if ( (!BG_InSpecialJump( legsAnim )
02602 ||BG_InReboundJump( legsAnim )
02603 ||BG_InBackFlip( legsAnim ) )
02604
02605 && pm->ps->velocity[2] > -1200
02606 && !(pm->ps->pm_flags&PMF_JUMP_HELD)
02607 && (pm->cmd.forwardmove||pm->cmd.rightmove)
02608
02609 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_2
02610
02611 && BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION)
02612 && (pm->ps->origin[2]-pm->ps->fd.forceJumpZStart) < (forceJumpHeightMax[FORCE_LEVEL_3]-(BG_ForceWallJumpStrength()/2.0f))
02613
02614 )
02615 {
02616 if ( allowWallGrabs )
02617 {
02618
02619
02620
02621
02622
02623 vec3_t checkDir, traceto, mins, maxs, fwdAngles;
02624 trace_t trace;
02625 vec3_t idealNormal;
02626 int anim = -1;
02627
02628 VectorSet(mins, pm->mins[0], pm->mins[1], 0.0f);
02629 VectorSet(maxs, pm->maxs[0], pm->maxs[1], 24.0f);
02630 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0.0f);
02631
02632 if ( pm->cmd.rightmove )
02633 {
02634 if ( pm->cmd.rightmove > 0 )
02635 {
02636 anim = BOTH_FORCEWALLREBOUND_RIGHT;
02637 AngleVectors( fwdAngles, NULL, checkDir, NULL );
02638 }
02639 else if ( pm->cmd.rightmove < 0 )
02640 {
02641 anim = BOTH_FORCEWALLREBOUND_LEFT;
02642 AngleVectors( fwdAngles, NULL, checkDir, NULL );
02643 VectorScale( checkDir, -1, checkDir );
02644 }
02645 }
02646 else if ( pm->cmd.forwardmove > 0 )
02647 {
02648 anim = BOTH_FORCEWALLREBOUND_FORWARD;
02649 AngleVectors( fwdAngles, checkDir, NULL, NULL );
02650 }
02651 else if ( pm->cmd.forwardmove < 0 )
02652 {
02653 anim = BOTH_FORCEWALLREBOUND_BACK;
02654 AngleVectors( fwdAngles, checkDir, NULL, NULL );
02655 VectorScale( checkDir, -1, checkDir );
02656 }
02657 if ( anim != -1 )
02658 {
02659 bgEntity_t *traceEnt;
02660
02661 VectorMA( pm->ps->origin, 8, checkDir, traceto );
02662 pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, CONTENTS_SOLID );
02663 VectorSubtract( pm->ps->origin, traceto, idealNormal );
02664 VectorNormalize( idealNormal );
02665 traceEnt = PM_BGEntForNum(trace.entityNum);
02666 if ( trace.fraction < 1.0f
02667 &&fabs(trace.plane.normal[2]) <= 0.2f
02668 &&((trace.entityNum<ENTITYNUM_WORLD&&traceEnt&&traceEnt->s.solid!=SOLID_BMODEL)||DotProduct(trace.plane.normal,idealNormal)>0.7) )
02669 {
02670 float dot = DotProduct( pm->ps->velocity, trace.plane.normal );
02671 if ( dot < 1.0f )
02672 {
02673
02674 PM_GrabWallForJump( anim );
02675 }
02676 }
02677 }
02678 }
02679 }
02680 else
02681 {
02682
02683 }
02684
02685 }
02686 }
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748 if ( pm->ps->groundEntityNum == ENTITYNUM_NONE )
02749 {
02750 return qfalse;
02751 }
02752 if ( pm->cmd.upmove > 0 )
02753 {
02754 pm->ps->velocity[2] = JUMP_VELOCITY;
02755 PM_SetForceJumpZStart(pm->ps->origin[2]);
02756 pm->ps->pm_flags |= PMF_JUMP_HELD;
02757 }
02758
02759
02760 pml.groundPlane = qfalse;
02761 pml.walking = qfalse;
02762 pm->ps->pm_flags |= PMF_JUMP_HELD;
02763 pm->ps->groundEntityNum = ENTITYNUM_NONE;
02764 PM_SetForceJumpZStart(pm->ps->origin[2]);
02765
02766 PM_AddEvent( EV_JUMP );
02767
02768
02769 if ( pm->ps->gravity > 0 && !BG_InSpecialJump( pm->ps->legsAnim ) )
02770 {
02771 PM_JumpForDir();
02772 }
02773
02774 return qtrue;
02775 }
02776
02777
02778
02779
02780
02781 static qboolean PM_CheckWaterJump( void ) {
02782 vec3_t spot;
02783 int cont;
02784 vec3_t flatforward;
02785
02786 if (pm->ps->pm_time) {
02787 return qfalse;
02788 }
02789
02790
02791 if ( pm->waterlevel != 2 ) {
02792 return qfalse;
02793 }
02794
02795 flatforward[0] = pml.forward[0];
02796 flatforward[1] = pml.forward[1];
02797 flatforward[2] = 0;
02798 VectorNormalize (flatforward);
02799
02800 VectorMA (pm->ps->origin, 30, flatforward, spot);
02801 spot[2] += 4;
02802 cont = pm->pointcontents (spot, pm->ps->clientNum );
02803 if ( !(cont & CONTENTS_SOLID) ) {
02804 return qfalse;
02805 }
02806
02807 spot[2] += 16;
02808 cont = pm->pointcontents (spot, pm->ps->clientNum );
02809 if ( cont ) {
02810 return qfalse;
02811 }
02812
02813
02814 VectorScale (pml.forward, 200, pm->ps->velocity);
02815 pm->ps->velocity[2] = 350;
02816
02817 pm->ps->pm_flags |= PMF_TIME_WATERJUMP;
02818 pm->ps->pm_time = 2000;
02819
02820 return qtrue;
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833 static void PM_WaterJumpMove( void ) {
02834
02835
02836 PM_StepSlideMove( qtrue );
02837
02838 pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime;
02839 if (pm->ps->velocity[2] < 0) {
02840
02841 pm->ps->pm_flags &= ~PMF_ALL_TIMES;
02842 pm->ps->pm_time = 0;
02843 }
02844 }
02845
02846
02847
02848
02849
02850
02851
02852 static void PM_WaterMove( void ) {
02853 int i;
02854 vec3_t wishvel;
02855 float wishspeed;
02856 vec3_t wishdir;
02857 float scale;
02858 float vel;
02859
02860 if ( PM_CheckWaterJump() ) {
02861 PM_WaterJumpMove();
02862 return;
02863 }
02864 #if 0
02865
02866 if ( pm->cmd.upmove >= 10 ) {
02867 if (pm->ps->velocity[2] > -300) {
02868 if ( pm->watertype == CONTENTS_WATER ) {
02869 pm->ps->velocity[2] = 100;
02870 } else if (pm->watertype == CONTENTS_SLIME) {
02871 pm->ps->velocity[2] = 80;
02872 } else {
02873 pm->ps->velocity[2] = 50;
02874 }
02875 }
02876 }
02877 #endif
02878 PM_Friction ();
02879
02880 scale = PM_CmdScale( &pm->cmd );
02881
02882
02883
02884 if ( !scale ) {
02885 wishvel[0] = 0;
02886 wishvel[1] = 0;
02887 wishvel[2] = -60;
02888 } else {
02889 for (i=0 ; i<3 ; i++)
02890 wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;
02891
02892 wishvel[2] += scale * pm->cmd.upmove;
02893 }
02894
02895 VectorCopy (wishvel, wishdir);
02896 wishspeed = VectorNormalize(wishdir);
02897
02898 if ( wishspeed > pm->ps->speed * pm_swimScale ) {
02899 wishspeed = pm->ps->speed * pm_swimScale;
02900 }
02901
02902 PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate);
02903
02904
02905 if ( pml.groundPlane && DotProduct( pm->ps->velocity, pml.groundTrace.plane.normal ) < 0 ) {
02906 vel = VectorLength(pm->ps->velocity);
02907
02908 PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal,
02909 pm->ps->velocity, OVERCLIP );
02910
02911 VectorNormalize(pm->ps->velocity);
02912 VectorScale(pm->ps->velocity, vel, pm->ps->velocity);
02913 }
02914
02915 PM_SlideMove( qfalse );
02916 }
02917
02918
02919
02920
02921
02922
02923
02924 static void PM_FlyVehicleMove( void )
02925 {
02926 int i;
02927 vec3_t wishvel;
02928 float wishspeed;
02929 vec3_t wishdir;
02930 float scale;
02931 float zVel;
02932 float fmove = 0.0f, smove = 0.0f;
02933
02934
02935
02936
02937
02938
02939
02940 if ( pm->ps->gravity && pm->ps->velocity[2] < 0 && pm->ps->groundEntityNum == ENTITYNUM_NONE )
02941 {
02942 zVel = pm->ps->velocity[2];
02943 PM_Friction ();
02944 pm->ps->velocity[2] = zVel;
02945 }
02946 else
02947 {
02948 PM_Friction ();
02949 if ( pm->ps->velocity[2] < 0 && pm->ps->groundEntityNum != ENTITYNUM_NONE )
02950 {
02951 pm->ps->velocity[2] = 0;
02952 }
02953 }
02954
02955 scale = PM_CmdScale( &pm->cmd );
02956
02957
02958
02959 if ( pm->ps->clientNum >= MAX_CLIENTS )
02960 {
02961
02962
02963
02964 if ((fmove!=0.0f || smove!=0.0f) && VectorCompare(pm->ps->moveDir, vec3_origin))
02965 {
02966
02967 for ( i = 0 ; i < 3 ; i++ )
02968 {
02969 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
02970 }
02971
02972 VectorCopy( wishvel, wishdir );
02973 wishspeed = VectorNormalize(wishdir);
02974 wishspeed *= scale;
02975 }
02976
02977
02978 else
02979 {
02980 wishspeed = pm->ps->speed;
02981 VectorScale( pm->ps->moveDir, pm->ps->speed, wishvel );
02982 VectorCopy( pm->ps->moveDir, wishdir );
02983 }
02984 }
02985 else
02986 {
02987 for ( i = 0 ; i < 3 ; i++ ) {
02988 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
02989 }
02990
02991
02992
02993 VectorCopy (wishvel, wishdir);
02994 wishspeed = VectorNormalize(wishdir);
02995 wishspeed *= scale;
02996 }
02997
02998
02999 if ( wishspeed < 0 )
03000 {
03001 wishspeed = wishspeed * -1.0f;
03002 VectorScale( wishvel, -1.0f, wishvel );
03003 VectorScale( wishdir, -1.0f, wishdir );
03004 }
03005
03006 VectorCopy( wishvel, wishdir );
03007 wishspeed = VectorNormalize( wishdir );
03008
03009 PM_Accelerate( wishdir, wishspeed, 100 );
03010
03011 PM_StepSlideMove( 1 );
03012 }
03013
03014
03015
03016
03017
03018
03019
03020
03021 static void PM_FlyMove( void ) {
03022 int i;
03023 vec3_t wishvel;
03024 float wishspeed;
03025 vec3_t wishdir;
03026 float scale;
03027
03028
03029 PM_Friction ();
03030
03031 scale = PM_CmdScale( &pm->cmd );
03032
03033 if ( pm->ps->pm_type == PM_SPECTATOR && pm->cmd.buttons & BUTTON_ALT_ATTACK) {
03034
03035 scale *= 10;
03036 }
03037
03038
03039
03040
03041 if ( !scale ) {
03042 wishvel[0] = 0;
03043 wishvel[1] = 0;
03044 wishvel[2] = pm->ps->speed * (pm->cmd.upmove/127.0f);
03045 } else {
03046 for (i=0 ; i<3 ; i++) {
03047 wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;
03048 }
03049
03050 wishvel[2] += scale * pm->cmd.upmove;
03051 }
03052
03053 VectorCopy (wishvel, wishdir);
03054 wishspeed = VectorNormalize(wishdir);
03055
03056 PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate);
03057
03058 PM_StepSlideMove( qfalse );
03059 }
03060
03061
03062
03063
03064
03065
03066
03067
03068 static void PM_AirMove( void ) {
03069 int i;
03070 vec3_t wishvel;
03071 float fmove, smove;
03072 vec3_t wishdir;
03073 float wishspeed;
03074 float scale;
03075 float accelerate;
03076 usercmd_t cmd;
03077 Vehicle_t *pVeh = NULL;
03078
03079 if (pm->ps->clientNum >= MAX_CLIENTS)
03080 {
03081 bgEntity_t *pEnt = pm_entSelf;
03082
03083 if ( pEnt && pEnt->s.NPC_class == CLASS_VEHICLE )
03084 {
03085 pVeh = pEnt->m_pVehicle;
03086 }
03087 }
03088
03089 if (pm->ps->pm_type != PM_SPECTATOR)
03090 {
03091 #if METROID_JUMP
03092 PM_CheckJump();
03093 #else
03094 if (pm->ps->fd.forceJumpZStart &&
03095 pm->ps->forceJumpFlip)
03096 {
03097 PM_CheckJump();
03098 }
03099 #endif
03100 }
03101 PM_Friction();
03102
03103 fmove = pm->cmd.forwardmove;
03104 smove = pm->cmd.rightmove;
03105
03106 cmd = pm->cmd;
03107 scale = PM_CmdScale( &cmd );
03108
03109
03110 PM_SetMovementDir();
03111
03112
03113 pml.forward[2] = 0;
03114 pml.right[2] = 0;
03115 VectorNormalize (pml.forward);
03116 VectorNormalize (pml.right);
03117
03118 if ( pVeh && pVeh->m_pVehicleInfo->hoverHeight > 0 )
03119 {
03120 if ( 1 )
03121 {
03122 wishspeed = pm->ps->speed;
03123 VectorScale( pm->ps->moveDir, pm->ps->speed, wishvel );
03124 VectorCopy( pm->ps->moveDir, wishdir );
03125 scale = 1.0f;
03126 }
03127 #if 0
03128 else
03129 {
03130 float controlMod = 1.0f;
03131 if ( pml.groundPlane )
03132 {
03133 controlMod = pml.groundTrace.plane.normal[2];
03134 }
03135
03136 vec3_t vfwd, vrt;
03137 vec3_t vAngles;
03138
03139 VectorCopy( pVeh->m_vOrientation, vAngles );
03140 vAngles[ROLL] = 0;
03141 AngleVectors( vAngles, vfwd, vrt, NULL );
03142
03143 float speed = pm->ps->speed;
03144 float strafeSpeed = 0;
03145
03146 if ( fmove < 0 )
03147 {
03148 if ( speed < 0 )
03149 {
03150 speed = fabs( speed );
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161 }
03162 else if ( speed > 0 )
03163 {
03164 speed = 0;
03165 }
03166 }
03167
03168 if ( pm->ps->clientNum < MAX_CLIENTS )
03169 {
03170 VectorScale( vfwd, speed*controlMod*(fmove/127.0f), wishvel );
03171
03172 if ( pVeh->m_pVehicleInfo->strafePerc )
03173 {
03174 if ( smove )
03175 {
03176 float minSpeed = pVeh->m_pVehicleInfo->speedMax * 0.5f * pVeh->m_pVehicleInfo->strafePerc;
03177 strafeSpeed = fabs(DotProduct( pm->ps->velocity, vfwd ))*pVeh->m_pVehicleInfo->strafePerc;
03178 if ( strafeSpeed < minSpeed )
03179 {
03180 strafeSpeed = minSpeed;
03181 }
03182 strafeSpeed *= controlMod*((float)(smove))/127.0f;
03183 if ( strafeSpeed < 0 )
03184 {
03185 strafeSpeed *= -1;
03186 VectorScale( vrt, -1, vrt );
03187 }
03188
03189 PM_Accelerate( vrt, strafeSpeed, pVeh->m_pVehicleInfo->traction );
03190 }
03191 }
03192 }
03193 else
03194 {
03195 if ( pVeh->m_pVehicleInfo->strafePerc )
03196 {
03197 if ( pm->ps->clientNum )
03198 {
03199 if ( smove )
03200 {
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211 strafeSpeed = ((float)(smove))/127.0f;
03212 }
03213 }
03214 }
03215
03216 VectorScale( vfwd, (fmove/127.0f)*(1.0f-pVeh->m_pVehicleInfo->strafePerc), wishvel );
03217 if ( strafeSpeed )
03218 {
03219 VectorMA( wishvel, strafeSpeed*pVeh->m_pVehicleInfo->strafePerc, vrt, wishvel );
03220 }
03221 VectorNormalize( wishvel );
03222 VectorScale( wishvel, speed*controlMod, wishvel );
03223 }
03224 }
03225 #endif
03226 }
03227 else if ( gPMDoSlowFall )
03228 {
03229 VectorClear( wishvel );
03230 }
03231 else if (pm->ps->pm_type == PM_JETPACK)
03232 {
03233 for ( i = 0 ; i < 2 ; i++ )
03234 {
03235 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
03236 }
03237 wishvel[2] = 0;
03238
03239 if (pm->cmd.upmove <= 0)
03240 {
03241 VectorScale(wishvel, 0.8f, wishvel);
03242 }
03243 else
03244 {
03245 VectorScale(wishvel, 2.0f, wishvel);
03246 }
03247 }
03248 else
03249 {
03250 for ( i = 0 ; i < 2 ; i++ )
03251 {
03252 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
03253 }
03254 wishvel[2] = 0;
03255 }
03256
03257 VectorCopy (wishvel, wishdir);
03258 wishspeed = VectorNormalize(wishdir);
03259 wishspeed *= scale;
03260
03261 accelerate = pm_airaccelerate;
03262 if ( pVeh && pVeh->m_pVehicleInfo->type == VH_SPEEDER )
03263 {
03264
03265 accelerate = pVeh->m_pVehicleInfo->traction;
03266 if ( pml.groundPlane )
03267 {
03268 accelerate *= 0.5f;
03269 }
03270 }
03271
03272 PM_Accelerate (wishdir, wishspeed, accelerate);
03273
03274
03275
03276
03277 if ( pml.groundPlane )
03278 {
03279 if ( !(pm->ps->pm_flags&PMF_STUCK_TO_WALL) )
03280 {
03281 if ( PM_GroundSlideOkay( pml.groundTrace.plane.normal[2] ) )
03282 {
03283 PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal,
03284 pm->ps->velocity, OVERCLIP );
03285 }
03286 }
03287 }
03288
03289 if ( (pm->ps->pm_flags&PMF_STUCK_TO_WALL) )
03290 {
03291 PM_StepSlideMove( qfalse );
03292 }
03293 else
03294 {
03295 PM_StepSlideMove( qtrue );
03296 }
03297 }
03298
03299
03300
03301
03302
03303
03304
03305 static void PM_WalkMove( void ) {
03306 int i;
03307 vec3_t wishvel;
03308 float fmove, smove;
03309 vec3_t wishdir;
03310 float wishspeed = 0.0f;
03311 float scale;
03312 usercmd_t cmd;
03313 float accelerate;
03314 float vel;
03315 qboolean npcMovement = qfalse;
03316
03317 if ( pm->waterlevel > 2 && DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 ) {
03318
03319 PM_WaterMove();
03320 return;
03321 }
03322
03323
03324 if (pm->ps->pm_type != PM_SPECTATOR)
03325 {
03326 if ( PM_CheckJump () ) {
03327
03328 if ( pm->waterlevel > 1 ) {
03329 PM_WaterMove();
03330 } else {
03331 PM_AirMove();
03332 }
03333 return;
03334 }
03335 }
03336
03337 PM_Friction ();
03338
03339 fmove = pm->cmd.forwardmove;
03340 smove = pm->cmd.rightmove;
03341
03342 cmd = pm->cmd;
03343 scale = PM_CmdScale( &cmd );
03344
03345
03346 PM_SetMovementDir();
03347
03348
03349 pml.forward[2] = 0;
03350 pml.right[2] = 0;
03351
03352
03353 PM_ClipVelocity (pml.forward, pml.groundTrace.plane.normal, pml.forward, OVERCLIP );
03354 PM_ClipVelocity (pml.right, pml.groundTrace.plane.normal, pml.right, OVERCLIP );
03355
03356 VectorNormalize (pml.forward);
03357 VectorNormalize (pml.right);
03358
03359
03360
03361 if ( pm->ps->clientNum >= MAX_CLIENTS && !VectorCompare( pm->ps->moveDir, vec3_origin ) )
03362 {
03363 bgEntity_t *pEnt = pm_entSelf;
03364
03365 if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE)
03366 {
03367
03368
03369 if ((fmove!=0.0f || smove!=0.0f) && VectorCompare(pm->ps->moveDir, vec3_origin))
03370 {
03371
03372 for ( i = 0 ; i < 3 ; i++ )
03373 {
03374 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
03375 }
03376
03377 VectorCopy( wishvel, wishdir );
03378 wishspeed = VectorNormalize(wishdir);
03379 wishspeed *= scale;
03380 }
03381
03382
03383 else
03384 {
03385
03386 VectorScale( pm->ps->moveDir, pm->ps->speed, wishvel );
03387 VectorCopy (wishvel, wishdir);
03388 wishspeed = VectorNormalize(wishdir);
03389 }
03390
03391 npcMovement = qtrue;
03392 }
03393 }
03394
03395 if (!npcMovement)
03396 {
03397 for ( i = 0 ; i < 3 ; i++ ) {
03398 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
03399 }
03400
03401
03402 VectorCopy (wishvel, wishdir);
03403 wishspeed = VectorNormalize(wishdir);
03404 wishspeed *= scale;
03405 }
03406
03407
03408 if ( pm->ps->pm_flags & PMF_DUCKED ) {
03409 if ( wishspeed > pm->ps->speed * pm_duckScale ) {
03410 wishspeed = pm->ps->speed * pm_duckScale;
03411 }
03412 }
03413 else if ( (pm->ps->pm_flags & PMF_ROLLING) && !BG_InRoll(pm->ps, pm->ps->legsAnim) &&
03414 !PM_InRollComplete(pm->ps, pm->ps->legsAnim))
03415 {
03416 if ( wishspeed > pm->ps->speed * pm_duckScale ) {
03417 wishspeed = pm->ps->speed * pm_duckScale;
03418 }
03419 }
03420
03421
03422 if ( pm->waterlevel ) {
03423 float waterScale;
03424
03425 waterScale = pm->waterlevel / 3.0;
03426 waterScale = 1.0 - ( 1.0 - pm_swimScale ) * waterScale;
03427 if ( wishspeed > pm->ps->speed * waterScale ) {
03428 wishspeed = pm->ps->speed * waterScale;
03429 }
03430 }
03431
03432
03433
03434 if ( pm_flying == FLY_HOVER )
03435 {
03436 accelerate = pm_vehicleaccelerate;
03437 }
03438 else if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK )
03439 {
03440 accelerate = pm_airaccelerate;
03441 }
03442 else
03443 {
03444 accelerate = pm_accelerate;
03445 }
03446
03447 PM_Accelerate (wishdir, wishspeed, accelerate);
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462 if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK )
03463 {
03464 pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime;
03465 }
03466
03467 vel = VectorLength(pm->ps->velocity);
03468
03469
03470 PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal,
03471 pm->ps->velocity, OVERCLIP );
03472
03473
03474 VectorNormalize(pm->ps->velocity);
03475 VectorScale(pm->ps->velocity, vel, pm->ps->velocity);
03476
03477
03478 if (!pm->ps->velocity[0] && !pm->ps->velocity[1]) {
03479 return;
03480 }
03481
03482 PM_StepSlideMove( qfalse );
03483
03484
03485 }
03486
03487
03488
03489
03490
03491
03492
03493 static void PM_DeadMove( void ) {
03494 float forward;
03495
03496 if ( !pml.walking ) {
03497 return;
03498 }
03499
03500
03501
03502 forward = VectorLength (pm->ps->velocity);
03503 forward -= 20;
03504 if ( forward <= 0 ) {
03505 VectorClear (pm->ps->velocity);
03506 } else {
03507 VectorNormalize (pm->ps->velocity);
03508 VectorScale (pm->ps->velocity, forward, pm->ps->velocity);
03509 }
03510 }
03511
03512
03513
03514
03515
03516
03517
03518 static void PM_NoclipMove( void ) {
03519 float speed, drop, friction, control, newspeed;
03520 int i;
03521 vec3_t wishvel;
03522 float fmove, smove;
03523 vec3_t wishdir;
03524 float wishspeed;
03525 float scale;
03526
03527 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
03528
03529
03530
03531 speed = VectorLength (pm->ps->velocity);
03532 if (speed < 1)
03533 {
03534 VectorCopy (vec3_origin, pm->ps->velocity);
03535 }
03536 else
03537 {
03538 drop = 0;
03539
03540 friction = pm_friction*1.5;
03541 control = speed < pm_stopspeed ? pm_stopspeed : speed;
03542 drop += control*friction*pml.frametime;
03543
03544
03545 newspeed = speed - drop;
03546 if (newspeed < 0)
03547 newspeed = 0;
03548 newspeed /= speed;
03549
03550 VectorScale (pm->ps->velocity, newspeed, pm->ps->velocity);
03551 }
03552
03553
03554 scale = PM_CmdScale( &pm->cmd );
03555 if (pm->cmd.buttons & BUTTON_ATTACK) {
03556 scale *= 10;
03557 }
03558 if (pm->cmd.buttons & BUTTON_ALT_ATTACK) {
03559 scale *= 10;
03560 }
03561
03562 fmove = pm->cmd.forwardmove;
03563 smove = pm->cmd.rightmove;
03564
03565 for (i=0 ; i<3 ; i++)
03566 wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
03567 wishvel[2] += pm->cmd.upmove;
03568
03569 VectorCopy (wishvel, wishdir);
03570 wishspeed = VectorNormalize(wishdir);
03571 wishspeed *= scale;
03572
03573 PM_Accelerate( wishdir, wishspeed, pm_accelerate );
03574
03575
03576 VectorMA (pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin);
03577 }
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588 static int PM_FootstepForSurface( void )
03589 {
03590 if ( pml.groundTrace.surfaceFlags & SURF_NOSTEPS )
03591 {
03592 return 0;
03593 }
03594 return ( pml.groundTrace.surfaceFlags & MATERIAL_MASK );
03595 }
03596
03597 extern qboolean PM_CanRollFromSoulCal( playerState_t *ps );
03598 static int PM_TryRoll( void )
03599 {
03600 trace_t trace;
03601 int anim = -1;
03602 vec3_t fwd, right, traceto, mins, maxs, fwdAngles;
03603
03604 if ( BG_SaberInAttack( pm->ps->saberMove ) || BG_SaberInSpecialAttack( pm->ps->torsoAnim )
03605 || BG_SpinningSaberAnim( pm->ps->legsAnim )
03606 || PM_SaberInStart( pm->ps->saberMove ) )
03607 {
03608 if ( PM_CanRollFromSoulCal( pm->ps ) )
03609 {
03610 }
03611 else
03612 {
03613 return 0;
03614 }
03615 }
03616
03617 if ((pm->ps->weapon != WP_SABER && pm->ps->weapon != WP_MELEE) ||
03618 PM_IsRocketTrooper() ||
03619 BG_HasYsalamiri(pm->gametype, pm->ps) ||
03620 !BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION))
03621 {
03622 return 0;
03623 }
03624
03625 if ( pm->ps->weapon == WP_SABER )
03626 {
03627 saberInfo_t *saber = BG_MySaber( pm->ps->clientNum, 0 );
03628 if ( saber
03629 && (saber->saberFlags&SFL_NO_ROLLS) )
03630 {
03631 return 0;
03632 }
03633 saber = BG_MySaber( pm->ps->clientNum, 1 );
03634 if ( saber
03635 && (saber->saberFlags&SFL_NO_ROLLS) )
03636 {
03637 return 0;
03638 }
03639 }
03640
03641 VectorSet(mins, pm->mins[0],pm->mins[1],pm->mins[2]+STEPSIZE);
03642 VectorSet(maxs, pm->maxs[0],pm->maxs[1],pm->ps->crouchheight);
03643
03644 VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
03645
03646 AngleVectors( fwdAngles, fwd, right, NULL );
03647
03648 if ( pm->cmd.forwardmove )
03649 {
03650 if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
03651 {
03652 anim = BOTH_ROLL_B;
03653 VectorMA( pm->ps->origin, -64, fwd, traceto );
03654 }
03655 else
03656 {
03657 anim = BOTH_ROLL_F;
03658 VectorMA( pm->ps->origin, 64, fwd, traceto );
03659 }
03660 }
03661 else if ( pm->cmd.rightmove > 0 )
03662 {
03663 anim = BOTH_ROLL_R;
03664 VectorMA( pm->ps->origin, 64, right, traceto );
03665 }
03666 else if ( pm->cmd.rightmove < 0 )
03667 {
03668 anim = BOTH_ROLL_L;
03669 VectorMA( pm->ps->origin, -64, right, traceto );
03670 }
03671
03672 if ( anim != -1 )
03673 {
03674 pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, CONTENTS_SOLID );
03675 if ( trace.fraction >= 1.0f )
03676 {
03677 pm->ps->saberMove = LS_NONE;
03678 return anim;
03679 }
03680 }
03681 return 0;
03682 }
03683
03684 #ifdef QAGAME
03685 static void PM_CrashLandEffect( void )
03686 {
03687 float delta;
03688 if ( pm->waterlevel )
03689 {
03690 return;
03691 }
03692 delta = fabs(pml.previous_velocity[2])/10;
03693 if ( delta >= 30 )
03694 {
03695 vec3_t bottom;
03696 int effectID = -1;
03697 int material = (pml.groundTrace.surfaceFlags&MATERIAL_MASK);
03698 VectorSet( bottom, pm->ps->origin[0],pm->ps->origin[1],pm->ps->origin[2]+pm->mins[2]+1 );
03699 switch ( material )
03700 {
03701 case MATERIAL_MUD:
03702 effectID = EFFECT_LANDING_MUD;
03703 break;
03704 case MATERIAL_SAND:
03705 effectID = EFFECT_LANDING_SAND;
03706 break;
03707 case MATERIAL_DIRT:
03708 effectID = EFFECT_LANDING_DIRT;
03709 break;
03710 case MATERIAL_SNOW:
03711 effectID = EFFECT_LANDING_SNOW;
03712 break;
03713 case MATERIAL_GRAVEL:
03714 effectID = EFFECT_LANDING_GRAVEL;
03715 break;
03716 }
03717
03718 if ( effectID != -1 )
03719 {
03720 G_PlayEffect( effectID, bottom, pml.groundTrace.plane.normal );
03721 }
03722 }
03723 }
03724 #endif
03725
03726
03727
03728
03729
03730
03731
03732 static void PM_CrashLand( void ) {
03733 float delta;
03734 float dist;
03735 float vel, acc;
03736 float t;
03737 float a, b, c, den;
03738 qboolean didRoll = qfalse;
03739
03740
03741 dist = pm->ps->origin[2] - pml.previous_origin[2];
03742 vel = pml.previous_velocity[2];
03743 acc = -pm->ps->gravity;
03744
03745 a = acc / 2;
03746 b = vel;
03747 c = -dist;
03748
03749 den = b * b - 4 * a * c;
03750 if ( den < 0 ) {
03751 pm->ps->inAirAnim = qfalse;
03752 return;
03753 }
03754 t = (-b - sqrt( den ) ) / ( 2 * a );
03755
03756 delta = vel + t * acc;
03757 delta = delta*delta * 0.0001;
03758
03759 #ifdef QAGAME
03760 PM_CrashLandEffect();
03761 #endif
03762
03763 if ( pm->ps->pm_flags & PMF_DUCKED ) {
03764 delta *= 2;
03765 }
03766
03767 if (pm->ps->legsAnim == BOTH_A7_KICK_F_AIR ||
03768 pm->ps->legsAnim == BOTH_A7_KICK_B_AIR ||
03769 pm->ps->legsAnim == BOTH_A7_KICK_R_AIR ||
03770 pm->ps->legsAnim == BOTH_A7_KICK_L_AIR)
03771 {
03772 int landAnim = -1;
03773 switch ( pm->ps->legsAnim )
03774 {
03775 case BOTH_A7_KICK_F_AIR:
03776 landAnim = BOTH_FORCELAND1;
03777 break;
03778 case BOTH_A7_KICK_B_AIR:
03779 landAnim = BOTH_FORCELANDBACK1;
03780 break;
03781 case BOTH_A7_KICK_R_AIR:
03782 landAnim = BOTH_FORCELANDRIGHT1;
03783 break;
03784 case BOTH_A7_KICK_L_AIR:
03785 landAnim = BOTH_FORCELANDLEFT1;
03786 break;
03787 }
03788 if ( landAnim != -1 )
03789 {
03790 if ( pm->ps->torsoAnim == pm->ps->legsAnim )
03791 {
03792 PM_SetAnim(SETANIM_BOTH, landAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
03793 }
03794 else
03795 {
03796 PM_SetAnim(SETANIM_LEGS, landAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
03797 }
03798 }
03799 }
03800 else if (pm->ps->legsAnim == BOTH_FORCEJUMPLEFT1 ||
03801 pm->ps->legsAnim == BOTH_FORCEJUMPRIGHT1 ||
03802 pm->ps->legsAnim == BOTH_FORCEJUMPBACK1 ||
03803 pm->ps->legsAnim == BOTH_FORCEJUMP1)
03804 {
03805 int fjAnim;
03806 switch (pm->ps->legsAnim)
03807 {
03808 case BOTH_FORCEJUMPLEFT1:
03809 fjAnim = BOTH_LANDLEFT1;
03810 break;
03811 case BOTH_FORCEJUMPRIGHT1:
03812 fjAnim = BOTH_LANDRIGHT1;
03813 break;
03814 case BOTH_FORCEJUMPBACK1:
03815 fjAnim = BOTH_LANDBACK1;
03816 break;
03817 default:
03818 fjAnim = BOTH_LAND1;
03819 break;
03820 }
03821 PM_SetAnim(SETANIM_BOTH, fjAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
03822 }
03823
03824 else if (!BG_InRoll(pm->ps, pm->ps->legsAnim) && pm->ps->inAirAnim && !pm->ps->m_iVehicleNum)
03825 {
03826 if (!BG_SaberInSpecial(pm->ps->saberMove))
03827 {
03828 if ( pm->ps->pm_flags & PMF_BACKWARDS_JUMP ) {
03829 PM_ForceLegsAnim( BOTH_LANDBACK1 );
03830 } else {
03831 PM_ForceLegsAnim( BOTH_LAND1 );
03832 }
03833 }
03834 }
03835
03836 if (pm->ps->weapon != WP_SABER && pm->ps->weapon != WP_MELEE && !PM_IsRocketTrooper())
03837 {
03838
03839 if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
03840 {
03841 PM_StartTorsoAnim( TORSO_WEAPONREADY4 );
03842 }
03843 else
03844 {
03845 if (pm->ps->weapon == WP_EMPLACED_GUN)
03846 {
03847 PM_StartTorsoAnim( BOTH_GUNSIT1 );
03848 }
03849 else
03850 {
03851 PM_StartTorsoAnim( WeaponReadyAnim[pm->ps->weapon] );
03852 }
03853 }
03854 }
03855
03856 if (!BG_InSpecialJump(pm->ps->legsAnim) ||
03857 pm->ps->legsTimer < 1 ||
03858 (pm->ps->legsAnim) == BOTH_WALL_RUN_LEFT ||
03859 (pm->ps->legsAnim) == BOTH_WALL_RUN_RIGHT)
03860 {
03861 if (!BG_InRoll(pm->ps, pm->ps->legsAnim) && pm->ps->inAirAnim)
03862 {
03863 if (!BG_SaberInSpecial(pm->ps->saberMove) || pm->ps->weapon != WP_SABER)
03864 {
03865 if (pm->ps->legsAnim != BOTH_FORCELAND1 &&
03866 pm->ps->legsAnim != BOTH_FORCELANDBACK1 &&
03867 pm->ps->legsAnim != BOTH_FORCELANDRIGHT1 &&
03868 pm->ps->legsAnim != BOTH_FORCELANDLEFT1)
03869 {
03870 pm->ps->legsTimer = TIMER_LAND;
03871 }
03872 }
03873 }
03874 }
03875
03876 pm->ps->inAirAnim = qfalse;
03877
03878 if (pm->ps->m_iVehicleNum)
03879 {
03880 return;
03881 }
03882
03883
03884 if ( pm->waterlevel == 3 ) {
03885 return;
03886 }
03887
03888
03889 if ( pm->waterlevel == 2 ) {
03890 delta *= 0.25;
03891 }
03892 if ( pm->waterlevel == 1 ) {
03893 delta *= 0.5;
03894 }
03895
03896 if ( delta < 1 ) {
03897 return;
03898 }
03899
03900 if ( pm->ps->pm_flags & PMF_DUCKED )
03901 {
03902 if( delta >= 2 && !PM_InOnGroundAnim( pm->ps->legsAnim ) && !PM_InKnockDown( pm->ps ) && !BG_InRoll(pm->ps, pm->ps->legsAnim) &&
03903 pm->ps->forceHandExtend == HANDEXTEND_NONE )
03904 {
03905 int anim = PM_TryRoll();
03906
03907 if (PM_InRollComplete(pm->ps, pm->ps->legsAnim))
03908 {
03909 anim = 0;
03910 pm->ps->legsTimer = 0;
03911 pm->ps->legsAnim = 0;
03912 PM_SetAnim(SETANIM_BOTH,BOTH_LAND1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
03913 pm->ps->legsTimer = TIMER_LAND;
03914 }
03915
03916 if ( anim )
03917 {
03918 pm->ps->legsTimer = 0;
03919 delta /= 3;
03920 pm->ps->legsAnim = 0;
03921 if (pm->ps->torsoAnim == BOTH_A7_SOULCAL)
03922 {
03923 pm->ps->torsoTimer = 0;
03924 }
03925 PM_SetAnim(SETANIM_BOTH,anim,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
03926 didRoll = qtrue;
03927 }
03928 }
03929 }
03930
03931
03932
03933 if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) {
03934 if (delta > 7)
03935 {
03936 int delta_send = (int)delta;
03937
03938 if (delta_send > 600)
03939 {
03940 delta_send = 600;
03941 }
03942
03943 if (pm->ps->fd.forceJumpZStart)
03944 {
03945 if ((int)pm->ps->origin[2] >= (int)pm->ps->fd.forceJumpZStart)
03946 {
03947 if (delta_send > 8)
03948 {
03949 delta_send = 8;
03950 }
03951 }
03952 else
03953 {
03954 if (delta_send > 8)
03955 {
03956 int dif = ((int)pm->ps->fd.forceJumpZStart - (int)pm->ps->origin[2]);
03957 int dmgLess = (forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]] - dif);
03958
03959 if (dmgLess < 0)
03960 {
03961 dmgLess = 0;
03962 }
03963
03964 delta_send -= (dmgLess*0.3);
03965
03966 if (delta_send < 8)
03967 {
03968 delta_send = 8;
03969 }
03970
03971
03972 }
03973 }
03974 }
03975
03976 if (didRoll)
03977 {
03978 PM_AddEventWithParm( EV_ROLL, delta_send );
03979 }
03980 else
03981 {
03982 PM_AddEventWithParm( EV_FALL, delta_send );
03983 }
03984 }
03985 else
03986 {
03987 if (didRoll)
03988 {
03989 PM_AddEventWithParm( EV_ROLL, 0 );
03990 }
03991 else
03992 {
03993 PM_AddEventWithParm( EV_FOOTSTEP, PM_FootstepForSurface() );
03994 }
03995 }
03996 }
03997
03998
03999 pm->ps->velocity[2] = 0;
04000
04001
04002 pm->ps->bobCycle = 0;
04003 }
04004
04005
04006
04007
04008
04009
04010 static int PM_CorrectAllSolid( trace_t *trace ) {
04011 int i, j, k;
04012 vec3_t point;
04013
04014 if ( pm->debugLevel ) {
04015 Com_Printf("%i:allsolid\n", c_pmove);
04016 }
04017
04018
04019 for (i = -1; i <= 1; i++) {
04020 for (j = -1; j <= 1; j++) {
04021 for (k = -1; k <= 1; k++) {
04022 VectorCopy(pm->ps->origin, point);
04023 point[0] += (float) i;
04024 point[1] += (float) j;
04025 point[2] += (float) k;
04026 pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
04027 if ( !trace->allsolid ) {
04028 point[0] = pm->ps->origin[0];
04029 point[1] = pm->ps->origin[1];
04030 point[2] = pm->ps->origin[2] - 0.25;
04031
04032 pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
04033 pml.groundTrace = *trace;
04034 return qtrue;
04035 }
04036 }
04037 }
04038 }
04039
04040 pm->ps->groundEntityNum = ENTITYNUM_NONE;
04041 pml.groundPlane = qfalse;
04042 pml.walking = qfalse;
04043
04044 return qfalse;
04045 }
04046
04047
04048
04049
04050
04051
04052
04053
04054 static void PM_GroundTraceMissed( void ) {
04055 trace_t trace;
04056 vec3_t point;
04057
04058
04059
04060 if ( pm->ps->pm_type == PM_FLOAT )
04061 {
04062
04063 int parts = SETANIM_LEGS;
04064
04065
04066
04067 PM_SetAnim(parts, BOTH_CHOKE3, SETANIM_FLAG_OVERRIDE, 100);
04068 }
04069 else if ( pm->ps->pm_type == PM_JETPACK )
04070 {
04071
04072
04073
04074 }
04075
04076 else if ( pm->ps->groundEntityNum != ENTITYNUM_NONE || (pm->ps->legsAnim) == BOTH_CHOKE3 )
04077 {
04078
04079 if ( pm->debugLevel ) {
04080 Com_Printf("%i:lift\n", c_pmove);
04081 }
04082
04083
04084
04085 VectorCopy( pm->ps->origin, point );
04086 point[2] -= 64;
04087
04088 pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
04089 if ( trace.fraction == 1.0 || pm->ps->pm_type == PM_FLOAT ) {
04090 if ( pm->ps->velocity[2] <= 0 && !(pm->ps->pm_flags&PMF_JUMP_HELD))
04091 {
04092
04093 PM_SetAnim(SETANIM_LEGS,BOTH_INAIR1,0, 100);
04094 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
04095 }
04096 else if ( pm->cmd.forwardmove >= 0 )
04097 {
04098 PM_SetAnim(SETANIM_LEGS,BOTH_JUMP1,SETANIM_FLAG_OVERRIDE, 100);
04099 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
04100 }
04101 else
04102 {
04103 PM_SetAnim(SETANIM_LEGS,BOTH_JUMPBACK1,SETANIM_FLAG_OVERRIDE, 100);
04104 pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
04105 }
04106
04107 pm->ps->inAirAnim = qtrue;
04108 }
04109 }
04110 else if (!pm->ps->inAirAnim)
04111 {
04112
04113
04114 VectorCopy( pm->ps->origin, point );
04115 point[2] -= 64;
04116
04117 pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
04118 if ( trace.fraction == 1.0 || pm->ps->pm_type == PM_FLOAT )
04119 {
04120 pm->ps->inAirAnim = qtrue;
04121 }
04122 }
04123
04124 if (PM_InRollComplete(pm->ps, pm->ps->legsAnim))
04125 {
04126
04127 PM_SetAnim(SETANIM_BOTH,BOTH_INAIR1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
04128 pm->ps->inAirAnim = qtrue;
04129 }
04130
04131 pm->ps->groundEntityNum = ENTITYNUM_NONE;
04132 pml.groundPlane = qfalse;
04133 pml.walking = qfalse;
04134 }
04135
04136
04137
04138
04139
04140
04141
04142 static void PM_GroundTrace( void ) {
04143 vec3_t point;
04144 trace_t trace;
04145 float minNormal = (float)MIN_WALK_NORMAL;
04146
04147 if ( pm->ps->clientNum >= MAX_CLIENTS)
04148 {
04149 bgEntity_t *pEnt = pm_entSelf;
04150
04151 if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE)
04152 {
04153 minNormal = pEnt->m_pVehicle->m_pVehicleInfo->maxSlope;
04154 }
04155 }
04156
04157 point[0] = pm->ps->origin[0];
04158 point[1] = pm->ps->origin[1];
04159 point[2] = pm->ps->origin[2] - 0.25;
04160
04161 pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
04162 pml.groundTrace = trace;
04163
04164
04165 if ( trace.allsolid ) {
04166 if ( !PM_CorrectAllSolid(&trace) )
04167 return;
04168 }
04169
04170 if (pm->ps->pm_type == PM_FLOAT || pm->ps->pm_type == PM_JETPACK)
04171 {
04172 PM_GroundTraceMissed();
04173 pml.groundPlane = qfalse;
04174 pml.walking = qfalse;
04175 return;
04176 }
04177
04178
04179 if ( trace.fraction == 1.0 ) {
04180 PM_GroundTraceMissed();
04181 pml.groundPlane = qfalse;
04182 pml.walking = qfalse;
04183 return;
04184 }
04185
04186
04187 if ( pm->ps->velocity[2] > 0 && DotProduct( pm->ps->velocity, trace.plane.normal ) > 10 ) {
04188 if ( pm->debugLevel ) {
04189 Com_Printf("%i:kickoff\n", c_pmove);
04190 }
04191
04192 if ( pm->cmd.forwardmove >= 0 ) {
04193 PM_ForceLegsAnim( BOTH_JUMP1 );
04194 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
04195 } else {
04196 PM_ForceLegsAnim( BOTH_JUMPBACK1 );
04197 pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
04198 }
04199
04200 pm->ps->groundEntityNum = ENTITYNUM_NONE;
04201 pml.groundPlane = qfalse;
04202 pml.walking = qfalse;
04203 return;
04204 }
04205
04206
04207 if ( trace.plane.normal[2] < minNormal ) {
04208 if ( pm->debugLevel ) {
04209 Com_Printf("%i:steep\n", c_pmove);
04210 }
04211 pm->ps->groundEntityNum = ENTITYNUM_NONE;
04212 pml.groundPlane = qtrue;
04213 pml.walking = qfalse;
04214 return;
04215 }
04216
04217 pml.groundPlane = qtrue;
04218 pml.walking = qtrue;
04219
04220
04221 if (pm->ps->pm_flags & PMF_TIME_WATERJUMP)
04222 {
04223 pm->ps->pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND);
04224 pm->ps->pm_time = 0;
04225 }
04226
04227 if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) {
04228
04229 if ( pm->debugLevel ) {
04230 Com_Printf("%i:Land\n", c_pmove);
04231 }
04232
04233 PM_CrashLand();
04234
04235 #ifdef QAGAME
04236 if (pm->ps->clientNum < MAX_CLIENTS &&
04237 !pm->ps->m_iVehicleNum &&
04238 trace.entityNum < ENTITYNUM_WORLD &&
04239 trace.entityNum >= MAX_CLIENTS &&
04240 !pm->ps->zoomMode &&
04241 pm_entSelf)
04242 {
04243 gentity_t *trEnt = &g_entities[trace.entityNum];
04244 if (trEnt->inuse && trEnt->client && trEnt->s.eType == ET_NPC && trEnt->s.NPC_class == CLASS_VEHICLE &&
04245 !trEnt->client->ps.m_iVehicleNum &&
04246 trEnt->m_pVehicle &&
04247 trEnt->m_pVehicle->m_pVehicleInfo->type != VH_WALKER &&
04248 trEnt->m_pVehicle->m_pVehicleInfo->type != VH_FIGHTER)
04249 {
04250 if (!BG_SaberInSpecial(pm->ps->saberMove) &&
04251 pm->ps->forceHandExtend == HANDEXTEND_NONE &&
04252 pm->ps->weaponTime <= 0)
04253 {
04254 gentity_t *servEnt = (gentity_t *)pm_entSelf;
04255 if (g_gametype.integer < GT_TEAM ||
04256 !trEnt->alliedTeam ||
04257 (trEnt->alliedTeam == servEnt->client->sess.sessionTeam))
04258 {
04259 trEnt->m_pVehicle->m_pVehicleInfo->Board(trEnt->m_pVehicle, pm_entSelf);
04260 }
04261 }
04262 }
04263 }
04264 #endif
04265
04266
04267 if ( pml.previous_velocity[2] < -200 ) {
04268
04269 pm->ps->pm_flags |= PMF_TIME_LAND;
04270 pm->ps->pm_time = 250;
04271 }
04272 }
04273
04274 pm->ps->groundEntityNum = trace.entityNum;
04275 pm->ps->lastOnGround = pm->cmd.serverTime;
04276
04277 PM_AddTouchEnt( trace.entityNum );
04278 }
04279
04280
04281
04282
04283
04284
04285
04286 static void PM_SetWaterLevel( void ) {
04287 vec3_t point;
04288 int cont;
04289 int sample1;
04290 int sample2;
04291
04292
04293
04294
04295 pm->waterlevel = 0;
04296 pm->watertype = 0;
04297
04298 point[0] = pm->ps->origin[0];
04299 point[1] = pm->ps->origin[1];
04300 point[2] = pm->ps->origin[2] + MINS_Z + 1;
04301 cont = pm->pointcontents( point, pm->ps->clientNum );
04302
04303 if ( cont & MASK_WATER ) {
04304 sample2 = pm->ps->viewheight - MINS_Z;
04305 sample1 = sample2 / 2;
04306
04307 pm->watertype = cont;
04308 pm->waterlevel = 1;
04309 point[2] = pm->ps->origin[2] + MINS_Z + sample1;
04310 cont = pm->pointcontents (point, pm->ps->clientNum );
04311 if ( cont & MASK_WATER ) {
04312 pm->waterlevel = 2;
04313 point[2] = pm->ps->origin[2] + MINS_Z + sample2;
04314 cont = pm->pointcontents (point, pm->ps->clientNum );
04315 if ( cont & MASK_WATER ){
04316 pm->waterlevel = 3;
04317 }
04318 }
04319 }
04320
04321 }
04322
04323 qboolean PM_CheckDualForwardJumpDuck( void )
04324 {
04325 qboolean resized = qfalse;
04326 if ( pm->ps->legsAnim == BOTH_JUMPATTACK6 )
04327 {
04328
04329 if ( ( pm->ps->legsTimer >= 1450
04330 && PM_AnimLength( 0, BOTH_JUMPATTACK6 ) - pm->ps->legsTimer >= 400 )
04331 ||(pm->ps->legsTimer >= 400
04332 && PM_AnimLength( 0, BOTH_JUMPATTACK6 ) - pm->ps->legsTimer >= 1100 ) )
04333 {
04334 pm->mins[2] = 0;
04335 pm->ps->pm_flags |= PMF_FIX_MINS;
04336 resized = qtrue;
04337 }
04338 }
04339 return resized;
04340 }
04341
04342 void PM_CheckFixMins( void )
04343 {
04344 if ( (pm->ps->pm_flags&PMF_FIX_MINS) )
04345 {
04346
04347 trace_t trace;
04348 vec3_t end, curMins, curMaxs;
04349
04350 VectorSet( end, pm->ps->origin[0], pm->ps->origin[1], pm->ps->origin[2]+MINS_Z );
04351 VectorSet( curMins, pm->mins[0], pm->mins[1], 0 );
04352 VectorSet( curMaxs, pm->maxs[0], pm->maxs[1], pm->ps->standheight );
04353
04354 pm->trace( &trace, pm->ps->origin, curMins, curMaxs, end, pm->ps->clientNum, pm->tracemask );
04355 if ( !trace.allsolid && !trace.startsolid )
04356 {
04357 if ( trace.fraction >= 1.0f )
04358 {
04359
04360 pm->mins[2] = MINS_Z;
04361 pm->ps->pm_flags &= ~PMF_FIX_MINS;
04362 }
04363 else
04364 {
04365
04366 float updist = ((1.0f-trace.fraction) * -MINS_Z);
04367 end[2] = pm->ps->origin[2]+updist;
04368 pm->trace( &trace, pm->ps->origin, curMins, curMaxs, end, pm->ps->clientNum, pm->tracemask );
04369 if ( !trace.allsolid && !trace.startsolid )
04370 {
04371 if ( trace.fraction >= 1.0f )
04372 {
04373
04374 pm->ps->origin[2] += updist;
04375
04376 pm->mins[2] = MINS_Z;
04377 pm->ps->pm_flags &= ~PMF_FIX_MINS;
04378 }
04379 else
04380 {
04381 if ( pm->ps->legsAnim != BOTH_JUMPATTACK6
04382 || pm->ps->legsTimer <= 200 )
04383 {
04384
04385 pm->maxs[2] += MINS_Z;
04386 pm->ps->origin[2] -= MINS_Z;
04387 pm->mins[2] = MINS_Z;
04388
04389 if ( pm->ps->legsAnim == BOTH_JUMPATTACK6 )
04390 {
04391 pm->ps->legsTimer = pm->ps->torsoTimer = 0;
04392 }
04393 pm->ps->pm_flags |= PMF_DUCKED;
04394
04395 pm->ps->pm_flags &= ~PMF_FIX_MINS;
04396 }
04397 }
04398 }
04399 }
04400 }
04401 }
04402 }
04403
04404
04405
04406
04407
04408
04409
04410
04411 static void PM_CheckDuck (void)
04412 {
04413 trace_t trace;
04414
04415 if ( pm->ps->m_iVehicleNum > 0 && pm->ps->m_iVehicleNum < ENTITYNUM_NONE )
04416 {
04417
04418
04419 pm->ps->pm_flags &= ~PMF_DUCKED;
04420 pm->ps->pm_flags &= ~PMF_ROLLING;
04421
04422
04423
04424
04425 if (pm->ps->clientNum >= MAX_CLIENTS)
04426 {
04427 return;
04428 }
04429 if (pm_entVeh && pm_entVeh->m_pVehicle &&
04430 (pm_entVeh->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER ||
04431 pm_entVeh->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL))
04432 {
04433 trace_t solidTr;
04434
04435 pm->mins[0] = -16;
04436 pm->mins[1] = -16;
04437 pm->mins[2] = MINS_Z;
04438
04439 pm->maxs[0] = 16;
04440 pm->maxs[1] = 16;
04441 pm->maxs[2] = pm->ps->standheight;
04442 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
04443
04444 pm->trace (&solidTr, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->m_iVehicleNum, pm->tracemask);
04445 if (solidTr.startsolid || solidTr.allsolid || solidTr.fraction != 1.0f)
04446 {
04447 VectorClear(pm->mins);
04448 VectorClear(pm->maxs);
04449 #ifdef QAGAME
04450 {
04451 gentity_t *me = &g_entities[pm->ps->clientNum];
04452 if (me->inuse && me->client)
04453 {
04454 me->client->solidHack = level.time + 200;
04455 }
04456 }
04457 #endif
04458 }
04459 }
04460 }
04461 else
04462 {
04463 if (pm->ps->clientNum < MAX_CLIENTS)
04464 {
04465 pm->mins[0] = -15;
04466 pm->mins[1] = -15;
04467
04468 pm->maxs[0] = 15;
04469 pm->maxs[1] = 15;
04470 }
04471
04472 if ( PM_CheckDualForwardJumpDuck() )
04473 {
04474 }
04475 else
04476 {
04477 PM_CheckFixMins();
04478
04479 if ( !pm->mins[2] )
04480 {
04481 pm->mins[2] = MINS_Z;
04482 }
04483 }
04484
04485 if (pm->ps->pm_type == PM_DEAD && pm->ps->clientNum < MAX_CLIENTS)
04486 {
04487 pm->maxs[2] = -8;
04488 pm->ps->viewheight = DEAD_VIEWHEIGHT;
04489 return;
04490 }
04491
04492 if (BG_InRoll(pm->ps, pm->ps->legsAnim) && !BG_KickingAnim(pm->ps->legsAnim))
04493 {
04494 pm->maxs[2] = pm->ps->crouchheight;
04495 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
04496 pm->ps->pm_flags &= ~PMF_DUCKED;
04497 pm->ps->pm_flags |= PMF_ROLLING;
04498 return;
04499 }
04500 else if (pm->ps->pm_flags & PMF_ROLLING)
04501 {
04502
04503 pm->maxs[2] = pm->ps->standheight;
04504 pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask );
04505 if (!trace.allsolid)
04506 pm->ps->pm_flags &= ~PMF_ROLLING;
04507 }
04508 else if (pm->cmd.upmove < 0 ||
04509 pm->ps->forceHandExtend == HANDEXTEND_KNOCKDOWN ||
04510 pm->ps->forceHandExtend == HANDEXTEND_PRETHROWN ||
04511 pm->ps->forceHandExtend == HANDEXTEND_POSTTHROWN)
04512 {
04513 pm->ps->pm_flags |= PMF_DUCKED;
04514 }
04515 else
04516 {
04517 if (pm->ps->pm_flags & PMF_DUCKED)
04518 {
04519
04520 pm->maxs[2] = pm->ps->standheight;
04521 pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask );
04522 if (!trace.allsolid)
04523 pm->ps->pm_flags &= ~PMF_DUCKED;
04524 }
04525 }
04526 }
04527
04528 if (pm->ps->pm_flags & PMF_DUCKED)
04529 {
04530 pm->maxs[2] = pm->ps->crouchheight;
04531 pm->ps->viewheight = CROUCH_VIEWHEIGHT;
04532 }
04533 else if (pm->ps->pm_flags & PMF_ROLLING)
04534 {
04535 pm->maxs[2] = pm->ps->crouchheight;
04536 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
04537 }
04538 else
04539 {
04540 pm->maxs[2] = pm->ps->standheight;
04541 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
04542 }
04543 }
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558 #define USE_DELAY 2000
04559
04560 void PM_Use( void )
04561 {
04562 if ( pm->ps->useTime > 0 )
04563 pm->ps->useTime -= 100;
04564
04565 if ( pm->ps->useTime > 0 ) {
04566 return;
04567 }
04568
04569 if ( ! (pm->cmd.buttons & BUTTON_USE ) )
04570 {
04571 pm->useEvent = 0;
04572 pm->ps->useTime = 0;
04573 return;
04574 }
04575
04576 pm->useEvent = EV_USE;
04577 pm->ps->useTime = USE_DELAY;
04578 }
04579
04580 qboolean PM_WalkingAnim( int anim )
04581 {
04582 switch ( anim )
04583 {
04584 case BOTH_WALK1:
04585 case BOTH_WALK2:
04586 case BOTH_WALK_STAFF:
04587 case BOTH_WALK_DUAL:
04588 case BOTH_WALK5:
04589 case BOTH_WALK6:
04590 case BOTH_WALK7:
04591 case BOTH_WALKBACK1:
04592 case BOTH_WALKBACK2:
04593 case BOTH_WALKBACK_STAFF:
04594 case BOTH_WALKBACK_DUAL:
04595 return qtrue;
04596 break;
04597 }
04598 return qfalse;
04599 }
04600
04601 qboolean PM_RunningAnim( int anim )
04602 {
04603 switch ( (anim) )
04604 {
04605 case BOTH_RUN1:
04606 case BOTH_RUN2:
04607 case BOTH_RUN_STAFF:
04608 case BOTH_RUN_DUAL:
04609 case BOTH_RUNBACK1:
04610 case BOTH_RUNBACK2:
04611 case BOTH_RUNBACK_STAFF:
04612 case BOTH_RUNBACK_DUAL:
04613 case BOTH_RUN1START:
04614 case BOTH_RUN1STOP:
04615 case BOTH_RUNSTRAFE_LEFT1:
04616 case BOTH_RUNSTRAFE_RIGHT1:
04617 return qtrue;
04618 break;
04619 }
04620 return qfalse;
04621 }
04622
04623 qboolean PM_SwimmingAnim( int anim )
04624 {
04625 switch ( anim )
04626 {
04627 case BOTH_SWIM_IDLE1:
04628 case BOTH_SWIMFORWARD:
04629 case BOTH_SWIMBACKWARD:
04630 return qtrue;
04631 break;
04632 }
04633 return qfalse;
04634 }
04635
04636 qboolean PM_RollingAnim( int anim )
04637 {
04638 switch ( anim )
04639 {
04640 case BOTH_ROLL_F:
04641 case BOTH_ROLL_B:
04642 case BOTH_ROLL_L:
04643 case BOTH_ROLL_R:
04644 return qtrue;
04645 break;
04646 }
04647 return qfalse;
04648 }
04649
04650 void PM_AnglesForSlope( const float yaw, const vec3_t slope, vec3_t angles )
04651 {
04652 vec3_t nvf, ovf, ovr, new_angles;
04653 float pitch, mod, dot;
04654
04655 VectorSet( angles, 0, yaw, 0 );
04656 AngleVectors( angles, ovf, ovr, NULL );
04657
04658 vectoangles( slope, new_angles );
04659 pitch = new_angles[PITCH] + 90;
04660 new_angles[ROLL] = new_angles[PITCH] = 0;
04661
04662 AngleVectors( new_angles, nvf, NULL, NULL );
04663
04664 mod = DotProduct( nvf, ovr );
04665
04666 if ( mod < 0 )
04667 mod = -1;
04668 else
04669 mod = 1;
04670
04671 dot = DotProduct( nvf, ovf );
04672
04673 angles[YAW] = 0;
04674 angles[PITCH] = dot * pitch;
04675 angles[ROLL] = ((1-Q_fabs(dot)) * pitch * mod);
04676 }
04677
04678 void PM_FootSlopeTrace( float *pDiff, float *pInterval )
04679 {
04680 vec3_t footLOrg, footROrg, footLBot, footRBot;
04681 vec3_t footLPoint, footRPoint;
04682 vec3_t footMins, footMaxs;
04683 vec3_t footLSlope, footRSlope;
04684
04685 trace_t trace;
04686 float diff, interval;
04687
04688 mdxaBone_t boltMatrix;
04689 vec3_t G2Angles;
04690
04691 VectorSet(G2Angles, 0, pm->ps->viewangles[YAW], 0);
04692
04693 interval = 4;
04694
04695 strap_G2API_GetBoltMatrix( pm->ghoul2, 0, pm->g2Bolts_LFoot,
04696 &boltMatrix, G2Angles, pm->ps->origin, pm->cmd.serverTime,
04697 NULL, pm->modelScale );
04698 footLPoint[0] = boltMatrix.matrix[0][3];
04699 footLPoint[1] = boltMatrix.matrix[1][3];
04700 footLPoint[2] = boltMatrix.matrix[2][3];
04701
04702 strap_G2API_GetBoltMatrix( pm->ghoul2, 0, pm->g2Bolts_RFoot,
04703 &boltMatrix, G2Angles, pm->ps->origin, pm->cmd.serverTime,
04704 NULL, pm->modelScale );
04705 footRPoint[0] = boltMatrix.matrix[0][3];
04706 footRPoint[1] = boltMatrix.matrix[1][3];
04707 footRPoint[2] = boltMatrix.matrix[2][3];
04708
04709
04710 VectorCopy( footLPoint, footLOrg );
04711 VectorCopy( footRPoint, footROrg );
04712
04713
04714 footLOrg[2] = pm->ps->origin[2] + pm->mins[2] + 1;
04715 footROrg[2] = pm->ps->origin[2] + pm->mins[2] + 1;
04716 VectorSet( footLBot, footLOrg[0], footLOrg[1], footLOrg[2] - interval*10 );
04717 VectorSet( footRBot, footROrg[0], footROrg[1], footROrg[2] - interval*10 );
04718
04719
04720 VectorSet( footMins, -3, -3, 0 );
04721 VectorSet( footMaxs, 3, 3, 1 );
04722
04723 pm->trace( &trace, footLOrg, footMins, footMaxs, footLBot, pm->ps->clientNum, pm->tracemask );
04724 VectorCopy( trace.endpos, footLBot );
04725 VectorCopy( trace.plane.normal, footLSlope );
04726
04727 pm->trace( &trace, footROrg, footMins, footMaxs, footRBot, pm->ps->clientNum, pm->tracemask );
04728 VectorCopy( trace.endpos, footRBot );
04729 VectorCopy( trace.plane.normal, footRSlope );
04730
04731 diff = footLBot[2] - footRBot[2];
04732
04733 if ( pDiff != NULL )
04734 {
04735 *pDiff = diff;
04736 }
04737 if ( pInterval != NULL )
04738 {
04739 *pInterval = interval;
04740 }
04741 }
04742
04743 qboolean BG_InSlopeAnim( int anim )
04744 {
04745 switch ( anim )
04746 {
04747 case LEGS_LEFTUP1:
04748 case LEGS_LEFTUP2:
04749 case LEGS_LEFTUP3:
04750 case LEGS_LEFTUP4:
04751 case LEGS_LEFTUP5:
04752 case LEGS_RIGHTUP1:
04753 case LEGS_RIGHTUP2:
04754 case LEGS_RIGHTUP3:
04755 case LEGS_RIGHTUP4:
04756 case LEGS_RIGHTUP5:
04757 case LEGS_S1_LUP1:
04758 case LEGS_S1_LUP2:
04759 case LEGS_S1_LUP3:
04760 case LEGS_S1_LUP4:
04761 case LEGS_S1_LUP5:
04762 case LEGS_S1_RUP1:
04763 case LEGS_S1_RUP2:
04764 case LEGS_S1_RUP3:
04765 case LEGS_S1_RUP4:
04766 case LEGS_S1_RUP5:
04767 case LEGS_S3_LUP1:
04768 case LEGS_S3_LUP2:
04769 case LEGS_S3_LUP3:
04770 case LEGS_S3_LUP4:
04771 case LEGS_S3_LUP5:
04772 case LEGS_S3_RUP1:
04773 case LEGS_S3_RUP2:
04774 case LEGS_S3_RUP3:
04775 case LEGS_S3_RUP4:
04776 case LEGS_S3_RUP5:
04777 case LEGS_S4_LUP1:
04778 case LEGS_S4_LUP2:
04779 case LEGS_S4_LUP3:
04780 case LEGS_S4_LUP4:
04781 case LEGS_S4_LUP5:
04782 case LEGS_S4_RUP1:
04783 case LEGS_S4_RUP2:
04784 case LEGS_S4_RUP3:
04785 case LEGS_S4_RUP4:
04786 case LEGS_S4_RUP5:
04787 case LEGS_S5_LUP1:
04788 case LEGS_S5_LUP2:
04789 case LEGS_S5_LUP3:
04790 case LEGS_S5_LUP4:
04791 case LEGS_S5_LUP5:
04792 case LEGS_S5_RUP1:
04793 case LEGS_S5_RUP2:
04794 case LEGS_S5_RUP3:
04795 case LEGS_S5_RUP4:
04796 case LEGS_S5_RUP5:
04797 return qtrue;
04798 break;
04799 }
04800 return qfalse;
04801 }
04802
04803 #define SLOPE_RECALC_INT 100
04804
04805 qboolean PM_AdjustStandAnimForSlope( void )
04806 {
04807 float diff;
04808 float interval;
04809 int destAnim;
04810 int legsAnim;
04811 #define SLOPERECALCVAR pm->ps->slopeRecalcTime //this is purely convenience
04812
04813 if (!pm->ghoul2)
04814 {
04815 return qfalse;
04816 }
04817
04818 if ( pm->g2Bolts_LFoot == -1 || pm->g2Bolts_RFoot == -1 )
04819 {
04820 return qfalse;
04821 }
04822
04823
04824 PM_FootSlopeTrace( &diff, &interval );
04825
04826
04827 if ( diff >= interval*5 )
04828 {
04829 destAnim = LEGS_LEFTUP5;
04830 }
04831 else if ( diff >= interval*4 )
04832 {
04833 destAnim = LEGS_LEFTUP4;
04834 }
04835 else if ( diff >= interval*3 )
04836 {
04837 destAnim = LEGS_LEFTUP3;
04838 }
04839 else if ( diff >= interval*2 )
04840 {
04841 destAnim = LEGS_LEFTUP2;
04842 }
04843 else if ( diff >= interval )
04844 {
04845 destAnim = LEGS_LEFTUP1;
04846 }
04847 else if ( diff <= interval*-5 )
04848 {
04849 destAnim = LEGS_RIGHTUP5;
04850 }
04851 else if ( diff <= interval*-4 )
04852 {
04853 destAnim = LEGS_RIGHTUP4;
04854 }
04855 else if ( diff <= interval*-3 )
04856 {
04857 destAnim = LEGS_RIGHTUP3;
04858 }
04859 else if ( diff <= interval*-2 )
04860 {
04861 destAnim = LEGS_RIGHTUP2;
04862 }
04863 else if ( diff <= interval*-1 )
04864 {
04865 destAnim = LEGS_RIGHTUP1;
04866 }
04867 else
04868 {
04869 return qfalse;
04870 }
04871
04872 legsAnim = pm->ps->legsAnim;
04873
04874 switch ( legsAnim )
04875 {
04876 case BOTH_STAND1:
04877
04878 case LEGS_S1_LUP1:
04879 case LEGS_S1_LUP2:
04880 case LEGS_S1_LUP3:
04881 case LEGS_S1_LUP4:
04882 case LEGS_S1_LUP5:
04883 case LEGS_S1_RUP1:
04884 case LEGS_S1_RUP2:
04885 case LEGS_S1_RUP3:
04886 case LEGS_S1_RUP4:
04887 case LEGS_S1_RUP5:
04888 destAnim = LEGS_S1_LUP1 + (destAnim-LEGS_LEFTUP1);
04889 break;
04890 case BOTH_STAND2:
04891 case BOTH_SABERFAST_STANCE:
04892 case BOTH_SABERSLOW_STANCE:
04893 case BOTH_CROUCH1IDLE:
04894 case BOTH_CROUCH1:
04895 case LEGS_LEFTUP1:
04896 case LEGS_LEFTUP2:
04897 case LEGS_LEFTUP3:
04898 case LEGS_LEFTUP4:
04899 case LEGS_LEFTUP5:
04900 case LEGS_RIGHTUP1:
04901 case LEGS_RIGHTUP2:
04902 case LEGS_RIGHTUP3:
04903 case LEGS_RIGHTUP4:
04904 case LEGS_RIGHTUP5:
04905
04906 break;
04907 case BOTH_STAND3:
04908 case LEGS_S3_LUP1:
04909 case LEGS_S3_LUP2:
04910 case LEGS_S3_LUP3:
04911 case LEGS_S3_LUP4:
04912 case LEGS_S3_LUP5:
04913 case LEGS_S3_RUP1:
04914 case LEGS_S3_RUP2:
04915 case LEGS_S3_RUP3:
04916 case LEGS_S3_RUP4:
04917 case LEGS_S3_RUP5:
04918 destAnim = LEGS_S3_LUP1 + (destAnim-LEGS_LEFTUP1);
04919 break;
04920 case BOTH_STAND4:
04921 case LEGS_S4_LUP1:
04922 case LEGS_S4_LUP2:
04923 case LEGS_S4_LUP3:
04924 case LEGS_S4_LUP4:
04925 case LEGS_S4_LUP5:
04926 case LEGS_S4_RUP1:
04927 case LEGS_S4_RUP2:
04928 case LEGS_S4_RUP3:
04929 case LEGS_S4_RUP4:
04930 case LEGS_S4_RUP5:
04931 destAnim = LEGS_S4_LUP1 + (destAnim-LEGS_LEFTUP1);
04932 break;
04933 case BOTH_STAND5:
04934 case LEGS_S5_LUP1:
04935 case LEGS_S5_LUP2:
04936 case LEGS_S5_LUP3:
04937 case LEGS_S5_LUP4:
04938 case LEGS_S5_LUP5:
04939 case LEGS_S5_RUP1:
04940 case LEGS_S5_RUP2:
04941 case LEGS_S5_RUP3:
04942 case LEGS_S5_RUP4:
04943 case LEGS_S5_RUP5:
04944 destAnim = LEGS_S5_LUP1 + (destAnim-LEGS_LEFTUP1);
04945 break;
04946 case BOTH_STAND6:
04947 default:
04948 return qfalse;
04949 break;
04950 }
04951
04952
04953
04954 if ( (legsAnim >= LEGS_LEFTUP1 && legsAnim <= LEGS_LEFTUP5)
04955 || (legsAnim >= LEGS_S1_LUP1 && legsAnim <= LEGS_S1_LUP5)
04956 || (legsAnim >= LEGS_S3_LUP1 && legsAnim <= LEGS_S3_LUP5)
04957 || (legsAnim >= LEGS_S4_LUP1 && legsAnim <= LEGS_S4_LUP5)
04958 || (legsAnim >= LEGS_S5_LUP1 && legsAnim <= LEGS_S5_LUP5) )
04959 {
04960 if ( destAnim > legsAnim && SLOPERECALCVAR < pm->cmd.serverTime )
04961 {
04962 legsAnim++;
04963 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
04964 }
04965 else if ( destAnim < legsAnim && SLOPERECALCVAR < pm->cmd.serverTime )
04966 {
04967 legsAnim--;
04968 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
04969 }
04970 else
04971 {
04972 legsAnim = destAnim;
04973 }
04974
04975 destAnim = legsAnim;
04976 }
04977 else if ( (legsAnim >= LEGS_RIGHTUP1 && legsAnim <= LEGS_RIGHTUP5)
04978 || (legsAnim >= LEGS_S1_RUP1 && legsAnim <= LEGS_S1_RUP5)
04979 || (legsAnim >= LEGS_S3_RUP1 && legsAnim <= LEGS_S3_RUP5)
04980 || (legsAnim >= LEGS_S4_RUP1 && legsAnim <= LEGS_S4_RUP5)
04981 || (legsAnim >= LEGS_S5_RUP1 && legsAnim <= LEGS_S5_RUP5) )
04982 {
04983 if ( destAnim > legsAnim && SLOPERECALCVAR < pm->cmd.serverTime )
04984 {
04985 legsAnim++;
04986 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
04987 }
04988 else if ( destAnim < legsAnim && SLOPERECALCVAR < pm->cmd.serverTime )
04989 {
04990 legsAnim--;
04991 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
04992 }
04993 else
04994 {
04995 legsAnim = destAnim;
04996 }
04997
04998 destAnim = legsAnim;
04999 }
05000 else
05001 {
05002 switch ( legsAnim )
05003 {
05004 case BOTH_STAND1:
05005 case TORSO_WEAPONREADY1:
05006 case TORSO_WEAPONREADY2:
05007 case TORSO_WEAPONREADY3:
05008 case TORSO_WEAPONREADY10:
05009
05010 if ( destAnim >= LEGS_S1_LUP1 && destAnim <= LEGS_S1_LUP5 )
05011 {
05012 destAnim = LEGS_S1_LUP1;
05013 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05014 }
05015 else if ( destAnim >= LEGS_S1_RUP1 && destAnim <= LEGS_S1_RUP5 )
05016 {
05017 destAnim = LEGS_S1_RUP1;
05018 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05019 }
05020 else
05021 {
05022 return qfalse;
05023 }
05024 break;
05025 case BOTH_STAND2:
05026 case BOTH_SABERFAST_STANCE:
05027 case BOTH_SABERSLOW_STANCE:
05028 case BOTH_CROUCH1IDLE:
05029 if ( destAnim >= LEGS_LEFTUP1 && destAnim <= LEGS_LEFTUP5 )
05030 {
05031 destAnim = LEGS_LEFTUP1;
05032 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05033 }
05034 else if ( destAnim >= LEGS_RIGHTUP1 && destAnim <= LEGS_RIGHTUP5 )
05035 {
05036 destAnim = LEGS_RIGHTUP1;
05037 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05038 }
05039 else
05040 {
05041 return qfalse;
05042 }
05043 break;
05044 case BOTH_STAND3:
05045 if ( destAnim >= LEGS_S3_LUP1 && destAnim <= LEGS_S3_LUP5 )
05046 {
05047 destAnim = LEGS_S3_LUP1;
05048 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05049 }
05050 else if ( destAnim >= LEGS_S3_RUP1 && destAnim <= LEGS_S3_RUP5 )
05051 {
05052 destAnim = LEGS_S3_RUP1;
05053 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05054 }
05055 else
05056 {
05057 return qfalse;
05058 }
05059 break;
05060 case BOTH_STAND4:
05061 if ( destAnim >= LEGS_S4_LUP1 && destAnim <= LEGS_S4_LUP5 )
05062 {
05063 destAnim = LEGS_S4_LUP1;
05064 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05065 }
05066 else if ( destAnim >= LEGS_S4_RUP1 && destAnim <= LEGS_S4_RUP5 )
05067 {
05068 destAnim = LEGS_S4_RUP1;
05069 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05070 }
05071 else
05072 {
05073 return qfalse;
05074 }
05075 break;
05076 case BOTH_STAND5:
05077 if ( destAnim >= LEGS_S5_LUP1 && destAnim <= LEGS_S5_LUP5 )
05078 {
05079 destAnim = LEGS_S5_LUP1;
05080 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05081 }
05082 else if ( destAnim >= LEGS_S5_RUP1 && destAnim <= LEGS_S5_RUP5 )
05083 {
05084 destAnim = LEGS_S5_RUP1;
05085 SLOPERECALCVAR = pm->cmd.serverTime + SLOPE_RECALC_INT;
05086 }
05087 else
05088 {
05089 return qfalse;
05090 }
05091 break;
05092 case BOTH_STAND6:
05093 default:
05094 return qfalse;
05095 break;
05096 }
05097 }
05098
05099
05100 PM_ContinueLegsAnim(destAnim);
05101
05102 return qtrue;
05103 }
05104
05105 extern int WeaponReadyLegsAnim[WP_NUM_WEAPONS];
05106
05107
05108 int PM_LegsSlopeBackTransition(int desiredAnim)
05109 {
05110 int anim = pm->ps->legsAnim;
05111 int resultingAnim = desiredAnim;
05112
05113 switch ( anim )
05114 {
05115 case LEGS_LEFTUP2:
05116 case LEGS_LEFTUP3:
05117 case LEGS_LEFTUP4:
05118 case LEGS_LEFTUP5:
05119 case LEGS_RIGHTUP2:
05120 case LEGS_RIGHTUP3:
05121 case LEGS_RIGHTUP4:
05122 case LEGS_RIGHTUP5:
05123 case LEGS_S1_LUP2:
05124 case LEGS_S1_LUP3:
05125 case LEGS_S1_LUP4:
05126 case LEGS_S1_LUP5:
05127 case LEGS_S1_RUP2:
05128 case LEGS_S1_RUP3:
05129 case LEGS_S1_RUP4:
05130 case LEGS_S1_RUP5:
05131 case LEGS_S3_LUP2:
05132 case LEGS_S3_LUP3:
05133 case LEGS_S3_LUP4:
05134 case LEGS_S3_LUP5:
05135 case LEGS_S3_RUP2:
05136 case LEGS_S3_RUP3:
05137 case LEGS_S3_RUP4:
05138 case LEGS_S3_RUP5:
05139 case LEGS_S4_LUP2:
05140 case LEGS_S4_LUP3:
05141 case LEGS_S4_LUP4:
05142 case LEGS_S4_LUP5:
05143 case LEGS_S4_RUP2:
05144 case LEGS_S4_RUP3:
05145 case LEGS_S4_RUP4:
05146 case LEGS_S4_RUP5:
05147 case LEGS_S5_LUP2:
05148 case LEGS_S5_LUP3:
05149 case LEGS_S5_LUP4:
05150 case LEGS_S5_LUP5:
05151 case LEGS_S5_RUP2:
05152 case LEGS_S5_RUP3:
05153 case LEGS_S5_RUP4:
05154 case LEGS_S5_RUP5:
05155 if (pm->ps->slopeRecalcTime < pm->cmd.serverTime)
05156 {
05157 resultingAnim = anim-1;
05158 pm->ps->slopeRecalcTime = pm->cmd.serverTime + 8;
05159 }
05160 else
05161 {
05162 resultingAnim = anim;
05163 }
05164 VectorClear(pm->ps->velocity);
05165 break;
05166 }
05167
05168 return resultingAnim;
05169 }
05170
05171
05172
05173
05174
05175
05176 static void PM_Footsteps( void ) {
05177 float bobmove;
05178 int old;
05179 qboolean footstep;
05180 int setAnimFlags = 0;
05181
05182 if ( (PM_InSaberAnim( (pm->ps->legsAnim) ) && !BG_SpinningSaberAnim( (pm->ps->legsAnim) ))
05183 || (pm->ps->legsAnim) == BOTH_STAND1
05184 || (pm->ps->legsAnim) == BOTH_STAND1TO2
05185 || (pm->ps->legsAnim) == BOTH_STAND2TO1
05186 || (pm->ps->legsAnim) == BOTH_STAND2
05187 || (pm->ps->legsAnim) == BOTH_SABERFAST_STANCE
05188 || (pm->ps->legsAnim) == BOTH_SABERSLOW_STANCE
05189 || (pm->ps->legsAnim) == BOTH_BUTTON_HOLD
05190 || (pm->ps->legsAnim) == BOTH_BUTTON_RELEASE
05191 || PM_LandingAnim( (pm->ps->legsAnim) )
05192 || PM_PainAnim( (pm->ps->legsAnim) ))
05193 {
05194 setAnimFlags |= SETANIM_FLAG_OVERRIDE;
05195 }
05196
05197
05198
05199
05200
05201 pm->xyspeed = sqrt( pm->ps->velocity[0] * pm->ps->velocity[0]
05202 + pm->ps->velocity[1] * pm->ps->velocity[1] );
05203
05204 if (pm->ps->saberMove == LS_SPINATTACK)
05205 {
05206 PM_ContinueLegsAnim( pm->ps->torsoAnim );
05207 }
05208 else if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) {
05209
05210
05211 if ( pm->waterlevel > 1 )
05212 {
05213 if (pm->xyspeed > 60)
05214 {
05215 PM_ContinueLegsAnim( BOTH_SWIMFORWARD );
05216 }
05217 else
05218 {
05219 PM_ContinueLegsAnim( BOTH_SWIM_IDLE1 );
05220 }
05221 }
05222 return;
05223 }
05224
05225 else if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) {
05226 if ( pm->xyspeed < 5 ) {
05227 pm->ps->bobCycle = 0;
05228 if ( pm->ps->clientNum >= MAX_CLIENTS &&
05229 pm_entSelf &&
05230 pm_entSelf->s.NPC_class == CLASS_RANCOR )
05231 {
05232 if ( (pm->ps->eFlags2&EF2_USE_ALT_ANIM) )
05233 {
05234 PM_ContinueLegsAnim( BOTH_STAND4 );
05235
05236 }
05237 else if ( (pm->ps->eFlags2&EF2_ALERTED) )
05238 {
05239 PM_ContinueLegsAnim( BOTH_STAND2 );
05240
05241 }
05242 else
05243 {
05244 PM_ContinueLegsAnim( BOTH_STAND1 );
05245
05246 }
05247 }
05248 else if ( pm->ps->clientNum >= MAX_CLIENTS &&
05249 pm_entSelf &&
05250 pm_entSelf->s.NPC_class == CLASS_WAMPA )
05251 {
05252 if ( (pm->ps->eFlags2&EF2_USE_ALT_ANIM) )
05253 {
05254 PM_ContinueLegsAnim( BOTH_STAND2 );
05255
05256 }
05257 else
05258 {
05259 PM_ContinueLegsAnim( BOTH_STAND1 );
05260
05261 }
05262 }
05263 else if ( (pm->ps->pm_flags & PMF_DUCKED) || (pm->ps->pm_flags & PMF_ROLLING) ) {
05264 if ((pm->ps->legsAnim) != BOTH_CROUCH1IDLE)
05265 {
05266 PM_SetAnim(SETANIM_LEGS, BOTH_CROUCH1IDLE, setAnimFlags, 100);
05267 }
05268 else
05269 {
05270 PM_ContinueLegsAnim( BOTH_CROUCH1IDLE );
05271 }
05272 } else {
05273 if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
05274 {
05276
05277 PM_ContinueLegsAnim( TORSO_WEAPONREADY4 );
05278 }
05279 else
05280 {
05281 if (pm->ps->weapon == WP_SABER && BG_SabersOff( pm->ps ) )
05282 {
05283 if (!PM_AdjustStandAnimForSlope())
05284 {
05285
05286 PM_ContinueLegsAnim(PM_LegsSlopeBackTransition(BOTH_STAND1));
05287 }
05288 }
05289 else
05290 {
05291 if (pm->ps->weapon != WP_SABER || !PM_AdjustStandAnimForSlope())
05292 {
05293 if (pm->ps->weapon == WP_SABER)
05294 {
05295 PM_ContinueLegsAnim(PM_LegsSlopeBackTransition(PM_GetSaberStance()));
05296 }
05297 else
05298 {
05299 PM_ContinueLegsAnim(PM_LegsSlopeBackTransition(WeaponReadyLegsAnim[pm->ps->weapon]));
05300 }
05301 }
05302 }
05303 }
05304 }
05305 }
05306 return;
05307 }
05308
05309
05310 footstep = qfalse;
05311
05312 if (pm->ps->saberMove == LS_SPINATTACK)
05313 {
05314 bobmove = 0.2f;
05315 PM_ContinueLegsAnim( pm->ps->torsoAnim );
05316 }
05317 else if ( pm->ps->pm_flags & PMF_DUCKED )
05318 {
05319 int rolled = 0;
05320
05321 bobmove = 0.5;
05322
05323 if ( ( (PM_RunningAnim( pm->ps->legsAnim )&&VectorLengthSquared(pm->ps->velocity)>=40000) || PM_CanRollFromSoulCal( pm->ps ) ) &&
05324 !BG_InRoll(pm->ps, pm->ps->legsAnim) )
05325 {
05326 rolled = PM_TryRoll();
05327 }
05328 if ( !rolled )
05329 {
05330 if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) {
05331 if ((pm->ps->legsAnim) != BOTH_CROUCH1WALKBACK)
05332 {
05333 PM_SetAnim(SETANIM_LEGS, BOTH_CROUCH1WALKBACK, setAnimFlags, 100);
05334 }
05335 else
05336 {
05337 PM_ContinueLegsAnim( BOTH_CROUCH1WALKBACK );
05338 }
05339 }
05340 else {
05341 if ((pm->ps->legsAnim) != BOTH_CROUCH1WALK)
05342 {
05343 PM_SetAnim(SETANIM_LEGS, BOTH_CROUCH1WALK, setAnimFlags, 100);
05344 }
05345 else
05346 {
05347 PM_ContinueLegsAnim( BOTH_CROUCH1WALK );
05348 }
05349 }
05350 }
05351 else
05352 {
05353 pm->ps->legsTimer = 0;
05354 pm->ps->legsAnim = 0;
05355 PM_SetAnim(SETANIM_BOTH,rolled,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
05356 PM_AddEventWithParm( EV_ROLL, 0 );
05357 pm->maxs[2] = pm->ps->crouchheight;
05358 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
05359 pm->ps->pm_flags &= ~PMF_DUCKED;
05360 pm->ps->pm_flags |= PMF_ROLLING;
05361 }
05362 }
05363 else if ((pm->ps->pm_flags & PMF_ROLLING) && !BG_InRoll(pm->ps, pm->ps->legsAnim) &&
05364 !PM_InRollComplete(pm->ps, pm->ps->legsAnim))
05365 {
05366 bobmove = 0.5;
05367
05368 if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
05369 {
05370 if ((pm->ps->legsAnim) != BOTH_CROUCH1WALKBACK)
05371 {
05372 PM_SetAnim(SETANIM_LEGS, BOTH_CROUCH1WALKBACK, setAnimFlags, 100);
05373 }
05374 else
05375 {
05376 PM_ContinueLegsAnim( BOTH_CROUCH1WALKBACK );
05377 }
05378 }
05379 else
05380 {
05381 if ((pm->ps->legsAnim) != BOTH_CROUCH1WALK)
05382 {
05383 PM_SetAnim(SETANIM_LEGS, BOTH_CROUCH1WALK, setAnimFlags, 100);
05384 }
05385 else
05386 {
05387 PM_ContinueLegsAnim( BOTH_CROUCH1WALK );
05388 }
05389 }
05390 }
05391 else
05392 {
05393 int desiredAnim = -1;
05394
05395 if ((pm->ps->legsAnim == BOTH_FORCELAND1 ||
05396 pm->ps->legsAnim == BOTH_FORCELANDBACK1 ||
05397 pm->ps->legsAnim == BOTH_FORCELANDRIGHT1 ||
05398 pm->ps->legsAnim == BOTH_FORCELANDLEFT1) &&
05399 pm->ps->legsTimer > 0)
05400 {
05401 bobmove = 0.2f;
05402 }
05403 else if ( !( pm->cmd.buttons & BUTTON_WALKING ) )
05404 {
05405 bobmove = 0.4f;
05406 if ( pm->ps->clientNum >= MAX_CLIENTS &&
05407 pm_entSelf &&
05408 pm_entSelf->s.NPC_class == CLASS_WAMPA )
05409 {
05410 if ( (pm->ps->eFlags2&EF2_USE_ALT_ANIM) )
05411 {
05412 desiredAnim = BOTH_RUN1;
05413 }
05414 else
05415 {
05416 desiredAnim = BOTH_RUN2;
05417 }
05418 }
05419 else if ( pm->ps->clientNum >= MAX_CLIENTS &&
05420 pm_entSelf &&
05421 pm_entSelf->s.NPC_class == CLASS_RANCOR )
05422 {
05423 if ( (pm->ps->pm_flags&PMF_BACKWARDS_RUN) )
05424 {
05425 desiredAnim = BOTH_WALKBACK1;
05426 }
05427 else
05428 {
05429 desiredAnim = BOTH_WALK1;
05430 }
05431 }
05432 else if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
05433 {
05434 switch (pm->ps->fd.saberAnimLevel)
05435 {
05436 case SS_STAFF:
05437 if ( pm->ps->saberHolstered > 1 )
05438 {
05439 desiredAnim = BOTH_RUNBACK1;
05440 }
05441 else
05442 {
05443
05444
05445 desiredAnim = BOTH_RUNBACK2;
05446 }
05447 break;
05448 case SS_DUAL:
05449 if ( pm->ps->saberHolstered > 1 )
05450 {
05451 desiredAnim = BOTH_RUNBACK1;
05452 }
05453 else
05454 {
05455
05456
05457 desiredAnim = BOTH_RUNBACK2;
05458 }
05459 break;
05460 default:
05461 if ( pm->ps->saberHolstered )
05462 {
05463 desiredAnim = BOTH_RUNBACK1;
05464 }
05465 else
05466 {
05467 desiredAnim = BOTH_RUNBACK2;
05468 }
05469 break;
05470 }
05471 }
05472 else
05473 {
05474 switch (pm->ps->fd.saberAnimLevel)
05475 {
05476 case SS_STAFF:
05477 if ( pm->ps->saberHolstered > 1 )
05478 {
05479 desiredAnim = BOTH_RUN1;
05480 }
05481 else if ( pm->ps->saberHolstered == 1 )
05482 {
05483 desiredAnim = BOTH_RUN2;
05484 }
05485 else
05486 {
05487 if (pm->ps->fd.forcePowersActive & (1<<FP_SPEED))
05488 {
05489 desiredAnim = BOTH_RUN1;
05490 }
05491 else
05492 {
05493 desiredAnim = BOTH_RUN_STAFF;
05494 }
05495 }
05496 break;
05497 case SS_DUAL:
05498 if ( pm->ps->saberHolstered > 1 )
05499 {
05500 desiredAnim = BOTH_RUN1;
05501 }
05502 else if ( pm->ps->saberHolstered == 1 )
05503 {
05504 desiredAnim = BOTH_RUN2;
05505 }
05506 else
05507 {
05508 desiredAnim = BOTH_RUN_DUAL;
05509 }
05510 break;
05511 default:
05512 if ( pm->ps->saberHolstered )
05513 {
05514 desiredAnim = BOTH_RUN1;
05515 }
05516 else
05517 {
05518 desiredAnim = BOTH_RUN2;
05519 }
05520 break;
05521 }
05522 }
05523 footstep = qtrue;
05524 }
05525 else
05526 {
05527 bobmove = 0.2f;
05528 if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
05529 {
05530 switch (pm->ps->fd.saberAnimLevel)
05531 {
05532 case SS_STAFF:
05533 if ( pm->ps->saberHolstered > 1 )
05534 {
05535 desiredAnim = BOTH_WALKBACK1;
05536 }
05537 else if ( pm->ps->saberHolstered )
05538 {
05539 desiredAnim = BOTH_WALKBACK2;
05540 }
05541 else
05542 {
05543 desiredAnim = BOTH_WALKBACK_STAFF;
05544 }
05545 break;
05546 case SS_DUAL:
05547 if ( pm->ps->saberHolstered > 1 )
05548 {
05549 desiredAnim = BOTH_WALKBACK1;
05550 }
05551 else if ( pm->ps->saberHolstered )
05552 {
05553 desiredAnim = BOTH_WALKBACK2;
05554 }
05555 else
05556 {
05557 desiredAnim = BOTH_WALKBACK_DUAL;
05558 }
05559 break;
05560 default:
05561 if ( pm->ps->saberHolstered )
05562 {
05563 desiredAnim = BOTH_WALKBACK1;
05564 }
05565 else
05566 {
05567 desiredAnim = BOTH_WALKBACK2;
05568 }
05569 break;
05570 }
05571 }
05572 else
05573 {
05574 if ( pm->ps->weapon == WP_MELEE )
05575 {
05576 desiredAnim = BOTH_WALK1;
05577 }
05578 else if ( BG_SabersOff( pm->ps ) )
05579 {
05580 desiredAnim = BOTH_WALK1;
05581 }
05582 else
05583 {
05584 switch (pm->ps->fd.saberAnimLevel)
05585 {
05586 case SS_STAFF:
05587 if ( pm->ps->saberHolstered > 1 )
05588 {
05589 desiredAnim = BOTH_WALK1;
05590 }
05591 else if ( pm->ps->saberHolstered )
05592 {
05593 desiredAnim = BOTH_WALK2;
05594 }
05595 else
05596 {
05597 desiredAnim = BOTH_WALK_STAFF;
05598 }
05599 break;
05600 case SS_DUAL:
05601 if ( pm->ps->saberHolstered > 1 )
05602 {
05603 desiredAnim = BOTH_WALK1;
05604 }
05605 else if ( pm->ps->saberHolstered )
05606 {
05607 desiredAnim = BOTH_WALK2;
05608 }
05609 else
05610 {
05611 desiredAnim = BOTH_WALK_DUAL;
05612 }
05613 break;
05614 default:
05615 if ( pm->ps->saberHolstered )
05616 {
05617 desiredAnim = BOTH_WALK1;
05618 }
05619 else
05620 {
05621 desiredAnim = BOTH_WALK2;
05622 }
05623 break;
05624 }
05625 }
05626 }
05627 }
05628
05629 if (desiredAnim != -1)
05630 {
05631 int ires = PM_LegsSlopeBackTransition(desiredAnim);
05632
05633 if ((pm->ps->legsAnim) != desiredAnim && ires == desiredAnim)
05634 {
05635 PM_SetAnim(SETANIM_LEGS, desiredAnim, setAnimFlags, 100);
05636 }
05637 else
05638 {
05639 PM_ContinueLegsAnim(ires);
05640 }
05641 }
05642 }
05643
05644
05645 old = pm->ps->bobCycle;
05646 pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255;
05647
05648
05649 if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 )
05650 {
05651 pm->ps->footstepTime = pm->cmd.serverTime + 300;
05652 if ( pm->waterlevel == 1 ) {
05653
05654 PM_AddEvent( EV_FOOTSPLASH );
05655 } else if ( pm->waterlevel == 2 ) {
05656
05657 PM_AddEvent( EV_SWIM );
05658 } else if ( pm->waterlevel == 3 ) {
05659
05660 }
05661 }
05662 }
05663
05664
05665
05666
05667
05668
05669
05670
05671 static void PM_WaterEvents( void ) {
05672 #ifdef QAGAME
05673 qboolean impact_splash = qfalse;
05674 #endif
05675
05676
05677
05678 if (!pml.previous_waterlevel && pm->waterlevel) {
05679 #ifdef QAGAME
05680 if ( VectorLengthSquared( pm->ps->velocity ) > 40000 )
05681 {
05682 impact_splash = qtrue;
05683 }
05684 #endif
05685 PM_AddEvent( EV_WATER_TOUCH );
05686 }
05687
05688
05689
05690
05691 if (pml.previous_waterlevel && !pm->waterlevel) {
05692 #ifdef QAGAME
05693 if ( VectorLengthSquared( pm->ps->velocity ) > 40000 )
05694 {
05695 impact_splash = qtrue;
05696 }
05697 #endif
05698 PM_AddEvent( EV_WATER_LEAVE );
05699 }
05700
05701 #ifdef QAGAME
05702 if ( impact_splash )
05703 {
05704
05705 trace_t tr;
05706 vec3_t start, end;
05707
05708
05709 VectorCopy( pm->ps->origin, start );
05710 VectorCopy( pm->ps->origin, end );
05711
05712
05713 start[2] += 10;
05714 end[2] -= 40;
05715
05716 pm->trace( &tr, start, vec3_origin, vec3_origin, end, pm->ps->clientNum, MASK_WATER );
05717
05718 if ( tr.fraction < 1.0f )
05719 {
05720 if ( (tr.contents&CONTENTS_LAVA) )
05721 {
05722 G_PlayEffect( EFFECT_LAVA_SPLASH, tr.endpos, tr.plane.normal );
05723 }
05724 else if ( (tr.contents&CONTENTS_SLIME) )
05725 {
05726 G_PlayEffect( EFFECT_ACID_SPLASH, tr.endpos, tr.plane.normal );
05727 }
05728 else
05729 {
05730 G_PlayEffect( EFFECT_WATER_SPLASH, tr.endpos, tr.plane.normal );
05731 }
05732 }
05733 }
05734 #endif
05735
05736
05737
05738
05739 if (pml.previous_waterlevel != 3 && pm->waterlevel == 3) {
05740 PM_AddEvent( EV_WATER_UNDER );
05741 }
05742
05743
05744
05745
05746 if (pml.previous_waterlevel == 3 && pm->waterlevel != 3) {
05747 PM_AddEvent( EV_WATER_CLEAR );
05748 }
05749 }
05750
05751 void BG_ClearRocketLock( playerState_t *ps )
05752 {
05753 if ( ps )
05754 {
05755 ps->rocketLockIndex = ENTITYNUM_NONE;
05756 ps->rocketLastValidTime = 0;
05757 ps->rocketLockTime = -1;
05758 ps->rocketTargetTime = 0;
05759 }
05760 }
05761
05762
05763
05764
05765
05766
05767 void PM_BeginWeaponChange( int weapon ) {
05768 if ( weapon <= WP_NONE || weapon >= WP_NUM_WEAPONS ) {
05769 return;
05770 }
05771
05772 if ( !( pm->ps->stats[STAT_WEAPONS] & ( 1 << weapon ) ) ) {
05773 return;
05774 }
05775
05776 if ( pm->ps->weaponstate == WEAPON_DROPPING ) {
05777 return;
05778 }
05779
05780
05781 if (pm->ps->zoomMode)
05782 {
05783 pm->ps->zoomMode = 0;
05784 pm->ps->zoomTime = pm->ps->commandTime;
05785 }
05786
05787 PM_AddEventWithParm( EV_CHANGE_WEAPON, weapon );
05788 pm->ps->weaponstate = WEAPON_DROPPING;
05789 pm->ps->weaponTime += 200;
05790
05791 PM_SetAnim(SETANIM_TORSO, TORSO_DROPWEAP1, SETANIM_FLAG_OVERRIDE, 0);
05792
05793 BG_ClearRocketLock( pm->ps );
05794 }
05795
05796
05797
05798
05799
05800
05801
05802 void PM_FinishWeaponChange( void ) {
05803 int weapon;
05804
05805 weapon = pm->cmd.weapon;
05806 if ( weapon < WP_NONE || weapon >= WP_NUM_WEAPONS ) {
05807 weapon = WP_NONE;
05808 }
05809
05810 if ( !( pm->ps->stats[STAT_WEAPONS] & ( 1 << weapon ) ) ) {
05811 weapon = WP_NONE;
05812 }
05813
05814 if (weapon == WP_SABER)
05815 {
05816 PM_SetSaberMove(LS_DRAW);
05817 }
05818 else
05819 {
05820
05821 PM_SetAnim(SETANIM_TORSO, TORSO_RAISEWEAP1, SETANIM_FLAG_OVERRIDE, 0);
05822 }
05823 pm->ps->weapon = weapon;
05824 pm->ps->weaponstate = WEAPON_RAISING;
05825 pm->ps->weaponTime += 250;
05826 }
05827
05828 #ifdef QAGAME
05829 extern void WP_GetVehicleCamPos( gentity_t *ent, gentity_t *pilot, vec3_t camPos );
05830 #else
05831 extern void CG_GetVehicleCamPos( vec3_t camPos );
05832 #endif
05833 #define MAX_XHAIR_DIST_ACCURACY 20000.0f
05834 int BG_VehTraceFromCamPos( trace_t *camTrace, bgEntity_t *bgEnt, const vec3_t entOrg, const vec3_t shotStart, const vec3_t end, vec3_t newEnd, vec3_t shotDir, float bestDist )
05835 {
05836
05837 vec3_t viewDir2End, extraEnd, camPos;
05838 float minAutoAimDist;
05839
05840 #ifdef QAGAME
05841 WP_GetVehicleCamPos( (gentity_t *)bgEnt, (gentity_t *)bgEnt->m_pVehicle->m_pPilot, camPos );
05842 #else
05843 CG_GetVehicleCamPos( camPos );
05844 #endif
05845
05846 minAutoAimDist = Distance( entOrg, camPos ) + (bgEnt->m_pVehicle->m_pVehicleInfo->length/2.0f) + 200.0f;
05847
05848 VectorCopy( end, newEnd );
05849 VectorSubtract( end, camPos, viewDir2End );
05850 VectorNormalize( viewDir2End );
05851 VectorMA( camPos, MAX_XHAIR_DIST_ACCURACY, viewDir2End, extraEnd );
05852
05853 #ifdef QAGAME
05854 trap_Trace( camTrace, camPos, vec3_origin, vec3_origin, extraEnd,
05855 bgEnt->s.number, CONTENTS_SOLID|CONTENTS_BODY );
05856 #else
05857 pm->trace( camTrace, camPos, vec3_origin, vec3_origin, extraEnd,
05858 bgEnt->s.number, CONTENTS_SOLID|CONTENTS_BODY );
05859 #endif
05860
05861 if ( !camTrace->allsolid
05862 && !camTrace->startsolid
05863 && camTrace->fraction < 1.0f
05864 && (camTrace->fraction*MAX_XHAIR_DIST_ACCURACY) > minAutoAimDist
05865 && ((camTrace->fraction*MAX_XHAIR_DIST_ACCURACY)-Distance( entOrg, camPos )) < bestDist )
05866 {
05867 VectorCopy( camTrace->endpos, newEnd );
05868 VectorSubtract( newEnd, shotStart, shotDir );
05869 VectorNormalize( shotDir );
05870 return (camTrace->entityNum+1);
05871 }
05872 return 0;
05873 }
05874
05875 void PM_RocketLock( float lockDist, qboolean vehicleLock )
05876 {
05877
05878
05879 vec3_t ang;
05880 trace_t tr;
05881
05882 vec3_t muzzleOffPoint, muzzlePoint, forward, right, up;
05883
05884 if ( vehicleLock )
05885 {
05886 AngleVectors( pm->ps->viewangles, forward, right, up );
05887 VectorCopy( pm->ps->origin, muzzlePoint );
05888 VectorMA( muzzlePoint, lockDist, forward, ang );
05889 }
05890 else
05891 {
05892 AngleVectors( pm->ps->viewangles, forward, right, up );
05893
05894 AngleVectors(pm->ps->viewangles, ang, NULL, NULL);
05895
05896 VectorCopy( pm->ps->origin, muzzlePoint );
05897 VectorCopy(WP_MuzzlePoint[WP_ROCKET_LAUNCHER], muzzleOffPoint);
05898
05899 VectorMA(muzzlePoint, muzzleOffPoint[0], forward, muzzlePoint);
05900 VectorMA(muzzlePoint, muzzleOffPoint[1], right, muzzlePoint);
05901 muzzlePoint[2] += pm->ps->viewheight + muzzleOffPoint[2];
05902 ang[0] = muzzlePoint[0] + ang[0]*lockDist;
05903 ang[1] = muzzlePoint[1] + ang[1]*lockDist;
05904 ang[2] = muzzlePoint[2] + ang[2]*lockDist;
05905 }
05906
05907
05908 pm->trace(&tr, muzzlePoint, NULL, NULL, ang, pm->ps->clientNum, MASK_PLAYERSOLID);
05909
05910 if ( vehicleLock )
05911 {
05912 if ( tr.fraction >= 1.0f )
05913 {
05914 trace_t camTrace;
05915 vec3_t newEnd, shotDir;
05916 if ( BG_VehTraceFromCamPos( &camTrace, PM_BGEntForNum(pm->ps->clientNum), pm->ps->origin, muzzlePoint, tr.endpos, newEnd, shotDir, (tr.fraction*lockDist) ) )
05917 {
05918 memcpy( &tr, &camTrace, sizeof(tr) );
05919 }
05920 }
05921 }
05922
05923 if (tr.fraction != 1 && tr.entityNum < ENTITYNUM_NONE && tr.entityNum != pm->ps->clientNum)
05924 {
05925 bgEntity_t *bgEnt = PM_BGEntForNum(tr.entityNum);
05926 if ( bgEnt && (bgEnt->s.powerups&PW_CLOAKED) )
05927 {
05928 pm->ps->rocketLockIndex = ENTITYNUM_NONE;
05929 pm->ps->rocketLockTime = 0;
05930 }
05931 else if (bgEnt && (bgEnt->s.eType == ET_PLAYER || bgEnt->s.eType == ET_NPC))
05932 {
05933 if (pm->ps->rocketLockIndex == ENTITYNUM_NONE)
05934 {
05935 pm->ps->rocketLockIndex = tr.entityNum;
05936 pm->ps->rocketLockTime = pm->cmd.serverTime;
05937 }
05938 else if (pm->ps->rocketLockIndex != tr.entityNum && pm->ps->rocketTargetTime < pm->cmd.serverTime)
05939 {
05940 pm->ps->rocketLockIndex = tr.entityNum;
05941 pm->ps->rocketLockTime = pm->cmd.serverTime;
05942 }
05943 else if (pm->ps->rocketLockIndex == tr.entityNum)
05944 {
05945 if (pm->ps->rocketLockTime == -1)
05946 {
05947 pm->ps->rocketLockTime = pm->ps->rocketLastValidTime;
05948 }
05949 }
05950
05951 if (pm->ps->rocketLockIndex == tr.entityNum)
05952 {
05953 pm->ps->rocketTargetTime = pm->cmd.serverTime + 500;
05954 }
05955 }
05956 else if (!vehicleLock)
05957 {
05958 if (pm->ps->rocketTargetTime < pm->cmd.serverTime)
05959 {
05960 pm->ps->rocketLockIndex = ENTITYNUM_NONE;
05961 pm->ps->rocketLockTime = 0;
05962 }
05963 }
05964 }
05965 else if (pm->ps->rocketTargetTime < pm->cmd.serverTime)
05966 {
05967 pm->ps->rocketLockIndex = ENTITYNUM_NONE;
05968 pm->ps->rocketLockTime = 0;
05969 }
05970 else
05971 {
05972 if (pm->ps->rocketLockTime != -1)
05973 {
05974 pm->ps->rocketLastValidTime = pm->ps->rocketLockTime;
05975 }
05976 pm->ps->rocketLockTime = -1;
05977 }
05978 }
05979
05980
05981 static qboolean PM_DoChargedWeapons( qboolean vehicleRocketLock, bgEntity_t *veh )
05982
05983 {
05984 qboolean charging = qfalse,
05985 altFire = qfalse;
05986
05987 if ( vehicleRocketLock )
05988 {
05989 if ( (pm->cmd.buttons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK)) )
05990 {
05991 if ( veh
05992 && veh->m_pVehicle )
05993 {
05994 if ( ( (pm->cmd.buttons&BUTTON_ATTACK)
05995 &&g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[0].ID].fHoming
05996 &&pm->ps->ammo[0]>=g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[0].ID].iAmmoPerShot )
05997 ||
05998 ( (pm->cmd.buttons&BUTTON_ALT_ATTACK)
05999 &&g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[1].ID].fHoming
06000 &&pm->ps->ammo[1]>=g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[1].ID].iAmmoPerShot ) )
06001 {
06002 PM_RocketLock(16384, qtrue);
06003 charging = qtrue;
06004 }
06005 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06006 {
06007 altFire = qtrue;
06008 }
06009 }
06010 }
06011
06012 }
06013 else
06014 {
06015
06016 switch( pm->ps->weapon )
06017 {
06018
06019 case WP_BRYAR_PISTOL:
06020
06021
06022
06023 if (1)
06024 {
06025 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06026 {
06027 charging = qtrue;
06028 altFire = qtrue;
06029 }
06030 }
06031 break;
06032
06033 case WP_CONCUSSION:
06034 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06035 {
06036 altFire = qtrue;
06037 }
06038 break;
06039
06040 case WP_BRYAR_OLD:
06041
06042
06043 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06044 {
06045 charging = qtrue;
06046 altFire = qtrue;
06047 }
06048 break;
06049
06050
06051 case WP_BOWCASTER:
06052
06053
06054 if ( pm->cmd.buttons & BUTTON_ATTACK )
06055 {
06056 charging = qtrue;
06057 }
06058 break;
06059
06060
06061 case WP_ROCKET_LAUNCHER:
06062 if ( (pm->cmd.buttons & BUTTON_ALT_ATTACK)
06063 && pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] >= weaponData[pm->ps->weapon].altEnergyPerShot )
06064 {
06065 PM_RocketLock(2048,qfalse);
06066 charging = qtrue;
06067 altFire = qtrue;
06068 }
06069 break;
06070
06071
06072 case WP_THERMAL:
06073
06074 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06075 {
06076 altFire = qtrue;
06077 charging = qtrue;
06078 }
06079 else if ( pm->cmd.buttons & BUTTON_ATTACK )
06080 {
06081 charging = qtrue;
06082 }
06083 break;
06084
06085 case WP_DEMP2:
06086 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06087 {
06088 altFire = qtrue;
06089 charging = qtrue;
06090 }
06091 break;
06092
06093 case WP_DISRUPTOR:
06094 if ((pm->cmd.buttons & BUTTON_ATTACK) &&
06095 pm->ps->zoomMode == 1 &&
06096 pm->ps->zoomLocked)
06097 {
06098 if (!pm->cmd.forwardmove &&
06099 !pm->cmd.rightmove &&
06100 pm->cmd.upmove <= 0)
06101 {
06102 charging = qtrue;
06103 altFire = qtrue;
06104 }
06105 else
06106 {
06107 charging = qfalse;
06108 altFire = qfalse;
06109 }
06110 }
06111
06112 if (pm->ps->zoomMode != 1 &&
06113 pm->ps->weaponstate == WEAPON_CHARGING_ALT)
06114 {
06115 pm->ps->weaponstate = WEAPON_READY;
06116 charging = qfalse;
06117 altFire = qfalse;
06118 }
06119
06120 }
06121 }
06122
06123
06124
06125 if ( charging )
06126 {
06127 if ( altFire )
06128 {
06129 if ( pm->ps->weaponstate != WEAPON_CHARGING_ALT )
06130 {
06131
06132 pm->ps->weaponstate = WEAPON_CHARGING_ALT;
06133 pm->ps->weaponChargeTime = pm->cmd.serverTime;
06134 pm->ps->weaponChargeSubtractTime = pm->cmd.serverTime + weaponData[pm->ps->weapon].altChargeSubTime;
06135
06136 #ifdef _DEBUG
06137 Com_Printf("Starting charge\n");
06138 #endif
06139 assert(pm->ps->weapon > WP_NONE);
06140 BG_AddPredictableEventToPlayerstate(EV_WEAPON_CHARGE_ALT, pm->ps->weapon, pm->ps);
06141 }
06142
06143 if ( vehicleRocketLock )
06144 {
06145 if ( veh && pm->ps->ammo[1] < g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[1].ID].iAmmoPerShot )
06146 {
06147 pm->ps->weaponstate = WEAPON_CHARGING_ALT;
06148 goto rest;
06149 }
06150 }
06151 else if (pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] < (weaponData[pm->ps->weapon].altChargeSub+weaponData[pm->ps->weapon].altEnergyPerShot))
06152 {
06153 pm->ps->weaponstate = WEAPON_CHARGING_ALT;
06154
06155 goto rest;
06156 }
06157 else if ((pm->cmd.serverTime - pm->ps->weaponChargeTime) < weaponData[pm->ps->weapon].altMaxCharge)
06158 {
06159 if (pm->ps->weaponChargeSubtractTime < pm->cmd.serverTime)
06160 {
06161 pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] -= weaponData[pm->ps->weapon].altChargeSub;
06162 pm->ps->weaponChargeSubtractTime = pm->cmd.serverTime + weaponData[pm->ps->weapon].altChargeSubTime;
06163 }
06164 }
06165 }
06166 else
06167 {
06168 if ( pm->ps->weaponstate != WEAPON_CHARGING )
06169 {
06170
06171 pm->ps->weaponstate = WEAPON_CHARGING;
06172 pm->ps->weaponChargeTime = pm->cmd.serverTime;
06173 pm->ps->weaponChargeSubtractTime = pm->cmd.serverTime + weaponData[pm->ps->weapon].chargeSubTime;
06174
06175 #ifdef _DEBUG
06176 Com_Printf("Starting charge\n");
06177 #endif
06178 BG_AddPredictableEventToPlayerstate(EV_WEAPON_CHARGE, pm->ps->weapon, pm->ps);
06179 }
06180
06181 if ( vehicleRocketLock )
06182 {
06183 if ( veh && pm->ps->ammo[0] < g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[0].ID].iAmmoPerShot )
06184 {
06185 pm->ps->weaponstate = WEAPON_CHARGING;
06186 goto rest;
06187 }
06188 }
06189 else if (pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] < (weaponData[pm->ps->weapon].chargeSub+weaponData[pm->ps->weapon].energyPerShot))
06190 {
06191 pm->ps->weaponstate = WEAPON_CHARGING;
06192
06193 goto rest;
06194 }
06195 else if ((pm->cmd.serverTime - pm->ps->weaponChargeTime) < weaponData[pm->ps->weapon].maxCharge)
06196 {
06197 if (pm->ps->weaponChargeSubtractTime < pm->cmd.serverTime)
06198 {
06199 pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] -= weaponData[pm->ps->weapon].chargeSub;
06200 pm->ps->weaponChargeSubtractTime = pm->cmd.serverTime + weaponData[pm->ps->weapon].chargeSubTime;
06201 }
06202 }
06203 }
06204
06205 return qtrue;
06206 }
06207 rest:
06208
06209
06210 if ( pm->ps->weaponstate == WEAPON_CHARGING )
06211 {
06212
06213 #ifdef _DEBUG
06214 Com_Printf("Firing. Charge time=%d\n", pm->cmd.serverTime - pm->ps->weaponChargeTime);
06215 #endif
06216
06217
06218 pm->cmd.buttons |= BUTTON_ATTACK;
06219 pm->ps->eFlags |= EF_FIRING;
06220 }
06221 else if ( pm->ps->weaponstate == WEAPON_CHARGING_ALT )
06222 {
06223
06224 #ifdef _DEBUG
06225 Com_Printf("Firing. Charge time=%d\n", pm->cmd.serverTime - pm->ps->weaponChargeTime);
06226 #endif
06227
06228
06229 pm->cmd.buttons |= BUTTON_ALT_ATTACK;
06230 pm->ps->eFlags |= (EF_FIRING|EF_ALT_FIRING);
06231 }
06232
06233 return qfalse;
06234 }
06235
06236
06237 #define BOWCASTER_CHARGE_UNIT 200.0f // bowcaster charging gives us one more unit every 200ms--if you change this, you'll have to do the same in g_weapon
06238 #define BRYAR_CHARGE_UNIT 200.0f // bryar charging gives us one more unit every 200ms--if you change this, you'll have to do the same in g_weapon
06239
06240 int PM_ItemUsable(playerState_t *ps, int forcedUse)
06241 {
06242 vec3_t fwd, fwdorg, dest, pos;
06243 vec3_t yawonly;
06244 vec3_t mins, maxs;
06245 vec3_t trtest;
06246 trace_t tr;
06247
06248 if (ps->m_iVehicleNum)
06249 {
06250 return 0;
06251 }
06252
06253 if (ps->pm_flags & PMF_USE_ITEM_HELD)
06254 {
06255 return 0;
06256 }
06257
06258 if (ps->duelInProgress)
06259 {
06260 return 0;
06261 }
06262
06263 if (!forcedUse)
06264 {
06265 forcedUse = bg_itemlist[ps->stats[STAT_HOLDABLE_ITEM]].giTag;
06266 }
06267
06268 if (!BG_IsItemSelectable(ps, forcedUse))
06269 {
06270 return 0;
06271 }
06272
06273 switch (forcedUse)
06274 {
06275 case HI_MEDPAC:
06276 case HI_MEDPAC_BIG:
06277 if (ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH])
06278 {
06279 return 0;
06280 }
06281 if (ps->stats[STAT_HEALTH] <= 0 ||
06282 (ps->eFlags & EF_DEAD))
06283 {
06284 return 0;
06285 }
06286
06287 return 1;
06288 case HI_SEEKER:
06289 if (ps->eFlags & EF_SEEKERDRONE)
06290 {
06291 PM_AddEventWithParm(EV_ITEMUSEFAIL, SEEKER_ALREADYDEPLOYED);
06292 return 0;
06293 }
06294
06295 return 1;
06296 case HI_SENTRY_GUN:
06297 if (ps->fd.sentryDeployed)
06298 {
06299 PM_AddEventWithParm(EV_ITEMUSEFAIL, SENTRY_ALREADYPLACED);
06300 return 0;
06301 }
06302
06303 yawonly[ROLL] = 0;
06304 yawonly[PITCH] = 0;
06305 yawonly[YAW] = ps->viewangles[YAW];
06306
06307 VectorSet( mins, -8, -8, 0 );
06308 VectorSet( maxs, 8, 8, 24 );
06309
06310 AngleVectors(yawonly, fwd, NULL, NULL);
06311
06312 fwdorg[0] = ps->origin[0] + fwd[0]*64;
06313 fwdorg[1] = ps->origin[1] + fwd[1]*64;
06314 fwdorg[2] = ps->origin[2] + fwd[2]*64;
06315
06316 trtest[0] = fwdorg[0] + fwd[0]*16;
06317 trtest[1] = fwdorg[1] + fwd[1]*16;
06318 trtest[2] = fwdorg[2] + fwd[2]*16;
06319
06320 pm->trace(&tr, ps->origin, mins, maxs, trtest, ps->clientNum, MASK_PLAYERSOLID);
06321
06322 if ((tr.fraction != 1 && tr.entityNum != ps->clientNum) || tr.startsolid || tr.allsolid)
06323 {
06324 PM_AddEventWithParm(EV_ITEMUSEFAIL, SENTRY_NOROOM);
06325 return 0;
06326 }
06327
06328 return 1;
06329 case HI_SHIELD:
06330 mins[0] = -8;
06331 mins[1] = -8;
06332 mins[2] = 0;
06333
06334 maxs[0] = 8;
06335 maxs[1] = 8;
06336 maxs[2] = 8;
06337
06338 AngleVectors (ps->viewangles, fwd, NULL, NULL);
06339 fwd[2] = 0;
06340 VectorMA(ps->origin, 64, fwd, dest);
06341 pm->trace(&tr, ps->origin, mins, maxs, dest, ps->clientNum, MASK_SHOT );
06342 if (tr.fraction > 0.9 && !tr.startsolid && !tr.allsolid)
06343 {
06344 VectorCopy(tr.endpos, pos);
06345 VectorSet( dest, pos[0], pos[1], pos[2] - 4096 );
06346 pm->trace( &tr, pos, mins, maxs, dest, ps->clientNum, MASK_SOLID );
06347 if ( !tr.startsolid && !tr.allsolid )
06348 {
06349 return 1;
06350 }
06351 }
06352 PM_AddEventWithParm(EV_ITEMUSEFAIL, SHIELD_NOROOM);
06353 return 0;
06354 case HI_JETPACK:
06355 return 1;
06356 case HI_HEALTHDISP:
06357 return 1;
06358 case HI_AMMODISP:
06359 return 1;
06360 case HI_EWEB:
06361 return 1;
06362 case HI_CLOAK:
06363 return 1;
06364 default:
06365 return 1;
06366 }
06367 }
06368
06369
06370 qboolean PM_CanSetWeaponAnims(void)
06371 {
06372 if (pm->ps->m_iVehicleNum)
06373 {
06374 return qfalse;
06375 }
06376
06377 return qtrue;
06378 }
06379
06380
06381 extern int PM_irand_timesync(int val1, int val2);
06382 void PM_VehicleWeaponAnimate(void)
06383 {
06384 bgEntity_t *veh = pm_entVeh;
06385 Vehicle_t *pVeh;
06386 int iFlags = 0, iBlend = 0, Anim = -1;
06387
06388 if (!veh ||
06389 !veh->m_pVehicle ||
06390 !veh->m_pVehicle->m_pPilot ||
06391 !veh->m_pVehicle->m_pPilot->playerState ||
06392 pm->ps->clientNum != veh->m_pVehicle->m_pPilot->playerState->clientNum)
06393 {
06394 return;
06395 }
06396
06397 pVeh = veh->m_pVehicle;
06398
06399 if (pVeh->m_pVehicleInfo->type == VH_WALKER ||
06400 pVeh->m_pVehicleInfo->type == VH_FIGHTER)
06401 {
06402 return;
06403 }
06404 backAgain:
06405
06406 if ( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_ALT_ATTACK ) )
06407 {
06408 iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
06409 iBlend = 200;
06410
06411 switch ( pm->ps->weapon )
06412 {
06413 case WP_SABER:
06414 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
06415 {
06416 pm->cmd.buttons &= ~BUTTON_ALT_ATTACK;
06417 goto backAgain;
06418 }
06419
06420 if (pm->ps->torsoTimer <= 0)
06421 {
06422 PM_AddEvent(EV_SABER_ATTACK);
06423 }
06424
06425
06426
06427 pm->ps->saberMove = LS_R_TL2BR;
06428
06429 if ( pm->ps->torsoTimer > 0 && (pm->ps->torsoAnim == BOTH_VS_ATR_S ||
06430 pm->ps->torsoAnim == BOTH_VS_ATL_S) )
06431 {
06432
06433
06434
06435
06436
06437
06438 return;
06439 }
06440
06441
06442 if ( pm->cmd.rightmove > 0 )
06443 {
06444 Anim = BOTH_VS_ATR_S;
06445 }
06446 else if ( pm->cmd.rightmove < 0 )
06447 {
06448 Anim = BOTH_VS_ATL_S;
06449 }
06450 else
06451 {
06452
06453
06454 if (!PM_irand_timesync(0, 1))
06455 {
06456 Anim = BOTH_VS_ATR_S;
06457 }
06458 else
06459 {
06460 Anim = BOTH_VS_ATL_S;
06461 }
06462 }
06463
06464 if (pm->ps->torsoTimer <= 0)
06465 {
06466 iFlags |= SETANIM_FLAG_RESTART;
06467 }
06468 break;
06469
06470 case WP_BLASTER:
06471
06472 if ( pm->ps->torsoAnim == BOTH_ATTACK3 )
06473 {
06474 if ( pm->cmd.rightmove > 0 )
06475 {
06476 Anim = BOTH_VS_ATR_G;
06477 }
06478 else if ( pm->cmd.rightmove < 0 )
06479 {
06480 Anim = BOTH_VS_ATL_G;
06481 }
06482 else
06483 {
06484 Anim = BOTH_VS_ATF_G;
06485 }
06486 }
06487 break;
06488
06489 default:
06490 Anim = BOTH_VS_IDLE;
06491 break;
06492 }
06493 }
06494 else if (veh->playerState && veh->playerState->speed < 0 &&
06495 pVeh->m_pVehicleInfo->type == VH_ANIMAL)
06496 {
06497 Anim = BOTH_VT_WALK_REV;
06498 iBlend = 600;
06499 }
06500 else if (veh->playerState && veh->playerState->speed < 0 &&
06501 pVeh->m_pVehicleInfo->type == VH_SPEEDER)
06502 {
06503 Anim = BOTH_VS_REV;
06504 iBlend = 600;
06505 }
06506
06507 else
06508 {
06509 iFlags = SETANIM_FLAG_NORMAL;
06510
06511 switch ( pm->ps->weapon )
06512 {
06513 case WP_SABER:
06514 if ( BG_SabersOff( pm->ps ) )
06515 {
06516 Anim = BOTH_VS_IDLE;
06517 }
06518
06519
06520 else if (0)
06521 {
06522 iBlend = 800;
06523 Anim = BOTH_VS_AIR_G;
06524 iFlags = SETANIM_FLAG_OVERRIDE;
06525 }
06526
06527
06528 else if (0)
06529 {
06530 pVeh->m_ulFlags &= ~VEH_CRASHING;
06531 iBlend = 800;
06532 Anim = BOTH_VS_LAND_SR;
06533 iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
06534 }
06535 else
06536 {
06537 Anim = BOTH_VS_IDLE_SR;
06538 }
06539 break;
06540
06541 case WP_BLASTER:
06542
06543
06544 if (0)
06545 {
06546 iBlend = 800;
06547 Anim = BOTH_VS_AIR_G;
06548 iFlags = SETANIM_FLAG_OVERRIDE;
06549 }
06550
06551
06552 else if (0)
06553 {
06554 pVeh->m_ulFlags &= ~VEH_CRASHING;
06555 iBlend = 800;
06556 Anim = BOTH_VS_LAND_G;
06557 iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
06558 }
06559 else
06560 {
06561 Anim = BOTH_VS_IDLE_G;
06562 }
06563 break;
06564
06565 default:
06566 Anim = BOTH_VS_IDLE;
06567 break;
06568 }
06569 }
06570
06571 if (Anim != -1)
06572 {
06573 if (pVeh->m_pVehicleInfo->type == VH_ANIMAL)
06574 {
06575 switch (Anim)
06576 {
06577 case BOTH_VS_IDLE:
06578 if (veh->playerState && veh->playerState->speed > 0)
06579 {
06580 if (veh->playerState->speed > pVeh->m_pVehicleInfo->speedMax)
06581 {
06582 Anim = BOTH_VT_TURBO;
06583 }
06584 else
06585 {
06586 Anim = BOTH_VT_RUN_FWD;
06587 }
06588 }
06589 else
06590 {
06591 Anim = BOTH_VT_IDLE;
06592 }
06593 break;
06594 case BOTH_VS_ATR_S:
06595 Anim = BOTH_VT_ATR_S;
06596 break;
06597 case BOTH_VS_ATL_S:
06598 Anim = BOTH_VT_ATL_S;
06599 break;
06600 case BOTH_VS_ATR_G:
06601 Anim = BOTH_VT_ATR_G;
06602 break;
06603 case BOTH_VS_ATL_G:
06604 Anim = BOTH_VT_ATL_G;
06605 break;
06606 case BOTH_VS_ATF_G:
06607 Anim = BOTH_VT_ATF_G;
06608 break;
06609 case BOTH_VS_IDLE_SL:
06610 Anim = BOTH_VT_IDLE_S;
06611 break;
06612 case BOTH_VS_IDLE_SR:
06613 Anim = BOTH_VT_IDLE_S;
06614 break;
06615 case BOTH_VS_IDLE_G:
06616 Anim = BOTH_VT_IDLE_G;
06617 break;
06618
06619
06620 case BOTH_VS_AIR_G:
06621 case BOTH_VS_LAND_SL:
06622 case BOTH_VS_LAND_SR:
06623 case BOTH_VS_LAND_G:
06624 return;
06625 default:
06626 break;
06627 }
06628 }
06629
06630 PM_SetAnim(SETANIM_BOTH, Anim, iFlags, iBlend);
06631 }
06632 }
06633
06634
06635
06636
06637
06638
06639
06640
06641 extern int PM_KickMoveForConditions(void);
06642 static void PM_Weapon( void )
06643 {
06644 int addTime;
06645 int amount;
06646 int killAfterItem = 0;
06647 bgEntity_t *veh = NULL;
06648 qboolean vehicleRocketLock = qfalse;
06649
06650 #ifdef QAGAME
06651 if (pm->ps->clientNum >= MAX_CLIENTS &&
06652 pm->ps->weapon == WP_NONE &&
06653 pm->cmd.weapon == WP_NONE &&
06654 pm_entSelf)
06655 {
06656 gentity_t *gent = (gentity_t *)pm_entSelf;
06657 if (gent->inuse && gent->client &&
06658 !gent->localAnimIndex)
06659 {
06660 pm->ps->torsoAnim = pm->ps->legsAnim;
06661 pm->ps->torsoTimer = pm->ps->legsTimer;
06662 return;
06663 }
06664 }
06665 #endif
06666
06667 if (!pm->ps->emplacedIndex &&
06668 pm->ps->weapon == WP_EMPLACED_GUN)
06669 {
06670 int i = 0;
06671 int weap = -1;
06672
06673 while (i < WP_NUM_WEAPONS)
06674 {
06675 if ((pm->ps->stats[STAT_WEAPONS] & (1 << i)) && i != WP_NONE)
06676 {
06677 weap = i;
06678 break;
06679 }
06680 i++;
06681 }
06682
06683 if (weap != -1)
06684 {
06685 pm->cmd.weapon = weap;
06686 pm->ps->weapon = weap;
06687 return;
06688 }
06689 }
06690
06691 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
06692 &&pm->ps->m_iVehicleNum)
06693 {
06694 veh = pm_entVeh;
06695 if ( veh &&
06696 (veh->m_pVehicle && veh->m_pVehicle->m_pVehicleInfo->type == VH_WALKER || veh->m_pVehicle && veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER) )
06697 {
06698
06699 pm->ps->saberHolstered = 2;
06700 #ifdef QAGAME
06701 pm->cmd.buttons &= ~(BUTTON_ATTACK|BUTTON_ALT_ATTACK);
06702 #else
06703 if ( g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[0].ID].fHoming
06704 || g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[1].ID].fHoming )
06705 {
06706 vehicleRocketLock = qtrue;
06707 pm->cmd.buttons &= ~BUTTON_ATTACK;
06708 }
06709 else
06710 {
06711 pm->cmd.buttons &= ~(BUTTON_ATTACK|BUTTON_ALT_ATTACK);
06712 }
06713 #endif
06714 }
06715 }
06716
06717 if (pm->ps->weapon != WP_DISRUPTOR
06718 && pm->ps->weapon != WP_ROCKET_LAUNCHER
06719 && pm->ps->weapon != WP_THERMAL
06720 && !pm->ps->m_iVehicleNum )
06721 {
06722 if ( pm->ps->weaponstate == WEAPON_CHARGING_ALT )
06723 {
06724 int timeDif = (pm->cmd.serverTime - pm->ps->weaponChargeTime);
06725
06726 if (timeDif > MAX_WEAPON_CHARGE_TIME)
06727 {
06728 pm->cmd.buttons &= ~BUTTON_ALT_ATTACK;
06729 }
06730 }
06731
06732 if ( pm->ps->weaponstate == WEAPON_CHARGING )
06733 {
06734 int timeDif = (pm->cmd.serverTime - pm->ps->weaponChargeTime);
06735
06736 if (timeDif > MAX_WEAPON_CHARGE_TIME)
06737 {
06738 pm->cmd.buttons &= ~BUTTON_ATTACK;
06739 }
06740 }
06741 }
06742
06743 if (pm->ps->forceHandExtend == HANDEXTEND_WEAPONREADY &&
06744 PM_CanSetWeaponAnims())
06745 {
06746 if (pm->ps->weapon != WP_SABER && pm->ps->weapon != WP_MELEE && !PM_IsRocketTrooper())
06747 {
06748 if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
06749 {
06750
06751 PM_StartTorsoAnim( TORSO_RAISEWEAP1);
06752 }
06753 else
06754 {
06755 if (pm->ps->weapon == WP_EMPLACED_GUN)
06756 {
06757 PM_StartTorsoAnim( BOTH_GUNSIT1 );
06758 }
06759 else
06760 {
06761
06762 PM_StartTorsoAnim( TORSO_RAISEWEAP1);
06763 }
06764 }
06765 }
06766
06767
06768
06769 pm->ps->weaponstate = WEAPON_RAISING;
06770 pm->ps->weaponTime += 250;
06771
06772 pm->ps->forceHandExtend = HANDEXTEND_NONE;
06773 }
06774 else if (pm->ps->forceHandExtend != HANDEXTEND_NONE)
06775 {
06776 int desiredAnim = 0;
06777 qboolean seperateOnTorso = qfalse;
06778 qboolean playFullBody = qfalse;
06779 int desiredOnTorso = 0;
06780
06781 switch(pm->ps->forceHandExtend)
06782 {
06783 case HANDEXTEND_FORCEPUSH:
06784 desiredAnim = BOTH_FORCEPUSH;
06785 break;
06786 case HANDEXTEND_FORCEPULL:
06787 desiredAnim = BOTH_FORCEPULL;
06788 break;
06789 case HANDEXTEND_FORCE_HOLD:
06790 if ( (pm->ps->fd.forcePowersActive&(1<<FP_GRIP)) )
06791 {
06792 desiredAnim = BOTH_FORCEGRIP_HOLD;
06793 }
06794 else if ( (pm->ps->fd.forcePowersActive&(1<<FP_LIGHTNING)) )
06795 {
06796 if ( pm->ps->weapon == WP_MELEE
06797 && pm->ps->activeForcePass > FORCE_LEVEL_2 )
06798 {
06799 desiredAnim = BOTH_FORCE_2HANDEDLIGHTNING_HOLD;
06800 }
06801 else
06802 {
06803 desiredAnim = BOTH_FORCELIGHTNING_HOLD;
06804 }
06805 }
06806 else if ( (pm->ps->fd.forcePowersActive&(1<<FP_DRAIN)) )
06807 {
06808 desiredAnim = BOTH_FORCEGRIP_HOLD;
06809 }
06810 else
06811 {
06812 desiredAnim = BOTH_FORCEGRIP_HOLD;
06813 }
06814 break;
06815 case HANDEXTEND_SABERPULL:
06816 desiredAnim = BOTH_SABERPULL;
06817 break;
06818 case HANDEXTEND_CHOKE:
06819 desiredAnim = BOTH_CHOKE3;
06820 break;
06821 case HANDEXTEND_DODGE:
06822 desiredAnim = pm->ps->forceDodgeAnim;
06823 break;
06824 case HANDEXTEND_KNOCKDOWN:
06825 if (pm->ps->forceDodgeAnim)
06826 {
06827 if (pm->ps->forceDodgeAnim > 4)
06828 {
06829 int originalDAnim = pm->ps->forceDodgeAnim-8;
06830 if (originalDAnim == 2)
06831 {
06832 desiredAnim = BOTH_FORCE_GETUP_B1;
06833 }
06834 else if (originalDAnim == 3)
06835 {
06836 desiredAnim = BOTH_FORCE_GETUP_B3;
06837 }
06838 else
06839 {
06840 desiredAnim = BOTH_GETUP1;
06841 }
06842
06843
06844 seperateOnTorso = qtrue;
06845 desiredOnTorso = BOTH_FORCEPUSH;
06846 }
06847 else if (pm->ps->forceDodgeAnim == 2)
06848 {
06849 desiredAnim = BOTH_FORCE_GETUP_B1;
06850 }
06851 else if (pm->ps->forceDodgeAnim == 3)
06852 {
06853 desiredAnim = BOTH_FORCE_GETUP_B3;
06854 }
06855 else
06856 {
06857 desiredAnim = BOTH_GETUP1;
06858 }
06859 }
06860 else
06861 {
06862 desiredAnim = BOTH_KNOCKDOWN1;
06863 }
06864 break;
06865 case HANDEXTEND_DUELCHALLENGE:
06866 desiredAnim = BOTH_ENGAGETAUNT;
06867 break;
06868 case HANDEXTEND_TAUNT:
06869 desiredAnim = pm->ps->forceDodgeAnim;
06870 if ( desiredAnim != BOTH_ENGAGETAUNT
06871 && VectorCompare( pm->ps->velocity, vec3_origin )
06872 && pm->ps->groundEntityNum != ENTITYNUM_NONE )
06873 {
06874 playFullBody = qtrue;
06875 }
06876 break;
06877 case HANDEXTEND_PRETHROW:
06878 desiredAnim = BOTH_A3_TL_BR;
06879 playFullBody = qtrue;
06880 break;
06881 case HANDEXTEND_POSTTHROW:
06882 desiredAnim = BOTH_D3_TL___;
06883 playFullBody = qtrue;
06884 break;
06885 case HANDEXTEND_PRETHROWN:
06886 desiredAnim = BOTH_KNEES1;
06887 playFullBody = qtrue;
06888 break;
06889 case HANDEXTEND_POSTTHROWN:
06890 if (pm->ps->forceDodgeAnim)
06891 {
06892 desiredAnim = BOTH_FORCE_GETUP_F2;
06893 }
06894 else
06895 {
06896 desiredAnim = BOTH_KNOCKDOWN5;
06897 }
06898 playFullBody = qtrue;
06899 break;
06900 case HANDEXTEND_DRAGGING:
06901 desiredAnim = BOTH_B1_BL___;
06902 break;
06903 case HANDEXTEND_JEDITAUNT:
06904 desiredAnim = BOTH_GESTURE1;
06905
06906 break;
06907
06908
06909
06910
06911
06912
06913
06914
06915
06916
06917
06918 default:
06919 desiredAnim = BOTH_FORCEPUSH;
06920 break;
06921 }
06922
06923 if (!seperateOnTorso)
06924 {
06925 PM_SetAnim(SETANIM_TORSO, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
06926 pm->ps->torsoTimer = 1;
06927 }
06928
06929 if (playFullBody)
06930 {
06931 PM_SetAnim(SETANIM_BOTH, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
06932 pm->ps->legsTimer = pm->ps->torsoTimer = 1;
06933 }
06934 else if (pm->ps->forceHandExtend == HANDEXTEND_DODGE || pm->ps->forceHandExtend == HANDEXTEND_KNOCKDOWN ||
06935 (pm->ps->forceHandExtend == HANDEXTEND_CHOKE && pm->ps->groundEntityNum == ENTITYNUM_NONE) )
06936 {
06937 if (seperateOnTorso)
06938 {
06939 PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
06940 pm->ps->legsTimer = 1;
06941
06942 PM_SetAnim(SETANIM_TORSO, desiredOnTorso, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
06943 pm->ps->torsoTimer = 1;
06944 }
06945 else
06946 {
06947 PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
06948 pm->ps->legsTimer = 1;
06949 }
06950 }
06951
06952 return;
06953 }
06954
06955 if (BG_InSpecialJump(pm->ps->legsAnim) ||
06956 BG_InRoll(pm->ps, pm->ps->legsAnim) ||
06957 PM_InRollComplete(pm->ps, pm->ps->legsAnim))
06958 {
06959
06960
06961
06962
06963
06964
06965
06966
06967
06968 if (pm->ps->weaponTime < pm->ps->legsTimer)
06969 {
06970 pm->ps->weaponTime = pm->ps->legsTimer;
06971 }
06972 }
06973
06974 if (pm->ps->duelInProgress)
06975 {
06976 pm->cmd.weapon = WP_SABER;
06977 pm->ps->weapon = WP_SABER;
06978
06979 if (pm->ps->duelTime >= pm->cmd.serverTime)
06980 {
06981 pm->cmd.upmove = 0;
06982 pm->cmd.forwardmove = 0;
06983 pm->cmd.rightmove = 0;
06984 }
06985 }
06986
06987 if (pm->ps->weapon == WP_SABER && pm->ps->saberMove != LS_READY && pm->ps->saberMove != LS_NONE)
06988 {
06989 pm->cmd.weapon = WP_SABER;
06990 }
06991
06992 if (pm->ps->weapon == WP_SABER)
06993 {
06994
06995 PM_WeaponLightsaber();
06996 killAfterItem = 1;
06997 }
06998 else if (pm->ps->weapon != WP_EMPLACED_GUN)
06999 {
07000 pm->ps->saberHolstered = 0;
07001 }
07002
07003 if (PM_CanSetWeaponAnims())
07004 {
07005 if (pm->ps->weapon == WP_THERMAL ||
07006 pm->ps->weapon == WP_TRIP_MINE ||
07007 pm->ps->weapon == WP_DET_PACK)
07008 {
07009 if (pm->ps->weapon == WP_THERMAL)
07010 {
07011 if ((pm->ps->torsoAnim) == WeaponAttackAnim[pm->ps->weapon] &&
07012 (pm->ps->weaponTime-200) <= 0)
07013 {
07014 PM_StartTorsoAnim( WeaponReadyAnim[pm->ps->weapon] );
07015 }
07016 }
07017 else
07018 {
07019 if ((pm->ps->torsoAnim) == WeaponAttackAnim[pm->ps->weapon] &&
07020 (pm->ps->weaponTime-700) <= 0)
07021 {
07022 PM_StartTorsoAnim( WeaponReadyAnim[pm->ps->weapon] );
07023 }
07024 }
07025 }
07026 }
07027
07028
07029 if ( pm->ps->pm_flags & PMF_RESPAWNED ) {
07030 return;
07031 }
07032
07033
07034 if ( pm->ps->clientNum < MAX_CLIENTS && pm->ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
07035 return;
07036 }
07037
07038
07039 if ( pm->ps->stats[STAT_HEALTH] <= 0 ) {
07040 pm->ps->weapon = WP_NONE;
07041 return;
07042 }
07043
07044
07045 if ( pm->cmd.buttons & BUTTON_USE_HOLDABLE ) {
07046 if ( ! ( pm->ps->pm_flags & PMF_USE_ITEM_HELD ) ) {
07047
07048 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
07049 && pm->ps->m_iVehicleNum)
07050 {
07051 return;
07052 }
07053
07054 if (!pm->ps->stats[STAT_HOLDABLE_ITEM])
07055 {
07056 return;
07057 }
07058
07059 if (!PM_ItemUsable(pm->ps, 0))
07060 {
07061 pm->ps->pm_flags |= PMF_USE_ITEM_HELD;
07062 return;
07063 }
07064 else
07065 {
07066 if (pm->ps->stats[STAT_HOLDABLE_ITEMS] & (1 << bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag))
07067 {
07068 if (bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_BINOCULARS &&
07069 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_JETPACK &&
07070 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_HEALTHDISP &&
07071 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_AMMODISP &&
07072 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_CLOAK &&
07073 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_EWEB)
07074 {
07075 pm->ps->stats[STAT_HOLDABLE_ITEMS] -= (1 << bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag);
07076 }
07077 }
07078 else
07079 {
07080 return;
07081 }
07082
07083 pm->ps->pm_flags |= PMF_USE_ITEM_HELD;
07084 PM_AddEvent( EV_USE_ITEM0 + bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag );
07085
07086 if (bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_BINOCULARS &&
07087 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_JETPACK &&
07088 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_HEALTHDISP &&
07089 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_AMMODISP &&
07090 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_CLOAK &&
07091 bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag != HI_EWEB)
07092 {
07093 pm->ps->stats[STAT_HOLDABLE_ITEM] = 0;
07094 BG_CycleInven(pm->ps, 1);
07095 }
07096 }
07097 return;
07098 }
07099 } else {
07100 pm->ps->pm_flags &= ~PMF_USE_ITEM_HELD;
07101 }
07102
07103
07104
07105
07106
07107
07108
07109
07110
07111
07112
07113 if (killAfterItem)
07114 {
07115 return;
07116 }
07117
07118
07119 if ( pm->ps->weaponTime > 0 ) {
07120 pm->ps->weaponTime -= pml.msec;
07121 }
07122
07123 if (pm->ps->isJediMaster && pm->ps->emplacedIndex)
07124 {
07125 pm->ps->emplacedIndex = 0;
07126 pm->ps->saberHolstered = 0;
07127 }
07128
07129 if (pm->ps->duelInProgress && pm->ps->emplacedIndex)
07130 {
07131 pm->ps->emplacedIndex = 0;
07132 pm->ps->saberHolstered = 0;
07133 }
07134
07135 if (pm->ps->weapon == WP_EMPLACED_GUN && pm->ps->emplacedIndex)
07136 {
07137 pm->cmd.weapon = WP_EMPLACED_GUN;
07138 PM_StartTorsoAnim( BOTH_GUNSIT1 );
07139 }
07140
07141 if (pm->ps->isJediMaster || pm->ps->duelInProgress || pm->ps->trueJedi)
07142 {
07143 pm->cmd.weapon = WP_SABER;
07144 pm->ps->weapon = WP_SABER;
07145
07146 if (pm->ps->isJediMaster || pm->ps->trueJedi)
07147 {
07148 pm->ps->stats[STAT_WEAPONS] = (1 << WP_SABER);
07149 }
07150 }
07151
07152 amount = weaponData[pm->ps->weapon].energyPerShot;
07153
07154
07155 if ( pm->ps->weapon != WP_NONE &&
07156 pm->ps->weapon == pm->cmd.weapon &&
07157 (pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING) )
07158 {
07159 if ( pm->ps->clientNum < MAX_CLIENTS && pm->ps->ammo[ weaponData[pm->ps->weapon].ammoIndex ] != -1 )
07160 {
07161
07162 if (pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] < weaponData[pm->ps->weapon].energyPerShot &&
07163 pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] < weaponData[pm->ps->weapon].altEnergyPerShot)
07164 {
07165
07166 PM_AddEventWithParm( EV_NOAMMO, WP_NUM_WEAPONS+pm->ps->weapon );
07167
07168 if (pm->ps->weaponTime < 500)
07169 {
07170 pm->ps->weaponTime += 500;
07171 }
07172 return;
07173 }
07174
07175 if (pm->ps->weapon == WP_DET_PACK && !pm->ps->hasDetPackPlanted && pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] < 1)
07176 {
07177 PM_AddEventWithParm( EV_NOAMMO, WP_NUM_WEAPONS+pm->ps->weapon );
07178
07179 if (pm->ps->weaponTime < 500)
07180 {
07181 pm->ps->weaponTime += 500;
07182 }
07183 return;
07184 }
07185 }
07186 }
07187
07188
07189
07190
07191 if ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) {
07192 if ( pm->ps->weapon != pm->cmd.weapon ) {
07193 PM_BeginWeaponChange( pm->cmd.weapon );
07194 }
07195 }
07196
07197 if ( pm->ps->weaponTime > 0 ) {
07198 return;
07199 }
07200
07201 if (pm->ps->weapon == WP_DISRUPTOR &&
07202 pm->ps->zoomMode == 1)
07203 {
07204 if (pm_cancelOutZoom)
07205 {
07206 pm->ps->zoomMode = 0;
07207 pm->ps->zoomFov = 0;
07208 pm->ps->zoomLocked = qfalse;
07209 pm->ps->zoomLockTime = 0;
07210 PM_AddEvent( EV_DISRUPTOR_ZOOMSOUND );
07211 return;
07212 }
07213
07214 if (pm->cmd.forwardmove ||
07215 pm->cmd.rightmove ||
07216 pm->cmd.upmove > 0)
07217 {
07218 return;
07219 }
07220 }
07221
07222
07223 if ( pm->ps->weaponstate == WEAPON_DROPPING ) {
07224 PM_FinishWeaponChange();
07225 return;
07226 }
07227
07228 if ( pm->ps->weaponstate == WEAPON_RAISING ) {
07229 pm->ps->weaponstate = WEAPON_READY;
07230 if (PM_CanSetWeaponAnims())
07231 {
07232 if ( pm->ps->weapon == WP_SABER )
07233 {
07234 PM_StartTorsoAnim( PM_GetSaberStance() );
07235 }
07236 else if (pm->ps->weapon == WP_MELEE || PM_IsRocketTrooper())
07237 {
07238 PM_StartTorsoAnim( pm->ps->legsAnim );
07239 }
07240 else
07241 {
07242 if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
07243 {
07244 PM_StartTorsoAnim( TORSO_WEAPONREADY4 );
07245 }
07246 else
07247 {
07248 if (pm->ps->weapon == WP_EMPLACED_GUN)
07249 {
07250 PM_StartTorsoAnim( BOTH_GUNSIT1 );
07251 }
07252 else
07253 {
07254 PM_StartTorsoAnim( WeaponReadyAnim[pm->ps->weapon] );
07255 }
07256 }
07257 }
07258 }
07259 return;
07260 }
07261
07262 if (PM_CanSetWeaponAnims() &&
07263 !PM_IsRocketTrooper() &&
07264 pm->ps->weaponstate == WEAPON_READY && pm->ps->weaponTime <= 0 &&
07265 (pm->ps->weapon >= WP_BRYAR_PISTOL || pm->ps->weapon == WP_STUN_BATON) &&
07266 pm->ps->torsoTimer <= 0 &&
07267 (pm->ps->torsoAnim) != WeaponReadyAnim[pm->ps->weapon] &&
07268 pm->ps->torsoAnim != TORSO_WEAPONIDLE3 &&
07269 pm->ps->weapon != WP_EMPLACED_GUN)
07270 {
07271 PM_StartTorsoAnim( WeaponReadyAnim[pm->ps->weapon] );
07272 }
07273 else if (PM_CanSetWeaponAnims() &&
07274 pm->ps->weapon == WP_MELEE)
07275 {
07276 if (pm->ps->weaponTime <= 0 &&
07277 pm->ps->forceHandExtend == HANDEXTEND_NONE)
07278 {
07279 int desTAnim = pm->ps->legsAnim;
07280
07281 if (desTAnim == BOTH_STAND1 ||
07282 desTAnim == BOTH_STAND2)
07283 {
07284 desTAnim = BOTH_STAND6;
07285 }
07286
07287 if (!(pm->cmd.buttons & (BUTTON_ATTACK|BUTTON_ALT_ATTACK)))
07288 {
07289 if (pm->ps->torsoAnim != desTAnim)
07290 {
07291 PM_StartTorsoAnim( desTAnim );
07292 }
07293 }
07294 }
07295 }
07296 else if (PM_CanSetWeaponAnims() && PM_IsRocketTrooper())
07297 {
07298 int desTAnim = pm->ps->legsAnim;
07299
07300 if (!(pm->cmd.buttons & (BUTTON_ATTACK|BUTTON_ALT_ATTACK)))
07301 {
07302 if (pm->ps->torsoAnim != desTAnim)
07303 {
07304 PM_StartTorsoAnim( desTAnim );
07305 }
07306 }
07307 }
07308
07309 if (((pm->ps->torsoAnim) == TORSO_WEAPONREADY4 ||
07310 (pm->ps->torsoAnim) == BOTH_ATTACK4) &&
07311 (pm->ps->weapon != WP_DISRUPTOR || pm->ps->zoomMode != 1))
07312 {
07313 if (pm->ps->weapon == WP_EMPLACED_GUN)
07314 {
07315 PM_StartTorsoAnim( BOTH_GUNSIT1 );
07316 }
07317 else if (PM_CanSetWeaponAnims())
07318 {
07319 PM_StartTorsoAnim( WeaponReadyAnim[pm->ps->weapon] );
07320 }
07321 }
07322 else if (((pm->ps->torsoAnim) != TORSO_WEAPONREADY4 &&
07323 (pm->ps->torsoAnim) != BOTH_ATTACK4) &&
07324 PM_CanSetWeaponAnims() &&
07325 (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1))
07326 {
07327 PM_StartTorsoAnim( TORSO_WEAPONREADY4 );
07328 }
07329
07330 if (pm->ps->clientNum >= MAX_CLIENTS &&
07331 pm_entSelf &&
07332 pm_entSelf->s.NPC_class == CLASS_VEHICLE)
07333 {
07334 veh = pm_entSelf;
07335 }
07336 if ( veh
07337 && veh->m_pVehicle )
07338 {
07339 if ( g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[0].ID].fHoming
07340 || g_vehWeaponInfo[veh->m_pVehicle->m_pVehicleInfo->weapon[1].ID].fHoming )
07341 {
07342 vehicleRocketLock = qtrue;
07343 }
07344 }
07345
07346 if ( !vehicleRocketLock )
07347 {
07348 if (pm->ps->weapon != WP_ROCKET_LAUNCHER)
07349 {
07350 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
07351 &&pm->ps->m_iVehicleNum)
07352 {
07353 }
07354 else
07355 {
07356 pm->ps->rocketLockIndex = ENTITYNUM_NONE;
07357 pm->ps->rocketLockTime = 0;
07358 pm->ps->rocketTargetTime = 0;
07359 }
07360 }
07361 }
07362
07363 if ( PM_DoChargedWeapons(vehicleRocketLock, veh))
07364 {
07365
07366 return;
07367 }
07368
07369
07370 if ( ! (pm->cmd.buttons & (BUTTON_ATTACK|BUTTON_ALT_ATTACK)))
07371 {
07372 pm->ps->weaponTime = 0;
07373 pm->ps->weaponstate = WEAPON_READY;
07374 return;
07375 }
07376
07377 if (pm->ps->weapon == WP_EMPLACED_GUN)
07378 {
07379 addTime = weaponData[pm->ps->weapon].fireTime;
07380 pm->ps->weaponTime += addTime;
07381 if ( (pm->cmd.buttons & BUTTON_ALT_ATTACK) )
07382 {
07383 PM_AddEvent( EV_ALT_FIRE );
07384 }
07385 else
07386 {
07387 PM_AddEvent( EV_FIRE_WEAPON );
07388 }
07389 return;
07390 }
07391 else if (pm->ps->m_iVehicleNum
07392 && pm_entSelf->s.NPC_class==CLASS_VEHICLE)
07393 {
07394 pm->ps->weaponstate = WEAPON_FIRING;
07395 pm->ps->weaponTime += 100;
07396 #ifdef QAGAME //hack, only do it game-side. vehicle weapons don't really need predicting I suppose.
07397 if ( (pm->cmd.buttons & BUTTON_ALT_ATTACK) )
07398 {
07399 G_CheapWeaponFire(pm->ps->clientNum, EV_ALT_FIRE);
07400 }
07401 else
07402 {
07403 G_CheapWeaponFire(pm->ps->clientNum, EV_FIRE_WEAPON);
07404 }
07405 #endif
07406
07407
07408
07409
07410
07411
07412
07413
07414
07415
07416
07417
07418 return;
07419 }
07420
07421 if (pm->ps->weapon == WP_DISRUPTOR &&
07422 (pm->cmd.buttons & BUTTON_ALT_ATTACK) &&
07423 !pm->ps->zoomLocked)
07424 {
07425 return;
07426 }
07427
07428 if (pm->ps->weapon == WP_DISRUPTOR &&
07429 (pm->cmd.buttons & BUTTON_ALT_ATTACK) &&
07430 pm->ps->zoomMode == 2)
07431 {
07432 return;
07433 }
07434
07435 if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
07436 {
07437 PM_StartTorsoAnim( BOTH_ATTACK4 );
07438 }
07439 else if (pm->ps->weapon == WP_MELEE)
07440 {
07441
07442 if (!pm->ps->m_iVehicleNum)
07443 {
07444 if (pm->debugMelee &&
07445 (pm->cmd.buttons & BUTTON_ATTACK) &&
07446 (pm->cmd.buttons & BUTTON_ALT_ATTACK))
07447 {
07448 #if 0 //eh, I want to try turning the saber off, but can't do that reliably for prediction..
07449 qboolean icandoit = qtrue;
07450 if (pm->ps->weaponTime > 0)
07451 {
07452 icandoit = qfalse;
07453 }
07454 if (pm->ps->forceHandExtend != HANDEXTEND_NONE)
07455 {
07456 icandoit = qfalse;
07457 }
07458 if (pm->ps->weapon != WP_SABER && pm->ps->weapon != WP_MELEE)
07459 {
07460 icandoit = qfalse;
07461 }
07462
07463 if (icandoit)
07464 {
07465
07466 PM_SetAnim(SETANIM_BOTH, BOTH_KYLE_GRAB, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
07467 if (pm->ps->torsoAnim == BOTH_KYLE_GRAB)
07468 {
07469 pm->ps->torsoTimer += 500;
07470 if (pm->ps->legsAnim == pm->ps->torsoAnim)
07471 {
07472 pm->ps->legsTimer = pm->ps->torsoTimer;
07473 }
07474 pm->ps->weaponTime = pm->ps->torsoTimer;
07475 return;
07476 }
07477 }
07478 #else
07479 #ifdef QAGAME
07480 if (pm_entSelf)
07481 {
07482 if (TryGrapple((gentity_t *)pm_entSelf))
07483 {
07484 return;
07485 }
07486 }
07487 #else
07488 return;
07489 #endif
07490 #endif
07491 }
07492 else if (pm->debugMelee &&
07493 (pm->cmd.buttons & BUTTON_ALT_ATTACK))
07494 {
07495 if (!BG_KickingAnim(pm->ps->torsoAnim) &&
07496 !BG_KickingAnim(pm->ps->legsAnim))
07497 {
07498 int kickMove = PM_KickMoveForConditions();
07499 if (kickMove == LS_HILT_BASH)
07500 {
07501 kickMove = LS_KICK_F;
07502 }
07503
07504 if (kickMove != -1)
07505 {
07506 if ( pm->ps->groundEntityNum == ENTITYNUM_NONE )
07507 {
07508 float gDist = PM_GroundDistance();
07509
07510
07511
07512 if ((!BG_FlippingAnim( pm->ps->legsAnim ) || pm->ps->legsTimer <= 0) &&
07513 gDist > 64.0f &&
07514 gDist > (-pm->ps->velocity[2])-64.0f
07515 )
07516 {
07517 switch ( kickMove )
07518 {
07519 case LS_KICK_F:
07520 kickMove = LS_KICK_F_AIR;
07521 break;
07522 case LS_KICK_B:
07523 kickMove = LS_KICK_B_AIR;
07524 break;
07525 case LS_KICK_R:
07526 kickMove = LS_KICK_R_AIR;
07527 break;
07528 case LS_KICK_L:
07529 kickMove = LS_KICK_L_AIR;
07530 break;
07531 default:
07532 kickMove = -1;
07533 break;
07534 }
07535 }
07536 else
07537 {
07538 kickMove = -1;
07539 }
07540 }
07541 }
07542
07543 if (kickMove != -1)
07544 {
07545 int kickAnim = saberMoveData[kickMove].animToUse;
07546
07547 if (kickAnim != -1)
07548 {
07549 PM_SetAnim(SETANIM_BOTH, kickAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
07550 if (pm->ps->legsAnim == kickAnim)
07551 {
07552 pm->ps->weaponTime = pm->ps->legsTimer;
07553 return;
07554 }
07555 }
07556 }
07557 }
07558
07559
07560 if (pm->ps->torsoAnim != pm->ps->legsAnim)
07561 {
07562 PM_SetAnim(SETANIM_BOTH, pm->ps->legsAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
07563 }
07564 pm->ps->weaponTime = 0;
07565 return;
07566 }
07567 else
07568 {
07569 int desTAnim = BOTH_MELEE1;
07570 if (pm->ps->torsoAnim == BOTH_MELEE1)
07571 {
07572 desTAnim = BOTH_MELEE2;
07573 }
07574 PM_StartTorsoAnim( desTAnim );
07575
07576 if (pm->ps->torsoAnim == desTAnim)
07577 {
07578 pm->ps->weaponTime = pm->ps->torsoTimer;
07579 }
07580 }
07581 }
07582 }
07583 else
07584 {
07585 PM_StartTorsoAnim( WeaponAttackAnim[pm->ps->weapon] );
07586 }
07587
07588 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
07589 {
07590 amount = weaponData[pm->ps->weapon].altEnergyPerShot;
07591 }
07592 else
07593 {
07594 amount = weaponData[pm->ps->weapon].energyPerShot;
07595 }
07596
07597 pm->ps->weaponstate = WEAPON_FIRING;
07598
07599
07600 if ( pm->ps->clientNum < MAX_CLIENTS && pm->ps->ammo[ weaponData[pm->ps->weapon].ammoIndex ] != -1 )
07601 {
07602
07603 if ((pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] - amount) >= 0)
07604 {
07605 pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] -= amount;
07606 }
07607 else
07608 {
07609
07610 if (pm->ps->weapon != WP_DET_PACK || !pm->ps->hasDetPackPlanted)
07611 {
07612 PM_AddEventWithParm( EV_NOAMMO, WP_NUM_WEAPONS+pm->ps->weapon );
07613 if (pm->ps->weaponTime < 500)
07614 {
07615 pm->ps->weaponTime += 500;
07616 }
07617 }
07618 return;
07619 }
07620 }
07621
07622 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK ) {
07623
07624 if (0)
07625 {
07626 PM_AddEvent( EV_FIRE_WEAPON );
07627 addTime = weaponData[pm->ps->weapon].fireTime;
07628 }
07629 else if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode != 1)
07630 {
07631 PM_AddEvent( EV_FIRE_WEAPON );
07632 addTime = weaponData[pm->ps->weapon].fireTime;
07633 }
07634 else
07635 {
07636 if (pm->ps->weapon != WP_MELEE ||
07637 !pm->ps->m_iVehicleNum)
07638 {
07639 PM_AddEvent( EV_ALT_FIRE );
07640 }
07641 addTime = weaponData[pm->ps->weapon].altFireTime;
07642 }
07643 }
07644 else {
07645 if (pm->ps->weapon != WP_MELEE ||
07646 !pm->ps->m_iVehicleNum)
07647 {
07648 PM_AddEvent( EV_FIRE_WEAPON );
07649 }
07650 addTime = weaponData[pm->ps->weapon].fireTime;
07651 if ( pm->gametype == GT_SIEGE && pm->ps->weapon == WP_DET_PACK )
07652 {
07653 addTime *= 2;
07654 }
07655 }
07656
07657
07658
07659
07660
07661
07662
07663 if (pm->ps->fd.forcePowersActive & (1 << FP_RAGE))
07664 {
07665 addTime *= 0.75;
07666 }
07667 else if (pm->ps->fd.forceRageRecoveryTime > pm->cmd.serverTime)
07668 {
07669 addTime *= 1.5;
07670 }
07671
07672 pm->ps->weaponTime += addTime;
07673 }
07674
07675
07676
07677
07678
07679
07680
07681 static void PM_Animate( void ) {
07682 if ( pm->cmd.buttons & BUTTON_GESTURE ) {
07683 if (pm->ps->m_iVehicleNum)
07684 {
07685 if (pm->ps->forceHandExtendTime < pm->cmd.serverTime)
07686 {
07687 pm->ps->forceHandExtend = HANDEXTEND_NONE;
07688 }
07689 }
07690
07691 if ( pm->ps->torsoTimer < 1 && pm->ps->forceHandExtend == HANDEXTEND_NONE &&
07692 pm->ps->legsTimer < 1 && pm->ps->weaponTime < 1 && pm->ps->saberLockTime < pm->cmd.serverTime) {
07693
07694 pm->ps->forceHandExtend = HANDEXTEND_TAUNT;
07695
07696
07697 pm->ps->forceDodgeAnim = BOTH_ENGAGETAUNT;
07698
07699 pm->ps->forceHandExtendTime = pm->cmd.serverTime + 1000;
07700
07701
07702
07703 PM_AddEvent( EV_TAUNT );
07704 }
07705 #if 0
07706
07707
07708
07709 } else if ( pm->cmd.buttons & BUTTON_GETFLAG ) {
07710 if ( pm->ps->torsoTimer == 0 ) {
07711 PM_StartTorsoAnim( TORSO_GETFLAG );
07712 pm->ps->torsoTimer = 600;
07713 }
07714 } else if ( pm->cmd.buttons & BUTTON_GUARDBASE ) {
07715 if ( pm->ps->torsoTimer == 0 ) {
07716 PM_StartTorsoAnim( TORSO_GUARDBASE );
07717 pm->ps->torsoTimer = 600;
07718 }
07719 } else if ( pm->cmd.buttons & BUTTON_PATROL ) {
07720 if ( pm->ps->torsoTimer == 0 ) {
07721 PM_StartTorsoAnim( TORSO_PATROL );
07722 pm->ps->torsoTimer = 600;
07723 }
07724 } else if ( pm->cmd.buttons & BUTTON_FOLLOWME ) {
07725 if ( pm->ps->torsoTimer == 0 ) {
07726 PM_StartTorsoAnim( TORSO_FOLLOWME );
07727 pm->ps->torsoTimer = 600;
07728 }
07729 } else if ( pm->cmd.buttons & BUTTON_AFFIRMATIVE ) {
07730 if ( pm->ps->torsoTimer == 0 ) {
07731 PM_StartTorsoAnim( TORSO_AFFIRMATIVE);
07732 pm->ps->torsoTimer = 600;
07733 }
07734 } else if ( pm->cmd.buttons & BUTTON_NEGATIVE ) {
07735 if ( pm->ps->torsoTimer == 0 ) {
07736 PM_StartTorsoAnim( TORSO_NEGATIVE );
07737 pm->ps->torsoTimer = 600;
07738 }
07739 #endif //
07740 }
07741 }
07742
07743
07744
07745
07746
07747
07748
07749 static void PM_DropTimers( void ) {
07750
07751 if ( pm->ps->pm_time ) {
07752 if ( pml.msec >= pm->ps->pm_time ) {
07753 pm->ps->pm_flags &= ~PMF_ALL_TIMES;
07754 pm->ps->pm_time = 0;
07755 } else {
07756 pm->ps->pm_time -= pml.msec;
07757 }
07758 }
07759
07760
07761 if ( pm->ps->legsTimer > 0 ) {
07762 pm->ps->legsTimer -= pml.msec;
07763 if ( pm->ps->legsTimer < 0 ) {
07764 pm->ps->legsTimer = 0;
07765 }
07766 }
07767
07768 if ( pm->ps->torsoTimer > 0 ) {
07769 pm->ps->torsoTimer -= pml.msec;
07770 if ( pm->ps->torsoTimer < 0 ) {
07771 pm->ps->torsoTimer = 0;
07772 }
07773 }
07774 }
07775
07776
07777
07778
07779
07780
07781 #include "../namespace_end.h"
07782
07783 #if !defined(_XBOX) || defined(QAGAME)
07784 extern vmCvar_t bg_fighterAltControl;
07785 qboolean BG_UnrestrainedPitchRoll( playerState_t *ps, Vehicle_t *pVeh )
07786 {
07787 if ( bg_fighterAltControl.integer
07788 && ps->clientNum < MAX_CLIENTS
07789 && ps->m_iVehicleNum
07790 && pVeh
07791 && pVeh->m_pVehicleInfo
07792 && pVeh->m_pVehicleInfo->type == VH_FIGHTER )
07793
07794
07795 {
07796 return qtrue;
07797 }
07798 return qfalse;
07799 }
07800 #else
07801 extern qboolean BG_UnrestrainedPitchRoll( playerState_t *ps, Vehicle_t *pVeh );
07802 #endif
07803
07804 #include "../namespace_begin.h"
07805
07806
07807
07808
07809
07810
07811
07812
07813
07814 void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) {
07815 short temp;
07816 int i;
07817
07818 if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPINTERMISSION) {
07819 return;
07820 }
07821
07822 if ( ps->pm_type != PM_SPECTATOR && ps->stats[STAT_HEALTH] <= 0 ) {
07823 return;
07824 }
07825
07826
07827 for (i=0 ; i<3 ; i++) {
07828 temp = cmd->angles[i] + ps->delta_angles[i];
07829 #ifdef VEH_CONTROL_SCHEME_4
07830 if ( pm_entVeh
07831 && pm_entVeh->m_pVehicle
07832 && pm_entVeh->m_pVehicle->m_pVehicleInfo
07833 && pm_entVeh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER
07834 && (cmd->serverTime-pm_entVeh->playerState->hyperSpaceTime) >= HYPERSPACE_TIME )
07835 {
07836 if ( i == PITCH )
07837 {
07838 int pitchClamp = ANGLE2SHORT(AngleNormalize180(pm_entVeh->m_pVehicle->m_vPrevRiderViewAngles[PITCH]+10.0f));
07839
07840 if ( temp > pitchClamp )
07841 {
07842 ps->delta_angles[i] = pitchClamp - cmd->angles[i];
07843 temp = pitchClamp;
07844 }
07845 else if ( temp < -pitchClamp )
07846 {
07847 ps->delta_angles[i] = -pitchClamp - cmd->angles[i];
07848 temp = -pitchClamp;
07849 }
07850 }
07851 if ( i == YAW )
07852 {
07853 int yawClamp = ANGLE2SHORT(AngleNormalize180(pm_entVeh->m_pVehicle->m_vPrevRiderViewAngles[YAW]+10.0f));
07854
07855 if ( temp > yawClamp )
07856 {
07857 ps->delta_angles[i] = yawClamp - cmd->angles[i];
07858 temp = yawClamp;
07859 }
07860 else if ( temp < -yawClamp )
07861 {
07862 ps->delta_angles[i] = -yawClamp - cmd->angles[i];
07863 temp = -yawClamp;
07864 }
07865 }
07866 }
07867 #else //VEH_CONTROL_SCHEME_4
07868 if ( pm_entVeh && BG_UnrestrainedPitchRoll( ps, pm_entVeh->m_pVehicle ) )
07869 {
07870
07871
07872
07873
07874
07875
07876
07877
07878 }
07879 #endif // VEH_CONTROL_SCHEME_4
07880 else
07881 {
07882 if ( i == PITCH ) {
07883
07884 if ( temp > 16000 ) {
07885 ps->delta_angles[i] = 16000 - cmd->angles[i];
07886 temp = 16000;
07887 } else if ( temp < -16000 ) {
07888 ps->delta_angles[i] = -16000 - cmd->angles[i];
07889 temp = -16000;
07890 }
07891 }
07892 }
07893 ps->viewangles[i] = SHORT2ANGLE(temp);
07894 }
07895 }
07896
07897
07898
07899
07900
07901
07902
07903
07904
07905
07906
07907
07908
07909
07910
07911
07912
07913
07914
07915
07916
07917
07918
07919
07920
07921
07922
07923
07924
07925
07926
07927
07928
07929
07930
07931
07932
07933
07934
07935
07936
07937
07938
07939
07940
07941
07942
07943
07944
07945
07946
07947
07948
07949
07950
07951
07952
07953
07954
07955
07956
07957
07958
07959
07960
07961
07962
07963
07964
07965
07966
07967
07968
07969
07970
07971
07972
07973
07974
07975
07976
07977
07978
07979
07980
07981
07982
07983
07984
07985
07986
07987
07988
07989
07990
07991
07992
07993
07994
07995
07996
07997
07998
07999
08000
08001
08002
08003
08004
08005
08006
08007
08008
08009
08010
08011
08012
08013
08014
08015
08016
08017
08018
08019
08020
08021
08022
08023
08024
08025
08026
08027
08028
08029
08030
08031
08032 void PM_AdjustAttackStates( pmove_t *pm )
08033
08034 {
08035 int amount;
08036
08037 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
08038 &&pm->ps->m_iVehicleNum)
08039 {
08040 bgEntity_t *veh = pm_entVeh;
08041 if ( veh &&
08042 (veh->m_pVehicle && (veh->m_pVehicle->m_pVehicleInfo->type == VH_WALKER || veh->m_pVehicle && veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER)) )
08043 {
08044
08045 pm->ps->eFlags &= ~(EF_FIRING|EF_ALT_FIRING);
08046 return;
08047 }
08048 }
08049
08050 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
08051 {
08052 amount = pm->ps->ammo[weaponData[ pm->ps->weapon ].ammoIndex] - weaponData[pm->ps->weapon].altEnergyPerShot;
08053 }
08054 else
08055 {
08056 amount = pm->ps->ammo[weaponData[ pm->ps->weapon ].ammoIndex] - weaponData[pm->ps->weapon].energyPerShot;
08057 }
08058
08059
08060 if ( pm->ps->weapon == WP_DISRUPTOR && pm->ps->weaponstate == WEAPON_READY )
08061 {
08062 if ( !(pm->ps->eFlags & EF_ALT_FIRING) && (pm->cmd.buttons & BUTTON_ALT_ATTACK)
08063 )
08064 {
08065
08066 if ( !pm->ps->zoomMode && pm->ps->pm_type != PM_DEAD )
08067 {
08068
08069 pm->ps->zoomMode = 1;
08070 pm->ps->zoomLocked = qfalse;
08071 pm->ps->zoomFov = 80.0f;
08072 pm->ps->zoomLockTime = pm->cmd.serverTime + 50;
08073 PM_AddEvent(EV_DISRUPTOR_ZOOMSOUND);
08074 }
08075 else if (pm->ps->zoomMode == 1 && pm->ps->zoomLockTime < pm->cmd.serverTime)
08076 {
08077
08078 pm->ps->zoomMode = 0;
08079 pm->ps->zoomTime = pm->ps->commandTime;
08080 pm->ps->zoomLocked = qfalse;
08081 PM_AddEvent(EV_DISRUPTOR_ZOOMSOUND);
08082 pm->ps->weaponTime = 1000;
08083 }
08084 }
08085 else if ( !(pm->cmd.buttons & BUTTON_ALT_ATTACK ) && pm->ps->zoomLockTime < pm->cmd.serverTime)
08086 {
08087
08088 if ( pm->ps->zoomMode )
08089 {
08090 if (pm->ps->zoomMode == 1 && !pm->ps->zoomLocked)
08091 {
08092 pm->ps->zoomFov = ((pm->cmd.serverTime+50) - pm->ps->zoomLockTime) * 0.035f;
08093 if (pm->ps->zoomFov > 50)
08094 {
08095 pm->ps->zoomFov = 50;
08096 }
08097 if (pm->ps->zoomFov < 1)
08098 {
08099 pm->ps->zoomFov = 1;
08100 }
08101 }
08102
08103 pm->ps->zoomLocked = qtrue;
08104 }
08105 }
08106
08107
08108
08109
08110
08111
08112
08113
08114
08115
08116
08117
08118
08119
08120
08121
08122
08123
08124
08125
08126
08127
08128
08129 if ( pm->cmd.buttons & BUTTON_ATTACK )
08130 {
08131
08132
08133 if ( pm->ps->zoomMode )
08134 {
08135 amount = pm->ps->ammo[weaponData[ pm->ps->weapon ].ammoIndex] -
08136 weaponData[pm->ps->weapon].altEnergyPerShot;
08137 }
08138 }
08139 else
08140 {
08141
08142 amount = 0;
08143 }
08144 }
08145
08146
08147
08148
08149
08150
08151
08152
08153
08154
08155
08156
08157
08158
08159
08160
08161
08162 if ( !(pm->ps->pm_flags & PMF_RESPAWNED) &&
08163 pm->ps->pm_type != PM_INTERMISSION &&
08164 ( pm->cmd.buttons & (BUTTON_ATTACK|BUTTON_ALT_ATTACK)) &&
08165 ( amount >= 0 || pm->ps->weapon == WP_SABER ))
08166 {
08167 if ( pm->cmd.buttons & BUTTON_ALT_ATTACK )
08168 {
08169 pm->ps->eFlags |= EF_ALT_FIRING;
08170 }
08171 else
08172 {
08173 pm->ps->eFlags &= ~EF_ALT_FIRING;
08174 }
08175
08176
08177 pm->ps->eFlags |= EF_FIRING;
08178 }
08179 else
08180 {
08181
08182 pm->ps->eFlags &= ~(EF_FIRING|EF_ALT_FIRING);
08183 }
08184
08185
08186 if ( pm->ps->weapon == WP_DISRUPTOR)
08187 {
08188 if ( pm->cmd.buttons & BUTTON_ATTACK && pm->ps->zoomMode == 1 && pm->ps->zoomLocked)
08189 {
08190
08191 pm->cmd.buttons |= BUTTON_ALT_ATTACK;
08192 pm->ps->eFlags |= EF_ALT_FIRING;
08193 }
08194 else if ( pm->cmd.buttons & BUTTON_ALT_ATTACK && pm->ps->zoomMode == 1 && pm->ps->zoomLocked)
08195 {
08196 pm->cmd.buttons &= ~BUTTON_ALT_ATTACK;
08197 pm->ps->eFlags &= ~EF_ALT_FIRING;
08198 }
08199 }
08200 }
08201
08202 void BG_CmdForRoll( playerState_t *ps, int anim, usercmd_t *pCmd )
08203 {
08204 switch ( (anim) )
08205 {
08206 case BOTH_ROLL_F:
08207 pCmd->forwardmove = 127;
08208 pCmd->rightmove = 0;
08209 break;
08210 case BOTH_ROLL_B:
08211 pCmd->forwardmove = -127;
08212 pCmd->rightmove = 0;
08213 break;
08214 case BOTH_ROLL_R:
08215 pCmd->forwardmove = 0;
08216 pCmd->rightmove = 127;
08217 break;
08218 case BOTH_ROLL_L:
08219 pCmd->forwardmove = 0;
08220 pCmd->rightmove = -127;
08221 break;
08222 case BOTH_GETUP_BROLL_R:
08223 pCmd->forwardmove = 0;
08224 pCmd->rightmove = 48;
08225
08226 break;
08227
08228 case BOTH_GETUP_FROLL_R:
08229 if ( ps->legsTimer <= 250 )
08230 {
08231 pCmd->forwardmove = pCmd->rightmove = 0;
08232 }
08233 else
08234 {
08235 pCmd->forwardmove = 0;
08236 pCmd->rightmove = 48;
08237
08238 }
08239 break;
08240
08241 case BOTH_GETUP_BROLL_L:
08242 pCmd->forwardmove = 0;
08243 pCmd->rightmove = -48;
08244
08245 break;
08246
08247 case BOTH_GETUP_FROLL_L:
08248 if ( ps->legsTimer <= 250 )
08249 {
08250 pCmd->forwardmove = pCmd->rightmove = 0;
08251 }
08252 else
08253 {
08254 pCmd->forwardmove = 0;
08255 pCmd->rightmove = -48;
08256
08257 }
08258 break;
08259
08260 case BOTH_GETUP_BROLL_B:
08261 if ( ps->torsoTimer <= 250 )
08262 {
08263 pCmd->forwardmove = pCmd->rightmove = 0;
08264 }
08265 else if ( PM_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->torsoTimer < 350 )
08266 {
08267 pCmd->forwardmove = pCmd->rightmove = 0;
08268 }
08269 else
08270 {
08271
08272 pCmd->forwardmove = -64;
08273 pCmd->rightmove = 0;
08274
08275 }
08276 break;
08277
08278 case BOTH_GETUP_FROLL_B:
08279 if ( ps->torsoTimer <= 100 )
08280 {
08281 pCmd->forwardmove = pCmd->rightmove = 0;
08282 }
08283 else if ( PM_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->torsoTimer < 200 )
08284 {
08285 pCmd->forwardmove = pCmd->rightmove = 0;
08286 }
08287 else
08288 {
08289
08290 pCmd->forwardmove = -64;
08291 pCmd->rightmove = 0;
08292
08293 }
08294 break;
08295
08296 case BOTH_GETUP_BROLL_F:
08297 if ( ps->torsoTimer <= 550 )
08298 {
08299 pCmd->forwardmove = pCmd->rightmove = 0;
08300 }
08301 else if ( PM_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->torsoTimer < 150 )
08302 {
08303 pCmd->forwardmove = pCmd->rightmove = 0;
08304 }
08305 else
08306 {
08307 pCmd->forwardmove = 64;
08308 pCmd->rightmove = 0;
08309
08310 }
08311 break;
08312
08313 case BOTH_GETUP_FROLL_F:
08314 if ( ps->torsoTimer <= 100 )
08315 {
08316 pCmd->forwardmove = pCmd->rightmove = 0;
08317 }
08318 else
08319 {
08320
08321 pCmd->forwardmove = 64;
08322 pCmd->rightmove = 0;
08323
08324 }
08325 break;
08326 }
08327 pCmd->upmove = 0;
08328 }
08329
08330 qboolean PM_SaberInTransition( int move );
08331
08332 void BG_AdjustClientSpeed(playerState_t *ps, usercmd_t *cmd, int svTime)
08333 {
08334 saberInfo_t *saber;
08335
08336 if (ps->clientNum >= MAX_CLIENTS)
08337 {
08338 bgEntity_t *bgEnt = pm_entSelf;
08339
08340 if (bgEnt && bgEnt->s.NPC_class == CLASS_VEHICLE)
08341 {
08342 return;
08343 }
08344 }
08345
08346
08347
08348
08349 ps->speed = ps->basespeed;
08350
08351 if (ps->forceHandExtend == HANDEXTEND_DODGE)
08352 {
08353 ps->speed = 0;
08354 }
08355
08356 if (ps->forceHandExtend == HANDEXTEND_KNOCKDOWN ||
08357 ps->forceHandExtend == HANDEXTEND_PRETHROWN ||
08358 ps->forceHandExtend == HANDEXTEND_POSTTHROWN)
08359 {
08360 ps->speed = 0;
08361 }
08362
08363
08364 if ( cmd->forwardmove < 0 && !(cmd->buttons&BUTTON_WALKING) && pm->ps->groundEntityNum != ENTITYNUM_NONE )
08365 {
08366 ps->speed *= 0.75;
08367 }
08368
08369 if (ps->fd.forcePowersActive & (1 << FP_GRIP))
08370 {
08371 ps->speed *= 0.4;
08372 }
08373
08374 if (ps->fd.forcePowersActive & (1 << FP_SPEED))
08375 {
08376 ps->speed *= 1.7;
08377 }
08378 else if (ps->fd.forcePowersActive & (1 << FP_RAGE))
08379 {
08380 ps->speed *= 1.3;
08381 }
08382 else if (ps->fd.forceRageRecoveryTime > svTime)
08383 {
08384 ps->speed *= 0.75;
08385 }
08386
08387 if (pm->ps->weapon == WP_DISRUPTOR &&
08388 pm->ps->zoomMode == 1 && pm->ps->zoomLockTime < pm->cmd.serverTime)
08389 {
08390 ps->speed *= 0.5f;
08391 }
08392
08393 if (ps->fd.forceGripCripple)
08394 {
08395 if (ps->fd.forcePowersActive & (1 << FP_RAGE))
08396 {
08397 ps->speed *= 0.9;
08398 }
08399 else if (ps->fd.forcePowersActive & (1 << FP_SPEED))
08400 {
08401 ps->speed *= 0.8;
08402 }
08403 else
08404 {
08405 ps->speed *= 0.2;
08406 }
08407 }
08408
08409 if ( BG_SaberInAttack( ps->saberMove ) && cmd->forwardmove < 0 )
08410 {
08411 switch( ps->fd.saberAnimLevel )
08412 {
08413 case FORCE_LEVEL_1:
08414 ps->speed *= 0.75f;
08415 break;
08416 case FORCE_LEVEL_2:
08417 case SS_DUAL:
08418 case SS_STAFF:
08419 ps->speed *= 0.60f;
08420 break;
08421 case FORCE_LEVEL_3:
08422 ps->speed *= 0.45f;
08423 break;
08424 default:
08425 break;
08426 }
08427 }
08428 else if ( BG_SpinningSaberAnim( ps->legsAnim ) )
08429 {
08430 if (ps->fd.saberAnimLevel == FORCE_LEVEL_3)
08431 {
08432 ps->speed *= 0.3f;
08433 }
08434 else
08435 {
08436 ps->speed *= 0.5f;
08437 }
08438 }
08439 else if ( ps->weapon == WP_SABER && BG_SaberInAttack( ps->saberMove ) )
08440 {
08441 switch( ps->fd.saberAnimLevel )
08442 {
08443 case FORCE_LEVEL_2:
08444 case SS_DUAL:
08445 case SS_STAFF:
08446 ps->speed *= 0.85f;
08447 break;
08448 case FORCE_LEVEL_3:
08449 ps->speed *= 0.55f;
08450 break;
08451 default:
08452 break;
08453 }
08454 }
08455 else if (ps->weapon == WP_SABER && ps->fd.saberAnimLevel == FORCE_LEVEL_3 &&
08456 PM_SaberInTransition(ps->saberMove))
08457 {
08458 if (cmd->forwardmove < 0)
08459 {
08460 ps->speed *= 0.4f;
08461 }
08462 else
08463 {
08464 ps->speed *= 0.6f;
08465 }
08466 }
08467
08468 if ( BG_InRoll( ps, ps->legsAnim ) && ps->speed > 50 )
08469 {
08470 if ((ps->legsAnim) == BOTH_ROLL_B)
08471 {
08472 if (ps->legsTimer > 800)
08473 {
08474 ps->speed = ps->legsTimer/2.5;
08475 }
08476 else
08477 {
08478 ps->speed = ps->legsTimer/6.0;
08479 }
08480 }
08481 else
08482 {
08483 if (ps->legsTimer > 800)
08484 {
08485 ps->speed = ps->legsTimer/1.5;
08486 }
08487 else
08488 {
08489 ps->speed = ps->legsTimer/5.0;
08490 }
08491 }
08492 if (ps->speed > 600)
08493 {
08494 ps->speed = 600;
08495 }
08496
08497 }
08498
08499 saber = BG_MySaber( ps->clientNum, 0 );
08500 if ( saber
08501 && saber->moveSpeedScale != 1.0f )
08502 {
08503 ps->speed *= saber->moveSpeedScale;
08504 }
08505 saber = BG_MySaber( ps->clientNum, 1 );
08506 if ( saber
08507 && saber->moveSpeedScale != 1.0f )
08508 {
08509 ps->speed *= saber->moveSpeedScale;
08510 }
08511 }
08512
08513 qboolean BG_InRollAnim( entityState_t *cent )
08514 {
08515 switch ( (cent->legsAnim) )
08516 {
08517 case BOTH_ROLL_F:
08518 case BOTH_ROLL_B:
08519 case BOTH_ROLL_R:
08520 case BOTH_ROLL_L:
08521 return qtrue;
08522 }
08523 return qfalse;
08524 }
08525
08526 qboolean BG_InKnockDown( int anim )
08527 {
08528 switch ( (anim) )
08529 {
08530 case BOTH_KNOCKDOWN1:
08531 case BOTH_KNOCKDOWN2:
08532 case BOTH_KNOCKDOWN3:
08533 case BOTH_KNOCKDOWN4:
08534 case BOTH_KNOCKDOWN5:
08535 return qtrue;
08536 break;
08537 case BOTH_GETUP1:
08538 case BOTH_GETUP2:
08539 case BOTH_GETUP3:
08540 case BOTH_GETUP4:
08541 case BOTH_GETUP5:
08542 case BOTH_FORCE_GETUP_F1:
08543 case BOTH_FORCE_GETUP_F2:
08544 case BOTH_FORCE_GETUP_B1:
08545 case BOTH_FORCE_GETUP_B2:
08546 case BOTH_FORCE_GETUP_B3:
08547 case BOTH_FORCE_GETUP_B4:
08548 case BOTH_FORCE_GETUP_B5:
08549 case BOTH_GETUP_BROLL_B:
08550 case BOTH_GETUP_BROLL_F:
08551 case BOTH_GETUP_BROLL_L:
08552 case BOTH_GETUP_BROLL_R:
08553 case BOTH_GETUP_FROLL_B:
08554 case BOTH_GETUP_FROLL_F:
08555 case BOTH_GETUP_FROLL_L:
08556 case BOTH_GETUP_FROLL_R:
08557 return qtrue;
08558 break;
08559 }
08560 return qfalse;
08561 }
08562
08563 qboolean BG_InRollES( entityState_t *ps, int anim )
08564 {
08565 switch ( (anim) )
08566 {
08567 case BOTH_ROLL_F:
08568 case BOTH_ROLL_B:
08569 case BOTH_ROLL_R:
08570 case BOTH_ROLL_L:
08571 return qtrue;
08572 break;
08573 }
08574 return qfalse;
08575 }
08576
08577 void BG_IK_MoveArm(void *ghoul2, int lHandBolt, int time, entityState_t *ent, int basePose, vec3_t desiredPos, qboolean *ikInProgress,
08578 vec3_t origin, vec3_t angles, vec3_t scale, int blendTime, qboolean forceHalt)
08579 {
08580 mdxaBone_t lHandMatrix;
08581 vec3_t lHand;
08582 vec3_t torg;
08583 float distToDest;
08584
08585 if (!ghoul2)
08586 {
08587 return;
08588 }
08589
08590 assert(bgHumanoidAnimations[basePose].firstFrame > 0);
08591
08592 if (!*ikInProgress && !forceHalt)
08593 {
08594 int baseposeAnim = basePose;
08595 sharedSetBoneIKStateParams_t ikP;
08596
08597
08598
08599
08600
08601
08602
08603
08604 VectorSet(ikP.pcjMins,0,0,0);
08605 VectorSet(ikP.pcjMaxs,0,0,0);
08606
08607
08608 ikP.blendTime = blendTime;
08609 VectorCopy(origin, ikP.origin);
08610 VectorCopy(angles, ikP.angles);
08611 ikP.angles[PITCH] = 0;
08612 ikP.pcjOverrides = 0;
08613 ikP.radius = 10.0f;
08614 VectorCopy(scale, ikP.scale);
08615
08616
08617 ikP.startFrame = bgHumanoidAnimations[baseposeAnim].firstFrame + bgHumanoidAnimations[baseposeAnim].numFrames;
08618 ikP.endFrame = bgHumanoidAnimations[baseposeAnim].firstFrame + bgHumanoidAnimations[baseposeAnim].numFrames;
08619
08620 ikP.forceAnimOnBone = qfalse;
08621
08622
08623
08624
08625 if (!strap_G2API_SetBoneIKState(ghoul2, time, NULL, IKS_DYNAMIC, &ikP))
08626 {
08627 assert(!"Failed to init IK system for g2 instance!");
08628 }
08629
08630
08631 if (strap_G2API_SetBoneIKState(ghoul2, time, "lhumerus", IKS_DYNAMIC, &ikP))
08632 {
08633
08634 VectorSet(ikP.pcjMins,-90.0f,-20.0f,-20.0f);
08635 VectorSet(ikP.pcjMaxs,30.0f,20.0f,-20.0f);
08636
08637 if (strap_G2API_SetBoneIKState(ghoul2, time, "lradius", IKS_DYNAMIC, &ikP))
08638 {
08639 *ikInProgress = qtrue;
08640 }
08641 }
08642 }
08643
08644 if (*ikInProgress && !forceHalt)
08645 {
08646 sharedIKMoveParams_t ikM;
08647 sharedRagDollUpdateParams_t tuParms;
08648 vec3_t tAngles;
08649
08650
08651 VectorCopy(desiredPos, ikM.desiredOrigin);
08652
08653 VectorCopy(angles, tAngles);
08654 tAngles[PITCH] = tAngles[ROLL] = 0;
08655
08656 strap_G2API_GetBoltMatrix(ghoul2, 0, lHandBolt, &lHandMatrix, tAngles, origin, time, 0, scale);
08657
08658 lHand[0] = lHandMatrix.matrix[0][3];
08659 lHand[1] = lHandMatrix.matrix[1][3];
08660 lHand[2] = lHandMatrix.matrix[2][3];
08661
08662 VectorSubtract(lHand, desiredPos, torg);
08663 distToDest = VectorLength(torg);
08664
08665
08666
08667 if (distToDest < 2)
08668 {
08669 ikM.movementSpeed = 0.4f;
08670 }
08671 else if (distToDest < 16)
08672 {
08673 ikM.movementSpeed = 0.9f;
08674 }
08675 else if (distToDest < 32)
08676 {
08677 ikM.movementSpeed = 0.8f;
08678 }
08679 else if (distToDest < 64)
08680 {
08681 ikM.movementSpeed = 0.7f;
08682 }
08683 else
08684 {
08685 ikM.movementSpeed = 0.6f;
08686 }
08687 VectorCopy(origin, ikM.origin);
08688
08689 ikM.boneName[0] = 0;
08690 if (strap_G2API_IKMove(ghoul2, time, &ikM))
08691 {
08692
08693 VectorCopy(angles, tuParms.angles);
08694 tuParms.angles[PITCH] = 0;
08695
08696 VectorCopy(origin, tuParms.position);
08697 VectorCopy(scale, tuParms.scale);
08698
08699 tuParms.me = ent->number;
08700 VectorClear(tuParms.velocity);
08701
08702 strap_G2API_AnimateG2Models(ghoul2, time, &tuParms);
08703 }
08704 else
08705 {
08706 *ikInProgress = qfalse;
08707 }
08708 }
08709 else if (*ikInProgress)
08710 {
08711 float cFrame, animSpeed;
08712 int sFrame, eFrame, flags;
08713
08714 strap_G2API_SetBoneIKState(ghoul2, time, "lhumerus", IKS_NONE, NULL);
08715 strap_G2API_SetBoneIKState(ghoul2, time, "lradius", IKS_NONE, NULL);
08716
08717
08718 strap_G2API_SetBoneAngles(ghoul2, 0, "lhumerus", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL, 0, time);
08719 strap_G2API_SetBoneAngles(ghoul2, 0, "lradius", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL, 0, time);
08720
08721
08722 strap_G2API_GetBoneAnim(ghoul2, "pelvis", (const int)time, &cFrame, &sFrame, &eFrame, &flags, &animSpeed, 0, 0);
08723 strap_G2API_SetBoneAnim(ghoul2, 0, "lhumerus", sFrame, eFrame, flags, animSpeed, time, sFrame, 300);
08724 strap_G2API_SetBoneAnim(ghoul2, 0, "lradius", sFrame, eFrame, flags, animSpeed, time, sFrame, 300);
08725
08726
08727 strap_G2API_SetBoneIKState(ghoul2, time, NULL, IKS_NONE, NULL);
08728
08729 *ikInProgress = qfalse;
08730 }
08731 }
08732
08733
08734 void BG_UpdateLookAngles( int lookingDebounceTime, vec3_t lastHeadAngles, int time, vec3_t lookAngles, float lookSpeed, float minPitch, float maxPitch, float minYaw, float maxYaw, float minRoll, float maxRoll )
08735 {
08736 static const float fFrameInter = 0.1f;
08737 static vec3_t oldLookAngles;
08738 static vec3_t lookAnglesDiff;
08739 static int ang;
08740
08741 if ( lookingDebounceTime > time )
08742 {
08743
08744 if ( lookAngles[PITCH] > maxPitch )
08745 {
08746 lookAngles[PITCH] = maxPitch;
08747 }
08748 else if ( lookAngles[PITCH] < minPitch )
08749 {
08750 lookAngles[PITCH] = minPitch;
08751 }
08752 if ( lookAngles[YAW] > maxYaw )
08753 {
08754 lookAngles[YAW] = maxYaw;
08755 }
08756 else if ( lookAngles[YAW] < minYaw )
08757 {
08758 lookAngles[YAW] = minYaw;
08759 }
08760 if ( lookAngles[ROLL] > maxRoll )
08761 {
08762 lookAngles[ROLL] = maxRoll;
08763 }
08764 else if ( lookAngles[ROLL] < minRoll )
08765 {
08766 lookAngles[ROLL] = minRoll;
08767 }
08768
08769
08770
08771 VectorCopy( lastHeadAngles, oldLookAngles );
08772 VectorSubtract( lookAngles, oldLookAngles, lookAnglesDiff );
08773
08774 for ( ang = 0; ang < 3; ang++ )
08775 {
08776 lookAnglesDiff[ang] = AngleNormalize180( lookAnglesDiff[ang] );
08777 }
08778
08779 if( VectorLengthSquared( lookAnglesDiff ) )
08780 {
08781 lookAngles[PITCH] = AngleNormalize180( oldLookAngles[PITCH]+(lookAnglesDiff[PITCH]*fFrameInter*lookSpeed) );
08782 lookAngles[YAW] = AngleNormalize180( oldLookAngles[YAW]+(lookAnglesDiff[YAW]*fFrameInter*lookSpeed) );
08783 lookAngles[ROLL] = AngleNormalize180( oldLookAngles[ROLL]+(lookAnglesDiff[ROLL]*fFrameInter*lookSpeed) );
08784 }
08785 }
08786
08787 VectorCopy( lookAngles, lastHeadAngles );
08788 }
08789
08790
08791 static void BG_G2ClientNeckAngles( void *ghoul2, int time, const vec3_t lookAngles, vec3_t headAngles, vec3_t neckAngles, vec3_t thoracicAngles, vec3_t headClampMinAngles, vec3_t headClampMaxAngles )
08792 {
08793 vec3_t lA;
08794 VectorCopy( lookAngles, lA );
08795
08796 if ( lA[PITCH] < headClampMinAngles[PITCH] )
08797 {
08798 lA[PITCH] = headClampMinAngles[PITCH];
08799 }
08800 else if ( lA[PITCH] > headClampMaxAngles[PITCH] )
08801 {
08802 lA[PITCH] = headClampMaxAngles[PITCH];
08803 }
08804
08805 if ( lA[YAW] < headClampMinAngles[YAW] )
08806 {
08807 lA[YAW] = headClampMinAngles[YAW];
08808 }
08809 else if ( lA[YAW] > headClampMaxAngles[YAW] )
08810 {
08811 lA[YAW] = headClampMaxAngles[YAW];
08812 }
08813
08814 if ( lA[ROLL] < headClampMinAngles[ROLL] )
08815 {
08816 lA[ROLL] = headClampMinAngles[ROLL];
08817 }
08818 else if ( lA[ROLL] > headClampMaxAngles[ROLL] )
08819 {
08820 lA[ROLL] = headClampMaxAngles[ROLL];
08821 }
08822
08823
08824 if ( thoracicAngles[PITCH] )
08825 {
08826 thoracicAngles[PITCH] = (thoracicAngles[PITCH] + (lA[PITCH] * 0.4)) * 0.5f;
08827 }
08828 else
08829 {
08830 thoracicAngles[PITCH] = lA[PITCH] * 0.4;
08831 }
08832 if ( thoracicAngles[YAW] )
08833 {
08834 thoracicAngles[YAW] = (thoracicAngles[YAW] + (lA[YAW] * 0.1)) * 0.5f;
08835 }
08836 else
08837 {
08838 thoracicAngles[YAW] = lA[YAW] * 0.1;
08839 }
08840 if ( thoracicAngles[ROLL] )
08841 {
08842 thoracicAngles[ROLL] = (thoracicAngles[ROLL] + (lA[ROLL] * 0.1)) * 0.5f;
08843 }
08844 else
08845 {
08846 thoracicAngles[ROLL] = lA[ROLL] * 0.1;
08847 }
08848
08849 neckAngles[PITCH] = lA[PITCH] * 0.2f;
08850 neckAngles[YAW] = lA[YAW] * 0.3f;
08851 neckAngles[ROLL] = lA[ROLL] * 0.3f;
08852
08853 headAngles[PITCH] = lA[PITCH] * 0.4;
08854 headAngles[YAW] = lA[YAW] * 0.6;
08855 headAngles[ROLL] = lA[ROLL] * 0.6;
08856
08857
08858
08859
08860
08861
08862
08863
08864 strap_G2API_SetBoneAngles(ghoul2, 0, "cranium", headAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
08865 strap_G2API_SetBoneAngles(ghoul2, 0, "cervical", neckAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
08866 strap_G2API_SetBoneAngles(ghoul2, 0, "thoracic", thoracicAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
08867 }
08868
08869
08870 static void BG_G2ClientSpineAngles( void *ghoul2, int motionBolt, vec3_t cent_lerpOrigin, vec3_t cent_lerpAngles, entityState_t *cent,
08871 int time, vec3_t viewAngles, int ciLegs, int ciTorso, const vec3_t angles, vec3_t thoracicAngles,
08872 vec3_t ulAngles, vec3_t llAngles, vec3_t modelScale, float *tPitchAngle, float *tYawAngle, int *corrTime )
08873 {
08874 qboolean doCorr = qfalse;
08875
08876
08877 viewAngles[YAW] = AngleDelta( cent_lerpAngles[YAW], angles[YAW] );
08878
08879
08880 #if 1
08881 if ( !BG_FlippingAnim( cent->legsAnim ) &&
08882 !BG_SpinningSaberAnim( cent->legsAnim ) &&
08883 !BG_SpinningSaberAnim( cent->torsoAnim ) &&
08884 !BG_InSpecialJump( cent->legsAnim ) &&
08885 !BG_InSpecialJump( cent->torsoAnim ) &&
08886 !BG_InDeathAnim(cent->legsAnim) &&
08887 !BG_InDeathAnim(cent->torsoAnim) &&
08888 !BG_InRollES(cent, cent->legsAnim) &&
08889 !BG_InRollAnim(cent) &&
08890 !BG_SaberInSpecial(cent->saberMove) &&
08891 !BG_SaberInSpecialAttack(cent->torsoAnim) &&
08892 !BG_SaberInSpecialAttack(cent->legsAnim) &&
08893
08894 !BG_InKnockDown(cent->torsoAnim) &&
08895 !BG_InKnockDown(cent->legsAnim) &&
08896 !BG_InKnockDown(ciTorso) &&
08897 !BG_InKnockDown(ciLegs) &&
08898
08899 !BG_FlippingAnim( ciLegs ) &&
08900 !BG_SpinningSaberAnim( ciLegs ) &&
08901 !BG_SpinningSaberAnim( ciTorso ) &&
08902 !BG_InSpecialJump( ciLegs ) &&
08903 !BG_InSpecialJump( ciTorso ) &&
08904 !BG_InDeathAnim(ciLegs) &&
08905 !BG_InDeathAnim(ciTorso) &&
08906 !BG_SaberInSpecialAttack(ciTorso) &&
08907 !BG_SaberInSpecialAttack(ciLegs) &&
08908
08909 !(cent->eFlags & EF_DEAD) &&
08910 (cent->legsAnim) != (cent->torsoAnim) &&
08911 (ciLegs) != (ciTorso) &&
08912 !cent->m_iVehicleNum)
08913 {
08914 doCorr = qtrue;
08915 }
08916 #else
08917 if ( ((!BG_FlippingAnim( cent->legsAnim )
08918 && !BG_SpinningSaberAnim( cent->legsAnim )
08919 && !BG_SpinningSaberAnim( cent->torsoAnim )
08920 && (cent->legsAnim) != (cent->torsoAnim))
08921 ||
08922 (!BG_FlippingAnim( ciLegs )
08923 && !BG_SpinningSaberAnim( ciLegs )
08924 && !BG_SpinningSaberAnim( ciTorso )
08925 && (ciLegs) != (ciTorso)))
08926 ||
08927 ciLegs != cent->legsAnim
08928 ||
08929 ciTorso != cent->torsoAnim)
08930 {
08931 doCorr = qtrue;
08932 *corrTime = time + 1000;
08933 }
08934 else if (*corrTime >= time)
08935 {
08936 if (!BG_FlippingAnim( cent->legsAnim )
08937 && !BG_SpinningSaberAnim( cent->legsAnim )
08938 && !BG_SpinningSaberAnim( cent->torsoAnim )
08939 && !BG_FlippingAnim( ciLegs )
08940 && !BG_SpinningSaberAnim( ciLegs )
08941 && !BG_SpinningSaberAnim( ciTorso ))
08942 {
08943 doCorr = qtrue;
08944 }
08945 }
08946 #endif
08947
08948 if (doCorr)
08949 {
08950
08951 mdxaBone_t boltMatrix;
08952 vec3_t motionFwd, motionAngles;
08953 vec3_t motionRt, tempAng;
08954 int ang;
08955
08956 strap_G2API_GetBoltMatrix_NoRecNoRot( ghoul2, 0, motionBolt, &boltMatrix, vec3_origin, cent_lerpOrigin, time, 0, modelScale);
08957
08958 motionFwd[0] = -boltMatrix.matrix[0][1];
08959 motionFwd[1] = -boltMatrix.matrix[1][1];
08960 motionFwd[2] = -boltMatrix.matrix[2][1];
08961
08962 vectoangles( motionFwd, motionAngles );
08963
08964
08965 motionRt[0] = -boltMatrix.matrix[0][0];
08966 motionRt[1] = -boltMatrix.matrix[1][0];
08967 motionRt[2] = -boltMatrix.matrix[2][0];
08968
08969 vectoangles( motionRt, tempAng );
08970 motionAngles[ROLL] = -tempAng[PITCH];
08971
08972 for ( ang = 0; ang < 3; ang++ )
08973 {
08974 viewAngles[ang] = AngleNormalize180( viewAngles[ang] - AngleNormalize180( motionAngles[ang] ) );
08975 }
08976 }
08977
08978
08979
08980 thoracicAngles[PITCH] = viewAngles[PITCH]*0.20f;
08981 llAngles[PITCH] = viewAngles[PITCH]*0.40f;
08982 ulAngles[PITCH] = viewAngles[PITCH]*0.40f;
08983
08984 thoracicAngles[YAW] = viewAngles[YAW]*0.20f;
08985 ulAngles[YAW] = viewAngles[YAW]*0.35f;
08986 llAngles[YAW] = viewAngles[YAW]*0.45f;
08987
08988 thoracicAngles[ROLL] = viewAngles[ROLL]*0.20f;
08989 ulAngles[ROLL] = viewAngles[ROLL]*0.35f;
08990 llAngles[ROLL] = viewAngles[ROLL]*0.45f;
08991 }
08992
08993
08994
08995
08996
08997
08998 static float BG_SwingAngles( float destination, float swingTolerance, float clampTolerance,
08999 float speed, float *angle, qboolean *swinging, int frametime ) {
09000 float swing;
09001 float move;
09002 float scale;
09003
09004 if ( !*swinging ) {
09005
09006 swing = AngleSubtract( *angle, destination );
09007 if ( swing > swingTolerance || swing < -swingTolerance ) {
09008 *swinging = qtrue;
09009 }
09010 }
09011
09012 if ( !*swinging ) {
09013 return 0;
09014 }
09015
09016
09017
09018 swing = AngleSubtract( destination, *angle );
09019 scale = fabs( swing );
09020 if ( scale < swingTolerance * 0.5 ) {
09021 scale = 0.5;
09022 } else if ( scale < swingTolerance ) {
09023 scale = 1.0;
09024 } else {
09025 scale = 2.0;
09026 }
09027
09028
09029 if ( swing >= 0 ) {
09030 move = frametime * scale * speed;
09031 if ( move >= swing ) {
09032 move = swing;
09033 *swinging = qfalse;
09034 }
09035 *angle = AngleMod( *angle + move );
09036 } else if ( swing < 0 ) {
09037 move = frametime * scale * -speed;
09038 if ( move <= swing ) {
09039 move = swing;
09040 *swinging = qfalse;
09041 }
09042 *angle = AngleMod( *angle + move );
09043 }
09044
09045
09046 swing = AngleSubtract( destination, *angle );
09047 if ( swing > clampTolerance ) {
09048 *angle = AngleMod( destination - (clampTolerance - 1) );
09049 } else if ( swing < -clampTolerance ) {
09050 *angle = AngleMod( destination + (clampTolerance - 1) );
09051 }
09052
09053 return swing;
09054 }
09055
09056
09057
09058
09059 qboolean BG_InRoll2( entityState_t *es )
09060 {
09061 switch ( (es->legsAnim) )
09062 {
09063 case BOTH_GETUP_BROLL_B:
09064 case BOTH_GETUP_BROLL_F:
09065 case BOTH_GETUP_BROLL_L:
09066 case BOTH_GETUP_BROLL_R:
09067 case BOTH_GETUP_FROLL_B:
09068 case BOTH_GETUP_FROLL_F:
09069 case BOTH_GETUP_FROLL_L:
09070 case BOTH_GETUP_FROLL_R:
09071 case BOTH_ROLL_F:
09072 case BOTH_ROLL_B:
09073 case BOTH_ROLL_R:
09074 case BOTH_ROLL_L:
09075 return qtrue;
09076 break;
09077 }
09078 return qfalse;
09079 }
09080
09081
09082 extern qboolean BG_SaberLockBreakAnim( int anim );
09083 void BG_G2PlayerAngles(void *ghoul2, int motionBolt, entityState_t *cent, int time, vec3_t cent_lerpOrigin,
09084 vec3_t cent_lerpAngles, vec3_t legs[3], vec3_t legsAngles, qboolean *tYawing,
09085 qboolean *tPitching, qboolean *lYawing, float *tYawAngle, float *tPitchAngle,
09086 float *lYawAngle, int frametime, vec3_t turAngles, vec3_t modelScale, int ciLegs,
09087 int ciTorso, int *corrTime, vec3_t lookAngles, vec3_t lastHeadAngles, int lookTime,
09088 entityState_t *emplaced, int *crazySmoothFactor)
09089 {
09090 int adddir = 0;
09091 static int dir;
09092 static int i;
09093 static int movementOffsets[8] = { 0, 22, 45, -22, 0, 22, -45, -22 };
09094 float degrees_negative = 0;
09095 float degrees_positive = 0;
09096 static float dif;
09097 static float dest;
09098 static float speed;
09099 static const float lookSpeed = 1.5f;
09100 #ifdef BONE_BASED_LEG_ANGLES
09101 static float legBoneYaw;
09102 #endif
09103 static vec3_t eyeAngles;
09104 static vec3_t neckAngles;
09105 static vec3_t velocity;
09106 static vec3_t torsoAngles, headAngles;
09107 static vec3_t velPos, velAng;
09108 static vec3_t ulAngles, llAngles, viewAngles, angles, thoracicAngles = {0,0,0};
09109 static vec3_t headClampMinAngles = {-25,-55,-10}, headClampMaxAngles = {50,50,10};
09110
09111 if ( cent->m_iVehicleNum || cent->forceFrame || BG_SaberLockBreakAnim(cent->legsAnim) || BG_SaberLockBreakAnim(cent->torsoAnim) )
09112 {
09113 vec3_t forcedAngles;
09114
09115 VectorClear(forcedAngles);
09116 forcedAngles[YAW] = cent_lerpAngles[YAW];
09117 forcedAngles[ROLL] = cent_lerpAngles[ROLL];
09118 AnglesToAxis( forcedAngles, legs );
09119 VectorCopy(forcedAngles, legsAngles);
09120
09121 if (cent->number < MAX_CLIENTS)
09122 {
09123 strap_G2API_SetBoneAngles(ghoul2, 0, "lower_lumbar", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09124 strap_G2API_SetBoneAngles(ghoul2, 0, "upper_lumbar", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09125 strap_G2API_SetBoneAngles(ghoul2, 0, "cranium", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09126 strap_G2API_SetBoneAngles(ghoul2, 0, "thoracic", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09127 strap_G2API_SetBoneAngles(ghoul2, 0, "cervical", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09128 }
09129 return;
09130 }
09131
09132 if ((time+2000) < *corrTime)
09133 {
09134 *corrTime = 0;
09135 }
09136
09137 VectorCopy( cent_lerpAngles, headAngles );
09138 headAngles[YAW] = AngleMod( headAngles[YAW] );
09139 VectorClear( legsAngles );
09140 VectorClear( torsoAngles );
09141
09142
09143
09144 if ((( cent->legsAnim ) != BOTH_STAND1) ||
09145 ( cent->torsoAnim ) != WeaponReadyAnim[cent->weapon] )
09146 {
09147
09148
09149 *tYawing = qtrue;
09150
09151 *tPitching = qtrue;
09152
09153 *lYawing = qtrue;
09154 }
09155
09156
09157 if ( cent->eFlags & EF_DEAD ) {
09158
09159 dir = 0;
09160 } else {
09161 dir = cent->angles2[YAW];
09162 if ( dir < 0 || dir > 7 ) {
09163 Com_Error( ERR_DROP, "Bad player movement angle (%i)", dir );
09164 }
09165 }
09166
09167 torsoAngles[YAW] = headAngles[YAW];
09168
09169
09170 *tYawAngle = torsoAngles[YAW];
09171
09172
09173
09174 VectorCopy( cent->pos.trDelta, velocity );
09175
09176 if (BG_InRoll2(cent))
09177 {
09178 VectorClear(velocity);
09179 }
09180 else if (cent->weapon == WP_SABER &&
09181 BG_SaberInSpecial(cent->saberMove))
09182 {
09183 VectorClear(velocity);
09184 }
09185
09186 speed = VectorNormalize( velocity );
09187
09188 if (!speed)
09189 {
09190 torsoAngles[YAW] = headAngles[YAW];
09191 }
09192
09193
09194 if ( headAngles[PITCH] > 180 ) {
09195 dest = (-360 + headAngles[PITCH]) * 0.75;
09196 } else {
09197 dest = headAngles[PITCH] * 0.75;
09198 }
09199
09200 if (cent->m_iVehicleNum)
09201 {
09202 *tPitchAngle = dest;
09203 }
09204 else
09205 {
09206 BG_SwingAngles( dest, 15, 30, 0.1, tPitchAngle, tPitching, frametime );
09207 }
09208 torsoAngles[PITCH] = *tPitchAngle;
09209
09210
09211
09212 if ( speed ) {
09213 vec3_t axis[3];
09214 float side;
09215
09216 speed *= 0.05;
09217
09218 AnglesToAxis( legsAngles, axis );
09219 side = speed * DotProduct( velocity, axis[1] );
09220 legsAngles[ROLL] -= side;
09221
09222 side = speed * DotProduct( velocity, axis[0] );
09223 legsAngles[PITCH] += side;
09224 }
09225
09226
09227
09228
09229 legsAngles[YAW] = headAngles[YAW];
09230 velPos[0] = cent_lerpOrigin[0] + velocity[0];
09231 velPos[1] = cent_lerpOrigin[1] + velocity[1];
09232 velPos[2] = cent_lerpOrigin[2];
09233
09234 if ( cent->groundEntityNum == ENTITYNUM_NONE ||
09235 cent->forceFrame ||
09236 (cent->weapon == WP_EMPLACED_GUN && emplaced) )
09237 {
09238 VectorCopy(cent_lerpOrigin, velPos);
09239 }
09240
09241 VectorSubtract(cent_lerpOrigin, velPos, velAng);
09242
09243 if (!VectorCompare(velAng, vec3_origin))
09244 {
09245 vectoangles(velAng, velAng);
09246
09247 if (velAng[YAW] <= legsAngles[YAW])
09248 {
09249 degrees_negative = (legsAngles[YAW] - velAng[YAW]);
09250 degrees_positive = (360 - legsAngles[YAW]) + velAng[YAW];
09251 }
09252 else
09253 {
09254 degrees_negative = legsAngles[YAW] + (360 - velAng[YAW]);
09255 degrees_positive = (velAng[YAW] - legsAngles[YAW]);
09256 }
09257
09258 if ( degrees_negative < degrees_positive )
09259 {
09260 dif = degrees_negative;
09261 adddir = 0;
09262 }
09263 else
09264 {
09265 dif = degrees_positive;
09266 adddir = 1;
09267 }
09268
09269 if (dif > 90)
09270 {
09271 dif = (180 - dif);
09272 }
09273
09274 if (dif > 60)
09275 {
09276 dif = 60;
09277 }
09278
09279
09280 if (dir == 3 || dir == 5)
09281 {
09282 dif = -dif;
09283 }
09284
09285 if (adddir)
09286 {
09287 legsAngles[YAW] -= dif;
09288 }
09289 else
09290 {
09291 legsAngles[YAW] += dif;
09292 }
09293 }
09294
09295 if (cent->m_iVehicleNum)
09296 {
09297 *lYawAngle = legsAngles[YAW];
09298 }
09299 else
09300 {
09301 BG_SwingAngles( legsAngles[YAW], 0, 90, 0.65, lYawAngle, lYawing, frametime );
09302 }
09303 legsAngles[YAW] = *lYawAngle;
09304
09305
09306
09307
09308
09309
09310 legsAngles[ROLL] = 0;
09311 torsoAngles[ROLL] = 0;
09312
09313
09314
09315
09316 AnglesSubtract( headAngles, torsoAngles, headAngles );
09317 AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
09318
09319 legsAngles[PITCH] = 0;
09320
09321 if (cent->heldByClient)
09322 {
09323
09324 VectorClear(legsAngles);
09325 legsAngles[YAW] = cent_lerpAngles[YAW];
09326 }
09327
09328 #ifdef BONE_BASED_LEG_ANGLES
09329 legBoneYaw = legsAngles[YAW];
09330 VectorClear(legsAngles);
09331 legsAngles[YAW] = cent_lerpAngles[YAW];
09332 #endif
09333
09334 VectorCopy(legsAngles, turAngles);
09335
09336 AnglesToAxis( legsAngles, legs );
09337
09338 VectorCopy( cent_lerpAngles, viewAngles );
09339 viewAngles[YAW] = viewAngles[ROLL] = 0;
09340 viewAngles[PITCH] *= 0.5;
09341
09342 VectorSet( angles, 0, legsAngles[1], 0 );
09343
09344 angles[0] = legsAngles[0];
09345 if ( angles[0] > 30 )
09346 {
09347 angles[0] = 30;
09348 }
09349 else if ( angles[0] < -30 )
09350 {
09351 angles[0] = -30;
09352 }
09353
09354 if (cent->weapon == WP_EMPLACED_GUN &&
09355 emplaced)
09356 {
09357 vec3_t facingAngles;
09358
09359 VectorSubtract(emplaced->pos.trBase, cent_lerpOrigin, facingAngles);
09360 vectoangles(facingAngles, facingAngles);
09361
09362 if (emplaced->weapon == WP_NONE)
09363 {
09364 VectorCopy(facingAngles, legsAngles);
09365 AnglesToAxis( legsAngles, legs );
09366 }
09367 else
09368 {
09369 float dif = AngleSubtract(cent_lerpAngles[YAW], facingAngles[YAW]);
09370
09371
09372
09373
09374
09375
09376
09377
09378 VectorSet(facingAngles, -16.0f, -dif, 0.0f);
09379
09380 if (cent->legsAnim == BOTH_STRAFE_LEFT1 || cent->legsAnim == BOTH_STRAFE_RIGHT1)
09381 {
09382 if (crazySmoothFactor)
09383 {
09384 *crazySmoothFactor = time + 1000;
09385 }
09386
09387 BG_G2ClientSpineAngles(ghoul2, motionBolt, cent_lerpOrigin, cent_lerpAngles, cent, time,
09388 viewAngles, ciLegs, ciTorso, angles, thoracicAngles, ulAngles, llAngles, modelScale,
09389 tPitchAngle, tYawAngle, corrTime);
09390 strap_G2API_SetBoneAngles(ghoul2, 0, "lower_lumbar", llAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09391 strap_G2API_SetBoneAngles(ghoul2, 0, "upper_lumbar", ulAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09392 strap_G2API_SetBoneAngles(ghoul2, 0, "cranium", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09393
09394 VectorAdd(facingAngles, thoracicAngles, facingAngles);
09395
09396 if (cent->legsAnim == BOTH_STRAFE_LEFT1)
09397 {
09398 facingAngles[YAW] -= 32.0f;
09399 }
09400 }
09401 else
09402 {
09403
09404
09405 strap_G2API_SetBoneAngles(ghoul2, 0, "cranium", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09406 }
09407
09408 VectorScale(facingAngles, 0.6f, facingAngles);
09409 strap_G2API_SetBoneAngles(ghoul2, 0, "lower_lumbar", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09410 VectorScale(facingAngles, 0.8f, facingAngles);
09411 strap_G2API_SetBoneAngles(ghoul2, 0, "upper_lumbar", facingAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09412 VectorScale(facingAngles, 0.8f, facingAngles);
09413 strap_G2API_SetBoneAngles(ghoul2, 0, "thoracic", facingAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09414
09415
09416 VectorSet(facingAngles, 0.0f, dif, 0.0f);
09417 VectorScale(facingAngles, 0.6f, facingAngles);
09418 strap_G2API_SetBoneAngles(ghoul2, 0, "cervical", facingAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09419
09420 return;
09421 }
09422 }
09423
09424 BG_G2ClientSpineAngles(ghoul2, motionBolt, cent_lerpOrigin, cent_lerpAngles, cent, time,
09425 viewAngles, ciLegs, ciTorso, angles, thoracicAngles, ulAngles, llAngles, modelScale,
09426 tPitchAngle, tYawAngle, corrTime);
09427
09428 VectorCopy(cent_lerpAngles, eyeAngles);
09429
09430 for ( i = 0; i < 3; i++ )
09431 {
09432 lookAngles[i] = AngleNormalize180( lookAngles[i] );
09433 eyeAngles[i] = AngleNormalize180( eyeAngles[i] );
09434 }
09435 AnglesSubtract( lookAngles, eyeAngles, lookAngles );
09436
09437 BG_UpdateLookAngles(lookTime, lastHeadAngles, time, lookAngles, lookSpeed, -50.0f, 50.0f, -70.0f, 70.0f, -30.0f, 30.0f);
09438
09439 BG_G2ClientNeckAngles(ghoul2, time, lookAngles, headAngles, neckAngles, thoracicAngles, headClampMinAngles, headClampMaxAngles);
09440
09441 #ifdef BONE_BASED_LEG_ANGLES
09442 {
09443 vec3_t bLAngles;
09444 VectorClear(bLAngles);
09445 bLAngles[ROLL] = AngleNormalize180((legBoneYaw - cent_lerpAngles[YAW]));
09446 strap_G2API_SetBoneAngles(ghoul2, 0, "model_root", bLAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09447
09448 if (!llAngles[YAW])
09449 {
09450 llAngles[YAW] -= bLAngles[ROLL];
09451 }
09452 }
09453 #endif
09454 strap_G2API_SetBoneAngles(ghoul2, 0, "lower_lumbar", llAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09455 strap_G2API_SetBoneAngles(ghoul2, 0, "upper_lumbar", ulAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09456 strap_G2API_SetBoneAngles(ghoul2, 0, "thoracic", thoracicAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09457
09458 }
09459
09460 void BG_G2ATSTAngles(void *ghoul2, int time, vec3_t cent_lerpAngles )
09461 {
09462 strap_G2API_SetBoneAngles(ghoul2, 0, "thoracic", cent_lerpAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, time);
09463 }
09464
09465 static qboolean PM_AdjustAnglesForDualJumpAttack( playerState_t *ps, usercmd_t *ucmd )
09466 {
09467
09468
09469 return qtrue;
09470 }
09471
09472 #ifdef __LCC__
09473 static void PM_CmdForSaberMoves(usercmd_t *ucmd)
09474 #else
09475 static ID_INLINE void PM_CmdForSaberMoves(usercmd_t *ucmd)
09476 #endif
09477 {
09478
09479 if ( ( pm->ps->legsAnim == BOTH_JUMPATTACK6
09480 && pm->ps->saberMove == LS_JUMPATTACK_DUAL )
09481 || ( pm->ps->legsAnim == BOTH_BUTTERFLY_FL1
09482 && pm->ps->saberMove == LS_JUMPATTACK_STAFF_LEFT )
09483 || ( pm->ps->legsAnim == BOTH_BUTTERFLY_FR1
09484 && pm->ps->saberMove == LS_JUMPATTACK_STAFF_RIGHT )
09485 || ( pm->ps->legsAnim == BOTH_BUTTERFLY_RIGHT
09486 && pm->ps->saberMove == LS_BUTTERFLY_RIGHT )
09487 || ( pm->ps->legsAnim == BOTH_BUTTERFLY_LEFT
09488 && pm->ps->saberMove == LS_BUTTERFLY_LEFT ) )
09489 {
09490 int aLen = PM_AnimLength(0, BOTH_JUMPATTACK6);
09491
09492 ucmd->forwardmove = ucmd->rightmove = ucmd->upmove = 0;
09493
09494 if ( pm->ps->legsAnim == BOTH_JUMPATTACK6 )
09495 {
09496 if ( pm->ps->legsTimer >= 100
09497 && (aLen - pm->ps->legsTimer) >= 250 )
09498 {
09499
09500 ucmd->forwardmove = 127;
09501 }
09502
09503 if ( (pm->ps->legsTimer >= 900
09504 && aLen - pm->ps->legsTimer >= 950 )
09505 || ( pm->ps->legsTimer >= 1600
09506 && aLen - pm->ps->legsTimer >= 400 ) )
09507 {
09508 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
09509 {
09510 if ( pm->ps->groundEntityNum >= MAX_CLIENTS )
09511 {
09512
09513 pm->ps->velocity[2] = 250;
09514 pm->ps->fd.forceJumpZStart = pm->ps->origin[2];
09515
09516
09517 PM_AddEvent(EV_JUMP);
09518
09519 }
09520 }
09521 else
09522 {
09523 }
09524 }
09525 }
09526 else
09527 {
09528 int aLen = PM_AnimLength(0, (animNumber_t)pm->ps->legsAnim);
09529 float lenMin = 1700.0f;
09530 float lenMax = 1800.0f;
09531
09532 if (pm->ps->legsAnim == BOTH_BUTTERFLY_LEFT)
09533 {
09534 lenMin = 1200.0f;
09535 lenMax = 1400.0f;
09536 }
09537
09538
09539 if ( pm->ps->legsAnim == BOTH_BUTTERFLY_RIGHT
09540 || pm->ps->legsAnim == BOTH_BUTTERFLY_LEFT )
09541 {
09542 if ( pm->ps->legsTimer > 450 )
09543 {
09544 switch ( pm->ps->legsAnim )
09545 {
09546 case BOTH_BUTTERFLY_LEFT:
09547 ucmd->rightmove = -127;
09548 break;
09549 case BOTH_BUTTERFLY_RIGHT:
09550 ucmd->rightmove = 127;
09551 break;
09552 default:
09553 break;
09554 }
09555 }
09556 }
09557 else
09558 {
09559 if ( pm->ps->legsTimer >= 100
09560 && aLen - pm->ps->legsTimer >= 250 )
09561 {
09562
09563 ucmd->forwardmove = 127;
09564 }
09565 }
09566
09567 if ( pm->ps->legsTimer >= lenMin && pm->ps->legsTimer < lenMax )
09568 {
09569 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
09570 {
09571
09572 if (pm->ps->legsAnim == BOTH_BUTTERFLY_LEFT)
09573 {
09574 pm->ps->velocity[2] = 350;
09575 }
09576 else
09577 {
09578 pm->ps->velocity[2] = 250;
09579 }
09580 pm->ps->fd.forceJumpZStart = pm->ps->origin[2];
09581
09582
09583 PM_AddEvent(EV_JUMP);
09584
09585 }
09586 else
09587 {
09588 }
09589 }
09590 }
09591
09592 if ( pm->ps->groundEntityNum == ENTITYNUM_NONE )
09593 {
09594 if (PM_AdjustAnglesForDualJumpAttack(pm->ps, ucmd))
09595 {
09596 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, ucmd);
09597 }
09598 }
09599
09600 }
09601
09602 else if (pm->ps->saberMove == LS_A_BACKFLIP_ATK &&
09603 pm->ps->legsAnim == BOTH_JUMPATTACK7)
09604 {
09605 int aLen = PM_AnimLength(0, BOTH_JUMPATTACK7);
09606
09607 if ( pm->ps->legsTimer > 800
09608 && aLen - pm->ps->legsTimer >= 400 )
09609 {
09610 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
09611 {
09612 vec3_t yawAngles, backDir;
09613
09614
09615 VectorSet( yawAngles, 0, pm->ps->viewangles[YAW]+180, 0 );
09616 AngleVectors( yawAngles, backDir, 0, 0 );
09617 VectorScale( backDir, 100, pm->ps->velocity );
09618
09619
09620 pm->ps->velocity[2] = 300;
09621 pm->ps->fd.forceJumpZStart = pm->ps->origin[2];
09622
09623
09624
09625 PM_AddEvent(EV_JUMP);
09626
09627 ucmd->upmove = 0;
09628 }
09629 }
09630 ucmd->forwardmove = ucmd->rightmove = ucmd->upmove = 0;
09631 }
09632
09633 else if (pm->ps->saberMove == LS_SPINATTACK ||
09634 pm->ps->saberMove == LS_SPINATTACK_DUAL)
09635 {
09636 ucmd->forwardmove = ucmd->rightmove = ucmd->upmove = 0;
09637
09638 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, ucmd);
09639 }
09640 }
09641
09642
09643 void PM_VehicleViewAngles(playerState_t *ps, bgEntity_t *veh, usercmd_t *ucmd)
09644 {
09645 Vehicle_t *pVeh = veh->m_pVehicle;
09646 qboolean setAngles = qtrue;
09647 vec3_t clampMin;
09648 vec3_t clampMax;
09649 int i;
09650
09651 if ( veh->m_pVehicle->m_pPilot
09652 && veh->m_pVehicle->m_pPilot->s.number == ps->clientNum )
09653 {
09654 #ifdef VEH_CONTROL_SCHEME_4
09655 if ( 1 )
09656 #else //VEH_CONTROL_SCHEME_4
09657 if ( !BG_UnrestrainedPitchRoll( ps, veh->m_pVehicle ) )
09658 #endif //VEH_CONTROL_SCHEME_4
09659 {
09660 setAngles = qtrue;
09661 clampMin[PITCH] = -pVeh->m_pVehicleInfo->lookPitch;
09662 clampMax[PITCH] = pVeh->m_pVehicleInfo->lookPitch;
09663 clampMin[YAW] = clampMax[YAW] = 0;
09664 clampMin[ROLL] = clampMax[ROLL] = -1;
09665 }
09666 }
09667 else
09668 {
09669
09670 for ( i = 0; i < MAX_VEHICLE_TURRETS; i++ )
09671 {
09672 if ( veh->m_pVehicle->m_pVehicleInfo->turret[i].passengerNum == ps->generic1 )
09673 {
09674 setAngles = qtrue;
09675 clampMin[PITCH] = veh->m_pVehicle->m_pVehicleInfo->turret[i].pitchClampUp;
09676 clampMax[PITCH] = veh->m_pVehicle->m_pVehicleInfo->turret[i].pitchClampDown;
09677 clampMin[YAW] = veh->m_pVehicle->m_pVehicleInfo->turret[i].yawClampRight;
09678 clampMax[YAW] = veh->m_pVehicle->m_pVehicleInfo->turret[i].yawClampLeft;
09679 clampMin[ROLL] = clampMax[ROLL] = 0;
09680 break;
09681 }
09682 }
09683 }
09684 if ( setAngles )
09685 {
09686 for ( i = 0; i < 3; i++ )
09687 {
09688 if ( clampMin[i] == -1 || clampMax[i] == -1 )
09689 {
09690 }
09691 else if ( !clampMin[i] && !clampMax[i] )
09692 {
09693
09694 }
09695 else
09696 {
09697 if (ps->viewangles[i] > clampMax[i])
09698 {
09699 ps->viewangles[i] = clampMax[i];
09700 }
09701 else if (ps->viewangles[i] < clampMin[i])
09702 {
09703 ps->viewangles[i] = clampMin[i];
09704 }
09705 }
09706 }
09707
09708 PM_SetPMViewAngle(ps, ps->viewangles, ucmd);
09709 }
09710 }
09711
09712
09713
09714
09715
09716
09717
09718
09719
09720
09721
09722
09723
09724
09725
09726
09727
09728
09729
09730
09731
09732
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742 qboolean PM_WeaponOkOnVehicle( int weapon )
09743 {
09744
09745 switch ( weapon )
09746 {
09747
09748 case WP_MELEE:
09749 case WP_SABER:
09750 case WP_BLASTER:
09751
09752 return qtrue;
09753 break;
09754 }
09755 return qfalse;
09756 }
09757
09758
09759 int PM_GetOkWeaponForVehicle(void)
09760 {
09761 int i = 0;
09762
09763 while (i < WP_NUM_WEAPONS)
09764 {
09765 if ((pm->ps->stats[STAT_WEAPONS] & (1 << i)) &&
09766 PM_WeaponOkOnVehicle(i))
09767 {
09768 return i;
09769 }
09770
09771 i++;
09772 }
09773
09774
09775
09776 return -1;
09777 }
09778
09779
09780 void PM_VehForcedTurning(bgEntity_t *veh)
09781 {
09782 bgEntity_t *dst = PM_BGEntForNum(veh->playerState->vehTurnaroundIndex);
09783 float pitchD, yawD;
09784 vec3_t dir;
09785
09786 if (!veh || !veh->m_pVehicle)
09787 {
09788 return;
09789 }
09790
09791 if (!dst)
09792 {
09793 return;
09794 }
09795
09796 pm->cmd.upmove = veh->m_pVehicle->m_ucmd.upmove = 127;
09797 pm->cmd.forwardmove = veh->m_pVehicle->m_ucmd.forwardmove = 0;
09798 pm->cmd.rightmove = veh->m_pVehicle->m_ucmd.rightmove = 0;
09799
09800 VectorSubtract(dst->s.origin, veh->playerState->origin, dir);
09801 vectoangles(dir, dir);
09802
09803 yawD = AngleSubtract(pm->ps->viewangles[YAW], dir[YAW]);
09804 pitchD = AngleSubtract(pm->ps->viewangles[PITCH], dir[PITCH]);
09805
09806 yawD *= 0.6f*pml.frametime;
09807 pitchD *= 0.6f*pml.frametime;
09808
09809 #ifdef VEH_CONTROL_SCHEME_4
09810 veh->playerState->viewangles[YAW] = AngleSubtract(veh->playerState->viewangles[YAW], yawD);
09811 veh->playerState->viewangles[PITCH] = AngleSubtract(veh->playerState->viewangles[PITCH], pitchD);
09812 pm->ps->viewangles[YAW] = veh->playerState->viewangles[YAW];
09813 pm->ps->viewangles[PITCH] = 0;
09814
09815 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
09816 PM_SetPMViewAngle(veh->playerState, veh->playerState->viewangles, &pm->cmd);
09817 VectorClear( veh->m_pVehicle->m_vPrevRiderViewAngles );
09818 veh->m_pVehicle->m_vPrevRiderViewAngles[YAW] = AngleNormalize180(pm->ps->viewangles[YAW]);
09819
09820 #else //VEH_CONTROL_SCHEME_4
09821
09822 pm->ps->viewangles[YAW] = AngleSubtract(pm->ps->viewangles[YAW], yawD);
09823 pm->ps->viewangles[PITCH] = AngleSubtract(pm->ps->viewangles[PITCH], pitchD);
09824
09825 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
09826 #endif //VEH_CONTROL_SCHEME_4
09827 }
09828
09829 #ifdef VEH_CONTROL_SCHEME_4
09830 void PM_VehFaceHyperspacePoint(bgEntity_t *veh)
09831 {
09832
09833 if (!veh || !veh->m_pVehicle)
09834 {
09835 return;
09836 }
09837 else
09838 {
09839 float timeFrac = ((float)(pm->cmd.serverTime-veh->playerState->hyperSpaceTime))/HYPERSPACE_TIME;
09840 float turnRate, aDelta;
09841 int i, matchedAxes = 0;
09842
09843 pm->cmd.upmove = veh->m_pVehicle->m_ucmd.upmove = 127;
09844 pm->cmd.forwardmove = veh->m_pVehicle->m_ucmd.forwardmove = 0;
09845 pm->cmd.rightmove = veh->m_pVehicle->m_ucmd.rightmove = 0;
09846
09847 turnRate = (90.0f*pml.frametime);
09848 for ( i = 0; i < 3; i++ )
09849 {
09850 aDelta = AngleSubtract(veh->playerState->hyperSpaceAngles[i], veh->m_pVehicle->m_vOrientation[i]);
09851 if ( fabs( aDelta ) < turnRate )
09852 {
09853 veh->playerState->viewangles[i] = veh->playerState->hyperSpaceAngles[i];
09854 matchedAxes++;
09855 }
09856 else
09857 {
09858 aDelta = AngleSubtract(veh->playerState->hyperSpaceAngles[i], veh->playerState->viewangles[i]);
09859 if ( fabs( aDelta ) < turnRate )
09860 {
09861 veh->playerState->viewangles[i] = veh->playerState->hyperSpaceAngles[i];
09862 }
09863 else if ( aDelta > 0 )
09864 {
09865 if ( i == YAW )
09866 {
09867 veh->playerState->viewangles[i] = AngleNormalize360( veh->playerState->viewangles[i]+turnRate );
09868 }
09869 else
09870 {
09871 veh->playerState->viewangles[i] = AngleNormalize180( veh->playerState->viewangles[i]+turnRate );
09872 }
09873 }
09874 else
09875 {
09876 if ( i == YAW )
09877 {
09878 veh->playerState->viewangles[i] = AngleNormalize360( veh->playerState->viewangles[i]-turnRate );
09879 }
09880 else
09881 {
09882 veh->playerState->viewangles[i] = AngleNormalize180( veh->playerState->viewangles[i]-turnRate );
09883 }
09884 }
09885 }
09886 }
09887
09888 pm->ps->viewangles[YAW] = veh->playerState->viewangles[YAW];
09889 pm->ps->viewangles[PITCH] = 0.0f;
09890
09891 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
09892 PM_SetPMViewAngle(veh->playerState, veh->playerState->viewangles, &pm->cmd);
09893 VectorClear( veh->m_pVehicle->m_vPrevRiderViewAngles );
09894 veh->m_pVehicle->m_vPrevRiderViewAngles[YAW] = AngleNormalize180(pm->ps->viewangles[YAW]);
09895
09896 if ( timeFrac < HYPERSPACE_TELEPORT_FRAC )
09897 {
09898 if ( matchedAxes < 3 )
09899 {
09900
09901 veh->playerState->hyperSpaceTime += pml.msec;
09902 }
09903 else if ( !(veh->playerState->eFlags2&EF2_HYPERSPACE))
09904 {
09905 veh->playerState->eFlags2 |= EF2_HYPERSPACE;
09906 }
09907 }
09908 }
09909 }
09910
09911 #else //VEH_CONTROL_SCHEME_4
09912
09913 void PM_VehFaceHyperspacePoint(bgEntity_t *veh)
09914 {
09915
09916 if (!veh || !veh->m_pVehicle)
09917 {
09918 return;
09919 }
09920 else
09921 {
09922 float timeFrac = ((float)(pm->cmd.serverTime-veh->playerState->hyperSpaceTime))/HYPERSPACE_TIME;
09923 float turnRate, aDelta;
09924 int i, matchedAxes = 0;
09925
09926 pm->cmd.upmove = veh->m_pVehicle->m_ucmd.upmove = 127;
09927 pm->cmd.forwardmove = veh->m_pVehicle->m_ucmd.forwardmove = 0;
09928 pm->cmd.rightmove = veh->m_pVehicle->m_ucmd.rightmove = 0;
09929
09930 turnRate = (90.0f*pml.frametime);
09931 for ( i = 0; i < 3; i++ )
09932 {
09933 aDelta = AngleSubtract(veh->playerState->hyperSpaceAngles[i], veh->m_pVehicle->m_vOrientation[i]);
09934 if ( fabs( aDelta ) < turnRate )
09935 {
09936 pm->ps->viewangles[i] = veh->playerState->hyperSpaceAngles[i];
09937 matchedAxes++;
09938 }
09939 else
09940 {
09941 aDelta = AngleSubtract(veh->playerState->hyperSpaceAngles[i], pm->ps->viewangles[i]);
09942 if ( fabs( aDelta ) < turnRate )
09943 {
09944 pm->ps->viewangles[i] = veh->playerState->hyperSpaceAngles[i];
09945 }
09946 else if ( aDelta > 0 )
09947 {
09948 if ( i == YAW )
09949 {
09950 pm->ps->viewangles[i] = AngleNormalize360( pm->ps->viewangles[i]+turnRate );
09951 }
09952 else
09953 {
09954 pm->ps->viewangles[i] = AngleNormalize180( pm->ps->viewangles[i]+turnRate );
09955 }
09956 }
09957 else
09958 {
09959 if ( i == YAW )
09960 {
09961 pm->ps->viewangles[i] = AngleNormalize360( pm->ps->viewangles[i]-turnRate );
09962 }
09963 else
09964 {
09965 pm->ps->viewangles[i] = AngleNormalize180( pm->ps->viewangles[i]-turnRate );
09966 }
09967 }
09968 }
09969 }
09970
09971 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
09972
09973 if ( timeFrac < HYPERSPACE_TELEPORT_FRAC )
09974 {
09975 if ( matchedAxes < 3 )
09976 {
09977
09978 veh->playerState->hyperSpaceTime += pml.msec;
09979 }
09980 else if ( !(veh->playerState->eFlags2&EF2_HYPERSPACE))
09981 {
09982 veh->playerState->eFlags2 |= EF2_HYPERSPACE;
09983 }
09984 }
09985 }
09986 }
09987
09988 #endif //VEH_CONTROL_SCHEME_4
09989
09990 void BG_VehicleAdjustBBoxForOrientation( Vehicle_t *veh, vec3_t origin, vec3_t mins, vec3_t maxs,
09991 int clientNum, int tracemask,
09992 void (*localTrace)(trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask))
09993 {
09994 if ( !veh
09995 || !veh->m_pVehicleInfo->length
09996 || !veh->m_pVehicleInfo->width
09997 || !veh->m_pVehicleInfo->height )
09998
09999 {
10000 return;
10001 }
10002 else if ( veh->m_pVehicleInfo->type != VH_FIGHTER
10003
10004 && veh->m_pVehicleInfo->type != VH_FLIER )
10005 {
10006 VectorSet( maxs, veh->m_pVehicleInfo->width/2.0f, veh->m_pVehicleInfo->width/2.0f, veh->m_pVehicleInfo->height+DEFAULT_MINS_2 );
10007 VectorSet( mins, veh->m_pVehicleInfo->width/-2.0f, veh->m_pVehicleInfo->width/-2.0f, DEFAULT_MINS_2 );
10008 return;
10009 }
10010 else
10011 {
10012 vec3_t axis[3], point[8];
10013 vec3_t newMins, newMaxs;
10014 int curAxis = 0, i;
10015 trace_t trace;
10016
10017 AnglesToAxis( veh->m_vOrientation, axis );
10018 VectorMA( origin, veh->m_pVehicleInfo->length/2.0f, axis[0], point[0] );
10019 VectorMA( origin, -veh->m_pVehicleInfo->length/2.0f, axis[0], point[1] );
10020
10021 VectorMA( point[0], veh->m_pVehicleInfo->height/2.0f, axis[2], point[0] );
10022 VectorMA( point[0], -veh->m_pVehicleInfo->height, axis[2], point[2] );
10023 VectorMA( point[1], veh->m_pVehicleInfo->height/2.0f, axis[2], point[1] );
10024 VectorMA( point[1], -veh->m_pVehicleInfo->height, axis[2], point[3] );
10025
10026 VectorMA( origin, veh->m_pVehicleInfo->width/2.0f, axis[1], point[4] );
10027 VectorMA( origin, -veh->m_pVehicleInfo->width/2.0f, axis[1], point[5] );
10028
10029 VectorMA( point[4], veh->m_pVehicleInfo->height/2.0f, axis[2], point[4] );
10030 VectorMA( point[4], -veh->m_pVehicleInfo->height, axis[2], point[6] );
10031 VectorMA( point[5], veh->m_pVehicleInfo->height/2.0f, axis[2], point[5] );
10032 VectorMA( point[5], -veh->m_pVehicleInfo->height, axis[2], point[7] );
10033
10034
10035
10036
10037
10038 VectorCopy( origin, newMins );
10039 VectorCopy( origin, newMaxs );
10040 for ( curAxis = 0; curAxis < 3; curAxis++ )
10041 {
10042 for ( i = 0; i < 8; i++ )
10043 {
10044 if ( point[i][curAxis] > newMaxs[curAxis] )
10045 {
10046 newMaxs[curAxis] = point[i][curAxis];
10047 }
10048 else if ( point[i][curAxis] < newMins[curAxis] )
10049 {
10050 newMins[curAxis] = point[i][curAxis];
10051 }
10052 }
10053 }
10054 VectorSubtract( newMins, origin, newMins );
10055 VectorSubtract( newMaxs, origin, newMaxs );
10056
10057 if (localTrace)
10058 {
10059 localTrace( &trace, origin, newMins, newMaxs, origin, clientNum, tracemask );
10060 }
10061 else
10062 {
10063 trace.startsolid = trace.allsolid = 0;
10064 }
10065 if ( !trace.startsolid && !trace.allsolid )
10066 {
10067 VectorCopy( newMins, mins );
10068 VectorCopy( newMaxs, maxs );
10069 }
10070
10071
10072 }
10073 }
10074
10075
10076
10077
10078
10079
10080 extern void trap_SnapVector( float *v );
10081 extern int BG_EmplacedView(vec3_t baseAngles, vec3_t angles, float *newYaw, float constraint);
10082 extern qboolean BG_FighterUpdate(Vehicle_t *pVeh, const usercmd_t *pUcmd, vec3_t trMins, vec3_t trMaxs, float gravity,
10083 void (*traceFunc)( trace_t *results, const vec3_t start, const vec3_t lmins, const vec3_t lmaxs, const vec3_t end, int passEntityNum, int contentMask ));
10084
10085 #define JETPACK_HOVER_HEIGHT 64
10086
10087
10088
10089 void PM_MoveForKata(usercmd_t *ucmd)
10090 {
10091 if ( pm->ps->legsAnim == BOTH_A7_SOULCAL
10092 && pm->ps->saberMove == LS_STAFF_SOULCAL )
10093 {
10094 ucmd->upmove = 0;
10095
10096 if ( PM_CanRollFromSoulCal( pm->ps ) )
10097 {
10098 ucmd->upmove = -127;
10099 ucmd->rightmove = 0;
10100 if (ucmd->forwardmove < 0)
10101 {
10102 ucmd->forwardmove = 0;
10103 }
10104 }
10105 else
10106 {
10107 ucmd->rightmove = 0;
10108
10109 if ( pm->ps->legsTimer >= 2750 )
10110 {
10111
10112 ucmd->forwardmove = 64;
10113 }
10114 else
10115 {
10116 ucmd->forwardmove = 0;
10117 }
10118 }
10119 if ( pm->ps->legsTimer >= 2650
10120 && pm->ps->legsTimer < 2850 )
10121 {
10122 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
10123 {
10124
10125 pm->ps->velocity[2] = 250;
10126 pm->ps->fd.forceJumpZStart = pm->ps->origin[2];
10127
10128
10129 PM_AddEvent(EV_JUMP);
10130 }
10131 }
10132 }
10133 else if (pm->ps->legsAnim == BOTH_A2_SPECIAL)
10134 {
10135 pm->cmd.rightmove = 0;
10136 pm->cmd.upmove = 0;
10137 if (pm->ps->legsTimer < 2700 && pm->ps->legsTimer > 2300)
10138 {
10139 pm->cmd.forwardmove = 127;
10140 }
10141 else if (pm->ps->legsTimer < 900 && pm->ps->legsTimer > 500)
10142 {
10143 pm->cmd.forwardmove = 127;
10144 }
10145 else
10146 {
10147 pm->cmd.forwardmove = 0;
10148 }
10149 }
10150 else if (pm->ps->legsAnim == BOTH_A3_SPECIAL)
10151 {
10152 pm->cmd.rightmove = 0;
10153 pm->cmd.upmove = 0;
10154 if (pm->ps->legsTimer < 1700 && pm->ps->legsTimer > 1000)
10155 {
10156 pm->cmd.forwardmove = 127;
10157 }
10158 else
10159 {
10160 pm->cmd.forwardmove = 0;
10161 }
10162 }
10163 else
10164 {
10165 pm->cmd.forwardmove = 0;
10166 pm->cmd.rightmove = 0;
10167 pm->cmd.upmove = 0;
10168 }
10169 }
10170
10171 void PmoveSingle (pmove_t *pmove) {
10172 qboolean stiffenedUp = qfalse;
10173 float gDist = 0;
10174 qboolean noAnimate = qfalse;
10175 int savedGravity = 0;
10176
10177 pm = pmove;
10178
10179 if (pm->ps->emplacedIndex)
10180 {
10181 if (pm->cmd.buttons & BUTTON_ALT_ATTACK)
10182 {
10183 pm->cmd.buttons &= ~BUTTON_ALT_ATTACK;
10184 pm->cmd.buttons |= BUTTON_ATTACK;
10185 }
10186 }
10187
10188
10189 pm_entSelf = PM_BGEntForNum(pm->ps->clientNum);
10190 if (pm->ps->m_iVehicleNum)
10191 {
10192 if (pm->ps->clientNum < MAX_CLIENTS)
10193 {
10194 pm_entVeh = PM_BGEntForNum(pm->ps->m_iVehicleNum);
10195 }
10196 else
10197 {
10198 pm_entVeh = PM_BGEntForNum(pm->ps->m_iVehicleNum-1);
10199 }
10200 }
10201 else
10202 {
10203 pm_entVeh = NULL;
10204 }
10205
10206 gPMDoSlowFall = PM_DoSlowFall();
10207
10208
10209
10210 c_pmove++;
10211
10212
10213 pm->numtouch = 0;
10214 pm->watertype = 0;
10215 pm->waterlevel = 0;
10216
10217 if (PM_IsRocketTrooper())
10218 {
10219 if (pm->cmd.upmove < 0)
10220 {
10221 pm->cmd.upmove = 0;
10222 }
10223 }
10224
10225 if (pm->ps->pm_type == PM_FLOAT)
10226 {
10227 stiffenedUp = qtrue;
10228 }
10229 else if (pm->ps->eFlags & EF_DISINTEGRATION)
10230 {
10231 stiffenedUp = qtrue;
10232 }
10233 else if ( BG_SaberLockBreakAnim( pm->ps->legsAnim )
10234 || BG_SaberLockBreakAnim( pm->ps->torsoAnim )
10235 || pm->ps->saberLockTime >= pm->cmd.serverTime )
10236 {
10237 stiffenedUp = qtrue;
10238 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10239 }
10240 else if ( pm->ps->saberMove == LS_A_BACK || pm->ps->saberMove == LS_A_BACK_CR ||
10241 pm->ps->saberMove == LS_A_BACKSTAB || pm->ps->saberMove == LS_A_FLIP_STAB ||
10242 pm->ps->saberMove == LS_A_FLIP_SLASH || pm->ps->saberMove == LS_A_JUMP_T__B_ ||
10243 pm->ps->saberMove == LS_DUAL_LR || pm->ps->saberMove == LS_DUAL_FB)
10244 {
10245 if (pm->ps->legsAnim == BOTH_JUMPFLIPSTABDOWN ||
10246 pm->ps->legsAnim == BOTH_JUMPFLIPSLASHDOWN1)
10247 {
10248 if (pm->ps->legsTimer < 1600 && pm->ps->legsTimer > 900)
10249 {
10250 pm->ps->viewangles[YAW] += pml.frametime*240.0f;
10251 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10252 }
10253 }
10254 stiffenedUp = qtrue;
10255 }
10256 else if ((pm->ps->legsAnim) == (BOTH_A2_STABBACK1) ||
10257 (pm->ps->legsAnim) == (BOTH_ATTACK_BACK) ||
10258 (pm->ps->legsAnim) == (BOTH_CROUCHATTACKBACK1) ||
10259 (pm->ps->legsAnim) == (BOTH_FORCELEAP2_T__B_) ||
10260 (pm->ps->legsAnim) == (BOTH_JUMPFLIPSTABDOWN) ||
10261 (pm->ps->legsAnim) == (BOTH_JUMPFLIPSLASHDOWN1))
10262 {
10263 stiffenedUp = qtrue;
10264 }
10265 else if (pm->ps->legsAnim == BOTH_ROLL_STAB)
10266 {
10267 stiffenedUp = qtrue;
10268 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10269 }
10270 else if (pm->ps->heldByClient)
10271 {
10272 stiffenedUp = qtrue;
10273 }
10274 else if (BG_KickMove(pm->ps->saberMove) || BG_KickingAnim(pm->ps->legsAnim))
10275 {
10276 stiffenedUp = qtrue;
10277 }
10278 else if (BG_InGrappleMove(pm->ps->torsoAnim))
10279 {
10280 stiffenedUp = qtrue;
10281 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10282 }
10283 else if ( pm->ps->saberMove == LS_STABDOWN_DUAL ||
10284 pm->ps->saberMove == LS_STABDOWN_STAFF ||
10285 pm->ps->saberMove == LS_STABDOWN)
10286 {
10287 if (pm->ps->legsTimer < 800)
10288 {
10289 stiffenedUp = qtrue;
10290 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10291 }
10292 else
10293 {
10294 pm->cmd.rightmove = 0;
10295 pm->cmd.upmove = 0;
10296 pm->cmd.forwardmove = 64;
10297 }
10298 }
10299 else if (pm->ps->saberMove == LS_PULL_ATTACK_STAB ||
10300 pm->ps->saberMove == LS_PULL_ATTACK_SWING)
10301 {
10302 stiffenedUp = qtrue;
10303 }
10304 else if (BG_SaberInKata(pm->ps->saberMove) ||
10305 BG_InKataAnim(pm->ps->torsoAnim) ||
10306 BG_InKataAnim(pm->ps->legsAnim))
10307 {
10308 PM_MoveForKata(&pm->cmd);
10309 }
10310 else if ( BG_FullBodyTauntAnim( pm->ps->legsAnim )
10311 && BG_FullBodyTauntAnim( pm->ps->torsoAnim ) )
10312 {
10313 if ( (pm->cmd.buttons&BUTTON_ATTACK)
10314 || (pm->cmd.buttons&BUTTON_ALT_ATTACK)
10315 || (pm->cmd.buttons&BUTTON_FORCEPOWER)
10316 || (pm->cmd.buttons&BUTTON_FORCEGRIP)
10317 || (pm->cmd.buttons&BUTTON_FORCE_LIGHTNING)
10318 || (pm->cmd.buttons&BUTTON_FORCE_DRAIN)
10319 || pm->cmd.upmove )
10320 {
10321 if ( pm->ps->legsAnim == BOTH_MEDITATE
10322 && pm->ps->torsoAnim == BOTH_MEDITATE )
10323 {
10324 PM_SetAnim( SETANIM_BOTH, BOTH_MEDITATE_END, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
10325 }
10326 else
10327 {
10328 pm->ps->legsTimer = pm->ps->torsoTimer = 0;
10329 }
10330 if ( pm->ps->forceHandExtend == HANDEXTEND_TAUNT )
10331 {
10332 pm->ps->forceHandExtend = 0;
10333 }
10334 }
10335 else
10336 {
10337 if ( pm->ps->legsAnim == BOTH_MEDITATE )
10338 {
10339 if ( pm->ps->legsTimer < 100 )
10340 {
10341 pm->ps->legsTimer = 100;
10342 }
10343 }
10344 if ( pm->ps->torsoAnim == BOTH_MEDITATE )
10345 {
10346 if ( pm->ps->torsoTimer < 100 )
10347 {
10348 pm->ps->legsTimer = 100;
10349 }
10350 pm->ps->forceHandExtend = HANDEXTEND_TAUNT;
10351 pm->ps->forceHandExtendTime = pm->cmd.serverTime + 100;
10352 }
10353 if ( pm->ps->legsTimer > 0 || pm->ps->torsoTimer > 0 )
10354 {
10355 stiffenedUp = qtrue;
10356 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10357 pm->cmd.rightmove = 0;
10358 pm->cmd.upmove = 0;
10359 pm->cmd.forwardmove = 0;
10360 pm->cmd.buttons = 0;
10361 }
10362 }
10363 }
10364 else if ( pm->ps->legsAnim == BOTH_MEDITATE_END
10365 && pm->ps->legsTimer > 0 )
10366 {
10367 stiffenedUp = qtrue;
10368 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10369 pm->cmd.rightmove = 0;
10370 pm->cmd.upmove = 0;
10371 pm->cmd.forwardmove = 0;
10372 pm->cmd.buttons = 0;
10373 }
10374 else if (pm->ps->legsAnim == BOTH_FORCELAND1 ||
10375 pm->ps->legsAnim == BOTH_FORCELANDBACK1 ||
10376 pm->ps->legsAnim == BOTH_FORCELANDRIGHT1 ||
10377 pm->ps->legsAnim == BOTH_FORCELANDLEFT1)
10378 {
10379 stiffenedUp = qtrue;
10380 }
10381
10382 if ( pm->ps->saberMove == LS_A_LUNGE )
10383 {
10384 pm->cmd.rightmove = pm->cmd.upmove = 0;
10385 if ( pm->ps->legsTimer > 500 )
10386 {
10387 pm->cmd.forwardmove = 127;
10388 }
10389 else
10390 {
10391 pm->cmd.forwardmove = 0;
10392 }
10393 }
10394
10395 if ( pm->ps->saberMove == LS_A_JUMP_T__B_ )
10396 {
10397 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
10398 {
10399 pm->cmd.forwardmove = 0;
10400 }
10401 pm->cmd.rightmove = pm->cmd.upmove = 0;
10402 }
10403
10404 #if 0
10405 if ((pm->ps->legsAnim) == BOTH_KISSER1LOOP ||
10406 (pm->ps->legsAnim) == BOTH_KISSEE1LOOP)
10407 {
10408 stiffenedUp = qtrue;
10409 }
10410 #endif
10411
10412 if (pm->ps->emplacedIndex)
10413 {
10414 if (pm->cmd.forwardmove < 0 || PM_GroundDistance() > 32.0f)
10415 {
10416 pm->ps->emplacedIndex = 0;
10417 pm->ps->saberHolstered = 0;
10418 }
10419 else
10420 {
10421 stiffenedUp = qtrue;
10422 }
10423 }
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437 if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->weaponstate == WEAPON_CHARGING_ALT)
10438 {
10439 if (pm->cmd.forwardmove ||
10440 pm->cmd.rightmove ||
10441 pm->cmd.upmove > 0)
10442 {
10443 pm->ps->weaponstate = WEAPON_READY;
10444 pm->ps->weaponTime = 1000;
10445 PM_AddEventWithParm(EV_WEAPON_CHARGE, WP_DISRUPTOR);
10446 pm->cmd.upmove = 0;
10447 }
10448 }
10449 else if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
10450 {
10451 if (pm->cmd.upmove > 0)
10452 {
10453 pm->cmd.upmove = 0;
10454 }
10455 }
10456
10457 if (stiffenedUp)
10458 {
10459 pm->cmd.forwardmove = 0;
10460 pm->cmd.rightmove = 0;
10461 pm->cmd.upmove = 0;
10462 }
10463
10464 if (pm->ps->fd.forceGripCripple)
10465 {
10466 pm->cmd.buttons &= ~BUTTON_ATTACK;
10467 pm->cmd.buttons &= ~BUTTON_ALT_ATTACK;
10468 }
10469
10470 if ( BG_InRoll( pm->ps, pm->ps->legsAnim ) )
10471 {
10472 BG_CmdForRoll( pm->ps, pm->ps->legsAnim, &pm->cmd );
10473 }
10474
10475 PM_CmdForSaberMoves(&pm->cmd);
10476
10477 BG_AdjustClientSpeed(pm->ps, &pm->cmd, pm->cmd.serverTime);
10478
10479 if ( pm->ps->stats[STAT_HEALTH] <= 0 ) {
10480 pm->tracemask &= ~CONTENTS_BODY;
10481 }
10482
10483
10484
10485 if ( abs( pm->cmd.forwardmove ) > 64 || abs( pm->cmd.rightmove ) > 64 ) {
10486 pm->cmd.buttons &= ~BUTTON_WALKING;
10487 }
10488
10489
10490 if ( pm->cmd.buttons & BUTTON_TALK ) {
10491 pm->ps->eFlags |= EF_TALK;
10492 } else {
10493 pm->ps->eFlags &= ~EF_TALK;
10494 }
10495
10496 pm_cancelOutZoom = qfalse;
10497 if (pm->ps->weapon == WP_DISRUPTOR &&
10498 pm->ps->zoomMode == 1)
10499 {
10500 if ((pm->cmd.buttons & BUTTON_ALT_ATTACK) &&
10501 !(pm->cmd.buttons & BUTTON_ATTACK) &&
10502 pm->ps->zoomLocked)
10503 {
10504 pm_cancelOutZoom = qtrue;
10505 }
10506 }
10507
10508
10509 PM_AdjustAttackStates( pm );
10510
10511
10512 if ( pm->ps->stats[STAT_HEALTH] > 0 &&
10513 !( pm->cmd.buttons & (BUTTON_ATTACK | BUTTON_USE_HOLDABLE) ) ) {
10514 pm->ps->pm_flags &= ~PMF_RESPAWNED;
10515 }
10516
10517
10518
10519
10520 if ( pmove->cmd.buttons & BUTTON_TALK ) {
10521
10522
10523 pmove->cmd.buttons = BUTTON_TALK;
10524 pmove->cmd.forwardmove = 0;
10525 pmove->cmd.rightmove = 0;
10526 pmove->cmd.upmove = 0;
10527 }
10528
10529
10530 memset (&pml, 0, sizeof(pml));
10531
10532
10533 pml.msec = pmove->cmd.serverTime - pm->ps->commandTime;
10534 if ( pml.msec < 1 ) {
10535 pml.msec = 1;
10536 } else if ( pml.msec > 200 ) {
10537 pml.msec = 200;
10538 }
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551 pm->ps->commandTime = pmove->cmd.serverTime;
10552
10553
10554 VectorCopy (pm->ps->origin, pml.previous_origin);
10555
10556
10557 VectorCopy (pm->ps->velocity, pml.previous_velocity);
10558
10559 pml.frametime = pml.msec * 0.001;
10560
10561 if (pm->ps->clientNum >= MAX_CLIENTS &&
10562 pm_entSelf &&
10563 pm_entSelf->s.NPC_class == CLASS_VEHICLE)
10564 {
10565 bgEntity_t *veh = pm_entSelf;
10566 assert( veh && veh->m_pVehicle);
10567 if ( veh && veh->m_pVehicle )
10568 {
10569 veh->m_pVehicle->m_fTimeModifier = pml.frametime*60.0f;
10570 }
10571 }
10572 else if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
10573 &&pm->ps->m_iVehicleNum)
10574 {
10575 bgEntity_t *veh = pm_entVeh;
10576
10577 if (veh && veh->playerState &&
10578 (pm->cmd.serverTime-veh->playerState->hyperSpaceTime) < HYPERSPACE_TIME)
10579 {
10580 PM_VehFaceHyperspacePoint(veh);
10581 }
10582 else if (veh && veh->playerState &&
10583 veh->playerState->vehTurnaroundIndex &&
10584 veh->playerState->vehTurnaroundTime > pm->cmd.serverTime)
10585 {
10586 PM_VehForcedTurning(veh);
10587 }
10588 }
10589
10590 if ( pm->ps->legsAnim == BOTH_FORCEWALLRUNFLIP_ALT &&
10591 pm->ps->legsTimer > 0 )
10592 {
10593 vec3_t vFwd, fwdAng;
10594 VectorSet(fwdAng, 0.0f, pm->ps->viewangles[YAW], 0.0f);
10595
10596 AngleVectors( fwdAng, vFwd, NULL, NULL );
10597 if ( pm->ps->groundEntityNum == ENTITYNUM_NONE )
10598 {
10599 float savZ = pm->ps->velocity[2];
10600 VectorScale( vFwd, 100, pm->ps->velocity );
10601 pm->ps->velocity[2] = savZ;
10602 }
10603 pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0;
10604 PM_AdjustAnglesForWallRunUpFlipAlt( &pm->cmd );
10605 }
10606
10607
10608
10609 PM_AdjustAngleForWallJump( pm->ps, &pm->cmd, qtrue );
10610 PM_AdjustAngleForWallRunUp( pm->ps, &pm->cmd, qtrue );
10611 PM_AdjustAngleForWallRun( pm->ps, &pm->cmd, qtrue );
10612
10613 if (pm->ps->saberMove == LS_A_JUMP_T__B_ || pm->ps->saberMove == LS_A_LUNGE ||
10614 pm->ps->saberMove == LS_A_BACK_CR || pm->ps->saberMove == LS_A_BACK ||
10615 pm->ps->saberMove == LS_A_BACKSTAB)
10616 {
10617 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10618 }
10619
10620 #if 0
10621 if ((pm->ps->legsAnim) == BOTH_KISSER1LOOP ||
10622 (pm->ps->legsAnim) == BOTH_KISSEE1LOOP)
10623 {
10624 pm->ps->viewangles[PITCH] = 0;
10625 PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
10626 }
10627 #endif
10628
10629 PM_SetSpecialMoveValues();
10630
10631
10632 PM_UpdateViewAngles( pm->ps, &pm->cmd );
10633
10634 AngleVectors (pm->ps->viewangles, pml.forward, pml.right, pml.up);
10635
10636 if ( pm->cmd.upmove < 10 && !(pm->ps->pm_flags & PMF_STUCK_TO_WALL)) {
10637
10638 pm->ps->pm_flags &= ~PMF_JUMP_HELD;
10639 }
10640
10641
10642 if ( pm->cmd.forwardmove < 0 ) {
10643 pm->ps->pm_flags |= PMF_BACKWARDS_RUN;
10644 } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) {
10645 pm->ps->pm_flags &= ~PMF_BACKWARDS_RUN;
10646 }
10647
10648 if ( pm->ps->pm_type >= PM_DEAD ) {
10649 pm->cmd.forwardmove = 0;
10650 pm->cmd.rightmove = 0;
10651 pm->cmd.upmove = 0;
10652 }
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664 if (pm->ps->saberLockTime >= pm->cmd.serverTime)
10665 {
10666 pm->cmd.upmove = 0;
10667 pm->cmd.forwardmove = 0;
10668 pm->cmd.rightmove = 0;
10669 }
10670
10671 if ( pm->ps->pm_type == PM_SPECTATOR ) {
10672 PM_CheckDuck ();
10673 if (!pm->noSpecMove)
10674 {
10675 PM_FlyMove ();
10676 }
10677 PM_DropTimers ();
10678 return;
10679 }
10680
10681 if ( pm->ps->pm_type == PM_NOCLIP ) {
10682 if (pm->ps->clientNum < MAX_CLIENTS)
10683 {
10684 PM_NoclipMove ();
10685 PM_DropTimers ();
10686 return;
10687 }
10688 }
10689
10690 if (pm->ps->pm_type == PM_FREEZE) {
10691 return;
10692 }
10693
10694 if ( pm->ps->pm_type == PM_INTERMISSION || pm->ps->pm_type == PM_SPINTERMISSION) {
10695 return;
10696 }
10697
10698
10699 PM_SetWaterLevel();
10700 pml.previous_waterlevel = pmove->waterlevel;
10701
10702
10703 PM_CheckDuck ();
10704
10705 if (pm->ps->pm_type == PM_JETPACK)
10706 {
10707 gDist = PM_GroundDistance();
10708 savedGravity = pm->ps->gravity;
10709
10710 if (gDist < JETPACK_HOVER_HEIGHT+64)
10711 {
10712 pm->ps->gravity *= 0.1f;
10713 }
10714 else
10715 {
10716 pm->ps->gravity *= 0.25f;
10717 }
10718 }
10719 else if (gPMDoSlowFall)
10720 {
10721 savedGravity = pm->ps->gravity;
10722 pm->ps->gravity *= 0.5;
10723 }
10724
10725
10726 if (pm->ps->pm_type == PM_JETPACK)
10727 {
10728 if (pm->cmd.rightmove > 0)
10729 {
10730 PM_ContinueLegsAnim(BOTH_INAIRRIGHT1);
10731 }
10732 else if (pm->cmd.rightmove < 0)
10733 {
10734 PM_ContinueLegsAnim(BOTH_INAIRLEFT1);
10735 }
10736 else if (pm->cmd.forwardmove > 0)
10737 {
10738 PM_ContinueLegsAnim(BOTH_INAIR1);
10739 }
10740 else if (pm->cmd.forwardmove < 0)
10741 {
10742 PM_ContinueLegsAnim(BOTH_INAIRBACK1);
10743 }
10744 else
10745 {
10746 PM_ContinueLegsAnim(BOTH_INAIR1);
10747 }
10748
10749 if (pm->ps->weapon == WP_SABER &&
10750 BG_SpinningSaberAnim( pm->ps->legsAnim ))
10751 {
10752 pm->ps->velocity[0] += Q_irand(-100, 100);
10753 pm->ps->velocity[1] += Q_irand(-100, 100);
10754 }
10755
10756 if (pm->cmd.upmove > 0 && pm->ps->velocity[2] < 256)
10757 {
10758 float addIn = 12.0f;
10759
10760
10761
10762
10763
10764
10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777 if (pm->ps->velocity[2] > 0)
10778 {
10779 addIn = 12.0f - (gDist / 64.0f);
10780 }
10781
10782 if (addIn > 0.0f)
10783 {
10784 pm->ps->velocity[2] += addIn;
10785 }
10786
10787 pm->ps->eFlags |= EF_JETPACK_FLAMING;
10788 }
10789 else
10790 {
10791 pm->ps->eFlags &= ~EF_JETPACK_FLAMING;
10792
10793 if (pm->ps->velocity[2] < 256)
10794 {
10795 if (pm->ps->velocity[2] < -100)
10796 {
10797 pm->ps->velocity[2] = -100;
10798 }
10799 if (gDist < JETPACK_HOVER_HEIGHT)
10800 {
10801 pm->ps->velocity[2] += 2;
10802 }
10803 }
10804 }
10805 }
10806
10807 if (pm->ps->clientNum >= MAX_CLIENTS &&
10808 pm_entSelf && pm_entSelf->m_pVehicle)
10809 {
10810 BG_VehicleAdjustBBoxForOrientation( pm_entSelf->m_pVehicle, pm->ps->origin, pm->mins, pm->maxs, pm->ps->clientNum, pm->tracemask, pm->trace );
10811 }
10812
10813
10814 PM_GroundTrace();
10815 if ( pm_flying == FLY_HOVER )
10816 {
10817 PM_HoverTrace();
10818 }
10819
10820 if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
10821 {
10822 pm->ps->fd.forceJumpZStart = 0;
10823 }
10824
10825 if ( pm->ps->pm_type == PM_DEAD ) {
10826 if (pm->ps->clientNum >= MAX_CLIENTS &&
10827 pm_entSelf &&
10828 pm_entSelf->s.NPC_class == CLASS_VEHICLE &&
10829 pm_entSelf->m_pVehicle->m_pVehicleInfo->type != VH_ANIMAL)
10830 {
10831 }
10832 else
10833 {
10834 PM_DeadMove ();
10835 }
10836 }
10837
10838 PM_DropTimers();
10839
10840 #ifdef _TESTING_VEH_PREDICTION
10841 #ifndef QAGAME
10842 {
10843 vec3_t blah;
10844 VectorMA(pm->ps->origin, 128.0f, pm->ps->moveDir, blah);
10845 CG_TestLine(pm->ps->origin, blah, 1, 0x0000ff, 1);
10846
10847 VectorMA(pm->ps->origin, 1.0f, pm->ps->velocity, blah);
10848 CG_TestLine(pm->ps->origin, blah, 1, 0xff0000, 1);
10849 }
10850 #endif
10851 #endif
10852
10853 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
10854 &&pm->ps->m_iVehicleNum)
10855 {
10856 bgEntity_t *veh = pm_entVeh;
10857
10858 if ( veh && veh->m_pVehicle &&
10859 (veh->m_pVehicle->m_pVehicleInfo->type == VH_WALKER || veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER) )
10860 {
10861 pm->cmd.buttons &= ~(BUTTON_ATTACK|BUTTON_ALT_ATTACK);
10862 pm->ps->eFlags &= ~(EF_FIRING|EF_ALT_FIRING);
10863
10864 }
10865 }
10866
10867 if (!pm->ps->m_iVehicleNum &&
10868 pm_entSelf->s.NPC_class!=CLASS_VEHICLE&&
10869 pm_entSelf->s.NPC_class!=CLASS_RANCOR&&
10870 pm->ps->groundEntityNum < ENTITYNUM_WORLD &&
10871 pm->ps->groundEntityNum >= MAX_CLIENTS)
10872 {
10873 bgEntity_t *pEnt = PM_BGEntForNum(pm->ps->groundEntityNum);
10874
10875 if (pEnt && pEnt->s.eType == ET_NPC &&
10876 pEnt->s.NPC_class != CLASS_VEHICLE)
10877 {
10878 if (pm->ps->velocity[2] < 270)
10879 {
10880 pm->ps->velocity[2] = 270;
10881 pm->cmd.upmove = 127;
10882 }
10883 }
10884 #ifdef QAGAME
10885 else if ( !pm->ps->zoomMode &&
10886 pm_entSelf
10887 && pEnt->m_pVehicle )
10888 {
10889 gentity_t *gEnt = (gentity_t*)pEnt;
10890 if ( gEnt->client
10891 && !gEnt->client->ps.m_iVehicleNum
10892 && (gEnt->spawnflags&2) )
10893 {
10894
10895 pEnt->m_pVehicle->m_pVehicleInfo->Board( pEnt->m_pVehicle, (bgEntity_t *)pm_entSelf );
10896 }
10897 }
10898 #endif
10899 }
10900
10901 if (pm->ps->clientNum >= MAX_CLIENTS &&
10902 pm_entSelf &&
10903 pm_entSelf->s.NPC_class == CLASS_VEHICLE)
10904 {
10905 bgEntity_t *veh = pm_entSelf;
10906
10907 assert(veh && veh->playerState && veh->m_pVehicle && veh->s.number >= MAX_CLIENTS);
10908
10909 if (veh->m_pVehicle->m_pVehicleInfo->type != VH_FIGHTER)
10910 {
10911 veh->m_pVehicle->m_vOrientation[PITCH] = pm->ps->viewangles[PITCH];
10912 }
10913
10914 if (!pm->ps->m_iVehicleNum)
10915 {
10916 #ifdef QAGAME
10917 veh->m_pVehicle->m_pVehicleInfo->Update(veh->m_pVehicle, &pm->cmd);
10918 veh->m_pVehicle->m_pVehicleInfo->Animate(veh->m_pVehicle);
10919 #endif
10920 }
10921 else
10922 {
10923 bgEntity_t *self = pm_entVeh;
10924 #ifdef QAGAME
10925 int i = 0;
10926 #endif
10927
10928 assert(self && self->playerState && self->s.number < MAX_CLIENTS);
10929
10930 if (pm->ps->pm_type == PM_DEAD &&
10931 (veh->m_pVehicle->m_ulFlags & VEH_CRASHING))
10932 {
10933 veh->m_pVehicle->m_ulFlags &= ~VEH_CRASHING;
10934 }
10935
10936 if (self->playerState->m_iVehicleNum)
10937 {
10938 PM_VehicleViewAngles(self->playerState, veh, &veh->m_pVehicle->m_ucmd);
10939 }
10940
10941 #ifdef QAGAME
10942 veh->m_pVehicle->m_pVehicleInfo->Update(veh->m_pVehicle, &veh->m_pVehicle->m_ucmd);
10943 veh->m_pVehicle->m_pVehicleInfo->Animate(veh->m_pVehicle);
10944
10945 veh->m_pVehicle->m_pVehicleInfo->UpdateRider(veh->m_pVehicle, self, &veh->m_pVehicle->m_ucmd);
10946
10947 while (i < veh->m_pVehicle->m_iNumPassengers)
10948 {
10949 if (veh->m_pVehicle->m_ppPassengers[i])
10950 {
10951 gentity_t *thePassenger = (gentity_t *)veh->m_pVehicle->m_ppPassengers[i];
10952 if (thePassenger->inuse && thePassenger->client)
10953 {
10954 veh->m_pVehicle->m_pVehicleInfo->UpdateRider(veh->m_pVehicle, veh->m_pVehicle->m_ppPassengers[i], &thePassenger->client->pers.cmd);
10955 }
10956 }
10957 i++;
10958 }
10959 #else
10960 if (!veh->playerState->vehBoarding )
10961 {
10962 if (veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER)
10963 {
10964 BG_FighterUpdate(veh->m_pVehicle, &veh->m_pVehicle->m_ucmd, pm->mins, pm->maxs, self->playerState->gravity, pm->trace);
10965 }
10966
10967 if (veh->m_pVehicle->m_iBoarding == 0)
10968 {
10969 vec3_t vRollAng;
10970
10971
10972 veh->m_pVehicle->m_pPilot = self;
10973
10974
10975 VectorCopy( veh->m_pVehicle->m_vOrientation, veh->m_pVehicle->m_vPrevOrientation );
10976
10977 veh->m_pVehicle->m_pVehicleInfo->ProcessOrientCommands(veh->m_pVehicle);
10978 PM_SetPMViewAngle(veh->playerState, veh->m_pVehicle->m_vOrientation, &veh->m_pVehicle->m_ucmd);
10979 veh->m_pVehicle->m_pVehicleInfo->ProcessMoveCommands(veh->m_pVehicle);
10980
10981 vRollAng[YAW] = self->playerState->viewangles[YAW];
10982 vRollAng[PITCH] = self->playerState->viewangles[PITCH];
10983 vRollAng[ROLL] = veh->m_pVehicle->m_vOrientation[ROLL];
10984 PM_SetPMViewAngle(self->playerState, vRollAng, &pm->cmd);
10985
10986
10987 if ( veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
10988 {
10989 AngleVectors( veh->m_pVehicle->m_vOrientation, veh->playerState->moveDir, NULL, NULL );
10990 }
10991 else
10992 {
10993 vec3_t vVehAngles;
10994
10995 VectorSet(vVehAngles, 0, veh->m_pVehicle->m_vOrientation[YAW], 0);
10996 AngleVectors( vVehAngles, veh->playerState->moveDir, NULL, NULL );
10997 }
10998 }
10999 }
11000
11001
11002
11003
11004
11005
11006
11007 else if (veh->playerState)
11008 {
11009 veh->playerState->speed = 0.0f;
11010 if (veh->m_pVehicle)
11011 {
11012 PM_SetPMViewAngle(self->playerState, veh->m_pVehicle->m_vOrientation, &pm->cmd);
11013 PM_SetPMViewAngle(veh->playerState, veh->m_pVehicle->m_vOrientation, &pm->cmd);
11014 }
11015 }
11016 #endif
11017 }
11018 noAnimate = qtrue;
11019 }
11020
11021 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
11022 &&pm->ps->m_iVehicleNum)
11023 {
11024 }
11025 else
11026 {
11027 if (pm->ps->pm_type == PM_FLOAT
11028 ||pm_flying == FLY_NORMAL)
11029 {
11030 PM_FlyMove ();
11031 }
11032 else if ( pm_flying == FLY_VEHICLE )
11033 {
11034 PM_FlyVehicleMove();
11035 }
11036 else
11037 {
11038 if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) {
11039 PM_WaterJumpMove();
11040 } else if ( pm->waterlevel > 1 ) {
11041
11042 PM_WaterMove();
11043 } else if ( pml.walking ) {
11044
11045 PM_WalkMove();
11046 } else {
11047
11048 PM_AirMove();
11049 }
11050 }
11051 }
11052
11053 if (!noAnimate)
11054 {
11055 PM_Animate();
11056 }
11057
11058
11059 PM_GroundTrace();
11060 if ( pm_flying == FLY_HOVER )
11061 {
11062 PM_HoverTrace();
11063 }
11064 PM_SetWaterLevel();
11065 if (pm->cmd.forcesel != -1 && (pm->ps->fd.forcePowersKnown & (1 << pm->cmd.forcesel)))
11066 {
11067 pm->ps->fd.forcePowerSelected = pm->cmd.forcesel;
11068 }
11069 if (pm->cmd.invensel != -1 && (pm->ps->stats[STAT_HOLDABLE_ITEMS] & (1 << pm->cmd.invensel)))
11070 {
11071 pm->ps->stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(pm->cmd.invensel, IT_HOLDABLE);
11072 }
11073
11074 if (pm->ps->m_iVehicleNum
11075
11076 && pm->ps->clientNum < MAX_CLIENTS)
11077 {
11078 if ( (pm->ps->eFlags&EF_NODRAW) )
11079 {
11080 }
11081 else if (!PM_WeaponOkOnVehicle(pm->cmd.weapon) || !PM_WeaponOkOnVehicle(pm->ps->weapon))
11082 {
11083 if (!PM_WeaponOkOnVehicle(pm->ps->weapon))
11084 {
11085 int weap = PM_GetOkWeaponForVehicle();
11086
11087 if (weap != -1)
11088 {
11089 pm->cmd.weapon = weap;
11090 pm->ps->weapon = weap;
11091 }
11092 }
11093 else
11094 {
11095 pm->cmd.weapon = pm->ps->weapon;
11096 }
11097 }
11098 }
11099
11100 if (!pm->ps->m_iVehicleNum
11101 || pm_entSelf->s.NPC_class==CLASS_VEHICLE
11102 || (!(pm->ps->eFlags&EF_NODRAW)&&PM_WeaponOkOnVehicle(pm->cmd.weapon)) )
11103 {
11104
11105 PM_Weapon();
11106 }
11107
11108 PM_Use();
11109
11110 if (!pm->ps->m_iVehicleNum &&
11111 (pm->ps->clientNum < MAX_CLIENTS ||
11112 !pm_entSelf ||
11113 pm_entSelf->s.NPC_class != CLASS_VEHICLE))
11114 {
11115
11116 PM_Footsteps();
11117 }
11118
11119
11120 PM_WaterEvents();
11121
11122
11123 trap_SnapVector( pm->ps->velocity );
11124
11125 if (pm->ps->pm_type == PM_JETPACK || gPMDoSlowFall )
11126 {
11127 pm->ps->gravity = savedGravity;
11128 }
11129
11130 if (
11131 pm->ps->clientNum >= MAX_CLIENTS &&
11132 pm_entSelf &&
11133 pm_entSelf->s.NPC_class == CLASS_VEHICLE)
11134 {
11135 bgEntity_t *veh;
11136
11137 veh = pm_entSelf;
11138
11139 assert(veh->m_pVehicle);
11140
11141
11142
11143 if (veh->m_pVehicle && veh->ghoul2)
11144 {
11145 veh->m_pVehicle->m_pVehicleInfo->AttachRiders( veh->m_pVehicle );
11146 }
11147 }
11148
11149 if (pm_entSelf->s.NPC_class!=CLASS_VEHICLE
11150 && pm->ps->m_iVehicleNum)
11151 {
11152 PM_VehicleWeaponAnimate();
11153 }
11154 }
11155
11156
11157
11158
11159
11160
11161
11162
11163
11164 void Pmove (pmove_t *pmove) {
11165 int finalTime;
11166
11167 finalTime = pmove->cmd.serverTime;
11168
11169 if ( finalTime < pmove->ps->commandTime ) {
11170 return;
11171 }
11172
11173 if ( finalTime > pmove->ps->commandTime + 1000 ) {
11174 pmove->ps->commandTime = finalTime - 1000;
11175 }
11176
11177 if (pmove->ps->fallingToDeath)
11178 {
11179 pmove->cmd.forwardmove = 0;
11180 pmove->cmd.rightmove = 0;
11181 pmove->cmd.upmove = 0;
11182 pmove->cmd.buttons = 0;
11183 }
11184
11185 pmove->ps->pmove_framecount = (pmove->ps->pmove_framecount+1) & ((1<<PS_PMOVEFRAMECOUNTBITS)-1);
11186
11187
11188
11189 while ( pmove->ps->commandTime != finalTime ) {
11190 int msec;
11191
11192 msec = finalTime - pmove->ps->commandTime;
11193
11194 if ( pmove->pmove_fixed ) {
11195 if ( msec > pmove->pmove_msec ) {
11196 msec = pmove->pmove_msec;
11197 }
11198 }
11199 else {
11200 if ( msec > 66 ) {
11201 msec = 66;
11202 }
11203 }
11204 pmove->cmd.serverTime = pmove->ps->commandTime + msec;
11205
11206 PmoveSingle( pmove );
11207
11208 if ( pmove->ps->pm_flags & PMF_JUMP_HELD ) {
11209 pmove->cmd.upmove = 20;
11210 }
11211 }
11212 }
11213
11214 #include "../namespace_end.h"