cg_localents.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. //
  19. // cg_localents.c -- every frame, generate renderer commands for locally
  20. // processed entities, like smoke puffs, gibs, shells, etc.
  21. #include "cg_local.h"
  22. #define MAX_LOCAL_ENTITIES 512
  23. localEntity_t cg_localEntities[MAX_LOCAL_ENTITIES];
  24. localEntity_t cg_activeLocalEntities; // double linked list
  25. localEntity_t *cg_freeLocalEntities; // single linked list
  26. /*
  27. ===================
  28. CG_InitLocalEntities
  29. This is called at startup and for tournement restarts
  30. ===================
  31. */
  32. void CG_InitLocalEntities( void ) {
  33. int i;
  34. memset( cg_localEntities, 0, sizeof( cg_localEntities ) );
  35. cg_activeLocalEntities.next = &cg_activeLocalEntities;
  36. cg_activeLocalEntities.prev = &cg_activeLocalEntities;
  37. cg_freeLocalEntities = cg_localEntities;
  38. for ( i = 0 ; i < MAX_LOCAL_ENTITIES - 1 ; i++ ) {
  39. cg_localEntities[i].next = &cg_localEntities[i+1];
  40. }
  41. }
  42. /*
  43. ==================
  44. CG_FreeLocalEntity
  45. ==================
  46. */
  47. void CG_FreeLocalEntity( localEntity_t *le ) {
  48. if ( !le->prev ) {
  49. CG_Error( "CG_FreeLocalEntity: not active" );
  50. }
  51. // remove from the doubly linked active list
  52. le->prev->next = le->next;
  53. le->next->prev = le->prev;
  54. // the free list is only singly linked
  55. le->next = cg_freeLocalEntities;
  56. cg_freeLocalEntities = le;
  57. }
  58. /*
  59. ===================
  60. CG_AllocLocalEntity
  61. Will allways succeed, even if it requires freeing an old active entity
  62. ===================
  63. */
  64. localEntity_t *CG_AllocLocalEntity( void ) {
  65. localEntity_t *le;
  66. if ( !cg_freeLocalEntities ) {
  67. // no free entities, so free the one at the end of the chain
  68. // remove the oldest active entity
  69. CG_FreeLocalEntity( cg_activeLocalEntities.prev );
  70. }
  71. le = cg_freeLocalEntities;
  72. cg_freeLocalEntities = cg_freeLocalEntities->next;
  73. memset( le, 0, sizeof( *le ) );
  74. // link into the active list
  75. le->next = cg_activeLocalEntities.next;
  76. le->prev = &cg_activeLocalEntities;
  77. cg_activeLocalEntities.next->prev = le;
  78. cg_activeLocalEntities.next = le;
  79. return le;
  80. }
  81. /*
  82. ====================================================================================
  83. FRAGMENT PROCESSING
  84. A fragment localentity interacts with the environment in some way (hitting walls),
  85. or generates more localentities along a trail.
  86. ====================================================================================
  87. */
  88. /*
  89. ================
  90. CG_BloodTrail
  91. Leave expanding blood puffs behind gibs
  92. ================
  93. */
  94. void CG_BloodTrail( localEntity_t *le ) {
  95. int t;
  96. int t2;
  97. int step;
  98. vec3_t newOrigin;
  99. localEntity_t *blood;
  100. step = 150;
  101. t = step * ( (cg.time - cg.frametime + step ) / step );
  102. t2 = step * ( cg.time / step );
  103. for ( ; t <= t2; t += step ) {
  104. BG_EvaluateTrajectory( &le->pos, t, newOrigin );
  105. blood = CG_SmokePuff( newOrigin, vec3_origin,
  106. 20, // radius
  107. 1, 1, 1, 1, // color
  108. 2000, // trailTime
  109. t, // startTime
  110. 0, // fadeInTime
  111. 0, // flags
  112. cgs.media.bloodTrailShader );
  113. // use the optimized version
  114. blood->leType = LE_FALL_SCALE_FADE;
  115. // drop a total of 40 units over its lifetime
  116. blood->pos.trDelta[2] = 40;
  117. }
  118. }
  119. /*
  120. ================
  121. CG_FragmentBounceMark
  122. ================
  123. */
  124. void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
  125. int radius;
  126. if ( le->leMarkType == LEMT_BLOOD ) {
  127. radius = 16 + (rand()&31);
  128. CG_ImpactMark( cgs.media.bloodMarkShader, trace->endpos, trace->plane.normal, random()*360,
  129. 1,1,1,1, qtrue, radius, qfalse );
  130. } else if ( le->leMarkType == LEMT_BURN ) {
  131. radius = 8 + (rand()&15);
  132. CG_ImpactMark( cgs.media.burnMarkShader, trace->endpos, trace->plane.normal, random()*360,
  133. 1,1,1,1, qtrue, radius, qfalse );
  134. }
  135. // don't allow a fragment to make multiple marks, or they
  136. // pile up while settling
  137. le->leMarkType = LEMT_NONE;
  138. }
  139. /*
  140. ================
  141. CG_FragmentBounceSound
  142. ================
  143. */
  144. void CG_FragmentBounceSound( localEntity_t *le, trace_t *trace ) {
  145. if ( le->leBounceSoundType == LEBS_BLOOD ) {
  146. // half the gibs will make splat sounds
  147. if ( rand() & 1 ) {
  148. int r = rand()&3;
  149. sfxHandle_t s;
  150. if ( r == 0 ) {
  151. s = cgs.media.gibBounce1Sound;
  152. } else if ( r == 1 ) {
  153. s = cgs.media.gibBounce2Sound;
  154. } else {
  155. s = cgs.media.gibBounce3Sound;
  156. }
  157. trap_S_StartSound( trace->endpos, ENTITYNUM_WORLD, CHAN_AUTO, s );
  158. }
  159. } else if ( le->leBounceSoundType == LEBS_BRASS ) {
  160. }
  161. // don't allow a fragment to make multiple bounce sounds,
  162. // or it gets too noisy as they settle
  163. le->leBounceSoundType = LEBS_NONE;
  164. }
  165. /*
  166. ================
  167. CG_ReflectVelocity
  168. ================
  169. */
  170. void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) {
  171. vec3_t velocity;
  172. float dot;
  173. int hitTime;
  174. // reflect the velocity on the trace plane
  175. hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
  176. BG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
  177. dot = DotProduct( velocity, trace->plane.normal );
  178. VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );
  179. VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );
  180. VectorCopy( trace->endpos, le->pos.trBase );
  181. le->pos.trTime = cg.time;
  182. // check for stop, making sure that even on low FPS systems it doesn't bobble
  183. if ( trace->allsolid ||
  184. ( trace->plane.normal[2] > 0 &&
  185. ( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) {
  186. le->pos.trType = TR_STATIONARY;
  187. } else {
  188. }
  189. }
  190. /*
  191. ================
  192. CG_AddFragment
  193. ================
  194. */
  195. void CG_AddFragment( localEntity_t *le ) {
  196. vec3_t newOrigin;
  197. trace_t trace;
  198. if ( le->pos.trType == TR_STATIONARY ) {
  199. // sink into the ground if near the removal time
  200. int t;
  201. float oldZ;
  202. t = le->endTime - cg.time;
  203. if ( t < SINK_TIME ) {
  204. // we must use an explicit lighting origin, otherwise the
  205. // lighting would be lost as soon as the origin went
  206. // into the ground
  207. VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
  208. le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
  209. oldZ = le->refEntity.origin[2];
  210. le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
  211. trap_R_AddRefEntityToScene( &le->refEntity );
  212. le->refEntity.origin[2] = oldZ;
  213. } else {
  214. trap_R_AddRefEntityToScene( &le->refEntity );
  215. }
  216. return;
  217. }
  218. // calculate new position
  219. BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
  220. // trace a line from previous position to new position
  221. CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
  222. if ( trace.fraction == 1.0 ) {
  223. // still in free fall
  224. VectorCopy( newOrigin, le->refEntity.origin );
  225. if ( le->leFlags & LEF_TUMBLE ) {
  226. vec3_t angles;
  227. BG_EvaluateTrajectory( &le->angles, cg.time, angles );
  228. AnglesToAxis( angles, le->refEntity.axis );
  229. }
  230. trap_R_AddRefEntityToScene( &le->refEntity );
  231. // add a blood trail
  232. if ( le->leBounceSoundType == LEBS_BLOOD ) {
  233. CG_BloodTrail( le );
  234. }
  235. return;
  236. }
  237. // if it is in a nodrop zone, remove it
  238. // this keeps gibs from waiting at the bottom of pits of death
  239. // and floating levels
  240. if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
  241. CG_FreeLocalEntity( le );
  242. return;
  243. }
  244. // leave a mark
  245. CG_FragmentBounceMark( le, &trace );
  246. // do a bouncy sound
  247. CG_FragmentBounceSound( le, &trace );
  248. // reflect the velocity on the trace plane
  249. CG_ReflectVelocity( le, &trace );
  250. trap_R_AddRefEntityToScene( &le->refEntity );
  251. }
  252. /*
  253. =====================================================================
  254. TRIVIAL LOCAL ENTITIES
  255. These only do simple scaling or modulation before passing to the renderer
  256. =====================================================================
  257. */
  258. /*
  259. ====================
  260. CG_AddFadeRGB
  261. ====================
  262. */
  263. void CG_AddFadeRGB( localEntity_t *le ) {
  264. refEntity_t *re;
  265. float c;
  266. re = &le->refEntity;
  267. c = ( le->endTime - cg.time ) * le->lifeRate;
  268. c *= 0xff;
  269. re->shaderRGBA[0] = le->color[0] * c;
  270. re->shaderRGBA[1] = le->color[1] * c;
  271. re->shaderRGBA[2] = le->color[2] * c;
  272. re->shaderRGBA[3] = le->color[3] * c;
  273. trap_R_AddRefEntityToScene( re );
  274. }
  275. /*
  276. ==================
  277. CG_AddMoveScaleFade
  278. ==================
  279. */
  280. static void CG_AddMoveScaleFade( localEntity_t *le ) {
  281. refEntity_t *re;
  282. float c;
  283. vec3_t delta;
  284. float len;
  285. re = &le->refEntity;
  286. if ( le->fadeInTime > le->startTime && cg.time < le->fadeInTime ) {
  287. // fade / grow time
  288. c = 1.0 - (float) ( le->fadeInTime - cg.time ) / ( le->fadeInTime - le->startTime );
  289. }
  290. else {
  291. // fade / grow time
  292. c = ( le->endTime - cg.time ) * le->lifeRate;
  293. }
  294. re->shaderRGBA[3] = 0xff * c * le->color[3];
  295. if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
  296. re->radius = le->radius * ( 1.0 - c ) + 8;
  297. }
  298. BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
  299. // if the view would be "inside" the sprite, kill the sprite
  300. // so it doesn't add too much overdraw
  301. VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  302. len = VectorLength( delta );
  303. if ( len < le->radius ) {
  304. CG_FreeLocalEntity( le );
  305. return;
  306. }
  307. trap_R_AddRefEntityToScene( re );
  308. }
  309. /*
  310. ===================
  311. CG_AddScaleFade
  312. For rocket smokes that hang in place, fade out, and are
  313. removed if the view passes through them.
  314. There are often many of these, so it needs to be simple.
  315. ===================
  316. */
  317. static void CG_AddScaleFade( localEntity_t *le ) {
  318. refEntity_t *re;
  319. float c;
  320. vec3_t delta;
  321. float len;
  322. re = &le->refEntity;
  323. // fade / grow time
  324. c = ( le->endTime - cg.time ) * le->lifeRate;
  325. re->shaderRGBA[3] = 0xff * c * le->color[3];
  326. re->radius = le->radius * ( 1.0 - c ) + 8;
  327. // if the view would be "inside" the sprite, kill the sprite
  328. // so it doesn't add too much overdraw
  329. VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  330. len = VectorLength( delta );
  331. if ( len < le->radius ) {
  332. CG_FreeLocalEntity( le );
  333. return;
  334. }
  335. trap_R_AddRefEntityToScene( re );
  336. }
  337. /*
  338. =================
  339. CG_AddFallScaleFade
  340. This is just an optimized CG_AddMoveScaleFade
  341. For blood mists that drift down, fade out, and are
  342. removed if the view passes through them.
  343. There are often 100+ of these, so it needs to be simple.
  344. =================
  345. */
  346. static void CG_AddFallScaleFade( localEntity_t *le ) {
  347. refEntity_t *re;
  348. float c;
  349. vec3_t delta;
  350. float len;
  351. re = &le->refEntity;
  352. // fade time
  353. c = ( le->endTime - cg.time ) * le->lifeRate;
  354. re->shaderRGBA[3] = 0xff * c * le->color[3];
  355. re->origin[2] = le->pos.trBase[2] - ( 1.0 - c ) * le->pos.trDelta[2];
  356. re->radius = le->radius * ( 1.0 - c ) + 16;
  357. // if the view would be "inside" the sprite, kill the sprite
  358. // so it doesn't add too much overdraw
  359. VectorSubtract( re->origin, cg.refdef.vieworg, delta );
  360. len = VectorLength( delta );
  361. if ( len < le->radius ) {
  362. CG_FreeLocalEntity( le );
  363. return;
  364. }
  365. trap_R_AddRefEntityToScene( re );
  366. }
  367. /*
  368. ================
  369. CG_AddExplosion
  370. ================
  371. */
  372. static void CG_AddExplosion( localEntity_t *ex ) {
  373. refEntity_t *ent;
  374. ent = &ex->refEntity;
  375. // add the entity
  376. trap_R_AddRefEntityToScene(ent);
  377. // add the dlight
  378. if ( ex->light ) {
  379. float light;
  380. light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime );
  381. if ( light < 0.5 ) {
  382. light = 1.0;
  383. } else {
  384. light = 1.0 - ( light - 0.5 ) * 2;
  385. }
  386. light = ex->light * light;
  387. trap_R_AddLightToScene(ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] );
  388. }
  389. }
  390. /*
  391. ================
  392. CG_AddSpriteExplosion
  393. ================
  394. */
  395. static void CG_AddSpriteExplosion( localEntity_t *le ) {
  396. refEntity_t re;
  397. float c;
  398. re = le->refEntity;
  399. c = ( le->endTime - cg.time ) / ( float ) ( le->endTime - le->startTime );
  400. if ( c > 1 ) {
  401. c = 1.0; // can happen during connection problems
  402. }
  403. re.shaderRGBA[0] = 0xff;
  404. re.shaderRGBA[1] = 0xff;
  405. re.shaderRGBA[2] = 0xff;
  406. re.shaderRGBA[3] = 0xff * c * 0.33;
  407. re.reType = RT_SPRITE;
  408. re.radius = 42 * ( 1.0 - c ) + 30;
  409. trap_R_AddRefEntityToScene( &re );
  410. // add the dlight
  411. if ( le->light ) {
  412. float light;
  413. light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime );
  414. if ( light < 0.5 ) {
  415. light = 1.0;
  416. } else {
  417. light = 1.0 - ( light - 0.5 ) * 2;
  418. }
  419. light = le->light * light;
  420. trap_R_AddLightToScene(re.origin, light, le->lightColor[0], le->lightColor[1], le->lightColor[2] );
  421. }
  422. }
  423. #ifdef MISSIONPACK
  424. /*
  425. ====================
  426. CG_AddKamikaze
  427. ====================
  428. */
  429. void CG_AddKamikaze( localEntity_t *le ) {
  430. refEntity_t *re;
  431. refEntity_t shockwave;
  432. float c;
  433. vec3_t test, axis[3];
  434. int t;
  435. re = &le->refEntity;
  436. t = cg.time - le->startTime;
  437. VectorClear( test );
  438. AnglesToAxis( test, axis );
  439. if (t > KAMI_SHOCKWAVE_STARTTIME && t < KAMI_SHOCKWAVE_ENDTIME) {
  440. if (!(le->leFlags & LEF_SOUND1)) {
  441. // trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeExplodeSound );
  442. trap_S_StartLocalSound(cgs.media.kamikazeExplodeSound, CHAN_AUTO);
  443. le->leFlags |= LEF_SOUND1;
  444. }
  445. // 1st kamikaze shockwave
  446. memset(&shockwave, 0, sizeof(shockwave));
  447. shockwave.hModel = cgs.media.kamikazeShockWave;
  448. shockwave.reType = RT_MODEL;
  449. shockwave.shaderTime = re->shaderTime;
  450. VectorCopy(re->origin, shockwave.origin);
  451. c = (float)(t - KAMI_SHOCKWAVE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVE_STARTTIME);
  452. VectorScale( axis[0], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] );
  453. VectorScale( axis[1], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] );
  454. VectorScale( axis[2], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] );
  455. shockwave.nonNormalizedAxes = qtrue;
  456. if (t > KAMI_SHOCKWAVEFADE_STARTTIME) {
  457. c = (float)(t - KAMI_SHOCKWAVEFADE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVEFADE_STARTTIME);
  458. }
  459. else {
  460. c = 0;
  461. }
  462. c *= 0xff;
  463. shockwave.shaderRGBA[0] = 0xff - c;
  464. shockwave.shaderRGBA[1] = 0xff - c;
  465. shockwave.shaderRGBA[2] = 0xff - c;
  466. shockwave.shaderRGBA[3] = 0xff - c;
  467. trap_R_AddRefEntityToScene( &shockwave );
  468. }
  469. if (t > KAMI_EXPLODE_STARTTIME && t < KAMI_IMPLODE_ENDTIME) {
  470. // explosion and implosion
  471. c = ( le->endTime - cg.time ) * le->lifeRate;
  472. c *= 0xff;
  473. re->shaderRGBA[0] = le->color[0] * c;
  474. re->shaderRGBA[1] = le->color[1] * c;
  475. re->shaderRGBA[2] = le->color[2] * c;
  476. re->shaderRGBA[3] = le->color[3] * c;
  477. if( t < KAMI_IMPLODE_STARTTIME ) {
  478. c = (float)(t - KAMI_EXPLODE_STARTTIME) / (float)(KAMI_IMPLODE_STARTTIME - KAMI_EXPLODE_STARTTIME);
  479. }
  480. else {
  481. if (!(le->leFlags & LEF_SOUND2)) {
  482. // trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeImplodeSound );
  483. trap_S_StartLocalSound(cgs.media.kamikazeImplodeSound, CHAN_AUTO);
  484. le->leFlags |= LEF_SOUND2;
  485. }
  486. c = (float)(KAMI_IMPLODE_ENDTIME - t) / (float) (KAMI_IMPLODE_ENDTIME - KAMI_IMPLODE_STARTTIME);
  487. }
  488. VectorScale( axis[0], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[0] );
  489. VectorScale( axis[1], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[1] );
  490. VectorScale( axis[2], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[2] );
  491. re->nonNormalizedAxes = qtrue;
  492. trap_R_AddRefEntityToScene( re );
  493. // add the dlight
  494. trap_R_AddLightToScene( re->origin, c * 1000.0, 1.0, 1.0, c );
  495. }
  496. if (t > KAMI_SHOCKWAVE2_STARTTIME && t < KAMI_SHOCKWAVE2_ENDTIME) {
  497. // 2nd kamikaze shockwave
  498. if (le->angles.trBase[0] == 0 &&
  499. le->angles.trBase[1] == 0 &&
  500. le->angles.trBase[2] == 0) {
  501. le->angles.trBase[0] = random() * 360;
  502. le->angles.trBase[1] = random() * 360;
  503. le->angles.trBase[2] = random() * 360;
  504. }
  505. else {
  506. c = 0;
  507. }
  508. memset(&shockwave, 0, sizeof(shockwave));
  509. shockwave.hModel = cgs.media.kamikazeShockWave;
  510. shockwave.reType = RT_MODEL;
  511. shockwave.shaderTime = re->shaderTime;
  512. VectorCopy(re->origin, shockwave.origin);
  513. test[0] = le->angles.trBase[0];
  514. test[1] = le->angles.trBase[1];
  515. test[2] = le->angles.trBase[2];
  516. AnglesToAxis( test, axis );
  517. c = (float)(t - KAMI_SHOCKWAVE2_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2_STARTTIME);
  518. VectorScale( axis[0], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] );
  519. VectorScale( axis[1], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] );
  520. VectorScale( axis[2], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] );
  521. shockwave.nonNormalizedAxes = qtrue;
  522. if (t > KAMI_SHOCKWAVE2FADE_STARTTIME) {
  523. c = (float)(t - KAMI_SHOCKWAVE2FADE_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2FADE_STARTTIME);
  524. }
  525. else {
  526. c = 0;
  527. }
  528. c *= 0xff;
  529. shockwave.shaderRGBA[0] = 0xff - c;
  530. shockwave.shaderRGBA[1] = 0xff - c;
  531. shockwave.shaderRGBA[2] = 0xff - c;
  532. shockwave.shaderRGBA[3] = 0xff - c;
  533. trap_R_AddRefEntityToScene( &shockwave );
  534. }
  535. }
  536. /*
  537. ===================
  538. CG_AddInvulnerabilityImpact
  539. ===================
  540. */
  541. void CG_AddInvulnerabilityImpact( localEntity_t *le ) {
  542. trap_R_AddRefEntityToScene( &le->refEntity );
  543. }
  544. /*
  545. ===================
  546. CG_AddInvulnerabilityJuiced
  547. ===================
  548. */
  549. void CG_AddInvulnerabilityJuiced( localEntity_t *le ) {
  550. int t;
  551. t = cg.time - le->startTime;
  552. if ( t > 3000 ) {
  553. le->refEntity.axis[0][0] = (float) 1.0 + 0.3 * (t - 3000) / 2000;
  554. le->refEntity.axis[1][1] = (float) 1.0 + 0.3 * (t - 3000) / 2000;
  555. le->refEntity.axis[2][2] = (float) 0.7 + 0.3 * (2000 - (t - 3000)) / 2000;
  556. }
  557. if ( t > 5000 ) {
  558. le->endTime = 0;
  559. CG_GibPlayer( le->refEntity.origin );
  560. }
  561. else {
  562. trap_R_AddRefEntityToScene( &le->refEntity );
  563. }
  564. }
  565. /*
  566. ===================
  567. CG_AddRefEntity
  568. ===================
  569. */
  570. void CG_AddRefEntity( localEntity_t *le ) {
  571. if (le->endTime < cg.time) {
  572. CG_FreeLocalEntity( le );
  573. return;
  574. }
  575. trap_R_AddRefEntityToScene( &le->refEntity );
  576. }
  577. #endif
  578. /*
  579. ===================
  580. CG_AddScorePlum
  581. ===================
  582. */
  583. #define NUMBER_SIZE 8
  584. void CG_AddScorePlum( localEntity_t *le ) {
  585. refEntity_t *re;
  586. vec3_t origin, delta, dir, vec, up = {0, 0, 1};
  587. float c, len;
  588. int i, score, digits[10], numdigits, negative;
  589. re = &le->refEntity;
  590. c = ( le->endTime - cg.time ) * le->lifeRate;
  591. score = le->radius;
  592. if (score < 0) {
  593. re->shaderRGBA[0] = 0xff;
  594. re->shaderRGBA[1] = 0x11;
  595. re->shaderRGBA[2] = 0x11;
  596. }
  597. else {
  598. re->shaderRGBA[0] = 0xff;
  599. re->shaderRGBA[1] = 0xff;
  600. re->shaderRGBA[2] = 0xff;
  601. if (score >= 50) {
  602. re->shaderRGBA[1] = 0;
  603. } else if (score >= 20) {
  604. re->shaderRGBA[0] = re->shaderRGBA[1] = 0;
  605. } else if (score >= 10) {
  606. re->shaderRGBA[2] = 0;
  607. } else if (score >= 2) {
  608. re->shaderRGBA[0] = re->shaderRGBA[2] = 0;
  609. }
  610. }
  611. if (c < 0.25)
  612. re->shaderRGBA[3] = 0xff * 4 * c;
  613. else
  614. re->shaderRGBA[3] = 0xff;
  615. re->radius = NUMBER_SIZE / 2;
  616. VectorCopy(le->pos.trBase, origin);
  617. origin[2] += 110 - c * 100;
  618. VectorSubtract(cg.refdef.vieworg, origin, dir);
  619. CrossProduct(dir, up, vec);
  620. VectorNormalize(vec);
  621. VectorMA(origin, -10 + 20 * sin(c * 2 * M_PI), vec, origin);
  622. // if the view would be "inside" the sprite, kill the sprite
  623. // so it doesn't add too much overdraw
  624. VectorSubtract( origin, cg.refdef.vieworg, delta );
  625. len = VectorLength( delta );
  626. if ( len < 20 ) {
  627. CG_FreeLocalEntity( le );
  628. return;
  629. }
  630. negative = qfalse;
  631. if (score < 0) {
  632. negative = qtrue;
  633. score = -score;
  634. }
  635. for (numdigits = 0; !(numdigits && !score); numdigits++) {
  636. digits[numdigits] = score % 10;
  637. score = score / 10;
  638. }
  639. if (negative) {
  640. digits[numdigits] = 10;
  641. numdigits++;
  642. }
  643. for (i = 0; i < numdigits; i++) {
  644. VectorMA(origin, (float) (((float) numdigits / 2) - i) * NUMBER_SIZE, vec, re->origin);
  645. re->customShader = cgs.media.numberShaders[digits[numdigits-1-i]];
  646. trap_R_AddRefEntityToScene( re );
  647. }
  648. }
  649. //==============================================================================
  650. /*
  651. ===================
  652. CG_AddLocalEntities
  653. ===================
  654. */
  655. void CG_AddLocalEntities( void ) {
  656. localEntity_t *le, *next;
  657. // walk the list backwards, so any new local entities generated
  658. // (trails, marks, etc) will be present this frame
  659. le = cg_activeLocalEntities.prev;
  660. for ( ; le != &cg_activeLocalEntities ; le = next ) {
  661. // grab next now, so if the local entity is freed we
  662. // still have it
  663. next = le->prev;
  664. if ( cg.time >= le->endTime ) {
  665. CG_FreeLocalEntity( le );
  666. continue;
  667. }
  668. switch ( le->leType ) {
  669. default:
  670. CG_Error( "Bad leType: %i", le->leType );
  671. break;
  672. case LE_MARK:
  673. break;
  674. case LE_SPRITE_EXPLOSION:
  675. CG_AddSpriteExplosion( le );
  676. break;
  677. case LE_EXPLOSION:
  678. CG_AddExplosion( le );
  679. break;
  680. case LE_FRAGMENT: // gibs and brass
  681. CG_AddFragment( le );
  682. break;
  683. case LE_MOVE_SCALE_FADE: // water bubbles
  684. CG_AddMoveScaleFade( le );
  685. break;
  686. case LE_FADE_RGB: // teleporters, railtrails
  687. CG_AddFadeRGB( le );
  688. break;
  689. case LE_FALL_SCALE_FADE: // gib blood trails
  690. CG_AddFallScaleFade( le );
  691. break;
  692. case LE_SCALE_FADE: // rocket trails
  693. CG_AddScaleFade( le );
  694. break;
  695. case LE_SCOREPLUM:
  696. CG_AddScorePlum( le );
  697. break;
  698. #ifdef MISSIONPACK
  699. case LE_KAMIKAZE:
  700. CG_AddKamikaze( le );
  701. break;
  702. case LE_INVULIMPACT:
  703. CG_AddInvulnerabilityImpact( le );
  704. break;
  705. case LE_INVULJUICED:
  706. CG_AddInvulnerabilityJuiced( le );
  707. break;
  708. case LE_SHOWREFENTITY:
  709. CG_AddRefEntity( le );
  710. break;
  711. #endif
  712. }
  713. }
  714. }