1884 lines
No EOL
37 KiB
C
1884 lines
No EOL
37 KiB
C
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
//
|
|
// particle engine
|
|
//
|
|
|
|
#include "quakedef.h"
|
|
|
|
typedef enum ptype_s ptype_t;
|
|
typedef struct particle_s particle_t;
|
|
typedef struct texcoords_s texcoords_t;
|
|
|
|
enum ptype_s
|
|
{
|
|
pt_static = 1 << 0,
|
|
pt_smoke = 1 << 1,
|
|
pt_bubble = 1 << 2,
|
|
pt_explode = 1 << 3,
|
|
pt_blood = 1 << 4,
|
|
pt_bulletpuff = 1 << 5,
|
|
pt_fade = 1 << 6,
|
|
pt_grav = 1 << 7,
|
|
pt_rail = 1 << 8,
|
|
pt_blob = 1 << 9,
|
|
pt_blob2 = 1 << 10,
|
|
pt_smokeexp = 1 << 11,
|
|
pt_fire = 1 << 12,
|
|
pt_fire2 = 1 << 13
|
|
};
|
|
|
|
struct particle_s
|
|
{
|
|
float *texcoords;
|
|
int contents;
|
|
int fade;
|
|
int growth;
|
|
|
|
float die;
|
|
float time;
|
|
float alpha;
|
|
float scale;
|
|
float bounce;
|
|
float gravity;
|
|
|
|
byte colorred;
|
|
byte colorgreen;
|
|
byte colorblue;
|
|
|
|
vec3_t origin;
|
|
vec3_t velocity;
|
|
|
|
ptype_t type;
|
|
|
|
qboolean glow;
|
|
|
|
particle_t *next;
|
|
particle_t *prev;
|
|
};
|
|
|
|
void AssignPartStuff ( particle_t *p,
|
|
float *texcoords,
|
|
float die,
|
|
float time,
|
|
float alpha,
|
|
float scale,
|
|
float bounce,
|
|
float gravity,
|
|
int fade,
|
|
int growth,
|
|
int contents,
|
|
byte colorred,
|
|
byte colorgreen,
|
|
byte colorblue,
|
|
vec3_t origin,
|
|
vec3_t velocity,
|
|
ptype_t type,
|
|
qboolean glow)
|
|
{
|
|
p->texcoords = texcoords;
|
|
p->die = die;
|
|
p->time = time;
|
|
p->alpha = alpha;
|
|
p->scale = scale;
|
|
p->bounce = bounce;
|
|
p->gravity = gravity;
|
|
p->fade = fade;
|
|
p->growth = growth;
|
|
p->contents = contents;
|
|
p->colorred = colorred;
|
|
p->colorgreen = colorgreen;
|
|
p->colorblue = colorblue;
|
|
p->origin[0] = origin[0];
|
|
p->origin[1] = origin[1];
|
|
p->origin[2] = origin[2];
|
|
p->velocity[0] = velocity[0];
|
|
p->velocity[1] = velocity[1];
|
|
p->velocity[2] = velocity[2];
|
|
p->type = type;
|
|
p->glow = glow;
|
|
}
|
|
|
|
int part_font;
|
|
byte data[64][64][4];
|
|
|
|
float smoke_coords[4];
|
|
float blood_coords[4];
|
|
float bubble_coords[4];
|
|
float particle_coords[4];
|
|
|
|
particle_t *active_particles, *free_particles, *particles;
|
|
|
|
int r_numparticles;
|
|
|
|
vec3_t r_pright, r_pup, r_ppn;
|
|
|
|
extern byte particle[32][32];
|
|
extern byte smoke[32][32];
|
|
extern byte blood[32][32];
|
|
extern byte bubble[32][32];
|
|
|
|
void R_MakeParticleTexture (int xx, int yy, byte texture[32][32])
|
|
{
|
|
int x, y;
|
|
|
|
for (x=xx ; x<xx+32 ; x++)
|
|
{
|
|
for (y=yy ; y<yy+32 ; y++)
|
|
{
|
|
data[x][y][0] = 255;
|
|
data[x][y][1] = 255;
|
|
data[x][y][2] = 255;
|
|
data[x][y][3] = texture[x-xx][y-yy];
|
|
}
|
|
}
|
|
}
|
|
|
|
void R_InitParticleTexture (void)
|
|
{
|
|
memset (data, 0, sizeof(data));
|
|
|
|
R_MakeParticleTexture (0, 0, smoke);
|
|
R_MakeParticleTexture (0, 32, blood);
|
|
R_MakeParticleTexture (32, 0, bubble);
|
|
R_MakeParticleTexture (32, 32, particle);
|
|
|
|
part_font = GL_LoadTexture ("particle", 64, 64, &data[0][0][0], true, true, 4);
|
|
|
|
// 0 = left, 1 = right, 2 = down, 3 = up
|
|
|
|
smoke_coords[0] = 0.0;
|
|
smoke_coords[1] = 0.5;
|
|
smoke_coords[2] = 0.0;
|
|
smoke_coords[3] = 0.5;
|
|
|
|
blood_coords[0] = 0.5;
|
|
blood_coords[1] = 1.0;
|
|
blood_coords[2] = 0.0;
|
|
blood_coords[3] = 0.5;
|
|
|
|
bubble_coords[0] = 0.0;
|
|
bubble_coords[1] = 0.5;
|
|
bubble_coords[2] = 0.5;
|
|
bubble_coords[3] = 1.0;
|
|
|
|
particle_coords[0] = 0.5;
|
|
particle_coords[1] = 1.0;
|
|
particle_coords[2] = 0.5;
|
|
particle_coords[3] = 1.0;
|
|
|
|
// 0 = left, 1 = right, 2 = down, 3 = up
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_InitParticles
|
|
===============
|
|
*/
|
|
void R_InitParticles (void)
|
|
{
|
|
int i = COM_CheckParm ("-particles");
|
|
|
|
r_numparticles = 4096;
|
|
|
|
if (i)
|
|
r_numparticles = (int)(atoi(com_argv[i+1]));
|
|
|
|
particles = (particle_t *) Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
|
|
|
|
memset(particles, 0, r_numparticles * sizeof(particle_t));
|
|
|
|
for( i = 0 ; i < r_numparticles ; ++i )
|
|
{
|
|
particles[i].prev = &particles[i - 1];
|
|
particles[i].next = &particles[i + 1];
|
|
}
|
|
|
|
particles[0].prev = NULL;
|
|
particles[r_numparticles - 1].next = NULL;
|
|
|
|
free_particles = &particles[0];
|
|
active_particles = NULL;
|
|
|
|
R_InitParticleTexture ();
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_ClearParticles
|
|
===============
|
|
*/
|
|
void R_ClearParticles (void)
|
|
{
|
|
int i;
|
|
|
|
free_particles = &particles[0];
|
|
active_particles = NULL;
|
|
|
|
memset(particles, 0, r_numparticles * sizeof(particle_t));
|
|
|
|
for( i = 0 ; i < r_numparticles ; ++i )
|
|
{
|
|
particles[i].prev = &particles[i - 1];
|
|
particles[i].next = &particles[i + 1];
|
|
}
|
|
|
|
particles[0].prev = NULL;
|
|
particles[r_numparticles - 1].next = NULL;
|
|
}
|
|
|
|
particle_t* addParticle()
|
|
{
|
|
particle_t* p = free_particles;
|
|
|
|
if(!p)
|
|
return NULL;
|
|
|
|
free_particles = p->next;
|
|
|
|
if(free_particles)
|
|
free_particles->prev = NULL;
|
|
|
|
p->next = active_particles;
|
|
|
|
if(active_particles)
|
|
active_particles->prev = p;
|
|
|
|
active_particles = p;
|
|
|
|
return p;
|
|
}
|
|
|
|
particle_t* remParticle(particle_t* p)
|
|
{
|
|
particle_t* next;
|
|
|
|
if(!p)
|
|
return NULL;
|
|
|
|
if(p == active_particles)
|
|
active_particles = p->next;
|
|
|
|
if(p->next)
|
|
p->next->prev = p->prev;
|
|
|
|
if(p->prev)
|
|
p->prev->next = p->next;
|
|
|
|
if(free_particles)
|
|
free_particles->prev = p;
|
|
|
|
next = p->next;
|
|
|
|
p->next = free_particles;
|
|
|
|
free_particles = p;
|
|
|
|
p->prev = NULL;
|
|
|
|
return next;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_ReadPointFile
|
|
===============
|
|
*/
|
|
void R_ReadPointFile_f (void)
|
|
{
|
|
FILE *f;
|
|
vec3_t origin;
|
|
int r;
|
|
int c;
|
|
particle_t *p;
|
|
char name[MAX_OSPATH];
|
|
byte *color;
|
|
|
|
sprintf (name,"maps/%s.pts", sv.name);
|
|
|
|
COM_FOpenFile (name, &f);
|
|
if (!f)
|
|
{
|
|
Con_Printf ("couldn't open %s\n", name);
|
|
return;
|
|
}
|
|
|
|
Con_Printf ("Reading %s...\n", name);
|
|
c = 0;
|
|
for ( ;; )
|
|
{
|
|
|
|
r = fscanf (f,"%f %f %f\n", &origin[0], &origin[1], &origin[2]);
|
|
if (r != 3)
|
|
break;
|
|
c++;
|
|
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
Con_Printf ("Not enough free particles\n");
|
|
break;
|
|
}
|
|
|
|
color = (byte *) &d_8to24table[(int)(-c)&15];
|
|
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->texcoords = particle_coords;
|
|
p->contents = 0;
|
|
|
|
p->die = 99;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = 2;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = color[0];
|
|
p->colorgreen = color[1];
|
|
p->colorblue = color[2];
|
|
|
|
p->origin[0] = origin[0];
|
|
p->origin[1] = origin[1];
|
|
p->origin[2] = origin[2];
|
|
p->velocity[0] = vec3_origin[0];
|
|
p->velocity[1] = vec3_origin[1];
|
|
p->velocity[2] = vec3_origin[2];
|
|
|
|
p->type = pt_static;
|
|
|
|
p->glow = true;
|
|
}
|
|
|
|
fclose (f);
|
|
Con_Printf ("%i points read\n", c);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_EntityParticles
|
|
===============
|
|
*/
|
|
|
|
float r_avertexnormals[162][3] =
|
|
{
|
|
#include "anorms.h"
|
|
};
|
|
|
|
vec3_t avelocities[128];
|
|
|
|
void R_EntityParticles (entity_t *ent)
|
|
{
|
|
int i;
|
|
float sp, sy, cp, cy, angle;
|
|
vec3_t forward;
|
|
particle_t *p;
|
|
|
|
if (!avelocities[0][0])
|
|
{
|
|
for (i=0 ; i<384 ; i++)
|
|
{
|
|
avelocities[0][i] = (rand() & 255) * 0.01;
|
|
}
|
|
}
|
|
|
|
for (i=0 ; i<128 ; i++)
|
|
{
|
|
angle = cl.time * avelocities[i][0];
|
|
sy = sin(angle);
|
|
cy = cos(angle);
|
|
|
|
angle = cl.time * avelocities[i][1];
|
|
sp = sin(angle);
|
|
cp = cos(angle);
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->texcoords = particle_coords;
|
|
p->contents = 0;
|
|
|
|
p->die = cl.time + 0.01;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = 2;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = 255;//255;
|
|
p->colorgreen = 255;//243;
|
|
p->colorblue = 255;//27;
|
|
|
|
p->origin[0] = ent->origin[0] + r_avertexnormals[i][0]*64 + forward[0]*16;
|
|
p->origin[1] = ent->origin[1] + r_avertexnormals[i][1]*64 + forward[1]*16;
|
|
p->origin[2] = ent->origin[2] + r_avertexnormals[i][2]*64 + forward[2]*16;
|
|
p->velocity[0] = 0;
|
|
p->velocity[1] = 0;
|
|
p->velocity[2] = 0;
|
|
|
|
p->type = pt_static;
|
|
|
|
p->glow = true;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_ParseParticleEffect
|
|
|
|
Parse an effect out of the server message
|
|
===============
|
|
*/
|
|
void R_ParseParticleEffect (void)
|
|
{
|
|
vec3_t origin, direction;
|
|
int count, color;
|
|
|
|
origin[0] = MSG_ReadCoord ();
|
|
origin[1] = MSG_ReadCoord ();
|
|
origin[2] = MSG_ReadCoord ();
|
|
|
|
direction[0] = MSG_ReadChar () * 0.0625;
|
|
direction[1] = MSG_ReadChar () * 0.0625;
|
|
direction[2] = MSG_ReadChar () * 0.0625;
|
|
|
|
count = MSG_ReadByte ();
|
|
color = MSG_ReadByte ();
|
|
|
|
R_RunParticleEffect (origin, direction, color, count);
|
|
}
|
|
|
|
/*
|
|
===================
|
|
R_ParticleExplosion
|
|
===================
|
|
*/
|
|
|
|
extern cvar_t sv_gravity;
|
|
|
|
void R_ParticleExplosion (vec3_t origin)
|
|
{
|
|
int i, contents;
|
|
particle_t *p;
|
|
|
|
contents = Mod_PointInLeaf(origin, cl.worldmodel)->contents;
|
|
|
|
for (i=0; i<64; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->fade = -196;
|
|
p->growth = 16;
|
|
|
|
p->texcoords = smoke_coords;
|
|
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = 2;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = 255;
|
|
p->colorgreen = rand() &255;
|
|
p->colorblue = 0;
|
|
|
|
p->origin[0] = origin[0] + (rand() &31) - 16;
|
|
p->origin[1] = origin[1] + (rand() &31) - 16;
|
|
p->origin[2] = origin[2] + (rand() &31) - 16;
|
|
p->velocity[0] = (rand() & 31) - 16;
|
|
p->velocity[1] = (rand() & 31) - 16;
|
|
p->velocity[2] = (rand() & 31) - 16;
|
|
|
|
p->type = pt_smokeexp;
|
|
|
|
p->glow = true;
|
|
}
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((contents == CONTENTS_EMPTY) || (contents == CONTENTS_SOLID))
|
|
{
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->texcoords = particle_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 1.5;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->colorred = 255;
|
|
p->colorgreen = rand() &255;
|
|
p->colorblue = 0;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_explode;
|
|
|
|
p->glow = true;
|
|
}
|
|
else
|
|
{
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->texcoords = bubble_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = 127;
|
|
p->colorgreen = 127;
|
|
p->colorblue = 255;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_bubble;
|
|
|
|
p->glow = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===================
|
|
R_ColoredExplosion
|
|
===================
|
|
*/
|
|
|
|
//Xsniper - Added RGB Colored Explosions
|
|
void R_ColoredExplosion (vec3_t origin, vec3_t colour)
|
|
{
|
|
int i, contents;
|
|
particle_t *p;
|
|
|
|
contents = Mod_PointInLeaf(origin, cl.worldmodel)->contents;
|
|
|
|
for (i=0; i<64; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->fade = -196;
|
|
p->growth = 16;
|
|
|
|
p->texcoords = smoke_coords;
|
|
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = 2;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = colour[0] * 255.0; //255;
|
|
p->colorgreen = colour[1] * 255.0; //rand() &255;
|
|
p->colorblue = colour[2] * 255.0; //0;
|
|
|
|
p->origin[0] = origin[0] + (rand() &31) - 16;
|
|
p->origin[1] = origin[1] + (rand() &31) - 16;
|
|
p->origin[2] = origin[2] + (rand() &31) - 16;
|
|
p->velocity[0] = (rand() & 31) - 16;
|
|
p->velocity[1] = (rand() & 31) - 16;
|
|
p->velocity[2] = (rand() & 31) - 16;
|
|
|
|
p->type = pt_smokeexp;
|
|
|
|
p->glow = true;
|
|
}
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((contents == CONTENTS_EMPTY) || (contents == CONTENTS_SOLID))
|
|
{
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->texcoords = particle_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 1.5;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->colorred = colour[0] * 255.0; //255;
|
|
p->colorgreen = colour[1] * 255.0; //rand() &255;
|
|
p->colorblue = colour[2] * 255.0; //0;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_explode;
|
|
|
|
p->glow = true;
|
|
}
|
|
else
|
|
{
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->texcoords = bubble_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = colour[0] * 255.0; //127;
|
|
p->colorgreen = colour[1] * 255.0; //127;
|
|
p->colorblue = colour[2] * 255.0; //255;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_bubble;
|
|
|
|
p->glow = false;
|
|
}
|
|
}
|
|
}
|
|
//Xsniper - End
|
|
|
|
/*
|
|
====================
|
|
R_ColoredExplosion2
|
|
====================
|
|
*/
|
|
//Xsniper - Added RGB Color Support
|
|
void R_ColoredExplosion2 (vec3_t origin, vec3_t colour)
|
|
{
|
|
int i,contents;
|
|
particle_t *p;
|
|
|
|
contents = Mod_PointInLeaf(origin, cl.worldmodel)->contents;
|
|
|
|
for (i=0; i<384; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((contents == CONTENTS_EMPTY) ||
|
|
(contents == CONTENTS_SOLID))
|
|
{
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->texcoords = particle_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->colorred = colour[0] * 255.0;
|
|
p->colorgreen = colour[1] * 255.0;
|
|
p->colorblue = colour[2] * 255.0;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_explode;
|
|
|
|
p->glow = true;
|
|
}
|
|
else
|
|
{
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->texcoords = bubble_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = colour[0] * 255.0; //127;
|
|
p->colorgreen = colour[1] * 255.0; //127;
|
|
p->colorblue = colour[2] * 255.0; //255;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_bubble;
|
|
|
|
p->glow = false;
|
|
}
|
|
}
|
|
}
|
|
//Xsniper - End
|
|
|
|
/*
|
|
====================
|
|
R_ParticleExplosion2
|
|
====================
|
|
*/
|
|
void R_ParticleExplosion2 (vec3_t origin, int colorStart, int colorLength)
|
|
{
|
|
int i,contents;
|
|
particle_t *p;
|
|
int colorMod = 0;
|
|
byte *color;
|
|
|
|
contents = Mod_PointInLeaf(origin, cl.worldmodel)->contents;
|
|
|
|
for (i=0; i<384; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((contents == CONTENTS_EMPTY) ||
|
|
(contents == CONTENTS_SOLID))
|
|
{
|
|
color = (byte *) &d_8to24table[(int)colorStart + (colorMod % colorLength)];
|
|
colorMod++;
|
|
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->texcoords = particle_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->colorred = color[0];
|
|
p->colorgreen = color[1];
|
|
p->colorblue = color[2];
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_explode;
|
|
|
|
p->glow = true;
|
|
}
|
|
else
|
|
{
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->texcoords = bubble_coords;
|
|
p->contents = contents;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = 0;
|
|
|
|
p->colorred = 127;
|
|
p->colorgreen = 127;
|
|
p->colorblue = 255;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_bubble;
|
|
|
|
p->glow = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_BlobExplosion
|
|
===============
|
|
*/
|
|
void R_BlobExplosion (vec3_t origin)
|
|
{
|
|
int i;
|
|
particle_t *p;
|
|
byte *color;
|
|
|
|
for (i=0 ; i<384 ; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
color = (byte *) &d_8to24table[(int)(rand() & 7) + 66];
|
|
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->texcoords = particle_coords;
|
|
p->contents = 0;
|
|
|
|
p->die = cl.time + 5;
|
|
p->time = 0;
|
|
p->alpha = 200;
|
|
p->scale = (rand() & 3) +1;
|
|
p->bounce = 0;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->colorred = color[0];
|
|
p->colorgreen = color[1];
|
|
p->colorblue = color[2];
|
|
|
|
p->origin[0] = origin[0] + (rand() & 31) - 16;
|
|
p->origin[1] = origin[1] + (rand() & 31) - 16;
|
|
p->origin[2] = origin[2] + (rand() & 31) - 16;
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
|
|
p->type = pt_blob;
|
|
|
|
p->glow = true;
|
|
|
|
if (i & 1)
|
|
{
|
|
color = (byte *) &d_8to24table[(int)(rand() & 7) + 150];
|
|
|
|
p->colorred = color[0];
|
|
p->colorgreen = color[1];
|
|
p->colorblue = color[2];
|
|
|
|
p->type = pt_blob2;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_RunParticleEffect
|
|
|
|
===============
|
|
*/
|
|
|
|
void R_RunParticleEffect (vec3_t origin, vec3_t direction, int color, int count)
|
|
{
|
|
int i, contents;
|
|
particle_t *p;
|
|
byte *color24;
|
|
|
|
if (count == 128)
|
|
{
|
|
for (i=0 ; i<count ; i++)
|
|
{ // rocket explosion
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
contents = Mod_PointInLeaf(p->origin, cl.worldmodel)->contents;
|
|
|
|
p->scale = 2;
|
|
p->alpha = 200;
|
|
p->die = cl.time + 5;
|
|
|
|
if ((contents == CONTENTS_EMPTY) ||
|
|
(contents == CONTENTS_SOLID))
|
|
{
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
|
|
p->colorred = 255;
|
|
p->colorgreen = 243;
|
|
p->colorblue = 147;
|
|
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->type = pt_explode;
|
|
p->glow = true;
|
|
}
|
|
else
|
|
{
|
|
p->texcoords = bubble_coords;
|
|
p->bounce = 0;
|
|
|
|
p->colorred = 127;
|
|
p->colorgreen = 127;
|
|
p->colorblue = 255;
|
|
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->gravity = 0;
|
|
|
|
p->type = pt_bubble;
|
|
p->glow = false;
|
|
}
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 31) - 16);
|
|
p->origin[1] = origin[1] + ((rand() & 31) - 16);
|
|
p->origin[2] = origin[2] + ((rand() & 31) - 16);
|
|
|
|
p->velocity[0] = (rand() & 511) - 256;
|
|
p->velocity[1] = (rand() & 511) - 256;
|
|
p->velocity[2] = (rand() & 511) - 256;
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->texcoords = blood_coords;
|
|
p->bounce = 0;
|
|
p->scale = 2;
|
|
p->alpha = 200;
|
|
p->die = cl.time + 5;
|
|
|
|
color24 = (byte *) &d_8to24table[(int)(rand() & 3) + color];
|
|
|
|
p->colorred = color24[0];
|
|
p->colorgreen = color24[1];
|
|
p->colorblue = color24[2];
|
|
|
|
p->growth = 0;
|
|
p->fade = -64;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->type = pt_blood;
|
|
p->glow = false;
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 15) - 8);
|
|
p->origin[1] = origin[1] + ((rand() & 15) - 8);
|
|
p->origin[2] = origin[2] + ((rand() & 15) - 8);
|
|
|
|
p->velocity[0] = direction[0] * 15;
|
|
p->velocity[1] = direction[1] * 15;
|
|
p->velocity[2] = direction[2] * 15;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_SparkShower
|
|
|
|
===============
|
|
*/
|
|
void R_SparkShower (vec3_t origin, vec3_t direction)
|
|
{
|
|
int i, contents;
|
|
particle_t *p;
|
|
|
|
p = addParticle();
|
|
if (!free_particles)
|
|
{
|
|
return;
|
|
}
|
|
|
|
contents = Mod_PointInLeaf(p->origin, cl.worldmodel)->contents;
|
|
|
|
if ((contents == CONTENTS_EMPTY) ||
|
|
(contents == CONTENTS_SOLID))
|
|
{
|
|
p->scale = 2;
|
|
p->alpha = 200;
|
|
|
|
p->texcoords = smoke_coords;
|
|
|
|
p->bounce = 0;
|
|
p->type = pt_bulletpuff;
|
|
p->glow = false;
|
|
|
|
p->colorred = 187;
|
|
p->colorgreen = 187;
|
|
p->colorblue = 187;
|
|
|
|
p->fade = -255;
|
|
p->growth = 16;
|
|
p->gravity = 0;
|
|
|
|
p->die = cl.time + 5;
|
|
|
|
p->origin[0] = origin[0];
|
|
p->origin[1] = origin[1];
|
|
p->origin[2] = origin[2];
|
|
|
|
p->velocity[0] = (rand() & 7) - 4;
|
|
p->velocity[1] = (rand() & 7) - 4;
|
|
p->velocity[2] = (rand() & 7) - 4;
|
|
}
|
|
|
|
for (i=0 ; i<10 ; i++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
contents = Mod_PointInLeaf(p->origin, cl.worldmodel)->contents;
|
|
|
|
p->scale = (rand() & 3) +1;
|
|
|
|
p->alpha = 200;
|
|
p->die = cl.time + 5;
|
|
|
|
if ((contents == CONTENTS_EMPTY) ||
|
|
(contents == CONTENTS_SOLID))
|
|
{
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 1.5;
|
|
|
|
p->colorred = 255;
|
|
p->colorgreen = 243;
|
|
p->colorblue = 147;
|
|
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->type = pt_explode;
|
|
p->glow = true;
|
|
}
|
|
else
|
|
{
|
|
p->texcoords = bubble_coords;
|
|
p->bounce = 0;
|
|
|
|
p->colorred = 127;
|
|
p->colorgreen = 127;
|
|
p->colorblue = 255;
|
|
|
|
p->fade = 0;
|
|
p->growth = 0;
|
|
p->gravity = 0;
|
|
|
|
p->type = pt_bubble;
|
|
p->glow = false;
|
|
}
|
|
|
|
p->origin[0] = origin[0] + ((rand() & 7) - 4);
|
|
p->origin[1] = origin[1] + ((rand() & 7) - 4);
|
|
p->origin[2] = origin[2] + ((rand() & 7) - 4);
|
|
|
|
p->velocity[0] = direction[0] + (rand() & 127) - 64;
|
|
p->velocity[1] = direction[1] + (rand() & 127) - 64;
|
|
p->velocity[2] = direction[2] + (rand() & 127) - 64;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_LavaSplash
|
|
===============
|
|
*/
|
|
void R_LavaSplash (vec3_t origin)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i=-16 ; i<16 ; i++)
|
|
{
|
|
for (j=-16 ; j<16 ; j++)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
p->scale = 5;
|
|
p->alpha = 255;
|
|
p->die = cl.time + 10;
|
|
|
|
p->fade = -64;
|
|
p->growth = 0;
|
|
p->gravity = -0.1f * sv_gravity.value;
|
|
|
|
p->colorred = 163;
|
|
p->colorgreen = 39;
|
|
p->colorblue = 11;
|
|
|
|
p->type = pt_grav;
|
|
p->glow = true;
|
|
|
|
p->velocity[0] = (rand() & 7) + (j * 8);
|
|
p->velocity[1] = (rand() & 7) + (i * 8);
|
|
p->velocity[2] = 256;
|
|
|
|
p->origin[0] = origin[0] + (rand() & 7) + (j * 8);
|
|
p->origin[1] = origin[1] + (rand() & 7) + (i * 8);
|
|
p->origin[2] = origin[2] + (rand() & 63);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_TeleportSplash
|
|
|
|
===============
|
|
*/
|
|
void R_TeleportSplash (vec3_t origin)
|
|
{
|
|
int i, j, k;
|
|
particle_t *p;
|
|
|
|
for (i=-16 ; i<16 ; i+=4)
|
|
{
|
|
for (j=-16 ; j<16 ; j+=4)
|
|
{
|
|
for (k=-24 ; k<32 ; k+=4)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
p->scale = 2;
|
|
p->alpha = 200;
|
|
p->die = cl.time + 1;
|
|
p->gravity = -0.05f * sv_gravity.value;
|
|
|
|
p->colorred = 255;
|
|
p->colorgreen = 255;
|
|
p->colorblue = 255;
|
|
|
|
p->fade = -255;
|
|
|
|
p->type = pt_fade;
|
|
p->glow = true;
|
|
|
|
p->origin[0] = origin[0] + i + (rand() & 7);
|
|
p->origin[1] = origin[1] + j + (rand() & 7);
|
|
p->origin[2] = origin[2] + k + (rand() & 7);
|
|
|
|
p->velocity[0] = i*2 + (rand() & 31) - 16;
|
|
p->velocity[1] = j*2 + (rand() & 31) - 16;
|
|
p->velocity[2] = k*2 + (rand() & 31) + 24;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void R_LightningTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
particle_t *p;
|
|
|
|
VectorSubtract (end, start, vec);
|
|
|
|
len = VectorNormalize (vec);
|
|
|
|
VectorScale (vec, 2, vec);
|
|
|
|
while (len > 0)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->alpha = 255;
|
|
p->scale = 3;
|
|
p->die = cl.time + 1;
|
|
p->glow = true;
|
|
|
|
p->colorred = 0;
|
|
p->colorgreen = 0;
|
|
p->colorblue = 255;
|
|
|
|
p->fade = -512;
|
|
p->growth = 0;
|
|
p->gravity = 0;
|
|
|
|
p->type = pt_rail;
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
|
|
p->origin[0] = start[0];
|
|
p->origin[1] = start[1];
|
|
p->origin[2] = start[2];
|
|
|
|
p->velocity[0] = 0;
|
|
p->velocity[1] = 0;
|
|
p->velocity[2] = 0;
|
|
|
|
len--;
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
void R_RocketTrail (vec3_t start, vec3_t end, entity_t *ent)
|
|
{
|
|
particle_t *p;
|
|
vec3_t velocity;
|
|
int contents;
|
|
|
|
contents = Mod_PointInLeaf(start, cl.worldmodel)->contents;
|
|
|
|
if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
|
|
return;
|
|
|
|
if (cl.time > ent->time_left)
|
|
{
|
|
p = addParticle();
|
|
|
|
if(!p)
|
|
return;
|
|
|
|
if (contents == CONTENTS_EMPTY || contents == CONTENTS_SOLID)
|
|
{
|
|
velocity[0] = (rand() & 15) - 8;
|
|
velocity[1] = (rand() & 15) - 8;
|
|
velocity[2] = (rand() & 31) + 15;
|
|
|
|
AssignPartStuff (p, smoke_coords, cl.time + 10, 0, 255, 2, 0, 0,
|
|
-255, 16, contents, 187, 187, 187, start, velocity, pt_smoke, false);
|
|
}
|
|
else
|
|
{
|
|
velocity[0] = 0;
|
|
velocity[1] = 0;
|
|
velocity[2] = 20;
|
|
|
|
AssignPartStuff (p, bubble_coords, cl.time + 10, 0, 200, (rand() & 3) +1, 0, 0,
|
|
0, 0, contents, 127, 127, 255, start, velocity, pt_bubble, false);
|
|
}
|
|
ent->time_left = cl.time + 0.01;
|
|
}
|
|
}
|
|
|
|
void R_BloodTrail (vec3_t start, vec3_t end, entity_t *ent)
|
|
{
|
|
particle_t *p;
|
|
byte *color;
|
|
|
|
if (cl.time > ent->time_left)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->die = cl.time + 10;
|
|
|
|
color = (byte *) &d_8to24table[(int)(rand() & 3) + 68];
|
|
|
|
p->colorred = color[0];
|
|
p->colorgreen = color[1];
|
|
p->colorblue = color[2];
|
|
|
|
p->fade = -128;
|
|
p->gravity = -0.5f * sv_gravity.value;
|
|
|
|
p->alpha = 200;
|
|
p->scale = 4;
|
|
p->texcoords = blood_coords;
|
|
p->bounce = 0;
|
|
p->type = pt_blood;
|
|
p->glow = false;
|
|
|
|
p->velocity[0] = (rand() & 15) - 8;
|
|
p->velocity[1] = (rand() & 15) - 8;
|
|
p->velocity[2] = (rand() & 15) - 8;
|
|
|
|
p->origin[0] = start[0] + ((rand() & 3) - 2);
|
|
p->origin[1] = start[1] + ((rand() & 3) - 2);
|
|
p->origin[2] = start[2] + ((rand() & 3) - 2);
|
|
|
|
ent->time_left = cl.time + 0.05;
|
|
}
|
|
}
|
|
|
|
void R_TracerTrail (vec3_t start, vec3_t end, entity_t *ent, byte color)
|
|
{
|
|
vec3_t vec;
|
|
static int tracercount;
|
|
particle_t *p;
|
|
byte *color24;
|
|
float len;
|
|
|
|
VectorSubtract (end, start, vec);
|
|
|
|
len = VectorNormalize (vec);
|
|
|
|
VectorScale (vec, 2, vec);
|
|
|
|
while (len > 0)
|
|
{
|
|
p = addParticle();
|
|
|
|
if(!p)
|
|
return;
|
|
|
|
VectorCopy (start, p->origin);
|
|
|
|
if (color == 77)
|
|
{
|
|
p->fade = -1024;
|
|
p->growth = 2;
|
|
}
|
|
else
|
|
{
|
|
p->fade = -512;
|
|
p->growth = 0;
|
|
}
|
|
|
|
p->time = 0;
|
|
p->gravity = 0;
|
|
|
|
p->die = cl.time + 5;
|
|
|
|
if (color == 63)
|
|
{
|
|
p->colorred = 0;
|
|
p->colorgreen = 255;
|
|
p->colorblue = 0;
|
|
p->scale = 5;
|
|
}
|
|
else if (color == 77)
|
|
{
|
|
p->colorred = 79;
|
|
p->colorgreen = 151;
|
|
p->colorblue = 227;
|
|
p->scale = 7;
|
|
}
|
|
else
|
|
{
|
|
color24 = (byte *) &d_8to24table[(int)color];
|
|
|
|
p->colorred = color24[0];
|
|
p->colorgreen = color24[1];
|
|
p->colorblue = color24[2];
|
|
p->scale = 5;
|
|
}
|
|
|
|
p->alpha = 255;
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
p->type = pt_static;
|
|
p->glow = true;
|
|
|
|
p->velocity[0] = 0;
|
|
p->velocity[1] = 0;
|
|
p->velocity[2] = 0;
|
|
|
|
len--;
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
void R_VoorTrail (vec3_t start, vec3_t end, entity_t *ent)
|
|
{
|
|
particle_t *p;
|
|
|
|
if (cl.time > ent->time_left)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
return;
|
|
|
|
p->die = cl.time + 5;
|
|
|
|
p->colorred = 187;
|
|
p->colorgreen = 115;
|
|
p->colorblue = 159;
|
|
|
|
p->fade = -128;
|
|
p->gravity = -0.05f * sv_gravity.value;
|
|
|
|
p->alpha = 200;
|
|
p->scale = 5;
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
p->type = pt_fade;
|
|
p->glow = true;
|
|
|
|
p->velocity[0] = (rand() & 15) - 8;
|
|
p->velocity[1] = (rand() & 15) - 8;
|
|
p->velocity[2] = (rand() & 15) - 8;
|
|
|
|
p->origin[0] = start[0] + ((rand() & 3) - 2);
|
|
p->origin[1] = start[1] + ((rand() & 3) - 2);
|
|
p->origin[2] = start[2] + ((rand() & 3) - 2);
|
|
|
|
ent->time_left = cl.time + 0.05;
|
|
}
|
|
}
|
|
|
|
/*
|
|
======
|
|
R_Fire
|
|
======
|
|
*/
|
|
void R_Fire (entity_t *ent, qboolean fire2)
|
|
{
|
|
particle_t *p;
|
|
|
|
if( cl.time + 2 < ent->time_left )
|
|
{
|
|
ent->time_left = 0;
|
|
}
|
|
|
|
if (cl.time > ent->time_left)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->die = cl.time + 5;
|
|
|
|
p->colorred = 227;
|
|
p->colorgreen = 151;
|
|
p->colorblue = 79;
|
|
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->gravity = 0.05f * sv_gravity.value;
|
|
|
|
p->alpha = 128;
|
|
p->scale = 10;
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
p->type = pt_fire;
|
|
p->glow = true;
|
|
|
|
p->velocity[0] = (rand() & 3) - 2;
|
|
p->velocity[1] = (rand() & 3) - 2;
|
|
p->velocity[2] = 0;
|
|
|
|
p->origin[0] = ent->origin[0];
|
|
p->origin[1] = ent->origin[1];
|
|
p->origin[2] = ent->origin[2] + 4;
|
|
|
|
if (fire2)
|
|
{
|
|
p->origin[2] = ent->origin[2] - 2;
|
|
if (ent->frame)
|
|
{
|
|
p->scale = 30;
|
|
p->velocity[0] = (rand() & 7) - 4;
|
|
p->velocity[1] = (rand() & 7) - 4;
|
|
p->velocity[2] = 0;
|
|
p->fade = -128;
|
|
p->growth = -4;
|
|
p->gravity = 0.1f * sv_gravity.value;
|
|
p->type = pt_fire2;
|
|
}
|
|
}
|
|
ent->time_left = cl.time + 0.05;
|
|
}
|
|
}
|
|
|
|
// New Fire Begin - Xsniper
|
|
|
|
/*
|
|
======
|
|
R_BlueFire
|
|
======
|
|
*/
|
|
void R_BlueFire (entity_t *ent, qboolean fire2)
|
|
{
|
|
particle_t *p;
|
|
|
|
if( cl.time + 2 < ent->time_left )
|
|
{
|
|
ent->time_left = 0;
|
|
}
|
|
|
|
if (cl.time > ent->time_left)
|
|
{
|
|
p = addParticle();
|
|
if(!p)
|
|
{
|
|
return;
|
|
}
|
|
|
|
p->die = cl.time + 5;
|
|
|
|
p->colorred = 79;
|
|
p->colorgreen = 151;
|
|
p->colorblue = 227;
|
|
|
|
p->fade = -128;
|
|
p->growth = -2;
|
|
p->gravity = 0.05f * sv_gravity.value;
|
|
|
|
p->alpha = 128;
|
|
p->scale = 10;
|
|
p->texcoords = particle_coords;
|
|
p->bounce = 0;
|
|
p->type = pt_fire;
|
|
p->glow = true;
|
|
|
|
p->velocity[0] = (rand() & 3) - 2;
|
|
p->velocity[1] = (rand() & 3) - 2;
|
|
p->velocity[2] = 0;
|
|
|
|
p->origin[0] = ent->origin[0];
|
|
p->origin[1] = ent->origin[1];
|
|
p->origin[2] = ent->origin[2] + 4;
|
|
|
|
if (fire2)
|
|
{
|
|
p->origin[2] = ent->origin[2] - 2;
|
|
if (ent->frame)
|
|
{
|
|
p->scale = 30;
|
|
p->velocity[0] = (rand() & 7) - 4;
|
|
p->velocity[1] = (rand() & 7) - 4;
|
|
p->velocity[2] = 0;
|
|
p->fade = -128;
|
|
p->growth = -4;
|
|
p->gravity = 0.1f * sv_gravity.value;
|
|
p->type = pt_fire2;
|
|
}
|
|
}
|
|
ent->time_left = cl.time + 0.05;
|
|
}
|
|
}
|
|
|
|
// New Fire End - Xsniper
|
|
|
|
#define DIST_EPSILON (0.03125)
|
|
|
|
int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
|
|
|
|
qboolean detectCollision( int num, vec3_t start, vec3_t end, vec3_t impact, vec3_t normal )
|
|
{
|
|
dclipnode_t *node, *nodes = cl.worldmodel->hulls->clipnodes;
|
|
mplane_t *plane, *planes = cl.worldmodel->hulls->planes;
|
|
float t1, t2;
|
|
float frac;
|
|
vec3_t mid;
|
|
int side;
|
|
|
|
qboolean t1neg, t2neg;
|
|
|
|
while( num >= 0 )
|
|
{
|
|
t1neg = false;
|
|
t2neg = false;
|
|
|
|
node = nodes + num;
|
|
plane = planes + node->planenum;
|
|
|
|
t1 = PlaneDiff(start, plane);
|
|
t2 = PlaneDiff(end, plane);
|
|
|
|
if( t1 < 0 )
|
|
{
|
|
t1neg = true;
|
|
}
|
|
if( t2 < 0 )
|
|
{
|
|
t2neg = true;
|
|
}
|
|
|
|
if( !t1neg && !t2neg )
|
|
{
|
|
num = node->children[0];
|
|
continue;
|
|
}
|
|
|
|
if( t1neg && t2neg )
|
|
{
|
|
num = node->children[1];
|
|
continue;
|
|
}
|
|
|
|
if( t1neg )
|
|
{
|
|
frac = (t1 + DIST_EPSILON)/(t1-t2);
|
|
}
|
|
else
|
|
{
|
|
frac = (t1 - DIST_EPSILON)/(t1-t2);
|
|
}
|
|
|
|
if(frac < 0)
|
|
{
|
|
frac = 0;
|
|
}
|
|
|
|
if(frac > 1)
|
|
{
|
|
frac = 1;
|
|
}
|
|
|
|
mid[0] = start[0] + frac*(end[0] - start[0]);
|
|
mid[1] = start[1] + frac*(end[1] - start[1]);
|
|
mid[2] = start[2] + frac*(end[2] - start[2]);
|
|
|
|
side = ( t1 < 0 );
|
|
|
|
if( detectCollision( node->children[side], start, mid, impact, normal ) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if( SV_HullPointContents( cl.worldmodel->hulls, node->children[side^1], mid ) != CONTENTS_SOLID )
|
|
{
|
|
num = node->children[ side^1 ];
|
|
VectorCopy (mid, start);
|
|
|
|
continue;
|
|
}
|
|
|
|
if( !side )
|
|
{
|
|
VectorCopy (plane->normal, normal);
|
|
}
|
|
else
|
|
{
|
|
VectorNegate (plane->normal, normal);
|
|
}
|
|
|
|
VectorCopy (mid, impact);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void R_MoveParticles( void )
|
|
{
|
|
particle_t *p = active_particles;
|
|
float frametime = cl.time - cl.oldtime;
|
|
float dist;
|
|
vec3_t impact, normal, oldorigin;
|
|
|
|
while (p)
|
|
{
|
|
if ((p->die < cl.time) || (!gl_particles.value))
|
|
{
|
|
p = remParticle (p);
|
|
continue;
|
|
}
|
|
|
|
VectorCopy (p->origin, oldorigin);
|
|
|
|
p->origin[0] += p->velocity[0] * frametime;
|
|
p->origin[1] += p->velocity[1] * frametime;
|
|
p->origin[2] += p->velocity[2] * frametime;
|
|
|
|
p->alpha += frametime * p->fade;
|
|
p->scale += frametime * p->growth;
|
|
|
|
if (p->alpha <= 0.0f || p->scale <= 0.0f)
|
|
{
|
|
p = remParticle (p);
|
|
continue;
|
|
}
|
|
|
|
p->contents = Mod_PointInLeaf(p->origin, cl.worldmodel)->contents;
|
|
|
|
if ((p->contents == CONTENTS_SKY) ||
|
|
((p->contents == CONTENTS_SOLID && !p->bounce)) ||
|
|
((p->contents == CONTENTS_EMPTY) && (p->type & pt_bubble)) ||
|
|
((p->contents != CONTENTS_EMPTY) && (p->contents != CONTENTS_SOLID) && (p->type & (pt_explode | pt_bulletpuff | pt_smokeexp))))
|
|
{
|
|
p = remParticle (p);
|
|
continue;
|
|
}
|
|
|
|
p->velocity[2] += frametime * p->gravity;
|
|
|
|
if (p->type == pt_bubble)
|
|
{
|
|
p->velocity[0] = (rand() & 15) - 8;
|
|
p->velocity[1] = (rand() & 15) - 8;
|
|
p->velocity[2] = (rand() & 31) + 64;
|
|
}
|
|
|
|
if (p->bounce)
|
|
{
|
|
if (detectCollision (0, oldorigin, p->origin, impact, normal))
|
|
{
|
|
VectorCopy (impact, p->origin);
|
|
|
|
dist = DotProduct (p->velocity, normal) * -p->bounce;
|
|
|
|
VectorMA (p->velocity, dist, normal, p->velocity);
|
|
|
|
if( DotProduct (p->velocity, p->velocity) < 0.03 )
|
|
{
|
|
VectorClear (p->velocity);
|
|
p = remParticle (p);
|
|
}
|
|
}
|
|
}
|
|
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
void R_DrawParticles (void)
|
|
{
|
|
byte alpha;
|
|
|
|
vec3_t up = {vup[0] * 0.75f, vup[1] * 0.75f, vup[2] * 0.75f};
|
|
vec3_t right = {vright[0] * 0.75f, vright[1] * 0.75f, vright[2] * 0.75f};
|
|
vec3_t coord[4];
|
|
|
|
particle_t *p = active_particles;
|
|
|
|
if( !p )
|
|
return;
|
|
|
|
VectorAdd (up, right, coord[0]);
|
|
VectorSubtract (right, up, coord[1]);
|
|
VectorNegate (coord[0], coord[2]);
|
|
VectorNegate (coord[1], coord[3]);
|
|
|
|
glBindTexture (GL_TEXTURE_2D, part_font);
|
|
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
glDepthMask (false);
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE);
|
|
|
|
while (p)
|
|
{
|
|
alpha = p->alpha;
|
|
|
|
glColor4ub (p->colorred, p->colorgreen, p->colorblue, alpha);
|
|
|
|
glPushMatrix ();
|
|
{
|
|
glTranslatef (p->origin[0], p->origin[1], p->origin[2]);
|
|
glScalef (p->scale, p->scale, p->scale);
|
|
|
|
glBegin (GL_QUADS);
|
|
{
|
|
glTexCoord2f (p->texcoords[1], p->texcoords[2]); glVertex3fv (coord[0]);
|
|
glTexCoord2f (p->texcoords[1], p->texcoords[3]); glVertex3fv (coord[1]);
|
|
glTexCoord2f (p->texcoords[0], p->texcoords[3]); glVertex3fv (coord[2]);
|
|
glTexCoord2f (p->texcoords[0], p->texcoords[2]); glVertex3fv (coord[3]);
|
|
}
|
|
glEnd ();
|
|
}
|
|
glPopMatrix ();
|
|
|
|
p = p->next;
|
|
}
|
|
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
glDepthMask (true);
|
|
glColor4f (1,1,1,1);
|
|
} |