4469 lines
97 KiB
C
4469 lines
97 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.
|
|
|
|
*/
|
|
|
|
#include "globaldef.h"
|
|
#include "r_local.h"
|
|
|
|
//#define MAX_PARTICLES 8192 // default max # of particles at one
|
|
// time
|
|
#define MAX_PARTICLES 16384 // default max # of particles at one
|
|
|
|
|
|
|
|
#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's
|
|
// on the command line
|
|
|
|
#define ZEROPROPERTIES (p->scale = 1; p->scaley = p->scale; p->blend = 0; p->alpha = 1; p->frame = 0; p->alphavel = 0;p->scalexvel = 0;p->scaleyvel = 0;p->anglevel[0] = 0;p->anglevel[1] = 0;p->anglevel[2] = 0;);
|
|
|
|
|
|
int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
|
|
int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
|
|
int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3};
|
|
int ramp4[8] = {239, 236, 231, 227, 224, 0, 0, 0};
|
|
float defaultscale = 0.4f;
|
|
particle_t *active_particles, *free_particles;
|
|
|
|
particle_t *particles;
|
|
extern flare_t *currentflare;
|
|
flare_t *active_flares, *free_flares;
|
|
flare_t *flares;
|
|
int r_numparticles;
|
|
int r_numflares;
|
|
|
|
vec3_t r_pright, r_pup, r_ppn;
|
|
void R_NormalFromHerePlease (vec3_t org, vec3_t steer);
|
|
extern int particlespray;
|
|
extern int particleblood;
|
|
extern int particleset;
|
|
extern int particlelit;
|
|
|
|
int sprity = 1; // enabled if particle.spr exists and if r_particlesprite is enabled
|
|
|
|
|
|
|
|
extern qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace);
|
|
|
|
static trace_t Particle_TraceLine(vec3_t start, vec3_t end)
|
|
{
|
|
trace_t trace;
|
|
|
|
memset(&trace, 0, sizeof(trace));
|
|
trace.fraction = 1.0f;
|
|
trace.allsolid = true;
|
|
VectorCopy(end, trace.endpos);
|
|
trace.color = 4;
|
|
SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
|
|
|
|
return trace;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_InitParticles
|
|
===============
|
|
*/
|
|
void R_InitParticles (void)
|
|
{
|
|
int i;
|
|
|
|
i = COM_CheckParm ("-particles");
|
|
|
|
if (i)
|
|
{
|
|
r_numparticles = (int)(Q_atoi(com_argv[i+1]));
|
|
if (r_numparticles < ABSOLUTE_MIN_PARTICLES)
|
|
r_numparticles = ABSOLUTE_MIN_PARTICLES;
|
|
}
|
|
else
|
|
{
|
|
r_numparticles = MAX_PARTICLES;
|
|
}
|
|
|
|
particles = (particle_t *)
|
|
Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
|
|
|
|
}
|
|
|
|
|
|
void R_InitFlares (void)
|
|
{
|
|
int i;
|
|
|
|
i = COM_CheckParm ("-flares");
|
|
|
|
if (i)
|
|
{
|
|
r_numflares = (int)(Q_atoi(com_argv[i+1]));
|
|
if (r_numflares < ABSOLUTE_MIN_PARTICLES)
|
|
r_numflares = ABSOLUTE_MIN_PARTICLES;
|
|
}
|
|
else
|
|
{
|
|
r_numflares = 256;
|
|
}
|
|
|
|
flares = (flare_t *)
|
|
Hunk_AllocName (r_numparticles * sizeof(flare_t), "flares");
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
R_EntityParticles
|
|
===============
|
|
*/
|
|
|
|
#define NUMVERTEXNORMALS 162
|
|
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
|
vec3_t avelocities[NUMVERTEXNORMALS];
|
|
float beamlength = 16;
|
|
vec3_t avelocity = {23, 7, 3};
|
|
float partstep = 0.01;
|
|
float timescale = 0.01;
|
|
|
|
void R_EntityParticles (entity_t *ent)
|
|
{
|
|
// int count; // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
int i;
|
|
particle_t *p;
|
|
float angle;
|
|
float sp, sy, cp, cy; //sr, cr, // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
vec3_t forward;
|
|
float dist;
|
|
|
|
dist = 64;
|
|
// count = 50; // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
|
|
if (!avelocities[0][0])
|
|
{
|
|
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
|
|
avelocities[0][i] = (rand()&255) * 0.01;
|
|
}
|
|
|
|
for (i=0 ; i<NUMVERTEXNORMALS ; 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);
|
|
angle = cl.time * avelocities[i][2];
|
|
// sr = sin(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
// cr = cos(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
// p->owner = NULL;
|
|
p->die = cl.time + 0.01;
|
|
p->polor = 0x6f;
|
|
p->type = pt_explode;
|
|
|
|
p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength;
|
|
p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength;
|
|
p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength;
|
|
}
|
|
}
|
|
|
|
|
|
// an entity on fire!
|
|
void R_EntityFireParticles (entity_t *ent, vec3_t org, float sizefix)
|
|
{
|
|
// int count; // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
int i, g;
|
|
particle_t *p;
|
|
float angle;
|
|
float sp, sy, cp, cy, sr, cr; // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
vec3_t forward, right;
|
|
float dist;
|
|
float langth;
|
|
int moed;
|
|
langth = 5;
|
|
dist = 1;
|
|
// count = 50; // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
|
|
|
|
moed = 1;
|
|
if (!avelocities[0][0])
|
|
{
|
|
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
|
|
avelocities[0][i] = (rand()&255) * 0.01;
|
|
}
|
|
|
|
|
|
if (cl.time < ent->partfinished)
|
|
return;
|
|
|
|
if (!sizefix)
|
|
sizefix = 1.0f;
|
|
ent->partfinished = cl.time + 0.1;
|
|
|
|
for (g=0 ; g<3 ; g++)
|
|
{
|
|
angle = cl.time * avelocities[g][0];
|
|
sy = sin(angle);
|
|
cy = cos(angle);
|
|
angle = cl.time * avelocities[g][1];
|
|
sp = sin(angle);
|
|
cp = cos(angle);
|
|
angle = cl.time * avelocities[g][2];
|
|
sr = sin(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
cr = cos(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
right[0] = cp*cr;
|
|
right[1] = cp*sr;
|
|
right[2] = -sr;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
|
|
p->die = cl.time + 0.8;
|
|
p->type = pt_smoke;
|
|
p->blend = 8;
|
|
p->frame = 1;
|
|
p->alpha = 1.4f;
|
|
p->scale = 0.2f;
|
|
p->scaley = 0.2f;
|
|
p->alphavel = -1.4;
|
|
p->sprtype = SPR_VP_PARALLEL_ORIENTED;
|
|
p->scalexvel = 1.7;
|
|
p->scaleyvel = 1.2;
|
|
|
|
p->angles[PITCH] = 0;
|
|
p->angles[YAW] = 0;
|
|
p->angles[ROLL] = rand()&360;
|
|
|
|
p->ramp = 0;
|
|
p->org[0] = org[0];
|
|
p->org[1] = org[1];
|
|
p->org[2] = org[2];
|
|
p->vel[2] = 35 + rand()%66;
|
|
|
|
p->angles[0] += ent->angles[0];
|
|
p->angles[1] += ent->angles[1];
|
|
p->angles[2] += ent->angles[2];
|
|
|
|
p->polor = 237;
|
|
// p->polor = ramp4[(int)p->ramp];
|
|
// p->type = pt_fire6;
|
|
|
|
|
|
}
|
|
|
|
|
|
// flutter streamer
|
|
for (i=0 ; i<11 ; 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);
|
|
angle = cl.time * avelocities[i][2];
|
|
sr = sin(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
cr = cos(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
right[0] = cp*cr;
|
|
right[1] = cp*sr;
|
|
right[2] = -sr;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
|
|
p->die = cl.time + 0.8;
|
|
//p->polor = 0x6f;
|
|
p->polor = 44;
|
|
p->type = pt_smoke;
|
|
p->blend = 8;
|
|
p->frame = 1;
|
|
p->alpha = 1.0f;
|
|
p->scale = 0.5f;
|
|
p->scaley = 0.5f;
|
|
p->alphavel = -0.8;
|
|
p->sprtype = SPR_ORIENTED;
|
|
p->scalexvel = 0.4;
|
|
p->scaleyvel = -1.7;
|
|
|
|
p->angles[PITCH] = 90;
|
|
p->angles[YAW] = rand()&720 - 360;
|
|
p->angles[ROLL] = rand()&360;
|
|
|
|
p->anglevel[PITCH] = -180;
|
|
//p->anglevel[YAW] = -180;
|
|
p->anglevel[ROLL] = rand()&720 - 360;
|
|
//p->vel[2] = 655;
|
|
p->ramp = 0;
|
|
// p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*langth;
|
|
// p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*langth;
|
|
// p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*langth;
|
|
p->org[0] = org[0] + r_avertexnormals[i][0]*dist + forward[0]*langth;
|
|
p->org[1] = org[1] + r_avertexnormals[i][1]*dist + forward[1]*langth;
|
|
p->org[2] = org[2] + r_avertexnormals[i][2]*dist + forward[2]*langth;
|
|
p->vel[2] = 77;
|
|
|
|
p->angles[0] += ent->angles[0];
|
|
p->angles[1] += ent->angles[1];
|
|
p->angles[2] += ent->angles[2];
|
|
|
|
p->polor = 232;
|
|
// p->polor = ramp4[(int)p->ramp];
|
|
// p->type = pt_fire6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// leilei - sprite versions!
|
|
void R_FireTrail (vec3_t start, vec3_t end, entity_t *ent)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 1;
|
|
|
|
// if (len < 0)
|
|
// {
|
|
// R_EntityFireParticles (ent, ent->origin); // if not moving, go to the still fire effect
|
|
// return;
|
|
// }
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time + 2;
|
|
p->sprtype = 4;
|
|
p->blend = 0;
|
|
p->scalexvel = 0;
|
|
p->trail = 0; // damnit
|
|
p->scaleyvel = 0;
|
|
p->alphavel = 0;
|
|
p->scale = 0.3f;
|
|
p->scaley = p->scale;
|
|
p->anglevel[0] = 0;
|
|
p->anglevel[1] = 0;
|
|
p->anglevel[2] = 0;
|
|
p->alpha = 1.7f;
|
|
|
|
p->type = pt_smoke;
|
|
p->frame = 1;
|
|
p->angles[2] = rand()&450;
|
|
p->alphavel = -1.3f;
|
|
p->blend = 8;
|
|
p->die = cl.time + 0.1f;
|
|
p->scalexvel = -2.3;
|
|
p->polor = 235;
|
|
p->scaleyvel = -2.3;
|
|
p->anglevel[2] = rand()&666 - 333;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%2)-1);
|
|
|
|
|
|
if (len > 3){ // embers
|
|
p->scale = 0.1f;
|
|
p->scaley = 0.1f;
|
|
p->alphavel = -0.6f - (rand()%7 * 0.1);
|
|
p->scalexvel = -0.1f;
|
|
p->scaleyvel = -0.1f;
|
|
p->polor = 234;
|
|
p->die = cl.time + 0.8;
|
|
p->sprtype = SPR_ORIENTED;
|
|
|
|
for (j=0 ; j<3 ; j++){
|
|
p->org[j] = start[j] + ((rand()%5)-2);
|
|
p->vel[j] = rand()%12 - 6;
|
|
|
|
p->angles[j] = rand()*1024;
|
|
}
|
|
p->vel[2] += 17;
|
|
}
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
R_ClearParticles
|
|
===============
|
|
*/
|
|
void R_ClearParticles (void)
|
|
{
|
|
int i;
|
|
|
|
free_particles = &particles[0];
|
|
active_particles = NULL;
|
|
|
|
for (i=0 ;i<r_numparticles ; i++)
|
|
particles[i].next = &particles[i+1];
|
|
particles[r_numparticles-1].next = NULL;
|
|
}
|
|
|
|
|
|
void R_ClearFlares (void)
|
|
{
|
|
int i;
|
|
|
|
free_flares = &flares[0];
|
|
active_flares = NULL;
|
|
|
|
for (i=0 ;i<r_numflares ; i++)
|
|
flares[i].next = &flares[i+1];
|
|
flares[r_numflares-1].next = NULL;
|
|
}
|
|
|
|
void R_ReadPointFile_f (void)
|
|
{
|
|
FILE *f;
|
|
vec3_t org;
|
|
int r;
|
|
int c;
|
|
particle_t *p;
|
|
char name[MAX_OSPATH];
|
|
|
|
sprintf (name,"maps/%s.pts", sv.name);
|
|
|
|
COM_FOpenFile (name, &f, NULL); // 2001-09-12 Returning from which searchpath a file was loaded by Maddes
|
|
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", &org[0], &org[1], &org[2]);
|
|
if (r != 3)
|
|
break;
|
|
c++;
|
|
|
|
if (!free_particles)
|
|
{
|
|
Con_Printf ("Not enough free particles\n");
|
|
break;
|
|
}
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
// p->owner = NULL;
|
|
p->die = 99999;
|
|
p->polor = (-c)&15;
|
|
p->type = pt_static;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
VectorCopy (org, p->org);
|
|
}
|
|
|
|
fclose (f);
|
|
Con_Printf ("%i points read\n", c);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_ParseParticleEffect
|
|
|
|
Parse an effect out of the server message
|
|
===============
|
|
*/
|
|
void R_ParseParticleEffect (void)
|
|
{
|
|
vec3_t org, dir;
|
|
int i, count, msgcount, color;
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
org[i] = MSG_ReadCoord ();
|
|
for (i=0 ; i<3 ; i++)
|
|
dir[i] = MSG_ReadChar () * (1.0/16);
|
|
msgcount = MSG_ReadByte ();
|
|
color = MSG_ReadByte ();
|
|
|
|
if (msgcount == 255)
|
|
count = 1024;
|
|
else
|
|
count = msgcount;
|
|
|
|
if (particlespray)
|
|
R_RunWarticleEffect (org, dir, color, count);
|
|
else
|
|
R_RunParticleEffect (org, dir, color, count);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_ParticleExplosion
|
|
|
|
===============
|
|
*/
|
|
void R_ParticleExplosion (vec3_t org)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i=0 ; i<1024 ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->frame = 0;
|
|
|
|
|
|
p->die = cl.time + 5;
|
|
p->polor = ramp1[0];
|
|
p->ramp = rand()&3;
|
|
if (i & 1)
|
|
{
|
|
p->type = pt_explode;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_explode2;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
extern cvar_t *temp2;
|
|
|
|
|
|
// leilei's redo
|
|
void R_NormalFromHerePlease (vec3_t org, vec3_t steer);
|
|
void R_ParticleExplosionSpritey (vec3_t org)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
flare_t *f;
|
|
|
|
|
|
|
|
for (i=0 ; i<2 ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->frame = 0;
|
|
|
|
|
|
p->die = cl.time + 4.7;
|
|
|
|
// Fireball
|
|
if (i < 2){
|
|
p->frame = 11;
|
|
p->scale = 0.1;
|
|
p->scalexvel = 4;
|
|
p->scaleyvel = 0;
|
|
p->blend = 1;
|
|
p->alpha = 1.0f;
|
|
p->alphavel = -0.9f;
|
|
p->angles[2] = rand()&360;
|
|
p->anglevel[2] = rand()&360 - 180;
|
|
p->sprtype = 4;
|
|
p->scaley = p->scale;
|
|
p->type = pt_smoke;
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%64)-32;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p->frame = 12;
|
|
p->scale = 0.1;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->polor = 15;
|
|
p->die = cl.time + 2.7;
|
|
p->blend = 8;
|
|
p->polor = 56 + (rand()%15);
|
|
VectorCopy(org, p->org);
|
|
// R_NormalFromHerePlease(p->org,p->angles);
|
|
p->scaley = p->scale;
|
|
p->alpha = 2.0f;
|
|
p->alphavel = -1.2f - rand()%2;
|
|
p->angles[2] = rand()&360;
|
|
p->type = pt_sparkvel;
|
|
//p->sprtype = 1; // for directional sprites!
|
|
p->sprtype = 1; // for directional sprites!
|
|
//p->scaley = 4;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = rand()% 1800 - 900;
|
|
}
|
|
// p->vel[2] = (rand()%356)-128;
|
|
}
|
|
}
|
|
|
|
// then the flare.
|
|
|
|
|
|
|
|
|
|
// else
|
|
|
|
/*
|
|
if (!free_flares)
|
|
return;
|
|
|
|
f = free_flares;
|
|
free_flares = f->next;
|
|
f->next = active_flares;
|
|
active_flares = f;
|
|
f->frame = 12;
|
|
f->scale = 0.2;
|
|
f->scalexvel = 6;
|
|
p->scaleyvel = 0;
|
|
f->blend = 3;
|
|
f->polor = 79;
|
|
// f->alpha = 1.2f;
|
|
f->die = cl.time + 0.3;
|
|
f->alphavel = -1.9f;
|
|
f->angles[2] = 0;
|
|
f->anglevel[2] = 0;
|
|
f->sprtype = 5;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
f->org[j] = org[j];
|
|
f->vel[j] = 0;
|
|
}
|
|
|
|
|
|
{
|
|
trace_t tarce;
|
|
tarce = Particle_TraceLine(org, r_refdef.vieworg);
|
|
if(tarce.fraction < 1)
|
|
f->alpha = 0;
|
|
else
|
|
f->alpha = 1;
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
extern cvar_t *r_particletrails;
|
|
|
|
/*
|
|
===============
|
|
R_ParticleTrail
|
|
|
|
===============
|
|
*/
|
|
void R_ParticleTrail (vec3_t org, vec3_t veloc, int trl, float tim, int coll, float alf, int blend)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
|
|
if (!free_particles)
|
|
return;
|
|
if (!r_particletrails->value)
|
|
return;
|
|
if ((cl.time - cl.oldtime) < 0.01) // you're too fast
|
|
return;
|
|
if ((cl.time - cl.oldtime) > 0.3) // you're slow
|
|
return;
|
|
return;
|
|
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->die = cl.time + tim;
|
|
p->frame = 0;
|
|
//p->die = cl.time + ( cl.time - cl.oldtime);
|
|
p->polor = coll;
|
|
p->type = pt_trail;
|
|
p->trail = trl - 1;
|
|
p->alpha = alf;
|
|
p->blend = blend;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = veloc[j] * -0.5;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
R_ParticleBloodSplash
|
|
|
|
|
|
for blood drip maybe
|
|
===============
|
|
*/
|
|
extern sfx_t *cl_sfx_wizhit;
|
|
|
|
extern sfx_t *cl_sfx_bloodhit1;
|
|
extern sfx_t *cl_sfx_bloodhit2;
|
|
extern sfx_t *cl_sfx_bloodhit3;
|
|
void R_ParticleBloodSplash (vec3_t org, int veel, int col)
|
|
{
|
|
int i, j;
|
|
float wa;
|
|
particle_t *p;
|
|
|
|
wa = veel;
|
|
if (wa > 0.6)
|
|
wa = 0.6;
|
|
if (wa < 0)
|
|
wa = 0.1;
|
|
|
|
veel = veel * -0.2;
|
|
S_StartSound2 (-1, 0, cl_sfx_wizhit, org, 0.2, 3.7, (rand()%12) + 4);
|
|
for (i=0 ; i<3 ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->die = cl.time + 0.6;
|
|
p->polor = col;
|
|
p->ramp = rand()&3;
|
|
p->trail = 3;
|
|
if (particleset == 2){
|
|
p->frame = 7;
|
|
p->scale = 0.02f;
|
|
p->scaley = 0.02f;
|
|
p->scalexvel = 1;
|
|
p->scaleyvel = 0;
|
|
p->alphavel = -0.3;
|
|
p->blend = 0;
|
|
p->alpha = 0.5f;
|
|
p->trail = 0;
|
|
}
|
|
else
|
|
{
|
|
p->alpha = 1;
|
|
p->alphavel = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->frame = 0;
|
|
p->scale = 1;
|
|
p->scaley = 1;
|
|
}
|
|
|
|
{
|
|
if (p->polor > 63 && p->polor < 80)
|
|
p->type = pt_bloodsplat;
|
|
else
|
|
p->type = pt_fastgrav;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%2)-1);
|
|
p->vel[j] = (rand()%32)-16;
|
|
|
|
}
|
|
p->vel[2] += (rand()%veel);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void R_ParticleWat (vec3_t org, int colr)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i=0 ; i<2 ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->die = cl.time + 0.02;
|
|
p->polor = colr;
|
|
|
|
{
|
|
p->type = pt_static;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = (rand()%64)-32;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
===============
|
|
R_ParticleExplosion2
|
|
|
|
===============
|
|
*/
|
|
void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int colorMod = 0;
|
|
|
|
for (i=0; i<512; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->frame = 0;
|
|
p->die = cl.time + 0.3;
|
|
p->polor = colorStart + (colorMod % colorLength);
|
|
colorMod++;
|
|
|
|
p->type = pt_blob;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void R_ParticleBloodSpewism (vec3_t org, int much)
|
|
{
|
|
int i, j;
|
|
vec3_t fe;
|
|
int colorMod = 0;
|
|
|
|
for (i=1; i<much; i+=2)
|
|
{
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
fe[j] = ((rand()%32)-16);
|
|
}
|
|
fe[2] += 4+i;
|
|
|
|
R_RunParticleEffect(org, fe, 79, 3 * i);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_BlobExplosion
|
|
|
|
===============
|
|
*/
|
|
void R_BlobExplosion (vec3_t org)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i=0 ; i<1024 ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
|
|
p->die = cl.time + 1 + (rand()&8)*0.05;
|
|
|
|
if (i & 1)
|
|
{
|
|
p->type = pt_blob;
|
|
p->polor = 66 + rand()%6;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_blob2;
|
|
p->polor = 150 + rand()%6;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
R_PlasmaExplosion
|
|
used by TE_TEI_PLASMAHIT
|
|
===============
|
|
*/
|
|
void R_PlasmaExplosion (vec3_t org, int colorStart, int colorLength, int count)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int colorMod = 0;
|
|
|
|
for (i=0; i<count; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
// TODO: Implement Spark Trail type
|
|
p->die = cl.time + 0.4;
|
|
p->frame = 0;
|
|
p->polor = colorStart + (colorMod % colorLength);
|
|
colorMod++;
|
|
|
|
p->type = pt_decel;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%4)-2);
|
|
p->vel[j] = (rand()%1500)-750;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
===============
|
|
R_RunParticleEffect
|
|
|
|
|
|
|
|
===============
|
|
*/
|
|
|
|
//
|
|
// The original Quack particles
|
|
//
|
|
extern cvar_t *r_particlesparks;
|
|
extern cvar_t *r_particletrails;
|
|
extern cvar_t *r_particlebloodfade;
|
|
extern cvar_t *temp2;
|
|
extern cvar_t *s_blood;
|
|
|
|
void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int density;
|
|
if (particleset == 2)
|
|
//density = (1 * (count / 5)); // reduce the spraying for sprites
|
|
density = 8; // reduce the spraying for sprites
|
|
else
|
|
density = 1;
|
|
|
|
if (particleblood < 0 && (color > 63) && (color < 80) && count != 1024)
|
|
return; //we disable the blood!
|
|
|
|
if (particleblood > 1 && (color > 63) && (color < 80) && count != 1024){
|
|
int o, m, f, g;
|
|
vec3_t shoo, ting, tha, tway;
|
|
// Blood Spurt of some sort.
|
|
|
|
// sound hack
|
|
if (s_blood->value){
|
|
if (count < 15)
|
|
S_StartSound2 (-1, 0, cl_sfx_bloodhit3, org, 0.2, 3.1, (12 / count ));
|
|
else if (count > 44)
|
|
S_StartSound2 (-1, 0, cl_sfx_bloodhit2, org, 0.6, 3.1, (20 / count ));
|
|
else
|
|
S_StartSound2 (-1, 0, cl_sfx_bloodhit3, org, 0.4, 3.1, (44 / count ));
|
|
}
|
|
|
|
o = (particleblood * 0.3)* count;
|
|
m = o;
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
shoo[j] = dir[j] + (rand()%5)-2.5 * -1;
|
|
ting[j] = dir[j] + (rand()%5)-2.5;
|
|
tha[j] = dir[j] + (rand()%5)-2.5;
|
|
tway[j] = dir[j] + (rand()%5)-2.5;
|
|
}
|
|
|
|
|
|
for (i=-3 ; i<o ; i+=density)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
//p->flat = 1; // testing
|
|
p->frame = 0;
|
|
p->scale = 0.4f;
|
|
p->scaley = 0.4f;
|
|
p->alpha = 1.0f;
|
|
p->alphavel = -0.5f;
|
|
p->scalexvel = 0.15f * (count / 2.4); // scale upper
|
|
p->scaleyvel = 0.0f; // don't do sticky drop...
|
|
|
|
|
|
|
|
p->next = active_particles;
|
|
if (particleset == 2){ p->frame = 8 - rand()%4; p->blend = 10; p->scale = 0.23f; p->scaley = p->scale; p->angles[2] = rand()&360; p->anglevel[2] = rand()&500-250; p->sprtype = 4; }
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
{
|
|
p->die = cl.time + 0.6*(rand()%32);
|
|
p->polor = 79 - (rand()&6);
|
|
if (particleblood > 2){
|
|
p->die = cl.time + 0.6*(rand()%32);
|
|
p->type = pt_bloodsplat;
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_slowgrav;
|
|
p->die = cl.time + 0.6*(rand()%2);
|
|
}
|
|
|
|
|
|
if (i<12){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()%4)-2;
|
|
p->vel[j] = dir[j]*(rand()*(count*0.5))-(count);
|
|
//p->polor = (color&~7) + (rand()&7);
|
|
// p->polor = 66 + (rand()&12);
|
|
}
|
|
}
|
|
else if (i<28){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()&((count/8))-(count/16));
|
|
p->vel[j] = dir[j]*(i * 0.8);
|
|
p->vel[2] += (i / 5);
|
|
}
|
|
}
|
|
else if (i<96){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()&((count/8))-(count/16)); // Prydon had a problem with this (fixed now though)
|
|
p->vel[j] = shoo[j]*(i * 0.2);
|
|
p->vel[2] += (i / 5);
|
|
}
|
|
}
|
|
else if (i<112){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()&((count/8))-(count/16));
|
|
p->vel[j] = ting[j]*(i * 0.2);
|
|
p->vel[2] += (i / 5);
|
|
}
|
|
}
|
|
else if (i<128){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()&((count/8))-(count/16));
|
|
p->vel[j] = tha[j]*(i * 0.2);
|
|
p->vel[2] += (i / 5);
|
|
}
|
|
}
|
|
else if (i<132){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()&((count/8))-(count/16));
|
|
p->vel[j] = tway[j]*(i * 0.2);
|
|
p->vel[2] += (i / 5);
|
|
}
|
|
}
|
|
else if (i>200){
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + (rand()&((count/8))-(count/16));
|
|
p->vel[j] = dir[j]* (rand()%i)-(i*0.5);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = dir[j]*(i * 0.3);
|
|
p->vel[2] *= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
if (particleset == 2){
|
|
p->scale = count / 48;
|
|
p->scalexvel = p->scale * 0.4;
|
|
p->scaleyvel = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (r_particlesparks->value && (color > 224)){
|
|
for (i=0 ; i<count ; i+=density)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->trail = 14; // testing
|
|
p->blend = 1;
|
|
p->frame = 0;
|
|
p->die = cl.time + 0.8*(rand()%5);
|
|
p->alphavel = -1;
|
|
p->polor = (color&~7) + (rand()&7);
|
|
//p->polor = color;
|
|
p->type = pt_spark;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
// p->org[j] = org[j] + ((rand()&15)-8);
|
|
p->org[j] = org[j];//+ ((rand()&15)-8);
|
|
p->vel[j] = dir[j]*16656 + (rand()%300)-150 ;
|
|
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
for (i=0 ; i<count ; i+=density)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
// p->trail = 6; // testing
|
|
|
|
// p->splatter = 0;
|
|
p->frame = 0;
|
|
|
|
if (count == 1024)
|
|
{ // rocket explosion
|
|
p->die = cl.time + 5;
|
|
p->polor = ramp1[0];
|
|
;
|
|
p->ramp = rand()&3;
|
|
if (particleset == 2){ R_ParticleExplosionSpritey(org); return; }
|
|
if (i & 1)
|
|
{
|
|
p->type = pt_explode;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_explode2;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
p->die = cl.time + 0.1*(rand()%5);
|
|
p->polor = (color&~7) + (rand()&7);
|
|
p->type = pt_slowgrav;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()&15)-8);
|
|
p->vel[j] = dir[j]*15;// + (rand()%300)-150;
|
|
|
|
}
|
|
if (particleblood){
|
|
if ((color > 63) && (color < 80)){
|
|
//p->lit = 1;
|
|
p->type = pt_blood;
|
|
}
|
|
}
|
|
if (particleset == 2){ p->alpha = 1.0f; p->frame = 1; p->blend = 8; p->scalexvel = 3; p->scaleyvel = 0; p->alphavel = -2.9f; p->scale = 0.01f;p->scaley = p->scale; p->angles[2] = rand()&360; p->anglevel[2] = rand()&800-400; p->sprtype = 4; }
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// different alternate 'additive' method
|
|
// origin is smaller and velocity is more random
|
|
// it also fades and prefers scale over quantity (to be implemented)
|
|
// using it depends on your taste.
|
|
|
|
void R_RunWarticleEffect (vec3_t org, vec3_t dir, int color, int count)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->frame = 0;
|
|
{
|
|
p->die = cl.time + 0.2*(rand()%5);
|
|
p->polor = color;
|
|
p->type = pt_bloodsplat;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = dir[j]*15 + (rand()%50)-25;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------
|
|
// Used by TE_TEI_SMOKE
|
|
// --------------------
|
|
|
|
void R_Smoke (vec3_t org, vec3_t dir, int color, int count)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int nexte = 1;
|
|
if (sprity) nexte = 8;
|
|
for (i=0 ; i<count ; i+=nexte)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
// p->owner = NULL;
|
|
p->type = pt_smoke;
|
|
p->frame = 1;
|
|
p->blend = 1;
|
|
R_NormalFromHerePlease(p->org, p->angles);
|
|
// p->vel[0] = p->angles[0];
|
|
// p->vel[1] = p->angles[1];
|
|
// p->vel[2] = p->angles[2];
|
|
// p->splatter = 0;
|
|
p->sprtype = 4;
|
|
p->angles[2] = rand()&555;
|
|
p->alpha = 1.0f;
|
|
p->scale = 0.02f;
|
|
p->scaley = p->scale;
|
|
p->alphavel = -0.5;
|
|
p->trail = 0;
|
|
p->scalexvel = 0.7;
|
|
p->scaleyvel = 0.5;
|
|
p->anglevel[2] = rand()&1000 - 500;
|
|
{
|
|
if (sprity)
|
|
p->die = cl.time + 2.6*(rand()%5);
|
|
else
|
|
p->die = cl.time + 0.1*(rand()%5);
|
|
p->polor = (color&~7) + (rand()&7);
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
if (sprity)
|
|
p->org[j] = org[j] + ((rand()%2)-1);
|
|
else
|
|
p->org[j] = org[j] + ((rand()%6)-3);
|
|
p->vel[j] = (rand()%50)-25;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void vectoangles2 (vec3_t value1, vec3_t angles);
|
|
|
|
void vectoangles(vec3_t vec, vec3_t ang)
|
|
{
|
|
float forward;
|
|
float yaw, pitch;
|
|
|
|
if (vec[1] == 0 && vec[0] == 0)
|
|
{
|
|
yaw = 0;
|
|
if (vec[2] > 0)
|
|
pitch = 90;
|
|
else
|
|
pitch = 270;
|
|
}
|
|
else
|
|
{
|
|
yaw = (int) (atan2(vec[1], vec[0]) * 180 / M_PI);
|
|
if (yaw < 0)
|
|
yaw += 360;
|
|
|
|
forward = sqrt (vec[0]*vec[0] + vec[1]*vec[1]);
|
|
pitch = (int) (atan2(vec[2], forward) * 180 / M_PI);
|
|
if (pitch < 0)
|
|
pitch += 360;
|
|
}
|
|
|
|
ang[0] = pitch;
|
|
ang[1] = yaw;
|
|
ang[2] = 0;
|
|
}
|
|
|
|
// partially butchered from Darkplaces' CL_SpawnDecalParticleForPoint
|
|
void R_Decal (vec3_t org, int decframe, int blend, float sceel, int splat)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int nexte = 1;
|
|
int count = 1;
|
|
|
|
trace_t trace;
|
|
|
|
float bestfrac, bestorg[3], bestnormal[3];
|
|
float org2[3];
|
|
float fraccy = 0;
|
|
vec3_t heer;
|
|
vec3_t nermal;
|
|
vec3_t teer;
|
|
int besthitent = 0, hitent;
|
|
int maxdist = 9;
|
|
bestfrac = 10;
|
|
//decframe = 4;
|
|
|
|
for (i = 0;i < 32;i++)
|
|
{
|
|
org2[0] = rand()%4 - rand()%2;
|
|
org2[1] = rand()%4 - rand()%2;
|
|
org2[2] = rand()%4 - rand()%2;
|
|
VectorMA(org, maxdist, org2, org2);
|
|
trace = Particle_TraceLine(org, org2);
|
|
// take the closest trace result that doesn't end up hitting a NOMARKS
|
|
// surface (sky for example)
|
|
if (bestfrac > trace.fraction)
|
|
{
|
|
bestfrac = trace.fraction;
|
|
// besthitent = hitent;
|
|
VectorCopy(trace.endpos, bestorg);
|
|
VectorCopy(trace.plane.normal, bestnormal);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (bestfrac < 1) // it's time to create.
|
|
{
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->type = pt_decal;
|
|
p->frame = decframe;
|
|
p->blend = blend;
|
|
// p->splatter = 0;
|
|
p->sprtype = 3;
|
|
|
|
p->alpha = 8.0f;
|
|
|
|
if (!sceel)
|
|
p->scale = 0.4f;
|
|
else
|
|
p->scale = sceel;
|
|
p->scaley = p->scale;
|
|
p->alphavel = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->anglevel[0] = 0;
|
|
p->trail = 0;
|
|
p->anglevel[1] = 0;
|
|
p->anglevel[2] = 0;
|
|
p->die = cl.time + 76;
|
|
|
|
p->angles[0] = -bestnormal[0];
|
|
p->angles[1] = -bestnormal[1];
|
|
p->angles[2] = -bestnormal[2];
|
|
p->angles[2] *= -1;
|
|
if (splat){
|
|
p->type = pt_bloodrun;
|
|
p->blend = blend;
|
|
}
|
|
|
|
// Con_Printf("%f yes\n",p->angles[2]);
|
|
vectoangles(p->angles, p->angles);
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = bestorg[j];
|
|
|
|
p->vel[j] = 0;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void R_NormalFromHerePlease (vec3_t org, vec3_t steer)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int nexte = 1;
|
|
int count = 1;
|
|
|
|
trace_t trace;
|
|
|
|
float bestfrac, bestorg[3], bestnormal[3];
|
|
float org2[3];
|
|
float org4[3];
|
|
float fraccy = 0;
|
|
vec3_t heer;
|
|
vec3_t nermal;
|
|
vec3_t teer;
|
|
|
|
int besthitent = 0, hitent;
|
|
int maxdist = 9;
|
|
bestfrac = 10;
|
|
//decframe = 4;
|
|
org4[0] = org[0];
|
|
org4[1] = org[1];
|
|
org4[2] = org[2];
|
|
for (i = 0;i < 32;i++)
|
|
{
|
|
org2[0] = rand()%4 - rand()%2;
|
|
org2[1] = rand()%4 - rand()%2;
|
|
org2[2] = rand()%4 - rand()%2;
|
|
|
|
VectorMA(org4, maxdist, org2, org2);
|
|
trace = Particle_TraceLine(org4, org2);
|
|
// take the closest trace result that doesn't end up hitting a NOMARKS
|
|
// surface (sky for example)
|
|
if (bestfrac > trace.fraction)
|
|
{
|
|
bestfrac = trace.fraction;
|
|
// besthitent = hitent;
|
|
VectorCopy(trace.endpos, bestorg);
|
|
VectorCopy(trace.plane.normal, bestnormal);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (bestfrac < 1) // it's time to create.
|
|
{
|
|
|
|
steer[0] = bestnormal[0];
|
|
steer[1] = bestnormal[1];
|
|
steer[2] = bestnormal[2];
|
|
//steer[2] *= -1;
|
|
//org[0] = bestorg[0]; // don't return orgies if we don't want them
|
|
//org[1] = bestorg[1];
|
|
//org[2] = bestorg[2];
|
|
vectoangles(steer, steer);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int R_GimmeTheColorOfThisWall (vec3_t org)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int nexte = 1;
|
|
int count = 1;
|
|
int color;
|
|
trace_t trace;
|
|
|
|
float bestfrac, bestorg[3], bestnormal[3];
|
|
float org2[3];
|
|
float fraccy = 0;
|
|
vec3_t heer;
|
|
vec3_t nermal;
|
|
vec3_t teer;
|
|
|
|
int besthitent = 0, hitent;
|
|
int maxdist = 9;
|
|
bestfrac = 10;
|
|
//decframe = 4;
|
|
|
|
for (i = 0;i < 32;i++)
|
|
{
|
|
org2[0] = rand()%4 - rand()%2;
|
|
org2[1] = rand()%4 - rand()%2;
|
|
org2[2] = rand()%4 - rand()%2;
|
|
VectorMA(org, maxdist, org2, org2);
|
|
trace = Particle_TraceLine(org, org2);
|
|
if (bestfrac > trace.fraction)
|
|
{
|
|
bestfrac = trace.fraction;
|
|
}
|
|
}
|
|
|
|
|
|
if (bestfrac < 1) // it's time to create.
|
|
{
|
|
color = trace.color;
|
|
return color;
|
|
}
|
|
}
|
|
|
|
|
|
void R_FlareInstant (vec3_t org, int decframe, int colr, int colg, int colb, int tayp)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
int nexte = 1;
|
|
int count = 1;
|
|
int gmcol;
|
|
|
|
|
|
for (i=0 ; i<1 ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
|
|
p->frame = decframe;
|
|
p->blend = 5;
|
|
gmcol = BestColor(colr, colg, colb, 12, 222); // determine color from bestcoloring
|
|
p->polor = gmcol;
|
|
p->color = gmcol;
|
|
|
|
|
|
// determine initial visibility first so we don't see exploded flares on spawn
|
|
p->sprtype = tayp;
|
|
p->angles[2] = 0; // will random these.
|
|
//p->alpha = 1.0f;
|
|
p->alpha = 1.0f; // we are drawing in front of everything anyway.
|
|
p->alphavel = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->anglevel[0] = 0;
|
|
p->anglevel[1] = 0;
|
|
p->anglevel[2] = 0;
|
|
|
|
p->type = pt_flare_will_die;
|
|
p->scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
|
|
+ (p->org[2] - r_origin[2])*vpn[2];
|
|
if (p->scale < 40)
|
|
p->scale = 0.3;
|
|
else
|
|
p->scale = 0.3 + p->scale * 0.004;
|
|
}
|
|
p->scaley = p->scale;
|
|
{
|
|
p->die = cl.time + 0.08; // for now
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
extern cvar_t *r_flares;
|
|
|
|
// leilei - experimental unr**l-style flares
|
|
void R_FlareTest (vec3_t org, int decframe, int colr, int colg, int colb, float gonnjardie, entity_t *ownme)
|
|
{
|
|
int i, j;
|
|
flare_t *p;
|
|
int nexte = 1;
|
|
int count = 1;
|
|
int gmcol;
|
|
int ownin;
|
|
int gonnadie = 0;
|
|
float initialalpha;
|
|
trace_t tarce;
|
|
|
|
if (!r_flares->value)
|
|
return; // don't draw flares if we don't want flares.
|
|
decframe = 12;
|
|
if (cls.demoplayback)
|
|
return; // because my checks for visibility cause a crash in demo playback. :(
|
|
if (ownme == NULL)
|
|
ownin = 0;
|
|
else
|
|
ownin = 1;
|
|
|
|
if (ownin && ownme->ourparticle)
|
|
return; //we got one.
|
|
|
|
|
|
// determine if we've spawned in a wall like an idiot would do.
|
|
mleaf_t *o;
|
|
o = Mod_PointInLeaf (org, cl.worldmodel);
|
|
|
|
if (o->contents != CONTENTS_EMPTY )
|
|
return;
|
|
|
|
// place each flare with their personal values!
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
if (!free_flares)
|
|
return;
|
|
p = free_flares;
|
|
free_flares = p->next;
|
|
p->next = active_flares;
|
|
p->owner = NULL;
|
|
active_flares = p;
|
|
|
|
p->frame = decframe;
|
|
p->blend = 5;
|
|
D_TestOurFlare(p);
|
|
|
|
if(!p->amiseen)
|
|
initialalpha = 0;
|
|
else{
|
|
if (gonnjardie)
|
|
initialalpha = gonnjardie;
|
|
else
|
|
initialalpha = 1;
|
|
}
|
|
|
|
// determine color. we are going to use gelmaps for flares.
|
|
gmcol = BestColor(colr, colg, colb, 12, 222); // determine color from bestcoloring
|
|
p->polor = gmcol;
|
|
p->color = gmcol;
|
|
|
|
if (ownin){
|
|
p->owner = ownme;
|
|
}
|
|
|
|
// determine initial visibility first so we don't see exploded flares on spawn
|
|
if((Traceline(p->org, r_refdef.vieworg, NULL, NULL)))
|
|
p->alpha = 1.0f;
|
|
else
|
|
p->alpha = 0.02f;
|
|
|
|
p->blend = 5;
|
|
p->sprtype = 5;
|
|
p->angles[2] = 0; // will random these.
|
|
p->alpha = initialalpha;
|
|
|
|
if (ownin){
|
|
p->owner = ownme;
|
|
ownme->ourparticle = p;
|
|
p->owned = 1; // OWNED.
|
|
}
|
|
|
|
p->alphavel = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->anglevel[0] = 0;
|
|
p->anglevel[1] = 0;
|
|
p->anglevel[2] = 0;
|
|
|
|
p->type = pt_flare;
|
|
p->scale = 0;
|
|
p->scaley = p->scale;
|
|
p->die = cl.time + 7500; // for EVER!
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------
|
|
// Used for the engine splash calls (by r_particle_splash)
|
|
// --------------------
|
|
|
|
void R_Splash (vec3_t org, vec3_t dir, int color, int count, int power)
|
|
{
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
// p->splatter = 0;
|
|
p->frame = 0;
|
|
p->trail = 0;
|
|
|
|
if (count == 1024)
|
|
{ // rocket explosion
|
|
p->die = cl.time + 5;
|
|
p->polor = ramp1[0];
|
|
p->ramp = rand()&3;
|
|
if (i & 1)
|
|
{
|
|
p->type = pt_smoke;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_smoke;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()%32)-16);
|
|
p->vel[j] = (rand()%512)-256;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p->die = cl.time + 0.4*(rand()%5);
|
|
p->polor = color;
|
|
p->type = pt_blob;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j];
|
|
p->vel[j] = (rand()%350)-(125);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_LavaSplash
|
|
|
|
===============
|
|
*/
|
|
|
|
void R_LavaSplash (vec3_t org)
|
|
{
|
|
int i, j, k;
|
|
particle_t *p;
|
|
float vel;
|
|
vec3_t dir;
|
|
|
|
for (i=-16 ; i<16 ; i++)
|
|
for (j=-16 ; j<16 ; j++)
|
|
for (k=0 ; k<1 ; k++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
|
|
p->die = cl.time + 2 + (rand()&31) * 0.02;
|
|
p->polor = 224 + (rand()&7);
|
|
p->type = pt_slowgrav;
|
|
p->frame = 0;
|
|
dir[0] = j*8 + (rand()&7);
|
|
dir[1] = i*8 + (rand()&7);
|
|
dir[2] = 256;
|
|
|
|
p->org[0] = org[0] + dir[0];
|
|
p->org[1] = org[1] + dir[1];
|
|
p->org[2] = org[2] + (rand()&63);
|
|
|
|
VectorNormalize (dir);
|
|
vel = 50 + (rand()&63);
|
|
VectorScale (dir, vel, p->vel);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_Blood
|
|
===============
|
|
*/
|
|
void R_Blood(int count, vec3_t mins, vec3_t maxs, vec3_t vel_mins, vec3_t vel_maxs)
|
|
{
|
|
const int color = 73;
|
|
int idist[3], vdist[3];
|
|
int i, j;
|
|
particle_t *p;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
idist[i] = (int)(maxs[i] - mins[i] + 0.1f);
|
|
vdist[i] = (int)(vel_maxs[i] - vel_mins[i] + 0.1f);
|
|
|
|
if (idist[i] < 1)
|
|
idist[i] = 1;
|
|
if (vdist[i] < 1)
|
|
vdist[i] = 1;
|
|
}
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (!free_particles)
|
|
break;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
//p->die = cl.time + 0.1*(rand()%5);
|
|
p->die = cl.time + 0.1*(rand()%65);
|
|
p->polor = (float)((color&~7) + (rand()&7));
|
|
//p->splatter = 3;
|
|
//p->lit = 1;
|
|
p->type = pt_bloodsplat;
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
p->org[j] = mins[j] + rand() % idist[j] + ((rand()&15)-8);
|
|
p->vel[j] = vel_mins[j] + rand() % vdist[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
R_Rain
|
|
|
|
Tomazquake code adopted
|
|
===============
|
|
*/
|
|
void R_Rain (vec3_t min, vec3_t max, int drops)
|
|
{
|
|
int i;
|
|
vec3_t difference;
|
|
particle_t *p;
|
|
|
|
for (i=0 ; i<drops ; i++)
|
|
{
|
|
if (!free_particles)
|
|
break;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorSubtract(max, min, difference);
|
|
p->die = cl.time + 10;
|
|
|
|
p->alpha = 0.4f;
|
|
|
|
p->polor = 8;
|
|
if (particleset == 2)
|
|
p->trail = 0;
|
|
else
|
|
p->trail = 6;
|
|
p->type = pt_drip;
|
|
p->scale = 0.01f;
|
|
p->scaley = 2;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 3;
|
|
p->frame = 3;
|
|
p->blend = 1;
|
|
p->sprtype = 3;
|
|
|
|
p->org[0] = difference[0] * (rand () & 2047) * 0.00048828125 + min[0]; // Tomaz - Speed
|
|
p->org[1] = difference[1] * (rand () & 2047) * 0.00048828125 + min[1]; // Tomaz - Speed
|
|
p->org[2] = max[2] - 10;
|
|
|
|
p->vel[0] = 0;
|
|
p->vel[1] = 0;
|
|
p->vel[2] = -400 - (rand() & 600);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void R_Snow (vec3_t min, vec3_t max, int drops)
|
|
{
|
|
int i;
|
|
vec3_t difference;
|
|
particle_t *p;
|
|
for (i=0 ; i<drops ; i++)
|
|
{
|
|
if (!free_particles)
|
|
break;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorSubtract(max, min, difference);
|
|
p->die = cl.time + 10;
|
|
|
|
p->alpha = 0.4f;
|
|
|
|
p->polor = 14;
|
|
p->trail = 0;
|
|
p->alpha = 0.27f;
|
|
p->blend = 1;
|
|
p->type = pt_snow;
|
|
|
|
if (particleset == 2){
|
|
p->scale = 0.05f;
|
|
p->scaley = 0.05f;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->frame = 3;
|
|
p->blend = 1;
|
|
|
|
}
|
|
|
|
p->org[0] = difference[0] * (rand () & 2047) * 0.00048828125 + min[0]; // Tomaz - Speed
|
|
p->org[1] = difference[1] * (rand () & 2047) * 0.00048828125 + min[1]; // Tomaz - Speed
|
|
p->org[2] = max[2] - 10;
|
|
|
|
p->vel[0] = 0;
|
|
p->vel[1] = 0;
|
|
p->vel[2] = -40;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_TeleportSplash
|
|
|
|
===============
|
|
*/
|
|
void R_TeleportSplash (vec3_t org)
|
|
{
|
|
int i, j, k;
|
|
particle_t *p;
|
|
float vel;
|
|
vec3_t dir;
|
|
|
|
for (i=-16 ; i<16 ; i+=4)
|
|
for (j=-16 ; j<16 ; j+=4)
|
|
for (k=-24 ; k<32 ; k+=4)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
p->alpha = 1.0f; // leilei - don't alpha!
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
p->die = cl.time + 0.2 + (rand()&7) * 0.02;
|
|
p->polor = 7 + (rand()&7);
|
|
p->type = pt_slowgrav;
|
|
|
|
dir[0] = j*8;
|
|
dir[1] = i*8;
|
|
dir[2] = k*8;
|
|
|
|
p->org[0] = org[0] + i + (rand()&3);
|
|
p->org[1] = org[1] + j + (rand()&3);
|
|
p->org[2] = org[2] + k + (rand()&3);
|
|
|
|
VectorNormalize (dir);
|
|
vel = 50 + (rand()&63);
|
|
VectorScale (dir, vel, p->vel);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
======
|
|
QUAKE2 SOURCE
|
|
vectoangles2 - this is duplicated in the game DLL, but I need it here.
|
|
======
|
|
*/
|
|
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
|
|
{
|
|
// PMM - fixed to correct for pitch of 0
|
|
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;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
QUAKE2 SOURCE
|
|
R_CurlyBloodTrail
|
|
|
|
Adapted from Quake2's CL_TrackerTrail for the unused Disintegrator/Disruptor
|
|
weapon for q2 rogue
|
|
===============
|
|
*/
|
|
void R_CurlyBloodTrail (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;
|
|
particle_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);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
VectorClear (p->vel);
|
|
p->frame = 0;
|
|
p->die = cl.time + 7.5;
|
|
p->type = pt_bloodsplat;
|
|
p->alpha = 1.0;
|
|
p->blend = 0;
|
|
if (particleset == 2)
|
|
p->frame = 7;
|
|
//p->alphavel = -2.0;
|
|
p->alphavel = 0;p->scalexvel = 0;p->scaleyvel = 0;p->anglevel[0] = 0;p->anglevel[1] = 0;p->anglevel[2] = 0;
|
|
p->polor = 75;
|
|
p->scaley = p->scale;
|
|
dist = DotProduct(move, forward);
|
|
VectorMA(move, 7 * cos(dist), up, p->org);
|
|
VectorMA(move, 7 * cos(dist), right, p->org);
|
|
p->scalexvel = 0.3f;
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
// p->org[j] = start[j] + ((rand()%6)-3);
|
|
//p->vel[j] = 100 * cos(dist) + (100 * sin(dist));
|
|
|
|
// p->vel[j] = 0;
|
|
//p->accel[j] = 0;
|
|
|
|
}
|
|
p->vel[0] += 22 * sin(dist);
|
|
p->vel[1] += 22 * sin(dist);
|
|
p->vel[2] += 22 * cos(dist);
|
|
//p->vel[2] = 5;
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
// f;or the plarticle blood vlariable
|
|
void R_GusherizeCurlyBloodTrail (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;
|
|
particle_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 = (56 / particleblood);
|
|
VectorScale (vec, 3, vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
VectorClear (p->vel);
|
|
p->alpha = 1; p->scale = defaultscale; p->alphavel = 0;p->scalexvel = 0;p->scaleyvel = 0;p->anglevel[0] = 0;p->anglevel[1] = 0;p->anglevel[2] = 0;
|
|
|
|
p->scaley = p->scale;
|
|
p->die = cl.time + 7.5;
|
|
p->type = pt_bloodsplat;
|
|
p->alpha = 1.0;
|
|
|
|
p->frame = 0;
|
|
if (particleset == 2)
|
|
p->frame = 7;
|
|
//p->alphavel = -2.0;
|
|
p->polor = 75;
|
|
|
|
dist = DotProduct(move, forward);
|
|
VectorMA(move, len * 5 * cos(dist), up, p->org);
|
|
VectorMA(move, len * 5 * cos(dist), right, p->org);
|
|
p->blend = 10;
|
|
p->alphavel = -0.5f;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
// p->org[j] = start[j] + ((rand()len)-(len * 0.5));
|
|
//p->vel[j] = 100 * cos(dist) + (100 * sin(dist));
|
|
|
|
// p->vel[j] = 0;
|
|
//p->accel[j] = 0;
|
|
|
|
}
|
|
p->vel[0] += 12 * sin(dist);
|
|
p->vel[1] += 12 * sin(dist);
|
|
p->vel[2] += 12 * cos(dist);
|
|
p->vel[0] *= vec[0];
|
|
p->vel[1] *= vec[1];
|
|
p->vel[2] *= vec[2];
|
|
|
|
p->scalexvel = p->vel[2] * 0.08;
|
|
p->scaleyvel = 0;
|
|
//p->vel[2] = 5;
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
void R_RocketTrail (vec3_t start, vec3_t end, int type)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
if (type < 128)
|
|
dec = 3;
|
|
else if (type == 7)
|
|
dec = 1;
|
|
else if (type == 2 && particleblood)
|
|
dec = 1;
|
|
else
|
|
{
|
|
dec = 1;
|
|
type -= 128;
|
|
}
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
p->trail = 0;
|
|
p->scale = 1;
|
|
p->scaley = p->scale;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time + 2;
|
|
|
|
switch (type)
|
|
{
|
|
case 0: // rocket trail
|
|
p->ramp = (rand()&3);
|
|
p->polor = ramp3[(int)p->ramp];
|
|
p->type = pt_fire;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
break;
|
|
|
|
case 1: // smoke smoke
|
|
p->ramp = (rand()&3) + 2;
|
|
p->polor = ramp3[(int)p->ramp];
|
|
p->type = pt_fire;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
break;
|
|
|
|
case 2: // blood
|
|
if (particleblood < 0)
|
|
break;
|
|
if (particleset == 2)
|
|
p->frame = 7;
|
|
if (particleblood > 2){
|
|
p->type = pt_bloodsplat;
|
|
p->polor = 77 + (rand()&3);
|
|
|
|
p->die = cl.time + (1 *(rand()%6));
|
|
if (len < 1){
|
|
for (j=0 ; j<3 ; j++){
|
|
p->org[j] = start[j] + ((rand()&4)-2);
|
|
p->vel[j] = ((rand()%100)-50) * (len * 2);
|
|
}
|
|
|
|
p->vel[2] *= len;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
for (j=0 ; j<3 ; j++){
|
|
p->org[j] = start[j] + ((rand()*(len))-(len*0.5));
|
|
//p->vel[j] += len;
|
|
p->die = cl.time + 0.6*(rand()%5);
|
|
}
|
|
|
|
// p->vel[2] -= len * 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_grav;
|
|
p->polor = 67 + (rand()&3);
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
case 5: // tracer
|
|
p->die = cl.time + 0.5;
|
|
p->type = pt_static;
|
|
if (type == 3)
|
|
p->polor = 52 + ((tracercount&4)<<1);
|
|
else
|
|
p->polor = 230 + ((tracercount&4)<<1);
|
|
|
|
tracercount++;
|
|
|
|
VectorCopy (start, p->org);
|
|
if (tracercount & 1)
|
|
{
|
|
p->vel[0] = 30*vec[1];
|
|
p->vel[1] = 30*-vec[0];
|
|
}
|
|
else
|
|
{
|
|
p->vel[0] = 30*-vec[1];
|
|
p->vel[1] = 30*vec[0];
|
|
}
|
|
break;
|
|
|
|
case 4: // slight blood
|
|
if (particleblood < 0)
|
|
break;
|
|
else
|
|
{
|
|
if (particleset == 2)
|
|
p->frame = 7;
|
|
p->type = pt_grav;
|
|
p->polor = 67 + (rand()&3);
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
len -= 3;
|
|
}
|
|
break;
|
|
|
|
case 6: // voor trail
|
|
p->polor = 9*16 + 8 + (rand()&3);
|
|
p->type = pt_static;
|
|
p->die = cl.time + 0.3;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()&15)-8);
|
|
break;
|
|
case 7: // rail trail smoke
|
|
p->ramp = (rand()&3) + 2;
|
|
p->polor = ramp3[(int)p->ramp];
|
|
p->alpha = 1;
|
|
p->alphavel = -3.7 - rand()%1;
|
|
p->type = pt_staticfade;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
break;
|
|
}
|
|
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
|
|
// leilei - sprite versions!
|
|
void R_RocketTrailSprites (vec3_t start, vec3_t end, int type)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
if (type < 128)
|
|
dec = 32;
|
|
else if (type == 7)
|
|
dec = 6;
|
|
else if (type == 2 && particleblood)
|
|
dec = 7;
|
|
else
|
|
{
|
|
dec = 1;
|
|
type -= 128;
|
|
}
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time + 2;
|
|
p->sprtype = 4;
|
|
p->blend = 0;
|
|
p->scalexvel = 0;
|
|
p->trail = 0; // damnit
|
|
p->scaleyvel = 0;
|
|
p->alphavel = 0;
|
|
p->scale = 0.2f;
|
|
p->scaley = p->scale;
|
|
p->anglevel[0] = 0;
|
|
p->anglevel[1] = 0;
|
|
p->anglevel[2] = 0;
|
|
p->alpha = 1.0f;
|
|
|
|
|
|
switch (type)
|
|
{
|
|
case 0: // rocket trail
|
|
// p->ramp = (rand()&3);
|
|
// p->polor = ramp3[(int)p->ramp];
|
|
p->type = pt_smoke;
|
|
p->frame = 1;
|
|
p->angles[2] = rand()&450;
|
|
p->scale = 0.03f;
|
|
p->blend = 1;
|
|
p->alphavel = -0.37f;
|
|
p->scalexvel = 0.7;
|
|
p->anglevel[2] = rand()&666 - 333;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
break;
|
|
|
|
case 1: // smoke smoke
|
|
// p->ramp = (rand()&3);
|
|
// p->polor = ramp3[(int)p->ramp];
|
|
p->type = pt_smoke;
|
|
p->frame = 1;
|
|
p->angles[2] = rand()&450;
|
|
p->alphavel = -0.37f;
|
|
p->blend = 1;
|
|
p->scale = 0.03f;
|
|
p->scalexvel = 0.5;
|
|
p->anglevel[2] = rand()&666 - 333;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
break;
|
|
|
|
case 2: // blood
|
|
if (particleblood < 0)
|
|
break;
|
|
if (particleblood > 2){
|
|
p->type = pt_bloodsplat;
|
|
if (particleset == 2)
|
|
p->frame = 7;
|
|
p->polor = 77 + (rand()&3);
|
|
p->blend = 0;
|
|
p->die = cl.time + (1 *(rand()%6));
|
|
if (len < 1){
|
|
for (j=0 ; j<3 ; j++){
|
|
p->org[j] = start[j] + ((rand()&4)-2);
|
|
p->vel[j] = ((rand()%100)-50) * (len * 2);
|
|
}
|
|
|
|
p->vel[2] *= len;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
for (j=0 ; j<3 ; j++){
|
|
p->org[j] = start[j] + ((rand()*(len))-(len*0.5));
|
|
//p->vel[j] += len;
|
|
p->die = cl.time + 0.6*(rand()%5);
|
|
}
|
|
|
|
// p->vel[2] -= len * 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
p->type = pt_grav;
|
|
p->polor = 67 + (rand()&3);
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
case 5: // tracer
|
|
p->die = cl.time + 0.5;
|
|
p->type = pt_static;
|
|
if (type == 3)
|
|
p->polor = 52 + ((tracercount&4)<<1);
|
|
else
|
|
p->polor = 230 + ((tracercount&4)<<1);
|
|
|
|
tracercount++;
|
|
|
|
VectorCopy (start, p->org);
|
|
if (tracercount & 1)
|
|
{
|
|
p->vel[0] = 30*vec[1];
|
|
p->vel[1] = 30*-vec[0];
|
|
}
|
|
else
|
|
{
|
|
p->vel[0] = 30*-vec[1];
|
|
p->vel[1] = 30*vec[0];
|
|
}
|
|
break;
|
|
|
|
case 4: // slight blood
|
|
if (particleblood < 0)
|
|
break;
|
|
else
|
|
{
|
|
if (particleset == 2)
|
|
p->frame = 7;
|
|
p->blend = 0;
|
|
p->type = pt_grav;
|
|
p->polor = 67 + (rand()&3);
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
len -= 3;
|
|
}
|
|
break;
|
|
|
|
case 6: // voor trail
|
|
p->polor = 9*16 + 8 + (rand()&3);
|
|
p->type = pt_static;
|
|
p->die = cl.time + 0.3;
|
|
if (particleset == 2){
|
|
p->frame = 1;
|
|
p->scalexvel = 2;
|
|
p->alphavel = -0.4;
|
|
p->anglevel[2] = rand()&600-300;
|
|
p->angles[2] = rand()&360;
|
|
p->blend = 8;
|
|
}
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()&15)-8);
|
|
break;
|
|
case 7: // rail trail smoke
|
|
p->ramp = (rand()&3) + 2;
|
|
p->polor = ramp3[(int)p->ramp];
|
|
p->alpha = 1;
|
|
p->alphavel = -3.7 - rand()%1;
|
|
p->type = pt_staticfade;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%6)-3);
|
|
break;
|
|
}
|
|
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
// LEI - particle trails 2
|
|
|
|
void R_ParticleTrail2 (vec3_t start, vec3_t end, int type, int blend, int color, float alpha)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
int thetrail;
|
|
|
|
thetrail = r_particletrails->value;
|
|
if (!thetrail)
|
|
return;
|
|
if (thetrail)
|
|
{
|
|
D_DrawSparkTrans(start,end,alpha,color, blend);
|
|
return;
|
|
}
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
{
|
|
dec = 8;
|
|
type -= 128;
|
|
}
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
|
|
active_particles = p;
|
|
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time + 0.02;
|
|
p->frame = 0;
|
|
p->type = pt_static;
|
|
p->polor = color;
|
|
p->blend = blend;
|
|
p->trail = 0; // do not ecurse
|
|
p->alpha = len * 0.3;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j];
|
|
len -= 6;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
// LEI - lame particle beam
|
|
// (TODO: Quake2 polygon beam)
|
|
void R_ParticleBeam (vec3_t start, vec3_t end, int thecol)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
int wat;
|
|
//int thecol;
|
|
|
|
|
|
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
dec = 1;
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time;
|
|
|
|
// wat = rand()&2;
|
|
{
|
|
/* if (wat == 2){ // Outer Glow
|
|
p->polor = thecol;
|
|
p->type = pt_staticfadeadd;
|
|
p->die = cl.time + 2;
|
|
p->alpha = 0.6;
|
|
p->alphavel = -0.7;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j] + ((rand()%4)-2);
|
|
}
|
|
else */
|
|
{ // Inner Line
|
|
p->polor = thecol;
|
|
p->type = pt_staticfadeadd;
|
|
p->die = cl.time + 0.01;
|
|
p->alpha = 1;
|
|
|
|
p->alphavel = -0.9;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j];
|
|
}
|
|
}
|
|
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
|
|
// uses the beam texture
|
|
void R_BeamBeam (vec3_t start, vec3_t end, int thecol, float thesize)
|
|
{
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
//int thecol;
|
|
vec3_t angel;
|
|
|
|
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
dec = 1;
|
|
|
|
vectoangles2 (vec, angel);
|
|
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time;
|
|
p->frame = 18;
|
|
p->blend = 8;
|
|
p->sprtype = 98;
|
|
p->angles[0] = angel[0] + 90;
|
|
p->angles[1] = angel[1];
|
|
p->angles[2] = angel[2];
|
|
//p->angles[0] = 0;
|
|
//p->angles[1] = 0;
|
|
//p->angles[2] = 0;
|
|
p->scale = 0.03f;
|
|
|
|
{
|
|
p->polor = thecol;
|
|
p->type = pt_staticfadeadd;
|
|
p->die = cl.time + 0.01;
|
|
p->alpha = 1;
|
|
|
|
p->alphavel = -0.9;
|
|
for (j=0 ; j<3 ; j++)
|
|
p->org[j] = start[j];
|
|
}
|
|
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
|
|
|
|
// uses the beam texture
|
|
void R_LightningBeam (vec3_t start, vec3_t end, float sized)
|
|
{
|
|
vec3_t vec;
|
|
vec3_t vec2;
|
|
float len;
|
|
float len2;
|
|
int j;
|
|
particle_t *p;
|
|
int dec;
|
|
static int tracercount;
|
|
int thecol = 214;
|
|
float dert;
|
|
float dert2;
|
|
vec3_t angel;
|
|
|
|
|
|
vec3_t divert;
|
|
|
|
VectorSubtract (end, start, vec);
|
|
VectorSubtract (start, end, vec2);
|
|
len = VectorNormalize (vec);
|
|
len2 = VectorNormalize (vec2);
|
|
if (!sized)
|
|
sized = 1;
|
|
dec = 1;
|
|
|
|
vectoangles2 (vec, angel);
|
|
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
//dert = sin(len2);
|
|
|
|
//dert2 = 1 - (len / len2);
|
|
dert = (len / len2);
|
|
dert2 = 1 - dert;
|
|
|
|
if (dert > 1)dert = 1;
|
|
if (dert2 > 1)dert2 = 1;
|
|
if (dert2 < 0)dert2 = 0;
|
|
if (dert < 0)dert = 0;
|
|
|
|
divert[0] += rand()%160 - 80;
|
|
divert[1] += rand()%160 - 80;
|
|
divert[2] += rand()%160 - 80;
|
|
|
|
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
VectorCopy (vec3_origin, p->vel);
|
|
p->die = cl.time;
|
|
p->frame = 12;
|
|
p->blend = 8;
|
|
p->sprtype = 1;
|
|
|
|
p->angles[0] = angel[0] + 90;
|
|
p->angles[1] = angel[1];
|
|
|
|
p->vel[0] = 0;
|
|
p->vel[1] = 0;
|
|
p->vel[2] = 0;
|
|
p->angles[2] = angel[2];
|
|
//p->angles[0] = 0;
|
|
//p->angles[1] = 0;
|
|
//p->angles[2] = 0;
|
|
p->scale = 0.3f * sized * dert * dert2;
|
|
p->scalexvel = -0.7f;
|
|
p->scaleyvel = -0.7f;
|
|
p->scaley = p->scale;
|
|
|
|
{
|
|
p->polor = thecol;
|
|
p->type = pt_staticfadeadd;
|
|
p->die = cl.time + 0.03;
|
|
p->alpha = 1.0f;
|
|
|
|
//p->alphavel = -0.9;
|
|
for (j=0 ; j<3 ; j++){
|
|
p->org[j] = start[j];
|
|
p->vel[j] += (divert[j] * dert2 * dert);
|
|
p->org[j] += (divert[j] * (dert2 * dert * 0.03f));
|
|
}
|
|
}
|
|
|
|
|
|
VectorAdd (start, vec, start);
|
|
}
|
|
}
|
|
/*
|
|
===============
|
|
R_RailTrail
|
|
Used by TE_RAILTRAIL
|
|
i'm a quake2 function short and stout
|
|
===============
|
|
*/
|
|
|
|
|
|
void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
|
|
{
|
|
float d;
|
|
|
|
// this rotate and negat guarantees a vector
|
|
// not colinear with the original
|
|
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 R_RailTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
float dec;
|
|
vec3_t right, up;
|
|
int i;
|
|
float d, c, s;
|
|
vec3_t dir;
|
|
byte clr = 40;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
MakeNormalVectors (vec, right, up);
|
|
|
|
for (i=0 ; i<len ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
p->die = cl.time + 2.0;
|
|
VectorClear (p->vel);
|
|
|
|
d = i * 0.1;
|
|
c = cos(d);
|
|
s = sin(d);
|
|
|
|
VectorScale (right, c, dir);
|
|
VectorMA (dir, s, up, dir);
|
|
p->type = pt_staticfadeadd;
|
|
p->alpha = 1.0;
|
|
// p->alphavel = -1.0 / (1+frand()*0.2);
|
|
p->alphavel = -1.0;
|
|
|
|
p->polor = 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);
|
|
}
|
|
|
|
dec = 0.75;
|
|
VectorScale (vec, dec, vec);
|
|
VectorCopy (start, move);
|
|
}
|
|
|
|
void R_SpiralBloodTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
particle_t *p;
|
|
float dec;
|
|
vec3_t right, up;
|
|
int i;
|
|
float d, c, s;
|
|
vec3_t dir;
|
|
byte clr = 40;
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
|
|
len = VectorNormalize (vec);
|
|
len *= 4;
|
|
MakeNormalVectors (vec, right, up);
|
|
dec = 24;
|
|
// for (i=0 ; i<len ; i++)
|
|
// {
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
if (!free_particles)
|
|
return;
|
|
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
// p->owner = NULL;
|
|
active_particles = p;
|
|
p->frame = 0;
|
|
p->die = cl.time + 2.0;
|
|
VectorClear (p->vel);
|
|
i = len * 6;
|
|
d = i * 0.1;
|
|
c = cos(d);
|
|
s = sin(d);
|
|
|
|
VectorScale (right, c, dir);
|
|
VectorMA (dir, s, up, dir);
|
|
p->type = pt_bloodsplat;
|
|
p->alpha = 1.0;
|
|
p->scale = 0.1;
|
|
p->blend = 0;
|
|
|
|
if (particleset == 2){
|
|
|
|
// p->alphavel = -1.0 / (1+frand()*0.2);
|
|
p->scalexvel = 0.8;
|
|
p->alphavel = -3.0;
|
|
p->frame = 7;
|
|
|
|
}
|
|
|
|
p->polor = 71;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = move[j] + dir[j]*1;
|
|
p->vel[j] = dir[j]* (len * 5);
|
|
}
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
|
|
// dec = 8;
|
|
VectorScale (vec, dec, vec);
|
|
VectorCopy (start, move);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
R_DrawParticles
|
|
===============
|
|
*/
|
|
extern cvar_t *sv_gravity;
|
|
extern int currentparticlepass;
|
|
extern cvar_t *r_particletrans;
|
|
extern cvar_t *r_particlesprite;
|
|
extern byte remapmap[256]; // For translating an old palette to new on load
|
|
extern int particletypeonly;
|
|
extern particle_t *currentparticle;
|
|
void R_DrawParticles (void)
|
|
{
|
|
particle_t *p, *kill;
|
|
entity_t *ent;
|
|
float grav;
|
|
int i;
|
|
int forg;
|
|
float time2, time3;
|
|
float time1;
|
|
int polor;
|
|
float dvel;
|
|
float frametime;
|
|
int where;
|
|
vec3_t whare;
|
|
int liftoff;
|
|
// hexen 2
|
|
mleaf_t *l;
|
|
mleaf_t *o;
|
|
vec3_t diff;
|
|
vec3_t below;
|
|
qboolean in_solid;
|
|
|
|
#ifdef GLQUAKE
|
|
vec3_t up, right;
|
|
float scale;
|
|
GL_Bind(particletexture);
|
|
glEnable (GL_BLEND);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
glBegin (GL_TRIANGLES);
|
|
|
|
VectorScale (vup, 8.5, up);
|
|
VectorScale (vright, 8.5, right);
|
|
|
|
#else
|
|
VectorScale (vright, xscaleshrink, r_pright);
|
|
VectorScale (vup, yscaleshrink, r_pup);
|
|
VectorCopy (vpn, r_ppn);
|
|
#endif
|
|
frametime = cl.time - cl.oldtime;
|
|
time3 = frametime * 15;
|
|
time2 = frametime * 10; // 15;
|
|
time1 = frametime * 5;
|
|
grav = frametime * sv_gravity->value * 0.05;
|
|
dvel = 4*frametime;
|
|
|
|
for ( ;; )
|
|
{
|
|
kill = active_particles;
|
|
if (kill && kill->die < cl.time)
|
|
{
|
|
|
|
active_particles = kill->next;
|
|
|
|
kill->next = free_particles;
|
|
|
|
free_particles = kill;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
for (p=active_particles ; p ; p=p->next)
|
|
{
|
|
for ( ;; )
|
|
{
|
|
kill = p->next;
|
|
if (kill && kill->die < cl.time)
|
|
{
|
|
p->next = kill->next;
|
|
kill->next = free_particles;
|
|
free_particles = kill;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
/* if (particletypeonly == 1 && p->sprtype == 5)
|
|
{
|
|
model_t *hello;
|
|
if ((p->model = Mod_ForName("particle.spr", false)))
|
|
{
|
|
currentparticle = p;
|
|
VectorCopy(p->org, r_entorigin);
|
|
VectorSubtract(r_origin, r_entorigin, modelorg);
|
|
R_DrawSprite2();
|
|
return;
|
|
}
|
|
|
|
}*/
|
|
#ifdef GLQUAKE
|
|
// hack a scale up to keep particles from disapearing
|
|
scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
|
|
+ (p->org[2] - r_origin[2])*vpn[2];
|
|
if (scale < 20)
|
|
scale = 1;
|
|
else
|
|
scale = 1 + scale * 0.004;
|
|
glColor3ubv ((byte *)&d_8to24table[(int)p->polor]);
|
|
glTexCoord2f (0,0);
|
|
glVertex3fv (p->org);
|
|
glTexCoord2f (1,0);
|
|
glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale);
|
|
glTexCoord2f (0,1);
|
|
glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale);
|
|
#else
|
|
|
|
if (p->blend == 5)
|
|
p->blend = 1;
|
|
if (p->sprtype == 5)
|
|
p->sprtype = 4;
|
|
|
|
// if (p->stickable == 2){
|
|
// VectorCopy(p->vstuck1, p->org);
|
|
//
|
|
// }
|
|
|
|
if (particleset == 1){
|
|
p->frame = 3; // glquake style particle hack
|
|
p->anglevel[2] = 0;
|
|
p->angles[2] = 0;
|
|
p->scale = 0.3f;
|
|
p->scaley = p->scale;
|
|
p->blend = 3;
|
|
p->alphavel = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->sprtype = 2;
|
|
}
|
|
|
|
// COLOR PRECALCULATE
|
|
|
|
|
|
/*
|
|
// LIT PARTICLES
|
|
if (p->lit){
|
|
int la, ra, ga, ba;
|
|
float lightvec[3];
|
|
float rlightvec[3];
|
|
float glightvec[3];
|
|
float blightvec[3];
|
|
float rlightvec2[3];
|
|
float glightvec2[3];
|
|
float blightvec2[3];
|
|
vec3_t dist;
|
|
float add;
|
|
float radd;
|
|
float gadd;
|
|
float badd;
|
|
int lnum;
|
|
dlight_t *dl;
|
|
vec3_t t;
|
|
vec3_t ar;
|
|
vec3_t ag;
|
|
vec3_t ab;
|
|
la = R_LightPoint(p->org);
|
|
|
|
|
|
|
|
// add dynamic lights
|
|
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
|
|
{
|
|
dl = &cl_dlights[lnum];
|
|
if (!dl->radius)
|
|
continue;
|
|
if (dl->die < cl.time)
|
|
continue;
|
|
if (dl->unmark) // leilei - skip world light
|
|
continue;
|
|
|
|
VectorSubtract (p->org, dl->origin, dist);
|
|
add = dl->radius - Length(dist);
|
|
radd = dl->radius * dl->color[0] - Length(dist) ;
|
|
gadd = dl->radius * dl->color[1] - Length(dist) ;
|
|
badd = dl->radius * dl->color[2] - Length(dist) ;
|
|
|
|
if (add > 0)
|
|
{
|
|
float scale = 1.0-(Length(dist)/dl->radius);
|
|
scale *= scale; // scale ^ 2
|
|
la += add*(scale);
|
|
ra += radd*(scale);
|
|
ga += gadd*(scale);
|
|
ba += badd*(scale);
|
|
|
|
|
|
}
|
|
|
|
if (radd > 0)
|
|
{
|
|
float scale = 1.0-(Length(dist)/dl->radius);
|
|
scale *= scale; // scale ^ 2
|
|
ra += radd*(scale);
|
|
VectorScale (dist, scale, dist);
|
|
|
|
|
|
}
|
|
|
|
if (gadd > 0)
|
|
{
|
|
float scale = 1.0-(Length(dist)/dl->radius);
|
|
scale *= scale; // scale ^ 2
|
|
ga += gadd*(scale);
|
|
VectorScale (dist, scale, dist);
|
|
|
|
}
|
|
|
|
if (badd > 0)
|
|
{
|
|
float scale = 1.0-(Length(dist)/dl->radius);
|
|
scale *= scale; // scale ^ 2
|
|
ba += badd*(scale);
|
|
VectorScale (dist, scale, dist);
|
|
|
|
}
|
|
}
|
|
la *= -64; la += 16300;
|
|
if (la < 0) la = 0;
|
|
polor = ((byte *)host_colormap)[p->polor + (la & 0xFF00)];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
else
|
|
*/
|
|
polor = p->polor;
|
|
|
|
|
|
// FOGGED PARTICLES
|
|
|
|
if (foguse){
|
|
|
|
vec3_t local, transformed;
|
|
float zi;
|
|
int izi;
|
|
// transform point
|
|
VectorSubtract (p->org, r_origin, local);
|
|
|
|
transformed[0] = DotProduct(local, r_pright);
|
|
transformed[1] = DotProduct(local, r_pup);
|
|
transformed[2] = DotProduct(local, r_ppn);
|
|
|
|
zi = 1.0 / transformed[2];
|
|
izi = (int)(zi * 0x8000);
|
|
forg = (float)izi * -128 + 32768;
|
|
if (forg > 32764) forg = 32764; if (forg < 0) forg = 0;
|
|
p->color = (int)host_fogmap [(int)polor + (forg >> 2 & 0xFF00)];
|
|
|
|
p->trail = 0; // don't do trails if we are fogged (covering up a visual bug that needs to be fixed)
|
|
}
|
|
else{
|
|
// PALETTE REMAPPED PARTICLES
|
|
if (rmap_ready)
|
|
polor= coltranslate[polor];
|
|
p->color = polor; //we got it.
|
|
}
|
|
|
|
|
|
|
|
if (!p->trail && !p->frame && !particletypeonly){
|
|
if (r_particletrans->value){
|
|
if (p->blend == 1) // Additive map case
|
|
D_DrawParticle_Add (p);
|
|
// else if (p->blend == 2) // Gelmap case
|
|
// D_DrawParticle_Gel (p);
|
|
else
|
|
if (p->alpha < 0.33f)
|
|
D_DrawParticle_A33 (p);
|
|
else if (p->alpha < 0.66f)
|
|
D_DrawParticle_A66 (p);
|
|
else
|
|
D_DrawParticle (p);
|
|
}
|
|
else
|
|
D_DrawParticle (p);
|
|
|
|
|
|
}
|
|
#endif// PARTICLE COLLISION CODE FROM HEXEN II! (It used to be for snow now it's for everything!)
|
|
// BEIGN
|
|
|
|
|
|
// leilei - particle sprites
|
|
if (p->frame && r_particlesprite->value && !particletypeonly)
|
|
{
|
|
model_t *hello;
|
|
if ((p->model = Mod_ForName("particle.spr", false)))
|
|
{
|
|
currentparticle = p;
|
|
VectorCopy(p->org, r_entorigin);
|
|
VectorSubtract(r_origin, r_entorigin, modelorg);
|
|
|
|
currentparticlepass = 3;
|
|
R_DrawSprite2(); // Subtractives first (i.e. decals!)
|
|
currentparticlepass = 1;
|
|
R_DrawSprite2(); // Alphas second....
|
|
currentparticlepass = 2;
|
|
R_DrawSprite2(); // Additives last
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(!r_particletrails->value)
|
|
p->trail = 0; // terminate trails
|
|
//else
|
|
|
|
if (p->die < cl.time - 0.1)
|
|
|
|
p->trail = 0; // don't trail...
|
|
// if (p->die > cl.time - 0.03)
|
|
|
|
|
|
// leilei - hook up a trail
|
|
if (p->trail && particleset != 2)
|
|
{
|
|
|
|
|
|
if (!p->org[0])
|
|
return; // apparently there isnt
|
|
VectorMA(p->org, -p->trail/(Length(p->vel)), p->vel, whare);
|
|
// Since Lines are drawn after particles, we also have to calculate fog. AGAIN!
|
|
if (foguse){
|
|
|
|
vec3_t local, transformed;
|
|
float zi;
|
|
int izi;
|
|
// transform point
|
|
VectorSubtract (whare, r_origin, local);
|
|
|
|
transformed[0] = DotProduct(local, r_pright);
|
|
transformed[1] = DotProduct(local, r_pup);
|
|
transformed[2] = DotProduct(local, r_ppn);
|
|
|
|
zi = 1.0 / transformed[2];
|
|
izi = (int)(zi * 0x8000);
|
|
forg = (float)izi * -128 + 32768;
|
|
if (forg > 32764) forg = 32764; if (forg < 0) forg = 0;
|
|
polor = (int)host_fogmap [(int)p->polor + (forg >> 2 & 0xFF00)];
|
|
|
|
|
|
}
|
|
else
|
|
polor = p->polor; //we got it.
|
|
|
|
// VectorMA(p->org, -p->trail/(Length(p->vel)), p->vel, whare);
|
|
D_DrawSparkTrans(p->org,whare,polor, p->blend);
|
|
|
|
}
|
|
|
|
|
|
if (particletypeonly)
|
|
break;
|
|
|
|
if(particletypeonly == 0){
|
|
p->org[0] += p->vel[0] * frametime;
|
|
p->org[1] += p->vel[1] * frametime;
|
|
p->org[2] += p->vel[2] * frametime;
|
|
|
|
p->alpha += frametime*p->alphavel;
|
|
p->scale += frametime*p->scalexvel;
|
|
p->scaley += frametime*p->scaleyvel;
|
|
p->angles[0] += frametime*p->anglevel[0];
|
|
p->angles[1] += frametime*p->anglevel[1];
|
|
p->angles[2] += frametime*p->anglevel[2];
|
|
|
|
if (p->alpha < 0.06 && p->alphavel && !(p->type==pt_flare))
|
|
p->die = -1;
|
|
else if (p->alpha < 0.06 && p->alphavel && (p->type==pt_flare))
|
|
p->alpha = 0.06;
|
|
if (p->alpha > 1.1)
|
|
p->alpha = 1.1;
|
|
|
|
}
|
|
if (p->stickable != 2)
|
|
p->stickable = 0; // don't stick........
|
|
switch (p->type)
|
|
{
|
|
case pt_static:
|
|
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_bloodsplatten: // leilei - blood hitting the world. We check for where in the world and how to treat it right.
|
|
p->alpha = 1;p->blend = 0;p->lit = 1;
|
|
if (!p->stickable)
|
|
p->stickable = 1;
|
|
//p->trail = 0;
|
|
// check floor
|
|
p->scalexvel = 0.0f;
|
|
p->scaleyvel = 0.0f;
|
|
if (p->scale > 3)
|
|
p->die = -1; // leilei - too much blood...
|
|
// does this actually work???
|
|
{
|
|
trace_t trace;
|
|
vec3_t nah;
|
|
vec3_t there;
|
|
VectorAdd(p->org, p->vel, there);
|
|
VectorAdd(p->org, p->vel, there);
|
|
VectorAdd(p->org, p->vel, there);
|
|
VectorAdd(p->org, p->vel, there);
|
|
VectorAdd(p->org, p->vel, there);
|
|
|
|
|
|
}
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] - 6;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 5;
|
|
else
|
|
where = 6;
|
|
|
|
// check sky (relaly quick)
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 12;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents == CONTENTS_SKY){
|
|
where = 54;
|
|
p->die = -1; // die particle! hahaha
|
|
}
|
|
|
|
// check ceil (relaly quick)
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 2;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 1;
|
|
|
|
|
|
|
|
// check walls...
|
|
whare[0] = p->org[0] + 4; whare[1] = p->org[1];
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0] - 4; whare[1] = p->org[1];
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1] + 4;
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1] - 4;
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 32;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (where == 7 && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) {
|
|
where = 2; // nothing over us (assumed on a wall now)
|
|
}
|
|
|
|
// Check the floor again
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] - 6;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 7) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 5;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 24;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) {
|
|
where = 1; // nothing under us...
|
|
// p->polor = 15;
|
|
|
|
}
|
|
|
|
// Case processing
|
|
|
|
if (where == 7) { // A Wall (Run down the wall)
|
|
p->type = pt_bloodrun;
|
|
p->scalexvel = -0.3f;
|
|
p->scaleyvel = 0.5f;
|
|
|
|
if (particleset == 2){
|
|
R_Decal (p->org, 6+rand()%3, 6, 0.8f, 1); // splatify.
|
|
p->die = -1;
|
|
}
|
|
else
|
|
{
|
|
p->trail = 3; // the linesy line method i teased before.
|
|
}
|
|
p->die += 5;
|
|
p->alphavel = -r_particlebloodfade->value;
|
|
|
|
// decal instead?
|
|
if (particleset == 2){
|
|
// if (rand()%8 > 7)
|
|
if (p->vel[2] > 0) // if it's going up, stick up
|
|
R_Decal (p->org, 6+rand()%3, 6, 0.8f, 0);
|
|
}
|
|
}
|
|
|
|
else if (where == 1){ // A Ceiling
|
|
// p->polor = 15;
|
|
//p->type = pt_blooddrip;
|
|
p->sprtype = 1;
|
|
p->angles[0] = 0;
|
|
p->angles[1] = 0;
|
|
p->angles[2] = 0;
|
|
p->scalexvel = -0.2f;
|
|
p->scaleyvel = 0.6f; // gravity pulls it downer...
|
|
p->sprtype = 3;
|
|
p->frame = 5;
|
|
if(p->die < cl.time + 1 || p->scale < 0.4){
|
|
p->type = pt_blooddrip;
|
|
p->trail = 10;
|
|
p->die += 5; // it's time to drip!
|
|
p->scaley = 5;
|
|
p->sprtype = 3;
|
|
// decal instead?
|
|
if (particleset == 2){
|
|
R_Decal (p->org, 6+rand()%3, 6, 1.2f, 0);
|
|
p->frame = 5;
|
|
p->trail = 0;
|
|
p->alpha = 0;
|
|
|
|
}
|
|
}
|
|
}
|
|
else if (where == 5){ // Floor
|
|
p->type = pt_bloodfloor;
|
|
p->trail = 0;
|
|
p->alphavel = -r_particlebloodfade->value;
|
|
p->scalexvel = 0.0f;
|
|
p->scaleyvel = 0.0f;
|
|
// decal instead?
|
|
if (particleset == 2){
|
|
p->die = -1;
|
|
if (rand()%8 > 4)
|
|
R_Decal (p->org, 6+rand()%3, 6, 0.7f, 0);//
|
|
|
|
}
|
|
}
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_blooddrip: // leilei - Blood dripping from the ceiling.
|
|
p->alpha = 1;p->blend = 0;p->lit = 1;p->trail = 5; //p->flat = 1;
|
|
if (!p->stickable)
|
|
p->stickable = 1;
|
|
p->sprtype = 1;
|
|
p->angles[0] = 0;
|
|
p->angles[1] = 0;
|
|
p->angles[2] = 0;
|
|
if (p->scale > 1){
|
|
p->scaley = p->scale; // leilei - too much blood.
|
|
p->scale = 1;
|
|
}
|
|
// p->scalexvel = -0.1f;
|
|
if (p->scale < 0.2)
|
|
p->scale = 0.2;
|
|
p->scaleyvel = 1; //.. leilei - drip vertically fast
|
|
if (p->scaley > 4)
|
|
p->scaley = 4;
|
|
if (!p->vel[2])
|
|
p->vel[2] = -70; // give an initial gravity pull as the drop gets off the ceiling.
|
|
|
|
p->vel[2] -= grav * 17;
|
|
|
|
|
|
|
|
// check floor
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] - 6;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 5;
|
|
else
|
|
where = 6;
|
|
|
|
// check sky (relaly quick)
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 12;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents == CONTENTS_SKY){
|
|
where = 54;
|
|
p->die = -1; // die particle! hahaha
|
|
}
|
|
|
|
|
|
// Case processing
|
|
|
|
if (where == 5){ // Floor
|
|
R_ParticleBloodSplash(p->org, p->vel[2], p->polor); // splat!
|
|
p->type = pt_bloodfloor;
|
|
if (particleset == 2){
|
|
R_Decal (p->org, 6+rand()%3, 6, 0.8f, 0); // splatify.
|
|
p->die = -1;
|
|
}
|
|
//p->die = -1; // terminate the drop
|
|
}
|
|
|
|
|
|
break;
|
|
case pt_drip: // leilei - generic dripping
|
|
p->lit = 0;
|
|
p->sprtype = 1;
|
|
p->angles[0] = 0;
|
|
p->angles[1] = 0;
|
|
p->angles[2] = 0;
|
|
if (p->scale > 1){
|
|
p->scaley = p->scale;
|
|
p->scale = 1;
|
|
}
|
|
// p->scalexvel = -0.1f;
|
|
if (p->scale < 0.2)
|
|
p->scale = 0.2;
|
|
p->scaleyvel = 5; //.. leilei - drip vertically fast
|
|
if (p->scaley > 4)
|
|
p->scaley = 4;
|
|
if (!p->vel[2])
|
|
p->vel[2] = -70; // give an initial gravity pull as the drop gets off the ceiling.
|
|
|
|
p->vel[2] -= grav * 17;
|
|
|
|
|
|
|
|
// check floor
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] - 6;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 5;
|
|
else
|
|
where = 6;
|
|
|
|
// check sky (relaly quick)
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 12;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents == CONTENTS_SKY){
|
|
where = 54;
|
|
p->die = -1; // die particle! hahaha
|
|
}
|
|
|
|
|
|
// Case processing
|
|
|
|
if (where == 5){ // Floor
|
|
|
|
|
|
if (particleset == 2){
|
|
p->die = -1;
|
|
}
|
|
//p->die = -1; // terminate the drop
|
|
}
|
|
|
|
|
|
break;
|
|
case pt_bloodrun: // leilei - Blood running down the wall.
|
|
//p->flat = 1;
|
|
//p->alpha += frametime*p->alphavel;
|
|
// p->scalexvel = -0.03f;
|
|
//p->scaleyvel = 0.3f;
|
|
|
|
p->scalexvel = p->vel[2] * 0.02;
|
|
p->scaleyvel = p->vel[2] * -0.2;
|
|
|
|
if (p->scaley > 1.7){
|
|
p->scaley = 1.7;
|
|
p->vel[0] = 0;
|
|
p->vel[1] = 0;
|
|
p->vel[2] = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
if (p->scale > 1)
|
|
p->die = -1; // leilei - too much blood...
|
|
if (p->alpha <= 0)
|
|
p->die = -1;
|
|
// TODO: Add a trail
|
|
if (!p->vel[2])
|
|
p->vel[2] = grav * -7; //- (rand()*55);
|
|
|
|
|
|
|
|
|
|
// check floor
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] - 1;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 5;
|
|
else
|
|
where = 6;
|
|
// check walls...
|
|
whare[0] = p->org[0] + 4; whare[1] = p->org[1];
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0] - 4; whare[1] = p->org[1];
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1] + 4;
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
whare[0] = p->org[0]; whare[1] = p->org[1] - 4;
|
|
whare[2] = p->org[2];
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 7;
|
|
|
|
|
|
// Case processing
|
|
|
|
if (where == 5){ // Floor
|
|
p->trail = 0;
|
|
p->type = pt_bloodfloor; // Become a drip
|
|
}
|
|
|
|
else if (where != 7){ // Not on a wall
|
|
p->trail = 6;
|
|
p->type = pt_blooddrip; // Become a drip
|
|
p->sprtype = 3;
|
|
}
|
|
|
|
//p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_bloodfloor: // leilei - Blood is drying up on that floor.
|
|
p->blend = 0;p->lit = 0;p->trail = 0;
|
|
p->alpha += frametime*p->alphavel;
|
|
if (p->scale > 4)
|
|
p->die = -1; // leilei - too much blood...
|
|
if (p->alpha <= 0)
|
|
p->die = -1;
|
|
// check floor
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] - 6;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME))
|
|
where = 5;
|
|
else
|
|
where = 6;
|
|
|
|
// check sky (relaly quick)
|
|
whare[0] = p->org[0]; whare[1] = p->org[1];
|
|
whare[2] = p->org[2] + 12;
|
|
o = Mod_PointInLeaf (whare, cl.worldmodel);
|
|
if (o->contents == CONTENTS_SKY){
|
|
where = 54;
|
|
p->die = -1; // die particle! hahaha
|
|
}
|
|
|
|
// Case processing
|
|
|
|
if (where == 6){ // Not the Floor
|
|
p->type = pt_blooddrip; // move off incase it's a platform maybe
|
|
p->die = cl.time + 2;
|
|
}
|
|
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_fire:
|
|
p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0;
|
|
p->ramp += time1;
|
|
if (p->ramp >= 6)
|
|
p->die = -1;
|
|
else
|
|
p->polor = ramp3[(int)p->ramp];
|
|
p->vel[2] += grav;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
|
|
case pt_explode:
|
|
|
|
p->ramp += time2;
|
|
// p->splatter = 0;
|
|
if (p->ramp >=8)
|
|
p->die = -1;
|
|
else
|
|
p->polor = ramp1[(int)p->ramp];
|
|
for (i=0 ; i<3 ; i++)
|
|
p->vel[i] += p->vel[i]*dvel;
|
|
p->vel[2] -= grav;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
|
|
case pt_explode2:
|
|
p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0;
|
|
p->ramp += time3;
|
|
// p->splatter = 0;
|
|
if (p->ramp >=8)
|
|
p->die = -1;
|
|
else
|
|
p->polor = ramp2[(int)p->ramp];
|
|
for (i=0 ; i<3 ; i++)
|
|
p->vel[i] -= p->vel[i]*frametime;
|
|
p->vel[2] -= grav;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
|
|
case pt_blob:
|
|
p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0;
|
|
for (i=0 ; i<3 ; i++)
|
|
p->vel[i] += p->vel[i]*dvel;
|
|
p->vel[2] -= grav;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
|
|
case pt_blob2:
|
|
p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0;
|
|
for (i=0 ; i<2 ; i++)
|
|
p->vel[i] -= p->vel[i]*dvel;
|
|
p->vel[2] -= grav;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
|
|
case pt_grav:
|
|
|
|
p->vel[2] -= grav * 12;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
// huge blood crap
|
|
case pt_bloodsplat:
|
|
//p->blend = 0; p->lit = 0;
|
|
//p->alpha += frametime*p->alphavel;
|
|
//p->scalexvel = 0;
|
|
p->stickable = 1;
|
|
//p->anglevel[2] = 0;
|
|
if (p->scale > 2)
|
|
p->scale = 2;; // leilei - too much blood.
|
|
l = Mod_PointInLeaf (p->org, cl.worldmodel);
|
|
|
|
if (l->contents == CONTENTS_WATER || l->contents == CONTENTS_LAVA || l->contents == CONTENTS_SLIME) // in a liquid
|
|
{
|
|
p->type = pt_bloodsplat;
|
|
p->alphavel = -0.4 * (rand()&8);
|
|
p->vel[0] *= 0.96;
|
|
p->vel[1] *= 0.96;
|
|
p->vel[2] *= 0.96;
|
|
p->vel[0] += (rand()%4-2);
|
|
p->vel[1] += (rand()%4-2); // disperse, dissolve, dissipate
|
|
p->vel[2] += (rand()%4-2);
|
|
p->vel[0] *= p->alpha;
|
|
p->vel[1] *= p->alpha;
|
|
p->vel[2] *= p->alpha;
|
|
p->scalexvel = 3.1;
|
|
p->scaleyvel = 3.1;
|
|
// p->alphavel = -0.2;
|
|
p->anglevel[2] *= 0.93; // reduce angle velocity as well, stop blood from spining
|
|
p->blend = 1; // additive because we get alpha in that
|
|
}
|
|
else if (l->contents != CONTENTS_EMPTY && ( l->contents != CONTENTS_WATER || l->contents != CONTENTS_LAVA || l->contents != CONTENTS_SLIME)) // || in_solid == true
|
|
{
|
|
p->type = pt_bloodsplatten;
|
|
p->alphavel = -0.1 * (rand()&8);
|
|
p->vel[0] = 0;
|
|
p->vel[1] = 0;
|
|
p->vel[2] = 0;
|
|
p->anglevel[2] = 0;
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
// p->vel[2] -= grav * 6;
|
|
|
|
VectorScale(p->vel, frametime, diff);
|
|
VectorAdd(p->org, diff, p->org);
|
|
|
|
// WHERE THE HITTING HAPPENS
|
|
// if hit solid, go to last position,
|
|
// no velocity, fade out.
|
|
l = Mod_PointInLeaf (p->org, cl.worldmodel);
|
|
if (l->contents != CONTENTS_EMPTY && ( l->contents != CONTENTS_WATER || l->contents != CONTENTS_LAVA || l->contents != CONTENTS_SLIME)) // || in_solid == true
|
|
{
|
|
VectorScale(diff, 0.2, p->vel);
|
|
i = 6;
|
|
while (l->contents != CONTENTS_EMPTY && ( l->contents != CONTENTS_WATER || l->contents != CONTENTS_LAVA || l->contents != CONTENTS_SLIME))
|
|
{
|
|
VectorNormalize(p->vel);
|
|
p->org[0] -= p->vel[0]*3;
|
|
p->org[1] -= p->vel[1]*3;
|
|
|
|
p->org[2] -= p->vel[2]*3;
|
|
|
|
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->anglevel[2] = 0;
|
|
//p->die += 1;
|
|
i--; //no infinite loops
|
|
if (!i)
|
|
{
|
|
p->die = -1; //should never happen now!
|
|
break;
|
|
}
|
|
l = Mod_PointInLeaf (p->org, cl.worldmodel);
|
|
}
|
|
p->vel[0] = p->vel[1] = p->vel[2] = 0;
|
|
p->anglevel[2] = 0;
|
|
if (particleset == 2){
|
|
p->die = -1;
|
|
R_Decal (p->org, p->frame, 6, p->scale, rand()%2);
|
|
|
|
}
|
|
p->ramp = 0;
|
|
p->trail = 0;
|
|
p->scalexvel = 0;
|
|
p->scaleyvel = 0;
|
|
p->anglevel[2] = 0;
|
|
p->type = pt_bloodsplatten;
|
|
}
|
|
else
|
|
{
|
|
//p->alpha = 1; // leileileilei
|
|
p->trail = 0;
|
|
|
|
// p->vel[2] -= grav * 4;
|
|
p->vel[2] -= grav * 10;
|
|
}
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
|
|
// END CODE of stupid hexen 2 particle collision
|
|
break;
|
|
|
|
case pt_slowgrav:
|
|
|
|
p->vel[2] -= grav;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_fastgrav:
|
|
|
|
p->vel[2] -= grav * 15;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_spark:
|
|
|
|
p->blend = 1;p->lit = 0;
|
|
|
|
p->vel[2] -= grav * 12;
|
|
// VectorMA(p->org, -8/(Length(p->vel)), p->vel, whare);
|
|
// R_ParticleTrail2(p->org,whare,0,p->blend,p->polor);
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_sparkvel:
|
|
|
|
p->vel[2] -= grav * 12;
|
|
p->vel[0] *= 0.9;
|
|
p->vel[1] *= 0.9;
|
|
p->vel[2] *= 0.9;
|
|
{
|
|
vec3_t vec, forward, angle_dir;
|
|
float lengthe;
|
|
|
|
// lengthe = Length(p->vel) * 0.0006;
|
|
//VectorCopy(vec, forward);
|
|
vectoangles2 (p->vel, angle_dir);
|
|
p->angles[0] = angle_dir[0];
|
|
p->angles[1] = angle_dir[2];
|
|
p->angles[2] = angle_dir[1] - 90;
|
|
// p->angles[2] *= 3;
|
|
p->sprtype = 44;
|
|
p->scaley = lengthe; // there are some types you don't want a vertical scale for
|
|
//p->scaley = 3; // there are some types you do want a vertical scale for
|
|
}
|
|
break;
|
|
case pt_blood:
|
|
p->lit = 1;p->trail = 0;
|
|
p->stickable = 1;
|
|
p->vel[2] -= grav * 12;
|
|
//p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
// leilei - flares
|
|
case pt_flare:
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_flare_will_die: // for entities.....
|
|
|
|
|
|
p->scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
|
|
+ (p->org[2] - r_origin[2])*vpn[2];
|
|
if (p->scale < 40)
|
|
p->scale = 0.1;
|
|
else
|
|
p->scale = 0.1 + p->scale * 0.004;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_smoke:
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
p->alpha += frametime*p->alphavel;
|
|
if (sprity){
|
|
p->vel[0] *= 0.96;
|
|
p->vel[1] *= 0.96;
|
|
p->vel[2] += (grav * 0.7);
|
|
}
|
|
else
|
|
p->vel[2] += grav;
|
|
p->anglevel[2] *= 0.96;
|
|
|
|
break;
|
|
// TomazQuake
|
|
case pt_snow:
|
|
if (cl.time > p->die)
|
|
{
|
|
p->die = cl.time + (rand() & 3) * 0.1;
|
|
p->vel[0] = (rand() & 64) - 32;
|
|
p->vel[1] = (rand() & 64) - 32;
|
|
}
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
// TomazQuake
|
|
case pt_trail:
|
|
p->trail = 0;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_add:
|
|
p->trail = 0;
|
|
if(p->alpha < 0.02)
|
|
p->alpha = 1;
|
|
else
|
|
p->alpha -= 0.5;
|
|
p->alpha = 0.5;
|
|
p->blend = 2;p->lit = 0;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
|
|
break;
|
|
case pt_decel:
|
|
p->alpha = 1;p->trail = 0;
|
|
p->blend = 0;p->lit = 0;
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
p->vel[i] += p->vel[i]* -dvel;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_staticfade:
|
|
p->alpha += frametime*p->alphavel;p->trail = 0;
|
|
p->alpha -= cl.time*(0.001 +(rand() % 6 * 0.006));
|
|
p->blend = 0;p->lit = 0;
|
|
|
|
if (p->alpha <= 0)
|
|
p->die = -1;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_staticfadeadd:
|
|
p->alpha += frametime*p->alphavel;p->trail = 0;
|
|
//p->blend = 2;p->lit = 0;
|
|
p->vel[0] *= 0.8f;
|
|
p->vel[1] *= 0.8f;
|
|
p->vel[2] *= 0.8f;
|
|
if (p->alpha <= 0)
|
|
p->die = -1;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
case pt_slowgravaddfade:
|
|
p->alpha += frametime*p->alphavel;p->trail = 0;
|
|
p->blend = 2;p->lit = 0;
|
|
p->vel[2] -= grav;
|
|
|
|
if (p->alpha <= 0)
|
|
p->die = -1;
|
|
p->scaley = p->scale; // there are some types you don't want a vertical scale for
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// test visibility of flares first....
|
|
void R_TestFlares (void)
|
|
{
|
|
flare_t *p, *kill;
|
|
entity_t *ent;
|
|
float grav;
|
|
int i;
|
|
float time2, time3;
|
|
float time1;
|
|
float frametime;
|
|
int liftoff;
|
|
int amiseen;
|
|
|
|
|
|
#ifndef GLQUAKE
|
|
VectorScale (vright, xscaleshrink, r_pright);
|
|
VectorScale (vup, yscaleshrink, r_pup);
|
|
VectorCopy (vpn, r_ppn);
|
|
#else
|
|
// VectorScale (vright, xscale, r_pright);
|
|
// VectorScale (vup, yscale, r_pup);
|
|
// VectorCopy (vpn, r_ppn);
|
|
#endif
|
|
|
|
for ( ;; )
|
|
{
|
|
kill = active_flares;
|
|
if (kill && kill->die < cl.time)
|
|
{
|
|
|
|
active_flares = kill->next;
|
|
|
|
kill->next = free_flares;
|
|
|
|
free_flares = kill;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
for (p=active_flares ; p ; p=p->next)
|
|
{
|
|
for ( ;; )
|
|
{
|
|
kill = p->next;
|
|
if (kill && kill->die < cl.time)
|
|
{
|
|
p->next = kill->next;
|
|
kill->next = free_flares;
|
|
free_flares = kill;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
{
|
|
|
|
int there;
|
|
int u1, v1, z1;
|
|
int eh;
|
|
int u2, v2, z2 = 88;
|
|
vec3_t hi;
|
|
trace_t yourface;
|
|
vec3_t forward, left, up;
|
|
AngleVectors(r_refdef.viewangles, forward, left, up);
|
|
VectorCompare(yourface.endpos,r_refdef.vieworg);
|
|
|
|
p->amiseen = 0; // reset to 0. when not seen. always. Stops a PVS bug where you saw a flare
|
|
// turn your back towards it, move to next room, then turn back to see it
|
|
// fade away late
|
|
D_TestOurFlare(p); // lets do it
|
|
}
|
|
}
|
|
}
|
|
|
|
void R_DrawFlares (void)
|
|
{
|
|
flare_t *p, *kill;
|
|
entity_t *ent;
|
|
float grav;
|
|
int i;
|
|
float time2, time3;
|
|
float time1;
|
|
float frametime;
|
|
int liftoff;
|
|
int amiseen;
|
|
|
|
VectorScale (vright, xscaleshrink, r_pright);
|
|
VectorScale (vup, yscaleshrink, r_pup);
|
|
VectorCopy (vpn, r_ppn);
|
|
frametime = cl.time - cl.oldtime;
|
|
time3 = frametime * 15;
|
|
time2 = frametime * 10; // 15;
|
|
time1 = frametime * 5;
|
|
grav = frametime * sv_gravity->value * 0.05;
|
|
|
|
for ( ;; )
|
|
{
|
|
kill = active_flares;
|
|
if (kill && kill->die < cl.time)
|
|
{
|
|
|
|
active_flares = kill->next;
|
|
|
|
kill->next = free_flares;
|
|
|
|
free_flares = kill;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
for (p=active_flares ; p ; p=p->next)
|
|
{
|
|
for ( ;; )
|
|
{
|
|
kill = p->next;
|
|
if (kill && kill->die < cl.time)
|
|
{
|
|
p->next = kill->next;
|
|
kill->next = free_flares;
|
|
free_flares = kill;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
p->org[0] += p->vel[0] * frametime;
|
|
p->org[1] += p->vel[1] * frametime;
|
|
p->org[2] += p->vel[2] * frametime;
|
|
|
|
p->alpha += frametime*p->alphavel;
|
|
p->scale += frametime*p->scalexvel;
|
|
p->scaley += frametime*p->scaleyvel;
|
|
p->angles[2] += frametime*p->anglevel[2];
|
|
|
|
if (p->alpha < 0.06 && p->alphavel && !(p->type==pt_flare))
|
|
p->die = -1;
|
|
else if (p->alpha < 0.06 && p->alphavel && (p->type==pt_flare))
|
|
p->alpha = 0.06;
|
|
if (p->alpha > 1.1)
|
|
p->alpha = 1.1;
|
|
if (p->scale < 0)
|
|
p->die = -1;
|
|
if (p->scaley < 0)
|
|
p->die = -1;
|
|
|
|
int there;
|
|
int u1, v1, z1;
|
|
int eh;
|
|
int u2, v2, z2 = 88;
|
|
vec3_t hi;
|
|
trace_t yourface;
|
|
vec3_t forward, left, up;
|
|
AngleVectors(r_refdef.viewangles, forward, left, up);
|
|
VectorCompare(yourface.endpos,r_refdef.vieworg);
|
|
|
|
// Removing an entity's flare
|
|
if (p->owned && p->owner){
|
|
if (p->oldmodel != p->owner->model){
|
|
p->owner->gotaflare = 0;
|
|
p->owner->ourparticle = NULL;
|
|
p->owner = NULL;
|
|
p->die = -1; // oh.....noooooooooo
|
|
}
|
|
|
|
p->org[0] = p->owner->origin[0];
|
|
p->org[1] = p->owner->origin[1];
|
|
p->org[2] = p->owner->origin[2];
|
|
}
|
|
|
|
for(eh=0; eh<3; eh++){
|
|
forward[eh] *= 350;
|
|
left[eh] *= -380; // 380
|
|
up[eh] *= 135;
|
|
}
|
|
|
|
|
|
p->scale = (p->org[0] - r_refdef.vieworg[0])*vpn[0] + (p->org[1] - r_refdef.vieworg[1])*vpn[1]
|
|
+ (p->org[2] - r_refdef.vieworg[2])*vpn[2];
|
|
if (p->scale < 50)
|
|
p->scale = 0.12f;
|
|
else
|
|
p->scale = 0.02f + p->scale * 0.002;
|
|
p->scaley = p->scale;
|
|
p->sprtype = 5;
|
|
|
|
|
|
|
|
// new z check
|
|
if (p->amiseen)
|
|
{
|
|
int sweetch;
|
|
sweetch = R_LightPoint (p->org);
|
|
if (sweetch < 16)
|
|
p->alphavel = -1.74;
|
|
else
|
|
p->alphavel = 1.8;
|
|
}
|
|
else
|
|
{
|
|
p->alphavel = -1.74;
|
|
}
|
|
|
|
if ((p->model = Mod_ForName("particle.spr", false)))
|
|
{
|
|
currentflare = p;
|
|
VectorCopy(p->org, r_entorigin);
|
|
VectorSubtract(r_origin, r_entorigin, modelorg);
|
|
R_DrawSprite3();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Stupid function for entities with instant flares to try and fade them out like normal flares!!
|
|
void R_FlareEntityAlphaMakeCheckDoStuff (vec3_t checkhere, float fe, float fi)
|
|
{
|
|
trace_t tarce;
|
|
|
|
float time1;
|
|
float frametime;
|
|
|
|
frametime = cl.time - cl.oldtime;
|
|
|
|
time1 = frametime * 5;
|
|
|
|
if (!fe)
|
|
fe = 1.0f;
|
|
|
|
//if (currententity->flalpha < 0.06 && currententity->flalphavel)
|
|
// currententity->flalpha = 0.01;
|
|
if (fe < 0.06)
|
|
fe = 0.06;
|
|
if (fe > 1.1)
|
|
fe = 1.1;
|
|
|
|
|
|
tarce = Particle_TraceLine(checkhere, r_refdef.vieworg);
|
|
if(tarce.fraction < 1)
|
|
fi = -1.74;
|
|
else{
|
|
fi = 1.8;
|
|
}
|
|
|
|
fe += frametime*fi;
|
|
|
|
|
|
|
|
}
|