1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 //
21 // cg_parttrail.c
22 //
23 
24 #include "cg_local.h"
25 
26 /*
27 =============================================================================
28 
29 	PARTICLE TRAILS
30 
31 =============================================================================
32 */
33 
34 /*
35 ===============
36 CG_BeamTrail
37 ===============
38 */
CG_BeamTrail(vec3_t start,vec3_t end,int color,float size,float alpha,float alphaVel)39 void __fastcall CG_BeamTrail (vec3_t start, vec3_t end, int color, float size, float alpha, float alphaVel)
40 {
41 	vec3_t		dest, move, vec;
42 	float		len, dec;
43 	float		run;
44 
45 	Vec3Copy (start, move);
46 	Vec3Subtract (end, start, vec);
47 	len = VectorNormalizeFastf (vec);
48 
49 	dec = 35.0f - (rand () % 27);
50 	Vec3Scale (vec, dec, vec);
51 
52 	for (; len>0 ; Vec3Add (move, vec, move)) {
53 		len -= dec;
54 
55 		if ((crand () > 0) || (rand () % 14))
56 			continue;
57 
58 		Vec3Copy (move, dest);
59 
60 		dest[0] += ((rand () % ((int)(size*32) + 1) - (int)(size*16))/32);
61 		dest[1] += ((rand () % ((int)(size*32) + 1) - (int)(size*16))/32);
62 		dest[2] += ((rand () % ((int)(size*32) + 1) - (int)(size*16))/32);
63 
64 		run = (frand () * 50);
65 		CG_SpawnParticle (
66 			dest[0],							dest[1],							dest[2],
67 			0,									0,									0,
68 			0,									0,									0,
69 			0,									0,									0,
70 			palRed (color) + run,				palGreen (color) + run,				palBlue (color) + run,
71 			palRed (color) + run,				palGreen (color) + run,				palBlue (color) + run,
72 			alpha,								alphaVel,
73 			size / 3.0f,						0.1f + (frand () * 0.1f),
74 			PT_FLAREGLOW,						0,
75 			0,									qFalse,
76 			PART_STYLE_QUAD,
77 			0);
78 	}
79 }
80 
81 
82 /*
83 ===============
84 CG_BfgTrail
85 ===============
86 */
CG_BfgTrail(refEntity_t * ent)87 void CG_BfgTrail (refEntity_t *ent)
88 {
89 	int			i;
90 	float		angle, sr, sp, sy, cr, cp, cy;
91 	float		ltime, size, dist = 64;
92 	vec3_t		forward, org;
93 
94 	// Outer
95 	CG_SpawnParticle (
96 		ent->origin[0],					ent->origin[1],					ent->origin[2],
97 		0,								0,								0,
98 		0,								0,								0,
99 		0,								0,								0,
100 		0,								200,							0,
101 		0,								200,							0,
102 		0.66f,							PART_INSTANT,
103 		60,								60,
104 		PT_BFG_DOT,						PF_SCALED,
105 		0,								qFalse,
106 		PART_STYLE_QUAD,
107 		0);
108 
109 	// Core
110 	CG_FlareEffect (ent->origin, PT_FLAREGLOW, 0 + (frand () * 32), 45, 45, 0xd0, 0xd0, 0.66f, PART_INSTANT);
111 	CG_FlareEffect (ent->origin, PT_FLAREGLOW, 180 + (frand () * 32), 55, 55, 0xd0, 0xd0, 0.66f, PART_INSTANT);
112 
113 	CG_FlareEffect (ent->origin, PT_FLAREGLOW, 0 + (frand () * 32), 35, 35, 0xd7, 0xd7, 0.66f, PART_INSTANT);
114 	CG_FlareEffect (ent->origin, PT_FLAREGLOW, 180 + (frand () * 32), 45, 45, 0xd7, 0xd7, 0.66f, PART_INSTANT);
115 
116 	ltime = (float)cg.realTime / 1000.0f;
117 	for (i=0 ; i<(NUMVERTEXNORMALS/2.0f) ; i++) {
118 		angle = ltime * cg_randVels[i][0];
119 		sy = (float)sin (angle);
120 		cy = (float)cos (angle);
121 		angle = ltime * cg_randVels[i][1];
122 		sp = (float)sin (angle);
123 		cp = (float)cos (angle);
124 		angle = ltime * cg_randVels[i][2];
125 		sr = (float)sin (angle);
126 		cr = (float)cos (angle);
127 
128 		Vec3Set (forward, cp*cy, cp*sy, -sp);
129 
130 		org[0] = ent->origin[0] + (m_byteDirs[i][0] * (float)sin (ltime + i) * 64) + (forward[0] * BEAMLENGTH);
131 		org[1] = ent->origin[1] + (m_byteDirs[i][1] * (float)sin (ltime + i) * 64) + (forward[0] * BEAMLENGTH);
132 		org[2] = ent->origin[2] + (m_byteDirs[i][2] * (float)sin (ltime + i) * 64) + (forward[0] * BEAMLENGTH);
133 
134 		dist = Vec3DistFast (org, ent->origin) / 90.0f;
135 
136 		size = (2 - (dist * 2 + 0.1f)) * 12;
137 		CG_SpawnParticle (
138 			org[0],								org[1],								org[2],
139 			0,									0,									0,
140 			0,									0,									0,
141 			0,									0,									0,
142 			115 + ((1 - (dist * 3)) * 40),		180 + ((1 - (dist * 3)) * 75),		115 + ((1 - (dist * 3)) * 40),
143 			115 + ((1 - (dist * 3)) * 40),		180 + ((1 - (dist * 3)) * 75),		115 + ((1 - (dist * 3)) * 40),
144 			0.95f - dist/2.0f,					-100,
145 			size,								size,
146 			PT_BFG_DOT,							PF_SCALED|PF_NOCLOSECULL,
147 			0,									qFalse,
148 			PART_STYLE_QUAD,
149 			0);
150 
151 		// Sparks
152 		if (!(rand () & 15)) {
153 			CG_SpawnParticle (
154 				org[0] + (crand () * 4),			org[1] + (crand () * 4),			org[2] + (crand () * 4),
155 				0,									0,									0,
156 				crand () * 16,						crand () * 16,						crand () * 16,
157 				0,									0,									-20,
158 				115 + ((1 - (dist * 3)) * 40),		180 + ((1 - (dist * 3)) * 75),		115 + ((1 - (dist * 3)) * 40),
159 				115 + ((1 - (dist * 3)) * 40),		180 + ((1 - (dist * 3)) * 75),		115 + ((1 - (dist * 3)) * 40),
160 				1.0f,								-0.9f / (0.4f + (frand () * 0.3f)),
161 				0.5f + (frand () * 0.25f),			0.4f + (frand () * 0.25f),
162 				PT_BFG_DOT,							PF_SCALED,
163 				pSplashThink,						qTrue,
164 				PART_STYLE_DIRECTION,
165 				PMAXSPLASHLEN);
166 		}
167 	}
168 }
169 
170 
171 /*
172 ===============
173 CG_BlasterGoldTrail
174 ===============
175 */
CG_BlasterGoldTrail(vec3_t start,vec3_t end)176 void CG_BlasterGoldTrail (vec3_t start, vec3_t end)
177 {
178 	vec3_t		move, vec;
179 	float		len, orgscale, velscale;
180 	int			dec, rnum, rnum2;
181 
182 	// Bubbles
183 	if (rand () % 2)
184 		CG_BubbleEffect (start);
185 
186 	// Dot trail
187 	Vec3Copy (start, move);
188 	Vec3Subtract (end, start, vec);
189 	len = VectorNormalizeFastf (vec);
190 
191 	dec = 5;
192 	Vec3Scale (vec, dec, vec);
193 
194 	if (cg.currGameMod == GAME_MOD_GLOOM) {
195 		orgscale = 0.5f;
196 		velscale = 3.0f;
197 	}
198 	else {
199 		orgscale = 0.75f;
200 		velscale = 4.0f;
201 	}
202 
203 	for (; len>0 ; Vec3Add (move, vec, move)) {
204 		len -= dec;
205 
206 		rnum = (rand () % 5);
207 		rnum2 = (rand () % 5);
208 		CG_SpawnParticle (
209 			move[0] + (crand () * orgscale),	move[1] + (crand () * orgscale),	move[2] + (crand () * orgscale),
210 			0,									0,									0,
211 			crand () * velscale,				crand () * velscale,				crand () * velscale,
212 			0,									0,									0,
213 			palRed (0xe0 + rnum),				palGreen (0xe0 + rnum),				palBlue (0xe0 + rnum),
214 			palRed (0xe0 + rnum2),				palGreen (0xe0 + rnum2),			palBlue (0xe0 + rnum2),
215 			1.0f,								-1.0f / (0.25f + (crand () * 0.05f)),
216 			7 + crand (),						frand () * 5,
217 			PT_BLASTER_RED,						PF_NOCLOSECULL,
218 			0,									qFalse,
219 			PART_STYLE_QUAD,
220 			0);
221 	}
222 }
223 
224 
225 /*
226 ===============
227 CG_BlasterGreenTrail
228 ===============
229 */
CG_BlasterGreenTrail(vec3_t start,vec3_t end)230 void CG_BlasterGreenTrail (vec3_t start, vec3_t end)
231 {
232 	vec3_t		move, vec;
233 	float		len, orgscale, velscale;
234 	int			dec, rnum, rnum2;
235 
236 	// bubbles
237 	if (rand () % 2)
238 		CG_BubbleEffect (start);
239 
240 	Vec3Copy (start, move);
241 	Vec3Subtract (end, start, vec);
242 	len = VectorNormalizeFastf (vec);
243 
244 	dec = 5;
245 	Vec3Scale (vec, dec, vec);
246 
247 	if (cg.currGameMod == GAME_MOD_GLOOM) {
248 		orgscale = 0.5;
249 		velscale = 3;
250 	}
251 	else {
252 		orgscale = 1;
253 		velscale = 5;
254 	}
255 
256 	for (; len>0 ; Vec3Add (move, vec, move)) {
257 		len -= dec;
258 
259 		rnum = (rand () % 5);
260 		rnum2 = (rand () % 5);
261 
262 		CG_SpawnParticle (
263 			move[0] + (crand () * orgscale),	move[1] + (crand () * orgscale),	move[2] + (crand ()* orgscale),
264 			0,									0,									0,
265 			crand () * velscale,				crand () * velscale,				crand () * velscale,
266 			0,									0,									0,
267 			palRed (0xd0 + rnum),				palGreen (0xd0 + rnum),				palBlue (0xd0 + rnum),
268 			palRed (0xd0 + rnum2),				palGreen (0xd0 + rnum2),			palBlue (0xd0 + rnum2),
269 			1.0f,								-1.0f / (0.25f + (crand () * 0.05f)),
270 			5,									1,
271 			PT_BLASTER_GREEN,					PF_NOCLOSECULL,
272 			0,									qFalse,
273 			PART_STYLE_QUAD,
274 			0);
275 	}
276 }
277 
278 
279 /*
280 ===============
281 CG_BubbleTrail
282 ===============
283 */
CG_BubbleTrail(vec3_t start,vec3_t end)284 void CG_BubbleTrail (vec3_t start, vec3_t end)
285 {
286 	vec3_t		move, vec;
287 	float		len;
288 	float		rnum, rnum2;
289 	int			i, dec;
290 
291 	Vec3Copy (start, move);
292 	Vec3Subtract (end, start, vec);
293 	len = VectorNormalizeFastf (vec);
294 
295 	dec = 32;
296 	Vec3Scale (vec, dec, vec);
297 
298 	for (i=0 ; i<len ; i+=dec, Vec3Add (move, vec, move)) {
299 		rnum = 230 + (frand () * 25);
300 		rnum2 = 230 + (frand () * 25);
301 
302 		CG_SpawnParticle (
303 			move[0] + crand (),				move[1] + crand (),				move[2] + crand (),
304 			0,								0,								0,
305 			crand () * 4,					crand () * 4,					10 + (crand () * 4),
306 			0,								0,								0,
307 			rnum,							rnum,							rnum,
308 			rnum2,							rnum2,							rnum2,
309 			0.9f + (crand () * 0.1f),		-1.0f / (3 + (frand () * 0.2f)),
310 			0.1f + frand (),				0.1f + frand (),
311 			PT_WATERBUBBLE,					PF_SHADE|PF_LAVAONLY|PF_SLIMEONLY|PF_WATERONLY|PF_NOCLOSECULL,
312 			0,								qFalse,
313 			PART_STYLE_QUAD,
314 			0);
315 	}
316 }
317 
318 
319 /*
320 ===============
321 CG_BubbleTrail2
322 
323 lets you control the number of bubbles by setting the distance between the spawns
324 ===============
325 */
CG_BubbleTrail2(vec3_t start,vec3_t end,int dist)326 void CG_BubbleTrail2 (vec3_t start, vec3_t end, int dist)
327 {
328 	vec3_t		move, vec;
329 	float		len;
330 	float		rnum, rnum2;
331 	int			i, dec;
332 
333 	Vec3Copy (start, move);
334 	Vec3Subtract (end, start, vec);
335 	len = VectorNormalizeFastf (vec);
336 
337 	dec = dist;
338 	Vec3Scale (vec, dec, vec);
339 
340 	for (i=0 ; i<len ; i+=dec, Vec3Add (move, vec, move)) {
341 		rnum = 230 + (frand () * 25);
342 		rnum2 = 230 + (frand () * 25);
343 
344 		CG_SpawnParticle (
345 			move[0] + crand (),				move[1] + crand (),				move[2] + crand (),
346 			0,								0,								0,
347 			crand () * 4,					crand () * 4,					10 + (crand () * 4),
348 			0,								0,								0,
349 			rnum,							rnum,							rnum,
350 			rnum2,							rnum2,							rnum2,
351 			0.9f + (crand () * 0.1f),		-1.0f / (3 + (frand () * 0.1f)),
352 			0.1f + frand (),				0.1f + frand (),
353 			PT_WATERBUBBLE,					PF_SHADE|PF_LAVAONLY|PF_SLIMEONLY|PF_WATERONLY|PF_NOCLOSECULL,
354 			0,								qFalse,
355 			PART_STYLE_QUAD,
356 			0);
357 	}
358 }
359 
360 
361 /*
362 ===============
363 CG_DebugTrail
364 ===============
365 */
CG_DebugTrail(vec3_t start,vec3_t end)366 void CG_DebugTrail (vec3_t start, vec3_t end)
367 {
368 	vec3_t		move, vec, right, up;
369 	float		len, dec, rnum, rnum2;
370 
371 	Vec3Copy (start, move);
372 	Vec3Subtract (end, start, vec);
373 	len = VectorNormalizeFastf (vec);
374 
375 	MakeNormalVectorsf (vec, right, up);
376 
377 	dec = 3;
378 	Vec3Scale (vec, dec, vec);
379 	Vec3Copy (start, move);
380 
381 	for (; len>0 ; Vec3Add (move, vec, move)) {
382 		len -= dec;
383 
384 		rnum = frand () * 40;
385 		rnum2 = frand () * 40;
386 		CG_SpawnParticle (
387 			move[0],						move[1],						move[2],
388 			0,								0,								0,
389 			0,								0,								0,
390 			0,								0,								0,
391 			0,								rnum,							215 + rnum,
392 			0,								rnum2,							215 + rnum2,
393 			1.0f,							-0.1f,
394 			3.0f,							1.0f,
395 			PT_BLASTER_BLUE,				PF_SCALED|PF_NOCLOSECULL,
396 			0,								qFalse,
397 			PART_STYLE_QUAD,
398 			0);
399 	}
400 }
401 
402 
403 /*
404 ===============
405 CG_FlagTrail
406 ===============
407 */
CG_FlagTrail(vec3_t start,vec3_t end,int flags)408 void CG_FlagTrail (vec3_t start, vec3_t end, int flags)
409 {
410 	vec3_t		move, vec;
411 	float		len, dec;
412 	float		clrmod;
413 
414 	Vec3Copy (start, move);
415 	Vec3Subtract (end, start, vec);
416 	len = VectorNormalizeFastf (vec);
417 
418 	dec = 4;
419 	Vec3Scale (vec, dec, vec);
420 
421 	// red
422 	if (flags & EF_FLAG1) {
423 		for (; len>0 ; Vec3Add (move, vec, move)) {
424 			len -= dec;
425 
426 			clrmod = (rand () % 2) ? (rand () % 170) : 0.0f;
427 			CG_SpawnParticle (
428 				move[0] + (crand () * 6),		move[1] + (crand () * 6),		move[2] + (crand () * 6),
429 				0,								0,								0,
430 				(crand () * 8),					(crand () * 8),					(crand () * 8),
431 				0,								0,								0,
432 				140 + (frand () * 50) + clrmod,	clrmod,							clrmod,
433 				140 + (frand () * 50) + clrmod,	clrmod,							clrmod,
434 				1.0f,							-1.0f / (0.8f + (frand () * 0.2f)),
435 				5,								2,
436 				PT_FLAREGLOW,					PF_SCALED|PF_NOCLOSECULL,
437 				0,								qFalse,
438 				PART_STYLE_QUAD,
439 				0);
440 		}
441 	}
442 
443 	// blue
444 	if (flags & EF_FLAG2) {
445 		for (; len>0 ; Vec3Add (move, vec, move)) {
446 			len -= dec;
447 
448 			clrmod = (rand () % 2) ? (rand () % 170) : 0.0f;
449 			CG_SpawnParticle (
450 				move[0] + (crand () * 6),		move[1] + (crand () * 6),		move[2] + (crand () * 6),
451 				0,								0,								0,
452 				crand () * 8,					crand () * 8,					crand () * 8,
453 				0,								0,								0,
454 				clrmod,							clrmod + (frand () * 70),		clrmod + 230 + (frand () * 50),
455 				clrmod,							clrmod + (frand () * 70),		clrmod + 230 + (frand () * 50),
456 				1.0f,							-1.0f / (0.8f + (frand () * 0.2f)),
457 				5,								2,
458 				PT_FLAREGLOW,					PF_SCALED|PF_NOCLOSECULL,
459 				0,								qFalse,
460 				PART_STYLE_QUAD,
461 				0);
462 		}
463 	}
464 }
465 
466 
467 /*
468 ===============
469 CG_GibTrail
470 ===============
471 */
CG_GibTrail(vec3_t start,vec3_t end,int flags)472 void CG_GibTrail (vec3_t start, vec3_t end, int flags)
473 {
474 	vec3_t		move, vec;
475 	float		len, dec;
476 	int			i, partFlags;
477 
478 	// Bubbles
479 	if (!(rand () % 10))
480 		CG_BubbleEffect (start);
481 
482 	// Blotches and more drips
483 	Vec3Copy (start, move);
484 	Vec3Subtract (end, start, vec);
485 	len = VectorNormalizeFastf (vec);
486 
487 	dec = 3.25f;
488 	Vec3Scale (vec, dec, vec);
489 
490 	//
491 	// EF_GIB
492 	//
493 	if (flags == EF_GIB) {
494 		for ( ; len > 0 ; Vec3Add (move, vec, move)) {
495 			len -= dec;
496 			// Floating blotches
497 			if (!(rand () & 31)) {
498 				partFlags = PF_SCALED|PF_ALPHACOLOR;
499 				if (rand () & 7)
500 					partFlags |= PF_NODECAL;
501 
502 				CG_SpawnParticle (
503 					move[0] + crand (),				move[1] + crand (),				move[2] + crand (),
504 					0,								0,								0,
505 					crand (),						crand (),						crand () - 40,
506 					0,								0,								0,
507 					115 + (frand () * 5),			125 + (frand () * 10),			120 + (frand () * 10),
508 					0,								0,								0,
509 					1.0f,							-0.5f / (0.4f + (frand () * 0.3f)),
510 					7.5f + (crand () * 2),			9 + (crand () * 2),
511 					pRandBloodMark (),				partFlags,
512 					pBloodThink,					qTrue,
513 					PART_STYLE_QUAD,
514 					frand () * 360);
515 			}
516 
517 			// Drip
518 			for (i=0 ; i<(clamp (cg_particleGore->floatVal + 1, 1, 11) / 5.0) ; i++) {
519 				if (!(rand () & 15)) {
520 					partFlags = PF_ALPHACOLOR|PF_GRAVITY;
521 					if (rand () & 1)
522 						partFlags |= PF_NODECAL;
523 
524 					CG_SpawnParticle (
525 						move[0] + crand (),				move[1] + crand (),				move[2] + crand () - (frand () * 4),
526 						0,								0,								0,
527 						crand () * 50,					crand () * 50,					crand () * 50 + 20,
528 						crand () * 10,					crand () * 10,					-50,
529 						230 + (frand () * 5),			245 + (frand () * 10),			245 + (frand () * 10),
530 						0,								0,								0,
531 						1.0f,							-0.5f / (0.6f + (frand ()* 0.3f)),
532 						1.25f + (frand () * 0.2f),		1.35f + (frand () * 0.2f),
533 						pRandBloodDrip (),				partFlags,
534 						pBloodDripThink,				qTrue,
535 						PART_STYLE_DIRECTION,
536 						PMAXBLDDRIPLEN*0.5f + (frand () * PMAXBLDDRIPLEN));
537 				}
538 			}
539 		}
540 
541 		return;
542 	}
543 
544 	//
545 	// EF_GREENGIB
546 	//
547 	if (flags == EF_GREENGIB) {
548 		for ( ; len > 0 ; Vec3Add (move, vec, move)) {
549 			len -= dec;
550 			// Floating blotches
551 			if (!(rand () & 31)) {
552 				partFlags = PF_SCALED|PF_ALPHACOLOR|PF_GREENBLOOD;
553 				if (rand () & 7)
554 					partFlags |= PF_NODECAL;
555 
556 				CG_SpawnParticle (
557 					move[0] + crand (),				move[1] + crand (),				move[2] + crand (),
558 					0,								0,								0,
559 					crand (),						crand (),						crand () - 40,
560 					0,								0,								0,
561 					20,								50 + (frand () * 90),			20,
562 					0,								0 + (frand () * 90),			0,
563 					0.8f + (frand () * 0.2f),		-1.0f / (0.5f + (frand () * 0.3f)),
564 					4 + (crand () * 2),				6 + (crand () * 2),
565 					pRandGrnBloodMark (),			partFlags,
566 					pBloodThink,					qTrue,
567 					PART_STYLE_QUAD,
568 					frand () * 360);
569 			}
570 
571 			// Drip
572 			for (i=0 ; i<(clamp (cg_particleGore->floatVal + 1, 1, 11) / 5.0) ; i++) {
573 				if (!(rand () & 15)) {
574 					partFlags = PF_ALPHACOLOR|PF_GRAVITY|PF_GREENBLOOD;
575 					if (rand () & 1)
576 						partFlags |= PF_NODECAL;
577 
578 					CG_SpawnParticle (
579 						move[0] + crand (),				move[1] + crand (),				move[2] + crand () - (frand () * 4),
580 						0,								0,								0,
581 						crand () * 50,					crand () * 50,					crand () * 50 + 20,
582 						crand () * 10,					crand () * 10,					-50,
583 						30,								70 + (frand () * 90),			30,
584 						0,								0,								0,
585 						1.0f,							-0.5f / (0.6f + (frand () * 0.3f)),
586 						1.25f + (frand () * 0.2f),		1.35f + (frand () * 0.2f),
587 						pRandGrnBloodDrip (),			partFlags,
588 						pBloodDripThink,				qTrue,
589 						PART_STYLE_DIRECTION,
590 						PMAXBLDDRIPLEN*0.5f + (frand () * PMAXBLDDRIPLEN));
591 				}
592 			}
593 		}
594 
595 		return;
596 	}
597 }
598 
599 
600 /*
601 ===============
602 CG_GrenadeTrail
603 ===============
604 */
CG_GrenadeTrail(vec3_t start,vec3_t end)605 void CG_GrenadeTrail (vec3_t start, vec3_t end)
606 {
607 	vec3_t		move, vec;
608 	float		len, dec;
609 	float		rnum, rnum2;
610 
611 	// Smoke
612 	Vec3Copy (start, move);
613 	Vec3Subtract (end, start, vec);
614 	len = VectorNormalizeFastf (vec);
615 
616 	// Didn't move far enough to deserve a trail
617 	if (len <= 0.001f)
618 		return;
619 
620 	// Bubbles
621 	CG_BubbleEffect (start);
622 
623 	// Smoke trail
624 	dec = 35;
625 	Vec3Scale (vec, dec, vec);
626 
627 	len++, dec++;
628 	for (; len>0 ; Vec3Add (move, vec, move)) {
629 		len -= dec;
630 
631 		rnum = 60 + (frand () * 50);
632 		rnum2 = 70 + (frand () * 50);
633 		CG_SpawnParticle (
634 			move[0] + (crand () * 2),		move[1] + (crand () * 2),		move[2] + (crand () * 2),
635 			0,								0,								0,
636 			crand () * 3,					crand () * 3,					crand () * 3,
637 			0,								0,								5,
638 			rnum,							rnum,							rnum,
639 			rnum2,							rnum2,							rnum2,
640 			0.8f + (crand () * 0.1f),		-3.0f / (1.0f + cg_particleSmokeLinger->floatVal + (crand () * 0.1f)),
641 			6 + (crand () * 3),				20 + (crand () * 5),
642 			pRandSmoke (),					PF_SHADE|PF_NOCLOSECULL,
643 			pSmokeThink,					qTrue,
644 			PART_STYLE_QUAD,
645 			frand () * 360);
646 	}
647 }
648 
649 
650 /*
651 ===============
652 CG_Heatbeam
653 ===============
654 */
CG_Heatbeam(vec3_t start,vec3_t forward)655 void CG_Heatbeam (vec3_t start, vec3_t forward)
656 {
657 	vec3_t		move, vec, right, up, dir, end;
658 	int			len, rnum, rnum2;
659 	float		c, s, ltime, rstep;
660 	float		i, step, start_pt, rot, variance;
661 
662 	step = 32;
663 
664 	Vec3MA (start, 4096, forward, end);
665 
666 	Vec3Copy (start, move);
667 	Vec3Subtract (end, start, vec);
668 	len = (int)VectorNormalizeFastf (vec);
669 
670 	Vec3Copy (cg.refDef.rightVec, right);
671 	Vec3Copy (cg.refDef.viewAxis[2], up);
672 	Vec3MA (move, -0.5f, right, move);
673 	Vec3MA (move, -0.5f, up, move);
674 
675 	ltime = (float) cg.realTime / 1000.0f;
676 	start_pt = (float)fmod (ltime * 96.0f, step);
677 	Vec3MA (move, start_pt, vec, move);
678 
679 	Vec3Scale (vec, step, vec);
680 
681 	rstep = M_PI / 10.0f;
682 	for (i=start_pt ; i<len ; i+=step) {
683 		if (i == 0)
684 			i = 0.01f;
685 		if (i > step * 5)
686 			break;
687 
688 		variance = 0.5;
689 		for (rot=0 ; rot<(M_PI * 2.0f) ; rot += rstep) {
690 			c = (float)cos (rot) * variance;
691 			s = (float)sin (rot) * variance;
692 
693 			// trim it so it looks like it's starting at the origin
694 			if (i < 10) {
695 				Vec3Scale (right, c*(i/10.0f), dir);
696 				Vec3MA (dir, s*(i/10.0f), up, dir);
697 			}
698 			else {
699 				Vec3Scale (right, c, dir);
700 				Vec3MA (dir, s, up, dir);
701 			}
702 
703 			rnum = (rand () % 5);
704 			rnum2 = (rand () % 5);
705 			CG_SpawnParticle (
706 				move[0] + dir[0]*3,				move[1] + dir[1]*3,				move[2] + dir[2]*3,
707 				0,								0,								0,
708 				0,								0,								0,
709 				0,								0,								0,
710 				palRed (223 - rnum),			palGreen (223 - rnum),			palBlue (223 - rnum),
711 				palRed (223 - rnum2),			palGreen (223 - rnum2),			palBlue (223 - rnum2),
712 				0.5,							-1000.0,
713 				1.0f,							1.0f,
714 				PT_GENERIC_GLOW,				PF_SCALED|PF_NOCLOSECULL,
715 				0,								qFalse,
716 				PART_STYLE_QUAD,
717 				0);
718 		}
719 
720 		Vec3Add (move, vec, move);
721 	}
722 }
723 
724 
725 /*
726 ===============
727 CG_IonripperTrail
728 ===============
729 */
CG_IonripperTrail(vec3_t start,vec3_t end)730 void CG_IonripperTrail (vec3_t start, vec3_t end)
731 {
732 	vec3_t	move, vec;
733 	vec3_t	tmpstart, tmpend;
734 	float	dec, len;
735 	int		left = 0, rnum, rnum2;
736 	float	tnum;
737 
738 	// gloom optional spiral
739 	Vec3Copy (start, tmpstart);
740 	Vec3Copy (end, tmpend);
741 	if (cg.currGameMod == GAME_MOD_GLOOM) {
742 		float		c, s;
743 		vec3_t		dir, right, up;
744 		int			i;
745 
746 		// I AM LAME ASS -- HEAR MY ROAR!
747 		tmpstart[2] += 12;
748 		tmpend[2] += 12;
749 		// I AM LAME ASS -- HEAR MY ROAR!
750 
751 		if (glm_blobtype->intVal) {
752 			Vec3Copy (tmpstart, move);
753 			Vec3Subtract (tmpend, tmpstart, vec);
754 			len = VectorNormalizeFastf (vec);
755 
756 			MakeNormalVectorsf (vec, right, up);
757 
758 			for (i=0 ; i<len ; i++) {
759 				if (i&1)
760 					continue;
761 
762 				c = (float)cos (i);
763 				s = (float)sin (i);
764 
765 				Vec3Scale (right, c, dir);
766 				Vec3MA (dir, s, up, dir);
767 
768 				tnum = (rand () % 2) ? 110 + (frand () * 125) : 0;
769 				CG_SpawnParticle (
770 					move[0] + (dir[0] * 1.15f),		move[1] + (dir[1] * 1.15f),		move[2] + (dir[2] * 1.15f),
771 					0,								0,								0,
772 					dir[0] * 40,					dir[1] * 40,					dir[2] * 40,
773 					0,								0,								0,
774 					tnum,							tnum + 60 + (frand () * 130),	tnum + (frand () * 30),
775 					tnum,							tnum + 60 + (frand () * 130),	tnum + (frand () * 30),
776 					0.9f,							-1.0f / (0.3f + (frand () * 0.2f)),
777 					3.5f,							1.8f,
778 					PT_IONTAIL,						PF_SCALED|PF_NOCLOSECULL,
779 					0,								qFalse,
780 					PART_STYLE_QUAD,
781 					0);
782 
783 				Vec3Add (move, vec, move);
784 			}
785 		}
786 	}
787 
788 	// Bubbles
789 	CG_BubbleEffect (tmpstart);
790 
791 	// Trail
792 	Vec3Copy (tmpstart, move);
793 	Vec3Subtract (tmpend, tmpstart, vec);
794 	len = VectorNormalizeFastf (vec);
795 
796 	dec = 5;
797 	Vec3Scale (vec, dec, vec);
798 
799 	for (; len>0 ; Vec3Add (move, vec, move)) {
800 		len -= dec;
801 
802 		rnum = rand () % 5;
803 		rnum2 = rand () % 5;
804 		CG_SpawnParticle (
805 			move[0],							move[1],							move[2],
806 			0,									0,									0,
807 			left ? 15.0f : -15.0f,				0,									0,
808 			0,									0,									0,
809 			palRed (0xe4 + rnum),				palGreen (0xe4 + rnum),				palBlue (0xe4 + rnum),
810 			palRed (0xe4 + rnum2),				palGreen (0xe4 + rnum2),			palBlue (0xe4 + rnum2),
811 			0.85f,								-1.0f / (0.33f + (frand () * 0.2f)),
812 			8,									3,
813 			PT_IONTIP,							PF_SCALED|PF_NOCLOSECULL,
814 			0,									qFalse,
815 			PART_STYLE_QUAD,
816 			0);
817 
818 		left = !left;
819 	}
820 }
821 
822 
823 /*
824 ===============
825 CG_QuadTrail
826 ===============
827 */
CG_QuadTrail(vec3_t start,vec3_t end)828 void CG_QuadTrail (vec3_t start, vec3_t end)
829 {
830 	vec3_t		move, vec;
831 	float		dec, len, rnum;
832 
833 	Vec3Copy (start, move);
834 	Vec3Subtract (end, start, vec);
835 	len = VectorNormalizeFastf (vec);
836 
837 	dec = 4;
838 	Vec3Scale (vec, dec, vec);
839 
840 	for (; len>0 ; Vec3Add (move, vec, move)) {
841 		len -= dec;
842 
843 		rnum = (rand () % 2) ? (frand () * 200) : 0;
844 		CG_SpawnParticle (
845 			move[0] + (crand () * 6),		move[1] + (crand () * 6),		move[2] + (crand () * 6),
846 			0,								0,								0,
847 			crand () * 8,					crand () * 8,					crand () * 8,
848 			0,								0,								0,
849 			rnum,							rnum + (frand () * 55),			rnum + 200 + (frand () * 50),
850 			rnum,							rnum + (frand () * 55),			rnum + 200 + (frand () * 50),
851 			1.0f,							-1.0f / (0.8f + (frand () * 0.2f)),
852 			5,								2,
853 			PT_FLAREGLOW,					PF_SCALED|PF_NOCLOSECULL,
854 			0,								qFalse,
855 			PART_STYLE_QUAD,
856 			0);
857 	}
858 }
859 
860 
861 /*
862 ===============
863 CG_RailTrail
864 ===============
865 */
CG_RailTrail(vec3_t start,vec3_t end)866 void CG_RailTrail (vec3_t start, vec3_t end)
867 {
868 	float		dec, len, dist;
869 	trace_t		tr;
870 	vec3_t		vec, move;
871 	vec3_t		angle;
872 	vec3_t		length;
873 
874 	// Bubbles
875 	if (cg.currGameMod != GAME_MOD_LOX && cg.currGameMod != GAME_MOD_GIEX) // FIXME: yay hack
876 		CG_BubbleTrail (start, end);
877 
878 	// Beam
879 	Vec3Subtract (end, start, length);
880 	CG_SpawnParticle (
881 		start[0],						start[1],						start[2],
882 		length[0],						length[1],						length[2],
883 		0,								0,								0,
884 		0,								0,								0,
885 		cg_railCoreRed->floatVal * 255,	cg_railCoreGreen->floatVal * 255,	cg_railCoreBlue->floatVal * 255,
886 		cg_railCoreRed->floatVal * 255,	cg_railCoreGreen->floatVal * 255,	cg_railCoreBlue->floatVal * 255,
887 		1.0f,							-0.7f,
888 		1.2f,							1.4f,
889 		PT_RAIL_CORE,					0,
890 		0,								qFalse,
891 		PART_STYLE_BEAM,
892 		0);
893 
894 	// Spots up the center
895 	Vec3Copy (start, move);
896 	Vec3Subtract (end, start, vec);
897 	len = VectorNormalizeFastf (vec);
898 
899 	dec = 20;
900 	Vec3Scale (vec, dec, vec);
901 	Vec3Copy (start, move);
902 
903 	for (; len>0 ; Vec3Add (move, vec, move)) {
904 		len -= dec;
905 
906 		CG_SpawnParticle (
907 			move[0],						move[1],						move[2],
908 			0,								0,								0,
909 			0,								0,								0,
910 			0,								0,								0,
911 			cg_railCoreRed->floatVal*255,	cg_railCoreGreen->floatVal*255,	cg_railCoreBlue->floatVal*255,
912 			cg_railCoreRed->floatVal*255,	cg_railCoreGreen->floatVal*255,	cg_railCoreBlue->floatVal*255,
913 			0.33f,							-1.0f,
914 			1.2f,							1.4f,
915 			PT_GENERIC_GLOW,				PF_NOCLOSECULL,
916 			NULL,							qFalse,
917 			PART_STYLE_QUAD,
918 			frand () * 360);
919 	}
920 
921 	// Spirals
922 	if (cg_railSpiral->intVal) {
923 		Vec3Copy (start, move);
924 		Vec3Subtract (end, start, vec);
925 		len = VectorNormalizeFastf (vec);
926 
927 		dist = Vec3DistFast (start, end);
928 		dist++;
929 
930 		dec = 4;
931 		Vec3Scale (vec, dec, vec);
932 		Vec3Copy (start, move);
933 
934 		for (; len>0 ; Vec3Add (move, vec, move)) {
935 			CG_SpawnParticle (
936 				move[0],						move[1],						move[2],
937 				0,								0,								0,
938 				0,								0,								0,
939 				crand () * 2,					crand () * 2,					crand () * 2,
940 				cg_railSpiralRed->floatVal*255,	cg_railSpiralGreen->floatVal*255,	cg_railSpiralBlue->floatVal*255,
941 				cg_railSpiralRed->floatVal*255,	cg_railSpiralGreen->floatVal*255,	cg_railSpiralBlue->floatVal*255,
942 				0.75f + (crand () * 0.1f),		-(0.5f + ((len/dist)*0.4f)),
943 				5 + crand (),					15 + (crand () * 3),
944 				PT_RAIL_SPIRAL,					PF_NOCLOSECULL,
945 				NULL,							qFalse,
946 				PART_STYLE_QUAD,
947 				frand () * 360);
948 
949 			len -= dec;
950 		}
951 	}
952 
953 	Vec3Copy (start, move);
954 	Vec3Subtract (end, start, vec);
955 	VectorNormalizeFastf (vec);
956 
957 	Vec3Scale (vec, 2, vec);
958 	Vec3Add (move, vec, move);
959 
960 	// Make a decal
961 	tr = cgi.CM_Trace (move, end, 1, 1);
962 	if (tr.fraction < 1) {
963 		CG_SparkEffect (tr.endPos, tr.plane.normal, 10, 10, 20, 2, 3);
964 
965 		// wave
966 		VecToAngleRolled (tr.plane.normal, frand () * 360, angle);
967 
968 		CG_SpawnParticle (
969 			tr.endPos[0] + tr.plane.normal[0],	tr.endPos[1] + tr.plane.normal[0],	tr.endPos[2] + tr.plane.normal[0],
970 			angle[0],							angle[1],							angle[2],
971 			0,									0,									0,
972 			0,									0,									0,
973 			cg_railCoreRed->floatVal*255,			cg_railCoreGreen->floatVal*255,		cg_railCoreBlue->floatVal*255,
974 			cg_railCoreRed->floatVal*255,			cg_railCoreGreen->floatVal*255,		cg_railCoreBlue->floatVal*255,
975 			0.7f + (crand () * 0.1f),			-1.0f / (0.3f + (frand () * 0.1f)),
976 			5 + (crand () * 2),					30 + (crand () * 5),
977 			PT_RAIL_WAVE,						PF_SCALED,
978 			NULL,								qFalse,
979 			PART_STYLE_ANGLED,
980 			0);
981 
982 		// fast-fading mark
983 		CG_SpawnDecal (
984 			tr.endPos[0],						tr.endPos[1],						tr.endPos[2],
985 			tr.plane.normal[0],					tr.plane.normal[1],					tr.plane.normal[2],
986 			cg_railCoreRed->floatVal*255,		cg_railCoreGreen->floatVal*255,		cg_railCoreBlue->floatVal*255,
987 			cg_railCoreRed->floatVal*255,		cg_railCoreGreen->floatVal*255,		cg_railCoreBlue->floatVal*255,
988 			1.0f,								0,
989 			10 + crand (),
990 			DT_RAIL_WHITE,						DF_FIXED_LIFE,
991 			0,									qFalse,
992 			0.25f + (frand () * 0.25f),			frand () * 360.0f);
993 
994 		// burn mark
995 		CG_SpawnDecal (
996 			tr.endPos[0],						tr.endPos[1],							tr.endPos[2],
997 			tr.plane.normal[0],					tr.plane.normal[1],						tr.plane.normal[2],
998 			(cg_railCoreRed->floatVal*128)+128,	(cg_railCoreGreen->floatVal*128)+128,	(cg_railCoreBlue->floatVal*128)+128,
999 			0,									0,										0,
1000 			0.9f + (crand () * 0.1f),			0.8f,
1001 			10 + crand (),
1002 			DT_RAIL_BURNMARK,					DF_ALPHACOLOR,
1003 			0,									qFalse,
1004 			0,									frand () * 360.0f);
1005 
1006 		// "flashing" glow marks
1007 		CG_SpawnDecal (
1008 			tr.endPos[0],					tr.endPos[1],					tr.endPos[2],
1009 			tr.plane.normal[0],				tr.plane.normal[1],				tr.plane.normal[2],
1010 			cg_railCoreRed->floatVal*255,	cg_railCoreGreen->floatVal*255,	cg_railCoreBlue->floatVal*255,
1011 			cg_railCoreRed->floatVal*255,	cg_railCoreGreen->floatVal*255,	cg_railCoreBlue->floatVal*255,
1012 			1.0f,							0,
1013 			30,
1014 			DT_RAIL_GLOWMARK,				DF_FIXED_LIFE,
1015 			0,								qFalse,
1016 			0.25f + (frand () * 0.25f),		frand () * 360.0f);
1017 
1018 		if (!cg_railSpiral->intVal) {
1019 			CG_SpawnDecal (
1020 				tr.endPos[0],					tr.endPos[1],						tr.endPos[2],
1021 				tr.plane.normal[0],				tr.plane.normal[1],					tr.plane.normal[2],
1022 				cg_railSpiralRed->floatVal*255,	cg_railSpiralGreen->floatVal*255,	cg_railSpiralBlue->floatVal*255,
1023 				cg_railSpiralRed->floatVal*255,	cg_railSpiralGreen->floatVal*255,	cg_railSpiralBlue->floatVal*255,
1024 				1.0f,							0,
1025 				12,
1026 				DT_RAIL_GLOWMARK,				DF_FIXED_LIFE,
1027 				0,								qFalse,
1028 				0.25f + (frand () * 0.25f),		frand () * 360.0f);
1029 		}
1030 	}
1031 }
1032 
1033 
1034 /*
1035 ===============
1036 CG_RocketTrail
1037 ===============
1038 */
CG_RocketTrail(vec3_t start,vec3_t end)1039 void CG_RocketTrail (vec3_t start, vec3_t end)
1040 {
1041 	int			fire;
1042 	vec3_t		move, vec;
1043 	float		len, dec;
1044 	float		rnum, rnum2;
1045 	qBool		inWater;
1046 
1047 	// Check if in water
1048 	if (cgi.CM_PointContents (start, 0) & MASK_WATER)
1049 		inWater = qTrue;
1050 	else
1051 		inWater = qFalse;
1052 
1053 	// Distance and vectors for trails
1054 	Vec3Copy (start, move);
1055 	Vec3Subtract (start, end, vec);
1056 	len = VectorNormalizeFastf (vec);
1057 
1058 	dec = 2.5f + (inWater ? 1 : 0);
1059 	Vec3Scale (vec, dec, vec);
1060 
1061 	// Didn't move far enough to deserve a trail
1062 	if (len <= 0.001f)
1063 		return;
1064 
1065 	// Bubbles
1066 	if (inWater)
1067 		CG_BubbleTrail (start, end);
1068 
1069 	// Flare glow
1070 	if (inWater) {
1071 		CG_SpawnParticle (
1072 			start[0],						start[1],						start[2],
1073 			0,								0,								0,
1074 			0,								0,								0,
1075 			0,								0,								0,
1076 			35.0f,							30.0f,							230.0f,
1077 			35.0f,							30.0f,							230.0f,
1078 			0.66f + (crand () * 0.3f),		PART_INSTANT,
1079 			12 + crand (),					15,
1080 			PT_FLAREGLOW,					0,
1081 			0,								qFalse,
1082 			PART_STYLE_QUAD,
1083 			0);
1084 	}
1085 	else {
1086 		CG_SpawnParticle (
1087 			start[0],						start[1],						start[2],
1088 			0,								0,								0,
1089 			0,								0,								0,
1090 			0,								0,								0,
1091 			255.0f,							170.0f,							100.0f,
1092 			255.0f,							170.0f,							100.0f,
1093 			0.66f + (crand () * 0.3f),		PART_INSTANT,
1094 			12 + crand (),					15,
1095 			PT_FLAREGLOW,					0,
1096 			0,								qFalse,
1097 			PART_STYLE_QUAD,
1098 			0);
1099 	}
1100 
1101 	// White flare core
1102 	CG_SpawnParticle (
1103 		start[0],						start[1],						start[2],
1104 		0,								0,								10,
1105 		0,								0,								0,
1106 		0,								0,								0,
1107 		255.0f,							255.0f,							255.0f,
1108 		255.0f,							255.0f,							255.0f,
1109 		0.66f + (crand () * 0.3f),		PART_INSTANT,
1110 		10 + crand (),					15,
1111 		PT_FLAREGLOW,					0,
1112 		0,								qFalse,
1113 		PART_STYLE_QUAD,
1114 		0);
1115 
1116 	// Trail elements
1117 	fire = inWater ? PT_BLUEFIRE : pRandFire ();
1118 	for (; len>0 ; Vec3Add (move, vec, move)) {
1119 		len -= dec;
1120 
1121 		if (rand () & 1) {
1122 			// Fire
1123 			CG_SpawnParticle (
1124 				move[0] + crand (),					move[1] + crand (),					move[2] + crand (),
1125 				0,									0,									0,
1126 				crand () * 20,						crand () * 20,						crand () * 20,
1127 				0,									0,									0,
1128 				235 + (frand () * 20),				235 + (frand () * 20),				235 + (frand () * 20),
1129 				235 + (frand () * 20),				235 + (frand () * 20),				235 + (frand () * 20),
1130 				0.9f + (crand () * 0.1f),			-1.0f / (0.2f + (crand () * 0.05f)),
1131 				3 + (frand () * 4),					10 + (frand () * 5),
1132 				fire,								PF_NOCLOSECULL,
1133 				pFireThink,							qTrue,
1134 				PART_STYLE_QUAD,
1135 				frand () * 360);
1136 
1137 			// Embers
1138 			if (!inWater && !(rand () % 5))
1139 				CG_SpawnParticle (
1140 					move[0],							move[1],							move[2],
1141 					0,									0,									0,
1142 					crand (),							crand (),							crand (),
1143 					0,									0,									0,
1144 					235 + (frand () * 20),				235 + (frand () * 20),				235 + (frand () * 20),
1145 					235 + (frand () * 20),				235 + (frand () * 20),				235 + (frand () * 20),
1146 					0.8f + (crand () * 0.1f),			-1.0f / (0.15f + (crand () * 0.05f)),
1147 					5 + (crand () * 4.5f),				2 + (frand () * 3),
1148 					pRandEmbers (),						PF_NOCLOSECULL,
1149 					pFireThink,							qTrue,
1150 					PART_STYLE_QUAD,
1151 					frand () * 360);
1152 		}
1153 		else {
1154 			// Fire
1155 			CG_SpawnParticle (
1156 				move[0] + crand (),					move[1] + crand (),					move[2] + crand (),
1157 				0,									0,									0,
1158 				0,									0,									0,
1159 				crand (),							crand (),							crand (),
1160 				235 + (frand () * 20),				235 + (frand () * 20),				235 + (frand () * 20),
1161 				235 + (frand () * 20),				235 + (frand () * 20),				235 + (frand () * 20),
1162 				0.9f + (crand () * 0.1f),			-1.0f / (0.25f + (crand () * 0.05f)),
1163 				5 + (frand () * 4),					4 + (frand () * 5),
1164 				fire,								PF_NOCLOSECULL,
1165 				pFireThink,							qTrue,
1166 				PART_STYLE_QUAD,
1167 				frand () * 360);
1168 
1169 			// Dots
1170 			CG_SpawnParticle (
1171 				move[0] + crand ()*2,				move[1] + crand ()*2,				move[2] + crand ()*2,
1172 				0,									0,									0,
1173 				0,									0,									0,
1174 				crand () * 128,						crand () * 128,						crand () * 128,
1175 				225 + (frand () * 30),				225 + (frand () * 30),				35 + (frand () * 100),
1176 				225 + (frand () * 30),				225 + (frand () * 30),				35 + (frand () * 100),
1177 				0.9f + (crand () * 0.1f),			-1.0f / (0.25f + (crand () * 0.05f)),
1178 				1 + (crand () * 0.5f),				0.5f + (crand () * 0.25f),
1179 				PT_GENERIC,							PF_NOCLOSECULL,
1180 				pFireThink,							qTrue,
1181 				PART_STYLE_QUAD,
1182 				frand () * 360);
1183 		}
1184 	}
1185 
1186 	// Smoke
1187 	Vec3Copy (start, move);
1188 	Vec3Subtract (start, end, vec);
1189 	len = VectorNormalizeFastf (vec);
1190 
1191 	dec = 60;
1192 	Vec3Scale (vec, dec, vec);
1193 
1194 	len += dec;
1195 	for (; len>0 ; Vec3Add (move, vec, move)) {
1196 		len -= dec;
1197 
1198 		rnum = 60 + (frand () * 50);
1199 		rnum2 = 70 + (frand () * 50);
1200 		CG_SpawnParticle (
1201 			move[0] + crand (),					move[1] + crand (),					move[2] + crand (),
1202 			0,									0,									0,
1203 			crand () * 2,						crand () * 2,						crand () * 2,
1204 			0,									0,									7 + (frand () * 10),
1205 			rnum,								rnum,								rnum,
1206 			rnum2,								rnum2,								rnum2,
1207 			0.5f + (crand () * 0.1f),			-1.5f / (1.0f + cg_particleSmokeLinger->floatVal + (crand () * 0.1f)),
1208 			9 + (crand () * 4),					45 + (frand () * 20),
1209 			pRandSmoke (),						PF_SHADE,
1210 			NULL,								qFalse,
1211 			PART_STYLE_QUAD,
1212 			frand () * 360.0f);
1213 	}
1214 }
1215 
1216 
1217 /*
1218 ===============
1219 CG_TagTrail
1220 ===============
1221 */
CG_TagTrail(vec3_t start,vec3_t end)1222 void CG_TagTrail (vec3_t start, vec3_t end)
1223 {
1224 	vec3_t		move, vec;
1225 	float		len, dec;
1226 
1227 	Vec3Copy (start, move);
1228 	Vec3Subtract (end, start, vec);
1229 	len = VectorNormalizeFastf (vec);
1230 
1231 	dec = 5;
1232 	Vec3Scale (vec, dec, vec);
1233 
1234 	while (len >= 0) {
1235 		len -= dec;
1236 
1237 		CG_SpawnParticle (
1238 			move[0] + (crand () * 16),		move[1] + (crand () * 16),		move[2] + (crand () * 16),
1239 			0,								0,								0,
1240 			crand () * 5,					crand () * 5,					crand () * 5,
1241 			0,								0,								0,
1242 			palRed (220),					palGreen (220),					palBlue (220),
1243 			palRed (220),					palGreen (220),					palBlue (220),
1244 			1.0f,							-1.0f / (0.8f + (frand () * 0.2f)),
1245 			1.0f,							1.0f,
1246 			PT_GENERIC,						PF_SCALED,
1247 			0,								qFalse,
1248 			PART_STYLE_QUAD,
1249 			0);
1250 
1251 		Vec3Add (move, vec, move);
1252 	}
1253 }
1254 
1255 
1256 /*
1257 ===============
1258 CG_TrackerTrail
1259 ===============
1260 */
CG_TrackerTrail(vec3_t start,vec3_t end)1261 void CG_TrackerTrail (vec3_t start, vec3_t end)
1262 {
1263 	vec3_t		move, vec, porg;
1264 	vec3_t		forward, right, up, angle_dir;
1265 	float		len, dec, dist;
1266 
1267 	Vec3Copy (start, move);
1268 	Vec3Subtract (end, start, vec);
1269 	len = VectorNormalizeFastf (vec);
1270 
1271 	Vec3Copy (vec, forward);
1272 	VecToAngles (forward, angle_dir);
1273 	Angles_Vectors (angle_dir, forward, right, up);
1274 
1275 	dec = 3;
1276 	Vec3Scale (vec, dec, vec);
1277 
1278 	for (; len>0 ; Vec3Add (move, vec, move)) {
1279 		len -= dec;
1280 
1281 		dist = DotProduct (move, forward);
1282 		Vec3MA (move, 8 * (float)cos (dist), up, porg);
1283 
1284 		CG_SpawnParticle (
1285 			porg[0],						porg[1],						porg[2],
1286 			0,								0,								0,
1287 			0,								0,								5,
1288 			0,								0,								0,
1289 			0,								0,								0,
1290 			0,								0,								0,
1291 			1.0,							-2.0,
1292 			1.0f,							1.0f,
1293 			PT_GENERIC,						PF_SCALED,
1294 			0,								qFalse,
1295 			PART_STYLE_QUAD,
1296 			0);
1297 	}
1298 }
1299