-/*
-===============
-CL_MoveParticles
-===============
-*/
-void CL_MoveParticles (void)
-{
- particle_t *p;
- int i, maxparticle, j, a, content;
- float gravity, dvel, bloodwaterfade, frametime, f, dist, org[3], oldorg[3];
- int hitent;
- trace_t trace;
-
- // LordHavoc: early out condition
- if (!cl.num_particles)
- {
- cl.free_particle = 0;
- return;
- }
-
- frametime = cl.time - cl.oldtime;
- 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 = cl.particles;i < cl.num_particles;i++, p++)
- {
- if (!p->type)
- continue;
- maxparticle = i;
- content = 0;
-
- p->alpha -= p->alphafade * frametime;
-
- if (p->alpha <= 0)
- {
- p->type = NULL;
- continue;
- }
-
- if (p->type->orientation != PARTICLE_BEAM)
- {
- VectorCopy(p->org, oldorg);
- VectorMA(p->org, frametime, p->vel, p->org);
- VectorCopy(p->org, org);
- if (p->bounce)
- {
- 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))
- {
- 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.plane.normal, p->vel);
- VectorAdd(p->org, p->vel, p->org);
- p->type = particletype + pt_raindecal;
- p->texnum = tex_rainsplash[0];
- p->time2 = cl.time;
- p->alphafade = p->alpha / 0.4;
- p->bounce = 0;
- p->friction = 0;
- p->gravity = 0;
- p->size = 8.0;
- count = rand() & 3;
- while(count--)
- 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
- 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, (int)(p->alpha * p->size * (1.0f / 40.0f)), 192, 48, 48, (int)(p->alpha * p->size * (1.0f / 40.0f)));
-
- p->type = particletype + pt_decal;
- p->texnum = tex_blooddecal[rand()&7];
- 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);
- p->time2 = cl.time;
- p->alphafade = 0;
- p->bounce = 0;
- p->friction = 0;
- p->gravity = 0;
- p->size *= 2.0f;
- }
- else if (p->bounce < 0)
- {
- // 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);
- }
- }
- }
- p->vel[2] -= p->gravity * gravity;
-
- if (p->friction)
- {
- f = p->friction * frametime;
- if (CL_PointSuperContents(p->org) & SUPERCONTENTS_LIQUIDSMASK)
- f *= 4;
- f = 1.0f - f;
- VectorScale(p->vel, f, p->vel);
- }
- }
-
- if (p->type != particletype + pt_static)
- {
- switch (p->type - particletype)
- {
- case pt_entityparticle:
- // particle that removes itself after one rendered frame
- if (p->time2)
- p->type = NULL;
- else
- p->time2 = 1;
- break;
- case pt_blood:
- a = CL_PointSuperContents(p->org);
- if (a & (SUPERCONTENTS_WATER | SUPERCONTENTS_SLIME))
- {
- p->size += frametime * 8;
- //p->alpha -= bloodwaterfade;
- }
- else
- p->vel[2] -= gravity;
- if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_LAVA | SUPERCONTENTS_NODROP))
- p->type = NULL;
- break;
- case pt_bubble:
- a = CL_PointSuperContents(p->org);
- if (!(a & (SUPERCONTENTS_WATER | SUPERCONTENTS_SLIME)))
- {
- p->type = NULL;
- break;
- }
- break;
- case pt_rain:
- a = CL_PointSuperContents(p->org);
- if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK))
- p->type = NULL;
- break;
- case pt_snow:
- if (cl.time > p->time2)
- {
- // snow flutter
- p->time2 = cl.time + (rand() & 3) * 0.1;
- p->vel[0] = p->relativedirection[0] + lhrandom(-32, 32);
- p->vel[1] = p->relativedirection[1] + lhrandom(-32, 32);
- //p->vel[2] = p->relativedirection[2] + lhrandom(-32, 32);
- }
- a = CL_PointSuperContents(p->org);
- if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK))
- p->type = NULL;
- break;
- case pt_smoke:
- //p->size += frametime * 15;
- break;
- 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;
- 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);
- }
- else
- p->type = NULL;
- break;
- case pt_raindecal:
- a = (int)max(0, (cl.time - p->time2) * 40);
- if (a < 16)
- p->texnum = tex_rainsplash[a];
- else
- p->type = NULL;
- break;
- default:
- break;
- }
- }
- }
- cl.num_particles = maxparticle + 1;
- cl.free_particle = 0;
-}
-
-#define MAX_PARTICLETEXTURES 64
-// particletexture_t is a rectangle in the particlefonttexture
-typedef struct particletexture_s
-{
- rtexture_t *texture;
- float s1, t1, s2, t2;
-}
-particletexture_t;
-
-static rtexturepool_t *particletexturepool;
-static rtexture_t *particlefonttexture;
-static particletexture_t particletexture[MAX_PARTICLETEXTURES];
-