File: client\cl_fx.c
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 #include "client.h"
23
24 void CL_LogoutEffect (vec3_t org, int type);
25 void CL_ItemRespawnParticles (vec3_t org);
26
27 static vec3_t avelocities [NUMVERTEXNORMALS];
28
29 extern struct model_s *cl_mod_smoke;
30 extern struct model_s *cl_mod_flash;
31
32 /*
33 ==============================================================
34
35 LIGHT STYLE MANAGEMENT
36
37 ==============================================================
38 */
39
40 typedef struct
41 {
42 int length;
43 float value[3];
44 float map[MAX_QPATH];
45 } clightstyle_t;
46
47 clightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
48 int lastofs;
49
50 /*
51 ================
52 CL_ClearLightStyles
53 ================
54 */
55 void CL_ClearLightStyles (void)
56 {
57 memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
58 lastofs = -1;
59 }
60
61 /*
62 ================
63 CL_RunLightStyles
64 ================
65 */
66 void CL_RunLightStyles (void)
67 {
68 int ofs;
69 int i;
70 clightstyle_t *ls;
71
72 ofs = cl.time / 100;
73 if (ofs == lastofs)
74 return;
75 lastofs = ofs;
76
77 for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
78 {
79 if (!ls->length)
80 {
81 ls->value[0] = ls->value[1] = ls->value[2] = 1.0;
82 continue;
83 }
84 if (ls->length == 1)
85 ls->value[0] = ls->value[1] = ls->value[2] = ls->map[0];
86 else
87 ls->value[0] = ls->value[1] = ls->value[2] = ls->map[ofs%ls->length];
88 }
89 }
90
91
92 void CL_SetLightstyle (int i)
93 {
94 char *s;
95 int j, k;
96
97 s = cl.configstrings[i+CS_LIGHTS];
98
99 j = strlen (s);
100 if (j >= MAX_QPATH)
101 Com_Error (ERR_DROP, "svc_lightstyle length=%i", j);
102
103 cl_lightstyle[i].length = j;
104
105 for (k=0 ; k<j ; k++)
106 cl_lightstyle[i].map[k] = (float)(s[k]-'a')/(float)('m'-'a');
107 }
108
109 /*
110 ================
111 CL_AddLightStyles
112 ================
113 */
114 void CL_AddLightStyles (void)
115 {
116 int i;
117 clightstyle_t *ls;
118
119 for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
120 V_AddLightStyle (i, ls->value[0], ls->value[1], ls->value[2]);
121 }
122
123 /*
124 ==============================================================
125
126 DLIGHT MANAGEMENT
127
128 ==============================================================
129 */
130
131 cdlight_t cl_dlights[MAX_DLIGHTS];
132
133 /*
134 ================
135 CL_ClearDlights
136 ================
137 */
138 void CL_ClearDlights (void)
139 {
140 memset (cl_dlights, 0, sizeof(cl_dlights));
141 }
142
143 /*
144 ===============
145 CL_AllocDlight
146
147 ===============
148 */
149 cdlight_t *CL_AllocDlight (int key)
150 {
151 int i;
152 cdlight_t *dl;
153
154 // first look for an exact key match
155 if (key)
156 {
157 dl = cl_dlights;
158 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
159 {
160 if (dl->key == key)
161 {
162 memset (dl, 0, sizeof(*dl));
163 dl->key = key;
164 return dl;
165 }
166 }
167 }
168
169 // then look for anything else
170 dl = cl_dlights;
171 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
172 {
173 if (dl->die < cl.time)
174 {
175 memset (dl, 0, sizeof(*dl));
176 dl->key = key;
177 return dl;
178 }
179 }
180
181 dl = &cl_dlights[0];
182 memset (dl, 0, sizeof(*dl));
183 dl->key = key;
184 return dl;
185 }
186
187 /*
188 ===============
189 CL_NewDlight
190 ===============
191 */
192 void CL_NewDlight (int key, float x, float y, float z, float radius, float time)
193 {
194 cdlight_t *dl;
195
196 dl = CL_AllocDlight (key);
197 dl->origin[0] = x;
198 dl->origin[1] = y;
199 dl->origin[2] = z;
200 dl->radius = radius;
201 dl->die = cl.time + time;
202 }
203
204
205 /*
206 ===============
207 CL_RunDLights
208
209 ===============
210 */
211 void CL_RunDLights (void)
212 {
213 int i;
214 cdlight_t *dl;
215
216 dl = cl_dlights;
217 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
218 {
219 if (!dl->radius)
220 continue;
221
222 if (dl->die < cl.time)
223 {
224 dl->radius = 0;
225 return;
226 }
227 dl->radius -= cls.frametime*dl->decay;
228 if (dl->radius < 0)
229 dl->radius = 0;
230 }
231 }
232
233 /*
234 ==============
235 CL_ParseMuzzleFlash
236 ==============
237 */
238 void CL_ParseMuzzleFlash (void)
239 {
240 vec3_t fv, rv;
241 cdlight_t *dl;
242 int i, weapon;
243 centity_t *pl;
244 int silenced;
245 float volume;
246 char soundname[64];
247
248 i = MSG_ReadShort (&net_message);
249 if (i < 1 || i >= MAX_EDICTS)
250 Com_Error (ERR_DROP, "CL_ParseMuzzleFlash: bad entity");
251
252 weapon = MSG_ReadByte (&net_message);
253 silenced = weapon & MZ_SILENCED;
254 weapon &= ~MZ_SILENCED;
255
256 pl = &cl_entities[i];
257
258 dl = CL_AllocDlight (i);
259 VectorCopy (pl->current.origin, dl->origin);
260 AngleVectors (pl->current.angles, fv, rv, NULL);
261 VectorMA (dl->origin, 18, fv, dl->origin);
262 VectorMA (dl->origin, 16, rv, dl->origin);
263 if (silenced)
264 dl->radius = 100 + (rand()&31);
265 else
266 dl->radius = 200 + (rand()&31);
267 dl->minlight = 32;
268 dl->die = cl.time; // + 0.1;
269
270 if (silenced)
271 volume = 0.2;
272 else
273 volume = 1;
274
275 switch (weapon)
276 {
277 case MZ_BLASTER:
278 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
279 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
280 break;
281 case MZ_BLUEHYPERBLASTER:
282 dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
283 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
284 break;
285 case MZ_HYPERBLASTER:
286 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
287 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
288 break;
289 case MZ_MACHINEGUN:
290 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
291 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
292 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
293 break;
294 case MZ_SHOTGUN:
295 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
296 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
297 S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
298 break;
299 case MZ_SSHOTGUN:
300 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
301 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
302 break;
303 case MZ_CHAINGUN1:
304 dl->radius = 200 + (rand()&31);
305 dl->color[0] = 1;dl->color[1] = 0.25;dl->color[2] = 0;
306 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
307 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
308 break;
309 case MZ_CHAINGUN2:
310 dl->radius = 225 + (rand()&31);
311 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
312 dl->die = cl.time + 0.1; // long delay
313 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
314 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
315 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
316 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
317 break;
318 case MZ_CHAINGUN3:
319 dl->radius = 250 + (rand()&31);
320 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
321 dl->die = cl.time + 0.1; // long delay
322 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
323 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
324 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
325 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
326 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
327 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
328 break;
329 case MZ_RAILGUN:
330 dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
331 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
332 break;
333 case MZ_ROCKET:
334 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
335 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
336 S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
337 break;
338 case MZ_GRENADE:
339 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
340 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
341 S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
342 break;
343 case MZ_BFG:
344 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
345 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
346 break;
347
348 case MZ_LOGIN:
349 dl->color[0] = 0;dl->color[1] = 1; dl->color[2] = 0;
350 dl->die = cl.time + 1.0;
351 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
352 CL_LogoutEffect (pl->current.origin, weapon);
353 break;
354 case MZ_LOGOUT:
355 dl->color[0] = 1;dl->color[1] = 0; dl->color[2] = 0;
356 dl->die = cl.time + 1.0;
357 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
358 CL_LogoutEffect (pl->current.origin, weapon);
359 break;
360 case MZ_RESPAWN:
361 dl->color[0] = 1;dl->color[1] = 1; dl->color[2] = 0;
362 dl->die = cl.time + 1.0;
363 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
364 CL_LogoutEffect (pl->current.origin, weapon);
365 break;
366 // RAFAEL
367 case MZ_PHALANX:
368 dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
369 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/plasshot.wav"), volume, ATTN_NORM, 0);
370 break;
371 // RAFAEL
372 case MZ_IONRIPPER:
373 dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
374 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0);
375 break;
376
377 // ======================
378 // PGM
379 case MZ_ETF_RIFLE:
380 dl->color[0] = 0.9;dl->color[1] = 0.7;dl->color[2] = 0;
381 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/nail1.wav"), volume, ATTN_NORM, 0);
382 break;
383 case MZ_SHOTGUN2:
384 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
385 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0);
386 break;
387 case MZ_HEATBEAM:
388 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
389 dl->die = cl.time + 100;
390 // S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__l1a.wav"), volume, ATTN_NORM, 0);
391 break;
392 case MZ_BLASTER2:
393 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
394 // FIXME - different sound for blaster2 ??
395 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
396 break;
397 case MZ_TRACKER:
398 // negative flashes handled the same in gl/soft until CL_AddDLights
399 dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1;
400 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), volume, ATTN_NORM, 0);
401 break;
402 case MZ_NUKE1:
403 dl->color[0] = 1;dl->color[1] = 0;dl->color[2] = 0;
404 dl->die = cl.time + 100;
405 break;
406 case MZ_NUKE2:
407 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
408 dl->die = cl.time + 100;
409 break;
410 case MZ_NUKE4:
411 dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
412 dl->die = cl.time + 100;
413 break;
414 case MZ_NUKE8:
415 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 1;
416 dl->die = cl.time + 100;
417 break;
418 // PGM
419 // ======================
420 }
421 }
422
423
424 /*
425 ==============
426 CL_ParseMuzzleFlash2
427 ==============
428 */
429 void CL_ParseMuzzleFlash2 (void)
430 {
431 int ent;
432 vec3_t origin;
433 int flash_number;
434 cdlight_t *dl;
435 vec3_t forward, right;
436 char soundname[64];
437
438 ent = MSG_ReadShort (&net_message);
439 if (ent < 1 || ent >= MAX_EDICTS)
440 Com_Error (ERR_DROP, "CL_ParseMuzzleFlash2: bad entity");
441
442 flash_number = MSG_ReadByte (&net_message);
443
444 // locate the origin
445 AngleVectors (cl_entities[ent].current.angles, forward, right, NULL);
446 origin[0] = cl_entities[ent].current.origin[0] + forward[0] * monster_flash_offset[flash_number][0] + right[0] * monster_flash_offset[flash_number][1];
447 origin[1] = cl_entities[ent].current.origin[1] + forward[1] * monster_flash_offset[flash_number][0] + right[1] * monster_flash_offset[flash_number][1];
448 origin[2] = cl_entities[ent].current.origin[2] + forward[2] * monster_flash_offset[flash_number][0] + right[2] * monster_flash_offset[flash_number][1] + monster_flash_offset[flash_number][2];
449
450 dl = CL_AllocDlight (ent);
451 VectorCopy (origin, dl->origin);
452 dl->radius = 200 + (rand()&31);
453 dl->minlight = 32;
454 dl->die = cl.time; // + 0.1;
455
456 switch (flash_number)
457 {
458 case MZ2_INFANTRY_MACHINEGUN_1:
459 case MZ2_INFANTRY_MACHINEGUN_2:
460 case MZ2_INFANTRY_MACHINEGUN_3:
461 case MZ2_INFANTRY_MACHINEGUN_4:
462 case MZ2_INFANTRY_MACHINEGUN_5:
463 case MZ2_INFANTRY_MACHINEGUN_6:
464 case MZ2_INFANTRY_MACHINEGUN_7:
465 case MZ2_INFANTRY_MACHINEGUN_8:
466 case MZ2_INFANTRY_MACHINEGUN_9:
467 case MZ2_INFANTRY_MACHINEGUN_10:
468 case MZ2_INFANTRY_MACHINEGUN_11:
469 case MZ2_INFANTRY_MACHINEGUN_12:
470 case MZ2_INFANTRY_MACHINEGUN_13:
471 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
472 CL_ParticleEffect (origin, vec3_origin, 0, 40);
473 CL_SmokeAndFlash(origin);
474 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
475 break;
476
477 case MZ2_SOLDIER_MACHINEGUN_1:
478 case MZ2_SOLDIER_MACHINEGUN_2:
479 case MZ2_SOLDIER_MACHINEGUN_3:
480 case MZ2_SOLDIER_MACHINEGUN_4:
481 case MZ2_SOLDIER_MACHINEGUN_5:
482 case MZ2_SOLDIER_MACHINEGUN_6:
483 case MZ2_SOLDIER_MACHINEGUN_7:
484 case MZ2_SOLDIER_MACHINEGUN_8:
485 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
486 CL_ParticleEffect (origin, vec3_origin, 0, 40);
487 CL_SmokeAndFlash(origin);
488 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck3.wav"), 1, ATTN_NORM, 0);
489 break;
490
491 case MZ2_GUNNER_MACHINEGUN_1:
492 case MZ2_GUNNER_MACHINEGUN_2:
493 case MZ2_GUNNER_MACHINEGUN_3:
494 case MZ2_GUNNER_MACHINEGUN_4:
495 case MZ2_GUNNER_MACHINEGUN_5:
496 case MZ2_GUNNER_MACHINEGUN_6:
497 case MZ2_GUNNER_MACHINEGUN_7:
498 case MZ2_GUNNER_MACHINEGUN_8:
499 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
500 CL_ParticleEffect (origin, vec3_origin, 0, 40);
501 CL_SmokeAndFlash(origin);
502 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck2.wav"), 1, ATTN_NORM, 0);
503 break;
504
505 case MZ2_ACTOR_MACHINEGUN_1:
506 case MZ2_SUPERTANK_MACHINEGUN_1:
507 case MZ2_SUPERTANK_MACHINEGUN_2:
508 case MZ2_SUPERTANK_MACHINEGUN_3:
509 case MZ2_SUPERTANK_MACHINEGUN_4:
510 case MZ2_SUPERTANK_MACHINEGUN_5:
511 case MZ2_SUPERTANK_MACHINEGUN_6:
512 case MZ2_TURRET_MACHINEGUN: // PGM
513 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
514
515 CL_ParticleEffect (origin, vec3_origin, 0, 40);
516 CL_SmokeAndFlash(origin);
517 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
518 break;
519
520 case MZ2_BOSS2_MACHINEGUN_L1:
521 case MZ2_BOSS2_MACHINEGUN_L2:
522 case MZ2_BOSS2_MACHINEGUN_L3:
523 case MZ2_BOSS2_MACHINEGUN_L4:
524 case MZ2_BOSS2_MACHINEGUN_L5:
525 case MZ2_CARRIER_MACHINEGUN_L1: // PMM
526 case MZ2_CARRIER_MACHINEGUN_L2: // PMM
527 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
528
529 CL_ParticleEffect (origin, vec3_origin, 0, 40);
530 CL_SmokeAndFlash(origin);
531 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NONE, 0);
532 break;
533
534 case MZ2_SOLDIER_BLASTER_1:
535 case MZ2_SOLDIER_BLASTER_2:
536 case MZ2_SOLDIER_BLASTER_3:
537 case MZ2_SOLDIER_BLASTER_4:
538 case MZ2_SOLDIER_BLASTER_5:
539 case MZ2_SOLDIER_BLASTER_6:
540 case MZ2_SOLDIER_BLASTER_7:
541 case MZ2_SOLDIER_BLASTER_8:
542 case MZ2_TURRET_BLASTER: // PGM
543 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
544 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0);
545 break;
546
547 case MZ2_FLYER_BLASTER_1:
548 case MZ2_FLYER_BLASTER_2:
549 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
550 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("flyer/flyatck3.wav"), 1, ATTN_NORM, 0);
551 break;
552
553 case MZ2_MEDIC_BLASTER_1:
554 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
555 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("medic/medatck1.wav"), 1, ATTN_NORM, 0);
556 break;
557
558 case MZ2_HOVER_BLASTER_1:
559 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
560 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("hover/hovatck1.wav"), 1, ATTN_NORM, 0);
561 break;
562
563 case MZ2_FLOAT_BLASTER_1:
564 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
565 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("floater/fltatck1.wav"), 1, ATTN_NORM, 0);
566 break;
567
568 case MZ2_SOLDIER_SHOTGUN_1:
569 case MZ2_SOLDIER_SHOTGUN_2:
570 case MZ2_SOLDIER_SHOTGUN_3:
571 case MZ2_SOLDIER_SHOTGUN_4:
572 case MZ2_SOLDIER_SHOTGUN_5:
573 case MZ2_SOLDIER_SHOTGUN_6:
574 case MZ2_SOLDIER_SHOTGUN_7:
575 case MZ2_SOLDIER_SHOTGUN_8:
576 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
577 CL_SmokeAndFlash(origin);
578 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck1.wav"), 1, ATTN_NORM, 0);
579 break;
580
581 case MZ2_TANK_BLASTER_1:
582 case MZ2_TANK_BLASTER_2:
583 case MZ2_TANK_BLASTER_3:
584 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
585 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
586 break;
587
588 case MZ2_TANK_MACHINEGUN_1:
589 case MZ2_TANK_MACHINEGUN_2:
590 case MZ2_TANK_MACHINEGUN_3:
591 case MZ2_TANK_MACHINEGUN_4:
592 case MZ2_TANK_MACHINEGUN_5:
593 case MZ2_TANK_MACHINEGUN_6:
594 case MZ2_TANK_MACHINEGUN_7:
595 case MZ2_TANK_MACHINEGUN_8:
596 case MZ2_TANK_MACHINEGUN_9:
597 case MZ2_TANK_MACHINEGUN_10:
598 case MZ2_TANK_MACHINEGUN_11:
599 case MZ2_TANK_MACHINEGUN_12:
600 case MZ2_TANK_MACHINEGUN_13:
601 case MZ2_TANK_MACHINEGUN_14:
602 case MZ2_TANK_MACHINEGUN_15:
603 case MZ2_TANK_MACHINEGUN_16:
604 case MZ2_TANK_MACHINEGUN_17:
605 case MZ2_TANK_MACHINEGUN_18:
606 case MZ2_TANK_MACHINEGUN_19:
607 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
608 CL_ParticleEffect (origin, vec3_origin, 0, 40);
609 CL_SmokeAndFlash(origin);
610 Com_sprintf(soundname, sizeof(soundname), "tank/tnkatk2%c.wav", 'a' + rand() % 5);
611 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound(soundname), 1, ATTN_NORM, 0);
612 break;
613
614 case MZ2_CHICK_ROCKET_1:
615 case MZ2_TURRET_ROCKET: // PGM
616 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
617 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0);
618 break;
619
620 case MZ2_TANK_ROCKET_1:
621 case MZ2_TANK_ROCKET_2:
622 case MZ2_TANK_ROCKET_3:
623 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
624 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck1.wav"), 1, ATTN_NORM, 0);
625 break;
626
627 case MZ2_SUPERTANK_ROCKET_1:
628 case MZ2_SUPERTANK_ROCKET_2:
629 case MZ2_SUPERTANK_ROCKET_3:
630 case MZ2_BOSS2_ROCKET_1:
631 case MZ2_BOSS2_ROCKET_2:
632 case MZ2_BOSS2_ROCKET_3:
633 case MZ2_BOSS2_ROCKET_4:
634 case MZ2_CARRIER_ROCKET_1:
635 // case MZ2_CARRIER_ROCKET_2:
636 // case MZ2_CARRIER_ROCKET_3:
637 // case MZ2_CARRIER_ROCKET_4:
638 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
639 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0);
640 break;
641
642 case MZ2_GUNNER_GRENADE_1:
643 case MZ2_GUNNER_GRENADE_2:
644 case MZ2_GUNNER_GRENADE_3:
645 case MZ2_GUNNER_GRENADE_4:
646 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
647 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck3.wav"), 1, ATTN_NORM, 0);
648 break;
649
650 case MZ2_GLADIATOR_RAILGUN_1:
651 // PMM
652 case MZ2_CARRIER_RAILGUN:
653 case MZ2_WIDOW_RAIL:
654 // pmm
655 dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
656 break;
657
658 // --- Xian's shit starts ---
659 case MZ2_MAKRON_BFG:
660 dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5;
661 //S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/bfg_fire.wav"), 1, ATTN_NORM, 0);
662 break;
663
664 case MZ2_MAKRON_BLASTER_1:
665 case MZ2_MAKRON_BLASTER_2:
666 case MZ2_MAKRON_BLASTER_3:
667 case MZ2_MAKRON_BLASTER_4:
668 case MZ2_MAKRON_BLASTER_5:
669 case MZ2_MAKRON_BLASTER_6:
670 case MZ2_MAKRON_BLASTER_7:
671 case MZ2_MAKRON_BLASTER_8:
672 case MZ2_MAKRON_BLASTER_9:
673 case MZ2_MAKRON_BLASTER_10:
674 case MZ2_MAKRON_BLASTER_11:
675 case MZ2_MAKRON_BLASTER_12:
676 case MZ2_MAKRON_BLASTER_13:
677 case MZ2_MAKRON_BLASTER_14:
678 case MZ2_MAKRON_BLASTER_15:
679 case MZ2_MAKRON_BLASTER_16:
680 case MZ2_MAKRON_BLASTER_17:
681 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
682 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0);
683 break;
684
685 case MZ2_JORG_MACHINEGUN_L1:
686 case MZ2_JORG_MACHINEGUN_L2:
687 case MZ2_JORG_MACHINEGUN_L3:
688 case MZ2_JORG_MACHINEGUN_L4:
689 case MZ2_JORG_MACHINEGUN_L5:
690 case MZ2_JORG_MACHINEGUN_L6:
691 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
692 CL_ParticleEffect (origin, vec3_origin, 0, 40);
693 CL_SmokeAndFlash(origin);
694 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfire.wav"), 1, ATTN_NORM, 0);
695 break;
696
697 case MZ2_JORG_MACHINEGUN_R1:
698 case MZ2_JORG_MACHINEGUN_R2:
699 case MZ2_JORG_MACHINEGUN_R3:
700 case MZ2_JORG_MACHINEGUN_R4:
701 case MZ2_JORG_MACHINEGUN_R5:
702 case MZ2_JORG_MACHINEGUN_R6:
703 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
704 CL_ParticleEffect (origin, vec3_origin, 0, 40);
705 CL_SmokeAndFlash(origin);
706 break;
707
708 case MZ2_JORG_BFG_1:
709 dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5;
710 break;
711
712 case MZ2_BOSS2_MACHINEGUN_R1:
713 case MZ2_BOSS2_MACHINEGUN_R2:
714 case MZ2_BOSS2_MACHINEGUN_R3:
715 case MZ2_BOSS2_MACHINEGUN_R4:
716 case MZ2_BOSS2_MACHINEGUN_R5:
717 case MZ2_CARRIER_MACHINEGUN_R1: // PMM
718 case MZ2_CARRIER_MACHINEGUN_R2: // PMM
719
720 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
721
722 CL_ParticleEffect (origin, vec3_origin, 0, 40);
723 CL_SmokeAndFlash(origin);
724 break;
725
726 // ======
727 // ROGUE
728 case MZ2_STALKER_BLASTER:
729 case MZ2_DAEDALUS_BLASTER:
730 case MZ2_MEDIC_BLASTER_2:
731 case MZ2_WIDOW_BLASTER:
732 case MZ2_WIDOW_BLASTER_SWEEP1:
733 case MZ2_WIDOW_BLASTER_SWEEP2:
734 case MZ2_WIDOW_BLASTER_SWEEP3:
735 case MZ2_WIDOW_BLASTER_SWEEP4:
736 case MZ2_WIDOW_BLASTER_SWEEP5:
737 case MZ2_WIDOW_BLASTER_SWEEP6:
738 case MZ2_WIDOW_BLASTER_SWEEP7:
739 case MZ2_WIDOW_BLASTER_SWEEP8:
740 case MZ2_WIDOW_BLASTER_SWEEP9:
741 case MZ2_WIDOW_BLASTER_100:
742 case MZ2_WIDOW_BLASTER_90:
743 case MZ2_WIDOW_BLASTER_80:
744 case MZ2_WIDOW_BLASTER_70:
745 case MZ2_WIDOW_BLASTER_60:
746 case MZ2_WIDOW_BLASTER_50:
747 case MZ2_WIDOW_BLASTER_40:
748 case MZ2_WIDOW_BLASTER_30:
749 case MZ2_WIDOW_BLASTER_20:
750 case MZ2_WIDOW_BLASTER_10:
751 case MZ2_WIDOW_BLASTER_0:
752 case MZ2_WIDOW_BLASTER_10L:
753 case MZ2_WIDOW_BLASTER_20L:
754 case MZ2_WIDOW_BLASTER_30L:
755 case MZ2_WIDOW_BLASTER_40L:
756 case MZ2_WIDOW_BLASTER_50L:
757 case MZ2_WIDOW_BLASTER_60L:
758 case MZ2_WIDOW_BLASTER_70L:
759 case MZ2_WIDOW_RUN_1:
760 case MZ2_WIDOW_RUN_2:
761 case MZ2_WIDOW_RUN_3:
762 case MZ2_WIDOW_RUN_4:
763 case MZ2_WIDOW_RUN_5:
764 case MZ2_WIDOW_RUN_6:
765 case MZ2_WIDOW_RUN_7:
766 case MZ2_WIDOW_RUN_8:
767 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
768 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
769 break;
770
771 case MZ2_WIDOW_DISRUPTOR:
772 dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1;
773 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), 1, ATTN_NORM, 0);
774 break;
775
776 case MZ2_WIDOW_PLASMABEAM:
777 case MZ2_WIDOW2_BEAMER_1:
778 case MZ2_WIDOW2_BEAMER_2:
779 case MZ2_WIDOW2_BEAMER_3:
780 case MZ2_WIDOW2_BEAMER_4:
781 case MZ2_WIDOW2_BEAMER_5:
782 case MZ2_WIDOW2_BEAM_SWEEP_1:
783 case MZ2_WIDOW2_BEAM_SWEEP_2:
784 case MZ2_WIDOW2_BEAM_SWEEP_3:
785 case MZ2_WIDOW2_BEAM_SWEEP_4:
786 case MZ2_WIDOW2_BEAM_SWEEP_5:
787 case MZ2_WIDOW2_BEAM_SWEEP_6:
788 case MZ2_WIDOW2_BEAM_SWEEP_7:
789 case MZ2_WIDOW2_BEAM_SWEEP_8:
790 case MZ2_WIDOW2_BEAM_SWEEP_9:
791 case MZ2_WIDOW2_BEAM_SWEEP_10:
792 case MZ2_WIDOW2_BEAM_SWEEP_11:
793 dl->radius = 300 + (rand()&100);
794 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
795 dl->die = cl.time + 200;
796 break;
797 // ROGUE
798 // ======
799
800 // --- Xian's shit ends ---
801
802 }
803 }
804
805
806 /*
807 ===============
808 CL_AddDLights
809
810 ===============
811 */
812 void CL_AddDLights (void)
813 {
814 int i;
815 cdlight_t *dl;
816
817 dl = cl_dlights;
818
819 //=====
820 //PGM
821 if(vidref_val == VIDREF_GL)
822 {
823 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
824 {
825 if (!dl->radius)
826 continue;
827 V_AddLight (dl->origin, dl->radius,
828 dl->color[0], dl->color[1], dl->color[2]);
829 }
830 }
831 else
832 {
833 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
834 {
835 if (!dl->radius)
836 continue;
837
838 // negative light in software. only black allowed
839 if ((dl->color[0] < 0) || (dl->color[1] < 0) || (dl->color[2] < 0))
840 {
841 dl->radius = -(dl->radius);
842 dl->color[0] = 1;
843 dl->color[1] = 1;
844 dl->color[2] = 1;
845 }
846 V_AddLight (dl->origin, dl->radius,
847 dl->color[0], dl->color[1], dl->color[2]);
848 }
849 }
850 //PGM
851 //=====
852 }
853
854
855
856 /*
857 ==============================================================
858
859 PARTICLE MANAGEMENT
860
861 ==============================================================
862 */
863
864 /*
865 // THIS HAS BEEN RELOCATED TO CLIENT.H
866 typedef struct particle_s
867 {
868 struct particle_s *next;
869
870 float time;
871
872 vec3_t org;
873 vec3_t vel;
874 vec3_t accel;
875 float color;
876 float colorvel;
877 float alpha;
878 float alphavel;
879 } cparticle_t;
880
881
882 #define PARTICLE_GRAVITY 40
883 */
884
885 cparticle_t *active_particles, *free_particles;
886
887 cparticle_t particles[MAX_PARTICLES];
888 int cl_numparticles = MAX_PARTICLES;
889
890
891 /*
892 ===============
893 CL_ClearParticles
894 ===============
895 */
896 void CL_ClearParticles (void)
897 {
898 int i;
899
900 free_particles = &particles[0];
901 active_particles = NULL;
902
903 for (i=0 ;i<cl_numparticles ; i++)
904 particles[i].next = &particles[i+1];
905 particles[cl_numparticles-1].next = NULL;
906 }
907
908
909 /*
910 ===============
911 CL_ParticleEffect
912
913 Wall impact puffs
914 ===============
915 */
916 void CL_ParticleEffect (vec3_t org, vec3_t dir, int color, int count)
917 {
918 int i, j;
919 cparticle_t *p;
920 float d;
921
922 for (i=0 ; i<count ; i++)
923 {
924 if (!free_particles)
925 return;
926 p = free_particles;
927 free_particles = p->next;
928 p->next = active_particles;
929 active_particles = p;
930
931 p->time = cl.time;
932 p->color = color + (rand()&7);
933
934 d = rand()&31;
935 for (j=0 ; j<3 ; j++)
936 {
937 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
938 p->vel[j] = crand()*20;
939 }
940
941 p->accel[0] = p->accel[1] = 0;
942 p->accel[2] = -PARTICLE_GRAVITY;
943 p->alpha = 1.0;
944
945 p->alphavel = -1.0 / (0.5 + frand()*0.3);
946 }
947 }
948
949
950 /*
951 ===============
952 CL_ParticleEffect2
953 ===============
954 */
955 void CL_ParticleEffect2 (vec3_t org, vec3_t dir, int color, int count)
956 {
957 int i, j;
958 cparticle_t *p;
959 float d;
960
961 for (i=0 ; i<count ; i++)
962 {
963 if (!free_particles)
964 return;
965 p = free_particles;
966 free_particles = p->next;
967 p->next = active_particles;
968 active_particles = p;
969
970 p->time = cl.time;
971 p->color = color;
972
973 d = rand()&7;
974 for (j=0 ; j<3 ; j++)
975 {
976 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
977 p->vel[j] = crand()*20;
978 }
979
980 p->accel[0] = p->accel[1] = 0;
981 p->accel[2] = -PARTICLE_GRAVITY;
982 p->alpha = 1.0;
983
984 p->alphavel = -1.0 / (0.5 + frand()*0.3);
985 }
986 }
987
988
989 // RAFAEL
990 /*
991 ===============
992 CL_ParticleEffect3
993 ===============
994 */
995 void CL_ParticleEffect3 (vec3_t org, vec3_t dir, int color, int count)
996 {
997 int i, j;
998 cparticle_t *p;
999 float d;
1000
1001 for (i=0 ; i<count ; i++)
1002 {
1003 if (!free_particles)
1004 return;
1005 p = free_particles;
1006 free_particles = p->next;
1007 p->next = active_particles;
1008 active_particles = p;
1009
1010 p->time = cl.time;
1011 p->color = color;
1012
1013 d = rand()&7;
1014 for (j=0 ; j<3 ; j++)
1015 {
1016 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
1017 p->vel[j] = crand()*20;
1018 }
1019
1020 p->accel[0] = p->accel[1] = 0;
1021 p->accel[2] = PARTICLE_GRAVITY;
1022 p->alpha = 1.0;
1023
1024 p->alphavel = -1.0 / (0.5 + frand()*0.3);
1025 }
1026 }
1027
1028 /*
1029 ===============
1030 CL_TeleporterParticles
1031 ===============
1032 */
1033 void CL_TeleporterParticles (entity_state_t *ent)
1034 {
1035 int i, j;
1036 cparticle_t *p;
1037
1038 for (i=0 ; i<8 ; i++)
1039 {
1040 if (!free_particles)
1041 return;
1042 p = free_particles;
1043 free_particles = p->next;
1044 p->next = active_particles;
1045 active_particles = p;
1046
1047 p->time = cl.time;
1048 p->color = 0xdb;
1049
1050 for (j=0 ; j<2 ; j++)
1051 {
1052 p->org[j] = ent->origin[j] - 16 + (rand()&31);
1053 p->vel[j] = crand()*14;
1054 }
1055
1056 p->org[2] = ent->origin[2] - 8 + (rand()&7);
1057 p->vel[2] = 80 + (rand()&7);
1058
1059 p->accel[0] = p->accel[1] = 0;
1060 p->accel[2] = -PARTICLE_GRAVITY;
1061 p->alpha = 1.0;
1062
1063 p->alphavel = -0.5;
1064 }
1065 }
1066
1067
1068 /*
1069 ===============
1070 CL_LogoutEffect
1071
1072 ===============
1073 */
1074 void CL_LogoutEffect (vec3_t org, int type)
1075 {
1076 int i, j;
1077 cparticle_t *p;
1078
1079 for (i=0 ; i<500 ; i++)
1080 {
1081 if (!free_particles)
1082 return;
1083 p = free_particles;
1084 free_particles = p->next;
1085 p->next = active_particles;
1086 active_particles = p;
1087
1088 p->time = cl.time;
1089
1090 if (type == MZ_LOGIN)
1091 p->color = 0xd0 + (rand()&7); // green
1092 else if (type == MZ_LOGOUT)
1093 p->color = 0x40 + (rand()&7); // red
1094 else
1095 p->color = 0xe0 + (rand()&7); // yellow
1096
1097 p->org[0] = org[0] - 16 + frand()*32;
1098 p->org[1] = org[1] - 16 + frand()*32;
1099 p->org[2] = org[2] - 24 + frand()*56;
1100
1101 for (j=0 ; j<3 ; j++)
1102 p->vel[j] = crand()*20;
1103
1104 p->accel[0] = p->accel[1] = 0;
1105 p->accel[2] = -PARTICLE_GRAVITY;
1106 p->alpha = 1.0;
1107
1108 p->alphavel = -1.0 / (1.0 + frand()*0.3);
1109 }
1110 }
1111
1112
1113 /*
1114 ===============
1115 CL_ItemRespawnParticles
1116
1117 ===============
1118 */
1119 void CL_ItemRespawnParticles (vec3_t org)
1120 {
1121 int i, j;
1122 cparticle_t *p;
1123
1124 for (i=0 ; i<64 ; i++)
1125 {
1126 if (!free_particles)
1127 return;
1128 p = free_particles;
1129 free_particles = p->next;
1130 p->next = active_particles;
1131 active_particles = p;
1132
1133 p->time = cl.time;
1134
1135 p->color = 0xd4 + (rand()&3); // green
1136
1137 p->org[0] = org[0] + crand()*8;
1138 p->org[1] = org[1] + crand()*8;
1139 p->org[2] = org[2] + crand()*8;
1140
1141 for (j=0 ; j<3 ; j++)
1142 p->vel[j] = crand()*8;
1143
1144 p->accel[0] = p->accel[1] = 0;
1145 p->accel[2] = -PARTICLE_GRAVITY*0.2;
1146 p->alpha = 1.0;
1147
1148 p->alphavel = -1.0 / (1.0 + frand()*0.3);
1149 }
1150 }
1151
1152
1153 /*
1154 ===============
1155 CL_ExplosionParticles
1156 ===============
1157 */
1158 void CL_ExplosionParticles (vec3_t org)
1159 {
1160 int i, j;
1161 cparticle_t *p;
1162
1163 for (i=0 ; i<256 ; i++)
1164 {
1165 if (!free_particles)
1166 return;
1167 p = free_particles;
1168 free_particles = p->next;
1169 p->next = active_particles;
1170 active_particles = p;
1171
1172 p->time = cl.time;
1173 p->color = 0xe0 + (rand()&7);
1174
1175 for (j=0 ; j<3 ; j++)
1176 {
1177 p->org[j] = org[j] + ((rand()%32)-16);
1178 p->vel[j] = (rand()%384)-192;
1179 }
1180
1181 p->accel[0] = p->accel[1] = 0;
1182 p->accel[2] = -PARTICLE_GRAVITY;
1183 p->alpha = 1.0;
1184
1185 p->alphavel = -0.8 / (0.5 + frand()*0.3);
1186 }
1187 }
1188
1189
1190 /*
1191 ===============
1192 CL_BigTeleportParticles
1193 ===============
1194 */
1195 void CL_BigTeleportParticles (vec3_t org)
1196 {
1197 int i;
1198 cparticle_t *p;
1199 float angle, dist;
1200 static int colortable[4] = {2*8,13*8,21*8,18*8};
1201
1202 for (i=0 ; i<4096 ; i++)
1203 {
1204 if (!free_particles)
1205 return;
1206 p = free_particles;
1207 free_particles = p->next;
1208 p->next = active_particles;
1209 active_particles = p;
1210
1211 p->time = cl.time;
1212
1213 p->color = colortable[rand()&3];
1214
1215 angle = M_PI*2*(rand()&1023)/1023.0;
1216 dist = rand()&31;
1217 p->org[0] = org[0] + cos(angle)*dist;
1218 p->vel[0] = cos(angle)*(70+(rand()&63));
1219 p->accel[0] = -cos(angle)*100;
1220
1221 p->org[1] = org[1] + sin(angle)*dist;
1222 p->vel[1] = sin(angle)*(70+(rand()&63));
1223 p->accel[1] = -sin(angle)*100;
1224
1225 p->org[2] = org[2] + 8 + (rand()%90);
1226 p->vel[2] = -100 + (rand()&31);
1227 p->accel[2] = PARTICLE_GRAVITY*4;
1228 p->alpha = 1.0;
1229
1230 p->alphavel = -0.3 / (0.5 + frand()*0.3);
1231 }
1232 }
1233
1234
1235 /*
1236 ===============
1237 CL_BlasterParticles
1238
1239 Wall impact puffs
1240 ===============
1241 */
1242 void CL_BlasterParticles (vec3_t org, vec3_t dir)
1243 {
1244 int i, j;
1245 cparticle_t *p;
1246 float d;
1247 int count;
1248
1249 count = 40;
1250 for (i=0 ; i<count ; i++)
1251 {
1252 if (!free_particles)
1253 return;
1254 p = free_particles;
1255 free_particles = p->next;
1256 p->next = active_particles;
1257 active_particles = p;
1258
1259 p->time = cl.time;
1260 p->color = 0xe0 + (rand()&7);
1261
1262 d = rand()&15;
1263 for (j=0 ; j<3 ; j++)
1264 {
1265 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
1266 p->vel[j] = dir[j] * 30 + crand()*40;
1267 }
1268
1269 p->accel[0] = p->accel[1] = 0;
1270 p->accel[2] = -PARTICLE_GRAVITY;
1271 p->alpha = 1.0;
1272
1273 p->alphavel = -1.0 / (0.5 + frand()*0.3);
1274 }
1275 }
1276
1277
1278 /*
1279 ===============
1280 CL_BlasterTrail
1281
1282 ===============
1283 */
1284 void CL_BlasterTrail (vec3_t start, vec3_t end)
1285 {
1286 vec3_t move;
1287 vec3_t vec;
1288 float len;
1289 int j;
1290 cparticle_t *p;
1291 int dec;
1292
1293 VectorCopy (start, move);
1294 VectorSubtract (end, start, vec);
1295 len = VectorNormalize (vec);
1296
1297 dec = 5;
1298 VectorScale (vec, 5, vec);
1299
1300 // FIXME: this is a really silly way to have a loop
1301 while (len > 0)
1302 {
1303 len -= dec;
1304
1305 if (!free_particles)
1306 return;
1307 p = free_particles;
1308 free_particles = p->next;
1309 p->next = active_particles;
1310 active_particles = p;
1311 VectorClear (p->accel);
1312
1313 p->time = cl.time;
1314
1315 p->alpha = 1.0;
1316 p->alphavel = -1.0 / (0.3+frand()*0.2);
1317 p->color = 0xe0;
1318 for (j=0 ; j<3 ; j++)
1319 {
1320 p->org[j] = move[j] + crand();
1321 p->vel[j] = crand()*5;
1322 p->accel[j] = 0;
1323 }
1324
1325 VectorAdd (move, vec, move);
1326 }
1327 }
1328
1329 /*
1330 ===============
1331 CL_QuadTrail
1332
1333 ===============
1334 */
1335 void CL_QuadTrail (vec3_t start, vec3_t end)
1336 {
1337 vec3_t move;
1338 vec3_t vec;
1339 float len;
1340 int j;
1341 cparticle_t *p;
1342 int dec;
1343
1344 VectorCopy (start, move);
1345 VectorSubtract (end, start, vec);
1346 len = VectorNormalize (vec);
1347
1348 dec = 5;
1349 VectorScale (vec, 5, vec);
1350
1351 while (len > 0)
1352 {
1353 len -= dec;
1354
1355 if (!free_particles)
1356 return;
1357 p = free_particles;
1358 free_particles = p->next;
1359 p->next = active_particles;
1360 active_particles = p;
1361 VectorClear (p->accel);
1362
1363 p->time = cl.time;
1364
1365 p->alpha = 1.0;
1366 p->alphavel = -1.0 / (0.8+frand()*0.2);
1367 p->color = 115;
1368 for (j=0 ; j<3 ; j++)
1369 {
1370 p->org[j] = move[j] + crand()*16;
1371 p->vel[j] = crand()*5;
1372 p->accel[j] = 0;
1373 }
1374
1375 VectorAdd (move, vec, move);
1376 }
1377 }
1378
1379 /*
1380 ===============
1381 CL_FlagTrail
1382
1383 ===============
1384 */
1385 void CL_FlagTrail (vec3_t start, vec3_t end, float color)
1386 {
1387 vec3_t move;
1388 vec3_t vec;
1389 float len;
1390 int j;
1391 cparticle_t *p;
1392 int dec;
1393
1394 VectorCopy (start, move);
1395 VectorSubtract (end, start, vec);
1396 len = VectorNormalize (vec);
1397
1398 dec = 5;
1399 VectorScale (vec, 5, vec);
1400
1401 while (len > 0)
1402 {
1403 len -= dec;
1404
1405 if (!free_particles)
1406 return;
1407 p = free_particles;
1408 free_particles = p->next;
1409 p->next = active_particles;
1410 active_particles = p;
1411 VectorClear (p->accel);
1412
1413 p->time = cl.time;
1414
1415 p->alpha = 1.0;
1416 p->alphavel = -1.0 / (0.8+frand()*0.2);
1417 p->color = color;
1418 for (j=0 ; j<3 ; j++)
1419 {
1420 p->org[j] = move[j] + crand()*16;
1421 p->vel[j] = crand()*5;
1422 p->accel[j] = 0;
1423 }
1424
1425 VectorAdd (move, vec, move);
1426 }
1427 }
1428
1429 /*
1430 ===============
1431 CL_DiminishingTrail
1432
1433 ===============
1434 */
1435 void CL_DiminishingTrail (vec3_t start, vec3_t end, centity_t *old, int flags)
1436 {
1437 vec3_t move;
1438 vec3_t vec;
1439 float len;
1440 int j;
1441 cparticle_t *p;
1442 float dec;
1443 float orgscale;
1444 float velscale;
1445
1446 VectorCopy (start, move);
1447 VectorSubtract (end, start, vec);
1448 len = VectorNormalize (vec);
1449
1450 dec = 0.5;
1451 VectorScale (vec, dec, vec);
1452
1453 if (old->trailcount > 900)
1454 {
1455 orgscale = 4;
1456 velscale = 15;
1457 }
1458 else if (old->trailcount > 800)
1459 {
1460 orgscale = 2;
1461 velscale = 10;
1462 }
1463 else
1464 {
1465 orgscale = 1;
1466 velscale = 5;
1467 }
1468
1469 while (len > 0)
1470 {
1471 len -= dec;
1472
1473 if (!free_particles)
1474 return;
1475
1476 // drop less particles as it flies
1477 if ((rand()&1023) < old->trailcount)
1478 {
1479 p = free_particles;
1480 free_particles = p->next;
1481 p->next = active_particles;
1482 active_particles = p;
1483 VectorClear (p->accel);
1484
1485 p->time = cl.time;
1486
1487 if (flags & EF_GIB)
1488 {
1489 p->alpha = 1.0;
1490 p->alphavel = -1.0 / (1+frand()*0.4);
1491 p->color = 0xe8 + (rand()&7);
1492 for (j=0 ; j<3 ; j++)
1493 {
1494 p->org[j] = move[j] + crand()*orgscale;
1495 p->vel[j] = crand()*velscale;
1496 p->accel[j] = 0;
1497 }
1498 p->vel[2] -= PARTICLE_GRAVITY;
1499 }
1500 else if (flags & EF_GREENGIB)
1501 {
1502 p->alpha = 1.0;
1503 p->alphavel = -1.0 / (1+frand()*0.4);
1504 p->color = 0xdb + (rand()&7);
1505 for (j=0; j< 3; j++)
1506 {
1507 p->org[j] = move[j] + crand()*orgscale;
1508 p->vel[j] = crand()*velscale;
1509 p->accel[j] = 0;
1510 }
1511 p->vel[2] -= PARTICLE_GRAVITY;
1512 }
1513 else
1514 {
1515 p->alpha = 1.0;
1516 p->alphavel = -1.0 / (1+frand()*0.2);
1517 p->color = 4 + (rand()&7);
1518 for (j=0 ; j<3 ; j++)
1519 {
1520 p->org[j] = move[j] + crand()*orgscale;
1521 p->vel[j] = crand()*velscale;
1522 }
1523 p->accel[2] = 20;
1524 }
1525 }
1526
1527 old->trailcount -= 5;
1528 if (old->trailcount < 100)
1529 old->trailcount = 100;
1530 VectorAdd (move, vec, move);
1531 }
1532 }
1533
1534 void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
1535 {
1536 float d;
1537
1538 // this rotate and negat guarantees a vector
1539 // not colinear with the original
1540 right[1] = -forward[0];
1541 right[2] = forward[1];
1542 right[0] = forward[2];
1543
1544 d = DotProduct (right, forward);
1545 VectorMA (right, -d, forward, right);
1546 VectorNormalize (right);
1547 CrossProduct (right, forward, up);
1548 }
1549
1550 /*
1551 ===============
1552 CL_RocketTrail
1553
1554 ===============
1555 */
1556 void CL_RocketTrail (vec3_t start, vec3_t end, centity_t *old)
1557 {
1558 vec3_t move;
1559 vec3_t vec;
1560 float len;
1561 int j;
1562 cparticle_t *p;
1563 float dec;
1564
1565 // smoke
1566 CL_DiminishingTrail (start, end, old, EF_ROCKET);
1567
1568 // fire
1569 VectorCopy (start, move);
1570 VectorSubtract (end, start, vec);
1571 len = VectorNormalize (vec);
1572
1573 dec = 1;
1574 VectorScale (vec, dec, vec);
1575
1576 while (len > 0)
1577 {
1578 len -= dec;
1579
1580 if (!free_particles)
1581 return;
1582
1583 if ( (rand()&7) == 0)
1584 {
1585 p = free_particles;
1586 free_particles = p->next;
1587 p->next = active_particles;
1588 active_particles = p;
1589
1590 VectorClear (p->accel);
1591 p->time = cl.time;
1592
1593 p->alpha = 1.0;
1594 p->alphavel = -1.0 / (1+frand()*0.2);
1595 p->color = 0xdc + (rand()&3);
1596 for (j=0 ; j<3 ; j++)
1597 {
1598 p->org[j] = move[j] + crand()*5;
1599 p->vel[j] = crand()*20;
1600 }
1601 p->accel[2] = -PARTICLE_GRAVITY;
1602 }
1603 VectorAdd (move, vec, move);
1604 }
1605 }
1606
1607 /*
1608 ===============
1609 CL_RailTrail
1610
1611 ===============
1612 */
1613 void CL_RailTrail (vec3_t start, vec3_t end)
1614 {
1615 vec3_t move;
1616 vec3_t vec;
1617 float len;
1618 int j;
1619 cparticle_t *p;
1620 float dec;
1621 vec3_t right, up;
1622 int i;
1623 float d, c, s;
1624 vec3_t dir;
1625 byte clr = 0x74;
1626
1627 VectorCopy (start, move);
1628 VectorSubtract (end, start, vec);
1629 len = VectorNormalize (vec);
1630
1631 MakeNormalVectors (vec, right, up);
1632
1633 for (i=0 ; i<len ; i++)
1634 {
1635 if (!free_particles)
1636 return;
1637
1638 p = free_particles;
1639 free_particles = p->next;
1640 p->next = active_particles;
1641 active_particles = p;
1642
1643 p->time = cl.time;
1644 VectorClear (p->accel);
1645
1646 d = i * 0.1;
1647 c = cos(d);
1648 s = sin(d);
1649
1650 VectorScale (right, c, dir);
1651 VectorMA (dir, s, up, dir);
1652
1653 p->alpha = 1.0;
1654 p->alphavel = -1.0 / (1+frand()*0.2);
1655 p->color = clr + (rand()&7);
1656 for (j=0 ; j<3 ; j++)
1657 {
1658 p->org[j] = move[j] + dir[j]*3;
1659 p->vel[j] = dir[j]*6;
1660 }
1661
1662 VectorAdd (move, vec, move);
1663 }
1664
1665 dec = 0.75;
1666 VectorScale (vec, dec, vec);
1667 VectorCopy (start, move);
1668
1669 while (len > 0)
1670 {
1671 len -= dec;
1672
1673 if (!free_particles)
1674 return;
1675 p = free_particles;
1676 free_particles = p->next;
1677 p->next = active_particles;
1678 active_particles = p;
1679
1680 p->time = cl.time;
1681 VectorClear (p->accel);
1682
1683 p->alpha = 1.0;
1684 p->alphavel = -1.0 / (0.6+frand()*0.2);
1685 p->color = 0x0 + rand()&15;
1686
1687 for (j=0 ; j<3 ; j++)
1688 {
1689 p->org[j] = move[j] + crand()*3;
1690 p->vel[j] = crand()*3;
1691 p->accel[j] = 0;
1692 }
1693
1694 VectorAdd (move, vec, move);
1695 }
1696 }
1697
1698 // RAFAEL
1699 /*
1700 ===============
1701 CL_IonripperTrail
1702 ===============
1703 */
1704 void CL_IonripperTrail (vec3_t start, vec3_t ent)
1705 {
1706 vec3_t move;
1707 vec3_t vec;
1708 float len;
1709 int j;
1710 cparticle_t *p;
1711 int dec;
1712 int left = 0;
1713
1714 VectorCopy (start, move);
1715 VectorSubtract (ent, start, vec);
1716 len = VectorNormalize (vec);
1717
1718 dec = 5;
1719 VectorScale (vec, 5, vec);
1720
1721 while (len > 0)
1722 {
1723 len -= dec;
1724
1725 if (!free_particles)
1726 return;
1727 p = free_particles;
1728 free_particles = p->next;
1729 p->next = active_particles;
1730 active_particles = p;
1731 VectorClear (p->accel);
1732
1733 p->time = cl.time;
1734 p->alpha = 0.5;
1735 p->alphavel = -1.0 / (0.3 + frand() * 0.2);
1736 p->color = 0xe4 + (rand()&3);
1737
1738 for (j=0; j<3; j++)
1739 {
1740 p->org[j] = move[j];
1741 p->accel[j] = 0;
1742 }
1743 if (left)
1744 {
1745 left = 0;
1746 p->vel[0] = 10;
1747 }
1748 else
1749 {
1750 left = 1;
1751 p->vel[0] = -10;
1752 }
1753
1754 p->vel[1] = 0;
1755 p->vel[2] = 0;
1756
1757 VectorAdd (move, vec, move);
1758 }
1759 }
1760
1761
1762 /*
1763 ===============
1764 CL_BubbleTrail
1765
1766 ===============
1767 */
1768 void CL_BubbleTrail (vec3_t start, vec3_t end)
1769 {
1770 vec3_t move;
1771 vec3_t vec;
1772 float len;
1773 int i, j;
1774 cparticle_t *p;
1775 float dec;
1776
1777 VectorCopy (start, move);
1778 VectorSubtract (end, start, vec);
1779 len = VectorNormalize (vec);
1780
1781 dec = 32;
1782 VectorScale (vec, dec, vec);
1783
1784 for (i=0 ; i<len ; i+=dec)
1785 {
1786 if (!free_particles)
1787 return;
1788
1789 p = free_particles;
1790 free_particles = p->next;
1791 p->next = active_particles;
1792 active_particles = p;
1793
1794 VectorClear (p->accel);
1795 p->time = cl.time;
1796
1797 p->alpha = 1.0;
1798 p->alphavel = -1.0 / (1+frand()*0.2);
1799 p->color = 4 + (rand()&7);
1800 for (j=0 ; j<3 ; j++)
1801 {
1802 p->org[j] = move[j] + crand()*2;
1803 p->vel[j] = crand()*5;
1804 }
1805 p->vel[2] += 6;
1806
1807 VectorAdd (move, vec, move);
1808 }
1809 }
1810
1811
1812 /*
1813 ===============
1814 CL_FlyParticles
1815 ===============
1816 */
1817
1818 #define BEAMLENGTH 16
1819 void CL_FlyParticles (vec3_t origin, int count)
1820 {
1821 int i;
1822 cparticle_t *p;
1823 float angle;
1824 float sr, sp, sy, cr, cp, cy;
1825 vec3_t forward;
1826 float dist = 64;
1827 float ltime;
1828
1829
1830 if (count > NUMVERTEXNORMALS)
1831 count = NUMVERTEXNORMALS;
1832
1833 if (!avelocities[0][0])
1834 {
1835 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
1836 avelocities[0][i] = (rand()&255) * 0.01;
1837 }
1838
1839
1840 ltime = (float)cl.time / 1000.0;
1841 for (i=0 ; i<count ; i+=2)
1842 {
1843 angle = ltime * avelocities[i][0];
1844 sy = sin(angle);
1845 cy = cos(angle);
1846 angle = ltime * avelocities[i][1];
1847 sp = sin(angle);
1848 cp = cos(angle);
1849 angle = ltime * avelocities[i][2];
1850 sr = sin(angle);
1851 cr = cos(angle);
1852
1853 forward[0] = cp*cy;
1854 forward[1] = cp*sy;
1855 forward[2] = -sp;
1856
1857 if (!free_particles)
1858 return;
1859 p = free_particles;
1860 free_particles = p->next;
1861 p->next = active_particles;
1862 active_particles = p;
1863
1864 p->time = cl.time;
1865
1866 dist = sin(ltime + i)*64;
1867 p->org[0] = origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
1868 p->org[1] = origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
1869 p->org[2] = origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
1870
1871 VectorClear (p->vel);
1872 VectorClear (p->accel);
1873
1874 p->color = 0;
1875 p->colorvel = 0;
1876
1877 p->alpha = 1;
1878 p->alphavel = -100;
1879 }
1880 }
1881
1882 void CL_FlyEffect (centity_t *ent, vec3_t origin)
1883 {
1884 int n;
1885 int count;
1886 int starttime;
1887
1888 if (ent->fly_stoptime < cl.time)
1889 {
1890 starttime = cl.time;
1891 ent->fly_stoptime = cl.time + 60000;
1892 }
1893 else
1894 {
1895 starttime = ent->fly_stoptime - 60000;
1896 }
1897
1898 n = cl.time - starttime;
1899 if (n < 20000)
1900 count = n * 162 / 20000.0;
1901 else
1902 {
1903 n = ent->fly_stoptime - cl.time;
1904 if (n < 20000)
1905 count = n * 162 / 20000.0;
1906 else
1907 count = 162;
1908 }
1909
1910 CL_FlyParticles (origin, count);
1911 }
1912
1913
1914 /*
1915 ===============
1916 CL_BfgParticles
1917 ===============
1918 */
1919
1920 #define BEAMLENGTH 16
1921 void CL_BfgParticles (entity_t *ent)
1922 {
1923 int i;
1924 cparticle_t *p;
1925 float angle;
1926 float sr, sp, sy, cr, cp, cy;
1927 vec3_t forward;
1928 float dist = 64;
1929 vec3_t v;
1930 float ltime;
1931
1932 if (!avelocities[0][0])
1933 {
1934 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
1935 avelocities[0][i] = (rand()&255) * 0.01;
1936 }
1937
1938
1939 ltime = (float)cl.time / 1000.0;
1940 for (i=0 ; i<NUMVERTEXNORMALS ; i++)
1941 {
1942 angle = ltime * avelocities[i][0];
1943 sy = sin(angle);
1944 cy = cos(angle);
1945 angle = ltime * avelocities[i][1];
1946 sp = sin(angle);
1947 cp = cos(angle);
1948 angle = ltime * avelocities[i][2];
1949 sr = sin(angle);
1950 cr = cos(angle);
1951
1952 forward[0] = cp*cy;
1953 forward[1] = cp*sy;
1954 forward[2] = -sp;
1955
1956 if (!free_particles)
1957 return;
1958 p = free_particles;
1959 free_particles = p->next;
1960 p->next = active_particles;
1961 active_particles = p;
1962
1963 p->time = cl.time;
1964
1965 dist = sin(ltime + i)*64;
1966 p->org[0] = ent->origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
1967 p->org[1] = ent->origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
1968 p->org[2] = ent->origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
1969
1970 VectorClear (p->vel);
1971 VectorClear (p->accel);
1972
1973 VectorSubtract (p->org, ent->origin, v);
1974 dist = VectorLength(v) / 90.0;
1975 p->color = floor (0xd0 + dist * 7);
1976 p->colorvel = 0;
1977
1978 p->alpha = 1.0 - dist;
1979 p->alphavel = -100;
1980 }
1981 }
1982
1983
1984 /*
1985 ===============
1986 CL_TrapParticles
1987 ===============
1988 */
1989 // RAFAEL
1990 void CL_TrapParticles (entity_t *ent)
1991 {
1992 vec3_t move;
1993 vec3_t vec;
1994 vec3_t start, end;
1995 float len;
1996 int j;
1997 cparticle_t *p;
1998 int dec;
1999
2000 ent->origin[2]-=14;
2001 VectorCopy (ent->origin, start);
2002 VectorCopy (ent->origin, end);
2003 end[2]+=64;
2004
2005 VectorCopy (start, move);
2006 VectorSubtract (end, start, vec);
2007 len = VectorNormalize (vec);
2008
2009 dec = 5;
2010 VectorScale (vec, 5, vec);
2011
2012 // FIXME: this is a really silly way to have a loop
2013 while (len > 0)
2014 {
2015 len -= dec;
2016
2017 if (!free_particles)
2018 return;
2019 p = free_particles;
2020 free_particles = p->next;
2021 p->next = active_particles;
2022 active_particles = p;
2023 VectorClear (p->accel);
2024
2025 p->time = cl.time;
2026
2027 p->alpha = 1.0;
2028 p->alphavel = -1.0 / (0.3+frand()*0.2);
2029 p->color = 0xe0;
2030 for (j=0 ; j<3 ; j++)
2031 {
2032 p->org[j] = move[j] + crand();
2033 p->vel[j] = crand()*15;
2034 p->accel[j] = 0;
2035 }
2036 p->accel[2] = PARTICLE_GRAVITY;
2037
2038 VectorAdd (move, vec, move);
2039 }
2040
2041 {
2042
2043
2044 int i, j, k;
2045 cparticle_t *p;
2046 float vel;
2047 vec3_t dir;
2048 vec3_t org;
2049
2050
2051 ent->origin[2]+=14;
2052 VectorCopy (ent->origin, org);
2053
2054
2055 for (i=-2 ; i<=2 ; i+=4)
2056 for (j=-2 ; j<=2 ; j+=4)
2057 for (k=-2 ; k<=4 ; k+=4)
2058 {
2059 if (!free_particles)
2060 return;
2061 p = free_particles;
2062 free_particles = p->next;
2063 p->next = active_particles;
2064 active_particles = p;
2065
2066 p->time = cl.time;
2067 p->color = 0xe0 + (rand()&3);
2068
2069 p->alpha = 1.0;
2070 p->alphavel = -1.0 / (0.3 + (rand()&7) * 0.02);
2071
2072 p->org[0] = org[0] + i + ((rand()&23) * crand());
2073 p->org[1] = org[1] + j + ((rand()&23) * crand());
2074 p->org[2] = org[2] + k + ((rand()&23) * crand());
2075
2076 dir[0] = j * 8;
2077 dir[1] = i * 8;
2078 dir[2] = k * 8;
2079
2080 VectorNormalize (dir);
2081 vel = 50 + rand()&63;
2082 VectorScale (dir, vel, p->vel);
2083
2084 p->accel[0] = p->accel[1] = 0;
2085 p->accel[2] = -PARTICLE_GRAVITY;
2086 }
2087 }
2088 }
2089
2090
2091 /*
2092 ===============
2093 CL_BFGExplosionParticles
2094 ===============
2095 */
2096 //FIXME combined with CL_ExplosionParticles
2097 void CL_BFGExplosionParticles (vec3_t org)
2098 {
2099 int i, j;
2100 cparticle_t *p;
2101
2102 for (i=0 ; i<256 ; i++)
2103 {
2104 if (!free_particles)
2105 return;
2106 p = free_particles;
2107 free_particles = p->next;
2108 p->next = active_particles;
2109 active_particles = p;
2110
2111 p->time = cl.time;
2112 p->color = 0xd0 + (rand()&7);
2113
2114 for (j=0 ; j<3 ; j++)
2115 {
2116 p->org[j] = org[j] + ((rand()%32)-16);
2117 p->vel[j] = (rand()%384)-192;
2118 }
2119
2120 p->accel[0] = p->accel[1] = 0;
2121 p->accel[2] = -PARTICLE_GRAVITY;
2122 p->alpha = 1.0;
2123
2124 p->alphavel = -0.8 / (0.5 + frand()*0.3);
2125 }
2126 }
2127
2128
2129 /*
2130 ===============
2131 CL_TeleportParticles
2132
2133 ===============
2134 */
2135 void CL_TeleportParticles (vec3_t org)
2136 {
2137 int i, j, k;
2138 cparticle_t *p;
2139 float vel;
2140 vec3_t dir;
2141
2142 for (i=-16 ; i<=16 ; i+=4)
2143 for (j=-16 ; j<=16 ; j+=4)
2144 for (k=-16 ; k<=32 ; k+=4)
2145 {
2146 if (!free_particles)
2147 return;
2148 p = free_particles;
2149 free_particles = p->next;
2150 p->next = active_particles;
2151 active_particles = p;
2152
2153 p->time = cl.time;
2154 p->color = 7 + (rand()&7);
2155
2156 p->alpha = 1.0;
2157 p->alphavel = -1.0 / (0.3 + (rand()&7) * 0.02);
2158
2159 p->org[0] = org[0] + i + (rand()&3);
2160 p->org[1] = org[1] + j + (rand()&3);
2161 p->org[2] = org[2] + k + (rand()&3);
2162
2163 dir[0] = j*8;
2164 dir[1] = i*8;
2165 dir[2] = k*8;
2166
2167 VectorNormalize (dir);
2168 vel = 50 + (rand()&63);
2169 VectorScale (dir, vel, p->vel);
2170
2171 p->accel[0] = p->accel[1] = 0;
2172 p->accel[2] = -PARTICLE_GRAVITY;
2173 }
2174 }
2175
2176
2177 /*
2178 ===============
2179 CL_AddParticles
2180 ===============
2181 */
2182 void CL_AddParticles (void)
2183 {
2184 cparticle_t *p, *next;
2185 float alpha;
2186 float time, time2;
2187 vec3_t org;
2188 int color;
2189 cparticle_t *active, *tail;
2190
2191 active = NULL;
2192 tail = NULL;
2193
2194 for (p=active_particles ; p ; p=next)
2195 {
2196 next = p->next;
2197
2198 // PMM - added INSTANT_PARTICLE handling for heat beam
2199 if (p->alphavel != INSTANT_PARTICLE)
2200 {
2201 time = (cl.time - p->time)*0.001;
2202 alpha = p->alpha + time*p->alphavel;
2203 if (alpha <= 0)
2204 { // faded out
2205 p->next = free_particles;
2206 free_particles = p;
2207 continue;
2208 }
2209 }
2210 else
2211 {
2212 alpha = p->alpha;
2213 }
2214
2215 p->next = NULL;
2216 if (!tail)
2217 active = tail = p;
2218 else
2219 {
2220 tail->next = p;
2221 tail = p;
2222 }
2223
2224 if (alpha > 1.0)
2225 alpha = 1;
2226 color = p->color;
2227
2228 time2 = time*time;
2229
2230 org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2;
2231 org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2;
2232 org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2;
2233
2234 V_AddParticle (org, color, alpha);
2235 // PMM
2236 if (p->alphavel == INSTANT_PARTICLE)
2237 {
2238 p->alphavel = 0.0;
2239 p->alpha = 0.0;
2240 }
2241 }
2242
2243 active_particles = active;
2244 }
2245
2246
2247 /*
2248 ==============
2249 CL_EntityEvent
2250
2251 An entity has just been parsed that has an event value
2252
2253 the female events are there for backwards compatability
2254 ==============
2255 */
2256 extern struct sfx_s *cl_sfx_footsteps[4];
2257
2258 void CL_EntityEvent (entity_state_t *ent)
2259 {
2260 switch (ent->event)
2261 {
2262 case EV_ITEM_RESPAWN:
2263 S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0);
2264 CL_ItemRespawnParticles (ent->origin);
2265 break;
2266 case EV_PLAYER_TELEPORT:
2267 S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0);
2268 CL_TeleportParticles (ent->origin);
2269 break;
2270 case EV_FOOTSTEP:
2271 if (cl_footsteps->value)
2272 S_StartSound (NULL, ent->number, CHAN_BODY, cl_sfx_footsteps[rand()&3], 1, ATTN_NORM, 0);
2273 break;
2274 case EV_FALLSHORT:
2275 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("player/land1.wav"), 1, ATTN_NORM, 0);
2276 break;
2277 case EV_FALL:
2278 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall2.wav"), 1, ATTN_NORM, 0);
2279 break;
2280 case EV_FALLFAR:
2281 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall1.wav"), 1, ATTN_NORM, 0);
2282 break;
2283 }
2284 }
2285
2286
2287 /*
2288 ==============
2289 CL_ClearEffects
2290
2291 ==============
2292 */
2293 void CL_ClearEffects (void)
2294 {
2295 CL_ClearParticles ();
2296 CL_ClearDlights ();
2297 CL_ClearLightStyles ();
2298 }
2299