1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 //
21 // cg_parteffects.c
22 //
23
24 #include "cg_local.h"
25
26 /*
27 ===============
28 CG_FindExplosionDir
29
30 This is a "necessary hack" for explosion decal placement.
31 ===============
32 */
CG_FindExplosionDir(vec3_t origin,float radius,vec3_t endPos,vec3_t dir)33 static qBool CG_FindExplosionDir (vec3_t origin, float radius, vec3_t endPos, vec3_t dir)
34 {
35 static vec3_t planes[6] = {{0,0,1}, {0,1,0}, {1,0,0}, {0,0,-1}, {0,-1,0}, {-1,0,0}};
36 trace_t tr;
37 vec3_t tempDir;
38 vec3_t tempOrg;
39 float best;
40 int i;
41
42 best = 1.0f;
43 Vec3Clear (endPos);
44 Vec3Clear (dir);
45 for (i=0 ; i<6 ; i++) {
46 Vec3MA (origin, radius * 0.9f, planes[i], tempDir);
47 Vec3MA (origin, radius * 0.1f, planes[(i+3)%6], tempOrg);
48
49 CG_PMTrace (&tr, tempOrg, NULL, NULL, tempDir, qFalse);
50 if (tr.allSolid || tr.fraction == 1.0f)
51 continue;
52
53 if (tr.fraction < best) {
54 best = tr.fraction;
55 Vec3Copy (tr.endPos, endPos);
56 Vec3Copy (tr.plane.normal, dir);
57 }
58 }
59
60 if (best < 1.0f) {
61 // FIXME: why does this "fix" decal normals on xdmt4? Something to do with the fragment planes...
62 byte dirByte = DirToByte (dir);
63 ByteToDir (dirByte, dir);
64 return qTrue;
65 }
66
67 return qFalse;
68 }
69
70 /*
71 =============================================================================
72
73 PARTICLE EFFECTS
74
75 =============================================================================
76 */
77
78 /*
79 ===============
80 CG_BlasterBlueParticles
81 ===============
82 */
CG_BlasterBlueParticles(vec3_t org,vec3_t dir)83 void CG_BlasterBlueParticles (vec3_t org, vec3_t dir)
84 {
85 int i, count;
86 int rnum, rnum2;
87 float d;
88
89 // Glow mark
90 rnum = (rand () % 5);
91 rnum2 = (rand () % 5);
92 CG_SpawnDecal (
93 org[0], org[1], org[2],
94 dir[0], dir[1], dir[2],
95 palRed (0x70 + rnum), palGreen (0x70 + rnum), palBlue (0x70 + rnum),
96 palRed (0x70 + rnum2), palGreen (0x70 + rnum2), palBlue (0x70 + rnum2),
97 1, 0,
98 7 + (frand() * 0.5f),
99 DT_BLASTER_BLUEMARK, DF_USE_BURNLIFE|DF_ALPHACOLOR,
100 0, qFalse,
101 0, frand () * 360);
102
103 // Burn mark
104 rnum = (rand () % 5);
105 CG_SpawnDecal (
106 org[0], org[1], org[2],
107 dir[0], dir[1], dir[2],
108 (255-palRed(0x70+rnum))*0.5f+128, (255-palGreen(0x70+rnum))*0.5f+128, (255-palBlue(0x70+rnum))*0.5f+128,
109 0, 0, 0,
110 0.9f + (crand() * 0.1f), 0.9f + (crand() * 0.1f),
111 5 + (frand() * 0.5f),
112 DT_BLASTER_BURNMARK, DF_ALPHACOLOR,
113 0, qFalse,
114 0, frand () * 360.0f);
115
116 // Smoke
117 count = 6 + (cg_particleSmokeLinger->floatVal * 0.25f);
118 for (i=0 ; i<count ; i++) {
119 d = 3 + (frand () * 6);
120 rnum = (rand () % 5);
121
122 CG_SpawnParticle (
123 org[0] + (d*dir[0]) + (crand()*2), org[1] + (d*dir[1]) + (crand()*2), org[2] + (d*dir[2]) + (crand()*2),
124 0, 0, 0,
125 0, 0, 0,
126 0, 0, 5 + (frand () * 25),
127 palRed (0x70 + rnum), palGreen (0x70 + rnum), palBlue (0x70 + rnum),
128 palRed (0x70 + rnum), palGreen (0x70 + rnum), palBlue (0x70 + rnum),
129 0.9f + (frand() * 0.1f), -1.0f / (0.8f + (cg_particleSmokeLinger->floatVal * 0.01f) + (frand() * 0.1f)),
130 5 + crand (), 16 + (crand () * 8),
131 pRandGlowSmoke (), PF_ALPHACOLOR,
132 NULL, qFalse,
133 PART_STYLE_QUAD,
134 frand () * 360);
135 }
136
137 // Dots
138 count = 60;
139 for (i=0 ; i<count ; i++) {
140 d = 6 + (frand () * 12);
141 rnum = (rand () % 5);
142
143 CG_SpawnParticle (
144 org[0] + (d*dir[0]) + (crand()*4), org[1] + (d*dir[1]) + (crand()*4), org[2] + (d*dir[2]) + (crand()*4),
145 0, 0, 0,
146 (dir[0] * 25) + (crand () * 35), (dir[1] * 25) + (crand () * 35), (dir[2] * 25) + (crand () * 35),
147 0, 0, -(frand () * 10),
148 palRed (0x70 + rnum), palGreen (0x70 + rnum), palBlue (0x70 + rnum),
149 palRed (0x70 + rnum), palGreen (0x70 + rnum), palBlue (0x70 + rnum),
150 0.9f + (frand () * 0.1f), -1.0f / (1 + frand () * 0.3f),
151 11 + (frand () * -10.75f), 0.1f + (frand () * 0.5f),
152 PT_BLASTER_BLUE, PF_SCALED|PF_GRAVITY|PF_ALPHACOLOR|PF_NOCLOSECULL,
153 pBounceThink, qTrue,
154 PART_STYLE_QUAD,
155 0);
156 }
157 }
158
159
160 /*
161 ===============
162 CG_BlasterGoldParticles
163 ===============
164 */
CG_BlasterGoldParticles(vec3_t org,vec3_t dir)165 void CG_BlasterGoldParticles (vec3_t org, vec3_t dir)
166 {
167 int i, count;
168 int rnum, rnum2;
169 float d;
170
171 // Glow mark
172 rnum = (rand () % 5);
173 rnum2 = (rand () % 5);
174 CG_SpawnDecal (
175 org[0], org[1], org[2],
176 dir[0], dir[1], dir[2],
177 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
178 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
179 1, 0,
180 7 + (frand() * 0.5f),
181 DT_BLASTER_REDMARK, DF_USE_BURNLIFE|DF_ALPHACOLOR,
182 0, qFalse,
183 0, frand () * 360);
184
185 // Burn mark
186 rnum = (rand () % 5);
187 CG_SpawnDecal (
188 org[0], org[1], org[2],
189 dir[0], dir[1], dir[2],
190 (255-palRed(0xe0+rnum))*0.5f+128, (255-palGreen(0xe0+rnum))*0.5f+128, (255-palBlue(0xe0+rnum))*0.5f+128,
191 0, 0, 0,
192 0.9f + (crand() * 0.1f), 0.9f + (crand() * 0.1f),
193 5 + (frand() * 0.5f),
194 DT_BLASTER_BURNMARK, DF_ALPHACOLOR,
195 0, qFalse,
196 0, frand () * 360);
197
198 // Smoke
199 count = 6 + (cg_particleSmokeLinger->floatVal * 0.25f);
200 for (i=0 ; i<count ; i++) {
201 d = 3 + (frand () * 6);
202 rnum = (rand () % 5);
203 rnum2 = (rand () % 5);
204
205 CG_SpawnParticle (
206 org[0] + (d*dir[0]) + (crand()*2), org[1] + (d*dir[1]) + (crand()*2), org[2] + (d*dir[2]) + (crand()*2),
207 0, 0, 0,
208 0, 0, 0,
209 0, 0, 5 + (frand () * 25),
210 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
211 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
212 0.9f + (frand() * 0.1f), -1.0f / (0.8f + (cg_particleSmokeLinger->floatVal * 0.01f) + (frand() * 0.1f)),
213 5 + crand (), 16 + (crand () * 8),
214 pRandGlowSmoke (), PF_ALPHACOLOR,
215 NULL, qFalse,
216 PART_STYLE_QUAD,
217 frand () * 360);
218 }
219
220 // Dots
221 count = 60.0f;
222 for (i=0 ; i<count ; i++) {
223 d = 6 + (frand () * 12);
224 rnum = (rand () % 5);
225
226 CG_SpawnParticle (
227 org[0] + (d*dir[0]) + (crand()*4), org[1] + (d*dir[1]) + (crand()*4), org[2] + (d*dir[2]) + (crand()*4),
228 0, 0, 0,
229 (dir[0] * 25) + (crand () * 35), (dir[1] * 25) + (crand () * 35), (dir[2] * 25) + (crand () * 35),
230 0, 0, -(frand () * 10),
231 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
232 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
233 0.9f + (frand () * 0.1f), -1.0f / (1 + frand () * 0.3f),
234 11 + (frand () * -10.75f), 0.1f + (frand () * 0.5f),
235 PT_BLASTER_RED, PF_SCALED|PF_GRAVITY|PF_ALPHACOLOR|PF_NOCLOSECULL,
236 pBounceThink, qTrue,
237 PART_STYLE_QUAD,
238 0);
239 }
240 }
241
242
243 /*
244 ===============
245 CG_BlasterGreenParticles
246 ===============
247 */
CG_BlasterGreenParticles(vec3_t org,vec3_t dir)248 void CG_BlasterGreenParticles (vec3_t org, vec3_t dir)
249 {
250 int i, count, rnum;
251 float d, randwhite;
252
253 // Glow mark
254 CG_SpawnDecal (
255 org[0], org[1], org[2],
256 dir[0], dir[1], dir[2],
257 (float)(rand()%41+135), (float)180 + (rand()%76), (float)(rand()%41+135),
258 (float)(rand()%41+135), (float)180 + (rand()%76), (float)(rand()%41+135),
259 1, 0,
260 5 + (frand() * 0.5f),
261 DT_BLASTER_GREENMARK, DF_USE_BURNLIFE|DF_ALPHACOLOR,
262 0, qFalse,
263 0, frand () * 360);
264
265 // Burn mark
266 rnum = (rand()%5);
267 CG_SpawnDecal (
268 org[0], org[1], org[2],
269 dir[0], dir[1], dir[2],
270 (255-palRed(0xd0+rnum))*0.5f+128, (255-palGreen(0xd0+rnum))*0.5f+128, (255-palBlue(0xd0+rnum))*0.5f+128,
271 0, 0, 0,
272 0.9f + (crand() * 0.1f), 0.9f + (crand() * 0.1f),
273 4 + (frand() * 0.5f),
274 DT_BLASTER_BURNMARK, DF_ALPHACOLOR,
275 0, qFalse,
276 0, frand () * 360);
277
278 // Smoke
279 count = 6 + (cg_particleSmokeLinger->floatVal * 0.25f);
280 for (i=0 ; i<count ; i++) {
281 d = 3 + (frand () * 6);
282 randwhite = (rand()&1)?150 + (rand()%26) : 0.0f;
283
284 CG_SpawnParticle (
285 org[0] + (d*dir[0]) + (crand()*2), org[1] + (d*dir[1]) + (crand()*2), org[2] + (d*dir[2]) + (crand()*2),
286 0, 0, 0,
287 0, 0, 0,
288 0, 0, 5 + (frand () * 25),
289 randwhite, 65 + (rand()%150) + randwhite, (rand()%50) + randwhite,
290 randwhite, 65 + (rand()%150) + randwhite, (rand()%50) + randwhite,
291 0.9f + (frand() * 0.1f), -1.0f / (0.8f + (cg_particleSmokeLinger->floatVal * 0.01f) + (frand() * 0.1f)),
292 5 + crand (), 16 + (crand () * 8),
293 pRandGlowSmoke (), PF_ALPHACOLOR,
294 NULL, qFalse,
295 PART_STYLE_QUAD,
296 frand () * 360);
297 }
298
299 // Dots
300 count = 60.0f;
301 for (i=0 ; i<count ; i++) {
302 d = 6 + (frand () * 12);
303 randwhite = (rand()&1)?150 + (rand()%26) : 0.0f;
304
305 CG_SpawnParticle (
306 org[0] + (d*dir[0]) + (crand()*4), org[1] + (d*dir[1]) + (crand()*4), org[2] + (d*dir[2]) + (crand()*4),
307 0, 0, 0,
308 (dir[0] * 25) + (crand () * 35), (dir[1] * 25) + (crand () * 35), (dir[2] * 25) + (crand () * 35),
309 0, 0, -(frand () * 10),
310 randwhite, 65 + (rand()%150) + randwhite, (rand()%50) + randwhite,
311 randwhite, 65 + (rand()%150) + randwhite, (rand()%50) + randwhite,
312 0.9f + (frand() * 0.1f), -0.4f / (0.3f + (frand () * 0.3f)),
313 10 + (frand() * -9.75f), 0.1f + (frand() * 0.5f),
314 PT_BLASTER_GREEN, PF_SCALED|PF_GRAVITY|PF_ALPHACOLOR|PF_NOCLOSECULL,
315 pBounceThink, qTrue,
316 PART_STYLE_QUAD,
317 0);
318 }
319 }
320
321
322 /*
323 ===============
324 CG_BlasterGreyParticles
325 ===============
326 */
CG_BlasterGreyParticles(vec3_t org,vec3_t dir)327 void CG_BlasterGreyParticles (vec3_t org, vec3_t dir)
328 {
329 int i, count;
330 float d;
331
332 // Smoke
333 count = 6 + (cg_particleSmokeLinger->floatVal * 0.25f);
334 for (i=0 ; i<count ; i++) {
335 d = (float)(rand()%13 + 3);
336
337 CG_SpawnParticle (
338 org[0] + d*dir[0], org[1] + d*dir[1], org[2] + d*dir[2],
339 0, 0, 0,
340 0, 0, 0,
341 0, 0, 10 + (frand () * 20),
342 130.0f + (rand()%6), 162.0f + (rand()%6), 178.0f + (rand()%6),
343 130.0f + (rand()%6), 162.0f + (rand()%6), 178.0f + (rand()%6),
344 0.9f + (frand() * 0.1f), -1.0f / (0.8f + (cg_particleSmokeLinger->floatVal * 0.01f) + (frand() * 0.1f)),
345 5 + crand (), 15 + (crand () * 8),
346 pRandGlowSmoke (), PF_ALPHACOLOR,
347 NULL, qFalse,
348 PART_STYLE_QUAD,
349 frand () * 360);
350 }
351
352 // Dots
353 count = 50.0f;
354 for (i=0 ; i<count ; i++) {
355 d = 1.5f + (rand()%13 + 3);
356
357 CG_SpawnParticle (
358 org[0] + crand () * 4 + d*dir[0], org[1] + crand () * 4 + d*dir[1], org[2] + crand () * 4 + d*dir[2],
359 0, 0, 0,
360 dir[0] * 25 + crand () * 35, dir[1] * 25 + crand () * 35, dir[2] * 25 + crand () * 35,
361 0, 0, -10 + (frand () * 10),
362 130.0f + (rand()%6), 162.0f + (rand()%6), 178.0f + (rand()%6),
363 130.0f + (rand()%6), 162.0f + (rand()%6), 178.0f + (rand()%6),
364 0.9f + (frand() * 0.1f), -1.0f / (0.8f + (frand () * 0.3f)),
365 10 + (frand() * -9.75f), 0.1f + (frand() * 0.5f),
366 PT_FLARE, PF_SCALED|PF_GRAVITY|PF_NOCLOSECULL,
367 pBounceThink, qTrue,
368 PART_STYLE_QUAD,
369 0);
370 }
371 }
372
373
374 /*
375 ===============
376 CG_BleedEffect
377 ===============
378 */
CG_BleedEffect(vec3_t org,vec3_t dir,int count)379 void CG_BleedEffect (vec3_t org, vec3_t dir, int count)
380 {
381 int i, flags;
382 float d, gore, amount, fly;
383 vec3_t orgVec, dirVec;
384
385 gore = clamp (cg_particleGore->floatVal, 0.0f, 10.0f);
386 fly = (gore * 0.1f) * 30;
387
388 // Splurt
389 amount = ((gore + 5) / 10.0f) + 0.5f;
390 for (i=0 ; i<amount ; i++) {
391 dirVec[0] = crand () * 3;
392 dirVec[1] = crand () * 3;
393 dirVec[2] = crand () * 3;
394
395 CG_SpawnParticle (
396 org[0] + (crand () * 3), org[1] + (crand () * 3), org[2] + (crand () * 3),
397 0, 0, 0,
398 dirVec[0], dirVec[1], dirVec[2],
399 dirVec[0] * -0.25f, dirVec[1] * -0.25f, dirVec[2] * -0.25f,
400 230 + (frand () * 5), 245 + (frand () * 10), 245 + (frand () * 10),
401 0, 0, 0,
402 1.0f, -0.5f / (0.4f + (frand () * 0.3f)),
403 9 + (crand () * 2), 14 + (crand () * 3),
404 PT_BLDSPURT, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
405 NULL, qFalse,
406 PART_STYLE_QUAD,
407 frand () * 360);
408 }
409
410 // Larger splurt
411 for (i=0 ; i<amount ; i++) {
412 dirVec[0] = crand () * 4;
413 dirVec[1] = crand () * 4;
414 dirVec[2] = crand () * 4;
415
416 CG_SpawnParticle (
417 org[0] + (crand () * 3), org[1] + (crand () * 3), org[2] + (crand () * 3),
418 0, 0, 0,
419 dirVec[0], dirVec[1], dirVec[2],
420 dirVec[0] * -0.25f, dirVec[1] * -0.25f, dirVec[2] * -0.25f,
421 230 + (frand () * 5), 245 + (frand () * 10), 245 + (frand () * 10),
422 0, 0, 0,
423 1.0f, -0.5f / (0.4f + (frand () * 0.3f)),
424 10 + (crand () * 2), 14 + (crand () * 3),
425 PT_BLDSPURT2, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
426 NULL, qFalse,
427 PART_STYLE_QUAD,
428 frand () * 360);
429 }
430
431 // Drips
432 amount = (count + gore) * 0.25f;
433 flags = PF_ALPHACOLOR|PF_SCALED|PF_GRAVITY;
434
435 for (i=0 ; i<amount ; i++) {
436 // Every other drip follows the last one
437 if (i+1 & 1) {
438 // Leader
439 d = 1 + (frand () * 6);
440
441 Vec3Copy (org, orgVec);
442 Vec3Copy (dir, dirVec);
443 Vec3Scale (dirVec, d, dirVec);
444
445 orgVec[0] += crand () * 3;
446 orgVec[1] += crand () * 3;
447 orgVec[2] += crand () * 3;
448
449 dirVec[0] += crand () * (200 + fly);
450 dirVec[1] += crand () * (200 + fly);
451 dirVec[2] += crand () * (200 + fly);
452
453 flags |= PF_NODECAL;
454 }
455 else {
456 // Follower
457 Vec3Scale (dirVec, 0.75f + (crand () * 0.1f), dirVec);
458
459 flags &= ~PF_NODECAL;
460 }
461
462 // Create the drip
463 CG_SpawnParticle (
464 orgVec[0] + (dir[0] * d), orgVec[1] + (dir[1] * d), orgVec[2] + (dir[2] * d),
465 0, 0, 0,
466 dirVec[0], dirVec[1], dirVec[2],
467 0, 0, -200,
468 230 + (frand () * 5), 245 + (frand () * 10), 245 + (frand () * 10),
469 0, 0, 0,
470 1.0f, -0.5f / (0.4f + (frand () * 0.9f)),
471 0.25f + (frand () * 0.9f), 0.35f + (frand () * 0.5f),
472 pRandBloodDrip (), flags,
473 pBloodDripThink, qTrue,
474 PART_STYLE_DIRECTION,
475 PMAXBLDDRIPLEN*0.5f + (frand () * PMAXBLDDRIPLEN));
476 }
477 }
478
479
480 /*
481 ===============
482 CG_BleedGreenEffect
483 ===============
484 */
CG_BleedGreenEffect(vec3_t org,vec3_t dir,int count)485 void CG_BleedGreenEffect (vec3_t org, vec3_t dir, int count)
486 {
487 int i, flags;
488 float d, gore, amount, fly;
489 vec3_t orgVec, dirVec;
490
491 gore = clamp ((cg_particleGore->floatVal + 1), 1, 11);
492 amount = (count + gore) * 0.5f;
493 fly = ((gore - 1) * 0.1f) * 30;
494
495 // Drip
496 for (i=0 ; i<amount ; i++) {
497 d = 1 + (frand () * 6);
498
499 Vec3Copy (org, orgVec);
500 Vec3Copy (dir, dirVec);
501 Vec3Scale (dirVec, d, dirVec);
502
503 orgVec[0] += crand () * 3;
504 orgVec[1] += crand () * 3;
505 orgVec[2] += crand () * 3;
506
507 dirVec[0] += crand () * (100 + fly);
508 dirVec[1] += crand () * (100 + fly);
509 dirVec[2] += crand () * (100 + fly);
510
511 flags = PF_SCALED|PF_GRAVITY|PF_GREENBLOOD;
512 if (rand () % (int)(clamp (amount + 1, gore + 1, amount + 1) - gore))
513 flags |= PF_NODECAL;
514
515 CG_SpawnParticle (
516 orgVec[0] + (dir[0] * d), orgVec[1] + (dir[1] * d), orgVec[2] + (dir[2] * d),
517 0, 0, 0,
518 dirVec[0], dirVec[1], dirVec[2],
519 0, 0, -220,
520 20.0f, 50.0f + (rand()%91), 20.0f,
521 10.0f, 50.0f + (rand()%91), 10.0f,
522 1.0f, -0.5f / (0.4f + (frand () * 0.3f)),
523 1.25f + (frand () * 0.2f), 1.35f + (frand () * 0.2f),
524 pRandGrnBloodDrip (), flags,
525 pBloodDripThink, qTrue,
526 PART_STYLE_DIRECTION,
527 PMAXBLDDRIPLEN);
528 }
529 }
530
531
532 /*
533 ===============
534 CG_BubbleEffect
535 ===============
536 */
CG_BubbleEffect(vec3_t origin)537 void CG_BubbleEffect (vec3_t origin)
538 {
539 float rnum, rnum2;
540
541 // why bother spawn a particle that's just going to die anyways?
542 if (!(cgi.CM_PointContents (origin, 0) & MASK_WATER))
543 return;
544
545 rnum = 230 + (frand () * 25);
546 rnum2 = 230 + (frand () * 25);
547 CG_SpawnParticle (
548 origin[0] + crand (), origin[1] + crand (), origin[2] + crand (),
549 0, 0, 0,
550 crand () * 4, crand () * 4, 10 + (crand () * 4),
551 0, 0, 0,
552 rnum, rnum, rnum,
553 rnum2, rnum2, rnum2,
554 0.9f + (crand () * 0.1f), -1.0f / (3 + (frand () * 0.2f)),
555 0.1f + frand (), 0.1f + frand (),
556 PT_WATERBUBBLE, PF_SHADE|PF_LAVAONLY|PF_SLIMEONLY|PF_WATERONLY|PF_NOCLOSECULL,
557 0, qFalse,
558 PART_STYLE_QUAD,
559 0);
560 }
561
562
563 /*
564 ===============
565 CG_ExplosionBFGEffect
566
567 Normally drawn at the feet of opponents when a bfg explodes
568 ===============
569 */
CG_ExplosionBFGEffect(vec3_t org)570 void CG_ExplosionBFGEffect (vec3_t org)
571 {
572 int i;
573 float randwhite;
574 float rnum, rnum2;
575
576 // Smoke
577 for (i=0 ; i<8 ; i++) {
578 rnum = 70 + (frand () * 40);
579 rnum2 = 80 + (frand () * 40);
580 CG_SpawnParticle (
581 org[0] + (crand () * 4), org[1] + (crand () * 4), org[2] + (crand () * 4),
582 0, 0, 0,
583 crand () * 2, crand () * 2, crand () * 2,
584 0, 0, 5 + (frand () * 6),
585 rnum, 80 + rnum, rnum,
586 rnum2, 100+ rnum2, rnum2,
587 0.75f + (crand () * 0.1f), -1.0f / (0.25f + (cg_particleSmokeLinger->floatVal * 0.1f) + (crand () * 0.1f)),
588 35 + (crand () * 15), 140 + (crand () * 30),
589 pRandGlowSmoke (), 0,
590 pSmokeThink, qTrue,
591 PART_STYLE_QUAD,
592 frand () * 361);
593 }
594
595 // Dots
596 for (i=0 ; i<256 ; i++) {
597 randwhite = (rand()&1) ? 150 + (rand()%26) : 0.0f;
598 CG_SpawnParticle (
599 org[0] + (crand () * 20), org[1] + (crand () * 20), org[2] + (crand () * 20),
600 0, 0, 0,
601 crand () * 50, crand () * 50, crand () * 50,
602 0, 0, -40,
603 randwhite, 75 + (rand()%150) + randwhite, (rand()%50) + randwhite,
604 randwhite, 75 + (rand()%150) + randwhite, (rand()%50) + randwhite,
605 1.0f, -0.8f / (0.8f + (frand () * 0.3f)),
606 11 + (crand () * 10.5f), 0.6f + (crand () * 0.5f),
607 PT_BFG_DOT, PF_SCALED|PF_GRAVITY|PF_ALPHACOLOR|PF_NOCLOSECULL,
608 pBounceThink, qTrue,
609 PART_STYLE_QUAD,
610 0);
611 }
612 }
613
614
615 /*
616 ===============
617 CG_FlareEffect
618 ===============
619 */
CG_FlareEffect(vec3_t origin,int type,float orient,float size,float sizevel,int color,int colorvel,float alpha,float alphavel)620 void __fastcall CG_FlareEffect (vec3_t origin, int type, float orient, float size, float sizevel, int color, int colorvel, float alpha, float alphavel)
621 {
622 CG_SpawnParticle (
623 origin[0], origin[1], origin[2],
624 0, 0, 0,
625 0, 0, 0,
626 0, 0, 0,
627 palRed (color), palGreen (color), palBlue (color),
628 palRed (colorvel), palGreen (colorvel), palBlue (colorvel),
629 alpha, alphavel,
630 size, sizevel,
631 type, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
632 pFlareThink, qTrue,
633 PART_STYLE_QUAD,
634 orient);
635 }
636
637
638 /*
639 ===============
640 CG_ItemRespawnEffect
641 ===============
642 */
CG_ItemRespawnEffect(vec3_t org)643 void CG_ItemRespawnEffect (vec3_t org)
644 {
645 int i;
646
647 for (i=0 ; i<64 ; i++) {
648 CG_SpawnParticle (
649 org[0] + (crand () * 9), org[1] + (crand () * 9), org[2] + (crand () * 9),
650 0, 0, 0,
651 crand () * 10, crand () * 10, crand () * 10,
652 crand () * 10, crand () * 10, 20 + (crand () * 10),
653 135 + (frand () * 40), 180 + (frand () * 75), 135 + (frand () * 40),
654 135 + (frand () * 40), 180 + (frand () * 75), 135 + (frand () * 40),
655 1.0f, -1.0f / (1.0f + (frand () * 0.3f)),
656 4, 2,
657 PT_ITEMRESPAWN, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
658 0, qFalse,
659 PART_STYLE_QUAD,
660 0);
661 }
662 }
663
664
665 /*
666 ===============
667 CG_LogoutEffect
668 ===============
669 */
CG_LogoutEffect(vec3_t org,int type)670 void CG_LogoutEffect (vec3_t org, int type)
671 {
672 int i, rnum, rnum2;
673 float count = 300;
674
675 switch (type) {
676 case MZ_LOGIN:
677 // green
678 for (i=0 ; i<count ; i++) {
679 rnum = (rand() % 5);
680 rnum2 = (rand() % 5);
681 CG_SpawnParticle (
682 org[0] - 16 + (frand () * 32), org[1] - 16 + (frand () * 32), org[2] - 24 + (frand () * 56),
683 0, 0, 0,
684 crand () * 20, crand () * 20, crand () * 20,
685 0, 0, -40,
686 palRed (0xd0 + rnum), palGreen (0xd0 + rnum), palBlue (0xd0 + rnum),
687 palRed (0xd0 + rnum2), palGreen (0xd0 + rnum2), palBlue (0xd0 + rnum2),
688 1.0f, -1.0f / (1.0f + (frand () * 0.3f)),
689 3, 1,
690 PT_GENERIC_GLOW, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
691 0, qFalse,
692 PART_STYLE_QUAD,
693 0);
694 }
695 break;
696
697 case MZ_LOGOUT:
698 // red
699 for (i=0 ; i<count ; i++) {
700 rnum = (rand() % 5);
701 rnum2 = (rand() % 5);
702 CG_SpawnParticle (
703 org[0] - 16 + (frand () * 32), org[1] - 16 + (frand () * 32), org[2] - 24 + (frand () * 56),
704 0, 0, 0,
705 crand () * 20, crand () * 20, crand () * 20,
706 0, 0, -40,
707 palRed (0x40 + rnum), palGreen (0x40 + rnum), palBlue (0x40 + rnum),
708 palRed (0x40 + rnum2), palGreen (0x40 + rnum2), palBlue (0x40 + rnum2),
709 1.0f, -1.0f / (1.0f + (frand () * 0.3f)),
710 3, 1,
711 PT_GENERIC_GLOW, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
712 0, qFalse,
713 PART_STYLE_QUAD,
714 0);
715 }
716 break;
717
718 default:
719 // golden
720 for (i=0 ; i<count ; i++) {
721 rnum = (rand() % 5);
722 rnum2 = (rand() % 5);
723 CG_SpawnParticle (
724 org[0] - 16 + (frand () * 32), org[1] - 16 + (frand () * 32), org[2] - 24 + (frand () * 56),
725 0, 0, 0,
726 crand () * 20, crand () * 20, crand () * 20,
727 0, 0, -40,
728 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
729 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
730 1.0f, -1.0f / (1.0f + (frand () * 0.3f)),
731 3, 1,
732 PT_GENERIC_GLOW, PF_SCALED|PF_ALPHACOLOR|PF_NOCLOSECULL,
733 0, qFalse,
734 PART_STYLE_QUAD,
735 0);
736 }
737 break;
738 }
739 }
740
741
742 /*
743 ===============
744 CG_ParticleEffect
745
746 Wall impact puffs
747 ===============
748 */
CG_ParticleEffect(vec3_t org,vec3_t dir,int color,int count)749 void __fastcall CG_ParticleEffect (vec3_t org, vec3_t dir, int color, int count)
750 {
751 int i, rnum, rnum2;
752 float d;
753
754 if (cg.currGameMod == GAME_MOD_GLOOM) {
755 switch (color) {
756 // drone spit
757 case 0xd0:
758 CG_GloomDroneEffect (org, dir);
759 return;
760
761 // slash
762 case 0xe0:
763 d = 5 + ((rand()%31*0.1f) - 1);
764 CG_SpawnDecal (
765 org[0], org[1], org[2],
766 dir[0], dir[1], dir[2],
767 255, 255, 255,
768 0, 0, 0,
769 0.9f + (crand () * 0.1f), 0.8f,
770 d,
771 dRandSlashMark (), DF_ALPHACOLOR,
772 0, qFalse,
773 0, frand () * 360);
774
775 for (i=0 ; i<count ; i++) {
776 d = (float)(rand()%17);
777 rnum = (rand()%5);
778 rnum2 = (rand()%5);
779
780 CG_SpawnParticle (
781 org[0] + (crand () * 4) + d*dir[0], org[1] + (crand () * 4) + d*dir[1], org[2] + (crand () * 4) + d*dir[2],
782 0, 0, 0,
783 dir[0] * crand () * 3, dir[1] * crand () * 3, dir[2] * crand () * 3,
784 (dir[0] * (crand() * 8)) + (crand () * 4),
785 (dir[1] * (crand() * 8)) + (crand () * 4),
786 (dir[2] * (crand() * 8)) + (crand () * 4) - (frand() * 60),
787 palRed (color + rnum), palGreen (color + rnum), palBlue (color + rnum),
788 palRed (color + rnum2), palGreen (color + rnum2), palBlue (color + rnum2),
789 1.0f, -1.0f / (0.5f + (frand () * 0.3f)),
790 0.5f, 0.6f,
791 PT_GENERIC_GLOW, PF_SCALED|PF_ALPHACOLOR,
792 0, qFalse,
793 PART_STYLE_QUAD,
794 0);
795 }
796
797 CG_SparkEffect (org, dir, color, color, count, 1, 1);
798 return;
799
800 // exterm
801 case 0x75:
802 CG_BlasterBlueParticles (org, dir);
803 return;
804 }
805 }
806
807 switch (color) {
808 // blood
809 case 0xe8:
810 CG_BleedEffect (org, dir, count);
811 return;
812
813 // bullet mark
814 case 0x0:
815 CG_RicochetEffect (org, dir, count);
816 return;
817
818 // default
819 default:
820 for (i=0 ; i<count ; i++) {
821 d = (float)(rand()%31);
822 rnum = (rand()%5);
823 rnum2 = (rand()%5);
824
825 CG_SpawnParticle (
826 org[0] + ((rand()%7)-4) + d*dir[0], org[1] + ((rand()%7)-4) + d*dir[1], org[2] + ((rand()%7)-4) + d*dir[2],
827 0, 0, 0,
828 crand () * 20, crand () * 20, crand () * 20,
829 0, 0, -40,
830 palRed (color + rnum), palGreen (color + rnum), palBlue (color + rnum),
831 palRed (color + rnum2), palGreen (color + rnum2), palBlue (color + rnum2),
832 1, -1.0f / (0.5f + (frand () * 0.3f)),
833 1, 1,
834 PT_GENERIC, PF_SCALED,
835 0, qFalse,
836 PART_STYLE_QUAD,
837 0);
838 }
839 return;
840 }
841 }
842
843
844 /*
845 ===============
846 CG_ParticleEffect2
847 ===============
848 */
CG_ParticleEffect2(vec3_t org,vec3_t dir,int color,int count)849 void __fastcall CG_ParticleEffect2 (vec3_t org, vec3_t dir, int color, int count)
850 {
851 if (color == 0xe2 && cg.currGameMod == GAME_MOD_GLOOM) {
852 CG_GloomRepairEffect (org, dir, count);
853 }
854 else {
855 int i, rnum, rnum2;
856 float d;
857
858 for (i=0 ; i<count ; i++) {
859 d = frand () * 7;
860 rnum = (rand () % 5);
861 rnum2 = (rand () % 5);
862
863 CG_SpawnParticle (
864 org[0] + (crand () * 4) + d*dir[0], org[1] + (crand () * 4) + d*dir[1], org[2] + (crand () * 4) + d*dir[2],
865 0, 0, 0,
866 crand () * 20, crand () * 20, crand () * 20,
867 0, 0, -40,
868 palRed (color + rnum), palGreen (color + rnum), palBlue (color + rnum),
869 palRed (color + rnum2), palGreen (color + rnum2), palBlue (color + rnum2),
870 1, -1.0f / (0.5f + (frand () * 0.3f)),
871 1, 1,
872 PT_GENERIC, PF_SCALED,
873 0, qFalse,
874 PART_STYLE_QUAD,
875 0);
876 }
877 }
878 }
879
880
881 /*
882 ===============
883 CG_ParticleEffect3
884 ===============
885 */
CG_ParticleEffect3(vec3_t org,vec3_t dir,int color,int count)886 void __fastcall CG_ParticleEffect3 (vec3_t org, vec3_t dir, int color, int count)
887 {
888 int i, rnum, rnum2;
889 float d;
890
891 for (i=0 ; i<count ; i++) {
892 d = frand () * 7;
893 rnum = (rand () % 5);
894 rnum2 = (rand () % 5);
895
896 CG_SpawnParticle (
897 org[0] + (crand () * 4) + d*dir[0], org[1] + (crand () * 4) + d*dir[1], org[2] + (crand () * 4) + d*dir[2],
898 0, 0, 0,
899 crand () * 20, crand () * 20, crand () * 20,
900 0, 0, 40,
901 palRed (color + rnum), palGreen (color + rnum), palBlue (color + rnum),
902 palRed (color + rnum2), palGreen (color + rnum2), palBlue (color + rnum2),
903 1.0f, -1.0f / (0.5f + (frand () * 0.3f)),
904 1, 1,
905 PT_GENERIC, PF_SCALED,
906 0, qFalse,
907 PART_STYLE_QUAD,
908 0);
909 }
910 }
911
912
913 /*
914 ===============
915 CG_ParticleSmokeEffect
916
917 like the steam effect, but unaffected by gravity
918 ===============
919 */
CG_ParticleSmokeEffect(vec3_t org,vec3_t dir,int color,int count,int magnitude)920 void __fastcall CG_ParticleSmokeEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude)
921 {
922 int i, rnum, rnum2;
923 float d;
924 vec3_t r, u, pvel;
925
926 MakeNormalVectorsf (dir, r, u);
927
928 for (i=0 ; i<count ; i++) {
929 Vec3Scale (dir, magnitude, pvel);
930 d = crand() * magnitude / 3;
931 Vec3MA (pvel, d, r, pvel);
932 d = crand() * magnitude/ 3;
933 Vec3MA (pvel, d, u, pvel);
934
935 rnum = (rand () % 5);
936 rnum2 = (rand () % 5);
937 CG_SpawnParticle (
938 org[0] + magnitude*0.1f*crand(),org[1] + magnitude*0.1f*crand(),org[2] + magnitude*0.1f*crand(),
939 0, 0, 0,
940 pvel[0], pvel[1], pvel[2],
941 0, 0, 0,
942 palRed (color + rnum), palGreen (color + rnum), palBlue (color + rnum),
943 palRed (color + rnum2), palGreen (color + rnum2), palBlue (color + rnum2),
944 0.9f + (crand () * 0.1f), -1.0f / (0.5f + (cg_particleSmokeLinger->floatVal * 0.5f) + (frand () * 0.3f)),
945 5 + (frand () * 4), 10 + (frand () * 4),
946 pRandSmoke (), PF_SHADE,
947 pSmokeThink, qTrue,
948 PART_STYLE_QUAD,
949 frand () * 360);
950 }
951 }
952
953
954 /*
955 ===============
956 CG_RicochetEffect
957 ===============
958 */
CG_RicochetEffect(vec3_t org,vec3_t dir,int count)959 void __fastcall CG_RicochetEffect (vec3_t org, vec3_t dir, int count)
960 {
961 int i, rnum, rnum2;
962 float d;
963
964 // Bullet mark
965 CG_SpawnDecal (
966 org[0], org[1], org[2],
967 dir[0], dir[1], dir[2],
968 255, 255, 255,
969 0, 0, 0,
970 0.9f + (crand () * 0.1f), 0.8f,
971 4 + crand (),
972 DT_BULLET, DF_ALPHACOLOR,
973 0, qFalse,
974 0, frand () * 360);
975
976 // Dots
977 for (i=0 ; i<count ; i++) {
978 d = (float)(rand()%17);
979 rnum = (rand()%3) + 2;
980 rnum2 = (rand()%5);
981
982 CG_SpawnParticle (
983 org[0] + ((rand()%7)-3) + d*dir[0], org[1] + ((rand()%7)-3) + d*dir[1], org[2] + ((rand()%7)-3) + d*dir[2],
984 0, 0, 0,
985 dir[0] * crand () * 3, dir[1] * crand () * 3, dir[2] * crand () * 3,
986 (dir[0] * (crand() * 8)) + ((rand()%7)-3),
987 (dir[1] * (crand() * 8)) + ((rand()%7)-3),
988 (dir[2] * (crand() * 8)) + ((rand()%7)-3) - (40 * frand() * 1.5f),
989 palRed (rnum), palGreen (rnum), palBlue (rnum),
990 palRed (rnum2), palGreen (rnum2), palBlue (rnum2),
991 1.0f, -1.0f / (0.5f + (frand() * 0.2f)),
992 0.5f, 0.6f,
993 PT_GENERIC, PF_SCALED|PF_NOCLOSECULL,
994 0, qFalse,
995 PART_STYLE_QUAD,
996 0);
997 }
998
999 CG_SparkEffect (org, dir, 10, 10, count/2, 1, 1);
1000 }
1001
1002
1003 /*
1004 ===============
1005 CG_RocketFireParticles
1006 ===============
1007 */
CG_RocketFireParticles(vec3_t org,vec3_t dir)1008 void CG_RocketFireParticles (vec3_t org, vec3_t dir)
1009 {
1010 float rnum, rnum2;
1011
1012 // FIXME: need to use dir to tell smoke where to fly to
1013 rnum = 60 + (frand () * 50);
1014 rnum2 = 70 + (frand () * 50);
1015
1016 CG_SpawnParticle (
1017 org[0] + (crand () * 4), org[1] + (crand () * 4), org[2] + (crand () * 4) + 16,
1018 0, 0, 0,
1019 crand () * 2, crand () * 2, crand () * 2,
1020 crand () * 2, crand () * 2, crand () + (frand () * 4),
1021 rnum, rnum, rnum,
1022 rnum2, rnum2, rnum2,
1023 0.4f, -1.0f / (1.75f + (crand () * 0.25f)),
1024 65 + (crand () * 10), 450 + (crand () * 10),
1025 pRandSmoke (), PF_SHADE,
1026 pSmokeThink, qTrue,
1027 PART_STYLE_QUAD,
1028 frand () * 360);
1029 }
1030
1031
1032 /*
1033 ===============
1034 CG_SparkEffect
1035 ===============
1036 */
CG_SparkEffect(vec3_t org,vec3_t dir,int color,int colorvel,int count,float smokeScale,float lifeScale)1037 void __fastcall CG_SparkEffect (vec3_t org, vec3_t dir, int color, int colorvel, int count, float smokeScale, float lifeScale)
1038 {
1039 int i;
1040 float d, d2;
1041 float rnum, rnum2;
1042
1043 // Sparks
1044 for (i=0 ; i<count ; i++) {
1045 d = 140 + (crand () * 40) * lifeScale;
1046 d2 = 1 + crand ();
1047 rnum = (float)(rand () % 5);
1048 rnum2 = (float)(rand () % 5);
1049
1050 CG_SpawnParticle (
1051 org[0] + (dir[0] * d2) + crand (), org[1] + (dir[1] * d2) + crand (), org[2] + (dir[2] * d2) + crand (),
1052 0, 0, 0,
1053 (dir[0] * d) + (crand () * 24), (dir[1] * d) + (crand () * 24), (dir[2] * d) + (crand () * 24),
1054 0, 0, 0,
1055 palRed ((int)(color + rnum)), palGreen ((int)(color + rnum)), palBlue ((int)(color + rnum)),
1056 palRed ((int)(colorvel + rnum2)), palGreen ((int)(colorvel + rnum2)), palBlue ((int)(colorvel + rnum2)),
1057 1, -1.0f / (0.175f + (frand() * 0.05f)),
1058 0.4f, 0.4f,
1059 PT_SPARK, PF_ALPHACOLOR,
1060 pRicochetSparkThink, qTrue,
1061 PART_STYLE_DIRECTION,
1062 16 + (crand () * 4));
1063 }
1064
1065 // Smoke
1066 for (i=1 ; i<4 ; i++) {
1067 rnum = 60 + (frand () * 50);
1068 rnum2 = 70 + (frand () * 50);
1069 CG_SpawnParticle (
1070 org[0] + (i*dir[0]*2.5f) + crand (),org[1] + (i*dir[1]*2.5f) + crand (),org[2] + (i*dir[2]*2.5f) + crand (),
1071 0, 0, 0,
1072 0, 0, 0,
1073 0, 0, i*3.5f,
1074 rnum, rnum, rnum,
1075 rnum2, rnum2, rnum2,
1076 0.9f + (crand () * 0.1f), -1.0f / (1.5f + (cg_particleSmokeLinger->floatVal * 0.05f) + (crand() * 0.2f)),
1077 (4 + (frand () * 3)) * smokeScale, (12 + (crand () * 3)) * smokeScale,
1078 pRandSmoke (), PF_SHADE|PF_NOCLOSECULL,
1079 pFastSmokeThink, qTrue,
1080 PART_STYLE_QUAD,
1081 frand () * 360);
1082 }
1083
1084 // Burst smoke
1085 for (i=1 ; i<7 ; i++) {
1086 rnum = 60 + (frand () * 50);
1087 rnum2 = 70 + (frand () * 50);
1088 CG_SpawnParticle (
1089 org[0]+(i*dir[0]*3.25f)+crand()*2, org[1]+(i*dir[1]*3.25f)+crand()*2, org[2]+(i*dir[2]*3.25f)+crand()*2,
1090 0, 0, 0,
1091 0, 0, 0,
1092 0, 0, 5,
1093 rnum, rnum, rnum,
1094 rnum2, rnum2, rnum2,
1095 0.9f + (crand () * 0.1f), -1.0f / (1.25f + (cg_particleSmokeLinger->floatVal * 0.05f) + (crand() * 0.2f)),
1096 (4 + (frand () * 3)) * smokeScale, (12 + (crand () * 3)) * smokeScale,
1097 pRandSmoke (), PF_SHADE|PF_NOCLOSECULL,
1098 pFastSmokeThink, qTrue,
1099 PART_STYLE_QUAD,
1100 frand () * 360);
1101 }
1102 }
1103
1104
1105 /*
1106 ===============
1107 CG_SplashEffect
1108 ===============
1109 */
CG_SplashParticles(vec3_t org,vec3_t dir,int color,int count,qBool glow)1110 void __fastcall CG_SplashParticles (vec3_t org, vec3_t dir, int color, int count, qBool glow)
1111 {
1112 int i, rnum, rnum2;
1113 vec3_t angle, dirVec;
1114 float d;
1115
1116 // Ripple
1117 rnum = (rand () % 5);
1118 rnum2 = (rand () % 5);
1119
1120 VecToAngleRolled (dir, frand () * 360, angle);
1121 CG_SpawnParticle (
1122 org[0] + dir[0], org[1] + dir[0], org[2] + dir[0],
1123 angle[0], angle[1], angle[2],
1124 0, 0, 0,
1125 0, 0, 0,
1126 palRed (color + rnum) + 64, palGreen (color + rnum) + 64, palBlue (color + rnum) + 64,
1127 palRed (color + rnum2) + 64, palGreen (color + rnum2) + 64, palBlue (color + rnum2) + 64,
1128 0.5f + (crand () * 0.1f), -1.0f / (1.9f + (frand () * 0.1f)),
1129 7 + (crand () * 2), 24 + (crand () * 3),
1130 PT_WATERRIPPLE, PF_SCALED,
1131 NULL, qFalse,
1132 PART_STYLE_ANGLED,
1133 0);
1134
1135 // Ring
1136 rnum = (rand () % 5);
1137 rnum2 = (rand () % 5);
1138
1139 VecToAngleRolled (dir, frand () * 360, angle);
1140 CG_SpawnParticle (
1141 org[0] + dir[0], org[1] + dir[0], org[2] + dir[0],
1142 angle[0], angle[1], angle[2],
1143 0, 0, 0,
1144 0, 0, 0,
1145 palRed (color + rnum) + 64, palGreen (color + rnum) + 64, palBlue (color + rnum) + 64,
1146 palRed (color + rnum2) + 64, palGreen (color + rnum2) + 64, palBlue (color + rnum2) + 64,
1147 0.9f + (crand () * 0.1f), -1.0f / (0.5f + (frand () * 0.1f)),
1148 2 + crand (), 15 + (crand () * 2),
1149 PT_WATERRING, PF_SCALED,
1150 NULL, qFalse,
1151 PART_STYLE_ANGLED,
1152 0);
1153
1154 // Impact
1155 rnum = (rand () % 5);
1156 rnum2 = (rand () % 5);
1157
1158 VecToAngleRolled (dir, frand () * 360, angle);
1159 CG_SpawnParticle (
1160 org[0] + dir[0], org[1] + dir[0], org[2] + dir[0],
1161 angle[0], angle[1], angle[2],
1162 0, 0, 0,
1163 0, 0, 0,
1164 palRed (color + rnum) + 64, palGreen (color + rnum) + 64, palBlue (color + rnum) + 64,
1165 palRed (color + rnum2) + 64, palGreen (color + rnum2) + 64, palBlue (color + rnum2) + 64,
1166 0.5f + (crand () * 0.1f), -1.0f / (0.2f + (frand () * 0.1f)),
1167 5 + (crand () * 2), 25 + (crand () * 3),
1168 PT_WATERIMPACT, PF_SCALED,
1169 NULL, qFalse,
1170 PART_STYLE_ANGLED,
1171 0);
1172
1173 // Mist
1174 for (i=0 ; i<2 ; i++) {
1175 d = 1 + (frand () * 3);
1176 rnum = (rand () % 5);
1177 rnum2 = (rand () % 5);
1178
1179 CG_SpawnParticle (
1180 org[0] + (dir[0] * d), org[1] + (dir[1] * d), org[2] + (dir[2] * d),
1181 0, 0, 0,
1182 d * dir[0], d * dir[1], d * dir[2],
1183 0, 0, 100,
1184 palRed (color + rnum) + 64, palGreen (color + rnum) + 64, palBlue (color + rnum) + 64,
1185 palRed (color + rnum2) + 64, palGreen (color + rnum2) + 64, palBlue (color + rnum2) + 64,
1186 0.6f + (crand () * 0.1f), -1.0f / (0.4f + (frand () * 0.1f)),
1187 5 + (crand () * 5), 35 + (crand () * 5),
1188 glow ? PT_WATERMIST_GLOW : PT_WATERMIST,
1189 PF_SCALED|PF_GRAVITY|PF_NOCLOSECULL,
1190 0, qFalse,
1191 PART_STYLE_QUAD,
1192 frand () * 360);
1193 }
1194
1195 // Point-away plume
1196 d = 10 + crand ();
1197 rnum = (rand () % 5);
1198 rnum2 = (rand () % 5);
1199 CG_SpawnParticle (
1200 org[0] + (dir[0] * 7.5f), org[1] + (dir[1] * 7.5f), org[2] + (dir[2] * 7.5f),
1201 dir[0], dir[1], dir[2],
1202 0, 0, 0,
1203 0, 0, 0,
1204 palRed (color + rnum) + 64, palGreen (color + rnum) + 64, palBlue (color + rnum) + 64,
1205 palRed (color + rnum2) + 64, palGreen (color + rnum2) + 64, palBlue (color + rnum2) + 64,
1206 1.0f, -1.0f / (0.2f + (frand() * 0.2f)),
1207 9, 9,
1208 glow ? PT_WATERPLUME_GLOW : PT_WATERPLUME, 0,
1209 NULL, qFalse,
1210 PART_STYLE_DIRECTION,
1211 0);
1212
1213 // Flying droplets
1214 for (i=0 ; i<count*2 ; i++) {
1215 d = 34 + (frand () * 14);
1216 rnum = (rand () % 5);
1217 rnum2 = (rand () % 5);
1218
1219 dirVec[0] = dir[0] + crand ();
1220 dirVec[1] = dir[1] + crand ();
1221 dirVec[2] = dir[2] + crand ();
1222
1223 CG_SpawnParticle (
1224 org[0] + dir[0], org[1] + dir[1], org[2] + dir[2],
1225 0, 0, 0,
1226 dirVec[0] * (frand () * 74), dirVec[1] * (frand () * 74), dirVec[2] * (frand () * 74),
1227 0, 0, 50,
1228 palRed (color + rnum) + 64, palGreen (color + rnum) + 64, palBlue (color + rnum) + 64,
1229 palRed (color + rnum2) + 64, palGreen (color + rnum2) + 64, palBlue (color + rnum2) + 64,
1230 0.7f + (frand () * 0.3f), -1.0f / (0.5f + (frand () * 0.3f)),
1231 1.5f + crand (), 0.15 + (crand () * 0.125f),
1232 PT_WATERDROPLET, PF_GRAVITY|PF_AIRONLY|PF_NOCLOSECULL,
1233 pDropletThink, qTrue,
1234 PART_STYLE_QUAD,
1235 frand () * 360);
1236 }
1237 }
1238
1239 byte clrtbl[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
CG_SplashEffect(vec3_t org,vec3_t dir,int color,int count)1240 void __fastcall CG_SplashEffect (vec3_t org, vec3_t dir, int color, int count)
1241 {
1242 // this function merely decides what route to take
1243 switch (color) {
1244 case SPLASH_UNKNOWN:
1245 CG_RicochetEffect (org, dir, count);
1246 break;
1247 case SPLASH_SPARKS:
1248 CG_SparkEffect (org, dir, 12, 12, count, 1, 4);
1249 break;
1250 case SPLASH_BLUE_WATER:
1251 CG_SplashParticles (org, dir, 0x09, count, qFalse);
1252 break;
1253 case SPLASH_BROWN_WATER:
1254 CG_ParticleEffect (org, dir, clrtbl[color], count);
1255 break;
1256 case SPLASH_SLIME: // also gloom drone spit
1257 if (cg.currGameMod == GAME_MOD_GLOOM)
1258 CG_GloomDroneEffect (org, dir);
1259 else
1260 CG_SplashParticles (org, dir, clrtbl[color], count, qTrue);
1261 break;
1262 case SPLASH_LAVA:
1263 CG_SplashParticles (org, dir, clrtbl[color], count, qTrue);
1264 break;
1265 case SPLASH_BLOOD:
1266 CG_BleedEffect (org, dir, count);
1267 break;
1268 }
1269 }
1270
1271 /*
1272 =============================================================================
1273
1274 MISCELLANEOUS PARTICLE EFFECTS
1275
1276 =============================================================================
1277 */
1278
1279 /*
1280 ===============
1281 CG_BigTeleportParticles
1282 ===============
1283 */
CG_BigTeleportParticles(vec3_t org)1284 void CG_BigTeleportParticles (vec3_t org)
1285 {
1286 int i;
1287 float angle, dist;
1288
1289 for (i=0 ; i<4096 ; i++) {
1290 angle = (M_PI * 2.0f) * (rand () & 1023) / 1023.0f;
1291 dist = (float)(rand () & 31);
1292
1293 CG_SpawnParticle (
1294 org[0] + (float)cos (angle) * dist, org[1] + (float)sin (angle) * dist, org[2] + 8 + (frand () * 90),
1295 0, 0, 0,
1296 (float)cos (angle) * (70+(rand()&63)), (float)sin (angle) * (70+(rand()&63)), -100.0f + (rand () & 31),
1297 -(float)cos (angle) * 100, -(float)sin (angle) * 100, 160.0f,
1298 255, 255, 255,
1299 230, 230, 230,
1300 1.0f, -0.3f / (0.2f + (frand () * 0.3f)),
1301 10, 3,
1302 PT_FLAREGLOW, PF_SCALED|PF_NOCLOSECULL,
1303 0, qFalse,
1304 PART_STYLE_QUAD,
1305 0);
1306 }
1307 }
1308
1309
1310 /*
1311 ===============
1312 CG_BlasterTip
1313 ===============
1314 */
CG_BlasterTip(vec3_t start,vec3_t end)1315 void CG_BlasterTip (vec3_t start, vec3_t end)
1316 {
1317 int rnum, rnum2;
1318 vec3_t move, vec;
1319 float len, dec;
1320 int i;
1321
1322 // Bubbles
1323 CG_BubbleEffect (start);
1324
1325 // Smoke
1326 dec = 1 + (cg_particleSmokeLinger->floatVal * 0.2f);
1327 for (i=0 ; i<dec ; i++) {
1328 rnum = (rand () % 5);
1329 rnum2 = (rand () % 5);
1330
1331 CG_SpawnParticle (
1332 start[0] + (crand()*2), start[1] + (crand()*2), start[2] + (crand()*2),
1333 0, 0, 0,
1334 0, 0, 0,
1335 0, 0, 5 + (frand () * 25),
1336 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
1337 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
1338 0.9f + (frand() * 0.1f), -1.0f / (0.25f + (cg_particleSmokeLinger->floatVal * 0.01f) + (frand() * 0.1f)),
1339 5 + crand (), 16 + (crand () * 8),
1340 pRandGlowSmoke (), PF_ALPHACOLOR,
1341 NULL, qFalse,
1342 PART_STYLE_QUAD,
1343 frand () * 360);
1344 }
1345
1346 // Dot trail
1347 Vec3Copy (start, move);
1348 Vec3Subtract (start, end, vec);
1349 len = VectorNormalizeFastf (vec);
1350
1351 dec = 2.5f;
1352 Vec3Scale (vec, dec, vec);
1353
1354 for (; len>0 ; Vec3Add (move, vec, move)) {
1355 len -= dec;
1356
1357 rnum = (rand () % 5);
1358 rnum2 = (rand () % 5);
1359
1360 CG_SpawnParticle (
1361 move[0] + crand (), move[1] + crand (), move[2] + crand (),
1362 0, 0, 0,
1363 crand () * 2, crand () * 2, crand () * 2,
1364 crand () * 2, crand () * 2, crand () * 2,
1365 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
1366 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
1367 1.0f, -15,
1368 4 + (frand () * 4), 1.5f + (frand () * 2.5f),
1369 PT_BLASTER_RED, PF_NOCLOSECULL,
1370 0, qFalse,
1371 PART_STYLE_QUAD,
1372 0);
1373 }
1374 }
1375
1376
1377 /*
1378 ===============
1379 CG_ExplosionParticles
1380
1381 FIXME: does scale actually scale the effect?
1382 ===============
1383 */
CG_ExplosionParticles(vec3_t org,float scale,qBool exploOnly,qBool inWater)1384 void CG_ExplosionParticles (vec3_t org, float scale, qBool exploOnly, qBool inWater)
1385 {
1386 int i, j;
1387 float rnum, rnum2;
1388 float waterOffset;
1389 vec3_t normal, angle, endPos;
1390 float distScale;
1391
1392 CG_ExploRattle (org, scale);
1393
1394 // Sparks
1395 for (i=0 ; i<20 ; i++) {
1396 CG_SpawnParticle (
1397 org[0] + (crand () * 10 * scale), org[1] + (crand () * 10 * scale), org[2] + (crand () * 10 * scale),
1398 0, 0, 0,
1399 crand () * (140 * scale), crand () * (140 * scale), crand () * (140 * scale),
1400 0, 0, 0,
1401 235 + (frand () * 20), 225 + (frand () * 20), 205,
1402 235 + (frand () * 20), 225 + (frand () * 20), 205,
1403 0.9f, -1.5f / (0.6f + (crand () * 0.15f)),
1404 0.3f, 0.4f,
1405 PT_SPARK, 0,
1406 pSparkGrowThink, qTrue,
1407 PART_STYLE_DIRECTION,
1408 (16 + (crand () * 4)) * scale);
1409 }
1410
1411 if (inWater) {
1412 waterOffset = 155;
1413
1414 // Bubbles
1415 for (i=0 ; i<50*scale ; i++) {
1416 rnum = 230 + (frand () * 25);
1417 rnum2 = 230 + (frand () * 25);
1418 CG_SpawnParticle (
1419 org[0] + crand (), org[1] + crand (), org[2] + crand (),
1420 0, 0, 0,
1421 crand () * (164 * scale), crand () * (164 * scale), 10 + (crand () * (164 * scale)),
1422 0, 0, 0,
1423 rnum, rnum, rnum,
1424 rnum2, rnum2, rnum2,
1425 0.9f + (crand () * 0.1f), -1.0f / (1 + (frand () * 0.2f)),
1426 0.1f + frand (), 0.1f + frand (),
1427 PT_WATERBUBBLE, PF_SHADE|PF_LAVAONLY|PF_SLIMEONLY|PF_WATERONLY,
1428 0, qFalse,
1429 PART_STYLE_QUAD,
1430 0);
1431 }
1432 }
1433 else
1434 waterOffset = 0;
1435
1436 // Explosion anim
1437 CG_SpawnParticle (
1438 org[0], org[1], org[2],
1439 0, 0, 0,
1440 0, 0, 0,
1441 0, 0, 0,
1442 255 - waterOffset, 255 - waterOffset, 255,
1443 255 - waterOffset, 255 - waterOffset, 255,
1444 1.0f, -3 + (crand () * 0.1f) + (scale * 0.33f),
1445 (40 + (crand () * 5)) * scale, (130 + (crand () * 10)) * scale,
1446 PT_EXPLO1, PF_NOCLOSECULL,
1447 pExploAnimThink, qTrue,
1448 PART_STYLE_QUAD,
1449 crand () * 12);
1450
1451 // Explosion embers
1452 for (i=0 ; i<2 ; i++) {
1453 CG_SpawnParticle (
1454 org[0] + (crand () * 3), org[1] + (crand () * 3), org[2] + (crand () * 3),
1455 0, 0, 0,
1456 0, 0, 0,
1457 0, 0, 0,
1458 255 - waterOffset, 255 - waterOffset, 255,
1459 255 - waterOffset, 255 - waterOffset, 255,
1460 1.0f, -3.15f + (crand () * 0.1f) + (scale * 0.33f),
1461 (2 + crand ()) * scale, (155 + (crand () * 10)) * scale,
1462 i?PT_EXPLOEMBERS1:PT_EXPLOEMBERS2, PF_NOCLOSECULL,
1463 0, qFalse,
1464 PART_STYLE_QUAD,
1465 crand () * 360);
1466 }
1467
1468 if (exploOnly)
1469 return;
1470
1471 // Explosion flash
1472 CG_SpawnParticle (
1473 org[0], org[1], org[2],
1474 0, 0, 0,
1475 crand () * 20, crand () * 20, crand () * 20,
1476 0, 0, 0,
1477 255 - waterOffset, 255 - waterOffset, 255,
1478 255 - waterOffset, 255 - waterOffset, 255,
1479 1.0f, -4.5f + (crand () * 0.1f) + (scale * 0.33f),
1480 (2 + crand ()) * scale, (130 + (crand () * 10)) * scale,
1481 PT_EXPLOFLASH, PF_NOCLOSECULL,
1482 0, qFalse,
1483 PART_STYLE_QUAD,
1484 crand () * 360);
1485
1486 // Smoke
1487 j = scale + 2;
1488 for (i=0 ; i<j ; i++) {
1489 rnum = 70 + (frand () * 40);
1490 rnum2 = 80 + (frand () * 40);
1491 CG_SpawnParticle (
1492 org[0] + (crand () * 4), org[1] + (crand () * 4), org[2] + (crand () * 4),
1493 0, 0, 0,
1494 crand () * 2, crand () * 2, crand () * 2,
1495 0, 0, 3 + (frand () * 4),
1496 rnum, rnum, rnum,
1497 rnum2, rnum2, rnum2,
1498 0.75f + (crand () * 0.1f), -1.0f / (1.5f + (cg_particleSmokeLinger->floatVal * 0.4f) + (crand () * 0.2f)),
1499 (40 + (crand () * 5)) * scale, (100 + (crand () * 10)) * scale,
1500 pRandSmoke (), PF_SHADE,
1501 pSmokeThink, qTrue,
1502 PART_STYLE_QUAD,
1503 frand () * 361);
1504 }
1505
1506 // Explosion mark
1507 if (!CG_FindExplosionDir (org, 30 * scale, endPos, normal))
1508 return;
1509
1510 // Directional smoke
1511 j = scale + 3;
1512 for (i=1 ; i<j ; i++) {
1513 // Color randomization
1514 rnum = 70 + (frand () * 40);
1515 rnum2 = 80 + (frand () * 40);
1516
1517 distScale = (float)i/(float)j;
1518
1519 // Spawn particles
1520 CG_SpawnParticle (
1521 org[0] + (crand () * 4), org[1] + (crand () * 4), org[2] + (crand () * 4),
1522 0, 0, 0,
1523 normal[0] * 90 * distScale, normal[1] * 90 * distScale, normal[2] * 90 * distScale,
1524 normal[0] * -32 * distScale, normal[1] * -32 * distScale, (normal[2] * -32 * distScale) + 5 + (frand () * 6),
1525 rnum, rnum, rnum,
1526 rnum2, rnum2, rnum2,
1527 0.75f + (crand () * 0.1f), -1.0f / (1.5f + (cg_particleSmokeLinger->floatVal * 0.1f) + (crand () * 0.2f)),
1528 (30 + (crand () * 5)) * scale, (100 + (crand () * 10)) * scale,
1529 pRandSmoke (), PF_SHADE,
1530 pSmokeThink, qTrue,
1531 PART_STYLE_QUAD,
1532 frand () * 361);
1533 }
1534
1535 // Directional sparks
1536 for (i=0 ; i<25 ; i++) {
1537 CG_SpawnParticle (
1538 org[0] + (crand () * 10 * scale), org[1] + (crand () * 10 * scale), org[2] + (crand () * 10 * scale),
1539 0, 0, 0,
1540 (normal[0] + (crand () * 0.4f)) * 175,
1541 (normal[1] + (crand () * 0.4f)) * 175,
1542 (normal[2] + (crand () * 0.4f)) * 175,
1543 0, 0, 0,
1544 235 + (frand () * 20), 225 + (frand () * 20), 205,
1545 235 + (frand () * 20), 225 + (frand () * 20), 205,
1546 0.9f, -1.5f / (0.5f + (crand () * 0.15f)),
1547 0.3f, 0.4f,
1548 PT_SPARK, 0,
1549 pSparkGrowThink, qTrue,
1550 PART_STYLE_DIRECTION,
1551 (16 + (crand () * 4)) * scale);
1552 }
1553
1554 // Burn mark
1555 CG_SpawnDecal (
1556 endPos[0], endPos[1], endPos[2],
1557 normal[0], normal[1], normal[2],
1558 255, 255, 255,
1559 0, 0, 0,
1560 0.9f + (crand () * 0.1f), 0.8f,
1561 (35 + (frand () * 5)) * scale,
1562 dRandExploMark (), DF_ALPHACOLOR,
1563 0, qFalse,
1564 0, frand () * 360);
1565
1566 // Only do these for small effects
1567 if (scale <= 2.0f) {
1568 VecToAngleRolled (normal, 180, angle);
1569 rnum = Vec3DistFast (org, endPos);
1570 if (rnum < 50.0f) {
1571 // Wave
1572 CG_SpawnParticle (
1573 endPos[0] + normal[0], endPos[1] + normal[0], endPos[2] + normal[0],
1574 angle[0], angle[1], angle[2],
1575 0, 0, 0,
1576 0, 0, 0,
1577 255 - waterOffset, 155 - waterOffset, waterOffset,
1578 255 - waterOffset, 155 - waterOffset, waterOffset,
1579 0.7f + (crand () * 0.1f), -1.0f / (0.1f + (frand () * 0.05f)),
1580 5 + (crand () * 2), (60 + (crand () * 5)) * scale,
1581 PT_EXPLOWAVE, PF_SCALED,
1582 NULL, qFalse,
1583 PART_STYLE_ANGLED,
1584 0);
1585 }
1586
1587 // Smoke
1588 for (j=0 ; j<1.25f + (cg_particleSmokeLinger->floatVal * 0.05f) ; j++) {
1589 rnum = 60 + (frand () * 50);
1590 rnum2 = 70 + (frand () * 50);
1591 CG_SpawnParticle (
1592 endPos[0] + normal[0], endPos[1] + normal[0], endPos[2] + normal[0],
1593 angle[0], angle[1], angle[2],
1594 0, 0, 0,
1595 0, 0, 0,
1596 rnum, rnum, rnum,
1597 rnum2, rnum2, rnum2,
1598 0.6f + (crand () * 0.1f), -1.0f / (1.65f + (cg_particleSmokeLinger->floatVal * 0.5f) + (crand () * 0.2f)),
1599 (60 + (crand () * 5)) * scale, (80 + (crand () * 10)) * scale,
1600 pRandSmoke (), PF_SHADE,
1601 pSmokeThink, qTrue,
1602 PART_STYLE_ANGLED,
1603 frand () * 361);
1604 }
1605 }
1606 }
1607
1608
1609 /*
1610 ===============
1611 CG_ExplosionBFGParticles
1612 ===============
1613 */
CG_ExplosionBFGParticles(vec3_t org)1614 void CG_ExplosionBFGParticles (vec3_t org)
1615 {
1616 int i;
1617 cgDecal_t *d;
1618 float mult;
1619 float rnum, rnum2;
1620 vec3_t endPos, dir;
1621
1622 // Smoke
1623 for (i=0 ; i<8 ; i++) {
1624 rnum = 70 + (frand () * 40);
1625 rnum2 = 80 + (frand () * 40);
1626 CG_SpawnParticle (
1627 org[0] + (crand () * 4), org[1] + (crand () * 4), org[2] + (crand () * 4),
1628 0, 0, 0,
1629 crand () * 2, crand () * 2, crand () * 2,
1630 0, 0, 5 + (frand () * 6),
1631 rnum, 80 + rnum, rnum,
1632 rnum2, 100+ rnum2, rnum2,
1633 0.75f + (crand () * 0.1f), -1.0f / (0.25f + (cg_particleSmokeLinger->floatVal * 0.1f) + (crand () * 0.1f)),
1634 35 + (crand () * 15), 140 + (crand () * 30),
1635 pRandGlowSmoke (), 0,
1636 pSmokeThink, qTrue,
1637 PART_STYLE_QUAD,
1638 frand () * 361);
1639 }
1640
1641 // Dots
1642 mult = (cg.currGameMod == GAME_MOD_GLOOM) ? 0.18f : 2.5f;
1643 for (i=0 ; i<196 ; i++) {
1644 rnum = (rand () % 2) ? 150 + (frand () * 25) : 0;
1645 CG_SpawnParticle (
1646 org[0] + (crand () * 16), org[1] + (crand () * 16), org[2] + (crand () * 16),
1647 0, 0, 0,
1648 (crand () * 192) * mult, (crand () * 192) * mult, (crand () * 192) * mult,
1649 0, 0, -40,
1650 rnum, rnum + 75 + (frand () * 150), rnum + (frand () * 50),
1651 rnum, rnum + 75 + (frand () * 150), rnum + (frand () * 50),
1652 1.0f, -0.8f / (0.8f + (frand () * 0.3f)),
1653 11 + (crand () * 10.5f), 0.1f + (frand () * 0.5f),
1654 PT_BFG_DOT, PF_SCALED|PF_GRAVITY|PF_NOCLOSECULL,
1655 pBounceThink, qTrue,
1656 PART_STYLE_QUAD,
1657 0);
1658 }
1659
1660 // Decal
1661 if (!CG_FindExplosionDir (org, 40, endPos, dir))
1662 return;
1663
1664 // Burn mark
1665 d = CG_SpawnDecal (
1666 endPos[0], endPos[1], endPos[2],
1667 dir[0], dir[1], dir[2],
1668 255, 255, 255,
1669 0, 0, 0,
1670 0.9f + (crand () * 0.1f), 0.8f,
1671 40 + (crand () * 3) - 8,
1672 DT_BFG_BURNMARK, DF_ALPHACOLOR,
1673 NULL, qFalse,
1674 0, frand () * 360);
1675
1676 // Glow mark
1677 d = CG_SpawnDecal (
1678 endPos[0], endPos[1], endPos[2],
1679 dir[0], dir[1], dir[2],
1680 255, 255, 255,
1681 0, 0, 0,
1682 1.0f, 0,
1683 40 + (crand () * 3) - 8,
1684 DT_BFG_GLOWMARK, DF_USE_BURNLIFE|DF_ALPHACOLOR,
1685 NULL, qFalse,
1686 0, frand () * 360);
1687 }
1688
1689
1690 /*
1691 ===============
1692 CG_ExplosionColorParticles
1693 ===============
1694 */
CG_ExplosionColorParticles(vec3_t org)1695 void CG_ExplosionColorParticles (vec3_t org)
1696 {
1697 int i;
1698
1699 for (i=0 ; i<128 ; i++) {
1700 CG_SpawnParticle (
1701 org[0] + (crand () * 16), org[1] + (crand () * 16), org[2] + (crand () * 16),
1702 0, 0, 0,
1703 crand () * 128, crand () * 128, crand () * 128,
1704 0, 0, -40,
1705 0 + crand (), 0 + crand (), 0 + crand (),
1706 0 + crand (), 0 + crand (), 0 + crand (),
1707 1.0f, -0.4f / (0.6f + (frand () * 0.2f)),
1708 1.0f, 1.0f,
1709 PT_GENERIC, PF_SCALED|PF_NOCLOSECULL,
1710 0, qFalse,
1711 PART_STYLE_QUAD,
1712 0);
1713 }
1714 }
1715
1716
1717 /*
1718 ===============
1719 CG_FlyEffect
1720 ===============
1721 */
CG_FlyParticles(vec3_t origin,int count)1722 void CG_FlyParticles (vec3_t origin, int count)
1723 {
1724 int i;
1725 float angle;
1726 float sr, sp, sy, cr, cp, cy;
1727 vec3_t forward;
1728 float dist = 64;
1729 float ltime;
1730
1731 if (count > NUMVERTEXNORMALS)
1732 count = NUMVERTEXNORMALS;
1733
1734 ltime = (float)cg.realTime / 1000.0f;
1735 for (i=0 ; i<count ; i+=2) {
1736 angle = ltime * cg_randVels[i][0];
1737 sy = (float)sin (angle);
1738 cy = (float)cos (angle);
1739 angle = ltime * cg_randVels[i][1];
1740 sp = (float)sin (angle);
1741 cp = (float)cos (angle);
1742 angle = ltime * cg_randVels[i][2];
1743 sr = (float)sin (angle);
1744 cr = (float)cos (angle);
1745
1746 forward[0] = cp*cy;
1747 forward[1] = cp*sy;
1748 forward[2] = -sp;
1749
1750 dist = (float)sin (ltime + i) * 64;
1751
1752 CG_SpawnParticle (
1753 origin[0] + (m_byteDirs[i][0] * dist) + (forward[0] * BEAMLENGTH),
1754 origin[1] + (m_byteDirs[i][1] * dist) + (forward[1] * BEAMLENGTH),
1755 origin[2] + (m_byteDirs[i][2] * dist) + (forward[2] * BEAMLENGTH),
1756 0, 0, 0,
1757 0, 0, 0,
1758 0, 0, 0,
1759 0, 0, 0,
1760 0, 0, 0,
1761 1, -100,
1762 1.5f, 1.5f,
1763 PT_FLY, PF_NOCLOSECULL,
1764 0, qFalse,
1765 PART_STYLE_QUAD,
1766 0);
1767 }
1768 }
1769
CG_FlyEffect(cgEntity_t * ent,vec3_t origin)1770 void CG_FlyEffect (cgEntity_t *ent, vec3_t origin)
1771 {
1772 int n;
1773 float count;
1774 int starttime;
1775
1776 if (ent->flyStopTime < cg.realTime) {
1777 starttime = cg.realTime;
1778 ent->flyStopTime = cg.realTime + 60000;
1779 }
1780 else
1781 starttime = ent->flyStopTime - 60000;
1782
1783 n = cg.realTime - starttime;
1784 if (n < 20000)
1785 count = n * 162 / 20000.0f;
1786 else {
1787 n = ent->flyStopTime - cg.realTime;
1788 if (n < 20000)
1789 count = n * 162 / 20000.0f;
1790 else
1791 count = 162;
1792 }
1793
1794 CG_FlyParticles (origin, count*2);
1795 }
1796
1797
1798 /*
1799 ===============
1800 CG_ForceWall
1801 ===============
1802 */
CG_ForceWall(vec3_t start,vec3_t end,int color)1803 void CG_ForceWall (vec3_t start, vec3_t end, int color)
1804 {
1805 vec3_t move, vec;
1806 float len, dec;
1807
1808 Vec3Copy (start, move);
1809 Vec3Subtract (end, start, vec);
1810 len = VectorNormalizeFastf (vec);
1811
1812 dec = 4;
1813 Vec3Scale (vec, dec, vec);
1814
1815 for (; len>0 ; Vec3Add (move, vec, move)) {
1816 len -= dec;
1817
1818 if (frand () > 0.3) {
1819 CG_SpawnParticle (
1820 move[0] + (crand () * 3), move[1] + (crand () * 3), move[2] + (crand () * 3),
1821 0, 0, 0,
1822 0, 0, -40 - (crand () * 10),
1823 0, 0, 0,
1824 palRed (color), palGreen (color), palBlue (color),
1825 palRed (color), palGreen (color), palBlue (color),
1826 1.0f, -1.0f / (3.0f + (frand () * 0.5f)),
1827 1.0f, 1.0f,
1828 PT_GENERIC, PF_SCALED,
1829 0, qFalse,
1830 PART_STYLE_QUAD,
1831 0);
1832 }
1833 }
1834 }
1835
1836
1837 /*
1838 ===============
1839 CG_MonsterPlasma_Shell
1840 ===============
1841 */
CG_MonsterPlasma_Shell(vec3_t origin)1842 void CG_MonsterPlasma_Shell (vec3_t origin)
1843 {
1844 vec3_t dir, porg;
1845 int i, rnum, rnum2;
1846
1847 for (i=0 ; i<40 ; i++) {
1848 Vec3Set (dir, crand (), crand (), crand ());
1849 VectorNormalizeFastf (dir);
1850 Vec3MA (origin, 10, dir, porg);
1851
1852 rnum = (rand () % 5);
1853 rnum2 = (rand () % 5);
1854 CG_SpawnParticle (
1855 porg[0], porg[1], porg[2],
1856 0, 0, 0,
1857 0, 0, 0,
1858 0, 0, 0,
1859 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
1860 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
1861 1.0, PART_INSTANT,
1862 1.0, 1.0,
1863 PT_GENERIC, PF_SCALED,
1864 0, qFalse,
1865 PART_STYLE_QUAD,
1866 0);
1867 }
1868 }
1869
1870
1871 /*
1872 ===============
1873 CG_PhalanxTip
1874 ===============
1875 */
CG_PhalanxTip(vec3_t start,vec3_t end)1876 void CG_PhalanxTip (vec3_t start, vec3_t end)
1877 {
1878 int i, j, k;
1879 int rnum, rnum2;
1880 vec3_t move, vec, dir;
1881 float len, dec, vel;
1882
1883 // Bubbles
1884 CG_BubbleEffect (start);
1885
1886 // Smoke
1887 dec = 1 + (cg_particleSmokeLinger->floatVal * 0.2f);
1888 for (i=0 ; i<dec ; i++) {
1889 rnum = (rand () % 5);
1890 rnum2 = (rand () % 5);
1891
1892 CG_SpawnParticle (
1893 start[0] + (crand()*2), start[1] + (crand()*2), start[2] + (crand()*2),
1894 0, 0, 0,
1895 0, 0, 0,
1896 0, 0, 5 + (frand () * 25),
1897 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
1898 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
1899 0.9f + (frand() * 0.1f), -1.0f / (0.25f + (cg_particleSmokeLinger->floatVal * 0.01f) + (frand() * 0.1f)),
1900 5 + crand (), 16 + (crand () * 8),
1901 pRandGlowSmoke (), PF_ALPHACOLOR,
1902 NULL, qFalse,
1903 PART_STYLE_QUAD,
1904 frand () * 360);
1905 }
1906
1907 // Trail
1908 Vec3Copy (start, move);
1909 Vec3Subtract (start, end, vec);
1910 len = VectorNormalizeFastf (vec);
1911
1912 dec = 2.5f;
1913 Vec3Scale (vec, dec, vec);
1914
1915 for (; len>0 ; Vec3Add (move, vec, move)) {
1916 len -= dec;
1917
1918 rnum = (rand () % 5);
1919 rnum2 = (rand () % 5);
1920
1921 CG_SpawnParticle (
1922 move[0] + crand (), move[1] + crand (), move[2] + crand (),
1923 0, 0, 0,
1924 crand () * 2, crand () * 2, crand () * 2,
1925 crand () * 2, crand () * 2, crand () * 2,
1926 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
1927 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
1928 1.0, -15,
1929 5 + (frand () * 4), 3 + (frand () * 2.5f),
1930 PT_PHALANXTIP, 0,
1931 0, qFalse,
1932 PART_STYLE_QUAD,
1933 0);
1934 }
1935
1936 for (i=-2 ; i<=2 ; i+=4) {
1937 for (j=-2 ; j<=2 ; j+=4) {
1938 for (k=-2 ; k<=4 ; k+=4) {
1939 Vec3Set (dir, (float)(j * 4), (float)(i * 4), (float)(k * 4));
1940 VectorNormalizeFastf (dir);
1941 vel = 10.0f + rand () % 11;
1942
1943 rnum = (rand () % 5);
1944 rnum2 = (rand () % 5);
1945 CG_SpawnParticle (
1946 start[0] + i + ((rand () % 6) * crand ()),
1947 start[1] + j + ((rand () % 6) * crand ()),
1948 start[2] + k + ((rand () % 6) * crand ()),
1949 0, 0, 0,
1950 dir[0] * vel, dir[1] * vel, dir[2] * vel,
1951 0, 0, -40,
1952 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
1953 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
1954 0.9f, -3.5f,
1955 2 + (frand () * 0.5f), 0.5f + (frand () * 0.5f),
1956 PT_GENERIC, PF_NOCLOSECULL,
1957 0, qFalse,
1958 PART_STYLE_QUAD,
1959 0);
1960 }
1961 }
1962 }
1963 }
1964
1965
1966 /*
1967 ===============
1968 CG_TeleportParticles
1969 ===============
1970 */
CG_TeleportParticles(vec3_t org)1971 void CG_TeleportParticles (vec3_t org)
1972 {
1973 int i;
1974
1975 for (i=0 ; i<300 ; i++) {
1976 CG_SpawnParticle (
1977 org[0] + (crand () * 32), org[1] + (crand () * 32), org[2] + (frand () * 85 - 25),
1978 0, 0, 0,
1979 crand () * 50, crand () * 50, crand () * 50,
1980 crand () * 50, crand () * 50, 50 + (crand () * 20),
1981 220, 190, 150,
1982 255, 255, 230,
1983 0.9f + (frand () * 0.25f), -0.3f / (0.1f + (frand () * 0.1f)),
1984 10 + (frand () * 0.25f), 0.5f + (frand () * 0.25f),
1985 PT_FLAREGLOW, PF_SCALED|PF_GRAVITY|PF_NOCLOSECULL,
1986 pBounceThink, qTrue,
1987 PART_STYLE_QUAD,
1988 0);
1989 }
1990 }
1991
1992
1993 /*
1994 ===============
1995 CG_TeleporterParticles
1996 ===============
1997 */
CG_TeleporterParticles(entityState_t * ent)1998 void CG_TeleporterParticles (entityState_t *ent)
1999 {
2000 int i;
2001
2002 for (i=0 ; i<2 ; i++) {
2003 CG_SpawnParticle (
2004 ent->origin[0] + (crand () * 16), ent->origin[1] + (crand () * 16), ent->origin[2] + (crand () * 8) - 3,
2005 0, 0, 0,
2006 crand () * 15, crand () * 15, 80 + (frand () * 5),
2007 0, 0, -40,
2008 210 + (crand () * 5), 180 + (crand () * 5), 120 + (crand () * 5),
2009 255 + (crand () * 5), 210 + (crand () * 5), 140 + (crand () * 5),
2010 1.0f, -0.6f + (crand () * 0.1f),
2011 2 + (frand () * 0.5f), 1 + (crand () * 0.5f),
2012 PT_GENERIC_GLOW, PF_SCALED|PF_NOCLOSECULL,
2013 0, qFalse,
2014 PART_STYLE_QUAD,
2015 0);
2016 }
2017 }
2018
2019
2020 /*
2021 ===============
2022 CG_TrackerShell
2023 ===============
2024 */
CG_TrackerShell(vec3_t origin)2025 void CG_TrackerShell (vec3_t origin)
2026 {
2027 vec3_t dir, porg;
2028 int i;
2029
2030 for (i=0 ; i<300 ; i++) {
2031 Vec3Set (dir, crand (), crand (), crand ());
2032 VectorNormalizeFastf (dir);
2033 Vec3MA (origin, 40, dir, porg);
2034
2035 CG_SpawnParticle (
2036 porg[0], porg[1], porg[2],
2037 0, 0, 0,
2038 0, 0, 0,
2039 0, 0, 0,
2040 0, 0, 0,
2041 0, 0, 0,
2042 1.0, PART_INSTANT,
2043 1.0f, 1.0f,
2044 PT_GENERIC, PF_SCALED,
2045 0, qFalse,
2046 PART_STYLE_QUAD,
2047 0);
2048 }
2049 }
2050
2051
2052 /*
2053 ===============
2054 CG_TrapParticles
2055 ===============
2056 */
CG_TrapParticles(refEntity_t * ent)2057 void CG_TrapParticles (refEntity_t *ent)
2058 {
2059 vec3_t move, vec, start, end, dir, org;
2060 int i, j, k, rnum, rnum2;
2061 float len, vel, dec;
2062
2063 ent->origin[2] -= 16;
2064 Vec3Copy (ent->origin, start);
2065 Vec3Copy (ent->origin, end);
2066 end[2] += 10;
2067
2068 Vec3Copy (start, move);
2069 Vec3Subtract (end, start, vec);
2070 len = VectorNormalizeFastf (vec);
2071
2072 dec = 5;
2073 Vec3Scale (vec, dec, vec);
2074
2075 for (; len>0 ; Vec3Add (move, vec, move)) {
2076 len -= dec;
2077
2078 rnum = (rand () % 5);
2079 rnum2 = (rand () % 5);
2080 CG_SpawnParticle (
2081 move[0] + (crand () * 2), move[1] + (crand () * 1.5f), move[2] + (crand () * 1.5f),
2082 0, 0, 0,
2083 crand () * 20, crand () * 20, crand () * 20,
2084 0, 0, 40,
2085 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
2086 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
2087 1.0f, -1.0f / (0.45f + (frand () * 0.2f)),
2088 5.0f, 1.0f,
2089 PT_GENERIC, PF_SCALED,
2090 0, qFalse,
2091 PART_STYLE_QUAD,
2092 0);
2093 }
2094
2095 ent->origin[2]+=14;
2096 Vec3Copy (ent->origin, org);
2097
2098 for (i=-2 ; i<=2 ; i+=4)
2099 for (j=-2 ; j<=2 ; j+=4)
2100 for (k=-2 ; k<=4 ; k+=4) {
2101 dir[0] = (float)(j * 8);
2102 dir[1] = (float)(i * 8);
2103 dir[2] = (float)(k * 8);
2104
2105 VectorNormalizeFastf (dir);
2106 vel = 50 + (float)(rand () & 63);
2107
2108 rnum = (rand () % 5);
2109 rnum2 = (rand () % 5);
2110 CG_SpawnParticle (
2111 org[0] + i + ((rand () & 23) * crand ()),
2112 org[1] + j + ((rand () & 23) * crand ()),
2113 org[2] + k + ((rand () & 23) * crand ()),
2114 0, 0, 0,
2115 dir[0] * vel, dir[1] * vel, dir[2] * vel,
2116 0, 0, -40,
2117 palRed (0xe0 + rnum), palGreen (0xe0 + rnum), palBlue (0xe0 + rnum),
2118 palRed (0xe0 + rnum2), palGreen (0xe0 + rnum2), palBlue (0xe0 + rnum2),
2119 1.0f, -1.0f / (0.3f + (frand () * 0.15f)),
2120 2.0f, 1.0f,
2121 PT_GENERIC, PF_SCALED,
2122 0, qFalse,
2123 PART_STYLE_QUAD,
2124 0);
2125 }
2126 }
2127
2128
2129 /*
2130 ===============
2131 CG_WidowSplash
2132 ===============
2133 */
CG_WidowSplash(vec3_t org)2134 void CG_WidowSplash (vec3_t org)
2135 {
2136 int clrtable[4] = {2*8, 13*8, 21*8, 18*8};
2137 int i, rnum, rnum2;
2138 vec3_t dir, porg, pvel;
2139
2140 for (i=0 ; i<256 ; i++) {
2141 Vec3Set (dir, crand (), crand (), crand ());
2142 VectorNormalizeFastf (dir);
2143 Vec3MA (org, 45.0f, dir, porg);
2144 Vec3MA (vec3Origin, 40.0f, dir, pvel);
2145
2146 rnum = (rand () % 4);
2147 rnum2 = (rand () % 4);
2148 CG_SpawnParticle (
2149 porg[0], porg[1], porg[2],
2150 0, 0, 0,
2151 pvel[0], pvel[1], pvel[2],
2152 0, 0, 0,
2153 palRed (clrtable[rnum]), palGreen (clrtable[rnum]), palBlue (clrtable[rnum]),
2154 palRed (clrtable[rnum2]), palGreen (clrtable[rnum2]), palBlue (clrtable[rnum2]),
2155 1.0f, -0.8f / (0.5f + (frand () * 0.3f)),
2156 1.0f, 1.0f,
2157 PT_GENERIC, PF_SCALED,
2158 0, qFalse,
2159 PART_STYLE_QUAD,
2160 0);
2161 }
2162 }
2163