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 // cl_newfx.c -- MORE entity effects parsing and management
21 
22 #include "client.h"
23 
24 extern cparticle_t	*active_particles, *free_particles;
25 extern cparticle_t	*particles;//[MAX_PARTICLES];
26 //extern int			cl_numparticles;
27 extern cvar_t		*vid_ref;
28 
29 extern void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up);
30 
31 
32 /*
33 ======
34 vectoangles2 - this is duplicated in the game DLL, but I need it here.
35 ======
36 */
vectoangles2(vec3_t value1,vec3_t angles)37 void vectoangles2 (vec3_t value1, vec3_t angles)
38 {
39 	float	forward;
40 	float	yaw, pitch;
41 
42 	if (FLOAT_EQ_ZERO(value1[0]) && FLOAT_EQ_ZERO(value1[1]))
43 	{
44 		yaw = 0;
45 		if (FLOAT_GT_ZERO(value1[2]))
46 			pitch = 90;
47 		else
48 			pitch = 270;
49 	}
50 	else
51 	{
52 	// PMM - fixed to correct for pitch of 0
53 		if (FLOAT_NE_ZERO(value1[0]))
54 			yaw = ((float)atan2(value1[1], value1[0]) * 180 / M_PI);
55 		else if (value1[1] > 0)
56 			yaw = 90;
57 		else
58 			yaw = 270;
59 
60 		if (FLOAT_LT_ZERO(yaw))
61 			yaw += 360;
62 
63 		forward = (float)sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
64 		pitch = ((float)atan2(value1[2], forward) * 180 / M_PI);
65 		if (FLOAT_LT_ZERO(pitch))
66 			pitch += 360;
67 	}
68 
69 	angles[PITCH] = -pitch;
70 	angles[YAW] = yaw;
71 	angles[ROLL] = 0;
72 }
73 
74 //=============
75 //=============
CL_Flashlight(int ent,vec3_t pos)76 void CL_Flashlight (int ent, vec3_t pos)
77 {
78 	cdlight_t	*dl;
79 
80 	dl = CL_AllocDlight (ent, true);
81 	FastVectorCopy (*pos,  dl->origin);
82 	dl->radius = 400;
83 	//dl->minlight = 250;
84 	dl->die = cl.time + 100;
85 	dl->color[0] = 1;
86 	dl->color[1] = 1;
87 	dl->color[2] = 1;
88 }
89 
90 /*
91 ======
92 CL_ColorFlash - flash of light
93 ======
94 */
CL_ColorFlash(vec3_t pos,int ent,float intensity,float r,float g,float b)95 void CL_ColorFlash (vec3_t pos, int ent, float intensity, float r, float g, float b)
96 {
97 	cdlight_t	*dl;
98 
99 	if((vidref_val == VIDREF_SOFT) && ((FLOAT_LT_ZERO(r) || FLOAT_LT_ZERO(g) || FLOAT_LT_ZERO(b))))
100 	{
101 		intensity = -intensity;
102 		r = -r;
103 		g = -g;
104 		b = -b;
105 	}
106 
107 	dl = CL_AllocDlight (ent, false);
108 	FastVectorCopy (*pos,  dl->origin);
109 	dl->radius = intensity;
110 	//dl->minlight = 250;
111 	dl->die = cl.time + 100;
112 	dl->color[0] = r;
113 	dl->color[1] = g;
114 	dl->color[2] = b;
115 }
116 
117 
118 /*
119 ======
120 CL_DebugTrail
121 ======
122 */
CL_DebugTrail(vec3_t start,vec3_t end)123 void CL_DebugTrail (vec3_t start, vec3_t end)
124 {
125 	vec3_t		move;
126 	vec3_t		vec;
127 	float		len;
128 //	int			j;
129 	cparticle_t	*p;
130 	float		dec;
131 	vec3_t		right, up;
132 //	int			i;
133 //	float		d, c, s;
134 //	vec3_t		dir;
135 
136 	FastVectorCopy (*start, move);
137 	VectorSubtract (end, start, vec);
138 	len = VectorNormalize (vec);
139 
140 	MakeNormalVectors (vec, right, up);
141 
142 //	VectorScale(vec, RT2_SKIP, vec);
143 
144 //	dec = 1.0;
145 //	dec = 0.75;
146 	dec = 3;
147 	VectorScale (vec, dec, vec);
148 	FastVectorCopy (*start, move);
149 
150 	while (len > 0)
151 	{
152 		len -= dec;
153 
154 		if (!free_particles)
155 			return;
156 		p = free_particles;
157 		free_particles = p->next;
158 		p->next = active_particles;
159 		active_particles = p;
160 
161 		p->type = PT_NONE;
162 		p->time = (float)cl.time;
163 		VectorClear (p->accel);
164 		VectorClear (p->vel);
165 		p->alpha = 1.0;
166 		p->alphavel = -0.1f;
167 //		p->alphavel = 0;
168 		p->color = 0x74 + (randomMT()&7);
169 		FastVectorCopy (move, p->org);
170 /*
171 		for (j=0 ; j<3 ; j++)
172 		{
173 			p->org[j] = move[j] + crand()*2;
174 			p->vel[j] = crand()*3;
175 			p->accel[j] = 0;
176 		}
177 */
178 		VectorAdd (move, vec, move);
179 	}
180 
181 }
182 
183 /*
184 ===============
185 CL_SmokeTrail
186 ===============
187 */
CL_SmokeTrail(vec3_t start,vec3_t end,int colorStart,int colorRun,int spacing)188 void CL_SmokeTrail (vec3_t start, vec3_t end, int colorStart, int colorRun, int spacing)
189 {
190 	vec3_t		move;
191 	vec3_t		vec;
192 	float		len, time;
193 	int			j;
194 	cparticle_t	*p;
195 
196 	FastVectorCopy (*start, move);
197 	VectorSubtract (end, start, vec);
198 	len = VectorNormalize (vec);
199 
200 	VectorScale (vec, spacing, vec);
201 
202 	time = (float)cl.time;
203 
204 	if (colorStart > 255 || colorStart < 0)
205 		Com_Error (ERR_DROP, "CL_SmokeTrail: bad color %d", colorStart);
206 
207 	// FIXME: this is a really silly way to have a loop
208 	while (len > 0)
209 	{
210 		len -= spacing;
211 
212 		if (!free_particles)
213 			return;
214 		p = free_particles;
215 		free_particles = p->next;
216 		p->next = active_particles;
217 		active_particles = p;
218 		VectorClear (p->accel);
219 
220 		p->type = PT_NONE;
221 		p->time = time;
222 
223 		p->alpha = 1.0;
224 		p->alphavel = -1.0f / (1+frand()*0.5f);
225 		p->color = colorStart + (randomMT() % colorRun);
226 		if (p->color > 255)
227 		{
228 			Com_Printf ("Warning, capped particle color %d in CL_SmokeTrail\n", LOG_CLIENT, p->color);
229 			p->color = 255;
230 		}
231 		for (j=0 ; j<3 ; j++)
232 		{
233 			p->org[j] = move[j] + crand()*3;
234 			p->accel[j] = 0;
235 		}
236 		p->vel[2] = 20 + crand()*5;
237 
238 		VectorAdd (move, vec, move);
239 	}
240 }
241 
CL_ForceWall(vec3_t start,vec3_t end,int color)242 void CL_ForceWall (vec3_t start, vec3_t end, int color)
243 {
244 	vec3_t		move;
245 	vec3_t		vec;
246 	float		len, time;
247 	int			j;
248 	cparticle_t	*p;
249 
250 	FastVectorCopy (*start, move);
251 	VectorSubtract (end, start, vec);
252 	len = VectorNormalize (vec);
253 
254 	VectorScale (vec, 4, vec);
255 
256 	time = (float)cl.time;
257 
258 	if (color > 255 || color < 0)
259 		Com_Error (ERR_DROP, "CL_ForceWall: bad color %d", color);
260 
261 	// FIXME: this is a really silly way to have a loop
262 	while (len > 0)
263 	{
264 		len -= 4;
265 
266 		if (!free_particles)
267 			return;
268 
269 		if (frand() > 0.3f)
270 		{
271 			p = free_particles;
272 			free_particles = p->next;
273 			p->next = active_particles;
274 			active_particles = p;
275 			VectorClear (p->accel);
276 
277 			p->type = PT_NONE;
278 			p->time = time;
279 
280 			p->alpha = 1.0;
281 			p->alphavel =  -1.0f / (3.0f+frand()*0.5f);
282 			p->color = color;
283 			for (j=0 ; j<3 ; j++)
284 			{
285 				p->org[j] = move[j] + crand()*3;
286 				p->accel[j] = 0;
287 			}
288 			p->vel[0] = 0;
289 			p->vel[1] = 0;
290 			p->vel[2] = -40 - (crand()*10);
291 		}
292 
293 		VectorAdd (move, vec, move);
294 	}
295 }
296 
297 /*
298 ===============
299 CL_GenericParticleEffect
300 ===============
301 */
CL_GenericParticleEffect(vec3_t org,vec3_t dir,int color,int count,int numcolors,int dirspread,float alphavel)302 void CL_GenericParticleEffect (vec3_t org, vec3_t dir, int color, int count, int numcolors, int dirspread, float alphavel)
303 {
304 	int			i, j;
305 	cparticle_t	*p;
306 	float		d;
307 	float		time;
308 
309 	time = (float)cl.time;
310 
311 	if (color < 0 || color + numcolors > 255)
312 		Com_Error (ERR_DROP, "CL_GenericParticleEffect: bad color/rand %d/%d", color, numcolors);
313 
314 	for (i=0 ; i<count ; i++)
315 	{
316 		if (!free_particles)
317 			return;
318 		p = free_particles;
319 		free_particles = p->next;
320 		p->next = active_particles;
321 		active_particles = p;
322 
323 		p->type = PT_NONE;
324 		p->time = time;
325 		if (numcolors > 1)
326 			p->color = color + (randomMT() & numcolors);
327 		else
328 			p->color = color;
329 
330 		d = (float)(randomMT() & dirspread);
331 		for (j=0 ; j<3 ; j++)
332 		{
333 			p->org[j] = org[j] + ((randomMT()&7)-4) + d*dir[j];
334 			p->vel[j] = crand()*20;
335 		}
336 
337 		p->accel[0] = p->accel[1] = 0;
338 		p->accel[2] = -PARTICLE_GRAVITY;
339 //		VectorCopy (accel, p->accel);
340 		p->alpha = 1.0;
341 
342 		p->alphavel = -1.0f / (0.5f + frand()*alphavel);
343 //		p->alphavel = alphavel;
344 	}
345 }
346 
347 /*
348 ===============
349 CL_BubbleTrail2 (lets you control the # of bubbles by setting the distance between the spawns)
350 
351 ===============
352 */
CL_BubbleTrail2(vec3_t start,vec3_t end,int dist)353 void CL_BubbleTrail2 (vec3_t start, vec3_t end, int dist)
354 {
355 	vec3_t		move;
356 	vec3_t		vec;
357 	float		len, time;
358 	int			i, j;
359 	cparticle_t	*p;
360 
361 	time = (float)cl.time;
362 
363 	FastVectorCopy (*start, move);
364 	VectorSubtract (end, start, vec);
365 	len = VectorNormalize (vec);
366 
367 	VectorScale (vec, dist, vec);
368 
369 	for (i=0 ; i<len ; i+= dist)
370 	{
371 		if (!free_particles)
372 			return;
373 
374 		p = free_particles;
375 		free_particles = p->next;
376 		p->next = active_particles;
377 		active_particles = p;
378 
379 		VectorClear (p->accel);
380 		p->time = time;
381 		p->type = PT_NONE;
382 
383 		p->alpha = 1.0;
384 		p->alphavel = -1.0f / (1+frand()*0.1f);
385 		p->color = 4 + (randomMT()&7);
386 		for (j=0 ; j<3 ; j++)
387 		{
388 			p->org[j] = move[j] + crand()*2;
389 			p->vel[j] = crand()*10;
390 		}
391 		p->org[2] -= 4;
392 //		p->vel[2] += 6;
393 		p->vel[2] += 20;
394 
395 		VectorAdd (move, vec, move);
396 	}
397 }
398 
399 //#define CORKSCREW		1
400 //#define DOUBLE_SCREW	1
401 #define	RINGS		1
402 //#define	SPRAY		1
403 
404 #ifdef CORKSCREW
CL_Heatbeam(vec3_t start,vec3_t end)405 void CL_Heatbeam (vec3_t start, vec3_t end)
406 {
407 	vec3_t		move;
408 	vec3_t		vec;
409 	float		len;
410 	int			j,k;
411 	cparticle_t	*p;
412 	vec3_t		right, up;
413 	int			i;
414 	float		d, c, s;
415 	vec3_t		dir;
416 	float		ltime;
417 	float		step = 5.0;
418 
419 	VectorCopy (start, move);
420 	VectorSubtract (end, start, vec);
421 	len = VectorNormalize (vec);
422 
423 //	MakeNormalVectors (vec, right, up);
424 	VectorCopy (cl.v_right, right);
425 	VectorCopy (cl.v_up, up);
426 	VectorMA (move, -1, right, move);
427 	VectorMA (move, -1, up, move);
428 
429 	VectorScale (vec, step, vec);
430 	ltime = (float) cl.time/1000.0;
431 
432 //	for (i=0 ; i<len ; i++)
433 	for (i=0 ; i<len ; i+=step)
434 	{
435 		d = i * 0.1 - fmod(ltime,16.0)*M_PI;
436 		c = cos(d)/1.75;
437 		s = sin(d)/1.75;
438 #ifdef DOUBLE_SCREW
439 		for (k=-1; k<2; k+=2)
440 		{
441 #else
442 		k=1;
443 #endif
444 			if (!free_particles)
445 				return;
446 
447 			p = free_particles;
448 			free_particles = p->next;
449 			p->next = active_particles;
450 			active_particles = p;
451 
452 			p->time = cl.time;
453 			VectorClear (p->accel);
454 
455 			p->alpha = 0.5;
456 	//		p->alphavel = -1.0 / (1+frand()*0.2);
457 			// only last one frame!
458 			//p->alphavel = INSTANT_PARTICLE;
459 			p->type = PT_INSTANT;
460 	//		p->color = 0x74 + (randomMT()&7);
461 //			p->color = 223 - (randomMT()&7);
462 			p->color = 223;
463 //			p->color = 240;
464 
465 			// trim it so it looks like it's starting at the origin
466 			if (i < 10)
467 			{
468 				VectorScale (right, c*(i/10.0)*k, dir);
469 				VectorMA (dir, s*(i/10.0)*k, up, dir);
470 			}
471 			else
472 			{
473 				VectorScale (right, c*k, dir);
474 				VectorMA (dir, s*k, up, dir);
475 			}
476 
477 			for (j=0 ; j<3 ; j++)
478 			{
479 				p->org[j] = move[j] + dir[j]*3;
480 	//			p->vel[j] = dir[j]*6;
481 				p->vel[j] = 0;
482 			}
483 #ifdef DOUBLE_SCREW
484 		}
485 #endif
486 		VectorAdd (move, vec, move);
487 	}
488 }
489 #endif
490 #ifdef RINGS
491 //void CL_Heatbeam (vec3_t start, vec3_t end)
CL_Heatbeam(vec3_t start,vec3_t forward)492 void CL_Heatbeam (vec3_t start, vec3_t forward)
493 {
494 	vec3_t		move;
495 	vec3_t		vec;
496 	float		len;
497 	int			j;
498 	cparticle_t	*p;
499 	vec3_t		right, up;
500 	float		i;
501 	float		c, s;
502 	vec3_t		dir;
503 	float		ltime;
504 	float		step = 32.0, rstep;
505 	float		start_pt;
506 	float		rot;
507 	float		variance;
508 	float		time;
509 	vec3_t		end;
510 
511 	VectorMA (start, 4096, forward, end);
512 
513 	FastVectorCopy (*start, move);
514 	VectorSubtract (end, start, vec);
515 	len = VectorNormalize (vec);
516 
517 	// FIXME - pmm - these might end up using old values?
518 //	MakeNormalVectors (vec, right, up);
519 	FastVectorCopy (cl.v_right, right);
520 	FastVectorCopy (cl.v_up, up);
521 
522 	/*if (vidref_val == VIDREF_GL)
523 	{ // GL mode
524 		VectorMA (move, -0.5, right, move);
525 		VectorMA (move, -0.5, up, move);
526 	}*/
527 	// otherwise assume SOFT
528 
529 	time = (float)cl.time;
530 
531 	ltime = (float) cl.time/1000.0f;
532 	start_pt = (float)fmod(ltime*96.0f,step);
533 	VectorMA (move, start_pt, vec, move);
534 
535 	VectorScale (vec, step, vec);
536 
537 //	Com_Printf ("%f\n", ltime);
538 	rstep = M_PI/10.0f;
539 	for (i=start_pt ; i<len ; i+=step)
540 	{
541 		if (i>step*5) // don't bother after the 5th ring
542 			break;
543 
544 		for (rot = 0; rot < M_PI*2; rot += rstep)
545 		{
546 
547 			if (!free_particles)
548 				return;
549 
550 			p = free_particles;
551 			free_particles = p->next;
552 			p->next = active_particles;
553 			active_particles = p;
554 
555 			p->type = PT_NONE;
556 			p->time = time;
557 			VectorClear (p->accel);
558 //			rot+= fmod(ltime, 12.0)*M_PI;
559 //			c = cos(rot)/2.0;
560 //			s = sin(rot)/2.0;
561 //			variance = 0.4 + ((float)randomMT()/(float)RAND_MAX) *0.2;
562 			variance = 0.5;
563 			c = (float)cos(rot)*variance;
564 			s = (float)sin(rot)*variance;
565 
566 			// trim it so it looks like it's starting at the origin
567 			if (i < 10)
568 			{
569 				VectorScale (right, c*(i/10.0f), dir);
570 				VectorMA (dir, s*(i/10.0f), up, dir);
571 			}
572 			else
573 			{
574 				VectorScale (right, c, dir);
575 				VectorMA (dir, s, up, dir);
576 			}
577 
578 			p->alpha = 0.5;
579 	//		p->alphavel = -1.0 / (1+frand()*0.2);
580 			p->alphavel = -1000.0;
581 	//		p->color = 0x74 + (randomMT()&7);
582 			p->color = 223 - (randomMT()&7);
583 			for (j=0 ; j<3 ; j++)
584 			{
585 				p->org[j] = move[j] + dir[j]*3;
586 	//			p->vel[j] = dir[j]*6;
587 				p->vel[j] = 0;
588 			}
589 		}
590 		VectorAdd (move, vec, move);
591 	}
592 }
593 #endif
594 #ifdef SPRAY
CL_Heatbeam(vec3_t start,vec3_t end)595 void CL_Heatbeam (vec3_t start, vec3_t end)
596 {
597 	vec3_t		move;
598 	vec3_t		vec;
599 	float		len;
600 	int			j;
601 	cparticle_t	*p;
602 	vec3_t		forward, right, up;
603 	int			i;
604 	float		d, c, s;
605 	vec3_t		dir;
606 	float		ltime;
607 	float		step = 32.0, rstep;
608 	float		start_pt;
609 	float		rot;
610 
611 	VectorCopy (start, move);
612 	VectorSubtract (end, start, vec);
613 	len = VectorNormalize (vec);
614 
615 //	MakeNormalVectors (vec, right, up);
616 	VectorCopy (cl.v_forward, forward);
617 	VectorCopy (cl.v_right, right);
618 	VectorCopy (cl.v_up, up);
619 	VectorMA (move, -0.5, right, move);
620 	VectorMA (move, -0.5, up, move);
621 
622 	for (i=0; i<8; i++)
623 	{
624 		if (!free_particles)
625 			return;
626 
627 		p = free_particles;
628 		free_particles = p->next;
629 		p->next = active_particles;
630 		active_particles = p;
631 
632 		p->type = PT_NONE;
633 		p->time = cl.time;
634 		VectorClear (p->accel);
635 
636 		d = crand()*M_PI;
637 		c = cos(d)*30;
638 		s = sin(d)*30;
639 
640 		p->alpha = 1.0;
641 		p->alphavel = -5.0 / (1+frand());
642 		p->color = 223 - (randomMT()&7);
643 
644 		for (j=0 ; j<3 ; j++)
645 		{
646 			p->org[j] = move[j];
647 		}
648 		VectorScale (vec, 450, p->vel);
649 		VectorMA (p->vel, c, right, p->vel);
650 		VectorMA (p->vel, s, up, p->vel);
651 	}
652 /*
653 
654 	ltime = (float) cl.time/1000.0;
655 	start_pt = fmod(ltime*16.0,step);
656 	VectorMA (move, start_pt, vec, move);
657 
658 	VectorScale (vec, step, vec);
659 
660 //	Com_Printf ("%f\n", ltime);
661 	rstep = M_PI/12.0;
662 	for (i=start_pt ; i<len ; i+=step)
663 	{
664 		if (i>step*5) // don't bother after the 5th ring
665 			break;
666 
667 		for (rot = 0; rot < M_PI*2; rot += rstep)
668 		{
669 			if (!free_particles)
670 				return;
671 
672 			p = free_particles;
673 			free_particles = p->next;
674 			p->next = active_particles;
675 			active_particles = p;
676 
677 			p->time = cl.time;
678 			VectorClear (p->accel);
679 //			rot+= fmod(ltime, 12.0)*M_PI;
680 //			c = cos(rot)/2.0;
681 //			s = sin(rot)/2.0;
682 			c = cos(rot)/1.5;
683 			s = sin(rot)/1.5;
684 
685 			// trim it so it looks like it's starting at the origin
686 			if (i < 10)
687 			{
688 				VectorScale (right, c*(i/10.0), dir);
689 				VectorMA (dir, s*(i/10.0), up, dir);
690 			}
691 			else
692 			{
693 				VectorScale (right, c, dir);
694 				VectorMA (dir, s, up, dir);
695 			}
696 
697 			p->alpha = 0.5;
698 	//		p->alphavel = -1.0 / (1+frand()*0.2);
699 			p->alphavel = -1000.0;
700 	//		p->color = 0x74 + (randomMT()&7);
701 			p->color = 223 - (randomMT()&7);
702 			for (j=0 ; j<3 ; j++)
703 			{
704 				p->org[j] = move[j] + dir[j]*3;
705 	//			p->vel[j] = dir[j]*6;
706 				p->vel[j] = 0;
707 			}
708 		}
709 		VectorAdd (move, vec, move);
710 	}
711 */
712 }
713 #endif
714 
715 /*
716 ===============
717 CL_ParticleSteamEffect
718 
719 Puffs with velocity along direction, with some randomness thrown in
720 ===============
721 */
CL_ParticleSteamEffect(vec3_t org,vec3_t dir,int color,int count,int magnitude)722 void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude)
723 {
724 	int			i, j;
725 	cparticle_t	*p;
726 	float		d, time;
727 	vec3_t		r, u;
728 
729 	time = (float)cl.time;
730 
731 //	vectoangles2 (dir, angle_dir);
732 //	AngleVectors (angle_dir, f, r, u);
733 
734 	if (color < 0 || color > 255-7)
735 		Com_Error (ERR_DROP, "CL_ParticleSteamEffect: bad color %d", color);
736 
737 	MakeNormalVectors (dir, r, u);
738 
739 	for (i=0 ; i<count ; i++)
740 	{
741 		if (!free_particles)
742 			return;
743 		p = free_particles;
744 		free_particles = p->next;
745 		p->next = active_particles;
746 		active_particles = p;
747 
748 		p->type = PT_NONE;
749 		p->time = time;
750 		p->color = color + (randomMT()&7);
751 
752 		for (j=0 ; j<3 ; j++)
753 		{
754 			p->org[j] = org[j] + magnitude*0.1f*crand();
755 //			p->vel[j] = dir[j]*magnitude;
756 		}
757 		VectorScale (dir, magnitude, p->vel);
758 		d = crand()*magnitude/3;
759 		VectorMA (p->vel, d, r, p->vel);
760 		d = crand()*magnitude/3;
761 		VectorMA (p->vel, d, u, p->vel);
762 
763 		p->accel[0] = p->accel[1] = 0;
764 		p->accel[2] = -PARTICLE_GRAVITY/2;
765 		p->alpha = 1.0;
766 
767 		p->alphavel = -1.0f / (0.5f + frand()*0.3f);
768 	}
769 }
770 
CL_ParticleSteamEffect2(cl_sustain_t * self)771 void CL_ParticleSteamEffect2 (cl_sustain_t *self)
772 //vec3_t org, vec3_t dir, int color, int count, int magnitude)
773 {
774 	int			i, j;
775 	cparticle_t	*p;
776 	float		d;
777 	vec3_t		r, u;
778 	vec3_t		dir;
779 	float		time;
780 
781 	time = (float)cl.time;
782 
783 //	vectoangles2 (dir, angle_dir);
784 //	AngleVectors (angle_dir, f, r, u);
785 
786 	FastVectorCopy (self->dir, dir);
787 	MakeNormalVectors (dir, r, u);
788 
789 	for (i=0 ; i<self->count ; i++)
790 	{
791 		if (!free_particles)
792 			return;
793 		p = free_particles;
794 		free_particles = p->next;
795 		p->next = active_particles;
796 		active_particles = p;
797 
798 		p->type = PT_NONE;
799 		p->time = time;
800 		p->color = self->color + (randomMT()&7);
801 		if (p->color > 255 || p->color < 0)
802 			Com_Error (ERR_DROP, "CL_ParticleSteamEffect2: bad color %d", p->color);
803 
804 		for (j=0 ; j<3 ; j++)
805 		{
806 			p->org[j] = self->org[j] + self->magnitude*0.1f*crand();
807 //			p->vel[j] = dir[j]*magnitude;
808 		}
809 		VectorScale (dir, self->magnitude, p->vel);
810 		d = crand()*self->magnitude/3;
811 		VectorMA (p->vel, d, r, p->vel);
812 		d = crand()*self->magnitude/3;
813 		VectorMA (p->vel, d, u, p->vel);
814 
815 		p->accel[0] = p->accel[1] = 0;
816 		p->accel[2] = -PARTICLE_GRAVITY/2;
817 		p->alpha = 1.0;
818 
819 		p->alphavel = -1.0f / (0.5f + frand()*0.3f);
820 	}
821 	self->nextthink += self->thinkinterval;
822 }
823 
824 /*
825 ===============
826 CL_TrackerTrail
827 ===============
828 */
CL_TrackerTrail(vec3_t start,vec3_t end,int particleColor)829 void CL_TrackerTrail (vec3_t start, vec3_t end, int particleColor)
830 {
831 	vec3_t		move;
832 	vec3_t		vec;
833 	vec3_t		forward,right,up,angle_dir;
834 	float		len;
835 	int			j;
836 	cparticle_t	*p;
837 	int			dec;
838 	float		dist;
839 	float		time;
840 
841 	time = (float)cl.time;
842 
843 	if (particleColor < 0 || particleColor > 255)
844 		Com_Error (ERR_DROP, "CL_TrackerTrail: bad color %d", particleColor);
845 
846 	FastVectorCopy (*start, move);
847 	VectorSubtract (end, start, vec);
848 	len = VectorNormalize (vec);
849 
850 	FastVectorCopy(vec, forward);
851 	vectoangles2 (forward, angle_dir);
852 	AngleVectors (angle_dir, forward, right, up);
853 
854 	dec = 3;
855 	VectorScale (vec, 3, vec);
856 
857 	// FIXME: this is a really silly way to have a loop
858 	while (len > 0)
859 	{
860 		len -= dec;
861 
862 		if (!free_particles)
863 			return;
864 		p = free_particles;
865 		free_particles = p->next;
866 		p->next = active_particles;
867 		active_particles = p;
868 		VectorClear (p->accel);
869 
870 		p->type = PT_NONE;
871 		p->time = time;
872 
873 		p->alpha = 1.0;
874 		p->alphavel = -2.0;
875 		p->color = particleColor;
876 		dist = DotProduct(move, forward);
877 		VectorMA(move, 8 * cos(dist), up, p->org);
878 		for (j=0 ; j<3 ; j++)
879 		{
880 //			p->org[j] = move[j] + crand();
881 			p->vel[j] = 0;
882 			p->accel[j] = 0;
883 		}
884 		p->vel[2] = 5;
885 
886 		VectorAdd (move, vec, move);
887 	}
888 }
889 
CL_Tracker_Shell(vec3_t origin)890 void CL_Tracker_Shell(vec3_t origin)
891 {
892 	vec3_t			dir;
893 	int				i;
894 	cparticle_t		*p;
895 	float			time;
896 
897 	time = (float)cl.time;
898 
899 	for(i=0;i<300;i++)
900 	{
901 		if (!free_particles)
902 			return;
903 		p = free_particles;
904 		free_particles = p->next;
905 		p->next = active_particles;
906 		active_particles = p;
907 		VectorClear (p->accel);
908 
909 		p->time = time;
910 
911 		p->alpha = 1.0;
912 		//p->alphavel = INSTANT_PARTICLE;
913 		p->type = PT_INSTANT;
914 		p->color = 0;
915 
916 		dir[0] = crand();
917 		dir[1] = crand();
918 		dir[2] = crand();
919 		VectorNormalize(dir);
920 
921 		VectorMA(origin, 40, dir, p->org);
922 	}
923 }
924 
CL_MonsterPlasma_Shell(vec3_t origin)925 void CL_MonsterPlasma_Shell(vec3_t origin)
926 {
927 	vec3_t			dir;
928 	int				i;
929 	cparticle_t		*p;
930 	float			time;
931 
932 	time = (float)cl.time;
933 
934 	for(i=0;i<40;i++)
935 	{
936 		if (!free_particles)
937 			return;
938 		p = free_particles;
939 		free_particles = p->next;
940 		p->next = active_particles;
941 		active_particles = p;
942 		VectorClear (p->accel);
943 
944 		p->time = time;
945 
946 		p->alpha = 1.0;
947 		//p->alphavel = INSTANT_PARTICLE;
948 		p->type = PT_INSTANT;
949 		p->color = 0xe0;
950 
951 		dir[0] = crand();
952 		dir[1] = crand();
953 		dir[2] = crand();
954 		VectorNormalize(dir);
955 
956 		VectorMA(origin, 10, dir, p->org);
957 //		VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org);
958 	}
959 }
960 
CL_Widowbeamout(cl_sustain_t * self)961 void CL_Widowbeamout (cl_sustain_t *self)
962 {
963 	vec3_t			dir;
964 	int				i;
965 	cparticle_t		*p;
966 	static int colortable[4] = {2*8,13*8,21*8,18*8};
967 	float			ratio;
968 	float			time;
969 
970 	time = (float)cl.time;
971 
972 	ratio = 1.0f - (((float)self->endtime - (float)cl.time)/2100.0f);
973 
974 	for(i=0;i<300;i++)
975 	{
976 		if (!free_particles)
977 			return;
978 		p = free_particles;
979 		free_particles = p->next;
980 		p->next = active_particles;
981 		active_particles = p;
982 		VectorClear (p->accel);
983 
984 		p->time = time;
985 
986 		p->alpha = 1.0;
987 		//p->alphavel = INSTANT_PARTICLE;
988 		p->type = PT_INSTANT;
989 		p->color = colortable[randomMT()&3];
990 
991 		dir[0] = crand();
992 		dir[1] = crand();
993 		dir[2] = crand();
994 		VectorNormalize(dir);
995 
996 		VectorMA(self->org, (45.0 * ratio), dir, p->org);
997 //		VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org);
998 	}
999 }
1000 
CL_Nukeblast(cl_sustain_t * self)1001 void CL_Nukeblast (cl_sustain_t *self)
1002 {
1003 	vec3_t			dir;
1004 	int				i;
1005 	cparticle_t		*p;
1006 	static int colortable[4] = {110, 112, 114, 116};
1007 	float			ratio;
1008 	float			time;
1009 
1010 	time = (float)cl.time;
1011 
1012 	ratio = 1.0f - (((float)self->endtime - (float)cl.time)/1000.0f);
1013 
1014 	for(i=0;i<700;i++)
1015 	{
1016 		if (!free_particles)
1017 			return;
1018 		p = free_particles;
1019 		free_particles = p->next;
1020 		p->next = active_particles;
1021 		active_particles = p;
1022 		VectorClear (p->accel);
1023 
1024 		p->time = time;
1025 
1026 		p->alpha = 1.0;
1027 		p->alphavel = 0;//-1000;
1028 		p->type = PT_INSTANT;
1029 		p->color = colortable[randomMT()&3];
1030 
1031 		dir[0] = crand();
1032 		dir[1] = crand();
1033 		dir[2] = crand();
1034 		VectorNormalize(dir);
1035 
1036 		VectorMA(self->org, (200.0 * ratio * crand()), dir, p->org);
1037 //		VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org);
1038 	}
1039 }
1040 
CL_WidowSplash(vec3_t org)1041 void CL_WidowSplash (vec3_t org)
1042 {
1043 	static int colortable[4] = {2*8,13*8,21*8,18*8};
1044 	int			i;
1045 	cparticle_t	*p;
1046 	vec3_t		dir;
1047 	float		time;
1048 
1049 	time = (float)cl.time;
1050 
1051 	for (i=0 ; i<256 ; i++)
1052 	{
1053 		if (!free_particles)
1054 			return;
1055 		p = free_particles;
1056 		free_particles = p->next;
1057 		p->next = active_particles;
1058 		active_particles = p;
1059 
1060 		p->type = PT_NONE;
1061 		p->time = time;
1062 		p->color = colortable[randomMT()&3];
1063 
1064 		dir[0] = crand();
1065 		dir[1] = crand();
1066 		dir[2] = crand();
1067 		VectorNormalize(dir);
1068 		VectorMA(org, 45.0, dir, p->org);
1069 		VectorMA(vec3_origin, 40.0, dir, p->vel);
1070 
1071 		p->accel[0] = p->accel[1] = 0;
1072 		p->alpha = 1.0;
1073 
1074 		p->alphavel = -0.8f / (0.5f + frand()*0.3f);
1075 	}
1076 
1077 }
1078 
CL_Tracker_Explode(vec3_t origin)1079 void CL_Tracker_Explode(vec3_t	origin)
1080 {
1081 	vec3_t			dir, backdir;
1082 	int				i;
1083 	cparticle_t		*p;
1084 	float			time;
1085 
1086 	time = (float)cl.time;
1087 
1088 	for(i=0;i<300;i++)
1089 	{
1090 		if (!free_particles)
1091 			return;
1092 		p = free_particles;
1093 		free_particles = p->next;
1094 		p->next = active_particles;
1095 		active_particles = p;
1096 		VectorClear (p->accel);
1097 
1098 		p->type = PT_NONE;
1099 		p->time = time;
1100 
1101 		p->alpha = 1.0;
1102 		p->alphavel = -1.0;
1103 		p->color = 0;
1104 
1105 		dir[0] = crand();
1106 		dir[1] = crand();
1107 		dir[2] = crand();
1108 		VectorNormalize(dir);
1109 		VectorScale(dir, -1, backdir);
1110 
1111 		VectorMA(origin, 64, dir, p->org);
1112 		VectorScale(backdir, 64, p->vel);
1113 	}
1114 
1115 }
1116 
1117 /*
1118 ===============
1119 CL_TagTrail
1120 
1121 ===============
1122 */
CL_TagTrail(vec3_t start,vec3_t end,int color)1123 void CL_TagTrail (vec3_t start, vec3_t end, int color)
1124 {
1125 	vec3_t		move;
1126 	vec3_t		vec;
1127 	float		len;
1128 	int			j;
1129 	cparticle_t	*p;
1130 	int			dec;
1131 	float		time;
1132 
1133 	time = (float)cl.time;
1134 
1135 	if (color < 0 || color > 255)
1136 		Com_Error (ERR_DROP, "CL_TagTrail: bad color %d", color);
1137 
1138 	FastVectorCopy (*start, move);
1139 	VectorSubtract (end, start, vec);
1140 	len = VectorNormalize (vec);
1141 
1142 	dec = 5;
1143 	VectorScale (vec, 5, vec);
1144 
1145 	while (len >= 0)
1146 	{
1147 		len -= dec;
1148 
1149 		if (!free_particles)
1150 			return;
1151 		p = free_particles;
1152 		free_particles = p->next;
1153 		p->next = active_particles;
1154 		active_particles = p;
1155 		VectorClear (p->accel);
1156 
1157 		p->type = PT_NONE;
1158 		p->time = time;
1159 
1160 		p->alpha = 1.0;
1161 		p->alphavel = -1.0f / (0.8f+frand()*0.2f);
1162 		p->color = color;
1163 		for (j=0 ; j<3 ; j++)
1164 		{
1165 			p->org[j] = move[j] + crand()*16;
1166 			p->vel[j] = crand()*5;
1167 			p->accel[j] = 0;
1168 		}
1169 
1170 		VectorAdd (move, vec, move);
1171 	}
1172 }
1173 
1174 /*
1175 ===============
1176 CL_ColorExplosionParticles
1177 ===============
1178 */
CL_ColorExplosionParticles(vec3_t org,int color,int run)1179 void CL_ColorExplosionParticles (vec3_t org, int color, int run)
1180 {
1181 	int			i, j;
1182 	cparticle_t	*p;
1183 	float		time;
1184 
1185 	time = (float)cl.time;
1186 
1187 	if (color < 0 || color + run > 255)
1188 		Com_Error (ERR_DROP, "CL_ColorExplosionParticles: bad color/rand %d/%d", color, run);
1189 
1190 	for (i=0 ; i<128 ; i++)
1191 	{
1192 		if (!free_particles)
1193 			return;
1194 		p = free_particles;
1195 		free_particles = p->next;
1196 		p->next = active_particles;
1197 		active_particles = p;
1198 
1199 		p->type = PT_NONE;
1200 		p->time = time;
1201 		p->color = color + (randomMT() % run);
1202 
1203 		for (j=0 ; j<3 ; j++)
1204 		{
1205 			p->org[j] = org[j] + crand() * 16;
1206 			p->vel[j] = crand() * 128;
1207 		}
1208 
1209 		p->accel[0] = p->accel[1] = 0;
1210 		p->accel[2] = -PARTICLE_GRAVITY;
1211 		p->alpha = 1.0;
1212 
1213 		p->alphavel = -0.4f / (0.6f + frand()*0.2f);
1214 	}
1215 }
1216 
1217 /*
1218 ===============
1219 CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity
1220 ===============
1221 */
CL_ParticleSmokeEffect(vec3_t org,vec3_t dir,int color,int count,int magnitude)1222 void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude)
1223 {
1224 	int			i, j;
1225 	cparticle_t	*p;
1226 	float		d;
1227 	vec3_t		r, u;
1228 	float		time;
1229 
1230 	time = (float)cl.time;
1231 
1232 	if (color < 0 || color > 255-7)
1233 		Com_Error (ERR_DROP, "CL_ParticleSmokeEffect: bad color %d", color);
1234 
1235 	MakeNormalVectors (dir, r, u);
1236 
1237 	for (i=0 ; i<count ; i++)
1238 	{
1239 		if (!free_particles)
1240 			return;
1241 		p = free_particles;
1242 		free_particles = p->next;
1243 		p->next = active_particles;
1244 		active_particles = p;
1245 
1246 		p->type = PT_NONE;
1247 		p->time = time;
1248 		p->color = color + (randomMT()&7);
1249 
1250 		for (j=0 ; j<3 ; j++)
1251 		{
1252 			p->org[j] = org[j] + magnitude*0.1f*crand();
1253 //			p->vel[j] = dir[j]*magnitude;
1254 		}
1255 		VectorScale (dir, magnitude, p->vel);
1256 		d = crand()*magnitude/3;
1257 		VectorMA (p->vel, d, r, p->vel);
1258 		d = crand()*magnitude/3;
1259 		VectorMA (p->vel, d, u, p->vel);
1260 
1261 		p->accel[0] = p->accel[1] = p->accel[2] = 0;
1262 		p->alpha = 1.0;
1263 
1264 		p->alphavel = -1.0f / (0.5f + frand()*0.3f);
1265 	}
1266 }
1267 
1268 /*
1269 ===============
1270 CL_BlasterParticles2
1271 
1272 Wall impact puffs (Green)
1273 ===============
1274 */
CL_BlasterParticles2(vec3_t org,vec3_t dir,uint32 color)1275 void CL_BlasterParticles2 (vec3_t org, vec3_t dir, uint32 color)
1276 {
1277 	int			i, j;
1278 	cparticle_t	*p;
1279 	float		d;
1280 	int			count;
1281 	float		time;
1282 
1283 	time = (float)cl.time;
1284 
1285 	if (color > 255-7)
1286 		Com_Error (ERR_DROP, "CL_BlasterParticles2: bad color %d", color);
1287 
1288 	count = 40;
1289 	for (i=0 ; i<count ; i++)
1290 	{
1291 		if (!free_particles)
1292 			return;
1293 		p = free_particles;
1294 		free_particles = p->next;
1295 		p->next = active_particles;
1296 		active_particles = p;
1297 
1298 		p->type = PT_NONE;
1299 		p->time = time;
1300 		p->color = color + (randomMT()&7);
1301 
1302 		d = (float)(randomMT()&15);
1303 		for (j=0 ; j<3 ; j++)
1304 		{
1305 			p->org[j] = org[j] + ((randomMT()&7)-4) + d*dir[j];
1306 			p->vel[j] = dir[j] * 30 + crand()*40;
1307 		}
1308 
1309 		p->accel[0] = p->accel[1] = 0;
1310 		p->accel[2] = -PARTICLE_GRAVITY;
1311 		p->alpha = 1.0;
1312 
1313 		p->alphavel = -1.0f / (0.5f + frand()*0.3f);
1314 	}
1315 }
1316 
1317 /*
1318 ===============
1319 CL_BlasterTrail2
1320 
1321 Green!
1322 ===============
1323 */
CL_BlasterTrail2(vec3_t start,vec3_t end)1324 void CL_BlasterTrail2 (vec3_t start, vec3_t end)
1325 {
1326 	vec3_t		move;
1327 	vec3_t		vec;
1328 	float		len;
1329 	int			j;
1330 	cparticle_t	*p;
1331 	int			dec;
1332 	float		time;
1333 
1334 	time = (float)cl.time;
1335 
1336 	FastVectorCopy (*start, move);
1337 	VectorSubtract (end, start, vec);
1338 	len = VectorNormalize (vec);
1339 
1340 	dec = 5;
1341 	VectorScale (vec, 5, vec);
1342 
1343 	// FIXME: this is a really silly way to have a loop
1344 	while (len > 0)
1345 	{
1346 		len -= dec;
1347 
1348 		if (!free_particles)
1349 			return;
1350 		p = free_particles;
1351 		free_particles = p->next;
1352 		p->next = active_particles;
1353 		active_particles = p;
1354 		VectorClear (p->accel);
1355 
1356 		p->type = PT_NONE;
1357 		p->time = time;
1358 
1359 		p->alpha = 1.0;
1360 		p->alphavel = -1.0f / (0.3f+frand()*0.2f);
1361 		p->color = 0xd0;
1362 		for (j=0 ; j<3 ; j++)
1363 		{
1364 			p->org[j] = move[j] + crand();
1365 			p->vel[j] = crand()*5;
1366 			p->accel[j] = 0;
1367 		}
1368 
1369 		VectorAdd (move, vec, move);
1370 	}
1371 }
1372