codemp/game/SpeederNPC.c

Go to the documentation of this file.
00001 // leave this line at the top for all g_xxxx.cpp files...
00002 #include "g_headers.h"
00003 
00004 //seems to be a compiler bug, it doesn't clean out the #ifdefs between dif-compiles
00005 //or something, so the headers spew errors on these defs from the previous compile.
00006 //this fixes that. -rww
00007 #ifdef _JK2MP
00008 //get rid of all the crazy defs we added for this file
00009 #undef currentAngles
00010 #undef currentOrigin
00011 #undef mins
00012 #undef maxs
00013 #undef legsAnimTimer
00014 #undef torsoAnimTimer
00015 #undef bool
00016 #undef false
00017 #undef true
00018 
00019 #undef sqrtf
00020 #undef Q_flrand
00021 
00022 #undef MOD_EXPLOSIVE
00023 #endif
00024 
00025 #ifdef _JK2 //SP does not have this preprocessor for game like MP does
00026 #ifndef _JK2MP
00027 #define _JK2MP
00028 #endif
00029 #endif
00030 
00031 #ifndef _JK2MP //if single player
00032 #ifndef QAGAME //I don't think we have a QAGAME define
00033 #define QAGAME //but define it cause in sp we're always in the game
00034 #endif
00035 #endif
00036 
00037 #ifdef QAGAME //including game headers on cgame is FORBIDDEN ^_^
00038 #include "g_local.h"
00039 #elif defined _JK2MP
00040 #include "bg_public.h"
00041 #endif
00042 
00043 #ifndef _JK2MP
00044 #include "g_functions.h"
00045 #include "g_vehicles.h"
00046 #include "..\game\wp_saber.h"
00047 #else
00048 #include "bg_vehicles.h"
00049 #endif
00050 
00051 #ifdef _JK2MP
00052 //this is really horrible, but it works! just be sure not to use any locals or anything
00053 //with these names (exluding bool, false, true). -rww
00054 #define currentAngles r.currentAngles
00055 #define currentOrigin r.currentOrigin
00056 #define mins r.mins
00057 #define maxs r.maxs
00058 #define legsAnimTimer legsTimer
00059 #define torsoAnimTimer torsoTimer
00060 #define bool qboolean
00061 #define false qfalse
00062 #define true qtrue
00063 
00064 #define sqrtf sqrt
00065 #define Q_flrand flrand
00066 
00067 #define MOD_EXPLOSIVE MOD_SUICIDE
00068 #else
00069 #define bgEntity_t gentity_t
00070 extern void NPC_SetAnim(gentity_t       *ent,int setAnimParts,int anim,int setAnimFlags, int iBlend);
00071 #endif
00072 
00073 extern float DotToSpot( vec3_t spot, vec3_t from, vec3_t fromAngles );
00074 #ifdef QAGAME //SP or gameside MP
00075 extern vmCvar_t cg_thirdPersonAlpha;
00076 extern vec3_t playerMins;
00077 extern vec3_t playerMaxs;
00078 extern cvar_t   *g_speederControlScheme;
00079 extern void ChangeWeapon( gentity_t *ent, int newWeapon );
00080 extern void PM_SetAnim(pmove_t  *pm,int setAnimParts,int anim,int setAnimFlags, int blendTime);
00081 extern int PM_AnimLength( int index, animNumber_t anim );
00082 #endif
00083 
00084 #ifdef _JK2MP
00085 
00086 #include "../namespace_begin.h"
00087 
00088 extern void BG_SetAnim(playerState_t *ps, animation_t *animations, int setAnimParts,int anim,int setAnimFlags, int blendTime);
00089 extern int BG_GetTime(void);
00090 extern qboolean BG_SabersOff( playerState_t *ps );
00091 #endif
00092 
00093 //Alright, actually, most of this file is shared between game and cgame for MP.
00094 //I would like to keep it this way, so when modifying for SP please keep in
00095 //mind the bgEntity restrictions imposed. -rww
00096 
00097 #define STRAFERAM_DURATION      8
00098 #define STRAFERAM_ANGLE         8
00099 
00100 
00101 #ifndef _JK2MP
00102 bool    VEH_StartStrafeRam(Vehicle_t *pVeh, bool Right)
00103 {
00104         if (!(pVeh->m_ulFlags&VEH_STRAFERAM))
00105         {
00106                 float   speed = VectorLength(pVeh->m_pParentEntity->client->ps.velocity);
00107                 if (speed>400.0f)
00108                 {
00109                         // Compute Pos3
00110                         //--------------
00111                         vec3_t  right;
00112                         AngleVectors(pVeh->m_vOrientation, 0, right, 0);
00113                         VectorMA(pVeh->m_pParentEntity->client->ps.velocity, (Right)?( speed):(-speed), right, pVeh->m_pParentEntity->pos3);
00114 
00115                         pVeh->m_ulFlags                         |= VEH_STRAFERAM;
00116                         parentPS->hackingTime            = (Right)?(STRAFERAM_DURATION):(-STRAFERAM_DURATION);
00117 
00118                         if (pVeh->m_iSoundDebounceTimer<level.time && Q_irand(0,1)==0)
00119                         {
00120                                 int     shiftSound = Q_irand(1,4);
00121                                 switch (shiftSound)
00122                                 {
00123                                 case 1: shiftSound=pVeh->m_pVehicleInfo->soundShift1; break;
00124                                 case 2: shiftSound=pVeh->m_pVehicleInfo->soundShift2; break;
00125                                 case 3: shiftSound=pVeh->m_pVehicleInfo->soundShift3; break;
00126                                 case 4: shiftSound=pVeh->m_pVehicleInfo->soundShift4; break;
00127                                 }
00128                                 if (shiftSound)
00129                                 {
00130                                         pVeh->m_iSoundDebounceTimer = level.time + Q_irand(1000, 4000);
00131                                         G_SoundIndexOnEnt( pVeh->m_pParentEntity, CHAN_AUTO, shiftSound);
00132                                 }
00133                         }
00134                         return true;
00135                 }
00136         }
00137         return false;
00138 }
00139 #else
00140 bool    VEH_StartStrafeRam(Vehicle_t *pVeh, bool Right, int Duration)
00141 {
00142         return false;
00143 }
00144 #endif
00145 
00146 
00147 #ifdef QAGAME //game-only.. for now
00148 // Like a think or move command, this updates various vehicle properties.
00149 bool Update( Vehicle_t *pVeh, const usercmd_t *pUcmd )
00150 {
00151         if ( !g_vehicleInfo[VEHICLE_BASE].Update( pVeh, pUcmd ) )
00152         {
00153                 return false;
00154         }
00155 
00156         // See whether this vehicle should be exploding.
00157         if ( pVeh->m_iDieTime != 0 )
00158         {
00159                 pVeh->m_pVehicleInfo->DeathUpdate( pVeh );
00160         }
00161 
00162         // Update move direction.
00163 #ifndef _JK2MP //this makes prediction unhappy, and rightfully so.
00164         gentity_t *parent = (gentity_t *)pVeh->m_pParentEntity;
00165 
00166         if ( pVeh->m_ulFlags & VEH_FLYING )
00167         {
00168                 vec3_t vVehAngles;
00169                 VectorSet(vVehAngles, 0, pVeh->m_vOrientation[YAW], 0 );
00170                 AngleVectors( vVehAngles, parent->client->ps.moveDir, NULL, NULL );
00171         }
00172         else
00173         {
00174                 vec3_t vVehAngles;
00175                 VectorSet(vVehAngles, pVeh->m_vOrientation[PITCH], pVeh->m_vOrientation[YAW], 0 );
00176                 AngleVectors( vVehAngles, parent->client->ps.moveDir, NULL, NULL );
00177         }
00178 
00179         // Check For A Strafe Ram
00180         //------------------------
00181         if (!(pVeh->m_ulFlags&VEH_STRAFERAM) && !(pVeh->m_ulFlags&VEH_FLYING))
00182         {
00183                 // Started A Strafe
00184                 //------------------
00185                 if (pVeh->m_ucmd.rightmove && !parentPS->hackingTime)
00186                 {
00187                         parentPS->hackingTime = (pVeh->m_ucmd.rightmove>0)?(level.time):(-1*level.time);
00188                 }
00189 
00190                 // Ended A Strafe
00191                 //----------------
00192                 else if (!pVeh->m_ucmd.rightmove && parentPS->hackingTime)
00193                 {
00194                         // If It Was A Short Burst, Start The Strafe Ram
00195                         //-----------------------------------------------
00196                         if ((level.time - abs(parentPS->hackingTime))<300)
00197                         {
00198                                 if (!VEH_StartStrafeRam(pVeh, (parentPS->hackingTime>0)))
00199                                 {
00200                                         parentPS->hackingTime = 0;
00201                                 }
00202                         }
00203 
00204                         // Otherwise, Clear The Timer
00205                         //----------------------------
00206                         else
00207                         {
00208                                 parentPS->hackingTime = 0;
00209                         }
00210                 }
00211         }
00212 
00213         // If Currently In A StrafeRam, Check To See If It Is Done (Timed Out)
00214         //---------------------------------------------------------------------
00215         else if (!parentPS->hackingTime)
00216         {
00217                 pVeh->m_ulFlags &=~VEH_STRAFERAM;
00218         }
00219 
00220 
00221         // Exhaust Effects Start And Stop When The Accelerator Is Pressed
00222         //----------------------------------------------------------------
00223         if (pVeh->m_pVehicleInfo->iExhaustFX)
00224         {
00225                 // Start It On Each Exhaust Bolt
00226                 //-------------------------------
00227                 if (pVeh->m_ucmd.forwardmove && !(pVeh->m_ulFlags&VEH_ACCELERATORON))
00228                 {
00229                         pVeh->m_ulFlags |= VEH_ACCELERATORON;
00230                         for (int i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
00231                         {
00232                                 G_PlayEffect(pVeh->m_pVehicleInfo->iExhaustFX, parent->playerModel, pVeh->m_iExhaustTag[i], parent->s.number, parent->currentOrigin, 1, qtrue);
00233                         }
00234                 }
00235 
00236                 // Stop It On Each Exhaust Bolt
00237                 //------------------------------
00238                 else if (!pVeh->m_ucmd.forwardmove && (pVeh->m_ulFlags&VEH_ACCELERATORON))
00239                 {
00240                         pVeh->m_ulFlags &=~VEH_ACCELERATORON;
00241                         for (int i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
00242                         {
00243                                 G_StopEffect(pVeh->m_pVehicleInfo->iExhaustFX, parent->playerModel, pVeh->m_iExhaustTag[i], parent->s.number);
00244                         }
00245                 }
00246         }
00247 
00248         if (!(pVeh->m_ulFlags&VEH_ARMORLOW) && (pVeh->m_iArmor <= pVeh->m_pVehicleInfo->armor/3))
00249         {
00250                 pVeh->m_ulFlags |= VEH_ARMORLOW;
00251 
00252         }
00253 
00254         // Armor Gone Effects (Fire)
00255         //---------------------------
00256         if (pVeh->m_pVehicleInfo->iArmorGoneFX)
00257         {
00258                 if (!(pVeh->m_ulFlags&VEH_ARMORGONE) && (pVeh->m_iArmor <= 0))
00259                 {
00260                         pVeh->m_ulFlags |= VEH_ARMORGONE;
00261                         G_PlayEffect(pVeh->m_pVehicleInfo->iArmorGoneFX, parent->playerModel, parent->crotchBolt, parent->s.number, parent->currentOrigin, 1, qtrue);
00262                         parent->s.loopSound = G_SoundIndex( "sound/vehicles/common/fire_lp.wav" );
00263                 }
00264         }
00265 #endif
00266 
00267         return true;
00268 }
00269 #endif //QAGAME
00270 
00271 //MP RULE - ALL PROCESSMOVECOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
00272 //If you really need to violate this rule for SP, then use ifdefs.
00273 //By BG-compatible, I mean no use of game-specific data - ONLY use
00274 //stuff available in the MP bgEntity (in SP, the bgEntity is #defined
00275 //as a gentity, but the MP-compatible access restrictions are based
00276 //on the bgEntity structure in the MP codebase) -rww
00277 // ProcessMoveCommands the Vehicle.
00278 static void ProcessMoveCommands( Vehicle_t *pVeh )
00279 {
00280         /************************************************************************************/
00281         /*      BEGIN   Here is where we move the vehicle (forward or back or whatever). BEGIN  */
00282         /************************************************************************************/
00283         //Client sets ucmds and such for speed alterations
00284         float speedInc, speedIdleDec, speedIdle, speedIdleAccel, speedMin, speedMax;
00285         playerState_t *parentPS;
00286         playerState_t *pilotPS = NULL;
00287         int     curTime;
00288 
00289 #ifdef _JK2MP
00290         parentPS = pVeh->m_pParentEntity->playerState;
00291         if (pVeh->m_pPilot)
00292         {
00293                 pilotPS = pVeh->m_pPilot->playerState;
00294         }
00295 #else
00296         parentPS = &pVeh->m_pParentEntity->client->ps;
00297         if (pVeh->m_pPilot)
00298         {
00299                 pilotPS = &pVeh->m_pPilot->client->ps;
00300         }
00301 #endif
00302 
00303 
00304         // If we're flying, make us accelerate at 40% (about half) acceleration rate, and restore the pitch
00305         // to origin (straight) position (at 5% increments). 
00306         if ( pVeh->m_ulFlags & VEH_FLYING ) 
00307         {
00308                 speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier * 0.4f;
00309         }
00310 #ifdef _JK2MP
00311         else if ( !parentPS->m_iVehicleNum )
00312 #else
00313         else if ( !pVeh->m_pVehicleInfo->Inhabited( pVeh ) )
00314 #endif
00315         {//drifts to a stop
00316                 speedInc = 0;
00317                 //pVeh->m_ucmd.forwardmove = 127;
00318         }
00319         else
00320         {
00321                 speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier;
00322         }
00323         speedIdleDec = pVeh->m_pVehicleInfo->decelIdle * pVeh->m_fTimeModifier;
00324 
00325 #ifndef _JK2MP//SP
00326         curTime = level.time;
00327 #elif QAGAME//MP GAME
00328         curTime = level.time;
00329 #elif CGAME//MP CGAME
00330         //FIXME: pass in ucmd?  Not sure if this is reliable...
00331         curTime = pm->cmd.serverTime;
00332 #endif
00333 
00334 
00335 
00336         if ( (pVeh->m_pPilot /*&& (pilotPS->weapon == WP_NONE || pilotPS->weapon == WP_MELEE )*/ &&
00337                 (pVeh->m_ucmd.buttons & BUTTON_ALT_ATTACK) && pVeh->m_pVehicleInfo->turboSpeed)
00338                 /*||
00339                 (parentPS && parentPS->electrifyTime > curTime && pVeh->m_pVehicleInfo->turboSpeed)*/ //make them go!
00340                 )
00341         {
00342                 if ( (parentPS && parentPS->electrifyTime > curTime) ||
00343                          (pVeh->m_pPilot->playerState &&
00344                           (pVeh->m_pPilot->playerState->weapon == WP_MELEE ||
00345                           (pVeh->m_pPilot->playerState->weapon == WP_SABER && BG_SabersOff( pVeh->m_pPilot->playerState ) ))) )
00346                 {
00347                         if ((curTime - pVeh->m_iTurboTime)>pVeh->m_pVehicleInfo->turboRecharge)
00348                         {
00349                                 pVeh->m_iTurboTime = (curTime + pVeh->m_pVehicleInfo->turboDuration);
00350                                 if (pVeh->m_pVehicleInfo->iTurboStartFX)
00351                                 {
00352                                         int i;
00353                                         for (i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
00354                                         {
00355 #ifdef QAGAME
00356                                                 if (pVeh->m_pParentEntity &&
00357                                                         pVeh->m_pParentEntity->ghoul2 &&
00358                                                         pVeh->m_pParentEntity->playerState)
00359                                                 { //fine, I'll use a tempent for this, but only because it's played only once at the start of a turbo.
00360                                                         vec3_t boltOrg, boltDir;
00361                                                         mdxaBone_t boltMatrix;
00362 
00363                                                         VectorSet(boltDir, 0.0f, pVeh->m_pParentEntity->playerState->viewangles[YAW], 0.0f);
00364 
00365                                                         trap_G2API_GetBoltMatrix(pVeh->m_pParentEntity->ghoul2, 0, pVeh->m_iExhaustTag[i], &boltMatrix, boltDir, pVeh->m_pParentEntity->playerState->origin, level.time, NULL, pVeh->m_pParentEntity->modelScale);
00366                                                         BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltOrg);
00367                                                         BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltDir);
00368                                                         G_PlayEffectID(pVeh->m_pVehicleInfo->iTurboStartFX, boltOrg, boltDir);
00369                                                 }
00370 #endif
00371                                         }
00372                                 }
00373                                 parentPS->speed = pVeh->m_pVehicleInfo->turboSpeed;     // Instantly Jump To Turbo Speed
00374                         }
00375                 }
00376         }
00377 
00378         // Slide Breaking
00379         if (pVeh->m_ulFlags&VEH_SLIDEBREAKING)
00380         {
00381                 if (pVeh->m_ucmd.forwardmove>=0 
00382 #ifndef _JK2MP
00383                         || ((level.time - pVeh->m_pParentEntity->lastMoveTime)>500)
00384 #endif
00385                         )
00386                 {
00387                         pVeh->m_ulFlags &= ~VEH_SLIDEBREAKING;
00388                 }
00389                 parentPS->speed = 0;
00390         }
00391         else if (
00392                 (curTime > pVeh->m_iTurboTime) && 
00393                 !(pVeh->m_ulFlags&VEH_FLYING) && 
00394                 pVeh->m_ucmd.forwardmove<0 && 
00395                 fabs(pVeh->m_vOrientation[ROLL])>25.0f)
00396         {
00397                 pVeh->m_ulFlags |= VEH_SLIDEBREAKING;
00398         }
00399 
00400 
00401         if ( curTime < pVeh->m_iTurboTime )
00402         {
00403                 speedMax = pVeh->m_pVehicleInfo->turboSpeed;
00404                 if (parentPS)
00405                 {
00406                         parentPS->eFlags |= EF_JETPACK_ACTIVE;
00407                 }
00408         }
00409         else
00410         {
00411                 speedMax = pVeh->m_pVehicleInfo->speedMax;
00412                 if (parentPS)
00413                 {
00414                         parentPS->eFlags &= ~EF_JETPACK_ACTIVE;
00415                 }
00416         }
00417 
00418 
00419         speedIdle = pVeh->m_pVehicleInfo->speedIdle;
00420         speedIdleAccel = pVeh->m_pVehicleInfo->accelIdle * pVeh->m_fTimeModifier;
00421         speedMin = pVeh->m_pVehicleInfo->speedMin;
00422 
00423         if ( parentPS->speed || parentPS->groundEntityNum == ENTITYNUM_NONE  ||
00424                  pVeh->m_ucmd.forwardmove || pVeh->m_ucmd.upmove > 0 )
00425         { 
00426                 if ( pVeh->m_ucmd.forwardmove > 0 && speedInc )
00427                 {
00428                         parentPS->speed += speedInc;
00429                 }
00430                 else if ( pVeh->m_ucmd.forwardmove < 0 )
00431                 {
00432                         if ( parentPS->speed > speedIdle )
00433                         {
00434                                 parentPS->speed -= speedInc;
00435                         }
00436                         else if ( parentPS->speed > speedMin )
00437                         {
00438                                 parentPS->speed -= speedIdleDec;
00439                         }
00440                 }
00441                 // No input, so coast to stop.
00442                 else if ( parentPS->speed > 0.0f )
00443                 {
00444                         parentPS->speed -= speedIdleDec;
00445                         if ( parentPS->speed < 0.0f )
00446                         {
00447                                 parentPS->speed = 0.0f;
00448                         }
00449                 }
00450                 else if ( parentPS->speed < 0.0f )
00451                 {
00452                         parentPS->speed += speedIdleDec;
00453                         if ( parentPS->speed > 0.0f )
00454                         {
00455                                 parentPS->speed = 0.0f;
00456                         }
00457                 }
00458         }
00459         else
00460         {
00461                 if ( !pVeh->m_pVehicleInfo->strafePerc 
00462 #ifdef _JK2MP
00463                         || (0 && pVeh->m_pParentEntity->s.number < MAX_CLIENTS) )
00464 #else
00465                         || (!g_speederControlScheme->value && !pVeh->m_pParentEntity->s.number) )
00466 #endif
00467                 {//if in a strafe-capable vehicle, clear strafing unless using alternate control scheme
00468                         //pVeh->m_ucmd.rightmove = 0;
00469                 }
00470         }
00471 
00472         if ( parentPS->speed > speedMax )
00473         {
00474                 parentPS->speed = speedMax;
00475         }
00476         else if ( parentPS->speed < speedMin )
00477         {
00478                 parentPS->speed = speedMin;
00479         }
00480 
00481         if (parentPS && parentPS->electrifyTime > curTime)
00482         {
00483                 parentPS->speed *= (pVeh->m_fTimeModifier/60.0f);
00484         }
00485 
00486 
00487         /********************************************************************************/
00488         /*      END Here is where we move the vehicle (forward or back or whatever). END        */
00489         /********************************************************************************/
00490 }
00491 
00492 //MP RULE - ALL PROCESSORIENTCOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
00493 //If you really need to violate this rule for SP, then use ifdefs.
00494 //By BG-compatible, I mean no use of game-specific data - ONLY use
00495 //stuff available in the MP bgEntity (in SP, the bgEntity is #defined
00496 //as a gentity, but the MP-compatible access restrictions are based
00497 //on the bgEntity structure in the MP codebase) -rww
00498 //Oh, and please, use "< MAX_CLIENTS" to check for "player" and not
00499 //"!s.number", this is a universal check that will work for both SP
00500 //and MP. -rww
00501 // ProcessOrientCommands the Vehicle.
00502 #ifdef _JK2MP //temp hack til mp speeder controls are sorted -rww
00503 extern void AnimalProcessOri(Vehicle_t *pVeh);
00504 #endif
00505 void ProcessOrientCommands( Vehicle_t *pVeh )
00506 {
00507         /********************************************************************************/
00508         /*      BEGIN   Here is where make sure the vehicle is properly oriented.       BEGIN   */
00509         /********************************************************************************/
00510         playerState_t *riderPS;
00511         playerState_t *parentPS;
00512 
00513 #ifdef _JK2MP
00514         float angDif;
00515 
00516         if (pVeh->m_pPilot)
00517         {
00518                 riderPS = pVeh->m_pPilot->playerState;
00519         }
00520         else
00521         {
00522                 riderPS = pVeh->m_pParentEntity->playerState;
00523         }
00524         parentPS = pVeh->m_pParentEntity->playerState;
00525 
00526         //pVeh->m_vOrientation[YAW] = 0.0f;//riderPS->viewangles[YAW];
00527         angDif = AngleSubtract(pVeh->m_vOrientation[YAW], riderPS->viewangles[YAW]);
00528         if (parentPS && parentPS->speed)
00529         {
00530                 float s = parentPS->speed;
00531                 float maxDif = pVeh->m_pVehicleInfo->turningSpeed*4.0f; //magic number hackery
00532                 if (s < 0.0f)
00533                 {
00534                         s = -s;
00535                 }
00536                 angDif *= s/pVeh->m_pVehicleInfo->speedMax;
00537                 if (angDif > maxDif)
00538                 {
00539                         angDif = maxDif;
00540                 }
00541                 else if (angDif < -maxDif)
00542                 {
00543                         angDif = -maxDif;
00544                 }
00545                 pVeh->m_vOrientation[YAW] = AngleNormalize180(pVeh->m_vOrientation[YAW] - angDif*(pVeh->m_fTimeModifier*0.2f));
00546 
00547                 if (parentPS->electrifyTime > pm->cmd.serverTime)
00548                 { //do some crazy stuff
00549                         pVeh->m_vOrientation[YAW] += (sin(pm->cmd.serverTime/1000.0f)*3.0f)*pVeh->m_fTimeModifier;
00550                 }
00551         }
00552 
00553 #else
00554         gentity_t *rider = pVeh->m_pParentEntity->owner;
00555         if ( !rider || !rider->client )
00556         {
00557                 riderPS = &pVeh->m_pParentEntity->client->ps;
00558         }
00559         else
00560         {
00561                 riderPS = &rider->client->ps;
00562         }
00563         parentPS = &pVeh->m_pParentEntity->client->ps;
00564 
00565         if (pVeh->m_ulFlags & VEH_FLYING)
00566         {
00567                 pVeh->m_vOrientation[YAW] += pVeh->m_vAngularVelocity;
00568         }
00569         else if (
00570                 (pVeh->m_ulFlags & VEH_SLIDEBREAKING) ||        // No Angles Control While Out Of Control 
00571                 (pVeh->m_ulFlags & VEH_OUTOFCONTROL)            // No Angles Control While Out Of Control 
00572                 )
00573         {
00574                 // Any ability to change orientation?
00575         }
00576         else if (
00577                 (pVeh->m_ulFlags & VEH_STRAFERAM)                       // No Angles Control While Strafe Ramming
00578                 )
00579         {
00580                 if (parentPS->hackingTime>0)
00581                 {
00582                         parentPS->hackingTime--;
00583                         pVeh->m_vOrientation[ROLL] += (parentPS->hackingTime<( STRAFERAM_DURATION/2))?(-STRAFERAM_ANGLE):( STRAFERAM_ANGLE);
00584                 }
00585                 else if (pVeh->hackingTime<0)
00586                 {
00587                         parentPS->hackingTime++;
00588                         pVeh->m_vOrientation[ROLL] += (parentPS->hackingTime>(-STRAFERAM_DURATION/2))?( STRAFERAM_ANGLE):(-STRAFERAM_ANGLE);
00589                 }
00590         }
00591         else
00592         {
00593                 pVeh->m_vOrientation[YAW] = riderPS->viewangles[YAW];
00594         }
00595 #endif
00596 
00597         /********************************************************************************/
00598         /*      END     Here is where make sure the vehicle is properly oriented.       END                     */
00599         /********************************************************************************/
00600 }
00601 
00602 #ifdef QAGAME
00603 
00604 extern void PM_SetAnim(pmove_t  *pm,int setAnimParts,int anim,int setAnimFlags, int blendTime);
00605 extern int PM_AnimLength( int index, animNumber_t anim );
00606 
00607 // This function makes sure that the vehicle is properly animated.
00608 void AnimateVehicle( Vehicle_t *pVeh )
00609 {
00610 }
00611 
00612 #endif //QAGAME
00613 
00614 //rest of file is shared
00615 
00616 #ifndef _JK2MP
00617 extern void CG_ChangeWeapon( int num );
00618 #endif
00619 
00620 
00621 #ifndef _JK2MP
00622 extern void G_StartMatrixEffect( gentity_t *ent, int meFlags = 0, int length = 1000, float timeScale = 0.0f, int spinTime = 0 );
00623 #endif
00624 
00625 
00626 //NOTE NOTE NOTE NOTE NOTE NOTE
00627 //I want to keep this function BG too, because it's fairly generic already, and it
00628 //would be nice to have proper prediction of animations. -rww
00629 // This function makes sure that the rider's in this vehicle are properly animated.
00630 void AnimateRiders( Vehicle_t *pVeh )
00631 {
00632         animNumber_t Anim = BOTH_VS_IDLE;
00633         float fSpeedPercToMax;
00634         int iFlags = SETANIM_FLAG_NORMAL, iBlend = 300;
00635         playerState_t *pilotPS;
00636         playerState_t *parentPS;
00637         int curTime;
00638 
00639 
00640         // Boarding animation.
00641         if ( pVeh->m_iBoarding != 0 )
00642         {
00643                 // We've just started moarding, set the amount of time it will take to finish moarding.
00644                 if ( pVeh->m_iBoarding < 0 )
00645                 {
00646                         int iAnimLen;
00647 
00648                         // Boarding from left...
00649                         if ( pVeh->m_iBoarding == -1 )
00650                         {
00651                                 Anim = BOTH_VS_MOUNT_L;
00652                         }
00653                         else if ( pVeh->m_iBoarding == -2 )
00654                         {
00655                                 Anim = BOTH_VS_MOUNT_R;
00656                         }
00657                         else if ( pVeh->m_iBoarding == -3 )
00658                         {
00659                                 Anim = BOTH_VS_MOUNTJUMP_L;
00660                         }
00661                         else if ( pVeh->m_iBoarding == VEH_MOUNT_THROW_LEFT)
00662                         {
00663                                 iBlend = 0;
00664                                 Anim = BOTH_VS_MOUNTTHROW_R;
00665                         }
00666                         else if ( pVeh->m_iBoarding == VEH_MOUNT_THROW_RIGHT)
00667                         {
00668                                 iBlend = 0;
00669                                 Anim = BOTH_VS_MOUNTTHROW_L;
00670                         }
00671 
00672                         // Set the delay time (which happens to be the time it takes for the animation to complete).
00673                         // NOTE: Here I made it so the delay is actually 40% (0.4f) of the animation time.
00674 #ifdef _JK2MP
00675                         iAnimLen = BG_AnimLength( pVeh->m_pPilot->localAnimIndex, Anim ) * 0.4f;
00676                         pVeh->m_iBoarding = BG_GetTime() + iAnimLen;
00677 #else
00678                         iAnimLen = PM_AnimLength( pVeh->m_pPilot->client->clientInfo.animFileIndex, Anim );// * 0.4f;
00679                         if (pVeh->m_iBoarding!=VEH_MOUNT_THROW_LEFT && pVeh->m_iBoarding!=VEH_MOUNT_THROW_RIGHT)
00680                         {
00681                                 pVeh->m_iBoarding = level.time + (iAnimLen*0.4f);
00682                         }
00683                         else
00684                         {
00685                                 pVeh->m_iBoarding = level.time + iAnimLen;
00686                         }
00687 #endif
00688                         // Set the animation, which won't be interrupted until it's completed.
00689                         // TODO: But what if he's killed? Should the animation remain persistant???
00690                         iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
00691                         
00692 #ifdef _JK2MP
00693                         BG_SetAnim(pVeh->m_pPilot->playerState, bgAllAnims[pVeh->m_pPilot->localAnimIndex].anims,
00694                                 SETANIM_BOTH, Anim, iFlags, iBlend);
00695 #else
00696                         NPC_SetAnim( pVeh->m_pPilot, SETANIM_BOTH, Anim, iFlags, iBlend );
00697                         if (pVeh->m_pOldPilot)
00698                         {
00699                                 iAnimLen = PM_AnimLength( pVeh->m_pPilot->client->clientInfo.animFileIndex, BOTH_VS_MOUNTTHROWEE);
00700                                 NPC_SetAnim( pVeh->m_pOldPilot, SETANIM_BOTH, BOTH_VS_MOUNTTHROWEE, iFlags, iBlend );
00701                         }
00702 #endif
00703                 }
00704 
00705 #ifndef _JK2MP
00706                 if (pVeh->m_pOldPilot && pVeh->m_pOldPilot->client->ps.torsoAnimTimer<=0)
00707                 {
00708                         if (Q_irand(0, player->count)==0)
00709                         {
00710                                 player->count++;
00711                                 player->lastEnemy = pVeh->m_pOldPilot;
00712                                 G_StartMatrixEffect(player, MEF_LOOK_AT_ENEMY|MEF_NO_RANGEVAR|MEF_NO_VERTBOB|MEF_NO_SPIN, 1000);
00713                         }
00714 
00715                         gentity_t*      oldPilot = pVeh->m_pOldPilot;
00716                         pVeh->m_pVehicleInfo->Eject(pVeh, pVeh->m_pOldPilot, qtrue);            // will set pointer to zero
00717 
00718                         // Kill Him
00719                         //----------
00720                         oldPilot->client->noRagTime = -1;       // no ragdoll for you
00721                         G_Damage(oldPilot, pVeh->m_pPilot, pVeh->m_pPilot, pVeh->m_pPilot->currentAngles, pVeh->m_pPilot->currentOrigin, 1000, 0, MOD_CRUSH);
00722 
00723                         // Compute THe Throw Direction As Backwards From The Vehicle's Velocity
00724                         //----------------------------------------------------------------------
00725                         vec3_t          throwDir;
00726                         VectorScale(pVeh->m_pParentEntity->client->ps.velocity, -1.0f, throwDir);
00727                         VectorNormalize(throwDir);
00728                         throwDir[2] += 0.3f;    // up a little
00729 
00730                         // Now Throw Him Out
00731                         //-------------------
00732                         G_Throw(oldPilot, throwDir, VectorLength(pVeh->m_pParentEntity->client->ps.velocity)/10.0f);
00733                         NPC_SetAnim(oldPilot, SETANIM_BOTH, BOTH_DEATHBACKWARD1, SETANIM_FLAG_OVERRIDE, iBlend );
00734                 }
00735 #endif
00736 
00737                 return;
00738         }
00739 
00740 #ifdef _JK2MP //fixme
00741         if (1) return;
00742 #endif
00743 
00744 #ifdef _JK2MP
00745         pilotPS = pVeh->m_pPilot->playerState;
00746         parentPS = pVeh->m_pPilot->playerState;
00747 #else
00748         pilotPS = &pVeh->m_pPilot->client->ps;
00749         parentPS = &pVeh->m_pParentEntity->client->ps;
00750 #endif
00751 
00752 #ifndef _JK2MP//SP
00753         curTime = level.time;
00754 #elif QAGAME//MP GAME
00755         curTime = level.time;
00756 #elif CGAME//MP CGAME
00757         //FIXME: pass in ucmd?  Not sure if this is reliable...
00758         curTime = pm->cmd.serverTime;
00759 #endif
00760 
00761         // Percentage of maximum speed relative to current speed.
00762         fSpeedPercToMax = parentPS->speed / pVeh->m_pVehicleInfo->speedMax;
00763 
00764         // Going in reverse...
00765 #ifdef _JK2MP
00766         if ( pVeh->m_ucmd.forwardmove < 0 && !(pVeh->m_ulFlags & VEH_SLIDEBREAKING))
00767 #else
00768         if ( fSpeedPercToMax < -0.018f && !(pVeh->m_ulFlags & VEH_SLIDEBREAKING))
00769 #endif
00770         {
00771                 Anim = BOTH_VS_REV;
00772                 iBlend = 500;
00773         }
00774         else 
00775         {
00776                 bool            HasWeapon       = ((pilotPS->weapon != WP_NONE) && (pilotPS->weapon != WP_MELEE));
00777                 bool            Attacking       = (HasWeapon && !!(pVeh->m_ucmd.buttons&BUTTON_ATTACK));
00778 #ifdef _JK2MP //fixme: flying tends to spaz out a lot
00779                 bool            Flying          = false;
00780                 bool            Crashing        = false;
00781 #else
00782                 bool            Flying          = !!(pVeh->m_ulFlags & VEH_FLYING);
00783                 bool            Crashing        = !!(pVeh->m_ulFlags & VEH_CRASHING);
00784 #endif
00785                 bool            Right           = (pVeh->m_ucmd.rightmove>0);
00786                 bool            Left            = (pVeh->m_ucmd.rightmove<0);
00787                 bool            Turbo           = (curTime<pVeh->m_iTurboTime);
00788                 EWeaponPose     WeaponPose      = WPOSE_NONE;
00789 
00790 
00791                 // Remove Crashing Flag
00792                 //----------------------
00793                 pVeh->m_ulFlags &= ~VEH_CRASHING;
00794 
00795 
00796                 // Put Away Saber When It Is Not Active
00797                 //--------------------------------------
00798 #ifndef _JK2MP
00799                 if (HasWeapon && (Turbo || (pilotPS->weapon==WP_SABER && !pilotPS->SaberActive())))
00800                 {
00801                         if (pVeh->m_pPilot->s.number<MAX_CLIENTS)
00802                         {
00803                                 CG_ChangeWeapon(WP_NONE);
00804                         }
00805 
00806                         pVeh->m_pPilot->client->ps.weapon = WP_NONE;
00807                         G_RemoveWeaponModels(pVeh->m_pPilot);
00808                 }
00809 #endif
00810 
00811                 // Don't Interrupt Attack Anims
00812                 //------------------------------
00813 #ifdef _JK2MP
00814                 if (pilotPS->weaponTime>0)
00815                 {
00816                         return;
00817                 }
00818 #else           
00819                 if (pilotPS->torsoAnim>=BOTH_VS_ATL_S && pilotPS->torsoAnim<=BOTH_VS_ATF_G)
00820                 {
00821                         float           bodyCurrent       = 0.0f;
00822                         int                     bodyEnd           = 0;
00823                         if (!!gi.G2API_GetBoneAnimIndex(&pVeh->m_pPilot->ghoul2[pVeh->m_pPilot->playerModel], pVeh->m_pPilot->rootBone, level.time, &bodyCurrent, NULL, &bodyEnd, NULL, NULL, NULL))
00824                         {
00825                                 if (bodyCurrent<=((float)(bodyEnd)-1.5f))
00826                                 {
00827                                         return;
00828                                 }
00829                         }
00830                 }
00831 #endif
00832 
00833                 // Compute The Weapon Pose
00834                 //--------------------------
00835                 if (pilotPS->weapon==WP_BLASTER)
00836                 {
00837                         WeaponPose = WPOSE_BLASTER;
00838                 }
00839                 else if (pilotPS->weapon==WP_SABER)
00840                 {
00841                         if ( (pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VS_ATL_TO_R_S)
00842                         {
00843                                 pVeh->m_ulFlags &= ~VEH_SABERINLEFTHAND;
00844                         }
00845                         if (!(pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VS_ATR_TO_L_S)
00846                         {
00847                                 pVeh->m_ulFlags |=  VEH_SABERINLEFTHAND;
00848                         }
00849                         WeaponPose = (pVeh->m_ulFlags&VEH_SABERINLEFTHAND)?(WPOSE_SABERLEFT):(WPOSE_SABERRIGHT);
00850                 }
00851                 
00852 
00853                 if (Attacking && WeaponPose)
00854                 {// Attack!
00855                         iBlend  = 100;
00856                         iFlags  = SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART;
00857         
00858                         // Auto Aiming
00859                         //===============================================
00860                         if (!Left && !Right)            // Allow player strafe keys to override
00861                         {
00862 #ifndef _JK2MP
00863                                 if (pVeh->m_pPilot->enemy)
00864                                 {
00865                                         vec3_t  toEnemy;
00866                                         float   toEnemyDistance;
00867                                         vec3_t  actorRight;
00868                                         float   actorRightDot;
00869 
00870                                         VectorSubtract(pVeh->m_pPilot->currentOrigin, pVeh->m_pPilot->enemy->currentOrigin, toEnemy);
00871                                         toEnemyDistance = VectorNormalize(toEnemy);
00872 
00873                                         AngleVectors(pVeh->m_pParentEntity->currentAngles, 0, actorRight, 0);
00874                                         actorRightDot = DotProduct(toEnemy, actorRight);
00875 
00876                                         if (fabsf(actorRightDot)>0.5f || pilotPS->weapon==WP_SABER)
00877                                         {
00878                                                 Left    = (actorRightDot>0.0f);
00879                                                 Right   = !Left;
00880                                         }
00881                                         else
00882                                         {
00883                                                 Right = Left = false;
00884                                         }
00885                                 }
00886                                 else 
00887 #endif
00888                                 if (pilotPS->weapon==WP_SABER && !Left && !Right)
00889                                 {
00890                                         Left = (WeaponPose==WPOSE_SABERLEFT);
00891                                         Right   = !Left;
00892                                 }
00893                         }
00894 
00895 
00896                         if (Left)
00897                         {// Attack Left
00898                                 switch(WeaponPose)
00899                                 {
00900                                 case WPOSE_BLASTER:             Anim = BOTH_VS_ATL_G;           break;
00901                                 case WPOSE_SABERLEFT:   Anim = BOTH_VS_ATL_S;           break;
00902                                 case WPOSE_SABERRIGHT:  Anim = BOTH_VS_ATR_TO_L_S;      break;
00903                                 default:                                assert(0);
00904                                 }
00905                         }
00906                         else if (Right)
00907                         {// Attack Right
00908                                 switch(WeaponPose)
00909                                 {
00910                                 case WPOSE_BLASTER:             Anim = BOTH_VS_ATR_G;           break;
00911                                 case WPOSE_SABERLEFT:   Anim = BOTH_VS_ATL_TO_R_S;      break;
00912                                 case WPOSE_SABERRIGHT:  Anim = BOTH_VS_ATR_S;           break;
00913                                 default:                                assert(0);
00914                                 }
00915                         }
00916                         else
00917                         {// Attack Ahead
00918                                 switch(WeaponPose)
00919                                 {
00920                                 case WPOSE_BLASTER:             Anim = BOTH_VS_ATF_G;           break;
00921                                 default:                                assert(0);
00922                                 }
00923                         }
00924 
00925                 }
00926                 else if (Left && pVeh->m_ucmd.buttons&BUTTON_USE)
00927                 {// Look To The Left Behind
00928                         iBlend  = 400;
00929                         iFlags  = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
00930                         switch(WeaponPose)
00931                         {
00932                         case WPOSE_SABERLEFT:   Anim = BOTH_VS_IDLE_SL;         break;
00933                         case WPOSE_SABERRIGHT:  Anim = BOTH_VS_IDLE_SR;         break;
00934                         default:                                Anim = BOTH_VS_LOOKLEFT;
00935                         }
00936                 }
00937                 else if (Right && pVeh->m_ucmd.buttons&BUTTON_USE)
00938                 {// Look To The Right Behind
00939                         iBlend  = 400;
00940                         iFlags  = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
00941                         switch(WeaponPose)
00942                         {
00943                         case WPOSE_SABERLEFT:   Anim = BOTH_VS_IDLE_SL;         break;
00944                         case WPOSE_SABERRIGHT:  Anim = BOTH_VS_IDLE_SR;         break;
00945                         default:                                Anim = BOTH_VS_LOOKRIGHT;
00946                         }
00947                 }
00948                 else if (Turbo)
00949                 {// Kicked In Turbo
00950                         iBlend  = 50;
00951                         iFlags  = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
00952                         Anim    = BOTH_VS_TURBO;
00953                 }
00954                 else if (Flying)
00955                 {// Off the ground in a jump
00956                         iBlend  = 800;
00957                         iFlags  = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
00958 
00959                         switch(WeaponPose)
00960                         {
00961                         case WPOSE_NONE:                Anim = BOTH_VS_AIR;                     break;
00962                         case WPOSE_BLASTER:             Anim = BOTH_VS_AIR_G;           break;
00963                         case WPOSE_SABERLEFT:   Anim = BOTH_VS_AIR_SL;          break;
00964                         case WPOSE_SABERRIGHT:  Anim = BOTH_VS_AIR_SR;          break;
00965                         default:                                assert(0);
00966                         }
00967                 }
00968                 else if (Crashing)
00969                 {// Hit the ground!
00970                         iBlend  = 100;
00971                         iFlags  = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
00972 
00973                         switch(WeaponPose)
00974                         {
00975                         case WPOSE_NONE:                Anim = BOTH_VS_LAND;            break;
00976                         case WPOSE_BLASTER:             Anim = BOTH_VS_LAND_G;          break;
00977                         case WPOSE_SABERLEFT:   Anim = BOTH_VS_LAND_SL;         break;
00978                         case WPOSE_SABERRIGHT:  Anim = BOTH_VS_LAND_SR;         break;
00979                         default:                                assert(0);
00980                         }
00981                 }
00982                 else
00983                 {// No Special Moves
00984                         iBlend  = 300;
00985                         iFlags  = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
00986 
00987                         if (pVeh->m_vOrientation[ROLL] <= -20)
00988                         {// Lean Left
00989                                 switch(WeaponPose)
00990                                 {
00991                                 case WPOSE_NONE:                Anim = BOTH_VS_LEANL;                   break;
00992                                 case WPOSE_BLASTER:             Anim = BOTH_VS_LEANL_G;                 break;
00993                                 case WPOSE_SABERLEFT:   Anim = BOTH_VS_LEANL_SL;                break;
00994                                 case WPOSE_SABERRIGHT:  Anim = BOTH_VS_LEANL_SR;                break;
00995                                 default:                                assert(0);
00996                                 }
00997                         }
00998                         else if (pVeh->m_vOrientation[ROLL] >= 20)
00999                         {// Lean Right
01000                                 switch(WeaponPose)
01001                                 {
01002                                 case WPOSE_NONE:                Anim = BOTH_VS_LEANR;                   break;
01003                                 case WPOSE_BLASTER:             Anim = BOTH_VS_LEANR_G;                 break;
01004                                 case WPOSE_SABERLEFT:   Anim = BOTH_VS_LEANR_SL;                break;
01005                                 case WPOSE_SABERRIGHT:  Anim = BOTH_VS_LEANR_SR;                break;
01006                                 default:                                assert(0);
01007                                 }
01008                         }
01009                         else
01010                         {// No Lean
01011                                 switch(WeaponPose)
01012                                 {
01013                                 case WPOSE_NONE:                Anim = BOTH_VS_IDLE;                    break;
01014                                 case WPOSE_BLASTER:             Anim = BOTH_VS_IDLE_G;                  break;
01015                                 case WPOSE_SABERLEFT:   Anim = BOTH_VS_IDLE_SL;                 break;
01016                                 case WPOSE_SABERRIGHT:  Anim = BOTH_VS_IDLE_SR;                 break;
01017                                 default:                                assert(0);
01018                                 }
01019                         }
01020                 }// No Special Moves
01021         }// Going backwards?
01022 
01023 #ifdef _JK2MP
01024         iFlags &= ~SETANIM_FLAG_OVERRIDE;
01025         if (pVeh->m_pPilot->playerState->torsoAnim == Anim)
01026         {
01027                 pVeh->m_pPilot->playerState->torsoTimer = BG_AnimLength(pVeh->m_pPilot->localAnimIndex, Anim);
01028         }
01029         if (pVeh->m_pPilot->playerState->legsAnim == Anim)
01030         {
01031                 pVeh->m_pPilot->playerState->legsTimer = BG_AnimLength(pVeh->m_pPilot->localAnimIndex, Anim);
01032         }
01033         BG_SetAnim(pVeh->m_pPilot->playerState, bgAllAnims[pVeh->m_pPilot->localAnimIndex].anims,
01034                 SETANIM_BOTH, Anim, iFlags|SETANIM_FLAG_HOLD, iBlend);
01035 #else
01036         NPC_SetAnim( pVeh->m_pPilot, SETANIM_BOTH, Anim, iFlags, iBlend );
01037 #endif
01038 }
01039 
01040 #ifndef QAGAME
01041 void AttachRidersGeneric( Vehicle_t *pVeh );
01042 #endif
01043 
01044 void G_SetSpeederVehicleFunctions( vehicleInfo_t *pVehInfo )
01045 {
01046 #ifdef QAGAME
01047         pVehInfo->AnimateVehicle                        =               AnimateVehicle;
01048         pVehInfo->AnimateRiders                         =               AnimateRiders;
01049 //      pVehInfo->ValidateBoard                         =               ValidateBoard;
01050 //      pVehInfo->SetParent                                     =               SetParent;
01051 //      pVehInfo->SetPilot                                      =               SetPilot;
01052 //      pVehInfo->AddPassenger                          =               AddPassenger;
01053 //      pVehInfo->Animate                                       =               Animate;
01054 //      pVehInfo->Board                                         =               Board;
01055 //      pVehInfo->Eject                                         =               Eject;
01056 //      pVehInfo->EjectAll                                      =               EjectAll;
01057 //      pVehInfo->StartDeathDelay                       =               StartDeathDelay;
01058 //      pVehInfo->DeathUpdate                           =               DeathUpdate;
01059 //      pVehInfo->RegisterAssets                        =               RegisterAssets;
01060 //      pVehInfo->Initialize                            =               Initialize;
01061         pVehInfo->Update                                        =               Update;
01062 //      pVehInfo->UpdateRider                           =               UpdateRider;
01063 #endif
01064 
01065         //shared
01066         pVehInfo->ProcessMoveCommands           =               ProcessMoveCommands;
01067         pVehInfo->ProcessOrientCommands         =               ProcessOrientCommands;
01068 
01069 #ifndef QAGAME //cgame prediction attachment func
01070         pVehInfo->AttachRiders                          =               AttachRidersGeneric;
01071 #endif
01072 //      pVehInfo->AttachRiders                          =               AttachRiders;
01073 //      pVehInfo->Ghost                                         =               Ghost;
01074 //      pVehInfo->UnGhost                                       =               UnGhost;
01075 //      pVehInfo->Inhabited                                     =               Inhabited;
01076 }
01077 
01078 // Following is only in game, not in namespace
01079 #ifdef _JK2MP
01080 #include "../namespace_end.h"
01081 #endif
01082 
01083 #ifdef QAGAME
01084 extern void G_AllocateVehicleObject(Vehicle_t **pVeh);
01085 #endif
01086 
01087 #ifdef _JK2MP
01088 #include "../namespace_begin.h"
01089 #endif
01090 
01091 // Create/Allocate a new Animal Vehicle (initializing it as well).
01092 void G_CreateSpeederNPC( Vehicle_t **pVeh, const char *strType )
01093 {
01094 #ifdef _JK2MP
01095 #ifdef QAGAME
01096         //these will remain on entities on the client once allocated because the pointer is
01097         //never stomped. on the server, however, when an ent is freed, the entity struct is
01098         //memset to 0, so this memory would be lost..
01099     G_AllocateVehicleObject(pVeh);
01100 #else
01101         if (!*pVeh)
01102         { //only allocate a new one if we really have to
01103                 (*pVeh) = (Vehicle_t *) BG_Alloc( sizeof(Vehicle_t) );
01104         }
01105 #endif
01106         memset(*pVeh, 0, sizeof(Vehicle_t));
01107         (*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strType )];
01108 #else
01109         // Allocate the Vehicle.
01110         (*pVeh) = (Vehicle_t *) gi.Malloc( sizeof(Vehicle_t), TAG_G_ALLOC, qtrue );
01111         (*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strType )];
01112 #endif
01113 }
01114 
01115 #ifdef _JK2MP
01116 
01117 #include "../namespace_end.h"
01118 
01119 //get rid of all the crazy defs we added for this file
01120 #undef currentAngles
01121 #undef currentOrigin
01122 #undef mins
01123 #undef maxs
01124 #undef legsAnimTimer
01125 #undef torsoAnimTimer
01126 #undef bool
01127 #undef false
01128 #undef true
01129 
01130 #undef sqrtf
01131 #undef Q_flrand
01132 
01133 #undef MOD_EXPLOSIVE
01134 #endif