bg_misc.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. // this include must remain at the top of every bg_xxxx CPP file
  2. #include "common_headers.h"
  3. // included in both game dll and client
  4. //#include "q_shared.h"
  5. #include "g_local.h"
  6. #include "bg_public.h"
  7. #include "g_items.h"
  8. #include "g_vehicles.h"
  9. extern weaponData_t weaponData[WP_NUM_WEAPONS];
  10. extern ammoData_t ammoData[AMMO_MAX];
  11. #define PICKUPSOUND "sound/weapons/w_pkup.wav"
  12. /*QUAKED weapon_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
  13. DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION for weapons, ammo, and item pickups.
  14. The suspended flag will allow items to hang in the air, otherwise they are dropped to the next surface.
  15. The NOPLAYER flag makes it so player cannot pick it up.
  16. The ALLOWNPC flag allows only NPCs to pick it up, too
  17. If an item is the target of another entity, it will spawn as normal, use INVISIBLE to hide it.
  18. An item fires all of its targets when it is picked up. If the toucher can't carry it, the targets won't be fired.
  19. "wait" override the default wait before respawning. -1 = never respawn automatically, which can be used with targeted spawning.
  20. "random" random number of plus or minus seconds varied from the respawn time
  21. "count" override quantity or duration on most items.
  22. "team" only this team can pick it up
  23. "player"
  24. "neutral"
  25. "enemy"
  26. */
  27. /*QUAKED weapon_stun_baton (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  28. model="/models/weapons2/stun_baton/baton.md3"
  29. */
  30. /*QUAKED weapon_saber (.3 .3 1) (-16 -16 -8) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE NOGLOW
  31. model="/models/weapons2/saber/saber_w.md3"
  32. When picked up, will be used as a second saber unless:
  33. 1) It's a two-handed saber
  34. 2) The old saber was two-handed
  35. OR
  36. 3) You set "saberSolo" to "1"
  37. saberType - entry name from sabers.cfg - which kind of saber this is - use "player" to make it so that the saber will be whatever saber the player is configured to use
  38. saberColor - red, orange, yellow, green, blue, and purple
  39. saberSolo - set to "1" and this will be the only saber the person who picks this up will be holding
  40. */
  41. /*QUAKED weapon_bryar_pistol (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  42. model="/models/weapons2/briar_pistol/briar_pistol.md3"
  43. */
  44. /*QUAKED weapon_blaster_pistol (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  45. model="/models/weapons2/blaster_pistol/blaster_pistol.md3"
  46. */
  47. /*QUAKED weapon_blaster (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  48. model="/models/weapons2/blaster_r/blaster.md3"
  49. */
  50. /*QUAKED weapon_disruptor (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  51. model="/models/weapons2/disruptor/disruptor.md3"
  52. */
  53. /*QUAKED weapon_bowcaster (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  54. model="/models/weapons2/bowcaster/bowcaster.md3"
  55. */
  56. /*QUAKED weapon_repeater (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  57. model="/models/weapons2/heavy_repeater/heavy_repeater.md3"
  58. */
  59. /*QUAKED weapon_demp2 (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  60. model="/models/weapons2/demp2/demp2.md3"
  61. */
  62. /*QUAKED weapon_flechette (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  63. model="/models/weapons2/golan_arms/golan_arms.md3"
  64. */
  65. /*QUAKED weapon_concussion_rifle (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  66. model="/models/weapons2/c_rifle/c_rifle.md3"
  67. */
  68. /*QUAKED weapon_rocket_launcher (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  69. model="/models/weapons2/merr_sonn/merr_sonn.md3"
  70. */
  71. /*QUAKED weapon_thermal (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  72. model="/models/weapons2/thermal/thermal.md3"
  73. */
  74. /*QUAKED weapon_trip_mine (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  75. model="/models/weapons2/laser_trap/laser_trap.md3"
  76. */
  77. /*QUAKED weapon_det_pack (.3 .3 1) (-16 -16 -2) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  78. model="/models/weapons2/detpack/det_pack.md3"
  79. */
  80. /*QUAKED item_seeker (.3 .3 1) (-8 -8 -4) (8 8 16) suspended
  81. 30 seconds of seeker drone
  82. */
  83. /*QUAKED item_bacta (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  84. model="/models/items/bacta.md3"
  85. */
  86. /*QUAKED item_datapad (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  87. model="/models/items/datapad.md3"
  88. */
  89. /*QUAKED item_binoculars (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  90. model="/models/items/binoculars.md3"
  91. */
  92. /*QUAKED item_sentry_gun (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  93. */
  94. /*QUAKED item_la_goggles (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  95. */
  96. /*QUAKED ammo_force (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  97. Ammo for the force.
  98. */
  99. /*QUAKED ammo_blaster (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  100. Ammo for the Bryar and Blaster pistols.
  101. */
  102. /*QUAKED ammo_powercell (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  103. Ammo for Tenloss Disruptor, Wookie Bowcaster, and the Destructive Electro Magnetic Pulse (demp2 ) guns
  104. */
  105. /*QUAKED ammo_metallic_bolts (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  106. Ammo for Imperial Heavy Repeater and the Golan Arms Flechette
  107. */
  108. /*QUAKED ammo_rockets (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  109. Ammo for Merr-Sonn portable missile launcher
  110. */
  111. /*QUAKED ammo_thermal (.3 .5 1) (-16 -16 -0) (16 16 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  112. Belt of thermal detonators
  113. */
  114. /*QUAKED ammo_tripmine (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  115. 3 pack of tripmines
  116. */
  117. /*QUAKED ammo_detpack (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  118. 3 pack of detpacks
  119. */
  120. /*QUAKED item_medpak_instant (.3 .3 1) (-8 -8 -4) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  121. */
  122. /*QUAKED item_shield_sm_instant (.3 .3 1) (-8 -8 -4) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  123. */
  124. /*QUAKED item_shield_lrg_instant (.3 .3 1) (-8 -8 -4) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID VERTICAL INVISIBLE
  125. */
  126. /*QUAKED item_goodie_key (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  127. */
  128. /*QUAKED item_security_key (.3 .3 1) (-8 -8 0) (8 8 16) suspended
  129. message - used to differentiate one key from another.
  130. */
  131. /*QUAKED item_battery (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  132. model="/models/items/battery.md3"
  133. battery pickup item
  134. */
  135. /*QUAKED holocron_force_heal (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  136. force heal pickup item
  137. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  138. */
  139. /*QUAKED holocron_force_levitation (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  140. force levitation pickup item
  141. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  142. */
  143. /*QUAKED holocron_force_speed (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  144. force speed pickup item
  145. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  146. */
  147. /*QUAKED holocron_force_push (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  148. force push pickup item
  149. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  150. */
  151. /*QUAKED holocron_force_pull (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  152. force pull pickup item
  153. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  154. */
  155. /*QUAKED holocron_force_telepathy (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  156. force telepathy pickup item
  157. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  158. */
  159. /*QUAKED holocron_force_grip (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  160. force grip pickup item
  161. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  162. */
  163. /*QUAKED holocron_force_lightining (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  164. force lighting pickup item
  165. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  166. */
  167. /*QUAKED holocron_force_saberthrow (.3 .5 1) (-8 -8 -0) (8 8 16) SUSPEND NOPLAYER ALLOWNPC NOTSOLID
  168. force saberthrow pickup item
  169. "count" level of force power this holocron gives activator ( range: 0-3, default 1)
  170. */
  171. gitem_t bg_itemlist[ITM_NUM_ITEMS+1];//need a null on the end
  172. //int bg_numItems = sizeof(bg_itemlist) / sizeof(bg_itemlist[0]) ;
  173. const int bg_numItems = ITM_NUM_ITEMS;
  174. /*
  175. ===============
  176. FindItemForWeapon
  177. ===============
  178. */
  179. gitem_t *FindItemForWeapon( weapon_t weapon ) {
  180. int i;
  181. for ( i = 1 ; i < bg_numItems ; i++ ) {
  182. if ( bg_itemlist[i].giType == IT_WEAPON && bg_itemlist[i].giTag == weapon ) {
  183. return &bg_itemlist[i];
  184. }
  185. }
  186. Com_Error( ERR_DROP, "Couldn't find item for weapon %i", weapon);
  187. return NULL;
  188. }
  189. //----------------------------------------------
  190. gitem_t *FindItemForInventory( int inv )
  191. {
  192. int i;
  193. gitem_t *it;
  194. // Now just check for any other kind of item.
  195. for ( i = 1 ; i < bg_numItems ; i++ )
  196. {
  197. it = &bg_itemlist[i];
  198. if ( it->giType == IT_HOLDABLE )
  199. {
  200. if ( it->giTag == inv )
  201. {
  202. return it;
  203. }
  204. }
  205. }
  206. Com_Error( ERR_DROP, "Couldn't find item for inventory %i", inv );
  207. return NULL;
  208. }
  209. /*
  210. ===============
  211. FindItemForWeapon
  212. ===============
  213. */
  214. gitem_t *FindItemForAmmo( ammo_t ammo )
  215. {
  216. int i;
  217. for ( i = 1 ; i < bg_numItems ; i++ )
  218. {
  219. if ( bg_itemlist[i].giType == IT_AMMO && bg_itemlist[i].giTag == ammo )
  220. {
  221. return &bg_itemlist[i];
  222. }
  223. }
  224. Com_Error( ERR_DROP, "Couldn't find item for ammo %i", ammo );
  225. return NULL;
  226. }
  227. /*
  228. ===============
  229. FindItem
  230. ===============
  231. */
  232. gitem_t *FindItem( const char *className ) {
  233. int i;
  234. for ( i = 1 ; i < bg_numItems ; i++ ) {
  235. if ( !Q_stricmp( bg_itemlist[i].classname, className ) )
  236. return &bg_itemlist[i];
  237. }
  238. return NULL;
  239. }
  240. /*
  241. ================
  242. BG_CanItemBeGrabbed
  243. Returns false if the item should not be picked up.
  244. This needs to be the same for client side prediction and server use.
  245. ================
  246. */
  247. qboolean BG_CanItemBeGrabbed( const entityState_t *ent, const playerState_t *ps ) {
  248. gitem_t *item;
  249. if ( ent->modelindex < 1 || ent->modelindex >= bg_numItems ) {
  250. Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: index out of range" );
  251. }
  252. item = &bg_itemlist[ent->modelindex];
  253. switch( item->giType ) {
  254. case IT_WEAPON:
  255. // See if we already have this weapon.
  256. if ( !(ps->stats[ STAT_WEAPONS ] & ( 1 << item->giTag )))
  257. {
  258. // Don't have this weapon yet, so pick it up.
  259. return qtrue;
  260. }
  261. else if ( item->giTag == WP_SABER )
  262. {//always pick up a saber, might be a new one?
  263. return qtrue;
  264. }
  265. // Make sure that we aren't already full on ammo for this weapon
  266. if ( ps->ammo[weaponData[item->giTag].ammoIndex] >= ammoData[weaponData[item->giTag].ammoIndex].max )
  267. {
  268. // full, so don't grab the item
  269. return qfalse;
  270. }
  271. return qtrue; // could use more of this type of ammo, so grab the item
  272. case IT_AMMO:
  273. if (item->giTag != AMMO_FORCE)
  274. {
  275. // since the ammo is the weapon in this case, picking up ammo should actually give you the weapon
  276. switch( item->giTag )
  277. {
  278. case AMMO_THERMAL:
  279. if( !(ps->stats[STAT_WEAPONS] & ( 1 << WP_THERMAL ) ) )
  280. {
  281. return qtrue;
  282. }
  283. break;
  284. case AMMO_DETPACK:
  285. if( !(ps->stats[STAT_WEAPONS] & ( 1 << WP_DET_PACK ) ) )
  286. {
  287. return qtrue;
  288. }
  289. break;
  290. case AMMO_TRIPMINE:
  291. if( !(ps->stats[STAT_WEAPONS] & ( 1 << WP_TRIP_MINE ) ) )
  292. {
  293. return qtrue;
  294. }
  295. break;
  296. }
  297. if ( ps->ammo[ item->giTag ] >= ammoData[item->giTag].max ) // checkme
  298. {
  299. return qfalse; // can't hold any more
  300. }
  301. }
  302. else
  303. {
  304. if (ps->forcePower >= ammoData[item->giTag].max*2)
  305. {
  306. return qfalse; // can't hold any more
  307. }
  308. }
  309. return qtrue;
  310. case IT_ARMOR:
  311. // we also clamp armor to the maxhealth for handicapping
  312. if ( ps->stats[STAT_ARMOR] >= ps->stats[STAT_MAX_HEALTH] ) {
  313. return qfalse;
  314. }
  315. return qtrue;
  316. case IT_HEALTH:
  317. if ((ps->forcePowersActive & (1 << FP_RAGE)))
  318. {//ragers can't use health
  319. return qfalse;
  320. }
  321. // don't pick up if already at max
  322. if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] ) {
  323. return qfalse;
  324. }
  325. return qtrue;
  326. case IT_BATTERY:
  327. // don't pick up if already at max
  328. if ( ps->batteryCharge >= MAX_BATTERIES )
  329. {
  330. return qfalse;
  331. }
  332. return qtrue;
  333. case IT_HOLOCRON:
  334. // pretty lame but for now you can always pick these up
  335. return qtrue;
  336. case IT_HOLDABLE:
  337. if ( item->giTag >= INV_ELECTROBINOCULARS && item->giTag <= INV_SENTRY )
  338. {
  339. // hardcoded--can only pick up five of any holdable
  340. if ( ps->inventory[item->giTag] >= 5 )
  341. {
  342. return qfalse;
  343. }
  344. }
  345. return qtrue;
  346. }
  347. return qfalse;
  348. }
  349. //======================================================================
  350. /*
  351. ================
  352. EvaluateTrajectory
  353. ================
  354. */
  355. void EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) {
  356. float deltaTime;
  357. float phase;
  358. switch( tr->trType ) {
  359. case TR_STATIONARY:
  360. case TR_INTERPOLATE:
  361. VectorCopy( tr->trBase, result );
  362. break;
  363. case TR_LINEAR:
  364. deltaTime = ( atTime - tr->trTime ) * 0.001F; // milliseconds to seconds
  365. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  366. break;
  367. case TR_SINE:
  368. deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
  369. phase = (float)sin( deltaTime * M_PI * 2 );
  370. VectorMA( tr->trBase, phase, tr->trDelta, result );
  371. break;
  372. case TR_LINEAR_STOP:
  373. if ( atTime > tr->trTime + tr->trDuration )
  374. {
  375. atTime = tr->trTime + tr->trDuration;
  376. }
  377. //old totally linear
  378. deltaTime = ( atTime - tr->trTime ) * 0.001F; // milliseconds to seconds
  379. if ( deltaTime < 0 )
  380. {//going past the total duration
  381. deltaTime = 0;
  382. }
  383. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  384. break;
  385. case TR_NONLINEAR_STOP:
  386. if ( atTime > tr->trTime + tr->trDuration )
  387. {
  388. atTime = tr->trTime + tr->trDuration;
  389. }
  390. //new slow-down at end
  391. if ( atTime - tr->trTime > tr->trDuration || atTime - tr->trTime <= 0 )
  392. {
  393. deltaTime = 0;
  394. }
  395. else
  396. {//FIXME: maybe scale this somehow? So that it starts out faster and stops faster?
  397. deltaTime = tr->trDuration*0.001f*((float)cos( DEG2RAD(90.0f - (90.0f*((float)atTime-tr->trTime)/(float)tr->trDuration)) ));
  398. }
  399. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  400. break;
  401. case TR_GRAVITY:
  402. deltaTime = ( atTime - tr->trTime ) * 0.001F; // milliseconds to seconds
  403. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  404. result[2] -= 0.5F * g_gravity->value * deltaTime * deltaTime;//DEFAULT_GRAVITY
  405. break;
  406. default:
  407. Com_Error( ERR_DROP, "EvaluateTrajectory: unknown trType: %i", tr->trTime );
  408. break;
  409. }
  410. }
  411. /*
  412. ================
  413. EvaluateTrajectoryDelta
  414. Returns current speed at given time
  415. ================
  416. */
  417. void EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ) {
  418. float deltaTime;
  419. float phase;
  420. switch( tr->trType ) {
  421. case TR_STATIONARY:
  422. case TR_INTERPOLATE:
  423. VectorClear( result );
  424. break;
  425. case TR_LINEAR:
  426. VectorCopy( tr->trDelta, result );
  427. break;
  428. case TR_SINE:
  429. deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
  430. phase = (float)cos( deltaTime * M_PI * 2 ); // derivative of sin = cos
  431. phase *= 0.5;
  432. VectorScale( tr->trDelta, phase, result );
  433. break;
  434. case TR_LINEAR_STOP:
  435. if ( atTime > tr->trTime + tr->trDuration )
  436. {
  437. VectorClear( result );
  438. return;
  439. }
  440. VectorCopy( tr->trDelta, result );
  441. break;
  442. case TR_NONLINEAR_STOP:
  443. if ( atTime - tr->trTime > tr->trDuration || atTime - tr->trTime <= 0 )
  444. {
  445. VectorClear( result );
  446. return;
  447. }
  448. deltaTime = tr->trDuration*0.001f*((float)cos( DEG2RAD(90.0f - (90.0f*((float)atTime-tr->trTime)/(float)tr->trDuration)) ));
  449. VectorScale( tr->trDelta, deltaTime, result );
  450. break;
  451. case TR_GRAVITY:
  452. deltaTime = ( atTime - tr->trTime ) * 0.001F; // milliseconds to seconds
  453. VectorCopy( tr->trDelta, result );
  454. result[2] -= g_gravity->value * deltaTime; // DEFAULT_GRAVITY
  455. break;
  456. default:
  457. Com_Error( ERR_DROP, "EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime );
  458. break;
  459. }
  460. }
  461. /*
  462. ===============
  463. AddEventToPlayerstate
  464. Handles the sequence numbers
  465. ===============
  466. */
  467. void AddEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) {
  468. ps->events[ps->eventSequence & (MAX_PS_EVENTS-1)] = newEvent;
  469. ps->eventParms[ps->eventSequence & (MAX_PS_EVENTS-1)] = eventParm;
  470. ps->eventSequence++;
  471. }
  472. /*
  473. ===============
  474. CurrentPlayerstateEvent
  475. ===============
  476. */
  477. int CurrentPlayerstateEvent( playerState_t *ps ) {
  478. return ps->events[ (ps->eventSequence-1) & (MAX_PS_EVENTS-1) ];
  479. }
  480. /*
  481. ========================
  482. PlayerStateToEntityState
  483. This is done after each set of usercmd_t on the server,
  484. and after local prediction on the client
  485. ========================
  486. */
  487. void PlayerStateToEntityState( playerState_t *ps, entityState_t *s )
  488. {
  489. int i;
  490. if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR )
  491. {
  492. s->eType = ET_INVISIBLE;
  493. }
  494. /*else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH )
  495. {
  496. s->eType = ET_INVISIBLE;
  497. } */
  498. else
  499. {
  500. s->eType = ET_PLAYER;
  501. }
  502. s->number = ps->clientNum;
  503. s->pos.trType = TR_INTERPOLATE;
  504. VectorCopy( ps->origin, s->pos.trBase );
  505. //SnapVector( s->pos.trBase );
  506. s->apos.trType = TR_INTERPOLATE;
  507. VectorCopy( ps->viewangles, s->apos.trBase );
  508. //SnapVector( s->apos.trBase );
  509. s->angles2[YAW] = ps->movementDir;
  510. s->legsAnim = ps->legsAnim;
  511. s->torsoAnim = ps->torsoAnim;
  512. s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
  513. // so corpses can also reference the proper config
  514. s->eFlags = ps->eFlags;
  515. // new sabre stuff
  516. s->saberActive = ps->SaberActive();//WHY is this on the entityState_t, too???
  517. s->saberInFlight = ps->saberInFlight;
  518. // NOTE: Although we store this stuff locally on a vehicle, who's to say we
  519. // can't bring back these variables and fill them at the appropriate time? -Aurelio
  520. // We need to bring these in from the vehicle NPC.
  521. if ( g_entities[ps->clientNum].client && g_entities[ps->clientNum].client->NPC_class == CLASS_VEHICLE && g_entities[ps->clientNum].NPC )
  522. {
  523. Vehicle_t *pVeh = g_entities[ps->clientNum].m_pVehicle;
  524. s->vehicleArmor = pVeh->m_iArmor;
  525. VectorCopy( pVeh->m_vOrientation, s->vehicleAngles );
  526. }
  527. s->weapon = ps->weapon;
  528. s->groundEntityNum = ps->groundEntityNum;
  529. s->powerups = 0;
  530. for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
  531. if ( ps->powerups[ i ] ) {
  532. s->powerups |= 1 << i;
  533. }
  534. }
  535. #if 0
  536. if ( ps->externalEvent ) {
  537. s->event = ps->externalEvent;
  538. s->eventParm = ps->externalEventParm;
  539. } else {
  540. int seq;
  541. seq = (ps->eventSequence-1) & (MAX_PS_EVENTS-1);
  542. s->event = ps->events[ seq ] | ( ( ps->eventSequence & 3 ) << 8 );
  543. s->eventParm = ps->eventParms[ seq ];
  544. }
  545. // show some roll in the body based on velocity and angle
  546. if ( ps->stats[STAT_HEALTH] > 0 ) {
  547. vec3_t right;
  548. float sign;
  549. float side;
  550. float value;
  551. AngleVectors( ps->viewangles, NULL, right, NULL );
  552. side = DotProduct (ps->velocity, right);
  553. sign = side < 0 ? -1 : 1;
  554. side = fabs(side);
  555. value = 2; // g_rollangle->value;
  556. if (side < 200 /* g_rollspeed->value */ )
  557. side = side * value / 200; // g_rollspeed->value;
  558. else
  559. side = value;
  560. s->angles[ROLL] = (int)(side*sign * 4);
  561. }
  562. #endif
  563. }
  564. /*
  565. ============
  566. BG_PlayerTouchesItem
  567. Items can be picked up without actually touching their physical bounds
  568. ============
  569. */
  570. qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime ) {
  571. vec3_t origin;
  572. EvaluateTrajectory( &item->pos, atTime, origin );
  573. // we are ignoring ducked differences here
  574. if ( ps->origin[0] - origin[0] > 44
  575. || ps->origin[0] - origin[0] < -50
  576. || ps->origin[1] - origin[1] > 36
  577. || ps->origin[1] - origin[1] < -36
  578. || ps->origin[2] - origin[2] > 36
  579. || ps->origin[2] - origin[2] < -36 ) {
  580. return qfalse;
  581. }
  582. return qtrue;
  583. }
  584. /*
  585. =================
  586. BG_EmplacedView
  587. Shared code for emplaced angle gun constriction
  588. =================
  589. */
  590. int BG_EmplacedView(vec3_t baseAngles, vec3_t angles, float *newYaw, float constraint)
  591. {
  592. float dif = AngleSubtract(baseAngles[YAW], angles[YAW]);
  593. if (dif > constraint ||
  594. dif < -constraint)
  595. {
  596. float amt;
  597. if (dif > constraint)
  598. {
  599. amt = (dif-constraint);
  600. dif = constraint;
  601. }
  602. else if (dif < -constraint)
  603. {
  604. amt = (dif+constraint);
  605. dif = -constraint;
  606. }
  607. else
  608. {
  609. amt = 0.0f;
  610. }
  611. *newYaw = AngleSubtract(angles[YAW], -dif);
  612. if (amt > 1.0f || amt < -1.0f)
  613. { //significant, force the view
  614. return 2;
  615. }
  616. else
  617. { //just a little out of range
  618. return 1;
  619. }
  620. }
  621. return 0;
  622. }