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_fx.c -- entity effects parsing and management
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "client.h"
27 #include "ref_gl/r_image.h"
28 #include "ref_gl/qgl.h"
29
30 extern particle_t particles[MAX_PARTICLES];
31 extern int cl_numparticles;
32 extern cvar_t *vid_ref;
33
34 extern void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up);
35
36 void CL_LogoutEffect (vec3_t org, int type);
37 void CL_ItemRespawnParticles (vec3_t org);
38 void CL_TeleportParticles (vec3_t start);
39
40 static vec3_t avelocities [NUMVERTEXNORMALS];
41
42 /*
43 ==============================================================
44
45 LIGHT STYLE MANAGEMENT
46
47 ==============================================================
48 */
49
50 typedef struct
51 {
52 int length;
53 float value[3];
54 float map[MAX_QPATH];
55 } clightstyle_t;
56
57 clightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
58 int lastofs;
59
60 /*
61 ================
62 CL_ClearLightStyles
63 ================
64 */
CL_ClearLightStyles(void)65 void CL_ClearLightStyles (void)
66 {
67 memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
68 lastofs = -1;
69 }
70
71 /*
72 ================
73 CL_RunLightStyles
74 ================
75 */
CL_RunLightStyles(void)76 void CL_RunLightStyles (void)
77 {
78 int ofs;
79 int i;
80 clightstyle_t *ls;
81
82 ofs = cl.time / 25;
83 if (ofs == lastofs)
84 return;
85 lastofs = ofs;
86
87 for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
88 {
89 if (!ls->length || !cl_flicker->integer)
90 {
91 ls->value[0] = ls->value[1] = ls->value[2] = 1.0;
92 continue;
93 }
94 if (ls->length == 1)
95 ls->value[0] = ls->value[1] = ls->value[2] = ls->map[0];
96 else
97 {
98 // nonlinear interpolation of the lightstyles for smoothness while
99 // still preserving some "jaggedness"
100 float a, b, dist;
101 a = ls->map[(ofs/4)%ls->length];
102 b = ls->map[(ofs/4+1)%ls->length];
103 dist = (float)(ofs%4)/4.0f;
104 if (dist != 0.75)
105 dist = 0;
106 ls->value[0] = ls->value[1] = ls->value[2] = a+(b-a)*dist;
107 }
108 }
109 }
110
111
CL_SetLightstyle(int i)112 void CL_SetLightstyle (int i)
113 {
114 char *s;
115 int j, k;
116
117 s = cl.configstrings[i+CS_LIGHTS];
118
119 j = strlen (s);
120 if (j >= MAX_QPATH)
121 Com_Error (ERR_DROP, "svc_lightstyle length=%i", j);
122
123 cl_lightstyle[i].length = j;
124
125 for (k=0 ; k<j ; k++)
126 cl_lightstyle[i].map[k] = (float)(s[k]-'a')/(float)('m'-'a');
127 }
128
129 /*
130 ================
131 CL_AddLightStyles
132 ================
133 */
CL_AddLightStyles(void)134 void CL_AddLightStyles (void)
135 {
136 int i;
137 clightstyle_t *ls;
138
139 for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
140 V_AddLightStyle (i, ls->value[0], ls->value[1], ls->value[2]);
141 }
142
143 /*
144 ==============================================================
145
146 DLIGHT MANAGEMENT
147
148 ==============================================================
149 */
150
151 cdlight_t cl_dlights[MAX_DLIGHTS];
152
153 /*
154 ================
155 CL_ClearDlights
156 ================
157 */
CL_ClearDlights(void)158 void CL_ClearDlights (void)
159 {
160 memset (cl_dlights, 0, sizeof(cl_dlights));
161 }
162
163 /*
164 ===============
165 CL_AllocDlight
166
167 ===============
168 */
CL_AllocDlight(int key)169 cdlight_t *CL_AllocDlight (int key)
170 {
171 int i;
172 cdlight_t *dl;
173
174 // first look for an exact key match
175 if (key)
176 {
177 dl = cl_dlights;
178 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
179 {
180 if (dl->key == key)
181 {
182 memset (dl, 0, sizeof(*dl));
183 dl->key = key;
184 return dl;
185 }
186 }
187 }
188
189 // then look for anything else
190 dl = cl_dlights;
191 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
192 {
193 if (dl->die < cl.time)
194 {
195 memset (dl, 0, sizeof(*dl));
196 dl->key = key;
197 return dl;
198 }
199 }
200
201 dl = &cl_dlights[0];
202 memset (dl, 0, sizeof(*dl));
203 dl->key = key;
204 return dl;
205 }
206
207 /*
208 ===============
209 CL_NewDlight
210 ===============
211 */
CL_NewDlight(int key,float x,float y,float z,float radius,float time)212 void CL_NewDlight (int key, float x, float y, float z, float radius, float time)
213 {
214 cdlight_t *dl;
215
216 dl = CL_AllocDlight (key);
217 dl->origin[0] = x;
218 dl->origin[1] = y;
219 dl->origin[2] = z;
220 dl->radius = radius;
221 dl->die = cl.time + time;
222 }
223
224
225 /*
226 ===============
227 CL_RunDLights
228
229 ===============
230 */
CL_RunDLights(void)231 void CL_RunDLights (void)
232 {
233 int i;
234 cdlight_t *dl;
235
236 dl = cl_dlights;
237 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
238 {
239 if (!dl->radius)
240 continue;
241
242 if (dl->die < cl.time)
243 {
244 dl->radius = 0;
245 return;
246 }
247 dl->radius -= cls.frametime*dl->decay;
248 if (dl->radius < 0)
249 dl->radius = 0;
250 }
251 }
252
RotateForNormal(vec3_t normal,vec3_t result)253 void RotateForNormal(vec3_t normal, vec3_t result){
254 float forward, pitch, yaw;
255
256 forward = sqrt(normal[0] * normal[0] + normal[1] * normal[1]);
257 pitch = (int)(atan2(normal[2], forward) * 180 / M_PI);
258 yaw = (int)(atan2(normal[1], normal[0]) * 180 / M_PI);
259
260 if(pitch < 0)
261 pitch += 360;
262
263 result[PITCH] = -pitch;
264 result[YAW] = yaw;
265 }
266
vectoanglerolled(vec3_t value1,float angleyaw,vec3_t angles)267 void vectoanglerolled (vec3_t value1, float angleyaw, vec3_t angles)
268 {
269 float forward, yaw, pitch;
270
271 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
272 forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
273 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
274
275 if (pitch < 0)
276 pitch += 360;
277
278 angles[PITCH] = -pitch;
279 angles[YAW] = yaw;
280 angles[ROLL] = -angleyaw;
281 }
282
283 /*
284 ==============
285 CL_ParseMuzzleFlash
286 ==============
287 */
CL_ParseMuzzleFlash(void)288 void CL_ParseMuzzleFlash (void)
289 {
290 vec3_t fv, rv, shell_brass, dir, up;
291 cdlight_t *dl;
292 int i, j, weapon;
293 centity_t *pl;
294 int silenced;
295 float volume;
296 char soundname[64];
297
298 i = MSG_ReadShort (&net_message);
299 if (i < 1 || i >= MAX_EDICTS)
300 Com_Error (ERR_DROP, "CL_ParseMuzzleFlash: bad entity");
301
302 weapon = MSG_ReadByte (&net_message);
303 silenced = weapon & MZ_SILENCED;
304 weapon &= ~MZ_SILENCED;
305
306 pl = &cl_entities[i];
307
308 dl = CL_AllocDlight (i);
309 VectorCopy (pl->current.origin, dl->origin);
310 AngleVectors (pl->current.angles, fv, rv, up);
311 VectorMA (dl->origin, 18, fv, dl->origin);
312 VectorMA (dl->origin, 16, rv, dl->origin);
313 if (silenced)
314 dl->radius = 100 + (rand()&31);
315 else
316 dl->radius = 200 + (rand()&31);
317 dl->minlight = 32;
318 dl->die = cl.time; // + 0.1;
319
320 if (silenced)
321 volume = 0.2;
322 else
323 volume = 1;
324
325 VectorMA(pl->current.origin, 10, fv, shell_brass);
326 VectorMA(shell_brass, 6, rv, shell_brass);
327 VectorMA(shell_brass, 21, up, shell_brass);
328
329 for (j = 0; j < 3; j++)
330 dir[j] = fv[j] + rv[j] + up[j] * 2;
331
332 // NOTE: sounds started here are subject to PVS rather than PHS
333 // which results in these sounds not being heard when others
334 // in same location can be heard
335 switch (weapon)
336 {
337 case MZ_BLASTER:
338 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
339 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
340 break;
341 case MZ_HYPERBLASTER:
342 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
343 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
344 break;
345 case MZ_MACHINEGUN:
346 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
347 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
348 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
349 break;
350 case MZ_SHOTGUN:
351 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
352 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
353 //[no file] S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
354 break;
355 case MZ_SSHOTGUN:
356 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
357 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
358 break;
359 case MZ_CHAINGUN1:
360 dl->radius = 200 + (rand()&31);
361 dl->color[0] = 1;dl->color[1] = 0.25;dl->color[2] = 0;
362 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
363 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
364 CL_BrassShells(shell_brass, dir, 1);
365 break;
366 case MZ_CHAINGUN2:
367 dl->radius = 225 + (rand()&31);
368 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
369 dl->die = cl.time + 0.1; // long delay
370 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
371 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
372 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
373 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
374 CL_BrassShells(shell_brass, dir, 1);
375 break;
376 case MZ_CHAINGUN3:
377 dl->radius = 250 + (rand()&31);
378 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
379 dl->die = cl.time + 0.1; // long delay
380 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
381 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
382 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
383 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
384 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
385 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
386 CL_BrassShells(shell_brass, dir, 1);
387 break;
388 case MZ_RAILGUN:
389 dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
390 // S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
391 break;
392 case MZ_ROCKET:
393 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
394 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
395 S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
396 break;
397 case MZ_GRENADE:
398 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
399 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
400 S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
401 break;
402 case MZ_BFG:
403 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
404 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
405 break;
406
407 case MZ_LOGIN:
408 dl->color[0] = 0;dl->color[1] = 1; dl->color[2] = 0;
409 dl->die = cl.time + 1.0;
410 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
411 //CL_LogoutEffect (pl->current.origin, weapon);
412 CL_TeleportParticles (pl->current.origin);
413 break;
414 case MZ_LOGOUT:
415 dl->color[0] = 1;dl->color[1] = 0; dl->color[2] = 0;
416 dl->die = cl.time + 1.0;
417 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
418 CL_LogoutEffect (pl->current.origin, weapon);
419 break;
420 case MZ_RESPAWN:
421 dl->color[0] = 1;dl->color[1] = 1; dl->color[2] = 0;
422 dl->die = cl.time + 1.0;
423 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
424 CL_LogoutEffect (pl->current.origin, weapon);
425 break;
426 }
427 }
428
429
430 /*
431 ===============
432 CL_AddDLights
433
434 ===============
435 */
CL_AddDLights(void)436 void CL_AddDLights (void)
437 {
438 int i;
439 cdlight_t *dl;
440
441 dl = cl_dlights;
442
443 //=====
444 //PGM
445 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
446 {
447 if (!dl->radius)
448 continue;
449 V_AddLight (dl->origin, dl->radius,
450 dl->color[0], dl->color[1], dl->color[2]);
451 }
452 //PGM
453 //=====
454 }
455
456
457
458 /*
459 ==============================================================
460
461 PARTICLE MANAGEMENT
462
463 ==============================================================
464 */
465
466 particle_t *active_particles, *free_particles;
467
468 particle_t particles[MAX_PARTICLES];
469 int cl_numparticles = MAX_PARTICLES;
470
addParticleLight(particle_t * p,float light,float lightvel,float lcol0,float lcol1,float lcol2)471 void addParticleLight (particle_t *p, float light, float lightvel, float lcol0, float lcol1, float lcol2)
472 {
473 int i;
474
475 for (i=0; i<P_LIGHTS_MAX; i++)
476 {
477 cplight_t *plight = &p->lights[i];
478
479 if (!plight->isactive)
480 {
481 plight->isactive = true;
482 plight->light = light;
483 plight->lightvel = lightvel;
484 plight->lightcol[0] = lcol0;
485 plight->lightcol[1] = lcol1;
486 plight->lightcol[2] = lcol2;
487 return;
488 }
489 }
490 }
491 /*
492 ===============
493 CL_ClearParticles
494 ===============
495 */
496 /*
497 Cl_ClearParticle
498 */
499
CL_ClearParticles(void)500 void CL_ClearParticles (void)
501 {
502 int i;
503
504
505 free_particles = &particles[0];
506 active_particles = NULL;
507
508 for (i=0 ;i<cl_numparticles ; i++)
509 particles[i].next = &particles[i+1];
510 particles[cl_numparticles-1].next = NULL;
511 }
512
new_particle(void)513 static inline particle_t *new_particle (void)
514 {
515 particle_t *p;
516 int j;
517
518 if (!free_particles)
519 return NULL;
520
521 p = free_particles;
522 free_particles = p->next;
523 p->next = active_particles;
524 p->type = 0;
525 p->image = NULL;
526 p->blenddst = 0;
527 p->blendsrc = 0;
528 p->scalevel = 0;
529 p->time = cl.time;
530 for(j=0; j<3; j++)
531 p->angle[j]=0;
532
533 for (j=0;j<P_LIGHTS_MAX;j++)
534 {
535 cplight_t *plight = &p->lights[j];
536 plight->isactive = false;
537 plight->light = 0;
538 plight->lightvel = 0;
539 plight->lightcol[0] = 0;
540 plight->lightcol[1] = 0;
541 plight->lightcol[2] = 0;
542 }
543 p->fromsustainedeffect = false;
544 p->chain_prev = NULL;
545
546 return (active_particles = p);
547 }
548
getColor(void)549 float getColor(void)
550 {
551 float color;
552
553 switch(cl_disbeamclr->integer) {
554 case 0:
555 default:
556 color = 0xd6; //bright green
557 break;
558 case 1:
559 color = 0x74; //blue
560 break;
561 case 2:
562 color = 0x40; //red
563 break;
564 case 3:
565 color = 0xe0; //yellow
566 break;
567 case 4:
568 color = 0xff; //purple
569 break;
570 }
571 return color;
572 }
573
getColorvec(vec3_t colorvec)574 void getColorvec(vec3_t colorvec)
575 {
576 switch(cl_disbeamclr->integer) {
577 case 0:
578 default:
579 colorvec[0] = 0; //bright green
580 colorvec[1] = 1;
581 colorvec[2] = 0.6;
582 break;
583 case 1:
584 colorvec[0] = 0; //blue
585 colorvec[1] = 0.5;
586 colorvec[2] = 0.7;
587 break;
588 case 2:
589 colorvec[0] = 0.6; //red
590 colorvec[1] = 0;
591 colorvec[2] = 0;
592 break;
593 case 3:
594 colorvec[0] = 0.7; //yellow
595 colorvec[1] = 0.7;
596 colorvec[2] = 0;
597 break;
598 case 4:
599 colorvec[0] = 0.7; //purple
600 colorvec[1] = 0;
601 colorvec[2] = 0.7;
602 break;
603 }
604 }
605
606 /*
607 ===============
608 CL_ParticleEffect
609
610 Wall impact puffs
611 ===============
612 */
CL_ParticleEffect(vec3_t org,vec3_t dir,int color,int count)613 void CL_ParticleEffect (vec3_t org, vec3_t dir, int color, int count)
614 {
615 int i, j;
616 particle_t *p;
617 float d;
618
619 if((color == 450 || color == 550) && cl_noblood->value)
620 return;
621
622 for (i=0 ; i<count ; i++)
623 {
624 if (!(p = new_particle()))
625 return;
626
627 d = rand()&31;
628 for (j=0 ; j<3 ; j++)
629 {
630 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
631 p->vel[j] = crand()*50;
632 }
633
634 p->accel[0] = p->accel[1] = 0;
635 p->accel[2] = -PARTICLE_GRAVITY;
636
637 if (color == 425) // gunshots: FIXME should be using type
638 {
639 p->type = PARTICLE_STANDARD;
640 p->image = r_pufftexture;
641 p->blendsrc = GL_SRC_ALPHA;
642 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
643 p->scale = 4 + (rand()&2);
644 p->scalevel = 0;
645 p->alpha = 0.2;
646 p->alphavel = -1.0 / (1.5 + frand()*0.3);
647 p->accel[2] = PARTICLE_GRAVITY;
648 }
649 else if (color == 450)
650 {
651 p->type = PARTICLE_STANDARD;
652 p->image = r_bloodtexture;
653 p->blendsrc = GL_SRC_ALPHA;
654 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
655 p->alpha = 0.2;
656 p->alphavel = -1.0 / (4.5 + frand()*0.3);
657 p->color = 0xe8;
658 p->scale = 6;
659 p->scalevel = 0;
660 }
661 else if (color == 550)
662 {
663 p->type = PARTICLE_STANDARD;
664 p->image = r_bloodtexture;
665 p->blendsrc = GL_SRC_ALPHA;
666 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
667 p->alpha = 0.2;
668 p->alphavel = -1.0 / (4.5 + frand()*0.3);
669 p->color = 0xd0 + (rand()&3);
670 p->scale = 6;
671 p->scalevel = 0;
672 }
673 else
674 {
675 p->type = PARTICLE_NONE;
676 p->image = r_particletexture;
677 p->blendsrc = GL_SRC_ALPHA;
678 p->blenddst = GL_ONE;
679 p->scale = 1;
680 p->scalevel = 0;
681 p->alpha = 1.0;
682 p->color = color;
683 p->alphavel = -1.0 / (0.5 + frand()*0.3);
684 }
685
686
687 }
688 }
689
690
691 /*
692 ===============
693 CL_ParticleEffect2
694 ===============
695 */
CL_ParticleEffect2(vec3_t org,vec3_t dir,int color,int count)696 void CL_ParticleEffect2 (vec3_t org, vec3_t dir, int color, int count)
697 {
698 int i, j;
699 particle_t *p;
700 float d;
701
702 for (i=0 ; i<count ; i++)
703 {
704 if (!(p = new_particle()))
705 return;
706
707 p->type = PARTICLE_STANDARD;
708 p->image = r_particletexture;
709 p->blendsrc = GL_SRC_ALPHA;
710 p->blenddst = GL_ONE;
711 p->scale = 1;
712 p->scalevel = 0;
713
714 p->color = color;
715
716 d = rand()&7;
717 for (j=0 ; j<3 ; j++)
718 {
719 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
720 p->vel[j] = crand()*20;
721 }
722
723 p->accel[0] = p->accel[1] = 0;
724 p->accel[2] = -PARTICLE_GRAVITY;
725 p->alpha = 1.0;
726
727 p->alphavel = -1.0 / (0.5 + frand()*0.3);
728 }
729 }
730
731 /*
732 ===============
733 CL_BulletSparks
734 ===============
735 */
CL_BulletSparks(vec3_t org,vec3_t dir)736 void CL_BulletSparks (vec3_t org, vec3_t dir)
737 {
738 int i, j, k;
739 float inc, scale, nudge;
740 particle_t *p;
741 particle_t *pr;
742 particle_t *center;
743
744 for( i=0; i<3; i++) {
745 nudge = frand();
746 if(nudge < 0.5)
747 dir[i] += frand();
748 else
749 dir[i] -= frand();
750 }
751
752 //draw a fatter glow at the impact point
753 if(!(p = new_particle()))
754 return;
755
756 p->type = PARTICLE_STANDARD;
757 p->image = r_particletexture;
758 p->blendsrc = GL_SRC_ALPHA;
759 p->blenddst = GL_ONE;
760 p->scale = 1;
761 p->scalevel = 0;
762
763 p->color = 0xe0 + (rand()&2);
764 for (j=0 ; j<3 ; j++)
765 {
766 p->org[j] = org[j];
767 p->vel[j] = 0;
768 }
769 p->accel[0] = p->accel[1] = p->accel[2] = 0;
770 p->alpha = .5;
771
772 p->alphavel = -1.0 / (3 + frand()*0.3);
773 center = p;
774
775 //shoot off sparks
776
777 VectorNormalize(dir);
778
779 for( k=0; k<2; k++) {
780
781 scale = frand()*3.0;
782 pr = NULL;
783
784 i = 0;
785 for (inc=1.0 ; inc<2.0 ; inc+=0.25, i++)
786 {
787 if (!(p = new_particle()))
788 return;
789
790 p->color = 0xe0 + (rand()&2);
791 p->type = PARTICLE_CHAINED;
792 p->image = r_raintexture;
793 p->blendsrc = GL_SRC_ALPHA;
794 p->blenddst = GL_ONE;
795 p->scale = 1.25*scale/inc;
796 p->scalevel = 0;
797
798 for (j=0 ; j<3 ; j++)
799 {
800 p->org[j] = org[j] + i*(-1.25*scale)*dir[j];
801 p->vel[j] = 60*dir[j];
802 }
803
804 p->accel[0] = 0;
805 p->accel[1] = 0;
806 p->accel[2] = -(PARTICLE_GRAVITY)/(.5*inc);
807 p->alpha = .5;
808
809 p->alphavel = -1.0 / (2.5 + frand()*0.3);
810
811 if (pr)
812 {
813 p->chain_prev = pr;
814 }
815 pr = p;
816 }
817 }
818 }
819
820 /*
821 ===============
822 CL_SplashEffect
823 ===============
824 */
825
CL_SplashEffect(vec3_t org,vec3_t dir,int color,int count)826 void CL_SplashEffect (vec3_t org, vec3_t dir, int color, int count)
827 {
828 int i, j, k;
829 float scale, nudge;
830 particle_t *p;
831 vec3_t angle;
832
833 //draw rings that expand outward
834 if(!(p = new_particle()))
835 return;
836 p->type = PARTICLE_RAISEDDECAL;
837 p->image = r_splashtexture;
838 p->blendsrc = GL_DST_COLOR;
839 p->blenddst = GL_SRC_COLOR;
840 p->scale = 1;
841 p->scalevel = 8;
842 p->color = 0 + (rand() & 1);
843
844 VectorScale(dir, -1, angle);
845 RotateForNormal(angle, p->angle);
846 p->angle[ROLL] = rand() % 360;
847 VectorAdd(org, dir, p->org);
848
849 for (j=0 ; j<3 ; j++)
850 {
851 p->org[j] = org[j];
852 p->vel[j] = 0;
853 }
854 p->accel[0] = p->accel[1] = p->accel[2] = 0;
855 p->alpha = .1;
856
857 p->alphavel = -0.1 / (1 + frand()*0.3);
858
859
860 for( k=0; k<count/4; k++) {
861
862 for( i=0; i<3; i++) {
863 nudge = frand();
864 if(nudge < 0.5)
865 dir[i] += frand()/2;
866 else
867 dir[i] -= frand()/2;
868 }
869
870 VectorNormalize(dir);
871 scale = frand();
872
873 //shoot off small plume of water
874 i = 0;
875 for (i=0; i<count/2; i++)
876 {
877 if (!(p = new_particle()))
878 return;
879
880 p->color = color - (rand()&2);
881 p->type = PARTICLE_VERT;
882 p->image = r_splash2texture;
883 p->blendsrc = GL_SRC_ALPHA;
884 p->blenddst = GL_ONE;
885 p->scale = 4*(rand()&8);
886 p->scalevel = 2;
887
888 for (j=0; j<3; j++)
889 {
890 p->org[j] = org[j] + 10*dir[j];
891 p->vel[j] = 60*dir[j];
892 }
893 p->org[2]+=32;
894
895 p->accel[0] = 0;
896 p->accel[1] = 0;
897 p->accel[2] = -(PARTICLE_GRAVITY)/0.5;
898 p->alpha = .5;
899
900 p->alphavel = -1.0 / (1.5 + frand()*0.3);
901 }
902 }
903 }
904 /*
905 ===============
906 CL_LaserSparks
907 ===============
908 */
CL_LaserSparks(vec3_t org,vec3_t dir,int color,int count)909 void CL_LaserSparks (vec3_t org, vec3_t dir, int color, int count)
910 {
911 int i, j, k;
912 float inc, scale, nudge;
913 particle_t *p;
914
915 for( i=0; i<3; i++) {
916 nudge = frand();
917 if(nudge < 0.5)
918 dir[i] += frand();
919 else
920 dir[i] -= frand();
921 }
922
923 //shoot off sparks
924 for( k=0; k<2; k++) {
925
926 VectorNormalize(dir);
927
928 scale = frand();
929
930 i = 0;
931 for (inc=1.0 ; inc<2.0 ; inc+=0.1, i++)
932 {
933 if (!(p = new_particle()))
934 return;
935
936 p->color = color + (rand()&2);
937 p->type = PARTICLE_STANDARD;
938 p->image = r_particletexture;
939 p->blendsrc = GL_SRC_ALPHA;
940 p->blenddst = GL_ONE;
941 p->scale = 1.5*scale/inc;
942 p->scalevel = 0;
943
944 for (j=0 ; j<3 ; j++)
945 {
946 p->org[j] = org[j] + i*(-1.5*scale)*dir[j];
947 p->vel[j] = 60*dir[j];
948 }
949
950 p->accel[0] = 0;
951 p->accel[1] = 0;
952 p->accel[2] = -(PARTICLE_GRAVITY)/(.5*inc);
953 p->alpha = .5;
954
955 p->alphavel = -1.0 / (1.5 + frand()*0.3);
956 }
957 }
958 }
959
960 /*
961 ===============
962 CL_LogoutEffect
963
964 ===============
965 */
CL_LogoutEffect(vec3_t org,int type)966 void CL_LogoutEffect (vec3_t org, int type)
967 {
968 int i, j;
969 particle_t *p;
970
971 for (i=0 ; i<500 ; i++)
972 {
973 if (!(p = new_particle()))
974 return;
975
976 p->type = PARTICLE_STANDARD;
977 p->scale = 1;
978 p->image = r_particletexture;
979 p->blendsrc = GL_SRC_ALPHA;
980 p->blenddst = GL_ONE;
981
982 if (type == MZ_LOGIN)
983 p->color = 0xd0 + (rand()&7); // green
984 else if (type == MZ_LOGOUT)
985 p->color = 0x40 + (rand()&7); // red
986 else
987 p->color = 0xe0 + (rand()&7); // yellow
988
989 p->org[0] = org[0] - 16 + frand()*32;
990 p->org[1] = org[1] - 16 + frand()*32;
991 p->org[2] = org[2] - 24 + frand()*56;
992
993 for (j=0 ; j<3 ; j++)
994 p->vel[j] = crand()*20;
995
996 p->accel[0] = p->accel[1] = 0;
997 p->accel[2] = -PARTICLE_GRAVITY;
998 p->alpha = 1.0;
999
1000 p->alphavel = -1.0 / (1.0 + frand()*0.3);
1001 }
1002 }
1003
1004
1005 /*
1006 ===============
1007 CL_ItemRespawnParticles
1008
1009 ===============
1010 */
CL_ItemRespawnParticles(vec3_t org)1011 void CL_ItemRespawnParticles (vec3_t org)
1012 {
1013 int i, j;
1014 particle_t *p;
1015
1016 for (i=0 ; i<64 ; i++)
1017 {
1018 if (!(p = new_particle()))
1019 return;
1020
1021 p->color = 0x74 + (rand()&7);
1022 p->scale = 12 + (rand()&7) ;
1023 p->scalevel = 0;
1024 p->type = PARTICLE_STANDARD;
1025 p->image = r_explosiontexture;
1026 p->blendsrc = GL_SRC_ALPHA;
1027 p->blenddst = GL_ONE;
1028 p->org[0] = org[0] + crand()*16;
1029 p->org[1] = org[1] + crand()*16;
1030 p->org[2] = org[2] + crand()*16;
1031
1032 for (j=0 ; j<3 ; j++)
1033 p->vel[j] = crand()*8;
1034
1035 p->accel[0] = p->accel[1] = 0;
1036 p->accel[2] = -PARTICLE_GRAVITY*0.2;
1037 p->alpha = .3;
1038
1039 p->alphavel = -1.0 / (1.0 + frand()*0.3);
1040
1041 if (i < 4)
1042 addParticleLight (p,
1043 p->scale*30, 10,
1044 0, 1, 1);
1045
1046 }
1047 }
1048
1049 /*
1050 ===============
1051 CL_ExplosionParticles - new version -
1052 ===============
1053 */
1054 extern int r_drawing_fbeffect;
1055 extern int r_fbFxType;
1056 extern float r_fbeffectTime;
1057 extern vec3_t r_explosionOrigin;
1058 extern float rs_realtime;
CL_ExplosionParticles(vec3_t org)1059 void CL_ExplosionParticles (vec3_t org)
1060 {
1061 int i, j, k;
1062 particle_t *p;
1063
1064 //for glsl framebuffer distortion effects
1065 if(!r_drawing_fbeffect && cl_explosiondist->value) {
1066 r_fbFxType = 1; //EXPLOSION
1067 r_drawing_fbeffect = true;
1068 VectorCopy(org, r_explosionOrigin);
1069 r_fbeffectTime = rs_realtime;
1070 }
1071
1072 for (i=0 ; i<7; i++)
1073 {
1074 for (k = 0; k<(12-i); k++) {
1075 if (!(p = new_particle()))
1076 return;
1077
1078 for (j=0 ; j<3 ; j++)
1079 {
1080 p->org[j] = org[j] + ((rand()%16)-8);
1081 p->vel[j] = 0;
1082 }
1083 p->type = PARTICLE_STANDARD;
1084 p->accel[0] = p->accel[1] = p->accel[2] = 0;
1085 p->alpha = 0.2;
1086 p->scale = 6;
1087 p->scalevel = 52;
1088 p->color = 0xd9 + (rand()&7);
1089 p->alphavel = -1.0 / (1 + i + k/5);
1090 p->blendsrc = GL_SRC_ALPHA;
1091 p->blenddst = GL_ONE;
1092 switch(i) {
1093 case 0:
1094 p->image = r_explosion1texture;
1095 break;
1096 case 1:
1097 p->image = r_explosion2texture;
1098 break;
1099 case 2:
1100 p->image = r_explosion3texture;
1101 break;
1102 case 3:
1103 p->image = r_explosion4texture;
1104 p->blendsrc = GL_SRC_ALPHA;
1105 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
1106 break;
1107 case 4:
1108 p->image = r_explosion5texture;
1109 break;
1110 case 5:
1111 p->image = r_explosion6texture;
1112 p->blendsrc = GL_SRC_ALPHA;
1113 p->blenddst = GL_ONE;
1114 break;
1115 case 6:
1116 p->image = r_explosion7texture;
1117 break;
1118 default:
1119 p->image = r_explosion1texture;
1120 break;
1121 }
1122 if (p && i < 4)
1123 addParticleLight (p,
1124 p->scale*50*i, 0,
1125 .4, .4, 0.1);
1126 }
1127 }
1128
1129 //place a big shock wave effect
1130 if (!(p = new_particle()))
1131 return;
1132 p->alpha = 1.0;
1133 p->alphavel = -2.0;
1134 p->type = PARTICLE_FLAT;
1135 p->image = r_explosion5texture;
1136 p->blendsrc = GL_SRC_ALPHA;
1137 p->blenddst = GL_ONE;
1138 p->color = 0xd9 + (rand()&7);
1139 p->scale = 12 + (rand()&4) ;
1140 p->scalevel = 100;
1141 for(j = 0; j < 3; j++) {
1142 p->org[j] = org[j];
1143 p->vel[j] = 0;
1144 p->accel[j] = 0;
1145 }
1146
1147 //add smoke
1148 for (i=0 ; i<7; i++)
1149 {
1150
1151 if (!(p = new_particle()))
1152 return;
1153
1154 for (j=0 ; j<3 ; j++)
1155 {
1156 p->org[j] = org[j] + ((rand()%32)-16);
1157 p->vel[j] = 0;
1158 }
1159 p->type = PARTICLE_STANDARD;
1160 p->accel[0] = p->accel[1] = p->accel[2] = 0;
1161 p->alpha = 0.2;
1162 p->alphavel = -2.0 / (30+frand()*1.4); //smoke lingers longer
1163
1164 p->blendsrc = GL_SRC_ALPHA;
1165 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
1166 p->scale = 1 + (rand()&4);
1167 p->scalevel = 12.0;
1168 p->color = 1 + (rand()&10);
1169 p->accel[2] = 10;
1170
1171 p->image = r_smoketexture;
1172
1173 }
1174 }
1175
1176 /*
1177 ===============
1178 CL_MuzzleParticles - changed this to a smoke effect in 6.06
1179 ===============
1180 */
CL_MuzzleParticles(vec3_t org)1181 void CL_MuzzleParticles (vec3_t org)
1182 {
1183 int i, j;
1184 particle_t *p;
1185
1186 for ( i = 0; i < 4; i++)
1187 {
1188 if (!(p = new_particle()))
1189 return;
1190
1191 for (j=0 ; j<3 ; j++)
1192 {
1193 p->org[j] = org[j] + crand()*1;
1194 p->vel[j] = crand()*5;
1195 }
1196
1197 p->alphavel = -1.0 / (30+frand()*1.4); //smoke lingers longer
1198 p->alpha = .07;
1199 p->type = PARTICLE_STANDARD;
1200 p->image = r_smoketexture;
1201 p->blendsrc = GL_SRC_ALPHA;
1202 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
1203 p->scale = 1 + (rand()&4);
1204 p->scalevel = 12.0;
1205 p->color = 15;
1206 p->accel[2] = 20;
1207 }
1208
1209 }
1210 /*
1211 ===============
1212 CL_MuzzleParticles - Blue
1213 ===============
1214 */
CL_BlueMuzzleParticles(vec3_t org)1215 void CL_BlueMuzzleParticles (vec3_t org)
1216 {
1217 int i, j;
1218 particle_t *p;
1219
1220 for ( i = 0; i < 4; i++)
1221 {
1222 if (!(p = new_particle()))
1223 return;
1224
1225 p->type = PARTICLE_STANDARD;
1226 p->image = r_cflashtexture;
1227 p->scale = 16 + (rand()&7);
1228 p->blendsrc = GL_SRC_ALPHA;
1229 p->blenddst = GL_ONE;
1230 for (j=0 ; j<3 ; j++)
1231 {
1232 p->org[j] = org[j] + ((rand()%2)-1);
1233 p->vel[j] = 0;
1234 }
1235 p->accel[0] = p->accel[1] = 0;
1236 p->accel[2] = 0;
1237 p->alpha = 0.4;
1238 p->color = 0x74;
1239
1240 p->alphavel = -2.8 / (0.5 + frand()*0.3);
1241 }
1242
1243 }
1244
1245 /*
1246 ===============
1247 CL_MuzzleFlashParticle
1248 ===============
1249 */
1250 extern cvar_t *r_lefthand;
CL_MuzzleFlashParticle(vec3_t org,vec3_t angles,qboolean from_client)1251 void CL_MuzzleFlashParticle (vec3_t org, vec3_t angles, qboolean from_client)
1252 {
1253 int j;
1254 particle_t *p;
1255 vec3_t mflashorg, vforward, vright, vup, vec;
1256 float rightoffset, len;
1257
1258 if(!from_client) {
1259 VectorSubtract (org, cl.refdef.vieworg, vec);
1260 len = VectorNormalize (vec);
1261 if(len < 128)
1262 return;
1263 }
1264
1265 VectorCopy(org, mflashorg);
1266 for (j=0 ; j<3 ; j++)
1267 {
1268 mflashorg[j] = mflashorg[j] + ((rand()%2)-1);
1269
1270 }
1271
1272 if(from_client) {
1273 AngleVectors (angles, vforward, vright, vup);
1274
1275 if (r_lefthand->value == 1.0F)
1276 rightoffset = -2.4;
1277 else
1278 rightoffset = 2.4;
1279
1280 VectorMA(mflashorg, 24, vforward, mflashorg);
1281 VectorMA(mflashorg, rightoffset, vright, mflashorg);
1282 VectorMA(mflashorg, -2.5, vup, mflashorg);
1283 }
1284
1285 if (!(p = new_particle()))
1286 return;
1287
1288 p->type = PARTICLE_STANDARD;
1289 p->image = r_bflashtexture;
1290 p->scale = 7 + (rand()&4);
1291 p->blendsrc = GL_SRC_ALPHA;
1292 p->blenddst = GL_ONE;
1293 for (j=0 ; j<3 ; j++)
1294 {
1295 p->org[j] = mflashorg[j];
1296 p->vel[j] = 0;
1297 }
1298 p->accel[0] = p->accel[1] = 0;
1299 p->accel[2] = 0;
1300 p->alpha = 0.8;
1301 p->color = 0xd9;
1302 p->alphavel = -100;
1303
1304 }
1305
CL_PlasmaFlashParticle(vec3_t org,vec3_t angles,qboolean from_client)1306 void CL_PlasmaFlashParticle (vec3_t org, vec3_t angles, qboolean from_client)
1307 {
1308 int i, j;
1309 particle_t *p;
1310 vec3_t mflashorg, vforward, vright, vup, vec;
1311 float rightoffset, len, color;
1312
1313 if(!from_client) {
1314 VectorSubtract (org, cl.refdef.vieworg, vec);
1315 len = VectorNormalize (vec);
1316 if(len < 128)
1317 return;
1318 }
1319
1320 VectorCopy(org, mflashorg);
1321 for (j=0 ; j<3 ; j++)
1322 {
1323 mflashorg[j] = mflashorg[j] + ((rand()%2)-1);
1324
1325 }
1326
1327 if(from_client) {
1328 AngleVectors (angles, vforward, vright, vup);
1329
1330 if (r_lefthand->value == 1.0F)
1331 rightoffset = -4.4;
1332 else
1333 rightoffset = 4.4;
1334
1335 VectorMA(mflashorg, 24, vforward, mflashorg);
1336 VectorMA(mflashorg, rightoffset, vright, mflashorg);
1337 VectorMA(mflashorg, -4.5, vup, mflashorg);
1338 }
1339
1340 //muzzleflash
1341 color = getColor();
1342 for(i = 0; i < 3; i++) {
1343
1344 if (!(p = new_particle()))
1345 return;
1346 p->alpha = 0.4;
1347 p->alphavel = -2.8 / (0.6+frand()*0.2);
1348 p->blenddst = GL_ONE;
1349 p->blendsrc = GL_SRC_ALPHA;
1350 p->image = r_cflashtexture;
1351 p->scale = 20/(i+1);
1352 p->type = PARTICLE_STANDARD;
1353 p->scalevel = 12;
1354 p->color = color;
1355 for (j=0 ; j<3 ; j++)
1356 {
1357 p->org[j] = mflashorg[j];
1358 p->vel[j] = 0;
1359 p->accel[j] = 0;
1360 }
1361 }
1362
1363 }
1364 /*
1365 ===============
1366 CL_SmartMuzzle
1367 ===============
1368 */
CL_SmartMuzzle(vec3_t org)1369 void CL_SmartMuzzle (vec3_t org)
1370 {
1371 int i, j;
1372 particle_t *p;
1373
1374 for ( i = 0; i < 3; i++)
1375 {
1376 if (!(p = new_particle()))
1377 return;
1378
1379 p->type = PARTICLE_STANDARD;
1380 p->image = r_leaderfieldtexture;
1381 p->scale = 24 + (rand()&2);
1382 p->color = 0xff;
1383 p->blendsrc = GL_SRC_ALPHA;
1384 p->blenddst = GL_ONE;
1385
1386 for (j=0 ; j<3 ; j++)
1387 {
1388 p->org[j] = org[j] + ((rand()%2)-1);
1389 p->vel[j] = 0;
1390 }
1391 p->accel[0] = p->accel[1] = 0;
1392 p->accel[2] = 0;
1393 p->alpha = 0.7;
1394
1395 p->alphavel = -2.8 / (0.5 + frand()*0.3);
1396 }
1397
1398 }
1399
1400 /*
1401 ===============
1402 CL_SmartMuzzle
1403 ===============
1404 */
CL_Voltage(vec3_t org)1405 void CL_Voltage (vec3_t org)
1406 {
1407 int i, j;
1408 particle_t *p;
1409
1410 for ( i = 0; i < 3; i++)
1411 {
1412 if (!(p = new_particle()))
1413 return;
1414
1415 p->type = PARTICLE_STANDARD;
1416 p->image = r_voltagetexture;
1417 p->scale = 14 + (rand()&14);
1418 p->color = 0xff;
1419 p->blendsrc = GL_SRC_ALPHA;
1420 p->blenddst = GL_ONE;
1421
1422 for (j=0 ; j<3 ; j++)
1423 {
1424 p->org[j] = org[j] + ((rand()%2)-1);
1425 p->vel[j] = 0;
1426 }
1427 p->accel[0] = p->accel[1] = 0;
1428 p->accel[2] = 0;
1429 p->alpha = 0.7;
1430
1431 p->alphavel = -2.8 / (0.5 + frand()*0.3);
1432 }
1433
1434 }
1435 /*
1436 ===============
1437 CL_Deathfield
1438 ===============
1439 */
CL_Deathfield(vec3_t org,int type)1440 void CL_Deathfield (vec3_t org, int type)
1441 {
1442 int j;
1443 particle_t *p;
1444
1445 if (!(p = new_particle()))
1446 return;
1447
1448 p->type = PARTICLE_STANDARD;
1449 if(type)
1450 p->image = r_deathfieldtexture2;
1451 else
1452 p->image = r_deathfieldtexture;
1453 p->blendsrc = GL_SRC_ALPHA;
1454 p->blenddst = GL_ONE;
1455 for (j=0 ; j<3 ; j++)
1456 {
1457 p->org[j] = org[j] + ((rand()%2)-1);
1458 p->vel[j] = 0;
1459 }
1460 p->accel[0] = p->accel[1] = 0;
1461 p->accel[2] = 0;
1462 p->alpha = 1.5;
1463 p->scale = 10 + (rand()&2);
1464 p->scalevel = 12;
1465 p->color = 0x72;
1466 p->accel[0] = p->accel[1] = 0;
1467 p->accel[2] = PARTICLE_GRAVITY;
1468 p->alphavel = -1.28 / (2.0 + frand()*0.3);
1469 }
1470
1471 /*
1472 ===============
1473 CL_SayIcon
1474
1475 Displays an icon above a player when talking
1476 ===============
1477 */
1478
CL_SayIcon(vec3_t org)1479 void CL_SayIcon(vec3_t org)
1480 {
1481 particle_t *p;
1482 int j;
1483
1484 if(!(p = new_particle()))
1485 return;
1486
1487 p->type = PARTICLE_STANDARD;
1488 p->image = r_sayicontexture;
1489 p->scale = 5;
1490 p->scalevel = 0;
1491 p->color = 15;
1492 p->blendsrc = GL_SRC_ALPHA;
1493 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
1494 for(j=0; j<3; j++)
1495 {
1496 p->org[j] = org[j];
1497 p->vel[j] = 0;
1498 p->accel[j] = 0;
1499 }
1500 p->org[2]+=40;
1501 p->alpha = 0.9;
1502
1503 p->alphavel = -0.5;
1504 }
1505
1506
1507 /*
1508 ===============
1509 CL_DustParticles
1510 ===============
1511 */
CL_DustParticles(vec3_t org)1512 void CL_DustParticles (vec3_t org)
1513 {
1514 int i, j;
1515 particle_t *p;
1516
1517 for (i=0 ; i<64 ; i++)
1518 {
1519 if (!(p = new_particle()))
1520 return;
1521
1522 p->type = PARTICLE_STANDARD;
1523 p->image = r_pufftexture;
1524 p->blendsrc = GL_SRC_ALPHA;
1525 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
1526 p->scale = 4 + (rand()&2);
1527 p->color = 15;
1528 p->scalevel = 1.5;
1529 for (j=0 ; j<3 ; j++)
1530 {
1531 p->org[j] = org[j] + ((rand()%4)-2);
1532 p->vel[j] = (rand()%88)-44;
1533 }
1534
1535 p->accel[0] = p->accel[1] = 0;
1536 p->accel[2] = -PARTICLE_GRAVITY;
1537 p->alpha = 0.5;
1538
1539 p->alphavel = -0.8 / (0.5 + frand()*0.3);
1540 }
1541 }
1542
1543 /*
1544 ===============
1545 CL_BigTeleportParticles
1546 ===============
1547 */
CL_BigTeleportParticles(vec3_t org)1548 void CL_BigTeleportParticles (vec3_t org)
1549 {
1550 int i, j;
1551 particle_t *p;
1552
1553 for (i=1 ; i<3 ; i++)
1554 {
1555 if (!(p = new_particle()))
1556 return;
1557
1558 if(i == 1)
1559 p->type = PARTICLE_ROTATINGROLL;
1560 else
1561 p->type = PARTICLE_STANDARD;
1562 p->image = r_leaderfieldtexture;
1563 p->scale = 16*i + (rand()&7);
1564 p->blendsrc = GL_SRC_ALPHA;
1565 p->blenddst = GL_ONE;
1566 if(i>1)
1567 p->color = 0xd4;
1568 else
1569 p->color = 0x74;
1570 p->scalevel = 30;
1571 for (j=0 ; j<3 ; j++)
1572 {
1573 p->org[j] = org[j];
1574 p->vel[j] = 0;
1575 }
1576 p->accel[0] = p->accel[1] = 0;
1577 p->accel[2] = 0;
1578 p->alpha = 0.5;
1579
1580 p->alphavel = -0.9 / (0.5 + frand()*0.3);
1581
1582 addParticleLight (p,
1583 p->scale*(2+(rand()&5)), 0,
1584 0, .6, 0.4);
1585 }
1586 }
1587 /*
1588 ===============
1589 CL_HealthParticles
1590 ===============
1591 */
CL_SmallHealthParticles(vec3_t org)1592 void CL_SmallHealthParticles (vec3_t org)
1593 {
1594 particle_t *p;
1595 float angle, dist;
1596
1597 if (!(p = new_particle()))
1598 return;
1599
1600 p->type = PARTICLE_STANDARD;
1601 p->image = r_cflashtexture;
1602 p->scale = 10 + (rand()&7);
1603 p->blendsrc = GL_SRC_ALPHA;
1604 p->blenddst = GL_ONE;
1605 p->color = 0xd4 + (rand() & 1);
1606
1607 angle = M_PI*2*(rand()&1023)/1023.0;
1608 dist = rand()&5;
1609 p->org[0] = org[0] + cos(angle)*dist;
1610 p->vel[0] = cos(angle)*(6+(rand()&6));
1611 p->accel[0] = -cos(angle)*6;
1612
1613 p->org[1] = org[1] + sin(angle)*dist;
1614 p->vel[1] = sin(angle)*(6+(rand()&6));
1615 p->accel[1] = -sin(angle)*100;
1616
1617 p->org[2] = org[2] + 8 + (rand()%10);
1618 p->vel[2] = -10 + (rand()&6);
1619 p->accel[2] = PARTICLE_GRAVITY*10;
1620 p->alpha = 0.2;
1621
1622 p->alphavel = -2.6 / (0.5 + frand()*0.3);
1623
1624 }
CL_MedHealthParticles(vec3_t org)1625 void CL_MedHealthParticles (vec3_t org)
1626 {
1627 particle_t *p;
1628 float angle, dist;
1629
1630 if (!(p = new_particle()))
1631 return;
1632
1633 p->type = PARTICLE_STANDARD;
1634 p->image = r_cflashtexture;
1635 p->scale = 10 + (rand()&7);
1636 p->blendsrc = GL_SRC_ALPHA;
1637 p->blenddst = GL_ONE;
1638 p->color = 0x74 + (rand() & 1);
1639
1640 angle = M_PI*2*(rand()&1023)/1023.0;
1641 dist = rand()&5;
1642 p->org[0] = org[0] + cos(angle)*dist;
1643 p->vel[0] = cos(angle)*(6+(rand()&6));
1644 p->accel[0] = -cos(angle)*6;
1645
1646 p->org[1] = org[1] + sin(angle)*dist;
1647 p->vel[1] = sin(angle)*(6+(rand()&6));
1648 p->accel[1] = -sin(angle)*100;
1649
1650 p->org[2] = org[2] + 8 + (rand()%10);
1651 p->vel[2] = -10 + (rand()&6);
1652 p->accel[2] = PARTICLE_GRAVITY*10;
1653 p->alpha = 0.3;
1654
1655 p->alphavel = -2.6 / (0.5 + frand()*0.3);
1656
1657 }
CL_LargeHealthParticles(vec3_t org)1658 void CL_LargeHealthParticles (vec3_t org)
1659 {
1660 particle_t *p;
1661 float angle, dist;
1662
1663 if (!(p = new_particle()))
1664 return;
1665
1666 p->type = PARTICLE_STANDARD;
1667 p->image = r_cflashtexture;
1668 p->scale = 10 + (rand()&7);
1669 p->blendsrc = GL_SRC_ALPHA;
1670 p->blenddst = GL_ONE;
1671 p->color = 0xff + (rand() & 1);
1672
1673 angle = M_PI*2*(rand()&1023)/1023.0;
1674 dist = rand()&5;
1675 p->org[0] = org[0] + cos(angle)*dist;
1676 p->vel[0] = cos(angle)*(6+(rand()&6));
1677 p->accel[0] = -cos(angle)*6;
1678
1679 p->org[1] = org[1] + sin(angle)*dist;
1680 p->vel[1] = sin(angle)*(6+(rand()&6));
1681 p->accel[1] = -sin(angle)*100;
1682
1683 p->org[2] = org[2] + 8 + (rand()%10);
1684 p->vel[2] = -10 + (rand()&6);
1685 p->accel[2] = PARTICLE_GRAVITY*10;
1686 p->alpha = 0.3;
1687
1688 p->alphavel = -2.6 / (0.5 + frand()*0.3);
1689
1690 }
1691 /*
1692 ===============
1693 CL_BlasterParticles
1694
1695 Wall impact puffs for standard blaster.
1696 ===============
1697 */
CL_BlasterParticles(vec3_t org,vec3_t dir)1698 void CL_BlasterParticles (vec3_t org, vec3_t dir)
1699 {
1700 int i, j;
1701 particle_t *p;
1702 float d;
1703 for (i=0 ; i<16 ; i++)
1704 {
1705 if (!(p = new_particle()))
1706 return;
1707
1708 p->type = PARTICLE_STANDARD;
1709 p->image = r_cflashtexture;
1710 p->blendsrc = GL_SRC_ALPHA;
1711 p->blenddst = GL_ONE;
1712 p->color = 0x74;
1713 p->scale = (.75 * (i+1)) + (rand()&2);
1714 p->scalevel = 12;
1715 d = rand()&7;
1716 for (j=0 ; j<3 ; j++)
1717 {
1718 p->org[j] = org[j] + d*dir[j];
1719 p->vel[j] = 0;
1720 p->accel[j] = 0;
1721 }
1722 p->alpha = 0.3;
1723
1724 p->alphavel = -8.8 / ((i*2) + frand()*0.3);
1725
1726 if (i > 4)
1727 addParticleLight (p,
1728 p->scale*25, 50,
1729 0, .8, 1);
1730 }
1731 }
1732
1733 /*
1734 ===============
1735 CL_BlasterBall
1736
1737 ===============
1738 */
CL_BlasterBall(vec3_t start,vec3_t end)1739 void CL_BlasterBall (vec3_t start, vec3_t end)
1740 {
1741 vec3_t move;
1742 vec3_t vec;
1743 float len;
1744 int j;
1745 particle_t *p;
1746
1747 VectorCopy (start, move);
1748 VectorSubtract (end, start, vec);
1749 len = VectorNormalize (vec);
1750
1751 VectorScale (vec, 5, vec);
1752
1753 if (!(p = new_particle()))
1754 return;
1755
1756 p->alpha = 1;
1757 p->alphavel = INSTANT_PARTICLE;
1758 p->type = PARTICLE_ROTATINGROLL;
1759 p->image = r_shottexture;
1760 p->scale = 8;
1761 p->angle[1] = cl.refdef.viewangles[0];
1762 p->angle[0] = sin(len);
1763 p->angle[2] = cl.refdef.viewangles[2];
1764 p->blendsrc = GL_SRC_ALPHA;
1765 p->blenddst = GL_ONE;
1766 p->color = 0x72;
1767
1768 for (j=0 ; j<3 ; j++)
1769 {
1770 p->org[j] = move[j];
1771 p->vel[j] = 0;
1772 p->accel[j] = 0;
1773 }
1774
1775 if (!(p = new_particle()))
1776 return;
1777
1778 p->alpha = .95;
1779 p->alphavel = INSTANT_PARTICLE;
1780 p->type = PARTICLE_STANDARD;
1781 p->image = r_cflashtexture;
1782 p->scale = 15+5*frand();
1783 p->blendsrc = GL_ONE;
1784 p->blenddst = GL_ONE;
1785 p->color = 0x79;
1786
1787 for (j=0 ; j<3 ; j++)
1788 {
1789 p->org[j] = move[j];
1790 p->vel[j] = 0;
1791 p->accel[j] = 0;
1792 }
1793 }
1794
1795 /*
1796 ===============
1797 Team Lights
1798
1799 ===============
1800 */
1801
CL_BlueTeamLight(vec3_t pos)1802 void CL_BlueTeamLight(vec3_t pos)
1803 {
1804
1805 int i,j;
1806 particle_t *p;
1807
1808 if(!server_is_team && !cl_dmlights->value)
1809 return;
1810
1811 for(i=1; i<3; i++) {
1812 if (!(p = new_particle()))
1813 return;
1814
1815 VectorClear (p->accel);
1816
1817 p->alpha = .7;
1818 p->type = PARTICLE_STANDARD;
1819 p->image = r_flaretexture;
1820 p->blendsrc = GL_ONE;
1821 p->blenddst = GL_ONE;
1822 if (server_is_team)
1823 p->color = 0x74;
1824 else
1825 p->color = 0xd3;
1826 p->scale = 10*i;
1827 p->alphavel = INSTANT_PARTICLE;
1828 for (j=0 ; j<3 ; j++)
1829 {
1830 p->org[j] = pos[j];
1831 p->vel[j] = 0;
1832 p->accel[j] = 0;
1833 }
1834 }
1835 }
CL_RedTeamLight(vec3_t pos)1836 void CL_RedTeamLight(vec3_t pos)
1837 {
1838
1839 int j,i;
1840 particle_t *p;
1841
1842 for(i=1; i<3; i++) {
1843 if (!(p = new_particle()))
1844 return;
1845
1846 VectorClear (p->accel);
1847
1848 p->alpha = .7;
1849 p->type = PARTICLE_STANDARD;
1850 p->image = r_flaretexture;
1851 p->blendsrc = GL_ONE;
1852 p->blenddst = GL_ONE;
1853 p->color = 0xe8;
1854 p->scale = 10*i;
1855 p->alphavel = INSTANT_PARTICLE;
1856 for (j=0 ; j<3 ; j++)
1857 {
1858 p->org[j] = pos[j];
1859 p->vel[j] = 0;
1860 p->accel[j] = 0;
1861 }
1862 }
1863 }
CL_FlagEffects(vec3_t pos,qboolean team)1864 void CL_FlagEffects(vec3_t pos, qboolean team)
1865 {
1866
1867 int i;
1868 particle_t *p;
1869 float dist, angle;
1870
1871 if (!(p = new_particle()))
1872 return;
1873
1874 VectorClear (p->accel);
1875
1876 p->alpha = 1.0;
1877 p->type = PARTICLE_ROTATINGYAW;
1878 p->image = r_flagtexture;
1879 p->blendsrc = GL_ONE;
1880 p->blenddst = GL_ONE;
1881 if(team)
1882 p->color = 0x74;
1883 else
1884 p->color = 0xe8;
1885 p->scale = 15;
1886 p->alphavel = INSTANT_PARTICLE;
1887 for (i=0 ; i<3 ; i++)
1888 {
1889 p->org[i] = pos[i];
1890 p->vel[i] = 0;
1891 p->accel[i] = 0;
1892 }
1893 p->org[2] += 64;
1894
1895
1896
1897 if (!(p = new_particle()))
1898 return;
1899
1900 p->type = PARTICLE_STANDARD;
1901 p->image = r_cflashtexture;
1902 p->scale = 20 + (rand()&7);
1903 p->blendsrc = GL_ONE;
1904 p->blenddst = GL_ONE;
1905 if(team)
1906 p->color = 0x74;
1907 else
1908 p->color = 0xe8;
1909
1910 angle = M_PI*2*(rand()&1023)/1023.0;
1911 dist = rand()&5;
1912 p->org[0] = pos[0] + cos(angle)*dist;
1913 p->vel[0] = cos(angle)*(6+(rand()&6));
1914 p->accel[0] = -cos(angle)*6;
1915
1916 p->org[1] = pos[1] + sin(angle)*dist;
1917 p->vel[1] = sin(angle)*(6+(rand()&6));
1918 p->accel[1] = -sin(angle)*100;
1919
1920 p->org[2] = pos[2] + 56 + (rand()%10);
1921 p->vel[2] = -10 + (rand()&6);
1922 p->accel[2] = PARTICLE_GRAVITY*10;
1923 p->alpha = 0.2;
1924
1925 p->alphavel = -50 / (0.5 + frand()*0.3);
1926 }
1927
1928 /*
1929 ===============
1930 CL_BloodSplatter - simple blood effects
1931 ===============
1932 */
1933
CL_BloodSplatter(vec3_t pos,vec3_t pos2,int color,int blend)1934 void CL_BloodSplatter ( vec3_t pos, vec3_t pos2, int color, int blend )
1935 {
1936 particle_t *p;
1937 vec3_t v;
1938 int j;
1939 trace_t trace;
1940 static vec3_t mins = { -1, -1, -1 };
1941 static vec3_t maxs = { 1, 1, 1 };
1942
1943 //trace to see if impact occurs with nearby brush
1944 trace = CL_Trace ( pos, mins, maxs, pos2, -1, MASK_SOLID, true, NULL);
1945 if(trace.contents) { //hit a brush
1946
1947 if(!(p = new_particle()))
1948 return;
1949
1950 p->image = r_bloodtexture;
1951 p->color = color + (rand() & 1);
1952 p->type = PARTICLE_DECAL;
1953 p->blendsrc = GL_SRC_ALPHA;
1954 if(blend) //glowing blood
1955 p->blenddst = GL_ONE;
1956 else
1957 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
1958 p->scale = 2;
1959 p->scalevel = 0;
1960
1961 VectorScale(trace.plane.normal, -1, v);
1962 RotateForNormal(v, p->angle);
1963 p->angle[ROLL] = rand() % 360;
1964 VectorAdd(pos2, trace.plane.normal, p->org);
1965
1966 p->alpha = 0.7;
1967 p->alphavel = -0.2 / (2.0 + frand() * 0.3);
1968 for (j=0 ; j<3 ; j++)
1969 {
1970 p->accel[j] = 0;
1971 p->vel[j] = 0;
1972 }
1973 }
1974 }
1975
1976 /*
1977 ===============
1978 CL_DiminishingTrail
1979
1980 ===============
1981 */
CL_DiminishingTrail(vec3_t start,vec3_t end,centity_t * old,int flags)1982 void CL_DiminishingTrail (vec3_t start, vec3_t end, centity_t *old, int flags)
1983 {
1984 vec3_t move;
1985 vec3_t vec;
1986 float len;
1987 int j;
1988 particle_t *p;
1989 float dec;
1990 float orgscale;
1991 float velscale;
1992
1993 if (((flags & EF_GIB) || (flags & EF_GREENGIB)) && cl_noblood->value)
1994 return;
1995
1996 VectorCopy (start, move);
1997 VectorSubtract (end, start, vec);
1998 len = VectorNormalize (vec);
1999
2000 dec = 2.5;
2001 VectorScale (vec, dec, vec);
2002
2003 if (old->trailcount > 900)
2004 {
2005 orgscale = 4;
2006 velscale = 15;
2007 }
2008 else if (old->trailcount > 800)
2009 {
2010 orgscale = 2;
2011 velscale = 10;
2012 }
2013 else
2014 {
2015 orgscale = 1;
2016 velscale = 5;
2017 }
2018
2019 // add stains if moving
2020 if ( len && !cl_noblood->value ) {
2021 if ( flags & EF_GIB ) {
2022 CL_BloodSplatter(start, end, 0xe8, 0);
2023 } else if ( flags & EF_GREENGIB ) {
2024 CL_BloodSplatter(start, end, 0xd0, 1);
2025 }
2026 }
2027
2028 while (len > 0)
2029 {
2030 len -= dec;
2031
2032 if (!free_particles)
2033 return;
2034
2035 // drop less particles as it flies
2036 if ((rand()&1023) < old->trailcount)
2037 {
2038 if (!(p = new_particle()))
2039 return;
2040
2041 if (flags & EF_GIB)
2042 {
2043 p->alpha = .6;//1.0;
2044 p->alphavel = -1.0 / (1+frand()*0.4);
2045 p->type = PARTICLE_STANDARD;
2046 p->image = r_bloodtexture;
2047 p->blendsrc = GL_SRC_ALPHA;
2048 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
2049 p->color = 0xe8;
2050 p->scale = 6;
2051 p->scalevel = 1.5;
2052 for (j=0 ; j<3 ; j++)
2053 {
2054 p->org[j] = move[j] + crand()*orgscale;
2055 p->vel[j] = crand()*velscale;
2056 p->accel[j] = 0;
2057 }
2058 p->vel[2] -= PARTICLE_GRAVITY;
2059 }
2060 else if (flags & EF_GREENGIB)
2061 {
2062 p->alpha = .6;
2063 p->alphavel = -1.0 / (1+frand()*0.4);
2064 p->type = PARTICLE_STANDARD;
2065 p->image = r_bloodtexture;
2066 p->blendsrc = GL_SRC_ALPHA;
2067 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
2068 p->color = 0xd0+ (rand()&3);
2069 p->scale = 6;
2070 p->scalevel = 1.5;
2071 for (j=0; j< 3; j++)
2072 {
2073 p->org[j] = move[j] + crand()*orgscale;
2074 p->vel[j] = crand()*velscale;
2075 p->accel[j] = 0;
2076 }
2077 p->vel[2] -= PARTICLE_GRAVITY;
2078 }
2079 else
2080 {
2081 dec = 10; //less smoke
2082 for (j=0 ; j<3 ; j++)
2083 {
2084 p->org[j] = move[j] + crand()*orgscale;
2085 p->vel[j] = crand()*velscale;
2086 }
2087
2088 p->alphavel = -1.0 / (10+frand()*1.4); //smoke lingers longer
2089 p->alpha = .07;
2090 p->type = PARTICLE_STANDARD;
2091 p->image = r_smoketexture;
2092 p->blendsrc = GL_SRC_ALPHA;
2093 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
2094 p->scale = 1 + (rand()&4);
2095 p->scalevel = 15.0;
2096 p->color = 15;
2097 p->accel[2] = 20;
2098 }
2099 }
2100
2101 old->trailcount -= 5;
2102 if (old->trailcount < 100)
2103 old->trailcount = 100;
2104 VectorAdd (move, vec, move);
2105 }
2106 }
2107
MakeNormalVectors(vec3_t forward,vec3_t right,vec3_t up)2108 void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
2109 {
2110 float d;
2111
2112 // this rotate and negat guarantees a vector
2113 // not colinear with the original
2114 right[1] = -forward[0];
2115 right[2] = forward[1];
2116 right[0] = forward[2];
2117
2118 d = DotProduct (right, forward);
2119 VectorMA (right, -d, forward, right);
2120 VectorNormalize (right);
2121 CrossProduct (right, forward, up);
2122 }
2123
2124 /*
2125 ===============
2126 CL_RocketTrail
2127
2128 ===============
2129 */
CL_RocketTrail(vec3_t start,vec3_t end,centity_t * old)2130 void CL_RocketTrail (vec3_t start, vec3_t end, centity_t *old)
2131 {
2132
2133 // smoke
2134 CL_DiminishingTrail (start, end, old, EF_ROCKET);
2135
2136 }
2137
CL_BlasterTrail(vec3_t start,vec3_t end,centity_t * old)2138 void CL_BlasterTrail (vec3_t start, vec3_t end, centity_t *old)
2139 {
2140 vec3_t move;
2141 vec3_t vec;
2142 float len;
2143 int j;
2144 particle_t *p;
2145 float dec;
2146
2147 VectorCopy (start, move);
2148 VectorSubtract (end, start, vec);
2149 len = VectorNormalize (vec);
2150
2151 dec = 20;
2152 VectorScale (vec, dec, vec);
2153
2154 while (len > 0)
2155 {
2156 len -= dec;
2157
2158 if ( (rand()&6) == 0)
2159 {
2160 if (!(p = new_particle()))
2161 return;
2162
2163 VectorClear (p->accel);
2164 p->color = 0xd0 + (rand()&2);
2165 p->scale = 2 + (rand()&7);
2166 p->scalevel = 5;
2167 p->alpha = .3;
2168 p->alphavel = -1.0 / (3+frand()*0.2);
2169 p->type = PARTICLE_STANDARD;
2170 p->image = r_cflashtexture;
2171 p->blendsrc = GL_SRC_ALPHA;
2172 p->blenddst = GL_ONE;
2173 for (j=0 ; j<3 ; j++)
2174 {
2175 p->org[j] = move[j] + crand()*2;
2176 p->vel[j] = crand()*2;
2177 }
2178 p->accel[2] = 0;
2179 }
2180 VectorAdd (move, vec, move);
2181
2182 }
2183 }
2184
CL_ShipExhaust(vec3_t start,vec3_t end,centity_t * old)2185 void CL_ShipExhaust (vec3_t start, vec3_t end, centity_t *old)
2186 {
2187 vec3_t move;
2188 vec3_t vec;
2189 float len;
2190 int j;
2191 particle_t *p;
2192 float dec;
2193
2194 VectorCopy (start, move);
2195 VectorSubtract (end, start, vec);
2196 len = VectorNormalize (vec);
2197
2198 dec = 3;
2199 VectorScale (vec, dec, vec);
2200
2201 while (len > 0)
2202 {
2203 len -= dec;
2204
2205 if ( (rand()&6) == 0)
2206 {
2207 if (!(p = new_particle()))
2208 return;
2209
2210 VectorClear (p->accel);
2211 p->color = 0xc0 + (rand()&2);
2212 p->scale = 2 + (rand()&7);
2213 p->scalevel = 5;
2214 p->alpha = .3;
2215 p->alphavel = -1.0 / (3+frand()*0.2);
2216 p->type = PARTICLE_STANDARD;
2217 p->image = r_explosiontexture;
2218 p->blendsrc = GL_SRC_ALPHA;
2219 p->blenddst = GL_ONE;
2220 for (j=0 ; j<3 ; j++)
2221 {
2222 p->org[j] = move[j] + crand()*2;
2223 p->vel[j] = crand()*2;
2224 }
2225 p->accel[2] = 0;
2226 }
2227 VectorAdd (move, vec, move);
2228
2229 }
2230 }
2231
CL_RocketExhaust(vec3_t start,vec3_t end,centity_t * old)2232 void CL_RocketExhaust (vec3_t start, vec3_t end, centity_t *old)
2233 {
2234 vec3_t move;
2235 vec3_t vec;
2236 float len;
2237 int j;
2238 particle_t *p;
2239
2240 VectorCopy (start, move);
2241 VectorSubtract (end, start, vec);
2242 len = VectorNormalize (vec);
2243
2244 VectorScale (vec, 5, vec);
2245
2246 if (!(p = new_particle()))
2247 return;
2248
2249 VectorClear (p->accel);
2250
2251 p->alpha = .3;
2252 p->alphavel = INSTANT_PARTICLE;
2253 p->type = PARTICLE_ROTATINGROLL;
2254 p->image = r_bflashtexture;
2255 p->scale = 5;
2256 p->angle[0] = cl.refdef.viewangles[0];
2257 p->angle[1] = cl.refdef.viewangles[1];
2258 p->angle[2] = cl.refdef.viewangles[2];
2259
2260 p->blendsrc = GL_SRC_ALPHA;
2261 p->blenddst = GL_ONE;
2262 p->color = 0xc0 + (rand()&2);
2263 for (j=0 ; j<3 ; j++)
2264 {
2265 p->org[j] = move[j];
2266 p->vel[j] = 0;
2267 p->accel[j] = 0;
2268 }
2269
2270 if (!(p = new_particle()))
2271 return;
2272
2273 VectorClear (p->accel);
2274
2275 p->alpha = .7;
2276 p->alphavel = INSTANT_PARTICLE;
2277 p->type = PARTICLE_STANDARD;
2278 p->image = r_bflashtexture;
2279 p->scale = 5;
2280 p->angle[0] = cl.refdef.viewangles[0];
2281 p->angle[1] = cl.refdef.viewangles[1];
2282 p->angle[2] = cl.refdef.viewangles[2];
2283
2284 p->blendsrc = GL_SRC_ALPHA;
2285 p->blenddst = GL_ONE;
2286 p->color = 0xc0 + (rand()&2);
2287 for (j=0 ; j<3 ; j++)
2288 {
2289 p->org[j] = move[j];
2290 p->vel[j] = 0;
2291 p->accel[j] = 0;
2292 }
2293
2294 if (!(p = new_particle()))
2295 return;
2296
2297 VectorClear (p->accel);
2298
2299 p->alpha = .7;
2300 p->alphavel = INSTANT_PARTICLE;
2301 p->type = PARTICLE_STANDARD;
2302 p->image = r_flaretexture;
2303 p->scale = 10;
2304 p->angle[0] = cl.refdef.viewangles[0];
2305 p->angle[1] = cl.refdef.viewangles[1];
2306 p->angle[2] = cl.refdef.viewangles[2];
2307
2308 p->blendsrc = GL_ONE;
2309 p->blenddst = GL_ONE;
2310 p->color = 0xc0 + (rand()&2);
2311 for (j=0 ; j<3 ; j++)
2312 {
2313 p->org[j] = move[j];
2314 p->vel[j] = 0;
2315 p->accel[j] = 0;
2316 }
2317
2318 VectorAdd (move, vec, move);
2319 }
2320
2321 /*
2322 ===============
2323 Wall Impacts
2324
2325 ===============
2326 */
2327
CL_BulletMarks(vec3_t org,vec3_t dir)2328 void CL_BulletMarks(vec3_t org, vec3_t dir){
2329 particle_t *p;
2330 vec3_t v;
2331 int j;
2332
2333 if(!(p = new_particle()))
2334 return;
2335
2336 p->image = r_bulletnormal;
2337 p->color = 0 + (rand() & 1);
2338 p->type = PARTICLE_RAISEDDECAL;
2339 p->blendsrc = GL_DST_COLOR;
2340 p->blenddst = GL_SRC_COLOR;
2341
2342 VectorScale(dir, -1, v);
2343 RotateForNormal(v, p->angle);
2344 p->angle[ROLL] = rand() % 360;
2345 VectorAdd(org, dir, p->org);
2346
2347 p->scale = .5;
2348 p->alpha = 0.5;
2349 p->alphavel = -0.2 / (2.0 + frand() * 0.3);
2350 for (j=0 ; j<3 ; j++)
2351 {
2352 p->accel[j] = 0;
2353 p->vel[j] = 0;
2354 }
2355 }
CL_BeamgunMark(vec3_t org,vec3_t dir,float dur,qboolean isDis)2356 void CL_BeamgunMark(vec3_t org, vec3_t dir, float dur, qboolean isDis){
2357 particle_t *p;
2358 vec3_t v;
2359 int j;
2360 float color;
2361 vec3_t colorvec;
2362
2363 if(isDis)
2364 color = getColor();
2365 else
2366 color = 0xd4;
2367
2368 if(!(p = new_particle()))
2369 return;
2370
2371 p->image = r_bullettexture;
2372 p->color = color + (rand() & 1);
2373 p->type = PARTICLE_DECAL;
2374 p->blendsrc = GL_SRC_ALPHA;
2375 p->blenddst = GL_ONE;
2376 p->scale = .75;
2377 p->scalevel = 0;
2378
2379 VectorScale(dir, -1, v);
2380 RotateForNormal(v, p->angle);
2381 p->angle[ROLL] = rand() % 360;
2382 VectorAdd(org, dir, p->org);
2383
2384 p->alpha = 0.5;
2385 p->alphavel = -dur / (2.0 + frand() * 0.3);
2386 for (j=0 ; j<3 ; j++)
2387 {
2388 p->accel[j] = 0;
2389 p->vel[j] = 0;
2390 }
2391 if(!(p = new_particle()))
2392 return;
2393
2394 p->image = r_bullettexture;
2395 p->color = color + (rand() & 1);
2396 p->type = PARTICLE_DECAL;
2397 p->blendsrc = GL_SRC_ALPHA;
2398 p->blenddst = GL_ONE;
2399 p->scale = 1.5;
2400 p->scalevel = 0;
2401
2402 VectorScale(dir, -1, v);
2403 RotateForNormal(v, p->angle);
2404 p->angle[ROLL] = rand() % 360;
2405 VectorAdd(org, dir, p->org);
2406
2407 p->alpha = 0.5;
2408 p->alphavel = -dur / (2.0 + frand() * 0.3);
2409 for (j=0 ; j<3 ; j++)
2410 {
2411 p->accel[j] = 0;
2412 p->vel[j] = 0;
2413 }
2414
2415 //add small shockwave effect
2416 if(!(p = new_particle()))
2417 return;
2418
2419 p->image = r_hittexture;
2420 p->color = color + (rand() & 1);
2421 p->type = PARTICLE_DECAL;
2422 p->blendsrc = GL_SRC_ALPHA;
2423 p->blenddst = GL_ONE;
2424 p->scale = .1;
2425 p->scalevel = 10;
2426
2427 VectorScale(dir, -1, v);
2428 RotateForNormal(v, p->angle);
2429 p->angle[ROLL] = rand() % 360;
2430 VectorAdd(org, dir, p->org);
2431
2432 p->alpha = 1.0;
2433 p->alphavel = -2.0;
2434 for (j=0 ; j<3 ; j++)
2435 {
2436 p->accel[j] = 0;
2437 p->vel[j] = 0;
2438 }
2439
2440 if(isDis)
2441 getColorvec(colorvec);
2442 else {
2443 colorvec[0] = 0; //bright green
2444 colorvec[1] = 1;
2445 colorvec[2] = 0.2;
2446 }
2447
2448 addParticleLight (p,
2449 isDis ? 120:80, 5,
2450 colorvec[0], colorvec[1], colorvec[2]);
2451 }
2452
CL_BlasterMark(vec3_t org,vec3_t dir)2453 void CL_BlasterMark(vec3_t org, vec3_t dir){
2454 particle_t *p;
2455 vec3_t v;
2456 int j;
2457
2458 if(!(p = new_particle()))
2459 return;
2460
2461 p->image = r_bullettexture;
2462 p->color = 0x74 + (rand() & 1);
2463 p->type = PARTICLE_DECAL;
2464 p->blendsrc = GL_SRC_ALPHA;
2465 p->blenddst = GL_ONE;
2466 p->scale = .75;
2467 p->scalevel = 0;
2468
2469 VectorScale(dir, -1, v);
2470 RotateForNormal(v, p->angle);
2471 p->angle[ROLL] = rand() % 360;
2472 VectorAdd(org, dir, p->org);
2473
2474 p->alpha = 0.7;
2475 p->alphavel = -0.4 / (2.0 + frand() * 0.3);
2476 for (j=0 ; j<3 ; j++)
2477 {
2478 p->accel[j] = 0;
2479 p->vel[j] = 0;
2480 }
2481 if(!(p = new_particle()))
2482 return;
2483
2484 p->image = r_bullettexture;
2485 p->color = 0x74 + (rand() & 1);
2486 p->type = PARTICLE_DECAL;
2487 p->blendsrc = GL_SRC_ALPHA;
2488 p->blenddst = GL_ONE;
2489 p->scale = 1.5;
2490 p->scalevel = 0;
2491
2492 VectorScale(dir, -1, v);
2493 RotateForNormal(v, p->angle);
2494 p->angle[ROLL] = rand() % 360;
2495 VectorAdd(org, dir, p->org);
2496
2497 p->alpha = 0.5;
2498 p->alphavel = -0.4 / (2.0 + frand() * 0.3);
2499 for (j=0 ; j<3 ; j++)
2500 {
2501 p->accel[j] = 0;
2502 p->vel[j] = 0;
2503 }
2504 }
2505
CL_VaporizerMarks(vec3_t org,vec3_t dir)2506 void CL_VaporizerMarks(vec3_t org, vec3_t dir){
2507 particle_t *p;
2508 vec3_t v, forward, right, up;
2509 int i,j;
2510 float scatter;
2511
2512 for(i = 0; i < 6; i ++) {
2513 if(!(p = new_particle()))
2514 return;
2515
2516 p->image = r_bullettexture;
2517 p->color = 0xd4 + (rand()&7);
2518 p->type = PARTICLE_DECAL;
2519 p->blendsrc = GL_SRC_ALPHA;
2520 p->blenddst = GL_ONE;
2521 p->scale = .75;
2522 p->scalevel = 0;
2523
2524 VectorScale(dir, -1, v);
2525 RotateForNormal(v, p->angle);
2526 p->angle[ROLL] = rand() % 360;
2527 VectorAdd(org, dir, p->org);
2528
2529 AngleVectors(p->angle, forward, right, up);
2530
2531 scatter = ((rand()%8)-4);
2532 VectorMA(p->org, scatter, up, p->org);
2533
2534 p->alpha = 0.7;
2535 p->alphavel = -0.4 / (2.0 + frand() * 0.3);
2536 for (j=0 ; j<3 ; j++)
2537 {
2538 p->accel[j] = 0;
2539 p->vel[j] = 0;
2540 }
2541 if(!(p = new_particle()))
2542 return;
2543
2544 p->image = r_bullettexture;
2545 p->color = 0x74 + (rand()&7);
2546 p->type = PARTICLE_DECAL;
2547 p->blendsrc = GL_SRC_ALPHA;
2548 p->blenddst = GL_ONE;
2549 p->scale = 1.5;
2550 p->scalevel = 0;
2551
2552 VectorScale(dir, -1, v);
2553 RotateForNormal(v, p->angle);
2554 p->angle[ROLL] = rand() % 360;
2555 VectorAdd(org, dir, p->org);
2556
2557 VectorMA(p->org, scatter, up, p->org);
2558
2559 p->alpha = 0.5;
2560 p->alphavel = -0.4 / (2.0 + frand() * 0.3);
2561 for (j=0 ; j<3 ; j++)
2562 {
2563 p->accel[j] = 0;
2564 p->vel[j] = 0;
2565 }
2566 }
2567 }
2568
2569 /*
2570 ===============
2571 Particle Beams
2572
2573 ===============
2574 */
2575
2576 //this is the length of each piece...
2577 #define RAILTRAILSPACE 20
2578 #define LASERTRAILSPACE 10
2579
CL_DisruptorBeam(vec3_t start,vec3_t end)2580 void CL_DisruptorBeam (vec3_t start, vec3_t end)
2581 {
2582 vec3_t move;
2583 vec3_t vec, point, last, vec2;
2584 float len, color;
2585 vec3_t right, up;
2586 particle_t *p;
2587 int i,j;
2588 float v;
2589
2590 color = getColor();
2591
2592 VectorSubtract (end, start, vec);
2593 len = VectorNormalize (vec);
2594 VectorCopy (vec, point);
2595
2596 MakeNormalVectors (vec, right, up);
2597 VectorCopy (vec, vec2);
2598 VectorScale (vec, RAILTRAILSPACE, vec);
2599 VectorCopy (start, move);
2600
2601 for (i = 0; len>0; len -= RAILTRAILSPACE, i+=100)
2602 {
2603 VectorCopy (move, last);
2604 VectorAdd (move, vec, move);
2605
2606 if (!(p = new_particle()))
2607 return;
2608
2609 p->alpha = 1;
2610 p->alphavel = -1.0 - (len/(float)i);
2611 p->blenddst = GL_ONE;
2612 p->blendsrc = GL_SRC_ALPHA;
2613
2614 v = frand();
2615 if(v < 0.2)
2616 p->image = r_dis3texture;
2617 else if(v < 0.5)
2618 p->image = r_dis2texture;
2619 else
2620 p->image = r_dis1texture;
2621
2622 p->scale = 4;
2623 VectorCopy(move, p->angle);
2624 p->type = PARTICLE_BEAM;
2625 p->scalevel = 0;
2626
2627 p->color = color;
2628
2629 for (j=0 ; j<3 ; j++)
2630 {
2631 p->org[j] = last[j];
2632 p->vel[j] = 0;
2633 p->accel[j] = 0;
2634 }
2635 }
2636 }
2637
CL_LaserBeam(vec3_t start,vec3_t end)2638 void CL_LaserBeam (vec3_t start, vec3_t end)
2639 {
2640
2641 vec3_t move;
2642 vec3_t vec, point, last, vec2;
2643 float len;
2644 vec3_t right, up;
2645 particle_t *p, *pr;
2646 int i,j;
2647
2648 VectorSubtract (end, start, vec);
2649 len = VectorNormalize (vec);
2650 VectorCopy (vec, point);
2651
2652 MakeNormalVectors (vec, right, up);
2653 VectorCopy (vec, vec2);
2654 VectorScale (vec, RAILTRAILSPACE, vec);
2655 VectorCopy (start, move);
2656
2657 //muzzleflash
2658 VectorScale (vec2, -RAILTRAILSPACE/2, vec2);
2659 VectorAdd(start, vec2, start);
2660 for(i = 0; i < 3; i++) {
2661
2662 if (!(p = new_particle()))
2663 return;
2664 p->alpha = 0.9;
2665 p->alphavel = -2.8 / (0.6+frand()*0.2);
2666 p->blenddst = GL_ONE;
2667 p->blendsrc = GL_SRC_ALPHA;
2668 p->image = r_cflashtexture;
2669 p->scale = 12/(i+1);
2670 for(j=0; j< 3; j++)
2671 p->angle[j] = 0;
2672 p->type = PARTICLE_STANDARD;
2673 p->scalevel = 8;
2674 p->color = 0xd4;
2675 for (j=0 ; j<3 ; j++)
2676 {
2677 p->org[j] = start[j];
2678 p->vel[j] = 0;
2679 p->accel[j] = 0;
2680 }
2681 }
2682
2683 //Dummy particle that won't get drawn -- the first particle in a chain is
2684 //always skipped.
2685 if (!(pr = new_particle ()))
2686 return;
2687 pr->alpha = 0.9;
2688 pr->alphavel = -2.8;
2689 pr->scale = 4;
2690 pr->scalevel = 0;
2691 VectorCopy (start, pr->org);
2692 VectorClear (pr->vel);
2693 VectorClear (pr->accel);
2694 pr->type = PARTICLE_CHAINED;
2695 pr->color = 0xd4;
2696 pr->image = r_beam2texture;
2697
2698 if (!(p = new_particle()))
2699 return;
2700
2701 p->alpha = 0.9;
2702 p->alphavel = -2.8;
2703 p->blenddst = GL_ONE;
2704 p->blendsrc = GL_SRC_ALPHA;
2705
2706 p->image = r_beam2texture;
2707 p->scale = 4;
2708 VectorCopy(move, p->angle);
2709 p->type = PARTICLE_CHAINED;
2710 p->scalevel = 0;
2711
2712 p->color = 0xd4;
2713 p->chain_prev = pr;
2714
2715 for (j=0 ; j<3 ; j++)
2716 {
2717 p->org[j] = end[j];
2718 p->vel[j] = 0;
2719 p->accel[j] = 0;
2720 }
2721
2722 for (; len>0; len -= RAILTRAILSPACE)
2723 {
2724 VectorCopy (move, last);
2725 VectorAdd (move, vec, move);
2726
2727 if (len > 40)
2728 continue;
2729
2730 if (!(p = new_particle()))
2731 return;
2732
2733 p->alpha = 0.9;
2734 p->alphavel = -2.8;
2735 p->blenddst = GL_ONE;
2736 p->blendsrc = GL_SRC_ALPHA;
2737 p->image = r_flaretexture;
2738 p->scale = 24;
2739 for(j=0; j< 3; j++)
2740 p->angle[j] = 0;
2741 p->type = PARTICLE_STANDARD;
2742 p->scalevel = 12;
2743 p->color = 0xd4;
2744
2745 for (j=0 ; j<3 ; j++)
2746 {
2747 p->org[j] = last[j];
2748 p->vel[j] = 0;
2749 p->accel[j] = 0;
2750 }
2751 }
2752 }
CL_BlasterBeam(vec3_t start,vec3_t end)2753 void CL_BlasterBeam (vec3_t start, vec3_t end)
2754 {
2755
2756 vec3_t move;
2757 vec3_t vec, point, vec2;
2758 float len;
2759 vec3_t right, up;
2760 particle_t *p, *pr;
2761 int i,j;
2762
2763 VectorSubtract (end, start, vec);
2764 len = VectorNormalize (vec);
2765 VectorCopy (vec, point);
2766
2767 MakeNormalVectors (vec, right, up);
2768 VectorCopy (vec, vec2);
2769 VectorScale (vec, LASERTRAILSPACE, vec);
2770 VectorCopy (start, move);
2771
2772
2773 //puff of blue gas
2774 VectorScale (vec2, -LASERTRAILSPACE/2, vec2);
2775 VectorAdd(start, vec2, start);
2776 for(i = 0; i < 6; i++) {
2777
2778 if (!(p = new_particle()))
2779 return;
2780 p->alpha = 0.9;
2781 p->alphavel = -1.8 / (0.6+frand()*0.2);
2782 p->blenddst = GL_ONE;
2783 p->blendsrc = GL_SRC_ALPHA;
2784 p->image = r_cflashtexture;
2785 p->scale = 8/(i+1);
2786 for(j=0; j< 3; j++)
2787 p->angle[j] = 0;
2788 p->type = PARTICLE_STANDARD;
2789 p->scalevel = 4;
2790 p->color = 0x74;
2791 for (j=0 ; j<3 ; j++)
2792 {
2793 p->org[j] = start[j];
2794 p->vel[j] = 0;
2795 p->accel[j] = 0;
2796 }
2797 }
2798
2799 //Dummy particle that won't get drawn -- the first particle in a chain is
2800 //always skipped.
2801 if (!(pr = new_particle ()))
2802 return;
2803 pr->alpha = 0.9;
2804 pr->alphavel = -1.8;
2805 pr->scale = 2;
2806 pr->scalevel = 0;
2807 VectorCopy (start, pr->org);
2808 VectorClear (pr->vel);
2809 VectorClear (pr->accel);
2810 pr->type = PARTICLE_CHAINED;
2811 pr->color = 0x74;
2812 pr->image = r_beam2texture;
2813
2814 for (i = 0; i < 3; i++)
2815 {
2816 if (!(p = new_particle()))
2817 return;
2818
2819 p->alpha = 0.9;
2820 p->alphavel = -1.8;
2821 p->blenddst = GL_ONE;
2822 p->blendsrc = GL_SRC_ALPHA;
2823
2824 p->image = r_beam2texture;
2825 p->scale = 2;
2826 VectorCopy(move, p->angle);
2827 p->type = PARTICLE_CHAINED;
2828 p->scalevel = 0;
2829
2830 p->color = 0x74;
2831 p->chain_prev = pr;
2832
2833 for (j=0 ; j<3 ; j++)
2834 {
2835 p->org[j] = end[j];
2836 p->vel[j] = 0;
2837 p->accel[j] = 0;
2838 }
2839 }
2840 }
2841
2842 #define VAPORIZORTRAILSPACE 20
2843
CL_VaporizerBeam(vec3_t start,vec3_t end)2844 void CL_VaporizerBeam (vec3_t start, vec3_t end)
2845 {
2846 vec3_t move;
2847 vec3_t vec, point, last, vec2;
2848 float len;
2849 vec3_t right, up;
2850 particle_t *p;
2851 int i,j;
2852
2853 VectorSubtract (end, start, vec);
2854 len = VectorNormalize (vec);
2855 VectorCopy (vec, point);
2856
2857 MakeNormalVectors (vec, right, up);
2858 VectorCopy (vec, vec2);
2859 VectorScale (vec, VAPORIZORTRAILSPACE, vec);
2860 VectorCopy (start, move);
2861
2862 //muzzleflash
2863 VectorScale (vec2, -VAPORIZORTRAILSPACE/2, vec2);
2864 VectorAdd(start, vec2, start);
2865 for(i = 0; i < 8; i++) {
2866
2867 if (!(p = new_particle()))
2868 return;
2869 p->alpha = 0.9;
2870 p->alphavel = -.8 / (0.6+frand()*0.2);
2871 p->blenddst = GL_ONE;
2872 p->blendsrc = GL_SRC_ALPHA;
2873 p->image = r_leaderfieldtexture;
2874 p->scale = 24/(i+1);
2875 for(j=0; j< 3; j++)
2876 p->angle[j] = 0;
2877 p->type = PARTICLE_STANDARD;
2878 p->scalevel = 12;
2879 p->color = 0x74 + (rand()&12);;
2880 for (j=0 ; j<3 ; j++)
2881 {
2882 p->org[j] = start[j];
2883 p->vel[j] = 0;
2884 p->accel[j] = 0;
2885 }
2886 }
2887
2888 for (; len>0; len -= VAPORIZORTRAILSPACE)
2889 {
2890 VectorCopy (move, last);
2891 VectorAdd (move, vec, move);
2892
2893 for(i = 0; i < 3; i++) {
2894 if (!(p = new_particle()))
2895 return;
2896
2897 p->alpha = 1;
2898 p->alphavel = -.8 / (0.6+frand()*0.2);
2899 p->blenddst = GL_ONE;
2900 p->blendsrc = GL_SRC_ALPHA;
2901 p->image = r_beam2texture;
2902 p->scale = 4;
2903 VectorCopy(move, p->angle);
2904 p->type = PARTICLE_BEAM;
2905 p->scalevel = 0;
2906
2907 p->color = 0x74 + (rand()&7);
2908
2909 for (j=0 ; j<3 ; j++)
2910 {
2911 p->org[j] = last[j];
2912 p->vel[j] = 0;
2913 p->accel[j] = 0;
2914 }
2915 }
2916 //do lightning effects
2917 if (!(p = new_particle()))
2918 return;
2919
2920 p->alpha = 1;
2921 p->alphavel = -.8 / (0.6+frand()*0.2);
2922 p->blenddst = GL_ONE;
2923 p->blendsrc = GL_SRC_ALPHA;
2924 p->image = r_beam3texture;
2925 p->scale = 4;
2926 VectorCopy(move, p->angle);
2927 p->type = PARTICLE_BEAM;
2928 p->scalevel = 0;
2929
2930 p->color = 0x74;
2931
2932 for (j=0 ; j<3 ; j++)
2933 {
2934 p->org[j] = last[j];
2935 p->vel[j] = 0;
2936 p->accel[j] = 0;
2937 }
2938
2939 }
2940
2941 }
2942
CL_NewLightning(vec3_t start,vec3_t end)2943 void CL_NewLightning (vec3_t start, vec3_t end)
2944 {
2945 vec3_t move;
2946 vec3_t vec;
2947 float len;
2948 int j;
2949 particle_t *p;
2950 particle_t *pr = NULL;
2951 float dec;
2952 vec3_t right, up;
2953 int i;
2954 float skewx, skewy, skewz;
2955 float x, y, z;
2956 // byte clr = 0xd4;
2957
2958 VectorCopy (start, move);
2959 VectorSubtract (end, start, vec);
2960 len = VectorNormalize (vec);
2961
2962 MakeNormalVectors (vec, right, up);
2963
2964 dec = .75;
2965 VectorScale (vec, dec, vec);
2966 VectorCopy (start, move);
2967 skewx = skewy = skewz = .1;
2968 i = 0;
2969 x = y = z = 0;
2970
2971 while (len > 0)
2972 {
2973 len -= dec;
2974 i++;
2975
2976 if (!(p = new_particle()))
2977 return;
2978
2979 VectorClear (p->accel);
2980
2981 x++;
2982 y++;
2983 z++;
2984
2985 // somehow increment x,y,z in random direction
2986 if (i > 10)//reset
2987 {
2988 i = 0;
2989 x = y = z = 0;
2990 if (frand() < 0.5)
2991 skewx = skewx * -1;
2992 if (frand() < 0.5)
2993 skewy = skewy * -1;
2994 if (frand() < 0.5)
2995 skewz = skewz * -1;
2996 }
2997
2998 p->org[0] = move[0] + skewx * ++x;
2999 p->org[1] = move[1] + skewy * ++y;
3000 p->org[2] = move[2] + skewz * ++z;
3001
3002 p->alpha = 1.2;
3003 p->alphavel = -3.33;
3004 p->type = PARTICLE_CHAINED;
3005 p->image = r_raintexture;
3006 p->blendsrc = GL_SRC_ALPHA;
3007 p->blenddst = GL_ONE;
3008 p->scale = 1 + (rand()&2);
3009 p->scalevel = 0;
3010 p->color = 0xff;
3011 for (j=0 ; j<3 ; j++)
3012 {
3013 p->vel[j] = 0;
3014 p->accel[j] = 0;
3015 }
3016 if (len < 4)
3017 addParticleLight (p,
3018 p->scale*75, 0,
3019 .25, 0, .3);
3020 VectorAdd (p->org, vec, move);
3021 if (pr)
3022 {
3023 p->chain_prev = pr;
3024 }
3025 pr = p;
3026 }
3027
3028 }
3029
CL_RedBlasterBeam(vec3_t start,vec3_t end)3030 void CL_RedBlasterBeam (vec3_t start, vec3_t end)
3031 {
3032
3033 vec3_t move;
3034 vec3_t vec, point, last, vec2;
3035 float len;
3036 vec3_t right, up;
3037 particle_t *p;
3038 int i,j;
3039
3040 VectorCopy (start, move);
3041 VectorSubtract (end, start, vec);
3042 len = VectorNormalize (vec);
3043 VectorCopy (vec, point);
3044
3045 MakeNormalVectors (vec, right, up);
3046 VectorCopy (vec, vec2);
3047 VectorScale (vec, LASERTRAILSPACE, vec);
3048 VectorCopy (start, move);
3049
3050
3051 //puff of blue gas
3052 VectorScale (vec2, -LASERTRAILSPACE/2, vec2);
3053 VectorAdd(start, vec2, start);
3054 for(i = 0; i < 6; i++) {
3055
3056 if (!(p = new_particle()))
3057 return;
3058 p->alpha = 0.9;
3059 p->alphavel = -1.8 / (0.6+frand()*0.2);
3060 p->blenddst = GL_ONE;
3061 p->blendsrc = GL_SRC_ALPHA;
3062 p->image = r_cflashtexture;
3063 p->scale = 8/(i+1);
3064 for(j=0; j< 3; j++)
3065 p->angle[j] = 0;
3066 p->type = PARTICLE_STANDARD;
3067 p->scalevel = 4;
3068 p->color = 0xe8;
3069 for (j=0 ; j<3 ; j++)
3070 {
3071 p->org[j] = start[j];
3072 p->vel[j] = 0;
3073 p->accel[j] = 0;
3074 }
3075 }
3076
3077 for (; len>0; len -= LASERTRAILSPACE)
3078 {
3079 VectorCopy (move, last);
3080 VectorAdd (move, vec, move);
3081
3082 for(i = 0; i < 3; i++) {
3083 if (!(p = new_particle()))
3084 return;
3085
3086 p->alpha = 0.9;
3087 p->alphavel = -1.8;
3088 p->blenddst = GL_ONE;
3089 p->blendsrc = GL_SRC_ALPHA;
3090
3091 p->image = r_beam2texture;
3092 p->scale = 2;
3093 VectorCopy(move, p->angle);
3094 p->type = PARTICLE_BEAM;
3095 p->scalevel = 0;
3096
3097 p->color = 0xe8;
3098
3099 for (j=0 ; j<3 ; j++)
3100 {
3101 p->org[j] = last[j];
3102 p->vel[j] = 0;
3103 p->accel[j] = 0;
3104 }
3105 }
3106 }
3107
3108 }
3109 /*
3110 ===============
3111 CL_BubbleTrail
3112
3113 ===============
3114 */
CL_BubbleTrail(vec3_t start,vec3_t end)3115 void CL_BubbleTrail (vec3_t start, vec3_t end)
3116 {
3117 vec3_t move;
3118 vec3_t vec;
3119 float len;
3120 int i, j;
3121 particle_t *p;
3122 float dec;
3123
3124 VectorCopy (start, move);
3125 VectorSubtract (end, start, vec);
3126 len = VectorNormalize (vec);
3127
3128 dec = 32;
3129 VectorScale (vec, dec, vec);
3130
3131 for (i=0 ; i<len ; i+=dec)
3132 {
3133 if (!(p = new_particle()))
3134 return;
3135
3136 VectorClear (p->accel);
3137
3138 p->alpha = 1.0;
3139 p->alphavel = -1.0 / (1+frand()*0.2);
3140 p->color = 4 + (rand()&7);
3141 p->type = PARTICLE_STANDARD;
3142 p->image = r_bubbletexture;
3143 p->scale = 2 + (rand()&2);
3144 p->blendsrc = GL_SRC_ALPHA;
3145 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
3146
3147 for (j=0 ; j<3 ; j++)
3148 {
3149 p->org[j] = move[j] + crand()*2;
3150 p->vel[j] = crand()*5;
3151 }
3152 p->vel[2] += 6;
3153
3154 VectorAdd (move, vec, move);
3155 }
3156 }
3157
3158 /*
3159 ===============
3160 CL_BFGExplosionParticles
3161 ===============
3162 */
3163
CL_BFGExplosionParticles(vec3_t org)3164 void CL_BFGExplosionParticles (vec3_t org)
3165 {
3166 int i, j;
3167 particle_t *p;
3168
3169 //for glsl framebuffer distortion effects
3170 if(!r_drawing_fbeffect && cl_explosiondist->value) {
3171 r_fbFxType = 1; //EXPLOSION
3172 r_drawing_fbeffect = true;
3173 VectorCopy(org, r_explosionOrigin);
3174 r_fbeffectTime = rs_realtime;
3175 }
3176
3177 for (i=0 ; i<32 ; i++)
3178 {
3179 if (!(p = new_particle()))
3180 return;
3181
3182 for (j=0 ; j<3 ; j++)
3183 {
3184 p->org[j] = org[j] + ((rand()%62)-32);
3185 p->vel[j] = (rand()%32)-16;
3186 }
3187
3188 p->accel[0] = p->accel[1] = 5+(rand()&7);
3189 p->accel[2] = 5+(rand()&7);
3190 p->scale = (24 + (rand()&2));
3191 p->scalevel = 24;
3192 p->type = PARTICLE_STANDARD;
3193 p->image = r_explosiontexture;
3194 p->blendsrc = GL_SRC_ALPHA;
3195 p->blenddst = GL_ONE;
3196 p->color = 0x74 + (rand()&7);
3197 p->alpha = 0.4;
3198
3199 p->alphavel = -0.8 / (2.5 + frand()*0.3);
3200 if (i > 28)
3201 addParticleLight (p,
3202 p->scale*(15+(rand()&5)), 10,
3203 0, 0.6, 0.5);
3204 }
3205
3206 //place a big shock wave effect
3207 if (!(p = new_particle()))
3208 return;
3209 p->alpha = 1.0;
3210 p->alphavel = -1.0;
3211 p->type = PARTICLE_FLAT;
3212 p->image = r_hittexture;
3213 p->blendsrc = GL_SRC_ALPHA;
3214 p->blenddst = GL_ONE;
3215 p->color = 0x74 + (rand()&7);
3216 p->scale = 24 + (rand()&4) ;
3217 p->scalevel = 100;
3218 for(j = 0; j < 3; j++) {
3219 p->org[j] = org[j];
3220 p->vel[j] = 0;
3221 p->accel[j] = 0;
3222 }
3223 }
3224
3225 /*
3226 ===============
3227 CL_TeleportParticles
3228
3229 ===============
3230 */
CL_TeleportParticles(vec3_t orig_start)3231 void CL_TeleportParticles (vec3_t orig_start)
3232 {
3233 vec3_t move;
3234 vec3_t vec;
3235 vec3_t start;
3236 vec3_t end;
3237 float len;
3238 int j;
3239 particle_t *p;
3240 int i;
3241 vec3_t pos1, pos2, v;
3242 float step = 16.0;
3243 // static vec3_t mins = { -1, -1, -1 };
3244 // static vec3_t maxs = { 1, 1, 1 };
3245
3246 //make a copy to prevent modifying an important vector
3247 VectorCopy(orig_start, start);
3248 VectorCopy(start, pos1);
3249 pos2[2] = 1;
3250 pos2[0] = pos2[1] = 0;
3251 pos1[2] -= 32;
3252
3253 if(!(p = new_particle()))
3254 return;
3255
3256 p->image = r_logotexture;
3257 p->color = 0x74 + (rand()&7);
3258 p->type = PARTICLE_DECAL;
3259 p->blendsrc = GL_SRC_ALPHA;
3260 p->blenddst = GL_ONE;
3261 p->scale = 4;
3262 p->scalevel = 0;
3263
3264 VectorScale(pos2, -1, v);
3265 RotateForNormal(v, p->angle);
3266 p->angle[ROLL] = rand() % 360;
3267 VectorCopy( pos1, p->org);
3268
3269 p->alpha = 0.7;
3270 p->alphavel = -0.15;
3271 for (j=0 ; j<3 ; j++)
3272 {
3273 p->accel[j] = 0;
3274 p->vel[j] = 0;
3275 }
3276
3277 //place a big shock wave effect
3278 if (!(p = new_particle()))
3279 return;
3280
3281 p->alpha = 1.0;
3282 p->alphavel = -.250;
3283 p->type = PARTICLE_DECAL;
3284 p->image = r_explosion5texture;
3285 p->blendsrc = GL_SRC_ALPHA;
3286 p->blenddst = GL_ONE;
3287 p->color = 0x74 + (rand()&7);
3288 p->scale = 1 + (rand()&4) ;
3289 p->scalevel = 4;
3290 VectorScale(pos2, -1, v);
3291 RotateForNormal(v, p->angle);
3292 p->angle[ROLL] = rand() % 360;
3293 VectorCopy( pos1, p->org);
3294 for(j = 0; j < 3; j++) {
3295 p->vel[j] = 0;
3296 p->accel[j] = 0;
3297 }
3298
3299 VectorCopy (start, move);
3300 VectorCopy (start, end);
3301 end[2] += 32;
3302 start[2] -= 48;
3303 VectorSubtract (end, start, vec);
3304 len = VectorNormalize (vec);
3305
3306 for (i=0 ; i<len ; i+=step)
3307 {
3308
3309 if (!(p = new_particle()))
3310 return;
3311
3312 VectorClear (p->accel);
3313
3314
3315 p->alpha = 1.0;
3316 p->alphavel = -2.5 / (2+frand()*0.2);
3317 p->type = PARTICLE_FLAT;
3318 p->image = r_hittexture;
3319 p->blendsrc = GL_ONE;
3320 p->blenddst = GL_ONE;
3321 p->color = 0x74 + (rand()&7);
3322 p->scale = 24 + (rand()&4) ;
3323 p->scalevel = 0;
3324 for(j = 0; j < 3; j++) {
3325 p->org[j] = start[j];
3326 p->vel[j] = 0;
3327 }
3328 p->vel[2] = PARTICLE_GRAVITY*2;
3329 if (i < 1)
3330 addParticleLight (p,
3331 p->scale, 10,
3332 0, 1, 1);
3333
3334 start[2] += 16;
3335 }
3336 }
3337
3338 #define WEATHER_PARTICLES 2048
3339 static int weather_particles;
3340 extern unsigned r_weather;
3341
3342 /*
3343 Cl_WeatherEffects - originally adopted from Jay Dolan's Q2W
3344 */
Cl_WeatherEffects()3345 void Cl_WeatherEffects()
3346 {
3347 int i, j, k;
3348 vec3_t start, end;
3349 trace_t tr;
3350 float ceiling;
3351 particle_t *p;
3352
3353 if(!r_weather)
3354 return;
3355
3356 i = weather_particles; // we count up from current particles
3357 p = NULL; // so that we add the right amount
3358
3359 k = 0;
3360
3361 if(r_weather == 5)
3362 {
3363 while(i++ < WEATHER_PARTICLES && k++ < 1)
3364 {
3365 VectorCopy(cl.refdef.vieworg, start);
3366 start[0] = start[0] + (rand() % 5096) - 2048;
3367 start[1] = start[1] + (rand() % 5096) - 2048;
3368
3369 VectorCopy(start, end);
3370 end[2] += 8192;
3371
3372 // trace up looking for sky
3373 tr = CM_BoxTrace(start, end, vec3_origin, vec3_origin, 0, MASK_SHOT);
3374
3375 if(!(tr.surface->flags & SURF_SKY))
3376 continue;
3377
3378 // drop down somewhere between sky and player
3379 ceiling = tr.endpos[2] > start[2] + 1024 ? start[2] + 1024 : tr.endpos[2];
3380 tr.endpos[2] = tr.endpos[2] - ((ceiling - start[2]) * frand());
3381
3382 if (!(p = new_particle()))
3383 return;
3384
3385 VectorCopy(tr.endpos, p->org);
3386 p->org[2] -= 1;
3387
3388 VectorCopy(start, end);
3389 end[2] -= 8192;
3390
3391 tr = CM_BoxTrace(p->org, end, vec3_origin, vec3_origin, 0, MASK_ALL);
3392
3393 if(!tr.surface) // this shouldn't happen
3394 VectorCopy(start, p->end);
3395 else
3396 VectorCopy(tr.endpos, p->end);
3397
3398 p->type = PARTICLE_FLUTTERWEATHER;
3399 // setup the particles
3400 //trash
3401 p->image = r_trashtexture;
3402 p->vel[2] = -80;
3403 p->accel[2] = 0;
3404 p->alpha = 0.9;
3405 p->alphavel = 0;
3406 p->color = 8;
3407 p->scale = 12;
3408 p->scalevel = 0;
3409 p->blendsrc = GL_SRC_ALPHA;
3410 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
3411
3412 for(j = 0; j < 2; j++)
3413 {
3414 p->vel[j] = crand() * 40;
3415 p->accel[j] = crand() * 50;
3416 }
3417 weather_particles++;
3418 }
3419 }
3420 else if(r_weather == 3 || r_weather == 4)
3421 {
3422 while(i++ < WEATHER_PARTICLES && k++ < 2)
3423 {
3424 VectorCopy(cl.refdef.vieworg, start);
3425 start[0] = start[0] + (rand() % 2048) - 1024;
3426 start[1] = start[1] + (rand() % 2048) - 1024;
3427
3428 VectorCopy(start, end);
3429 end[2] += 8192;
3430
3431 // trace up looking for sky
3432 tr = CM_BoxTrace(start, end, vec3_origin, vec3_origin, 0, MASK_SHOT);
3433
3434 if(!(tr.surface->flags & SURF_SKY))
3435 continue;
3436
3437 // drop down somewhere between sky and player
3438 ceiling = tr.endpos[2] > start[2] + 1024 ? start[2] + 1024 : tr.endpos[2];
3439 tr.endpos[2] = tr.endpos[2] - ((ceiling - start[2]) * frand());
3440
3441 if (!(p = new_particle()))
3442 return;
3443
3444 VectorCopy(tr.endpos, p->org);
3445 p->org[2] -= 1;
3446
3447 VectorCopy(start, end);
3448 end[2] -= 8192;
3449
3450 tr = CM_BoxTrace(p->org, end, vec3_origin, vec3_origin, 0, MASK_ALL);
3451
3452 if(!tr.surface) // this shouldn't happen
3453 VectorCopy(start, p->end);
3454 else
3455 VectorCopy(tr.endpos, p->end);
3456
3457 // setup the particles
3458 if(r_weather == 3) //leaves
3459 {
3460 p->type = PARTICLE_FLUTTERWEATHER;
3461 p->image = r_leaftexture;
3462 p->vel[2] = -80;
3463 p->accel[2] = 0;
3464 p->alpha = 0.9;
3465 p->alphavel = 0;
3466 p->color = 8;
3467 p->scale = 2;
3468 p->scalevel = 0;
3469 p->blendsrc = GL_SRC_ALPHA;
3470 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
3471 }
3472 else if(r_weather == 4) //embers
3473 {
3474 p->type = PARTICLE_WEATHER;
3475 p->image = r_particletexture;
3476 p->vel[2] = -80;
3477 p->accel[2] = 0;
3478 p->alpha = 0.9;
3479 p->alphavel = frand() * -1;
3480 p->color = 0xe8;
3481 p->scale = 2;
3482 p->scalevel = 0;
3483 p->blendsrc = GL_SRC_ALPHA;
3484 p->blenddst = GL_ONE;
3485 }
3486 for(j = 0; j < 2; j++)
3487 {
3488 p->vel[j] = crand() * 25;
3489 p->accel[j] = crand() * 50;
3490 }
3491 weather_particles++;
3492 }
3493 }
3494 else
3495 {
3496 while(i++ < WEATHER_PARTICLES && k++ < 25)
3497 {
3498 VectorCopy(cl.refdef.vieworg, start);
3499 start[0] = start[0] + (rand() % 2048) - 1024;
3500 start[1] = start[1] + (rand() % 2048) - 1024;
3501
3502 VectorCopy(start, end);
3503 end[2] += 8192;
3504
3505 // trace up looking for sky
3506 tr = CM_BoxTrace(start, end, vec3_origin, vec3_origin, 0, MASK_SHOT);
3507
3508 if(!(tr.surface->flags & SURF_SKY))
3509 continue;
3510
3511 // drop down somewhere between sky and player
3512 ceiling = tr.endpos[2] > start[2] + 1024 ? start[2] + 1024 : tr.endpos[2];
3513 tr.endpos[2] = tr.endpos[2] - ((ceiling - start[2]) * frand());
3514
3515 if (!(p = new_particle()))
3516 return;
3517
3518 VectorCopy(tr.endpos, p->org);
3519 p->org[2] -= 1;
3520
3521 VectorCopy(start, end);
3522 end[2] -= 8192;
3523
3524 tr = CM_BoxTrace(p->org, end, vec3_origin, vec3_origin, 0, MASK_ALL);
3525
3526 if(!tr.surface) // this shouldn't happen
3527 VectorCopy(start, p->end);
3528 else
3529 VectorCopy(tr.endpos, p->end);
3530
3531 p->type = PARTICLE_WEATHER;
3532 // setup the particles
3533 if(r_weather == 1) //rain
3534 {
3535 p->image = r_raintexture;
3536 p->vel[2] = -800;
3537 p->accel[2] = 0;
3538 p->alpha = 0.3;
3539 p->alphavel = frand() * -1;
3540 p->color = 8;
3541 p->scale = 6;
3542 p->scalevel = 0;
3543 }
3544 else if(r_weather == 2) //snow
3545 {
3546 p->image = r_particletexture;
3547 p->vel[2] = -120;
3548 p->accel[2] = 0;
3549 p->alpha = 0.8;
3550 p->alphavel = frand() * -1;
3551 p->color = 8;
3552 p->scale = 1;
3553 p->scalevel = 0;
3554 }
3555 p->blendsrc = GL_SRC_ALPHA;
3556 p->blenddst = GL_ONE;
3557
3558 for(j = 0; j < 2; j++)
3559 {
3560 p->vel[j] = crand() * 2;
3561 p->accel[j] = crand() * 2;
3562 }
3563 weather_particles++;
3564 }
3565 }
3566 }
3567
3568 /*
3569 Powered up effects
3570 */
3571
3572 #define BEAMLENGTH 16
CL_PoweredEffects(vec3_t origin)3573 void CL_PoweredEffects (vec3_t origin)
3574 {
3575 int i;
3576 particle_t *p;
3577 float angle;
3578 float sr, sp, sy, cr, cp, cy;
3579 vec3_t forward;
3580 float dist = 64;
3581 float ltime;
3582
3583 if (!avelocities[0][0])
3584 {
3585 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
3586 avelocities[0][i] = (rand()&255) * 0.01;
3587 }
3588
3589 ltime = (float)cl.time / 1000.0;
3590 for (i=0 ; i<32 ; i+=2)
3591 {
3592 angle = ltime * avelocities[i][0];
3593 sy = sin(angle);
3594 cy = cos(angle);
3595 angle = ltime * avelocities[i][1];
3596 sp = sin(angle);
3597 cp = cos(angle);
3598 angle = ltime * avelocities[i][2];
3599 sr = sin(angle);
3600 cr = cos(angle);
3601
3602 forward[0] = cp*cy;
3603 forward[1] = cp*sy;
3604 forward[2] = -sp;
3605
3606 if (!(p = new_particle()))
3607 return;
3608
3609 dist = sin(ltime + i)*32;
3610 p->org[0] = origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
3611 p->org[1] = origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
3612 p->org[2] = origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
3613
3614 VectorClear (p->vel);
3615 VectorClear (p->accel);
3616
3617 p->type = PARTICLE_STANDARD;
3618 p->image = r_logotexture;
3619 p->blendsrc = GL_ONE;
3620 p->blenddst = GL_ONE;
3621 p->scale = 2;
3622 p->scalevel = 2;
3623 p->color = 0xd4;
3624
3625 p->alpha = .7;
3626 p->alphavel = -50 / (0.5 + frand()*0.3);
3627 }
3628 }
3629
3630 /*
3631 ======
3632 vectoangles2 - this is duplicated in the game DLL, but I need it here.
3633 ======
3634 */
vectoangles2(vec3_t value1,vec3_t angles)3635 void vectoangles2 (vec3_t value1, vec3_t angles)
3636 {
3637 float forward;
3638 float yaw, pitch;
3639
3640 if (value1[1] == 0 && value1[0] == 0)
3641 {
3642 yaw = 0;
3643 if (value1[2] > 0)
3644 pitch = 90;
3645 else
3646 pitch = 270;
3647 }
3648 else
3649 {
3650 // PMM - fixed to correct for pitch of 0
3651 if (value1[0])
3652 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
3653 else if (value1[1] > 0)
3654 yaw = 90;
3655 else
3656 yaw = 270;
3657
3658 if (yaw < 0)
3659 yaw += 360;
3660
3661 forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
3662 pitch = (atan2(value1[2], forward) * 180 / M_PI);
3663 if (pitch < 0)
3664 pitch += 360;
3665 }
3666
3667 angles[PITCH] = -pitch;
3668 angles[YAW] = yaw;
3669 angles[ROLL] = 0;
3670 }
3671
3672 /*
3673 ===============
3674 CL_SmokeTrail
3675 ===============
3676 */
CL_SmokeTrail(vec3_t start,vec3_t end,int colorStart,int colorRun,int spacing)3677 void CL_SmokeTrail (vec3_t start, vec3_t end, int colorStart, int colorRun, int spacing)
3678 {
3679 vec3_t move;
3680 vec3_t vec;
3681 float len;
3682 int j;
3683 particle_t *p;
3684
3685 VectorCopy (start, move);
3686 VectorSubtract (end, start, vec);
3687 len = VectorNormalize (vec);
3688
3689 VectorScale (vec, spacing, vec);
3690
3691 // FIXME: this is a really silly way to have a loop
3692 while (len > 0)
3693 {
3694 len -= spacing;
3695
3696 if (!(p = new_particle()))
3697 return;
3698 VectorClear (p->accel);
3699
3700 p->alpha = 1.0;
3701 p->alphavel = -1.0 / (1+frand()*0.5);
3702 p->color = colorStart + (rand() % colorRun);
3703 for (j=0 ; j<3 ; j++)
3704 {
3705 p->org[j] = move[j] + crand()*3;
3706 p->accel[j] = 0;
3707 }
3708 p->vel[2] = 20 + crand()*5;
3709
3710 VectorAdd (move, vec, move);
3711 }
3712 }
3713
3714 /*
3715 ===============
3716 CL_ParticleSteamEffect
3717
3718 Puffs with velocity along direction, with some randomness thrown in
3719 ===============
3720 */
3721
CL_ParticleSteamEffect(cl_sustain_t * self)3722 void CL_ParticleSteamEffect (cl_sustain_t *self)
3723 {
3724 int i, j;
3725 particle_t *p;
3726 float d;
3727 vec3_t r, u;
3728 vec3_t dir;
3729
3730 VectorCopy (self->dir, dir);
3731 MakeNormalVectors (dir, r, u);
3732
3733 for (i=0 ; i<2 ; i++)
3734 {
3735 if (!(p = new_particle()))
3736 return;
3737
3738 p->type = PARTICLE_STANDARD;
3739 p->image = r_pufftexture;
3740 p->blendsrc = GL_SRC_ALPHA;
3741 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
3742 p->scale = 4 + (rand()&2);
3743 p->scalevel = 10;
3744 p->color = self->color;
3745
3746 for (j=0 ; j<3 ; j++)
3747 {
3748 p->org[j] = self->org[j] + self->magnitude*0.1*crand();
3749 }
3750 VectorScale (dir, self->magnitude, p->vel);
3751 d = crand()*self->magnitude/3;
3752 VectorMA (p->vel, d, r, p->vel);
3753 d = crand()*self->magnitude/3;
3754 VectorMA (p->vel, d, u, p->vel);
3755
3756 p->accel[0] = p->accel[1] = 0;
3757 p->accel[2] = -PARTICLE_GRAVITY/2;
3758 p->alpha = 0.1;
3759
3760 p->alphavel = -1.0 / (6.5 + frand()*0.3);
3761
3762 p->fromsustainedeffect = true;
3763 }
3764 self->nextthink += self->thinkinterval;
3765 }
CL_ParticleFireEffect2(cl_sustain_t * self)3766 void CL_ParticleFireEffect2 (cl_sustain_t *self)
3767 {
3768 int i, j;
3769 particle_t *p;
3770 float d;
3771 vec3_t r, u;
3772 vec3_t dir;
3773
3774 VectorCopy (self->dir, dir);
3775 MakeNormalVectors (dir, r, u);
3776
3777 for (i=0 ; i<1 ; i++)
3778 {
3779 if (!(p = new_particle()))
3780 return;
3781
3782 p->type = PARTICLE_STANDARD;
3783 p->image = r_explosiontexture;
3784 p->blendsrc = GL_SRC_ALPHA;
3785 p->blenddst = GL_ONE;
3786 p->color = 0xe0;
3787 p->scale = 24 + (rand()&7);
3788 p->scalevel = 4;
3789 for (j=0 ; j<3 ; j++)
3790 {
3791 p->org[j] = self->org[j] + self->magnitude*0.1*crand();
3792
3793 }
3794 p->vel[2] = 100;
3795 VectorScale (dir, self->magnitude, p->vel);
3796 d = crand()*self->magnitude/3;
3797 VectorMA (p->vel, d, r, p->vel);
3798 d = crand()*self->magnitude/3;
3799 VectorMA (p->vel, d, u, p->vel);
3800
3801 p->accel[0] = p->accel[1] = 0;
3802 p->accel[2] = -PARTICLE_GRAVITY/3;
3803 p->alpha = 0.03;
3804
3805 p->alphavel = -.015 / (0.8 + frand()*0.3);
3806
3807 p->fromsustainedeffect = true;
3808 }
3809 self->nextthink += self->thinkinterval;
3810 }
CL_ParticleSmokeEffect2(cl_sustain_t * self)3811 void CL_ParticleSmokeEffect2 (cl_sustain_t *self)
3812 {
3813 int i, j;
3814 particle_t *p;
3815 float d;
3816 vec3_t r, u;
3817 vec3_t dir;
3818
3819 VectorCopy (self->dir, dir);
3820 MakeNormalVectors (dir, r, u);
3821
3822 for (i=0 ; i<self->count ; i++)
3823 {
3824 if (!(p = new_particle()))
3825 return;
3826
3827 p->type = PARTICLE_STANDARD;
3828 p->image = r_smoketexture;
3829 p->blendsrc = GL_SRC_ALPHA;
3830 p->blenddst = GL_ONE_MINUS_SRC_ALPHA;
3831 p->scale = 6 + (rand()&7);
3832 p->color = 14;
3833 p->scalevel = 4.5;
3834 for (j=0 ; j<3 ; j++)
3835 {
3836 p->org[j] = self->org[j] + self->magnitude*0.1*crand();
3837 }
3838 p->vel[2] = 10;
3839 VectorScale (dir, self->magnitude, p->vel);
3840 d = crand()*self->magnitude/3;
3841 VectorMA (p->vel, d, r, p->vel);
3842 d = crand()*self->magnitude/3;
3843 VectorMA (p->vel, d, u, p->vel);
3844
3845 p->accel[0] = p->accel[1] = 0;
3846 p->accel[2] = -PARTICLE_GRAVITY/3;
3847 p->alpha = 0.03;
3848
3849 p->alphavel = -.015 / (7.8 + frand()*0.3);
3850
3851 p->fromsustainedeffect = true;
3852 }
3853 self->nextthink += self->thinkinterval;
3854 }
3855
3856 /*
3857 ===============
3858 CL_AddParticles
3859 ===============
3860 */
CL_AddParticles(void)3861 void CL_AddParticles (void)
3862 {
3863 particle_t *p, *next;
3864 float light;
3865 float time = 0.0f;
3866 particle_t *active, *tail;
3867 int i;
3868
3869 Cl_WeatherEffects();
3870
3871 active = NULL;
3872 tail = NULL;
3873
3874 for (p=active_particles ; p ; p=next)
3875 {
3876 next = p->next;
3877
3878 // PMM - added INSTANT_PARTICLE handling for heat beam
3879 if (p->alphavel != INSTANT_PARTICLE)
3880 {
3881 time = (cl.time - p->time)*0.001;
3882 p->current_alpha = p->alpha + time*p->alphavel;
3883 if (p->current_alpha <= 0)
3884 { // faded out
3885 if(p->type == PARTICLE_WEATHER || p->type == PARTICLE_FLUTTERWEATHER)
3886 weather_particles--;
3887 p->next = free_particles;
3888 free_particles = p;
3889 continue;
3890 }
3891 }
3892 else
3893 {
3894 p->current_alpha = p->alpha;
3895 p->alpha = p->alphavel = 0.0;
3896 }
3897 if(p->scalevel > 1) {
3898 time = (cl.time - p->time)*0.001;
3899 p->current_scale = p->scale + time * p->scalevel;
3900 }
3901 else
3902 p->current_scale = p->scale;
3903
3904 if (p->colorvel != 0) {
3905 time = (cl.time - p->time)*0.001;
3906 p->current_color = (p->color + time * p->colorvel);
3907 } else
3908 p->current_color = p->color;
3909
3910 if(p->current_scale > 64)
3911 p->current_scale = 64; //don't want them getting too large.
3912 if(p->current_scale < 0)
3913 p->current_scale = 0;
3914
3915 if(p->current_color < 0)
3916 p->current_color = 0;
3917
3918 // update origin
3919 for(i = 0; i < 3; i++) {
3920 p->current_origin[i] = p->org[i] + p->vel[i]*time + p->accel[i]*(time*time);
3921 }
3922
3923 // free up weather particles that have hit the ground
3924 if(p->type == PARTICLE_WEATHER || p->type == PARTICLE_FLUTTERWEATHER)
3925 {
3926 if (p->current_origin[2] <= p->end[2]){
3927 p->next = free_particles;
3928 free_particles = p;
3929 weather_particles--;
3930 continue;
3931 }
3932 }
3933
3934 // some weather particles flutter around as they fall
3935 if (p->type == PARTICLE_FLUTTERWEATHER)
3936 {
3937 // An accurate-looking model of particle rotation is to model the
3938 // particle as a sphere rotating on a surface (or a circle on each
3939 // axis.) If the particle was a marble moving on some hypothetical
3940 // 3D tabletop, how many degrees in each direction has it rotated
3941 // since it was spawned?
3942 float circumference;
3943 vec3_t distance;
3944
3945 // Use a slightly larger radius so it rotates slower.
3946 circumference = 2.0*M_PI*(3.5*p->current_scale);
3947
3948 VectorSubtract (p->current_origin, p->org, distance);
3949 VectorScale (distance, 360.0/circumference, p->angle);
3950 }
3951
3952 p->next = NULL;
3953 if (!tail)
3954 active = tail = p;
3955 else
3956 {
3957 tail->next = p;
3958 tail = p;
3959 }
3960
3961 if (p->current_alpha > 1.0)
3962 p->current_alpha = 1;
3963
3964 for (i=0;i<P_LIGHTS_MAX;i++)
3965 {
3966 const cplight_t *plight = &p->lights[i];
3967 if (plight->isactive && !p->fromsustainedeffect)
3968 {
3969 light = plight->light*p->current_alpha*2.0 + plight->lightvel*time;
3970 V_AddLight (p->current_origin, light, plight->lightcol[0], plight->lightcol[1], plight->lightcol[2]);
3971 }
3972 }
3973
3974 // hack a scale up to keep particles from disapearing
3975 p->dist = ( p->current_origin[0] - r_origin[0] ) * vpn[0] +
3976 ( p->current_origin[1] - r_origin[1] ) * vpn[1] +
3977 ( p->current_origin[2] - r_origin[2] ) * vpn[2];
3978
3979 if (p->type != PARTICLE_CHAINED && p->dist < 0)
3980 continue;
3981 else if (p->dist >= 40)
3982 p->dist = 2 + p->dist * 0.004;
3983 else
3984 p->dist = 2;
3985
3986 if ((p->type == PARTICLE_CHAINED && true) != (p->chain_prev && true))
3987 continue;
3988
3989 if (p->type == PARTICLE_CHAINED && p->chain_prev) {
3990 vec3_t span, delta;
3991 VectorSubtract (p->current_origin, p->chain_prev->current_origin, span);
3992 VectorSubtract (r_origin, p->current_origin, delta);
3993 CrossProduct (span, delta, p->current_pspan);
3994 VectorNormalize (p->current_pspan);
3995 VectorScale (p->current_pspan, p->dist*p->current_scale, p->current_pspan);
3996 }
3997
3998 V_AddParticle (p);
3999 }
4000
4001 active_particles = active;
4002 }
4003
4004
4005 /*
4006 ==============
4007 CL_EntityEvent
4008
4009 An entity has just been parsed that has an event value
4010
4011 the female events are there for backwards compatability
4012 ==============
4013 */
4014 extern struct sfx_s *cl_sfx_footsteps[4];
4015 extern struct sfx_s *cl_sfx_metal_footsteps[4];
4016
4017 //Knightmare- modified by Irritant
4018 /*
4019 ===============
4020 CL_Footsteps
4021 Plays appropriate footstep sound depending on surface flags of the ground surface.
4022 Since this is a replacement for plain Jane EV_FOOTSTEP, we already know
4023 the player is definitely on the ground when this is called.
4024 ===============
4025 */
4026
CL_FootSteps(entity_state_t * ent,qboolean loud)4027 void CL_FootSteps (entity_state_t *ent, qboolean loud)
4028 {
4029 trace_t tr;
4030 vec3_t end;
4031 int r;
4032 int surface;
4033 struct sfx_s *stepsound;
4034 float volume = 0.5;
4035
4036 r = (rand()&3);
4037
4038 VectorCopy(ent->origin,end);
4039 end[2] -= 64;
4040 tr = CL_PMSurfaceTrace (ent->origin,NULL,NULL,end,MASK_SOLID | MASK_WATER);
4041 if (!tr.surface)
4042 return;
4043 surface = tr.surface->flags;
4044 switch (surface)
4045 {
4046 case SURF_TRANS66:
4047 case SURF_TRANS33|SURF_TRANS66: //all metal grates in AA have these flags set
4048 stepsound = cl_sfx_metal_footsteps[r];
4049 break;
4050 default:
4051 stepsound = cl_sfx_footsteps[r];
4052 break;
4053 }
4054
4055 volume = 1.0;
4056 S_StartSound (NULL, ent->number, CHAN_BODY, stepsound, volume, ATTN_NORM, 0);
4057 }
4058
CL_WaterWade(entity_state_t * ent)4059 void CL_WaterWade (entity_state_t *ent)
4060 {
4061 particle_t *p;
4062 trace_t tr;
4063 vec3_t end, angle;
4064 int j;
4065
4066 S_StartSound (NULL, ent->number, CHAN_BODY, S_RegisterSound("player/wade1.wav"), 1, ATTN_NORM, 0);
4067
4068 VectorCopy(ent->origin,end);
4069 end[2] -= 64;
4070 tr = CL_PMSurfaceTrace (ent->origin,NULL,NULL,end,MASK_SOLID | MASK_WATER);
4071 if (!tr.surface)
4072 return;
4073
4074 //draw rings that expand outward
4075 if(!(p = new_particle()))
4076 return;
4077 p->type = PARTICLE_RAISEDDECAL;
4078 p->image = r_splashtexture;
4079 p->blendsrc = GL_DST_COLOR;
4080 p->blenddst = GL_SRC_COLOR;
4081 p->scale = 1;
4082 p->scalevel = 8;
4083 p->color = 0 + (rand() & 1);
4084
4085 VectorScale(tr.plane.normal, -1, angle);
4086 RotateForNormal(angle, p->angle);
4087 p->angle[ROLL] = rand() % 360;
4088 VectorAdd(tr.endpos, tr.plane.normal, p->org);
4089
4090 for (j=0 ; j<3 ; j++)
4091 {
4092 p->org[j] = tr.endpos[j];
4093 p->vel[j] = 0;
4094 }
4095 p->accel[0] = p->accel[1] = p->accel[2] = 0;
4096 p->alpha = .1;
4097
4098 p->alphavel = -0.1 / (1 + frand()*0.3);
4099 }
4100
CL_EntityEvent(entity_state_t * ent)4101 void CL_EntityEvent (entity_state_t *ent)
4102 {
4103 switch (ent->event)
4104 {
4105 case EV_ITEM_RESPAWN:
4106 S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0);
4107 CL_ItemRespawnParticles (ent->origin);
4108 break;
4109 case EV_PLAYER_TELEPORT:
4110 S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0);
4111 CL_TeleportParticles (ent->origin);
4112 break;
4113 case EV_FOOTSTEP:
4114 if (cl_footsteps->value)
4115 CL_FootSteps (ent, false);
4116 break;
4117 case EV_WADE:
4118 if (cl_footsteps->value)
4119 CL_WaterWade ( ent );
4120 break;
4121 case EV_FALLSHORT:
4122 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("player/land1.wav"), 1, ATTN_NORM, 0);
4123 break;
4124 case EV_FALL:
4125 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall2.wav"), 1, ATTN_NORM, 0);
4126 break;
4127 case EV_FALLFAR:
4128 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall1.wav"), 1, ATTN_NORM, 0);
4129 break;
4130 }
4131 }
4132
4133
4134 /*
4135 ==============
4136 CL_ClearEffects
4137
4138 ==============
4139 */
CL_ClearEffects(void)4140 void CL_ClearEffects (void)
4141 {
4142 CL_ClearParticles ();
4143 CL_ClearDlights ();
4144 CL_ClearLightStyles ();
4145 CL_ClearClEntities();
4146 }
4147