#include "client.h"
void CL_LogoutEffect(vec3_t org, int type);
void CL_ItemRespawnParticles(vec3_t org);
static vec3_t avelocities[NUMVERTEXNORMALS];
extern struct model_s *cl_mod_smoke;
extern struct model_s *cl_mod_flash;
typedef struct {
int length;
float value[3];
float map[MAX_QPATH];
} clightstyle_t;
clightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
int lastofs;
void CL_ClearLightStyles(void) {
memset(cl_lightstyle, 0, sizeof(cl_lightstyle));
lastofs = -1;
}
void CL_RunLightStyles(void) {
int ofs;
int i;
clightstyle_t *ls;
ofs = cl.time / 100;
if(ofs == lastofs)
return;
lastofs = ofs;
for(i = 0, ls = cl_lightstyle; i < MAX_LIGHTSTYLES; i++, ls++) {
if(!ls->length) {
ls->value[0] = ls->value[1] = ls->value[2] = 1.0;
continue;
}
if(ls->length == 1)
ls->value[0] = ls->value[1] = ls->value[2] = ls->map[0];
else
ls->value[0] = ls->value[1] = ls->value[2] = ls->map[ofs % ls->length];
}
}
void CL_SetLightstyle(int i) {
char *s;
int j, k;
s = cl.configstrings[i + CS_LIGHTS];
j = strlen(s);
if(j >= MAX_QPATH)
Com_Error(ERR_DROP, "svc_lightstyle length=%i", j);
cl_lightstyle[i].length = j;
for(k = 0; k < j; k++)
cl_lightstyle[i].map[k] = (float)(s[k] - 'a') / (float)('m' - 'a');
}
void CL_AddLightStyles(void) {
int i;
clightstyle_t *ls;
for(i = 0, ls = cl_lightstyle; i < MAX_LIGHTSTYLES; i++, ls++)
V_AddLightStyle(i, ls->value[0], ls->value[1], ls->value[2]);
}
cdlight_t cl_dlights[MAX_DLIGHTS];
void CL_ClearDlights(void) { memset(cl_dlights, 0, sizeof(cl_dlights)); }
cdlight_t *CL_AllocDlight(int key) {
int i;
cdlight_t *dl;
if(key) {
dl = cl_dlights;
for(i = 0; i < MAX_DLIGHTS; i++, dl++) {
if(dl->key == key) {
memset(dl, 0, sizeof(*dl));
dl->key = key;
return dl;
}
}
}
dl = cl_dlights;
for(i = 0; i < MAX_DLIGHTS; i++, dl++) {
if(dl->die < cl.time) {
memset(dl, 0, sizeof(*dl));
dl->key = key;
return dl;
}
}
dl = &cl_dlights[0];
memset(dl, 0, sizeof(*dl));
dl->key = key;
return dl;
}
void CL_NewDlight(int key, float x, float y, float z, float radius, float time) {
cdlight_t *dl;
dl = CL_AllocDlight(key);
dl->origin[0] = x;
dl->origin[1] = y;
dl->origin[2] = z;
dl->radius = radius;
dl->die = cl.time + time;
}
void CL_RunDLights(void) {
int i;
cdlight_t *dl;
dl = cl_dlights;
for(i = 0; i < MAX_DLIGHTS; i++, dl++) {
if(!dl->radius)
continue;
if(dl->die < cl.time) {
dl->radius = 0;
return;
}
dl->radius -= cls.frametime * dl->decay;
if(dl->radius < 0)
dl->radius = 0;
}
}
void CL_ParseMuzzleFlash(void) {
vec3_t fv, rv;
cdlight_t *dl;
int i, weapon;
centity_t *pl;
int silenced;
float volume;
char soundname[64];
i = MSG_ReadShort(&net_message);
if(i < 1 || i >= MAX_EDICTS)
Com_Error(ERR_DROP, "CL_ParseMuzzleFlash: bad entity");
weapon = MSG_ReadByte(&net_message);
silenced = weapon & MZ_SILENCED;
weapon &= ~MZ_SILENCED;
pl = &cl_entities[i];
dl = CL_AllocDlight(i);
VectorCopy(pl->current.origin, dl->origin);
AngleVectors(pl->current.angles, fv, rv, NULL);
VectorMA(dl->origin, 18, fv, dl->origin);
VectorMA(dl->origin, 16, rv, dl->origin);
if(silenced)
dl->radius = 100 + (rand() & 31);
else
dl->radius = 200 + (rand() & 31);
dl->minlight = 32;
dl->die = cl.time;
if(silenced)
volume = 0.2;
else
volume = 1;
switch(weapon) {
case MZ_BLASTER:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
break;
case MZ_BLUEHYPERBLASTER:
dl->color[0] = 0;
dl->color[1] = 0;
dl->color[2] = 1;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
break;
case MZ_HYPERBLASTER:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
break;
case MZ_MACHINEGUN:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
break;
case MZ_SHOTGUN:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
S_StartSound(NULL, i, CHAN_AUTO, S_RegisterSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case MZ_SSHOTGUN:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
break;
case MZ_CHAINGUN1:
dl->radius = 200 + (rand() & 31);
dl->color[0] = 1;
dl->color[1] = 0.25;
dl->color[2] = 0;
Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
break;
case MZ_CHAINGUN2:
dl->radius = 225 + (rand() & 31);
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0;
dl->die = cl.time + 0.1; Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
break;
case MZ_CHAINGUN3:
dl->radius = 250 + (rand() & 31);
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
dl->die = cl.time + 0.1; Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
break;
case MZ_RAILGUN:
dl->color[0] = 0.5;
dl->color[1] = 0.5;
dl->color[2] = 1.0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
break;
case MZ_ROCKET:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0.2;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
S_StartSound(NULL, i, CHAN_AUTO, S_RegisterSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case MZ_GRENADE:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
S_StartSound(NULL, i, CHAN_AUTO, S_RegisterSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case MZ_BFG:
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
break;
case MZ_LOGIN:
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 0;
dl->die = cl.time + 1.0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
CL_LogoutEffect(pl->current.origin, weapon);
break;
case MZ_LOGOUT:
dl->color[0] = 1;
dl->color[1] = 0;
dl->color[2] = 0;
dl->die = cl.time + 1.0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
CL_LogoutEffect(pl->current.origin, weapon);
break;
case MZ_RESPAWN:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
dl->die = cl.time + 1.0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
CL_LogoutEffect(pl->current.origin, weapon);
break;
case MZ_PHALANX:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0.5;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/plasshot.wav"), volume, ATTN_NORM, 0);
break;
case MZ_IONRIPPER:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0.5;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0);
break;
case MZ_ETF_RIFLE:
dl->color[0] = 0.9;
dl->color[1] = 0.7;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/nail1.wav"), volume, ATTN_NORM, 0);
break;
case MZ_SHOTGUN2:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0);
break;
case MZ_HEATBEAM:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case MZ_BLASTER2:
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
break;
case MZ_TRACKER:
dl->color[0] = -1;
dl->color[1] = -1;
dl->color[2] = -1;
S_StartSound(NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), volume, ATTN_NORM, 0);
break;
case MZ_NUKE1:
dl->color[0] = 1;
dl->color[1] = 0;
dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case MZ_NUKE2:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case MZ_NUKE4:
dl->color[0] = 0;
dl->color[1] = 0;
dl->color[2] = 1;
dl->die = cl.time + 100;
break;
case MZ_NUKE8:
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 1;
dl->die = cl.time + 100;
break;
}
}
void CL_ParseMuzzleFlash2(void) {
int ent;
vec3_t origin;
int flash_number;
cdlight_t *dl;
vec3_t forward, right;
char soundname[64];
ent = MSG_ReadShort(&net_message);
if(ent < 1 || ent >= MAX_EDICTS)
Com_Error(ERR_DROP, "CL_ParseMuzzleFlash2: bad entity");
flash_number = MSG_ReadByte(&net_message);
AngleVectors(cl_entities[ent].current.angles, forward, right, NULL);
origin[0] = cl_entities[ent].current.origin[0] + forward[0] * monster_flash_offset[flash_number][0] +
right[0] * monster_flash_offset[flash_number][1];
origin[1] = cl_entities[ent].current.origin[1] + forward[1] * monster_flash_offset[flash_number][0] +
right[1] * monster_flash_offset[flash_number][1];
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];
dl = CL_AllocDlight(ent);
VectorCopy(origin, dl->origin);
dl->radius = 200 + (rand() & 31);
dl->minlight = 32;
dl->die = cl.time;
switch(flash_number) {
case MZ2_INFANTRY_MACHINEGUN_1:
case MZ2_INFANTRY_MACHINEGUN_2:
case MZ2_INFANTRY_MACHINEGUN_3:
case MZ2_INFANTRY_MACHINEGUN_4:
case MZ2_INFANTRY_MACHINEGUN_5:
case MZ2_INFANTRY_MACHINEGUN_6:
case MZ2_INFANTRY_MACHINEGUN_7:
case MZ2_INFANTRY_MACHINEGUN_8:
case MZ2_INFANTRY_MACHINEGUN_9:
case MZ2_INFANTRY_MACHINEGUN_10:
case MZ2_INFANTRY_MACHINEGUN_11:
case MZ2_INFANTRY_MACHINEGUN_12:
case MZ2_INFANTRY_MACHINEGUN_13:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_SOLDIER_MACHINEGUN_1:
case MZ2_SOLDIER_MACHINEGUN_2:
case MZ2_SOLDIER_MACHINEGUN_3:
case MZ2_SOLDIER_MACHINEGUN_4:
case MZ2_SOLDIER_MACHINEGUN_5:
case MZ2_SOLDIER_MACHINEGUN_6:
case MZ2_SOLDIER_MACHINEGUN_7:
case MZ2_SOLDIER_MACHINEGUN_8:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck3.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_GUNNER_MACHINEGUN_1:
case MZ2_GUNNER_MACHINEGUN_2:
case MZ2_GUNNER_MACHINEGUN_3:
case MZ2_GUNNER_MACHINEGUN_4:
case MZ2_GUNNER_MACHINEGUN_5:
case MZ2_GUNNER_MACHINEGUN_6:
case MZ2_GUNNER_MACHINEGUN_7:
case MZ2_GUNNER_MACHINEGUN_8:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck2.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_ACTOR_MACHINEGUN_1:
case MZ2_SUPERTANK_MACHINEGUN_1:
case MZ2_SUPERTANK_MACHINEGUN_2:
case MZ2_SUPERTANK_MACHINEGUN_3:
case MZ2_SUPERTANK_MACHINEGUN_4:
case MZ2_SUPERTANK_MACHINEGUN_5:
case MZ2_SUPERTANK_MACHINEGUN_6:
case MZ2_TURRET_MACHINEGUN: dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_BOSS2_MACHINEGUN_L1:
case MZ2_BOSS2_MACHINEGUN_L2:
case MZ2_BOSS2_MACHINEGUN_L3:
case MZ2_BOSS2_MACHINEGUN_L4:
case MZ2_BOSS2_MACHINEGUN_L5:
case MZ2_CARRIER_MACHINEGUN_L1: case MZ2_CARRIER_MACHINEGUN_L2: dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NONE, 0);
break;
case MZ2_SOLDIER_BLASTER_1:
case MZ2_SOLDIER_BLASTER_2:
case MZ2_SOLDIER_BLASTER_3:
case MZ2_SOLDIER_BLASTER_4:
case MZ2_SOLDIER_BLASTER_5:
case MZ2_SOLDIER_BLASTER_6:
case MZ2_SOLDIER_BLASTER_7:
case MZ2_SOLDIER_BLASTER_8:
case MZ2_TURRET_BLASTER: dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_FLYER_BLASTER_1:
case MZ2_FLYER_BLASTER_2:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("flyer/flyatck3.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_MEDIC_BLASTER_1:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("medic/medatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_HOVER_BLASTER_1:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("hover/hovatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_FLOAT_BLASTER_1:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("floater/fltatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_SOLDIER_SHOTGUN_1:
case MZ2_SOLDIER_SHOTGUN_2:
case MZ2_SOLDIER_SHOTGUN_3:
case MZ2_SOLDIER_SHOTGUN_4:
case MZ2_SOLDIER_SHOTGUN_5:
case MZ2_SOLDIER_SHOTGUN_6:
case MZ2_SOLDIER_SHOTGUN_7:
case MZ2_SOLDIER_SHOTGUN_8:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_TANK_BLASTER_1:
case MZ2_TANK_BLASTER_2:
case MZ2_TANK_BLASTER_3:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_TANK_MACHINEGUN_1:
case MZ2_TANK_MACHINEGUN_2:
case MZ2_TANK_MACHINEGUN_3:
case MZ2_TANK_MACHINEGUN_4:
case MZ2_TANK_MACHINEGUN_5:
case MZ2_TANK_MACHINEGUN_6:
case MZ2_TANK_MACHINEGUN_7:
case MZ2_TANK_MACHINEGUN_8:
case MZ2_TANK_MACHINEGUN_9:
case MZ2_TANK_MACHINEGUN_10:
case MZ2_TANK_MACHINEGUN_11:
case MZ2_TANK_MACHINEGUN_12:
case MZ2_TANK_MACHINEGUN_13:
case MZ2_TANK_MACHINEGUN_14:
case MZ2_TANK_MACHINEGUN_15:
case MZ2_TANK_MACHINEGUN_16:
case MZ2_TANK_MACHINEGUN_17:
case MZ2_TANK_MACHINEGUN_18:
case MZ2_TANK_MACHINEGUN_19:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
Com_sprintf(soundname, sizeof(soundname), "tank/tnkatk2%c.wav", 'a' + rand() % 5);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound(soundname), 1, ATTN_NORM, 0);
break;
case MZ2_CHICK_ROCKET_1:
case MZ2_TURRET_ROCKET: dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0.2;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_TANK_ROCKET_1:
case MZ2_TANK_ROCKET_2:
case MZ2_TANK_ROCKET_3:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0.2;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck1.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_SUPERTANK_ROCKET_1:
case MZ2_SUPERTANK_ROCKET_2:
case MZ2_SUPERTANK_ROCKET_3:
case MZ2_BOSS2_ROCKET_1:
case MZ2_BOSS2_ROCKET_2:
case MZ2_BOSS2_ROCKET_3:
case MZ2_BOSS2_ROCKET_4:
case MZ2_CARRIER_ROCKET_1:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0.2;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_GUNNER_GRENADE_1:
case MZ2_GUNNER_GRENADE_2:
case MZ2_GUNNER_GRENADE_3:
case MZ2_GUNNER_GRENADE_4:
dl->color[0] = 1;
dl->color[1] = 0.5;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck3.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_GLADIATOR_RAILGUN_1:
case MZ2_CARRIER_RAILGUN:
case MZ2_WIDOW_RAIL:
dl->color[0] = 0.5;
dl->color[1] = 0.5;
dl->color[2] = 1.0;
break;
case MZ2_MAKRON_BFG:
dl->color[0] = 0.5;
dl->color[1] = 1;
dl->color[2] = 0.5;
break;
case MZ2_MAKRON_BLASTER_1:
case MZ2_MAKRON_BLASTER_2:
case MZ2_MAKRON_BLASTER_3:
case MZ2_MAKRON_BLASTER_4:
case MZ2_MAKRON_BLASTER_5:
case MZ2_MAKRON_BLASTER_6:
case MZ2_MAKRON_BLASTER_7:
case MZ2_MAKRON_BLASTER_8:
case MZ2_MAKRON_BLASTER_9:
case MZ2_MAKRON_BLASTER_10:
case MZ2_MAKRON_BLASTER_11:
case MZ2_MAKRON_BLASTER_12:
case MZ2_MAKRON_BLASTER_13:
case MZ2_MAKRON_BLASTER_14:
case MZ2_MAKRON_BLASTER_15:
case MZ2_MAKRON_BLASTER_16:
case MZ2_MAKRON_BLASTER_17:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_JORG_MACHINEGUN_L1:
case MZ2_JORG_MACHINEGUN_L2:
case MZ2_JORG_MACHINEGUN_L3:
case MZ2_JORG_MACHINEGUN_L4:
case MZ2_JORG_MACHINEGUN_L5:
case MZ2_JORG_MACHINEGUN_L6:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfire.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_JORG_MACHINEGUN_R1:
case MZ2_JORG_MACHINEGUN_R2:
case MZ2_JORG_MACHINEGUN_R3:
case MZ2_JORG_MACHINEGUN_R4:
case MZ2_JORG_MACHINEGUN_R5:
case MZ2_JORG_MACHINEGUN_R6:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
break;
case MZ2_JORG_BFG_1:
dl->color[0] = 0.5;
dl->color[1] = 1;
dl->color[2] = 0.5;
break;
case MZ2_BOSS2_MACHINEGUN_R1:
case MZ2_BOSS2_MACHINEGUN_R2:
case MZ2_BOSS2_MACHINEGUN_R3:
case MZ2_BOSS2_MACHINEGUN_R4:
case MZ2_BOSS2_MACHINEGUN_R5:
case MZ2_CARRIER_MACHINEGUN_R1: case MZ2_CARRIER_MACHINEGUN_R2:
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
CL_ParticleEffect(origin, vec3_origin, 0, 40);
CL_SmokeAndFlash(origin);
break;
case MZ2_STALKER_BLASTER:
case MZ2_DAEDALUS_BLASTER:
case MZ2_MEDIC_BLASTER_2:
case MZ2_WIDOW_BLASTER:
case MZ2_WIDOW_BLASTER_SWEEP1:
case MZ2_WIDOW_BLASTER_SWEEP2:
case MZ2_WIDOW_BLASTER_SWEEP3:
case MZ2_WIDOW_BLASTER_SWEEP4:
case MZ2_WIDOW_BLASTER_SWEEP5:
case MZ2_WIDOW_BLASTER_SWEEP6:
case MZ2_WIDOW_BLASTER_SWEEP7:
case MZ2_WIDOW_BLASTER_SWEEP8:
case MZ2_WIDOW_BLASTER_SWEEP9:
case MZ2_WIDOW_BLASTER_100:
case MZ2_WIDOW_BLASTER_90:
case MZ2_WIDOW_BLASTER_80:
case MZ2_WIDOW_BLASTER_70:
case MZ2_WIDOW_BLASTER_60:
case MZ2_WIDOW_BLASTER_50:
case MZ2_WIDOW_BLASTER_40:
case MZ2_WIDOW_BLASTER_30:
case MZ2_WIDOW_BLASTER_20:
case MZ2_WIDOW_BLASTER_10:
case MZ2_WIDOW_BLASTER_0:
case MZ2_WIDOW_BLASTER_10L:
case MZ2_WIDOW_BLASTER_20L:
case MZ2_WIDOW_BLASTER_30L:
case MZ2_WIDOW_BLASTER_40L:
case MZ2_WIDOW_BLASTER_50L:
case MZ2_WIDOW_BLASTER_60L:
case MZ2_WIDOW_BLASTER_70L:
case MZ2_WIDOW_RUN_1:
case MZ2_WIDOW_RUN_2:
case MZ2_WIDOW_RUN_3:
case MZ2_WIDOW_RUN_4:
case MZ2_WIDOW_RUN_5:
case MZ2_WIDOW_RUN_6:
case MZ2_WIDOW_RUN_7:
case MZ2_WIDOW_RUN_8:
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 0;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_WIDOW_DISRUPTOR:
dl->color[0] = -1;
dl->color[1] = -1;
dl->color[2] = -1;
S_StartSound(NULL, ent, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), 1, ATTN_NORM, 0);
break;
case MZ2_WIDOW_PLASMABEAM:
case MZ2_WIDOW2_BEAMER_1:
case MZ2_WIDOW2_BEAMER_2:
case MZ2_WIDOW2_BEAMER_3:
case MZ2_WIDOW2_BEAMER_4:
case MZ2_WIDOW2_BEAMER_5:
case MZ2_WIDOW2_BEAM_SWEEP_1:
case MZ2_WIDOW2_BEAM_SWEEP_2:
case MZ2_WIDOW2_BEAM_SWEEP_3:
case MZ2_WIDOW2_BEAM_SWEEP_4:
case MZ2_WIDOW2_BEAM_SWEEP_5:
case MZ2_WIDOW2_BEAM_SWEEP_6:
case MZ2_WIDOW2_BEAM_SWEEP_7:
case MZ2_WIDOW2_BEAM_SWEEP_8:
case MZ2_WIDOW2_BEAM_SWEEP_9:
case MZ2_WIDOW2_BEAM_SWEEP_10:
case MZ2_WIDOW2_BEAM_SWEEP_11:
dl->radius = 300 + (rand() & 100);
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0;
dl->die = cl.time + 200;
break;
}
}
void CL_AddDLights(void) {
int i;
cdlight_t *dl;
dl = cl_dlights;
for(i = 0; i < MAX_DLIGHTS; i++, dl++) {
if(!dl->radius)
continue;
V_AddLight(dl->origin, dl->radius, dl->color[0], dl->color[1], dl->color[2]);
}
}
void CL_AddParticle(const vec3_t origin, const vec3_t velocity, const vec3_t acceleration, int albedo, int emit,
float alpha, float alphavel, float incandescence, float incandescencevel) {
void GL_AddParticle(float time, const vec3_t origin, const vec3_t velocity, const vec3_t acceleration, int albedo,
int emit, float alpha, float alphavel, float incandescence, float incandescencevel);
GL_AddParticle(cl.time * 0.001, origin, velocity, acceleration, albedo, emit, alpha, alphavel, incandescence,
incandescencevel);
}
void CL_ParticleEffect(vec3_t org, vec3_t dir, int color, int count) {
int i, j;
cparticle_t p;
float d;
memset(&p, 0, sizeof(p));
for(i = 0; i < count; i++) {
p.albedo = color + (rand() & 7);
d = rand() & 31;
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() & 7) - 4) + d * dir[j];
p.vel[j] = crand() * 20;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -1.0 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_ParticleEffect2(vec3_t org, vec3_t dir, int color, int count) {
int i, j;
cparticle_t p;
float d;
memset(&p, 0, sizeof(p));
for(i = 0; i < count; i++) {
p.albedo = color;
p.emit = 0;
d = rand() & 7;
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() & 7) - 4) + d * dir[j];
p.vel[j] = crand() * 20;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -1.0 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_ParticleEffect3(vec3_t org, vec3_t dir, int color, int count) {
int i, j;
cparticle_t p;
float d;
memset(&p, 0, sizeof(p));
for(i = 0; i < count; i++) {
p.albedo = color;
d = rand() & 7;
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() & 7) - 4) + d * dir[j];
p.vel[j] = crand() * 20;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -1.0 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_TeleporterParticles(entity_state_t *ent) {
int i, j;
cparticle_t p;
memset(&p, 0, sizeof(p));
for(i = 0; i < 80; i++) {
p.albedo = (i & 3) * 0x20 + (rand() & 2);
p.emit = p.albedo;
for(j = 0; j < 2; j++) {
p.org[j] = ent->origin[j] - 16 + (rand() & 31);
p.vel[j] = frand() * 8 + 8;
}
p.vel[i & 1] *= ((i >> 1) & 1) ? 4 : -4;
p.org[2] = ent->origin[2] - 16 + (rand() & 7);
p.vel[2] = 80 + (rand() & 31);
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -0.5;
p.incandescence = 2;
p.incandescencevel = 0;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_LogoutEffect(vec3_t org, int type) {
int i, j;
cparticle_t p;
memset(&p, 0, sizeof(p));
for(i = 0; i < 500; i++) {
if(type == MZ_LOGIN)
p.albedo = 0xd0 + (rand() & 7); else if(type == MZ_LOGOUT)
p.albedo = 0x40 + (rand() & 7); else
p.albedo = 0xe0 + (rand() & 7);
p.org[0] = org[0] - 16 + frand() * 32;
p.org[1] = org[1] - 16 + frand() * 32;
p.org[2] = org[2] - 24 + frand() * 56;
for(j = 0; j < 3; j++)
p.vel[j] = crand() * 20;
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -1.0 / (1.0 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_ItemRespawnParticles(vec3_t org) {
int i, j;
cparticle_t p;
memset(&p, 0, sizeof(p));
for(i = 0; i < 64; i++) {
p.albedo = 0xd4 + (rand() & 3);
p.org[0] = org[0] + crand() * 8;
p.org[1] = org[1] + crand() * 8;
p.org[2] = org[2] + crand() * 8;
for(j = 0; j < 3; j++)
p.vel[j] = crand() * 8;
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY * 0.2;
p.alpha = 1.0;
p.alphavel = -1.0 / (1.0 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_ExplosionParticles(vec3_t org) {
int i, j;
cparticle_t p;
memset(&p, 0, sizeof(p));
for(i = 0; i < 256; i++) {
p.albedo = 0xe0 + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() % 32) - 16);
p.vel[j] = (rand() % 384) - 192;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -0.8 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_BigTeleportParticles(vec3_t org) {
int i;
cparticle_t p;
float angle, dist;
static int colortable[4] = {2 * 8, 13 * 8, 21 * 8, 18 * 8};
memset(&p, 0, sizeof(p));
for(i = 0; i < 4096; i++) {
p.albedo = colortable[rand() & 3];
angle = M_PI * 2 * (rand() & 1023) / 1023.0;
dist = rand() & 31;
p.org[0] = org[0] + cos(angle) * dist;
p.vel[0] = cos(angle) * (70 + (rand() & 63));
p.accel[0] = -cos(angle) * 100;
p.org[1] = org[1] + sin(angle) * dist;
p.vel[1] = sin(angle) * (70 + (rand() & 63));
p.accel[1] = -sin(angle) * 100;
p.org[2] = org[2] + 8 + (rand() % 90);
p.vel[2] = -100 + (rand() & 31);
p.accel[2] = PARTICLE_GRAVITY * 4;
p.alpha = 1.0;
p.alphavel = -0.3 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_BlasterParticles(vec3_t org, vec3_t dir) {
int i, j;
cparticle_t p;
float d;
int count;
memset(&p, 0, sizeof(p));
count = 40;
for(i = 0; i < count; i++) {
p.albedo = 0xe0 + (rand() & 7);
d = rand() & 15;
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() & 7) - 4) + d * dir[j];
p.vel[j] = dir[j] * 30 + crand() * 40;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -1.0 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_BlasterTrail(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
int dec;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = 5;
VectorScale(vec, 5, vec);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (0.3 + frand() * 0.2);
p.albedo = 0xe0;
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand();
p.vel[j] = crand() * 5;
p.accel[j] = 0;
}
VectorAdd(move, vec, move);
p.emit = p.albedo;
p.albedo = 0;
p.incandescence = 2;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_QuadTrail(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
int dec;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = 5;
VectorScale(vec, 5, vec);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (0.8 + frand() * 0.2);
p.albedo = 115;
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 16;
p.vel[j] = crand() * 5;
p.accel[j] = 0;
}
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_FlagTrail(vec3_t start, vec3_t end, float color) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
int dec;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = 5;
VectorScale(vec, 5, vec);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (0.8 + frand() * 0.2);
p.albedo = color;
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 16;
p.vel[j] = crand() * 5;
p.accel[j] = 0;
}
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_DiminishingTrail(vec3_t start, vec3_t end, centity_t *old, int flags) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
float dec;
float orgscale;
float velscale;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = 0.5;
VectorScale(vec, dec, vec);
if(old->trailcount > 900) {
orgscale = 4;
velscale = 15;
} else if(old->trailcount > 800) {
orgscale = 2;
velscale = 10;
} else {
orgscale = 1;
velscale = 5;
}
while(len > 0) {
len -= dec;
if((rand() & 1023) < old->trailcount) {
VectorClear(p.accel);
if(flags & EF_GIB) {
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.4);
p.albedo = 0xe8 + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * orgscale;
p.vel[j] = crand() * velscale;
p.accel[j] = 0;
}
p.vel[2] -= PARTICLE_GRAVITY;
} else if(flags & EF_GREENGIB) {
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.4);
p.albedo = 0xdb + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * orgscale;
p.vel[j] = crand() * velscale;
p.accel[j] = 0;
}
p.vel[2] -= PARTICLE_GRAVITY;
} else {
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.2);
p.albedo = 4 + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * orgscale;
p.vel[j] = crand() * velscale;
}
p.accel[2] = 20;
if(flags & EF_ROCKET) {
p.emit = 0xdc + (rand() & 3);
p.incandescence = 1;
p.incandescencevel = p.alphavel * 4;
}
}
}
old->trailcount -= 5;
if(old->trailcount < 100)
old->trailcount = 100;
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void MakeNormalVectors(vec3_t forward, vec3_t right, vec3_t up) {
float d;
right[1] = -forward[0];
right[2] = forward[1];
right[0] = forward[2];
d = DotProduct(right, forward);
VectorMA(right, -d, forward, right);
VectorNormalize(right);
CrossProduct(right, forward, up);
}
void CL_RocketTrail(vec3_t start, vec3_t end, centity_t *old) {
cparticle_t p;
memset(&p, 0, sizeof(p));
CL_DiminishingTrail(start, end, old, EF_ROCKET);
}
void CL_RailTrail(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
float dec;
vec3_t right, up;
int i;
float d, c, s;
vec3_t dir;
byte clr = 0x74;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
MakeNormalVectors(vec, right, up);
for(i = 0; i < len; i++) {
VectorClear(p.accel);
d = i * 0.1;
c = cos(d);
s = sin(d);
VectorScale(right, c, dir);
VectorMA(dir, s, up, dir);
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.2);
p.albedo = clr + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + dir[j] * 3;
p.vel[j] = dir[j] * 6;
}
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
dec = 0.75;
VectorScale(vec, dec, vec);
VectorCopy(start, move);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (0.6 + frand() * 0.2);
p.albedo = 0x0 + (rand() & 15);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 3;
p.vel[j] = crand() * 3;
p.accel[j] = 0;
}
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_IonripperTrail(vec3_t start, vec3_t ent) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
int dec;
int left = 0;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(ent, start, vec);
len = VectorNormalize(vec);
dec = 5;
VectorScale(vec, 5, vec);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.time = cl.time;
p.alpha = 0.5;
p.alphavel = -1.0 / (0.3 + frand() * 0.2);
p.albedo = 0xe4 + (rand() & 3);
for(j = 0; j < 3; j++) {
p.org[j] = move[j];
p.accel[j] = 0;
}
if(left) {
left = 0;
p.vel[0] = 10;
} else {
left = 1;
p.vel[0] = -10;
}
p.vel[1] = 0;
p.vel[2] = 0;
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_BubbleTrail(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int i, j;
cparticle_t p;
float dec;
memset(&p, 0, sizeof(p));
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = 32;
VectorScale(vec, dec, vec);
for(i = 0; i < len; i += dec) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.2);
p.albedo = 4 + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 2;
p.vel[j] = crand() * 5;
}
p.vel[2] += 6;
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
#define BEAMLENGTH 16
void CL_FlyParticles(vec3_t origin, int count) {
int i;
cparticle_t p;
vec3_t forward;
float dist = 64;
float ltime;
memset(&p, 0, sizeof(p));
if(count > NUMVERTEXNORMALS)
count = NUMVERTEXNORMALS;
if(!avelocities[0][0]) {
for(i = 0; i < NUMVERTEXNORMALS * 3; i++)
avelocities[0][i] = (rand() & 255) * 0.01;
}
ltime = (float)cl.time / 1000.0;
for(i = 0; i < count; i += 2) {
float angle = ltime * avelocities[i][0];
float sy = sin(angle);
float cy = cos(angle);
angle = ltime * avelocities[i][1];
float sp = sin(angle);
float cp = cos(angle);
forward[0] = cp * cy;
forward[1] = cp * sy;
forward[2] = -sp;
dist = sin(ltime + i) * 64;
p.org[0] = origin[0] + bytedirs[i][0] * dist + forward[0] * BEAMLENGTH;
p.org[1] = origin[1] + bytedirs[i][1] * dist + forward[1] * BEAMLENGTH;
p.org[2] = origin[2] + bytedirs[i][2] * dist + forward[2] * BEAMLENGTH;
VectorClear(p.vel);
VectorClear(p.accel);
p.albedo = 0;
p.alpha = 1;
p.alphavel = -100;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_FlyEffect(centity_t *ent, vec3_t origin) {
int n;
int count;
int starttime;
if(ent->fly_stoptime < cl.time) {
starttime = cl.time;
ent->fly_stoptime = cl.time + 60000;
} else {
starttime = ent->fly_stoptime - 60000;
}
n = cl.time - starttime;
if(n < 20000)
count = n * 162 / 20000.0;
else {
n = ent->fly_stoptime - cl.time;
if(n < 20000)
count = n * 162 / 20000.0;
else
count = 162;
}
CL_FlyParticles(origin, count);
}
#define BEAMLENGTH 16
void CL_BfgParticles(entity_t *ent) {
int i;
cparticle_t p;
vec3_t forward;
float dist = 64;
vec3_t v;
float ltime;
memset(&p, 0, sizeof(p));
if(!avelocities[0][0]) {
for(i = 0; i < NUMVERTEXNORMALS * 3; i++)
avelocities[0][i] = (rand() & 255) * 0.01;
}
ltime = (float)cl.time / 1000.0;
for(i = 0; i < NUMVERTEXNORMALS; i++) {
float angle = ltime * avelocities[i][0];
float sy = sin(angle); float cy = cos(angle); angle = ltime * avelocities[i][1];
float sp = sin(angle); float cp = cos(angle);
forward[0] = cp * cy;
forward[1] = cp * sy;
forward[2] = -sp;
dist = sin(ltime + i) * 64;
p.org[0] = ent->origin[0] + bytedirs[i][0] * dist + forward[0] * BEAMLENGTH;
p.org[1] = ent->origin[1] + bytedirs[i][1] * dist + forward[1] * BEAMLENGTH;
p.org[2] = ent->origin[2] + bytedirs[i][2] * dist + forward[2] * BEAMLENGTH;
VectorClear(p.vel);
VectorClear(p.accel);
VectorSubtract(p.org, ent->origin, v);
dist = VectorLength(v) / 90.0;
p.albedo = floor(0xd0 + dist * 7);
p.alpha = 1.0 - dist;
p.alphavel = -100;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_TrapParticles(entity_t *ent) {
vec3_t move;
vec3_t vec;
vec3_t start, end;
float len;
int j;
cparticle_t p;
int dec;
memset(&p, 0, sizeof(p));
ent->origin[2] -= 14;
VectorCopy(ent->origin, start);
VectorCopy(ent->origin, end);
end[2] += 64;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = 5;
VectorScale(vec, 5, vec);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.time = cl.time;
p.alpha = 1.0;
p.alphavel = -1.0 / (0.3 + frand() * 0.2);
p.albedo = 0xe0;
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand();
p.vel[j] = crand() * 15;
p.accel[j] = 0;
}
p.accel[2] = PARTICLE_GRAVITY;
VectorAdd(move, vec, move);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
{
int i, j, k;
cparticle_t p;
float vel;
vec3_t dir;
vec3_t org;
ent->origin[2] += 14;
VectorCopy(ent->origin, org);
for(i = -2; i <= 2; i += 4)
for(j = -2; j <= 2; j += 4)
for(k = -2; k <= 4; k += 4) {
p.albedo = 0xe0 + (rand() & 3);
p.alpha = 1.0;
p.alphavel = -1.0 / (0.3 + (rand() & 7) * 0.02);
p.org[0] = org[0] + i + ((rand() & 23) * crand());
p.org[1] = org[1] + j + ((rand() & 23) * crand());
p.org[2] = org[2] + k + ((rand() & 23) * crand());
dir[0] = j * 8;
dir[1] = i * 8;
dir[2] = k * 8;
VectorNormalize(dir);
vel = 50 + (rand() & 63);
VectorScale(dir, vel, p.vel);
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence,
p.incandescencevel);
}
}
}
void CL_BFGExplosionParticles(vec3_t org) {
int i, j;
cparticle_t p;
memset(&p, 0, sizeof(p));
for(i = 0; i < 256; i++) {
p.albedo = 0xd0 + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() % 32) - 16);
p.vel[j] = (rand() % 384) - 192;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -0.8 / (0.5 + frand() * 0.3);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_TeleportParticles(vec3_t org) {
int i, j, k;
cparticle_t p;
float vel;
vec3_t dir;
memset(&p, 0, sizeof(p));
for(i = -16; i <= 16; i += 4)
for(j = -16; j <= 16; j += 4)
for(k = -16; k <= 32; k += 4) {
p.emit = 7 + (rand() & 7);
p.alpha = 1.0;
p.alphavel = -1.0 / (0.3 + (rand() & 7) * 0.02);
p.org[0] = org[0] + i + (rand() & 3);
p.org[1] = org[1] + j + (rand() & 3);
p.org[2] = org[2] + k + (rand() & 3);
dir[0] = j * 8;
dir[1] = i * 8;
dir[2] = k * 8;
VectorNormalize(dir);
vel = 50 + (rand() & 63);
VectorScale(dir, vel, p.vel);
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.incandescence = 1;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence,
p.incandescencevel);
}
}
extern struct sfx_s *cl_sfx_footsteps[4];
void CL_EntityEvent(entity_state_t *ent) {
switch(ent->event) {
case EV_ITEM_RESPAWN:
S_StartSound(NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0);
CL_ItemRespawnParticles(ent->origin);
break;
case EV_PLAYER_TELEPORT:
S_StartSound(NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0);
CL_TeleportParticles(ent->origin);
break;
case EV_FOOTSTEP:
if(cl_footsteps->value)
S_StartSound(NULL, ent->number, CHAN_BODY, cl_sfx_footsteps[rand() & 3], 1, ATTN_NORM, 0);
break;
case EV_FALLSHORT:
S_StartSound(NULL, ent->number, CHAN_AUTO, S_RegisterSound("player/land1.wav"), 1, ATTN_NORM, 0);
break;
case EV_FALL:
S_StartSound(NULL, ent->number, CHAN_AUTO, S_RegisterSound("*fall2.wav"), 1, ATTN_NORM, 0);
break;
case EV_FALLFAR:
S_StartSound(NULL, ent->number, CHAN_AUTO, S_RegisterSound("*fall1.wav"), 1, ATTN_NORM, 0);
break;
}
}
void CL_ClearEffects(void) {
CL_ClearDlights();
CL_ClearLightStyles();
}