1 /*
2 * Copyright(c) 1997-2001 Id Software, Inc.
3 * Copyright(c) 2002 The Quakeforge Project.
4 * Copyright(c) 2006 Quetoo.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or(at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21 
22 #include "client.h"
23 
24 extern cvar_t *cl_railtrailcolor;
25 
26 void CL_LogoutEffect(vec3_t org, int type);
27 void CL_ItemRespawnParticles(vec3_t org);
28 
29 static vec3_t avelocities [NUMVERTEXNORMALS];
30 
31 
32 /*
33 CL_ParseMuzzleFlash
34 */
CL_ParseMuzzleFlash(void)35 void CL_ParseMuzzleFlash(void){
36 	int i, weapon, silenced;
37 	centity_t *pl;
38 	float volume;
39 	char soundname[64];
40 
41 	i = MSG_ReadShort(&net_message);
42 	if(i < 1 || i >= MAX_EDICTS){
43 		Com_Printf("CL_ParseMuzzleFlash: bad entity\n");
44 		return;
45 	}
46 
47 	weapon = MSG_ReadByte(&net_message);
48 	silenced = weapon & MZ_SILENCED;
49 	weapon &= ~MZ_SILENCED;
50 	pl = &cl_entities[i];
51 
52 	if(silenced)
53 		volume = 0.2f;
54 	else
55 		volume = 1.0f;
56 
57 	switch(weapon){
58 		case MZ_BLASTER:
59 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
60 			break;
61 		case MZ_HYPERBLASTER:
62 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
63 			break;
64 		case MZ_MACHINEGUN:
65 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
66 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
67 			break;
68 		case MZ_SHOTGUN:
69 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
70 			S_StartSound(NULL, i, CHAN_AUTO, S_RegisterSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
71 			break;
72 		case MZ_SSHOTGUN:
73 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
74 			break;
75 		case MZ_CHAINGUN1:
76 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
77 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
78 			break;
79 		case MZ_CHAINGUN2:
80 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
81 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
82 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
83 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
84 			break;
85 		case MZ_CHAINGUN3:
86 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
87 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
88 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
89 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
90 			Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav",(rand() % 5) + 1);
91 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
92 			break;
93 		case MZ_RAILGUN:
94 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
95 			break;
96 		case MZ_ROCKET:
97 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
98 			S_StartSound(NULL, i, CHAN_AUTO, S_RegisterSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
99 			break;
100 		case MZ_GRENADE:
101 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
102 			S_StartSound(NULL, i, CHAN_AUTO, S_RegisterSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
103 			break;
104 		case MZ_BFG:
105 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
106 			break;
107 
108 		case MZ_LOGIN:
109 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
110 			CL_LogoutEffect(pl->current.origin, weapon);
111 			break;
112 		case MZ_LOGOUT:
113 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
114 			CL_LogoutEffect(pl->current.origin, weapon);
115 			break;
116 		case MZ_RESPAWN:
117 			S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
118 			CL_LogoutEffect(pl->current.origin, weapon);
119 			break;
120 		default: break;
121 	}
122 }
123 
124 
125 /*
126 CL_ParseMuzzleFlash2
127 */
CL_ParseMuzzleFlash2(void)128 void CL_ParseMuzzleFlash2(void){
129 	int ent;
130 	vec3_t origin;
131 	int flash_number;
132 	vec3_t forward, right;
133 	char soundname[64];
134 
135 	ent = MSG_ReadShort(&net_message);
136 	if(ent < 1 || ent >= MAX_EDICTS){
137 		Com_Printf("CL_ParseMuzzleFlash2: bad entity");
138 		return;
139 	}
140 
141 	flash_number = MSG_ReadByte(&net_message);
142 
143 	// locate the origin
144 	AngleVectors(cl_entities[ent].current.angles, forward, right, NULL);
145 
146 	origin[0] = cl_entities[ent].current.origin[0] + forward[0] *
147 		monster_flash_offset[flash_number][0] + right[0] * monster_flash_offset[flash_number][1];
148 
149 	origin[1] = cl_entities[ent].current.origin[1] + forward[1] *
150 		monster_flash_offset[flash_number][0] + right[1] * monster_flash_offset[flash_number][1];
151 
152 	origin[2] = cl_entities[ent].current.origin[2] + forward[2] *
153 		monster_flash_offset[flash_number][0] + right[2] * monster_flash_offset[flash_number][1] +
154 		monster_flash_offset[flash_number][2];  //FIXME is this right?
155 
156 	switch(flash_number){
157 		case MZ2_INFANTRY_MACHINEGUN_1:
158 		case MZ2_INFANTRY_MACHINEGUN_2:
159 		case MZ2_INFANTRY_MACHINEGUN_3:
160 		case MZ2_INFANTRY_MACHINEGUN_4:
161 		case MZ2_INFANTRY_MACHINEGUN_5:
162 		case MZ2_INFANTRY_MACHINEGUN_6:
163 		case MZ2_INFANTRY_MACHINEGUN_7:
164 		case MZ2_INFANTRY_MACHINEGUN_8:
165 		case MZ2_INFANTRY_MACHINEGUN_9:
166 		case MZ2_INFANTRY_MACHINEGUN_10:
167 		case MZ2_INFANTRY_MACHINEGUN_11:
168 		case MZ2_INFANTRY_MACHINEGUN_12:
169 		case MZ2_INFANTRY_MACHINEGUN_13:
170 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
171 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
172 			break;
173 
174 		case MZ2_SOLDIER_MACHINEGUN_1:
175 		case MZ2_SOLDIER_MACHINEGUN_2:
176 		case MZ2_SOLDIER_MACHINEGUN_3:
177 		case MZ2_SOLDIER_MACHINEGUN_4:
178 		case MZ2_SOLDIER_MACHINEGUN_5:
179 		case MZ2_SOLDIER_MACHINEGUN_6:
180 		case MZ2_SOLDIER_MACHINEGUN_7:
181 		case MZ2_SOLDIER_MACHINEGUN_8:
182 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
183 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck3.wav"), 1, ATTN_NORM, 0);
184 			break;
185 
186 		case MZ2_GUNNER_MACHINEGUN_1:
187 		case MZ2_GUNNER_MACHINEGUN_2:
188 		case MZ2_GUNNER_MACHINEGUN_3:
189 		case MZ2_GUNNER_MACHINEGUN_4:
190 		case MZ2_GUNNER_MACHINEGUN_5:
191 		case MZ2_GUNNER_MACHINEGUN_6:
192 		case MZ2_GUNNER_MACHINEGUN_7:
193 		case MZ2_GUNNER_MACHINEGUN_8:
194 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
195 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck2.wav"), 1, ATTN_NORM, 0);
196 			break;
197 
198 		case MZ2_ACTOR_MACHINEGUN_1:
199 		case MZ2_SUPERTANK_MACHINEGUN_1:
200 		case MZ2_SUPERTANK_MACHINEGUN_2:
201 		case MZ2_SUPERTANK_MACHINEGUN_3:
202 		case MZ2_SUPERTANK_MACHINEGUN_4:
203 		case MZ2_SUPERTANK_MACHINEGUN_5:
204 		case MZ2_SUPERTANK_MACHINEGUN_6:
205 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
206 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
207 			break;
208 
209 		case MZ2_BOSS2_MACHINEGUN_L1:
210 		case MZ2_BOSS2_MACHINEGUN_L2:
211 		case MZ2_BOSS2_MACHINEGUN_L3:
212 		case MZ2_BOSS2_MACHINEGUN_L4:
213 		case MZ2_BOSS2_MACHINEGUN_L5:
214 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
215 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NONE, 0);
216 			break;
217 
218 		case MZ2_SOLDIER_BLASTER_1:
219 		case MZ2_SOLDIER_BLASTER_2:
220 		case MZ2_SOLDIER_BLASTER_3:
221 		case MZ2_SOLDIER_BLASTER_4:
222 		case MZ2_SOLDIER_BLASTER_5:
223 		case MZ2_SOLDIER_BLASTER_6:
224 		case MZ2_SOLDIER_BLASTER_7:
225 		case MZ2_SOLDIER_BLASTER_8:
226 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0);
227 			break;
228 
229 		case MZ2_FLYER_BLASTER_1:
230 		case MZ2_FLYER_BLASTER_2:
231 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("flyer/flyatck3.wav"), 1, ATTN_NORM, 0);
232 			break;
233 
234 		case MZ2_MEDIC_BLASTER_1:
235 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("medic/medatck1.wav"), 1, ATTN_NORM, 0);
236 			break;
237 
238 		case MZ2_HOVER_BLASTER_1:
239 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("hover/hovatck1.wav"), 1, ATTN_NORM, 0);
240 			break;
241 
242 		case MZ2_FLOAT_BLASTER_1:
243 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("floater/fltatck1.wav"), 1, ATTN_NORM, 0);
244 			break;
245 
246 		case MZ2_SOLDIER_SHOTGUN_1:
247 		case MZ2_SOLDIER_SHOTGUN_2:
248 		case MZ2_SOLDIER_SHOTGUN_3:
249 		case MZ2_SOLDIER_SHOTGUN_4:
250 		case MZ2_SOLDIER_SHOTGUN_5:
251 		case MZ2_SOLDIER_SHOTGUN_6:
252 		case MZ2_SOLDIER_SHOTGUN_7:
253 		case MZ2_SOLDIER_SHOTGUN_8:
254 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck1.wav"), 1, ATTN_NORM, 0);
255 			break;
256 
257 		case MZ2_TANK_BLASTER_1:
258 		case MZ2_TANK_BLASTER_2:
259 		case MZ2_TANK_BLASTER_3:
260 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
261 			break;
262 
263 		case MZ2_TANK_MACHINEGUN_1:
264 		case MZ2_TANK_MACHINEGUN_2:
265 		case MZ2_TANK_MACHINEGUN_3:
266 		case MZ2_TANK_MACHINEGUN_4:
267 		case MZ2_TANK_MACHINEGUN_5:
268 		case MZ2_TANK_MACHINEGUN_6:
269 		case MZ2_TANK_MACHINEGUN_7:
270 		case MZ2_TANK_MACHINEGUN_8:
271 		case MZ2_TANK_MACHINEGUN_9:
272 		case MZ2_TANK_MACHINEGUN_10:
273 		case MZ2_TANK_MACHINEGUN_11:
274 		case MZ2_TANK_MACHINEGUN_12:
275 		case MZ2_TANK_MACHINEGUN_13:
276 		case MZ2_TANK_MACHINEGUN_14:
277 		case MZ2_TANK_MACHINEGUN_15:
278 		case MZ2_TANK_MACHINEGUN_16:
279 		case MZ2_TANK_MACHINEGUN_17:
280 		case MZ2_TANK_MACHINEGUN_18:
281 		case MZ2_TANK_MACHINEGUN_19:
282 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
283 			Com_sprintf(soundname, sizeof(soundname), "tank/tnkatk2%c.wav", 'a' + rand() % 5);
284 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound(soundname), 1, ATTN_NORM, 0);
285 			break;
286 
287 		case MZ2_CHICK_ROCKET_1:
288 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0);
289 			break;
290 
291 		case MZ2_TANK_ROCKET_1:
292 		case MZ2_TANK_ROCKET_2:
293 		case MZ2_TANK_ROCKET_3:
294 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck1.wav"), 1, ATTN_NORM, 0);
295 			break;
296 
297 		case MZ2_SUPERTANK_ROCKET_1:
298 		case MZ2_SUPERTANK_ROCKET_2:
299 		case MZ2_SUPERTANK_ROCKET_3:
300 		case MZ2_BOSS2_ROCKET_1:
301 		case MZ2_BOSS2_ROCKET_2:
302 		case MZ2_BOSS2_ROCKET_3:
303 		case MZ2_BOSS2_ROCKET_4:
304 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0);
305 			break;
306 
307 		case MZ2_GUNNER_GRENADE_1:
308 		case MZ2_GUNNER_GRENADE_2:
309 		case MZ2_GUNNER_GRENADE_3:
310 		case MZ2_GUNNER_GRENADE_4:
311 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck3.wav"), 1, ATTN_NORM, 0);
312 			break;
313 
314 		case MZ2_MAKRON_BLASTER_1:
315 		case MZ2_MAKRON_BLASTER_2:
316 		case MZ2_MAKRON_BLASTER_3:
317 		case MZ2_MAKRON_BLASTER_4:
318 		case MZ2_MAKRON_BLASTER_5:
319 		case MZ2_MAKRON_BLASTER_6:
320 		case MZ2_MAKRON_BLASTER_7:
321 		case MZ2_MAKRON_BLASTER_8:
322 		case MZ2_MAKRON_BLASTER_9:
323 		case MZ2_MAKRON_BLASTER_10:
324 		case MZ2_MAKRON_BLASTER_11:
325 		case MZ2_MAKRON_BLASTER_12:
326 		case MZ2_MAKRON_BLASTER_13:
327 		case MZ2_MAKRON_BLASTER_14:
328 		case MZ2_MAKRON_BLASTER_15:
329 		case MZ2_MAKRON_BLASTER_16:
330 		case MZ2_MAKRON_BLASTER_17:
331 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0);
332 			break;
333 
334 		case MZ2_JORG_MACHINEGUN_L1:
335 		case MZ2_JORG_MACHINEGUN_L2:
336 		case MZ2_JORG_MACHINEGUN_L3:
337 		case MZ2_JORG_MACHINEGUN_L4:
338 		case MZ2_JORG_MACHINEGUN_L5:
339 		case MZ2_JORG_MACHINEGUN_L6:
340 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
341 			S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfive.wav"), 1, ATTN_NORM, 0);
342 			break;
343 
344 		case MZ2_JORG_MACHINEGUN_R1:
345 		case MZ2_JORG_MACHINEGUN_R2:
346 		case MZ2_JORG_MACHINEGUN_R3:
347 		case MZ2_JORG_MACHINEGUN_R4:
348 		case MZ2_JORG_MACHINEGUN_R5:
349 		case MZ2_JORG_MACHINEGUN_R6:
350 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
351 			break;
352 
353 		case MZ2_BOSS2_MACHINEGUN_R1:
354 		case MZ2_BOSS2_MACHINEGUN_R2:
355 		case MZ2_BOSS2_MACHINEGUN_R3:
356 		case MZ2_BOSS2_MACHINEGUN_R4:
357 		case MZ2_BOSS2_MACHINEGUN_R5:
358 			CL_ParticleEffect(origin, vec3_origin, 0, 40);
359 			break;
360 	}
361 }
362 
363 
364 /*
365 
366 PARTICLE MANAGEMENT
367 
368 */
369 
370 cparticle_t *active_particles, *free_particles;
371 
372 cparticle_t particles[MAX_PARTICLES];
373 int cl_numparticles = MAX_PARTICLES;
374 
375 
376 /*
377 CL_ClearParticles
378 */
CL_ClearParticles(void)379 void CL_ClearParticles(void){
380 	int i;
381 
382 	free_particles = &particles[0];
383 	active_particles = NULL;
384 
385 	for(i = 0;i < cl_numparticles; i++)
386 		particles[i].next = &particles[i + 1];
387 	particles[cl_numparticles - 1].next = NULL;
388 }
389 
390 
391 /*
392 CL_ParticleEffect
393 
394 Wall impact puffs
395 */
CL_ParticleEffect(vec3_t org,vec3_t dir,int color,int count)396 void CL_ParticleEffect(vec3_t org, vec3_t dir, int color, int count){
397 	int i, j;
398 	cparticle_t *p;
399 	float d;
400 
401 	for(i = 0; i < count; i++){
402 		if(!free_particles)
403 			return;
404 		p = free_particles;
405 		free_particles = p->next;
406 		p->next = active_particles;
407 		active_particles = p;
408 
409 		p->time = cl.time;
410 		p->color = color +(rand() & 7);
411 
412 		d = rand() & 31;
413 		for(j = 0; j < 3; j++){
414 			p->org[j] = org[j] +((rand() & 7) - 4) + d * dir[j];
415 			p->vel[j] = crand() * 20;
416 		}
417 
418 		p->accel[0] = p->accel[1] = 0;
419 		p->accel[2] = -PARTICLE_GRAVITY;
420 		p->alpha = 1.0;
421 
422 		p->alphavel = -1.0 /(0.5 + frand() * 0.3);
423 	}
424 }
425 
426 
427 /*
428 CL_ParticleEffect2
429 */
CL_ParticleEffect2(vec3_t org,vec3_t dir,int color,int count)430 void CL_ParticleEffect2(vec3_t org, vec3_t dir, int color, int count){
431 	int i, j;
432 	cparticle_t *p;
433 	float d;
434 
435 	for(i = 0; i < count; i++){
436 		if(!free_particles)
437 			return;
438 		p = free_particles;
439 		free_particles = p->next;
440 		p->next = active_particles;
441 		active_particles = p;
442 
443 		p->time = cl.time;
444 		p->color = color;
445 
446 		d = rand() & 7;
447 		for(j = 0; j < 3; j++){
448 			p->org[j] = org[j] +((rand() & 7) - 4) + d * dir[j];
449 			p->vel[j] = crand() * 20;
450 		}
451 
452 		p->accel[0] = p->accel[1] = 0;
453 		p->accel[2] = -PARTICLE_GRAVITY;
454 		p->alpha = 1.0;
455 
456 		p->alphavel = -1.0 /(0.5 + frand() * 0.3);
457 	}
458 }
459 
460 
461 // RAFAEL
462 /*
463 CL_ParticleEffect3
464 */
CL_ParticleEffect3(vec3_t org,vec3_t dir,int color,int count)465 void CL_ParticleEffect3(vec3_t org, vec3_t dir, int color, int count){
466 	int i, j;
467 	cparticle_t *p;
468 	float d;
469 
470 	for(i = 0; i < count; i++){
471 		if(!free_particles)
472 			return;
473 		p = free_particles;
474 		free_particles = p->next;
475 		p->next = active_particles;
476 		active_particles = p;
477 
478 		p->time = cl.time;
479 		p->color = color;
480 
481 		d = rand() & 7;
482 		for(j = 0; j < 3; j++){
483 			p->org[j] = org[j] + ((rand() & 7) - 4) + d * dir[j];
484 			p->vel[j] = crand() * 20;
485 		}
486 
487 		p->accel[0] = p->accel[1] = 0;
488 		p->accel[2] = PARTICLE_GRAVITY;
489 		p->alpha = 1.0;
490 
491 		p->alphavel = -1.0 / (0.5 + frand() * 0.3);
492 	}
493 }
494 
495 /*
496 CL_TeleporterParticles
497 */
CL_TeleporterParticles(entity_state_t * ent)498 void CL_TeleporterParticles(entity_state_t *ent){
499 	int i, j;
500 	cparticle_t *p;
501 
502 	for(i = 0; i < 8; i++){
503 		if(!free_particles)
504 			return;
505 		p = free_particles;
506 		free_particles = p->next;
507 		p->next = active_particles;
508 		active_particles = p;
509 
510 		p->time = cl.time;
511 		p->color = 0xdb;
512 
513 		for(j = 0; j < 2; j++){
514 			p->org[j] = ent->origin[j] - 16 + (rand() & 31);
515 			p->vel[j] = crand() * 14;
516 		}
517 
518 		p->org[2] = ent->origin[2] - 8 + (rand() & 7);
519 		p->vel[2] = 80 + (rand() & 7);
520 
521 		p->accel[0] = p->accel[1] = 0;
522 		p->accel[2] = -PARTICLE_GRAVITY;
523 		p->alpha = 1.0;
524 
525 		p->alphavel = -0.5;
526 	}
527 }
528 
529 
530 /*
531 CL_LogoutEffect
532 
533 */
CL_LogoutEffect(vec3_t org,int type)534 void CL_LogoutEffect(vec3_t org, int type){
535 	int i, j;
536 	cparticle_t *p;
537 
538 	for(i = 0; i < 500; i++){
539 		if(!free_particles)
540 			return;
541 		p = free_particles;
542 		free_particles = p->next;
543 		p->next = active_particles;
544 		active_particles = p;
545 
546 		p->time = cl.time;
547 
548 		if(type == MZ_LOGIN)
549 			p->color = 0xd0 +(rand() & 7);  // green
550 		else if(type == MZ_LOGOUT)
551 			p->color = 0x40 +(rand() & 7);  // red
552 		else
553 			p->color = 0xe0 +(rand() & 7);  // yellow
554 
555 		p->org[0] = org[0] - 16 + frand() * 32;
556 		p->org[1] = org[1] - 16 + frand() * 32;
557 		p->org[2] = org[2] - 24 + frand() * 56;
558 
559 		for(j = 0; j < 3; j++)
560 			p->vel[j] = crand() * 20;
561 
562 		p->accel[0] = p->accel[1] = 0;
563 		p->accel[2] = -PARTICLE_GRAVITY;
564 		p->alpha = 1.0;
565 
566 		p->alphavel = -1.0 /(1.0 + frand() * 0.3);
567 	}
568 }
569 
570 
571 /*
572 CL_ItemRespawnParticles
573 
574 */
CL_ItemRespawnParticles(vec3_t org)575 void CL_ItemRespawnParticles(vec3_t org){
576 	int i, j;
577 	cparticle_t *p;
578 
579 	for(i = 0; i < 64; i++){
580 		if(!free_particles)
581 			return;
582 		p = free_particles;
583 		free_particles = p->next;
584 		p->next = active_particles;
585 		active_particles = p;
586 
587 		p->time = cl.time;
588 
589 		p->color = 0xd4 +(rand() & 3);  // green
590 
591 		p->org[0] = org[0] + crand() * 8;
592 		p->org[1] = org[1] + crand() * 8;
593 		p->org[2] = org[2] + crand() * 8;
594 
595 		for(j = 0; j < 3; j++)
596 			p->vel[j] = crand() * 8;
597 
598 		p->accel[0] = p->accel[1] = 0;
599 		p->accel[2] = -PARTICLE_GRAVITY * 0.2;
600 		p->alpha = 1.0;
601 
602 		p->alphavel = -1.0 /(1.0 + frand() * 0.3);
603 	}
604 }
605 
606 
607 /*
608 CL_ExplosionParticles
609 */
CL_ExplosionParticles(vec3_t org)610 void CL_ExplosionParticles(vec3_t org){
611 	int i, j;
612 	cparticle_t *p;
613 
614 	for(i = 0; i < 256; i++){
615 		if(!free_particles)
616 			return;
617 		p = free_particles;
618 		free_particles = p->next;
619 		p->next = active_particles;
620 		active_particles = p;
621 
622 		p->time = cl.time;
623 		p->color = 0xe0 +(rand() & 7);
624 
625 		for(j = 0; j < 3; j++){
626 			p->org[j] = org[j] +((rand() % 32) - 16);
627 			p->vel[j] =(rand() % 384) - 192;
628 		}
629 
630 		p->accel[0] = p->accel[1] = 0;
631 		p->accel[2] = -PARTICLE_GRAVITY;
632 		p->alpha = 1.0;
633 
634 		p->alphavel = -0.8 /(0.5 + frand() * 0.3);
635 	}
636 }
637 
638 
639 /*
640 CL_BigTeleportParticles
641 */
CL_BigTeleportParticles(vec3_t org)642 void CL_BigTeleportParticles(vec3_t org){
643 	int i;
644 	cparticle_t *p;
645 	float angle, dist;
646 	static int colortable[4] = {2 * 8, 13 * 8, 21 * 8, 18 * 8};
647 
648 	for(i = 0; i < 4096; i++){
649 		if(!free_particles)
650 			return;
651 		p = free_particles;
652 		free_particles = p->next;
653 		p->next = active_particles;
654 		active_particles = p;
655 
656 		p->time = cl.time;
657 
658 		p->color = colortable[rand() & 3];
659 
660 		angle = M_PI * 2 *(rand() & 1023) / 1023.0;
661 		dist = rand() & 31;
662 		p->org[0] = org[0] + cos(angle) * dist;
663 		p->vel[0] = cos(angle) *(70 +(rand() & 63));
664 		p->accel[0] = -cos(angle) * 100;
665 
666 		p->org[1] = org[1] + sin(angle) * dist;
667 		p->vel[1] = sin(angle) *(70 +(rand() & 63));
668 		p->accel[1] = -sin(angle) * 100;
669 
670 		p->org[2] = org[2] + 8 +(rand() % 90);
671 		p->vel[2] = -100 +(rand() & 31);
672 		p->accel[2] = PARTICLE_GRAVITY * 4;
673 		p->alpha = 1.0;
674 
675 		p->alphavel = -0.3 /(0.5 + frand() * 0.3);
676 	}
677 }
678 
679 
680 /*
681 CL_BlasterParticles
682 
683 Wall impact puffs
684 */
CL_BlasterParticles(vec3_t org,vec3_t dir)685 void CL_BlasterParticles(vec3_t org, vec3_t dir){
686 	int i, j;
687 	cparticle_t *p;
688 	float d;
689 	int count;
690 
691 	count = 40;
692 	for(i = 0; i < count; i++){
693 		if(!free_particles)
694 			return;
695 		p = free_particles;
696 		free_particles = p->next;
697 		p->next = active_particles;
698 		active_particles = p;
699 
700 		p->time = cl.time;
701 		p->color = 0xe0 + (rand() & 7);
702 
703 		d = rand() & 15;
704 		for(j = 0; j < 3; j++){
705 			p->org[j] = org[j] + ((rand() & 7) - 4) + d * dir[j];
706 			p->vel[j] = dir[j] * 30 + crand() * 40;
707 		}
708 
709 		p->accel[0] = p->accel[1] = 0;
710 		p->accel[2] = -PARTICLE_GRAVITY;
711 		p->alpha = 1.0;
712 
713 		p->alphavel = -1.0 / (0.5 + frand() * 0.3);
714 	}
715 }
716 
717 
718 /*
719 CL_BlasterTrail
720 
721 */
CL_BlasterTrail(vec3_t start,vec3_t end)722 void CL_BlasterTrail(vec3_t start, vec3_t end){
723 	vec3_t move;
724 	vec3_t vec;
725 	float len;
726 	int j;
727 	cparticle_t *p;
728 	int dec;
729 
730 	VectorCopy(start, move);
731 	VectorSubtract(end, start, vec);
732 	len = VectorNormalize(vec) / 10;
733 
734 	dec = 100;
735 	VectorScale(vec, 5, vec);
736 
737 	// FIXME: this is a really silly way to have a loop
738 	while(len > 0){
739 		len -= dec;
740 
741 		if(!free_particles)
742 			return;
743 		p = free_particles;
744 		free_particles = p->next;
745 		p->next = active_particles;
746 		active_particles = p;
747 		VectorClear(p->accel);
748 
749 		p->time = cl.time;
750 
751 		p->alpha = 1.0;
752 		p->alphavel = -1.0 /(0.3 + frand() * 0.2);
753 		p->color = 0xe0;
754 		for(j = 0; j < 3; j++){
755 			p->org[j] = move[j] + crand();
756 			p->vel[j] = crand() * 5;
757 			p->accel[j] = 0;
758 		}
759 
760 		VectorAdd(move, vec, move);
761 	}
762 }
763 
764 /*
765 CL_QuadTrail
766 
767 */
CL_QuadTrail(vec3_t start,vec3_t end)768 void CL_QuadTrail(vec3_t start, vec3_t end){
769 	vec3_t move;
770 	vec3_t vec;
771 	float len;
772 	int j;
773 	cparticle_t *p;
774 	int dec;
775 
776 	VectorCopy(start, move);
777 	VectorSubtract(end, start, vec);
778 	len = VectorNormalize(vec);
779 
780 	dec = 5;
781 	VectorScale(vec, 5, vec);
782 
783 	while(len > 0){
784 		len -= dec;
785 
786 		if(!free_particles)
787 			return;
788 		p = free_particles;
789 		free_particles = p->next;
790 		p->next = active_particles;
791 		active_particles = p;
792 		VectorClear(p->accel);
793 
794 		p->time = cl.time;
795 
796 		p->alpha = 1.0;
797 		p->alphavel = -1.0 /(0.8 + frand() * 0.2);
798 		p->color = 115;
799 		for(j = 0; j < 3; j++){
800 			p->org[j] = move[j] + crand() * 16;
801 			p->vel[j] = crand() * 5;
802 			p->accel[j] = 0;
803 		}
804 
805 		VectorAdd(move, vec, move);
806 	}
807 }
808 
809 /*
810 CL_FlagTrail
811 
812 */
CL_FlagTrail(vec3_t start,vec3_t end,float color)813 void CL_FlagTrail(vec3_t start, vec3_t end, float color){
814 	vec3_t move;
815 	vec3_t vec;
816 	float len;
817 	int j;
818 	cparticle_t *p;
819 	int dec;
820 
821 	VectorCopy(start, move);
822 	VectorSubtract(end, start, vec);
823 	len = VectorNormalize(vec);
824 
825 	dec = 5;
826 	VectorScale(vec, 5, vec);
827 
828 	while(len > 0){
829 		len -= dec;
830 
831 		if(!free_particles)
832 			return;
833 		p = free_particles;
834 		free_particles = p->next;
835 		p->next = active_particles;
836 		active_particles = p;
837 		VectorClear(p->accel);
838 
839 		p->time = cl.time;
840 
841 		p->alpha = 1.0;
842 		p->alphavel = -1.0 /(0.8 + frand() * 0.2);
843 		p->color = color;
844 		for(j = 0; j < 3; j++){
845 			p->org[j] = move[j] + crand() * 16;
846 			p->vel[j] = crand() * 5;
847 			p->accel[j] = 0;
848 		}
849 
850 		VectorAdd(move, vec, move);
851 	}
852 }
853 
854 /*
855 CL_DiminishingTrail
856 
857 */
CL_DiminishingTrail(vec3_t start,vec3_t end,centity_t * old,int flags)858 void CL_DiminishingTrail(vec3_t start, vec3_t end, centity_t *old, int flags){
859 	vec3_t move;
860 	vec3_t vec;
861 	float len;
862 	int j;
863 	cparticle_t *p;
864 	float dec;
865 	float orgscale;
866 	float velscale;
867 
868 	VectorCopy(start, move);
869 	VectorSubtract(end, start, vec);
870 	len = VectorNormalize(vec);
871 
872 	dec = 0.5;
873 	VectorScale(vec, dec, vec);
874 
875 	if(old->trailcount > 900){
876 		orgscale = 4;
877 		velscale = 15;
878 	} else if(old->trailcount > 800){
879 		orgscale = 2;
880 		velscale = 10;
881 	} else {
882 		orgscale = 1;
883 		velscale = 5;
884 	}
885 
886 	while(len > 0){
887 		len -= dec;
888 
889 		if(!free_particles)
890 			return;
891 
892 		// drop less particles as it flies
893 		if((rand() & 1023) < old->trailcount){
894 			p = free_particles;
895 			free_particles = p->next;
896 			p->next = active_particles;
897 			active_particles = p;
898 			VectorClear(p->accel);
899 
900 			p->time = cl.time;
901 
902 			if(flags & EF_GIB){
903 				p->alpha = 1.0;
904 				p->alphavel = -1.0 / (1 + frand() * 0.4);
905 				p->color = 0xe8 + (rand() & 7);
906 				for(j = 0; j < 3; j++){
907 					p->org[j] = move[j] + crand() * orgscale;
908 					p->vel[j] = crand() * velscale;
909 					p->accel[j] = 0;
910 				}
911 				p->vel[2] -= PARTICLE_GRAVITY;
912 			} else {
913 				p->alpha = 1.0;
914 				p->alphavel = -1.0 / (1 + frand() * 0.2);
915 				p->color = 4 + (rand() & 7);
916 				for(j = 0; j < 3; j++){
917 					p->org[j] = move[j] + crand() * orgscale;
918 					p->vel[j] = crand() * velscale;
919 				}
920 				p->accel[2] = 20;
921 			}
922 		}
923 
924 		old->trailcount -= 5;
925 		if(old->trailcount < 100)
926 			old->trailcount = 100;
927 		VectorAdd(move, vec, move);
928 	}
929 }
930 
MakeNormalVectors(vec3_t forward,vec3_t right,vec3_t up)931 void MakeNormalVectors(vec3_t forward, vec3_t right, vec3_t up){
932 	float d;
933 
934 	// this rotate and negat guarantees a vector
935 	// not colinear with the original
936 	right[1] = -forward[0];
937 	right[2] = forward[1];
938 	right[0] = forward[2];
939 
940 	d = DotProduct(right, forward);
941 	VectorMA(right, -d, forward, right);
942 	VectorNormalize(right);
943 	CrossProduct(right, forward, up);
944 }
945 
946 /*
947 CL_RocketTrail
948 
949 */
CL_RocketTrail(vec3_t start,vec3_t end,centity_t * old)950 void CL_RocketTrail(vec3_t start, vec3_t end, centity_t *old){
951 	CL_DiminishingTrail(start, end, old, EF_ROCKET);
952 }
953 
954 /*
955 CL_RailTrail
956 
957 */
CL_RailTrail(vec3_t start,vec3_t end)958 void CL_RailTrail(vec3_t start, vec3_t end){
959 	vec3_t move;
960 	vec3_t vec;
961 	float len;
962 	int j;
963 	cparticle_t *p;
964 	vec3_t right, up;
965 	int i;
966 	float d, c, s;
967 	vec3_t dir;
968 	static byte clr = 0x34;
969 
970 	VectorCopy(start, move);
971 	VectorSubtract(end, start, vec);
972 	len = VectorNormalize(vec);
973 
974 	MakeNormalVectors(vec, right, up);
975 
976 	if (cl_railtrailcolor->modified) {
977 		if (!strcmp(cl_railtrailcolor->string, "blue"))
978 			clr = 0x74;	/* vanilla q2 color */
979 		else if (!strcmp(cl_railtrailcolor->string, "tan"))
980 			clr = 0x34;	/* quetoo default one */
981 		else	/* unrecognized values are either numbers or zero
982 			   if it was string (but none of the above), so
983 			   it is safe to assign numeric here.  hex numbers
984 			   are already taken care of automagically for us */
985 			clr = cl_railtrailcolor->value;
986 		cl_railtrailcolor->modified = false;
987 	}
988 
989 	for(i = 0; i < len; i++){
990 		if(!free_particles)
991 			return;
992 
993 		p = free_particles;
994 		free_particles = p->next;
995 		p->next = active_particles;
996 		active_particles = p;
997 
998 		p->time = cl.time;
999 		VectorClear(p->accel);
1000 
1001 		d = i * 0.1;
1002 		c = cos(d);
1003 		s = sin(d);
1004 
1005 		VectorScale(right, c, dir);
1006 		VectorMA(dir, s, up, dir);
1007 
1008 		p->alpha = 1.0;
1009 		p->alphavel = -1.0 / (1 + frand() * 0.2);
1010 		p->color = clr + (rand() & 7);
1011 		for(j = 0; j < 3; j++){
1012 			p->org[j] = move[j] + dir[j] * 3;
1013 			p->vel[j] = dir[j] * 6;
1014 		}
1015 
1016 		VectorAdd(move, vec, move);
1017 	}
1018 }
1019 
1020 /*
1021 CL_BubbleTrail
1022 
1023 */
CL_BubbleTrail(vec3_t start,vec3_t end)1024 void CL_BubbleTrail(vec3_t start, vec3_t end){
1025 	vec3_t move;
1026 	vec3_t vec;
1027 	float len;
1028 	int i, j;
1029 	cparticle_t *p;
1030 	float dec;
1031 
1032 	VectorCopy(start, move);
1033 	VectorSubtract(end, start, vec);
1034 	len = VectorNormalize(vec);
1035 
1036 	dec = 32;
1037 	VectorScale(vec, dec, vec);
1038 
1039 	for(i = 0; i < len; i += dec){
1040 		if(!free_particles)
1041 			return;
1042 
1043 		p = free_particles;
1044 		free_particles = p->next;
1045 		p->next = active_particles;
1046 		active_particles = p;
1047 
1048 		VectorClear(p->accel);
1049 		p->time = cl.time;
1050 
1051 		p->alpha = 1.0;
1052 		p->alphavel = -1.0 / (1 + frand() * 0.2);
1053 		p->color = 4 + (rand() & 7);
1054 		for(j = 0; j < 3; j++){
1055 			p->org[j] = move[j] + crand() * 2;
1056 			p->vel[j] = crand() * 5;
1057 		}
1058 		p->vel[2] += 6;
1059 
1060 		VectorAdd(move, vec, move);
1061 	}
1062 }
1063 
1064 /*
1065 CL_FlyParticles
1066 */
1067 
1068 #define BEAMLENGTH 16
CL_FlyParticles(vec3_t origin,int count)1069 void CL_FlyParticles(vec3_t origin, int count){
1070 	int i;
1071 	cparticle_t *p;
1072 	float angle;
1073 	float sr, sp, sy, cr, cp, cy;
1074 	vec3_t forward;
1075 	float dist = 64;
1076 	float ltime;
1077 
1078 
1079 	if(count > NUMVERTEXNORMALS)
1080 		count = NUMVERTEXNORMALS;
1081 
1082 	if(!avelocities[0][0]){
1083 		for(i = 0; i < NUMVERTEXNORMALS * 3; i++)
1084 			avelocities[0][i] = (rand() & 255) * 0.01;
1085 	}
1086 
1087 	ltime = (float)cl.time / 1000.0;
1088 	for(i = 0; i < count; i += 2){
1089 		angle = ltime * avelocities[i][0];
1090 		sy = sin(angle);
1091 		cy = cos(angle);
1092 		angle = ltime * avelocities[i][1];
1093 		sp = sin(angle);
1094 		cp = cos(angle);
1095 		angle = ltime * avelocities[i][2];
1096 		sr = sin(angle);
1097 		cr = cos(angle);
1098 
1099 		forward[0] = cp * cy;
1100 		forward[1] = cp * sy;
1101 		forward[2] = -sp;
1102 
1103 		if(!free_particles)
1104 			return;
1105 		p = free_particles;
1106 		free_particles = p->next;
1107 		p->next = active_particles;
1108 		active_particles = p;
1109 
1110 		p->time = cl.time;
1111 
1112 		dist = sin(ltime + i) * 64;
1113 		p->org[0] = origin[0] + bytedirs[i][0] * dist + forward[0] * BEAMLENGTH;
1114 		p->org[1] = origin[1] + bytedirs[i][1] * dist + forward[1] * BEAMLENGTH;
1115 		p->org[2] = origin[2] + bytedirs[i][2] * dist + forward[2] * BEAMLENGTH;
1116 
1117 		VectorClear(p->vel);
1118 		VectorClear(p->accel);
1119 
1120 		p->color = 0;
1121 		p->colorvel = 0;
1122 
1123 		p->alpha = 1;
1124 		p->alphavel = -100;
1125 	}
1126 }
1127 
CL_FlyEffect(centity_t * ent,vec3_t origin)1128 void CL_FlyEffect(centity_t *ent, vec3_t origin){
1129 	int n;
1130 	int count;
1131 	int starttime;
1132 
1133 	if(ent->fly_stoptime < cl.time){
1134 		starttime = cl.time;
1135 		ent->fly_stoptime = cl.time + 60000;
1136 	} else {
1137 		starttime = ent->fly_stoptime - 60000;
1138 	}
1139 
1140 	n = cl.time - starttime;
1141 	if(n < 20000)
1142 		count = n * 162 / 20000.0;
1143 	else {
1144 		n = ent->fly_stoptime - cl.time;
1145 		if(n < 20000)
1146 			count = n * 162 / 20000.0;
1147 		else
1148 			count = 162;
1149 	}
1150 
1151 	CL_FlyParticles(origin, count);
1152 }
1153 
1154 
1155 /*
1156 CL_BFGParticles
1157 */
1158 
1159 #define BEAMLENGTH 16
CL_BFGParticles(entity_t * ent)1160 void CL_BFGParticles(entity_t *ent){
1161 	int i;
1162 	cparticle_t *p;
1163 	float angle;
1164 	float sr, sp, sy, cr, cp, cy;
1165 	vec3_t forward;
1166 	float dist = 64;
1167 	vec3_t v;
1168 	float ltime;
1169 
1170 	if(!avelocities[0][0]){
1171 		for(i = 0; i < NUMVERTEXNORMALS * 3; i++)
1172 			avelocities[0][i] = (rand() & 255) * 0.01;
1173 	}
1174 
1175 
1176 	ltime = (float)cl.time / 1000.0;
1177 	for(i = 0; i < NUMVERTEXNORMALS; i++){
1178 		angle = ltime * avelocities[i][0];
1179 		sy = sin(angle);
1180 		cy = cos(angle);
1181 		angle = ltime * avelocities[i][1];
1182 		sp = sin(angle);
1183 		cp = cos(angle);
1184 		angle = ltime * avelocities[i][2];
1185 		sr = sin(angle);
1186 		cr = cos(angle);
1187 
1188 		forward[0] = cp * cy;
1189 		forward[1] = cp * sy;
1190 		forward[2] = -sp;
1191 
1192 		if(!free_particles)
1193 			return;
1194 		p = free_particles;
1195 		free_particles = p->next;
1196 		p->next = active_particles;
1197 		active_particles = p;
1198 
1199 		p->time = cl.time;
1200 
1201 		dist = sin(ltime + i) * 32;
1202 		p->org[0] = ent->origin[0] + bytedirs[i][0] * dist + forward[0] * BEAMLENGTH;
1203 		p->org[1] = ent->origin[1] + bytedirs[i][1] * dist + forward[1] * BEAMLENGTH;
1204 		p->org[2] = ent->origin[2] + bytedirs[i][2] * dist + forward[2] * BEAMLENGTH;
1205 
1206 		VectorClear(p->vel);
1207 		VectorClear(p->accel);
1208 
1209 		VectorSubtract(p->org, ent->origin, v);
1210 		dist = VectorLength(v) / 90.0;
1211 		p->color = floor(0xd0 + dist * 7);
1212 		p->colorvel = 0;
1213 
1214 		p->alpha = 1.0 - dist;
1215 		p->alphavel = -100;
1216 	}
1217 }
1218 
1219 
1220 /*
1221 CL_BFGExplosionParticles
1222 */
CL_BFGExplosionParticles(vec3_t org)1223 void CL_BFGExplosionParticles(vec3_t org){
1224 	int i, j;
1225 	cparticle_t *p;
1226 
1227 	for(i = 0; i < 128; i++){
1228 		if(!free_particles)
1229 			return;
1230 		p = free_particles;
1231 		free_particles = p->next;
1232 		p->next = active_particles;
1233 		active_particles = p;
1234 
1235 		p->time = cl.time;
1236 		p->color = 0xd0 + (rand() & 7);
1237 
1238 		for(j = 0; j < 3; j++){
1239 			p->org[j] = org[j] + ((rand() % 32) - 16);
1240 			p->vel[j] = (rand() % 384) - 192;
1241 		}
1242 
1243 		p->accel[0] = p->accel[1] = 0;
1244 		p->accel[2] = -PARTICLE_GRAVITY;
1245 		p->alpha = 1.0;
1246 
1247 		p->alphavel = -0.8 / (0.5 + frand() * 0.3);
1248 	}
1249 }
1250 
1251 
1252 /*
1253 CL_TeleportParticles
1254 
1255 */
CL_TeleportParticles(vec3_t org)1256 void CL_TeleportParticles(vec3_t org){
1257 	int i, j, k;
1258 	cparticle_t *p;
1259 	float vel;
1260 	vec3_t dir;
1261 
1262 	for(i = -16; i <= 16; i += 4)
1263 		for(j = -16; j <= 16; j += 4)
1264 			for(k = -16; k <= 32; k += 4){
1265 				if(!free_particles)
1266 					return;
1267 				p = free_particles;
1268 				free_particles = p->next;
1269 				p->next = active_particles;
1270 				active_particles = p;
1271 
1272 				p->time = cl.time;
1273 				p->color = 7 + (rand() & 7);
1274 
1275 				p->alpha = 1.0;
1276 				p->alphavel = -1.0 / (0.3 + (rand() & 7) * 0.02);
1277 
1278 				p->org[0] = org[0] + i +(rand() & 3);
1279 				p->org[1] = org[1] + j +(rand() & 3);
1280 				p->org[2] = org[2] + k +(rand() & 3);
1281 
1282 				dir[0] = j * 8;
1283 				dir[1] = i * 8;
1284 				dir[2] = k * 8;
1285 
1286 				VectorNormalize(dir);
1287 				vel = 50 +(rand() & 63);
1288 				VectorScale(dir, vel, p->vel);
1289 
1290 				p->accel[0] = p->accel[1] = 0;
1291 				p->accel[2] = -PARTICLE_GRAVITY;
1292 			}
1293 }
1294 
1295 
1296 /*
1297 CL_AddParticles
1298 */
CL_AddParticles(void)1299 void CL_AddParticles(void){
1300 	cparticle_t *p, *next;
1301 	float alpha;
1302 	float time, time2;
1303 	vec3_t org;
1304 	int color;
1305 	cparticle_t *active, *tail;
1306 
1307 	active = NULL;
1308 	tail = NULL;
1309 
1310 	for(p = active_particles; p; p = next){
1311 		next = p->next;
1312 
1313 		time = (cl.time - p->time) * 0.001;
1314 		alpha = p->alpha + time * p->alphavel;
1315 		if(alpha <= 0){  // faded out
1316 			p->next = free_particles;
1317 			free_particles = p;
1318 			continue;
1319 		}
1320 
1321 		p->next = NULL;
1322 		if(!tail)
1323 			active = tail = p;
1324 		else {
1325 			tail->next = p;
1326 			tail = p;
1327 		}
1328 
1329 		if(alpha > 1.0)
1330 			alpha = 1;
1331 		color = p->color;
1332 
1333 		time2 = time * time;
1334 
1335 		org[0] = p->org[0] + p->vel[0] * time + p->accel[0] * time2;
1336 		org[1] = p->org[1] + p->vel[1] * time + p->accel[1] * time2;
1337 		org[2] = p->org[2] + p->vel[2] * time + p->accel[2] * time2;
1338 
1339 		V_AddParticle(org, color, alpha);
1340 	}
1341 
1342 	active_particles = active;
1343 }
1344 
1345 
1346 /*
1347 CL_EntityEvent
1348 
1349 An entity has just been parsed that has an event value
1350 
1351 the female events are there for backwards compatability
1352 */
1353 extern struct sfx_s	*cl_sfx_footsteps[4];
1354 
CL_EntityEvent(entity_state_t * ent)1355 void CL_EntityEvent(entity_state_t *ent){
1356 	switch(ent->event){
1357 		case EV_ITEM_RESPAWN:
1358 			S_StartSound(NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0);
1359 			CL_ItemRespawnParticles(ent->origin);
1360 			break;
1361 		case EV_PLAYER_TELEPORT:
1362 			S_StartSound(NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0);
1363 			CL_TeleportParticles(ent->origin);
1364 			break;
1365 		case EV_FOOTSTEP:
1366 			if(cl_footsteps->value)
1367 				S_StartSound(NULL, ent->number, CHAN_BODY, cl_sfx_footsteps[rand()&3], 1, ATTN_NORM, 0);
1368 			break;
1369 		case EV_FALLSHORT:
1370 			S_StartSound(NULL, ent->number, CHAN_AUTO, S_RegisterSound("player/land1.wav"), 1, ATTN_NORM, 0);
1371 			break;
1372 		case EV_FALL:
1373 			S_StartSound(NULL, ent->number, CHAN_AUTO, S_RegisterSound("*fall2.wav"), 1, ATTN_NORM, 0);
1374 			break;
1375 		case EV_FALLFAR:
1376 			S_StartSound(NULL, ent->number, CHAN_AUTO, S_RegisterSound("*fall1.wav"), 1, ATTN_NORM, 0);
1377 			break;
1378 	}
1379 }
1380 
1381 
1382 /*
1383 CL_ClearEffects
1384 
1385 */
CL_ClearEffects(void)1386 void CL_ClearEffects(void){
1387 	CL_ClearParticles();
1388 }
1389