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