siextern float r_avertexnormals[NUMVERTEXNORMALS][3];
#define m_bytenormals r_avertexnormals
#define VectorNormalizeFast VectorNormalize
-#define Mod_PointContents(v,m) (Mod_PointInLeaf(v,m)->contents)
+#define CL_PointContents(v) (Mod_PointInLeaf(v,cl.worldmodel)->contents)
typedef unsigned char qbyte;
#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_RunParticleEffect R_RunParticleEffect
#define CL_LavaSplash R_LavaSplash
#define CL_RocketTrail2 R_RocketTrail2
-void R_CalcBeamVerts (float *vert, vec3_t org1, vec3_t org2, float width)
+void R_CalcBeam_Vertex3f (float *vert, vec3_t org1, vec3_t org2, float width)
{
vec3_t right1, right2, diff, normal;
vert[ 0] = org1[0] + width * right1[0];
vert[ 1] = org1[1] + width * right1[1];
vert[ 2] = org1[2] + width * right1[2];
- vert[ 4] = org1[0] - width * right1[0];
- vert[ 5] = org1[1] - width * right1[1];
- vert[ 6] = org1[2] - width * right1[2];
- vert[ 8] = org2[0] - width * right2[0];
- vert[ 9] = org2[1] - width * right2[1];
- vert[10] = org2[2] - width * right2[2];
- vert[12] = org2[0] + width * right2[0];
- vert[13] = org2[1] + width * right2[1];
- vert[14] = org2[2] + width * right2[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(qbyte *noise, int size, int startgrid)
{
trace.fraction = 1;
VectorCopy (end, trace.endpos);
#if QW
- PM_RecursiveHullCheck (cl.model_precache[1]->hulls, 0, 0, 1, start, end, &trace);
+ PM_RecursiveHullCheck (cl.model_precache[1]->brushq1.hulls, 0, 0, 1, start, end, &trace);
#else
- RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
+ RecursiveHullCheck (cl.worldmodel->brushq1.hulls, 0, 0, 1, start, end, &trace);
#endif
VectorCopy(trace.endpos, impact);
VectorCopy(trace.plane.normal, normal);
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;\
forward[2] = -sp;
#ifdef WORKINGLQUAKE
- particle(pt_static, PARTICLE_BILLBOARD, particlepalette[0x6f], particlepalette[0x6f], tex_particle, false, PBLEND_ALPHA, 2, 2, 255, 0, 0, 0, 0, ent->origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ particle(pt_static, PARTICLE_BILLBOARD, particlepalette[0x6f], particlepalette[0x6f], tex_particle, false, PBLEND_ADD, 2, 2, 255, 0, 0, 0, 0, ent->origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#else
- particle(pt_static, PARTICLE_BILLBOARD, particlepalette[0x6f], particlepalette[0x6f], tex_particle, false, PBLEND_ALPHA, 2, 2, 255, 0, 0, 0, 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_static, PARTICLE_BILLBOARD, particlepalette[0x6f], particlepalette[0x6f], tex_particle, false, PBLEND_ADD, 2, 2, 255, 0, 0, 0, 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);
#endif
}
}
void CL_ReadPointFile_f (void)
{
- vec3_t org;
- int r, c;
- char *pointfile = NULL, *pointfilepos, *t, tchar;
+ vec3_t org, leakorg;
+ int r, c, s;
+ char *pointfile = NULL, *pointfilepos, *t, tchar;
+ char name[MAX_OSPATH];
+
+ if (!cl.worldmodel)
+ return;
+
+ FS_StripExtension(cl.worldmodel->name, name);
+ strcat(name, ".pts");
#if WORKINGLQUAKE
- char name[MAX_OSPATH];
-
- sprintf (name,"maps/%s.pts", cl.worldmodel->name);
- COM_FOpenFile (name, &f);
- if (f)
- {
- int pointfilelength;
- fseek(f, 0, SEEK_END);
- pointfilelength = ftell(f);
- fseek(f, 0, SEEK_SET);
- pointfile = malloc(pointfilelength + 1);
- fread(pointfile, 1, pointfilelength, f);
- pointfile[pointfilelength] = 0;
- fclose(f);
- }
+ pointfile = COM_LoadTempFile (name);
#else
- pointfile = COM_LoadFile(va("maps/%s.pts", cl.worldmodel->name), true);
+ pointfile = FS_LoadFile(name, true);
#endif
if (!pointfile)
{
- Con_Printf ("couldn't open %s.pts\n", cl.worldmodel->name);
+ Con_Printf ("Could not open %s\n", name);
return;
}
- Con_Printf ("Reading %s.pts...\n", cl.worldmodel->name);
+ Con_Printf ("Reading %s...\n", name);
c = 0;
+ s = 0;
pointfilepos = pointfile;
while (*pointfilepos)
{
pointfilepos = t;
if (r != 3)
break;
+ if (c == 0)
+ VectorCopy(org, leakorg);
c++;
- if (cl_numparticles >= cl_maxparticles)
+ if (cl_numparticles < cl_maxparticles - 3)
{
- Con_Printf ("Not enough free particles\n");
- break;
+ s++;
+ particle(pt_static, PARTICLE_BILLBOARD, particlepalette[(-c)&15], particlepalette[(-c)&15], tex_particle, false, PBLEND_ALPHA, 2, 2, 255, 0, 99999, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
- particle(pt_static, PARTICLE_BILLBOARD, particlepalette[(-c)&15], particlepalette[(-c)&15], tex_particle, false, PBLEND_ALPHA, 2, 2, 255, 0, 99999, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-
-#ifdef WORKINGLQUAKE
- free(pointfile);
-#else
+#ifndef WORKINGLQUAKE
Mem_Free(pointfile);
#endif
- Con_Printf ("%i points read\n", c);
+ 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]);
+
+ particle(pt_static, PARTICLE_BEAM, 0xFF0000, 0xFF0000, tex_beam, false, PBLEND_ALPHA, 64, 64, 255, 0, 99999, 0, 0, org[0] - 4096, org[1], org[2], 0, 0, 0, 0, org[0] + 4096, org[1], org[2], 0, 0);
+ particle(pt_static, PARTICLE_BEAM, 0x00FF00, 0x00FF00, tex_beam, false, PBLEND_ALPHA, 64, 64, 255, 0, 99999, 0, 0, org[0], org[1] - 4096, org[2], 0, 0, 0, 0, org[0], org[1] + 4096, org[2], 0, 0);
+ particle(pt_static, PARTICLE_BEAM, 0x0000FF, 0x0000FF, tex_beam, false, PBLEND_ALPHA, 64, 64, 255, 0, 99999, 0, 0, org[0], org[1], org[2] - 4096, 0, 0, 0, 0, org[0], org[1], org[2] + 4096, 0, 0);
}
/*
if (cl_stainmaps.integer)
R_Stain(org, 96, 80, 80, 80, 64, 176, 176, 176, 64);
- i = Mod_PointContents(org, cl.worldmodel);
+ i = CL_PointContents(org);
if ((i == CONTENTS_SLIME || i == CONTENTS_WATER) && cl_particles.integer && cl_particles_bubbles.integer)
{
for (i = 0;i < 128;i++)
/*
// LordHavoc: smoke effect similar to UT2003, chews fillrate too badly up close
// smoke puff
- if (cl_particles_smoke.integer)
+ if (cl_particles.integer && cl_particles_smoke.integer)
{
for (i = 0;i < 64;i++)
{
}
*/
- if (cl_particles_sparks.integer)
+ if (cl_particles.integer && cl_particles_sparks.integer)
{
// sparks
for (i = 0;i < 256;i++)
while (count--)
{
k = particlepalette[color + (rand()&7)];
- particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ALPHA, 1, 1, 255, 512, 9999, 0, 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);
+ if (gamemode == GAME_GOODVSBAD2)
+ {
+ particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ALPHA, 5, 5, 255, 300, 9999, 0, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-10, 10), lhrandom(-10, 10), lhrandom(-10, 10), 0, 0, 0, 0, 0, 0);
+ }
+ else
+ {
+ particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ALPHA, 1, 1, 255, 512, 9999, 0, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), dir[0] + lhrandom(-15, 15), dir[1] + lhrandom(-15, 15), dir[2] + lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
+ }
}
}
*/
void CL_SparkShower (vec3_t org, vec3_t dir, int count)
{
+ vec3_t org2, org3;
int k;
- if (!cl_particles.integer) return;
if (cl_stainmaps.integer)
R_Stain(org, 32, 96, 96, 96, 24, 128, 128, 128, 24);
+ if (!cl_particles.integer) return;
+
if (cl_particles_bulletimpacts.integer)
{
// smoke puff
k = count / 4;
while(k--)
{
- particle(pt_grow, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, PBLEND_ADD, 3, 3, 255, 1024, 9999, -0.2, 0, org[0] + 0.125f * lhrandom(-count, count), org[1] + 0.125f * lhrandom (-count, count), org[2] + 0.125f * lhrandom(-count, count), lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 15, 0, 0, 0, 0, 0);
+ org2[0] = org[0] + 0.125f * lhrandom(-count, count);
+ org2[1] = org[1] + 0.125f * lhrandom(-count, count);
+ org2[2] = org[2] + 0.125f * lhrandom(-count, count);
+ CL_TraceLine(org, org2, org3, NULL, 0, true, NULL);
+ particle(pt_grow, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, PBLEND_ADD, 3, 3, 255, 1024, 9999, -0.2, 0, org3[0], org3[1], org3[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 15, 0, 0, 0, 0, 0);
}
}
void CL_BloodPuff (vec3_t org, vec3_t vel, int count)
{
float s, r, a;
+ vec3_t org2, org3;
// bloodcount is used to accumulate counts too small to cause a blood particle
if (!cl_particles.integer) return;
if (!cl_particles_blood.integer) return;
a = cl_particles_blood_alpha.value * 255;
while(bloodcount > 0)
{
- particle(pt_blood, PARTICLE_BILLBOARD, 0xFFFFFF, 0xFFFFFF, tex_blooddecal[rand()&7], true, PBLEND_MOD, r, r, a * 3, a * 1.5, 9999, 0, -1, org[0], org[1], org[2], vel[0] + lhrandom(-s, s), vel[1] + lhrandom(-s, s), vel[2] + lhrandom(-s, s), 0, 0, 0, 0, 1, 0);
- //particle(pt_blood, PARTICLE_BILLBOARD, 0x000000, 0x200000, tex_smoke[rand()&7], true, PBLEND_ALPHA, r, r, a, a * 0.5, 9999, 0, -1, org[0], org[1], org[2], vel[0] + lhrandom(-s, s), vel[1] + lhrandom(-s, s), vel[2] + lhrandom(-s, s), 0, 0, 0, 0, 1, 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);
+ CL_TraceLine(org, org2, org3, NULL, 0, true, NULL);
+ particle(pt_blood, PARTICLE_BILLBOARD, 0xFFFFFF, 0xFFFFFF, tex_blooddecal[rand()&7], true, PBLEND_MOD, r, r, a * 3, a * 1.5, 9999, 0, -1, org3[0], org3[1], org3[2], vel[0] + lhrandom(-s, s), vel[1] + lhrandom(-s, s), vel[2] + lhrandom(-s, s), 0, 0, 0, 0, 1, 0);
+ //particle(pt_blood, PARTICLE_BILLBOARD, 0x000000, 0x200000, tex_smoke[rand()&7], true, PBLEND_ALPHA, r, r, a, a * 0.5, 9999, 0, -1, org3[0], org3[1], org3[2], vel[0] + lhrandom(-s, s), vel[1] + lhrandom(-s, s), vel[2] + lhrandom(-s, s), 0, 0, 0, 0, 1, 0);
bloodcount -= r;
}
}
while(count--)
{
k = particlepalette[colorbase + (rand()&3)];
- particle(pt_rain, PARTICLE_SPARK, k, k, tex_particle, true, PBLEND_ADD, 0.5, 0.02, lhrandom(8, 16), 0, t, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], cl.time + 9999, dir[0], dir[1], dir[2], 0, 0);
+ if (gamemode == GAME_GOODVSBAD2)
+ {
+ particle(pt_rain, PARTICLE_SPARK, k, k, tex_particle, true, PBLEND_ADD, 20, 20, lhrandom(8, 16), 0, t, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], cl.time + 9999, dir[0], dir[1], dir[2], 0, 0);
+ }
+ else
+ {
+ particle(pt_rain, PARTICLE_SPARK, k, k, tex_particle, true, PBLEND_ADD, 0.5, 0.02, lhrandom(8, 16), 0, t, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], cl.time + 9999, dir[0], dir[1], dir[2], 0, 0);
+ }
}
break;
case 1:
while(count--)
{
k = particlepalette[colorbase + (rand()&3)];
- particle(pt_rain, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ADD, 1, 1, lhrandom(64, 128), 0, t, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, dir[0], dir[1], dir[2], 0, 0);
+ if (gamemode == GAME_GOODVSBAD2)
+ {
+ particle(pt_rain, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ADD, 20, 20, lhrandom(64, 128), 0, t, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, dir[0], dir[1], dir[2], 0, 0);
+ }
+ else
+ {
+ particle(pt_rain, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ADD, 1, 1, lhrandom(64, 128), 0, t, 0, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(minz, maxz), dir[0], dir[1], dir[2], 0, dir[0], dir[1], dir[2], 0, 0);
+ }
}
break;
default:
*/
void CL_LavaSplash (vec3_t origin)
{
- int i, j, k;
+ int i, j, k, l, inc;
float vel;
vec3_t dir, org;
if (!cl_particles.integer) return;
- for (i=-128 ; i<128 ; i+=16)
+ inc = 32;
+ for (i = -128;i < 128;i += inc)
{
- for (j=-128 ; j<128 ; j+=16)
+ for (j = -128;j < 128;j += inc)
{
dir[0] = j + lhrandom(0, 8);
dir[1] = i + lhrandom(0, 8);
org[1] = origin[1] + dir[1];
org[2] = origin[2] + lhrandom(0, 64);
vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
- k = particlepalette[224 + (rand()&7)];
- particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ADD, 7, 7, 255, 192, 9999, 0.05, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
+ if (gamemode == GAME_GOODVSBAD2)
+ {
+ k = particlepalette[0 + (rand()&255)];
+ l = particlepalette[0 + (rand()&255)];
+ particle(pt_static, PARTICLE_BILLBOARD, k, l, tex_particle, false, PBLEND_ADD, 12, 12, 255, 240, 9999, 0.05, 1, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
+ }
+ else
+ {
+ k = l = particlepalette[224 + (rand()&7)];
+ particle(pt_static, PARTICLE_BILLBOARD, k, l, tex_particle, false, PBLEND_ADD, 12, 12, 255, 240, 9999, 0.05, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
+ }
}
}
}
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);
VectorMA(start, dec, vec, pos);
len -= dec;
- contents = Mod_PointContents(pos, cl.worldmodel);
+ contents = CL_PointContents(pos);
if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
return;
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)
{
case 1: // grenade trail
// FIXME: make it gradually stop smoking
dec = 3;
- if (cl_particles.integer && cl_particles_smoke.integer)
+ if (smoke)
{
- 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;
dec = 6;
if (smoke)
{
- particle(pt_static, PARTICLE_BILLBOARD, 0x002000, 0x003000, tex_particle, false, PBLEND_ADD, dec, dec, 128, 384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ if (gamemode == GAME_GOODVSBAD2)
+ {
+ particle(pt_static, PARTICLE_BILLBOARD, 0x00002E, 0x000030, tex_particle, false, PBLEND_ADD, dec, dec, 128, 384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ }
+ else
+ {
+ particle(pt_static, PARTICLE_BILLBOARD, 0x002000, 0x003000, tex_particle, false, PBLEND_ADD, dec, dec, 128, 384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ }
}
break;
dec = 6;
if (smoke)
{
- particle(pt_static, PARTICLE_BILLBOARD, 0x502030, 0x502030, tex_particle, false, PBLEND_ADD, dec, dec, 128, 384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ if (gamemode == GAME_GOODVSBAD2)
+ {
+ particle(pt_static, PARTICLE_BILLBOARD, particlepalette[0 + (rand()&255)], particlepalette[0 + (rand()&255)], tex_particle, false, PBLEND_ALPHA, dec, dec, 255, 384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ }
+ else
+ {
+ particle(pt_static, PARTICLE_BILLBOARD, 0x502030, 0x502030, tex_particle, false, PBLEND_ADD, dec, dec, 128, 384, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(-8, 8), 0, 0, 0, 0, 0, 0);
+ }
}
break;
particle(pt_static, PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], true, PBLEND_ALPHA, dec, dec, 64, 320, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
}
break;
- case 8: // Nexiuz plasma trail
+ case 8: // Nexuiz plasma trail
dec = 4;
if (smoke)
{
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, org);
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)
{
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;
{
f = p->friction * frametime;
if (!content)
- content = Mod_PointContents(p->org, cl.worldmodel);
+ content = CL_PointContents(p->org);
if (content != CONTENTS_EMPTY)
f *= 4;
f = 1.0f - f;
{
case pt_blood:
if (!content)
- content = Mod_PointContents(p->org, cl.worldmodel);
+ content = CL_PointContents(p->org);
a = content;
if (a != CONTENTS_EMPTY)
{
break;
case pt_bubble:
if (!content)
- content = Mod_PointContents(p->org, cl.worldmodel);
+ content = CL_PointContents(p->org);
if (content != CONTENTS_WATER && content != CONTENTS_SLIME)
{
p->die = -1;
p->vel[2] = /*lhrandom(-32, 32) +*/ p->vel2[2];
}
if (!content)
- content = Mod_PointContents(p->org, cl.worldmodel);
+ content = CL_PointContents(p->org);
a = content;
if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
p->die = -1;
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);
}
break;
default:
- printf("unknown particle type %i\n", p->type);
+ Con_Printf("unknown particle type %i\n", p->type);
p->die = -1;
break;
}
CL_Particles_Init();
R_Particles_Init();
}
-
-float varray_vertex[16];
#endif
+float particle_vertex3f[12], particle_texcoord2f[8];
+
#ifdef WORKINGLQUAKE
void R_DrawParticle(particle_t *p)
{
VectorCopy(p->org, org);
- if (p->orientation == PARTICLE_BILLBOARD)
- {
- VectorScale(vright, p->scalex, right);
- VectorScale(vup, p->scaley, up);
- varray_vertex[ 0] = org[0] + right[0] - up[0];
- varray_vertex[ 1] = org[1] + right[1] - up[1];
- varray_vertex[ 2] = org[2] + right[2] - up[2];
- varray_vertex[ 4] = org[0] - right[0] - up[0];
- varray_vertex[ 5] = org[1] - right[1] - up[1];
- varray_vertex[ 6] = org[2] - right[2] - up[2];
- varray_vertex[ 8] = org[0] - right[0] + up[0];
- varray_vertex[ 9] = org[1] - right[1] + up[1];
- varray_vertex[10] = org[2] - right[2] + up[2];
- varray_vertex[12] = org[0] + right[0] + up[0];
- varray_vertex[13] = org[1] + right[1] + up[1];
- varray_vertex[14] = org[2] + right[2] + up[2];
- }
- else if (p->orientation == PARTICLE_SPARK)
- {
- VectorMA(p->org, -p->scaley, p->vel, v);
- VectorMA(p->org, p->scaley, p->vel, up2);
- R_CalcBeamVerts(varray_vertex, v, up2, p->scalex);
- }
- else if (p->orientation == PARTICLE_BEAM)
- R_CalcBeamVerts(varray_vertex, p->org, p->vel2, p->scalex);
- else if (p->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
- {
- // double-sided
- if (DotProduct(p->vel2, r_origin) > DotProduct(p->vel2, org))
- {
- VectorNegate(p->vel2, v);
- VectorVectors(v, right, up);
- }
- else
- VectorVectors(p->vel2, right, up);
- VectorScale(right, p->scalex, right);
- VectorScale(up, p->scaley, up);
- varray_vertex[ 0] = org[0] + right[0] - up[0];
- varray_vertex[ 1] = org[1] + right[1] - up[1];
- varray_vertex[ 2] = org[2] + right[2] - up[2];
- varray_vertex[ 4] = org[0] - right[0] - up[0];
- varray_vertex[ 5] = org[1] - right[1] - up[1];
- varray_vertex[ 6] = org[2] - right[2] - up[2];
- varray_vertex[ 8] = org[0] - right[0] + up[0];
- varray_vertex[ 9] = org[1] - right[1] + up[1];
- varray_vertex[10] = org[2] - right[2] + up[2];
- varray_vertex[12] = org[0] + right[0] + up[0];
- varray_vertex[13] = org[1] + right[1] + up[1];
- varray_vertex[14] = org[2] + right[2] + up[2];
- }
- else
- Host_Error("R_DrawParticles: unknown particle orientation %i\n", p->orientation);
-
tex = &particletexture[p->texnum];
cr = p->color[0] * (1.0f / 255.0f);
cg = p->color[1] * (1.0f / 255.0f);
ca = 1;
}
-#if WORKINGLQUAKE
- if (p->blendmode == 0)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- else if (p->blendmode == 1)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- else
- glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- glBegin(GL_QUADS);
- glColor4f(cr, cg, cb, ca);
- glTexCoord2f(tex->s2, tex->t1);glVertex3f(varray_vertex[ 0], varray_vertex[ 1], varray_vertex[ 2]);
- glTexCoord2f(tex->s1, tex->t1);glVertex3f(varray_vertex[ 4], varray_vertex[ 5], varray_vertex[ 6]);
- glTexCoord2f(tex->s1, tex->t2);glVertex3f(varray_vertex[ 8], varray_vertex[ 9], varray_vertex[10]);
- glTexCoord2f(tex->s2, tex->t2);glVertex3f(varray_vertex[12], varray_vertex[13], varray_vertex[14]);
- glEnd();
-#else
- memset(&m, 0, sizeof(m));
- if (p->blendmode == 0)
- {
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- }
- else if (p->blendmode == 1)
- {
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE;
- }
- else
- {
- m.blendfunc1 = GL_ZERO;
- m.blendfunc2 = GL_ONE_MINUS_SRC_COLOR;
- }
- m.tex[0] = R_GetTexture(tex->texture);
- R_Mesh_Matrix(&r_identitymatrix);
- R_Mesh_State(&m);
-
+#ifndef WORKINGLQUAKE
if (fogenabled && p->blendmode != PBLEND_MOD)
{
VectorSubtract(org, r_origin, fogvec);
cg *= r_colorscale;
cb *= r_colorscale;
- if (p->orientation == PARTICLE_BEAM)
+ GL_Color(cr, cg, cb, ca);
+
+ R_Mesh_Matrix(&r_identitymatrix);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(tex->texture);
+ m.pointer_texcoord[0] = particle_texcoord2f;
+ R_Mesh_State_Texture(&m);
+
+ if (p->blendmode == 0)
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ else if (p->blendmode == 1)
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ else
+ GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ GL_VertexPointer(particle_vertex3f);
+#endif
+ if (p->orientation == PARTICLE_BILLBOARD || p->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
+ {
+ if (p->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
+ {
+ // double-sided
+ if (DotProduct(p->vel2, r_origin) > DotProduct(p->vel2, org))
+ {
+ VectorNegate(p->vel2, v);
+ VectorVectors(v, right, up);
+ }
+ else
+ VectorVectors(p->vel2, right, up);
+ VectorScale(right, p->scalex, right);
+ VectorScale(up, p->scaley, up);
+ }
+ else
+ {
+ VectorScale(vright, p->scalex, right);
+ VectorScale(vup, p->scaley, up);
+ }
+ particle_vertex3f[ 0] = org[0] - right[0] - up[0];
+ particle_vertex3f[ 1] = org[1] - right[1] - up[1];
+ particle_vertex3f[ 2] = org[2] - right[2] - up[2];
+ particle_vertex3f[ 3] = org[0] - right[0] + up[0];
+ particle_vertex3f[ 4] = org[1] - right[1] + up[1];
+ particle_vertex3f[ 5] = org[2] - right[2] + up[2];
+ particle_vertex3f[ 6] = org[0] + right[0] + up[0];
+ particle_vertex3f[ 7] = org[1] + right[1] + up[1];
+ particle_vertex3f[ 8] = org[2] + right[2] + up[2];
+ particle_vertex3f[ 9] = org[0] + right[0] - up[0];
+ particle_vertex3f[10] = org[1] + right[1] - up[1];
+ particle_vertex3f[11] = org[2] + right[2] - up[2];
+ particle_texcoord2f[0] = tex->s1;particle_texcoord2f[1] = tex->t2;
+ particle_texcoord2f[2] = tex->s1;particle_texcoord2f[3] = tex->t1;
+ particle_texcoord2f[4] = tex->s2;particle_texcoord2f[5] = tex->t1;
+ particle_texcoord2f[6] = tex->s2;particle_texcoord2f[7] = tex->t2;
+ }
+ else if (p->orientation == PARTICLE_SPARK)
+ {
+ VectorMA(p->org, -p->scaley, p->vel, v);
+ VectorMA(p->org, p->scaley, p->vel, up2);
+ R_CalcBeam_Vertex3f(particle_vertex3f, v, up2, p->scalex);
+ particle_texcoord2f[0] = tex->s1;particle_texcoord2f[1] = tex->t2;
+ particle_texcoord2f[2] = tex->s1;particle_texcoord2f[3] = tex->t1;
+ particle_texcoord2f[4] = tex->s2;particle_texcoord2f[5] = tex->t1;
+ particle_texcoord2f[6] = tex->s2;particle_texcoord2f[7] = tex->t2;
+ }
+ else if (p->orientation == PARTICLE_BEAM)
{
+ R_CalcBeam_Vertex3f(particle_vertex3f, p->org, p->vel2, p->scalex);
VectorSubtract(p->vel2, p->org, up);
VectorNormalizeFast(up);
v[0] = DotProduct(p->org, up) * (1.0f / 64.0f) - cl.time * 0.25;
v[1] = DotProduct(p->vel2, up) * (1.0f / 64.0f) - cl.time * 0.25;
- varray_texcoord[0][0] = 1;varray_texcoord[0][1] = v[0];
- varray_texcoord[0][4] = 0;varray_texcoord[0][5] = v[0];
- varray_texcoord[0][8] = 0;varray_texcoord[0][9] = v[1];
- varray_texcoord[0][12] = 1;varray_texcoord[0][13] = v[1];
+ particle_texcoord2f[0] = 1;particle_texcoord2f[1] = v[0];
+ particle_texcoord2f[2] = 0;particle_texcoord2f[3] = v[0];
+ particle_texcoord2f[4] = 0;particle_texcoord2f[5] = v[1];
+ particle_texcoord2f[6] = 1;particle_texcoord2f[7] = v[1];
}
else
- {
- varray_texcoord[0][0] = tex->s2;varray_texcoord[0][1] = tex->t1;
- varray_texcoord[0][4] = tex->s1;varray_texcoord[0][5] = tex->t1;
- varray_texcoord[0][8] = tex->s1;varray_texcoord[0][9] = tex->t2;
- varray_texcoord[0][12] = tex->s2;varray_texcoord[0][13] = tex->t2;
- }
+ Host_Error("R_DrawParticles: unknown particle orientation %i\n", p->orientation);
- GL_Color(cr, cg, cb, ca);
+#if WORKINGLQUAKE
+ if (p->blendmode == 0)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ else if (p->blendmode == 1)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ else
+ 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(4, 2, polygonelements);
#endif
}