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 void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up);
25 
26 cparticle_t *setupParticle (
27 			float angle0,		float angle1,		float angle2,
28 			float org0,			float org1,			float org2,
29 			float vel0,			float vel1,			float vel2,
30 			float accel0,		float accel1,		float accel2,
31 			float color0,		float color1,		float color2,
32 			float colorvel0,	float colorvel1,	float colorvel2,
33 			float alpha,		float alphavel,
34 			int	blendfunc_src,	int blendfunc_dst,
35 			float size,			float sizevel,
36 			int	image,
37 			int flags,
38 			void (*think)(cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time),
39 			qboolean thinknext);
40 
41 /*
42 ======
43 vectoangles2 - this is duplicated in the game DLL, but I need it here.
44 ======
45 */
vectoangles2(vec3_t value1,vec3_t angles)46 void vectoangles2 (vec3_t value1, vec3_t angles)
47 {
48 	float	forward;
49 	float	yaw, pitch;
50 
51 	if (value1[1] == 0 && value1[0] == 0)
52 	{
53 		yaw = 0;
54 		if (value1[2] > 0)
55 			pitch = 90;
56 		else
57 			pitch = 270;
58 	}
59 	else
60 	{
61 	// PMM - fixed to correct for pitch of 0
62 		if (value1[0])
63 			yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
64 		else if (value1[1] > 0)
65 			yaw = 90;
66 		else
67 			yaw = 270;
68 
69 		if (yaw < 0)
70 			yaw += 360;
71 
72 		forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
73 		pitch = (atan2(value1[2], forward) * 180 / M_PI);
74 		if (pitch < 0)
75 			pitch += 360;
76 	}
77 
78 	angles[PITCH] = -pitch;
79 	angles[YAW] = yaw;
80 	angles[ROLL] = 0;
81 }
82 
83 //=============
84 //=============
CL_Flashlight(int ent,vec3_t pos)85 void CL_Flashlight (int ent, vec3_t pos)
86 {
87 	cdlight_t	*dl;
88 
89 	dl = CL_AllocDlight (ent);
90 	VectorCopy (pos,  dl->origin);
91 	dl->radius = 400;
92 	dl->minlight = 250;
93 	dl->die = cl.time + 100;
94 	dl->color[0] = dl->color[1] = dl->color[2] = 1;
95 }
96 
97 /*
98 ======
99 CL_ColorFlash - flash of light
100 ======
101 */
CL_ColorFlash(vec3_t pos,int ent,int intensity,float r,float g,float b)102 void CL_ColorFlash (vec3_t pos, int ent, int intensity, float r, float g, float b)
103 {
104 	cdlight_t	*dl;
105 
106 	dl = CL_AllocDlight (ent);
107 	VectorCopy (pos,  dl->origin);
108 	dl->radius = intensity;
109 	dl->minlight = 250;
110 	dl->die = cl.time + 100;
111 	dl->color[0] = r;
112 	dl->color[1] = g;
113 	dl->color[2] = b;
114 }
115 
116 
117 /*
118 ======
119 CL_DebugTrail
120 ======
121 */
CL_DebugTrail(vec3_t start,vec3_t end)122 void CL_DebugTrail (vec3_t start, vec3_t end)
123 {
124 	vec3_t		move;
125 	vec3_t		vec;
126 	float		len;
127 	float		dec;
128 	vec3_t		right, up;
129 
130 	VectorCopy (start, move);
131 	VectorSubtract (end, start, vec);
132 	len = VectorNormalize (vec);
133 
134 	MakeNormalVectors (vec, right, up);
135 
136 	dec = 2;
137 	VectorScale (vec, dec, vec);
138 	VectorCopy (start, move);
139 
140 	while (len > 0)
141 	{
142 		len -= dec;
143 
144 		setupParticle (
145 			0,	0,	0,
146 			move[0],	move[1],	move[2],
147 			0,	0,	0,
148 			0,		0,		0,
149 			50,	50,	255,
150 			0,	0,	0,
151 			1,		-0.75,
152 			GL_SRC_ALPHA, GL_ONE,
153 			7.5,			0,
154 			particle_generic,
155 			0,
156 			NULL,0);
157 
158 		VectorAdd (move, vec, move);
159 	}
160 
161 }
162 
CL_ForceWall(vec3_t start,vec3_t end,int color8)163 void CL_ForceWall (vec3_t start, vec3_t end, int color8)
164 {
165 	vec3_t		move;
166 	vec3_t		vec;
167 	float		len;
168 	vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
169 
170 	VectorCopy (start, move);
171 	VectorSubtract (end, start, vec);
172 	len = VectorNormalize (vec);
173 
174 	VectorScale (vec, 4, vec);
175 
176 	// FIXME: this is a really silly way to have a loop
177 	while (len > 0)
178 	{
179 		len -= 4;
180 
181 		if (frand() > 0.3)
182 			setupParticle (
183 				0,	0,	0,
184 				move[0] + crand()*3,	move[1] + crand()*3,	move[2] + crand()*3,
185 				0,	0,	-40 - (crand()*10),
186 				0,		0,		0,
187 				color[0]+5,	color[1]+5,	color[2]+5,
188 				0,	0,	0,
189 				1,		-1.0 / (3.0+frand()*0.5),
190 				GL_SRC_ALPHA, GL_ONE,
191 				5,			0,
192 				particle_generic,
193 				0,
194 				NULL,0);
195 
196 		VectorAdd (move, vec, move);
197 	}
198 }
199 
200 
201 
202 /*
203 ===============
204 CL_BubbleTrail2 (lets you control the # of bubbles by setting the distance between the spawns)
205 
206 ===============
207 */
CL_BubbleTrail2(vec3_t start,vec3_t end,int dist)208 void CL_BubbleTrail2 (vec3_t start, vec3_t end, int dist)
209 {
210 	vec3_t		move;
211 	vec3_t		vec;
212 	float		len;
213 	int			i;
214 	float		dec, size;
215 
216 	VectorCopy (start, move);
217 	VectorSubtract (end, start, vec);
218 	len = VectorNormalize (vec);
219 
220 	dec = dist;
221 	VectorScale (vec, dec, vec);
222 
223 	for (i=0 ; i<len ; i+=dec)
224 	{
225 		size = (frand()>0.25)? 1 : (frand()>0.5) ? 2 : (frand()>0.75) ? 3 : 4;
226 
227 		setupParticle (
228 			0,	0,	0,
229 			move[0]+crand()*2,	move[1]+crand()*2,	move[2]+crand()*2,
230 			crand()*5,	crand()*5,	crand()*5+6,
231 			0,		0,		0,
232 			255,	255,	255,
233 			0,	0,	0,
234 			0.75,		-1.0 / (1 + frand() * 0.2),
235 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
236 			size,			1,
237 			particle_bubble,
238 			PART_SHADED,
239 			NULL,0);
240 
241 		VectorAdd (move, vec, move);
242 	}
243 }
244 
CL_Heatbeam(vec3_t start,vec3_t forward)245 void CL_Heatbeam (vec3_t start, vec3_t forward)
246 {
247 	vec3_t		move;
248 	vec3_t		vec;
249 	float		len;
250 	vec3_t		right, up;
251 	int			i;
252 	float		c, s;
253 	vec3_t		dir;
254 	float		ltime;
255 	float		step = 32.0, rstep;
256 	float		start_pt;
257 	float		rot;
258 	float		variance;
259 	vec3_t		end;
260 
261 	VectorMA (start, 4096, forward, end);
262 
263 	VectorCopy (start, move);
264 	VectorSubtract (end, start, vec);
265 	len = VectorNormalize (vec);
266 
267 	// FIXME - pmm - these might end up using old values?
268 //	MakeNormalVectors (vec, right, up);
269 	VectorCopy (cl.v_right, right);
270 	VectorCopy (cl.v_up, up);
271 
272 	VectorMA (move, -0.5, right, move);
273 	VectorMA (move, -0.5, up, move);
274 
275 	ltime = (float) cl.time/1000.0;
276 	start_pt = fmod(ltime*96.0,step);
277 	VectorMA (move, start_pt, vec, move);
278 
279 	VectorScale (vec, step, vec);
280 
281 //	Com_Printf ("%f\n", ltime);
282 	rstep = M_PI/10.0;
283 	for (i=start_pt ; i<len ; i+=step)
284 	{
285 		if (i>step*5) // don't bother after the 5th ring
286 			break;
287 
288 		for (rot = 0; rot < M_PI*2; rot += rstep)
289 		{
290 			variance = 0.5;
291 			c = cos(rot)*variance;
292 			s = sin(rot)*variance;
293 
294 			// trim it so it looks like it's starting at the origin
295 			if (i < 10)
296 			{
297 				VectorScale (right, c*(i/10.0), dir);
298 				VectorMA (dir, s*(i/10.0), up, dir);
299 			}
300 			else
301 			{
302 				VectorScale (right, c, dir);
303 				VectorMA (dir, s, up, dir);
304 			}
305 
306 			setupParticle (
307 				0,	0,	0,
308 				move[0]+dir[0]*3,	move[1]+dir[1]*3,	move[2]+dir[2]*3,
309 				0,	0,	0,
310 				0,		0,		0,
311 				200+rand()*50,	200+rand()*25,	rand()*50,
312 				0,	0,	0,
313 				0.5,		-1000.0,
314 				GL_SRC_ALPHA, GL_ONE,
315 				3,			1,
316 				particle_blaster,
317 				0,
318 				NULL,0);
319 		}
320 		VectorAdd (move, vec, move);
321 	}
322 }
323 
324 /*
325 ===============
326 CL_ParticleSteamEffect
327 
328 Puffs with velocity along direction, with some randomness thrown in
329 ===============
330 */
CL_ParticleSteamEffect(vec3_t org,vec3_t dir,int color8,int count,int magnitude)331 void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int color8, int count, int magnitude)
332 {
333 	int			i;
334 	cparticle_t	*p;
335 	float		d;
336 	vec3_t		r, u;
337 	vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
338 
339 //	vectoangles2 (dir, angle_dir);
340 //	AngleVectors (angle_dir, f, r, u);
341 
342 	MakeNormalVectors (dir, r, u);
343 
344 	for (i=0 ; i<count ; i++)
345 	{
346 		p = setupParticle (
347 			0,	0,	0,
348 			org[0]+magnitude*0.1*crand(),	org[1]+magnitude*0.1*crand(),	org[2]+magnitude*0.1*crand(),
349 			0,	0,	0,
350 			0,		0,		0,
351 			color[0],	color[1],	color[2],
352 			0,	0,	0,
353 			0.5,		-1.0 / (0.5 + frand()*0.3),
354 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
355 			4,			-2,
356 			particle_smoke,
357 			0,
358 			NULL,0);
359 
360 		if (!p)
361 			return;
362 
363 		VectorScale (dir, magnitude, p->vel);
364 		d = crand()*magnitude/3;
365 		VectorMA (p->vel, d, r, p->vel);
366 		d = crand()*magnitude/3;
367 		VectorMA (p->vel, d, u, p->vel);
368 	}
369 }
370 
CL_ParticleSteamEffect2(cl_sustain_t * self)371 void CL_ParticleSteamEffect2 (cl_sustain_t *self)
372 //vec3_t org, vec3_t dir, int color, int count, int magnitude)
373 {
374 	int			i;
375 	cparticle_t	*p;
376 	float		d;
377 	vec3_t		r, u;
378 	vec3_t		dir;
379 	int index;
380 
381 //	vectoangles2 (dir, angle_dir);
382 //	AngleVectors (angle_dir, f, r, u);
383 
384 	VectorCopy (self->dir, dir);
385 	MakeNormalVectors (dir, r, u);
386 
387 	for (i=0 ; i<self->count ; i++)
388 	{
389 		index = rand()&255;
390 		p = setupParticle (
391 			0,	0,	0,
392 			self->org[0] + self->magnitude*0.1*crand(),	self->org[1] + self->magnitude*0.1*crand(),	self->org[2] + self->magnitude*0.1*crand(),
393 			0,	0,	0,
394 			0,		0,		0,
395 			index,	index,	index,
396 			0,	0,	0,
397 			1.0,		-1.0 / (0.5 + frand()*0.3),
398 			GL_SRC_ALPHA, GL_ONE,
399 			4,			0,
400 			particle_smoke,
401 			PART_GRAVITY,
402 			NULL,0);
403 
404 		if (!p)
405 			return;
406 
407 		VectorScale (dir, self->magnitude, p->vel);
408 		d = crand()*self->magnitude/3;
409 		VectorMA (p->vel, d, r, p->vel);
410 		d = crand()*self->magnitude/3;
411 		VectorMA (p->vel, d, u, p->vel);
412 	}
413 	self->nextthink += self->thinkinterval;
414 }
415 
416 /*
417 ===============
418 CL_TrackerTrail
419 ===============
420 */
CL_TrackerTrail(vec3_t start,vec3_t end)421 void CL_TrackerTrail (vec3_t start, vec3_t end)
422 {
423 	vec3_t		move;
424 	vec3_t		vec;
425 	vec3_t		forward,right,up,angle_dir;
426 	float		len;
427 	cparticle_t	*p;
428 	int			dec;
429 	float		dist;
430 
431 	VectorCopy (start, move);
432 	VectorSubtract (end, start, vec);
433 	len = VectorNormalize (vec);
434 
435 	VectorCopy(vec, forward);
436 	vectoangles2 (forward, angle_dir);
437 	AngleVectors (angle_dir, forward, right, up);
438 
439 	dec = 3;
440 	VectorScale (vec, 3, vec);
441 
442 	// FIXME: this is a really silly way to have a loop
443 	while (len > 0)
444 	{
445 		len -= dec;
446 
447 		p = setupParticle (
448 			0,	0,	0,
449 			0,	0,	0,
450 			0,	0,	5,
451 			0,		0,		0,
452 			0,	0,	0,
453 			0,	0,	0,
454 			1.0,		-2.0,
455 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
456 			2,			0,
457 			particle_generic,
458 			0,
459 			NULL,0);
460 
461 		if (!p)
462 			return;
463 
464 		dist = DotProduct(move, forward);
465 		VectorMA(move, 8 * cos(dist), up, p->org);
466 
467 		VectorAdd (move, vec, move);
468 	}
469 }
470 
CL_Tracker_Shell(vec3_t origin)471 void CL_Tracker_Shell(vec3_t origin)
472 {
473 	vec3_t			dir;
474 	int				i;
475 	cparticle_t		*p;
476 
477 	for(i=0;i<300;i++)
478 	{
479 		p = setupParticle (
480 			0,	0,	0,
481 			0,	0,	0,
482 			0,	0,	0,
483 			0,		0,		0,
484 			0,	0,	0,
485 			0,	0,	0,
486 			1.0,		-2.0,
487 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
488 			2,			0,
489 			particle_generic,
490 			0,
491 			NULL,0);
492 
493 		if (!p)
494 			return;
495 
496 		dir[0] = crand();
497 		dir[1] = crand();
498 		dir[2] = crand();
499 		VectorNormalize(dir);
500 		VectorMA(origin, 40, dir, p->org);
501 	}
502 }
503 
CL_MonsterPlasma_Shell(vec3_t origin)504 void CL_MonsterPlasma_Shell(vec3_t origin)
505 {
506 	vec3_t			dir;
507 	int				i;
508 	cparticle_t		*p;
509 
510 	for(i=0;i<40;i++)
511 	{
512 		p = setupParticle (
513 			0,	0,	0,
514 			0,	0,	0,
515 			0,	0,	0,
516 			0,	0,	0,
517 			0,	0,	0,
518 			0,	0,	0,
519 			1.0,	0,
520 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
521 			2,		0,
522 			particle_generic,
523 			PART_INSTANT,
524 			NULL,0);
525 
526 		if (!p)
527 			return;
528 
529 		dir[0] = crand();
530 		dir[1] = crand();
531 		dir[2] = crand();
532 		VectorNormalize(dir);
533 
534 		VectorMA(origin, 10, dir, p->org);
535 	}
536 }
537 
CL_Widowbeamout(cl_sustain_t * self)538 void CL_Widowbeamout (cl_sustain_t *self)
539 {
540 	vec3_t			dir;
541 	int				i;
542 	cparticle_t		*p;
543 	float			ratio;
544 
545 	ratio = 1.0 - (((float)self->endtime - (float)cl.time)/2100.0);
546 
547 	for(i=0;i<300;i++)
548 	{
549 		p = setupParticle (
550 			0,	0,	0,
551 			0,	0,	0,
552 			0,	0,	0,
553 			0,	0,	0,
554 			0,	0,	0,
555 			0,	0,	0,
556 			1.0,	0,
557 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
558 			2,		0,
559 			particle_generic,
560 			PART_INSTANT,
561 			NULL,0);
562 
563 		if (!p)
564 			return;
565 
566 		dir[0] = crand();
567 		dir[1] = crand();
568 		dir[2] = crand();
569 		VectorNormalize(dir);
570 
571 		VectorMA(self->org, (45.0 * ratio), dir, p->org);
572 	}
573 }
574 
CL_Nukeblast(cl_sustain_t * self)575 void CL_Nukeblast (cl_sustain_t *self)
576 {
577 	vec3_t			dir;
578 	int				i;
579 	cparticle_t		*p;
580 	static int colortable0[4] = {255,	215,	185,	150};
581 	static int colortable1[4] = {255,	215,	185,	150};
582 	static int colortable2[4] = {255,	255,	255,	255};
583 	float			ratio, size;
584 	int				index;
585 	int colors[][3] =
586 	{
587 		250, 250, 255,
588 		200, 225, 255,
589 		150, 175, 255,
590 		100, 100, 255,
591 		0
592 	};
593 
594 	ratio = 1.0 - (((float)self->endtime - (float)cl.time)/1000.0);
595 	size = ratio*ratio;
596 
597 	for(i=0;i<256;i++)
598 	{
599 		index = rand()&3;
600 		p = setupParticle (
601 			0,	0,	0,
602 			0,	0,	0,
603 			0,	0,	0,
604 			0,	0,	0,
605 			colors[index][0],	colors[index][1],	colors[index][2],
606 			0,	0,	0,
607 			1-size,	0,
608 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
609 			3*(0.5+ratio*0.5),	-1,
610 			particle_generic,
611 			PART_DIRECTION|PART_INSTANT,
612 			NULL,0);
613 
614 		if (!p)
615 			return;
616 
617 		VectorSet(dir, crandom(), crandom(), crandom());
618 		VectorNormalize(dir);
619 
620 		VectorScale(dir, 50.0*size, p->angle);
621 		VectorCopy(self->org, p->org);
622 	}
623 }
624 
CL_WidowSplash(vec3_t org)625 void CL_WidowSplash (vec3_t org)
626 {
627 	static int colortable[4] = {2*8,13*8,21*8,18*8};
628 	int			i;
629 	cparticle_t	*p;
630 	vec3_t		dir;
631 
632 	for (i=0 ; i<256 ; i++)
633 	{
634 		p = setupParticle (
635 			0,	0,	0,
636 			0,	0,	0,
637 			0,	0,	0,
638 			0,	0,	0,
639 			rand()&255,	rand()&255,	rand()&255,
640 			0,	0,	0,
641 			1.0,		-0.8 / (0.5 + frand()*0.3),
642 			GL_SRC_ALPHA, GL_ONE,
643 			3,			0,
644 			particle_generic,
645 			0,
646 			NULL,0);
647 
648 		if (!p)
649 			return;
650 
651 		dir[0] = crand();
652 		dir[1] = crand();
653 		dir[2] = crand();
654 		VectorNormalize(dir);
655 		VectorMA(org, 45.0, dir, p->org);
656 		VectorMA(vec3_origin, 40.0, dir, p->vel);
657 	}
658 
659 }
660 
CL_Tracker_Explode(vec3_t origin)661 void CL_Tracker_Explode(vec3_t	origin)
662 {
663 	vec3_t			dir, backdir;
664 	int				i;
665 	cparticle_t		*p;
666 
667 	for(i=0;i<300;i++)
668 	{
669 		p = setupParticle (
670 			0,	0,	0,
671 			0,	0,	0,
672 			0,	0,	0,
673 			0,		0,		20,
674 			0,	0,	0,
675 			0,	0,	0,
676 			1.0,		-1.0,
677 			GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
678 			1.5,			0,
679 			particle_generic,
680 			0,
681 			NULL,0);
682 
683 		if (!p)
684 			return;
685 
686 		dir[0] = crand();
687 		dir[1] = crand();
688 		dir[2] = crand();
689 		VectorNormalize(dir);
690 		VectorScale(dir, -1, backdir);
691 
692 		VectorMA(origin, 64, dir, p->org);
693 		VectorScale(backdir, 64, p->vel);
694 	}
695 
696 }
697 
698 /*
699 ===============
700 CL_TagTrail
701 
702 ===============
703 */
CL_TagTrail(vec3_t start,vec3_t end,int color8)704 void CL_TagTrail (vec3_t start, vec3_t end, int color8)
705 {
706 	vec3_t		move;
707 	vec3_t		vec;
708 	float		len;
709 	int			dec;
710 	vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
711 
712 	VectorCopy (start, move);
713 	VectorSubtract (end, start, vec);
714 	len = VectorNormalize (vec);
715 
716 	dec = 5;
717 	VectorScale (vec, 5, vec);
718 
719 	while (len >= 0)
720 	{
721 		len -= dec;
722 
723 		setupParticle (
724 			0,	0,	0,
725 			move[0] + crand()*16,	move[1] + crand()*16,	move[2] + crand()*16,
726 			crand()*5,	crand()*5,	crand()*5,
727 			0,		0,		20,
728 			color[0],	color[1],	color[2],
729 			0,	0,	0,
730 			1.0,		-1.0 / (0.8+frand()*0.2),
731 			GL_SRC_ALPHA, GL_ONE,
732 			1.5,			0,
733 			particle_generic,
734 			0,
735 			NULL,0);
736 
737 		VectorAdd (move, vec, move);
738 	}
739 }
740 
741 /*
742 ===============
743 CL_ColorExplosionParticles
744 ===============
745 */
CL_ColorExplosionParticles(vec3_t org,int color8,int run)746 void CL_ColorExplosionParticles (vec3_t org, int color8, int run)
747 {
748 	int			i;
749 	vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
750 
751 	for (i=0 ; i<128 ; i++)
752 	{
753 		setupParticle (
754 			0,	0,	0,
755 			org[0] + ((rand()%32)-16),	org[1] + ((rand()%32)-16),	org[2] + ((rand()%32)-16),
756 			(rand()%256)-128,	(rand()%256)-128,	(rand()%256)-128,
757 			0,		0,		20,
758 			color[0] + (rand() % run),	color[1] + (rand() % run),	color[2] + (rand() % run),
759 			0,	0,	0,
760 			1.0,		-0.4 / (0.6 + frand()*0.2),
761 			GL_SRC_ALPHA, GL_ONE,
762 			2,			1,
763 			particle_generic,
764 			0,
765 			NULL,0);
766 	}
767 }
768 
769 /*
770 ===============
771 CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity
772 ===============
773 */
774 
pRotateThink(cparticle_t * p,vec3_t org,vec3_t angle,float * alpha,float * size,int * image,float * time)775 void pRotateThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
776 {
777 	angle[2] =	angle[0] + *time*angle[1] + *time**time*angle[2];
778 	p->thinknext=true;
779 }
780 
CL_ParticleSmokeEffect(vec3_t org,vec3_t dir,float size,float alpha)781 void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, float size, float alpha)
782 {
783 	setupParticle (
784 		crand()*180, crand()*100, 0,
785 		org[0],	org[1],	org[2],
786 		dir[0],	dir[1],	dir[2],
787 		0,		0,		10,
788 		255,	255,	255,
789 		0,	0,	0,
790 		alpha,		-2.0,
791 		GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
792 		size,			5,
793 		particle_smoke,
794 		PART_SHADED|PART_OVERBRIGHT,
795 		pRotateThink,true);
796 }
797 
798 /*
799 ===============
800 CL_BlasterParticles2
801 
802 Wall impact puffs (Green)
803 ===============
804 */
805 #define pBlasterMaxSize 5
pBlaster2Think(cparticle_t * p,vec3_t org,vec3_t angle,float * alpha,float * size,int * image,float * time)806 void pBlaster2Think (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
807 {
808 	vec3_t len;
809 	VectorSubtract(p->angle, org, len);
810 
811 	*size *= (float)(pBlasterMaxSize/VectorLength(len)) * 1.0/((4-*size));
812 	if (*size > pBlasterMaxSize)
813 		*size = pBlasterMaxSize;
814 
815 	p->thinknext = true;
816 }
CL_BlasterParticles2(vec3_t org,vec3_t dir,unsigned int color)817 void CL_BlasterParticles2 (vec3_t org, vec3_t dir, unsigned int color)
818 {
819 	int			i;
820 	float		d;
821 	int			count;
822 	float speed = .75;
823 
824 	count = 40;
825 	for (i=0 ; i<count ; i++)
826 	{
827 		d = rand()&5;
828 		setupParticle (
829 			org[0],	org[1],	org[2],
830 			org[0]+((rand()&5)-2)+d*dir[0],	org[1]+((rand()&5)-2)+d*dir[1],	org[2]+((rand()&5)-2)+d*dir[2],
831 			(dir[0]*50 + crand()*20)*speed,	(dir[1]*50 + crand()*20)*speed,	(dir[2]*50 + crand()*20)*speed,
832 			0,		0,		0,
833 			50,		235,		50,
834 			-10,	0,	-10,
835 			1,		-1.0 / (0.5 + frand()*0.3),
836 			GL_SRC_ALPHA, GL_ONE,
837 			4,			-6,
838 			particle_generic,
839 			PART_GRAVITY,
840 			pBlaster2Think,true);
841 	}
842 }
843 
844 /*
845 ===============
846 CL_BlasterTrail2
847 
848 Green!
849 ===============
850 */
CL_BlasterTrail2(vec3_t start,vec3_t end)851 void CL_BlasterTrail2 (vec3_t start, vec3_t end)
852 {
853 	vec3_t		move;
854 	vec3_t		vec;
855 	float		len;
856 	int			dec;
857 
858 	VectorCopy (start, move);
859 	VectorSubtract (end, start, vec);
860 	len = VectorNormalize (vec);
861 
862 	dec = 5;
863 	VectorScale (vec, 5, vec);
864 
865 	// FIXME: this is a really silly way to have a loop
866 	while (len > 0)
867 	{
868 		len -= dec;
869 
870 		setupParticle (
871 			0,	0,	0,
872 			move[0] + crand(),	move[1] + crand(),	move[2] + crand(),
873 			crand()*5,	crand()*5,	crand()*5,
874 			0,		0,		0,
875 			50,		235,		50,
876 			-10,	0,	-10,
877 			1,		-1.0 / (0.5 + frand()*0.3),
878 			GL_SRC_ALPHA, GL_ONE,
879 			4,			-6,
880 			particle_generic,
881 			0,
882 			NULL,0);
883 
884 		VectorAdd (move, vec, move);
885 	}
886 }
887