]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_particles.c
fixed totally mixed up vis culling (as a result of botched bmodel vis handling -...
[xonotic/darkplaces.git] / cl_particles.c
index 081d3ae531801f89dad6fde7187d2867c3dffa17..d5f9b93f22d716e2e9b903047aecf2b95400b398 100644 (file)
@@ -40,7 +40,6 @@ void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, i
 #define CL_BlobExplosion R_BlobExplosion
 #define CL_RunParticleEffect R_RunParticleEffect
 #define CL_LavaSplash R_LavaSplash
-#define CL_RocketTrail2 R_RocketTrail2
 void R_CalcBeam_Vertex3f (float *vert, vec3_t org1, vec3_t org2, float width)
 {
        vec3_t right1, right2, diff, normal;
@@ -173,6 +172,7 @@ float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int
 }
 #else
 #include "cl_collision.h"
+#include "image.h"
 #endif
 
 #define MAX_PARTICLES                  32768   // default max # of particles at one time
@@ -293,6 +293,10 @@ cvar_t cl_particles_blood = {CVAR_SAVE, "cl_particles_blood", "1"};
 cvar_t cl_particles_blood_alpha = {CVAR_SAVE, "cl_particles_blood_alpha", "0.5"};
 cvar_t cl_particles_blood_bloodhack = {CVAR_SAVE, "cl_particles_blood_bloodhack", "1"};
 cvar_t cl_particles_bulletimpacts = {CVAR_SAVE, "cl_particles_bulletimpacts", "1"};
+cvar_t cl_particles_explosions_bubbles = {CVAR_SAVE, "cl_particles_explosions_bubbles", "1"};
+cvar_t cl_particles_explosions_smoke = {CVAR_SAVE, "cl_particles_explosions_smokes", "0"};
+cvar_t cl_particles_explosions_sparks = {CVAR_SAVE, "cl_particles_explosions_sparks", "1"};
+cvar_t cl_particles_explosions_shell = {CVAR_SAVE, "cl_particles_explosions_shell", "0"};
 cvar_t cl_particles_smoke = {CVAR_SAVE, "cl_particles_smoke", "1"};
 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"};
@@ -310,6 +314,7 @@ void CL_Particles_Clear(void)
 {
        cl_numparticles = 0;
        cl_freeparticle = 0;
+       memset(particles, 0, sizeof(particle_t) * cl_maxparticles);
 }
 
 /*
@@ -342,6 +347,10 @@ void CL_Particles_Init (void)
        Cvar_RegisterVariable (&cl_particles_blood);
        Cvar_RegisterVariable (&cl_particles_blood_alpha);
        Cvar_RegisterVariable (&cl_particles_blood_bloodhack);
+       Cvar_RegisterVariable (&cl_particles_explosions_bubbles);
+       Cvar_RegisterVariable (&cl_particles_explosions_smoke);
+       Cvar_RegisterVariable (&cl_particles_explosions_sparks);
+       Cvar_RegisterVariable (&cl_particles_explosions_shell);
        Cvar_RegisterVariable (&cl_particles_bulletimpacts);
        Cvar_RegisterVariable (&cl_particles_smoke);
        Cvar_RegisterVariable (&cl_particles_smoke_alpha);
@@ -355,11 +364,10 @@ void CL_Particles_Init (void)
 #ifdef WORKINGLQUAKE
        particles = (particle_t *) Hunk_AllocName(cl_maxparticles * sizeof(particle_t), "particles");
 #else
-       cl_part_mempool = Mem_AllocPool("CL_Part");
+       cl_part_mempool = Mem_AllocPool("CL_Part", 0, NULL);
        particles = (particle_t *) Mem_Alloc(cl_part_mempool, cl_maxparticles * sizeof(particle_t));
 #endif
-       cl_numparticles = 0;
-       cl_freeparticle = 0;
+       CL_Particles_Clear();
 }
 
 // list of all 26 parameters:
@@ -604,7 +612,7 @@ void CL_ParseParticleEffect (void)
        vec3_t org, dir;
        int i, count, msgcount, color;
 
-       MSG_ReadVector(org);
+       MSG_ReadVector(org, cl.protocol);
        for (i=0 ; i<3 ; i++)
                dir[i] = MSG_ReadChar () * (1.0/16);
        msgcount = MSG_ReadByte ();
@@ -649,66 +657,59 @@ void CL_ParticleExplosion (vec3_t org)
        CL_SpawnDecalParticleForPoint(org, 40, 48, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
 
        i = CL_PointQ1Contents(org);
-       if ((i == CONTENTS_SLIME || i == CONTENTS_WATER) && cl_particles.integer && cl_particles_bubbles.integer)
+       if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
        {
-               for (i = 0;i < 128 * cl_particles_quality.value;i++)
-                       particle(pt_bubble, PARTICLE_BILLBOARD, 0x404040, 0x808080, tex_bubble, false, PBLEND_ADD, 2, 2, (1.0f / cl_particles_quality.value) * lhrandom(128, 255), (1.0f / cl_particles_quality.value) * 256, 9999, -0.25, 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, (1.0 / 16.0), 0);
+               if (cl_particles.integer && cl_particles_bubbles.integer && cl_particles_explosions_bubbles.integer)
+                       for (i = 0;i < 128 * cl_particles_quality.value;i++)
+                               particle(pt_bubble, PARTICLE_BILLBOARD, 0x404040, 0x808080, tex_bubble, false, PBLEND_ADD, 2, 2, (1.0f / cl_particles_quality.value) * lhrandom(128, 255), (1.0f / cl_particles_quality.value) * 256, 9999, -0.25, 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, (1.0 / 16.0), 0);
        }
        else
        {
-               /*
                // LordHavoc: smoke effect similar to UT2003, chews fillrate too badly up close
                // smoke puff
-               if (cl_particles.integer && cl_particles_smoke.integer)
+               if (cl_particles.integer && cl_particles_smoke.integer && cl_particles_explosions_smoke.integer)
                {
-                       for (i = 0;i < 64;i++)
+                       for (i = 0;i < 32;i++)
                        {
+                               int k;
+                               vec3_t v, v2;
 #ifdef WORKINGLQUAKE
-                               v2[0] = lhrandom(-64, 64);
-                               v2[1] = lhrandom(-64, 64);
-                               v2[2] = lhrandom(-8, 24);
+                               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(-64, 64);
-                                       v[1] = org[1] + lhrandom(-64, 64);
-                                       v[2] = org[2] + lhrandom(-8, 24);
+                                       v[0] = org[0] + lhrandom(-48, 48);
+                                       v[1] = org[1] + lhrandom(-48, 48);
+                                       v[2] = org[2] + lhrandom(-48, 48);
                                        if (CL_TraceLine(org, v, v2, NULL, true, NULL, SUPERCONTENTS_SOLID) >= 0.1)
                                                break;
                                }
                                VectorSubtract(v2, org, v2);
 #endif
                                VectorScale(v2, 2.0f, v2);
-                               particle(pt_static, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, PBLEND_ADD, 12, 12, 255, 512, 9999, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0, 0, 0, 0, 0, 0);
+                               particle(pt_static, PARTICLE_BILLBOARD, 0xFFFFFF, 0xFFFFFF, tex_smoke[rand()&7], true, PBLEND_ADD, 12, 12, 32, 64, 9999, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0, 0, 0, 0, 0, 0);
                        }
                }
-               */
 
 #if 1
-               if (cl_particles.integer && cl_particles_sparks.integer)
+               if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
                        for (i = 0;i < 128 * cl_particles_quality.value;i++)
                                particle(pt_static, PARTICLE_SPARK, 0x903010, 0xFFD030, tex_particle, false, PBLEND_ADD, 1.0f, 0.02f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 512, 9999, 1, 0, org[0], org[1], org[2], lhrandom(-256, 256), lhrandom(-256, 256), lhrandom(-256, 256) + 80, 0, 0, 0, 0, 0.2, 0);
-       }
-
-       //if (cl_explosions.integer)
-       //      R_NewExplosion(org);
 #elif 1
-               if (cl_particles.integer && cl_particles_sparks.integer)
+               if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
                        for (i = 0;i < 64 * cl_particles_quality.value;i++)
                                particle(pt_ember, PARTICLE_SPARK, 0x903010, 0xFFD030, tex_particle, false, PBLEND_ADD, 1.0f, 0.01f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 256, 9999, 0.7, 0, org[0], org[1], org[2], lhrandom(-256, 256), lhrandom(-256, 256), lhrandom(-256, 256) + 80, cl.time, 0, 0, 0, 0, 0);
-       }
-
-       //if (cl_explosions.integer)
-       //      R_NewExplosion(org);
 #else
-               if (cl_particles.integer && cl_particles_sparks.integer)
+               if (cl_particles.integer && cl_particles_sparks.integer && cl_particles_explosions_sparks.integer)
                        for (i = 0;i < 256 * cl_particles_quality.value;i++)
                                particle(pt_static, PARTICLE_SPARK, 0x903010, 0xFFD030, tex_particle, false, PBLEND_ADD, 1.5f, 0.05f, (1.0f / cl_particles_quality.value) * lhrandom(0, 255), (1.0f / cl_particles_quality.value) * 512, 9999, 1, 0, org[0], org[1], org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 160, 0, 0, 0, 0, 0.2, 0);
+#endif
        }
 
-       if (cl_explosions.integer)
+       if (cl_particles_explosions_shell.integer)
                R_NewExplosion(org);
-#endif
 }
 
 /*
@@ -722,6 +723,7 @@ void CL_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
        vec3_t vel;
        vec3_t offset;
        int i, k;
+       float pscale;
        if (!cl_particles.integer) return;
 
        for (i = 0;i < 512 * cl_particles_quality.value;i++)
@@ -730,7 +732,8 @@ void CL_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
                VectorScale (offset, 192, vel);
                VectorScale (offset, 8, offset);
                k = particlepalette[colorStart + (i % colorLength)];
-               particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ALPHA, 1.5, 1.5, (1.0f / cl_particles_quality.value) * 255, (1.0f / cl_particles_quality.value) * 384, 0.3, 0, 0, org[0] + offset[0], org[1] + offset[1], org[2] + offset[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1, 0);
+               pscale = lhrandom(0.5, 1.5);
+               particle(pt_static, PARTICLE_BILLBOARD, k, k, tex_particle, false, PBLEND_ADD, pscale, pscale, (1.0f / cl_particles_quality.value) * 255, (1.0f/cl_particles_quality.value)*512, 9999, 0, 0, org[0] + offset[0], org[1] + offset[1], org[2] + offset[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, lhrandom(1.5, 3), 0);
        }
 }
 
@@ -742,12 +745,7 @@ CL_BlobExplosion
 */
 void CL_BlobExplosion (vec3_t org)
 {
-       if (cl_stainmaps.integer)
-               R_Stain(org, 96, 80, 80, 80, 64, 176, 176, 176, 64);
-       CL_SpawnDecalParticleForPoint(org, 40, 48, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
-
-       if (cl_explosions.integer)
-               R_NewExplosion(org);
+       CL_ParticleExplosion(org);
 }
 
 /*
@@ -1093,7 +1091,7 @@ void R_TeleportSplash (vec3_t org)
 #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, entity_t *ent)
+void CL_RocketTrail (vec3_t start, vec3_t end, int type, int color, entity_t *ent)
 #endif
 {
        vec3_t vec, dir, vel, pos;
@@ -1201,7 +1199,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                                particle(pt_static, PARTICLE_BILLBOARD, 0x502030, 0x502030, tex_particle, false, PBLEND_ADD, 6, 6, qd*128, qd*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;
-
+#ifndef WORKINGLQUAKE
                        case 7: // Nehahra smoke tracer
                                dec = qd*7;
                                if (smoke)
@@ -1212,6 +1210,12 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                if (smoke)
                                        particle(pt_static, PARTICLE_BILLBOARD, 0x283880, 0x283880, tex_particle, false, PBLEND_ADD, 4, 4, qd*255, qd*1024, 9999, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
+                       case 9: // glow trail
+                               dec = qd*3;
+                               if (smoke)
+                                       particle(pt_static, PARTICLE_BILLBOARD, color, color, tex_particle, false, PBLEND_ALPHA, 5, 5, qd*128, qd*320, 9999, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                               break;
+#endif
                }
 
                // advance to next time and position
@@ -1223,30 +1227,6 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
 #endif
 }
 
-void CL_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
-{
-       float dec, len;
-       vec3_t vec, pos;
-       if (!cl_particles.integer) return;
-       if (!cl_particles_smoke.integer) return;
-
-       VectorCopy(start, pos);
-       VectorSubtract(end, start, vec);
-#ifdef WORKINGLQUAKE
-       len = VectorNormalize(vec);
-#else
-       len = VectorNormalizeLength(vec);
-#endif
-       color = particlepalette[color];
-       dec = 3.0f / cl_particles_quality.value;
-       while (len > 0)
-       {
-               particle(pt_static, PARTICLE_BILLBOARD, color, color, tex_particle, false, PBLEND_ALPHA, 5, 5, 128 / cl_particles_quality.value, 320 / cl_particles_quality.value, 9999, 0, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
-               len -= dec;
-               VectorMA(pos, dec, vec, pos);
-       }
-}
-
 void CL_BeamParticle (const vec3_t start, const vec3_t end, vec_t radius, float red, float green, float blue, float alpha, float lifetime)
 {
        int tempcolor2, cr, cg, cb;
@@ -1756,11 +1736,13 @@ static void R_InitParticleTexture (void)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 #else
-       particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
+       particlefonttexture = loadtextureimage(particletexturepool, "particles/particlefont.tga", 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
+       if (!particlefonttexture)
+               particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
        for (i = 0;i < MAX_PARTICLETEXTURES;i++)
                particletexture[i].texture = particlefonttexture;
 
-       // beam
+       // nexbeam
        fractalnoise(&noise1[0][0], 64, 4);
        m = 0;
        for (y = 0;y < 64;y++)
@@ -1777,7 +1759,9 @@ static void R_InitParticleTexture (void)
                }
        }
 
-       particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "beam", 16, 64, &data2[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+       particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
+       if (!particletexture[tex_beam].texture)
+               particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "nexbeam", 16, 64, &data2[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
        particletexture[tex_beam].s1 = 0;
        particletexture[tex_beam].t1 = 0;
        particletexture[tex_beam].s2 = 1;