SpeederNPC.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. // leave this line at the top for all g_xxxx.cpp files...
  2. #include "g_headers.h"
  3. //seems to be a compiler bug, it doesn't clean out the #ifdefs between dif-compiles
  4. //or something, so the headers spew errors on these defs from the previous compile.
  5. //this fixes that. -rww
  6. #ifdef _JK2MP
  7. //get rid of all the crazy defs we added for this file
  8. #undef currentAngles
  9. #undef currentOrigin
  10. #undef mins
  11. #undef maxs
  12. #undef legsAnimTimer
  13. #undef torsoAnimTimer
  14. #undef bool
  15. #undef false
  16. #undef true
  17. #undef sqrtf
  18. #undef Q_flrand
  19. #undef MOD_EXPLOSIVE
  20. #endif
  21. #ifdef _JK2 //SP does not have this preprocessor for game like MP does
  22. #ifndef _JK2MP
  23. #define _JK2MP
  24. #endif
  25. #endif
  26. #ifndef _JK2MP //if single player
  27. #ifndef QAGAME //I don't think we have a QAGAME define
  28. #define QAGAME //but define it cause in sp we're always in the game
  29. #endif
  30. #endif
  31. #ifdef QAGAME //including game headers on cgame is FORBIDDEN ^_^
  32. #include "g_local.h"
  33. #elif defined _JK2MP
  34. #include "bg_public.h"
  35. #endif
  36. #ifndef _JK2MP
  37. #include "g_functions.h"
  38. #include "g_vehicles.h"
  39. #include "..\game\wp_saber.h"
  40. #include "../cgame/cg_local.h"
  41. #else
  42. #include "bg_vehicles.h"
  43. #endif
  44. #ifdef _JK2MP
  45. //this is really horrible, but it works! just be sure not to use any locals or anything
  46. //with these names (exluding bool, false, true). -rww
  47. #define currentAngles r.currentAngles
  48. #define currentOrigin r.currentOrigin
  49. #define mins r.mins
  50. #define maxs r.maxs
  51. #define legsAnimTimer legsTimer
  52. #define torsoAnimTimer torsoTimer
  53. #define bool qboolean
  54. #define false qfalse
  55. #define true qtrue
  56. #define sqrtf sqrt
  57. #define Q_flrand flrand
  58. #define MOD_EXPLOSIVE MOD_SUICIDE
  59. #else
  60. #define bgEntity_t gentity_t
  61. extern void NPC_SetAnim(gentity_t *ent,int setAnimParts,int anim,int setAnimFlags, int iBlend);
  62. #endif
  63. extern float DotToSpot( vec3_t spot, vec3_t from, vec3_t fromAngles );
  64. #ifdef QAGAME //SP or gameside MP
  65. extern vmCvar_t cg_thirdPersonAlpha;
  66. extern vec3_t playerMins;
  67. extern vec3_t playerMaxs;
  68. extern cvar_t *g_speederControlScheme;
  69. extern void ChangeWeapon( gentity_t *ent, int newWeapon );
  70. extern void PM_SetAnim(pmove_t *pm,int setAnimParts,int anim,int setAnimFlags, int blendTime);
  71. extern int PM_AnimLength( int index, animNumber_t anim );
  72. #endif
  73. #ifdef _JK2MP
  74. #include "../namespace_begin.h"
  75. extern void BG_SetAnim(playerState_t *ps, animation_t *animations, int setAnimParts,int anim,int setAnimFlags, int blendTime);
  76. extern int BG_GetTime(void);
  77. #endif
  78. //Alright, actually, most of this file is shared between game and cgame for MP.
  79. //I would like to keep it this way, so when modifying for SP please keep in
  80. //mind the bgEntity restrictions imposed. -rww
  81. #define STRAFERAM_DURATION 8
  82. #define STRAFERAM_ANGLE 8
  83. #ifndef _JK2MP
  84. bool VEH_StartStrafeRam(Vehicle_t *pVeh, bool Right)
  85. {
  86. if (!(pVeh->m_ulFlags&VEH_STRAFERAM))
  87. {
  88. float speed = VectorLength(pVeh->m_pParentEntity->client->ps.velocity);
  89. if (speed>400.0f)
  90. {
  91. // Compute Pos3
  92. //--------------
  93. vec3_t right;
  94. AngleVectors(pVeh->m_vOrientation, 0, right, 0);
  95. VectorMA(pVeh->m_pParentEntity->client->ps.velocity, (Right)?( speed):(-speed), right, pVeh->m_pParentEntity->pos3);
  96. pVeh->m_ulFlags |= VEH_STRAFERAM;
  97. pVeh->m_fStrafeTime = (Right)?(STRAFERAM_DURATION):(-STRAFERAM_DURATION);
  98. if (pVeh->m_iSoundDebounceTimer<level.time && Q_irand(0,1)==0)
  99. {
  100. int shiftSound = Q_irand(1,4);
  101. switch (shiftSound)
  102. {
  103. case 1: shiftSound=pVeh->m_pVehicleInfo->soundShift1; break;
  104. case 2: shiftSound=pVeh->m_pVehicleInfo->soundShift2; break;
  105. case 3: shiftSound=pVeh->m_pVehicleInfo->soundShift3; break;
  106. case 4: shiftSound=pVeh->m_pVehicleInfo->soundShift4; break;
  107. }
  108. if (shiftSound)
  109. {
  110. pVeh->m_iSoundDebounceTimer = level.time + Q_irand(1000, 4000);
  111. G_SoundIndexOnEnt( pVeh->m_pParentEntity, CHAN_AUTO, shiftSound);
  112. }
  113. }
  114. return true;
  115. }
  116. }
  117. return false;
  118. }
  119. #else
  120. bool VEH_StartStrafeRam(Vehicle_t *pVeh, bool Right, int Duration)
  121. {
  122. return false;
  123. }
  124. #endif
  125. #ifdef QAGAME //game-only.. for now
  126. // Like a think or move command, this updates various vehicle properties.
  127. bool Update( Vehicle_t *pVeh, const usercmd_t *pUcmd )
  128. {
  129. if ( !g_vehicleInfo[VEHICLE_BASE].Update( pVeh, pUcmd ) )
  130. {
  131. return false;
  132. }
  133. // See whether this vehicle should be exploding.
  134. if ( pVeh->m_iDieTime != 0 )
  135. {
  136. pVeh->m_pVehicleInfo->DeathUpdate( pVeh );
  137. }
  138. // Update move direction.
  139. #ifndef _JK2MP //this makes prediction unhappy, and rightfully so.
  140. gentity_t *parent = (gentity_t *)pVeh->m_pParentEntity;
  141. if ( pVeh->m_ulFlags & VEH_FLYING )
  142. {
  143. vec3_t vVehAngles;
  144. VectorSet(vVehAngles, 0, pVeh->m_vOrientation[YAW], 0 );
  145. AngleVectors( vVehAngles, parent->client->ps.moveDir, NULL, NULL );
  146. }
  147. else
  148. {
  149. vec3_t vVehAngles;
  150. VectorSet(vVehAngles, pVeh->m_vOrientation[PITCH], pVeh->m_vOrientation[YAW], 0 );
  151. AngleVectors( vVehAngles, parent->client->ps.moveDir, NULL, NULL );
  152. }
  153. // Check For A Strafe Ram
  154. //------------------------
  155. if (!(pVeh->m_ulFlags&VEH_STRAFERAM) && !(pVeh->m_ulFlags&VEH_FLYING))
  156. {
  157. // Started A Strafe
  158. //------------------
  159. if (pVeh->m_ucmd.rightmove && !pVeh->m_fStrafeTime)
  160. {
  161. pVeh->m_fStrafeTime = (pVeh->m_ucmd.rightmove>0)?(level.time):(-1*level.time);
  162. }
  163. // Ended A Strafe
  164. //----------------
  165. else if (!pVeh->m_ucmd.rightmove && pVeh->m_fStrafeTime)
  166. {
  167. // If It Was A Short Burst, Start The Strafe Ram
  168. //-----------------------------------------------
  169. if ((level.time - abs(pVeh->m_fStrafeTime))<300)
  170. {
  171. if (!VEH_StartStrafeRam(pVeh, (pVeh->m_fStrafeTime>0)))
  172. {
  173. pVeh->m_fStrafeTime = 0;
  174. }
  175. }
  176. // Otherwise, Clear The Timer
  177. //----------------------------
  178. else
  179. {
  180. pVeh->m_fStrafeTime = 0;
  181. }
  182. }
  183. }
  184. // If Currently In A StrafeRam, Check To See If It Is Done (Timed Out)
  185. //---------------------------------------------------------------------
  186. else if (!pVeh->m_fStrafeTime)
  187. {
  188. pVeh->m_ulFlags &=~VEH_STRAFERAM;
  189. }
  190. // Exhaust Effects Start And Stop When The Accelerator Is Pressed
  191. //----------------------------------------------------------------
  192. if (pVeh->m_pVehicleInfo->iExhaustFX)
  193. {
  194. // Start It On Each Exhaust Bolt
  195. //-------------------------------
  196. if (pVeh->m_ucmd.forwardmove && !(pVeh->m_ulFlags&VEH_ACCELERATORON))
  197. {
  198. pVeh->m_ulFlags |= VEH_ACCELERATORON;
  199. for (int i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
  200. {
  201. G_PlayEffect(pVeh->m_pVehicleInfo->iExhaustFX, parent->playerModel, pVeh->m_iExhaustTag[i], parent->s.number, parent->currentOrigin, 1, qtrue);
  202. }
  203. }
  204. // Stop It On Each Exhaust Bolt
  205. //------------------------------
  206. else if (!pVeh->m_ucmd.forwardmove && (pVeh->m_ulFlags&VEH_ACCELERATORON))
  207. {
  208. pVeh->m_ulFlags &=~VEH_ACCELERATORON;
  209. for (int i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
  210. {
  211. G_StopEffect(pVeh->m_pVehicleInfo->iExhaustFX, parent->playerModel, pVeh->m_iExhaustTag[i], parent->s.number);
  212. }
  213. }
  214. }
  215. if (!(pVeh->m_ulFlags&VEH_ARMORLOW) && (pVeh->m_iArmor <= pVeh->m_pVehicleInfo->armor/3))
  216. {
  217. pVeh->m_ulFlags |= VEH_ARMORLOW;
  218. }
  219. // Armor Gone Effects (Fire)
  220. //---------------------------
  221. if (pVeh->m_pVehicleInfo->iArmorGoneFX)
  222. {
  223. if (!(pVeh->m_ulFlags&VEH_ARMORGONE) && (pVeh->m_iArmor <= 0))
  224. {
  225. pVeh->m_ulFlags |= VEH_ARMORGONE;
  226. G_PlayEffect(pVeh->m_pVehicleInfo->iArmorGoneFX, parent->playerModel, parent->crotchBolt, parent->s.number, parent->currentOrigin, 1, qtrue);
  227. parent->s.loopSound = G_SoundIndex( "sound/vehicles/common/fire_lp.wav" );
  228. }
  229. }
  230. #endif
  231. return true;
  232. }
  233. #endif //QAGAME
  234. //MP RULE - ALL PROCESSMOVECOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
  235. //If you really need to violate this rule for SP, then use ifdefs.
  236. //By BG-compatible, I mean no use of game-specific data - ONLY use
  237. //stuff available in the MP bgEntity (in SP, the bgEntity is #defined
  238. //as a gentity, but the MP-compatible access restrictions are based
  239. //on the bgEntity structure in the MP codebase) -rww
  240. // ProcessMoveCommands the Vehicle.
  241. static void ProcessMoveCommands( Vehicle_t *pVeh )
  242. {
  243. /************************************************************************************/
  244. /* BEGIN Here is where we move the vehicle (forward or back or whatever). BEGIN */
  245. /************************************************************************************/
  246. //Client sets ucmds and such for speed alterations
  247. float speedInc, speedIdleDec, speedIdle, speedIdleAccel, speedMin, speedMax;
  248. playerState_t *parentPS;
  249. playerState_t *pilotPS = NULL;
  250. int curTime;
  251. #ifdef _JK2MP
  252. parentPS = pVeh->m_pParentEntity->playerState;
  253. if (pVeh->m_pPilot)
  254. {
  255. pilotPS = pVeh->m_pPilot->playerState;
  256. }
  257. #else
  258. parentPS = &pVeh->m_pParentEntity->client->ps;
  259. if (pVeh->m_pPilot)
  260. {
  261. pilotPS = &pVeh->m_pPilot->client->ps;
  262. }
  263. #endif
  264. // If we're flying, make us accelerate at 40% (about half) acceleration rate, and restore the pitch
  265. // to origin (straight) position (at 5% increments).
  266. if ( pVeh->m_ulFlags & VEH_FLYING )
  267. {
  268. speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier * 0.4f;
  269. }
  270. #ifdef _JK2MP
  271. else if ( !parentPS->m_iVehicleNum )
  272. #else
  273. else if ( !pVeh->m_pVehicleInfo->Inhabited( pVeh ) )
  274. #endif
  275. {//drifts to a stop
  276. speedInc = 0;
  277. //pVeh->m_ucmd.forwardmove = 127;
  278. }
  279. else
  280. {
  281. speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier;
  282. }
  283. speedIdleDec = pVeh->m_pVehicleInfo->decelIdle * pVeh->m_fTimeModifier;
  284. #ifndef _JK2MP//SP
  285. curTime = level.time;
  286. #elif QAGAME//MP GAME
  287. curTime = level.time;
  288. #elif CGAME//MP CGAME
  289. //FIXME: pass in ucmd? Not sure if this is reliable...
  290. curTime = pm->cmd.serverTime;
  291. #endif
  292. if ( (pVeh->m_pPilot /*&& (pilotPS->weapon == WP_NONE || pilotPS->weapon == WP_MELEE )*/ &&
  293. (pVeh->m_ucmd.buttons & BUTTON_ALT_ATTACK) && pVeh->m_pVehicleInfo->turboSpeed)
  294. #ifdef _JK2MP
  295. ||
  296. (parentPS && parentPS->electrifyTime > curTime && pVeh->m_pVehicleInfo->turboSpeed) //make them go!
  297. #endif
  298. )
  299. {
  300. #ifdef _JK2MP
  301. if ( (parentPS && parentPS->electrifyTime > curTime) ||
  302. (pVeh->m_pPilot->playerState &&
  303. (pVeh->m_pPilot->playerState->weapon == WP_MELEE ||
  304. (pVeh->m_pPilot->playerState->weapon == WP_SABER && pVeh->m_pPilot->playerState->saberHolstered))) )
  305. {
  306. #endif
  307. if ((curTime - pVeh->m_iTurboTime)>pVeh->m_pVehicleInfo->turboRecharge)
  308. {
  309. pVeh->m_iTurboTime = (curTime + pVeh->m_pVehicleInfo->turboDuration);
  310. if (pVeh->m_pVehicleInfo->iTurboStartFX)
  311. {
  312. int i;
  313. for (i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
  314. {
  315. #ifndef _JK2MP//SP
  316. // Start The Turbo Fx Start
  317. //--------------------------
  318. G_PlayEffect(pVeh->m_pVehicleInfo->iTurboStartFX, pVeh->m_pParentEntity->playerModel, pVeh->m_iExhaustTag[i], pVeh->m_pParentEntity->s.number, pVeh->m_pParentEntity->currentOrigin );
  319. // Start The Looping Effect
  320. //--------------------------
  321. if (pVeh->m_pVehicleInfo->iTurboFX)
  322. {
  323. G_PlayEffect(pVeh->m_pVehicleInfo->iTurboFX, pVeh->m_pParentEntity->playerModel, pVeh->m_iExhaustTag[i], pVeh->m_pParentEntity->s.number, pVeh->m_pParentEntity->currentOrigin, pVeh->m_pVehicleInfo->turboDuration, qtrue);
  324. }
  325. #else
  326. #ifdef QAGAME
  327. if (pVeh->m_pParentEntity &&
  328. pVeh->m_pParentEntity->ghoul2 &&
  329. pVeh->m_pParentEntity->playerState)
  330. { //fine, I'll use a tempent for this, but only because it's played only once at the start of a turbo.
  331. vec3_t boltOrg, boltDir;
  332. mdxaBone_t boltMatrix;
  333. VectorSet(boltDir, 0.0f, pVeh->m_pParentEntity->playerState->viewangles[YAW], 0.0f);
  334. 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);
  335. BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltOrg);
  336. BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltDir);
  337. G_PlayEffectID(pVeh->m_pVehicleInfo->iTurboStartFX, boltOrg, boltDir);
  338. }
  339. #endif
  340. #endif
  341. }
  342. }
  343. #ifndef _JK2MP //kill me now
  344. if (pVeh->m_pVehicleInfo->soundTurbo)
  345. {
  346. G_SoundIndexOnEnt(pVeh->m_pParentEntity, CHAN_AUTO, pVeh->m_pVehicleInfo->soundTurbo);
  347. }
  348. #endif
  349. parentPS->speed = pVeh->m_pVehicleInfo->turboSpeed; // Instantly Jump To Turbo Speed
  350. }
  351. #ifdef _JK2MP
  352. }
  353. #endif
  354. }
  355. // Slide Breaking
  356. if (pVeh->m_ulFlags&VEH_SLIDEBREAKING)
  357. {
  358. if (pVeh->m_ucmd.forwardmove>=0
  359. #ifndef _JK2MP
  360. || ((level.time - pVeh->m_pParentEntity->lastMoveTime)>500)
  361. #endif
  362. )
  363. {
  364. pVeh->m_ulFlags &= ~VEH_SLIDEBREAKING;
  365. }
  366. parentPS->speed = 0;
  367. }
  368. else if (
  369. (curTime > pVeh->m_iTurboTime) &&
  370. !(pVeh->m_ulFlags&VEH_FLYING) &&
  371. pVeh->m_ucmd.forwardmove<0 &&
  372. fabs(pVeh->m_vOrientation[ROLL])>25.0f)
  373. {
  374. pVeh->m_ulFlags |= VEH_SLIDEBREAKING;
  375. }
  376. if ( curTime < pVeh->m_iTurboTime )
  377. {
  378. speedMax = pVeh->m_pVehicleInfo->turboSpeed;
  379. if (parentPS)
  380. {
  381. parentPS->eFlags |= EF_JETPACK_ACTIVE;
  382. }
  383. }
  384. else
  385. {
  386. speedMax = pVeh->m_pVehicleInfo->speedMax;
  387. if (parentPS)
  388. {
  389. parentPS->eFlags &= ~EF_JETPACK_ACTIVE;
  390. }
  391. }
  392. speedIdle = pVeh->m_pVehicleInfo->speedIdle;
  393. speedIdleAccel = pVeh->m_pVehicleInfo->accelIdle * pVeh->m_fTimeModifier;
  394. speedMin = pVeh->m_pVehicleInfo->speedMin;
  395. // Xbox - yeah, see we have these input devices -- and they're ANALOG! Wow!
  396. if( pVeh->m_ucmd.forwardmove > 0 )
  397. speedMax *= pVeh->m_ucmd.forwardmove / 127.0f;
  398. if ( parentPS->speed || parentPS->groundEntityNum == ENTITYNUM_NONE ||
  399. pVeh->m_ucmd.forwardmove || pVeh->m_ucmd.upmove > 0 )
  400. {
  401. if ( pVeh->m_ucmd.forwardmove > 0 && speedInc )
  402. {
  403. parentPS->speed += speedInc;
  404. }
  405. else if ( pVeh->m_ucmd.forwardmove < 0 )
  406. {
  407. if ( parentPS->speed > speedIdle )
  408. {
  409. parentPS->speed -= speedInc;
  410. }
  411. else if ( parentPS->speed > speedMin )
  412. {
  413. parentPS->speed -= speedIdleDec;
  414. }
  415. }
  416. // No input, so coast to stop.
  417. else if ( parentPS->speed > 0.0f )
  418. {
  419. parentPS->speed -= speedIdleDec;
  420. if ( parentPS->speed < 0.0f )
  421. {
  422. parentPS->speed = 0.0f;
  423. }
  424. }
  425. else if ( parentPS->speed < 0.0f )
  426. {
  427. parentPS->speed += speedIdleDec;
  428. if ( parentPS->speed > 0.0f )
  429. {
  430. parentPS->speed = 0.0f;
  431. }
  432. }
  433. }
  434. else
  435. {
  436. if ( !pVeh->m_pVehicleInfo->strafePerc
  437. #ifdef _JK2MP
  438. || (0 && pVeh->m_pParentEntity->s.number < MAX_CLIENTS) )
  439. #else
  440. || (!g_speederControlScheme->value && !pVeh->m_pParentEntity->s.number) )
  441. #endif
  442. {//if in a strafe-capable vehicle, clear strafing unless using alternate control scheme
  443. //pVeh->m_ucmd.rightmove = 0;
  444. }
  445. }
  446. if ( parentPS->speed > speedMax )
  447. {
  448. parentPS->speed = speedMax;
  449. }
  450. else if ( parentPS->speed < speedMin )
  451. {
  452. parentPS->speed = speedMin;
  453. }
  454. #ifndef _JK2MP
  455. // In SP, The AI Pilots Can Directly Control The Speed Of Their Bike In Order To
  456. // Match The Speed Of The Person They Are Trying To Chase
  457. //-------------------------------------------------------------------------------
  458. if (pVeh->m_pPilot && (pVeh->m_ucmd.buttons&BUTTON_VEH_SPEED))
  459. {
  460. parentPS->speed = pVeh->m_pPilot->client->ps.speed;
  461. }
  462. #endif
  463. /********************************************************************************/
  464. /* END Here is where we move the vehicle (forward or back or whatever). END */
  465. /********************************************************************************/
  466. }
  467. //MP RULE - ALL PROCESSORIENTCOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
  468. //If you really need to violate this rule for SP, then use ifdefs.
  469. //By BG-compatible, I mean no use of game-specific data - ONLY use
  470. //stuff available in the MP bgEntity (in SP, the bgEntity is #defined
  471. //as a gentity, but the MP-compatible access restrictions are based
  472. //on the bgEntity structure in the MP codebase) -rww
  473. //Oh, and please, use "< MAX_CLIENTS" to check for "player" and not
  474. //"!s.number", this is a universal check that will work for both SP
  475. //and MP. -rww
  476. // ProcessOrientCommands the Vehicle.
  477. #ifdef _JK2MP //temp hack til mp speeder controls are sorted -rww
  478. extern void AnimalProcessOri(Vehicle_t *pVeh);
  479. #endif
  480. void ProcessOrientCommands( Vehicle_t *pVeh )
  481. {
  482. /********************************************************************************/
  483. /* BEGIN Here is where make sure the vehicle is properly oriented. BEGIN */
  484. /********************************************************************************/
  485. playerState_t *riderPS;
  486. playerState_t *parentPS;
  487. #ifdef _JK2MP
  488. float angDif;
  489. if (pVeh->m_pPilot)
  490. {
  491. riderPS = pVeh->m_pPilot->playerState;
  492. }
  493. else
  494. {
  495. riderPS = pVeh->m_pParentEntity->playerState;
  496. }
  497. parentPS = pVeh->m_pParentEntity->playerState;
  498. //pVeh->m_vOrientation[YAW] = 0.0f;//riderPS->viewangles[YAW];
  499. angDif = AngleSubtract(pVeh->m_vOrientation[YAW], riderPS->viewangles[YAW]);
  500. if (parentPS && parentPS->speed)
  501. {
  502. float s = parentPS->speed;
  503. float maxDif = pVeh->m_pVehicleInfo->turningSpeed*4.0f; //magic number hackery
  504. if (s < 0.0f)
  505. {
  506. s = -s;
  507. }
  508. angDif *= s/pVeh->m_pVehicleInfo->speedMax;
  509. if (angDif > maxDif)
  510. {
  511. angDif = maxDif;
  512. }
  513. else if (angDif < -maxDif)
  514. {
  515. angDif = -maxDif;
  516. }
  517. pVeh->m_vOrientation[YAW] = AngleNormalize180(pVeh->m_vOrientation[YAW] - angDif*(pVeh->m_fTimeModifier*0.2f));
  518. if (parentPS->electrifyTime > pm->cmd.serverTime)
  519. { //do some crazy stuff
  520. pVeh->m_vOrientation[YAW] += (sin(pm->cmd.serverTime/1000.0f)*3.0f)*pVeh->m_fTimeModifier;
  521. }
  522. }
  523. #else
  524. gentity_t *rider = pVeh->m_pParentEntity->owner;
  525. if ( !rider || !rider->client )
  526. {
  527. riderPS = &pVeh->m_pParentEntity->client->ps;
  528. }
  529. else
  530. {
  531. riderPS = &rider->client->ps;
  532. }
  533. parentPS = &pVeh->m_pParentEntity->client->ps;
  534. if (pVeh->m_ulFlags & VEH_FLYING)
  535. {
  536. pVeh->m_vOrientation[YAW] += pVeh->m_vAngularVelocity;
  537. }
  538. else if (
  539. (pVeh->m_ulFlags & VEH_SLIDEBREAKING) || // No Angles Control While Out Of Control
  540. (pVeh->m_ulFlags & VEH_OUTOFCONTROL) // No Angles Control While Out Of Control
  541. )
  542. {
  543. // Any ability to change orientation?
  544. }
  545. else if (
  546. (pVeh->m_ulFlags & VEH_STRAFERAM) // No Angles Control While Strafe Ramming
  547. )
  548. {
  549. if (pVeh->m_fStrafeTime>0)
  550. {
  551. pVeh->m_fStrafeTime--;
  552. pVeh->m_vOrientation[ROLL] += (pVeh->m_fStrafeTime<( STRAFERAM_DURATION/2))?(-STRAFERAM_ANGLE):( STRAFERAM_ANGLE);
  553. }
  554. else if (pVeh->m_fStrafeTime<0)
  555. {
  556. pVeh->m_fStrafeTime++;
  557. pVeh->m_vOrientation[ROLL] += (pVeh->m_fStrafeTime>(-STRAFERAM_DURATION/2))?( STRAFERAM_ANGLE):(-STRAFERAM_ANGLE);
  558. }
  559. }
  560. else
  561. {
  562. pVeh->m_vOrientation[YAW] = riderPS->viewangles[YAW];
  563. }
  564. #endif
  565. /********************************************************************************/
  566. /* END Here is where make sure the vehicle is properly oriented. END */
  567. /********************************************************************************/
  568. }
  569. #ifdef QAGAME
  570. extern void PM_SetAnim(pmove_t *pm,int setAnimParts,int anim,int setAnimFlags, int blendTime);
  571. extern int PM_AnimLength( int index, animNumber_t anim );
  572. // This function makes sure that the vehicle is properly animated.
  573. void AnimateVehicle( Vehicle_t *pVeh )
  574. {
  575. }
  576. #endif //QAGAME
  577. //rest of file is shared
  578. #ifndef _JK2MP
  579. extern void CG_ChangeWeapon( int num );
  580. #endif
  581. #ifndef _JK2MP
  582. extern void G_StartMatrixEffect( gentity_t *ent, int meFlags = 0, int length = 1000, float timeScale = 0.0f, int spinTime = 0 );
  583. #endif
  584. //NOTE NOTE NOTE NOTE NOTE NOTE
  585. //I want to keep this function BG too, because it's fairly generic already, and it
  586. //would be nice to have proper prediction of animations. -rww
  587. // This function makes sure that the rider's in this vehicle are properly animated.
  588. void AnimateRiders( Vehicle_t *pVeh )
  589. {
  590. animNumber_t Anim = BOTH_VS_IDLE;
  591. float fSpeedPercToMax;
  592. int iFlags = SETANIM_FLAG_NORMAL, iBlend = 300;
  593. playerState_t *pilotPS;
  594. playerState_t *parentPS;
  595. int curTime;
  596. // Boarding animation.
  597. if ( pVeh->m_iBoarding != 0 )
  598. {
  599. // We've just started moarding, set the amount of time it will take to finish moarding.
  600. if ( pVeh->m_iBoarding < 0 )
  601. {
  602. int iAnimLen;
  603. // Boarding from left...
  604. if ( pVeh->m_iBoarding == -1 )
  605. {
  606. Anim = BOTH_VS_MOUNT_L;
  607. }
  608. else if ( pVeh->m_iBoarding == -2 )
  609. {
  610. Anim = BOTH_VS_MOUNT_R;
  611. }
  612. else if ( pVeh->m_iBoarding == -3 )
  613. {
  614. Anim = BOTH_VS_MOUNTJUMP_L;
  615. }
  616. else if ( pVeh->m_iBoarding == VEH_MOUNT_THROW_LEFT)
  617. {
  618. iBlend = 0;
  619. Anim = BOTH_VS_MOUNTTHROW_R;
  620. }
  621. else if ( pVeh->m_iBoarding == VEH_MOUNT_THROW_RIGHT)
  622. {
  623. iBlend = 0;
  624. Anim = BOTH_VS_MOUNTTHROW_L;
  625. }
  626. // Set the delay time (which happens to be the time it takes for the animation to complete).
  627. // NOTE: Here I made it so the delay is actually 40% (0.4f) of the animation time.
  628. #ifdef _JK2MP
  629. iAnimLen = BG_AnimLength( pVeh->m_pPilot->localAnimIndex, Anim ) * 0.4f;
  630. pVeh->m_iBoarding = BG_GetTime() + iAnimLen;
  631. #else
  632. iAnimLen = PM_AnimLength( pVeh->m_pPilot->client->clientInfo.animFileIndex, Anim );// * 0.4f;
  633. if (pVeh->m_iBoarding!=VEH_MOUNT_THROW_LEFT && pVeh->m_iBoarding!=VEH_MOUNT_THROW_RIGHT)
  634. {
  635. pVeh->m_iBoarding = level.time + (iAnimLen*0.4f);
  636. }
  637. else
  638. {
  639. pVeh->m_iBoarding = level.time + iAnimLen;
  640. }
  641. #endif
  642. // Set the animation, which won't be interrupted until it's completed.
  643. // TODO: But what if he's killed? Should the animation remain persistant???
  644. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
  645. #ifdef _JK2MP
  646. BG_SetAnim(pVeh->m_pPilot->playerState, bgAllAnims[pVeh->m_pPilot->localAnimIndex].anims,
  647. SETANIM_BOTH, Anim, iFlags, iBlend);
  648. #else
  649. NPC_SetAnim( pVeh->m_pPilot, SETANIM_BOTH, Anim, iFlags, iBlend );
  650. if (pVeh->m_pOldPilot)
  651. {
  652. iAnimLen = PM_AnimLength( pVeh->m_pPilot->client->clientInfo.animFileIndex, BOTH_VS_MOUNTTHROWEE);
  653. NPC_SetAnim( pVeh->m_pOldPilot, SETANIM_BOTH, BOTH_VS_MOUNTTHROWEE, iFlags, iBlend );
  654. }
  655. #endif
  656. }
  657. #ifndef _JK2MP
  658. if (pVeh->m_pOldPilot && pVeh->m_pOldPilot->client->ps.torsoAnimTimer<=0)
  659. {
  660. if (Q_irand(0, player->count)==0)
  661. {
  662. player->count++;
  663. player->lastEnemy = pVeh->m_pOldPilot;
  664. G_StartMatrixEffect(player, MEF_LOOK_AT_ENEMY|MEF_NO_RANGEVAR|MEF_NO_VERTBOB|MEF_NO_SPIN, 1000);
  665. }
  666. gentity_t* oldPilot = pVeh->m_pOldPilot;
  667. pVeh->m_pVehicleInfo->Eject(pVeh, pVeh->m_pOldPilot, qtrue); // will set pointer to zero
  668. // Kill Him
  669. //----------
  670. oldPilot->client->noRagTime = -1; // no ragdoll for you
  671. G_Damage(oldPilot, pVeh->m_pPilot, pVeh->m_pPilot, pVeh->m_pPilot->currentAngles, pVeh->m_pPilot->currentOrigin, 1000, 0, MOD_CRUSH);
  672. // Compute THe Throw Direction As Backwards From The Vehicle's Velocity
  673. //----------------------------------------------------------------------
  674. vec3_t throwDir;
  675. VectorScale(pVeh->m_pParentEntity->client->ps.velocity, -1.0f, throwDir);
  676. VectorNormalize(throwDir);
  677. throwDir[2] += 0.3f; // up a little
  678. // Now Throw Him Out
  679. //-------------------
  680. G_Throw(oldPilot, throwDir, VectorLength(pVeh->m_pParentEntity->client->ps.velocity)/10.0f);
  681. NPC_SetAnim(oldPilot, SETANIM_BOTH, BOTH_DEATHBACKWARD1, SETANIM_FLAG_OVERRIDE, iBlend );
  682. }
  683. #endif
  684. return;
  685. }
  686. #ifdef _JK2MP //fixme
  687. if (1) return;
  688. #endif
  689. #ifdef _JK2MP
  690. pilotPS = pVeh->m_pPilot->playerState;
  691. parentPS = pVeh->m_pPilot->playerState;
  692. #else
  693. pilotPS = &pVeh->m_pPilot->client->ps;
  694. parentPS = &pVeh->m_pParentEntity->client->ps;
  695. #endif
  696. #ifndef _JK2MP//SP
  697. curTime = level.time;
  698. #elif QAGAME//MP GAME
  699. curTime = level.time;
  700. #elif CGAME//MP CGAME
  701. //FIXME: pass in ucmd? Not sure if this is reliable...
  702. curTime = pm->cmd.serverTime;
  703. #endif
  704. // Percentage of maximum speed relative to current speed.
  705. fSpeedPercToMax = parentPS->speed / pVeh->m_pVehicleInfo->speedMax;
  706. /* // Going in reverse...
  707. #ifdef _JK2MP
  708. if ( pVeh->m_ucmd.forwardmove < 0 && !(pVeh->m_ulFlags & VEH_SLIDEBREAKING))
  709. #else
  710. if ( fSpeedPercToMax < -0.018f && !(pVeh->m_ulFlags & VEH_SLIDEBREAKING))
  711. #endif
  712. {
  713. Anim = BOTH_VS_REV;
  714. iBlend = 500;
  715. bool HasWeapon = ((pilotPS->weapon != WP_NONE) && (pilotPS->weapon != WP_MELEE));
  716. if (HasWeapon)
  717. {
  718. if (pVeh->m_pPilot->s.number<MAX_CLIENTS)
  719. {
  720. CG_ChangeWeapon(WP_NONE);
  721. }
  722. pVeh->m_pPilot->client->ps.weapon = WP_NONE;
  723. G_RemoveWeaponModels(pVeh->m_pPilot);
  724. }
  725. }
  726. else
  727. */
  728. {
  729. bool HasWeapon = ((pilotPS->weapon != WP_NONE) && (pilotPS->weapon != WP_MELEE));
  730. bool Attacking = (HasWeapon && !!(pVeh->m_ucmd.buttons&BUTTON_ATTACK));
  731. #ifdef _JK2MP //fixme: flying tends to spaz out a lot
  732. bool Flying = false;
  733. bool Crashing = false;
  734. #else
  735. bool Flying = !!(pVeh->m_ulFlags & VEH_FLYING);
  736. bool Crashing = !!(pVeh->m_ulFlags & VEH_CRASHING);
  737. #endif
  738. bool Right = (pVeh->m_ucmd.rightmove>0);
  739. bool Left = (pVeh->m_ucmd.rightmove<0);
  740. bool Turbo = (curTime<pVeh->m_iTurboTime);
  741. EWeaponPose WeaponPose = WPOSE_NONE;
  742. // Remove Crashing Flag
  743. //----------------------
  744. pVeh->m_ulFlags &= ~VEH_CRASHING;
  745. // Put Away Saber When It Is Not Active
  746. //--------------------------------------
  747. #ifndef _JK2MP
  748. if (HasWeapon &&
  749. (pVeh->m_pPilot->s.number>=MAX_CLIENTS || (cg.weaponSelectTime+500)<cg.time) &&
  750. (Turbo || (pilotPS->weapon==WP_SABER && !pilotPS->SaberActive())))
  751. {
  752. if (pVeh->m_pPilot->s.number<MAX_CLIENTS)
  753. {
  754. pVeh->m_pPilot->client->ps.stats[ STAT_WEAPONS ] |= 1; // Riding means you get WP_NONE
  755. CG_ChangeWeapon(WP_NONE);
  756. }
  757. pVeh->m_pPilot->client->ps.weapon = WP_NONE;
  758. G_RemoveWeaponModels(pVeh->m_pPilot);
  759. }
  760. #endif
  761. // Don't Interrupt Attack Anims
  762. //------------------------------
  763. #ifdef _JK2MP
  764. if (pilotPS->weaponTime>0)
  765. {
  766. return;
  767. }
  768. #else
  769. if (pilotPS->torsoAnim>=BOTH_VS_ATL_S && pilotPS->torsoAnim<=BOTH_VS_ATF_G)
  770. {
  771. float bodyCurrent = 0.0f;
  772. int bodyEnd = 0;
  773. if (!!gi.G2API_GetBoneAnimIndex(&pVeh->m_pPilot->ghoul2[pVeh->m_pPilot->playerModel], pVeh->m_pPilot->rootBone, level.time, &bodyCurrent, NULL, &bodyEnd, NULL, NULL, NULL))
  774. {
  775. if (bodyCurrent<=((float)(bodyEnd)-1.5f))
  776. {
  777. return;
  778. }
  779. }
  780. }
  781. #endif
  782. // Compute The Weapon Pose
  783. //--------------------------
  784. if (pilotPS->weapon==WP_BLASTER)
  785. {
  786. WeaponPose = WPOSE_BLASTER;
  787. }
  788. else if (pilotPS->weapon==WP_SABER)
  789. {
  790. if ( (pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VS_ATL_TO_R_S)
  791. {
  792. pVeh->m_ulFlags &= ~VEH_SABERINLEFTHAND;
  793. }
  794. if (!(pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VS_ATR_TO_L_S)
  795. {
  796. pVeh->m_ulFlags |= VEH_SABERINLEFTHAND;
  797. }
  798. WeaponPose = (pVeh->m_ulFlags&VEH_SABERINLEFTHAND)?(WPOSE_SABERLEFT):(WPOSE_SABERRIGHT);
  799. }
  800. if (Attacking && WeaponPose)
  801. {// Attack!
  802. iBlend = 100;
  803. iFlags = SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART;
  804. // Auto Aiming
  805. //===============================================
  806. if (!Left && !Right) // Allow player strafe keys to override
  807. {
  808. #ifndef _JK2MP
  809. if (pVeh->m_pPilot->enemy)
  810. {
  811. vec3_t toEnemy;
  812. float toEnemyDistance;
  813. vec3_t actorRight;
  814. float actorRightDot;
  815. VectorSubtract(pVeh->m_pPilot->currentOrigin, pVeh->m_pPilot->enemy->currentOrigin, toEnemy);
  816. toEnemyDistance = VectorNormalize(toEnemy);
  817. AngleVectors(pVeh->m_pParentEntity->currentAngles, 0, actorRight, 0);
  818. actorRightDot = DotProduct(toEnemy, actorRight);
  819. if (fabsf(actorRightDot)>0.5f || pilotPS->weapon==WP_SABER)
  820. {
  821. Left = (actorRightDot>0.0f);
  822. Right = !Left;
  823. }
  824. else
  825. {
  826. Right = Left = false;
  827. }
  828. }
  829. else
  830. #endif
  831. if (pilotPS->weapon==WP_SABER && !Left && !Right)
  832. {
  833. Left = (WeaponPose==WPOSE_SABERLEFT);
  834. Right = !Left;
  835. }
  836. }
  837. if (Left)
  838. {// Attack Left
  839. switch(WeaponPose)
  840. {
  841. case WPOSE_BLASTER: Anim = BOTH_VS_ATL_G; break;
  842. case WPOSE_SABERLEFT: Anim = BOTH_VS_ATL_S; break;
  843. case WPOSE_SABERRIGHT: Anim = BOTH_VS_ATR_TO_L_S; break;
  844. default: assert(0);
  845. }
  846. }
  847. else if (Right)
  848. {// Attack Right
  849. switch(WeaponPose)
  850. {
  851. case WPOSE_BLASTER: Anim = BOTH_VS_ATR_G; break;
  852. case WPOSE_SABERLEFT: Anim = BOTH_VS_ATL_TO_R_S; break;
  853. case WPOSE_SABERRIGHT: Anim = BOTH_VS_ATR_S; break;
  854. default: assert(0);
  855. }
  856. }
  857. else
  858. {// Attack Ahead
  859. switch(WeaponPose)
  860. {
  861. case WPOSE_BLASTER: Anim = BOTH_VS_ATF_G; break;
  862. default: assert(0);
  863. }
  864. }
  865. }
  866. else if (Left && pVeh->m_ucmd.buttons&BUTTON_USE)
  867. {// Look To The Left Behind
  868. iBlend = 400;
  869. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
  870. switch(WeaponPose)
  871. {
  872. case WPOSE_SABERLEFT: Anim = BOTH_VS_IDLE_SL; break;
  873. case WPOSE_SABERRIGHT: Anim = BOTH_VS_IDLE_SR; break;
  874. default: Anim = BOTH_VS_LOOKLEFT;
  875. }
  876. }
  877. else if (Right && pVeh->m_ucmd.buttons&BUTTON_USE)
  878. {// Look To The Right Behind
  879. iBlend = 400;
  880. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
  881. switch(WeaponPose)
  882. {
  883. case WPOSE_SABERLEFT: Anim = BOTH_VS_IDLE_SL; break;
  884. case WPOSE_SABERRIGHT: Anim = BOTH_VS_IDLE_SR; break;
  885. default: Anim = BOTH_VS_LOOKRIGHT;
  886. }
  887. }
  888. else if (Turbo)
  889. {// Kicked In Turbo
  890. iBlend = 50;
  891. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
  892. Anim = BOTH_VS_TURBO;
  893. }
  894. else if (Flying)
  895. {// Off the ground in a jump
  896. iBlend = 800;
  897. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
  898. switch(WeaponPose)
  899. {
  900. case WPOSE_NONE: Anim = BOTH_VS_AIR; break;
  901. case WPOSE_BLASTER: Anim = BOTH_VS_AIR_G; break;
  902. case WPOSE_SABERLEFT: Anim = BOTH_VS_AIR_SL; break;
  903. case WPOSE_SABERRIGHT: Anim = BOTH_VS_AIR_SR; break;
  904. default: assert(0);
  905. }
  906. }
  907. else if (Crashing)
  908. {// Hit the ground!
  909. iBlend = 100;
  910. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
  911. switch(WeaponPose)
  912. {
  913. case WPOSE_NONE: Anim = BOTH_VS_LAND; break;
  914. case WPOSE_BLASTER: Anim = BOTH_VS_LAND_G; break;
  915. case WPOSE_SABERLEFT: Anim = BOTH_VS_LAND_SL; break;
  916. case WPOSE_SABERRIGHT: Anim = BOTH_VS_LAND_SR; break;
  917. default: assert(0);
  918. }
  919. }
  920. else
  921. {// No Special Moves
  922. iBlend = 300;
  923. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
  924. if (pVeh->m_vOrientation[ROLL] <= -20)
  925. {// Lean Left
  926. switch(WeaponPose)
  927. {
  928. case WPOSE_NONE: Anim = BOTH_VS_LEANL; break;
  929. case WPOSE_BLASTER: Anim = BOTH_VS_LEANL_G; break;
  930. case WPOSE_SABERLEFT: Anim = BOTH_VS_LEANL_SL; break;
  931. case WPOSE_SABERRIGHT: Anim = BOTH_VS_LEANL_SR; break;
  932. default: assert(0);
  933. }
  934. }
  935. else if (pVeh->m_vOrientation[ROLL] >= 20)
  936. {// Lean Right
  937. switch(WeaponPose)
  938. {
  939. case WPOSE_NONE: Anim = BOTH_VS_LEANR; break;
  940. case WPOSE_BLASTER: Anim = BOTH_VS_LEANR_G; break;
  941. case WPOSE_SABERLEFT: Anim = BOTH_VS_LEANR_SL; break;
  942. case WPOSE_SABERRIGHT: Anim = BOTH_VS_LEANR_SR; break;
  943. default: assert(0);
  944. }
  945. }
  946. else
  947. {// No Lean
  948. switch(WeaponPose)
  949. {
  950. case WPOSE_NONE: Anim = BOTH_VS_IDLE; break;
  951. case WPOSE_BLASTER: Anim = BOTH_VS_IDLE_G; break;
  952. case WPOSE_SABERLEFT: Anim = BOTH_VS_IDLE_SL; break;
  953. case WPOSE_SABERRIGHT: Anim = BOTH_VS_IDLE_SR; break;
  954. default: assert(0);
  955. }
  956. }
  957. }// No Special Moves
  958. }// Going backwards?
  959. #ifdef _JK2MP
  960. iFlags &= ~SETANIM_FLAG_OVERRIDE;
  961. if (pVeh->m_pPilot->playerState->torsoAnim == Anim)
  962. {
  963. pVeh->m_pPilot->playerState->torsoTimer = BG_AnimLength(pVeh->m_pPilot->localAnimIndex, Anim);
  964. }
  965. if (pVeh->m_pPilot->playerState->legsAnim == Anim)
  966. {
  967. pVeh->m_pPilot->playerState->legsTimer = BG_AnimLength(pVeh->m_pPilot->localAnimIndex, Anim);
  968. }
  969. BG_SetAnim(pVeh->m_pPilot->playerState, bgAllAnims[pVeh->m_pPilot->localAnimIndex].anims,
  970. SETANIM_BOTH, Anim, iFlags|SETANIM_FLAG_HOLD, iBlend);
  971. #else
  972. NPC_SetAnim( pVeh->m_pPilot, SETANIM_BOTH, Anim, iFlags, iBlend );
  973. #endif
  974. }
  975. #ifndef QAGAME
  976. void AttachRidersGeneric( Vehicle_t *pVeh );
  977. #endif
  978. void G_SetSpeederVehicleFunctions( vehicleInfo_t *pVehInfo )
  979. {
  980. #ifdef QAGAME
  981. pVehInfo->AnimateVehicle = AnimateVehicle;
  982. pVehInfo->AnimateRiders = AnimateRiders;
  983. // pVehInfo->ValidateBoard = ValidateBoard;
  984. // pVehInfo->SetParent = SetParent;
  985. // pVehInfo->SetPilot = SetPilot;
  986. // pVehInfo->AddPassenger = AddPassenger;
  987. // pVehInfo->Animate = Animate;
  988. // pVehInfo->Board = Board;
  989. // pVehInfo->Eject = Eject;
  990. // pVehInfo->EjectAll = EjectAll;
  991. // pVehInfo->StartDeathDelay = StartDeathDelay;
  992. // pVehInfo->DeathUpdate = DeathUpdate;
  993. // pVehInfo->RegisterAssets = RegisterAssets;
  994. // pVehInfo->Initialize = Initialize;
  995. pVehInfo->Update = Update;
  996. // pVehInfo->UpdateRider = UpdateRider;
  997. #endif
  998. //shared
  999. pVehInfo->ProcessMoveCommands = ProcessMoveCommands;
  1000. pVehInfo->ProcessOrientCommands = ProcessOrientCommands;
  1001. #ifndef QAGAME //cgame prediction attachment func
  1002. pVehInfo->AttachRiders = AttachRidersGeneric;
  1003. #endif
  1004. // pVehInfo->AttachRiders = AttachRiders;
  1005. // pVehInfo->Ghost = Ghost;
  1006. // pVehInfo->UnGhost = UnGhost;
  1007. // pVehInfo->Inhabited = Inhabited;
  1008. }
  1009. // Following is only in game, not in namespace
  1010. #ifdef _JK2MP
  1011. #include "../namespace_end.h"
  1012. #endif
  1013. #ifdef QAGAME
  1014. extern void G_AllocateVehicleObject(Vehicle_t **pVeh);
  1015. #endif
  1016. #ifdef _JK2MP
  1017. #include "../namespace_begin.h"
  1018. #endif
  1019. extern char current_speeders;
  1020. // Create/Allocate a new Animal Vehicle (initializing it as well).
  1021. void G_CreateSpeederNPC( Vehicle_t **pVeh, const char *strType )
  1022. {
  1023. current_speeders++;
  1024. #ifdef _JK2MP
  1025. #ifdef QAGAME
  1026. //these will remain on entities on the client once allocated because the pointer is
  1027. //never stomped. on the server, however, when an ent is freed, the entity struct is
  1028. //memset to 0, so this memory would be lost..
  1029. G_AllocateVehicleObject(pVeh);
  1030. #else
  1031. if (!*pVeh)
  1032. { //only allocate a new one if we really have to
  1033. (*pVeh) = (Vehicle_t *) BG_Alloc( sizeof(Vehicle_t) );
  1034. }
  1035. #endif
  1036. memset(*pVeh, 0, sizeof(Vehicle_t));
  1037. (*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strType )];
  1038. #else
  1039. // Allocate the Vehicle.
  1040. (*pVeh) = (Vehicle_t *) gi.Malloc( sizeof(Vehicle_t), TAG_G_ALLOC, qtrue );
  1041. (*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strType )];
  1042. #endif
  1043. (*pVeh)->alreadyCleaned = false;
  1044. }
  1045. #ifdef _JK2MP
  1046. #include "../namespace_end.h"
  1047. //get rid of all the crazy defs we added for this file
  1048. #undef currentAngles
  1049. #undef currentOrigin
  1050. #undef mins
  1051. #undef maxs
  1052. #undef legsAnimTimer
  1053. #undef torsoAnimTimer
  1054. #undef bool
  1055. #undef false
  1056. #undef true
  1057. #undef sqrtf
  1058. #undef Q_flrand
  1059. #undef MOD_EXPLOSIVE
  1060. #endif