WalkerNPC.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  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. #else
  40. #include "bg_vehicles.h"
  41. #endif
  42. #ifdef _JK2MP
  43. //this is really horrible, but it works! just be sure not to use any locals or anything
  44. //with these names (exluding bool, false, true). -rww
  45. #define currentAngles r.currentAngles
  46. #define currentOrigin r.currentOrigin
  47. #define mins r.mins
  48. #define maxs r.maxs
  49. #define legsAnimTimer legsTimer
  50. #define torsoAnimTimer torsoTimer
  51. #define bool qboolean
  52. #define false qfalse
  53. #define true qtrue
  54. #define sqrtf sqrt
  55. #define Q_flrand flrand
  56. #define MOD_EXPLOSIVE MOD_SUICIDE
  57. #else
  58. #define bgEntity_t gentity_t
  59. #endif
  60. #ifdef QAGAME //we only want a few of these functions for BG
  61. extern float DotToSpot( vec3_t spot, vec3_t from, vec3_t fromAngles );
  62. extern vmCvar_t cg_thirdPersonAlpha;
  63. extern vec3_t playerMins;
  64. extern vec3_t playerMaxs;
  65. extern cvar_t *g_speederControlScheme;
  66. extern void PM_SetAnim(pmove_t *pm,int setAnimParts,int anim,int setAnimFlags, int blendTime);
  67. extern int PM_AnimLength( int index, animNumber_t anim );
  68. extern void Vehicle_SetAnim(gentity_t *ent,int setAnimParts,int anim,int setAnimFlags, int iBlend);
  69. extern void G_Knockdown( gentity_t *self, gentity_t *attacker, const vec3_t pushDir, float strength, qboolean breakSaberLock );
  70. extern void G_VehicleTrace( trace_t *results, const vec3_t start, const vec3_t tMins, const vec3_t tMaxs, const vec3_t end, int passEntityNum, int contentmask );
  71. static void RegisterAssets( Vehicle_t *pVeh )
  72. {
  73. //atst uses turret weapon
  74. #ifdef _JK2MP
  75. RegisterItem(BG_FindItemForWeapon(WP_TURRET));
  76. #else
  77. // PUT SOMETHING HERE...
  78. #endif
  79. //call the standard RegisterAssets now
  80. g_vehicleInfo[VEHICLE_BASE].RegisterAssets( pVeh );
  81. }
  82. // Like a think or move command, this updates various vehicle properties.
  83. /*
  84. static bool Update( Vehicle_t *pVeh, const usercmd_t *pUcmd )
  85. {
  86. return g_vehicleInfo[VEHICLE_BASE].Update( pVeh, pUcmd );
  87. }
  88. */
  89. // Board this Vehicle (get on). The first entity to board an empty vehicle becomes the Pilot.
  90. static bool Board( Vehicle_t *pVeh, bgEntity_t *pEnt )
  91. {
  92. if ( !g_vehicleInfo[VEHICLE_BASE].Board( pVeh, pEnt ) )
  93. return false;
  94. // Set the board wait time (they won't be able to do anything, including getting off, for this amount of time).
  95. pVeh->m_iBoarding = level.time + 1500;
  96. return true;
  97. }
  98. #endif //QAGAME
  99. #ifdef _JK2MP
  100. #include "../namespace_begin.h"
  101. #endif
  102. //MP RULE - ALL PROCESSMOVECOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
  103. //If you really need to violate this rule for SP, then use ifdefs.
  104. //By BG-compatible, I mean no use of game-specific data - ONLY use
  105. //stuff available in the MP bgEntity (in SP, the bgEntity is #defined
  106. //as a gentity, but the MP-compatible access restrictions are based
  107. //on the bgEntity structure in the MP codebase) -rww
  108. // ProcessMoveCommands the Vehicle.
  109. static void ProcessMoveCommands( Vehicle_t *pVeh )
  110. {
  111. /************************************************************************************/
  112. /* BEGIN Here is where we move the vehicle (forward or back or whatever). BEGIN */
  113. /************************************************************************************/
  114. //Client sets ucmds and such for speed alterations
  115. float speedInc, speedIdleDec, speedIdle, speedIdleAccel, speedMin, speedMax;
  116. float fWalkSpeedMax;
  117. bgEntity_t *parent = pVeh->m_pParentEntity;
  118. #ifdef _JK2MP
  119. playerState_t *parentPS = parent->playerState;
  120. #else
  121. playerState_t *parentPS = &parent->client->ps;
  122. #endif
  123. speedIdleDec = pVeh->m_pVehicleInfo->decelIdle * pVeh->m_fTimeModifier;
  124. speedMax = pVeh->m_pVehicleInfo->speedMax;
  125. speedIdle = pVeh->m_pVehicleInfo->speedIdle;
  126. speedIdleAccel = pVeh->m_pVehicleInfo->accelIdle * pVeh->m_fTimeModifier;
  127. speedMin = pVeh->m_pVehicleInfo->speedMin;
  128. #ifdef _JK2MP
  129. if ( !parentPS->m_iVehicleNum )
  130. #else
  131. if ( !pVeh->m_pVehicleInfo->Inhabited( pVeh ) )
  132. #endif
  133. {//drifts to a stop
  134. speedInc = speedIdle * pVeh->m_fTimeModifier;
  135. VectorClear( parentPS->moveDir );
  136. //m_ucmd.forwardmove = 127;
  137. parentPS->speed = 0;
  138. }
  139. else
  140. {
  141. speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier;
  142. }
  143. if ( parentPS->speed || parentPS->groundEntityNum == ENTITYNUM_NONE ||
  144. pVeh->m_ucmd.forwardmove || pVeh->m_ucmd.upmove > 0 )
  145. {
  146. if ( pVeh->m_ucmd.forwardmove > 0 && speedInc )
  147. {
  148. parentPS->speed += speedInc;
  149. }
  150. else if ( pVeh->m_ucmd.forwardmove < 0 )
  151. {
  152. if ( parentPS->speed > speedIdle )
  153. {
  154. parentPS->speed -= speedInc;
  155. }
  156. else if ( parentPS->speed > speedMin )
  157. {
  158. parentPS->speed -= speedIdleDec;
  159. }
  160. }
  161. // No input, so coast to stop.
  162. else if ( parentPS->speed > 0.0f )
  163. {
  164. parentPS->speed -= speedIdleDec;
  165. if ( parentPS->speed < 0.0f )
  166. {
  167. parentPS->speed = 0.0f;
  168. }
  169. }
  170. else if ( parentPS->speed < 0.0f )
  171. {
  172. parentPS->speed += speedIdleDec;
  173. if ( parentPS->speed > 0.0f )
  174. {
  175. parentPS->speed = 0.0f;
  176. }
  177. }
  178. }
  179. else
  180. {
  181. if ( pVeh->m_ucmd.forwardmove < 0 )
  182. {
  183. pVeh->m_ucmd.forwardmove = 0;
  184. }
  185. if ( pVeh->m_ucmd.upmove < 0 )
  186. {
  187. pVeh->m_ucmd.upmove = 0;
  188. }
  189. pVeh->m_ucmd.rightmove = 0;
  190. /*if ( !pVeh->m_pVehicleInfo->strafePerc
  191. || (!g_speederControlScheme->value && !parent->s.number) )
  192. {//if in a strafe-capable vehicle, clear strafing unless using alternate control scheme
  193. pVeh->m_ucmd.rightmove = 0;
  194. }*/
  195. }
  196. fWalkSpeedMax = speedMax * 0.275f;
  197. if ( pVeh->m_ucmd.buttons & BUTTON_WALKING && parentPS->speed > fWalkSpeedMax )
  198. {
  199. parentPS->speed = fWalkSpeedMax;
  200. }
  201. else if ( parentPS->speed > speedMax )
  202. {
  203. parentPS->speed = speedMax;
  204. }
  205. else if ( parentPS->speed < speedMin )
  206. {
  207. parentPS->speed = speedMin;
  208. }
  209. /********************************************************************************/
  210. /* END Here is where we move the vehicle (forward or back or whatever). END */
  211. /********************************************************************************/
  212. }
  213. #ifdef _JK2MP
  214. extern void FighterYawAdjust(Vehicle_t *pVeh, playerState_t *riderPS, playerState_t *parentPS); //FighterNPC.c
  215. extern void FighterPitchAdjust(Vehicle_t *pVeh, playerState_t *riderPS, playerState_t *parentPS); //FighterNPC.c
  216. #endif
  217. //MP RULE - ALL PROCESSORIENTCOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
  218. //If you really need to violate this rule for SP, then use ifdefs.
  219. //By BG-compatible, I mean no use of game-specific data - ONLY use
  220. //stuff available in the MP bgEntity (in SP, the bgEntity is #defined
  221. //as a gentity, but the MP-compatible access restrictions are based
  222. //on the bgEntity structure in the MP codebase) -rww
  223. // ProcessOrientCommands the Vehicle.
  224. static void ProcessOrientCommands( Vehicle_t *pVeh )
  225. {
  226. /********************************************************************************/
  227. /* BEGIN Here is where make sure the vehicle is properly oriented. BEGIN */
  228. /********************************************************************************/
  229. float speed;
  230. bgEntity_t *parent = pVeh->m_pParentEntity;
  231. playerState_t *parentPS, *riderPS;
  232. #ifdef _JK2MP
  233. bgEntity_t *rider = NULL;
  234. if (parent->s.owner != ENTITYNUM_NONE)
  235. {
  236. rider = PM_BGEntForNum(parent->s.owner); //&g_entities[parent->r.ownerNum];
  237. }
  238. #else
  239. gentity_t *rider = parent->owner;
  240. #endif
  241. #ifdef _JK2MP
  242. if ( !rider )
  243. #else
  244. if ( !rider || !rider->client )
  245. #endif
  246. {
  247. rider = parent;
  248. }
  249. #ifdef _JK2MP
  250. parentPS = parent->playerState;
  251. riderPS = rider->playerState;
  252. #else
  253. parentPS = &parent->client->ps;
  254. riderPS = &rider->client->ps;
  255. #endif
  256. speed = VectorLength( parentPS->velocity );
  257. // If the player is the rider...
  258. if ( rider->s.number < MAX_CLIENTS )
  259. {//FIXME: use the vehicle's turning stat in this calc
  260. #ifdef _JK2MP
  261. FighterYawAdjust(pVeh, riderPS, parentPS);
  262. //FighterPitchAdjust(pVeh, riderPS, parentPS);
  263. pVeh->m_vOrientation[PITCH] = riderPS->viewangles[PITCH];
  264. #else
  265. pVeh->m_vOrientation[YAW] = riderPS->viewangles[YAW];
  266. pVeh->m_vOrientation[PITCH] = riderPS->viewangles[PITCH];
  267. #endif
  268. }
  269. else
  270. {
  271. float turnSpeed = pVeh->m_pVehicleInfo->turningSpeed;
  272. if ( !pVeh->m_pVehicleInfo->turnWhenStopped
  273. && !parentPS->speed )//FIXME: or !pVeh->m_ucmd.forwardmove?
  274. {//can't turn when not moving
  275. //FIXME: or ramp up to max turnSpeed?
  276. turnSpeed = 0.0f;
  277. }
  278. #ifdef _JK2MP
  279. if (rider->s.eType == ET_NPC)
  280. #else
  281. if ( !rider || rider->NPC )
  282. #endif
  283. {//help NPCs out some
  284. turnSpeed *= 2.0f;
  285. #ifdef _JK2MP
  286. if (parentPS->speed > 200.0f)
  287. #else
  288. if ( parent->client->ps.speed > 200.0f )
  289. #endif
  290. {
  291. turnSpeed += turnSpeed * parentPS->speed/200.0f*0.05f;
  292. }
  293. }
  294. turnSpeed *= pVeh->m_fTimeModifier;
  295. //default control scheme: strafing turns, mouselook aims
  296. if ( pVeh->m_ucmd.rightmove < 0 )
  297. {
  298. pVeh->m_vOrientation[YAW] += turnSpeed;
  299. }
  300. else if ( pVeh->m_ucmd.rightmove > 0 )
  301. {
  302. pVeh->m_vOrientation[YAW] -= turnSpeed;
  303. }
  304. if ( pVeh->m_pVehicleInfo->malfunctionArmorLevel && pVeh->m_iArmor <= pVeh->m_pVehicleInfo->malfunctionArmorLevel )
  305. {//damaged badly
  306. }
  307. }
  308. /********************************************************************************/
  309. /* END Here is where make sure the vehicle is properly oriented. END */
  310. /********************************************************************************/
  311. }
  312. #ifdef QAGAME //back to our game-only functions
  313. // This function makes sure that the vehicle is properly animated.
  314. static void AnimateVehicle( Vehicle_t *pVeh )
  315. {
  316. animNumber_t Anim = BOTH_STAND1;
  317. int iFlags = SETANIM_FLAG_NORMAL, iBlend = 300;
  318. gentity_t *parent = (gentity_t *)pVeh->m_pParentEntity;
  319. float fSpeedPercToMax;
  320. // We're dead (boarding is reused here so I don't have to make another variable :-).
  321. if ( parent->health <= 0 )
  322. {
  323. if ( pVeh->m_iBoarding != -999 ) // Animate the death just once!
  324. {
  325. pVeh->m_iBoarding = -999;
  326. iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
  327. // FIXME! Why do you keep repeating over and over!!?!?!? Bastard!
  328. //Vehicle_SetAnim( parent, SETANIM_LEGS, BOTH_VT_DEATH1, iFlags, iBlend );
  329. }
  330. return;
  331. }
  332. // Following is redundant to g_vehicles.c
  333. // if ( pVeh->m_iBoarding )
  334. // {
  335. // //we have no boarding anim
  336. // if (pVeh->m_iBoarding < level.time)
  337. // { //we are on now
  338. // pVeh->m_iBoarding = 0;
  339. // }
  340. // else
  341. // {
  342. // return;
  343. // }
  344. // }
  345. // Percentage of maximum speed relative to current speed.
  346. //float fSpeed = VectorLength( client->ps.velocity );
  347. fSpeedPercToMax = parent->client->ps.speed / pVeh->m_pVehicleInfo->speedMax;
  348. // If we're moving...
  349. if ( fSpeedPercToMax > 0.0f ) //fSpeedPercToMax >= 0.85f )
  350. {
  351. float fYawDelta;
  352. iBlend = 300;
  353. iFlags = SETANIM_FLAG_OVERRIDE;
  354. fYawDelta = pVeh->m_vPrevOrientation[YAW] - pVeh->m_vOrientation[YAW];
  355. // NOTE: Mikes suggestion for fixing the stuttering walk (left/right) is to maintain the
  356. // current frame between animations. I have no clue how to do this and have to work on other
  357. // stuff so good luck to him :-p AReis
  358. // If we're walking (or our speed is less than .275%)...
  359. if ( ( pVeh->m_ucmd.buttons & BUTTON_WALKING ) || fSpeedPercToMax < 0.275f )
  360. {
  361. // Make them lean if we're turning.
  362. /*if ( fYawDelta < -0.0001f )
  363. {
  364. Anim = BOTH_VT_WALK_FWD_L;
  365. }
  366. else if ( fYawDelta > 0.0001 )
  367. {
  368. Anim = BOTH_VT_WALK_FWD_R;
  369. }
  370. else*/
  371. {
  372. Anim = BOTH_WALK1;
  373. }
  374. }
  375. // otherwise we're running.
  376. else
  377. {
  378. // Make them lean if we're turning.
  379. /*if ( fYawDelta < -0.0001f )
  380. {
  381. Anim = BOTH_VT_RUN_FWD_L;
  382. }
  383. else if ( fYawDelta > 0.0001 )
  384. {
  385. Anim = BOTH_VT_RUN_FWD_R;
  386. }
  387. else*/
  388. {
  389. Anim = BOTH_RUN1;
  390. }
  391. }
  392. }
  393. else
  394. {
  395. // Going in reverse...
  396. if ( fSpeedPercToMax < -0.018f )
  397. {
  398. iFlags = SETANIM_FLAG_NORMAL;
  399. Anim = BOTH_WALKBACK1;
  400. iBlend = 500;
  401. }
  402. else
  403. {
  404. //int iChance = Q_irand( 0, 20000 );
  405. // Every once in a while buck or do a different idle...
  406. iFlags = SETANIM_FLAG_NORMAL | SETANIM_FLAG_RESTART | SETANIM_FLAG_HOLD;
  407. iBlend = 600;
  408. #ifdef _JK2MP
  409. if (parent->client->ps.m_iVehicleNum)
  410. #else
  411. if ( pVeh->m_pVehicleInfo->Inhabited( pVeh ) )
  412. #endif
  413. {//occupado
  414. Anim = BOTH_STAND1;
  415. }
  416. else
  417. {//wide open for you, baby
  418. Anim = BOTH_STAND2;
  419. }
  420. }
  421. }
  422. Vehicle_SetAnim( parent, SETANIM_LEGS, Anim, iFlags, iBlend );
  423. }
  424. //rwwFIXMEFIXME: This is all going to have to be predicted I think, or it will feel awful
  425. //and lagged
  426. #endif //QAGAME
  427. #ifndef QAGAME
  428. void AttachRidersGeneric( Vehicle_t *pVeh );
  429. #endif
  430. //on the client this function will only set up the process command funcs
  431. void G_SetWalkerVehicleFunctions( vehicleInfo_t *pVehInfo )
  432. {
  433. #ifdef QAGAME
  434. pVehInfo->AnimateVehicle = AnimateVehicle;
  435. // pVehInfo->AnimateRiders = AnimateRiders;
  436. // pVehInfo->ValidateBoard = ValidateBoard;
  437. // pVehInfo->SetParent = SetParent;
  438. // pVehInfo->SetPilot = SetPilot;
  439. // pVehInfo->AddPassenger = AddPassenger;
  440. // pVehInfo->Animate = Animate;
  441. pVehInfo->Board = Board;
  442. // pVehInfo->Eject = Eject;
  443. // pVehInfo->EjectAll = EjectAll;
  444. // pVehInfo->StartDeathDelay = StartDeathDelay;
  445. // pVehInfo->DeathUpdate = DeathUpdate;
  446. pVehInfo->RegisterAssets = RegisterAssets;
  447. // pVehInfo->Initialize = Initialize;
  448. // pVehInfo->Update = Update;
  449. // pVehInfo->UpdateRider = UpdateRider;
  450. #endif //QAGAME
  451. pVehInfo->ProcessMoveCommands = ProcessMoveCommands;
  452. pVehInfo->ProcessOrientCommands = ProcessOrientCommands;
  453. #ifndef QAGAME //cgame prediction attachment func
  454. pVehInfo->AttachRiders = AttachRidersGeneric;
  455. #endif
  456. // pVehInfo->AttachRiders = AttachRiders;
  457. // pVehInfo->Ghost = Ghost;
  458. // pVehInfo->UnGhost = UnGhost;
  459. // pVehInfo->Inhabited = Inhabited;
  460. }
  461. // Following is only in game, not in namespace
  462. #ifdef _JK2MP
  463. #include "../namespace_end.h"
  464. #endif
  465. #ifdef QAGAME
  466. extern void G_AllocateVehicleObject(Vehicle_t **pVeh);
  467. #endif
  468. #ifdef _JK2MP
  469. #include "../namespace_begin.h"
  470. #endif
  471. // Create/Allocate a new Animal Vehicle (initializing it as well).
  472. //this is a BG function too in MP so don't un-bg-compatibilify it -rww
  473. void G_CreateWalkerNPC( Vehicle_t **pVeh, const char *strAnimalType )
  474. {
  475. // Allocate the Vehicle.
  476. #ifdef _JK2MP
  477. #ifdef QAGAME
  478. //these will remain on entities on the client once allocated because the pointer is
  479. //never stomped. on the server, however, when an ent is freed, the entity struct is
  480. //memset to 0, so this memory would be lost..
  481. G_AllocateVehicleObject(pVeh);
  482. #else
  483. if (!*pVeh)
  484. { //only allocate a new one if we really have to
  485. (*pVeh) = (Vehicle_t *) BG_Alloc( sizeof(Vehicle_t) );
  486. }
  487. #endif
  488. memset(*pVeh, 0, sizeof(Vehicle_t));
  489. (*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strAnimalType )];
  490. #else
  491. (*pVeh) = (Vehicle_t *) gi.Malloc( sizeof(Vehicle_t), TAG_G_ALLOC, qtrue );
  492. (*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strAnimalType )];
  493. #endif
  494. }
  495. #ifdef _JK2MP
  496. #include "../namespace_end.h"
  497. //get rid of all the crazy defs we added for this file
  498. #undef currentAngles
  499. #undef currentOrigin
  500. #undef mins
  501. #undef maxs
  502. #undef legsAnimTimer
  503. #undef torsoAnimTimer
  504. #undef bool
  505. #undef false
  506. #undef true
  507. #undef sqrtf
  508. #undef Q_flrand
  509. #undef MOD_EXPLOSIVE
  510. #endif