Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

cl_fx.c (49451B)


      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 }