#include "client.h"
extern cvar_t *vid_ref;
extern void MakeNormalVectors(vec3_t forward, vec3_t right, vec3_t up);
void vectoangles2(vec3_t value1, vec3_t angles) {
float forward;
float yaw, pitch;
if(value1[1] == 0 && value1[0] == 0) {
yaw = 0;
if(value1[2] > 0)
pitch = 90;
else
pitch = 270;
} else {
if(value1[0])
yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
else if(value1[1] > 0)
yaw = 90;
else
yaw = 270;
if(yaw < 0)
yaw += 360;
forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
pitch = (atan2(value1[2], forward) * 180 / M_PI);
if(pitch < 0)
pitch += 360;
}
angles[PITCH] = -pitch;
angles[YAW] = yaw;
angles[ROLL] = 0;
}
void CL_Flashlight(int ent, vec3_t pos) {
cdlight_t *dl;
dl = CL_AllocDlight(ent);
VectorCopy(pos, dl->origin);
dl->radius = 400;
dl->minlight = 250;
dl->die = cl.time + 100;
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 1;
}
void CL_ColorFlash(vec3_t pos, int ent, int intensity, float r, float g, float b) {
cdlight_t *dl;
if((vidref_val == VIDREF_SOFT) && ((r < 0) || (g < 0) || (b < 0))) {
intensity = -intensity;
r = -r;
g = -g;
b = -b;
}
dl = CL_AllocDlight(ent);
VectorCopy(pos, dl->origin);
dl->radius = intensity;
dl->minlight = 250;
dl->die = cl.time + 100;
dl->color[0] = r;
dl->color[1] = g;
dl->color[2] = b;
}
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 CL_DebugTrail(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
cparticle_t p;
float dec;
vec3_t right, up;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
MakeNormalVectors(vec, right, up);
dec = 3;
VectorScale(vec, dec, vec);
VectorCopy(start, move);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
VectorClear(p.vel);
p.alpha = 1.0;
p.alphavel = -0.1;
p.albedo = 0x74 + (rand() & 7);
VectorCopy(move, p.org);
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_SmokeTrail(vec3_t start, vec3_t end, int colorStart, int colorRun, int spacing) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
VectorScale(vec, spacing, vec);
while(len > 0) {
len -= spacing;
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.5);
p.albedo = colorStart + (rand() % colorRun);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 3;
p.accel[j] = 0;
}
p.vel[2] = 20 + crand() * 5;
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_ForceWall(vec3_t start, vec3_t end, int color) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
VectorScale(vec, 4, vec);
while(len > 0) {
len -= 4;
if(frand() > 0.3) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (3.0 + frand() * 0.5);
p.albedo = color;
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 3;
p.accel[j] = 0;
}
p.vel[0] = 0;
p.vel[1] = 0;
p.vel[2] = -40 - (crand() * 10);
}
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_FlameEffects(centity_t *ent, vec3_t origin) {
int n, count;
int j;
cparticle_t p;
count = rand() & 0xF;
for(n = 0; n < count; n++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.2);
p.albedo = 226 + (rand() % 4);
for(j = 0; j < 3; j++) {
p.org[j] = origin[j] + crand() * 5;
p.vel[j] = crand() * 5;
}
p.vel[2] = crand() * -10;
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);
}
count = rand() & 0x7;
for(n = 0; n < count; n++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0 / (1 + frand() * 0.5);
p.albedo = 0 + (rand() % 4);
for(j = 0; j < 3; j++) {
p.org[j] = origin[j] + crand() * 3;
}
p.vel[2] = 20 + crand() * 5;
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_GenericParticleEffect(vec3_t org, vec3_t dir, int color, int count, int numcolors, int dirspread,
float alphavel) {
int i, j;
cparticle_t p;
float d;
for(i = 0; i < count; i++) {
if(numcolors > 1)
p.albedo = color + (rand() & numcolors);
else
p.albedo = color;
d = rand() & dirspread;
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() * alphavel);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_BubbleTrail2(vec3_t start, vec3_t end, int dist) {
vec3_t move;
vec3_t vec;
float len;
int i, j;
cparticle_t p;
float dec;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
dec = dist;
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.1);
p.albedo = 4 + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + crand() * 2;
p.vel[j] = crand() * 10;
}
p.org[2] -= 4;
p.vel[2] += 20;
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 RINGS 1
#ifdef CORKSCREW
void CL_Heatbeam(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int j, k;
cparticle_t p;
vec3_t right, up;
int i;
float d, c, s;
vec3_t dir;
float ltime;
float step = 5.0;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
VectorCopy(cl.v_right, right);
VectorCopy(cl.v_up, up);
VectorMA(move, -1, right, move);
VectorMA(move, -1, up, move);
VectorScale(vec, step, vec);
ltime = (float)cl.time / 1000.0;
for(i = 0; i < len; i += step) {
d = i * 0.1 - fmod(ltime, 16.0) * M_PI;
c = cos(d) / 1.75;
s = sin(d) / 1.75;
#ifdef DOUBLE_SCREW
for(k = -1; k < 2; k += 2) {
#else
k = 1;
#endif
VectorClear(p.accel);
p.alpha = 0.5;
p.alphavel = INSTANT_PARTICLE;
p.albedo = 223;
if(i < 10) {
VectorScale(right, c * (i / 10.0) * k, dir);
VectorMA(dir, s * (i / 10.0) * k, up, dir);
} else {
VectorScale(right, c * k, dir);
VectorMA(dir, s * k, up, dir);
}
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + dir[j] * 3;
p.vel[j] = 0;
}
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
#ifdef DOUBLE_SCREW
}
#endif
VectorAdd(move, vec, move);
}
}
#endif
#ifdef RINGS
void CL_Heatbeam(vec3_t start, vec3_t forward) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
vec3_t right, up;
int i;
float c, s;
vec3_t dir;
float ltime;
float step = 32.0, rstep;
float start_pt;
float rot;
float variance;
vec3_t end;
VectorMA(start, 4096, forward, end);
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
VectorCopy(cl.v_right, right);
VectorCopy(cl.v_up, up);
if(vidref_val == VIDREF_GL) { VectorMA(move, -0.5, right, move);
VectorMA(move, -0.5, up, move);
}
ltime = (float)cl.time / 1000.0;
start_pt = fmod(ltime * 96.0, step);
VectorMA(move, start_pt, vec, move);
VectorScale(vec, step, vec);
rstep = M_PI / 10.0;
for(i = start_pt; i < len; i += step) {
if(i > step * 5) break;
for(rot = 0; rot < M_PI * 2; rot += rstep) {
VectorClear(p.accel);
variance = 0.5;
c = cos(rot) * variance;
s = sin(rot) * variance;
if(i < 10) {
VectorScale(right, c * (i / 10.0), dir);
VectorMA(dir, s * (i / 10.0), up, dir);
} else {
VectorScale(right, c, dir);
VectorMA(dir, s, up, dir);
}
p.alpha = 0.5;
p.alphavel = -1000.0;
p.albedo = 223 - (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j] + dir[j] * 3;
p.vel[j] = 0;
}
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
VectorAdd(move, vec, move);
}
}
#endif
#ifdef SPRAY
void CL_Heatbeam(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t *p;
vec3_t forward, right, up;
int i;
float d, c, s;
vec3_t dir;
float ltime;
float step = 32.0, rstep;
float start_pt;
float rot;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
VectorCopy(cl.v_forward, forward);
VectorCopy(cl.v_right, right);
VectorCopy(cl.v_up, up);
VectorMA(move, -0.5, right, move);
VectorMA(move, -0.5, up, move);
for(i = 0; i < 8; i++) {
VectorClear(p.accel);
d = crand() * M_PI;
c = cos(d) * 30;
s = sin(d) * 30;
p.alpha = 1.0;
p.alphavel = -5.0 / (1 + frand());
p.albedo = 223 - (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = move[j];
}
VectorScale(vec, 450, p.vel);
VectorMA(p.vel, c, right, p.vel);
VectorMA(p.vel, s, up, p.vel);
}
}
#endif
void CL_ParticleSteamEffect(vec3_t org, vec3_t dir, int color, int count, int magnitude) {
int i, j;
cparticle_t p;
float d;
vec3_t r, u;
MakeNormalVectors(dir, r, u);
for(i = 0; i < count; i++) {
p.albedo = color + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + magnitude * 0.1 * crand();
}
VectorScale(dir, magnitude, p.vel);
d = crand() * magnitude / 3;
VectorMA(p.vel, d, r, p.vel);
d = crand() * magnitude / 3;
VectorMA(p.vel, d, u, p.vel);
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY / 2;
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_ParticleSteamEffect2(cl_sustain_t *self)
{
int i, j;
cparticle_t p;
float d;
vec3_t r, u;
vec3_t dir;
VectorCopy(self->dir, dir);
MakeNormalVectors(dir, r, u);
for(i = 0; i < self->count; i++) {
p.albedo = self->color + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = self->org[j] + self->magnitude * 0.1 * crand();
}
VectorScale(dir, self->magnitude, p.vel);
d = crand() * self->magnitude / 3;
VectorMA(p.vel, d, r, p.vel);
d = crand() * self->magnitude / 3;
VectorMA(p.vel, d, u, p.vel);
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY / 2;
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);
}
self->nextthink += self->thinkinterval;
}
void CL_TrackerTrail(vec3_t start, vec3_t end, int particleColor) {
vec3_t move;
vec3_t vec;
vec3_t forward, right, up, angle_dir;
float len;
int j;
cparticle_t p;
int dec;
float dist;
VectorCopy(start, move);
VectorSubtract(end, start, vec);
len = VectorNormalize(vec);
VectorCopy(vec, forward);
vectoangles2(forward, angle_dir);
AngleVectors(angle_dir, forward, right, up);
dec = 3;
VectorScale(vec, 3, vec);
while(len > 0) {
len -= dec;
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -2.0;
p.albedo = particleColor;
dist = DotProduct(move, forward);
VectorMA(move, 8 * cos(dist), up, p.org);
for(j = 0; j < 3; j++) {
p.vel[j] = 0;
p.accel[j] = 0;
}
p.vel[2] = 5;
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_Tracker_Shell(vec3_t origin) {
vec3_t dir;
int i;
cparticle_t p;
for(i = 0; i < 300; i++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = INSTANT_PARTICLE;
p.albedo = 0;
dir[0] = crand();
dir[1] = crand();
dir[2] = crand();
VectorNormalize(dir);
VectorMA(origin, 40, dir, p.org);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_MonsterPlasma_Shell(vec3_t origin) {
vec3_t dir;
int i;
cparticle_t p;
for(i = 0; i < 40; i++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = INSTANT_PARTICLE;
p.albedo = 0xe0;
dir[0] = crand();
dir[1] = crand();
dir[2] = crand();
VectorNormalize(dir);
VectorMA(origin, 10, dir, p.org);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_Widowbeamout(cl_sustain_t *self) {
vec3_t dir;
int i;
cparticle_t p;
static int colortable[4] = {2 * 8, 13 * 8, 21 * 8, 18 * 8};
float ratio;
ratio = 1.0 - (((float)self->endtime - (float)cl.time) / 2100.0);
for(i = 0; i < 300; i++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = INSTANT_PARTICLE;
p.albedo = colortable[rand() & 3];
dir[0] = crand();
dir[1] = crand();
dir[2] = crand();
VectorNormalize(dir);
VectorMA(self->org, (45.0 * ratio), dir, p.org);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_Nukeblast(cl_sustain_t *self) {
vec3_t dir;
int i;
cparticle_t p;
static int colortable[4] = {110, 112, 114, 116};
float ratio;
ratio = 1.0 - (((float)self->endtime - (float)cl.time) / 1000.0);
for(i = 0; i < 700; i++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = INSTANT_PARTICLE;
p.albedo = colortable[rand() & 3];
dir[0] = crand();
dir[1] = crand();
dir[2] = crand();
VectorNormalize(dir);
VectorMA(self->org, (200.0 * ratio), dir, p.org);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_WidowSplash(vec3_t org) {
static int colortable[4] = {2 * 8, 13 * 8, 21 * 8, 18 * 8};
int i;
cparticle_t p;
vec3_t dir;
for(i = 0; i < 256; i++) {
p.albedo = colortable[rand() & 3];
dir[0] = crand();
dir[1] = crand();
dir[2] = crand();
VectorNormalize(dir);
VectorMA(org, 45.0, dir, p.org);
VectorMA(vec3_origin, 40.0, dir, p.vel);
p.accel[0] = p.accel[1] = 0;
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_Tracker_Explode(vec3_t origin) {
vec3_t dir, backdir;
int i;
cparticle_t p;
for(i = 0; i < 300; i++) {
VectorClear(p.accel);
p.alpha = 1.0;
p.alphavel = -1.0;
p.albedo = 0;
dir[0] = crand();
dir[1] = crand();
dir[2] = crand();
VectorNormalize(dir);
VectorScale(dir, -1, backdir);
VectorMA(origin, 64, dir, p.org);
VectorScale(backdir, 64, p.vel);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_TagTrail(vec3_t start, vec3_t end, float color) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
int dec;
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_ColorExplosionParticles(vec3_t org, int color, int run) {
int i, j;
cparticle_t p;
for(i = 0; i < 128; i++) {
p.albedo = color + (rand() % run);
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + ((rand() % 32) - 16);
p.vel[j] = (rand() % 256) - 128;
}
p.accel[0] = p.accel[1] = 0;
p.accel[2] = -PARTICLE_GRAVITY;
p.alpha = 1.0;
p.alphavel = -0.4 / (0.6 + frand() * 0.2);
CL_AddParticle(p.org, p.vel, p.accel, p.albedo, p.emit, p.alpha, p.alphavel, p.incandescence, p.incandescencevel);
}
}
void CL_ParticleSmokeEffect(vec3_t org, vec3_t dir, int color, int count, int magnitude) {
int i, j;
cparticle_t p;
float d;
vec3_t r, u;
MakeNormalVectors(dir, r, u);
for(i = 0; i < count; i++) {
p.albedo = color + (rand() & 7);
for(j = 0; j < 3; j++) {
p.org[j] = org[j] + magnitude * 0.1 * crand();
}
VectorScale(dir, magnitude, p.vel);
d = crand() * magnitude / 3;
VectorMA(p.vel, d, r, p.vel);
d = crand() * magnitude / 3;
VectorMA(p.vel, d, u, p.vel);
p.accel[0] = p.accel[1] = p.accel[2] = 0;
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_BlasterParticles2(vec3_t org, vec3_t dir, unsigned int color) {
int i, j;
cparticle_t p;
float d;
int count;
count = 40;
for(i = 0; i < count; i++) {
p.albedo = color + (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_BlasterTrail2(vec3_t start, vec3_t end) {
vec3_t move;
vec3_t vec;
float len;
int j;
cparticle_t p;
int dec;
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 = 0xd0;
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);
}
}