int orientation; // typically PARTICLE_BILLBOARD
vec3_t org;
vec3_t vel;
+ int additive;
int tex;
float die;
float scalex;
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
int dynlight; // if set the particle will be dynamically lit (if cl_dynamicparticles is on), used for smoke and blood
- byte color[4];
+ qbyte color[4];
}
particle_t;
// these must match r_part.c's textures
static const int tex_smoke[8] = {0, 1, 2, 3, 4, 5, 6, 7};
-static const int tex_bullethole[8] = {8, 9, 10, 11, 12, 13, 14, 15};
-static const int tex_rainsplash[16] = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
-static const int tex_particle = 32;
-static const int tex_rain = 33;
-static const int tex_bubble = 34;
-static const int tex_rocketglow = 35;
+static const int tex_rainsplash[16] = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+static const int tex_particle = 24;
+static const int tex_rain = 25;
+static const int tex_bubble = 26;
+static const int tex_rocketglow = 27;
static int cl_maxparticles;
static int cl_numparticles;
r_refdef.particles = cl_renderparticles = Mem_Alloc(cl_refdef_mempool, cl_maxparticles * sizeof(renderparticle_t));
}
-#define particle(ptype, porientation, pcolor, ptex, plight, pscalex, pscaley, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
+#define particle(ptype, porientation, pcolor, ptex, plight, padditive, pscalex, pscaley, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
{\
particle_t *part;\
int tempcolor;\
part->tex = (ptex);\
part->orientation = (porientation);\
part->dynlight = (plight);\
+ part->additive = (padditive);\
part->scalex = (pscalex);\
part->scaley = (pscaley);\
part->alpha = (palpha);\
forward[1] = cp*sy;
forward[2] = -sp;
- particle(pt_oneframe, PARTICLE_BILLBOARD, particlepalette[0x6f], tex_particle, false, 2, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_oneframe, PARTICLE_BILLBOARD, particlepalette[0x6f], tex_particle, false, true, 2, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
}
Con_Printf ("Not enough free particles\n");
break;
}
- particle(pt_static, PARTICLE_BILLBOARD, particlepalette[(-c)&15], tex_particle, false, 2, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_static, PARTICLE_BILLBOARD, particlepalette[(-c)&15], tex_particle, false, false, 2, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
Mem_Free(pointfile);
*/
void CL_ParticleExplosion (vec3_t org, int smoke)
{
- int i, j;
- float f;
- vec3_t v, end, ang;
- byte noise1[32*32], noise2[32*32];
-
- VectorClear(end); // hush MSVC
if (cl_particles.integer && cl_particles_explosions.integer)
{
+ int i, j;
+ float f;
+ vec3_t v, end, ang;
+ qbyte noise1[32*32], noise2[32*32];
+
+ VectorClear(end); // hush MSVC
i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
{
for (i = 0;i < 128;i++)
- particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, true, 2, 2, 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
ang[2] = lhrandom(0, 360);
- fractalnoise(noise1, 32, 4);
- fractalnoise(noise2, 32, 8);
+ fractalnoisequick(noise1, 32, 4);
+ fractalnoisequick(noise2, 32, 8);
for (i = 0;i < 32;i++)
{
for (j = 0;j < 32;j++)
{
VectorRandom(v);
VectorMA(org, 16, v, v);
- TraceLine(org, v, end, NULL, 0);
+ TraceLine(org, v, end, NULL, 0, true);
ang[0] = (j + 0.5f) * (360.0f / 32.0f);
ang[1] = (i + 0.5f) * (360.0f / 32.0f);
AngleVectors(ang, v, NULL, NULL);
f = noise1[j*32+i] * 1.5f;
VectorScale(v, f, v);
- particle(pt_underwaterspark, PARTICLE_BILLBOARD, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+ particle(pt_underwaterspark, PARTICLE_BILLBOARD, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
VectorScale(v, 0.75, v);
- particle(pt_underwaterspark, PARTICLE_BILLBOARD, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+ particle(pt_underwaterspark, PARTICLE_BILLBOARD, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, true, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
}
}
}
else
{
ang[2] = lhrandom(0, 360);
- fractalnoise(noise1, 32, 4);
- fractalnoise(noise2, 32, 8);
+ fractalnoisequick(noise1, 32, 4);
+ fractalnoisequick(noise2, 32, 8);
for (i = 0;i < 32;i++)
{
for (j = 0;j < 32;j++)
{
VectorRandom(v);
VectorMA(org, 16, v, v);
- TraceLine(org, v, end, NULL, 0);
+ TraceLine(org, v, end, NULL, 0, true);
ang[0] = (j + 0.5f) * (360.0f / 32.0f);
ang[1] = (i + 0.5f) * (360.0f / 32.0f);
AngleVectors(ang, v, NULL, NULL);
f = noise1[j*32+i] * 1.5f;
VectorScale(v, f, v);
- particle(pt_spark, PARTICLE_BILLBOARD, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+ particle(pt_spark, PARTICLE_BILLBOARD, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
VectorScale(v, 0.75, v);
- particle(pt_spark, PARTICLE_BILLBOARD, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+ particle(pt_spark, PARTICLE_BILLBOARD, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, true, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
// VectorRandom(v);
// VectorScale(v, 384, v);
- // particle(pt_spark, PARTICLE_BILLBOARD, explosparkramp[rand()&7], tex_particle, false, 2, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+ // particle(pt_spark, PARTICLE_BILLBOARD, explosparkramp[rand()&7], tex_particle, false, true, 2, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
}
}
}
}
else
R_NewExplosion(org);
+ R_Stain(org, 96, 80, 80, 80, 128, 176, 176, 176, 128);
}
/*
if (!cl_particles.integer) return;
for (i = 0;i < 512;i++)
- particle(pt_fade, PARTICLE_BILLBOARD, particlepalette[colorStart + (i % colorLength)], tex_particle, false, 1.5, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 0.1f, 0);
+ particle(pt_fade, PARTICLE_BILLBOARD, particlepalette[colorStart + (i % colorLength)], tex_particle, false, false, 1.5, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 1, 0);
}
/*
int i;
if (!cl_particles.integer) return;
+ R_Stain(org, 96, 96, 64, 96, 128, 160, 128, 160, 128);
for (i = 0;i < 256;i++)
- particle(pt_blob , PARTICLE_BILLBOARD, particlepalette[ 66+(rand()%6)], tex_particle, false, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
+ particle(pt_blob , PARTICLE_BILLBOARD, particlepalette[ 66+(rand()%6)], tex_particle, false, true, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
for (i = 0;i < 256;i++)
- particle(pt_blob2, PARTICLE_BILLBOARD, particlepalette[150+(rand()%6)], tex_particle, false, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
+ particle(pt_blob2, PARTICLE_BILLBOARD, particlepalette[150+(rand()%6)], tex_particle, false, true, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
}
/*
return;
}
while (count--)
- particle(pt_fade, PARTICLE_BILLBOARD, particlepalette[color + (rand()&7)], tex_particle, false, 1, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
+ particle(pt_fade, PARTICLE_BILLBOARD, particlepalette[color + (rand()&7)], tex_particle, false, false, 1, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
}
// LordHavoc: added this for spawning sparks/dust (which have strong gravity)
{
if (!cl_particles.integer) return;
- CL_Decal(org, tex_bullethole[rand()&7], 16 * cl_particles_size.value, 0, 0, 0, 1);
+ R_Stain(org, 32, 96, 96, 96, 32, 128, 128, 128, 32);
// smoke puff
if (cl_particles_smoke.integer)
- particle(pt_bulletsmoke, PARTICLE_BILLBOARD, 0xA0A0A0, tex_smoke[rand()&7], true, 5, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_bulletsmoke, PARTICLE_BILLBOARD, 0xFFFFFF /*0xA0A0A0*/, tex_smoke[rand()&7], true, true, 5, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
if (cl_particles_sparks.integer)
{
// sparks
while(count--)
- particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0);
+ particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64) + dir[0], lhrandom(-64, 64) + dir[1], lhrandom(0, 128) + dir[2], 512, 0, 0, 0, 1, 0);
}
}
+void CL_PlasmaBurn (vec3_t org)
+{
+ if (!cl_particles.integer) return;
+
+ R_Stain(org, 48, 96, 96, 96, 48, 128, 128, 128, 48);
+}
+
void CL_BloodPuff (vec3_t org, vec3_t vel, int count)
{
// bloodcount is used to accumulate counts too small to cause a blood particle
bloodcount += count;
while(bloodcount >= 10)
{
- particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
+ particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, false, 24, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1, 0);
bloodcount -= 10;
}
}
vel[0] = (org[0] - center[0]) * velscale[0];
vel[1] = (org[1] - center[1]) * velscale[1];
vel[2] = (org[2] - center[2]) * velscale[2];
- particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1.0f, 0);
+ particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, false, 24, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1, 0);
}
}
void CL_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel)
{
- float t;
+ float t;
if (!cl_particles.integer) return;
if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
while (count--)
- particle(gravity ? pt_grav : pt_static, PARTICLE_BILLBOARD, particlepalette[colorbase + (rand()&3)], tex_particle, false, 2, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0);
+ particle(gravity ? pt_grav : pt_static, PARTICLE_BILLBOARD, particlepalette[colorbase + (rand()&3)], tex_particle, false, false, 2, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0);
}
void CL_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type)
{
- vec3_t vel;
- float t, z;
+ vec3_t vel;
+ float t, z;
if (!cl_particles.integer) return;
if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
vel[0] = dir[0] + lhrandom(-16, 16);
vel[1] = dir[1] + lhrandom(-16, 16);
vel[2] = dir[2] + lhrandom(-32, 32);
- particle(pt_rain, PARTICLE_UPRIGHT_FACING, particlepalette[colorbase + (rand()&3)], tex_particle, true, 1, 64, 64, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
+ particle(pt_rain, PARTICLE_UPRIGHT_FACING, particlepalette[colorbase + (rand()&3)], tex_particle, true, true, 1, 64, 64, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
}
break;
case 1:
vel[0] = dir[0] + lhrandom(-16, 16);
vel[1] = dir[1] + lhrandom(-16, 16);
vel[2] = dir[2] + lhrandom(-32, 32);
- particle(pt_snow, PARTICLE_BILLBOARD, particlepalette[colorbase + (rand()&3)], tex_particle, false, 2, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
+ particle(pt_snow, PARTICLE_BILLBOARD, particlepalette[colorbase + (rand()&3)], tex_particle, false, true, 2, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
}
break;
default:
void CL_FlameCube (vec3_t mins, vec3_t maxs, int count)
{
- float t;
+ float t;
if (!cl_particles.integer) return;
if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
while (count--)
- particle(pt_flame, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&15)], tex_particle, false, 8, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 0.1f, 0);
+ particle(pt_flame, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&15)], tex_particle, false, true, 8, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 1, 0);
}
void CL_Flames (vec3_t org, vec3_t vel, int count)
if (!cl_particles.integer) return;
while (count--)
- particle(pt_flame, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&15)], tex_particle, false, 8, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 0.1f, 0);
+ particle(pt_flame, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&15)], tex_particle, false, true, 8, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 1, 0);
}
org[1] = origin[1] + dir[1];
org[2] = origin[2] + lhrandom(0, 64);
vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
- particle(pt_lavasplash, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&7)], tex_particle, false, 7, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
+ particle(pt_lavasplash, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&7)], tex_particle, false, true, 7, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
}
}
}
for (i=-16 ; i<16 ; i+=8)
for (j=-16 ; j<16 ; j+=8)
for (k=-24 ; k<32 ; k+=8)
- particle(pt_fade, PARTICLE_BILLBOARD, 0xFFFFFF, tex_particle, false, 1, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 0.1f, -512.0f);
+ //particle(pt_fade, PARTICLE_BILLBOARD, 0xFFFFFF, tex_particle, false, true, 1.5, 1.5, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 1, 0);
+ particle(pt_spark, PARTICLE_BILLBOARD, 0xFFFFFF, tex_particle, false, true, 2, 2, lhrandom(64, 255), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 512), 512.0f, 0, 0, 0, 1, 0);
}
void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
{
- vec3_t vec, dir, vel;
+ vec3_t vec, dir, vel, pos;
float len, dec = 0, speed;
int contents, bubbles;
double t;
VectorSubtract(end, start, dir);
VectorNormalize(dir);
- if (type == 0 && host_frametime != 0) // rocket glow
- particle(pt_oneframe, PARTICLE_BILLBOARD, 0xFFFFFF, tex_rocketglow, false, 24, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ //if (type == 0 && host_frametime != 0) // rocket glow
+ // particle(pt_oneframe, PARTICLE_BILLBOARD, 0xFFFFFF, tex_rocketglow, false, true, 24, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
t = ent->persistent.trail_time;
if (t >= cl.time)
// advance into this frame to reach the first puff location
dec = t - cl.oldtime;
dec *= speed;
- VectorMA(start, dec, vec, start);
+ VectorMA(start, dec, vec, pos);
- contents = Mod_PointInLeaf(start, cl.worldmodel)->contents;
+ contents = Mod_PointInLeaf(pos, cl.worldmodel)->contents;
if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
{
// advance the trail time
else if (bubbles && cl_particles_bubbles.integer)
{
dec = 0.005f;
- particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
- particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
- particle(pt_smoke, PARTICLE_BILLBOARD, 0xFFFFFF, tex_smoke[rand()&7], false, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, true, 2, 2, 255, 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, true, 2, 2, 255, 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_smoke, PARTICLE_BILLBOARD, 0xFFFFFF, tex_smoke[rand()&7], false, false, 2, 2, 160, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
else
{
dec = 0.005f;
- particle(pt_smoke, PARTICLE_BILLBOARD, 0xC0C0C0, tex_smoke[rand()&7], true, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
- //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
- //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
- //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
- //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+ particle(pt_smoke, PARTICLE_BILLBOARD, 0xC0C0C0, tex_smoke[rand()&7], true, false, 2, 2, 160, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(128, 255), 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 1, 0);
+ //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(128, 255), 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 1, 0);
+ //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(128, 255), 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 1, 0);
+ //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, true, 1, 1, lhrandom(128, 255), 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 1, 0);
}
break;
else if (bubbles && cl_particles_bubbles.integer)
{
dec = 0.02f;
- particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
- particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
- particle(pt_smoke, PARTICLE_BILLBOARD, 0xFFFFFF, tex_smoke[rand()&7], false, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, true, 2, 2, 255, 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, true, 2, 2, 255, 9999, 1.5, pos[0], pos[1], pos[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_smoke, PARTICLE_BILLBOARD, 0xFFFFFF, tex_smoke[rand()&7], false, false, 2, 2, 160, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
else
{
dec = 0.02f;
- particle(pt_smoke, PARTICLE_BILLBOARD, 0x808080, tex_smoke[rand()&7], true, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_smoke, PARTICLE_BILLBOARD, 0x808080, tex_smoke[rand()&7], true, false, 2, 2, 160, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
break;
else
{
dec = 0.1f;
- particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
+ particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, false, 24, 24, 255, 9999, -1, pos[0], pos[1], pos[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1, 0);
}
break;
else
{
dec = 0.15f;
- particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
+ particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, false, 24, 24, 255, 9999, -1, pos[0], pos[1], pos[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1, 0);
}
break;
case 3: // green tracer
dec = 0.02f;
- particle(pt_fade, PARTICLE_BILLBOARD, 0x373707, tex_smoke[rand()&7], false, 4, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_fade, PARTICLE_BILLBOARD, 0x373707, tex_smoke[rand()&7], false, false, 4, 4, 255, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
case 5: // flame tracer
dec = 0.02f;
- particle(pt_fade, PARTICLE_BILLBOARD, 0xCF632B, tex_smoke[rand()&7], false, 4, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_fade, PARTICLE_BILLBOARD, 0xCF632B, tex_smoke[rand()&7], false, false, 4, 4, 255, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
case 6: // voor trail
dec = 0.05f; // sparse trail
- particle(pt_fade, PARTICLE_BILLBOARD, 0x47232B, tex_smoke[rand()&7], false, 4, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_fade, PARTICLE_BILLBOARD, 0x47232B, tex_smoke[rand()&7], false, false, 4, 4, 255, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
case 7: // Nehahra smoke tracer
else
{
dec = 0.14f;
- particle(pt_smoke, PARTICLE_BILLBOARD, 0xC0C0C0, tex_smoke[rand()&7], true, 10, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_smoke, PARTICLE_BILLBOARD, 0xC0C0C0, tex_smoke[rand()&7], true, false, 10, 10, 64, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
break;
}
// advance to next time and position
t += dec;
dec *= speed;
- VectorMA (start, dec, vec, start);
+ VectorMA (pos, dec, vec, pos);
}
ent->persistent.trail_time = t;
}
void CL_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
{
- vec3_t vec;
+ vec3_t vec, pos;
int len;
if (!cl_particles.integer) return;
if (!cl_particles_smoke.integer) return;
+ VectorCopy(start, pos);
VectorSubtract (end, start, vec);
len = (int) (VectorNormalizeLength (vec) * (1.0f / 3.0f));
VectorScale(vec, 3, vec);
color = particlepalette[color];
while (len--)
{
- particle(pt_smoke, PARTICLE_BILLBOARD, color, tex_particle, false, 8, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
- VectorAdd (start, vec, start);
+ particle(pt_smoke, PARTICLE_BILLBOARD, color, tex_particle, false, false, 8, 8, 192, 9999, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ VectorAdd (pos, vec, pos);
}
}
{
particle_t *p;
renderparticle_t *r;
- int i, activeparticles, maxparticle, j, a, b, pressureused = false;
- float gravity, dvel, frametime, f, dist, normal[3], v[3], org[3], o[3];
+ int i, activeparticles, maxparticle, j, a, pressureused = false, content;
+ float gravity, dvel, frametime, f, dist, normal[3], v[3], org[3];
// LordHavoc: early out condition
if (!cl_numparticles)
continue;
}
+ content = 0;
VectorCopy(p->org, p->oldorg);
VectorMA(p->org, frametime, p->vel, p->org);
if (p->friction)
{
- f = 1.0f - (p->friction * frametime);
+ f = p->friction * frametime;
+ if (!content)
+ content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (content != CONTENTS_EMPTY)
+ f *= 4;
+ f = 1.0f - f;
VectorScale(p->vel, f, p->vel);
}
VectorCopy(p->org, org);
if (p->bounce)
{
- if (TraceLine(p->oldorg, p->org, v, normal, 0) < 1)
+ if (TraceLine(p->oldorg, p->org, v, normal, 0, true) < 1)
{
VectorCopy(v, p->org);
if (p->bounce < 0)
{
- CL_Decal(v, p->tex, p->scalex * cl_particles_size.value, p->color[0] * (1.0f / 255.0f), p->color[1] * (1.0f / 255.0f), p->color[2] * (1.0f / 255.0f), p->alpha * (1.0f / 255.0f));
+ // assume it's blood (lame, but...)
+ R_Stain(v, 48, 64, 24, 24, 48, 192, 48, 48, 48);
p->die = -1;
freeparticles[j++] = p;
continue;
p->vel[1] = (rand()&63)-32 + p->vel2[1];
p->vel[2] = (rand()&63)-32 + p->vel2[2];
}
- a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (!content)
+ content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ a = content;
if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
{
p->die = -1;
p->vel[2] = 96;
break;
default: // CONTENTS_SOLID and any others
- TraceLine(p->oldorg, p->org, v, normal, 0);
+ TraceLine(p->oldorg, p->org, v, normal, 0, true);
VectorCopy(v, p->org);
p->tex = tex_smoke[rand()&7];
p->orientation = PARTICLE_BILLBOARD;
break;
case pt_blood:
p->friction = 1;
- a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (!content)
+ content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ a = content;
if (a != CONTENTS_EMPTY)
{
if (a == CONTENTS_WATER || a == CONTENTS_SLIME)
p->vel[2] -= gravity;
if (p->alpha < 1)
p->die = -1;
- else if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
- p->type = pt_underwaterspark;
- break;
- case pt_underwaterspark:
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
+ else
{
- p->tex = tex_smoke[rand()&7];
- p->orientation = PARTICLE_BILLBOARD;
- p->color[0] = p->color[1] = p->color[2] = 255;
- p->scalex = 8;
- p->scaley = 8;
- p->type = pt_explosionsplash;
+ if (!content)
+ content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (content != CONTENTS_EMPTY)
+ p->die = -1;
}
- else
- p->vel[2] += gravity * 0.5f;
- p->alpha -= frametime * p->time2;
- if (p->alpha < 1)
- p->die = -1;
break;
case pt_explosionsplash:
if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
p->die = -1;
break;
case pt_fade:
- p->alpha -= frametime * 512;
+ p->alpha -= frametime * 384;
if (p->alpha < 1)
p->die = -1;
break;
case pt_bubble:
- a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
- if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
+ if (!content)
+ content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (content != CONTENTS_WATER && content != CONTENTS_SLIME)
{
p->tex = tex_smoke[rand()&7];
p->orientation = PARTICLE_BILLBOARD;
p->vel[0] = p->vel[1] = p->vel[2] = 0;
break;
}
- p->vel[2] += gravity * 0.25;
p->vel[0] *= (1 - (frametime * 0.0625));
p->vel[1] *= (1 - (frametime * 0.0625));
- p->vel[2] *= (1 - (frametime * 0.0625));
+ p->vel[2] = (p->vel[2] + gravity * 0.25) * (1 - (frametime * 0.0625));
if (cl.time > p->time2)
{
p->time2 = cl.time + lhrandom(0, 0.5);
p->die = -1;
break;
case pt_rain:
+ if (!content)
+ content = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ a = content;
+ if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
+ p->die = -1;
+ /*
f = 0;
b = Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents;
VectorCopy(p->oldorg, o);
while (f < 1)
{
a = b;
- f = TraceLine(o, p->org, v, normal, a);
+ f = TraceLine(o, p->org, v, normal, a, true);
b = traceline_endcontents;
if (f < 1 && b != CONTENTS_EMPTY && b != CONTENTS_SKY)
{
+ #if 1
p->die = -1;
- /*
+ #else
p->die = cl.time + 1000;
p->vel[0] = p->vel[1] = p->vel[2] = 0;
VectorCopy(v, p->org);
p->scaley = 8;
break;
}
- */
+ #endif
+ break;
}
}
+ */
break;
/*
case pt_raindropsplash:
// build renderparticle for renderer to use
r->orientation = p->orientation;
+ r->additive = p->additive;
r->dir[0] = p->vel2[0];
r->dir[1] = p->vel2[1];
r->dir[2] = p->vel2[2];