#include "quakedef.h"
-#ifdef WORKINGLQUAKE
-#define lhrandom(MIN,MAX) ((rand() & 32767) * (((MAX)-(MIN)) * (1.0f / 32767.0f)) + (MIN))
-#define NUMVERTEXNORMALS 162
-siextern float r_avertexnormals[NUMVERTEXNORMALS][3];
-#define m_bytenormals r_avertexnormals
-#define CL_PointQ1Contents(v) (Mod_PointInLeaf(v,cl.worldmodel)->contents)
-typedef unsigned char unsigned char;
-#define cl_stainmaps.integer 0
-void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
-{
-}
-#define CL_EntityParticles R_EntityParticles
-#define CL_ReadPointFile_f R_ReadPointFile_f
-#define CL_ParseParticleEffect R_ParseParticleEffect
-#define CL_ParticleExplosion R_ParticleExplosion
-#define CL_ParticleExplosion2 R_ParticleExplosion2
-#define CL_TeleportSplash R_TeleportSplash
-#define CL_BlobExplosion R_BlobExplosion
-#define CL_RunParticleEffect R_RunParticleEffect
-#define CL_LavaSplash R_LavaSplash
-void R_CalcBeam_Vertex3f (float *vert, vec3_t org1, vec3_t org2, float width)
-{
- vec3_t right1, right2, diff, normal;
-
- VectorSubtract (org2, org1, normal);
- VectorNormalize (normal);
-
- // calculate 'right' vector for start
- VectorSubtract (r_vieworigin, org1, diff);
- VectorNormalize (diff);
- CrossProduct (normal, diff, right1);
-
- // calculate 'right' vector for end
- VectorSubtract (r_vieworigin, org2, diff);
- VectorNormalize (diff);
- CrossProduct (normal, diff, right2);
-
- vert[ 0] = org1[0] + width * right1[0];
- vert[ 1] = org1[1] + width * right1[1];
- vert[ 2] = org1[2] + width * right1[2];
- vert[ 3] = org1[0] - width * right1[0];
- vert[ 4] = org1[1] - width * right1[1];
- vert[ 5] = org1[2] - width * right1[2];
- vert[ 6] = org2[0] - width * right2[0];
- vert[ 7] = org2[1] - width * right2[1];
- vert[ 8] = org2[2] - width * right2[2];
- vert[ 9] = org2[0] + width * right2[0];
- vert[10] = org2[1] + width * right2[1];
- vert[11] = org2[2] + width * right2[2];
-}
-void fractalnoise(unsigned char *noise, int size, int startgrid)
-{
- int x, y, g, g2, amplitude, min, max, size1 = size - 1, sizepower, gridpower;
- int *noisebuf;
-#define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
-
- for (sizepower = 0;(1 << sizepower) < size;sizepower++);
- if (size != (1 << sizepower))
- {
- Con_Printf("fractalnoise: size must be power of 2\n");
- return;
- }
-
- for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
- if (startgrid != (1 << gridpower))
- {
- Con_Printf("fractalnoise: grid must be power of 2\n");
- return;
- }
-
- startgrid = bound(0, startgrid, size);
-
- amplitude = 0xFFFF; // this gets halved before use
- noisebuf = malloc(size*size*sizeof(int));
- memset(noisebuf, 0, size*size*sizeof(int));
-
- for (g2 = startgrid;g2;g2 >>= 1)
- {
- // brownian motion (at every smaller level there is random behavior)
- amplitude >>= 1;
- for (y = 0;y < size;y += g2)
- for (x = 0;x < size;x += g2)
- n(x,y) += (rand()&litude);
-
- g = g2 >> 1;
- if (g)
- {
- // subdivide, diamond-square algorithm (really this has little to do with squares)
- // diamond
- for (y = 0;y < size;y += g2)
- for (x = 0;x < size;x += g2)
- n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
- // square
- for (y = 0;y < size;y += g2)
- for (x = 0;x < size;x += g2)
- {
- n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
- n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
- }
- }
- }
- // find range of noise values
- min = max = 0;
- for (y = 0;y < size;y++)
- for (x = 0;x < size;x++)
- {
- if (n(x,y) < min) min = n(x,y);
- if (n(x,y) > max) max = n(x,y);
- }
- max -= min;
- max++;
- // normalize noise and copy to output
- for (y = 0;y < size;y++)
- for (x = 0;x < size;x++)
- *noise++ = (unsigned char) (((n(x,y) - min) * 256) / max);
- free(noisebuf);
-#undef n
-}
-void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
-{
- float d;
-
- right[0] = forward[2];
- right[1] = -forward[0];
- right[2] = forward[1];
-
- d = DotProduct(forward, right);
- right[0] -= d * forward[0];
- right[1] -= d * forward[1];
- right[2] -= d * forward[2];
- VectorNormalize(right);
- CrossProduct(right, forward, up);
-}
-#if QW
-#include "pmove.h"
-extern qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace);
-#endif
-trace_t CL_TraceBox (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hitbmodels, int *hitent, int hitsupercontentsmask, qboolean hitplayers)
-{
-#if QW
- pmtrace_t trace;
-#else
- trace_t trace;
-#endif
- memset (&trace, 0, sizeof(trace));
- trace.fraction = 1;
- VectorCopy (end, trace.endpos);
-#if QW
- PM_RecursiveHullCheck (cl.model_precache[1]->hulls, 0, 0, 1, start, end, &trace);
-#else
- RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
-#endif
- return trace;
-}
-#else
#include "cl_collision.h"
#include "image.h"
-#endif
-
-#define MAX_PARTICLES 32768 // default max # of particles at one time
-#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's on the command line
-
-typedef enum
-{
- PARTICLE_BILLBOARD = 0,
- PARTICLE_SPARK = 1,
- PARTICLE_ORIENTED_DOUBLESIDED = 2,
- PARTICLE_BEAM = 3
-}
-porientation_t;
-
-typedef enum
-{
- PBLEND_ALPHA = 0,
- PBLEND_ADD = 1,
- PBLEND_MOD = 2
-}
-pblend_t;
-
-typedef struct particletype_s
-{
- pblend_t blendmode;
- porientation_t orientation;
- qboolean lighting;
-}
-particletype_t;
-
-typedef enum
-{
- pt_alphastatic, pt_static, pt_spark, pt_beam, pt_rain, pt_raindecal, pt_snow, pt_bubble, pt_blood, pt_smoke, pt_decal, pt_entityparticle, pt_total
-}
-ptype_t;
// must match ptype_t values
particletype_t particletype[pt_total] =
{PBLEND_ALPHA, PARTICLE_BILLBOARD, false}, //pt_entityparticle
};
-typedef struct particle_s
-{
- particletype_t *type;
- int texnum;
- vec3_t org;
- vec3_t vel; // velocity of particle, or orientation of decal, or end point of beam
- float size;
- float alpha; // 0-255
- float alphafade; // how much alpha reduces per second
- float time2; // used for snow fluttering and decal fade
- float bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
- float gravity; // how much gravity affects this particle (1.0 = normal gravity, 0.0 = none)
- float friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
- unsigned char color[4];
- unsigned short owner; // decal stuck to this entity
- model_t *ownermodel; // model the decal is stuck to (used to make sure the entity is still alive)
- vec3_t relativeorigin; // decal at this location in entity's coordinate space
- vec3_t relativedirection; // decal oriented this way relative to entity's coordinate space
-}
-particle_t;
-
static int particlepalette[256] =
{
0x000000,0x0f0f0f,0x1f1f1f,0x2f2f2f,0x3f3f3f,0x4b4b4b,0x5b5b5b,0x6b6b6b, // 0-7
static const int tex_raindrop = 61;
static const int tex_beam = 60;
-static int cl_maxparticles;
-static int cl_numparticles;
-static int cl_freeparticle;
-static particle_t *particles;
-
cvar_t cl_particles = {CVAR_SAVE, "cl_particles", "1", "enables particle effects"};
cvar_t cl_particles_quality = {CVAR_SAVE, "cl_particles_quality", "1", "multiplies number of particles and reduces their alpha"};
cvar_t cl_particles_size = {CVAR_SAVE, "cl_particles_size", "1", "multiplies particle size"};
cvar_t cl_decals_time = {CVAR_SAVE, "cl_decals_time", "0", "how long before decals start to fade away"};
cvar_t cl_decals_fadetime = {CVAR_SAVE, "cl_decals_fadetime", "20", "how long decals take to fade away"};
-void CL_Particles_Clear(void)
-{
- cl_numparticles = 0;
- cl_freeparticle = 0;
- memset(particles, 0, sizeof(particle_t) * cl_maxparticles);
-}
-
/*
===============
CL_InitParticles
void CL_ReadPointFile_f (void);
void CL_Particles_Init (void)
{
- int i;
-
-// COMMANDLINEOPTION: Client: -particles <number> changes maximum number of particles at once, default 32768
- i = COM_CheckParm ("-particles");
-
- if (i && i < com_argc - 1)
- {
- cl_maxparticles = (int)(atoi(com_argv[i+1]));
- if (cl_maxparticles < ABSOLUTE_MIN_PARTICLES)
- cl_maxparticles = ABSOLUTE_MIN_PARTICLES;
- }
- else
- cl_maxparticles = MAX_PARTICLES;
-
Cmd_AddCommand ("pointfile", CL_ReadPointFile_f, "display point file produced by qbsp when a leak was detected in the map (a line leading through the leak hole, to an entity inside the level)");
Cvar_RegisterVariable (&cl_particles);
Cvar_RegisterVariable (&cl_decals);
Cvar_RegisterVariable (&cl_decals_time);
Cvar_RegisterVariable (&cl_decals_fadetime);
-
-#ifdef WORKINGLQUAKE
- particles = (particle_t *) Hunk_AllocName(cl_maxparticles * sizeof(particle_t), "particles");
-#else
- particles = (particle_t *) Mem_Alloc(cl_mempool, cl_maxparticles * sizeof(particle_t));
-#endif
- CL_Particles_Clear();
}
void CL_Particles_Shutdown (void)
{
-#ifdef WORKINGLQUAKE
- // No clue what to do here...
-#endif
}
// list of all 26 parameters:
int l1, l2;
particle_t *part;
vec3_t v;
- for (;cl_freeparticle < cl_maxparticles && particles[cl_freeparticle].type;cl_freeparticle++);
- if (cl_freeparticle >= cl_maxparticles)
+ for (;cl.free_particle < cl.max_particles && cl.particles[cl.free_particle].type;cl.free_particle++);
+ if (cl.free_particle >= cl.max_particles)
return NULL;
- part = &particles[cl_freeparticle++];
- if (cl_numparticles < cl_freeparticle)
- cl_numparticles = cl_freeparticle;
+ part = &cl.particles[cl.free_particle++];
+ if (cl.num_particles < cl.free_particle)
+ cl.num_particles = cl.free_particle;
memset(part, 0, sizeof(*part));
part->type = ptype;
l2 = (int)lhrandom(0.5, 256.5);
if (p)
{
p->time2 = cl.time;
-#ifndef WORKINGLQUAKE
p->owner = hitent;
- p->ownermodel = cl_entities[p->owner].render.model;
- Matrix4x4_Transform(&cl_entities[p->owner].render.inversematrix, org, p->relativeorigin);
- Matrix4x4_Transform3x3(&cl_entities[p->owner].render.inversematrix, normal, p->relativedirection);
+ p->ownermodel = cl.entities[p->owner].render.model;
+ Matrix4x4_Transform(&cl.entities[p->owner].render.inversematrix, org, p->relativeorigin);
+ Matrix4x4_Transform3x3(&cl.entities[p->owner].render.inversematrix, normal, p->relativedirection);
VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
-#endif
}
}
{
VectorRandom(org2);
VectorMA(org, maxdist, org2, org2);
- trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, &hitent, SUPERCONTENTS_SOLID, false);
- if (bestfrac > trace.fraction)
+ trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false);
+ // take the closest trace result that doesn't end up hitting a NOMARKS
+ // surface (sky for example)
+ if (bestfrac > trace.fraction && !(trace.hitq3surfaceflags & Q3SURFACEFLAG_NOMARKS))
{
bestfrac = trace.fraction;
besthitent = hitent;
static vec3_t avelocities[NUMVERTEXNORMALS];
if (!cl_particles.integer) return;
-#ifdef WORKINGLQUAKE
- VectorCopy(ent->origin, org);
-#else
Matrix4x4_OriginFromMatrix(&ent->render.matrix, org);
-#endif
if (!avelocities[0][0])
for (i = 0;i < NUMVERTEXNORMALS * 3;i++)
FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
strlcat (name, ".pts", sizeof (name));
-#if WORKINGLQUAKE
- pointfile = COM_LoadTempFile (name);
-#else
pointfile = (char *)FS_LoadFile(name, tempmempool, true, NULL);
-#endif
if (!pointfile)
{
Con_Printf("Could not open %s\n", name);
VectorCopy(org, leakorg);
c++;
- if (cl_numparticles < cl_maxparticles - 3)
+ if (cl.num_particles < cl.max_particles - 3)
{
s++;
particle(particletype + pt_static, particlepalette[(-c)&15], particlepalette[(-c)&15], tex_particle, 2, 255, 0, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0);
}
}
-#ifndef WORKINGLQUAKE
Mem_Free(pointfile);
-#endif
VectorCopy(leakorg, org);
Con_Printf("%i points read (%i particles spawned)\nLeak at %f %f %f\n", c, s, org[0], org[1], org[2]);
if (i & 1)
{
color = particlepalette[ramp1[r]];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, (1.0f / cl_particles_quality.value) * 32 * (8 - r), (1.0f / cl_particles_quality.value) * 318, 0, 0, org[0], org[1], org[2], 0, 0, 0, -4, 16, 256);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 32 * (8 - r), 318, 0, 0, org[0], org[1], org[2], 0, 0, 0, -4, 16, 256);
}
else
{
color = particlepalette[ramp2[r]];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, (1.0f / cl_particles_quality.value) * 32 * (8 - r), (1.0f / cl_particles_quality.value) * 478, 0, 0, org[0], org[1], org[2], 0, 0, 0, 1, 16, 256);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 32 * (8 - r), 478, 0, 0, org[0], org[1], org[2], 0, 0, 0, 1, 16, 256);
}
}
}
{
if (cl_particles.integer && cl_particles_bubbles.integer && cl_particles_explosions_bubbles.integer)
for (i = 0;i < 128 * cl_particles_quality.value;i++)
- particle(particletype + pt_bubble, 0x404040, 0x808080, tex_bubble, 2, (1.0f / cl_particles_quality.value) * lhrandom(128, 255), (1.0f / cl_particles_quality.value) * 128, -0.125, 1.5, org[0], org[1], org[2], 0, 0, 0, (1.0 / 16.0), 16, 96);
+ particle(particletype + pt_bubble, 0x404040, 0x808080, tex_bubble, 2, lhrandom(128, 255), 128, -0.125, 1.5, org[0], org[1], org[2], 0, 0, 0, (1.0 / 16.0), 16, 96);
}
else
{
{
int k;
vec3_t v, v2;
-#ifdef WORKINGLQUAKE
- v2[0] = lhrandom(-48, 48);
- v2[1] = lhrandom(-48, 48);
- v2[2] = lhrandom(-48, 48);
-#else
for (k = 0;k < 16;k++)
{
v[0] = org[0] + lhrandom(-48, 48);
break;
}
VectorSubtract(trace.endpos, org, v2);
-#endif
VectorScale(v2, 2.0f, v2);
particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 12, 32, 64, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0, 0, 0);
}
if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
for (i = 0;i < 128 * cl_particles_quality.value;i++)
- particle(particletype + pt_spark, 0x903010, 0xFFD030, tex_particle, 1.0f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 512, 1, 0, org[0], org[1], org[2], 0, 0, 80, 0.2, 0, 256);
+ particle(particletype + pt_spark, 0x903010, 0xFFD030, tex_particle, 1.0f, lhrandom(0, 255), 512, 1, 0, org[0], org[1], org[2], 0, 0, 80, 0.2, 0, 256);
}
}
{
k = particlepalette[colorStart + (i % colorLength)];
if (cl_particles_quake.integer)
- particle(particletype + pt_static, k, k, tex_particle, 1, (1.0f / cl_particles_quality.value) * 255, (1.0f/cl_particles_quality.value)*850, 0, 0, org[0], org[1], org[2], 0, 0, 0, -4, 8, 256);
+ particle(particletype + pt_static, k, k, tex_particle, 1, 255, 850, 0, 0, org[0], org[1], org[2], 0, 0, 0, -4, 8, 256);
else
- particle(particletype + pt_static, k, k, tex_particle, lhrandom(0.5, 1.5), (1.0f / cl_particles_quality.value) * 255, (1.0f/cl_particles_quality.value)*512, 0, 0, org[0], org[1], org[2], 0, 0, 0, lhrandom(1.5, 3), 8, 192);
+ particle(particletype + pt_static, k, k, tex_particle, lhrandom(0.5, 1.5), 255, 512, 0, 0, org[0], org[1], org[2], 0, 0, 0, lhrandom(1.5, 3), 8, 192);
}
}
if (i & 1)
{
k = particlepalette[66 + rand()%6];
- particle(particletype + pt_static, k, k, tex_particle, 1, (1.0f / cl_particles_quality.value) * lhrandom(182, 255), (1.0f/cl_particles_quality.value)*182, 0, 0, org[0], org[1], org[2], 0, 0, 0, -4, 16, 256);
+ particle(particletype + pt_static, k, k, tex_particle, 1, lhrandom(182, 255), 182, 0, 0, org[0], org[1], org[2], 0, 0, 0, -4, 16, 256);
}
else
{
k = particlepalette[150 + rand()%6];
- particle(particletype + pt_static, k, k, tex_particle, 1, (1.0f / cl_particles_quality.value) * lhrandom(182, 255), (1.0f/cl_particles_quality.value)*182, 0, 0, org[0], org[1], org[2], 0, 0, lhrandom(-256, 256), 0, 16, 0);
+ particle(particletype + pt_static, k, k, tex_particle, 1, lhrandom(182, 255), 182, 0, 0, org[0], org[1], org[2], 0, 0, lhrandom(-256, 256), 0, 16, 0);
}
}
}
while (count--)
{
k = particlepalette[color + (rand()&7)];
- particle(particletype + pt_alphastatic, k, k, tex_particle, 1, (1.0f / cl_particles_quality.value) * lhrandom(51, 255), (1.0f / cl_particles_quality.value) * 512, 0, 0.05, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 8, 0);
+ particle(particletype + pt_alphastatic, k, k, tex_particle, 1, lhrandom(51, 255), 512, 0, 0.05, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 8, 0);
}
}
else
{
k = particlepalette[color + (rand()&7)];
if (gamemode == GAME_GOODVSBAD2)
- particle(particletype + pt_alphastatic, k, k, tex_particle, 5, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 300, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 8, 10);
+ particle(particletype + pt_alphastatic, k, k, tex_particle, 5, 255, 300, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 8, 10);
else
- particle(particletype + pt_alphastatic, k, k, tex_particle, 1, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 512, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 8, 15);
+ particle(particletype + pt_alphastatic, k, k, tex_particle, 1, 255, 512, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 8, 15);
}
}
}
while(count--)
{
k = particlepalette[0x68 + (rand() & 7)];
- particle(particletype + pt_spark, k, k, tex_particle, 0.4f, (1.0f / cl_particles_quality.value) * lhrandom(64, 255), (1.0f / cl_particles_quality.value) * 512, gravityscale, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2] + sv_gravity.value * 0.1, 0, radius, 64);
+ particle(particletype + pt_spark, k, k, tex_particle, 0.4f, lhrandom(64, 255), 512, gravityscale, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2] + sv_gravity.value * 0.1, 0, radius, 64);
}
}
}
org2[1] = org[1] + 0.125f * lhrandom(-count, count);
org2[2] = org[2] + 0.125f * lhrandom(-count, count);
trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, NULL, SUPERCONTENTS_SOLID, false);
- particle(particletype + pt_smoke, 0x101010, 0x202020, tex_smoke[rand()&7], 3, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 1024, 0, 0, trace.endpos[0], trace.endpos[1], trace.endpos[2], 0, 0, 0, 0, radius, 8);
+ particle(particletype + pt_smoke, 0x101010, 0x202020, tex_smoke[rand()&7], 3, 255, 1024, 0, 0, trace.endpos[0], trace.endpos[1], trace.endpos[2], 0, 0, 0, 0, radius, 8);
}
}
}
count *= 5.0f;
if (count > 1000)
count = 1000;
- bloodcount += count;
+ bloodcount += count * cl_particles_quality.value;
while(bloodcount > 0)
{
org2[0] = org[0] + 0.125f * lhrandom(-bloodcount, bloodcount);
org2[1] = org[1] + 0.125f * lhrandom(-bloodcount, bloodcount);
org2[2] = org[2] + 0.125f * lhrandom(-bloodcount, bloodcount);
trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, NULL, SUPERCONTENTS_SOLID, false);
- particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, cl_particles_blood_alpha.value * 768 / cl_particles_quality.value, cl_particles_blood_alpha.value * 384 / cl_particles_quality.value, 0, -1, trace.endpos[0], trace.endpos[1], trace.endpos[2], vel[0], vel[1], vel[2], 1, 0, s);
- bloodcount -= 16 / cl_particles_quality.value;
+ particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, cl_particles_blood_alpha.value * 768, cl_particles_blood_alpha.value * 384, 0, -1, trace.endpos[0], trace.endpos[1], trace.endpos[2], vel[0], vel[1], vel[2], 1, 0, s);
+ bloodcount -= 16;
}
}
velscale[1] = velspeed * 2.0 / diff[1];
velscale[2] = velspeed * 2.0 / diff[2];
- bloodcount += count * 5.0f;
+ bloodcount += count * 5.0f * cl_particles_quality.value;
while (bloodcount > 0)
{
org[0] = lhrandom(mins[0], maxs[0]);
vel[0] = (org[0] - center[0]) * velscale[0];
vel[1] = (org[1] - center[1]) * velscale[1];
vel[2] = (org[2] - center[2]) * velscale[2];
- bloodcount -= 16 / cl_particles_quality.value;
- particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, cl_particles_blood_alpha.value * 768 / cl_particles_quality.value, cl_particles_blood_alpha.value * 384 / cl_particles_quality.value, 0, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 1, 0, 0);
+ bloodcount -= 16;
+ particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, cl_particles_blood_alpha.value * 768, cl_particles_blood_alpha.value * 384, 0, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 1, 0, 0);
}
}
while (count--)
{
k = particlepalette[colorbase + (rand()&3)];
- particle(particletype + pt_alphastatic, k, k, tex_particle, 2, 255 / cl_particles_quality.value, (255 / cl_particles_quality.value) / 2, gravity ? 1 : 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0], dir[1], dir[2], 0, 0, randomvel);
+ particle(particletype + pt_alphastatic, k, k, tex_particle, 2, 255, 128, gravity ? 1 : 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0], dir[1], dir[2], 0, 0, randomvel);
}
}
{
k = particlepalette[colorbase + (rand()&3)];
if (gamemode == GAME_GOODVSBAD2)
- particle(particletype + pt_rain, k, k, tex_particle, 20, lhrandom(8, 16) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
+ particle(particletype + pt_rain, k, k, tex_particle, 20, lhrandom(8, 16), 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
else
- particle(particletype + pt_rain, k, k, tex_particle, 0.5, lhrandom(8, 16) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
+ particle(particletype + pt_rain, k, k, tex_particle, 0.5, lhrandom(8, 16), 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
}
break;
case 1:
{
k = particlepalette[colorbase + (rand()&3)];
if (gamemode == GAME_GOODVSBAD2)
- p = particle(particletype + pt_snow, k, k, tex_particle, 20, lhrandom(64, 128) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
+ p = particle(particletype + pt_snow, k, k, tex_particle, 20, lhrandom(64, 128), 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
else
- p = particle(particletype + pt_snow, k, k, tex_particle, 1, lhrandom(64, 128) / cl_particles_quality.value, 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
+ p = particle(particletype + pt_snow, k, k, tex_particle, 1, lhrandom(64, 128), 0, 0, -1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, 0, 0);
if (p)
VectorCopy(p->vel, p->relativedirection);
}
VectorNormalize(v);
VectorScale(v, 100, v);
v[2] += sv_gravity.value * 0.15f;
- particle(particletype + pt_static, 0x903010, 0xFFD030, tex_particle, 1.5, lhrandom(64, 128) / cl_particles_quality.value, 128 / cl_particles_quality.value, 1, 0, o[0], o[1], o[2], v[0], v[1], v[2], 0.2, 0, 0);
+ particle(particletype + pt_static, 0x903010, 0xFFD030, tex_particle, 1.5, lhrandom(64, 128), 128, 1, 0, o[0], o[1], o[2], v[0], v[1], v[2], 0.2, 0, 0);
}
}
while (count--)
{
k = particlepalette[224 + (rand()&15)];
- particle(particletype + pt_static, k, k, tex_particle, 4, lhrandom(64, 128) / cl_particles_quality.value, 384 / cl_particles_quality.value, -1, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), 0, 0, 32, 1, 0, 32);
+ particle(particletype + pt_static, k, k, tex_particle, 4, lhrandom(64, 128), 384, -1, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), 0, 0, 32, 1, 0, 32);
if (count & 1)
- particle(particletype + pt_static, 0x303030, 0x606060, tex_smoke[rand()&7], 6, lhrandom(48, 96) / cl_particles_quality.value, 64 / cl_particles_quality.value, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), 0, 0, 24, 0, 0, 8);
+ particle(particletype + pt_static, 0x303030, 0x606060, tex_smoke[rand()&7], 6, lhrandom(48, 96), 64, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), 0, 0, 24, 0, 0, 8);
}
}
while (count--)
{
k = particlepalette[224 + (rand()&15)];
- particle(particletype + pt_static, k, k, tex_particle, 4, lhrandom(64, 128) / cl_particles_quality.value, 384 / cl_particles_quality.value, -1, 1.1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 1, 0, 128);
+ particle(particletype + pt_static, k, k, tex_particle, 4, lhrandom(64, 128), 384, -1, 1.1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 1, 0, 128);
}
}
}
}
-#ifdef WORKINGLQUAKE
-void R_RocketTrail (vec3_t start, vec3_t end, int type)
-#else
void CL_RocketTrail (vec3_t start, vec3_t end, int type, int color, entity_t *ent)
-#endif
{
vec3_t vec, dir, vel, pos;
float len, dec, speed, qd;
int smoke, blood, bubbles, r;
-#ifdef WORKINGLQUAKE
- int contents;
-#endif
if (end[0] == start[0] && end[1] == start[1] && end[2] == start[2])
return;
VectorNormalize(dir);
VectorSubtract (end, start, vec);
-#ifdef WORKINGLQUAKE
- len = VectorNormalize (vec);
- dec = 0;
- speed = 1.0f / cl.frametime;
- VectorSubtract(end, start, vel);
-#else
len = VectorNormalizeLength (vec);
dec = -ent->persistent.trail_time;
ent->persistent.trail_time += len;
speed = 1.0f / speed;
VectorSubtract(ent->state_current.origin, ent->state_previous.origin, vel);
color = particlepalette[color];
-#endif
VectorScale(vel, speed, vel);
// advance into this frame to reach the first puff location
smoke = cl_particles.integer && cl_particles_smoke.integer;
blood = cl_particles.integer && cl_particles_blood.integer;
-#ifdef WORKINGLQUAKE
- contents = CL_PointQ1Contents(pos);
- bubbles = cl_particles.integer && cl_particles_bubbles.integer && (contents == CONTENTS_WATER || contents == CONTENTS_SLIME);
-#else
bubbles = cl_particles.integer && cl_particles_bubbles.integer && (CL_PointSuperContents(pos) & (SUPERCONTENTS_WATER | SUPERCONTENTS_SLIME));
-#endif
qd = 1.0f / cl_particles_quality.value;
while (len >= 0)
case 0: // rocket trail
if (cl_particles_quake.integer)
{
- dec = qd*3;
+ dec = 3;
r = rand()&3;
color = particlepalette[ramp3[r]];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*42*(6-r), qd*306, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 42*(6-r), 306, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
}
else
{
- dec = qd*3;
+ dec = 3;
if (smoke)
{
- particle(particletype + pt_smoke, 0x303030, 0x606060, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*62, qd*cl_particles_smoke_alphafade.value*62, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
- particle(particletype + pt_static, 0x801010, 0xFFA020, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*288, qd*cl_particles_smoke_alphafade.value*1400, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 20);
+ particle(particletype + pt_smoke, 0x303030, 0x606060, tex_smoke[rand()&7], 3, cl_particles_smoke_alpha.value*62, cl_particles_smoke_alphafade.value*62, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ particle(particletype + pt_static, 0x801010, 0xFFA020, tex_smoke[rand()&7], 3, cl_particles_smoke_alpha.value*288, cl_particles_smoke_alphafade.value*1400, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 20);
}
if (bubbles)
- particle(particletype + pt_bubble, 0x404040, 0x808080, tex_bubble, 2, qd*lhrandom(64, 255), qd*256, -0.25, 1.5, pos[0], pos[1], pos[2], 0, 0, 0, (1.0 / 16.0), 0, 16);
+ particle(particletype + pt_bubble, 0x404040, 0x808080, tex_bubble, 2, lhrandom(64, 255), 256, -0.25, 1.5, pos[0], pos[1], pos[2], 0, 0, 0, (1.0 / 16.0), 0, 16);
}
break;
case 1: // grenade trail
if (cl_particles_quake.integer)
{
- dec = qd*3;
+ dec = 3;
r = 2 + (rand()%5);
color = particlepalette[ramp3[r]];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*42*(6-r), qd*306, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 42*(6-r), 306, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
}
else
{
- dec = qd*3;
+ dec = 3;
if (smoke)
- particle(particletype + pt_smoke, 0x303030, 0x606060, tex_smoke[rand()&7], 3, qd*cl_particles_smoke_alpha.value*50, qd*cl_particles_smoke_alphafade.value*50, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ particle(particletype + pt_smoke, 0x303030, 0x606060, tex_smoke[rand()&7], 3, cl_particles_smoke_alpha.value*50, cl_particles_smoke_alphafade.value*50, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
break;
{
if (type == 2)
{
- dec = qd*3;
+ dec = 3;
color = particlepalette[67 + (rand()&3)];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*128, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 128, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
}
else
{
- dec = qd*6;
+ dec = 6;
color = particlepalette[67 + (rand()&3)];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*128, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 128, 0, -0.05, pos[0], pos[1], pos[2], 0, 0, 0, 0, 3, 0);
}
}
else
{
- dec = qd*16;
+ dec = 16;
if (blood)
particle(particletype + pt_blood, 0xFFFFFF, 0xFFFFFF, tex_bloodparticle[rand()&7], 8, qd * cl_particles_blood_alpha.value * 768.0f, qd * cl_particles_blood_alpha.value * 384.0f, 0, -1, pos[0], pos[1], pos[2], vel[0] * 0.5f, vel[1] * 0.5f, vel[2] * 0.5f, 1, 0, 64);
}
case 3: // green tracer
if (cl_particles_quake.integer)
{
- dec = qd*6;
+ dec = 6;
color = particlepalette[52 + (rand()&7)];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*512, 0, 0, pos[0], pos[1], pos[2], 30*vec[1], 30*-vec[0], 0, 0, 0, 0);
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*512, 0, 0, pos[0], pos[1], pos[2], 30*-vec[1], 30*vec[0], 0, 0, 0, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 512, 0, 0, pos[0], pos[1], pos[2], 30*vec[1], 30*-vec[0], 0, 0, 0, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 512, 0, 0, pos[0], pos[1], pos[2], 30*-vec[1], 30*vec[0], 0, 0, 0, 0);
}
else
{
- dec = qd*16;
+ dec = 16;
if (smoke)
{
if (gamemode == GAME_GOODVSBAD2)
{
- dec = qd*6;
- particle(particletype + pt_static, 0x00002E, 0x000030, tex_particle, 6, qd*128, qd*384, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ dec = 6;
+ particle(particletype + pt_static, 0x00002E, 0x000030, tex_particle, 6, 128, 384, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
else
{
- dec = qd*3;
+ dec = 3;
color = particlepalette[20 + (rand()&7)];
- particle(particletype + pt_static, color, color, tex_particle, 2, qd*64, qd*192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ particle(particletype + pt_static, color, color, tex_particle, 2, 64, 192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
}
}
case 5: // flame tracer
if (cl_particles_quake.integer)
{
- dec = qd*6;
+ dec = 6;
color = particlepalette[230 + (rand()&7)];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*512, 0, 0, pos[0], pos[1], pos[2], 30*vec[1], 30*-vec[0], 0, 0, 0, 0);
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*512, 0, 0, pos[0], pos[1], pos[2], 30*-vec[1], 30*vec[0], 0, 0, 0, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 512, 0, 0, pos[0], pos[1], pos[2], 30*vec[1], 30*-vec[0], 0, 0, 0, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 512, 0, 0, pos[0], pos[1], pos[2], 30*-vec[1], 30*vec[0], 0, 0, 0, 0);
}
else
{
- dec = qd*3;
+ dec = 3;
if (smoke)
{
color = particlepalette[226 + (rand()&7)];
- particle(particletype + pt_static, color, color, tex_particle, 2, qd*64, qd*192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ particle(particletype + pt_static, color, color, tex_particle, 2, 64, 192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
}
break;
case 6: // voor trail
if (cl_particles_quake.integer)
{
- dec = qd*3;
+ dec = 3;
color = particlepalette[152 + (rand()&3)];
- particle(particletype + pt_alphastatic, color, color, tex_particle, 1, qd*255, qd*850, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 8, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 1, 255, 850, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 8, 0);
}
else
{
- dec = qd*16;
+ dec = 16;
if (smoke)
{
if (gamemode == GAME_GOODVSBAD2)
{
- dec = qd*6;
- particle(particletype + pt_alphastatic, particlepalette[0 + (rand()&255)], particlepalette[0 + (rand()&255)], tex_particle, 6, qd*255, qd*384, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ dec = 6;
+ particle(particletype + pt_alphastatic, particlepalette[0 + (rand()&255)], particlepalette[0 + (rand()&255)], tex_particle, 6, 255, 384, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
else if (gamemode == GAME_PRYDON)
{
- dec = qd*6;
- particle(particletype + pt_static, 0x103040, 0x204050, tex_particle, 6, qd*64, qd*192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ dec = 6;
+ particle(particletype + pt_static, 0x103040, 0x204050, tex_particle, 6, 64, 192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
else
{
- dec = qd*3;
- particle(particletype + pt_static, 0x502030, 0x502030, tex_particle, 3, qd*64, qd*192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ dec = 3;
+ particle(particletype + pt_static, 0x502030, 0x502030, tex_particle, 3, 64, 192, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
}
}
}
break;
-#ifndef WORKINGLQUAKE
case 7: // Nehahra smoke tracer
- dec = qd*7;
+ dec = 7;
if (smoke)
- particle(particletype + pt_alphastatic, 0x303030, 0x606060, tex_smoke[rand()&7], 7, qd*64, qd*320, 0, 0, pos[0], pos[1], pos[2], 0, 0, lhrandom(4, 12), 0, 0, 4);
+ particle(particletype + pt_alphastatic, 0x303030, 0x606060, tex_smoke[rand()&7], 7, 64, 320, 0, 0, pos[0], pos[1], pos[2], 0, 0, lhrandom(4, 12), 0, 0, 4);
break;
case 8: // Nexuiz plasma trail
- dec = qd*4;
+ dec = 4;
if (smoke)
- particle(particletype + pt_static, 0x283880, 0x283880, tex_particle, 4, qd*255, qd*1024, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 16);
+ particle(particletype + pt_static, 0x283880, 0x283880, tex_particle, 4, 255, 1024, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 16);
break;
case 9: // glow trail
- dec = qd*3;
+ dec = 3;
if (smoke)
- particle(particletype + pt_alphastatic, color, color, tex_particle, 5, qd*128, qd*320, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
+ particle(particletype + pt_alphastatic, color, color, tex_particle, 5, 128, 320, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0);
break;
-#endif
default:
Sys_Error("CL_RocketTrail: unknown trail type %i", type);
}
// advance to next time and position
+ dec *= qd;
len -= dec;
VectorMA (pos, dec, vec, pos);
}
-#ifndef WORKINGLQUAKE
ent->persistent.trail_time = len;
-#endif
}
void CL_BeamParticle (const vec3_t start, const vec3_t end, vec_t radius, float red, float green, float blue, float alpha, float lifetime)
// smoke puff
if (cl_particles_smoke.integer)
for (f = 0;f < count;f += 4.0f / cl_particles_quality.value)
- particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255 / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, count * 0.125f, count * 0.5f);
+ particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255, 512, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, count * 0.125f, count * 0.5f);
}
void CL_Tei_PlasmaHit(const vec3_t org, const vec3_t dir, int count)
// smoke puff
if (cl_particles_smoke.integer)
for (f = 0;f < count;f += 4.0f / cl_particles_quality.value)
- particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255 / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, count * 0.125f, count);
+ particle(particletype + pt_smoke, 0x202020, 0x404040, tex_smoke[rand()&7], 5, 255, 512, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, count * 0.125f, count);
// sparks
if (cl_particles_sparks.integer)
for (f = 0;f < count;f += 1.0f / cl_particles_quality.value)
- particle(particletype + pt_spark, 0x2030FF, 0x80C0FF, tex_particle, 2.0f, lhrandom(64, 255) / cl_particles_quality.value, 512 / cl_particles_quality.value, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 0, count * 3.0f);
+ particle(particletype + pt_spark, 0x2030FF, 0x80C0FF, tex_particle, 2.0f, lhrandom(64, 255), 512, 0, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 0, count * 3.0f);
}
/*
trace_t trace;
// LordHavoc: early out condition
- if (!cl_numparticles)
+ if (!cl.num_particles)
{
- cl_freeparticle = 0;
+ cl.free_particle = 0;
return;
}
-#ifdef WORKINGLQUAKE
- frametime = cl.frametime;
-#else
frametime = cl.time - cl.oldtime;
-#endif
gravity = frametime * sv_gravity.value;
dvel = 1+4*frametime;
bloodwaterfade = max(cl_particles_blood_alpha.value, 0.01f) * frametime * 128.0f;
maxparticle = -1;
j = 0;
- for (i = 0, p = particles;i < cl_numparticles;i++, p++)
+ for (i = 0, p = cl.particles;i < cl.num_particles;i++, p++)
{
if (!p->type)
continue;
VectorCopy(p->org, org);
if (p->bounce)
{
- if (p->type == particletype + pt_rain)
+ trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | (p->type == particletype + pt_rain ? SUPERCONTENTS_LIQUIDSMASK : 0), false);
+ // if the trace started in or hit something of SUPERCONTENTS_NODROP
+ // or if the trace hit something flagged as NOIMPACT
+ // then remove the particle
+ if (trace.hitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT || ((trace.startsupercontents | trace.hitsupercontents) & SUPERCONTENTS_NODROP))
{
- // raindrop - splash on solid/water/slime/lava
- trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK, false);
- if (trace.fraction < 1)
+ p->type = NULL;
+ continue;
+ }
+ // react if the particle hit something
+ if (trace.fraction < 1)
+ {
+ VectorCopy(trace.endpos, p->org);
+ if (p->type == particletype + pt_rain)
{
+ // raindrop - splash on solid/water/slime/lava
int count;
// convert from a raindrop particle to a rainsplash decal
- VectorCopy(trace.endpos, p->org);
VectorCopy(trace.plane.normal, p->vel);
VectorAdd(p->org, p->vel, p->org);
p->type = particletype + pt_raindecal;
p->size = 8.0;
count = rand() & 3;
while(count--)
- particle(particletype + pt_spark, 0x000000, 0x707070, tex_particle, 0.25f, (1.0f / cl_particles_quality.value) * lhrandom(64, 255), (1.0f / cl_particles_quality.value) * 512, 1, 0, p->org[0], p->org[1], p->org[2], p->vel[0]*16, p->vel[1]*16, 32 + p->vel[2]*16, 0, 0, 32);
+ particle(particletype + pt_spark, 0x000000, 0x707070, tex_particle, 0.25f, lhrandom(64, 255), 512, 1, 0, p->org[0], p->org[1], p->org[2], p->vel[0]*16, p->vel[1]*16, 32 + p->vel[2]*16, 0, 0, 32);
}
- }
- else if (p->type == particletype + pt_blood)
- {
- // blood - splash on solid
- trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, &hitent, SUPERCONTENTS_SOLID, false);
- if (trace.fraction < 1)
+ else if (p->type == particletype + pt_blood)
{
- // convert from a blood particle to a blood decal
- VectorCopy(trace.endpos, p->org);
- VectorCopy(trace.plane.normal, p->vel);
- VectorAdd(p->org, p->vel, p->org);
-#ifndef WORKINGLQUAKE
- if (cl_stainmaps.integer)
- R_Stain(p->org, 32, 32, 16, 16, p->alpha * p->size * (1.0f / 40.0f), 192, 48, 48, p->alpha * p->size * (1.0f / 40.0f));
-#endif
+ // blood - splash on solid
+ if (trace.hitq3surfaceflags & Q3SURFACEFLAG_NOMARKS)
+ {
+ p->type = NULL;
+ continue;
+ }
if (!cl_decals.integer)
{
p->type = NULL;
continue;
}
+ // convert from a blood particle to a blood decal
+ VectorCopy(trace.plane.normal, p->vel);
+ VectorAdd(p->org, p->vel, p->org);
+ if (cl_stainmaps.integer)
+ R_Stain(p->org, 32, 32, 16, 16, p->alpha * p->size * (1.0f / 40.0f), 192, 48, 48, p->alpha * p->size * (1.0f / 40.0f));
p->type = particletype + pt_decal;
p->texnum = tex_blooddecal[rand()&7];
-#ifndef WORKINGLQUAKE
p->owner = hitent;
- p->ownermodel = cl_entities[hitent].render.model;
- Matrix4x4_Transform(&cl_entities[hitent].render.inversematrix, p->org, p->relativeorigin);
- Matrix4x4_Transform3x3(&cl_entities[hitent].render.inversematrix, p->vel, p->relativedirection);
-#endif
+ p->ownermodel = cl.entities[hitent].render.model;
+ Matrix4x4_Transform(&cl.entities[hitent].render.inversematrix, p->org, p->relativeorigin);
+ Matrix4x4_Transform3x3(&cl.entities[hitent].render.inversematrix, p->vel, p->relativedirection);
p->time2 = cl.time;
p->alphafade = 0;
p->bounce = 0;
p->gravity = 0;
p->size *= 2.0f;
}
- }
- else
- {
- trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, NULL, SUPERCONTENTS_SOLID, false);
- if (trace.fraction < 1)
+ else if (p->bounce < 0)
{
- VectorCopy(trace.endpos, p->org);
- if (p->bounce < 0)
- {
- p->type = NULL;
- continue;
- }
- else
- {
- dist = DotProduct(p->vel, trace.plane.normal) * -p->bounce;
- VectorMA(p->vel, dist, trace.plane.normal, p->vel);
- if (DotProduct(p->vel, p->vel) < 0.03)
- VectorClear(p->vel);
- }
+ // bounce -1 means remove on impact
+ p->type = NULL;
+ continue;
+ }
+ else
+ {
+ // anything else - bounce off solid
+ dist = DotProduct(p->vel, trace.plane.normal) * -p->bounce;
+ VectorMA(p->vel, dist, trace.plane.normal, p->vel);
+ if (DotProduct(p->vel, p->vel) < 0.03)
+ VectorClear(p->vel);
}
}
}
if (p->friction)
{
f = p->friction * frametime;
-#ifdef WORKINGLQUAKE
- if (CL_PointQ1Contents(p->org) != CONTENTS_EMPTY)
-#else
if (CL_PointSuperContents(p->org) & SUPERCONTENTS_LIQUIDSMASK)
-#endif
f *= 4;
f = 1.0f - f;
VectorScale(p->vel, f, p->vel);
p->time2 = 1;
break;
case pt_blood:
-#ifdef WORKINGLQUAKE
- a = CL_PointQ1Contents(p->org);
- if (a <= CONTENTS_WATER)
-#else
a = CL_PointSuperContents(p->org);
if (a & (SUPERCONTENTS_WATER | SUPERCONTENTS_SLIME))
-#endif
{
p->size += frametime * 8;
//p->alpha -= bloodwaterfade;
}
else
p->vel[2] -= gravity;
-#ifdef WORKINGLQUAKE
- if (a == CONTENTS_SOLID || a == CONTENTS_LAVA)
-#else
if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_LAVA | SUPERCONTENTS_NODROP))
-#endif
p->type = NULL;
break;
case pt_bubble:
-#ifdef WORKINGLQUAKE
- a = CL_PointQ1Contents(p->org);
- if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
-#else
a = CL_PointSuperContents(p->org);
if (!(a & (SUPERCONTENTS_WATER | SUPERCONTENTS_SLIME)))
-#endif
{
p->type = NULL;
break;
}
break;
case pt_rain:
-#ifdef WORKINGLQUAKE
- a = CL_PointQ1Contents(p->org);
- if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
-#else
a = CL_PointSuperContents(p->org);
- if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK))
-#endif
+ if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK))
p->type = NULL;
break;
case pt_snow:
p->vel[1] = p->relativedirection[1] + lhrandom(-32, 32);
//p->vel[2] = p->relativedirection[2] + lhrandom(-32, 32);
}
-#ifdef WORKINGLQUAKE
- a = CL_PointQ1Contents(p->org);
- if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
-#else
a = CL_PointSuperContents(p->org);
- if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK))
-#endif
+ if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK))
p->type = NULL;
break;
case pt_smoke:
case pt_decal:
// FIXME: this has fairly wacky handling of alpha
p->alphafade = cl.time > (p->time2 + cl_decals_time.value) ? (255 / cl_decals_fadetime.value) : 0;
-#ifndef WORKINGLQUAKE
- if (cl_entities[p->owner].render.model == p->ownermodel)
+ if (cl.entities[p->owner].render.model == p->ownermodel)
{
- Matrix4x4_Transform(&cl_entities[p->owner].render.matrix, p->relativeorigin, p->org);
- Matrix4x4_Transform3x3(&cl_entities[p->owner].render.matrix, p->relativedirection, p->vel);
+ Matrix4x4_Transform(&cl.entities[p->owner].render.matrix, p->relativeorigin, p->org);
+ Matrix4x4_Transform3x3(&cl.entities[p->owner].render.matrix, p->relativedirection, p->vel);
}
else
p->type = NULL;
-#endif
break;
case pt_raindecal:
a = max(0, (cl.time - p->time2) * 40);
}
}
}
- cl_numparticles = maxparticle + 1;
- cl_freeparticle = 0;
+ cl.num_particles = maxparticle + 1;
+ cl.free_particle = 0;
}
#define MAX_PARTICLETEXTURES 64
}
particletexture_t;
-#if WORKINGLQUAKE
-static int particlefonttexture;
-#else
static rtexturepool_t *particletexturepool;
static rtexture_t *particlefonttexture;
-#endif
static particletexture_t particletexture[MAX_PARTICLETEXTURES];
static cvar_t r_drawparticles = {0, "r_drawparticles", "1", "enables drawing of particles"};
setuptex(tex_bulletdecal[i], &data[0][0][0], particletexturedata);
}
-#if WORKINGLQUAKE
- glBindTexture(GL_TEXTURE_2D, (particlefonttexture = gl_extension_number++));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#else
-
#if 0
Image_WriteTGARGBA ("particles/particlefont.tga", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata);
#endif
particletexture[tex_beam].t1 = 0;
particletexture[tex_beam].s2 = 1;
particletexture[tex_beam].t2 = 1;
-#endif
Mem_Free(particletexturedata);
}
static void r_part_newmap(void)
{
- cl_numparticles = 0;
- cl_freeparticle = 0;
}
void R_Particles_Init (void)
{
Cvar_RegisterVariable(&r_drawparticles);
-#ifdef WORKINGLQUAKE
- r_part_start();
-#else
R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap);
-#endif
}
-#ifdef WORKINGLQUAKE
-void R_InitParticles(void)
-{
- CL_Particles_Init();
- R_Particles_Init();
-}
-#endif
-
float particle_vertex3f[12], particle_texcoord2f[8];
-#ifdef WORKINGLQUAKE
-void R_DrawParticle(particle_t *p)
-{
-#else
void R_DrawParticle_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
{
- const particle_t *p = particles + surfacenumber;
+ const particle_t *p = cl.particles + surfacenumber;
rmeshstate_t m;
-#endif
pblend_t blendmode;
float org[3], up2[3], v[3], right[3], up[3], fog, ifog, cr, cg, cb, ca, size;
particletexture_t *tex;
cb = min(cb, 1);
ca = 1;
}
-#ifndef WORKINGLQUAKE
+ ca /= cl_particles_quality.value;
if (p->type->lighting)
{
float ambient[3], diffuse[3], diffusenormal[3];
GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
GL_DepthMask(false);
GL_DepthTest(true);
-#endif
size = p->size * cl_particles_size.value;
if (p->type->orientation == PARTICLE_BILLBOARD || p->type->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
{
return;
}
-#if WORKINGLQUAKE
- if (blendmode == PBLEND_ALPHA)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- else if (blendmode == PBLEND_ADD)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- else //if (blendmode == PBLEND_MOD)
- glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- glColor4f(cr, cg, cb, ca);
- glBegin(GL_QUADS);
- glTexCoord2f(particle_texcoord2f[0], particle_texcoord2f[1]);glVertex3f(particle_vertex3f[ 0], particle_vertex3f[ 1], particle_vertex3f[ 2]);
- glTexCoord2f(particle_texcoord2f[2], particle_texcoord2f[3]);glVertex3f(particle_vertex3f[ 3], particle_vertex3f[ 4], particle_vertex3f[ 5]);
- glTexCoord2f(particle_texcoord2f[4], particle_texcoord2f[5]);glVertex3f(particle_vertex3f[ 6], particle_vertex3f[ 7], particle_vertex3f[ 8]);
- glTexCoord2f(particle_texcoord2f[6], particle_texcoord2f[7]);glVertex3f(particle_vertex3f[ 9], particle_vertex3f[10], particle_vertex3f[11]);
- glEnd();
-#else
R_Mesh_Draw(0, 4, 2, polygonelements);
-#endif
}
void R_DrawParticles (void)
float minparticledist;
particle_t *p;
-#ifdef WORKINGLQUAKE
- CL_MoveParticles();
-#endif
-
// LordHavoc: early out conditions
- if ((!cl_numparticles) || (!r_drawparticles.integer))
+ if ((!cl.num_particles) || (!r_drawparticles.integer))
return;
minparticledist = DotProduct(r_vieworigin, r_viewforward) + 4.0f;
-#ifdef WORKINGLQUAKE
- glBindTexture(GL_TEXTURE_2D, particlefonttexture);
- glEnable(GL_BLEND);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glDepthMask(0);
// LordHavoc: only render if not too close
- for (i = 0, p = particles;i < cl_numparticles;i++, p++)
- if (p->type && DotProduct(p->org, r_viewforward) >= minparticledist)
- R_DrawParticle(p);
- glDepthMask(1);
- glDisable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-#else
- // LordHavoc: only render if not too close
- for (i = 0, p = particles;i < cl_numparticles;i++, p++)
+ for (i = 0, p = cl.particles;i < cl.num_particles;i++, p++)
{
if (p->type)
{
}
}
}
-#endif
}