VectorNormalizeFast(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
+float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents, int hitbmodels, void **hitent)
+{
+#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
+ VectorCopy(trace.endpos, impact);
+ VectorCopy(trace.plane.normal, normal);
+ return trace.fraction;
+}
#else
#include "cl_collision.h"
#endif
float friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
float pressure; // if non-zero, apply pressure to other particles
qbyte color[4];
+#ifndef WORKINGLQUAKE
+ entity_render_t *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
+#endif
}
particle_t;
cvar_t cl_particles_blood_alpha = {CVAR_SAVE, "cl_particles_blood_alpha", "0.5"};
cvar_t cl_particles_bulletimpacts = {CVAR_SAVE, "cl_particles_bulletimpacts", "1"};
cvar_t cl_particles_smoke = {CVAR_SAVE, "cl_particles_smoke", "1"};
+cvar_t cl_particles_smoke_size = {CVAR_SAVE, "cl_particles_smoke_size", "7"};
+cvar_t cl_particles_smoke_alpha = {CVAR_SAVE, "cl_particles_smoke_alpha", "0.5"};
+cvar_t cl_particles_smoke_alphafade = {CVAR_SAVE, "cl_particles_smoke_alphafade", "0.55"};
cvar_t cl_particles_sparks = {CVAR_SAVE, "cl_particles_sparks", "1"};
cvar_t cl_particles_bubbles = {CVAR_SAVE, "cl_particles_bubbles", "1"};
cvar_t cl_decals = {CVAR_SAVE, "cl_decals", "0"};
Cvar_RegisterVariable (&cl_particles_blood_alpha);
Cvar_RegisterVariable (&cl_particles_bulletimpacts);
Cvar_RegisterVariable (&cl_particles_smoke);
+ Cvar_RegisterVariable (&cl_particles_smoke_size);
+ Cvar_RegisterVariable (&cl_particles_smoke_alpha);
+ Cvar_RegisterVariable (&cl_particles_smoke_alphafade);
Cvar_RegisterVariable (&cl_particles_sparks);
Cvar_RegisterVariable (&cl_particles_bubbles);
Cvar_RegisterVariable (&cl_decals);
pcb2 = (((pcb2 - pcb1) * ptempcolor) >> 8) + pcb1;\
}\
part = &particles[cl_numparticles++];\
+ memset(part, 0, sizeof(*part));\
part->type = (ptype);\
part->color[0] = pcr2;\
part->color[1] = pcg2;\
float len, dec, speed, r;
int contents, smoke, blood, bubbles;
+ if (end[0] == start[0] && end[1] == start[1] && end[2] == start[2])
+ return;
+
VectorSubtract(end, start, dir);
VectorNormalize(dir);
dec = 3;
if (smoke)
{
- particle(pt_grow, PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], false, PBLEND_ADD, dec, dec, 32, 64, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 6, 0, 0, 0, 0, 0);
- particle(pt_static, PARTICLE_BILLBOARD, 0x801010, 0xFFA020, tex_smoke[rand()&7], false, PBLEND_ADD, dec, dec, 128, 768, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-20, 20), lhrandom(-20, 20), lhrandom(-20, 20), 0, 0, 0, 0, 0, 0);
+ particle(pt_grow, PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], false, PBLEND_ADD, dec, dec, cl_particles_smoke_alpha.value*125, cl_particles_smoke_alphafade.value*125, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), cl_particles_smoke_size.value, 0, 0, 0, 0, 0);
+ particle(pt_static, PARTICLE_BILLBOARD, 0x801010, 0xFFA020, tex_smoke[rand()&7], false, PBLEND_ADD, dec, dec, cl_particles_smoke_alpha.value*288, cl_particles_smoke_alphafade.value*1400, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-20, 20), lhrandom(-20, 20), lhrandom(-20, 20), 0, 0, 0, 0, 0, 0);
}
if (bubbles)
{
dec = 3;
if (cl_particles.integer && cl_particles_smoke.integer)
{
- particle(pt_static, PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], false, PBLEND_ADD, dec, dec, 32, 96, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 0, 0, 0, 0, 0, 0);
+ particle(pt_grow, PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], false, PBLEND_ADD, dec, dec, cl_particles_smoke_alpha.value*100, cl_particles_smoke_alphafade.value*100, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), cl_particles_smoke_size.value, 0, 0, 0, 0, 0);
}
break;
particle_t *p;
int i, activeparticles, maxparticle, j, a, pressureused = false, content;
float gravity, dvel, bloodwaterfade, frametime, f, dist, normal[3], v[3], org[3];
+#ifdef WORKINGLQUAKE
+ void *hitent;
+#else
+ entity_render_t *hitent;
+#endif
// LordHavoc: early out condition
if (!cl_numparticles)
VectorCopy(p->org, p->oldorg);
VectorMA(p->org, frametime, p->vel, p->org);
VectorCopy(p->org, org);
-#ifndef WORKINGLQUAKE
if (p->bounce)
{
- if (CL_TraceLine(p->oldorg, p->org, v, normal, 0, true, NULL) < 1)
+ if (CL_TraceLine(p->oldorg, p->org, v, normal, 0, true, &hitent) < 1)
{
VectorCopy(v, p->org);
if (p->bounce < 0)
{
// assume it's blood (lame, but...)
+#ifndef WORKINGLQUAKE
if (cl_stainmaps.integer)
R_Stain(v, 32, 32, 16, 16, p->alpha * p->scalex * (1.0f / 40.0f), 192, 48, 48, p->alpha * p->scalex * (1.0f / 40.0f));
+#endif
if (cl_decals.integer)
{
p->type = pt_decal;
p->orientation = PARTICLE_ORIENTED_DOUBLESIDED;
+#ifndef WORKINGLQUAKE
+ p->owner = hitent;
+ p->ownermodel = hitent->model;
+ Matrix4x4_Transform(&hitent->inversematrix, v, p->relativeorigin);
+ Matrix4x4_Transform3x3(&hitent->inversematrix, normal, p->relativedirection);
+ VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
+#endif
p->time2 = cl.time + cl_decals_time.value;
p->die = p->time2 + cl_decals_fadetime.value;
p->alphafade = 0;
}
}
}
-#endif
p->vel[2] -= p->gravity * gravity;
p->alpha -= p->alphafade * frametime;
if (p->friction)
p->scaley += frametime * p->time2;
break;
case pt_decal:
+#ifndef WORKINGLQUAKE
+ if (p->owner->model == p->ownermodel)
+ {
+ Matrix4x4_Transform(&p->owner->matrix, p->relativeorigin, p->org);
+ Matrix4x4_Transform3x3(&p->owner->matrix, p->relativedirection, p->vel2);
+ }
+ else
+ p->die = -1;
+#endif
if (cl.time > p->time2)
{
p->alphafade = p->alpha / (p->die - cl.time);
float varray_vertex[16];
#endif
+#ifdef WORKINGLQUAKE
+void R_DrawParticle(particle_t *p)
+{
+#else
void R_DrawParticleCallback(const void *calldata1, int calldata2)
{
- float org[3], up2[3], v[3], right[3], up[3], fog, ifog, fogvec[3], cr, cg, cb, ca;
- particletexture_t *tex;
-#ifndef WORKINGLQUAKE
+ const particle_t *p = calldata1;
rmeshstate_t m;
#endif
- const particle_t *p = calldata1;
+ float org[3], up2[3], v[3], right[3], up[3], fog, ifog, fogvec[3], cr, cg, cb, ca;
+ particletexture_t *tex;
VectorCopy(p->org, org);
// LordHavoc: only render if not too close
for (i = 0, p = particles;i < cl_numparticles;i++, p++)
if (DotProduct(p->org, vpn) >= minparticledist)
- R_DrawParticleCallback(p, 0);
+ R_DrawParticle(p);
glDepthMask(1);
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);