mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-14 16:40:57 +00:00
1e5348cbe0
Added new graphic for text box. Made edict_t pointer arrays static in 3ZB2, Awakening2, and Zaero DLLs due to stack size concerns.
3638 lines
No EOL
73 KiB
C
3638 lines
No EOL
73 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
This file is part of Quake 2 source code.
|
|
|
|
Quake 2 source code 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.
|
|
|
|
Quake 2 source code 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 Quake 2 source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// cl_effects.c -- particle and decal effects parsing/generation
|
|
|
|
#include "client.h"
|
|
#include "particles.h"
|
|
|
|
static vec3_t avelocities [NUMVERTEXNORMALS];
|
|
|
|
|
|
//=================================================
|
|
|
|
/*
|
|
===============
|
|
CL_LightningBeam
|
|
===============
|
|
*/
|
|
/*
|
|
void CL_LightningBeam (vec3_t start, vec3_t end, int srcEnt, int dstEnt, float size)
|
|
{
|
|
cparticle_t *list;
|
|
cparticle_t *p=NULL;
|
|
|
|
for (list=active_particles; list; list=list->next)
|
|
if ( (list->src_ent == srcEnt) && (list->dst_ent == dstEnt) )
|
|
{
|
|
p=list;
|
|
p->time = cl.time;
|
|
VectorCopy(start, p->angle);
|
|
VectorCopy(end, p->org);
|
|
|
|
if (p->link)
|
|
{
|
|
p->link->time = cl.time;
|
|
VectorCopy(start, p->link->angle);
|
|
VectorCopy(end, p->link->org);
|
|
}
|
|
else
|
|
{
|
|
p->link = CL_SetupParticle (
|
|
start[0], start[1], start[2],
|
|
end[0], end[1], end[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
150, 150, 255,
|
|
0, 0, 0,
|
|
1, -1.0,
|
|
size, 0,
|
|
particle_beam,
|
|
PART_BEAM,
|
|
NULL, false);
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (p)
|
|
return;
|
|
|
|
p = CL_SetupParticle (
|
|
start[0], start[1], start[2],
|
|
end[0], end[1], end[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
115, 115, 255,
|
|
0, 0, 0,
|
|
1, -1.0,
|
|
size, 0,
|
|
particle_lightning,
|
|
PART_LIGHTNING,
|
|
NULL, false);
|
|
|
|
p->src_ent = srcEnt;
|
|
p->dst_ent = dstEnt;
|
|
|
|
p->link = CL_SetupParticle (
|
|
start[0], start[1], start[2],
|
|
end[0], end[1], end[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
150, 150, 255,
|
|
0, 0, 0,
|
|
1, -1.0,
|
|
size, 0,
|
|
particle_beam,
|
|
PART_BEAM,
|
|
NULL, false);
|
|
}
|
|
*/
|
|
void CL_LightningBeam (vec3_t start, vec3_t end, int srcEnt, int dstEnt, float size)
|
|
{
|
|
cparticle_t *list;
|
|
cparticle_t *p=NULL;
|
|
|
|
for (list=active_particles; list; list=list->next)
|
|
if ( (list->src_ent == srcEnt) && (list->dst_ent == dstEnt) && (list->image == particle_lightning) )
|
|
{
|
|
p=list;
|
|
/*p->start =*/ p->time = cl.time;
|
|
VectorCopy(start, p->angle);
|
|
VectorCopy(end, p->org);
|
|
|
|
return;
|
|
}
|
|
|
|
p = CL_SetupParticle (
|
|
start[0], start[1], start[2],
|
|
end[0], end[1], end[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, -2,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size, 0,
|
|
particle_lightning,
|
|
PART_LIGHTNING,
|
|
0, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
p->src_ent = srcEnt;
|
|
p->dst_ent = dstEnt;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_Explosion_Decal
|
|
===============
|
|
*/
|
|
void CL_Explosion_Decal (vec3_t org, float size, int decalnum)
|
|
{
|
|
// if (r_decals->value)
|
|
if (r_decals->integer)
|
|
{
|
|
int i, j, offset=8; //size/2
|
|
cparticle_t *p;
|
|
vec3_t angle[6], ang;
|
|
trace_t trace1, trace2;
|
|
vec3_t end1, end2, normal, sorg, dorg;
|
|
vec3_t planenormals[6];
|
|
|
|
VectorSet(angle[0], -1, 0, 0);
|
|
VectorSet(angle[1], 1, 0, 0);
|
|
VectorSet(angle[2], 0, 1, 0);
|
|
VectorSet(angle[3], 0, -1, 0);
|
|
VectorSet(angle[4], 0, 0, 1);
|
|
VectorSet(angle[5], 0, 0, -1);
|
|
|
|
for (i=0; i<6; i++)
|
|
{
|
|
VectorMA(org, -offset, angle[i], sorg); // move origin 8 units back
|
|
VectorMA(sorg, size/2+offset, angle[i], end1);
|
|
trace1 = CL_Trace (sorg, end1, 0, CONTENTS_SOLID);
|
|
if (trace1.fraction < 1) // hit a surface
|
|
{ // make sure we haven't hit this plane before
|
|
VectorCopy(trace1.plane.normal, planenormals[i]);
|
|
for (j=0; j<i; j++)
|
|
if (VectorCompare(planenormals[j],planenormals[i])) continue;
|
|
// try tracing directly to hit plane
|
|
VectorNegate(trace1.plane.normal, normal);
|
|
VectorMA(sorg, size/2, normal, end2);
|
|
trace2 = CL_Trace (sorg, end2, 0, CONTENTS_SOLID);
|
|
// if seond trace hit same plane
|
|
if (trace2.fraction < 1 && VectorCompare(trace2.plane.normal, trace1.plane.normal))
|
|
VectorCopy(trace2.endpos, dorg);
|
|
else
|
|
VectorCopy(trace1.endpos, dorg);
|
|
//if (CM_PointContents(dorg,0) & MASK_WATER) // no scorch marks underwater
|
|
// continue;
|
|
VecToAngleRolled(normal, rand()%360, ang);
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
dorg[0],dorg[1],dorg[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, -1/r_decal_life->value,
|
|
GL_ZERO, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 0,
|
|
decalnum, // particle_burnmark
|
|
PART_SHADED|PART_DECAL|PART_ALPHACOLOR,
|
|
CL_DecalAlphaThink, true);
|
|
}
|
|
/*VecToAngleRolled(angle[i], rand()%360, ang);
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
org[0], org[1], org[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, -0.001,
|
|
GL_ZERO, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 0,
|
|
particle_burnmark,
|
|
PART_SHADED|PART_DECAL|PART_ALPHACOLOR,
|
|
CL_DecalAlphaThink, true);*/
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ExplosionThink
|
|
===============
|
|
*/
|
|
void CL_ExplosionThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
if (*alpha>.85)
|
|
*image = particle_rexplosion1;
|
|
else if (*alpha>.7)
|
|
*image = particle_rexplosion2;
|
|
else if (*alpha>.5)
|
|
*image = particle_rexplosion3;
|
|
else if (*alpha>.4)
|
|
*image = particle_rexplosion4;
|
|
else if (*alpha>.25)
|
|
*image = particle_rexplosion5;
|
|
else if (*alpha>.1)
|
|
*image = particle_rexplosion6;
|
|
else
|
|
*image = particle_rexplosion7;
|
|
|
|
*alpha *= 3.0;
|
|
|
|
if (*alpha > 1.0)
|
|
*alpha = 1;
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ExplosionBubbleThink
|
|
===============
|
|
*/
|
|
void CL_ExplosionBubbleThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
|
|
if (CM_PointContents(org,0) & MASK_WATER)
|
|
p->thinknext = true;
|
|
else
|
|
{
|
|
p->think = NULL;
|
|
p->alpha = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_Explosion_Particle
|
|
|
|
Explosion effect
|
|
===============
|
|
*/
|
|
void CL_Explosion_Particle (vec3_t org, float size, qboolean rocket)
|
|
{
|
|
cparticle_t *p;
|
|
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0], org[1], org[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, (rocket)? -2 : -1.5,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
// GL_ONE, GL_ONE,
|
|
(size != 0) ? size : (150 - ( (!rocket) ? 75 : 0)), 0,
|
|
particle_rexplosion1,
|
|
PART_DEPTHHACK_SHORT,
|
|
CL_ExplosionThink, true);
|
|
|
|
if (p)
|
|
{ // smooth color blend :D
|
|
/* CL_AddParticleLight (p, 225, 0, 1, 0, 0);
|
|
CL_AddParticleLight (p, 250, 0, 1, 0.3, 0);
|
|
CL_AddParticleLight (p, 275, 0, 1, 0.6, 0);
|
|
CL_AddParticleLight (p, 300, 0, 1, 1, 0);*/
|
|
// use just one, 4 lights kills the framerate
|
|
CL_AddParticleLight (p, 300, 0, 1, 0.514, 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_Explosion_FlashParticle
|
|
|
|
Explosion fash
|
|
===============
|
|
*/
|
|
void CL_Explosion_FlashParticle (vec3_t org, float size, qboolean large)
|
|
{
|
|
if (large)
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0], org[1], org[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 175, 100,
|
|
0, 0, 0,
|
|
1, -1.75,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
//GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
(size!=0)?size:50, -10,
|
|
//100-(!rocket)?50:0, -10,
|
|
particle_rflash,
|
|
PART_DEPTHHACK_SHORT,
|
|
NULL, false);
|
|
}
|
|
else
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0], org[1], org[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 175, 100,
|
|
0, 0, 0,
|
|
1, -1.75,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
(size!=0)?size:50, -10,
|
|
//100-(!rocket)?50:0, -10,
|
|
particle_blaster,
|
|
0,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleExplosionSparksThink
|
|
===============
|
|
*/
|
|
void CL_ParticleExplosionSparksThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
int i;
|
|
|
|
//setting up angle for sparks
|
|
{
|
|
float time1, time2;
|
|
|
|
time1 = *time;
|
|
time2 = time1*time1;
|
|
|
|
for (i=0;i<2;i++)
|
|
angle[i] = 0.25*(p->vel[i]*time1 + (p->accel[i])*time2);
|
|
angle[2] = 0.25*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2);
|
|
}
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_Explosion_Sparks
|
|
===============
|
|
*/
|
|
void CL_Explosion_Sparks (vec3_t org, int size, int count)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i < (count/max(cl_particle_scale->value, 1.0f)); i++) // was 256
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] + ((rand()%size)-16), org[1] + ((rand()%size)-16), org[2] + ((rand()%size)-16),
|
|
(rand()%150)-75, (rand()%150)-75, (rand()%150)-75,
|
|
0, 0, 0,
|
|
255, 100, 25,
|
|
0, 0, 0,
|
|
1, -0.8 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size, size*-1.5f, // was 6, -9
|
|
particle_solid,
|
|
PART_GRAVITY|PART_SPARK,
|
|
CL_ParticleExplosionSparksThink, true);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
|
|
Blood effects
|
|
|
|
=====================
|
|
*/
|
|
void CL_ParticleBloodThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time);
|
|
void CL_BloodPuff (vec3_t org, vec3_t dir, int count);
|
|
|
|
#define MAXBLEEDSIZE 5
|
|
#define TIMEBLOODGROW 2.5f
|
|
#define BLOOD_DECAL_CHANCE 0.5F
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBloodDecalThink
|
|
===============
|
|
*/
|
|
void CL_ParticleBloodDecalThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{ // This REALLY slows things down
|
|
/*if (*time<TIMEBLOODGROW)
|
|
{
|
|
vec3_t dir;
|
|
|
|
*size *= sqrt(0.5 + 0.5*(*time/TIMEBLOODGROW));
|
|
|
|
AngleVectors (angle, dir, NULL, NULL);
|
|
VectorNegate(dir, dir);
|
|
CL_ClipDecal(p, *size, angle[2], org, dir);
|
|
}*/
|
|
|
|
//now calc alpha
|
|
CL_DecalAlphaThink (p, org, angle, alpha, size, image, time);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBloodDropThink
|
|
===============
|
|
*/
|
|
void CL_ParticleBloodDropThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
float length;
|
|
vec3_t len;
|
|
|
|
VectorSubtract(p->angle, org, len);
|
|
{
|
|
CL_CalcPartVelocity(p, 0.2, time, angle);
|
|
|
|
length = VectorNormalize(angle);
|
|
if (length>MAXBLEEDSIZE) length = MAXBLEEDSIZE;
|
|
VectorScale(angle, -length, angle);
|
|
}
|
|
|
|
//now to trace for impact...
|
|
CL_ParticleBloodThink (p, org, angle, alpha, size, image, time);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBloodPuffThink
|
|
===============
|
|
*/
|
|
void CL_ParticleBloodPuffThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
angle[2] = angle[0] + *time*angle[1] + *time**time*angle[2];
|
|
|
|
//now to trace for impact...
|
|
CL_ParticleBloodThink (p, org, angle, alpha, size, image, time);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBloodThink
|
|
===============
|
|
*/
|
|
void CL_ParticleBloodThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
trace_t trace = CL_Trace (p->oldorg, org, 0, CONTENTS_SOLID); // was 0.1
|
|
qboolean became_decal = false;
|
|
|
|
if (trace.fraction < 1.0) // delete and stain...
|
|
{
|
|
// if (r_decals->value && (p->flags & PART_LEAVEMARK)
|
|
if (r_decals->integer && (p->flags & PART_LEAVEMARK)
|
|
&& !VectorCompare(trace.plane.normal, vec3_origin)
|
|
&& !(CM_PointContents(p->oldorg,0) & MASK_WATER)) // no blood splatters underwater...
|
|
{
|
|
vec3_t normal, dir;
|
|
int i;
|
|
qboolean greenblood = false;
|
|
qboolean timedout = false;
|
|
if (p->color[1] > 0 && p->color[2] > 0)
|
|
greenblood = true;
|
|
// time cutoff for gib trails
|
|
if (p->flags & PART_GRAVITY && !(p->flags & PART_DIRECTION))
|
|
{ // gekk gibs go flyin faster...
|
|
if ((greenblood) && (cl.time - p->time)*0.001 > 1.0F)
|
|
timedout = true;
|
|
if ((!greenblood) && (cl.time - p->time)*0.001 > 0.5F)
|
|
timedout = true;
|
|
}
|
|
|
|
if (!timedout)
|
|
{
|
|
VectorNegate(trace.plane.normal, normal);
|
|
VecToAngleRolled(normal, rand()%360, p->angle);
|
|
|
|
VectorCopy(trace.endpos, p->org);
|
|
VectorClear(p->vel);
|
|
VectorClear(p->accel);
|
|
p->image = CL_GetRandomBloodParticle();
|
|
p->blendfunc_src = GL_SRC_ALPHA; //GL_ZERO
|
|
p->blendfunc_dst = GL_ONE_MINUS_SRC_ALPHA; //GL_ONE_MINUS_SRC_COLOR
|
|
p->flags = PART_DECAL|PART_SHADED|PART_ALPHACOLOR;
|
|
p->alpha = *alpha;
|
|
p->alphavel = -1/r_decal_life->value;
|
|
if (greenblood)
|
|
p->color[1] = 210;
|
|
else
|
|
for (i=0; i<3; i++)
|
|
p->color[i] *= 0.5;
|
|
p->start = CL_NewParticleTime();
|
|
p->think = CL_ParticleBloodDecalThink;
|
|
p->thinknext = true;
|
|
p->size = MAXBLEEDSIZE*0.5*(random()*5.0+5);
|
|
//p->size = *size*(random()*5.0+5);
|
|
p->sizevel = 0;
|
|
|
|
p->decalnum = 0;
|
|
p->decal = NULL;
|
|
AngleVectors (p->angle, dir, NULL, NULL);
|
|
VectorNegate(dir, dir);
|
|
CL_ClipDecal(p, p->size, -p->angle[2], p->org, dir);
|
|
if (p->decalnum)
|
|
became_decal = true;
|
|
//else
|
|
// Com_Printf(S_COLOR_YELLOW"Blood decal not clipped!\n");
|
|
}
|
|
}
|
|
if (!became_decal)
|
|
{
|
|
*alpha = 0;
|
|
*size = 0;
|
|
p->alpha = 0;
|
|
}
|
|
}
|
|
VectorCopy(org, p->oldorg);
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BloodSmack
|
|
===============
|
|
*/
|
|
void CL_BloodSmack (vec3_t org, vec3_t dir)
|
|
{
|
|
cparticle_t *p;
|
|
|
|
p = CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
org[0], org[1], org[2],
|
|
dir[0], dir[1], dir[2],
|
|
0, 0, 0,
|
|
255, 0, 0,
|
|
0, 0, 0,
|
|
1.0, -1 / (0.5 + frand()*0.3), //was -0.75
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
10, 0,
|
|
particle_redblood,
|
|
PART_SHADED|PART_OVERBRIGHT,
|
|
CL_ParticleRotateThink, true);
|
|
|
|
CL_BloodPuff(org, dir, 1);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BloodBleed
|
|
===============
|
|
*/
|
|
void CL_BloodBleed (vec3_t org, vec3_t dir, int count)
|
|
{
|
|
cparticle_t *p;
|
|
vec3_t pos;
|
|
int i;
|
|
|
|
VectorScale(dir, 10, pos);
|
|
for (i=0; i<count; i++)
|
|
{
|
|
VectorSet(pos,
|
|
dir[0]+random()*(cl_blood->value-2)*0.01,
|
|
dir[1]+random()*(cl_blood->value-2)*0.01,
|
|
dir[2]+random()*(cl_blood->value-2)*0.01);
|
|
VectorScale(pos, 10 + (cl_blood->value-2)*0.0001*random(), pos);
|
|
|
|
p = CL_SetupParticle (
|
|
org[0], org[1], org[2],
|
|
org[0] + ((rand()&7)-4) + dir[0], org[1] + ((rand()&7)-4) + dir[1], org[2] + ((rand()&7)-4) + dir[2],
|
|
pos[0]*(random()*3+5), pos[1]*(random()*3+5), pos[2]*(random()*3+5),
|
|
0, 0, 0,
|
|
255, 0, 0,
|
|
0, 0, 0,
|
|
0.7, -0.25 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
MAXBLEEDSIZE*0.5, 0,
|
|
particle_blooddrip,
|
|
PART_SHADED|PART_DIRECTION|PART_GRAVITY|PART_OVERBRIGHT,
|
|
CL_ParticleBloodDropThink, true);
|
|
|
|
if (p && i == 0 && random() < BLOOD_DECAL_CHANCE)
|
|
p->flags |= PART_LEAVEMARK;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_BloodPuff
|
|
===============
|
|
*/
|
|
void CL_BloodPuff (vec3_t org, vec3_t dir, int count)
|
|
{
|
|
cparticle_t *p;
|
|
int i;
|
|
float d;
|
|
|
|
for (i=0; i<count; i++)
|
|
{
|
|
d = rand()&31;
|
|
p = CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
org[0] + ((rand()&7)-4) + d*dir[0], org[1] + ((rand()&7)-4) + d*dir[1], org[2] + ((rand()&7)-4) + d*dir[2],
|
|
dir[0]*(crand()*3+5), dir[1]*(crand()*3+5), dir[2]*(crand()*3+5),
|
|
0, 0, -100,
|
|
255, 0, 0,
|
|
0, 0, 0,
|
|
1.0, -1.0,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
10, 0,
|
|
particle_blood,
|
|
PART_SHADED,
|
|
CL_ParticleBloodPuffThink, true);
|
|
|
|
if (p && i == 0 && random() < BLOOD_DECAL_CHANCE)
|
|
p->flags |= PART_LEAVEMARK;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_BloodHit
|
|
===============
|
|
*/
|
|
void CL_BloodHit (vec3_t org, vec3_t dir)
|
|
{
|
|
if (cl_blood->integer < 1) // disable blood option
|
|
return;
|
|
if (cl_blood->integer == 2) // splat
|
|
CL_BloodSmack(org, dir);
|
|
else if (cl_blood->integer == 3) // bleed
|
|
CL_BloodBleed (org, dir, 6);
|
|
else if (cl_blood->integer == 4) // gore
|
|
CL_BloodBleed (org, dir, 16);
|
|
else // 1 = puff
|
|
CL_BloodPuff(org, dir, 5);
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CL_GreenBloodHit
|
|
|
|
green blood spray
|
|
==================
|
|
*/
|
|
void CL_GreenBloodHit (vec3_t org, vec3_t dir)
|
|
{
|
|
cparticle_t *p;
|
|
int i;
|
|
float d;
|
|
|
|
if (cl_blood->integer < 1) // disable blood option
|
|
return;
|
|
|
|
for (i=0;i<5;i++)
|
|
{
|
|
d = rand()&31;
|
|
p = CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
org[0] + ((rand()&7)-4) + d*dir[0], org[1] + ((rand()&7)-4) + d*dir[1], org[2] + ((rand()&7)-4) + d*dir[2],
|
|
dir[0]*(crand()*3+5), dir[1]*(crand()*3+5), dir[2]*(crand()*3+5),
|
|
0, 0, -100,
|
|
255, 180, 50,
|
|
0, 0, 0,
|
|
1, -1.0,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
10, 0,
|
|
particle_blood,
|
|
PART_SHADED|PART_OVERBRIGHT,
|
|
CL_ParticleBloodPuffThink, true);
|
|
|
|
if (p && i == 0 && random() < BLOOD_DECAL_CHANCE)
|
|
p->flags |= PART_LEAVEMARK;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleEffect
|
|
|
|
Wall impact puffs
|
|
===============
|
|
*/
|
|
void CL_ParticleEffect (vec3_t org, vec3_t dir, int color8, int count)
|
|
{
|
|
int i;
|
|
float d;
|
|
vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
d = rand()&31;
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] + ((rand()&7)-4) + d*dir[0], org[1] + ((rand()&7)-4) + d*dir[1], org[2] + ((rand()&7)-4) + d*dir[2],
|
|
crand()*20, crand()*20, crand()*20,
|
|
0, 0, 0,
|
|
color[0], color[1], color[2],
|
|
0, 0, 0,
|
|
1.0, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 0,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleEffect2
|
|
===============
|
|
*/
|
|
|
|
#define colorAdd 25
|
|
void CL_ParticleEffect2 (vec3_t org, vec3_t dir, int color8, int count)
|
|
{
|
|
int i;
|
|
float d;
|
|
vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
d = rand()&7;
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0]+((rand()&7)-4)+d*dir[0], org[1]+((rand()&7)-4)+d*dir[1], org[2]+((rand()&7)-4)+d*dir[2],
|
|
crand()*20, crand()*20, crand()*20,
|
|
0, 0, 0,
|
|
color[0] + colorAdd, color[1] + colorAdd, color[2] + colorAdd,
|
|
0, 0, 0,
|
|
1, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 0,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
// RAFAEL
|
|
/*
|
|
===============
|
|
CL_ParticleEffect3
|
|
===============
|
|
*/
|
|
|
|
void CL_ParticleEffect3 (vec3_t org, vec3_t dir, int color8, int count)
|
|
{
|
|
int i;
|
|
float d;
|
|
vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
d = rand()&7;
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0]+((rand()&7)-4)+d*dir[0], org[1]+((rand()&7)-4)+d*dir[1], org[2]+((rand()&7)-4)+d*dir[2],
|
|
crand()*20, crand()*20, crand()*20,
|
|
0, 0, 0,
|
|
color[0] + colorAdd, color[1] + colorAdd, color[2] + colorAdd,
|
|
0, 0, 0,
|
|
1, -0.25 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
2, -0.25,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleSplashThink
|
|
===============
|
|
*/
|
|
#define SplashSize 7.5
|
|
void CL_ParticleSplashThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
int i;
|
|
vec3_t len;
|
|
VectorSubtract(p->angle, org, len);
|
|
|
|
// *size *= (float)(SplashSize/VectorLength(len)) * 0.5/((4-*size));
|
|
// if (*size > SplashSize)
|
|
// *size = SplashSize;
|
|
|
|
//setting up angle for sparks
|
|
{
|
|
float time1, time2;
|
|
|
|
time1 = *time;
|
|
time2 = time1*time1;
|
|
|
|
for (i=0;i<2;i++)
|
|
angle[i] = 0.5*(p->vel[i]*time1 + (p->accel[i])*time2);
|
|
angle[2] = 0.5*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2);
|
|
}
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleEffectSplash
|
|
|
|
Water Splashing
|
|
===============
|
|
*/
|
|
void CL_ParticleEffectSplash (vec3_t org, vec3_t dir, int color8, int count)
|
|
{
|
|
int i;
|
|
float d;
|
|
vec3_t color = {color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
d = rand()&5;
|
|
CL_SetupParticle (
|
|
org[0], org[1], org[2],
|
|
org[0]+d*dir[0], org[1]+d*dir[1], org[2]+d*dir[2],
|
|
dir[0]*40 + crand()*10, dir[1]*40 + crand()*10, dir[2]*40 + crand()*10,
|
|
0, 0, 0,
|
|
color[0], color[1], color[2],
|
|
0, 0, 0,
|
|
1, -0.75 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, -7,
|
|
particle_smoke,
|
|
PART_GRAVITY|PART_DIRECTION /*|PART_TRANS|PART_SHADED*/,
|
|
CL_ParticleSplashThink, true);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleSparksThink
|
|
===============
|
|
*/
|
|
void CL_ParticleSparksThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
//vec3_t dir;
|
|
int i;
|
|
|
|
//setting up angle for sparks
|
|
{
|
|
float time1, time2;
|
|
|
|
time1 = *time;
|
|
time2 = time1*time1;
|
|
|
|
for (i=0;i<2;i++)
|
|
angle[i] = 0.25*(p->vel[i]*time1 + (p->accel[i])*time2);
|
|
angle[2] = 0.25*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2);
|
|
}
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleEffectSparks
|
|
===============
|
|
*/
|
|
void CL_ParticleEffectSparks (vec3_t org, vec3_t dir, vec3_t color, int count)
|
|
{
|
|
int i;
|
|
float d;
|
|
cparticle_t *p;
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
d = rand()&7;
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0]+((rand()&3)-2), org[1]+((rand()&3)-2), org[2]+((rand()&3)-2),
|
|
crand()*20 + dir[0]*40, crand()*20 + dir[1]*40, crand()*20 + dir[2]*40,
|
|
0, 0, 0,
|
|
color[0], color[1], color[2],
|
|
0, 0, 0,
|
|
0.75, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
4, 0, //Knightmare- increase size
|
|
particle_solid,
|
|
PART_GRAVITY|PART_SPARK,
|
|
CL_ParticleSparksThink, true);
|
|
}
|
|
if (p) // added light effect
|
|
CL_AddParticleLight (p, (count>8)?130:65, 0, color[0]/255, color[1]/255, color[2]/255);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBulletDecal
|
|
===============
|
|
*/
|
|
#define DECAL_OFFSET 0.5f
|
|
void CL_ParticleBulletDecal (vec3_t org, vec3_t dir, float size)
|
|
{
|
|
cparticle_t *p;
|
|
vec3_t ang, angle, end, origin;
|
|
trace_t tr;
|
|
|
|
if (!r_decals->integer)
|
|
return;
|
|
|
|
VectorMA(org, DECAL_OFFSET, dir, origin);
|
|
VectorMA(org, -DECAL_OFFSET, dir, end);
|
|
tr = CL_Trace (origin, end, 0, CONTENTS_SOLID);
|
|
//tr = CL_Trace (origin, end, 1, 1);
|
|
|
|
if (tr.fraction == 1)
|
|
//if (!tr.allsolid)
|
|
return;
|
|
|
|
VectorNegate(tr.plane.normal, angle);
|
|
//VectorNegate(dir, angle);
|
|
VecToAngleRolled(angle, rand()%360, ang);
|
|
VectorCopy(tr.endpos, origin);
|
|
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, -1/r_decal_life->value,
|
|
GL_ZERO, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 0,
|
|
particle_bulletmark,
|
|
PART_SHADED|PART_DECAL|PART_ALPHACOLOR, // was part_saturate
|
|
CL_DecalAlphaThink, true);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleRailDecal
|
|
===============
|
|
*/
|
|
#define RAIL_DECAL_OFFSET 2.0f
|
|
void CL_ParticleRailDecal (vec3_t org, vec3_t dir, float size, int red, int green, int blue)
|
|
{
|
|
vec3_t ang, angle, end, origin;
|
|
trace_t tr;
|
|
|
|
if (!r_decals->integer)
|
|
return;
|
|
|
|
VectorMA(org, -RAIL_DECAL_OFFSET, dir, origin);
|
|
VectorMA(org, 2*RAIL_DECAL_OFFSET, dir, end);
|
|
tr = CL_Trace (origin, end, 0, CONTENTS_SOLID);
|
|
|
|
if (tr.fraction==1)
|
|
return;
|
|
if (VectorCompare(tr.plane.normal, vec3_origin))
|
|
return;
|
|
|
|
VectorNegate(tr.plane.normal, angle);
|
|
VecToAngleRolled(angle, rand()%360, ang);
|
|
VectorCopy(tr.endpos, origin);
|
|
|
|
CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, -1/r_decal_life->value,
|
|
GL_ZERO, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 0,
|
|
particle_bulletmark,
|
|
PART_SHADED|PART_DECAL|PART_ALPHACOLOR,
|
|
CL_DecalAlphaThink, true);
|
|
|
|
CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, 0, 0,
|
|
1, -0.25,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size, 0,
|
|
particle_generic,
|
|
PART_DECAL,
|
|
NULL, false);
|
|
|
|
CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
1, -0.25,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size*0.67, 0,
|
|
particle_generic,
|
|
PART_DECAL,
|
|
NULL, false);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBlasterDecal
|
|
===============
|
|
*/
|
|
void CL_ParticleBlasterDecal (vec3_t org, vec3_t dir, float size, int red, int green, int blue)
|
|
{
|
|
cparticle_t *p;
|
|
vec3_t ang, angle, end, origin;
|
|
trace_t tr;
|
|
|
|
if (!r_decals->integer)
|
|
return;
|
|
|
|
VectorMA(org, DECAL_OFFSET, dir, origin);
|
|
VectorMA(org, -DECAL_OFFSET, dir, end);
|
|
tr = CL_Trace (origin, end, 0, CONTENTS_SOLID);
|
|
|
|
if (tr.fraction==1)
|
|
return;
|
|
if (VectorCompare(tr.plane.normal, vec3_origin))
|
|
return;
|
|
|
|
VectorNegate(tr.plane.normal, angle);
|
|
VecToAngleRolled(angle, rand()%360, ang);
|
|
VectorCopy(tr.endpos, origin);
|
|
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.7, -1/r_decal_life->value,
|
|
GL_ZERO, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 0,
|
|
particle_shadow,
|
|
PART_SHADED|PART_DECAL,
|
|
NULL, false);
|
|
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, 0, 0,
|
|
1, -0.3,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size*0.4, 0,
|
|
particle_generic,
|
|
PART_SHADED|PART_DECAL,
|
|
NULL, false);
|
|
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, 0, 0,
|
|
1, -0.6,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size*0.3, 0,
|
|
particle_generic,
|
|
PART_SHADED|PART_DECAL,
|
|
NULL, false);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticlePlasmaBeamDecal
|
|
===============
|
|
*/
|
|
void CL_ParticlePlasmaBeamDecal (vec3_t org, vec3_t dir, float size)
|
|
{
|
|
cparticle_t *p;
|
|
vec3_t ang, angle, end, origin;
|
|
trace_t tr;
|
|
|
|
if (!r_decals->integer)
|
|
return;
|
|
|
|
VectorMA(org, DECAL_OFFSET, dir, origin);
|
|
VectorMA(org, -DECAL_OFFSET, dir, end);
|
|
tr = CL_Trace (origin, end, 0, CONTENTS_SOLID);
|
|
|
|
if (tr.fraction==1)
|
|
return;
|
|
if (VectorCompare(tr.plane.normal, vec3_origin))
|
|
return;
|
|
|
|
VectorNegate(tr.plane.normal, angle);
|
|
VecToAngleRolled(angle, rand()%360, ang);
|
|
VectorCopy(tr.endpos, origin);
|
|
|
|
p = CL_SetupParticle (
|
|
ang[0], ang[1], ang[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.85, -1/r_decal_life->value,
|
|
GL_ZERO, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 0,
|
|
particle_shadow,
|
|
PART_SHADED|PART_DECAL,
|
|
NULL, false);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_TeleporterParticles
|
|
===============
|
|
*/
|
|
void CL_TeleporterParticles (entity_state_t *ent)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
ent->origin[0]-16+(rand()&31), ent->origin[1]-16+(rand()&31), ent->origin[2]-16+(rand()&31),
|
|
crand()*14, crand()*14, 80 + (rand()&7),
|
|
0, 0, 0,
|
|
230+crand()*25, 125+crand()*25, 25+crand()*25,
|
|
0, 0, 0,
|
|
1, -0.5,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
2, 0,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_LogoutEffect
|
|
===============
|
|
*/
|
|
void CL_LogoutEffect (vec3_t org, int type)
|
|
{
|
|
int i;
|
|
vec3_t color;
|
|
|
|
for (i=0 ; i<500 ; i++)
|
|
{
|
|
if (type == MZ_LOGIN)// green
|
|
{
|
|
color[0] = 20;
|
|
color[1] = 200;
|
|
color[2] = 20;
|
|
}
|
|
else if (type == MZ_LOGOUT)// red
|
|
{
|
|
color[0] = 200;
|
|
color[1] = 20;
|
|
color[2] = 20;
|
|
}
|
|
else// yellow
|
|
{
|
|
color[0] = 200;
|
|
color[1] = 200;
|
|
color[2] = 20;
|
|
}
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] - 16 + frand()*32, org[1] - 16 + frand()*32, org[2] - 24 + frand()*56,
|
|
crand()*20, crand()*20, crand()*20,
|
|
0, 0, 0,
|
|
color[0], color[1], color[2],
|
|
0, 0, 0,
|
|
1, -1.0 / (1.0 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 0,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ItemRespawnParticles
|
|
===============
|
|
*/
|
|
void CL_ItemRespawnParticles (vec3_t org)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<64 ; i++)
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] + crand()*8, org[1] + crand()*8, org[2] + crand()*8,
|
|
crand()*8, crand()*8, crand()*8,
|
|
0, 0, PARTICLE_GRAVITY*0.2,
|
|
0, 150+rand()*25, 0,
|
|
0, 0, 0,
|
|
1, -1.0 / (1.0 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 0,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BigTeleportParticles
|
|
===============
|
|
*/
|
|
void CL_BigTeleportParticles (vec3_t org)
|
|
{
|
|
int i, index;
|
|
float angle, dist;
|
|
static int colortable0[4] = {10,50,150,50};
|
|
static int colortable1[4] = {150,150,50,10};
|
|
static int colortable2[4] = {50,10,10,150};
|
|
|
|
for (i=0; i<(1024/max(cl_particle_scale->value, 1.0f)); i++) // was 4096
|
|
{
|
|
|
|
index = rand()&3;
|
|
angle = M_PI*2*(rand()&1023)/1023.0;
|
|
dist = rand()&31;
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0]+cos(angle)*dist, org[1] + sin(angle)*dist,org[2] + 8 + (rand()%90),
|
|
cos(angle)*(70+(rand()&63)),sin(angle)*(70+(rand()&63)),-100 + (rand()&31),
|
|
-cos(angle)*100, -sin(angle)*100,PARTICLE_GRAVITY*4,
|
|
colortable0[index], colortable1[index], colortable2[index],
|
|
0, 0, 0,
|
|
1, -0.1 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, 0.15 / (0.5 + frand()*0.3), // was 2, 0.05
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBlasterThink
|
|
|
|
Wall impact puffs
|
|
===============
|
|
*/
|
|
#define pBlasterMaxVelocity 100
|
|
#define pBlasterMinSize 1.0
|
|
#define pBlasterMaxSize 5.0
|
|
|
|
void CL_ParticleBlasterThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
vec_t length;
|
|
vec3_t len;
|
|
float clipsize = 1.0;
|
|
VectorSubtract(p->angle, org, len);
|
|
|
|
*size *= (float)(pBlasterMaxSize/VectorLength(len)) * 1.0/((4-*size));
|
|
*size += *time * p->sizevel;
|
|
|
|
if (*size > pBlasterMaxSize)
|
|
*size = pBlasterMaxSize;
|
|
if (*size < pBlasterMinSize)
|
|
*size = pBlasterMinSize;
|
|
|
|
CL_ParticleBounceThink (p, org, angle, alpha, &clipsize, image, time); // was size
|
|
|
|
length = VectorNormalize(p->vel);
|
|
if (length>pBlasterMaxVelocity)
|
|
VectorScale(p->vel, pBlasterMaxVelocity, p->vel);
|
|
else
|
|
VectorScale(p->vel, length, p->vel);
|
|
|
|
/* vec3_t len;
|
|
VectorSubtract(p->angle, org, len);
|
|
|
|
*size *= (float)(pBlasterMaxSize/VectorLength(len)) * 1.0/((4-*size));
|
|
if (*size > pBlasterMaxSize)
|
|
*size = pBlasterMaxSize;
|
|
|
|
p->thinknext = true;*/
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BlasterParticles
|
|
|
|
Wall impact puffs
|
|
===============
|
|
*/
|
|
void CL_BlasterParticles (vec3_t org, vec3_t dir, int count, float size,
|
|
int red, int green, int blue, int reddelta, int greendelta, int bluedelta)
|
|
{
|
|
int i;
|
|
float speed = .75;
|
|
cparticle_t *p;
|
|
vec3_t origin;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
VectorSet(origin,
|
|
org[0] + dir[0]*(1 + random()*3 + pBlasterMaxSize/2.0),
|
|
org[1] + dir[1]*(1 + random()*3 + pBlasterMaxSize/2.0),
|
|
org[2] + dir[2]*(1 + random()*3 + pBlasterMaxSize/2.0)
|
|
);
|
|
|
|
p = CL_SetupParticle (
|
|
org[0], org[1], org[2],
|
|
origin[0], origin[1], origin[2],
|
|
(dir[0]*75 + crand()*40)*speed, (dir[1]*75 + crand()*40)*speed, (dir[2]*75 + crand()*40)*speed,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
reddelta, greendelta, bluedelta,
|
|
1, -0.5 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size, size*-0.125, // was 4, -0.5
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
CL_ParticleBlasterThink, true);
|
|
|
|
/* d = rand()&5;
|
|
p = CL_SetupParticle (
|
|
org[0], org[1], org[2],
|
|
org[0]+((rand()&5)-2)+d*dir[0], org[1]+((rand()&5)-2)+d*dir[1], org[2]+((rand()&5)-2)+d*dir[2],
|
|
(dir[0]*50 + crand()*20)*speed, (dir[1]*50 + crand()*20)*speed, (dir[2]*50 + crand()*20)*speed,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
reddelta, greendelta, bluedelta,
|
|
1, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
4, -1.0,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
CL_ParticleBlasterThink, true);*/
|
|
}
|
|
if (p) // added light effect
|
|
CL_AddParticleLight (p, 150, 0, ((float)red)/255, ((float)green)/255, ((float)blue)/255);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BlasterTrail
|
|
===============
|
|
*/
|
|
void CL_BlasterTrail (vec3_t start, vec3_t end, int red, int green, int blue,
|
|
int reddelta, int greendelta, int bluedelta)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int dec;
|
|
|
|
VectorCopy (start, move);
|
|
// VectorSubtract (end, start, vec);
|
|
VectorSubtract (start, end, vec);
|
|
len = VectorNormalize (vec);
|
|
VectorMA (move, -5.0f, vec, move);
|
|
|
|
dec = 4 * cl_particle_scale->value;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand(), move[1] + crand(), move[2] + crand(),
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
reddelta, greendelta, bluedelta,
|
|
1, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
3, -7, // was 4, -6;
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_HyperBlasterGlow
|
|
|
|
Hyperblaster particle glow effect
|
|
===============
|
|
*/
|
|
#if 1
|
|
void CL_HyperBlasterGlow (vec3_t start, vec3_t end, int red, int green, int blue,
|
|
int reddelta, int greendelta, int bluedelta)
|
|
{
|
|
vec3_t move, vec;
|
|
float len, dec, size;
|
|
int i;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (start, end, vec);
|
|
len = VectorNormalize (vec);
|
|
VectorMA (move, -16.5f, vec, move);
|
|
|
|
dec = 3.0f; // was 1, 5
|
|
VectorScale (vec, dec, vec);
|
|
|
|
for (i = 0; i < 12; i++) // was 18
|
|
{
|
|
size = 4.2f - (0.1f*(float)i);
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + 0.5*crand(), move[1] + 0.5*crand(), move[2] + 0.5*crand(),
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
reddelta, greendelta, bluedelta,
|
|
1, INSTANT_PARTICLE, // was -16.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size, 0, // was 3, -36; 5, -60
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
#else
|
|
void CL_HyperBlasterTrail (vec3_t start, vec3_t end, int red, int green, int blue,
|
|
int reddelta, int greendelta, int bluedelta)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int dec;
|
|
int i;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
VectorMA (move, 0.25, vec, move); // was 0.5
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 5; // was 1
|
|
VectorScale (vec, dec, vec);
|
|
|
|
for (i = 0; i < 5; i++) // was 18
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + 0.5*crand(), move[1] + 0.5*crand(), move[2] + 0.5*crand(),
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
reddelta, greendelta, bluedelta,
|
|
1, -16.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, -60, // was 3, -36
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
===============
|
|
CL_BlasterTracer
|
|
===============
|
|
*/
|
|
void CL_BlasterTracer (vec3_t origin, vec3_t angle, int red, int green, int blue, float len, float size)
|
|
{
|
|
// int i;
|
|
vec3_t dir;
|
|
|
|
AngleVectors (angle, dir, NULL, NULL);
|
|
VectorScale (dir, len,dir);
|
|
|
|
//for (i=0; i<3; i++)
|
|
CL_SetupParticle (
|
|
dir[0], dir[1], dir[2],
|
|
origin[0], origin[1], origin[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, 0, 0,
|
|
1, INSTANT_PARTICLE,
|
|
GL_ONE, GL_ONE, // was GL_SRC_ALPHA, GL_ONE
|
|
size, 0,
|
|
particle_blasterblob, // was particle_generic
|
|
PART_DIRECTION|PART_INSTANT|PART_OVERBRIGHT,
|
|
NULL, false);
|
|
}
|
|
|
|
void CL_HyperBlasterEffect (vec3_t start, vec3_t end, vec3_t angle, int red, int green, int blue,
|
|
int reddelta, int greendelta, int bluedelta, float len, float size)
|
|
{
|
|
CL_BlasterTracer (end, angle, red, green, blue, len, size);
|
|
if (cl_particle_scale->integer < 2)
|
|
// CL_HyperBlasterTrail (start, end, red, green, blue, reddelta, greendelta, bluedelta);
|
|
CL_HyperBlasterGlow (start, end, red, green, blue, reddelta, greendelta, bluedelta);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_QuadTrail
|
|
===============
|
|
*/
|
|
void CL_QuadTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int dec;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 5;
|
|
VectorScale (vec, 5, vec);
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*16, move[1] + crand()*16, move[2] + crand()*16,
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 0,
|
|
0, 0, 200,
|
|
0, 0, 0,
|
|
1, -1.0 / (0.8+frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_FlagTrail
|
|
===============
|
|
*/
|
|
void CL_FlagTrail (vec3_t start, vec3_t end, qboolean isred, qboolean isgreen)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int dec;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 5;
|
|
VectorScale (vec, 5, vec);
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*16, move[1] + crand()*16, move[2] + crand()*16,
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 0,
|
|
(isred)?255:0, (isgreen)?255:0, (!isred && !isgreen)?255:0,
|
|
0, 0, 0,
|
|
1, -1.0 / (0.8+frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_DiminishingTrail
|
|
===============
|
|
*/
|
|
void CL_DiminishingTrail (vec3_t start, vec3_t end, centity_t *old, int flags)
|
|
{
|
|
cparticle_t *p;
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len, oldlen;
|
|
float dec;
|
|
float orgscale;
|
|
float velscale;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = oldlen = VectorNormalize (vec);
|
|
|
|
dec = (flags & EF_ROCKET) ? 10 : 2;
|
|
dec *= cl_particle_scale->value;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
if (old->trailcount > 900)
|
|
{
|
|
orgscale = 4;
|
|
velscale = 15;
|
|
}
|
|
else if (old->trailcount > 800)
|
|
{
|
|
orgscale = 2;
|
|
velscale = 10;
|
|
}
|
|
else
|
|
{
|
|
orgscale = 1;
|
|
velscale = 5;
|
|
}
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
|
|
if (flags & EF_ROCKET)
|
|
{
|
|
if (CM_PointContents(move,0) & MASK_WATER)
|
|
CL_SetupParticle (
|
|
0, 0, crand()*360,
|
|
move[0], move[1], move[2],
|
|
crand()*9, crand()*9, crand()*9+5,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.75, -0.2 / (1 + frand() * 0.2),
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
1+random()*3, 1,
|
|
particle_bubble,
|
|
PART_TRANS|PART_SHADED,
|
|
CL_ExplosionBubbleThink, true);
|
|
else
|
|
CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
move[0], move[1], move[2],
|
|
crand()*5, crand()*5, crand()*10,
|
|
0, 0, 5,
|
|
255, 255, 255,
|
|
-50, -50, -50,
|
|
0.75, -0.75, // was 1, -0.5
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
5, 15,
|
|
particle_smoke,
|
|
PART_TRANS|PART_SHADED,
|
|
CL_ParticleRotateThink, true);
|
|
}
|
|
else
|
|
{
|
|
// drop less particles as it flies
|
|
if ((rand()&1023) < old->trailcount)
|
|
{
|
|
if (flags & EF_GIB)
|
|
{
|
|
if (cl_blood->integer > 1)
|
|
p = CL_SetupParticle (
|
|
0, 0, random()*360,
|
|
move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale,
|
|
crand()*velscale, crand()*velscale, crand()*velscale,
|
|
0, 0, 0,
|
|
255, 0, 0,
|
|
0, 0, 0,
|
|
0.75, -0.75 / (1+frand()*0.4),
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
3 + random()*2, 0,
|
|
particle_blooddrop,
|
|
PART_OVERBRIGHT|PART_GRAVITY|PART_SHADED,
|
|
CL_ParticleBloodThink, true);
|
|
else
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale,
|
|
crand()*velscale, crand()*velscale, crand()*velscale,
|
|
0, 0, 0,
|
|
255, 0, 0,
|
|
0, 0, 0,
|
|
1, -1.0 / (1+frand()*0.4),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, -1,
|
|
particle_blood,
|
|
PART_GRAVITY|PART_SHADED,
|
|
CL_ParticleBloodThink, true);
|
|
if ( p && (crand() < (double)0.0001F) )
|
|
p->flags |= PART_LEAVEMARK;
|
|
}
|
|
else if (flags & EF_GREENGIB)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale,
|
|
crand()*velscale, crand()*velscale, crand()*velscale,
|
|
0, 0, 0,
|
|
255, 180, 50,
|
|
0, 0, 0,
|
|
1, -0.5 / (1+frand()*0.4),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, -1,
|
|
particle_blood,
|
|
PART_OVERBRIGHT|PART_GRAVITY|PART_SHADED,
|
|
CL_ParticleBloodThink, true);
|
|
if ( p && (crand() < (double)0.0001F) )
|
|
p->flags |= PART_LEAVEMARK;
|
|
|
|
}
|
|
else if (flags & EF_GRENADE) // no overbrights on grenade trails
|
|
{
|
|
if (CM_PointContents(move,0) & MASK_WATER)
|
|
CL_SetupParticle (
|
|
0, 0, crand()*360,
|
|
move[0], move[1], move[2],
|
|
crand()*9, crand()*9, crand()*9+5,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.75, -0.2 / (1 + frand() * 0.2),
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
1+random()*3, 1,
|
|
particle_bubble,
|
|
PART_TRANS|PART_SHADED,
|
|
CL_ExplosionBubbleThink, true);
|
|
else
|
|
CL_SetupParticle (
|
|
crand()*180, crand()*50, 0,
|
|
move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale,
|
|
crand()*velscale, crand()*velscale, crand()*velscale,
|
|
0, 0, 20,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.5, -0.5,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
5, 5,
|
|
particle_smoke,
|
|
PART_TRANS|PART_SHADED,
|
|
CL_ParticleRotateThink, true);
|
|
}
|
|
else
|
|
{
|
|
CL_SetupParticle (
|
|
crand()*180, crand()*50, 0,
|
|
move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale,
|
|
crand()*velscale, crand()*velscale, crand()*velscale,
|
|
0, 0, 20,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.5, -0.5,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
5, 5,
|
|
particle_smoke,
|
|
PART_OVERBRIGHT|PART_TRANS|PART_SHADED,
|
|
CL_ParticleRotateThink, true);
|
|
}
|
|
}
|
|
|
|
old->trailcount -= 5;
|
|
if (old->trailcount < 100)
|
|
old->trailcount = 100;
|
|
}
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_RocketTrail
|
|
===============
|
|
*/
|
|
void CL_RocketTrail (vec3_t start, vec3_t end, centity_t *old)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len, totallen;
|
|
float dec;
|
|
|
|
// smoke
|
|
CL_DiminishingTrail (start, end, old, EF_ROCKET);
|
|
|
|
// fire
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
totallen = len = VectorNormalize (vec);
|
|
|
|
dec = 1 * cl_particle_scale->value;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
|
|
// falling particles
|
|
if ( (rand()&7) == 0)
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*5, move[1] + crand()*5, move[2] + crand()*5,
|
|
crand()*20, crand()*20, crand()*20,
|
|
0, 0, 20,
|
|
255, 255, 200,
|
|
0, -50, 0,
|
|
1, -1.0 / (1+frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
2, -2,
|
|
particle_blaster,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
totallen = len = VectorNormalize (vec);
|
|
dec = 1.5 * cl_particle_scale->value;
|
|
VectorScale (vec, dec, vec);
|
|
/* len = totallen;
|
|
VectorCopy (start, move);
|
|
dec = 1.5;// * cl_particle_scale->value;
|
|
VectorScale (vec, dec, vec);*/
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
// flame
|
|
CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
move[0], move[1], move[2],
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 5,
|
|
255, 225, 200,
|
|
-50, -50, -50,
|
|
0.5, -2, // was 0.75, -3
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, 5,
|
|
particle_inferno,
|
|
0,
|
|
CL_ParticleRotateThink, true);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_RailSprial
|
|
===============
|
|
*/
|
|
#define DEVRAILSTEPS 2
|
|
//this is the length of each piece...
|
|
#define RAILTRAILSPACE 15
|
|
|
|
void CL_RailSprial (vec3_t start, vec3_t end, int red, int green, int blue)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
vec3_t right, up;
|
|
int i;
|
|
float d, c, s;
|
|
vec3_t dir;
|
|
|
|
// Draw from closest point
|
|
if (FartherPoint(start, end)) {
|
|
VectorCopy (end, move);
|
|
VectorSubtract (start, end, vec);
|
|
}
|
|
else {
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
}
|
|
len = VectorNormalize (vec);
|
|
len = min (len, cl_rail_length->value); // cap length
|
|
MakeNormalVectors (vec, right, up);
|
|
|
|
VectorScale(vec, cl_rail_space->value * cl_particle_scale->value, vec);
|
|
|
|
for (i=0; i<len; i += cl_rail_space->value * cl_particle_scale->value)
|
|
{
|
|
d = i * 0.1;
|
|
c = cos(d);
|
|
s = sin(d);
|
|
|
|
VectorScale (right, c, dir);
|
|
VectorMA (dir, s, up, dir);
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + dir[0]*3, move[1] + dir[1]*3, move[2] + dir[2]*3,
|
|
dir[0]*6, dir[1]*6, dir[2]*6,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, 0, 0,
|
|
1, -1.0,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
3, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleDevRailThink
|
|
===============
|
|
*/
|
|
void CL_ParticleDevRailThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
int i;
|
|
vec3_t len;
|
|
VectorSubtract(p->angle, org, len);
|
|
|
|
*size *= (float)(SplashSize/VectorLength(len)) * 0.5/((4-*size));
|
|
if (*size > SplashSize)
|
|
*size = SplashSize;
|
|
|
|
//setting up angle for sparks
|
|
{
|
|
float time1, time2;
|
|
|
|
time1 = *time;
|
|
time2 = time1*time1;
|
|
|
|
for (i=0;i<2;i++)
|
|
angle[i] = 3*(p->vel[i]*time1 + (p->accel[i])*time2);
|
|
angle[2] = 3*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2);
|
|
}
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_DevRailTrail
|
|
===============
|
|
*/
|
|
void CL_DevRailTrail (vec3_t start, vec3_t end, int red, int green, int blue)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec, point;
|
|
float len;
|
|
int dec, i=0;
|
|
|
|
// Draw from closest point
|
|
if (FartherPoint(start, end)) {
|
|
VectorCopy (end, move);
|
|
VectorSubtract (start, end, vec);
|
|
}
|
|
else {
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
}
|
|
len = VectorNormalize (vec);
|
|
len = min (len, cl_rail_length->value); // cap length
|
|
VectorCopy(vec, point);
|
|
|
|
dec = 4;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
i++;
|
|
|
|
if (i>=DEVRAILSTEPS)
|
|
{
|
|
for (i=3;i>0;i--)
|
|
CL_SetupParticle (
|
|
point[0], point[1], point[2],
|
|
move[0], move[1], move[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, -90, -30,
|
|
0.75, -.75,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
dec*DEVRAILSTEPS*TWOTHIRDS, 0,
|
|
particle_beam2,
|
|
PART_DIRECTION,
|
|
NULL, false);
|
|
}
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0], move[1], move[2],
|
|
crand()*10, crand()*10, crand()*10+20,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
0, 0, 0,
|
|
1, -0.75 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
2, -0.25,
|
|
particle_solid,
|
|
PART_GRAVITY|PART_SPARK,
|
|
CL_ParticleDevRailThink, true);
|
|
|
|
CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
move[0], move[1], move[2],
|
|
crand()*10, crand()*10, crand()*10+20,
|
|
0, 0, 5,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.25, -0.25,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
5, 10,
|
|
particle_smoke,
|
|
PART_TRANS|PART_GRAVITY|PART_OVERBRIGHT,
|
|
CL_ParticleRotateThink, true);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_RailTrail
|
|
===============
|
|
*/
|
|
void CL_RailTrail (vec3_t start, vec3_t end, int red, int green, int blue)
|
|
{
|
|
vec3_t move, last;
|
|
vec3_t vec, point;
|
|
// vec3_t right, up;
|
|
int i;
|
|
int beamred, beamgreen, beamblue;
|
|
float len; // dec
|
|
qboolean colored = ( (cl_railtype->integer == 1) || (cl_railtype->integer == 2) );
|
|
|
|
VectorSubtract (end, start, vec);
|
|
VectorNormalize(vec);
|
|
CL_ParticleRailDecal (end, vec, 7, red, green, blue);
|
|
|
|
if (cl_railtype->integer == 2)
|
|
{
|
|
CL_DevRailTrail (start, end, red, green, blue);
|
|
return;
|
|
}
|
|
// Draw from closest point
|
|
if (FartherPoint(start, end)) {
|
|
VectorCopy (end, move);
|
|
VectorSubtract (start, end, vec);
|
|
}
|
|
else {
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
}
|
|
len = VectorNormalize (vec);
|
|
if (cl_railtype->integer == 0)
|
|
len = min (len, cl_rail_length->value); // cap length
|
|
VectorCopy (vec, point);
|
|
VectorScale (vec, RAILTRAILSPACE, vec);
|
|
// MakeNormalVectors (vec, right, up);
|
|
|
|
if (colored) {
|
|
beamred = red;
|
|
beamgreen = green;
|
|
beamblue = blue;
|
|
}
|
|
else
|
|
beamred = beamgreen = beamblue = 255;
|
|
|
|
while (len > 0)
|
|
{
|
|
VectorCopy (move, last);
|
|
VectorAdd (move, vec, move);
|
|
|
|
len -= RAILTRAILSPACE;
|
|
|
|
for (i=0;i<3;i++)
|
|
CL_SetupParticle (
|
|
last[0], last[1], last[2],
|
|
move[0], move[1], move[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
beamred, beamgreen, beamblue,
|
|
0, 0, 0,
|
|
0.75, -0.75,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
RAILTRAILSPACE*TWOTHIRDS, (colored)?0:-5,
|
|
particle_beam2,
|
|
PART_BEAM,
|
|
NULL, false);
|
|
}
|
|
if ( !colored ) {
|
|
CL_RailSprial (start, end, red, green, blue);
|
|
}
|
|
}
|
|
|
|
|
|
// RAFAEL
|
|
/*
|
|
===============
|
|
CL_IonripperTrail
|
|
===============
|
|
*/
|
|
void CL_IonripperTrail (vec3_t start, vec3_t ent)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
vec3_t leftdir,up;
|
|
float len;
|
|
int dec;
|
|
int left = 0;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (ent, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
MakeNormalVectors (vec, leftdir, up);
|
|
|
|
dec = 3 * cl_particle_scale->value;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0], move[1], move[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
255, 75, 0,
|
|
0, 0, 0,
|
|
0.75, -1.0 / (0.3 + frand() * 0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
3, 0, // was dec
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BubbleTrail
|
|
|
|
===============
|
|
*/
|
|
void CL_BubbleTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int i;
|
|
float dec, size;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 32;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
for (i=0 ; i<len ; i+=dec)
|
|
{
|
|
size = (frand()>0.25)? 1 : (frand()>0.5) ? 2 : (frand()>0.75) ? 3 : 4;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0]+crand()*2, move[1]+crand()*2, move[2]+crand()*2,
|
|
crand()*5, crand()*5, crand()*5+6,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.75, -0.5 / (1 + frand() * 0.2),
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 1,
|
|
particle_bubble,
|
|
PART_TRANS|PART_SHADED,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_FlyParticles
|
|
===============
|
|
*/
|
|
#define BEAMLENGTH 16
|
|
|
|
|
|
void CL_FlyParticles (vec3_t origin, int count)
|
|
{
|
|
int i;
|
|
float angle;
|
|
float sr, sp, sy, cr, cp, cy;
|
|
vec3_t forward;
|
|
float dist = 64;
|
|
float ltime;
|
|
|
|
|
|
if (count > NUMVERTEXNORMALS)
|
|
count = NUMVERTEXNORMALS;
|
|
|
|
if (!avelocities[0][0])
|
|
{
|
|
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
|
|
avelocities[0][i] = (rand()&255) * 0.01;
|
|
}
|
|
|
|
|
|
ltime = (float)cl.time / 1000.0;
|
|
for (i=0 ; i<count ; i+=2)
|
|
{
|
|
angle = ltime * avelocities[i][0];
|
|
sy = sin(angle);
|
|
cy = cos(angle);
|
|
angle = ltime * avelocities[i][1];
|
|
sp = sin(angle);
|
|
cp = cos(angle);
|
|
angle = ltime * avelocities[i][2];
|
|
sr = sin(angle);
|
|
cr = cos(angle);
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
|
|
dist = sin(ltime + i)*64;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH,origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH,
|
|
origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
1, -100,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
1+sin(i+ltime), 1,
|
|
particle_generic,
|
|
PART_TRANS,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_FlyEffect
|
|
===============
|
|
*/
|
|
void CL_FlyEffect (centity_t *ent, vec3_t origin)
|
|
{
|
|
int n;
|
|
int count;
|
|
int starttime;
|
|
|
|
if (ent->fly_stoptime < cl.time)
|
|
{
|
|
starttime = cl.time;
|
|
ent->fly_stoptime = cl.time + 60000;
|
|
}
|
|
else
|
|
{
|
|
starttime = ent->fly_stoptime - 60000;
|
|
}
|
|
|
|
n = cl.time - starttime;
|
|
if (n < 20000)
|
|
count = n * 162 / 20000.0;
|
|
else
|
|
{
|
|
n = ent->fly_stoptime - cl.time;
|
|
if (n < 20000)
|
|
count = n * 162 / 20000.0;
|
|
else
|
|
count = 162;
|
|
}
|
|
|
|
CL_FlyParticles (origin, count);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleBFGThink
|
|
===============
|
|
*/
|
|
void CL_ParticleBFGThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
vec3_t len;
|
|
VectorSubtract(p->angle, p->org, len);
|
|
|
|
*size = (float)((300/VectorLength(len))*0.75);
|
|
}
|
|
|
|
#define BEAMLENGTH 16
|
|
|
|
/*
|
|
===============
|
|
CL_BfgParticles
|
|
===============
|
|
*/
|
|
void CL_BfgParticles (entity_t *ent)
|
|
{
|
|
int i;
|
|
cparticle_t *p;
|
|
float angle;
|
|
float sr, sp, sy, cr, cp, cy;
|
|
vec3_t forward;
|
|
float dist = 64, dist2;
|
|
vec3_t v;
|
|
float ltime;
|
|
|
|
if (!avelocities[0][0])
|
|
{
|
|
for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
|
|
avelocities[0][i] = (rand()&255) * 0.01;
|
|
}
|
|
|
|
|
|
ltime = (float)cl.time / 1000.0;
|
|
for (i=0 ; i<NUMVERTEXNORMALS ; i++)
|
|
{
|
|
angle = ltime * avelocities[i][0];
|
|
sy = sin(angle);
|
|
cy = cos(angle);
|
|
angle = ltime * avelocities[i][1];
|
|
sp = sin(angle);
|
|
cp = cos(angle);
|
|
angle = ltime * avelocities[i][2];
|
|
sr = sin(angle);
|
|
cr = cos(angle);
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
|
|
dist2 = dist;
|
|
dist = sin(ltime + i)*64;
|
|
|
|
p = CL_SetupParticle (
|
|
ent->origin[0], ent->origin[1], ent->origin[2],
|
|
ent->origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH,ent->origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH,
|
|
ent->origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
50, 200*dist2, 20,
|
|
0, 0, 0,
|
|
1, -100,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 1,
|
|
particle_generic,
|
|
0,
|
|
CL_ParticleBFGThink, true);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
VectorSubtract (p->org, ent->origin, v);
|
|
dist = VectorLength(v) / 90.0;
|
|
}
|
|
}
|
|
|
|
|
|
// RAFAEL
|
|
/*
|
|
===============
|
|
CL_TrapParticles
|
|
===============
|
|
*/
|
|
void CL_TrapParticles (entity_t *ent)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
vec3_t start, end;
|
|
float len;
|
|
int dec;
|
|
|
|
ent->origin[2]-=14;
|
|
VectorCopy (ent->origin, start);
|
|
VectorCopy (ent->origin, end);
|
|
end[2]+=64;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 5;
|
|
VectorScale (vec, 5, vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand(), move[1] + crand(), move[2] + crand(),
|
|
crand()*15, crand()*15, crand()*15,
|
|
0, 0, PARTICLE_GRAVITY,
|
|
230+crand()*25, 125+crand()*25, 25+crand()*25,
|
|
0, 0, 0,
|
|
1, -1.0 / (0.3+frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
3, -3,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
|
|
{
|
|
int i, j, k;
|
|
float vel;
|
|
vec3_t dir;
|
|
vec3_t org;
|
|
|
|
|
|
ent->origin[2]+=14;
|
|
VectorCopy (ent->origin, org);
|
|
|
|
|
|
for (i=-2 ; i<=2 ; i+=4)
|
|
for (j=-2 ; j<=2 ; j+=4)
|
|
for (k=-2 ; k<=4 ; k+=4)
|
|
{
|
|
|
|
dir[0] = j * 8;
|
|
dir[1] = i * 8;
|
|
dir[2] = k * 8;
|
|
|
|
VectorNormalize (dir);
|
|
vel = 50 + rand()&63;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] + i + ((rand()&23) * crand()), org[1] + j + ((rand()&23) * crand()), org[2] + k + ((rand()&23) * crand()),
|
|
dir[0]*vel, dir[1]*vel, dir[2]*vel,
|
|
0, 0, 0,
|
|
230+crand()*25, 125+crand()*25, 25+crand()*25,
|
|
0, 0, 0,
|
|
1, -1.0 / (0.3+frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 1,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BFGExplosionParticles
|
|
===============
|
|
*/
|
|
//FIXME combined with CL_ExplosionParticles
|
|
void CL_BFGExplosionParticles (vec3_t org)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] + ((rand()%32)-16), org[1] + ((rand()%32)-16), org[2] + ((rand()%32)-16),
|
|
(rand()%150)-75, (rand()%150)-75, (rand()%150)-75,
|
|
0, 0, 0,
|
|
50, 100+rand()*50, 0, //Knightmare- made more green
|
|
0, 0, 0,
|
|
1, -0.8 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
10, -10,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_TeleportParticles
|
|
===============
|
|
*/
|
|
void CL_TeleportParticles (vec3_t org)
|
|
{
|
|
int i, j, k;
|
|
float vel;
|
|
vec3_t dir;
|
|
|
|
for (i=-16 ; i<=16 ; i+=4)
|
|
for (j=-16 ; j<=16 ; j+=4)
|
|
for (k=-16 ; k<=32 ; k+=4)
|
|
{
|
|
dir[0] = j*16;
|
|
dir[1] = i*16;
|
|
dir[2] = k*16;
|
|
|
|
VectorNormalize (dir);
|
|
vel = 150 + (rand()&63);
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0]+i+(rand()&3), org[1]+j+(rand()&3), org[2]+k+(rand()&3),
|
|
dir[0]*vel, dir[1]*vel, dir[2]*vel,
|
|
0, 0, 0,
|
|
200 + 55*rand(), 200 + 55*rand(), 200 + 55*rand(),
|
|
0, 0, 0,
|
|
1, -1.0 / (0.3 + (rand()&7) * 0.02),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1, 3,
|
|
particle_generic,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_Flashlight
|
|
===============
|
|
*/
|
|
void CL_Flashlight (int ent, vec3_t pos)
|
|
{
|
|
cdlight_t *dl;
|
|
|
|
dl = CL_AllocDlight (ent);
|
|
VectorCopy (pos, dl->origin);
|
|
dl->radius = 400;
|
|
dl->minlight = 250;
|
|
dl->die = cl.time + 100;
|
|
dl->color[0] = 1;
|
|
dl->color[1] = 1;
|
|
dl->color[2] = 1;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ColorFlash - flash of light
|
|
===============
|
|
*/
|
|
void CL_ColorFlash (vec3_t pos, int ent, int intensity, float r, float g, float b)
|
|
{
|
|
cdlight_t *dl;
|
|
|
|
dl = CL_AllocDlight (ent);
|
|
VectorCopy (pos, dl->origin);
|
|
dl->radius = intensity;
|
|
dl->minlight = 250;
|
|
dl->die = cl.time + 100;
|
|
dl->color[0] = r;
|
|
dl->color[1] = g;
|
|
dl->color[2] = b;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_DebugTrail
|
|
===============
|
|
*/
|
|
void CL_DebugTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
float dec;
|
|
vec3_t right, up;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
MakeNormalVectors (vec, right, up);
|
|
|
|
dec = 8; // was 2
|
|
VectorScale (vec, dec, vec);
|
|
VectorCopy (start, move);
|
|
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0], move[1], move[2],
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
50, 50, 255,
|
|
0, 0, 0,
|
|
1, -0.75,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
7.5, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ForceWall
|
|
===============
|
|
*/
|
|
void CL_ForceWall (vec3_t start, vec3_t end, int color8)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
VectorScale (vec, 4, vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= 4;
|
|
|
|
if (frand() > 0.3)
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*3, move[1] + crand()*3, move[2] + crand()*3,
|
|
0, 0, -40 - (crand()*10),
|
|
0, 0, 0,
|
|
color[0]+5, color[1]+5, color[2]+5,
|
|
0, 0, 0,
|
|
1, -1.0 / (3.0+frand()*0.5),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
5, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_BubbleTrail2 (lets you control the # of bubbles by setting the distance between the spawns)
|
|
===============
|
|
*/
|
|
void CL_BubbleTrail2 (vec3_t start, vec3_t end, int dist)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int i;
|
|
float dec, size;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = dist;
|
|
VectorScale (vec, dec, vec);
|
|
|
|
for (i=0 ; i<len ; i+=dec)
|
|
{
|
|
size = (frand()>0.25)? 1 : (frand()>0.5) ? 2 : (frand()>0.75) ? 3 : 4;
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0]+crand()*2, move[1]+crand()*2, move[2]+crand()*2,
|
|
crand()*5, crand()*5, crand()*5+6,
|
|
0, 0, 0,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
0.75, -0.5 / (1 + frand() * 0.2),
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 1,
|
|
particle_bubble,
|
|
PART_TRANS|PART_SHADED,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_HeatbeamParticles
|
|
===============
|
|
*/
|
|
void CL_HeatbeamParticles (vec3_t start, vec3_t forward)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
vec3_t right, up;
|
|
int i;
|
|
float c, s;
|
|
vec3_t dir;
|
|
float ltime;
|
|
float step, rstep;
|
|
float start_pt;
|
|
float rot;
|
|
float variance;
|
|
float size;
|
|
int maxsteps;
|
|
vec3_t end;
|
|
|
|
VectorMA (start, 4096, forward, end);
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
// FIXME - pmm - these might end up using old values?
|
|
//MakeNormalVectors (vec, right, up);
|
|
VectorCopy (cl.v_right, right);
|
|
VectorCopy (cl.v_up, up);
|
|
|
|
if (cg_thirdperson->integer) {
|
|
ltime = (float) cl.time/250.0;
|
|
step = 96;
|
|
maxsteps = 10;
|
|
variance = 1.2;
|
|
size = 2;
|
|
}
|
|
else {
|
|
ltime = (float) cl.time/1000.0;
|
|
step = 32;
|
|
maxsteps = 7;
|
|
variance = 0.5;
|
|
size = 1;
|
|
}
|
|
|
|
// this just misaligns rings with beam
|
|
//VectorMA (move, -0.5, right, move);
|
|
//VectorMA (move, -0.5, up, move);
|
|
|
|
//ltime = (float) cl.time/1000.0;
|
|
start_pt = fmod(ltime*96.0,step);
|
|
VectorMA (move, start_pt, vec, move);
|
|
|
|
VectorScale (vec, step, vec);
|
|
|
|
//Com_Printf ("%f\n", ltime);
|
|
rstep = M_PI/10.0 * min(cl_particle_scale->value, 2);
|
|
for (i=start_pt; i<len; i+=step)
|
|
{
|
|
if (i>step*maxsteps) // don't bother after the nth ring
|
|
break;
|
|
|
|
for (rot = 0; rot < M_PI*2; rot += rstep)
|
|
{
|
|
// variance = 0.5;
|
|
c = cos(rot)*variance;
|
|
s = sin(rot)*variance;
|
|
|
|
// trim it so it looks like it's starting at the origin
|
|
if (i < 10)
|
|
{
|
|
VectorScale (right, c*(i/10.0), dir);
|
|
VectorMA (dir, s*(i/10.0), up, dir);
|
|
}
|
|
else
|
|
{
|
|
VectorScale (right, c, dir);
|
|
VectorMA (dir, s, up, dir);
|
|
}
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0]+dir[0]*2, move[1]+dir[1]*2, move[2]+dir[2]*2, //Knightmare- decreased radius
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
200+rand()*50, 200+rand()*25, rand()*50,
|
|
0, 0, 0,
|
|
0.25, -1000.0, // decreased alpha
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
size, 1, // shrunk size
|
|
particle_blaster,
|
|
0,
|
|
NULL, false);
|
|
}
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleSteamEffect
|
|
|
|
Puffs with velocity along direction, with some randomness thrown in
|
|
===============
|
|
*/
|
|
void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int red, int green, int blue,
|
|
int reddelta, int greendelta, int bluedelta, int count, int magnitude)
|
|
{
|
|
int i;
|
|
cparticle_t *p;
|
|
float d;
|
|
vec3_t r, u;
|
|
//vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
//vectoangles2 (dir, angle_dir);
|
|
//AngleVectors (angle_dir, f, r, u);
|
|
|
|
MakeNormalVectors (dir, r, u);
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0]+magnitude*0.1*crand(), org[1]+magnitude*0.1*crand(), org[2]+magnitude*0.1*crand(),
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
red, green, blue,
|
|
reddelta, greendelta, bluedelta,
|
|
0.5, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
4, -2,
|
|
particle_smoke,
|
|
0,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
VectorScale (dir, magnitude, p->vel);
|
|
d = crand()*magnitude/3;
|
|
VectorMA (p->vel, d, r, p->vel);
|
|
d = crand()*magnitude/3;
|
|
VectorMA (p->vel, d, u, p->vel);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleSteamEffect2
|
|
|
|
Puffs with velocity along direction, with some randomness thrown in
|
|
===============
|
|
*/
|
|
void CL_ParticleSteamEffect2 (cl_sustain_t *self)
|
|
//vec3_t org, vec3_t dir, int color, int count, int magnitude)
|
|
{
|
|
int i;
|
|
cparticle_t *p;
|
|
float d;
|
|
vec3_t r, u;
|
|
vec3_t dir;
|
|
int color8 = self->color + (rand()&7);
|
|
vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
//vectoangles2 (dir, angle_dir);
|
|
//AngleVectors (angle_dir, f, r, u);
|
|
|
|
VectorCopy (self->dir, dir);
|
|
MakeNormalVectors (dir, r, u);
|
|
|
|
for (i=0; i<self->count; i++)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
self->org[0] + self->magnitude*0.1*crand(), self->org[1] + self->magnitude*0.1*crand(), self->org[2] + self->magnitude*0.1*crand(),
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
color[0], color[1], color[2],
|
|
0, 0, 0,
|
|
1.0, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
4, 0,
|
|
particle_smoke,
|
|
PART_GRAVITY,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
VectorScale (dir, self->magnitude, p->vel);
|
|
d = crand()*self->magnitude/3;
|
|
VectorMA (p->vel, d, r, p->vel);
|
|
d = crand()*self->magnitude/3;
|
|
VectorMA (p->vel, d, u, p->vel);
|
|
}
|
|
self->nextthink += self->thinkinterval;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_TrackerTrail
|
|
===============
|
|
*/
|
|
void CL_TrackerTrail (vec3_t start, vec3_t end)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
vec3_t forward,right,up,angle_dir;
|
|
float len;
|
|
cparticle_t *p;
|
|
int dec;
|
|
float dist;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
VectorCopy(vec, forward);
|
|
vectoangles2 (forward, angle_dir);
|
|
AngleVectors (angle_dir, forward, right, up);
|
|
|
|
dec = 3 * max(cl_particle_scale->value/2, 1);
|
|
VectorScale (vec, 3 * max(cl_particle_scale->value/2, 1), vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= dec;
|
|
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 5,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
1.0, -2.0,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
2, 0,
|
|
particle_generic,
|
|
PART_TRANS,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
dist = DotProduct(move, forward);
|
|
VectorMA(move, 8 * cos(dist), up, p->org);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_TrackerShell
|
|
===============
|
|
*/
|
|
void CL_Tracker_Shell (vec3_t origin)
|
|
{
|
|
vec3_t dir;
|
|
int i;
|
|
cparticle_t *p;
|
|
|
|
for (i=0; i < (300/max(cl_particle_scale->value, 1.0f)); i++)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
1.0, -2.0,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
1, 0, //Knightmare- changed size
|
|
particle_generic,
|
|
PART_TRANS,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
dir[0] = crand();
|
|
dir[1] = crand();
|
|
dir[2] = crand();
|
|
VectorNormalize(dir);
|
|
VectorMA(origin, 40, dir, p->org);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
======================
|
|
CL_MonsterPlasma_Shell
|
|
======================
|
|
*/
|
|
void CL_MonsterPlasma_Shell(vec3_t origin)
|
|
{
|
|
vec3_t dir;
|
|
int i;
|
|
cparticle_t *p;
|
|
|
|
for(i=0; i<40; i++)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
220, 140, 50, //Knightmare- this was all black
|
|
0, 0, 0,
|
|
1.0, INSTANT_PARTICLE,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
2, 0,
|
|
particle_generic,
|
|
PART_TRANS|PART_INSTANT,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
dir[0] = crand();
|
|
dir[1] = crand();
|
|
dir[2] = crand();
|
|
VectorNormalize(dir);
|
|
|
|
VectorMA(origin, 10, dir, p->org);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_Widowbeamout
|
|
===============
|
|
*/
|
|
void CL_Widowbeamout (cl_sustain_t *self)
|
|
{
|
|
vec3_t dir;
|
|
int i;
|
|
static int colortable0[6] = {125, 255, 185, 125, 185, 255};
|
|
static int colortable1[6] = {185, 125, 255, 255, 125, 185};
|
|
static int colortable2[6] = {255, 185, 125, 185, 255, 125};
|
|
cparticle_t *p;
|
|
float ratio;
|
|
int index;
|
|
|
|
ratio = 1.0 - (((float)self->endtime - (float)cl.time)/2100.0);
|
|
|
|
for(i=0; i<300; i++)
|
|
{
|
|
index = rand()&5;
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
colortable0[index], colortable1[index], colortable2[index],
|
|
0, 0, 0,
|
|
1.0, INSTANT_PARTICLE,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
2, 0,
|
|
particle_generic,
|
|
PART_TRANS|PART_INSTANT,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
dir[0] = crand();
|
|
dir[1] = crand();
|
|
dir[2] = crand();
|
|
VectorNormalize(dir);
|
|
|
|
VectorMA(self->org, (45.0 * ratio), dir, p->org);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
CL_Nukeblast
|
|
============
|
|
*/
|
|
void CL_Nukeblast (cl_sustain_t *self)
|
|
{
|
|
vec3_t dir;
|
|
int i;
|
|
cparticle_t *p;
|
|
static int colortable0[4] = {185, 155, 125, 95};
|
|
static int colortable1[4] = {185, 155, 125, 95};
|
|
static int colortable2[4] = {255, 255, 255, 255};
|
|
float ratio, size;
|
|
int index;
|
|
|
|
ratio = 1.0 - (((float)self->endtime - (float)cl.time)/1000.0);
|
|
size = ratio*ratio;
|
|
|
|
for (i=0; i<(700/max(cl_particle_scale->value, 1.0f)); i++)
|
|
{
|
|
index = rand()&3;
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
colortable0[index], colortable1[index], colortable2[index],
|
|
0, 0, 0,
|
|
1-size, INSTANT_PARTICLE,
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
10*(0.5+ratio*0.5), -1,
|
|
particle_generic,
|
|
PART_INSTANT,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
|
|
dir[0] = crand();
|
|
dir[1] = crand();
|
|
dir[2] = crand();
|
|
VectorNormalize(dir);
|
|
VectorScale(dir, -1, p->angle);
|
|
VectorMA(self->org, 200.0*size, dir, p->org); //was 100
|
|
VectorMA(vec3_origin, 400.0*size, dir, p->vel); //was 100
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
CL_WidowSplash
|
|
==============
|
|
*/
|
|
void CL_WidowSplash (vec3_t org)
|
|
{
|
|
static int colortable[4] = {2*8,13*8,21*8,18*8};
|
|
int i;
|
|
cparticle_t *p;
|
|
vec3_t dir;
|
|
|
|
for (i=0; i<256; i++)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
rand()&255, rand()&255, rand()&255,
|
|
0, 0, 0,
|
|
1.0, -0.8 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
3, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
dir[0] = crand();
|
|
dir[1] = crand();
|
|
dir[2] = crand();
|
|
VectorNormalize(dir);
|
|
VectorMA(org, 45.0, dir, p->org);
|
|
VectorMA(vec3_origin, 40.0, dir, p->vel);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
CL_Tracker_Explode
|
|
==================
|
|
*/
|
|
void CL_Tracker_Explode (vec3_t origin)
|
|
{
|
|
vec3_t dir, backdir;
|
|
int i;
|
|
cparticle_t *p;
|
|
|
|
for (i=0; i<(300/max(cl_particle_scale->value, 1.0f)); i++)
|
|
{
|
|
p = CL_SetupParticle (
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, -10, //was 20
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
1.0, -0.5,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
2, 0,
|
|
particle_generic,
|
|
PART_TRANS,
|
|
NULL, false);
|
|
|
|
if (!p)
|
|
return;
|
|
|
|
dir[0] = crand();
|
|
dir[1] = crand();
|
|
dir[2] = crand();
|
|
VectorNormalize(dir);
|
|
VectorScale(dir, -1, backdir);
|
|
|
|
VectorCopy (origin, p->org); //Knightmare- start at center, not edge
|
|
// VectorMA(origin, 64, dir, p->org);
|
|
VectorScale(dir, (crand()*128), p->vel); //was backdir, 64
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_TagTrail
|
|
===============
|
|
*/
|
|
void CL_TagTrail (vec3_t start, vec3_t end, int color8)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int dec;
|
|
vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
dec = 5;
|
|
VectorScale (vec, 5, vec);
|
|
|
|
while (len >= 0)
|
|
{
|
|
len -= dec;
|
|
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
move[0] + crand()*16, move[1] + crand()*16, move[2] + crand()*16,
|
|
crand()*5, crand()*5, crand()*5,
|
|
0, 0, 20,
|
|
color[0], color[1], color[2],
|
|
0, 0, 0,
|
|
1.0, -1.0 / (0.8+frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
1.5, 0,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==========================
|
|
CL_ColorExplosionParticles
|
|
==========================
|
|
*/
|
|
void CL_ColorExplosionParticles (vec3_t org, int color8, int run)
|
|
{
|
|
int i;
|
|
vec3_t color = {color8red(color8), color8green(color8), color8blue(color8)};
|
|
|
|
for (i=0 ; i<128 ; i++)
|
|
{
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
org[0] + ((rand()%32)-16), org[1] + ((rand()%32)-16), org[2] + ((rand()%32)-16),
|
|
(rand()%256)-128, (rand()%256)-128, (rand()%256)-128,
|
|
0, 0, 20,
|
|
color[0] + (rand() % run), color[1] + (rand() % run), color[2] + (rand() % run),
|
|
0, 0, 0,
|
|
1.0, -0.4 / (0.6 + frand()*0.2),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
2, 1,
|
|
particle_generic,
|
|
0,
|
|
NULL, false);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=======================
|
|
CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity
|
|
=======================
|
|
*/
|
|
void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, float size)
|
|
{
|
|
float alpha = fabs(crand())*0.25 + 0.750;
|
|
|
|
CL_SetupParticle (
|
|
crand()*180, crand()*100, 0,
|
|
org[0], org[1], org[2],
|
|
dir[0], dir[1], dir[2],
|
|
0, 0, 10,
|
|
255, 255, 255,
|
|
0, 0, 0,
|
|
alpha, -1.0,
|
|
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
size, 5,
|
|
particle_smoke,
|
|
PART_TRANS|PART_SHADED|PART_OVERBRIGHT,
|
|
CL_ParticleRotateThink, true);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_ParticleElectricSparksThink
|
|
===============
|
|
*/
|
|
void CL_ParticleElectricSparksThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time)
|
|
{
|
|
int i;
|
|
|
|
//setting up angle for sparks
|
|
{
|
|
float time1, time2;
|
|
|
|
time1 = *time;
|
|
time2 = time1*time1;
|
|
|
|
for (i=0;i<2;i++)
|
|
angle[i] = 0.25*(p->vel[i]*time1 + (p->accel[i])*time2);
|
|
angle[2] = 0.25*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2);
|
|
}
|
|
|
|
p->thinknext = true;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_ElectricParticles
|
|
|
|
new sparks for Rogue turrets
|
|
===============
|
|
*/
|
|
void CL_ElectricParticles (vec3_t org, vec3_t dir, int count)
|
|
{
|
|
int i, j;
|
|
vec3_t start;
|
|
float d;
|
|
|
|
for (i = 0; i < 40; i++)
|
|
{
|
|
d = rand()&31;
|
|
for (j = 0; j < 3; j++)
|
|
start[j] = org[j] + ((rand()&7)-4) + d*dir[j];
|
|
CL_SetupParticle (
|
|
0, 0, 0,
|
|
start[0], start[1], start[2],
|
|
crand()*20, crand()*20, crand()*20,
|
|
0, 0, -PARTICLE_GRAVITY,
|
|
25, 100, 255,
|
|
50, 50, 50,
|
|
1, -1.0 / (0.5 + frand()*0.3),
|
|
GL_SRC_ALPHA, GL_ONE,
|
|
6, -3,
|
|
particle_solid,
|
|
PART_GRAVITY|PART_SPARK,
|
|
CL_ParticleElectricSparksThink, true);
|
|
}
|
|
}
|
|
|
|
|
|
//Knightmare- removed for Psychospaz's enhanced particle code
|
|
#if 0
|
|
/*
|
|
===============
|
|
CL_SmokeTrail
|
|
===============
|
|
*/
|
|
void CL_SmokeTrail (vec3_t start, vec3_t end, int colorStart, int colorRun, int spacing)
|
|
{
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int j;
|
|
cparticle_t *p;
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
VectorScale (vec, spacing, vec);
|
|
|
|
// FIXME: this is a really silly way to have a loop
|
|
while (len > 0)
|
|
{
|
|
len -= spacing;
|
|
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
VectorClear (p->accel);
|
|
|
|
p->time = cl.time;
|
|
|
|
p->alpha = 1.0;
|
|
p->alphavel = -1.0 / (1+frand()*0.5);
|
|
p->color = colorStart + (rand() % colorRun);
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = move[j] + crand()*3;
|
|
p->accel[j] = 0;
|
|
}
|
|
p->vel[2] = 20 + crand()*5;
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_FlameEffects
|
|
===============
|
|
*/
|
|
void CL_FlameEffects (centity_t *ent, vec3_t origin)
|
|
{
|
|
int n, count;
|
|
int j;
|
|
cparticle_t *p;
|
|
|
|
count = rand() & 0xF;
|
|
|
|
for(n=0;n<count;n++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
|
|
VectorClear (p->accel);
|
|
p->time = cl.time;
|
|
|
|
p->alpha = 1.0;
|
|
p->alphavel = -1.0 / (1+frand()*0.2);
|
|
p->color = 226 + (rand() % 4);
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = origin[j] + crand()*5;
|
|
p->vel[j] = crand()*5;
|
|
}
|
|
p->vel[2] = crand() * -10;
|
|
p->accel[2] = -PARTICLE_GRAVITY;
|
|
}
|
|
|
|
count = rand() & 0x7;
|
|
|
|
for(n=0;n<count;n++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
VectorClear (p->accel);
|
|
|
|
p->time = cl.time;
|
|
|
|
p->alpha = 1.0;
|
|
p->alphavel = -1.0 / (1+frand()*0.5);
|
|
p->color = 0 + (rand() % 4);
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = origin[j] + crand()*3;
|
|
}
|
|
p->vel[2] = 20 + crand()*5;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
CL_GenericParticleEffect
|
|
===============
|
|
*/
|
|
void CL_GenericParticleEffect (vec3_t org, vec3_t dir, int color, int count, int numcolors, int dirspread, float alphavel)
|
|
{
|
|
int i, j;
|
|
cparticle_t *p;
|
|
float d;
|
|
|
|
for (i=0 ; i<count ; i++)
|
|
{
|
|
if (!free_particles)
|
|
return;
|
|
p = free_particles;
|
|
free_particles = p->next;
|
|
p->next = active_particles;
|
|
active_particles = p;
|
|
|
|
p->time = cl.time;
|
|
if (numcolors > 1)
|
|
p->color = color + (rand() & numcolors);
|
|
else
|
|
p->color = color;
|
|
|
|
d = rand() & dirspread;
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
|
|
p->vel[j] = crand()*20;
|
|
}
|
|
|
|
p->accel[0] = p->accel[1] = 0;
|
|
p->accel[2] = -PARTICLE_GRAVITY;
|
|
// VectorCopy (accel, p->accel);
|
|
p->alpha = 1.0;
|
|
|
|
p->alphavel = -1.0 / (0.5 + frand()*alphavel);
|
|
// p->alphavel = alphavel;
|
|
}
|
|
}
|
|
#endif
|
|
//end Knightmare
|